3 * Linux cfg80211 driver
5 * Copyright (C) 1999-2013, Broadcom Corporation
7 * Unless you and Broadcom execute a separate written software license
8 * agreement governing use of this software, this software is licensed to you
9 * under the terms of the GNU General Public License version 2 (the "GPL"),
10 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
11 * following added to such license:
13 * As a special exception, the copyright holders of this software give you
14 * permission to link this software with independent modules, and to copy and
15 * distribute the resulting executable under terms of your choice, provided that
16 * you also meet, for each linked independent module, the terms and conditions of
17 * the license of that module. An independent module is a module which is not
18 * derived from this software. The special exception does not apply to any
19 * modifications of the software.
21 * Notwithstanding the above, under no circumstances may you combine this
22 * software in any way with any other Broadcom software provided under a license
23 * other than the GPL, without Broadcom's express prior written consent.
25 * $Id: wl_cfg80211.c 432088 2013-10-25 15:02:04Z $
31 #include <linux/kernel.h>
34 #include <bcmwifi_channels.h>
35 #include <bcmendian.h>
36 #include <proto/ethernet.h>
37 #include <proto/802.11.h>
38 #include <linux/if_arp.h>
39 #include <asm/uaccess.h>
41 #include <dngl_stats.h>
45 #include <dhd_cfg80211.h>
48 #endif /* PNO_SUPPORT */
50 #include <proto/ethernet.h>
51 #include <linux/kernel.h>
52 #include <linux/kthread.h>
53 #include <linux/netdevice.h>
54 #include <linux/sched.h>
55 #include <linux/etherdevice.h>
56 #include <linux/wireless.h>
57 #include <linux/ieee80211.h>
58 #include <linux/wait.h>
59 #include <net/cfg80211.h>
60 #include <net/rtnetlink.h>
63 #include <wldev_common.h>
64 #include <wl_cfg80211.h>
65 #include <wl_cfgp2p.h>
66 #include <wl_android.h>
74 #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
76 static struct device *cfg80211_parent_dev = NULL;
77 struct wl_priv *wlcfg_drv_priv = NULL;
78 u32 wl_dbg_level = WL_DBG_ERR;
80 #define MAX_WAIT_TIME 1500
83 /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
84 #define DEFAULT_SLEEP_TIME_VSDB 120
85 #define OFF_CHAN_TIME_THRESHOLD_MS 200
86 #define AF_RETRY_DELAY_TIME 40
88 /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
89 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl) \
91 if (wl_get_drv_status(wl, CONNECTED, wl_to_prmry_ndev(wl)) || \
92 wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) { \
93 OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB); \
97 /* if not VSDB, do nothing */
98 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl)
101 #ifdef WL_CFG80211_SYNC_GON
102 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl) \
103 (wl_get_drv_status_all(wl, SENDING_ACT_FRM) || \
104 wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN))
106 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl) wl_get_drv_status_all(wl, SENDING_ACT_FRM)
107 #endif /* WL_CFG80211_SYNC_GON */
109 #define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
112 #define DNGL_FUNC(func, parameters) func parameters;
115 #define WLAN_EID_SSID 0
116 #define CH_MIN_5G_CHANNEL 34
117 #define CH_MIN_2G_CHANNEL 1
119 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
120 * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
121 * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
122 * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
123 * All the chnages in world regulatory domain are to be done here.
125 static const struct ieee80211_regdomain brcm_regdom = {
129 /* IEEE 802.11b/g, channels 1..11 */
130 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
132 /* IEEE 802.11 channel 14 - Only JP enables
133 * this and for 802.11b only
135 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
136 /* IEEE 802.11a, channel 36..64 */
137 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
138 /* IEEE 802.11a, channel 100..165 */
139 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
142 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
143 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
145 * Possible interface combinations supported by driver
147 * ADHOC Mode - #ADHOC <= 1 on channels = 1
148 * SoftAP Mode - #AP <= 1 on channels = 1
149 * STA + P2P Mode - #STA <= 2, #{P2P-GO, P2P-client} <= 1, #P2P-device <= 1
152 static const struct ieee80211_iface_limit softap_limits[] = {
155 .types = BIT(NL80211_IFTYPE_AP),
159 static const struct ieee80211_iface_limit sta_p2p_limits[] = {
161 * During P2P-GO removal, P2P-GO is first changed to STA and later only
162 * removed. So setting maximum possible number of STA interfaces as 3 to
163 * accommodate the above behaviour.
166 #ifdef WL_ENABLE_P2P_IF
170 #endif /* WL_ENABLE_P2P_IF */
172 .types = BIT(NL80211_IFTYPE_STATION),
176 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
178 #if defined(WL_CFG80211_P2P_DEV_IF)
181 .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
183 #endif /* WL_CFG80211_P2P_DEV_IF */
186 .types = BIT(NL80211_IFTYPE_ADHOC),
190 static const struct ieee80211_iface_combination
191 softap_iface_combinations[] = {
193 .num_different_channels = 1,
195 .limits = softap_limits,
196 .n_limits = ARRAY_SIZE(softap_limits),
200 static const struct ieee80211_iface_combination
201 sta_p2p_iface_combinations[] = {
203 #ifdef DHD_ENABLE_MCC
204 .num_different_channels = 2,
206 .num_different_channels = 1,
209 .limits = sta_p2p_limits,
210 .n_limits = ARRAY_SIZE(sta_p2p_limits),
213 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
215 /* Data Element Definitions */
216 #define WPS_ID_CONFIG_METHODS 0x1008
217 #define WPS_ID_REQ_TYPE 0x103A
218 #define WPS_ID_DEVICE_NAME 0x1011
219 #define WPS_ID_VERSION 0x104A
220 #define WPS_ID_DEVICE_PWD_ID 0x1012
221 #define WPS_ID_REQ_DEV_TYPE 0x106A
222 #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
223 #define WPS_ID_PRIM_DEV_TYPE 0x1054
225 /* Device Password ID */
226 #define DEV_PW_DEFAULT 0x0000
227 #define DEV_PW_USER_SPECIFIED 0x0001,
228 #define DEV_PW_MACHINE_SPECIFIED 0x0002
229 #define DEV_PW_REKEY 0x0003
230 #define DEV_PW_PUSHBUTTON 0x0004
231 #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
234 #define WPS_CONFIG_USBA 0x0001
235 #define WPS_CONFIG_ETHERNET 0x0002
236 #define WPS_CONFIG_LABEL 0x0004
237 #define WPS_CONFIG_DISPLAY 0x0008
238 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
239 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
240 #define WPS_CONFIG_NFC_INTERFACE 0x0040
241 #define WPS_CONFIG_PUSHBUTTON 0x0080
242 #define WPS_CONFIG_KEYPAD 0x0100
243 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
244 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
245 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
246 #define WPS_CONFIG_PHY_DISPLAY 0x4008
253 #ifndef IBSS_COALESCE_ALLOWED
254 #define IBSS_COALESCE_ALLOWED 0
257 #ifndef IBSS_INITIAL_SCAN_ALLOWED
258 #define IBSS_INITIAL_SCAN_ALLOWED 0
261 * cfg80211_ops api/callback list
263 static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
264 const struct ether_addr *sa, const struct ether_addr *bssid,
265 u8 **pheader, u32 *body_len, u8 *pbody);
266 static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
267 struct cfg80211_scan_request *request,
268 struct cfg80211_ssid *this_ssid);
269 #if defined(WL_CFG80211_P2P_DEV_IF)
271 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
274 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
275 struct cfg80211_scan_request *request);
276 #endif /* WL_CFG80211_P2P_DEV_IF */
277 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
278 static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
279 struct cfg80211_ibss_params *params);
280 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
281 struct net_device *dev);
282 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
283 struct net_device *dev, u8 *mac,
284 struct station_info *sinfo);
285 static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
286 struct net_device *dev, bool enabled,
288 static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
289 struct cfg80211_connect_params *sme);
290 static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
292 #if defined(WL_CFG80211_P2P_DEV_IF)
294 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
295 enum nl80211_tx_power_setting type, s32 mbm);
298 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
299 enum nl80211_tx_power_setting type, s32 dbm);
300 #endif /* WL_CFG80211_P2P_DEV_IF */
301 #if defined(WL_CFG80211_P2P_DEV_IF)
302 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
303 struct wireless_dev *wdev, s32 *dbm);
305 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
306 #endif /* WL_CFG80211_P2P_DEV_IF */
307 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
308 struct net_device *dev,
309 u8 key_idx, bool unicast, bool multicast);
310 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
311 u8 key_idx, bool pairwise, const u8 *mac_addr,
312 struct key_params *params);
313 static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
314 u8 key_idx, bool pairwise, const u8 *mac_addr);
315 static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
316 u8 key_idx, bool pairwise, const u8 *mac_addr,
317 void *cookie, void (*callback) (void *cookie,
318 struct key_params *params));
319 static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
320 struct net_device *dev, u8 key_idx);
321 static s32 wl_cfg80211_resume(struct wiphy *wiphy);
322 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
324 static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
325 bcm_struct_cfgdev *cfgdev, u64 cookie);
326 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
327 struct net_device *ndev, u8* mac_addr);
328 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
329 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
330 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
332 static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
334 static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
335 struct cfg80211_pmksa *pmksa);
336 static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
337 struct cfg80211_pmksa *pmksa);
338 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
339 struct net_device *dev);
340 static void wl_cfg80211_scan_abort(struct wl_priv *wl);
341 static s32 wl_notify_escan_complete(struct wl_priv *wl,
342 struct net_device *ndev, bool aborted, bool fw_abort);
343 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
344 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
345 u8 *peer, enum nl80211_tdls_operation oper);
349 * event & event Q handlers for cfg80211 interfaces
351 static s32 wl_create_event_handler(struct wl_priv *wl);
352 static void wl_destroy_event_handler(struct wl_priv *wl);
353 static s32 wl_event_handler(void *data);
354 static void wl_init_eq(struct wl_priv *wl);
355 static void wl_flush_eq(struct wl_priv *wl);
356 static unsigned long wl_lock_eq(struct wl_priv *wl);
357 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags);
358 static void wl_init_eq_lock(struct wl_priv *wl);
359 static void wl_init_event_handler(struct wl_priv *wl);
360 static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
361 static s32 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 type,
362 const wl_event_msg_t *msg, void *data);
363 static void wl_put_event(struct wl_event_q *e);
364 static void wl_wakeup_event(struct wl_priv *wl);
365 static s32 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
366 const wl_event_msg_t *e, void *data);
367 static s32 wl_notify_connect_status(struct wl_priv *wl,
368 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
369 static s32 wl_notify_roaming_status(struct wl_priv *wl,
370 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
371 static s32 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
372 const wl_event_msg_t *e, void *data);
373 static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
374 const wl_event_msg_t *e, void *data, bool completed);
375 static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
376 const wl_event_msg_t *e, void *data);
377 static s32 wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
378 const wl_event_msg_t *e, void *data);
381 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
382 const wl_event_msg_t *e, void *data);
383 #endif /* WL_SCHED_SCAN */
385 static s32 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
386 const wl_event_msg_t *e, void *data);
387 #endif /* PNO_SUPPORT */
388 static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
389 enum wl_status state, bool set);
392 static s32 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
393 const wl_event_msg_t *e, void *data);
396 static s32 wl_ccx_s69_response(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
397 const wl_event_msg_t *e, void *data);
400 * register/deregister parent device
402 static void wl_cfg80211_clear_parent_dev(void);
409 * cfg80211 set_wiphy_params utilities
411 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
412 static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
413 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
416 * wl profile utilities
418 static s32 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
419 const wl_event_msg_t *e, void *data, s32 item);
420 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item);
421 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev);
424 * cfg80211 connect utilites
426 static s32 wl_set_wpa_version(struct net_device *dev,
427 struct cfg80211_connect_params *sme);
428 static s32 wl_set_auth_type(struct net_device *dev,
429 struct cfg80211_connect_params *sme);
430 static s32 wl_set_set_cipher(struct net_device *dev,
431 struct cfg80211_connect_params *sme);
432 static s32 wl_set_key_mgmt(struct net_device *dev,
433 struct cfg80211_connect_params *sme);
434 static s32 wl_set_set_sharedkey(struct net_device *dev,
435 struct cfg80211_connect_params *sme);
436 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev);
437 static void wl_ch_to_chanspec(int ch,
438 struct wl_join_params *join_params, size_t *join_params_size);
441 * information element utilities
443 static void wl_rst_ie(struct wl_priv *wl);
444 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
445 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size);
446 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size);
447 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size);
448 static u32 wl_get_ielen(struct wl_priv *wl);
451 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data);
452 static void wl_free_wdev(struct wl_priv *wl);
453 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
455 wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
456 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
458 static s32 wl_inform_bss(struct wl_priv *wl);
459 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
460 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev);
461 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
462 s32 wl_cfg80211_channel_to_freq(u32 channel);
465 static void wl_cfg80211_work_handler(struct work_struct *work);
466 static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
467 u8 key_idx, const u8 *mac_addr,
468 struct key_params *params);
470 * key indianess swap utilities
472 static void swap_key_from_BE(struct wl_wsec_key *key);
473 static void swap_key_to_BE(struct wl_wsec_key *key);
476 * wl_priv memory init/deinit utilities
478 static s32 wl_init_priv_mem(struct wl_priv *wl);
479 static void wl_deinit_priv_mem(struct wl_priv *wl);
481 static void wl_delay(u32 ms);
484 * ibss mode utilities
486 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev);
487 static __used bool wl_is_ibssstarter(struct wl_priv *wl);
490 * link up/down , default configuration utilities
492 static s32 __wl_cfg80211_up(struct wl_priv *wl);
493 static s32 __wl_cfg80211_down(struct wl_priv *wl);
494 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
495 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev);
496 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
497 static void wl_link_up(struct wl_priv *wl);
498 static void wl_link_down(struct wl_priv *wl);
499 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype);
500 static void wl_init_conf(struct wl_conf *conf);
505 static void wl_iscan_timer(unsigned long data);
506 static void wl_term_iscan(struct wl_priv *wl);
507 static s32 wl_init_scan(struct wl_priv *wl);
508 static s32 wl_iscan_thread(void *data);
509 static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request,
511 static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request);
512 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
513 static s32 wl_invoke_iscan(struct wl_priv *wl);
514 static s32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
515 struct wl_scan_results **bss_list);
516 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
517 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan);
518 static s32 wl_iscan_done(struct wl_priv *wl);
519 static s32 wl_iscan_pending(struct wl_priv *wl);
520 static s32 wl_iscan_inprogress(struct wl_priv *wl);
521 static s32 wl_iscan_aborted(struct wl_priv *wl);
524 * find most significant bit set
526 static __used u32 wl_find_msb(u16 bit16);
531 static int wl_setup_rfkill(struct wl_priv *wl, bool setup);
532 static int wl_rfkill_set(void *data, bool blocked);
533 #ifdef DEBUGFS_CFG80211
534 static s32 wl_setup_debugfs(struct wl_priv *wl);
535 static s32 wl_free_debugfs(struct wl_priv *wl);
538 static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel,
539 int nprobes, int *out_params_size);
540 static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role);
543 * Some external functions, TODO: move them to dhd_linux.h
545 int dhd_add_monitor(char *name, struct net_device **new_ndev);
546 int dhd_del_monitor(struct net_device *ndev);
547 int dhd_monitor_init(void *dhd_pub);
548 int dhd_monitor_uninit(void);
549 int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
553 #define RETURN_EIO_IF_NOT_UP(wlpriv) \
555 struct net_device *checkSysUpNDev = wl_to_prmry_ndev(wlpriv); \
556 if (unlikely(!wl_get_drv_status(wlpriv, READY, checkSysUpNDev))) { \
557 WL_INFO(("device is not ready\n")); \
563 static s32 wl_rssi_offset(s32 rssi)
571 #define wl_rssi_offset(x) x
574 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \
575 (akm) == RSN_AKM_UNSPECIFIED || \
576 (akm) == RSN_AKM_PSK)
579 extern int dhd_wait_pend8021x(struct net_device *dev);
580 #ifdef PROP_TXSTATUS_VSDB
581 extern int disable_proptx;
582 extern int dhd_wlfc_init(dhd_pub_t *dhd);
583 extern void dhd_wlfc_deinit(dhd_pub_t *dhd);
584 #endif /* PROP_TXSTATUS_VSDB */
586 #if (WL_DBG_LEVEL > 0)
587 #define WL_DBG_ESTR_MAX 50
588 static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
589 "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
590 "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
591 "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
592 "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
593 "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
594 "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
595 "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
597 "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
599 "RADIO", "PSM_WATCHDOG", "WLC_E_CCX_ASSOC_START", "WLC_E_CCX_ASSOC_ABORT",
601 "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
602 "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
603 "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
604 "WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE",
605 "RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG",
606 "ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND",
607 "WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED",
608 "WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT",
609 "WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE",
610 "WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP",
611 "WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE"
613 #endif /* WL_DBG_LEVEL */
615 #define CHAN2G(_channel, _freq, _flags) { \
616 .band = IEEE80211_BAND_2GHZ, \
617 .center_freq = (_freq), \
618 .hw_value = (_channel), \
620 .max_antenna_gain = 0, \
624 #define CHAN5G(_channel, _flags) { \
625 .band = IEEE80211_BAND_5GHZ, \
626 .center_freq = 5000 + (5 * (_channel)), \
627 .hw_value = (_channel), \
629 .max_antenna_gain = 0, \
633 #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
634 #define RATETAB_ENT(_rateid, _flags) \
636 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
637 .hw_value = (_rateid), \
641 static struct ieee80211_rate __wl_rates[] = {
642 RATETAB_ENT(DOT11_RATE_1M, 0),
643 RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
644 RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
645 RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
646 RATETAB_ENT(DOT11_RATE_6M, 0),
647 RATETAB_ENT(DOT11_RATE_9M, 0),
648 RATETAB_ENT(DOT11_RATE_12M, 0),
649 RATETAB_ENT(DOT11_RATE_18M, 0),
650 RATETAB_ENT(DOT11_RATE_24M, 0),
651 RATETAB_ENT(DOT11_RATE_36M, 0),
652 RATETAB_ENT(DOT11_RATE_48M, 0),
653 RATETAB_ENT(DOT11_RATE_54M, 0)
656 #define wl_a_rates (__wl_rates + 4)
657 #define wl_a_rates_size 8
658 #define wl_g_rates (__wl_rates + 0)
659 #define wl_g_rates_size 12
661 static struct ieee80211_channel __wl_2ghz_channels[] = {
678 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
679 CHAN5G(34, 0), CHAN5G(36, 0),
680 CHAN5G(38, 0), CHAN5G(40, 0),
681 CHAN5G(42, 0), CHAN5G(44, 0),
682 CHAN5G(46, 0), CHAN5G(48, 0),
683 CHAN5G(52, 0), CHAN5G(56, 0),
684 CHAN5G(60, 0), CHAN5G(64, 0),
685 CHAN5G(100, 0), CHAN5G(104, 0),
686 CHAN5G(108, 0), CHAN5G(112, 0),
687 CHAN5G(116, 0), CHAN5G(120, 0),
688 CHAN5G(124, 0), CHAN5G(128, 0),
689 CHAN5G(132, 0), CHAN5G(136, 0),
690 CHAN5G(140, 0), CHAN5G(149, 0),
691 CHAN5G(153, 0), CHAN5G(157, 0),
692 CHAN5G(161, 0), CHAN5G(165, 0)
695 static struct ieee80211_supported_band __wl_band_2ghz = {
696 .band = IEEE80211_BAND_2GHZ,
697 .channels = __wl_2ghz_channels,
698 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
699 .bitrates = wl_g_rates,
700 .n_bitrates = wl_g_rates_size
703 static struct ieee80211_supported_band __wl_band_5ghz_a = {
704 .band = IEEE80211_BAND_5GHZ,
705 .channels = __wl_5ghz_a_channels,
706 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
707 .bitrates = wl_a_rates,
708 .n_bitrates = wl_a_rates_size
711 static const u32 __wl_cipher_suites[] = {
712 WLAN_CIPHER_SUITE_WEP40,
713 WLAN_CIPHER_SUITE_WEP104,
714 WLAN_CIPHER_SUITE_TKIP,
715 WLAN_CIPHER_SUITE_CCMP,
716 WLAN_CIPHER_SUITE_AES_CMAC,
720 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
721 static int maxrxpktglom = 0;
724 /* IOCtl version read from targeted driver */
725 static int ioctl_version;
726 #ifdef DEBUGFS_CFG80211
727 #define S_SUBLOGLEVEL 20
728 static const struct {
731 } sublogname_map[] = {
733 {WL_DBG_INFO, "INFO"},
735 {WL_DBG_SCAN, "SCAN"},
736 {WL_DBG_TRACE, "TRACE"},
737 {WL_DBG_P2P_ACTION, "P2PACTION"}
742 static void wl_add_remove_pm_enable_work(struct wl_priv *wl, bool add_remove,
743 enum wl_handler_del_type type)
745 if (wl->pm_enable_work_on) {
747 schedule_delayed_work(&wl->pm_enable_work,
748 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT));
750 cancel_delayed_work_sync(&wl->pm_enable_work);
752 case WL_HANDLER_MAINTAIN:
753 schedule_delayed_work(&wl->pm_enable_work,
754 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT));
756 case WL_HANDLER_PEND:
757 schedule_delayed_work(&wl->pm_enable_work,
758 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT*2));
762 wl->pm_enable_work_on = false;
769 /* Return a new chanspec given a legacy chanspec
770 * Returns INVCHANSPEC on error
773 wl_chspec_from_legacy(chanspec_t legacy_chspec)
777 /* get the channel number */
778 chspec = LCHSPEC_CHANNEL(legacy_chspec);
780 /* convert the band */
781 if (LCHSPEC_IS2G(legacy_chspec)) {
782 chspec |= WL_CHANSPEC_BAND_2G;
784 chspec |= WL_CHANSPEC_BAND_5G;
787 /* convert the bw and sideband */
788 if (LCHSPEC_IS20(legacy_chspec)) {
789 chspec |= WL_CHANSPEC_BW_20;
791 chspec |= WL_CHANSPEC_BW_40;
792 if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
793 chspec |= WL_CHANSPEC_CTL_SB_L;
795 chspec |= WL_CHANSPEC_CTL_SB_U;
799 if (wf_chspec_malformed(chspec)) {
800 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
808 /* Return a legacy chanspec given a new chanspec
809 * Returns INVCHANSPEC on error
812 wl_chspec_to_legacy(chanspec_t chspec)
816 if (wf_chspec_malformed(chspec)) {
817 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
822 /* get the channel number */
823 lchspec = CHSPEC_CHANNEL(chspec);
825 /* convert the band */
826 if (CHSPEC_IS2G(chspec)) {
827 lchspec |= WL_LCHANSPEC_BAND_2G;
829 lchspec |= WL_LCHANSPEC_BAND_5G;
832 /* convert the bw and sideband */
833 if (CHSPEC_IS20(chspec)) {
834 lchspec |= WL_LCHANSPEC_BW_20;
835 lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
836 } else if (CHSPEC_IS40(chspec)) {
837 lchspec |= WL_LCHANSPEC_BW_40;
838 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
839 lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
841 lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
844 /* cannot express the bandwidth */
845 char chanbuf[CHANSPEC_STR_LEN];
847 "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
848 "to pre-11ac format\n",
849 wf_chspec_ntoa(chspec, chanbuf), chspec));
856 /* given a chanspec value, do the endian and chanspec version conversion to
858 * Returns INVCHANSPEC on error
861 wl_chspec_host_to_driver(chanspec_t chanspec)
863 if (ioctl_version == 1) {
864 chanspec = wl_chspec_to_legacy(chanspec);
865 if (chanspec == INVCHANSPEC) {
869 chanspec = htodchanspec(chanspec);
874 /* given a channel value, do the endian and chanspec version conversion to
876 * Returns INVCHANSPEC on error
879 wl_ch_host_to_driver(u16 channel)
884 chanspec = channel & WL_CHANSPEC_CHAN_MASK;
886 if (channel <= CH_MAX_2G_CHANNEL)
887 chanspec |= WL_CHANSPEC_BAND_2G;
889 chanspec |= WL_CHANSPEC_BAND_5G;
891 chanspec |= WL_CHANSPEC_BW_20;
892 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
894 return wl_chspec_host_to_driver(chanspec);
897 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
899 * Returns INVCHANSPEC on error
902 wl_chspec_driver_to_host(chanspec_t chanspec)
904 chanspec = dtohchanspec(chanspec);
905 if (ioctl_version == 1) {
906 chanspec = wl_chspec_from_legacy(chanspec);
912 /* There isn't a lot of sense in it, but you can transmit anything you like */
913 static const struct ieee80211_txrx_stypes
914 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
915 [NL80211_IFTYPE_ADHOC] = {
917 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
919 [NL80211_IFTYPE_STATION] = {
921 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
922 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
924 [NL80211_IFTYPE_AP] = {
926 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
927 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
928 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
929 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
930 BIT(IEEE80211_STYPE_AUTH >> 4) |
931 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
932 BIT(IEEE80211_STYPE_ACTION >> 4)
934 [NL80211_IFTYPE_AP_VLAN] = {
937 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
938 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
939 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
940 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
941 BIT(IEEE80211_STYPE_AUTH >> 4) |
942 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
943 BIT(IEEE80211_STYPE_ACTION >> 4)
945 [NL80211_IFTYPE_P2P_CLIENT] = {
947 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
948 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
950 [NL80211_IFTYPE_P2P_GO] = {
952 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
953 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
954 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
955 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
956 BIT(IEEE80211_STYPE_AUTH >> 4) |
957 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
958 BIT(IEEE80211_STYPE_ACTION >> 4)
960 #if defined(WL_CFG80211_P2P_DEV_IF)
961 [NL80211_IFTYPE_P2P_DEVICE] = {
963 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
964 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
966 #endif /* WL_CFG80211_P2P_DEV_IF */
969 static void swap_key_from_BE(struct wl_wsec_key *key)
971 key->index = htod32(key->index);
972 key->len = htod32(key->len);
973 key->algo = htod32(key->algo);
974 key->flags = htod32(key->flags);
975 key->rxiv.hi = htod32(key->rxiv.hi);
976 key->rxiv.lo = htod16(key->rxiv.lo);
977 key->iv_initialized = htod32(key->iv_initialized);
980 static void swap_key_to_BE(struct wl_wsec_key *key)
982 key->index = dtoh32(key->index);
983 key->len = dtoh32(key->len);
984 key->algo = dtoh32(key->algo);
985 key->flags = dtoh32(key->flags);
986 key->rxiv.hi = dtoh32(key->rxiv.hi);
987 key->rxiv.lo = dtoh16(key->rxiv.lo);
988 key->iv_initialized = dtoh32(key->iv_initialized);
991 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !0
992 /* For debug: Dump the contents of the encoded wps ie buffe */
994 wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
996 #define WPS_IE_FIXED_LEN 6
1002 u8 *valptr = (uint8*) &val;
1003 if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
1004 WL_ERR(("invalid argument : NULL\n"));
1007 len = (u16)wps_ie[TLV_LEN_OFF];
1009 if (len > wps_ie_len) {
1010 WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
1013 WL_DBG(("wps_ie len=%d\n", len));
1014 len -= 4; /* for the WPS IE's OUI, oui_type fields */
1015 subel = wps_ie + WPS_IE_FIXED_LEN;
1016 while (len >= 4) { /* must have attr id, attr len fields */
1017 valptr[0] = *subel++;
1018 valptr[1] = *subel++;
1019 subelt_id = HTON16(val);
1021 valptr[0] = *subel++;
1022 valptr[1] = *subel++;
1023 subelt_len = HTON16(val);
1025 len -= 4; /* for the attr id, attr len fields */
1026 len -= subelt_len; /* for the remaining fields in this attribute */
1027 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1028 subel, subelt_id, subelt_len));
1030 if (subelt_id == WPS_ID_VERSION) {
1031 WL_DBG((" attr WPS_ID_VERSION: %u\n", *subel));
1032 } else if (subelt_id == WPS_ID_REQ_TYPE) {
1033 WL_DBG((" attr WPS_ID_REQ_TYPE: %u\n", *subel));
1034 } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
1036 valptr[1] = *(subel + 1);
1037 WL_DBG((" attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
1038 } else if (subelt_id == WPS_ID_DEVICE_NAME) {
1040 memcpy(devname, subel, subelt_len);
1041 devname[subelt_len] = '\0';
1042 WL_DBG((" attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1043 devname, subelt_len));
1044 } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
1046 valptr[1] = *(subel + 1);
1047 WL_DBG((" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
1048 *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
1049 } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
1051 valptr[1] = *(subel + 1);
1052 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
1053 valptr[0] = *(subel + 6);
1054 valptr[1] = *(subel + 7);
1055 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
1056 } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
1058 valptr[1] = *(subel + 1);
1059 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
1060 valptr[0] = *(subel + 6);
1061 valptr[1] = *(subel + 7);
1062 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
1063 } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
1065 valptr[1] = *(subel + 1);
1066 WL_DBG((" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1067 ": cat=%u\n", HTON16(val)));
1069 WL_DBG((" unknown attr 0x%x\n", subelt_id));
1072 subel += subelt_len;
1077 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
1081 struct wl_priv *wl = wiphy_priv(wiphy);
1082 struct net_device *dev = wl_to_prmry_ndev(wl);
1083 struct ether_addr bssid;
1084 struct wl_bss_info *bss = NULL;
1086 if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) {
1087 /* STA interface is not associated. So start the new interface on a temp
1088 * channel . Later proper channel will be applied by the above framework
1089 * via set_channel (cfg80211 API).
1091 WL_DBG(("Not associated. Return a temp channel. \n"));
1092 return wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1096 *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
1097 if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf,
1098 WL_EXTRA_BUF_MAX, false))) {
1099 WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1100 chspec = wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1103 bss = (struct wl_bss_info *) (wl->extra_buf + 4);
1104 chspec = bss->chanspec;
1106 WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
1111 static bcm_struct_cfgdev *
1112 wl_cfg80211_add_monitor_if(char *name)
1114 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1115 WL_INFO(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1116 return ERR_PTR(-EOPNOTSUPP);
1118 struct net_device* ndev = NULL;
1120 dhd_add_monitor(name, &ndev);
1121 WL_INFO(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
1122 return ndev_to_cfgdev(ndev);
1123 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1126 static bcm_struct_cfgdev *
1127 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
1128 #if defined(WL_CFG80211_P2P_DEV_IF)
1132 #endif /* WL_CFG80211_P2P_DEV_IF */
1133 enum nl80211_iftype type, u32 *flags,
1134 struct vif_params *params)
1143 struct wl_priv *wl = wiphy_priv(wiphy);
1144 struct net_device *_ndev;
1145 struct ether_addr primary_mac;
1146 int (*net_attach)(void *dhdp, int ifidx);
1147 bool rollback_lock = false;
1148 #ifdef PROP_TXSTATUS_VSDB
1151 #endif /* PROP_TXSTATUS_VSDB */
1154 return ERR_PTR(-EINVAL);
1156 #ifdef PROP_TXSTATUS_VSDB
1157 dhd = (dhd_pub_t *)(wl->pub);
1158 #endif /* PROP_TXSTATUS_VSDB */
1160 /* Use primary I/F for sending cmds down to firmware */
1161 _ndev = wl_to_prmry_ndev(wl);
1163 if (wl_get_drv_status(wl, CONNECTING, _ndev)) {
1164 WL_ERR(("Already AP connection going on\n"));
1168 WL_DBG(("if name: %s, type: %d\n", name, type));
1170 case NL80211_IFTYPE_ADHOC:
1171 case NL80211_IFTYPE_AP_VLAN:
1172 case NL80211_IFTYPE_WDS:
1173 case NL80211_IFTYPE_MESH_POINT:
1174 WL_ERR(("Unsupported interface type\n"));
1175 mode = WL_MODE_IBSS;
1177 case NL80211_IFTYPE_MONITOR:
1178 return wl_cfg80211_add_monitor_if((char *)name);
1179 #if defined(WL_CFG80211_P2P_DEV_IF)
1180 case NL80211_IFTYPE_P2P_DEVICE:
1181 return wl_cfgp2p_add_p2p_disc_if();
1182 #endif /* WL_CFG80211_P2P_DEV_IF */
1183 case NL80211_IFTYPE_P2P_CLIENT:
1184 case NL80211_IFTYPE_STATION:
1185 wlif_type = WL_P2P_IF_CLIENT;
1188 case NL80211_IFTYPE_P2P_GO:
1189 case NL80211_IFTYPE_AP:
1190 wlif_type = WL_P2P_IF_GO;
1194 WL_ERR(("Unsupported interface type\n"));
1200 WL_ERR(("name is NULL\n"));
1203 if (wl->p2p_supported && (wlif_type != -1)) {
1204 ASSERT(wl->p2p); /* ensure expectation of p2p initialization */
1205 if (wl_get_p2p_status(wl, IF_DELETING)) {
1206 /* wait till IF_DEL is complete
1207 * release the lock for the unregister to proceed
1209 if (rtnl_is_locked()) {
1211 rollback_lock = true;
1213 WL_INFO(("Released the lock and wait till IF_DEL is complete\n"));
1214 timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1215 (wl_get_p2p_status(wl, IF_DELETING) == false),
1216 msecs_to_jiffies(MAX_WAIT_TIME));
1218 /* put back the rtnl_lock again */
1219 if (rollback_lock) {
1221 rollback_lock = false;
1224 WL_ERR(("IF DEL is Success\n"));
1227 WL_ERR(("timeount < 0, return -EAGAIN\n"));
1228 return ERR_PTR(-EAGAIN);
1230 /* It should be now be safe to put this check here since we are sure
1231 * by now netdev_notifier (unregister) would have been called
1233 if (wl->iface_cnt == IFACE_MAX_CNT)
1234 return ERR_PTR(-ENOMEM);
1237 #ifdef PROP_TXSTATUS_VSDB
1239 return ERR_PTR(-ENODEV);
1240 #endif /* PROP_TXSTATUS_VSDB */
1242 return ERR_PTR(-ENODEV);
1244 if (wl->p2p && !wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
1246 wl_cfgp2p_set_firm_p2p(wl);
1247 wl_cfgp2p_init_discovery(wl);
1248 get_primary_mac(wl, &primary_mac);
1249 wl_cfgp2p_generate_bss_mac(&primary_mac,
1250 &wl->p2p->dev_addr, &wl->p2p->int_addr);
1253 memset(wl->p2p->vir_ifname, 0, IFNAMSIZ);
1254 strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1);
1256 wl_cfg80211_scan_abort(wl);
1257 #ifdef PROP_TXSTATUS_VSDB
1258 if (dhd->op_mode != DHD_FLAG_IBSS_MODE && !wl->wlfc_on && !disable_proptx) {
1259 dhd->wlfc_enabled = true;
1261 err = wldev_ioctl(_ndev, WLC_UP, &up, sizeof(s32), true);
1263 WL_ERR(("WLC_UP return err:%d\n", err));
1266 #endif /* PROP_TXSTATUS_VSDB */
1268 /* In concurrency case, STA may be already associated in a particular channel.
1269 * so retrieve the current channel of primary interface and then start the virtual
1270 * interface on that.
1272 chspec = wl_cfg80211_get_shared_freq(wiphy);
1274 /* For P2P mode, use P2P-specific driver features to create the
1275 * bss: "wl p2p_ifadd"
1277 wl_set_p2p_status(wl, IF_ADD);
1278 if (wlif_type == WL_P2P_IF_GO)
1279 wldev_iovar_setint(_ndev, "mpc", 0);
1280 err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
1282 if (unlikely(err)) {
1283 WL_ERR((" virtual iface add failed (%d) \n", err));
1284 return ERR_PTR(-ENOMEM);
1287 timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1288 (wl_get_p2p_status(wl, IF_ADD) == false),
1289 msecs_to_jiffies(MAX_WAIT_TIME));
1290 if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) {
1292 struct wireless_dev *vwdev;
1293 vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
1294 if (unlikely(!vwdev)) {
1295 WL_ERR(("Could not allocate wireless device\n"));
1296 return ERR_PTR(-ENOMEM);
1298 vwdev->wiphy = wl->wdev->wiphy;
1299 WL_INFO((" virtual interface(%s) is created memalloc done \n",
1300 wl->p2p->vir_ifname));
1301 vwdev->iftype = type;
1302 _ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
1303 _ndev->ieee80211_ptr = vwdev;
1304 #ifndef CONFIG_BCMDHD_DISABLE_P2P_SYSFS_DEVICE_NODE
1305 SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy));
1307 vwdev->netdev = _ndev;
1308 wl_set_drv_status(wl, READY, _ndev);
1309 wl->p2p->vif_created = true;
1310 wl_set_mode_by_netdev(wl, _ndev, mode);
1311 net_attach = wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION);
1312 if (net_attach && !net_attach(wl->pub, _ndev->ifindex)) {
1313 wl_alloc_netinfo(wl, _ndev, vwdev, mode, PM_ENABLE);
1315 /* Disable firmware roaming for P2P interface */
1316 wldev_iovar_setint(_ndev, "roam_off", val);
1318 if (mode != WL_MODE_AP)
1319 wldev_iovar_setint(_ndev, "buf_key_b4_m4", 1);
1321 WL_ERR((" virtual interface(%s) is "
1322 "created net attach done\n", wl->p2p->vir_ifname));
1323 if (mode == WL_MODE_AP)
1324 wl_set_drv_status(wl, CONNECTED, _ndev);
1325 if (type == NL80211_IFTYPE_P2P_CLIENT)
1326 dhd_mode = DHD_FLAG_P2P_GC_MODE;
1327 else if (type == NL80211_IFTYPE_P2P_GO)
1328 dhd_mode = DHD_FLAG_P2P_GO_MODE;
1329 DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode));
1330 #ifdef PROP_TXSTATUS_VSDB
1331 if (dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->plat_enable)
1332 dhd->plat_enable((void *)dhd);
1333 #endif /* PROP_TXSTATUS_VSDB */
1334 /* reinitialize completion to clear previous count */
1335 INIT_COMPLETION(wl->iface_disable);
1339 return ndev_to_cfgdev(_ndev);
1341 wl_clr_p2p_status(wl, IF_ADD);
1342 WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname));
1343 memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
1344 wl->p2p->vif_created = false;
1345 #ifdef PROP_TXSTATUS_VSDB
1346 if (dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->wlfc_enabled && wl->wlfc_on) {
1347 dhd->wlfc_enabled = false;
1348 dhd_wlfc_deinit(dhd);
1349 if (dhd->plat_deinit)
1350 dhd->plat_deinit((void *)dhd);
1351 wl->wlfc_on = false;
1353 #endif /* PROP_TXSTATUS_VSDB */
1357 if (wlif_type == WL_P2P_IF_GO)
1358 wldev_iovar_setint(_ndev, "mpc", 1);
1359 return ERR_PTR(-ENODEV);
1363 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
1365 struct net_device *dev = NULL;
1366 struct ether_addr p2p_mac;
1367 struct wl_priv *wl = wiphy_priv(wiphy);
1371 WL_DBG(("Enter\n"));
1374 return ERR_PTR(-EINVAL);
1376 #if defined(WL_CFG80211_P2P_DEV_IF)
1377 if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
1378 return wl_cfgp2p_del_p2p_disc_if(cfgdev);
1380 #endif /* WL_CFG80211_P2P_DEV_IF */
1381 dev = cfgdev_to_wlc_ndev(cfgdev, wl);
1383 if (wl_cfgp2p_find_idx(wl, dev, &index) != BCME_OK) {
1384 WL_ERR(("Find p2p index from ndev(%p) failed\n", dev));
1387 if (wl->p2p_supported) {
1388 memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN);
1390 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
1392 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
1393 wl_clr_p2p_status(wl, GO_NEG_PHASE);
1394 if (wl->p2p->vif_created) {
1395 if (wl_get_drv_status(wl, SCANNING, dev)) {
1396 wl_notify_escan_complete(wl, dev, true, true);
1398 wldev_iovar_setint(dev, "mpc", 1);
1399 /* Delete pm_enable_work */
1400 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
1403 if (wl_get_drv_status(wl, DISCONNECTING, dev) &&
1404 (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)) {
1405 WL_ERR(("Wait for Link Down event for GC !\n"));
1406 wait_for_completion_timeout
1407 (&wl->iface_disable, msecs_to_jiffies(500));
1409 wl_set_p2p_status(wl, IF_DELETING);
1410 DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl));
1413 if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
1414 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
1415 /* disable interface before bsscfg free */
1416 ret = wl_cfgp2p_ifdisable(wl, &p2p_mac);
1417 /* if fw doesn't support "ifdis",
1418 do not wait for link down of ap mode
1421 WL_ERR(("Wait for Link Down event for GO !!!\n"));
1422 wait_for_completion_timeout(&wl->iface_disable,
1423 msecs_to_jiffies(500));
1424 } else if (ret != BCME_UNSUPPORTED) {
1428 wl_cfgp2p_clear_management_ie(wl, index);
1430 if (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)
1431 wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
1433 /* delete interface after link down */
1434 ret = wl_cfgp2p_ifdel(wl, &p2p_mac);
1435 /* Firmware could not delete the interface so we will not get WLC_E_IF
1436 * event for cleaning the dhd virtual nw interace
1437 * So lets do it here. Failures from fw will ensure the application to do
1438 * ifconfig <inter> down and up sequnce, which will reload the fw
1439 * however we should cleanup the linux network virtual interfaces
1441 /* Request framework to RESET and clean up */
1443 struct net_device *ndev = wl_to_prmry_ndev(wl);
1444 WL_ERR(("Firmware returned an error (%d) from p2p_ifdel"
1445 "HANG Notification sent to %s\n", ret, ndev->name));
1446 net_os_send_hang_message(ndev);
1448 /* Wait for IF_DEL operation to be finished in firmware */
1449 timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1450 (wl->p2p->vif_created == false),
1451 msecs_to_jiffies(MAX_WAIT_TIME));
1452 if (timeout > 0 && (wl->p2p->vif_created == false)) {
1453 WL_DBG(("IFDEL operation done\n"));
1455 WL_ERR(("IFDEL didn't complete properly\n"));
1457 ret = dhd_del_monitor(dev);
1464 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
1465 enum nl80211_iftype type, u32 *flags,
1466 struct vif_params *params)
1475 struct wl_priv *wl = wiphy_priv(wiphy);
1476 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
1477 WL_DBG(("Enter type %d\n", type));
1480 return ERR_PTR(-EINVAL);
1482 case NL80211_IFTYPE_MONITOR:
1483 case NL80211_IFTYPE_WDS:
1484 case NL80211_IFTYPE_MESH_POINT:
1486 WL_ERR(("type (%d) : currently we do not support this type\n",
1489 case NL80211_IFTYPE_ADHOC:
1490 mode = WL_MODE_IBSS;
1493 case NL80211_IFTYPE_STATION:
1494 case NL80211_IFTYPE_P2P_CLIENT:
1498 case NL80211_IFTYPE_AP:
1499 case NL80211_IFTYPE_AP_VLAN:
1500 case NL80211_IFTYPE_P2P_GO:
1510 wl_set_mode_by_netdev(wl, ndev, mode);
1511 if (wl->p2p_supported && wl->p2p->vif_created) {
1512 WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created,
1514 wldev_iovar_setint(ndev, "mpc", 0);
1515 wl_notify_escan_complete(wl, ndev, true, true);
1517 /* In concurrency case, STA may be already associated in a particular
1518 * channel. so retrieve the current channel of primary interface and
1519 * then start the virtual interface on that.
1521 chspec = wl_cfg80211_get_shared_freq(wiphy);
1523 wlif_type = WL_P2P_IF_GO;
1524 WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n",
1525 ndev->name, ap, infra, type));
1526 wl_set_p2p_status(wl, IF_CHANGING);
1527 wl_clr_p2p_status(wl, IF_CHANGED);
1528 wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
1529 wait_event_interruptible_timeout(wl->netif_change_event,
1530 (wl_get_p2p_status(wl, IF_CHANGED) == true),
1531 msecs_to_jiffies(MAX_WAIT_TIME));
1532 wl_set_mode_by_netdev(wl, ndev, mode);
1533 dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
1534 dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
1535 wl_clr_p2p_status(wl, IF_CHANGING);
1536 wl_clr_p2p_status(wl, IF_CHANGED);
1537 if (mode == WL_MODE_AP)
1538 wl_set_drv_status(wl, CONNECTED, ndev);
1539 } else if (ndev == wl_to_prmry_ndev(wl) &&
1540 !wl_get_drv_status(wl, AP_CREATED, ndev)) {
1541 wl_set_drv_status(wl, AP_CREATING, ndev);
1543 !(wl->ap_info = kzalloc(sizeof(struct ap_info), GFP_KERNEL))) {
1544 WL_ERR(("struct ap_saved_ie allocation failed\n"));
1548 WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
1552 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA"));
1557 wl_set_mode_by_netdev(wl, ndev, mode);
1558 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
1560 WL_ERR(("SET Adhoc error %d\n", err));
1565 ndev->ieee80211_ptr->iftype = type;
1570 wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx,
1573 struct wl_priv *wl = wlcfg_drv_priv;
1577 WL_ERR(("net is NULL\n"));
1580 if (wl->p2p_supported && wl_get_p2p_status(wl, IF_ADD)) {
1581 WL_DBG(("IF_ADD event called from dongle, old interface name: %s,"
1582 "new name: %s\n", ndev->name, wl->p2p->vir_ifname));
1583 /* Assign the net device to CONNECT BSSCFG */
1584 strncpy(ndev->name, wl->p2p->vir_ifname, IFNAMSIZ - 1);
1585 wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = ndev;
1586 wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = bssidx;
1587 wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION) = _net_attach;
1588 ndev->ifindex = idx;
1589 wl_clr_p2p_status(wl, IF_ADD);
1591 wake_up_interruptible(&wl->netif_change_event);
1593 ret = BCME_NOTREADY;
1599 wl_cfg80211_notify_ifdel(void)
1601 struct wl_priv *wl = wlcfg_drv_priv;
1603 WL_DBG(("Enter \n"));
1604 wl_clr_p2p_status(wl, IF_DELETING);
1605 wake_up_interruptible(&wl->netif_change_event);
1610 wl_cfg80211_ifdel_ops(struct net_device *ndev)
1612 struct wl_priv *wl = wlcfg_drv_priv;
1613 bool rollback_lock = false;
1617 #ifdef PROP_TXSTATUS_VSDB
1618 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
1619 #endif /* PROP_TXSTATUS_VSDB */
1620 if (!ndev || (strlen(ndev->name) == 0)) {
1621 WL_ERR(("net is NULL\n"));
1625 if (p2p_is_on(wl) && wl->p2p->vif_created &&
1626 wl_get_p2p_status(wl, IF_DELETING)) {
1627 if (wl->scan_request &&
1628 (wl->escan_info.ndev == ndev)) {
1629 /* Abort any pending scan requests */
1630 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
1631 if (!rtnl_is_locked()) {
1633 rollback_lock = true;
1635 WL_DBG(("ESCAN COMPLETED\n"));
1636 wl_notify_escan_complete(wl, ndev, true, false);
1640 WL_ERR(("IF_DEL event called from dongle, net %p, vif name: %s\n",
1641 ndev, wl->p2p->vir_ifname));
1643 memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
1644 if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) {
1645 WL_ERR(("Find p2p bssidx from ndev(%p) failed\n", ndev));
1648 if (wl_cfgp2p_find_type(wl, bssidx, &type) != BCME_OK) {
1649 WL_ERR(("Find p2p type from bssidx(%d) failed\n", bssidx));
1652 wl_to_p2p_bss_ndev(wl, type) = NULL;
1653 wl_to_p2p_bss_bssidx(wl, type) = WL_INVALID;
1654 wl->p2p->vif_created = false;
1656 WL_DBG(("type : %d\n", type));
1657 #ifdef PROP_TXSTATUS_VSDB
1658 if (dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->wlfc_enabled && wl->wlfc_on) {
1659 dhd->wlfc_enabled = false;
1660 dhd_wlfc_deinit(dhd);
1661 if (dhd->plat_deinit)
1662 dhd->plat_deinit((void *)dhd);
1663 wl->wlfc_on = false;
1665 #endif /* PROP_TXSTATUS_VSDB */
1666 wl_clr_drv_status(wl, CONNECTED, ndev);
1668 /* Wake up any waiting thread */
1669 wake_up_interruptible(&wl->netif_change_event);
1675 wl_cfg80211_is_progress_ifadd(void)
1677 s32 is_progress = 0;
1678 struct wl_priv *wl = wlcfg_drv_priv;
1679 if (wl_get_p2p_status(wl, IF_ADD))
1685 wl_cfg80211_is_progress_ifchange(void)
1687 s32 is_progress = 0;
1688 struct wl_priv *wl = wlcfg_drv_priv;
1689 if (wl_get_p2p_status(wl, IF_CHANGING))
1696 wl_cfg80211_notify_ifchange(void)
1698 struct wl_priv *wl = wlcfg_drv_priv;
1699 if (wl_get_p2p_status(wl, IF_CHANGING)) {
1700 wl_set_p2p_status(wl, IF_CHANGED);
1701 wake_up_interruptible(&wl->netif_change_event);
1706 /* Find listen channel */
1707 static s32 wl_find_listen_channel(struct wl_priv *wl,
1708 const u8 *ie, u32 ie_len)
1710 wifi_p2p_ie_t *p2p_ie;
1715 p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
1720 pos = p2p_ie->subelts;
1721 end = p2p_ie->subelts + (p2p_ie->len - 4);
1723 CFGP2P_DBG((" found p2p ie ! lenth %d \n",
1728 if (pos + 2 >= end) {
1729 CFGP2P_DBG((" -- Invalid P2P attribute"));
1732 attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
1734 if (pos + 3 + attr_len > end) {
1735 CFGP2P_DBG(("P2P: Attribute underflow "
1737 attr_len, (int) (end - pos - 3)));
1741 /* if Listen Channel att id is 6 and the vailue is valid,
1742 * return the listen channel
1745 /* listen channel subel length format
1746 * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
1748 listen_channel = pos[1 + 2 + 3 + 1];
1750 if (listen_channel == SOCIAL_CHAN_1 ||
1751 listen_channel == SOCIAL_CHAN_2 ||
1752 listen_channel == SOCIAL_CHAN_3) {
1753 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
1754 return listen_channel;
1757 pos += 3 + attr_len;
1762 static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
1767 chanspec_t chanspec;
1768 s32 i = 0, j = 0, offset;
1771 struct wl_priv *wl = wlcfg_drv_priv;
1773 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
1774 params->bss_type = DOT11_BSSTYPE_ANY;
1775 params->scan_type = 0;
1776 params->nprobes = -1;
1777 params->active_time = -1;
1778 params->passive_time = -1;
1779 params->home_time = -1;
1780 params->channel_num = 0;
1781 memset(¶ms->ssid, 0, sizeof(wlc_ssid_t));
1783 WL_SCAN(("Preparing Scan request\n"));
1784 WL_SCAN(("nprobes=%d\n", params->nprobes));
1785 WL_SCAN(("active_time=%d\n", params->active_time));
1786 WL_SCAN(("passive_time=%d\n", params->passive_time));
1787 WL_SCAN(("home_time=%d\n", params->home_time));
1788 WL_SCAN(("scan_type=%d\n", params->scan_type));
1790 params->nprobes = htod32(params->nprobes);
1791 params->active_time = htod32(params->active_time);
1792 params->passive_time = htod32(params->passive_time);
1793 params->home_time = htod32(params->home_time);
1795 /* if request is null just exit so it will be all channel broadcast scan */
1799 n_ssids = request->n_ssids;
1800 n_channels = request->n_channels;
1802 /* Copy channel array if applicable */
1803 WL_SCAN(("### List of channelspecs to scan ###\n"));
1804 if (n_channels > 0) {
1805 for (i = 0; i < n_channels; i++) {
1807 channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
1808 /* SKIP DFS channels for Secondary interface */
1809 if ((wl->escan_info.ndev != wl_to_prmry_ndev(wl)) &&
1810 (request->channels[i]->flags &
1811 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
1814 if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
1815 chanspec |= WL_CHANSPEC_BAND_2G;
1817 chanspec |= WL_CHANSPEC_BAND_5G;
1820 chanspec |= WL_CHANSPEC_BW_20;
1821 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1823 params->channel_list[j] = channel;
1824 params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
1825 params->channel_list[j] |= chanspec;
1826 WL_SCAN(("Chan : %d, Channel spec: %x \n",
1827 channel, params->channel_list[j]));
1828 params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
1832 WL_SCAN(("Scanning all channels\n"));
1835 /* Copy ssid array if applicable */
1836 WL_SCAN(("### List of SSIDs to scan ###\n"));
1838 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
1839 offset = roundup(offset, sizeof(u32));
1840 ptr = (char*)params + offset;
1841 for (i = 0; i < n_ssids; i++) {
1842 memset(&ssid, 0, sizeof(wlc_ssid_t));
1843 ssid.SSID_len = request->ssids[i].ssid_len;
1844 memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
1846 WL_SCAN(("%d: Broadcast scan\n", i));
1848 WL_SCAN(("%d: scan for %s size =%d\n", i,
1849 ssid.SSID, ssid.SSID_len));
1850 memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
1851 ptr += sizeof(wlc_ssid_t);
1854 WL_SCAN(("Broadcast scan\n"));
1856 /* Adding mask to channel numbers */
1857 params->channel_num =
1858 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
1859 (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
1861 if (n_channels == 1) {
1862 params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
1863 params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
1868 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, u16 action)
1873 (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
1874 struct wl_iscan_params *params = NULL;
1877 if (request != NULL) {
1878 n_channels = request->n_channels;
1879 n_ssids = request->n_ssids;
1880 /* Allocate space for populating ssids in wl_iscan_params struct */
1882 /* If n_channels is odd, add a padd of u16 */
1883 params_size += sizeof(u16) * (n_channels + 1);
1885 params_size += sizeof(u16) * n_channels;
1887 /* Allocate space for populating ssids in wl_iscan_params struct */
1888 params_size += sizeof(struct wlc_ssid) * n_ssids;
1890 params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
1895 wl_scan_prep(¶ms->params, request);
1897 params->version = htod32(ISCAN_REQ_VERSION);
1898 params->action = htod16(action);
1899 params->scan_duration = htod16(0);
1901 if (params_size + sizeof("iscan") >= WLC_IOCTL_MEDLEN) {
1902 WL_ERR(("ioctl buffer length is not sufficient\n"));
1906 err = wldev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
1907 iscan->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
1908 if (unlikely(err)) {
1909 if (err == -EBUSY) {
1910 WL_ERR(("system busy : iscan canceled\n"));
1912 WL_ERR(("error (%d)\n", err));
1922 static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request)
1924 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
1925 struct net_device *ndev = wl_to_prmry_ndev(wl);
1929 iscan->state = WL_ISCAN_STATE_SCANING;
1931 passive_scan = wl->active_scan ? 0 : 1;
1932 err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
1933 &passive_scan, sizeof(passive_scan), true);
1934 if (unlikely(err)) {
1935 WL_DBG(("error (%d)\n", err));
1938 wl->iscan_kickstart = true;
1939 wl_run_iscan(iscan, request, WL_SCAN_ACTION_START);
1940 mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
1941 iscan->timer_on = 1;
1946 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
1948 wl_uint32_list_t *list;
1950 if (valid_chan_list == NULL || size <= 0)
1953 memset(valid_chan_list, 0, size);
1954 list = (wl_uint32_list_t *)(void *) valid_chan_list;
1955 list->count = htod32(WL_NUMCHANNELS);
1956 err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
1958 WL_ERR(("get channels failed with %d\n", err));
1964 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
1965 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
1967 g_first_broadcast_scan = TRUE;
1971 wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
1972 struct cfg80211_scan_request *request, uint16 action)
1977 s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
1978 wl_escan_params_t *params = NULL;
1979 u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
1983 s32 search_state = WL_P2P_DISC_ST_SCAN;
1984 u32 i, j, n_nodfs = 0;
1985 u16 *default_chan_list = NULL;
1986 wl_uint32_list_t *list;
1987 struct net_device *dev = NULL;
1988 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
1989 bool is_first_init_2g_scan = false;
1991 p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
1993 WL_DBG(("Enter \n"));
1995 /* scan request can come with empty request : perform all default scan */
2000 if (!wl->p2p_supported || !p2p_scan(wl)) {
2001 /* LEGACY SCAN TRIGGER */
2002 WL_SCAN((" LEGACY E-SCAN START\n"));
2004 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2009 if (ndev == wl_to_prmry_ndev(wl) && g_first_broadcast_scan == true) {
2010 is_first_init_2g_scan = true;
2011 g_first_broadcast_scan = false;
2015 /* if scan request is not empty parse scan request paramters */
2016 if (request != NULL) {
2017 n_channels = request->n_channels;
2018 n_ssids = request->n_ssids;
2019 /* Allocate space for populating ssids in wl_iscan_params struct */
2021 /* If n_channels is odd, add a padd of u16 */
2022 params_size += sizeof(u16) * (n_channels + 1);
2024 params_size += sizeof(u16) * n_channels;
2026 /* Allocate space for populating ssids in wl_iscan_params struct */
2027 params_size += sizeof(struct wlc_ssid) * n_ssids;
2029 params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
2030 if (params == NULL) {
2034 wl_scan_prep(¶ms->params, request);
2036 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2037 /* Override active_time to reduce scan time if it's first bradcast scan. */
2038 if (is_first_init_2g_scan)
2039 params->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
2042 params->version = htod32(ESCAN_REQ_VERSION);
2043 params->action = htod16(action);
2044 wl_escan_set_sync_id(params->sync_id, wl);
2045 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
2046 WL_ERR(("ioctl buffer length not sufficient\n"));
2051 err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
2052 wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2053 if (unlikely(err)) {
2054 if (err == BCME_EPERM)
2055 /* Scan Not permitted at this point of time */
2056 WL_DBG((" Escan not permitted at this time (%d)\n", err));
2058 WL_ERR((" Escan set error (%d)\n", err));
2062 else if (p2p_is_on(wl) && p2p_scan(wl)) {
2063 /* P2P SCAN TRIGGER */
2066 if (request && request->n_channels) {
2067 num_chans = request->n_channels;
2068 WL_SCAN((" chann number : %d\n", num_chans));
2069 default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
2071 if (default_chan_list == NULL) {
2072 WL_ERR(("channel list allocation failed \n"));
2076 if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
2077 list = (wl_uint32_list_t *) chan_buf;
2078 n_valid_chan = dtoh32(list->count);
2079 for (i = 0; i < num_chans; i++)
2081 _freq = request->channels[i]->center_freq;
2082 channel = ieee80211_frequency_to_channel(_freq);
2084 /* ignore DFS channels */
2085 if (request->channels[i]->flags &
2086 (IEEE80211_CHAN_RADAR
2087 | IEEE80211_CHAN_PASSIVE_SCAN))
2090 for (j = 0; j < n_valid_chan; j++) {
2091 /* allows only supported channel on
2094 if (channel == (dtoh32(list->element[j])))
2095 default_chan_list[n_nodfs++] =
2101 if (num_chans == SOCIAL_CHAN_CNT && (
2102 (default_chan_list[0] == SOCIAL_CHAN_1) &&
2103 (default_chan_list[1] == SOCIAL_CHAN_2) &&
2104 (default_chan_list[2] == SOCIAL_CHAN_3))) {
2105 /* SOCIAL CHANNELS 1, 6, 11 */
2106 search_state = WL_P2P_DISC_ST_SEARCH;
2107 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2108 WL_INFO(("P2P SEARCH PHASE START \n"));
2109 } else if ((dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)) &&
2110 (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP)) {
2111 /* If you are already a GO, then do SEARCH only */
2112 WL_INFO(("Already a GO. Do SEARCH Only"));
2113 search_state = WL_P2P_DISC_ST_SEARCH;
2114 num_chans = n_nodfs;
2115 p2p_scan_purpose = P2P_SCAN_NORMAL;
2117 } else if (num_chans == 1) {
2118 p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
2119 } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
2120 /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2123 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2125 WL_INFO(("P2P SCAN STATE START \n"));
2126 num_chans = n_nodfs;
2127 p2p_scan_purpose = P2P_SCAN_NORMAL;
2133 err = wl_cfgp2p_escan(wl, ndev, wl->active_scan, num_chans, default_chan_list,
2134 search_state, action,
2135 wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE), NULL,
2139 wl->p2p->search_state = search_state;
2141 kfree(default_chan_list);
2144 if (unlikely(err)) {
2145 /* Don't print Error incase of Scan suppress */
2146 if ((err == BCME_EPERM) && wl->scan_suppressed)
2147 WL_DBG(("Escan failed: Scan Suppressed \n"));
2149 WL_ERR(("error (%d)\n", err));
2156 wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev,
2157 struct cfg80211_scan_request *request)
2161 wl_scan_results_t *results;
2162 WL_SCAN(("Enter \n"));
2163 mutex_lock(&wl->usr_sync);
2165 results = wl_escan_get_buf(wl, FALSE);
2166 results->version = 0;
2168 results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
2170 wl->escan_info.ndev = ndev;
2171 wl->escan_info.wiphy = wiphy;
2172 wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
2173 passive_scan = wl->active_scan ? 0 : 1;
2174 err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2175 &passive_scan, sizeof(passive_scan), true);
2176 if (unlikely(err)) {
2177 WL_ERR(("error (%d)\n", err));
2181 err = wl_run_escan(wl, ndev, request, WL_SCAN_ACTION_START);
2183 mutex_unlock(&wl->usr_sync);
2188 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2189 struct cfg80211_scan_request *request,
2190 struct cfg80211_ssid *this_ssid)
2192 struct wl_priv *wl = wiphy_priv(wiphy);
2193 struct cfg80211_ssid *ssids;
2194 struct wl_scan_req *sr = wl_to_sr(wl);
2195 struct ether_addr primary_mac;
2198 bool escan_req = false;
2204 unsigned long flags;
2205 static s32 busy_count = 0;
2209 dhd = (dhd_pub_t *)(wl->pub);
2210 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
2211 WL_ERR(("Invalid Scan Command at SoftAP mode\n"));
2215 ndev = ndev_to_wlc_ndev(ndev, wl);
2217 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl)) {
2218 WL_ERR(("Sending Action Frames. Try it again.\n"));
2222 WL_DBG(("Enter wiphy (%p)\n", wiphy));
2223 if (wl_get_drv_status_all(wl, SCANNING)) {
2224 if (wl->scan_request == NULL) {
2225 wl_clr_drv_status_all(wl, SCANNING);
2226 WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
2228 WL_ERR(("Scanning already\n"));
2232 if (wl_get_drv_status(wl, SCAN_ABORTING, ndev)) {
2233 WL_ERR(("Scanning being aborted\n"));
2236 if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
2237 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
2240 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2241 if (wl_get_drv_status_all(wl, REMAINING_ON_CHANNEL)) {
2242 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
2243 wl_notify_escan_complete(wl, ndev, true, true);
2245 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
2248 /* Arm scan timeout timer */
2249 mod_timer(&wl->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
2251 if (request) { /* scan bss */
2252 ssids = request->ssids;
2253 if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) {
2255 } else if (wl->escan_on) {
2258 for (i = 0; i < request->n_ssids; i++) {
2259 if (ssids[i].ssid_len &&
2260 IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
2266 if (wl->p2p_supported) {
2267 /* p2p scan trigger */
2268 if (p2p_on(wl) == false) {
2269 /* p2p on at the first time */
2271 wl_cfgp2p_set_firm_p2p(wl);
2272 get_primary_mac(wl, &primary_mac);
2273 wl_cfgp2p_generate_bss_mac(&primary_mac,
2274 &wl->p2p->dev_addr, &wl->p2p->int_addr);
2276 wl_clr_p2p_status(wl, GO_NEG_PHASE);
2277 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
2278 p2p_scan(wl) = true;
2281 /* legacy scan trigger
2282 * So, we have to disable p2p discovery if p2p discovery is on
2284 if (wl->p2p_supported) {
2285 p2p_scan(wl) = false;
2286 /* If Netdevice is not equals to primary and p2p is on
2287 * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
2290 if (p2p_scan(wl) == false) {
2291 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
2292 err = wl_cfgp2p_discover_enable_search(wl,
2294 if (unlikely(err)) {
2301 if (!wl->p2p_supported || !p2p_scan(wl)) {
2303 if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) {
2304 WL_ERR(("Find p2p index from ndev(%p) failed\n",
2309 err = wl_cfgp2p_set_management_ie(wl, ndev, bssidx,
2310 VNDR_IE_PRBREQ_FLAG, (u8 *)request->ie,
2313 if (unlikely(err)) {
2320 } else { /* scan in ibss */
2321 /* we don't do iscan in ibss */
2324 if (request && !p2p_scan(wl))
2325 WL_TRACE_HW4(("START SCAN\n"));
2326 wl->scan_request = request;
2327 wl_set_drv_status(wl, SCANNING, ndev);
2329 err = wl_do_iscan(wl, request);
2334 } else if (escan_req) {
2335 if (wl->p2p_supported) {
2336 if (p2p_on(wl) && p2p_scan(wl)) {
2338 /* find my listen channel */
2339 wl->afx_hdl->my_listen_chan =
2340 wl_find_listen_channel(wl, request->ie,
2342 err = wl_cfgp2p_enable_discovery(wl, ndev,
2343 request->ie, request->ie_len);
2345 if (unlikely(err)) {
2350 err = wl_do_escan(wl, wiphy, ndev, request);
2358 memset(&sr->ssid, 0, sizeof(sr->ssid));
2360 min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
2361 if (sr->ssid.SSID_len) {
2362 memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
2363 sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
2364 WL_SCAN(("Specific scan ssid=\"%s\" len=%d\n",
2365 sr->ssid.SSID, sr->ssid.SSID_len));
2367 WL_SCAN(("Broadcast scan\n"));
2369 WL_SCAN(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
2370 passive_scan = wl->active_scan ? 0 : 1;
2371 err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2372 &passive_scan, sizeof(passive_scan), true);
2373 if (unlikely(err)) {
2374 WL_SCAN(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
2377 err = wldev_ioctl(ndev, WLC_SCAN, &sr->ssid,
2378 sizeof(sr->ssid), false);
2380 if (err == -EBUSY) {
2381 WL_ERR(("system busy : scan for \"%s\" "
2382 "canceled\n", sr->ssid.SSID));
2384 WL_ERR(("WLC_SCAN error (%d)\n", err));
2396 if (err == BCME_BUSY || err == BCME_NOTREADY) {
2397 WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
2401 #define SCAN_EBUSY_RETRY_LIMIT 10
2402 if (err == -EBUSY) {
2403 if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
2404 struct ether_addr bssid;
2407 WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
2408 wl_get_drv_status(wl, SCANNING, ndev),
2409 wl_get_drv_status(wl, SCAN_ABORTING, ndev),
2410 wl_get_drv_status(wl, CONNECTING, ndev),
2411 wl_get_drv_status(wl, CONNECTED, ndev),
2412 wl_get_drv_status(wl, DISCONNECTING, ndev),
2413 wl_get_drv_status(wl, AP_CREATING, ndev),
2414 wl_get_drv_status(wl, AP_CREATED, ndev),
2415 wl_get_drv_status(wl, SENDING_ACT_FRM, ndev),
2416 wl_get_drv_status(wl, SENDING_ACT_FRM, ndev)));
2418 bzero(&bssid, sizeof(bssid));
2419 if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID,
2420 &bssid, ETHER_ADDR_LEN, false)) == 0)
2421 WL_ERR(("FW is connected with " MACDBG "/n",
2422 MAC2STRDBG(bssid.octet)));
2424 WL_ERR(("GET BSSID failed with %d\n", ret));
2426 wl_cfg80211_scan_abort(wl);
2432 wl_clr_drv_status(wl, SCANNING, ndev);
2433 if (timer_pending(&wl->scan_timeout))
2434 del_timer_sync(&wl->scan_timeout);
2435 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
2436 wl->scan_request = NULL;
2437 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
2442 #if defined(WL_CFG80211_P2P_DEV_IF)
2444 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
2447 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2448 struct cfg80211_scan_request *request)
2449 #endif /* WL_CFG80211_P2P_DEV_IF */
2452 struct wl_priv *wl = wiphy_priv(wiphy);
2453 #if defined(WL_CFG80211_P2P_DEV_IF)
2454 struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, wl);
2455 #endif /* WL_CFG80211_P2P_DEV_IF */
2457 WL_DBG(("Enter \n"));
2458 RETURN_EIO_IF_NOT_UP(wl);
2460 err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
2461 if (unlikely(err)) {
2462 if ((err == BCME_EPERM) && wl->scan_suppressed)
2463 WL_DBG(("scan not permitted at this time (%d)\n", err));
2465 WL_ERR(("scan error (%d)\n", err));
2472 static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
2476 err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
2477 if (unlikely(err)) {
2478 WL_ERR(("Error (%d)\n", err));
2484 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
2488 err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
2489 if (unlikely(err)) {
2490 WL_ERR(("Error (%d)\n", err));
2496 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
2499 u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
2501 retry = htod32(retry);
2502 err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true);
2503 if (unlikely(err)) {
2504 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
2510 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
2512 struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
2513 struct net_device *ndev = wl_to_prmry_ndev(wl);
2516 RETURN_EIO_IF_NOT_UP(wl);
2517 WL_DBG(("Enter\n"));
2518 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
2519 (wl->conf->rts_threshold != wiphy->rts_threshold)) {
2520 wl->conf->rts_threshold = wiphy->rts_threshold;
2521 err = wl_set_rts(ndev, wl->conf->rts_threshold);
2525 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
2526 (wl->conf->frag_threshold != wiphy->frag_threshold)) {
2527 wl->conf->frag_threshold = wiphy->frag_threshold;
2528 err = wl_set_frag(ndev, wl->conf->frag_threshold);
2532 if (changed & WIPHY_PARAM_RETRY_LONG &&
2533 (wl->conf->retry_long != wiphy->retry_long)) {
2534 wl->conf->retry_long = wiphy->retry_long;
2535 err = wl_set_retry(ndev, wl->conf->retry_long, true);
2539 if (changed & WIPHY_PARAM_RETRY_SHORT &&
2540 (wl->conf->retry_short != wiphy->retry_short)) {
2541 wl->conf->retry_short = wiphy->retry_short;
2542 err = wl_set_retry(ndev, wl->conf->retry_short, false);
2551 channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
2553 struct wl_priv *wl = wiphy_priv(wiphy);
2555 wl_uint32_list_t *list;
2557 chanspec_t c = 0, ret_c = 0;
2558 int bw = 0, tmp_bw = 0;
2561 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2562 #define LOCAL_BUF_SIZE 1024
2563 buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
2565 WL_ERR(("buf memory alloc failed\n"));
2568 list = (wl_uint32_list_t *)(void *)buf;
2569 list->count = htod32(WL_NUMCHANSPECS);
2570 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
2571 0, buf, LOCAL_BUF_SIZE, 0, &wl->ioctl_buf_sync);
2572 if (err != BCME_OK) {
2573 WL_ERR(("get chanspecs failed with %d\n", err));
2576 for (i = 0; i < dtoh32(list->count); i++) {
2577 c = dtoh32(list->element[i]);
2578 if (channel <= CH_MAX_2G_CHANNEL) {
2579 if (!CHSPEC_IS20(c))
2581 if (channel == CHSPEC_CHANNEL(c)) {
2587 if (CHSPEC_IS20(c)) {
2588 tmp_c = CHSPEC_CHANNEL(c);
2589 tmp_bw = WLC_BW_CAP_20MHZ;
2591 else if (CHSPEC_IS40(c)) {
2592 tmp_c = CHSPEC_CHANNEL(c);
2593 if (CHSPEC_SB_UPPER(c)) {
2594 tmp_c += CH_10MHZ_APART;
2596 tmp_c -= CH_10MHZ_APART;
2598 tmp_bw = WLC_BW_CAP_40MHZ;
2601 tmp_c = CHSPEC_CHANNEL(c);
2602 sb = c & WL_CHANSPEC_CTL_SB_MASK;
2603 if (sb == WL_CHANSPEC_CTL_SB_LL) {
2604 tmp_c -= (CH_10MHZ_APART + CH_20MHZ_APART);
2605 } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
2606 tmp_c -= CH_10MHZ_APART;
2607 } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
2608 tmp_c += CH_10MHZ_APART;
2610 /* WL_CHANSPEC_CTL_SB_UU */
2611 tmp_c += (CH_10MHZ_APART + CH_20MHZ_APART);
2613 tmp_bw = WLC_BW_CAP_80MHZ;
2615 if (tmp_c != channel)
2618 if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
2628 #undef LOCAL_BUF_SIZE
2629 WL_INFO(("return chanspec %x %d\n", ret_c, bw));
2634 wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len)
2636 struct wl_priv *wl = wlcfg_drv_priv;
2638 if (wl != NULL && ibss_vsie != NULL) {
2639 if (wl->ibss_vsie != NULL) {
2640 kfree(wl->ibss_vsie);
2642 wl->ibss_vsie = ibss_vsie;
2643 wl->ibss_vsie_len = ibss_vsie_len;
2648 wl_cfg80211_ibss_vsie_free(struct wl_priv *wl)
2650 /* free & initiralize VSIE (Vendor Specific IE) */
2651 if (wl->ibss_vsie != NULL) {
2652 kfree(wl->ibss_vsie);
2653 wl->ibss_vsie = NULL;
2654 wl->ibss_vsie_len = 0;
2659 wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
2661 struct wl_priv *wl = wlcfg_drv_priv;
2662 char *ioctl_buf = NULL;
2665 if (wl != NULL && wl->ibss_vsie != NULL) {
2666 ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
2668 WL_ERR(("ioctl memory alloc failed\n"));
2672 /* change the command from "add" to "del" */
2673 strncpy(wl->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
2674 wl->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
2676 ret = wldev_iovar_setbuf(dev, "ie",
2677 wl->ibss_vsie, wl->ibss_vsie_len,
2678 ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2679 WL_ERR(("ret=%d\n", ret));
2681 if (ret == BCME_OK) {
2682 /* free & initiralize VSIE */
2683 kfree(wl->ibss_vsie);
2684 wl->ibss_vsie = NULL;
2685 wl->ibss_vsie_len = 0;
2697 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
2698 struct cfg80211_ibss_params *params)
2700 struct wl_priv *wl = wiphy_priv(wiphy);
2701 struct cfg80211_bss *bss;
2702 struct ieee80211_channel *chan;
2703 struct wl_join_params join_params;
2704 struct cfg80211_ssid ssid;
2707 int scan_suppress = 1;
2708 size_t join_params_size;
2709 chanspec_t chanspec = 0;
2710 u32 param[2] = {0, 0};
2714 RETURN_EIO_IF_NOT_UP(wl);
2715 WL_INFO(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
2716 if (!params->ssid || params->ssid_len <= 0) {
2717 WL_ERR(("Invalid parameter\n"));
2721 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
2722 chan = params->chandef.chan;
2724 chan = params->channel;
2725 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) */
2727 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
2728 if (wl_get_drv_status(wl, CONNECTED, dev)) {
2729 struct wlc_ssid *ssid = (struct wlc_ssid *)wl_read_prof(wl, dev, WL_PROF_SSID);
2730 u8 *bssid = (u8 *)wl_read_prof(wl, dev, WL_PROF_BSSID);
2731 u32 *channel = (u32 *)wl_read_prof(wl, dev, WL_PROF_CHAN);
2732 if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
2733 (memcmp(params->ssid, ssid->SSID, ssid->SSID_len) == 0) &&
2734 (*channel == wl->channel))) {
2735 WL_ERR(("Connection already existed to " MACDBG "\n",
2736 MAC2STRDBG((u8 *)wl_read_prof(wl, dev, WL_PROF_BSSID))));
2739 WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
2740 ssid->SSID, MAC2STRDBG(bssid)));
2743 /* remove the VSIE */
2744 wl_cfg80211_ibss_vsie_delete(dev);
2746 bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
2748 if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
2749 memcpy(ssid.ssid, params->ssid, params->ssid_len);
2750 ssid.ssid_len = params->ssid_len;
2753 (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
2759 } while (++scan_retry < WL_SCAN_RETRY_MAX);
2761 /* wait 4 secons till scan done.... */
2762 schedule_timeout_interruptible(msecs_to_jiffies(4000));
2763 bss = cfg80211_get_ibss(wiphy, NULL,
2764 params->ssid, params->ssid_len);
2767 if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
2768 ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
2769 !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
2770 wl->ibss_starter = false;
2771 WL_DBG(("Found IBSS\n"));
2773 wl->ibss_starter = true;
2776 if (chan->band == IEEE80211_BAND_5GHZ)
2777 param[0] = WLC_BAND_5G;
2778 else if (chan->band == IEEE80211_BAND_2GHZ)
2779 param[0] = WLC_BAND_2G;
2780 err = wldev_iovar_getint(dev, "bw_cap", param);
2781 if (unlikely(err)) {
2782 WL_ERR(("Get bw_cap Failed (%d)\n", err));
2786 chanspec = channel_to_chanspec(wiphy, dev, wl->channel, bw_cap);
2789 * Join with specific BSSID and cached SSID
2790 * If SSID is zero join based on BSSID only
2792 memset(&join_params, 0, sizeof(join_params));
2793 memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
2795 join_params.ssid.SSID_len = htod32(params->ssid_len);
2796 if (params->bssid) {
2797 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
2798 err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
2799 ETHER_ADDR_LEN, true);
2800 if (unlikely(err)) {
2801 WL_ERR(("Error (%d)\n", err));
2805 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
2807 wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED);
2809 if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
2810 scan_suppress = TRUE;
2811 /* Set the SCAN SUPRESS Flag in the firmware to skip join scan */
2812 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS, &scan_suppress, sizeof(int), true);
2813 if (unlikely(err)) {
2814 WL_ERR(("Scan Supress Setting failed(%d)\n", err));
2819 join_params.params.chanspec_list[0] = chanspec;
2820 join_params.params.chanspec_num = 1;
2821 wldev_iovar_setint(dev, "chanspec", chanspec);
2822 join_params_size = sizeof(join_params);
2824 /* Disable Authentication, IBSS will add key if it required */
2825 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
2826 wldev_iovar_setint(dev, "wsec", 0);
2828 err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
2829 join_params_size, true);
2830 if (unlikely(err)) {
2831 WL_ERR(("Error (%d)\n", err));
2835 if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
2836 scan_suppress = FALSE;
2837 /* Restore the SCAN SUPPRESS Falg */
2838 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
2839 &scan_suppress, sizeof(int), true);
2840 if (unlikely(err)) {
2841 WL_ERR(("Reset SCAN Suppress Flag failed (%d)\n", err));
2845 wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID);
2846 wl_update_prof(wl, dev, NULL, &wl->channel, WL_PROF_CHAN);
2850 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
2852 struct wl_priv *wl = wiphy_priv(wiphy);
2857 RETURN_EIO_IF_NOT_UP(wl);
2859 WL_ERR(("Leave IBSS\n"));
2860 curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
2861 wl_set_drv_status(wl, DISCONNECTING, dev);
2863 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
2864 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
2865 sizeof(scb_val_t), true);
2866 if (unlikely(err)) {
2867 wl_clr_drv_status(wl, DISCONNECTING, dev);
2868 WL_ERR(("error(%d)\n", err));
2872 /* remove the VSIE */
2873 wl_cfg80211_ibss_vsie_delete(dev);
2880 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
2882 struct wl_priv *wl = wlcfg_drv_priv;
2883 struct wl_security *sec;
2887 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
2888 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
2892 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
2893 val = WPA_AUTH_PSK |
2894 WPA_AUTH_UNSPECIFIED;
2895 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
2896 val = WPA2_AUTH_PSK|
2897 WPA2_AUTH_UNSPECIFIED;
2899 val = WPA_AUTH_DISABLED;
2901 if (is_wps_conn(sme))
2902 val = WPA_AUTH_DISABLED;
2904 WL_DBG(("setting wpa_auth to 0x%0x\n", val));
2905 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
2906 if (unlikely(err)) {
2907 WL_ERR(("set wpa_auth failed (%d)\n", err));
2910 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
2911 sec->wpa_versions = sme->crypto.wpa_versions;
2917 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
2919 struct wl_priv *wl = wlcfg_drv_priv;
2920 struct wl_security *sec;
2924 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
2925 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
2929 switch (sme->auth_type) {
2930 case NL80211_AUTHTYPE_OPEN_SYSTEM:
2931 val = WL_AUTH_OPEN_SYSTEM;
2932 WL_DBG(("open system\n"));
2934 case NL80211_AUTHTYPE_SHARED_KEY:
2935 val = WL_AUTH_SHARED_KEY;
2936 WL_DBG(("shared key\n"));
2938 case NL80211_AUTHTYPE_AUTOMATIC:
2939 val = WL_AUTH_OPEN_SHARED;
2940 WL_DBG(("automatic\n"));
2944 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
2948 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
2949 if (unlikely(err)) {
2950 WL_ERR(("set auth failed (%d)\n", err));
2953 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
2954 sec->auth_type = sme->auth_type;
2959 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
2961 struct wl_priv *wl = wlcfg_drv_priv;
2962 struct wl_security *sec;
2969 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
2970 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
2974 if (sme->crypto.n_ciphers_pairwise) {
2975 switch (sme->crypto.ciphers_pairwise[0]) {
2976 case WLAN_CIPHER_SUITE_WEP40:
2977 case WLAN_CIPHER_SUITE_WEP104:
2980 case WLAN_CIPHER_SUITE_TKIP:
2981 pval = TKIP_ENABLED;
2983 case WLAN_CIPHER_SUITE_CCMP:
2984 case WLAN_CIPHER_SUITE_AES_CMAC:
2988 WL_ERR(("invalid cipher pairwise (%d)\n",
2989 sme->crypto.ciphers_pairwise[0]));
2993 if (sme->crypto.cipher_group) {
2994 switch (sme->crypto.cipher_group) {
2995 case WLAN_CIPHER_SUITE_WEP40:
2996 case WLAN_CIPHER_SUITE_WEP104:
2999 case WLAN_CIPHER_SUITE_TKIP:
3000 gval = TKIP_ENABLED;
3002 case WLAN_CIPHER_SUITE_CCMP:
3005 case WLAN_CIPHER_SUITE_AES_CMAC:
3009 WL_ERR(("invalid cipher group (%d)\n",
3010 sme->crypto.cipher_group));
3015 WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
3017 if (is_wps_conn(sme)) {
3019 err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
3021 /* WPS-2.0 allows no security */
3022 err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
3024 WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
3025 wsec_val = pval | gval;
3027 WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
3028 err = wldev_iovar_setint_bsscfg(dev, "wsec",
3031 if (unlikely(err)) {
3032 WL_ERR(("error (%d)\n", err));
3036 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3037 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
3038 sec->cipher_group = sme->crypto.cipher_group;
3044 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
3046 struct wl_priv *wl = wlcfg_drv_priv;
3047 struct wl_security *sec;
3051 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3052 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3056 if (sme->crypto.n_akm_suites) {
3057 err = wldev_iovar_getint(dev, "wpa_auth", &val);
3058 if (unlikely(err)) {
3059 WL_ERR(("could not get wpa_auth (%d)\n", err));
3062 if (val & (WPA_AUTH_PSK |
3063 WPA_AUTH_UNSPECIFIED)) {
3064 switch (sme->crypto.akm_suites[0]) {
3065 case WLAN_AKM_SUITE_8021X:
3066 val = WPA_AUTH_UNSPECIFIED;
3068 case WLAN_AKM_SUITE_PSK:
3072 WL_ERR(("invalid cipher group (%d)\n",
3073 sme->crypto.cipher_group));
3076 } else if (val & (WPA2_AUTH_PSK |
3077 WPA2_AUTH_UNSPECIFIED)) {
3078 switch (sme->crypto.akm_suites[0]) {
3079 case WLAN_AKM_SUITE_8021X:
3080 val = WPA2_AUTH_UNSPECIFIED;
3082 case WLAN_AKM_SUITE_PSK:
3083 val = WPA2_AUTH_PSK;
3086 WL_ERR(("invalid cipher group (%d)\n",
3087 sme->crypto.cipher_group));
3091 WL_DBG(("setting wpa_auth to %d\n", val));
3094 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
3095 if (unlikely(err)) {
3096 WL_ERR(("could not set wpa_auth (%d)\n", err));
3100 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3101 sec->wpa_auth = sme->crypto.akm_suites[0];
3107 wl_set_set_sharedkey(struct net_device *dev,
3108 struct cfg80211_connect_params *sme)
3110 struct wl_priv *wl = wlcfg_drv_priv;
3111 struct wl_security *sec;
3112 struct wl_wsec_key key;
3116 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3117 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3121 WL_DBG(("key len (%d)\n", sme->key_len));
3123 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3124 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
3125 sec->wpa_versions, sec->cipher_pairwise));
3126 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
3127 NL80211_WPA_VERSION_2)) &&
3128 (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
3129 WLAN_CIPHER_SUITE_WEP104)))
3131 memset(&key, 0, sizeof(key));
3132 key.len = (u32) sme->key_len;
3133 key.index = (u32) sme->key_idx;
3134 if (unlikely(key.len > sizeof(key.data))) {
3135 WL_ERR(("Too long key length (%u)\n", key.len));
3138 memcpy(key.data, sme->key, key.len);
3139 key.flags = WL_PRIMARY_KEY;
3140 switch (sec->cipher_pairwise) {
3141 case WLAN_CIPHER_SUITE_WEP40:
3142 key.algo = CRYPTO_ALGO_WEP1;
3144 case WLAN_CIPHER_SUITE_WEP104:
3145 key.algo = CRYPTO_ALGO_WEP128;
3148 WL_ERR(("Invalid algorithm (%d)\n",
3149 sme->crypto.ciphers_pairwise[0]));
3152 /* Set the new key/index */
3153 WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
3154 key.len, key.index, key.algo));
3155 WL_DBG(("key \"%s\"\n", key.data));
3156 swap_key_from_BE(&key);
3157 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
3158 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3159 if (unlikely(err)) {
3160 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3163 if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
3164 WL_DBG(("set auth_type to shared key\n"));
3165 val = WL_AUTH_SHARED_KEY; /* shared key */
3166 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
3167 if (unlikely(err)) {
3168 WL_ERR(("set auth failed (%d)\n", err));
3177 #if defined(ESCAN_RESULT_PATCH)
3178 static u8 connect_req_bssid[6];
3179 static u8 broad_bssid[6];
3180 #endif /* ESCAN_RESULT_PATCH */
3185 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
3186 struct cfg80211_connect_params *sme)
3188 struct wl_priv *wl = wiphy_priv(wiphy);
3189 struct ieee80211_channel *chan = sme->channel;
3190 wl_extjoin_params_t *ext_join_params;
3191 struct wl_join_params join_params;
3192 size_t join_params_size;
3194 wpa_ie_fixed_t *wpa_ie;
3199 struct ether_addr bssid;
3206 if (unlikely(!sme->ssid)) {
3207 WL_ERR(("Invalid ssid\n"));
3211 if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
3212 WL_ERR(("Invalid SSID info: SSID=%s, length=%d\n",
3213 sme->ssid, sme->ssid_len));
3217 RETURN_EIO_IF_NOT_UP(wl);
3220 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
3222 #if !defined(ESCAN_RESULT_PATCH)
3223 if (wl->scan_request) {
3224 wl_notify_escan_complete(wl, dev, true, true);
3227 #if defined(ESCAN_RESULT_PATCH)
3229 memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
3231 bzero(connect_req_bssid, ETHER_ADDR_LEN);
3232 bzero(broad_bssid, ETHER_ADDR_LEN);
3234 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
3237 bzero(&bssid, sizeof(bssid));
3238 if (!wl_get_drv_status(wl, CONNECTED, dev)&&
3239 (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
3240 if (!ETHER_ISNULLADDR(&bssid)) {
3242 wl_set_drv_status(wl, DISCONNECTING, dev);
3243 scbval.val = DOT11_RC_DISASSOC_LEAVING;
3244 memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
3245 scbval.val = htod32(scbval.val);
3247 WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n",
3248 MAC2STRDBG(bssid.octet)));
3249 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3250 sizeof(scb_val_t), true);
3251 if (unlikely(err)) {
3252 wl_clr_drv_status(wl, DISCONNECTING, dev);
3253 WL_ERR(("error (%d)\n", err));
3257 while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) {
3258 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
3264 WL_DBG(("Currently not associated!\n"));
3266 /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */
3268 while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) {
3269 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt));
3276 bzero(&bssid, sizeof(bssid));
3277 if (!wl_get_drv_status(wl, DISCONNECTING, dev))
3278 wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
3280 if (p2p_is_on(wl) && (dev != wl_to_prmry_ndev(wl))) {
3281 /* we only allow to connect using virtual interface in case of P2P */
3282 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3283 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3286 wl_cfgp2p_set_management_ie(wl, dev, bssidx,
3287 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
3288 } else if (dev == wl_to_prmry_ndev(wl)) {
3289 /* find the RSN_IE */
3290 if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
3291 DOT11_MNG_RSN_ID)) != NULL) {
3292 WL_DBG((" WPA2 IE is found\n"));
3294 /* find the WPA_IE */
3295 if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
3296 sme->ie_len)) != NULL) {
3297 WL_DBG((" WPA IE is found\n"));
3299 if (wpa_ie != NULL || wpa2_ie != NULL) {
3300 wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
3301 wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
3302 wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
3303 wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
3304 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
3306 wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
3307 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
3310 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3311 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3314 err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
3315 VNDR_IE_ASSOCREQ_FLAG, (u8 *)sme->ie, sme->ie_len);
3316 if (unlikely(err)) {
3321 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
3323 WL_DBG(("channel (%d), center_req (%d), %d channels\n", wl->channel,
3324 chan->center_freq, chan_cnt));
3327 WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
3328 WL_DBG(("3. set wapi version \n"));
3329 err = wl_set_wpa_version(dev, sme);
3330 if (unlikely(err)) {
3331 WL_ERR(("Invalid wpa_version\n"));
3334 err = wl_set_auth_type(dev, sme);
3335 if (unlikely(err)) {
3336 WL_ERR(("Invalid auth type\n"));
3340 err = wl_set_set_cipher(dev, sme);
3341 if (unlikely(err)) {
3342 WL_ERR(("Invalid ciper\n"));
3346 err = wl_set_key_mgmt(dev, sme);
3347 if (unlikely(err)) {
3348 WL_ERR(("Invalid key mgmt\n"));
3352 err = wl_set_set_sharedkey(dev, sme);
3353 if (unlikely(err)) {
3354 WL_ERR(("Invalid shared key\n"));
3359 * Join with specific BSSID and cached SSID
3360 * If SSID is zero join based on BSSID only
3362 join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
3363 chan_cnt * sizeof(chanspec_t);
3364 ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
3365 if (ext_join_params == NULL) {
3367 wl_clr_drv_status(wl, CONNECTING, dev);
3370 ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
3371 memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
3372 wl_update_prof(wl, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
3373 ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
3374 /* increate dwell time to receive probe response or detect Beacon
3375 * from target AP at a noisy air only when channel info is provided in connect command
3377 ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
3378 ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
3379 /* Set up join scan parameters */
3380 ext_join_params->scan.scan_type = -1;
3381 ext_join_params->scan.nprobes = chan_cnt ?
3382 (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
3383 ext_join_params->scan.home_time = -1;
3386 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
3388 memcpy(&ext_join_params->assoc.bssid, ðer_bcast, ETH_ALEN);
3389 ext_join_params->assoc.chanspec_num = chan_cnt;
3391 u16 channel, band, bw, ctl_sb;
3393 channel = wl->channel;
3394 band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
3395 : WL_CHANSPEC_BAND_5G;
3396 bw = WL_CHANSPEC_BW_20;
3397 ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
3398 chspec = (channel | band | bw | ctl_sb);
3399 ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
3400 ext_join_params->assoc.chanspec_list[0] |= chspec;
3401 ext_join_params->assoc.chanspec_list[0] =
3402 wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
3404 ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
3405 if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
3406 WL_INFO(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
3407 ext_join_params->ssid.SSID_len));
3409 wl_set_drv_status(wl, CONNECTING, dev);
3411 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3412 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3415 err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
3416 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3418 WL_ERR(("Connectting with" MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n",
3419 MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), wl->channel,
3420 ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len));
3422 kfree(ext_join_params);
3424 wl_clr_drv_status(wl, CONNECTING, dev);
3425 if (err == BCME_UNSUPPORTED) {
3426 WL_DBG(("join iovar is not supported\n"));
3429 WL_ERR(("error (%d)\n", err));
3434 memset(&join_params, 0, sizeof(join_params));
3435 join_params_size = sizeof(join_params.ssid);
3437 join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
3438 memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
3439 join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
3440 wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID);
3442 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
3444 memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN);
3446 wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
3447 WL_DBG(("join_param_size %zu\n", join_params_size));
3449 if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
3450 WL_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
3451 join_params.ssid.SSID_len));
3453 wl_set_drv_status(wl, CONNECTING, dev);
3454 err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
3456 WL_ERR(("error (%d)\n", err));
3457 wl_clr_drv_status(wl, CONNECTING, dev);
3464 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
3467 struct wl_priv *wl = wiphy_priv(wiphy);
3472 WL_ERR(("Reason %d\n", reason_code));
3473 RETURN_EIO_IF_NOT_UP(wl);
3474 act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT);
3475 curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
3478 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
3480 #if !defined(ESCAN_RESULT_PATCH)
3481 /* Let scan aborted by F/W */
3482 if (wl->scan_request) {
3483 wl_notify_escan_complete(wl, dev, true, true);
3485 #endif /* ESCAN_RESULT_PATCH */
3486 wl_set_drv_status(wl, DISCONNECTING, dev);
3487 scbval.val = reason_code;
3488 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
3489 scbval.val = htod32(scbval.val);
3490 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3491 sizeof(scb_val_t), true);
3492 if (unlikely(err)) {
3493 wl_clr_drv_status(wl, DISCONNECTING, dev);
3494 WL_ERR(("error (%d)\n", err));
3502 #if defined(WL_CFG80211_P2P_DEV_IF)
3504 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
3505 enum nl80211_tx_power_setting type, s32 mbm)
3508 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
3509 enum nl80211_tx_power_setting type, s32 dbm)
3510 #endif /* WL_CFG80211_P2P_DEV_IF */
3513 struct wl_priv *wl = wiphy_priv(wiphy);
3514 struct net_device *ndev = wl_to_prmry_ndev(wl);
3519 #if defined(WL_CFG80211_P2P_DEV_IF)
3520 s32 dbm = MBM_TO_DBM(mbm);
3521 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
3522 defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
3523 dbm = MBM_TO_DBM(dbm);
3524 #endif /* WL_CFG80211_P2P_DEV_IF */
3526 RETURN_EIO_IF_NOT_UP(wl);
3528 case NL80211_TX_POWER_AUTOMATIC:
3530 case NL80211_TX_POWER_LIMITED:
3532 WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
3536 case NL80211_TX_POWER_FIXED:
3538 WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
3543 /* Make sure radio is off or on as far as software is concerned */
3544 disable = WL_RADIO_SW_DISABLE << 16;
3545 disable = htod32(disable);
3546 err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), true);
3547 if (unlikely(err)) {
3548 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
3555 txpwrmw = (u16) dbm;
3556 txpwrqdbm = (s32)bcm_mw_to_qdbm(txpwrmw);
3557 #ifdef SUPPORT_WL_TXPOWER
3558 if (type == NL80211_TX_POWER_AUTOMATIC)
3561 txpwrqdbm |= WL_TXPWR_OVERRIDE;
3562 #endif /* SUPPORT_WL_TXPOWER */
3563 err = wldev_iovar_setint(ndev, "qtxpower", txpwrqdbm);
3564 if (unlikely(err)) {
3565 WL_ERR(("qtxpower error (%d)\n", err));
3568 wl->conf->tx_power = dbm;
3573 #if defined(WL_CFG80211_P2P_DEV_IF)
3574 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
3575 struct wireless_dev *wdev, s32 *dbm)
3577 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
3578 #endif /* WL_CFG80211_P2P_DEV_IF */
3580 struct wl_priv *wl = wiphy_priv(wiphy);
3581 struct net_device *ndev = wl_to_prmry_ndev(wl);
3586 RETURN_EIO_IF_NOT_UP(wl);
3587 err = wldev_iovar_getint(ndev, "qtxpower", &txpwrdbm);
3588 if (unlikely(err)) {
3589 WL_ERR(("error (%d)\n", err));
3592 result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
3593 *dbm = (s32) bcm_qdbm_to_mw(result);
3599 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
3600 u8 key_idx, bool unicast, bool multicast)
3602 struct wl_priv *wl = wiphy_priv(wiphy);
3607 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3608 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3612 WL_DBG(("key index (%d)\n", key_idx));
3613 RETURN_EIO_IF_NOT_UP(wl);
3614 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
3615 if (unlikely(err)) {
3616 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
3619 /* fix IOT issue with Apple Airport */
3620 if (wsec == WEP_ENABLED) {
3621 /* Just select a new current key */
3622 index = (u32) key_idx;
3623 index = htod32(index);
3624 err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
3625 sizeof(index), true);
3626 if (unlikely(err)) {
3627 WL_ERR(("error (%d)\n", err));
3634 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
3635 u8 key_idx, const u8 *mac_addr, struct key_params *params)
3637 struct wl_priv *wl = wiphy_priv(wiphy);
3638 struct wl_wsec_key key;
3641 s32 mode = wl_get_mode_by_netdev(wl, dev);
3642 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3643 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3646 memset(&key, 0, sizeof(key));
3647 key.index = (u32) key_idx;
3649 if (!ETHER_ISMULTI(mac_addr))
3650 memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
3651 key.len = (u32) params->key_len;
3653 /* check for key index change */
3656 swap_key_from_BE(&key);
3657 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
3658 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3659 if (unlikely(err)) {
3660 WL_ERR(("key delete error (%d)\n", err));
3664 if (key.len > sizeof(key.data)) {
3665 WL_ERR(("Invalid key length (%d)\n", key.len));
3668 WL_DBG(("Setting the key index %d\n", key.index));
3669 memcpy(key.data, params->key, key.len);
3671 if ((mode == WL_MODE_BSS) &&
3672 (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
3674 memcpy(keybuf, &key.data[24], sizeof(keybuf));
3675 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
3676 memcpy(&key.data[16], keybuf, sizeof(keybuf));
3679 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
3680 if (params->seq && params->seq_len == 6) {
3683 ivptr = (u8 *) params->seq;
3684 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
3685 (ivptr[3] << 8) | ivptr[2];
3686 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
3687 key.iv_initialized = true;
3690 switch (params->cipher) {
3691 case WLAN_CIPHER_SUITE_WEP40:
3692 key.algo = CRYPTO_ALGO_WEP1;
3693 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
3695 case WLAN_CIPHER_SUITE_WEP104:
3696 key.algo = CRYPTO_ALGO_WEP128;
3697 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
3699 case WLAN_CIPHER_SUITE_TKIP:
3700 key.algo = CRYPTO_ALGO_TKIP;
3701 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
3703 case WLAN_CIPHER_SUITE_AES_CMAC:
3704 key.algo = CRYPTO_ALGO_AES_CCM;
3705 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
3707 case WLAN_CIPHER_SUITE_CCMP:
3708 key.algo = CRYPTO_ALGO_AES_CCM;
3709 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
3712 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
3715 swap_key_from_BE(&key);
3716 /* need to guarantee EAPOL 4/4 send out before set key */
3717 if (mode != WL_MODE_AP)
3718 dhd_wait_pend8021x(dev);
3719 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
3720 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3721 if (unlikely(err)) {
3722 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3730 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
3731 u8 key_idx, bool pairwise, const u8 *mac_addr,
3732 struct key_params *params)
3734 struct wl_wsec_key key;
3740 struct wl_priv *wl = wiphy_priv(wiphy);
3741 s32 mode = wl_get_mode_by_netdev(wl, dev);
3742 WL_DBG(("key index (%d)\n", key_idx));
3743 RETURN_EIO_IF_NOT_UP(wl);
3745 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3746 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3751 ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
3752 (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
3753 wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
3756 memset(&key, 0, sizeof(key));
3758 key.len = (u32) params->key_len;
3759 key.index = (u32) key_idx;
3761 if (unlikely(key.len > sizeof(key.data))) {
3762 WL_ERR(("Too long key length (%u)\n", key.len));
3765 memcpy(key.data, params->key, key.len);
3767 key.flags = WL_PRIMARY_KEY;
3768 switch (params->cipher) {
3769 case WLAN_CIPHER_SUITE_WEP40:
3770 key.algo = CRYPTO_ALGO_WEP1;
3772 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
3774 case WLAN_CIPHER_SUITE_WEP104:
3775 key.algo = CRYPTO_ALGO_WEP128;
3777 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
3779 case WLAN_CIPHER_SUITE_TKIP:
3780 key.algo = CRYPTO_ALGO_TKIP;
3782 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
3783 if (mode == WL_MODE_BSS) {
3784 bcopy(&key.data[24], keybuf, sizeof(keybuf));
3785 bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
3786 bcopy(keybuf, &key.data[16], sizeof(keybuf));
3788 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
3790 case WLAN_CIPHER_SUITE_AES_CMAC:
3791 key.algo = CRYPTO_ALGO_AES_CCM;
3793 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
3795 case WLAN_CIPHER_SUITE_CCMP:
3796 key.algo = CRYPTO_ALGO_AES_CCM;
3798 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
3801 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
3805 /* Set the new key/index */
3806 if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
3807 WL_ERR(("IBSS KEY setted\n"));
3808 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
3810 swap_key_from_BE(&key);
3811 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf,
3812 WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3813 if (unlikely(err)) {
3814 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3819 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
3820 if (unlikely(err)) {
3821 WL_ERR(("get wsec error (%d)\n", err));
3826 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
3827 if (unlikely(err)) {
3828 WL_ERR(("set wsec error (%d)\n", err));
3836 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
3837 u8 key_idx, bool pairwise, const u8 *mac_addr)
3839 struct wl_wsec_key key;
3840 struct wl_priv *wl = wiphy_priv(wiphy);
3845 return ERR_PTR(-EINVAL);
3847 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3848 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3851 WL_DBG(("Enter\n"));
3854 if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
3858 RETURN_EIO_IF_NOT_UP(wl);
3859 memset(&key, 0, sizeof(key));
3861 key.flags = WL_PRIMARY_KEY;
3862 key.algo = CRYPTO_ALGO_OFF;
3863 key.index = (u32) key_idx;
3865 WL_DBG(("key index (%d)\n", key_idx));
3866 /* Set the new key/index */
3867 swap_key_from_BE(&key);
3868 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf,
3869 WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3870 if (unlikely(err)) {
3871 if (err == -EINVAL) {
3872 if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
3873 /* we ignore this key index in this case */
3874 WL_DBG(("invalid key index (%d)\n", key_idx));
3877 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3885 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
3886 u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
3887 void (*callback) (void *cookie, struct key_params * params))
3889 struct key_params params;
3890 struct wl_wsec_key key;
3891 struct wl_priv *wl = wiphy_priv(wiphy);
3892 struct wl_security *sec;
3896 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3897 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3900 WL_DBG(("key index (%d)\n", key_idx));
3901 RETURN_EIO_IF_NOT_UP(wl);
3902 memset(&key, 0, sizeof(key));
3903 key.index = key_idx;
3904 swap_key_to_BE(&key);
3905 memset(¶ms, 0, sizeof(params));
3906 params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
3907 memcpy(params.key, key.data, params.key_len);
3909 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
3910 if (unlikely(err)) {
3911 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
3914 switch (wsec & ~SES_OW_ENABLED) {
3916 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3917 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
3918 params.cipher = WLAN_CIPHER_SUITE_WEP40;
3919 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
3920 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
3921 params.cipher = WLAN_CIPHER_SUITE_WEP104;
3922 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
3926 params.cipher = WLAN_CIPHER_SUITE_TKIP;
3927 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
3930 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
3931 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
3934 WL_ERR(("Invalid algo (0x%x)\n", wsec));
3938 callback(cookie, ¶ms);
3943 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
3944 struct net_device *dev, u8 key_idx)
3946 WL_INFO(("Not supported\n"));
3951 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
3952 u8 *mac, struct station_info *sinfo)
3954 struct wl_priv *wl = wiphy_priv(wiphy);
3960 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) || 0
3961 s8 eabuf[ETHER_ADDR_STR_LEN];
3963 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
3964 RETURN_EIO_IF_NOT_UP(wl);
3965 if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
3966 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
3967 ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync);
3969 WL_ERR(("GET STA INFO failed, %d\n", err));
3972 sinfo->filled = STATION_INFO_INACTIVE_TIME;
3973 sta = (sta_info_t *)wl->ioctl_buf;
3974 sta->len = dtoh16(sta->len);
3975 sta->cap = dtoh16(sta->cap);
3976 sta->flags = dtoh32(sta->flags);
3977 sta->idle = dtoh32(sta->idle);
3978 sta->in = dtoh32(sta->in);
3979 sinfo->inactive_time = sta->idle * 1000;
3980 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) || 0
3981 if (sta->flags & WL_STA_ASSOC) {
3982 sinfo->filled |= STATION_INFO_CONNECTED_TIME;
3983 sinfo->connected_time = sta->in;
3985 WL_INFO(("STA %s : idle time : %d sec, connected time :%d ms\n",
3986 bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
3989 } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS ||
3990 wl_get_mode_by_netdev(wl, dev) == WL_MODE_IBSS) {
3991 get_pktcnt_t pktcnt;
3992 u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID);
3993 if (!wl_get_drv_status(wl, CONNECTED, dev) ||
3994 (dhd_is_associated(dhd, NULL, &err) == FALSE)) {
3995 WL_ERR(("NOT assoc\n"));
3996 if (err == -ERESTARTSYS)
4001 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
4002 WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
4003 MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
4006 /* Report the current tx rate */
4007 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
4009 WL_ERR(("Could not get rate (%d)\n", err));
4011 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4014 rate = dtoh32(rate);
4015 sinfo->filled |= STATION_INFO_TX_BITRATE;
4016 sinfo->txrate.legacy = rate * 5;
4017 WL_DBG(("Rate %d Mbps\n", (rate / 2)));
4018 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4019 rxpktglom = ((rate/2) > 150) ? 20 : 10;
4021 if (maxrxpktglom != rxpktglom) {
4022 maxrxpktglom = rxpktglom;
4023 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
4025 err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
4026 (char*)&maxrxpktglom, 4, wl->ioctl_buf,
4027 WLC_IOCTL_MAXLEN, NULL);
4029 WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
4035 memset(&scb_val, 0, sizeof(scb_val));
4037 err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
4038 sizeof(scb_val_t), false);
4040 WL_ERR(("Could not get rssi (%d)\n", err));
4041 goto get_station_err;
4043 rssi = wl_rssi_offset(dtoh32(scb_val.val));
4044 sinfo->filled |= STATION_INFO_SIGNAL;
4045 sinfo->signal = rssi;
4046 WL_DBG(("RSSI %d dBm\n", rssi));
4047 err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt,
4048 sizeof(pktcnt), false);
4050 sinfo->filled |= (STATION_INFO_RX_PACKETS |
4051 STATION_INFO_RX_DROP_MISC |
4052 STATION_INFO_TX_PACKETS |
4053 STATION_INFO_TX_FAILED);
4054 sinfo->rx_packets = pktcnt.rx_good_pkt;
4055 sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
4056 sinfo->tx_packets = pktcnt.tx_good_pkt;
4057 sinfo->tx_failed = pktcnt.tx_bad_pkt;
4060 if (err && (err != -ERESTARTSYS)) {
4061 /* Disconnect due to zero BSSID or error to get RSSI */
4062 WL_ERR(("force cfg80211_disconnected: %d\n", err));
4063 wl_clr_drv_status(wl, CONNECTED, dev);
4064 cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL);
4069 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(wl, dev)));
4075 /* Function to update sta power save mode for Kernel wifi stack */
4076 int wl_cfg80211_update_power_mode(struct net_device *dev)
4081 err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), false);
4082 if (err || (pm == -1)) {
4083 WL_ERR(("error (%d)\n", err));
4085 pm = (pm == PM_OFF) ? false : true;
4086 WL_DBG(("%s: %d\n", __func__, pm));
4087 if (dev->ieee80211_ptr)
4088 dev->ieee80211_ptr->ps = pm;
4094 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
4095 bool enabled, s32 timeout)
4099 struct wl_priv *wl = wiphy_priv(wiphy);
4100 struct net_info *_net_info = wl_get_netinfo_by_netdev(wl, dev);
4101 #if !defined(SUPPORT_PM2_ONLY)
4102 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
4103 #endif /* (OEM_ANDROID) */
4104 RETURN_EIO_IF_NOT_UP(wl);
4105 WL_DBG(("Enter\n"));
4106 #if defined(WL_ENABLE_P2P_IF)
4107 if (wl->p2p_net == dev || _net_info == NULL || wl->vsdb_mode ||
4108 !wl_get_drv_status(wl, CONNECTED, dev)) {
4110 if (_net_info == NULL || wl->vsdb_mode ||
4111 !wl_get_drv_status(wl, CONNECTED, dev)) {
4112 #endif /* WL_ENABLE_P2P_IF */
4115 WL_DBG(("%s: Enter power save enabled %d\n", dev->name, enabled));
4117 /* Delete pm_enable_work */
4118 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_PEND);
4120 #if !defined(SUPPORT_PM2_ONLY)
4121 /* android has special hooks to change pm when kernel suspended */
4122 pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF;
4124 pm = enabled ? PM_FAST : PM_OFF;
4125 #endif /* SUPPORT_PM2_ONLY */
4126 if (_net_info->pm_block) {
4127 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
4128 dev->name, _net_info->pm_block));
4132 WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
4133 err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
4134 if (unlikely(err)) {
4136 WL_DBG(("net_device is not ready yet\n"));
4138 WL_ERR(("error (%d)\n", err));
4144 static __used u32 wl_find_msb(u16 bit16)
4148 if (bit16 & 0xff00) {
4171 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
4173 struct wl_priv *wl = wiphy_priv(wiphy);
4174 struct net_device *ndev = wl_to_prmry_ndev(wl);
4177 if (unlikely(!wl_get_drv_status(wl, READY, ndev))) {
4178 WL_INFO(("device is not ready\n"));
4182 wl_invoke_iscan(wl);
4187 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
4188 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
4190 static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
4193 #ifdef DHD_CLEAR_ON_SUSPEND
4194 struct wl_priv *wl = wiphy_priv(wiphy);
4195 struct net_info *iter, *next;
4196 struct net_device *ndev = wl_to_prmry_ndev(wl);
4197 unsigned long flags;
4198 if (unlikely(!wl_get_drv_status(wl, READY, ndev))) {
4199 WL_INFO(("device is not ready : status (%d)\n",
4203 for_each_ndev(wl, iter, next)
4204 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
4206 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
4207 if (wl->scan_request) {
4208 cfg80211_scan_done(wl->scan_request, true);
4209 wl->scan_request = NULL;
4211 for_each_ndev(wl, iter, next) {
4212 wl_clr_drv_status(wl, SCANNING, iter->ndev);
4213 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
4215 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
4216 for_each_ndev(wl, iter, next) {
4217 if (wl_get_drv_status(wl, CONNECTING, iter->ndev)) {
4218 wl_bss_connect_done(wl, iter->ndev, NULL, NULL, false);
4221 #endif /* DHD_CLEAR_ON_SUSPEND */
4226 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
4230 struct wl_priv *wl = wlcfg_drv_priv;
4231 struct net_device *primary_dev = wl_to_prmry_ndev(wl);
4234 printk("pmk_list is NULL\n");
4237 /* pmk list is supported only for STA interface i.e. primary interface
4238 * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
4240 if (primary_dev != dev) {
4241 WL_INFO(("Not supporting Flushing pmklist on virtual"
4242 " interfaces than primary interface\n"));
4246 WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
4247 for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
4248 WL_DBG(("PMKID[%d]: %pM =\n", i,
4249 &pmk_list->pmkids.pmkid[i].BSSID));
4250 for (j = 0; j < WPA2_PMKID_LEN; j++) {
4251 WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
4255 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
4256 sizeof(*pmk_list), wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
4263 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
4264 struct cfg80211_pmksa *pmksa)
4266 struct wl_priv *wl = wiphy_priv(wiphy);
4270 RETURN_EIO_IF_NOT_UP(wl);
4271 for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
4272 if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
4275 if (i < WL_NUM_PMKIDS_MAX) {
4276 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
4278 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
4280 if (i == wl->pmk_list->pmkids.npmkid)
4281 wl->pmk_list->pmkids.npmkid++;
4285 WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
4286 &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].BSSID));
4287 for (i = 0; i < WPA2_PMKID_LEN; i++) {
4289 wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].
4293 err = wl_update_pmklist(dev, wl->pmk_list, err);
4299 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
4300 struct cfg80211_pmksa *pmksa)
4302 struct wl_priv *wl = wiphy_priv(wiphy);
4303 struct _pmkid_list pmkid = {0};
4307 RETURN_EIO_IF_NOT_UP(wl);
4308 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
4309 memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
4311 WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
4312 &pmkid.pmkid[0].BSSID));
4313 for (i = 0; i < WPA2_PMKID_LEN; i++) {
4314 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
4317 for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
4319 (pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
4323 if ((wl->pmk_list->pmkids.npmkid > 0) &&
4324 (i < wl->pmk_list->pmkids.npmkid)) {
4325 memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
4326 for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
4327 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
4328 &wl->pmk_list->pmkids.pmkid[i + 1].BSSID,
4330 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
4331 &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
4334 wl->pmk_list->pmkids.npmkid--;
4339 err = wl_update_pmklist(dev, wl->pmk_list, err);
4346 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
4348 struct wl_priv *wl = wiphy_priv(wiphy);
4350 RETURN_EIO_IF_NOT_UP(wl);
4351 memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
4352 err = wl_update_pmklist(dev, wl->pmk_list, err);
4357 static wl_scan_params_t *
4358 wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
4360 wl_scan_params_t *params;
4364 *out_params_size = 0;
4366 /* Our scan params only need space for 1 channel and 0 ssids */
4367 params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
4368 params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
4369 if (params == NULL) {
4370 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
4373 memset(params, 0, params_size);
4374 params->nprobes = nprobes;
4376 num_chans = (channel == 0) ? 0 : 1;
4378 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
4379 params->bss_type = DOT11_BSSTYPE_ANY;
4380 params->scan_type = DOT11_SCANTYPE_ACTIVE;
4381 params->nprobes = htod32(1);
4382 params->active_time = htod32(-1);
4383 params->passive_time = htod32(-1);
4384 params->home_time = htod32(10);
4386 params->channel_list[0] = htodchanspec(channel);
4388 params->channel_list[0] = wl_ch_host_to_driver(channel);
4390 /* Our scan params have 1 channel and 0 ssids */
4391 params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
4392 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
4394 *out_params_size = params_size; /* rtn size to the caller */
4398 #if defined(WL_CFG80211_P2P_DEV_IF)
4400 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4401 struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
4404 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4405 struct ieee80211_channel * channel,
4406 enum nl80211_channel_type channel_type,
4407 unsigned int duration, u64 *cookie)
4408 #endif /* WL_CFG80211_P2P_DEV_IF */
4413 struct ether_addr primary_mac;
4414 struct net_device *ndev = NULL;
4415 struct wl_priv *wl = wiphy_priv(wiphy);
4418 return ERR_PTR(-EINVAL);
4420 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
4422 WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
4423 ieee80211_frequency_to_channel(channel->center_freq),
4424 duration, (wl_get_drv_status(wl, SCANNING, ndev)) ? "YES":"NO"));
4427 WL_ERR(("wl->p2p is not initialized\n"));
4432 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4433 if (wl_get_drv_status_all(wl, SCANNING)) {
4434 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
4436 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4438 target_channel = ieee80211_frequency_to_channel(channel->center_freq);
4439 memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel));
4440 #if defined(WL_ENABLE_P2P_IF)
4441 wl->remain_on_chan_type = channel_type;
4442 #endif /* WL_ENABLE_P2P_IF */
4443 id = ++wl->last_roc_id;
4445 id = ++wl->last_roc_id;
4448 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4449 if (wl_get_drv_status(wl, SCANNING, ndev)) {
4450 struct timer_list *_timer;
4451 WL_DBG(("scan is running. go to fake listen state\n"));
4453 wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4455 if (timer_pending(&wl->p2p->listen_timer)) {
4456 WL_DBG(("cancel current listen timer \n"));
4457 del_timer_sync(&wl->p2p->listen_timer);
4460 _timer = &wl->p2p->listen_timer;
4461 wl_clr_p2p_status(wl, LISTEN_EXPIRED);
4463 INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
4468 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4470 #ifdef WL_CFG80211_SYNC_GON
4471 if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) {
4472 /* do not enter listen mode again if we are in listen mode already for next af.
4473 * remain on channel completion will be returned by waiting next af completion.
4475 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4476 wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4478 wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4479 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4482 #endif /* WL_CFG80211_SYNC_GON */
4483 if (wl->p2p && !wl->p2p->on) {
4484 /* In case of p2p_listen command, supplicant send remain_on_channel
4485 * without turning on P2P
4487 get_primary_mac(wl, &primary_mac);
4488 wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
4492 if (p2p_is_on(wl)) {
4493 err = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0);
4494 if (unlikely(err)) {
4497 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4498 wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4499 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4500 err = wl_cfgp2p_discover_listen(wl, target_channel, duration);
4502 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4503 if (err == BCME_OK) {
4504 wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4506 /* if failed, firmware may be internal scanning state.
4507 * so other scan request shall not abort it
4509 wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4511 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4512 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
4513 * and expire timer will send a completion to the upper layer
4519 if (err == BCME_OK) {
4520 WL_INFO(("Success\n"));
4521 #if defined(WL_CFG80211_P2P_DEV_IF)
4522 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
4523 duration, GFP_KERNEL);
4525 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
4526 channel_type, duration, GFP_KERNEL);
4527 #endif /* WL_CFG80211_P2P_DEV_IF */
4529 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
4535 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
4536 bcm_struct_cfgdev *cfgdev, u64 cookie)
4540 #if defined(WL_CFG80211_P2P_DEV_IF)
4541 if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
4542 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
4545 WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
4546 #endif /* WL_CFG80211_P2P_DEV_IF */
4551 wl_cfg80211_afx_handler(struct work_struct *work)
4553 struct afx_hdl *afx_instance;
4554 struct wl_priv *wl = wlcfg_drv_priv;
4557 afx_instance = container_of(work, struct afx_hdl, work);
4558 if (afx_instance != NULL && wl->afx_hdl->is_active) {
4559 if (wl->afx_hdl->is_listen && wl->afx_hdl->my_listen_chan) {
4560 ret = wl_cfgp2p_discover_listen(wl, wl->afx_hdl->my_listen_chan,
4561 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
4563 ret = wl_cfgp2p_act_frm_search(wl, wl->afx_hdl->dev,
4564 wl->afx_hdl->bssidx, wl->afx_hdl->peer_listen_chan,
4567 if (unlikely(ret != BCME_OK)) {
4568 WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
4569 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL))
4570 complete(&wl->act_frm_scan);
4576 wl_cfg80211_af_searching_channel(struct wl_priv *wl, struct net_device *dev)
4578 u32 max_retry = WL_CHANNEL_SYNC_RETRY;
4583 WL_DBG((" enter ) \n"));
4585 wl_set_drv_status(wl, FINDING_COMMON_CHANNEL, dev);
4586 wl->afx_hdl->is_active = TRUE;
4588 /* Loop to wait until we find a peer's channel or the
4589 * pending action frame tx is cancelled.
4591 while ((wl->afx_hdl->retry < max_retry) &&
4592 (wl->afx_hdl->peer_chan == WL_INVALID)) {
4593 wl->afx_hdl->is_listen = FALSE;
4594 wl_set_drv_status(wl, SCANNING, dev);
4595 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
4596 wl->afx_hdl->retry));
4597 /* search peer on peer's listen channel */
4598 schedule_work(&wl->afx_hdl->work);
4599 wait_for_completion_timeout(&wl->act_frm_scan,
4600 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
4602 if ((wl->afx_hdl->peer_chan != WL_INVALID) ||
4603 !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)))
4606 if (wl->afx_hdl->my_listen_chan) {
4607 WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
4608 wl->afx_hdl->my_listen_chan));
4609 /* listen on my listen channel */
4610 wl->afx_hdl->is_listen = TRUE;
4611 schedule_work(&wl->afx_hdl->work);
4612 wait_for_completion_timeout(&wl->act_frm_scan,
4613 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
4615 if ((wl->afx_hdl->peer_chan != WL_INVALID) ||
4616 !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)))
4619 wl->afx_hdl->retry++;
4621 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
4624 wl->afx_hdl->is_active = FALSE;
4626 wl_clr_drv_status(wl, SCANNING, dev);
4627 wl_clr_drv_status(wl, FINDING_COMMON_CHANNEL, dev);
4629 return (wl->afx_hdl->peer_chan);
4632 struct p2p_config_af_params {
4633 s32 max_tx_retry; /* max tx retry count if tx no ack */
4634 /* To make sure to send successfully action frame, we have to turn off mpc
4635 * 0: off, 1: on, (-1): do nothing
4638 #ifdef WL_CFG80211_SYNC_GON
4641 bool search_channel; /* 1: search peer's channel to send af */
4645 wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
4646 wl_action_frame_t *action_frame, wl_af_params_t *af_params,
4647 struct p2p_config_af_params *config_af_params)
4650 struct wl_priv *wl = wiphy_priv(wiphy);
4651 wifi_p2p_pub_act_frame_t *act_frm =
4652 (wifi_p2p_pub_act_frame_t *) (action_frame->data);
4654 /* initialize default value */
4655 #ifdef WL_CFG80211_SYNC_GON
4656 config_af_params->extra_listen = true;
4658 config_af_params->search_channel = false;
4659 config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
4660 config_af_params->mpc_onoff = -1;
4661 wl->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
4663 switch (act_frm->subtype) {
4664 case P2P_PAF_GON_REQ: {
4665 WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
4666 wl_set_p2p_status(wl, GO_NEG_PHASE);
4668 config_af_params->mpc_onoff = 0;
4669 config_af_params->search_channel = true;
4670 wl->next_af_subtype = act_frm->subtype + 1;
4672 /* increase dwell time to wait for RESP frame */
4673 af_params->dwell_time = WL_MED_DWELL_TIME;
4677 case P2P_PAF_GON_RSP: {
4678 wl->next_af_subtype = act_frm->subtype + 1;
4679 /* increase dwell time to wait for CONF frame */
4680 af_params->dwell_time = WL_MED_DWELL_TIME + 100;
4683 case P2P_PAF_GON_CONF: {
4684 /* If we reached till GO Neg confirmation reset the filter */
4685 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
4686 wl_clr_p2p_status(wl, GO_NEG_PHASE);
4688 /* turn on mpc again if go nego is done */
4689 config_af_params->mpc_onoff = 1;
4691 /* minimize dwell time */
4692 af_params->dwell_time = WL_MIN_DWELL_TIME;
4694 #ifdef WL_CFG80211_SYNC_GON
4695 config_af_params->extra_listen = false;
4696 #endif /* WL_CFG80211_SYNC_GON */
4699 case P2P_PAF_INVITE_REQ: {
4700 config_af_params->search_channel = true;
4701 wl->next_af_subtype = act_frm->subtype + 1;
4703 /* increase dwell time */
4704 af_params->dwell_time = WL_MED_DWELL_TIME;
4707 case P2P_PAF_INVITE_RSP:
4708 /* minimize dwell time */
4709 af_params->dwell_time = WL_MIN_DWELL_TIME;
4710 #ifdef WL_CFG80211_SYNC_GON
4711 config_af_params->extra_listen = false;
4712 #endif /* WL_CFG80211_SYNC_GON */
4714 case P2P_PAF_DEVDIS_REQ: {
4715 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
4716 action_frame->len)) {
4717 config_af_params->search_channel = true;
4720 wl->next_af_subtype = act_frm->subtype + 1;
4721 /* maximize dwell time to wait for RESP frame */
4722 af_params->dwell_time = WL_LONG_DWELL_TIME;
4725 case P2P_PAF_DEVDIS_RSP:
4726 /* minimize dwell time */
4727 af_params->dwell_time = WL_MIN_DWELL_TIME;
4728 #ifdef WL_CFG80211_SYNC_GON
4729 config_af_params->extra_listen = false;
4730 #endif /* WL_CFG80211_SYNC_GON */
4732 case P2P_PAF_PROVDIS_REQ: {
4733 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
4734 action_frame->len)) {
4735 config_af_params->search_channel = true;
4738 config_af_params->mpc_onoff = 0;
4739 wl->next_af_subtype = act_frm->subtype + 1;
4740 /* increase dwell time to wait for RESP frame */
4741 af_params->dwell_time = WL_MED_DWELL_TIME;
4744 case P2P_PAF_PROVDIS_RSP: {
4745 wl->next_af_subtype = P2P_PAF_GON_REQ;
4746 af_params->dwell_time = WL_MIN_DWELL_TIME;
4747 #ifdef WL_CFG80211_SYNC_GON
4748 config_af_params->extra_listen = false;
4749 #endif /* WL_CFG80211_SYNC_GON */
4753 WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
4763 wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
4764 bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
4765 wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
4767 struct wl_priv *wl = wiphy_priv(wiphy);
4769 u8 category, action;
4771 struct p2p_config_af_params config_af_params;
4773 ulong off_chan_started_jiffies = 0;
4775 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
4778 category = action_frame->data[DOT11_ACTION_CAT_OFF];
4779 action = action_frame->data[DOT11_ACTION_ACT_OFF];
4781 /* initialize variables */
4783 wl->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
4784 config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
4785 config_af_params.mpc_onoff = -1;
4786 config_af_params.search_channel = false;
4787 #ifdef WL_CFG80211_SYNC_GON
4788 config_af_params.extra_listen = false;
4791 /* config parameters */
4792 /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
4793 if (category == DOT11_ACTION_CAT_PUBLIC) {
4794 if ((action == P2P_PUB_AF_ACTION) &&
4795 (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
4796 /* p2p public action frame process */
4797 if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
4798 action_frame, af_params, &config_af_params)) {
4799 WL_DBG(("Unknown subtype.\n"));
4802 } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
4803 /* service discovery process */
4804 if (action == P2PSD_ACTION_ID_GAS_IREQ ||
4805 action == P2PSD_ACTION_ID_GAS_CREQ) {
4806 /* configure service discovery query frame */
4808 config_af_params.search_channel = true;
4810 /* save next af suptype to cancel remained dwell time */
4811 wl->next_af_subtype = action + 1;
4813 af_params->dwell_time = WL_MED_DWELL_TIME;
4814 } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
4815 action == P2PSD_ACTION_ID_GAS_CRESP) {
4816 /* configure service discovery response frame */
4817 af_params->dwell_time = WL_MIN_DWELL_TIME;
4819 WL_DBG(("Unknown action type: %d\n", action));
4822 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
4823 category, action, action_frame_len));
4825 } else if (category == P2P_AF_CATEGORY) {
4826 /* do not configure anything. it will be sent with a default configuration */
4828 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
4830 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
4831 wl_clr_drv_status(wl, SENDING_ACT_FRM, dev);
4836 /* To make sure to send successfully action frame, we have to turn off mpc */
4837 if (config_af_params.mpc_onoff == 0) {
4838 wldev_iovar_setint(dev, "mpc", 0);
4841 /* validate channel and p2p ies */
4842 if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
4843 wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) {
4844 config_af_params.search_channel = true;
4846 config_af_params.search_channel = false;
4850 /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
4851 if (wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) {
4856 /* if scan is ongoing, abort current scan. */
4857 if (wl_get_drv_status_all(wl, SCANNING)) {
4858 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
4862 /* set status and destination address before sending af */
4863 if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
4864 /* set this status to cancel the remained dwell time in rx process */
4865 wl_set_drv_status(wl, WAITING_NEXT_ACT_FRM, dev);
4867 wl_set_drv_status(wl, SENDING_ACT_FRM, dev);
4868 memcpy(wl->afx_hdl->tx_dst_addr.octet,
4869 af_params->action_frame.da.octet,
4870 sizeof(wl->afx_hdl->tx_dst_addr.octet));
4872 /* save af_params for rx process */
4873 wl->afx_hdl->pending_tx_act_frm = af_params;
4875 /* search peer's channel */
4876 if (config_af_params.search_channel) {
4877 /* initialize afx_hdl */
4878 if (wl_cfgp2p_find_idx(wl, dev, &wl->afx_hdl->bssidx) != BCME_OK) {
4879 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4882 wl->afx_hdl->dev = dev;
4883 wl->afx_hdl->retry = 0;
4884 wl->afx_hdl->peer_chan = WL_INVALID;
4886 if (wl_cfg80211_af_searching_channel(wl, dev) == WL_INVALID) {
4887 WL_ERR(("couldn't find peer's channel.\n"));
4888 wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
4889 af_params->channel);
4893 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
4895 * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
4896 * but after the check of piggyback algorithm.
4897 * To take care of current piggback algo, lets abort the scan here itself.
4899 wl_notify_escan_complete(wl, dev, true, true);
4900 /* Suspend P2P discovery's search-listen to prevent it from
4901 * starting a scan or changing the channel.
4903 wl_cfgp2p_discover_enable_search(wl, false);
4905 /* update channel */
4906 af_params->channel = wl->afx_hdl->peer_chan;
4910 off_chan_started_jiffies = jiffies;
4913 wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
4915 /* Now send a tx action frame */
4916 ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ? false : true;
4918 /* if failed, retry it. tx_retry_max value is configure by .... */
4919 while ((ack == false) && (tx_retry++ < config_af_params.max_tx_retry)) {
4921 if (af_params->channel) {
4922 if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
4923 OFF_CHAN_TIME_THRESHOLD_MS) {
4924 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
4925 off_chan_started_jiffies = jiffies;
4927 OSL_SLEEP(AF_RETRY_DELAY_TIME);
4930 ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ?
4934 WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
4937 /* Clear SENDING_ACT_FRM after all sending af is done */
4938 wl_clr_drv_status(wl, SENDING_ACT_FRM, dev);
4940 #ifdef WL_CFG80211_SYNC_GON
4941 /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
4942 * if we coundn't get the next action response frame and dongle does not keep
4943 * the dwell time, go to listen state again to get next action response frame.
4945 if (ack && config_af_params.extra_listen &&
4946 wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM) &&
4947 wl->af_sent_channel == wl->afx_hdl->my_listen_chan) {
4948 s32 extar_listen_time;
4950 extar_listen_time = af_params->dwell_time -
4951 jiffies_to_msecs(jiffies - wl->af_tx_sent_jiffies);
4953 if (extar_listen_time > 50) {
4954 wl_set_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, dev);
4955 WL_DBG(("Wait more time! actual af time:%d,"
4956 "calculated extar listen:%d\n",
4957 af_params->dwell_time, extar_listen_time));
4958 if (wl_cfgp2p_discover_listen(wl, wl->af_sent_channel,
4959 extar_listen_time + 100) == BCME_OK) {
4960 wait_for_completion_timeout(&wl->wait_next_af,
4961 msecs_to_jiffies(extar_listen_time + 100 + 300));
4963 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, dev);
4966 #endif /* WL_CFG80211_SYNC_GON */
4967 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, dev);
4969 if (wl->afx_hdl->pending_tx_act_frm)
4970 wl->afx_hdl->pending_tx_act_frm = NULL;
4972 WL_INFO(("-- sending Action Frame is %s, listen chan: %d\n",
4973 (ack) ? "Succeeded!!":"Failed!!", wl->afx_hdl->my_listen_chan));
4976 /* if all done, turn mpc on again */
4977 if (config_af_params.mpc_onoff == 1) {
4978 wldev_iovar_setint(dev, "mpc", 1);
4984 #define MAX_NUM_OF_ASSOCIATED_DEV 64
4985 #if defined(WL_CFG80211_P2P_DEV_IF)
4987 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4988 struct ieee80211_channel *channel, bool offchan,
4989 unsigned int wait, const u8* buf, size_t len, bool no_cck,
4990 bool dont_wait_for_ack, u64 *cookie)
4993 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4994 struct ieee80211_channel *channel, bool offchan,
4995 enum nl80211_channel_type channel_type,
4996 bool channel_type_valid, unsigned int wait,
4997 const u8* buf, size_t len,
4998 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) || 0
5001 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || 0
5002 bool dont_wait_for_ack,
5005 #endif /* WL_CFG80211_P2P_DEV_IF */
5007 wl_action_frame_t *action_frame;
5008 wl_af_params_t *af_params;
5010 const struct ieee80211_mgmt *mgmt;
5011 struct wl_priv *wl = wiphy_priv(wiphy);
5012 struct net_device *dev = NULL;
5017 s8 eabuf[ETHER_ADDR_STR_LEN];
5019 WL_DBG(("Enter \n"));
5022 return ERR_PTR(-EINVAL);
5023 dev = cfgdev_to_wlc_ndev(cfgdev, wl);
5025 /* find bssidx based on dev */
5026 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
5027 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
5030 if (p2p_is_on(wl)) {
5031 /* Suspend P2P discovery search-listen to prevent it from changing the
5034 if ((err = wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
5035 WL_ERR(("Can not disable discovery mode\n"));
5040 id = wl->send_action_id++;
5042 id = wl->send_action_id++;
5044 mgmt = (const struct ieee80211_mgmt *)buf;
5045 if (ieee80211_is_mgmt(mgmt->frame_control)) {
5046 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
5047 s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
5048 s32 ie_len = len - ie_offset;
5049 if (dev == wl_to_prmry_ndev(wl))
5050 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
5051 wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5052 VNDR_IE_PRBRSP_FLAG, (u8 *)(buf + ie_offset), ie_len);
5053 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
5055 } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
5056 ieee80211_is_deauth(mgmt->frame_control)) {
5057 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
5058 sizeof(struct ether_addr) + sizeof(uint)] = {0};
5059 int num_associated = 0;
5060 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
5061 if (!bcmp((const uint8 *)BSSID_BROADCAST,
5062 (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
5063 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
5064 err = wldev_ioctl(dev, WLC_GET_ASSOCLIST,
5065 assoc_maclist, sizeof(mac_buf), false);
5067 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
5069 num_associated = assoc_maclist->count;
5071 memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
5072 scb_val.val = mgmt->u.disassoc.reason_code;
5073 err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
5074 sizeof(scb_val_t), true);
5076 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
5077 WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
5078 bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
5081 if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
5084 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
5087 } else if (ieee80211_is_action(mgmt->frame_control)) {
5088 /* Abort the dwell time of any previous off-channel
5089 * action frame that may be still in effect. Sending
5090 * off-channel action frames relies on the driver's
5091 * scan engine. If a previous off-channel action frame
5092 * tx is still in progress (including the dwell time),
5093 * then this new action frame will not be sent out.
5095 /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
5096 * And previous off-channel action frame must be ended before new af tx.
5098 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5099 wl_notify_escan_complete(wl, dev, true, true);
5100 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5104 WL_ERR(("Driver only allows MGMT packet type\n"));
5108 af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
5110 if (af_params == NULL)
5112 WL_ERR(("unable to allocate frame\n"));
5116 action_frame = &af_params->action_frame;
5118 /* Add the packet Id */
5119 action_frame->packetId = *cookie;
5120 WL_DBG(("action frame %d\n", action_frame->packetId));
5122 memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
5123 memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
5125 /* Add the length exepted for 802.11 header */
5126 action_frame->len = len - DOT11_MGMT_HDR_LEN;
5127 WL_DBG(("action_frame->len: %d\n", action_frame->len));
5129 /* Add the channel */
5130 af_params->channel =
5131 ieee80211_frequency_to_channel(channel->center_freq);
5133 /* Save listen_chan for searching common channel */
5134 wl->afx_hdl->peer_listen_chan = af_params->channel;
5135 WL_DBG(("channel from upper layer %d\n", wl->afx_hdl->peer_listen_chan));
5137 /* Add the default dwell time
5138 * Dwell time to stay off-channel to wait for a response action frame
5139 * after transmitting an GO Negotiation action frame
5141 af_params->dwell_time = WL_DWELL_TIME;
5143 memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
5145 ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
5146 action_frame, action_frame->len, bssidx);
5147 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
5156 wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5157 u16 frame_type, bool reg)
5160 WL_DBG(("frame_type: %x, reg: %d\n", frame_type, reg));
5162 if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
5170 wl_cfg80211_change_bss(struct wiphy *wiphy,
5171 struct net_device *dev,
5172 struct bss_parameters *params)
5174 if (params->use_cts_prot >= 0) {
5177 if (params->use_short_preamble >= 0) {
5180 if (params->use_short_slot_time >= 0) {
5183 if (params->basic_rates) {
5186 if (params->ap_isolate >= 0) {
5189 if (params->ht_opmode >= 0) {
5196 wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
5197 struct ieee80211_channel *chan,
5198 enum nl80211_channel_type channel_type)
5201 chanspec_t chspec = 0;
5202 chanspec_t fw_chspec = 0;
5203 u32 bw = WL_CHANSPEC_BW_40;
5205 struct net_info *iter, *next;
5208 struct wl_priv *wl = wiphy_priv(wiphy);
5211 return ERR_PTR(-EINVAL);
5212 dev = ndev_to_wlc_ndev(dev, wl);
5213 _chan = ieee80211_frequency_to_channel(chan->center_freq);
5214 WL_ERR(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
5215 dev->ifindex, channel_type, _chan));
5217 /* In 5GHz band If AP is connected in 20 MHz then follow AP's bw
5218 else 40MHz by default. */
5219 for_each_ndev(wl, iter, next) {
5220 /* In case interface name is not wlan0 put the right
5222 if(!strncmp(iter->ndev->name, "wlan0", strlen("wlan0"))) {
5223 if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) {
5224 if (chan->band == IEEE80211_BAND_5GHZ) {
5225 if(wldev_iovar_getint(iter->ndev,
5226 "chanspec", (s32 *)&chanspec) == BCME_OK) {
5227 chanspec = wl_chspec_driver_to_host(chanspec);
5228 /* bits 11,12 and 13 starting from 0 are bw
5229 bits. So, values formed with these bits
5230 are 0 ,1, 2, 3, 4, 5, 6 which are mapped
5231 to 5, 10, 20 ,40 ,80, 160, 80+80 MHz
5232 respectively. In below case, 0x1000 = 2
5233 which is for 20 MHz */
5234 if((chanspec & 0x3800) == 0x1000)
5235 bw = WL_CHANSPEC_BW_20;
5238 /* In 2.4 GHz supported bw is 20 MHz */
5239 bw = WL_CHANSPEC_BW_20;
5245 chspec = wf_channel2chspec(_chan, bw);
5246 if (wf_chspec_valid(chspec)) {
5247 fw_chspec = wl_chspec_host_to_driver(chspec);
5248 if (fw_chspec != INVCHANSPEC) {
5249 if ((err = wldev_iovar_setint(dev, "chanspec",
5250 fw_chspec)) == BCME_BADCHAN) {
5251 if (bw == WL_CHANSPEC_BW_80)
5253 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
5254 &_chan, sizeof(_chan), true);
5256 WL_ERR(("WLC_SET_CHANNEL error %d"
5257 "chip may not be supporting this channel\n", err));
5260 WL_ERR(("failed to set chanspec error %d\n", err));
5263 WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
5268 if (bw == WL_CHANSPEC_BW_80)
5269 bw = WL_CHANSPEC_BW_40;
5270 else if (bw == WL_CHANSPEC_BW_40)
5271 bw = WL_CHANSPEC_BW_20;
5276 WL_ERR(("Invalid chanspec 0x%x\n", chspec));
5283 wl_validate_opensecurity(struct net_device *dev, s32 bssidx)
5288 err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
5290 WL_ERR(("auth error %d\n", err));
5294 err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
5296 WL_ERR(("wsec error %d\n", err));
5299 /* set upper-layer auth */
5300 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", WPA_AUTH_NONE, bssidx);
5302 WL_ERR(("wpa_auth error %d\n", err));
5310 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
5314 u16 auth = 0; /* d11 open authentication */
5319 wpa_suite_mcast_t *mcast;
5320 wpa_suite_ucast_t *ucast;
5321 wpa_suite_auth_key_mgmt_t *mgmt;
5325 u32 wme_bss_disable;
5330 WL_DBG(("Enter \n"));
5332 /* check the mcast cipher */
5333 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
5334 switch (mcast->type) {
5335 case WPA_CIPHER_NONE:
5338 case WPA_CIPHER_WEP_40:
5339 case WPA_CIPHER_WEP_104:
5342 case WPA_CIPHER_TKIP:
5343 gval = TKIP_ENABLED;
5345 case WPA_CIPHER_AES_CCM:
5349 WL_ERR(("No Security Info\n"));
5352 if ((len -= WPA_SUITE_LEN) <= 0)
5355 /* check the unicast cipher */
5356 ucast = (wpa_suite_ucast_t *)&mcast[1];
5357 suite_count = ltoh16_ua(&ucast->count);
5358 switch (ucast->list[0].type) {
5359 case WPA_CIPHER_NONE:
5362 case WPA_CIPHER_WEP_40:
5363 case WPA_CIPHER_WEP_104:
5366 case WPA_CIPHER_TKIP:
5367 pval = TKIP_ENABLED;
5369 case WPA_CIPHER_AES_CCM:
5373 WL_ERR(("No Security Info\n"));
5375 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
5378 /* FOR WPS , set SEC_OW_ENABLED */
5379 wsec = (pval | gval | SES_OW_ENABLED);
5381 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
5382 suite_count = ltoh16_ua(&mgmt->count);
5383 switch (mgmt->list[0].type) {
5385 wpa_auth = WPA_AUTH_NONE;
5387 case RSN_AKM_UNSPECIFIED:
5388 wpa_auth = WPA2_AUTH_UNSPECIFIED;
5391 wpa_auth = WPA2_AUTH_PSK;
5394 WL_ERR(("No Key Mgmt Info\n"));
5397 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
5398 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
5399 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
5401 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
5402 wme_bss_disable = 0;
5404 wme_bss_disable = 1;
5407 /* set wme_bss_disable to sync RSN Capabilities */
5408 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
5410 WL_ERR(("wme_bss_disable error %d\n", err));
5414 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
5418 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5420 WL_ERR(("auth error %d\n", err));
5424 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5426 WL_ERR(("wsec error %d\n", err));
5429 /* set upper-layer auth */
5430 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5432 WL_ERR(("wpa_auth error %d\n", err));
5440 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
5442 wpa_suite_mcast_t *mcast;
5443 wpa_suite_ucast_t *ucast;
5444 wpa_suite_auth_key_mgmt_t *mgmt;
5445 u16 auth = 0; /* d11 open authentication */
5458 WL_DBG(("Enter \n"));
5459 len = wpaie->length; /* value length */
5460 len -= WPA_IE_TAG_FIXED_LEN;
5461 /* check for multicast cipher suite */
5462 if (len < WPA_SUITE_LEN) {
5463 WL_INFO(("no multicast cipher suite\n"));
5467 /* pick up multicast cipher */
5468 mcast = (wpa_suite_mcast_t *)&wpaie[1];
5469 len -= WPA_SUITE_LEN;
5470 if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
5471 if (IS_WPA_CIPHER(mcast->type)) {
5473 switch (mcast->type) {
5474 case WPA_CIPHER_NONE:
5477 case WPA_CIPHER_WEP_40:
5478 case WPA_CIPHER_WEP_104:
5481 case WPA_CIPHER_TKIP:
5484 case WPA_CIPHER_AES_CCM:
5488 WL_ERR(("No Security Info\n"));
5493 /* Check for unicast suite(s) */
5494 if (len < WPA_IE_SUITE_COUNT_LEN) {
5495 WL_INFO(("no unicast suite\n"));
5498 /* walk thru unicast cipher list and pick up what we recognize */
5499 ucast = (wpa_suite_ucast_t *)&mcast[1];
5500 count = ltoh16_ua(&ucast->count);
5501 len -= WPA_IE_SUITE_COUNT_LEN;
5502 for (i = 0; i < count && len >= WPA_SUITE_LEN;
5503 i++, len -= WPA_SUITE_LEN) {
5504 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5505 if (IS_WPA_CIPHER(ucast->list[i].type)) {
5507 switch (ucast->list[i].type) {
5508 case WPA_CIPHER_NONE:
5511 case WPA_CIPHER_WEP_40:
5512 case WPA_CIPHER_WEP_104:
5515 case WPA_CIPHER_TKIP:
5518 case WPA_CIPHER_AES_CCM:
5522 WL_ERR(("No Security Info\n"));
5528 len -= (count - i) * WPA_SUITE_LEN;
5529 /* Check for auth key management suite(s) */
5530 if (len < WPA_IE_SUITE_COUNT_LEN) {
5531 WL_INFO((" no auth key mgmt suite\n"));
5534 /* walk thru auth management suite list and pick up what we recognize */
5535 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
5536 count = ltoh16_ua(&mgmt->count);
5537 len -= WPA_IE_SUITE_COUNT_LEN;
5538 for (i = 0; i < count && len >= WPA_SUITE_LEN;
5539 i++, len -= WPA_SUITE_LEN) {
5540 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5541 if (IS_WPA_AKM(mgmt->list[i].type)) {
5543 switch (mgmt->list[i].type) {
5545 tmp = WPA_AUTH_NONE;
5547 case RSN_AKM_UNSPECIFIED:
5548 tmp = WPA_AUTH_UNSPECIFIED;
5554 WL_ERR(("No Key Mgmt Info\n"));
5561 /* FOR WPS , set SEC_OW_ENABLED */
5562 wsec = (pval | gval | SES_OW_ENABLED);
5564 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5566 WL_ERR(("auth error %d\n", err));
5570 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5572 WL_ERR(("wsec error %d\n", err));
5575 /* set upper-layer auth */
5576 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5578 WL_ERR(("wpa_auth error %d\n", err));
5586 wl_cfg80211_bcn_validate_sec(
5587 struct net_device *dev,
5588 struct parsed_ies *ies,
5592 struct wl_priv *wl = wlcfg_drv_priv;
5594 if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
5595 /* For P2P GO, the sec type is WPA2-PSK */
5596 WL_DBG(("P2P GO: validating wpa2_ie"));
5597 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0)
5600 } else if (dev_role == NL80211_IFTYPE_AP) {
5602 WL_DBG(("SoftAP: validating security"));
5603 /* If wpa2_ie or wpa_ie is present validate it */
5604 if ((ies->wpa2_ie || ies->wpa_ie) &&
5605 ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
5606 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
5607 wl->ap_info->security_mode = false;
5611 wl->ap_info->security_mode = true;
5612 if (wl->ap_info->rsn_ie) {
5613 kfree(wl->ap_info->rsn_ie);
5614 wl->ap_info->rsn_ie = NULL;
5616 if (wl->ap_info->wpa_ie) {
5617 kfree(wl->ap_info->wpa_ie);
5618 wl->ap_info->wpa_ie = NULL;
5620 if (wl->ap_info->wps_ie) {
5621 kfree(wl->ap_info->wps_ie);
5622 wl->ap_info->wps_ie = NULL;
5624 if (ies->wpa_ie != NULL) {
5626 wl->ap_info->rsn_ie = NULL;
5627 wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5628 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5630 } else if (ies->wpa2_ie != NULL) {
5632 wl->ap_info->wpa_ie = NULL;
5633 wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5634 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5638 if (!ies->wpa2_ie && !ies->wpa_ie) {
5639 wl_validate_opensecurity(dev, bssidx);
5640 wl->ap_info->security_mode = false;
5644 wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5652 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
5653 static s32 wl_cfg80211_bcn_set_params(
5654 struct cfg80211_ap_settings *info,
5655 struct net_device *dev,
5656 u32 dev_role, s32 bssidx)
5658 struct wl_priv *wl = wlcfg_drv_priv;
5661 WL_DBG(("interval (%d) \ndtim_period (%d) \n",
5662 info->beacon_interval, info->dtim_period));
5664 if (info->beacon_interval) {
5665 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
5666 &info->beacon_interval, sizeof(s32), true)) < 0) {
5667 WL_ERR(("Beacon Interval Set Error, %d\n", err));
5672 if (info->dtim_period) {
5673 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
5674 &info->dtim_period, sizeof(s32), true)) < 0) {
5675 WL_ERR(("DTIM Interval Set Error, %d\n", err));
5680 if ((info->ssid) && (info->ssid_len > 0) &&
5681 (info->ssid_len <= 32)) {
5682 WL_DBG(("SSID (%s) len:%d \n", info->ssid, info->ssid_len));
5683 if (dev_role == NL80211_IFTYPE_AP) {
5684 /* Store the hostapd SSID */
5685 memset(wl->hostapd_ssid.SSID, 0x00, 32);
5686 memcpy(wl->hostapd_ssid.SSID, info->ssid, info->ssid_len);
5687 wl->hostapd_ssid.SSID_len = info->ssid_len;
5690 memset(wl->p2p->ssid.SSID, 0x00, 32);
5691 memcpy(wl->p2p->ssid.SSID, info->ssid, info->ssid_len);
5692 wl->p2p->ssid.SSID_len = info->ssid_len;
5696 if (info->hidden_ssid) {
5697 if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
5698 WL_ERR(("failed to set hidden : %d\n", err));
5699 WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
5707 wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
5711 memset(ies, 0, sizeof(struct parsed_ies));
5713 /* find the WPSIE */
5714 if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
5715 WL_DBG(("WPSIE in beacon \n"));
5716 ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
5718 WL_ERR(("No WPSIE in beacon \n"));
5721 /* find the RSN_IE */
5722 if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
5723 DOT11_MNG_RSN_ID)) != NULL) {
5724 WL_DBG((" WPA2 IE found\n"));
5725 ies->wpa2_ie_len = ies->wpa2_ie->len;
5728 /* find the WPA_IE */
5729 if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
5730 WL_DBG((" WPA found\n"));
5731 ies->wpa_ie_len = ies->wpa_ie->length;
5739 wl_cfg80211_bcn_bringup_ap(
5740 struct net_device *dev,
5741 struct parsed_ies *ies,
5742 u32 dev_role, s32 bssidx)
5744 struct wl_priv *wl = wlcfg_drv_priv;
5745 struct wl_join_params join_params;
5746 bool is_bssup = false;
5748 s32 join_params_size = 0;
5750 #ifdef DISABLE_11H_SOFTAP
5752 #endif /* DISABLE_11H_SOFTAP */
5755 WL_DBG(("Enter dev_role: %d\n", dev_role));
5757 /* Common code for SoftAP and P2P GO */
5758 wldev_iovar_setint(dev, "mpc", 0);
5760 if (dev_role == NL80211_IFTYPE_P2P_GO) {
5761 is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
5762 if (!is_bssup && (ies->wpa2_ie != NULL)) {
5764 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
5766 WL_ERR(("SET INFRA error %d\n", err));
5770 err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid,
5771 sizeof(wl->p2p->ssid), wl->ioctl_buf, WLC_IOCTL_MAXLEN,
5772 bssidx, &wl->ioctl_buf_sync);
5774 WL_ERR(("GO SSID setting error %d\n", err));
5778 /* Do abort scan before creating GO */
5779 wl_cfg80211_scan_abort(wl);
5781 if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) {
5782 WL_ERR(("GO Bring up error %d\n", err));
5786 WL_DBG(("Bss is already up\n"));
5787 } else if ((dev_role == NL80211_IFTYPE_AP) &&
5788 (wl_get_drv_status(wl, AP_CREATING, dev))) {
5789 /* Device role SoftAP */
5790 err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
5792 WL_ERR(("WLC_DOWN error %d\n", err));
5795 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
5797 WL_ERR(("SET INFRA error %d\n", err));
5800 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
5801 WL_ERR(("setting AP mode failed %d \n", err));
5804 #ifdef DISABLE_11H_SOFTAP
5805 err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT,
5806 &spect, sizeof(s32), true);
5808 WL_ERR(("SET SPECT_MANAGMENT error %d\n", err));
5811 #endif /* DISABLE_11H_SOFTAP */
5813 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
5814 if (unlikely(err)) {
5815 WL_ERR(("WLC_UP error (%d)\n", err));
5819 memset(&join_params, 0, sizeof(join_params));
5820 /* join parameters starts with ssid */
5821 join_params_size = sizeof(join_params.ssid);
5822 memcpy(join_params.ssid.SSID, wl->hostapd_ssid.SSID,
5823 wl->hostapd_ssid.SSID_len);
5824 join_params.ssid.SSID_len = htod32(wl->hostapd_ssid.SSID_len);
5827 if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
5828 join_params_size, true)) == 0) {
5829 WL_DBG(("SoftAP set SSID (%s) success\n", join_params.ssid.SSID));
5830 wl_clr_drv_status(wl, AP_CREATING, dev);
5831 wl_set_drv_status(wl, AP_CREATED, dev);
5840 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
5842 wl_cfg80211_parse_ap_ies(
5843 struct net_device *dev,
5844 struct cfg80211_beacon_data *info,
5845 struct parsed_ies *ies)
5847 struct parsed_ies prb_ies;
5848 struct wl_priv *wl = wlcfg_drv_priv;
5849 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
5851 u32 vndr_ie_len = 0;
5854 /* Parse Beacon IEs */
5855 if (wl_cfg80211_parse_ies((u8 *)info->tail,
5856 info->tail_len, ies) < 0) {
5857 WL_ERR(("Beacon get IEs failed \n"));
5862 vndr = (u8 *)info->proberesp_ies;
5863 vndr_ie_len = info->proberesp_ies_len;
5865 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
5867 struct ieee80211_mgmt *mgmt;
5868 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
5870 vndr = (u8 *)&mgmt->u.probe_resp.variable;
5871 vndr_ie_len = info->probe_resp_len -
5872 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
5876 /* Parse Probe Response IEs */
5877 if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) {
5878 WL_ERR(("PROBE RESP get IEs failed \n"));
5888 wl_cfg80211_set_ies(
5889 struct net_device *dev,
5890 struct cfg80211_beacon_data *info,
5893 struct wl_priv *wl = wlcfg_drv_priv;
5894 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
5896 u32 vndr_ie_len = 0;
5899 /* Set Beacon IEs to FW */
5900 if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5901 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
5902 info->tail_len)) < 0) {
5903 WL_ERR(("Set Beacon IE Failed \n"));
5905 WL_DBG(("Applied Vndr IEs for Beacon \n"));
5908 vndr = (u8 *)info->proberesp_ies;
5909 vndr_ie_len = info->proberesp_ies_len;
5911 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
5913 struct ieee80211_mgmt *mgmt;
5914 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
5916 vndr = (u8 *)&mgmt->u.probe_resp.variable;
5917 vndr_ie_len = info->probe_resp_len -
5918 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
5922 /* Set Probe Response IEs to FW */
5923 if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5924 VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
5925 WL_ERR(("Set Probe Resp IE Failed \n"));
5927 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
5934 static s32 wl_cfg80211_hostapd_sec(
5935 struct net_device *dev,
5936 struct parsed_ies *ies,
5939 bool update_bss = 0;
5940 struct wl_priv *wl = wlcfg_drv_priv;
5944 if (wl->ap_info->wps_ie &&
5945 memcmp(wl->ap_info->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
5946 WL_DBG((" WPS IE is changed\n"));
5947 kfree(wl->ap_info->wps_ie);
5948 wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5949 } else if (wl->ap_info->wps_ie == NULL) {
5950 WL_DBG((" WPS IE is added\n"));
5951 wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5953 if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
5954 if (!wl->ap_info->security_mode) {
5955 /* change from open mode to security mode */
5957 if (ies->wpa_ie != NULL) {
5958 wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5959 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5962 wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5963 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5966 } else if (wl->ap_info->wpa_ie) {
5967 /* change from WPA2 mode to WPA mode */
5968 if (ies->wpa_ie != NULL) {
5970 kfree(wl->ap_info->rsn_ie);
5971 wl->ap_info->rsn_ie = NULL;
5972 wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5973 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5975 } else if (memcmp(wl->ap_info->rsn_ie,
5976 ies->wpa2_ie, ies->wpa2_ie->len
5977 + WPA_RSN_IE_TAG_FIXED_LEN)) {
5979 kfree(wl->ap_info->rsn_ie);
5980 wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5981 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5983 wl->ap_info->wpa_ie = NULL;
5987 wl->ap_info->security_mode = true;
5988 wl_cfgp2p_bss(wl, dev, bssidx, 0);
5989 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
5990 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
5993 wl_cfgp2p_bss(wl, dev, bssidx, 1);
5997 WL_ERR(("No WPSIE in beacon \n"));
6002 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6005 wl_cfg80211_del_station(
6006 struct wiphy *wiphy,
6007 struct net_device *ndev,
6010 struct net_device *dev;
6011 struct wl_priv *wl = wiphy_priv(wiphy);
6013 s8 eabuf[ETHER_ADDR_STR_LEN];
6015 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
6016 sizeof(struct ether_addr) + sizeof(uint)] = {0};
6017 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
6018 int num_associated = 0;
6020 WL_DBG(("Entry\n"));
6021 if (mac_addr == NULL) {
6022 WL_DBG(("mac_addr is NULL ignore it\n"));
6027 return ERR_PTR(-EINVAL);
6029 dev = ndev_to_wlc_ndev(ndev, wl);
6031 if (p2p_is_on(wl)) {
6032 /* Suspend P2P discovery search-listen to prevent it from changing the
6035 if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
6036 WL_ERR(("Can not disable discovery mode\n"));
6041 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
6042 err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST,
6043 assoc_maclist, sizeof(mac_buf), false);
6045 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
6047 num_associated = assoc_maclist->count;
6049 memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
6050 scb_val.val = DOT11_RC_DEAUTH_LEAVING;
6051 err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
6052 sizeof(scb_val_t), true);
6054 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
6055 WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
6056 bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
6059 if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
6064 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
6066 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
6068 wl_cfg80211_start_ap(
6069 struct wiphy *wiphy,
6070 struct net_device *dev,
6071 struct cfg80211_ap_settings *info)
6073 struct wl_priv *wl = wiphy_priv(wiphy);
6075 struct parsed_ies ies;
6079 WL_DBG(("Enter \n"));
6082 return ERR_PTR(-EINVAL);
6084 if (dev == wl_to_prmry_ndev(wl)) {
6085 WL_DBG(("Start AP req on primary iface: Softap\n"));
6086 dev_role = NL80211_IFTYPE_AP;
6088 #if defined(WL_ENABLE_P2P_IF)
6089 else if (dev == wl->p2p_net) {
6090 /* Group Add request on p2p0 */
6091 WL_DBG(("Start AP req on P2P iface: GO\n"));
6092 dev = wl_to_prmry_ndev(wl);
6093 dev_role = NL80211_IFTYPE_P2P_GO;
6095 #endif /* WL_ENABLE_P2P_IF */
6096 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6097 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6100 if (p2p_is_on(wl) &&
6101 (bssidx == wl_to_p2p_bss_bssidx(wl,
6102 P2PAPI_BSSCFG_CONNECTION))) {
6103 dev_role = NL80211_IFTYPE_P2P_GO;
6104 WL_DBG(("Start AP req on P2P connection iface\n"));
6107 if (!check_dev_role_integrity(wl, dev_role))
6110 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && !0)
6111 if ((err = wl_cfg80211_set_channel(wiphy, dev,
6112 dev->ieee80211_ptr->preset_chandef.chan,
6113 NL80211_CHAN_HT20) < 0)) {
6114 WL_ERR(("Set channel failed \n"));
6119 if ((err = wl_cfg80211_bcn_set_params(info, dev,
6120 dev_role, bssidx)) < 0) {
6121 WL_ERR(("Beacon params set failed \n"));
6126 if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
6127 WL_ERR(("Set IEs failed \n"));
6131 if ((wl_cfg80211_bcn_validate_sec(dev, &ies,
6132 dev_role, bssidx)) < 0)
6134 WL_ERR(("Beacon set security failed \n"));
6138 if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
6139 dev_role, bssidx)) < 0) {
6140 WL_ERR(("Beacon bring up AP/GO failed \n"));
6144 WL_DBG(("** AP/GO Created **\n"));
6147 if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
6148 WL_ERR(("Set IEs failed \n"));
6152 WL_ERR(("ADD/SET beacon failed\n"));
6153 wldev_iovar_setint(dev, "mpc", 1);
6160 wl_cfg80211_stop_ap(
6161 struct wiphy *wiphy,
6162 struct net_device *dev)
6169 struct wl_priv *wl = wiphy_priv(wiphy);
6171 WL_DBG(("Enter \n"));
6174 return ERR_PTR(-EINVAL);
6176 if (dev == wl_to_prmry_ndev(wl)) {
6177 dev_role = NL80211_IFTYPE_AP;
6179 #if defined(WL_ENABLE_P2P_IF)
6180 else if (dev == wl->p2p_net) {
6181 /* Group Add request on p2p0 */
6182 dev = wl_to_prmry_ndev(wl);
6183 dev_role = NL80211_IFTYPE_P2P_GO;
6185 #endif /* WL_ENABLE_P2P_IF */
6186 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6187 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6190 if (p2p_is_on(wl) &&
6191 (bssidx == wl_to_p2p_bss_bssidx(wl,
6192 P2PAPI_BSSCFG_CONNECTION))) {
6193 dev_role = NL80211_IFTYPE_P2P_GO;
6196 if (!check_dev_role_integrity(wl, dev_role))
6199 if (dev_role == NL80211_IFTYPE_AP) {
6200 /* SoftAp on primary Interface.
6201 * Shut down AP and turn on MPC
6203 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
6204 WL_ERR(("setting AP mode failed %d \n", err));
6208 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
6210 WL_ERR(("SET INFRA error %d\n", err));
6215 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
6216 if (unlikely(err)) {
6217 WL_ERR(("WLC_UP error (%d)\n", err));
6222 wl_clr_drv_status(wl, AP_CREATED, dev);
6223 /* Turn on the MPC */
6224 wldev_iovar_setint(dev, "mpc", 1);
6226 kfree(wl->ap_info->wpa_ie);
6227 kfree(wl->ap_info->rsn_ie);
6228 kfree(wl->ap_info->wps_ie);
6233 WL_DBG(("Stopping P2P GO \n"));
6241 wl_cfg80211_change_beacon(
6242 struct wiphy *wiphy,
6243 struct net_device *dev,
6244 struct cfg80211_beacon_data *info)
6247 struct wl_priv *wl = wiphy_priv(wiphy);
6248 struct parsed_ies ies;
6252 WL_DBG(("Enter \n"));
6255 return ERR_PTR(-EINVAL);
6256 if (dev == wl_to_prmry_ndev(wl)) {
6257 dev_role = NL80211_IFTYPE_AP;
6259 #if defined(WL_ENABLE_P2P_IF)
6260 else if (dev == wl->p2p_net) {
6261 /* Group Add request on p2p0 */
6262 dev = wl_to_prmry_ndev(wl);
6263 dev_role = NL80211_IFTYPE_P2P_GO;
6265 #endif /* WL_ENABLE_P2P_IF */
6266 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6267 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6270 if (p2p_is_on(wl) &&
6271 (bssidx == wl_to_p2p_bss_bssidx(wl,
6272 P2PAPI_BSSCFG_CONNECTION))) {
6273 dev_role = NL80211_IFTYPE_P2P_GO;
6276 if (dev_role == 0) {
6277 WL_ERR(("Unknown device role!\n"));
6282 if (!check_dev_role_integrity(wl, dev_role))
6285 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (wl->p2p_wdev == NULL)) {
6286 WL_ERR(("P2P already down status!\n"));
6292 if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
6293 WL_ERR(("Parse IEs failed \n"));
6298 if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
6299 WL_ERR(("Set IEs failed \n"));
6303 if (dev_role == NL80211_IFTYPE_AP) {
6304 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6305 WL_ERR(("Hostapd update sec failed \n"));
6314 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */
6316 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
6317 struct beacon_parameters *info)
6320 struct wl_priv *wl = wiphy_priv(wiphy);
6323 u32 dev_role = NL80211_IFTYPE_AP;
6324 struct parsed_ies ies;
6327 WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
6328 info->interval, info->dtim_period, info->head_len, info->tail_len));
6331 return ERR_PTR(-EINVAL);
6333 if (dev == wl_to_prmry_ndev(wl)) {
6334 dev_role = NL80211_IFTYPE_AP;
6336 #if defined(WL_ENABLE_P2P_IF)
6337 else if (dev == wl->p2p_net) {
6338 /* Group Add request on p2p0 */
6339 dev = wl_to_prmry_ndev(wl);
6340 dev_role = NL80211_IFTYPE_P2P_GO;
6342 #endif /* WL_ENABLE_P2P_IF */
6343 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6344 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6347 if (p2p_is_on(wl) &&
6348 (bssidx == wl_to_p2p_bss_bssidx(wl,
6349 P2PAPI_BSSCFG_CONNECTION))) {
6350 dev_role = NL80211_IFTYPE_P2P_GO;
6353 if (dev_role == 0) {
6354 WL_ERR(("Unknown device role!\n"));
6359 if (!check_dev_role_integrity(wl, dev_role))
6362 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (wl->p2p_wdev == NULL)) {
6363 WL_ERR(("P2P already down status!\n"));
6368 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
6370 if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
6371 info->head_len - ie_offset,
6372 DOT11_MNG_SSID_ID)) != NULL) {
6373 if (dev_role == NL80211_IFTYPE_AP) {
6374 /* Store the hostapd SSID */
6375 memset(&wl->hostapd_ssid.SSID[0], 0x00, 32);
6376 memcpy(&wl->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
6377 wl->hostapd_ssid.SSID_len = ssid_ie->len;
6380 memset(&wl->p2p->ssid.SSID[0], 0x00, 32);
6381 memcpy(wl->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
6382 wl->p2p->ssid.SSID_len = ssid_ie->len;
6386 if (wl_cfg80211_parse_ies((u8 *)info->tail,
6387 info->tail_len, &ies) < 0) {
6388 WL_ERR(("Beacon get IEs failed \n"));
6393 if (wl_cfgp2p_set_management_ie(wl, dev, bssidx,
6394 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
6395 info->tail_len) < 0) {
6396 WL_ERR(("Beacon set IEs failed \n"));
6399 WL_DBG(("Applied Vndr IEs for Beacon \n"));
6401 if (!wl_cfgp2p_bss_isup(dev, bssidx) &&
6402 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx) < 0))
6404 WL_ERR(("Beacon set security failed \n"));
6408 /* Set BI and DTIM period */
6409 if (info->interval) {
6410 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
6411 &info->interval, sizeof(s32), true)) < 0) {
6412 WL_ERR(("Beacon Interval Set Error, %d\n", err));
6416 if (info->dtim_period) {
6417 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
6418 &info->dtim_period, sizeof(s32), true)) < 0) {
6419 WL_ERR(("DTIM Interval Set Error, %d\n", err));
6424 if (wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx) < 0) {
6425 WL_ERR(("Beacon bring up AP/GO failed \n"));
6429 if (wl_get_drv_status(wl, AP_CREATED, dev)) {
6430 /* Soft AP already running. Update changed params */
6431 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6432 WL_ERR(("Hostapd update sec failed \n"));
6438 /* Enable Probe Req filter */
6439 if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
6440 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
6441 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
6443 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
6446 WL_DBG(("** ADD/SET beacon done **\n"));
6450 WL_ERR(("ADD/SET beacon failed\n"));
6451 wldev_iovar_setint(dev, "mpc", 1);
6458 #ifdef WL_SCHED_SCAN
6460 #define PNO_REPEAT 4
6461 #define PNO_FREQ_EXPO_MAX 2
6462 int wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
6463 struct net_device *dev,
6464 struct cfg80211_sched_scan_request *request)
6466 ushort pno_time = PNO_TIME;
6467 int pno_repeat = PNO_REPEAT;
6468 int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
6469 wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
6470 struct wl_priv *wl = wiphy_priv(wiphy);
6471 struct cfg80211_ssid *ssid = NULL;
6476 WL_DBG(("Enter \n"));
6479 return ERR_PTR(-EINVAL);
6481 WL_PNO((">>> SCHED SCAN START\n"));
6482 WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
6483 request->n_match_sets, request->n_ssids));
6484 WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
6485 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
6488 if (!request || !request->n_ssids || !request->n_match_sets) {
6489 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
6493 memset(&ssids_local, 0, sizeof(ssids_local));
6495 if (request->n_match_sets > 0) {
6496 for (i = 0; i < request->n_match_sets; i++) {
6497 ssid = &request->match_sets[i].ssid;
6498 memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len);
6499 ssids_local[i].SSID_len = ssid->ssid_len;
6500 WL_PNO((">>> PNO filter set for ssid (%s) \n", ssid->ssid));
6505 if (request->n_ssids > 0) {
6506 for (i = 0; i < request->n_ssids; i++) {
6507 /* Active scan req for ssids */
6508 WL_PNO((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid));
6510 /* match_set ssids is a supert set of n_ssid list, so we need
6511 * not add these set seperately
6517 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, request->n_match_sets,
6518 pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
6519 WL_ERR(("PNO setup failed!! ret=%d \n", ret));
6522 wl->sched_scan_req = request;
6530 int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
6532 struct wl_priv *wl = wiphy_priv(wiphy);
6534 WL_DBG(("Enter \n"));
6537 return ERR_PTR(-EINVAL);
6539 WL_PNO((">>> SCHED SCAN STOP\n"));
6541 if (dhd_dev_pno_stop_for_ssid(dev) < 0)
6542 WL_ERR(("PNO Stop for SSID failed"));
6544 if (wl->scan_request && wl->sched_scan_running) {
6545 WL_PNO((">>> Sched scan running. Aborting it..\n"));
6546 wl_notify_escan_complete(wl, dev, true, true);
6549 wl->sched_scan_req = NULL;
6550 wl->sched_scan_running = FALSE;
6554 #endif /* WL_SCHED_SCAN */
6556 static struct cfg80211_ops wl_cfg80211_ops = {
6557 .add_virtual_intf = wl_cfg80211_add_virtual_iface,
6558 .del_virtual_intf = wl_cfg80211_del_virtual_iface,
6559 .change_virtual_intf = wl_cfg80211_change_virtual_iface,
6560 #if defined(WL_CFG80211_P2P_DEV_IF)
6561 .start_p2p_device = wl_cfgp2p_start_p2p_device,
6562 .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
6563 #endif /* WL_CFG80211_P2P_DEV_IF */
6564 .scan = wl_cfg80211_scan,
6565 .set_wiphy_params = wl_cfg80211_set_wiphy_params,
6566 .join_ibss = wl_cfg80211_join_ibss,
6567 .leave_ibss = wl_cfg80211_leave_ibss,
6568 .get_station = wl_cfg80211_get_station,
6569 .set_tx_power = wl_cfg80211_set_tx_power,
6570 .get_tx_power = wl_cfg80211_get_tx_power,
6571 .add_key = wl_cfg80211_add_key,
6572 .del_key = wl_cfg80211_del_key,
6573 .get_key = wl_cfg80211_get_key,
6574 .set_default_key = wl_cfg80211_config_default_key,
6575 .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
6576 .set_power_mgmt = wl_cfg80211_set_power_mgmt,
6577 .connect = wl_cfg80211_connect,
6578 .disconnect = wl_cfg80211_disconnect,
6579 .suspend = wl_cfg80211_suspend,
6580 .resume = wl_cfg80211_resume,
6581 .set_pmksa = wl_cfg80211_set_pmksa,
6582 .del_pmksa = wl_cfg80211_del_pmksa,
6583 .flush_pmksa = wl_cfg80211_flush_pmksa,
6584 .remain_on_channel = wl_cfg80211_remain_on_channel,
6585 .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
6586 .mgmt_tx = wl_cfg80211_mgmt_tx,
6587 .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
6588 .change_bss = wl_cfg80211_change_bss,
6589 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) || 0
6590 .set_channel = wl_cfg80211_set_channel,
6592 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !0
6593 .set_beacon = wl_cfg80211_add_set_beacon,
6594 .add_beacon = wl_cfg80211_add_set_beacon,
6596 .change_beacon = wl_cfg80211_change_beacon,
6597 .start_ap = wl_cfg80211_start_ap,
6598 .stop_ap = wl_cfg80211_stop_ap,
6600 #ifdef WL_SCHED_SCAN
6601 .sched_scan_start = wl_cfg80211_sched_scan_start,
6602 .sched_scan_stop = wl_cfg80211_sched_scan_stop,
6603 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */
6604 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6606 .del_station = wl_cfg80211_del_station,
6607 .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
6608 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
6609 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
6610 .tdls_oper = wl_cfg80211_tdls_oper
6614 s32 wl_mode_to_nl80211_iftype(s32 mode)
6620 return NL80211_IFTYPE_STATION;
6622 return NL80211_IFTYPE_ADHOC;
6624 return NL80211_IFTYPE_AP;
6626 return NL80211_IFTYPE_UNSPECIFIED;
6632 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
6633 /* Kernel Network Support->Wireless->Regulatory rules database
6634 options should be enabled and regulatory CRDA regdb table populated in Kernel
6635 for proper country reg notification
6638 wl_cfg80211_reg_notifier(
6639 struct wiphy *wiphy,
6640 struct regulatory_request *request)
6642 struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
6645 if (!request || !wl) {
6646 WL_ERR(("Invalid arg\n"));
6650 WL_DBG(("ccode: %c%c Initiator: %d\n",
6651 request->alpha2[0], request->alpha2[1], request->initiator));
6653 /* We support only REGDOM_SET_BY_USER as of now */
6654 if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
6655 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
6656 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
6657 request->initiator));
6658 /* in case of no supported country by regdb
6659 lets driver setup platform default Locale
6663 WL_ERR(("Set country code %c%c from %s\n",
6664 request->alpha2[0], request->alpha2[1],
6665 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
6667 if ((ret = wldev_set_country(wl_to_prmry_ndev(wl), request->alpha2,
6668 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false))) < 0) {
6669 WL_ERR(("set country Failed :%d\n", ret));
6674 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
6676 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *data)
6679 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
6680 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
6681 dhd_pub_t *dhd = (dhd_pub_t *)data;
6682 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
6685 wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv));
6686 if (unlikely(!wdev->wiphy)) {
6687 WL_ERR(("Couldn not allocate wiphy device\n"));
6691 set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
6692 wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
6693 /* Report how many SSIDs Driver can support per Scan request */
6694 wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
6695 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
6696 #ifdef WL_SCHED_SCAN
6697 wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
6698 wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
6699 wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
6700 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
6701 #endif /* WL_SCHED_SCAN */
6702 wdev->wiphy->interface_modes =
6703 BIT(NL80211_IFTYPE_STATION)
6704 | BIT(NL80211_IFTYPE_ADHOC)
6705 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
6707 * This monitor mode support creates an issue in registering
6708 * Action frame for P2P-GO, this was leading an error in receiving
6709 * action frames to GO interface.Keeping the code here because
6710 * monitor mode code has kept as it is in other modules,
6711 * though we are not supporting this mode.
6713 | BIT(NL80211_IFTYPE_MONITOR)
6714 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
6715 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
6716 | BIT(NL80211_IFTYPE_P2P_CLIENT)
6717 | BIT(NL80211_IFTYPE_P2P_GO)
6718 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
6719 #if defined(WL_CFG80211_P2P_DEV_IF)
6720 | BIT(NL80211_IFTYPE_P2P_DEVICE)
6721 #endif /* WL_CFG80211_P2P_DEV_IF */
6722 | BIT(NL80211_IFTYPE_AP);
6724 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
6725 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
6726 if (dhd && dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
6727 WL_DBG(("Setting interface combinations for SoftAP mode\n"));
6728 wdev->wiphy->iface_combinations = softap_iface_combinations;
6729 wdev->wiphy->n_iface_combinations =
6730 ARRAY_SIZE(softap_iface_combinations);
6732 WL_DBG(("Setting interface combinations for STA+P2P mode\n"));
6733 wdev->wiphy->iface_combinations = sta_p2p_iface_combinations;
6734 wdev->wiphy->n_iface_combinations =
6735 ARRAY_SIZE(sta_p2p_iface_combinations);
6737 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
6739 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
6741 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
6742 wdev->wiphy->cipher_suites = __wl_cipher_suites;
6743 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
6744 wdev->wiphy->max_remain_on_channel_duration = 5000;
6745 wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
6746 #ifndef WL_POWERSAVE_DISABLED
6747 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
6749 wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
6750 #endif /* !WL_POWERSAVE_DISABLED */
6751 wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
6752 WIPHY_FLAG_4ADDR_AP |
6753 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && !0
6754 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
6756 WIPHY_FLAG_4ADDR_STATION;
6757 /* If driver advertises FW_ROAM, the supplicant wouldn't
6758 * send the BSSID & Freq in the connect command allowing the
6759 * the driver to choose the AP to connect to. But unless we
6760 * support ROAM_CACHE in firware this will delay the ASSOC as
6761 * as the FW need to do a full scan before attempting to connect
6762 * So that feature will just increase assoc. The better approach
6763 * to let Supplicant to provide channel info and FW letter may roam
6764 * if needed so DON'T advertise that featur eto Supplicant.
6766 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
6767 /* wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */
6769 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || 0
6770 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
6771 WIPHY_FLAG_OFFCHAN_TX;
6773 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6775 /* From 3.4 kernel ownards AP_SME flag can be advertised
6776 * to remove the patch from supplicant
6778 wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
6779 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
6781 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
6782 wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
6783 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
6785 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
6786 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
6789 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
6791 * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
6792 * disconnection of connected network before suspend. So a dummy wowlan
6793 * filter is configured for kernels linux-3.8 and above.
6795 wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
6796 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
6798 WL_DBG(("Registering custom regulatory)\n"));
6799 wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
6800 wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
6801 /* Now we can register wiphy with cfg80211 module */
6802 err = wiphy_register(wdev->wiphy);
6803 if (unlikely(err < 0)) {
6804 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
6805 wiphy_free(wdev->wiphy);
6808 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
6809 KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
6810 wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
6811 #endif /* ((LINUX_VER >= 3.0) && (LINUX_VER <= 3.3)) && WL_IFACE_COMB_NUM_CHANNELS */
6816 static void wl_free_wdev(struct wl_priv *wl)
6818 struct wireless_dev *wdev = wl->wdev;
6819 struct wiphy *wiphy;
6821 WL_ERR(("wdev is invalid\n"));
6824 wiphy = wdev->wiphy;
6825 wiphy_unregister(wdev->wiphy);
6826 wdev->wiphy->dev.parent = NULL;
6828 wl_delete_all_netinfo(wl);
6830 /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "wl",
6831 * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
6835 static s32 wl_inform_bss(struct wl_priv *wl)
6837 struct wl_scan_results *bss_list;
6838 struct wl_bss_info *bi = NULL; /* must be initialized */
6842 bss_list = wl->bss_list;
6843 WL_DBG(("scanned AP count (%d)\n", bss_list->count));
6844 bi = next_bss(bss_list, bi);
6845 for_each_bss(bss_list, bi, i) {
6846 err = wl_inform_single_bss(wl, bi);
6853 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
6855 struct wiphy *wiphy = wl_to_wiphy(wl);
6856 struct ieee80211_mgmt *mgmt;
6857 struct ieee80211_channel *channel;
6858 struct ieee80211_supported_band *band;
6859 struct wl_cfg80211_bss_info *notif_bss_info;
6860 struct wl_scan_req *sr = wl_to_sr(wl);
6861 struct beacon_proberesp *beacon_proberesp;
6862 struct cfg80211_bss *cbss = NULL;
6869 if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
6870 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
6873 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
6874 notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
6875 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
6876 if (unlikely(!notif_bss_info)) {
6877 WL_ERR(("notif_bss_info alloc failed\n"));
6880 mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
6881 notif_bss_info->channel =
6882 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
6884 if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
6885 band = wiphy->bands[IEEE80211_BAND_2GHZ];
6887 band = wiphy->bands[IEEE80211_BAND_5GHZ];
6889 WL_ERR(("No valid band"));
6890 kfree(notif_bss_info);
6893 notif_bss_info->rssi = wl_rssi_offset(dtoh16(bi->RSSI));
6894 memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
6895 mgmt_type = wl->active_scan ?
6896 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
6897 if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
6898 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
6900 beacon_proberesp = wl->active_scan ?
6901 (struct beacon_proberesp *)&mgmt->u.probe_resp :
6902 (struct beacon_proberesp *)&mgmt->u.beacon;
6903 beacon_proberesp->timestamp = 0;
6904 beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
6905 beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
6907 wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length);
6908 wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
6909 wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
6910 offsetof(struct wl_cfg80211_bss_info, frame_buf));
6911 notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
6912 u.beacon.variable) + wl_get_ielen(wl);
6913 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
6914 freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
6917 freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
6920 WL_ERR(("Invalid channel, fail to chcnage channel to freq\n"));
6921 kfree(notif_bss_info);
6924 channel = ieee80211_get_channel(wiphy, freq);
6925 if (unlikely(!channel)) {
6926 WL_ERR(("ieee80211_get_channel error\n"));
6927 kfree(notif_bss_info);
6930 WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
6931 "mgmt_type %d frame_len %d\n", bi->SSID,
6932 notif_bss_info->rssi, notif_bss_info->channel,
6933 mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
6934 notif_bss_info->frame_len));
6936 signal = notif_bss_info->rssi * 100;
6937 if (!mgmt->u.probe_resp.timestamp) {
6938 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
6940 get_monotonic_boottime(&ts);
6941 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
6942 + ts.tv_nsec / 1000;
6945 do_gettimeofday(&tv);
6946 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
6952 cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
6953 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
6954 if (unlikely(!cbss)) {
6955 WL_ERR(("cfg80211_inform_bss_frame error\n"));
6956 kfree(notif_bss_info);
6960 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
6961 cfg80211_put_bss(wiphy, cbss);
6963 cfg80211_put_bss(cbss);
6964 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
6965 kfree(notif_bss_info);
6969 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
6971 u32 event = ntoh32(e->event_type);
6972 u32 status = ntoh32(e->status);
6973 u16 flags = ntoh16(e->flags);
6975 WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
6976 if (event == WLC_E_SET_SSID) {
6977 if (status == WLC_E_STATUS_SUCCESS) {
6978 if (!wl_is_ibssmode(wl, ndev))
6981 } else if (event == WLC_E_LINK) {
6982 if (flags & WLC_EVENT_MSG_LINK)
6986 WL_DBG(("wl_is_linkup false\n"));
6990 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
6992 u32 event = ntoh32(e->event_type);
6993 u16 flags = ntoh16(e->flags);
6995 if (event == WLC_E_DEAUTH_IND ||
6996 event == WLC_E_DISASSOC_IND ||
6997 event == WLC_E_DISASSOC ||
6998 event == WLC_E_DEAUTH) {
6999 #if (WL_DBG_LEVEL > 0)
7000 WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
7001 #endif /* (WL_DBG_LEVEL > 0) */
7003 } else if (event == WLC_E_LINK) {
7004 if (!(flags & WLC_EVENT_MSG_LINK)) {
7005 #if (WL_DBG_LEVEL > 0)
7006 WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
7007 #endif /* (WL_DBG_LEVEL > 0) */
7015 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
7017 u32 event = ntoh32(e->event_type);
7018 u32 status = ntoh32(e->status);
7020 if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
7022 if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
7028 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
7029 * to AP/P2P GO via events. If this change is backported to kernel for which
7030 * this driver is being built, then define WL_CFG80211_STA_EVENT. You
7031 * should use this new/del sta event mechanism for BRCM supplicant >= 22.
7034 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
7035 const wl_event_msg_t *e, void *data)
7038 u32 event = ntoh32(e->event_type);
7039 u32 reason = ntoh32(e->reason);
7040 u32 len = ntoh32(e->datalen);
7042 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7044 bool isfree = false;
7046 u8 bsscfgidx = e->bsscfgidx;
7052 struct ieee80211_supported_band *band;
7053 struct ether_addr da;
7054 struct ether_addr bssid;
7055 struct wiphy *wiphy = wl_to_wiphy(wl);
7058 struct station_info sinfo;
7061 WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
7062 /* if link down, bsscfg is disabled. */
7063 if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
7064 wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) {
7065 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
7066 WL_INFO(("AP mode link down !! \n"));
7067 complete(&wl->iface_disable);
7071 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7073 WL_DBG(("Enter \n"));
7074 if (!len && (event == WLC_E_DEAUTH)) {
7075 len = 2; /* reason code field */
7079 body = kzalloc(len, GFP_KERNEL);
7082 WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
7086 memset(&bssid, 0, ETHER_ADDR_LEN);
7087 WL_DBG(("Enter event %d ndev %p\n", event, ndev));
7088 if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) {
7093 memcpy(body, data, len);
7095 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
7096 NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
7097 memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
7098 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
7100 case WLC_E_ASSOC_IND:
7103 case WLC_E_REASSOC_IND:
7104 fc = FC_REASSOC_REQ;
7106 case WLC_E_DISASSOC_IND:
7108 WL_ERR(("event %s(%d) status %d reason %d\n",
7109 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7111 case WLC_E_DEAUTH_IND:
7113 WL_ERR(("event %s(%d) status %d reason %d\n",
7114 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7118 WL_ERR(("event %s(%d) status %d reason %d\n",
7119 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7125 if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
7130 channel = dtoh32(ci.hw_channel);
7131 if (channel <= CH_MAX_2G_CHANNEL)
7132 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7134 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7136 WL_ERR(("No valid band"));
7141 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
7142 freq = ieee80211_channel_to_frequency(channel);
7145 freq = ieee80211_channel_to_frequency(channel, band->band);
7148 err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
7149 &mgmt_frame, &len, body);
7154 if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
7155 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7156 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7158 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7160 } else if (event == WLC_E_DISASSOC_IND) {
7161 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7162 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7164 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7166 } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7167 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7168 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7170 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7179 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
7181 if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
7182 reason == DOT11_SC_SUCCESS) {
7183 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
7185 WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
7188 sinfo.assoc_req_ies = data;
7189 sinfo.assoc_req_ies_len = len;
7190 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
7191 } else if (event == WLC_E_DISASSOC_IND) {
7192 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7193 } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7194 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7201 wl_get_auth_assoc_status(struct wl_priv *wl, struct net_device *ndev,
7202 const wl_event_msg_t *e)
7204 u32 reason = ntoh32(e->reason);
7205 u32 event = ntoh32(e->event_type);
7206 struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
7207 WL_DBG(("event type : %d, reason : %d\n", event, reason));
7212 sec->auth_assoc_res_status = reason;
7217 WL_ERR(("sec is NULL\n"));
7222 wl_notify_connect_status_ibss(struct wl_priv *wl, struct net_device *ndev,
7223 const wl_event_msg_t *e, void *data)
7226 u32 event = ntoh32(e->event_type);
7227 u16 flags = ntoh16(e->flags);
7228 u32 status = ntoh32(e->status);
7231 if (event == WLC_E_JOIN) {
7232 WL_DBG(("joined in IBSS network\n"));
7234 if (event == WLC_E_START) {
7235 WL_DBG(("started IBSS network\n"));
7237 if (event == WLC_E_JOIN || event == WLC_E_START ||
7238 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
7239 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7240 /* ROAM or Redundant */
7241 u8 *cur_bssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7242 if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
7243 WL_DBG(("IBSS connected event from same BSSID("
7244 MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
7247 WL_INFO(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
7248 MAC2STRDBG(cur_bssid), MAC2STRDBG((u8 *)&e->addr)));
7249 wl_get_assoc_ies(wl, ndev);
7250 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7251 wl_update_bss_info(wl, ndev);
7252 cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7255 /* New connection */
7256 WL_INFO(("IBSS connected to " MACDBG "\n", MAC2STRDBG((u8 *)&e->addr)));
7258 wl_get_assoc_ies(wl, ndev);
7259 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7260 wl_update_bss_info(wl, ndev);
7261 cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7262 wl_set_drv_status(wl, CONNECTED, ndev);
7264 wl_update_prof(wl, ndev, NULL, (void *)&active, WL_PROF_ACT);
7266 } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
7267 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
7268 wl_clr_drv_status(wl, CONNECTED, ndev);
7270 wl_init_prof(wl, ndev);
7272 else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
7273 WL_DBG(("no action - join fail (IBSS mode)\n"));
7276 WL_DBG(("no action (IBSS mode)\n"));
7282 wl_notify_connect_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7283 const wl_event_msg_t *e, void *data)
7286 struct net_device *ndev = NULL;
7288 u32 event = ntoh32(e->event_type);
7290 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7292 if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
7293 err = wl_notify_connect_status_ap(wl, ndev, e, data);
7294 } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS) {
7295 err = wl_notify_connect_status_ibss(wl, ndev, e, data);
7296 } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) {
7297 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
7298 ntoh32(e->event_type), ntoh32(e->status), ndev));
7299 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
7300 wl_get_auth_assoc_status(wl, ndev, e);
7303 if (wl_is_linkup(wl, e, ndev)) {
7306 if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7307 printk("wl_bss_connect_done succeeded with " MACDBG "\n",
7308 MAC2STRDBG((u8*)(&e->addr)));
7309 wl_bss_connect_done(wl, ndev, e, data, true);
7310 WL_DBG(("joined in BSS network \"%s\"\n",
7311 ((struct wlc_ssid *)
7312 wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID));
7314 wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7315 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7317 } else if (wl_is_linkdown(wl, e)) {
7318 if (wl->scan_request) {
7320 wl_notify_escan_complete(wl, ndev, true, true);
7322 del_timer_sync(&wl->scan_timeout);
7323 wl_iscan_aborted(wl);
7326 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7328 u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7330 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
7331 reason = ntoh32(e->reason);
7332 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
7333 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
7335 printk("link down if %s may call cfg80211_disconnected. "
7336 "event : %d, reason=%d from " MACDBG "\n",
7337 ndev->name, event, ntoh32(e->reason),
7338 MAC2STRDBG((u8*)(&e->addr)));
7339 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
7340 WL_ERR(("BSSID of event is not the connected BSSID"
7341 "(ignore it) cur: " MACDBG " event: " MACDBG"\n",
7342 MAC2STRDBG(curbssid), MAC2STRDBG((u8*)(&e->addr))));
7345 wl_clr_drv_status(wl, CONNECTED, ndev);
7346 if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7347 /* To make sure disconnect, explictly send dissassoc
7348 * for BSSID 00:00:00:00:00:00 issue
7350 scbval.val = WLAN_REASON_DEAUTH_LEAVING;
7352 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
7353 scbval.val = htod32(scbval.val);
7354 err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
7355 sizeof(scb_val_t), true);
7357 WL_ERR(("WLC_DISASSOC error %d\n", err));
7360 cfg80211_disconnected(ndev, reason, NULL, 0, GFP_KERNEL);
7362 wl_init_prof(wl, ndev);
7365 else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
7367 printk("link down, during connecting\n");
7368 #ifdef ESCAN_RESULT_PATCH
7369 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7370 (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7371 (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
7372 /* In case this event comes while associating another AP */
7373 #endif /* ESCAN_RESULT_PATCH */
7374 wl_bss_connect_done(wl, ndev, e, data, false);
7376 wl_clr_drv_status(wl, DISCONNECTING, ndev);
7378 /* if link down, bsscfg is diabled */
7379 if (ndev != wl_to_prmry_ndev(wl))
7380 complete(&wl->iface_disable);
7382 } else if (wl_is_nonetwork(wl, e)) {
7383 printk("connect failed event=%d e->status %d e->reason %d \n",
7384 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
7385 /* Clean up any pending scan request */
7386 if (wl->scan_request) {
7388 wl_notify_escan_complete(wl, ndev, true, true);
7390 del_timer_sync(&wl->scan_timeout);
7391 wl_iscan_aborted(wl);
7394 if (wl_get_drv_status(wl, CONNECTING, ndev))
7395 wl_bss_connect_done(wl, ndev, e, data, false);
7397 printk("%s nothing\n", __FUNCTION__);
7400 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(wl, ndev)));
7407 wl_notify_roaming_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7408 const wl_event_msg_t *e, void *data)
7411 struct net_device *ndev = NULL;
7413 u32 event = be32_to_cpu(e->event_type);
7414 u32 status = be32_to_cpu(e->status);
7416 WL_DBG(("Enter \n"));
7418 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7420 if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) {
7421 if (wl_get_drv_status(wl, CONNECTED, ndev))
7422 wl_bss_roaming_done(wl, ndev, e, data);
7424 wl_bss_connect_done(wl, ndev, e, data, true);
7426 wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7427 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7432 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
7434 wl_assoc_info_t assoc_info;
7435 struct wl_connect_info *conn_info = wl_to_conn(wl);
7438 WL_DBG(("Enter \n"));
7439 err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, wl->extra_buf,
7440 WL_ASSOC_INFO_MAX, NULL);
7441 if (unlikely(err)) {
7442 WL_ERR(("could not get assoc info (%d)\n", err));
7445 memcpy(&assoc_info, wl->extra_buf, sizeof(wl_assoc_info_t));
7446 assoc_info.req_len = htod32(assoc_info.req_len);
7447 assoc_info.resp_len = htod32(assoc_info.resp_len);
7448 assoc_info.flags = htod32(assoc_info.flags);
7449 if (conn_info->req_ie_len) {
7450 conn_info->req_ie_len = 0;
7451 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
7453 if (conn_info->resp_ie_len) {
7454 conn_info->resp_ie_len = 0;
7455 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
7457 if (assoc_info.req_len) {
7458 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, wl->extra_buf,
7459 WL_ASSOC_INFO_MAX, NULL);
7460 if (unlikely(err)) {
7461 WL_ERR(("could not get assoc req (%d)\n", err));
7464 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
7465 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
7466 conn_info->req_ie_len -= ETHER_ADDR_LEN;
7468 if (conn_info->req_ie_len <= MAX_REQ_LINE)
7469 memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len);
7471 WL_ERR(("IE size %d above max %d size \n",
7472 conn_info->req_ie_len, MAX_REQ_LINE));
7476 conn_info->req_ie_len = 0;
7478 if (assoc_info.resp_len) {
7479 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, wl->extra_buf,
7480 WL_ASSOC_INFO_MAX, NULL);
7481 if (unlikely(err)) {
7482 WL_ERR(("could not get assoc resp (%d)\n", err));
7485 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
7486 if (conn_info->resp_ie_len <= MAX_REQ_LINE)
7487 memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len);
7489 WL_ERR(("IE size %d above max %d size \n",
7490 conn_info->resp_ie_len, MAX_REQ_LINE));
7494 conn_info->resp_ie_len = 0;
7496 WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
7497 conn_info->resp_ie_len));
7502 static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
7503 size_t *join_params_size)
7505 chanspec_t chanspec = 0;
7507 join_params->params.chanspec_num = 1;
7508 join_params->params.chanspec_list[0] = ch;
7510 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
7511 chanspec |= WL_CHANSPEC_BAND_2G;
7513 chanspec |= WL_CHANSPEC_BAND_5G;
7515 chanspec |= WL_CHANSPEC_BW_20;
7516 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
7518 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
7519 join_params->params.chanspec_num * sizeof(chanspec_t);
7521 join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
7522 join_params->params.chanspec_list[0] |= chanspec;
7523 join_params->params.chanspec_list[0] =
7524 wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
7526 join_params->params.chanspec_num =
7527 htod32(join_params->params.chanspec_num);
7528 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
7529 join_params->params.chanspec_list[0],
7530 join_params->params.chanspec_num));
7534 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
7536 struct cfg80211_bss *bss;
7537 struct wl_bss_info *bi;
7538 struct wlc_ssid *ssid;
7539 struct bcm_tlv *tim;
7540 s32 beacon_interval;
7546 struct wiphy *wiphy;
7547 struct ieee80211_supported_band *band;
7548 struct ieee80211_channel *channel = NULL;
7552 mutex_lock(&wl->usr_sync);
7553 wiphy = wl_to_wiphy(wl);
7555 ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID);
7556 curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7557 *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
7558 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
7559 wl->extra_buf, WL_EXTRA_BUF_MAX, false);
7560 if (unlikely(err)) {
7561 WL_ERR(("Could not get bss info %d\n", err));
7562 goto update_bss_info_out;
7564 bi = (struct wl_bss_info *)(wl->extra_buf + 4);
7565 chan = bi->ctl_ch ? bi->ctl_ch :
7566 CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
7567 if (chan <= CH_MAX_2G_CHANNEL)
7568 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7570 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7571 freq = ieee80211_channel_to_frequency(chan, band->band);
7572 channel = ieee80211_get_channel(wiphy, freq);
7573 bss = cfg80211_get_bss(wiphy, channel, curbssid,
7574 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
7575 WLAN_CAPABILITY_ESS);
7577 WL_DBG(("Could not find the AP\n"));
7578 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
7579 WL_ERR(("Bssid doesn't match\n"));
7581 goto update_bss_info_out;
7583 err = wl_inform_single_bss(wl, bi);
7585 goto update_bss_info_out;
7587 ie = ((u8 *)bi) + bi->ie_offset;
7588 ie_len = bi->ie_length;
7589 beacon_interval = cpu_to_le16(bi->beacon_period);
7591 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
7592 #if defined(WL_CFG80211_P2P_DEV_IF)
7593 ie = (u8 *)bss->ies->data;
7594 ie_len = bss->ies->len;
7596 ie = bss->information_elements;
7597 ie_len = bss->len_information_elements;
7598 #endif /* WL_CFG80211_P2P_DEV_IF */
7599 beacon_interval = bss->beacon_interval;
7600 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
7601 cfg80211_put_bss(wiphy, bss);
7603 cfg80211_put_bss(bss);
7604 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
7607 tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
7609 dtim_period = tim->data[1];
7612 * active scan was done so we could not get dtim
7613 * information out of probe response.
7614 * so we speficially query dtim information.
7616 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
7617 &dtim_period, sizeof(dtim_period), false);
7618 if (unlikely(err)) {
7619 WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
7620 goto update_bss_info_out;
7624 wl_update_prof(wl, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
7625 wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
7627 update_bss_info_out:
7628 if (unlikely(err)) {
7629 WL_ERR(("Failed with error %d\n", err));
7631 mutex_unlock(&wl->usr_sync);
7636 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
7637 const wl_event_msg_t *e, void *data)
7639 struct wl_connect_info *conn_info = wl_to_conn(wl);
7642 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7643 struct wl_bss_info *bss_info;
7644 struct wiphy *wiphy = wl_to_wiphy(wl);
7645 struct ieee80211_supported_band *band;
7646 struct ieee80211_channel *notify_channel = NULL;
7652 wl_get_assoc_ies(wl, ndev);
7653 wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
7654 curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7655 wl_update_bss_info(wl, ndev);
7656 wl_update_pmklist(ndev, wl->pmk_list, err);
7658 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7659 /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
7660 buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
7664 *(__le32 *)buf = htod32(WL_EXTRA_BUF_MAX);
7665 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX, false);
7669 bss_info = (struct wl_bss_info *)(buf + 4);
7670 channel = bss_info->ctl_ch ? bss_info->ctl_ch :
7671 CHSPEC_CHANNEL(wl_chspec_driver_to_host(bss_info->chanspec));
7672 if (channel <= CH_MAX_2G_CHANNEL)
7673 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7675 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7676 freq = ieee80211_channel_to_frequency(channel, band->band);
7677 notify_channel = ieee80211_get_channel(wiphy, freq);
7681 printk("wl_bss_roaming_done succeeded to " MACDBG "\n",
7682 MAC2STRDBG((u8*)(&e->addr)));
7684 cfg80211_roamed(ndev,
7685 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7689 conn_info->req_ie, conn_info->req_ie_len,
7690 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
7691 WL_DBG(("Report roaming result\n"));
7693 wl_set_drv_status(wl, CONNECTED, ndev);
7699 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
7700 const wl_event_msg_t *e, void *data, bool completed)
7702 struct wl_connect_info *conn_info = wl_to_conn(wl);
7703 struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
7705 u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7707 WL_ERR(("sec is NULL\n"));
7710 WL_DBG((" enter\n"));
7711 #ifdef ESCAN_RESULT_PATCH
7712 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7713 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
7714 WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
7715 ntoh32(e->event_type), ntoh32(e->status)));
7719 if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
7720 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
7721 WL_DBG(("copy bssid\n"));
7722 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
7726 if (wl->scan_request) {
7727 wl_notify_escan_complete(wl, ndev, true, true);
7729 #endif /* ESCAN_RESULT_PATCH */
7730 if (wl_get_drv_status(wl, CONNECTING, ndev) && (e->event_type == WLC_E_SET_SSID)) {
7731 wl_cfg80211_scan_abort(wl);
7732 wl_clr_drv_status(wl, CONNECTING, ndev);
7734 wl_get_assoc_ies(wl, ndev);
7735 wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
7736 curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7737 wl_update_bss_info(wl, ndev);
7738 wl_update_pmklist(ndev, wl->pmk_list, err);
7739 wl_set_drv_status(wl, CONNECTED, ndev);
7740 if (ndev != wl_to_prmry_ndev(wl)) {
7741 /* reinitialize completion to clear previous count */
7742 INIT_COMPLETION(wl->iface_disable);
7745 /* Update the cfg layer with the lates active channels available */
7746 wl_update_wiphybands(NULL, true);
7748 cfg80211_connect_result(ndev,
7751 conn_info->req_ie_len,
7753 conn_info->resp_ie_len,
7754 completed ? WLAN_STATUS_SUCCESS :
7755 (sec->auth_assoc_res_status) ?
7756 sec->auth_assoc_res_status :
7757 WLAN_STATUS_UNSPECIFIED_FAILURE,
7760 WL_INFO(("Report connect result - connection succeeded\n"));
7762 WL_ERR(("Report connect result - connection failed\n"));
7768 wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7769 const wl_event_msg_t *e, void *data)
7771 struct net_device *ndev = NULL;
7772 u16 flags = ntoh16(e->flags);
7773 enum nl80211_key_type key_type;
7775 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7777 mutex_lock(&wl->usr_sync);
7778 if (flags & WLC_EVENT_MSG_GROUP)
7779 key_type = NL80211_KEYTYPE_GROUP;
7781 key_type = NL80211_KEYTYPE_PAIRWISE;
7783 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
7785 mutex_unlock(&wl->usr_sync);
7792 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7793 const wl_event_msg_t *e, void *data)
7795 struct net_device *ndev = NULL;
7797 WL_ERR((">>> PNO Event\n"));
7799 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7801 #ifndef WL_SCHED_SCAN
7802 mutex_lock(&wl->usr_sync);
7803 /* TODO: Use cfg80211_sched_scan_results(wiphy); */
7804 cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
7805 mutex_unlock(&wl->usr_sync);
7807 /* If cfg80211 scheduled scan is supported, report the pno results via sched
7810 wl_notify_sched_scan_results(wl, ndev, e, data);
7811 #endif /* WL_SCHED_SCAN */
7814 #endif /* PNO_SUPPORT */
7817 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7818 const wl_event_msg_t *e, void *data)
7820 struct channel_info channel_inform;
7821 struct wl_scan_results *bss_list;
7822 struct net_device *ndev = NULL;
7823 u32 len = WL_SCAN_BUF_MAX;
7825 unsigned long flags;
7827 WL_DBG(("Enter \n"));
7828 if (!wl_get_drv_status(wl, SCANNING, ndev)) {
7829 WL_ERR(("scan is not ready \n"));
7832 if (wl->iscan_on && wl->iscan_kickstart)
7833 return wl_wakeup_iscan(wl_to_iscan(wl));
7835 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7837 mutex_lock(&wl->usr_sync);
7838 wl_clr_drv_status(wl, SCANNING, ndev);
7839 err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
7840 sizeof(channel_inform), false);
7841 if (unlikely(err)) {
7842 WL_ERR(("scan busy (%d)\n", err));
7845 channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
7846 if (unlikely(channel_inform.scan_channel)) {
7848 WL_DBG(("channel_inform.scan_channel (%d)\n",
7849 channel_inform.scan_channel));
7851 wl->bss_list = wl->scan_results;
7852 bss_list = wl->bss_list;
7853 memset(bss_list, 0, len);
7854 bss_list->buflen = htod32(len);
7855 err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
7856 if (unlikely(err) && unlikely(!wl->scan_suppressed)) {
7857 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
7861 bss_list->buflen = dtoh32(bss_list->buflen);
7862 bss_list->version = dtoh32(bss_list->version);
7863 bss_list->count = dtoh32(bss_list->count);
7865 err = wl_inform_bss(wl);
7868 del_timer_sync(&wl->scan_timeout);
7869 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
7870 if (wl->scan_request) {
7871 cfg80211_scan_done(wl->scan_request, false);
7872 wl->scan_request = NULL;
7874 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
7875 WL_DBG(("cfg80211_scan_done\n"));
7876 mutex_unlock(&wl->usr_sync);
7881 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
7882 const struct ether_addr *sa, const struct ether_addr *bssid,
7883 u8 **pheader, u32 *body_len, u8 *pbody)
7885 struct dot11_management_header *hdr;
7889 u32 prebody_len = *body_len;
7892 /* capability , listen interval */
7893 totlen = DOT11_ASSOC_REQ_FIXED_LEN;
7894 *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
7897 case FC_REASSOC_REQ:
7898 /* capability, listen inteval, ap address */
7899 totlen = DOT11_REASSOC_REQ_FIXED_LEN;
7900 *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
7903 totlen += DOT11_MGMT_HDR_LEN + prebody_len;
7904 *pheader = kzalloc(totlen, GFP_KERNEL);
7905 if (*pheader == NULL) {
7906 WL_ERR(("memory alloc failed \n"));
7909 hdr = (struct dot11_management_header *) (*pheader);
7910 hdr->fc = htol16(fc);
7913 offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
7914 bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
7915 bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
7916 bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
7917 if ((pbody != NULL) && prebody_len)
7918 bcopy((const char*)pbody, offset, prebody_len);
7925 wl_stop_wait_next_action_frame(struct wl_priv *wl)
7927 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
7928 if (!(wl_get_p2p_status(wl, ACTION_TX_COMPLETED) ||
7929 wl_get_p2p_status(wl, ACTION_TX_NOACK)))
7930 wl_set_p2p_status(wl, ACTION_TX_COMPLETED);
7932 WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
7933 /* if channel is not zero, "actfame" uses off channel scan.
7934 * So abort scan for off channel completion.
7936 if (wl->af_sent_channel)
7937 wl_cfg80211_scan_abort(wl);
7939 #ifdef WL_CFG80211_SYNC_GON
7940 else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) {
7941 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
7942 /* So abort scan to cancel listen */
7943 wl_cfg80211_scan_abort(wl);
7945 #endif /* WL_CFG80211_SYNC_GON */
7949 int wl_cfg80211_get_ioctl_version(void)
7951 return ioctl_version;
7955 wl_notify_rx_mgmt_frame(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7956 const wl_event_msg_t *e, void *data)
7959 struct ieee80211_supported_band *band;
7960 struct wiphy *wiphy = wl_to_wiphy(wl);
7961 struct ether_addr da;
7962 struct ether_addr bssid;
7963 bool isfree = false;
7966 struct net_device *ndev = NULL;
7967 wifi_p2p_pub_act_frame_t *act_frm = NULL;
7968 wifi_p2p_action_frame_t *p2p_act_frm = NULL;
7969 wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
7970 wl_event_rx_frame_data_t *rxframe =
7971 (wl_event_rx_frame_data_t*)data;
7972 u32 event = ntoh32(e->event_type);
7974 u8 bsscfgidx = e->bsscfgidx;
7975 u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
7976 u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
7978 memset(&bssid, 0, ETHER_ADDR_LEN);
7980 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7982 if (channel <= CH_MAX_2G_CHANNEL)
7983 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7985 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7987 WL_ERR(("No valid band"));
7990 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
7991 freq = ieee80211_channel_to_frequency(channel);
7994 freq = ieee80211_channel_to_frequency(channel, band->band);
7996 if (event == WLC_E_ACTION_FRAME_RX) {
7997 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
7998 NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
8000 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
8002 WL_ERR(("WLC_GET_BSSID error %d\n", err));
8003 memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
8004 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
8005 &mgmt_frame, &mgmt_frame_len,
8006 (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
8008 WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
8009 mgmt_frame_len, channel, freq));
8013 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8014 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8015 act_frm = (wifi_p2p_pub_act_frame_t *)
8016 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8017 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8018 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8019 p2p_act_frm = (wifi_p2p_action_frame_t *)
8020 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8022 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8023 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8025 sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
8026 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8027 if (sd_act_frm && wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8028 if (wl->next_af_subtype == sd_act_frm->action) {
8029 WL_DBG(("We got a right next frame of SD!(%d)\n",
8030 sd_act_frm->action));
8031 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8033 /* Stop waiting for next AF. */
8034 wl_stop_wait_next_action_frame(wl);
8040 * if we got normal action frame and ndev is p2p0,
8041 * we have to change ndev from p2p0 to wlan0
8043 #if defined(WL_ENABLE_P2P_IF)
8044 if (wl->p2p_net == cfgdev)
8045 cfgdev = wl_to_prmry_ndev(wl);
8046 #endif /* WL_ENABLE_P2P_IF */
8048 if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
8050 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8051 mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
8052 WL_DBG(("Recived action is not public action frame\n"));
8053 } else if (wl->next_af_subtype == action) {
8054 WL_DBG(("Recived action is the waiting action(%d)\n",
8056 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8058 /* Stop waiting for next AF. */
8059 wl_stop_wait_next_action_frame(wl);
8066 if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8067 if (wl->next_af_subtype == act_frm->subtype) {
8068 WL_DBG(("We got a right next frame!(%d)\n",
8070 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8072 if (wl->next_af_subtype == P2P_PAF_GON_CONF) {
8076 /* Stop waiting for next AF. */
8077 wl_stop_wait_next_action_frame(wl);
8082 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
8083 mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
8085 * After complete GO Negotiation, roll back to mpc mode
8087 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
8088 (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
8089 wldev_iovar_setint(ndev, "mpc", 1);
8091 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
8092 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
8093 wl_clr_p2p_status(wl, GO_NEG_PHASE);
8096 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
8098 /* wpa supplicant use probe request event for restarting another GON Req.
8099 * but it makes GON Req repetition.
8100 * so if src addr of prb req is same as my target device,
8101 * do not send probe request event during sending action frame.
8103 if (event == WLC_E_P2P_PROBREQ_MSG) {
8104 WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
8105 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
8108 /* Filter any P2P probe reqs arriving during the
8112 wl_get_p2p_status(wl, GO_NEG_PHASE)) {
8113 WL_DBG(("Filtering P2P probe_req while "
8114 "being in GO-Neg state\n"));
8120 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
8121 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8123 cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8126 WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
8127 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
8134 #ifdef WL_SCHED_SCAN
8135 /* If target scan is not reliable, set the below define to "1" to do a
8138 #define FULL_ESCAN_ON_PFN_NET_FOUND 0
8140 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
8141 const wl_event_msg_t *e, void *data)
8143 wl_pfn_net_info_t *netinfo, *pnetinfo;
8144 struct wiphy *wiphy = wl_to_wiphy(wl);
8146 struct cfg80211_scan_request *request = NULL;
8147 struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
8148 struct ieee80211_channel *channel = NULL;
8149 int channel_req = 0;
8151 struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
8152 int n_pfn_results = pfn_result->count;
8154 WL_DBG(("Enter\n"));
8156 if (e->event_type == WLC_E_PFN_NET_LOST) {
8157 WL_PNO(("PFN NET LOST event. Do Nothing \n"));
8160 WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
8161 if (n_pfn_results > 0) {
8164 if (n_pfn_results > MAX_PFN_LIST_COUNT)
8165 n_pfn_results = MAX_PFN_LIST_COUNT;
8166 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
8167 - sizeof(wl_pfn_net_info_t));
8169 memset(&ssid, 0x00, sizeof(ssid));
8171 request = kzalloc(sizeof(*request)
8172 + sizeof(*request->channels) * n_pfn_results,
8174 channel = (struct ieee80211_channel *)kzalloc(
8175 (sizeof(struct ieee80211_channel) * n_pfn_results),
8177 if (!request || !channel) {
8178 WL_ERR(("No memory"));
8183 request->wiphy = wiphy;
8185 for (i = 0; i < n_pfn_results; i++) {
8186 netinfo = &pnetinfo[i];
8188 WL_ERR(("Invalid netinfo ptr. index:%d", i));
8192 WL_PNO((">>> SSID:%s Channel:%d \n",
8193 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
8194 /* PFN result doesn't have all the info which are required by the supplicant
8195 * (For e.g IEs) Do a target Escan so that sched scan results are reported
8196 * via wl_inform_single_bss in the required format. Escan does require the
8197 * scan request in the form of cfg80211_scan_request. For timebeing, create
8198 * cfg80211_scan_request one out of the received PNO event.
8200 memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
8201 netinfo->pfnsubnet.SSID_len);
8202 ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
8205 channel_req = netinfo->pfnsubnet.channel;
8206 band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
8207 : NL80211_BAND_5GHZ;
8208 channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
8209 channel[i].band = band;
8210 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
8211 request->channels[i] = &channel[i];
8212 request->n_channels++;
8215 /* assign parsed ssid array */
8216 if (request->n_ssids)
8217 request->ssids = &ssid[0];
8219 if (wl_get_drv_status_all(wl, SCANNING)) {
8220 /* Abort any on-going scan */
8221 wl_notify_escan_complete(wl, ndev, true, true);
8224 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
8225 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
8226 err = wl_cfgp2p_discover_enable_search(wl, false);
8227 if (unlikely(err)) {
8228 wl_clr_drv_status(wl, SCANNING, ndev);
8233 wl_set_drv_status(wl, SCANNING, ndev);
8234 #if FULL_ESCAN_ON_PFN_NET_FOUND
8235 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
8236 err = wl_do_escan(wl, wiphy, ndev, NULL);
8238 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
8239 err = wl_do_escan(wl, wiphy, ndev, request);
8242 wl_clr_drv_status(wl, SCANNING, ndev);
8245 wl->sched_scan_running = TRUE;
8248 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
8257 #endif /* WL_SCHED_SCAN */
8259 static void wl_init_conf(struct wl_conf *conf)
8261 WL_DBG(("Enter \n"));
8262 conf->frag_threshold = (u32)-1;
8263 conf->rts_threshold = (u32)-1;
8264 conf->retry_short = (u32)-1;
8265 conf->retry_long = (u32)-1;
8266 conf->tx_power = -1;
8269 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev)
8271 unsigned long flags;
8272 struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
8274 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8275 memset(profile, 0, sizeof(struct wl_profile));
8276 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8279 static void wl_init_event_handler(struct wl_priv *wl)
8281 memset(wl->evt_handler, 0, sizeof(wl->evt_handler));
8283 wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
8284 wl->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
8285 wl->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
8286 wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
8287 wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
8288 wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
8289 wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
8290 wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
8291 wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
8292 wl->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
8293 wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
8294 wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
8295 wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
8296 wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8297 wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8298 wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
8299 wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
8300 wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
8301 wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
8302 wl->evt_handler[WLC_E_START] = wl_notify_connect_status;
8304 wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
8305 #endif /* PNO_SUPPORT */
8307 wl->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
8310 wl->evt_handler[WLC_E_CCX_S69_RESP_RX] = wl_ccx_s69_response;
8314 #if defined(STATIC_WL_PRIV_STRUCT)
8316 wl_init_escan_result_buf(struct wl_priv *wl)
8318 wl->escan_info.escan_buf = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0);
8319 bzero(wl->escan_info.escan_buf, ESCAN_BUF_SIZE);
8323 wl_deinit_escan_result_buf(struct wl_priv *wl)
8325 wl->escan_info.escan_buf = NULL;
8328 #endif /* STATIC_WL_PRIV_STRUCT */
8330 static s32 wl_init_priv_mem(struct wl_priv *wl)
8332 WL_DBG(("Enter \n"));
8333 wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
8334 if (unlikely(!wl->scan_results)) {
8335 WL_ERR(("Scan results alloc failed\n"));
8336 goto init_priv_mem_out;
8338 wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
8339 if (unlikely(!wl->conf)) {
8340 WL_ERR(("wl_conf alloc failed\n"));
8341 goto init_priv_mem_out;
8344 (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
8345 if (unlikely(!wl->scan_req_int)) {
8346 WL_ERR(("Scan req alloc failed\n"));
8347 goto init_priv_mem_out;
8349 wl->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8350 if (unlikely(!wl->ioctl_buf)) {
8351 WL_ERR(("Ioctl buf alloc failed\n"));
8352 goto init_priv_mem_out;
8354 wl->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8355 if (unlikely(!wl->escan_ioctl_buf)) {
8356 WL_ERR(("Ioctl buf alloc failed\n"));
8357 goto init_priv_mem_out;
8359 wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
8360 if (unlikely(!wl->extra_buf)) {
8361 WL_ERR(("Extra buf alloc failed\n"));
8362 goto init_priv_mem_out;
8364 wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
8365 if (unlikely(!wl->iscan)) {
8366 WL_ERR(("Iscan buf alloc failed\n"));
8367 goto init_priv_mem_out;
8369 wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
8370 if (unlikely(!wl->pmk_list)) {
8371 WL_ERR(("pmk list alloc failed\n"));
8372 goto init_priv_mem_out;
8374 wl->sta_info = (void *)kzalloc(sizeof(*wl->sta_info), GFP_KERNEL);
8375 if (unlikely(!wl->sta_info)) {
8376 WL_ERR(("sta info alloc failed\n"));
8377 goto init_priv_mem_out;
8380 #if defined(STATIC_WL_PRIV_STRUCT)
8381 wl->conn_info = (void *)kzalloc(sizeof(*wl->conn_info), GFP_KERNEL);
8382 if (unlikely(!wl->conn_info)) {
8383 WL_ERR(("wl->conn_info alloc failed\n"));
8384 goto init_priv_mem_out;
8386 wl->ie = (void *)kzalloc(sizeof(*wl->ie), GFP_KERNEL);
8387 if (unlikely(!wl->ie)) {
8388 WL_ERR(("wl->ie alloc failed\n"));
8389 goto init_priv_mem_out;
8391 wl_init_escan_result_buf(wl);
8392 #endif /* STATIC_WL_PRIV_STRUCT */
8393 wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL);
8394 if (unlikely(!wl->afx_hdl)) {
8395 WL_ERR(("afx hdl alloc failed\n"));
8396 goto init_priv_mem_out;
8398 init_completion(&wl->act_frm_scan);
8399 init_completion(&wl->wait_next_af);
8401 INIT_WORK(&wl->afx_hdl->work, wl_cfg80211_afx_handler);
8406 wl_deinit_priv_mem(wl);
8411 static void wl_deinit_priv_mem(struct wl_priv *wl)
8413 kfree(wl->scan_results);
8414 wl->scan_results = NULL;
8417 kfree(wl->scan_req_int);
8418 wl->scan_req_int = NULL;
8419 kfree(wl->ioctl_buf);
8420 wl->ioctl_buf = NULL;
8421 kfree(wl->escan_ioctl_buf);
8422 wl->escan_ioctl_buf = NULL;
8423 kfree(wl->extra_buf);
8424 wl->extra_buf = NULL;
8427 kfree(wl->pmk_list);
8428 wl->pmk_list = NULL;
8429 kfree(wl->sta_info);
8430 wl->sta_info = NULL;
8431 #if defined(STATIC_WL_PRIV_STRUCT)
8432 kfree(wl->conn_info);
8433 wl->conn_info = NULL;
8436 wl_deinit_escan_result_buf(wl);
8437 #endif /* STATIC_WL_PRIV_STRUCT */
8439 cancel_work_sync(&wl->afx_hdl->work);
8445 kfree(wl->ap_info->wpa_ie);
8446 kfree(wl->ap_info->rsn_ie);
8447 kfree(wl->ap_info->wps_ie);
8453 static s32 wl_create_event_handler(struct wl_priv *wl)
8456 WL_DBG(("Enter \n"));
8458 /* Do not use DHD in cfg driver */
8459 wl->event_tsk.thr_pid = -1;
8461 PROC_START(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler");
8462 if (wl->event_tsk.thr_pid < 0)
8467 static void wl_destroy_event_handler(struct wl_priv *wl)
8469 if (wl->event_tsk.thr_pid >= 0)
8470 PROC_STOP(&wl->event_tsk);
8473 static void wl_term_iscan(struct wl_priv *wl)
8475 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
8477 if (wl->iscan_on && iscan->tsk) {
8478 iscan->state = WL_ISCAN_STATE_IDLE;
8479 WL_INFO(("SIGTERM\n"));
8480 send_sig(SIGTERM, iscan->tsk, 1);
8481 WL_DBG(("kthread_stop\n"));
8482 kthread_stop(iscan->tsk);
8487 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
8489 struct wl_priv *wl = iscan_to_wl(iscan);
8490 struct net_device *ndev = wl_to_prmry_ndev(wl);
8491 unsigned long flags;
8493 WL_DBG(("Enter \n"));
8494 if (!wl_get_drv_status(wl, SCANNING, ndev)) {
8495 wl_clr_drv_status(wl, SCANNING, ndev);
8496 WL_ERR(("Scan complete while device not scanning\n"));
8499 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8500 wl_clr_drv_status(wl, SCANNING, ndev);
8501 if (likely(wl->scan_request)) {
8502 cfg80211_scan_done(wl->scan_request, aborted);
8503 wl->scan_request = NULL;
8505 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8506 wl->iscan_kickstart = false;
8509 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
8511 if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
8512 WL_DBG(("wake up iscan\n"));
8521 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
8522 struct wl_scan_results **bss_list)
8524 struct wl_iscan_results list;
8525 struct wl_scan_results *results;
8526 struct wl_iscan_results *list_buf;
8529 WL_DBG(("Enter \n"));
8530 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
8531 list_buf = (struct wl_iscan_results *)iscan->scan_buf;
8532 results = &list_buf->results;
8533 results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
8534 results->version = 0;
8537 memset(&list, 0, sizeof(list));
8538 list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
8539 err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list,
8540 WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
8541 WL_ISCAN_BUF_MAX, NULL);
8542 if (unlikely(err)) {
8543 WL_ERR(("error (%d)\n", err));
8546 results->buflen = dtoh32(results->buflen);
8547 results->version = dtoh32(results->version);
8548 results->count = dtoh32(results->count);
8549 WL_DBG(("results->count = %d\n", results->count));
8550 WL_DBG(("results->buflen = %d\n", results->buflen));
8551 *status = dtoh32(list_buf->status);
8552 *bss_list = results;
8557 static s32 wl_iscan_done(struct wl_priv *wl)
8559 struct wl_iscan_ctrl *iscan = wl->iscan;
8562 iscan->state = WL_ISCAN_STATE_IDLE;
8563 mutex_lock(&wl->usr_sync);
8565 wl_notify_iscan_complete(iscan, false);
8566 mutex_unlock(&wl->usr_sync);
8571 static s32 wl_iscan_pending(struct wl_priv *wl)
8573 struct wl_iscan_ctrl *iscan = wl->iscan;
8576 /* Reschedule the timer */
8577 mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
8578 iscan->timer_on = 1;
8583 static s32 wl_iscan_inprogress(struct wl_priv *wl)
8585 struct wl_iscan_ctrl *iscan = wl->iscan;
8588 mutex_lock(&wl->usr_sync);
8590 wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
8591 mutex_unlock(&wl->usr_sync);
8592 /* Reschedule the timer */
8593 mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
8594 iscan->timer_on = 1;
8599 static s32 wl_iscan_aborted(struct wl_priv *wl)
8601 struct wl_iscan_ctrl *iscan = wl->iscan;
8604 iscan->state = WL_ISCAN_STATE_IDLE;
8605 mutex_lock(&wl->usr_sync);
8606 wl_notify_iscan_complete(iscan, true);
8607 mutex_unlock(&wl->usr_sync);
8612 static s32 wl_iscan_thread(void *data)
8614 struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
8615 struct wl_priv *wl = iscan_to_wl(iscan);
8619 allow_signal(SIGTERM);
8620 status = WL_SCAN_RESULTS_PARTIAL;
8621 while (likely(!down_interruptible(&iscan->sync))) {
8622 if (kthread_should_stop())
8624 if (iscan->timer_on) {
8625 del_timer_sync(&iscan->timer);
8626 iscan->timer_on = 0;
8628 mutex_lock(&wl->usr_sync);
8629 err = wl_get_iscan_results(iscan, &status, &wl->bss_list);
8630 if (unlikely(err)) {
8631 status = WL_SCAN_RESULTS_ABORTED;
8632 WL_ERR(("Abort iscan\n"));
8634 mutex_unlock(&wl->usr_sync);
8635 iscan->iscan_handler[status] (wl);
8637 if (iscan->timer_on) {
8638 del_timer_sync(&iscan->timer);
8639 iscan->timer_on = 0;
8641 WL_DBG(("was terminated\n"));
8646 static void wl_scan_timeout(unsigned long data)
8649 struct wl_priv *wl = (struct wl_priv *)data;
8651 if (!(wl->scan_request)) {
8652 WL_ERR(("timer expired but no scan request\n"));
8655 bzero(&msg, sizeof(wl_event_msg_t));
8656 WL_ERR(("timer expired\n"));
8658 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
8659 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
8660 msg.reason = 0xFFFFFFFF;
8661 wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL);
8663 /* Need to check it try to access SDIO */
8664 WL_ERR(("SCAN Timeout(ISCAN)\n"));
8665 wl_notify_iscan_complete(wl_to_iscan(wl), true);
8669 static void wl_iscan_timer(unsigned long data)
8671 struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
8674 iscan->timer_on = 0;
8675 WL_DBG(("timer expired\n"));
8676 wl_wakeup_iscan(iscan);
8680 static s32 wl_invoke_iscan(struct wl_priv *wl)
8682 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
8685 if (wl->iscan_on && !iscan->tsk) {
8686 iscan->state = WL_ISCAN_STATE_IDLE;
8687 sema_init(&iscan->sync, 0);
8688 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
8689 if (IS_ERR(iscan->tsk)) {
8690 WL_ERR(("Could not create iscan thread\n"));
8699 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan)
8701 memset(iscan->iscan_handler, 0, sizeof(iscan->iscan_handler));
8702 iscan->iscan_handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
8703 iscan->iscan_handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
8704 iscan->iscan_handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
8705 iscan->iscan_handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
8706 iscan->iscan_handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
8710 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
8711 unsigned long state,
8714 struct net_device *dev = ndev;
8715 struct wireless_dev *wdev = dev->ieee80211_ptr;
8716 struct wl_priv *wl = wlcfg_drv_priv;
8719 WL_DBG(("Enter \n"));
8720 if (!wdev || !wl || dev == wl_to_prmry_ndev(wl))
8725 int max_wait_timeout = 2;
8726 int max_wait_count = 100;
8727 unsigned long limit = jiffies + max_wait_timeout * HZ;
8728 while (work_pending(&wdev->cleanup_work)) {
8729 if (refcnt%5 == 0) {
8730 WL_ERR(("[NETDEV_DOWN] wait for "
8731 "complete of cleanup_work"
8732 " (%d th)\n", refcnt));
8734 if (!time_before(jiffies, limit)) {
8735 WL_ERR(("[NETDEV_DOWN] cleanup_work"
8736 " of CFG80211 is not"
8737 " completed in %d sec\n",
8741 if (refcnt >= max_wait_count) {
8742 WL_ERR(("[NETDEV_DOWN] cleanup_work"
8743 " of CFG80211 is not"
8744 " completed in %d loop\n",
8748 set_current_state(TASK_INTERRUPTIBLE);
8749 schedule_timeout(100);
8750 set_current_state(TASK_RUNNING);
8756 case NETDEV_UNREGISTER:
8757 /* after calling list_del_rcu(&wdev->list) */
8758 wl_remove_netinfo(wl, ndev);
8760 case NETDEV_GOING_DOWN:
8761 /* At NETDEV_DOWN state, wdev_cleanup_work work will be called.
8762 * In front of door, the function checks
8763 * whether current scan is working or not.
8764 * If the scanning is still working, wdev_cleanup_work call WARN_ON and
8765 * make the scan done forcibly.
8767 if (wl_get_drv_status(wl, SCANNING, dev)) {
8769 wl_notify_escan_complete(wl, dev, true, true);
8776 static struct notifier_block wl_cfg80211_netdev_notifier = {
8777 .notifier_call = wl_cfg80211_netdev_notifier_call,
8780 static void wl_cfg80211_scan_abort(struct wl_priv *wl)
8782 wl_scan_params_t *params = NULL;
8783 s32 params_size = 0;
8785 struct net_device *dev = wl_to_prmry_ndev(wl);
8787 /* Our scan params only need space for 1 channel and 0 ssids */
8788 params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size);
8789 if (params == NULL) {
8790 WL_ERR(("scan params allocation failed \n"));
8793 /* Do a scan abort to stop the driver's scan engine */
8794 err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
8796 WL_ERR(("scan abort failed \n"));
8802 static s32 wl_notify_escan_complete(struct wl_priv *wl,
8803 struct net_device *ndev,
8804 bool aborted, bool fw_abort)
8807 unsigned long flags;
8808 struct net_device *dev;
8810 WL_DBG(("Enter \n"));
8812 WL_ERR(("ndev is null\n"));
8817 if (wl->escan_info.ndev != ndev) {
8818 WL_ERR(("ndev is different %p %p\n", wl->escan_info.ndev, ndev));
8823 if (wl->scan_request) {
8824 dev = wl_to_prmry_ndev(wl);
8825 #if defined(WL_ENABLE_P2P_IF)
8826 if (wl->scan_request->dev != wl->p2p_net)
8827 dev = wl->scan_request->dev;
8828 #endif /* WL_ENABLE_P2P_IF */
8831 WL_DBG(("wl->scan_request is NULL may be internal scan."
8832 "doing scan_abort for ndev %p primary %p",
8833 ndev, wl_to_prmry_ndev(wl)));
8836 if (fw_abort && !in_atomic()) {
8837 wl_cfg80211_scan_abort(wl);
8840 if (timer_pending(&wl->scan_timeout))
8841 del_timer_sync(&wl->scan_timeout);
8842 #if defined(ESCAN_RESULT_PATCH)
8843 if (likely(wl->scan_request)) {
8844 wl->bss_list = wl_escan_get_buf(wl, aborted);
8847 #endif /* ESCAN_RESULT_PATCH */
8848 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8849 #ifdef WL_SCHED_SCAN
8850 if (wl->sched_scan_req && !wl->scan_request) {
8851 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
8853 cfg80211_sched_scan_results(wl->sched_scan_req->wiphy);
8854 wl->sched_scan_running = FALSE;
8855 wl->sched_scan_req = NULL;
8857 #endif /* WL_SCHED_SCAN */
8858 if (likely(wl->scan_request)) {
8859 cfg80211_scan_done(wl->scan_request, aborted);
8860 wl->scan_request = NULL;
8863 wl_clr_p2p_status(wl, SCANNING);
8864 wl_clr_drv_status(wl, SCANNING, dev);
8865 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8869 static s32 wl_escan_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8870 const wl_event_msg_t *e, void *data)
8873 s32 status = ntoh32(e->status);
8875 wl_escan_result_t *escan_result;
8876 wl_bss_info_t *bss = NULL;
8877 wl_scan_results_t *list;
8878 wifi_p2p_ie_t * p2p_ie;
8879 struct net_device *ndev = NULL;
8882 u8 *p2p_dev_addr = NULL;
8884 WL_DBG((" enter event type : %d, status : %d \n",
8885 ntoh32(e->event_type), ntoh32(e->status)));
8887 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8889 mutex_lock(&wl->usr_sync);
8890 /* P2P SCAN is coming from primary interface */
8891 if (wl_get_p2p_status(wl, SCANNING)) {
8892 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM))
8893 ndev = wl->afx_hdl->dev;
8895 ndev = wl->escan_info.ndev;
8898 if (!ndev || !wl->escan_on ||
8899 (!wl_get_drv_status(wl, SCANNING, ndev) &&
8900 !wl->sched_scan_running)) {
8901 WL_ERR(("escan is not ready ndev %p wl->escan_on %d"
8902 " drv_status 0x%x e_type %d e_states %d\n",
8903 ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev),
8904 ntoh32(e->event_type), ntoh32(e->status)));
8907 escan_result = (wl_escan_result_t *)data;
8909 if (status == WLC_E_STATUS_PARTIAL) {
8910 WL_INFO(("WLC_E_STATUS_PARTIAL \n"));
8911 if (!escan_result) {
8912 WL_ERR(("Invalid escan result (NULL pointer)\n"));
8915 if (dtoh16(escan_result->bss_count) != 1) {
8916 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
8919 bi = escan_result->bss_info;
8921 WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
8924 bi_length = dtoh32(bi->length);
8925 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
8926 WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
8929 if (wl_escan_check_sync_id(status, escan_result->sync_id,
8930 wl->escan_info.cur_sync_id) < 0)
8933 if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
8934 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
8935 WL_DBG(("Ignoring IBSS result\n"));
8940 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
8941 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
8942 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
8943 wl->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
8944 s32 channel = wf_chspec_ctlchan(
8945 wl_chspec_driver_to_host(bi->chanspec));
8947 if ((channel > MAXCHANNEL) || (channel <= 0))
8948 channel = WL_INVALID;
8950 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
8952 MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet),
8955 wl_clr_p2p_status(wl, SCANNING);
8956 wl->afx_hdl->peer_chan = channel;
8957 complete(&wl->act_frm_scan);
8962 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
8963 list = wl_escan_get_buf(wl, FALSE);
8964 if (scan_req_match(wl)) {
8965 /* p2p scan && allow only probe response */
8966 if ((wl->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
8967 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
8969 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
8970 bi->ie_length)) == NULL) {
8971 WL_ERR(("Couldn't find P2PIE in probe"
8972 " response/beacon\n"));
8976 for (i = 0; i < list->count; i++) {
8977 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
8980 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
8981 (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
8982 == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
8983 bi->SSID_len == bss->SSID_len &&
8984 !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
8986 /* do not allow beacon data to update
8987 *the data recd from a probe response
8989 if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
8990 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
8993 WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d"
8994 " flags 0x%x, new: RSSI %d flags 0x%x\n",
8995 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
8996 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
8998 if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
8999 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
9000 /* preserve max RSSI if the measurements are
9001 * both on-channel or both off-channel
9003 WL_SCAN(("%s("MACDBG"), same onchan"
9004 ", RSSI: prev %d new %d\n",
9005 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9006 bss->RSSI, bi->RSSI));
9007 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
9008 } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
9009 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
9010 /* preserve the on-channel rssi measurement
9011 * if the new measurement is off channel
9013 WL_SCAN(("%s("MACDBG"), prev onchan"
9014 ", RSSI: prev %d new %d\n",
9015 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9016 bss->RSSI, bi->RSSI));
9017 bi->RSSI = bss->RSSI;
9018 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
9020 if (dtoh32(bss->length) != bi_length) {
9021 u32 prev_len = dtoh32(bss->length);
9023 WL_SCAN(("bss info replacement"
9024 " is occured(bcast:%d->probresp%d)\n",
9025 bss->ie_length, bi->ie_length));
9026 WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n",
9027 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9028 prev_len, bi_length));
9030 if (list->buflen - prev_len + bi_length
9032 WL_ERR(("Buffer is too small: keep the"
9033 " previous result of this AP\n"));
9034 /* Only update RSSI */
9035 bss->RSSI = bi->RSSI;
9036 bss->flags |= (bi->flags
9037 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
9041 if (i < list->count - 1) {
9042 /* memory copy required by this case only */
9043 memmove((u8 *)bss + bi_length,
9044 (u8 *)bss + prev_len,
9045 list->buflen - cur_len - prev_len);
9047 list->buflen -= prev_len;
9048 list->buflen += bi_length;
9050 list->version = dtoh32(bi->version);
9051 memcpy((u8 *)bss, (u8 *)bi, bi_length);
9054 cur_len += dtoh32(bss->length);
9056 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
9057 WL_ERR(("Buffer is too small: ignoring\n"));
9061 memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
9062 list->version = dtoh32(bi->version);
9063 list->buflen += bi_length;
9069 else if (status == WLC_E_STATUS_SUCCESS) {
9070 #if defined(P2P_DISCOVERY_WAR)
9071 if (scan_req_match(wl) && !wl->p2p->vif_created) {
9072 if (wldev_iovar_setint(wl_to_prmry_ndev(wl), "mpc", 1) < 0) {
9073 WL_ERR(("mpc enabling back failed\n"));
9076 #endif /* defined(P2P_DISCOVERY_WAR) */
9077 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9078 wl_escan_print_sync_id(status, wl->escan_info.cur_sync_id,
9079 escan_result->sync_id);
9081 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9082 WL_INFO(("ACTION FRAME SCAN DONE\n"));
9083 wl_clr_p2p_status(wl, SCANNING);
9084 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9085 if (wl->afx_hdl->peer_chan == WL_INVALID)
9086 complete(&wl->act_frm_scan);
9087 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9088 WL_INFO(("ESCAN COMPLETED\n"));
9089 wl->bss_list = wl_escan_get_buf(wl, FALSE);
9090 if (!scan_req_match(wl)) {
9091 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
9092 wl->bss_list->count));
9095 wl_notify_escan_complete(wl, ndev, false, false);
9097 wl_escan_increment_sync_id(wl, SCAN_BUF_NEXT);
9099 else if (status == WLC_E_STATUS_ABORT) {
9100 #if defined(P2P_DISCOVERY_WAR)
9101 if (scan_req_match(wl) && !wl->p2p->vif_created) {
9102 if (wldev_iovar_setint(wl_to_prmry_ndev(wl), "mpc", 1) < 0) {
9103 WL_ERR(("mpc enabling back failed\n"));
9106 #endif /* defined(P2P_DISCOVERY_WAR) */
9107 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9108 wl_escan_print_sync_id(status, escan_result->sync_id,
9109 wl->escan_info.cur_sync_id);
9110 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9111 WL_INFO(("ACTION FRAME SCAN DONE\n"));
9112 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9113 wl_clr_p2p_status(wl, SCANNING);
9114 if (wl->afx_hdl->peer_chan == WL_INVALID)
9115 complete(&wl->act_frm_scan);
9116 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9117 WL_INFO(("ESCAN ABORTED\n"));
9118 wl->bss_list = wl_escan_get_buf(wl, TRUE);
9119 if (!scan_req_match(wl)) {
9120 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
9121 wl->bss_list->count));
9124 wl_notify_escan_complete(wl, ndev, true, false);
9126 wl_escan_increment_sync_id(wl, SCAN_BUF_CNT);
9127 } else if (status == WLC_E_STATUS_NEWSCAN) {
9128 WL_ERR(("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", wl->scan_request));
9129 WL_ERR(("sync_id[%d], bss_count[%d]\n", escan_result->sync_id,
9130 escan_result->bss_count));
9131 } else if (status == WLC_E_STATUS_TIMEOUT) {
9132 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", wl->scan_request));
9133 WL_ERR(("escan_on[%d], reason[0x%x]\n", wl->escan_on, e->reason));
9134 if (e->reason == 0xFFFFFFFF) {
9135 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
9138 WL_ERR(("unexpected Escan Event %d : abort\n", status));
9139 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9140 wl_escan_print_sync_id(status, escan_result->sync_id,
9141 wl->escan_info.cur_sync_id);
9142 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9143 WL_INFO(("ACTION FRAME SCAN DONE\n"));
9144 wl_clr_p2p_status(wl, SCANNING);
9145 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9146 if (wl->afx_hdl->peer_chan == WL_INVALID)
9147 complete(&wl->act_frm_scan);
9148 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9149 wl->bss_list = wl_escan_get_buf(wl, TRUE);
9150 if (!scan_req_match(wl)) {
9151 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
9152 "scanned AP count=%d\n",
9153 wl->bss_list->count));
9156 wl_notify_escan_complete(wl, ndev, true, false);
9158 wl_escan_increment_sync_id(wl, 2);
9161 mutex_unlock(&wl->usr_sync);
9165 static void wl_cfg80211_concurrent_roam(struct wl_priv *wl, int enable)
9167 u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED);
9168 struct net_info *iter, *next;
9171 if (!wl->roamoff_on_concurrent)
9173 if (enable && connected_cnt > 1) {
9174 for_each_ndev(wl, iter, next) {
9175 /* Save the current roam setting */
9176 if ((err = wldev_iovar_getint(iter->ndev, "roam_off",
9177 (s32 *)&iter->roam_off)) != BCME_OK) {
9178 WL_ERR(("%s:Failed to get current roam setting err %d\n",
9179 iter->ndev->name, err));
9182 if ((err = wldev_iovar_setint(iter->ndev, "roam_off", 1)) != BCME_OK) {
9183 WL_ERR((" %s:failed to set roam_off : %d\n",
9184 iter->ndev->name, err));
9189 for_each_ndev(wl, iter, next) {
9190 if (iter->roam_off != WL_INVALID) {
9191 if ((err = wldev_iovar_setint(iter->ndev, "roam_off",
9192 iter->roam_off)) == BCME_OK)
9193 iter->roam_off = WL_INVALID;
9195 WL_ERR((" %s:failed to set roam_off : %d\n",
9196 iter->ndev->name, err));
9204 static void wl_cfg80211_determine_vsdb_mode(struct wl_priv *wl)
9206 struct net_info *iter, *next;
9209 u32 pre_ctl_chan = 0;
9210 u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED);
9211 wl->vsdb_mode = false;
9213 if (connected_cnt <= 1) {
9216 for_each_ndev(wl, iter, next) {
9219 if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) {
9220 if (wldev_iovar_getint(iter->ndev, "chanspec",
9221 (s32 *)&chanspec) == BCME_OK) {
9222 chanspec = wl_chspec_driver_to_host(chanspec);
9223 ctl_chan = wf_chspec_ctlchan(chanspec);
9224 wl_update_prof(wl, iter->ndev, NULL,
9225 &ctl_chan, WL_PROF_CHAN);
9227 if (!wl->vsdb_mode) {
9228 if (!pre_ctl_chan && ctl_chan)
9229 pre_ctl_chan = ctl_chan;
9230 else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
9231 wl->vsdb_mode = true;
9236 WL_ERR(("%s concurrency is enabled\n", wl->vsdb_mode ? "Multi Channel" : "Same Channel"));
9240 static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
9241 enum wl_status state, bool set)
9247 struct net_info *iter, *next;
9248 struct net_device *primary_dev = wl_to_prmry_ndev(wl);
9249 WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
9250 state, set, _net_info->pm_restore, _net_info->ndev->name));
9252 if (state != WL_STATUS_CONNECTED)
9254 mode = wl_get_mode_by_netdev(wl, _net_info->ndev);
9256 wl_cfg80211_concurrent_roam(wl, 1);
9258 if (mode == WL_MODE_AP) {
9260 if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
9261 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
9263 wl_cfg80211_determine_vsdb_mode(wl);
9264 if (wl->vsdb_mode || _net_info->pm_block) {
9265 /* Delete pm_enable_work */
9266 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_MAINTAIN);
9267 /* save PM_FAST in _net_info to restore this
9268 * if _net_info->pm_block is false
9270 if (!_net_info->pm_block && (mode == WL_MODE_BSS)) {
9271 _net_info->pm = PM_FAST;
9272 _net_info->pm_restore = true;
9275 down_read(&wl->netif_sem);
9276 for_each_ndev(wl, iter, next) {
9277 if (iter->pm_restore)
9279 /* Save the current power mode */
9280 err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm,
9281 sizeof(iter->pm), false);
9282 WL_DBG(("%s:power save %s\n", iter->ndev->name,
9283 iter->pm ? "enabled" : "disabled"));
9284 if (!err && iter->pm) {
9285 iter->pm_restore = true;
9289 for_each_ndev(wl, iter, next) {
9290 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9291 sizeof(pm), true)) != 0) {
9293 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9295 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9297 iter->ndev->ieee80211_ptr->ps = false;
9299 up_read(&wl->netif_sem);
9301 /* add PM Enable timer to go to power save mode
9302 * if supplicant control pm mode, it will be cleared or
9303 * updated by wl_cfg80211_set_power_mgmt() if not - for static IP & HW4 P2P,
9304 * PM will be configured when timer expired
9308 * before calling pm_enable_timer, we need to set PM -1 for all ndev
9311 down_read(&wl->netif_sem);
9312 for_each_ndev(wl, iter, next) {
9313 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9314 sizeof(pm), true)) != 0) {
9316 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9318 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9321 up_read(&wl->netif_sem);
9323 if (wl->pm_enable_work_on) {
9324 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
9327 wl->pm_enable_work_on = true;
9328 wl_add_remove_pm_enable_work(wl, TRUE, WL_HANDLER_NOTUSE);
9333 /* clear chan information when the net device is disconnected */
9334 wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
9335 wl_cfg80211_determine_vsdb_mode(wl);
9336 down_read(&wl->netif_sem);
9337 for_each_ndev(wl, iter, next) {
9338 if (iter->pm_restore && iter->pm) {
9339 WL_DBG(("%s:restoring power save %s\n",
9340 iter->ndev->name, (iter->pm ? "enabled" : "disabled")));
9341 err = wldev_ioctl(iter->ndev,
9342 WLC_SET_PM, &iter->pm, sizeof(iter->pm), true);
9343 if (unlikely(err)) {
9345 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9347 WL_ERR(("%s:error(%d)\n", iter->ndev->name, err));
9350 iter->pm_restore = 0;
9351 iter->ndev->ieee80211_ptr->ps = true;
9354 up_read(&wl->netif_sem);
9355 wl_cfg80211_concurrent_roam(wl, 0);
9359 static s32 wl_init_scan(struct wl_priv *wl)
9361 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
9365 iscan->dev = wl_to_prmry_ndev(wl);
9366 iscan->state = WL_ISCAN_STATE_IDLE;
9367 wl_init_iscan_handler(iscan);
9368 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
9369 init_timer(&iscan->timer);
9370 iscan->timer.data = (unsigned long) iscan;
9371 iscan->timer.function = wl_iscan_timer;
9372 sema_init(&iscan->sync, 0);
9373 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
9374 if (IS_ERR(iscan->tsk)) {
9375 WL_ERR(("Could not create iscan thread\n"));
9380 } else if (wl->escan_on) {
9381 wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
9382 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9383 wl_escan_init_sync_id(wl);
9385 /* Init scan_timeout timer */
9386 init_timer(&wl->scan_timeout);
9387 wl->scan_timeout.data = (unsigned long) wl;
9388 wl->scan_timeout.function = wl_scan_timeout;
9393 static void wl_dealloc_netinfo(struct work_struct *work)
9395 struct net_info *_net_info, *next;
9396 struct wl_priv *wl = container_of(work, struct wl_priv, dealloc_work);
9398 down_write(&wl->netif_sem);
9399 list_for_each_entry_safe(_net_info, next, &wl->dealloc_list, list) {
9400 list_del(&_net_info->list);
9401 if (_net_info->wdev) {
9402 flush_work(&_net_info->wdev->cleanup_work);
9403 WARN_ON(work_pending(&_net_info->wdev->cleanup_work));
9404 kfree(_net_info->wdev);
9408 up_write(&wl->netif_sem);
9411 static s32 wl_init_priv(struct wl_priv *wl)
9413 struct wiphy *wiphy = wl_to_wiphy(wl);
9414 struct net_device *ndev = wl_to_prmry_ndev(wl);
9417 wl->scan_request = NULL;
9418 wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
9419 wl->iscan_on = false;
9420 wl->escan_on = true;
9421 wl->roam_on = false;
9422 wl->iscan_kickstart = false;
9423 wl->active_scan = true;
9424 wl->rf_blocked = false;
9425 wl->vsdb_mode = false;
9426 wl->wlfc_on = false;
9427 wl->roamoff_on_concurrent = true;
9428 /* register interested state */
9429 set_bit(WL_STATUS_CONNECTED, &wl->interrested_state);
9430 spin_lock_init(&wl->cfgdrv_lock);
9431 mutex_init(&wl->ioctl_buf_sync);
9432 init_rwsem(&wl->netif_sem);
9433 init_waitqueue_head(&wl->netif_change_event);
9434 init_completion(&wl->send_af_done);
9435 init_completion(&wl->iface_disable);
9437 err = wl_init_priv_mem(wl);
9440 if (wl_create_event_handler(wl))
9442 wl_init_event_handler(wl);
9443 mutex_init(&wl->usr_sync);
9444 mutex_init(&wl->event_sync);
9445 err = wl_init_scan(wl);
9448 wl_init_conf(wl->conf);
9449 wl_init_prof(wl, ndev);
9451 DNGL_FUNC(dhd_cfg80211_init, (wl));
9452 INIT_LIST_HEAD(&wl->dealloc_list);
9453 INIT_WORK(&wl->dealloc_work, wl_dealloc_netinfo);
9458 static void wl_deinit_priv(struct wl_priv *wl)
9460 DNGL_FUNC(dhd_cfg80211_deinit, (wl));
9461 wl_destroy_event_handler(wl);
9464 del_timer_sync(&wl->scan_timeout);
9466 wl_deinit_priv_mem(wl);
9467 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
9470 #if defined(WL_ENABLE_P2P_IF)
9471 static s32 wl_cfg80211_attach_p2p(void)
9473 struct wl_priv *wl = wlcfg_drv_priv;
9475 WL_TRACE(("Enter \n"));
9477 if (wl_cfgp2p_register_ndev(wl) < 0) {
9478 WL_ERR(("P2P attach failed. \n"));
9485 static s32 wl_cfg80211_detach_p2p(void)
9487 struct wl_priv *wl = wlcfg_drv_priv;
9488 struct wireless_dev *wdev;
9490 WL_DBG(("Enter \n"));
9492 WL_ERR(("Invalid Ptr\n"));
9495 wdev = wl->p2p_wdev;
9498 WL_ERR(("Invalid Ptr\n"));
9502 wl_cfgp2p_unregister_ndev(wl);
9504 wl->p2p_wdev = NULL;
9506 WL_DBG(("Freeing 0x%08x \n", (unsigned int)wdev));
9511 #endif /* WL_ENABLE_P2P_IF */
9513 s32 wl_cfg80211_attach_post(struct net_device *ndev)
9515 struct wl_priv * wl = NULL;
9518 if (unlikely(!ndev)) {
9519 WL_ERR(("ndev is invaild\n"));
9522 wl = wlcfg_drv_priv;
9523 if (unlikely(!wl)) {
9524 WL_ERR(("wl is invaild\n"));
9527 if (!wl_get_drv_status(wl, READY, ndev)) {
9528 if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) {
9529 #if !defined(WL_ENABLE_P2P_IF)
9530 wl->wdev->wiphy->interface_modes |=
9531 (BIT(NL80211_IFTYPE_P2P_CLIENT)|
9532 BIT(NL80211_IFTYPE_P2P_GO));
9533 #endif /* !WL_ENABLE_P2P_IF */
9534 if ((err = wl_cfgp2p_init_priv(wl)) != 0)
9537 #if defined(WL_ENABLE_P2P_IF)
9539 /* Update MAC addr for p2p0 interface here. */
9540 memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
9541 wl->p2p_net->dev_addr[0] |= 0x02;
9542 WL_ERR(("%s: p2p_dev_addr="MACDBG "\n",
9544 MAC2STRDBG(wl->p2p_net->dev_addr)));
9546 WL_ERR(("p2p_net not yet populated."
9547 " Couldn't update the MAC Address for p2p0 \n"));
9550 #endif /* WL_ENABLE_P2P_IF */
9552 wl->p2p_supported = true;
9555 wl_set_drv_status(wl, READY, ndev);
9560 s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
9562 struct wireless_dev *wdev;
9569 WL_ERR(("ndev is invaild\n"));
9572 WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
9573 dev = wl_cfg80211_get_parent_dev();
9575 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
9576 if (unlikely(!wdev)) {
9577 WL_ERR(("Could not allocate wireless device\n"));
9580 err = wl_setup_wiphy(wdev, dev, data);
9581 if (unlikely(err)) {
9585 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
9586 wl = (struct wl_priv *)wiphy_priv(wdev->wiphy);
9589 INIT_LIST_HEAD(&wl->net_list);
9590 ndev->ieee80211_ptr = wdev;
9591 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
9592 wdev->netdev = ndev;
9593 wl->state_notifier = wl_notifier_change_state;
9594 err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS, PM_ENABLE);
9596 WL_ERR(("Failed to alloc net_info (%d)\n", err));
9597 goto cfg80211_attach_out;
9599 err = wl_init_priv(wl);
9601 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
9602 goto cfg80211_attach_out;
9605 err = wl_setup_rfkill(wl, TRUE);
9607 WL_ERR(("Failed to setup rfkill %d\n", err));
9608 goto cfg80211_attach_out;
9610 #ifdef DEBUGFS_CFG80211
9611 err = wl_setup_debugfs(wl);
9613 WL_ERR(("Failed to setup debugfs %d\n", err));
9614 goto cfg80211_attach_out;
9617 err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
9619 WL_ERR(("Failed to register notifierl %d\n", err));
9620 goto cfg80211_attach_out;
9622 #if defined(COEX_DHCP)
9623 err = wl_cfg80211_btcoex_init(wl);
9625 goto cfg80211_attach_out;
9628 wlcfg_drv_priv = wl;
9630 #if defined(WL_ENABLE_P2P_IF)
9631 err = wl_cfg80211_attach_p2p();
9633 goto cfg80211_attach_out;
9634 #endif /* WL_ENABLE_P2P_IF */
9638 cfg80211_attach_out:
9639 wl_setup_rfkill(wl, FALSE);
9644 void wl_cfg80211_detach(void *para)
9649 wl = wlcfg_drv_priv;
9653 #if defined(COEX_DHCP)
9654 wl_cfg80211_btcoex_deinit(wl);
9657 wl_setup_rfkill(wl, FALSE);
9658 #ifdef DEBUGFS_CFG80211
9659 wl_free_debugfs(wl);
9661 if (wl->p2p_supported) {
9662 if (timer_pending(&wl->p2p->listen_timer))
9663 del_timer_sync(&wl->p2p->listen_timer);
9664 wl_cfgp2p_deinit_priv(wl);
9667 #if defined(WL_CFG80211_P2P_DEV_IF)
9668 wl_cfgp2p_del_p2p_disc_if(wl->p2p_wdev);
9669 #elif defined(WL_ENABLE_P2P_IF)
9670 wl_cfg80211_detach_p2p();
9671 #endif /* WL_CFG80211_P2P_DEV_IF */
9673 wl_cfg80211_ibss_vsie_free(wl);
9675 wlcfg_drv_priv = NULL;
9676 wl_cfg80211_clear_parent_dev();
9678 /* PLEASE do NOT call any function after wl_free_wdev, the driver's private structure "wl",
9679 * which is the private part of wiphy, has been freed in wl_free_wdev !!!!!!!!!!!
9683 static void wl_wakeup_event(struct wl_priv *wl)
9685 if (wl->event_tsk.thr_pid >= 0) {
9686 DHD_OS_WAKE_LOCK(wl->pub);
9687 up(&wl->event_tsk.sema);
9691 #if (defined(WL_CFG80211_P2P_DEV_IF) || defined(WL_ENABLE_P2P_IF))
9692 static int wl_is_p2p_event(struct wl_event_q *e)
9695 /* We have to seperate out the P2P events received
9696 * on primary interface so that it can be send up
9697 * via p2p0 interface.
9699 case WLC_E_P2P_PROBREQ_MSG:
9700 case WLC_E_P2P_DISC_LISTEN_COMPLETE:
9701 case WLC_E_ACTION_FRAME_RX:
9702 case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE:
9703 case WLC_E_ACTION_FRAME_COMPLETE:
9705 if (e->emsg.ifidx != 0) {
9706 WL_TRACE(("P2P event(%d) on virtual interface(ifidx:%d)\n",
9707 e->etype, e->emsg.ifidx));
9708 /* We are only bothered about the P2P events received
9709 * on primary interface. For rest of them return false
9710 * so that it is sent over the interface corresponding
9715 WL_TRACE(("P2P event(%d) on interface(ifidx:%d)\n",
9716 e->etype, e->emsg.ifidx));
9722 WL_TRACE(("NON-P2P event(%d) on interface(ifidx:%d)\n",
9723 e->etype, e->emsg.ifidx));
9727 #endif /* BCMDONGLEHOST && (WL_CFG80211_P2P_DEV_IF || WL_ENABLE_P2P_IF) */
9729 static s32 wl_event_handler(void *data)
9731 struct wl_priv *wl = NULL;
9732 struct wl_event_q *e;
9733 tsk_ctl_t *tsk = (tsk_ctl_t *)data;
9734 bcm_struct_cfgdev *cfgdev = NULL;
9735 struct net_device *netdev;
9737 wl = (struct wl_priv *)tsk->parent;
9739 WL_ERR(("tsk Enter, tsk = 0x%08x\n", (unsigned int)tsk));
9741 while (down_interruptible (&tsk->sema) == 0) {
9742 SMP_RD_BARRIER_DEPENDS();
9743 if (tsk->terminated)
9745 while ((e = wl_deq_event(wl))) {
9746 WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx));
9747 /* All P2P device address related events comes on primary interface since
9748 * there is no corresponding bsscfg for P2P interface. Map it to p2p0
9751 #if defined(WL_CFG80211_P2P_DEV_IF)
9752 if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_wdev)) {
9753 cfgdev = wl_to_p2p_wdev(wl);
9755 netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx);
9757 cfgdev = ndev_to_wdev(netdev);
9759 #elif defined(WL_ENABLE_P2P_IF)
9760 if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) {
9761 cfgdev = wl->p2p_net;
9763 cfgdev = dhd_idx2net((struct dhd_pub *)(wl->pub),
9766 #endif /* WL_CFG80211_P2P_DEV_IF */
9769 #if defined(WL_CFG80211_P2P_DEV_IF)
9770 cfgdev = wl_to_prmry_wdev(wl);
9771 #elif defined(WL_ENABLE_P2P_IF)
9772 cfgdev = wl_to_prmry_ndev(wl);
9773 #endif /* WL_CFG80211_P2P_DEV_IF */
9775 if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
9776 wl->evt_handler[e->etype] (wl, cfgdev, &e->emsg, e->edata);
9778 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
9782 DHD_OS_WAKE_UNLOCK(wl->pub);
9784 WL_ERR(("was terminated\n"));
9785 complete_and_exit(&tsk->completed, 0);
9790 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
9792 u32 event_type = ntoh32(e->event_type);
9793 struct wl_priv *wl = wlcfg_drv_priv;
9795 #if (WL_DBG_LEVEL > 0)
9796 s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
9797 wl_dbg_estr[event_type] : (s8 *) "Unknown";
9798 WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
9799 #endif /* (WL_DBG_LEVEL > 0) */
9801 if (event_type == WLC_E_PFN_NET_FOUND) {
9802 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
9804 else if (event_type == WLC_E_PFN_NET_LOST) {
9805 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
9808 if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
9809 wl_wakeup_event(wl);
9812 static void wl_init_eq(struct wl_priv *wl)
9814 wl_init_eq_lock(wl);
9815 INIT_LIST_HEAD(&wl->eq_list);
9818 static void wl_flush_eq(struct wl_priv *wl)
9820 struct wl_event_q *e;
9821 unsigned long flags;
9823 flags = wl_lock_eq(wl);
9824 while (!list_empty(&wl->eq_list)) {
9825 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
9826 list_del(&e->eq_list);
9829 wl_unlock_eq(wl, flags);
9833 * retrieve first queued event from head
9836 static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
9838 struct wl_event_q *e = NULL;
9839 unsigned long flags;
9841 flags = wl_lock_eq(wl);
9842 if (likely(!list_empty(&wl->eq_list))) {
9843 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
9844 list_del(&e->eq_list);
9846 wl_unlock_eq(wl, flags);
9852 * push event to tail of the queue
9856 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_event_msg_t *msg,
9859 struct wl_event_q *e;
9863 unsigned long flags;
9868 data_len = ntoh32(msg->datalen);
9869 evtq_size = sizeof(struct wl_event_q) + data_len;
9870 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
9871 e = kzalloc(evtq_size, aflags);
9873 WL_ERR(("event alloc failed\n"));
9877 memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
9879 memcpy(e->edata, data, data_len);
9880 flags = wl_lock_eq(wl);
9881 list_add_tail(&e->eq_list, &wl->eq_list);
9882 wl_unlock_eq(wl, flags);
9887 static void wl_put_event(struct wl_event_q *e)
9892 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype)
9898 case NL80211_IFTYPE_MONITOR:
9899 case NL80211_IFTYPE_WDS:
9900 WL_ERR(("type (%d) : currently we do not support this mode\n",
9904 case NL80211_IFTYPE_ADHOC:
9905 mode = WL_MODE_IBSS;
9907 case NL80211_IFTYPE_STATION:
9908 case NL80211_IFTYPE_P2P_CLIENT:
9912 case NL80211_IFTYPE_AP:
9913 case NL80211_IFTYPE_P2P_GO:
9919 WL_ERR(("invalid type (%d)\n", iftype));
9922 infra = htod32(infra);
9923 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
9924 if (unlikely(err)) {
9925 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
9929 wl_set_mode_by_netdev(wl, ndev, mode);
9934 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
9936 if (!ev || (event > WLC_E_LAST))
9939 if (ev->num < MAX_EVENT_BUF_NUM) {
9940 ev->event[ev->num].type = event;
9941 ev->event[ev->num].set = set;
9944 WL_ERR(("evenbuffer doesn't support > %u events. Update"
9945 " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
9950 s32 wl_cfg80211_apply_eventbuffer(
9951 struct net_device *ndev,
9953 wl_eventmsg_buf_t *ev)
9955 char eventmask[WL_EVENTING_MASK_LEN];
9957 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
9959 if (!ev || (!ev->num))
9962 mutex_lock(&wl->event_sync);
9964 /* Read event_msgs mask */
9965 bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
9967 ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
9968 if (unlikely(ret)) {
9969 WL_ERR(("Get event_msgs error (%d)\n", ret));
9972 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
9974 /* apply the set bits */
9975 for (i = 0; i < ev->num; i++) {
9976 if (ev->event[i].set)
9977 setbit(eventmask, ev->event[i].type);
9979 clrbit(eventmask, ev->event[i].type);
9982 /* Write updated Event mask */
9983 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
9985 ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
9986 if (unlikely(ret)) {
9987 WL_ERR(("Set event_msgs error (%d)\n", ret));
9991 mutex_unlock(&wl->event_sync);
9995 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
9997 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
9998 s8 eventmask[WL_EVENTING_MASK_LEN];
10000 struct wl_priv *wl = wlcfg_drv_priv;
10005 mutex_lock(&wl->event_sync);
10007 /* Setup event_msgs */
10008 bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
10010 err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
10011 if (unlikely(err)) {
10012 WL_ERR(("Get event_msgs error (%d)\n", err));
10015 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
10017 setbit(eventmask, event);
10019 clrbit(eventmask, event);
10021 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
10023 err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
10024 if (unlikely(err)) {
10025 WL_ERR(("Set event_msgs error (%d)\n", err));
10030 mutex_unlock(&wl->event_sync);
10034 static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
10036 struct net_device *dev = wl_to_prmry_ndev(wl);
10037 struct ieee80211_channel *band_chan_arr = NULL;
10038 wl_uint32_list_t *list;
10039 u32 i, j, index, n_2g, n_5g, band, channel, array_size;
10046 bool dfs_radar_disabled = FALSE;
10048 #define LOCAL_BUF_LEN 1024
10049 pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
10051 if (pbuf == NULL) {
10052 WL_ERR(("failed to allocate local buf\n"));
10055 list = (wl_uint32_list_t *)(void *)pbuf;
10056 list->count = htod32(WL_NUMCHANSPECS);
10059 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
10060 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync);
10062 WL_ERR(("get chanspecs failed with %d\n", err));
10066 #undef LOCAL_BUF_LEN
10068 list = (wl_uint32_list_t *)(void *)pbuf;
10069 band = array_size = n_2g = n_5g = 0;
10070 for (i = 0; i < dtoh32(list->count); i++) {
10073 ht40_allowed = false;
10074 c = (chanspec_t)dtoh32(list->element[i]);
10075 c = wl_chspec_driver_to_host(c);
10076 channel = CHSPEC_CHANNEL(c);
10077 if (CHSPEC_IS40(c)) {
10078 if (CHSPEC_SB_UPPER(c))
10079 channel += CH_10MHZ_APART;
10081 channel -= CH_10MHZ_APART;
10082 } else if (CHSPEC_IS80(c)) {
10083 WL_DBG(("HT80 center channel : %d\n", channel));
10086 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
10087 (channel <= CH_MAX_2G_CHANNEL)) {
10088 band_chan_arr = __wl_2ghz_channels;
10089 array_size = ARRAYSIZE(__wl_2ghz_channels);
10091 band = IEEE80211_BAND_2GHZ;
10092 ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false;
10093 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
10094 band_chan_arr = __wl_5ghz_a_channels;
10095 array_size = ARRAYSIZE(__wl_5ghz_a_channels);
10097 band = IEEE80211_BAND_5GHZ;
10098 ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
10100 WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
10103 if (!ht40_allowed && CHSPEC_IS40(c))
10105 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
10106 if (band_chan_arr[j].hw_value == channel) {
10115 if (index < array_size) {
10116 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
10117 band_chan_arr[index].center_freq =
10118 ieee80211_channel_to_frequency(channel);
10120 band_chan_arr[index].center_freq =
10121 ieee80211_channel_to_frequency(channel, band);
10123 band_chan_arr[index].hw_value = channel;
10125 if (CHSPEC_IS40(c) && ht40_allowed) {
10126 /* assuming the order is HT20, HT40 Upper,
10127 * HT40 lower from chanspecs
10129 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
10130 if (CHSPEC_SB_UPPER(c)) {
10131 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10132 band_chan_arr[index].flags &=
10133 ~IEEE80211_CHAN_NO_HT40;
10134 band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
10136 /* It should be one of
10137 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
10139 band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
10140 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10141 band_chan_arr[index].flags |=
10142 IEEE80211_CHAN_NO_HT40MINUS;
10145 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
10146 if (!dfs_radar_disabled) {
10147 if (band == IEEE80211_BAND_2GHZ)
10148 channel |= WL_CHANSPEC_BAND_2G;
10150 channel |= WL_CHANSPEC_BAND_5G;
10151 channel |= WL_CHANSPEC_BW_20;
10152 channel = wl_chspec_host_to_driver(channel);
10153 err = wldev_iovar_getint(dev, "per_chan_info", &channel);
10155 if (channel & WL_CHAN_RADAR)
10156 band_chan_arr[index].flags |=
10157 (IEEE80211_CHAN_RADAR |
10158 IEEE80211_CHAN_NO_IBSS);
10159 if (channel & WL_CHAN_PASSIVE)
10160 band_chan_arr[index].flags |=
10161 IEEE80211_CHAN_PASSIVE_SCAN;
10162 } else if (err == BCME_UNSUPPORTED) {
10163 dfs_radar_disabled = TRUE;
10164 WL_ERR(("does not support per_chan_info\n"));
10173 __wl_band_2ghz.n_channels = n_2g;
10174 __wl_band_5ghz_a.n_channels = n_5g;
10179 s32 wl_update_wiphybands(struct wl_priv *wl, bool notify)
10181 struct wiphy *wiphy;
10182 struct net_device *dev;
10189 bool rollback_lock = false;
10192 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
10195 wl = wlcfg_drv_priv;
10196 mutex_lock(&wl->usr_sync);
10197 rollback_lock = true;
10199 dev = wl_to_prmry_ndev(wl);
10201 memset(bandlist, 0, sizeof(bandlist));
10202 err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
10203 sizeof(bandlist), false);
10204 if (unlikely(err)) {
10205 WL_ERR(("error read bandlist (%d)\n", err));
10208 err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
10209 sizeof(s32), false);
10210 if (unlikely(err)) {
10211 WL_ERR(("error (%d)\n", err));
10215 err = wldev_iovar_getint(dev, "nmode", &nmode);
10216 if (unlikely(err)) {
10217 WL_ERR(("error reading nmode (%d)\n", err));
10219 /* For nmodeonly check bw cap */
10220 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
10221 if (unlikely(err)) {
10222 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
10226 err = wl_construct_reginfo(wl, bw_cap);
10228 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
10229 if (err != BCME_UNSUPPORTED)
10233 wiphy = wl_to_wiphy(wl);
10234 nband = bandlist[0];
10236 for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
10238 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
10239 bands[IEEE80211_BAND_5GHZ] =
10241 index = IEEE80211_BAND_5GHZ;
10242 if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
10243 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10245 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
10246 bands[IEEE80211_BAND_2GHZ] =
10248 index = IEEE80211_BAND_2GHZ;
10249 if (bw_cap == WLC_N_BW_40ALL)
10250 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10253 if ((index >= 0) && nmode) {
10254 bands[index]->ht_cap.cap |=
10255 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
10256 bands[index]->ht_cap.ht_supported = TRUE;
10257 bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
10258 bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
10259 /* An HT shall support all EQM rates for one spatial stream */
10260 bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
10265 wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
10266 wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
10268 /* check if any bands populated otherwise makes 2Ghz as default */
10269 if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
10270 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
10271 /* Setup 2Ghz band as default */
10272 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
10276 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
10280 mutex_unlock(&wl->usr_sync);
10284 static s32 __wl_cfg80211_up(struct wl_priv *wl)
10287 struct net_device *ndev = wl_to_prmry_ndev(wl);
10288 struct wireless_dev *wdev = ndev->ieee80211_ptr;
10292 err = dhd_config_dongle(wl, false);
10296 err = wl_config_ifmode(wl, ndev, wdev->iftype);
10297 if (unlikely(err && err != -EINPROGRESS)) {
10298 WL_ERR(("wl_config_ifmode failed\n"));
10300 err = wl_update_wiphybands(wl, true);
10301 if (unlikely(err)) {
10302 WL_ERR(("wl_update_wiphybands failed\n"));
10305 err = dhd_monitor_init(wl->pub);
10306 err = wl_invoke_iscan(wl);
10309 INIT_DELAYED_WORK(&wl->pm_enable_work, wl_cfg80211_work_handler);
10310 wl_set_drv_status(wl, READY, ndev);
10314 static s32 __wl_cfg80211_down(struct wl_priv *wl)
10317 unsigned long flags;
10318 struct net_info *iter, *next;
10319 struct net_device *ndev = wl_to_prmry_ndev(wl);
10320 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10321 struct net_device *p2p_net = wl->p2p_net;
10322 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10324 #ifdef PROP_TXSTATUS_VSDB
10325 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
10326 #endif /* PROP_TXSTATUS_VSDB */
10328 /* Delete pm_enable_work */
10329 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
10331 if (wl->p2p_supported) {
10332 wl_clr_p2p_status(wl, GO_NEG_PHASE);
10333 #ifdef PROP_TXSTATUS_VSDB
10334 if (wl->p2p->vif_created) {
10335 if (dhd-> op_mode != DHD_FLAG_IBSS_MODE &&
10336 dhd->wlfc_enabled && wl->wlfc_on) {
10337 dhd->wlfc_enabled = false;
10338 dhd_wlfc_deinit(dhd);
10339 if (dhd->plat_deinit)
10340 dhd->plat_deinit((void *)dhd);
10341 wl->wlfc_on = false;
10344 #endif /* PROP_TXSTATUS_VSDB */
10348 /* If primary BSS is operational (for e.g SoftAP), bring it down */
10349 if (!(wl_cfgp2p_find_idx(wl, ndev, &bssidx)) &&
10350 wl_cfgp2p_bss_isup(ndev, bssidx)) {
10351 if (wl_cfgp2p_bss(wl, ndev, bssidx, 0) < 0)
10352 WL_ERR(("BSS down failed \n"));
10355 /* Check if cfg80211 interface is already down */
10356 if (!wl_get_drv_status(wl, READY, ndev))
10357 return err; /* it is even not ready */
10358 for_each_ndev(wl, iter, next)
10359 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
10363 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10364 if (wl->scan_request) {
10365 cfg80211_scan_done(wl->scan_request, true);
10366 wl->scan_request = NULL;
10368 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10370 for_each_ndev(wl, iter, next) {
10371 wl_clr_drv_status(wl, READY, iter->ndev);
10372 wl_clr_drv_status(wl, SCANNING, iter->ndev);
10373 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
10374 wl_clr_drv_status(wl, CONNECTING, iter->ndev);
10375 wl_clr_drv_status(wl, CONNECTED, iter->ndev);
10376 wl_clr_drv_status(wl, DISCONNECTING, iter->ndev);
10377 wl_clr_drv_status(wl, AP_CREATED, iter->ndev);
10378 wl_clr_drv_status(wl, AP_CREATING, iter->ndev);
10380 wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype =
10381 NL80211_IFTYPE_STATION;
10382 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10384 dev_close(p2p_net);
10385 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10386 DNGL_FUNC(dhd_cfg80211_down, (wl));
10389 if (wl->p2p_supported)
10390 wl_cfgp2p_down(wl);
10391 dhd_monitor_uninit();
10396 s32 wl_cfg80211_up(void *para)
10398 struct wl_priv *wl;
10405 wl = wlcfg_drv_priv;
10407 if ((err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_VERSION, &val,
10408 sizeof(int), false) < 0)) {
10409 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
10413 if (val != WLC_IOCTL_VERSION && val != 1) {
10414 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
10415 val, WLC_IOCTL_VERSION));
10416 return BCME_VERSION;
10418 ioctl_version = val;
10419 WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
10421 mutex_lock(&wl->usr_sync);
10422 dhd = (dhd_pub_t *)(wl->pub);
10423 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
10424 err = wl_cfg80211_attach_post(wl_to_prmry_ndev(wl));
10428 err = __wl_cfg80211_up(wl);
10430 WL_ERR(("__wl_cfg80211_up failed\n"));
10431 mutex_unlock(&wl->usr_sync);
10435 /* Private Event to Supplicant with indication that chip hangs */
10436 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
10438 struct wl_priv *wl;
10439 wl = wlcfg_drv_priv;
10441 WL_ERR(("In : chip crash eventing\n"));
10442 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
10443 cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL);
10450 s32 wl_cfg80211_down(void *para)
10452 struct wl_priv *wl;
10457 wl = wlcfg_drv_priv;
10458 mutex_lock(&wl->usr_sync);
10459 err = __wl_cfg80211_down(wl);
10460 mutex_unlock(&wl->usr_sync);
10465 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item)
10467 unsigned long flags;
10469 struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10473 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10476 rptr = &profile->sec;
10479 rptr = &profile->active;
10481 case WL_PROF_BSSID:
10482 rptr = profile->bssid;
10485 rptr = &profile->ssid;
10488 rptr = &profile->channel;
10491 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10493 WL_ERR(("invalid item (%d)\n", item));
10498 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
10499 const wl_event_msg_t *e, void *data, s32 item)
10502 struct wlc_ssid *ssid;
10503 unsigned long flags;
10504 struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10508 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10511 ssid = (wlc_ssid_t *) data;
10512 memset(profile->ssid.SSID, 0,
10513 sizeof(profile->ssid.SSID));
10514 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
10515 profile->ssid.SSID_len = ssid->SSID_len;
10517 case WL_PROF_BSSID:
10519 memcpy(profile->bssid, data, ETHER_ADDR_LEN);
10521 memset(profile->bssid, 0, ETHER_ADDR_LEN);
10524 memcpy(&profile->sec, data, sizeof(profile->sec));
10527 profile->active = *(bool *)data;
10529 case WL_PROF_BEACONINT:
10530 profile->beacon_interval = *(u16 *)data;
10532 case WL_PROF_DTIMPERIOD:
10533 profile->dtim_period = *(u8 *)data;
10536 profile->channel = *(u32*)data;
10542 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10544 if (err == -EOPNOTSUPP)
10545 WL_ERR(("unsupported item (%d)\n", item));
10550 void wl_cfg80211_dbg_level(u32 level)
10553 * prohibit to change debug level
10554 * by insmod parameter.
10555 * eventually debug level will be configured
10556 * in compile time by using CONFIG_XXX
10558 /* wl_dbg_level = level; */
10561 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev)
10563 return wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS;
10566 static __used bool wl_is_ibssstarter(struct wl_priv *wl)
10568 return wl->ibss_starter;
10571 static void wl_rst_ie(struct wl_priv *wl)
10573 struct wl_ie *ie = wl_to_ie(wl);
10578 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
10580 struct wl_ie *ie = wl_to_ie(wl);
10583 if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
10584 WL_ERR(("ei crosses buffer boundary\n"));
10587 ie->buf[ie->offset] = t;
10588 ie->buf[ie->offset + 1] = l;
10589 memcpy(&ie->buf[ie->offset + 2], v, l);
10590 ie->offset += l + 2;
10595 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size)
10598 ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
10601 if (ssidie[1] != bi->SSID_len) {
10603 WL_ERR(("%s: Wrong SSID len: %d != %d\n",
10604 __FUNCTION__, ssidie[1], bi->SSID_len));
10607 memmove(ssidie + bi->SSID_len + 2, ssidie + 2, *ie_size - (ssidie + 2 - ie_stream));
10608 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
10609 *ie_size = *ie_size + bi->SSID_len;
10610 ssidie[1] = bi->SSID_len;
10613 if (*(ssidie + 2) == '\0')
10614 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
10618 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size)
10620 struct wl_ie *ie = wl_to_ie(wl);
10623 if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
10624 WL_ERR(("ei_stream crosses buffer boundary\n"));
10627 memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
10628 ie->offset += ie_size;
10633 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size)
10635 struct wl_ie *ie = wl_to_ie(wl);
10638 if (unlikely(ie->offset > dst_size)) {
10639 WL_ERR(("dst_size is not enough\n"));
10642 memcpy(dst, &ie->buf[0], ie->offset);
10647 static u32 wl_get_ielen(struct wl_priv *wl)
10649 struct wl_ie *ie = wl_to_ie(wl);
10654 static void wl_link_up(struct wl_priv *wl)
10656 wl->link_up = true;
10659 static void wl_link_down(struct wl_priv *wl)
10661 struct wl_connect_info *conn_info = wl_to_conn(wl);
10664 wl->link_up = false;
10665 conn_info->req_ie_len = 0;
10666 conn_info->resp_ie_len = 0;
10669 static unsigned long wl_lock_eq(struct wl_priv *wl)
10671 unsigned long flags;
10673 spin_lock_irqsave(&wl->eq_lock, flags);
10677 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags)
10679 spin_unlock_irqrestore(&wl->eq_lock, flags);
10682 static void wl_init_eq_lock(struct wl_priv *wl)
10684 spin_lock_init(&wl->eq_lock);
10687 static void wl_delay(u32 ms)
10689 if (in_atomic() || (ms < jiffies_to_msecs(1))) {
10690 OSL_DELAY(ms*1000);
10696 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
10698 struct wl_priv *wl = wlcfg_drv_priv;
10699 struct ether_addr p2pif_addr;
10700 struct ether_addr primary_mac;
10703 if (!p2p_is_on(wl)) {
10704 get_primary_mac(wl, &primary_mac);
10705 wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr);
10707 memcpy(p2pdev_addr->octet,
10708 wl->p2p->dev_addr.octet, ETHER_ADDR_LEN);
10714 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
10716 struct wl_priv *wl;
10718 wl = wlcfg_drv_priv;
10720 return wl_cfgp2p_set_p2p_noa(wl, net, buf, len);
10723 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
10725 struct wl_priv *wl;
10726 wl = wlcfg_drv_priv;
10728 return wl_cfgp2p_get_p2p_noa(wl, net, buf, len);
10731 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
10733 struct wl_priv *wl;
10734 wl = wlcfg_drv_priv;
10736 return wl_cfgp2p_set_p2p_ps(wl, net, buf, len);
10739 s32 wl_cfg80211_channel_to_freq(u32 channel)
10743 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
10744 freq = ieee80211_channel_to_frequency(channel);
10748 if (channel <= CH_MAX_2G_CHANNEL)
10749 band = IEEE80211_BAND_2GHZ;
10751 band = IEEE80211_BAND_5GHZ;
10752 freq = ieee80211_channel_to_frequency(channel, band);
10761 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
10762 const wl_event_msg_t *e, void *data) {
10764 struct net_device *ndev = NULL;
10765 u32 reason = ntoh32(e->reason);
10768 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
10771 case WLC_E_TDLS_PEER_DISCOVERED :
10772 msg = " TDLS PEER DISCOVERD ";
10774 case WLC_E_TDLS_PEER_CONNECTED :
10775 msg = " TDLS PEER CONNECTED ";
10777 case WLC_E_TDLS_PEER_DISCONNECTED :
10778 msg = "TDLS PEER DISCONNECTED ";
10782 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
10783 (wl_to_prmry_ndev(wl) == ndev) ? "primary" : "secondary"));
10788 #endif /* WLTDLS */
10790 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
10792 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
10793 u8 *peer, enum nl80211_tdls_operation oper)
10797 struct wl_priv *wl = wlcfg_drv_priv;
10800 return ERR_PTR(-EINVAL);
10803 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
10804 memset(&info, 0, sizeof(tdls_iovar_t));
10806 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
10808 case NL80211_TDLS_DISCOVERY_REQ:
10809 if (!dhd->tdls_enable)
10810 ret = dhd_tdls_enable_disable(dhd, 1);
10813 info.mode = TDLS_MANUAL_EP_DISCOVERY;
10815 case NL80211_TDLS_SETUP:
10816 info.mode = TDLS_MANUAL_EP_CREATE;
10818 case NL80211_TDLS_TEARDOWN:
10819 info.mode = TDLS_MANUAL_EP_DELETE;
10822 WL_ERR(("Unsupported operation : %d\n", oper));
10825 ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
10826 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
10828 WL_ERR(("tdls_endpoint error %d\n", ret));
10831 #endif /* WLTDLS */
10836 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
10837 enum wl_management_type type)
10839 struct wl_priv *wl;
10840 struct net_device *ndev = NULL;
10841 struct ether_addr primary_mac;
10845 wl = wlcfg_drv_priv;
10847 if (wl_get_drv_status(wl, AP_CREATING, net)) {
10848 /* Vendor IEs should be set to FW
10849 * after SoftAP interface is brought up
10852 } else if (wl_get_drv_status(wl, AP_CREATED, net)) {
10855 } else if (wl->p2p) {
10856 net = ndev_to_wlc_ndev(net, wl);
10857 if (!wl->p2p->on) {
10858 get_primary_mac(wl, &primary_mac);
10859 wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr,
10860 &wl->p2p->int_addr);
10861 /* In case of p2p_listen command, supplicant send remain_on_channel
10862 * without turning on P2P
10866 ret = wl_cfgp2p_enable_discovery(wl, net, NULL, 0);
10868 if (unlikely(ret)) {
10872 if (net != wl_to_prmry_ndev(wl)) {
10873 if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) {
10874 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
10875 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
10878 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
10879 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
10882 if (ndev != NULL) {
10885 pktflag = VNDR_IE_BEACON_FLAG;
10887 case WL_PROBE_RESP:
10888 pktflag = VNDR_IE_PRBRSP_FLAG;
10890 case WL_ASSOC_RESP:
10891 pktflag = VNDR_IE_ASSOCRSP_FLAG;
10895 ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
10901 #ifdef WL_SUPPORT_AUTO_CHANNEL
10903 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
10906 s32 ret = BCME_ERROR;
10907 struct wl_priv *wl = wlcfg_drv_priv;
10909 /* Disable mpc, to avoid automatic interface down. */
10912 ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
10913 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
10914 &wl->ioctl_buf_sync);
10916 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
10920 /* Set interface up, explicitly. */
10923 ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
10925 WL_ERR(("set interface up failed, error = %d\n", ret));
10929 /* Stop all scan explicitly, till auto channel selection complete. */
10930 wl_set_drv_status(wl, SCANNING, ndev);
10931 ret = wl_notify_escan_complete(wl, ndev, true, true);
10933 WL_ERR(("set scan abort failed, error = %d\n", ret));
10942 wl_cfg80211_valid_chanspec_p2p(chanspec_t chanspec)
10944 bool valid = false;
10946 /* channel 1 to 14 */
10947 if ((chanspec >= 0x2b01) && (chanspec <= 0x2b0e)) {
10950 /* channel 36 to 48 */
10951 else if ((chanspec >= 0x1b24) && (chanspec <= 0x1b30)) {
10954 /* channel 149 to 161 */
10955 else if ((chanspec >= 0x1b95) && (chanspec <= 0x1ba1)) {
10960 WL_INFO(("invalid P2P chanspec, channel = %d, chanspec = %04x\n",
10961 CHSPEC_CHANNEL(chanspec), chanspec));
10968 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
10970 s32 ret = BCME_ERROR;
10971 struct wl_priv *wl = NULL;
10972 wl_uint32_list_t *list = NULL;
10973 chanspec_t chanspec = 0;
10975 memset(buf, 0, buflen);
10977 wl = wlcfg_drv_priv;
10978 list = (wl_uint32_list_t *)buf;
10979 list->count = htod32(WL_NUMCHANSPECS);
10981 /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
10982 chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
10983 WL_CHANSPEC_CTL_SB_NONE);
10984 chanspec = wl_chspec_host_to_driver(chanspec);
10986 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
10987 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
10989 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
10996 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
10999 s32 ret = BCME_ERROR;
11002 struct wl_priv *wl = NULL;
11003 wl_uint32_list_t *list = NULL;
11004 chanspec_t chanspec = 0;
11006 memset(buf, 0, buflen);
11008 wl = wlcfg_drv_priv;
11009 list = (wl_uint32_list_t *)buf;
11010 list->count = htod32(WL_NUMCHANSPECS);
11012 /* Restrict channels to 5GHz, 20MHz BW, no SB. */
11013 chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
11014 WL_CHANSPEC_CTL_SB_NONE);
11015 chanspec = wl_chspec_host_to_driver(chanspec);
11017 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
11018 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
11020 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
11024 /* Skip DFS and inavlid P2P channel. */
11025 for (i = 0, j = 0; i < dtoh32(list->count); i++) {
11026 chanspec = (chanspec_t) dtoh32(list->element[i]);
11027 channel = CHSPEC_CHANNEL(chanspec);
11029 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
11031 WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
11035 if (CHANNEL_IS_RADAR(channel) ||
11036 !(wl_cfg80211_valid_chanspec_p2p(chanspec))) {
11039 list->element[j] = list->element[i];
11052 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
11055 s32 ret = BCME_ERROR;
11059 /* Start auto channel selection scan. */
11060 ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
11062 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
11067 /* Wait for auto channel selection, worst case possible delay is 5250ms. */
11068 retry = CHAN_SEL_RETRY_COUNT;
11071 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
11073 ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
11075 if ((ret == 0) && (dtoh32(chosen) != 0)) {
11076 *channel = (u16)(chosen & 0x00FF);
11077 WL_INFO(("selected channel = %d\n", *channel));
11080 WL_INFO(("attempt = %d, ret = %d, chosen = %d\n",
11081 (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
11085 WL_ERR(("failure, auto channel selection timed out\n"));
11095 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
11098 s32 ret = BCME_ERROR;
11099 struct wl_priv *wl = wlcfg_drv_priv;
11101 /* Clear scan stop driver status. */
11102 wl_clr_drv_status(wl, SCANNING, ndev);
11104 /* Enable mpc back to 1, irrespective of initial state. */
11107 ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
11108 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
11109 &wl->ioctl_buf_sync);
11111 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
11118 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
11121 s32 ret = BCME_ERROR;
11124 struct wl_priv *wl = NULL;
11125 struct net_device *ndev = NULL;
11127 memset(cmd, 0, total_len);
11129 buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
11131 WL_ERR(("failed to allocate chanspec buffer\n"));
11136 * Always use primary interface, irrespective of interface on which
11139 wl = wlcfg_drv_priv;
11140 ndev = wl_to_prmry_ndev(wl);
11143 * Make sure that FW and driver are in right state to do auto channel
11146 ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
11148 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
11152 /* Best channel selection in 2.4GHz band. */
11153 ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
11155 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
11159 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
11162 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
11166 if (CHANNEL_IS_2G(channel)) {
11167 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
11169 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
11173 sprintf(pos, "%04d ", channel);
11176 /* Best channel selection in 5GHz band. */
11177 ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
11179 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
11183 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
11186 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
11190 if (CHANNEL_IS_5G(channel)) {
11191 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
11193 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
11197 sprintf(pos, "%04d ", channel);
11200 /* Set overall best channel same as 5GHz best channel. */
11201 sprintf(pos, "%04d ", channel);
11209 /* Restore FW and driver back to normal state. */
11210 ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
11212 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
11215 return (pos - cmd);
11217 #endif /* WL_SUPPORT_AUTO_CHANNEL */
11219 static const struct rfkill_ops wl_rfkill_ops = {
11220 .set_block = wl_rfkill_set
11223 static int wl_rfkill_set(void *data, bool blocked)
11225 struct wl_priv *wl = (struct wl_priv *)data;
11227 WL_DBG(("Enter \n"));
11228 WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
11233 wl->rf_blocked = blocked;
11238 static int wl_setup_rfkill(struct wl_priv *wl, bool setup)
11242 WL_DBG(("Enter \n"));
11246 wl->rfkill = rfkill_alloc("brcmfmac-wifi",
11247 wl_cfg80211_get_parent_dev(),
11248 RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)wl);
11255 err = rfkill_register(wl->rfkill);
11258 rfkill_destroy(wl->rfkill);
11265 rfkill_unregister(wl->rfkill);
11266 rfkill_destroy(wl->rfkill);
11273 #ifdef DEBUGFS_CFG80211
11275 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
11276 * to turn on SCAN and DBG log.
11277 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
11278 * To see current setting of debug level,
11279 * cat /sys/kernel/debug/dhd/debug_level
11282 wl_debuglevel_write(struct file *file, const char __user *userbuf,
11283 size_t count, loff_t *ppos)
11285 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
11286 char *params, *token, *colon;
11287 uint i, tokens, log_on = 0;
11288 memset(tbuf, 0, sizeof(tbuf));
11289 memset(sublog, 0, sizeof(sublog));
11290 if (copy_from_user(&tbuf, userbuf, min_t(size_t, sizeof(tbuf), count)))
11294 colon = strchr(params, '\n');
11297 while ((token = strsep(¶ms, " ")) != NULL) {
11298 memset(sublog, 0, sizeof(sublog));
11299 if (token == NULL || !*token)
11301 if (*token == '\0')
11303 colon = strchr(token, ':');
11304 if (colon != NULL) {
11307 tokens = sscanf(token, "%s %u", sublog, &log_on);
11312 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
11313 if (!strncmp(sublog, sublogname_map[i].sublogname,
11314 strlen(sublogname_map[i].sublogname))) {
11317 (sublogname_map[i].log_level);
11320 ~(sublogname_map[i].log_level);
11324 WL_ERR(("%s: can't parse '%s' as a "
11325 "SUBMODULE:LEVEL (%d tokens)\n",
11326 tbuf, token, tokens));
11334 wl_debuglevel_read(struct file *file, char __user *user_buf,
11335 size_t count, loff_t *ppos)
11338 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
11340 memset(tbuf, 0, sizeof(tbuf));
11342 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
11343 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
11344 sublogname_map[i].sublogname,
11345 (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
11348 return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
11351 static const struct file_operations fops_debuglevel = {
11353 .write = wl_debuglevel_write,
11354 .read = wl_debuglevel_read,
11355 .owner = THIS_MODULE,
11359 static s32 wl_setup_debugfs(struct wl_priv *wl)
11362 struct dentry *_dentry;
11365 wl->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
11366 if (!wl->debugfs || IS_ERR(wl->debugfs)) {
11367 if (wl->debugfs == ERR_PTR(-ENODEV))
11368 WL_ERR(("Debugfs is not enabled on this kernel\n"));
11370 WL_ERR(("Can not create debugfs directory\n"));
11371 wl->debugfs = NULL;
11375 _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
11376 wl->debugfs, wl, &fops_debuglevel);
11377 if (!_dentry || IS_ERR(_dentry)) {
11378 WL_ERR(("failed to create debug_level debug file\n"));
11379 wl_free_debugfs(wl);
11384 static s32 wl_free_debugfs(struct wl_priv *wl)
11389 debugfs_remove_recursive(wl->debugfs);
11390 wl->debugfs = NULL;
11393 #endif /* DEBUGFS_CFG80211 */
11395 struct device *wl_cfg80211_get_parent_dev(void)
11397 return cfg80211_parent_dev;
11400 void wl_cfg80211_set_parent_dev(void *dev)
11402 cfg80211_parent_dev = dev;
11405 static void wl_cfg80211_clear_parent_dev(void)
11407 cfg80211_parent_dev = NULL;
11410 void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac)
11412 wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL,
11413 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, 0, &wl->ioctl_buf_sync);
11414 memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN);
11416 static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role)
11418 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
11419 if (((dev_role == NL80211_IFTYPE_AP) &&
11420 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
11421 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
11422 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
11424 WL_ERR(("device role select failed\n"));
11430 int wl_cfg80211_do_driver_init(struct net_device *net)
11432 struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net);
11434 if (!wl || !wl->wdev)
11437 if (dhd_do_driver_init(wl->wdev->netdev) < 0)
11443 void wl_cfg80211_enable_trace(bool set, u32 level)
11446 wl_dbg_level = level & WL_DBG_LEVEL;
11448 wl_dbg_level |= (WL_DBG_LEVEL & level);
11450 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
11453 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
11454 bcm_struct_cfgdev *cfgdev, u64 cookie)
11456 /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
11457 * is passed with CMD_FRAME. This callback is supposed to cancel
11458 * the OFFCHANNEL Wait. Since we are already taking care of that
11459 * with the tx_mgmt logic, do nothing here.
11464 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
11469 static void wl_cfg80211_work_handler(struct work_struct * work)
11471 struct wl_priv *wl = NULL;
11472 struct net_info *iter, *next;
11476 wl = container_of(work, struct wl_priv, pm_enable_work.work);
11477 WL_DBG(("Enter \n"));
11478 if (wl->pm_enable_work_on) {
11479 wl->pm_enable_work_on = false;
11480 for_each_ndev(wl, iter, next) {
11481 if (!wl_get_drv_status(wl, CONNECTED, iter->ndev) ||
11482 (wl_get_mode_by_netdev(wl, iter->ndev) != WL_MODE_BSS))
11485 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
11486 &pm, sizeof(pm), true)) != 0) {
11487 if (err == -ENODEV)
11488 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
11490 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
11492 iter->ndev->ieee80211_ptr->ps = true;
11499 wl_get_action_category(void *frame, u32 frame_len)
11502 u8 *ptr = (u8 *)frame;
11504 return DOT11_ACTION_CAT_ERR_MASK;
11505 if (frame_len < DOT11_ACTION_HDR_LEN)
11506 return DOT11_ACTION_CAT_ERR_MASK;
11507 category = ptr[DOT11_ACTION_CAT_OFF];
11508 WL_INFO(("Action Category: %d\n", category));
11513 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
11515 u8 *ptr = (u8 *)frame;
11516 if (frame == NULL || ret_action == NULL)
11518 if (frame_len < DOT11_ACTION_HDR_LEN)
11520 if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
11522 *ret_action = ptr[DOT11_ACTION_ACT_OFF];
11523 WL_INFO(("Public Action : %d\n", *ret_action));
11528 wl_ccx_s69_response(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
11529 const wl_event_msg_t *e, void *data)
11531 struct net_device *ndev = NULL;
11532 u32 event = ntoh32(e->event_type);
11533 u32 datalen = ntoh32(e->datalen);
11536 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
11537 err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
11541 #endif /* BCMCCX_S69 */