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_20;
5211 struct wl_priv *wl = wiphy_priv(wiphy);
5214 return ERR_PTR(-EINVAL);
5215 dev = ndev_to_wlc_ndev(dev, wl);
5216 _chan = ieee80211_frequency_to_channel(chan->center_freq);
5217 WL_ERR(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
5218 dev->ifindex, channel_type, _chan));
5221 if (chan->band == IEEE80211_BAND_5GHZ) {
5222 param.band = WLC_BAND_5G;
5223 err = wldev_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param),
5224 wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync);
5226 if (err != BCME_UNSUPPORTED) {
5227 WL_ERR(("bw_cap failed, %d\n", err));
5230 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
5232 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
5234 if (bw_cap != WLC_N_BW_20ALL)
5235 bw = WL_CHANSPEC_BW_40;
5238 if (WL_BW_CAP_80MHZ(wl->ioctl_buf[0]))
5239 bw = WL_CHANSPEC_BW_80;
5240 else if (WL_BW_CAP_40MHZ(wl->ioctl_buf[0]))
5241 bw = WL_CHANSPEC_BW_40;
5243 bw = WL_CHANSPEC_BW_20;
5247 } else if (chan->band == IEEE80211_BAND_2GHZ)
5248 bw = WL_CHANSPEC_BW_20;
5250 chspec = wf_channel2chspec(_chan, bw);
5251 if (wf_chspec_valid(chspec)) {
5252 fw_chspec = wl_chspec_host_to_driver(chspec);
5253 if (fw_chspec != INVCHANSPEC) {
5254 if ((err = wldev_iovar_setint(dev, "chanspec",
5255 fw_chspec)) == BCME_BADCHAN) {
5256 if (bw == WL_CHANSPEC_BW_80)
5258 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
5259 &_chan, sizeof(_chan), true);
5261 WL_ERR(("WLC_SET_CHANNEL error %d"
5262 "chip may not be supporting this channel\n", err));
5265 WL_ERR(("failed to set chanspec error %d\n", err));
5268 WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
5273 if (bw == WL_CHANSPEC_BW_80)
5274 bw = WL_CHANSPEC_BW_40;
5275 else if (bw == WL_CHANSPEC_BW_40)
5276 bw = WL_CHANSPEC_BW_20;
5281 WL_ERR(("Invalid chanspec 0x%x\n", chspec));
5288 wl_validate_opensecurity(struct net_device *dev, s32 bssidx)
5293 err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
5295 WL_ERR(("auth error %d\n", err));
5299 err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
5301 WL_ERR(("wsec error %d\n", err));
5304 /* set upper-layer auth */
5305 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", WPA_AUTH_NONE, bssidx);
5307 WL_ERR(("wpa_auth error %d\n", err));
5315 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
5319 u16 auth = 0; /* d11 open authentication */
5324 wpa_suite_mcast_t *mcast;
5325 wpa_suite_ucast_t *ucast;
5326 wpa_suite_auth_key_mgmt_t *mgmt;
5330 u32 wme_bss_disable;
5335 WL_DBG(("Enter \n"));
5337 /* check the mcast cipher */
5338 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
5339 switch (mcast->type) {
5340 case WPA_CIPHER_NONE:
5343 case WPA_CIPHER_WEP_40:
5344 case WPA_CIPHER_WEP_104:
5347 case WPA_CIPHER_TKIP:
5348 gval = TKIP_ENABLED;
5350 case WPA_CIPHER_AES_CCM:
5354 WL_ERR(("No Security Info\n"));
5357 if ((len -= WPA_SUITE_LEN) <= 0)
5360 /* check the unicast cipher */
5361 ucast = (wpa_suite_ucast_t *)&mcast[1];
5362 suite_count = ltoh16_ua(&ucast->count);
5363 switch (ucast->list[0].type) {
5364 case WPA_CIPHER_NONE:
5367 case WPA_CIPHER_WEP_40:
5368 case WPA_CIPHER_WEP_104:
5371 case WPA_CIPHER_TKIP:
5372 pval = TKIP_ENABLED;
5374 case WPA_CIPHER_AES_CCM:
5378 WL_ERR(("No Security Info\n"));
5380 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
5383 /* FOR WPS , set SEC_OW_ENABLED */
5384 wsec = (pval | gval | SES_OW_ENABLED);
5386 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
5387 suite_count = ltoh16_ua(&mgmt->count);
5388 switch (mgmt->list[0].type) {
5390 wpa_auth = WPA_AUTH_NONE;
5392 case RSN_AKM_UNSPECIFIED:
5393 wpa_auth = WPA2_AUTH_UNSPECIFIED;
5396 wpa_auth = WPA2_AUTH_PSK;
5399 WL_ERR(("No Key Mgmt Info\n"));
5402 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
5403 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
5404 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
5406 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
5407 wme_bss_disable = 0;
5409 wme_bss_disable = 1;
5412 /* set wme_bss_disable to sync RSN Capabilities */
5413 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
5415 WL_ERR(("wme_bss_disable error %d\n", err));
5419 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
5423 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5425 WL_ERR(("auth error %d\n", err));
5429 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5431 WL_ERR(("wsec error %d\n", err));
5434 /* set upper-layer auth */
5435 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5437 WL_ERR(("wpa_auth error %d\n", err));
5445 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
5447 wpa_suite_mcast_t *mcast;
5448 wpa_suite_ucast_t *ucast;
5449 wpa_suite_auth_key_mgmt_t *mgmt;
5450 u16 auth = 0; /* d11 open authentication */
5463 WL_DBG(("Enter \n"));
5464 len = wpaie->length; /* value length */
5465 len -= WPA_IE_TAG_FIXED_LEN;
5466 /* check for multicast cipher suite */
5467 if (len < WPA_SUITE_LEN) {
5468 WL_INFO(("no multicast cipher suite\n"));
5472 /* pick up multicast cipher */
5473 mcast = (wpa_suite_mcast_t *)&wpaie[1];
5474 len -= WPA_SUITE_LEN;
5475 if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
5476 if (IS_WPA_CIPHER(mcast->type)) {
5478 switch (mcast->type) {
5479 case WPA_CIPHER_NONE:
5482 case WPA_CIPHER_WEP_40:
5483 case WPA_CIPHER_WEP_104:
5486 case WPA_CIPHER_TKIP:
5489 case WPA_CIPHER_AES_CCM:
5493 WL_ERR(("No Security Info\n"));
5498 /* Check for unicast suite(s) */
5499 if (len < WPA_IE_SUITE_COUNT_LEN) {
5500 WL_INFO(("no unicast suite\n"));
5503 /* walk thru unicast cipher list and pick up what we recognize */
5504 ucast = (wpa_suite_ucast_t *)&mcast[1];
5505 count = ltoh16_ua(&ucast->count);
5506 len -= WPA_IE_SUITE_COUNT_LEN;
5507 for (i = 0; i < count && len >= WPA_SUITE_LEN;
5508 i++, len -= WPA_SUITE_LEN) {
5509 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5510 if (IS_WPA_CIPHER(ucast->list[i].type)) {
5512 switch (ucast->list[i].type) {
5513 case WPA_CIPHER_NONE:
5516 case WPA_CIPHER_WEP_40:
5517 case WPA_CIPHER_WEP_104:
5520 case WPA_CIPHER_TKIP:
5523 case WPA_CIPHER_AES_CCM:
5527 WL_ERR(("No Security Info\n"));
5533 len -= (count - i) * WPA_SUITE_LEN;
5534 /* Check for auth key management suite(s) */
5535 if (len < WPA_IE_SUITE_COUNT_LEN) {
5536 WL_INFO((" no auth key mgmt suite\n"));
5539 /* walk thru auth management suite list and pick up what we recognize */
5540 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
5541 count = ltoh16_ua(&mgmt->count);
5542 len -= WPA_IE_SUITE_COUNT_LEN;
5543 for (i = 0; i < count && len >= WPA_SUITE_LEN;
5544 i++, len -= WPA_SUITE_LEN) {
5545 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5546 if (IS_WPA_AKM(mgmt->list[i].type)) {
5548 switch (mgmt->list[i].type) {
5550 tmp = WPA_AUTH_NONE;
5552 case RSN_AKM_UNSPECIFIED:
5553 tmp = WPA_AUTH_UNSPECIFIED;
5559 WL_ERR(("No Key Mgmt Info\n"));
5566 /* FOR WPS , set SEC_OW_ENABLED */
5567 wsec = (pval | gval | SES_OW_ENABLED);
5569 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5571 WL_ERR(("auth error %d\n", err));
5575 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5577 WL_ERR(("wsec error %d\n", err));
5580 /* set upper-layer auth */
5581 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5583 WL_ERR(("wpa_auth error %d\n", err));
5591 wl_cfg80211_bcn_validate_sec(
5592 struct net_device *dev,
5593 struct parsed_ies *ies,
5597 struct wl_priv *wl = wlcfg_drv_priv;
5599 if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
5600 /* For P2P GO, the sec type is WPA2-PSK */
5601 WL_DBG(("P2P GO: validating wpa2_ie"));
5602 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0)
5605 } else if (dev_role == NL80211_IFTYPE_AP) {
5607 WL_DBG(("SoftAP: validating security"));
5608 /* If wpa2_ie or wpa_ie is present validate it */
5609 if ((ies->wpa2_ie || ies->wpa_ie) &&
5610 ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
5611 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
5612 wl->ap_info->security_mode = false;
5616 wl->ap_info->security_mode = true;
5617 if (wl->ap_info->rsn_ie) {
5618 kfree(wl->ap_info->rsn_ie);
5619 wl->ap_info->rsn_ie = NULL;
5621 if (wl->ap_info->wpa_ie) {
5622 kfree(wl->ap_info->wpa_ie);
5623 wl->ap_info->wpa_ie = NULL;
5625 if (wl->ap_info->wps_ie) {
5626 kfree(wl->ap_info->wps_ie);
5627 wl->ap_info->wps_ie = NULL;
5629 if (ies->wpa_ie != NULL) {
5631 wl->ap_info->rsn_ie = NULL;
5632 wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5633 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5635 } else if (ies->wpa2_ie != NULL) {
5637 wl->ap_info->wpa_ie = NULL;
5638 wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5639 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5643 if (!ies->wpa2_ie && !ies->wpa_ie) {
5644 wl_validate_opensecurity(dev, bssidx);
5645 wl->ap_info->security_mode = false;
5649 wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5657 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
5658 static s32 wl_cfg80211_bcn_set_params(
5659 struct cfg80211_ap_settings *info,
5660 struct net_device *dev,
5661 u32 dev_role, s32 bssidx)
5663 struct wl_priv *wl = wlcfg_drv_priv;
5666 WL_DBG(("interval (%d) \ndtim_period (%d) \n",
5667 info->beacon_interval, info->dtim_period));
5669 if (info->beacon_interval) {
5670 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
5671 &info->beacon_interval, sizeof(s32), true)) < 0) {
5672 WL_ERR(("Beacon Interval Set Error, %d\n", err));
5677 if (info->dtim_period) {
5678 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
5679 &info->dtim_period, sizeof(s32), true)) < 0) {
5680 WL_ERR(("DTIM Interval Set Error, %d\n", err));
5685 if ((info->ssid) && (info->ssid_len > 0) &&
5686 (info->ssid_len <= 32)) {
5687 WL_DBG(("SSID (%s) len:%d \n", info->ssid, info->ssid_len));
5688 if (dev_role == NL80211_IFTYPE_AP) {
5689 /* Store the hostapd SSID */
5690 memset(wl->hostapd_ssid.SSID, 0x00, 32);
5691 memcpy(wl->hostapd_ssid.SSID, info->ssid, info->ssid_len);
5692 wl->hostapd_ssid.SSID_len = info->ssid_len;
5695 memset(wl->p2p->ssid.SSID, 0x00, 32);
5696 memcpy(wl->p2p->ssid.SSID, info->ssid, info->ssid_len);
5697 wl->p2p->ssid.SSID_len = info->ssid_len;
5701 if (info->hidden_ssid) {
5702 if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
5703 WL_ERR(("failed to set hidden : %d\n", err));
5704 WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
5712 wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
5716 memset(ies, 0, sizeof(struct parsed_ies));
5718 /* find the WPSIE */
5719 if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
5720 WL_DBG(("WPSIE in beacon \n"));
5721 ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
5723 WL_ERR(("No WPSIE in beacon \n"));
5726 /* find the RSN_IE */
5727 if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
5728 DOT11_MNG_RSN_ID)) != NULL) {
5729 WL_DBG((" WPA2 IE found\n"));
5730 ies->wpa2_ie_len = ies->wpa2_ie->len;
5733 /* find the WPA_IE */
5734 if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
5735 WL_DBG((" WPA found\n"));
5736 ies->wpa_ie_len = ies->wpa_ie->length;
5744 wl_cfg80211_bcn_bringup_ap(
5745 struct net_device *dev,
5746 struct parsed_ies *ies,
5747 u32 dev_role, s32 bssidx)
5749 struct wl_priv *wl = wlcfg_drv_priv;
5750 struct wl_join_params join_params;
5751 bool is_bssup = false;
5753 s32 join_params_size = 0;
5755 #ifdef DISABLE_11H_SOFTAP
5757 #endif /* DISABLE_11H_SOFTAP */
5760 WL_DBG(("Enter dev_role: %d\n", dev_role));
5762 /* Common code for SoftAP and P2P GO */
5763 wldev_iovar_setint(dev, "mpc", 0);
5765 if (dev_role == NL80211_IFTYPE_P2P_GO) {
5766 is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
5767 if (!is_bssup && (ies->wpa2_ie != NULL)) {
5769 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
5771 WL_ERR(("SET INFRA error %d\n", err));
5775 err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid,
5776 sizeof(wl->p2p->ssid), wl->ioctl_buf, WLC_IOCTL_MAXLEN,
5777 bssidx, &wl->ioctl_buf_sync);
5779 WL_ERR(("GO SSID setting error %d\n", err));
5783 /* Do abort scan before creating GO */
5784 wl_cfg80211_scan_abort(wl);
5786 if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) {
5787 WL_ERR(("GO Bring up error %d\n", err));
5791 WL_DBG(("Bss is already up\n"));
5792 } else if ((dev_role == NL80211_IFTYPE_AP) &&
5793 (wl_get_drv_status(wl, AP_CREATING, dev))) {
5794 /* Device role SoftAP */
5795 err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
5797 WL_ERR(("WLC_DOWN error %d\n", err));
5800 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
5802 WL_ERR(("SET INFRA error %d\n", err));
5805 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
5806 WL_ERR(("setting AP mode failed %d \n", err));
5809 #ifdef DISABLE_11H_SOFTAP
5810 err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT,
5811 &spect, sizeof(s32), true);
5813 WL_ERR(("SET SPECT_MANAGMENT error %d\n", err));
5816 #endif /* DISABLE_11H_SOFTAP */
5818 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
5819 if (unlikely(err)) {
5820 WL_ERR(("WLC_UP error (%d)\n", err));
5824 memset(&join_params, 0, sizeof(join_params));
5825 /* join parameters starts with ssid */
5826 join_params_size = sizeof(join_params.ssid);
5827 memcpy(join_params.ssid.SSID, wl->hostapd_ssid.SSID,
5828 wl->hostapd_ssid.SSID_len);
5829 join_params.ssid.SSID_len = htod32(wl->hostapd_ssid.SSID_len);
5832 if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
5833 join_params_size, true)) == 0) {
5834 WL_DBG(("SoftAP set SSID (%s) success\n", join_params.ssid.SSID));
5835 wl_clr_drv_status(wl, AP_CREATING, dev);
5836 wl_set_drv_status(wl, AP_CREATED, dev);
5845 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
5847 wl_cfg80211_parse_ap_ies(
5848 struct net_device *dev,
5849 struct cfg80211_beacon_data *info,
5850 struct parsed_ies *ies)
5852 struct parsed_ies prb_ies;
5853 struct wl_priv *wl = wlcfg_drv_priv;
5854 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
5856 u32 vndr_ie_len = 0;
5859 /* Parse Beacon IEs */
5860 if (wl_cfg80211_parse_ies((u8 *)info->tail,
5861 info->tail_len, ies) < 0) {
5862 WL_ERR(("Beacon get IEs failed \n"));
5867 vndr = (u8 *)info->proberesp_ies;
5868 vndr_ie_len = info->proberesp_ies_len;
5870 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
5872 struct ieee80211_mgmt *mgmt;
5873 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
5875 vndr = (u8 *)&mgmt->u.probe_resp.variable;
5876 vndr_ie_len = info->probe_resp_len -
5877 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
5881 /* Parse Probe Response IEs */
5882 if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) {
5883 WL_ERR(("PROBE RESP get IEs failed \n"));
5893 wl_cfg80211_set_ies(
5894 struct net_device *dev,
5895 struct cfg80211_beacon_data *info,
5898 struct wl_priv *wl = wlcfg_drv_priv;
5899 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
5901 u32 vndr_ie_len = 0;
5904 /* Set Beacon IEs to FW */
5905 if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5906 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
5907 info->tail_len)) < 0) {
5908 WL_ERR(("Set Beacon IE Failed \n"));
5910 WL_DBG(("Applied Vndr IEs for Beacon \n"));
5913 vndr = (u8 *)info->proberesp_ies;
5914 vndr_ie_len = info->proberesp_ies_len;
5916 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
5918 struct ieee80211_mgmt *mgmt;
5919 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
5921 vndr = (u8 *)&mgmt->u.probe_resp.variable;
5922 vndr_ie_len = info->probe_resp_len -
5923 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
5927 /* Set Probe Response IEs to FW */
5928 if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5929 VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
5930 WL_ERR(("Set Probe Resp IE Failed \n"));
5932 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
5939 static s32 wl_cfg80211_hostapd_sec(
5940 struct net_device *dev,
5941 struct parsed_ies *ies,
5944 bool update_bss = 0;
5945 struct wl_priv *wl = wlcfg_drv_priv;
5949 if (wl->ap_info->wps_ie &&
5950 memcmp(wl->ap_info->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
5951 WL_DBG((" WPS IE is changed\n"));
5952 kfree(wl->ap_info->wps_ie);
5953 wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5954 } else if (wl->ap_info->wps_ie == NULL) {
5955 WL_DBG((" WPS IE is added\n"));
5956 wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
5958 if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
5959 if (!wl->ap_info->security_mode) {
5960 /* change from open mode to security mode */
5962 if (ies->wpa_ie != NULL) {
5963 wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5964 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5967 wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5968 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5971 } else if (wl->ap_info->wpa_ie) {
5972 /* change from WPA2 mode to WPA mode */
5973 if (ies->wpa_ie != NULL) {
5975 kfree(wl->ap_info->rsn_ie);
5976 wl->ap_info->rsn_ie = NULL;
5977 wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
5978 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
5980 } else if (memcmp(wl->ap_info->rsn_ie,
5981 ies->wpa2_ie, ies->wpa2_ie->len
5982 + WPA_RSN_IE_TAG_FIXED_LEN)) {
5984 kfree(wl->ap_info->rsn_ie);
5985 wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
5986 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
5988 wl->ap_info->wpa_ie = NULL;
5992 wl->ap_info->security_mode = true;
5993 wl_cfgp2p_bss(wl, dev, bssidx, 0);
5994 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
5995 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
5998 wl_cfgp2p_bss(wl, dev, bssidx, 1);
6002 WL_ERR(("No WPSIE in beacon \n"));
6007 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6010 wl_cfg80211_del_station(
6011 struct wiphy *wiphy,
6012 struct net_device *ndev,
6015 struct net_device *dev;
6016 struct wl_priv *wl = wiphy_priv(wiphy);
6018 s8 eabuf[ETHER_ADDR_STR_LEN];
6020 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
6021 sizeof(struct ether_addr) + sizeof(uint)] = {0};
6022 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
6023 int num_associated = 0;
6025 WL_DBG(("Entry\n"));
6026 if (mac_addr == NULL) {
6027 WL_DBG(("mac_addr is NULL ignore it\n"));
6032 return ERR_PTR(-EINVAL);
6034 dev = ndev_to_wlc_ndev(ndev, wl);
6036 if (p2p_is_on(wl)) {
6037 /* Suspend P2P discovery search-listen to prevent it from changing the
6040 if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
6041 WL_ERR(("Can not disable discovery mode\n"));
6046 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
6047 err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST,
6048 assoc_maclist, sizeof(mac_buf), false);
6050 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
6052 num_associated = assoc_maclist->count;
6054 memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
6055 scb_val.val = DOT11_RC_DEAUTH_LEAVING;
6056 err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
6057 sizeof(scb_val_t), true);
6059 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
6060 WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
6061 bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
6064 if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
6069 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
6071 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
6073 wl_cfg80211_start_ap(
6074 struct wiphy *wiphy,
6075 struct net_device *dev,
6076 struct cfg80211_ap_settings *info)
6078 struct wl_priv *wl = wiphy_priv(wiphy);
6080 struct parsed_ies ies;
6084 WL_DBG(("Enter \n"));
6087 return ERR_PTR(-EINVAL);
6089 if (dev == wl_to_prmry_ndev(wl)) {
6090 WL_DBG(("Start AP req on primary iface: Softap\n"));
6091 dev_role = NL80211_IFTYPE_AP;
6093 #if defined(WL_ENABLE_P2P_IF)
6094 else if (dev == wl->p2p_net) {
6095 /* Group Add request on p2p0 */
6096 WL_DBG(("Start AP req on P2P iface: GO\n"));
6097 dev = wl_to_prmry_ndev(wl);
6098 dev_role = NL80211_IFTYPE_P2P_GO;
6100 #endif /* WL_ENABLE_P2P_IF */
6101 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6102 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6105 if (p2p_is_on(wl) &&
6106 (bssidx == wl_to_p2p_bss_bssidx(wl,
6107 P2PAPI_BSSCFG_CONNECTION))) {
6108 dev_role = NL80211_IFTYPE_P2P_GO;
6109 WL_DBG(("Start AP req on P2P connection iface\n"));
6112 if (!check_dev_role_integrity(wl, dev_role))
6115 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && !0)
6116 if ((err = wl_cfg80211_set_channel(wiphy, dev,
6117 dev->ieee80211_ptr->preset_chandef.chan,
6118 NL80211_CHAN_HT20) < 0)) {
6119 WL_ERR(("Set channel failed \n"));
6124 if ((err = wl_cfg80211_bcn_set_params(info, dev,
6125 dev_role, bssidx)) < 0) {
6126 WL_ERR(("Beacon params set failed \n"));
6131 if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
6132 WL_ERR(("Set IEs failed \n"));
6136 if ((wl_cfg80211_bcn_validate_sec(dev, &ies,
6137 dev_role, bssidx)) < 0)
6139 WL_ERR(("Beacon set security failed \n"));
6143 if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
6144 dev_role, bssidx)) < 0) {
6145 WL_ERR(("Beacon bring up AP/GO failed \n"));
6149 WL_DBG(("** AP/GO Created **\n"));
6152 if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
6153 WL_ERR(("Set IEs failed \n"));
6157 WL_ERR(("ADD/SET beacon failed\n"));
6158 wldev_iovar_setint(dev, "mpc", 1);
6165 wl_cfg80211_stop_ap(
6166 struct wiphy *wiphy,
6167 struct net_device *dev)
6174 struct wl_priv *wl = wiphy_priv(wiphy);
6176 WL_DBG(("Enter \n"));
6179 return ERR_PTR(-EINVAL);
6181 if (dev == wl_to_prmry_ndev(wl)) {
6182 dev_role = NL80211_IFTYPE_AP;
6184 #if defined(WL_ENABLE_P2P_IF)
6185 else if (dev == wl->p2p_net) {
6186 /* Group Add request on p2p0 */
6187 dev = wl_to_prmry_ndev(wl);
6188 dev_role = NL80211_IFTYPE_P2P_GO;
6190 #endif /* WL_ENABLE_P2P_IF */
6191 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6192 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6195 if (p2p_is_on(wl) &&
6196 (bssidx == wl_to_p2p_bss_bssidx(wl,
6197 P2PAPI_BSSCFG_CONNECTION))) {
6198 dev_role = NL80211_IFTYPE_P2P_GO;
6201 if (!check_dev_role_integrity(wl, dev_role))
6204 if (dev_role == NL80211_IFTYPE_AP) {
6205 /* SoftAp on primary Interface.
6206 * Shut down AP and turn on MPC
6208 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
6209 WL_ERR(("setting AP mode failed %d \n", err));
6213 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
6215 WL_ERR(("SET INFRA error %d\n", err));
6220 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
6221 if (unlikely(err)) {
6222 WL_ERR(("WLC_UP error (%d)\n", err));
6227 wl_clr_drv_status(wl, AP_CREATED, dev);
6228 /* Turn on the MPC */
6229 wldev_iovar_setint(dev, "mpc", 1);
6231 kfree(wl->ap_info->wpa_ie);
6232 kfree(wl->ap_info->rsn_ie);
6233 kfree(wl->ap_info->wps_ie);
6238 WL_DBG(("Stopping P2P GO \n"));
6246 wl_cfg80211_change_beacon(
6247 struct wiphy *wiphy,
6248 struct net_device *dev,
6249 struct cfg80211_beacon_data *info)
6252 struct wl_priv *wl = wiphy_priv(wiphy);
6253 struct parsed_ies ies;
6257 WL_DBG(("Enter \n"));
6260 return ERR_PTR(-EINVAL);
6261 if (dev == wl_to_prmry_ndev(wl)) {
6262 dev_role = NL80211_IFTYPE_AP;
6264 #if defined(WL_ENABLE_P2P_IF)
6265 else if (dev == wl->p2p_net) {
6266 /* Group Add request on p2p0 */
6267 dev = wl_to_prmry_ndev(wl);
6268 dev_role = NL80211_IFTYPE_P2P_GO;
6270 #endif /* WL_ENABLE_P2P_IF */
6271 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6272 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6275 if (p2p_is_on(wl) &&
6276 (bssidx == wl_to_p2p_bss_bssidx(wl,
6277 P2PAPI_BSSCFG_CONNECTION))) {
6278 dev_role = NL80211_IFTYPE_P2P_GO;
6281 if (!check_dev_role_integrity(wl, dev_role))
6284 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (wl->p2p_wdev == NULL)) {
6285 WL_ERR(("P2P already down status!\n"));
6291 if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
6292 WL_ERR(("Parse IEs failed \n"));
6297 if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
6298 WL_ERR(("Set IEs failed \n"));
6302 if (dev_role == NL80211_IFTYPE_AP) {
6303 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6304 WL_ERR(("Hostapd update sec failed \n"));
6313 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */
6315 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
6316 struct beacon_parameters *info)
6319 struct wl_priv *wl = wiphy_priv(wiphy);
6322 u32 dev_role = NL80211_IFTYPE_AP;
6323 struct parsed_ies ies;
6326 WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
6327 info->interval, info->dtim_period, info->head_len, info->tail_len));
6330 return ERR_PTR(-EINVAL);
6332 if (dev == wl_to_prmry_ndev(wl)) {
6333 dev_role = NL80211_IFTYPE_AP;
6335 #if defined(WL_ENABLE_P2P_IF)
6336 else if (dev == wl->p2p_net) {
6337 /* Group Add request on p2p0 */
6338 dev = wl_to_prmry_ndev(wl);
6339 dev_role = NL80211_IFTYPE_P2P_GO;
6341 #endif /* WL_ENABLE_P2P_IF */
6342 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6343 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6346 if (p2p_is_on(wl) &&
6347 (bssidx == wl_to_p2p_bss_bssidx(wl,
6348 P2PAPI_BSSCFG_CONNECTION))) {
6349 dev_role = NL80211_IFTYPE_P2P_GO;
6352 if (!check_dev_role_integrity(wl, dev_role))
6355 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (wl->p2p_wdev == NULL)) {
6356 WL_ERR(("P2P already down status!\n"));
6361 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
6363 if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
6364 info->head_len - ie_offset,
6365 DOT11_MNG_SSID_ID)) != NULL) {
6366 if (dev_role == NL80211_IFTYPE_AP) {
6367 /* Store the hostapd SSID */
6368 memset(&wl->hostapd_ssid.SSID[0], 0x00, 32);
6369 memcpy(&wl->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
6370 wl->hostapd_ssid.SSID_len = ssid_ie->len;
6373 memset(&wl->p2p->ssid.SSID[0], 0x00, 32);
6374 memcpy(wl->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
6375 wl->p2p->ssid.SSID_len = ssid_ie->len;
6379 if (wl_cfg80211_parse_ies((u8 *)info->tail,
6380 info->tail_len, &ies) < 0) {
6381 WL_ERR(("Beacon get IEs failed \n"));
6386 if (wl_cfgp2p_set_management_ie(wl, dev, bssidx,
6387 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
6388 info->tail_len) < 0) {
6389 WL_ERR(("Beacon set IEs failed \n"));
6392 WL_DBG(("Applied Vndr IEs for Beacon \n"));
6394 if (!wl_cfgp2p_bss_isup(dev, bssidx) &&
6395 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx) < 0))
6397 WL_ERR(("Beacon set security failed \n"));
6401 /* Set BI and DTIM period */
6402 if (info->interval) {
6403 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
6404 &info->interval, sizeof(s32), true)) < 0) {
6405 WL_ERR(("Beacon Interval Set Error, %d\n", err));
6409 if (info->dtim_period) {
6410 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
6411 &info->dtim_period, sizeof(s32), true)) < 0) {
6412 WL_ERR(("DTIM Interval Set Error, %d\n", err));
6417 if (wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx) < 0) {
6418 WL_ERR(("Beacon bring up AP/GO failed \n"));
6422 if (wl_get_drv_status(wl, AP_CREATED, dev)) {
6423 /* Soft AP already running. Update changed params */
6424 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6425 WL_ERR(("Hostapd update sec failed \n"));
6431 /* Enable Probe Req filter */
6432 if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
6433 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
6434 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
6436 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
6439 WL_DBG(("** ADD/SET beacon done **\n"));
6443 WL_ERR(("ADD/SET beacon failed\n"));
6444 wldev_iovar_setint(dev, "mpc", 1);
6451 #ifdef WL_SCHED_SCAN
6453 #define PNO_REPEAT 4
6454 #define PNO_FREQ_EXPO_MAX 2
6455 int wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
6456 struct net_device *dev,
6457 struct cfg80211_sched_scan_request *request)
6459 ushort pno_time = PNO_TIME;
6460 int pno_repeat = PNO_REPEAT;
6461 int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
6462 wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
6463 struct wl_priv *wl = wiphy_priv(wiphy);
6464 struct cfg80211_ssid *ssid = NULL;
6469 WL_DBG(("Enter \n"));
6472 return ERR_PTR(-EINVAL);
6474 WL_PNO((">>> SCHED SCAN START\n"));
6475 WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
6476 request->n_match_sets, request->n_ssids));
6477 WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
6478 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
6481 if (!request || !request->n_ssids || !request->n_match_sets) {
6482 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
6486 memset(&ssids_local, 0, sizeof(ssids_local));
6488 if (request->n_match_sets > 0) {
6489 for (i = 0; i < request->n_match_sets; i++) {
6490 ssid = &request->match_sets[i].ssid;
6491 memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len);
6492 ssids_local[i].SSID_len = ssid->ssid_len;
6493 WL_PNO((">>> PNO filter set for ssid (%s) \n", ssid->ssid));
6498 if (request->n_ssids > 0) {
6499 for (i = 0; i < request->n_ssids; i++) {
6500 /* Active scan req for ssids */
6501 WL_PNO((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid));
6503 /* match_set ssids is a supert set of n_ssid list, so we need
6504 * not add these set seperately
6510 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, request->n_match_sets,
6511 pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
6512 WL_ERR(("PNO setup failed!! ret=%d \n", ret));
6515 wl->sched_scan_req = request;
6523 int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
6525 struct wl_priv *wl = wiphy_priv(wiphy);
6527 WL_DBG(("Enter \n"));
6530 return ERR_PTR(-EINVAL);
6532 WL_PNO((">>> SCHED SCAN STOP\n"));
6534 if (dhd_dev_pno_stop_for_ssid(dev) < 0)
6535 WL_ERR(("PNO Stop for SSID failed"));
6537 if (wl->scan_request && wl->sched_scan_running) {
6538 WL_PNO((">>> Sched scan running. Aborting it..\n"));
6539 wl_notify_escan_complete(wl, dev, true, true);
6542 wl->sched_scan_req = NULL;
6543 wl->sched_scan_running = FALSE;
6547 #endif /* WL_SCHED_SCAN */
6549 static struct cfg80211_ops wl_cfg80211_ops = {
6550 .add_virtual_intf = wl_cfg80211_add_virtual_iface,
6551 .del_virtual_intf = wl_cfg80211_del_virtual_iface,
6552 .change_virtual_intf = wl_cfg80211_change_virtual_iface,
6553 #if defined(WL_CFG80211_P2P_DEV_IF)
6554 .start_p2p_device = wl_cfgp2p_start_p2p_device,
6555 .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
6556 #endif /* WL_CFG80211_P2P_DEV_IF */
6557 .scan = wl_cfg80211_scan,
6558 .set_wiphy_params = wl_cfg80211_set_wiphy_params,
6559 .join_ibss = wl_cfg80211_join_ibss,
6560 .leave_ibss = wl_cfg80211_leave_ibss,
6561 .get_station = wl_cfg80211_get_station,
6562 .set_tx_power = wl_cfg80211_set_tx_power,
6563 .get_tx_power = wl_cfg80211_get_tx_power,
6564 .add_key = wl_cfg80211_add_key,
6565 .del_key = wl_cfg80211_del_key,
6566 .get_key = wl_cfg80211_get_key,
6567 .set_default_key = wl_cfg80211_config_default_key,
6568 .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
6569 .set_power_mgmt = wl_cfg80211_set_power_mgmt,
6570 .connect = wl_cfg80211_connect,
6571 .disconnect = wl_cfg80211_disconnect,
6572 .suspend = wl_cfg80211_suspend,
6573 .resume = wl_cfg80211_resume,
6574 .set_pmksa = wl_cfg80211_set_pmksa,
6575 .del_pmksa = wl_cfg80211_del_pmksa,
6576 .flush_pmksa = wl_cfg80211_flush_pmksa,
6577 .remain_on_channel = wl_cfg80211_remain_on_channel,
6578 .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
6579 .mgmt_tx = wl_cfg80211_mgmt_tx,
6580 .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
6581 .change_bss = wl_cfg80211_change_bss,
6582 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0)) || 0
6583 .set_channel = wl_cfg80211_set_channel,
6585 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !0
6586 .set_beacon = wl_cfg80211_add_set_beacon,
6587 .add_beacon = wl_cfg80211_add_set_beacon,
6589 .change_beacon = wl_cfg80211_change_beacon,
6590 .start_ap = wl_cfg80211_start_ap,
6591 .stop_ap = wl_cfg80211_stop_ap,
6593 #ifdef WL_SCHED_SCAN
6594 .sched_scan_start = wl_cfg80211_sched_scan_start,
6595 .sched_scan_stop = wl_cfg80211_sched_scan_stop,
6596 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */
6597 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6599 .del_station = wl_cfg80211_del_station,
6600 .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
6601 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
6602 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
6603 .tdls_oper = wl_cfg80211_tdls_oper
6607 s32 wl_mode_to_nl80211_iftype(s32 mode)
6613 return NL80211_IFTYPE_STATION;
6615 return NL80211_IFTYPE_ADHOC;
6617 return NL80211_IFTYPE_AP;
6619 return NL80211_IFTYPE_UNSPECIFIED;
6625 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
6626 /* Kernel Network Support->Wireless->Regulatory rules database
6627 options should be enabled and regulatory CRDA regdb table populated in Kernel
6628 for proper country reg notification
6631 wl_cfg80211_reg_notifier(
6632 struct wiphy *wiphy,
6633 struct regulatory_request *request)
6635 struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
6638 if (!request || !wl) {
6639 WL_ERR(("Invalid arg\n"));
6643 WL_DBG(("ccode: %c%c Initiator: %d\n",
6644 request->alpha2[0], request->alpha2[1], request->initiator));
6646 /* We support only REGDOM_SET_BY_USER as of now */
6647 if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
6648 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
6649 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
6650 request->initiator));
6651 /* in case of no supported country by regdb
6652 lets driver setup platform default Locale
6656 WL_ERR(("Set country code %c%c from %s\n",
6657 request->alpha2[0], request->alpha2[1],
6658 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
6660 if ((ret = wldev_set_country(wl_to_prmry_ndev(wl), request->alpha2,
6661 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false))) < 0) {
6662 WL_ERR(("set country Failed :%d\n", ret));
6667 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
6669 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *data)
6672 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
6673 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
6674 dhd_pub_t *dhd = (dhd_pub_t *)data;
6675 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
6678 wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv));
6679 if (unlikely(!wdev->wiphy)) {
6680 WL_ERR(("Couldn not allocate wiphy device\n"));
6684 set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
6685 wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
6686 /* Report how many SSIDs Driver can support per Scan request */
6687 wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
6688 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
6689 #ifdef WL_SCHED_SCAN
6690 wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
6691 wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
6692 wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
6693 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
6694 #endif /* WL_SCHED_SCAN */
6695 wdev->wiphy->interface_modes =
6696 BIT(NL80211_IFTYPE_STATION)
6697 | BIT(NL80211_IFTYPE_ADHOC)
6698 #if !defined(WL_ENABLE_P2P_IF)
6699 | BIT(NL80211_IFTYPE_MONITOR)
6700 #endif /* !WL_ENABLE_P2P_IF */
6701 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
6702 | BIT(NL80211_IFTYPE_P2P_CLIENT)
6703 | BIT(NL80211_IFTYPE_P2P_GO)
6704 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
6705 #if defined(WL_CFG80211_P2P_DEV_IF)
6706 | BIT(NL80211_IFTYPE_P2P_DEVICE)
6707 #endif /* WL_CFG80211_P2P_DEV_IF */
6708 | BIT(NL80211_IFTYPE_AP);
6710 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
6711 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
6712 if (dhd && dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
6713 WL_DBG(("Setting interface combinations for SoftAP mode\n"));
6714 wdev->wiphy->iface_combinations = softap_iface_combinations;
6715 wdev->wiphy->n_iface_combinations =
6716 ARRAY_SIZE(softap_iface_combinations);
6718 WL_DBG(("Setting interface combinations for STA+P2P mode\n"));
6719 wdev->wiphy->iface_combinations = sta_p2p_iface_combinations;
6720 wdev->wiphy->n_iface_combinations =
6721 ARRAY_SIZE(sta_p2p_iface_combinations);
6723 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
6725 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
6727 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
6728 wdev->wiphy->cipher_suites = __wl_cipher_suites;
6729 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
6730 wdev->wiphy->max_remain_on_channel_duration = 5000;
6731 wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
6732 #ifndef WL_POWERSAVE_DISABLED
6733 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
6735 wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
6736 #endif /* !WL_POWERSAVE_DISABLED */
6737 wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
6738 WIPHY_FLAG_4ADDR_AP |
6739 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && !0
6740 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
6742 WIPHY_FLAG_4ADDR_STATION;
6743 /* If driver advertises FW_ROAM, the supplicant wouldn't
6744 * send the BSSID & Freq in the connect command allowing the
6745 * the driver to choose the AP to connect to. But unless we
6746 * support ROAM_CACHE in firware this will delay the ASSOC as
6747 * as the FW need to do a full scan before attempting to connect
6748 * So that feature will just increase assoc. The better approach
6749 * to let Supplicant to provide channel info and FW letter may roam
6750 * if needed so DON'T advertise that featur eto Supplicant.
6752 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
6753 /* wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */
6755 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || 0
6756 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
6757 WIPHY_FLAG_OFFCHAN_TX;
6759 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6761 /* From 3.4 kernel ownards AP_SME flag can be advertised
6762 * to remove the patch from supplicant
6764 wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
6765 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
6767 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
6768 wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
6769 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
6771 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
6772 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
6775 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
6777 * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
6778 * disconnection of connected network before suspend. So a dummy wowlan
6779 * filter is configured for kernels linux-3.8 and above.
6781 wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
6782 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
6784 WL_DBG(("Registering custom regulatory)\n"));
6785 wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
6786 wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
6787 /* Now we can register wiphy with cfg80211 module */
6788 err = wiphy_register(wdev->wiphy);
6789 if (unlikely(err < 0)) {
6790 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
6791 wiphy_free(wdev->wiphy);
6794 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
6795 KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
6796 wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
6797 #endif /* ((LINUX_VER >= 3.0) && (LINUX_VER <= 3.3)) && WL_IFACE_COMB_NUM_CHANNELS */
6802 static void wl_free_wdev(struct wl_priv *wl)
6804 struct wireless_dev *wdev = wl->wdev;
6805 struct wiphy *wiphy;
6807 WL_ERR(("wdev is invalid\n"));
6810 wiphy = wdev->wiphy;
6811 wiphy_unregister(wdev->wiphy);
6812 wdev->wiphy->dev.parent = NULL;
6814 wl_delete_all_netinfo(wl);
6816 /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "wl",
6817 * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
6821 static s32 wl_inform_bss(struct wl_priv *wl)
6823 struct wl_scan_results *bss_list;
6824 struct wl_bss_info *bi = NULL; /* must be initialized */
6828 bss_list = wl->bss_list;
6829 WL_DBG(("scanned AP count (%d)\n", bss_list->count));
6830 bi = next_bss(bss_list, bi);
6831 for_each_bss(bss_list, bi, i) {
6832 err = wl_inform_single_bss(wl, bi);
6839 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
6841 struct wiphy *wiphy = wl_to_wiphy(wl);
6842 struct ieee80211_mgmt *mgmt;
6843 struct ieee80211_channel *channel;
6844 struct ieee80211_supported_band *band;
6845 struct wl_cfg80211_bss_info *notif_bss_info;
6846 struct wl_scan_req *sr = wl_to_sr(wl);
6847 struct beacon_proberesp *beacon_proberesp;
6848 struct cfg80211_bss *cbss = NULL;
6855 if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
6856 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
6859 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
6860 notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
6861 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
6862 if (unlikely(!notif_bss_info)) {
6863 WL_ERR(("notif_bss_info alloc failed\n"));
6866 mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
6867 notif_bss_info->channel =
6868 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
6870 if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
6871 band = wiphy->bands[IEEE80211_BAND_2GHZ];
6873 band = wiphy->bands[IEEE80211_BAND_5GHZ];
6875 WL_ERR(("No valid band"));
6876 kfree(notif_bss_info);
6879 notif_bss_info->rssi = wl_rssi_offset(dtoh16(bi->RSSI));
6880 memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
6881 mgmt_type = wl->active_scan ?
6882 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
6883 if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
6884 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
6886 beacon_proberesp = wl->active_scan ?
6887 (struct beacon_proberesp *)&mgmt->u.probe_resp :
6888 (struct beacon_proberesp *)&mgmt->u.beacon;
6889 beacon_proberesp->timestamp = 0;
6890 beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
6891 beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
6893 wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length);
6894 wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
6895 wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
6896 offsetof(struct wl_cfg80211_bss_info, frame_buf));
6897 notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
6898 u.beacon.variable) + wl_get_ielen(wl);
6899 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
6900 freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
6903 freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
6906 WL_ERR(("Invalid channel, fail to chcnage channel to freq\n"));
6907 kfree(notif_bss_info);
6910 channel = ieee80211_get_channel(wiphy, freq);
6911 if (unlikely(!channel)) {
6912 WL_ERR(("ieee80211_get_channel error\n"));
6913 kfree(notif_bss_info);
6916 WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM"
6917 "mgmt_type %d frame_len %d\n", bi->SSID,
6918 notif_bss_info->rssi, notif_bss_info->channel,
6919 mgmt->u.beacon.capab_info, &bi->BSSID, mgmt_type,
6920 notif_bss_info->frame_len));
6922 signal = notif_bss_info->rssi * 100;
6923 if (!mgmt->u.probe_resp.timestamp) {
6924 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
6926 get_monotonic_boottime(&ts);
6927 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
6928 + ts.tv_nsec / 1000;
6931 do_gettimeofday(&tv);
6932 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
6938 cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
6939 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
6940 if (unlikely(!cbss)) {
6941 WL_ERR(("cfg80211_inform_bss_frame error\n"));
6942 kfree(notif_bss_info);
6946 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
6947 cfg80211_put_bss(wiphy, cbss);
6949 cfg80211_put_bss(cbss);
6950 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
6951 kfree(notif_bss_info);
6955 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
6957 u32 event = ntoh32(e->event_type);
6958 u32 status = ntoh32(e->status);
6959 u16 flags = ntoh16(e->flags);
6961 WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
6962 if (event == WLC_E_SET_SSID) {
6963 if (status == WLC_E_STATUS_SUCCESS) {
6964 if (!wl_is_ibssmode(wl, ndev))
6967 } else if (event == WLC_E_LINK) {
6968 if (flags & WLC_EVENT_MSG_LINK)
6972 WL_DBG(("wl_is_linkup false\n"));
6976 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
6978 u32 event = ntoh32(e->event_type);
6979 u16 flags = ntoh16(e->flags);
6981 if (event == WLC_E_DEAUTH_IND ||
6982 event == WLC_E_DISASSOC_IND ||
6983 event == WLC_E_DISASSOC ||
6984 event == WLC_E_DEAUTH) {
6985 #if (WL_DBG_LEVEL > 0)
6986 WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
6987 #endif /* (WL_DBG_LEVEL > 0) */
6989 } else if (event == WLC_E_LINK) {
6990 if (!(flags & WLC_EVENT_MSG_LINK)) {
6991 #if (WL_DBG_LEVEL > 0)
6992 WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
6993 #endif /* (WL_DBG_LEVEL > 0) */
7001 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
7003 u32 event = ntoh32(e->event_type);
7004 u32 status = ntoh32(e->status);
7006 if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
7008 if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
7014 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
7015 * to AP/P2P GO via events. If this change is backported to kernel for which
7016 * this driver is being built, then define WL_CFG80211_STA_EVENT. You
7017 * should use this new/del sta event mechanism for BRCM supplicant >= 22.
7020 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
7021 const wl_event_msg_t *e, void *data)
7024 u32 event = ntoh32(e->event_type);
7025 u32 reason = ntoh32(e->reason);
7026 u32 len = ntoh32(e->datalen);
7028 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7030 bool isfree = false;
7032 u8 bsscfgidx = e->bsscfgidx;
7038 struct ieee80211_supported_band *band;
7039 struct ether_addr da;
7040 struct ether_addr bssid;
7041 struct wiphy *wiphy = wl_to_wiphy(wl);
7044 struct station_info sinfo;
7047 WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
7048 /* if link down, bsscfg is disabled. */
7049 if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
7050 wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) {
7051 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
7052 WL_INFO(("AP mode link down !! \n"));
7053 complete(&wl->iface_disable);
7057 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7059 WL_DBG(("Enter \n"));
7060 if (!len && (event == WLC_E_DEAUTH)) {
7061 len = 2; /* reason code field */
7065 body = kzalloc(len, GFP_KERNEL);
7068 WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
7072 memset(&bssid, 0, ETHER_ADDR_LEN);
7073 WL_DBG(("Enter event %d ndev %p\n", event, ndev));
7074 if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) {
7079 memcpy(body, data, len);
7081 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
7082 NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
7083 memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
7084 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
7086 case WLC_E_ASSOC_IND:
7089 case WLC_E_REASSOC_IND:
7090 fc = FC_REASSOC_REQ;
7092 case WLC_E_DISASSOC_IND:
7094 WL_ERR(("event %s(%d) status %d reason %d\n",
7095 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7097 case WLC_E_DEAUTH_IND:
7099 WL_ERR(("event %s(%d) status %d reason %d\n",
7100 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7104 WL_ERR(("event %s(%d) status %d reason %d\n",
7105 bcmevent_names[event].name, event, ntoh32(e->status), reason));
7111 if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
7116 channel = dtoh32(ci.hw_channel);
7117 if (channel <= CH_MAX_2G_CHANNEL)
7118 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7120 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7122 WL_ERR(("No valid band"));
7127 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
7128 freq = ieee80211_channel_to_frequency(channel);
7131 freq = ieee80211_channel_to_frequency(channel, band->band);
7134 err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
7135 &mgmt_frame, &len, body);
7140 if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
7141 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7142 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7144 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7146 } else if (event == WLC_E_DISASSOC_IND) {
7147 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7148 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7150 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7152 } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7153 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
7154 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7156 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7165 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
7167 if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
7168 reason == DOT11_SC_SUCCESS) {
7169 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
7171 WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
7174 sinfo.assoc_req_ies = data;
7175 sinfo.assoc_req_ies_len = len;
7176 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
7177 } else if (event == WLC_E_DISASSOC_IND) {
7178 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7179 } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7180 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7187 wl_get_auth_assoc_status(struct wl_priv *wl, struct net_device *ndev,
7188 const wl_event_msg_t *e)
7190 u32 reason = ntoh32(e->reason);
7191 u32 event = ntoh32(e->event_type);
7192 struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
7193 WL_DBG(("event type : %d, reason : %d\n", event, reason));
7198 sec->auth_assoc_res_status = reason;
7203 WL_ERR(("sec is NULL\n"));
7208 wl_notify_connect_status_ibss(struct wl_priv *wl, struct net_device *ndev,
7209 const wl_event_msg_t *e, void *data)
7212 u32 event = ntoh32(e->event_type);
7213 u16 flags = ntoh16(e->flags);
7214 u32 status = ntoh32(e->status);
7217 if (event == WLC_E_JOIN) {
7218 WL_DBG(("joined in IBSS network\n"));
7220 if (event == WLC_E_START) {
7221 WL_DBG(("started IBSS network\n"));
7223 if (event == WLC_E_JOIN || event == WLC_E_START ||
7224 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
7225 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7226 /* ROAM or Redundant */
7227 u8 *cur_bssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7228 if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
7229 WL_DBG(("IBSS connected event from same BSSID("
7230 MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
7233 WL_INFO(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
7234 MAC2STRDBG(cur_bssid), MAC2STRDBG((u8 *)&e->addr)));
7235 wl_get_assoc_ies(wl, ndev);
7236 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7237 wl_update_bss_info(wl, ndev);
7238 cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7241 /* New connection */
7242 WL_INFO(("IBSS connected to " MACDBG "\n", MAC2STRDBG((u8 *)&e->addr)));
7244 wl_get_assoc_ies(wl, ndev);
7245 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7246 wl_update_bss_info(wl, ndev);
7247 cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7248 wl_set_drv_status(wl, CONNECTED, ndev);
7250 wl_update_prof(wl, ndev, NULL, (void *)&active, WL_PROF_ACT);
7252 } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
7253 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
7254 wl_clr_drv_status(wl, CONNECTED, ndev);
7256 wl_init_prof(wl, ndev);
7258 else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
7259 WL_DBG(("no action - join fail (IBSS mode)\n"));
7262 WL_DBG(("no action (IBSS mode)\n"));
7268 wl_notify_connect_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7269 const wl_event_msg_t *e, void *data)
7272 struct net_device *ndev = NULL;
7274 u32 event = ntoh32(e->event_type);
7276 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7278 if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
7279 err = wl_notify_connect_status_ap(wl, ndev, e, data);
7280 } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS) {
7281 err = wl_notify_connect_status_ibss(wl, ndev, e, data);
7282 } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) {
7283 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
7284 ntoh32(e->event_type), ntoh32(e->status), ndev));
7285 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
7286 wl_get_auth_assoc_status(wl, ndev, e);
7289 if (wl_is_linkup(wl, e, ndev)) {
7292 if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7293 printk("wl_bss_connect_done succeeded with " MACDBG "\n",
7294 MAC2STRDBG((u8*)(&e->addr)));
7295 wl_bss_connect_done(wl, ndev, e, data, true);
7296 WL_DBG(("joined in BSS network \"%s\"\n",
7297 ((struct wlc_ssid *)
7298 wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID));
7300 wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7301 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7303 } else if (wl_is_linkdown(wl, e)) {
7304 if (wl->scan_request) {
7306 wl_notify_escan_complete(wl, ndev, true, true);
7308 del_timer_sync(&wl->scan_timeout);
7309 wl_iscan_aborted(wl);
7312 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7314 u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7316 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
7317 reason = ntoh32(e->reason);
7318 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
7319 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
7321 printk("link down if %s may call cfg80211_disconnected. "
7322 "event : %d, reason=%d from " MACDBG "\n",
7323 ndev->name, event, ntoh32(e->reason),
7324 MAC2STRDBG((u8*)(&e->addr)));
7325 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
7326 WL_ERR(("BSSID of event is not the connected BSSID"
7327 "(ignore it) cur: " MACDBG " event: " MACDBG"\n",
7328 MAC2STRDBG(curbssid), MAC2STRDBG((u8*)(&e->addr))));
7331 wl_clr_drv_status(wl, CONNECTED, ndev);
7332 if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7333 /* To make sure disconnect, explictly send dissassoc
7334 * for BSSID 00:00:00:00:00:00 issue
7336 scbval.val = WLAN_REASON_DEAUTH_LEAVING;
7338 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
7339 scbval.val = htod32(scbval.val);
7340 err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
7341 sizeof(scb_val_t), true);
7343 WL_ERR(("WLC_DISASSOC error %d\n", err));
7346 cfg80211_disconnected(ndev, reason, NULL, 0, GFP_KERNEL);
7348 wl_init_prof(wl, ndev);
7351 else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
7353 printk("link down, during connecting\n");
7354 #ifdef ESCAN_RESULT_PATCH
7355 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7356 (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7357 (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
7358 /* In case this event comes while associating another AP */
7359 #endif /* ESCAN_RESULT_PATCH */
7360 wl_bss_connect_done(wl, ndev, e, data, false);
7362 wl_clr_drv_status(wl, DISCONNECTING, ndev);
7364 /* if link down, bsscfg is diabled */
7365 if (ndev != wl_to_prmry_ndev(wl))
7366 complete(&wl->iface_disable);
7368 } else if (wl_is_nonetwork(wl, e)) {
7369 printk("connect failed event=%d e->status %d e->reason %d \n",
7370 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
7371 /* Clean up any pending scan request */
7372 if (wl->scan_request) {
7374 wl_notify_escan_complete(wl, ndev, true, true);
7376 del_timer_sync(&wl->scan_timeout);
7377 wl_iscan_aborted(wl);
7380 if (wl_get_drv_status(wl, CONNECTING, ndev))
7381 wl_bss_connect_done(wl, ndev, e, data, false);
7383 printk("%s nothing\n", __FUNCTION__);
7386 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(wl, ndev)));
7393 wl_notify_roaming_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7394 const wl_event_msg_t *e, void *data)
7397 struct net_device *ndev = NULL;
7399 u32 event = be32_to_cpu(e->event_type);
7400 u32 status = be32_to_cpu(e->status);
7402 WL_DBG(("Enter \n"));
7404 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7406 if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) {
7407 if (wl_get_drv_status(wl, CONNECTED, ndev))
7408 wl_bss_roaming_done(wl, ndev, e, data);
7410 wl_bss_connect_done(wl, ndev, e, data, true);
7412 wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7413 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7418 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
7420 wl_assoc_info_t assoc_info;
7421 struct wl_connect_info *conn_info = wl_to_conn(wl);
7424 WL_DBG(("Enter \n"));
7425 err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, wl->extra_buf,
7426 WL_ASSOC_INFO_MAX, NULL);
7427 if (unlikely(err)) {
7428 WL_ERR(("could not get assoc info (%d)\n", err));
7431 memcpy(&assoc_info, wl->extra_buf, sizeof(wl_assoc_info_t));
7432 assoc_info.req_len = htod32(assoc_info.req_len);
7433 assoc_info.resp_len = htod32(assoc_info.resp_len);
7434 assoc_info.flags = htod32(assoc_info.flags);
7435 if (conn_info->req_ie_len) {
7436 conn_info->req_ie_len = 0;
7437 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
7439 if (conn_info->resp_ie_len) {
7440 conn_info->resp_ie_len = 0;
7441 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
7443 if (assoc_info.req_len) {
7444 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, wl->extra_buf,
7445 WL_ASSOC_INFO_MAX, NULL);
7446 if (unlikely(err)) {
7447 WL_ERR(("could not get assoc req (%d)\n", err));
7450 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
7451 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
7452 conn_info->req_ie_len -= ETHER_ADDR_LEN;
7454 if (conn_info->req_ie_len <= MAX_REQ_LINE)
7455 memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len);
7457 WL_ERR(("IE size %d above max %d size \n",
7458 conn_info->req_ie_len, MAX_REQ_LINE));
7462 conn_info->req_ie_len = 0;
7464 if (assoc_info.resp_len) {
7465 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, wl->extra_buf,
7466 WL_ASSOC_INFO_MAX, NULL);
7467 if (unlikely(err)) {
7468 WL_ERR(("could not get assoc resp (%d)\n", err));
7471 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
7472 if (conn_info->resp_ie_len <= MAX_REQ_LINE)
7473 memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len);
7475 WL_ERR(("IE size %d above max %d size \n",
7476 conn_info->resp_ie_len, MAX_REQ_LINE));
7480 conn_info->resp_ie_len = 0;
7482 WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
7483 conn_info->resp_ie_len));
7488 static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
7489 size_t *join_params_size)
7491 chanspec_t chanspec = 0;
7493 join_params->params.chanspec_num = 1;
7494 join_params->params.chanspec_list[0] = ch;
7496 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
7497 chanspec |= WL_CHANSPEC_BAND_2G;
7499 chanspec |= WL_CHANSPEC_BAND_5G;
7501 chanspec |= WL_CHANSPEC_BW_20;
7502 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
7504 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
7505 join_params->params.chanspec_num * sizeof(chanspec_t);
7507 join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
7508 join_params->params.chanspec_list[0] |= chanspec;
7509 join_params->params.chanspec_list[0] =
7510 wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
7512 join_params->params.chanspec_num =
7513 htod32(join_params->params.chanspec_num);
7514 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
7515 join_params->params.chanspec_list[0],
7516 join_params->params.chanspec_num));
7520 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
7522 struct cfg80211_bss *bss;
7523 struct wl_bss_info *bi;
7524 struct wlc_ssid *ssid;
7525 struct bcm_tlv *tim;
7526 s32 beacon_interval;
7532 struct wiphy *wiphy;
7534 wiphy = wl_to_wiphy(wl);
7536 ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID);
7537 curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7538 bss = cfg80211_get_bss(wiphy, NULL, curbssid,
7539 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
7540 WLAN_CAPABILITY_ESS);
7542 mutex_lock(&wl->usr_sync);
7544 WL_DBG(("Could not find the AP\n"));
7545 *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
7546 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
7547 wl->extra_buf, WL_EXTRA_BUF_MAX, false);
7548 if (unlikely(err)) {
7549 WL_ERR(("Could not get bss info %d\n", err));
7550 goto update_bss_info_out;
7552 bi = (struct wl_bss_info *)(wl->extra_buf + 4);
7553 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
7554 WL_ERR(("Bssid doesn't match\n"));
7556 goto update_bss_info_out;
7558 err = wl_inform_single_bss(wl, bi);
7560 goto update_bss_info_out;
7562 ie = ((u8 *)bi) + bi->ie_offset;
7563 ie_len = bi->ie_length;
7564 beacon_interval = cpu_to_le16(bi->beacon_period);
7566 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
7567 #if defined(WL_CFG80211_P2P_DEV_IF)
7568 ie = (u8 *)bss->ies->data;
7569 ie_len = bss->ies->len;
7571 ie = bss->information_elements;
7572 ie_len = bss->len_information_elements;
7573 #endif /* WL_CFG80211_P2P_DEV_IF */
7574 beacon_interval = bss->beacon_interval;
7575 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
7576 cfg80211_put_bss(wiphy, bss);
7578 cfg80211_put_bss(bss);
7579 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
7582 tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
7584 dtim_period = tim->data[1];
7587 * active scan was done so we could not get dtim
7588 * information out of probe response.
7589 * so we speficially query dtim information.
7591 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
7592 &dtim_period, sizeof(dtim_period), false);
7593 if (unlikely(err)) {
7594 WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
7595 goto update_bss_info_out;
7599 wl_update_prof(wl, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
7600 wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
7602 update_bss_info_out:
7603 if (unlikely(err)) {
7604 WL_ERR(("Failed with error %d\n", err));
7606 mutex_unlock(&wl->usr_sync);
7611 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
7612 const wl_event_msg_t *e, void *data)
7614 struct wl_connect_info *conn_info = wl_to_conn(wl);
7617 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7618 struct wl_bss_info *bss_info;
7619 struct wiphy *wiphy = wl_to_wiphy(wl);
7620 struct ieee80211_supported_band *band;
7621 struct ieee80211_channel *notify_channel = NULL;
7627 wl_get_assoc_ies(wl, ndev);
7628 wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
7629 curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7630 wl_update_bss_info(wl, ndev);
7631 wl_update_pmklist(ndev, wl->pmk_list, err);
7633 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7634 /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
7635 buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
7639 *(__le32 *)buf = htod32(WL_EXTRA_BUF_MAX);
7640 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX, false);
7644 bss_info = (struct wl_bss_info *)(buf + 4);
7645 channel = bss_info->ctl_ch ? bss_info->ctl_ch :
7646 CHSPEC_CHANNEL(wl_chspec_driver_to_host(bss_info->chanspec));
7647 if (channel <= CH_MAX_2G_CHANNEL)
7648 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7650 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7651 freq = ieee80211_channel_to_frequency(channel, band->band);
7652 notify_channel = ieee80211_get_channel(wiphy, freq);
7656 printk("wl_bss_roaming_done succeeded to " MACDBG "\n",
7657 MAC2STRDBG((u8*)(&e->addr)));
7659 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
7660 WL_DBG(("BSSID Mismatch, so indicate roam to cfg80211\n"));
7661 cfg80211_roamed(ndev,
7662 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || 0
7666 conn_info->req_ie, conn_info->req_ie_len,
7667 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
7669 WL_DBG(("Report roaming result\n"));
7671 wl_set_drv_status(wl, CONNECTED, ndev);
7677 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
7678 const wl_event_msg_t *e, void *data, bool completed)
7680 struct wl_connect_info *conn_info = wl_to_conn(wl);
7681 struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
7683 u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7685 WL_ERR(("sec is NULL\n"));
7688 WL_DBG((" enter\n"));
7689 #ifdef ESCAN_RESULT_PATCH
7690 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7691 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
7692 WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
7693 ntoh32(e->event_type), ntoh32(e->status)));
7697 if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
7698 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
7699 WL_DBG(("copy bssid\n"));
7700 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
7704 if (wl->scan_request) {
7705 wl_notify_escan_complete(wl, ndev, true, true);
7707 #endif /* ESCAN_RESULT_PATCH */
7708 if (wl_get_drv_status(wl, CONNECTING, ndev) && (e->event_type == WLC_E_SET_SSID)) {
7709 wl_cfg80211_scan_abort(wl);
7710 wl_clr_drv_status(wl, CONNECTING, ndev);
7712 wl_get_assoc_ies(wl, ndev);
7713 wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
7714 curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7715 wl_update_bss_info(wl, ndev);
7716 wl_update_pmklist(ndev, wl->pmk_list, err);
7717 wl_set_drv_status(wl, CONNECTED, ndev);
7718 if (ndev != wl_to_prmry_ndev(wl)) {
7719 /* reinitialize completion to clear previous count */
7720 INIT_COMPLETION(wl->iface_disable);
7723 cfg80211_connect_result(ndev,
7726 conn_info->req_ie_len,
7728 conn_info->resp_ie_len,
7729 completed ? WLAN_STATUS_SUCCESS :
7730 (sec->auth_assoc_res_status) ?
7731 sec->auth_assoc_res_status :
7732 WLAN_STATUS_UNSPECIFIED_FAILURE,
7735 WL_INFO(("Report connect result - connection succeeded\n"));
7737 WL_ERR(("Report connect result - connection failed\n"));
7743 wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7744 const wl_event_msg_t *e, void *data)
7746 struct net_device *ndev = NULL;
7747 u16 flags = ntoh16(e->flags);
7748 enum nl80211_key_type key_type;
7750 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7752 mutex_lock(&wl->usr_sync);
7753 if (flags & WLC_EVENT_MSG_GROUP)
7754 key_type = NL80211_KEYTYPE_GROUP;
7756 key_type = NL80211_KEYTYPE_PAIRWISE;
7758 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
7760 mutex_unlock(&wl->usr_sync);
7767 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7768 const wl_event_msg_t *e, void *data)
7770 struct net_device *ndev = NULL;
7772 WL_ERR((">>> PNO Event\n"));
7774 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7776 #ifndef WL_SCHED_SCAN
7777 mutex_lock(&wl->usr_sync);
7778 /* TODO: Use cfg80211_sched_scan_results(wiphy); */
7779 cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
7780 mutex_unlock(&wl->usr_sync);
7782 /* If cfg80211 scheduled scan is supported, report the pno results via sched
7785 wl_notify_sched_scan_results(wl, ndev, e, data);
7786 #endif /* WL_SCHED_SCAN */
7789 #endif /* PNO_SUPPORT */
7792 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7793 const wl_event_msg_t *e, void *data)
7795 struct channel_info channel_inform;
7796 struct wl_scan_results *bss_list;
7797 struct net_device *ndev = NULL;
7798 u32 len = WL_SCAN_BUF_MAX;
7800 unsigned long flags;
7802 WL_DBG(("Enter \n"));
7803 if (!wl_get_drv_status(wl, SCANNING, ndev)) {
7804 WL_ERR(("scan is not ready \n"));
7807 if (wl->iscan_on && wl->iscan_kickstart)
7808 return wl_wakeup_iscan(wl_to_iscan(wl));
7810 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7812 mutex_lock(&wl->usr_sync);
7813 wl_clr_drv_status(wl, SCANNING, ndev);
7814 err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
7815 sizeof(channel_inform), false);
7816 if (unlikely(err)) {
7817 WL_ERR(("scan busy (%d)\n", err));
7820 channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
7821 if (unlikely(channel_inform.scan_channel)) {
7823 WL_DBG(("channel_inform.scan_channel (%d)\n",
7824 channel_inform.scan_channel));
7826 wl->bss_list = wl->scan_results;
7827 bss_list = wl->bss_list;
7828 memset(bss_list, 0, len);
7829 bss_list->buflen = htod32(len);
7830 err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
7831 if (unlikely(err) && unlikely(!wl->scan_suppressed)) {
7832 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
7836 bss_list->buflen = dtoh32(bss_list->buflen);
7837 bss_list->version = dtoh32(bss_list->version);
7838 bss_list->count = dtoh32(bss_list->count);
7840 err = wl_inform_bss(wl);
7843 del_timer_sync(&wl->scan_timeout);
7844 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
7845 if (wl->scan_request) {
7846 cfg80211_scan_done(wl->scan_request, false);
7847 wl->scan_request = NULL;
7849 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
7850 WL_DBG(("cfg80211_scan_done\n"));
7851 mutex_unlock(&wl->usr_sync);
7856 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
7857 const struct ether_addr *sa, const struct ether_addr *bssid,
7858 u8 **pheader, u32 *body_len, u8 *pbody)
7860 struct dot11_management_header *hdr;
7864 u32 prebody_len = *body_len;
7867 /* capability , listen interval */
7868 totlen = DOT11_ASSOC_REQ_FIXED_LEN;
7869 *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
7872 case FC_REASSOC_REQ:
7873 /* capability, listen inteval, ap address */
7874 totlen = DOT11_REASSOC_REQ_FIXED_LEN;
7875 *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
7878 totlen += DOT11_MGMT_HDR_LEN + prebody_len;
7879 *pheader = kzalloc(totlen, GFP_KERNEL);
7880 if (*pheader == NULL) {
7881 WL_ERR(("memory alloc failed \n"));
7884 hdr = (struct dot11_management_header *) (*pheader);
7885 hdr->fc = htol16(fc);
7888 offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
7889 bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
7890 bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
7891 bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
7892 if ((pbody != NULL) && prebody_len)
7893 bcopy((const char*)pbody, offset, prebody_len);
7900 wl_stop_wait_next_action_frame(struct wl_priv *wl)
7902 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
7903 if (!(wl_get_p2p_status(wl, ACTION_TX_COMPLETED) ||
7904 wl_get_p2p_status(wl, ACTION_TX_NOACK)))
7905 wl_set_p2p_status(wl, ACTION_TX_COMPLETED);
7907 WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
7908 /* if channel is not zero, "actfame" uses off channel scan.
7909 * So abort scan for off channel completion.
7911 if (wl->af_sent_channel)
7912 wl_cfg80211_scan_abort(wl);
7914 #ifdef WL_CFG80211_SYNC_GON
7915 else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) {
7916 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
7917 /* So abort scan to cancel listen */
7918 wl_cfg80211_scan_abort(wl);
7920 #endif /* WL_CFG80211_SYNC_GON */
7924 int wl_cfg80211_get_ioctl_version(void)
7926 return ioctl_version;
7930 wl_notify_rx_mgmt_frame(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7931 const wl_event_msg_t *e, void *data)
7934 struct ieee80211_supported_band *band;
7935 struct wiphy *wiphy = wl_to_wiphy(wl);
7936 struct ether_addr da;
7937 struct ether_addr bssid;
7938 bool isfree = false;
7941 struct net_device *ndev = NULL;
7942 wifi_p2p_pub_act_frame_t *act_frm = NULL;
7943 wifi_p2p_action_frame_t *p2p_act_frm = NULL;
7944 wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
7945 wl_event_rx_frame_data_t *rxframe =
7946 (wl_event_rx_frame_data_t*)data;
7947 u32 event = ntoh32(e->event_type);
7949 u8 bsscfgidx = e->bsscfgidx;
7950 u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
7951 u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
7953 memset(&bssid, 0, ETHER_ADDR_LEN);
7955 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7957 if (channel <= CH_MAX_2G_CHANNEL)
7958 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7960 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7962 WL_ERR(("No valid band"));
7965 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
7966 freq = ieee80211_channel_to_frequency(channel);
7969 freq = ieee80211_channel_to_frequency(channel, band->band);
7971 if (event == WLC_E_ACTION_FRAME_RX) {
7972 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
7973 NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
7975 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
7977 WL_ERR(("WLC_GET_BSSID error %d\n", err));
7978 memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
7979 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
7980 &mgmt_frame, &mgmt_frame_len,
7981 (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
7983 WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
7984 mgmt_frame_len, channel, freq));
7988 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
7989 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
7990 act_frm = (wifi_p2p_pub_act_frame_t *)
7991 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
7992 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
7993 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
7994 p2p_act_frm = (wifi_p2p_action_frame_t *)
7995 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
7997 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
7998 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8000 sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
8001 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8002 if (sd_act_frm && wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8003 if (wl->next_af_subtype == sd_act_frm->action) {
8004 WL_DBG(("We got a right next frame of SD!(%d)\n",
8005 sd_act_frm->action));
8006 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8008 /* Stop waiting for next AF. */
8009 wl_stop_wait_next_action_frame(wl);
8015 * if we got normal action frame and ndev is p2p0,
8016 * we have to change ndev from p2p0 to wlan0
8018 #if defined(WL_ENABLE_P2P_IF)
8019 if (wl->p2p_net == cfgdev)
8020 cfgdev = wl_to_prmry_ndev(wl);
8021 #endif /* WL_ENABLE_P2P_IF */
8023 if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
8025 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8026 mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
8027 WL_DBG(("Recived action is not public action frame\n"));
8028 } else if (wl->next_af_subtype == action) {
8029 WL_DBG(("Recived action is the waiting action(%d)\n",
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);
8041 if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8042 if (wl->next_af_subtype == act_frm->subtype) {
8043 WL_DBG(("We got a right next frame!(%d)\n",
8045 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8047 if (wl->next_af_subtype == P2P_PAF_GON_CONF) {
8051 /* Stop waiting for next AF. */
8052 wl_stop_wait_next_action_frame(wl);
8057 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
8058 mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
8060 * After complete GO Negotiation, roll back to mpc mode
8062 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
8063 (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
8064 wldev_iovar_setint(ndev, "mpc", 1);
8066 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
8067 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
8068 wl_clr_p2p_status(wl, GO_NEG_PHASE);
8071 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
8073 /* wpa supplicant use probe request event for restarting another GON Req.
8074 * but it makes GON Req repetition.
8075 * so if src addr of prb req is same as my target device,
8076 * do not send probe request event during sending action frame.
8078 if (event == WLC_E_P2P_PROBREQ_MSG) {
8079 WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
8080 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
8083 /* Filter any P2P probe reqs arriving during the
8087 wl_get_p2p_status(wl, GO_NEG_PHASE)) {
8088 WL_DBG(("Filtering P2P probe_req while "
8089 "being in GO-Neg state\n"));
8095 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || 0
8096 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8098 cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8101 WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
8102 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
8109 #ifdef WL_SCHED_SCAN
8110 /* If target scan is not reliable, set the below define to "1" to do a
8113 #define FULL_ESCAN_ON_PFN_NET_FOUND 0
8115 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
8116 const wl_event_msg_t *e, void *data)
8118 wl_pfn_net_info_t *netinfo, *pnetinfo;
8119 struct wiphy *wiphy = wl_to_wiphy(wl);
8121 struct cfg80211_scan_request *request = NULL;
8122 struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
8123 struct ieee80211_channel *channel = NULL;
8124 int channel_req = 0;
8126 struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
8127 int n_pfn_results = pfn_result->count;
8129 WL_DBG(("Enter\n"));
8131 if (e->event_type == WLC_E_PFN_NET_LOST) {
8132 WL_PNO(("PFN NET LOST event. Do Nothing \n"));
8135 WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
8136 if (n_pfn_results > 0) {
8139 if (n_pfn_results > MAX_PFN_LIST_COUNT)
8140 n_pfn_results = MAX_PFN_LIST_COUNT;
8141 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
8142 - sizeof(wl_pfn_net_info_t));
8144 memset(&ssid, 0x00, sizeof(ssid));
8146 request = kzalloc(sizeof(*request)
8147 + sizeof(*request->channels) * n_pfn_results,
8149 channel = (struct ieee80211_channel *)kzalloc(
8150 (sizeof(struct ieee80211_channel) * n_pfn_results),
8152 if (!request || !channel) {
8153 WL_ERR(("No memory"));
8158 request->wiphy = wiphy;
8160 for (i = 0; i < n_pfn_results; i++) {
8161 netinfo = &pnetinfo[i];
8163 WL_ERR(("Invalid netinfo ptr. index:%d", i));
8167 WL_PNO((">>> SSID:%s Channel:%d \n",
8168 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
8169 /* PFN result doesn't have all the info which are required by the supplicant
8170 * (For e.g IEs) Do a target Escan so that sched scan results are reported
8171 * via wl_inform_single_bss in the required format. Escan does require the
8172 * scan request in the form of cfg80211_scan_request. For timebeing, create
8173 * cfg80211_scan_request one out of the received PNO event.
8175 memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
8176 netinfo->pfnsubnet.SSID_len);
8177 ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
8180 channel_req = netinfo->pfnsubnet.channel;
8181 band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
8182 : NL80211_BAND_5GHZ;
8183 channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
8184 channel[i].band = band;
8185 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
8186 request->channels[i] = &channel[i];
8187 request->n_channels++;
8190 /* assign parsed ssid array */
8191 if (request->n_ssids)
8192 request->ssids = &ssid[0];
8194 if (wl_get_drv_status_all(wl, SCANNING)) {
8195 /* Abort any on-going scan */
8196 wl_notify_escan_complete(wl, ndev, true, true);
8199 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
8200 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
8201 err = wl_cfgp2p_discover_enable_search(wl, false);
8202 if (unlikely(err)) {
8203 wl_clr_drv_status(wl, SCANNING, ndev);
8208 wl_set_drv_status(wl, SCANNING, ndev);
8209 #if FULL_ESCAN_ON_PFN_NET_FOUND
8210 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
8211 err = wl_do_escan(wl, wiphy, ndev, NULL);
8213 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
8214 err = wl_do_escan(wl, wiphy, ndev, request);
8217 wl_clr_drv_status(wl, SCANNING, ndev);
8220 wl->sched_scan_running = TRUE;
8223 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
8232 #endif /* WL_SCHED_SCAN */
8234 static void wl_init_conf(struct wl_conf *conf)
8236 WL_DBG(("Enter \n"));
8237 conf->frag_threshold = (u32)-1;
8238 conf->rts_threshold = (u32)-1;
8239 conf->retry_short = (u32)-1;
8240 conf->retry_long = (u32)-1;
8241 conf->tx_power = -1;
8244 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev)
8246 unsigned long flags;
8247 struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
8249 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8250 memset(profile, 0, sizeof(struct wl_profile));
8251 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8254 static void wl_init_event_handler(struct wl_priv *wl)
8256 memset(wl->evt_handler, 0, sizeof(wl->evt_handler));
8258 wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
8259 wl->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
8260 wl->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
8261 wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
8262 wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
8263 wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
8264 wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
8265 wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
8266 wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
8267 wl->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
8268 wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
8269 wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
8270 wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
8271 wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8272 wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8273 wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
8274 wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
8275 wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
8276 wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
8277 wl->evt_handler[WLC_E_START] = wl_notify_connect_status;
8279 wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
8280 #endif /* PNO_SUPPORT */
8282 wl->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
8285 wl->evt_handler[WLC_E_CCX_S69_RESP_RX] = wl_ccx_s69_response;
8289 #if defined(STATIC_WL_PRIV_STRUCT)
8291 wl_init_escan_result_buf(struct wl_priv *wl)
8293 wl->escan_info.escan_buf = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0);
8294 bzero(wl->escan_info.escan_buf, ESCAN_BUF_SIZE);
8298 wl_deinit_escan_result_buf(struct wl_priv *wl)
8300 wl->escan_info.escan_buf = NULL;
8303 #endif /* STATIC_WL_PRIV_STRUCT */
8305 static s32 wl_init_priv_mem(struct wl_priv *wl)
8307 WL_DBG(("Enter \n"));
8308 wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
8309 if (unlikely(!wl->scan_results)) {
8310 WL_ERR(("Scan results alloc failed\n"));
8311 goto init_priv_mem_out;
8313 wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
8314 if (unlikely(!wl->conf)) {
8315 WL_ERR(("wl_conf alloc failed\n"));
8316 goto init_priv_mem_out;
8319 (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
8320 if (unlikely(!wl->scan_req_int)) {
8321 WL_ERR(("Scan req alloc failed\n"));
8322 goto init_priv_mem_out;
8324 wl->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8325 if (unlikely(!wl->ioctl_buf)) {
8326 WL_ERR(("Ioctl buf alloc failed\n"));
8327 goto init_priv_mem_out;
8329 wl->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8330 if (unlikely(!wl->escan_ioctl_buf)) {
8331 WL_ERR(("Ioctl buf alloc failed\n"));
8332 goto init_priv_mem_out;
8334 wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
8335 if (unlikely(!wl->extra_buf)) {
8336 WL_ERR(("Extra buf alloc failed\n"));
8337 goto init_priv_mem_out;
8339 wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
8340 if (unlikely(!wl->iscan)) {
8341 WL_ERR(("Iscan buf alloc failed\n"));
8342 goto init_priv_mem_out;
8344 wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
8345 if (unlikely(!wl->pmk_list)) {
8346 WL_ERR(("pmk list alloc failed\n"));
8347 goto init_priv_mem_out;
8349 wl->sta_info = (void *)kzalloc(sizeof(*wl->sta_info), GFP_KERNEL);
8350 if (unlikely(!wl->sta_info)) {
8351 WL_ERR(("sta info alloc failed\n"));
8352 goto init_priv_mem_out;
8355 #if defined(STATIC_WL_PRIV_STRUCT)
8356 wl->conn_info = (void *)kzalloc(sizeof(*wl->conn_info), GFP_KERNEL);
8357 if (unlikely(!wl->conn_info)) {
8358 WL_ERR(("wl->conn_info alloc failed\n"));
8359 goto init_priv_mem_out;
8361 wl->ie = (void *)kzalloc(sizeof(*wl->ie), GFP_KERNEL);
8362 if (unlikely(!wl->ie)) {
8363 WL_ERR(("wl->ie alloc failed\n"));
8364 goto init_priv_mem_out;
8366 wl_init_escan_result_buf(wl);
8367 #endif /* STATIC_WL_PRIV_STRUCT */
8368 wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL);
8369 if (unlikely(!wl->afx_hdl)) {
8370 WL_ERR(("afx hdl alloc failed\n"));
8371 goto init_priv_mem_out;
8373 init_completion(&wl->act_frm_scan);
8374 init_completion(&wl->wait_next_af);
8376 INIT_WORK(&wl->afx_hdl->work, wl_cfg80211_afx_handler);
8381 wl_deinit_priv_mem(wl);
8386 static void wl_deinit_priv_mem(struct wl_priv *wl)
8388 kfree(wl->scan_results);
8389 wl->scan_results = NULL;
8392 kfree(wl->scan_req_int);
8393 wl->scan_req_int = NULL;
8394 kfree(wl->ioctl_buf);
8395 wl->ioctl_buf = NULL;
8396 kfree(wl->escan_ioctl_buf);
8397 wl->escan_ioctl_buf = NULL;
8398 kfree(wl->extra_buf);
8399 wl->extra_buf = NULL;
8402 kfree(wl->pmk_list);
8403 wl->pmk_list = NULL;
8404 kfree(wl->sta_info);
8405 wl->sta_info = NULL;
8406 #if defined(STATIC_WL_PRIV_STRUCT)
8407 kfree(wl->conn_info);
8408 wl->conn_info = NULL;
8411 wl_deinit_escan_result_buf(wl);
8412 #endif /* STATIC_WL_PRIV_STRUCT */
8414 cancel_work_sync(&wl->afx_hdl->work);
8420 kfree(wl->ap_info->wpa_ie);
8421 kfree(wl->ap_info->rsn_ie);
8422 kfree(wl->ap_info->wps_ie);
8428 static s32 wl_create_event_handler(struct wl_priv *wl)
8431 WL_DBG(("Enter \n"));
8433 /* Do not use DHD in cfg driver */
8434 wl->event_tsk.thr_pid = -1;
8436 PROC_START(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler");
8437 if (wl->event_tsk.thr_pid < 0)
8442 static void wl_destroy_event_handler(struct wl_priv *wl)
8444 if (wl->event_tsk.thr_pid >= 0)
8445 PROC_STOP(&wl->event_tsk);
8448 static void wl_term_iscan(struct wl_priv *wl)
8450 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
8452 if (wl->iscan_on && iscan->tsk) {
8453 iscan->state = WL_ISCAN_STATE_IDLE;
8454 WL_INFO(("SIGTERM\n"));
8455 send_sig(SIGTERM, iscan->tsk, 1);
8456 WL_DBG(("kthread_stop\n"));
8457 kthread_stop(iscan->tsk);
8462 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
8464 struct wl_priv *wl = iscan_to_wl(iscan);
8465 struct net_device *ndev = wl_to_prmry_ndev(wl);
8466 unsigned long flags;
8468 WL_DBG(("Enter \n"));
8469 if (!wl_get_drv_status(wl, SCANNING, ndev)) {
8470 wl_clr_drv_status(wl, SCANNING, ndev);
8471 WL_ERR(("Scan complete while device not scanning\n"));
8474 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8475 wl_clr_drv_status(wl, SCANNING, ndev);
8476 if (likely(wl->scan_request)) {
8477 cfg80211_scan_done(wl->scan_request, aborted);
8478 wl->scan_request = NULL;
8480 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8481 wl->iscan_kickstart = false;
8484 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
8486 if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
8487 WL_DBG(("wake up iscan\n"));
8496 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
8497 struct wl_scan_results **bss_list)
8499 struct wl_iscan_results list;
8500 struct wl_scan_results *results;
8501 struct wl_iscan_results *list_buf;
8504 WL_DBG(("Enter \n"));
8505 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
8506 list_buf = (struct wl_iscan_results *)iscan->scan_buf;
8507 results = &list_buf->results;
8508 results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
8509 results->version = 0;
8512 memset(&list, 0, sizeof(list));
8513 list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
8514 err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list,
8515 WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
8516 WL_ISCAN_BUF_MAX, NULL);
8517 if (unlikely(err)) {
8518 WL_ERR(("error (%d)\n", err));
8521 results->buflen = dtoh32(results->buflen);
8522 results->version = dtoh32(results->version);
8523 results->count = dtoh32(results->count);
8524 WL_DBG(("results->count = %d\n", results->count));
8525 WL_DBG(("results->buflen = %d\n", results->buflen));
8526 *status = dtoh32(list_buf->status);
8527 *bss_list = results;
8532 static s32 wl_iscan_done(struct wl_priv *wl)
8534 struct wl_iscan_ctrl *iscan = wl->iscan;
8537 iscan->state = WL_ISCAN_STATE_IDLE;
8538 mutex_lock(&wl->usr_sync);
8540 wl_notify_iscan_complete(iscan, false);
8541 mutex_unlock(&wl->usr_sync);
8546 static s32 wl_iscan_pending(struct wl_priv *wl)
8548 struct wl_iscan_ctrl *iscan = wl->iscan;
8551 /* Reschedule the timer */
8552 mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
8553 iscan->timer_on = 1;
8558 static s32 wl_iscan_inprogress(struct wl_priv *wl)
8560 struct wl_iscan_ctrl *iscan = wl->iscan;
8563 mutex_lock(&wl->usr_sync);
8565 wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
8566 mutex_unlock(&wl->usr_sync);
8567 /* Reschedule the timer */
8568 mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
8569 iscan->timer_on = 1;
8574 static s32 wl_iscan_aborted(struct wl_priv *wl)
8576 struct wl_iscan_ctrl *iscan = wl->iscan;
8579 iscan->state = WL_ISCAN_STATE_IDLE;
8580 mutex_lock(&wl->usr_sync);
8581 wl_notify_iscan_complete(iscan, true);
8582 mutex_unlock(&wl->usr_sync);
8587 static s32 wl_iscan_thread(void *data)
8589 struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
8590 struct wl_priv *wl = iscan_to_wl(iscan);
8594 allow_signal(SIGTERM);
8595 status = WL_SCAN_RESULTS_PARTIAL;
8596 while (likely(!down_interruptible(&iscan->sync))) {
8597 if (kthread_should_stop())
8599 if (iscan->timer_on) {
8600 del_timer_sync(&iscan->timer);
8601 iscan->timer_on = 0;
8603 mutex_lock(&wl->usr_sync);
8604 err = wl_get_iscan_results(iscan, &status, &wl->bss_list);
8605 if (unlikely(err)) {
8606 status = WL_SCAN_RESULTS_ABORTED;
8607 WL_ERR(("Abort iscan\n"));
8609 mutex_unlock(&wl->usr_sync);
8610 iscan->iscan_handler[status] (wl);
8612 if (iscan->timer_on) {
8613 del_timer_sync(&iscan->timer);
8614 iscan->timer_on = 0;
8616 WL_DBG(("was terminated\n"));
8621 static void wl_scan_timeout(unsigned long data)
8624 struct wl_priv *wl = (struct wl_priv *)data;
8626 if (!(wl->scan_request)) {
8627 WL_ERR(("timer expired but no scan request\n"));
8630 bzero(&msg, sizeof(wl_event_msg_t));
8631 WL_ERR(("timer expired\n"));
8633 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
8634 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
8635 msg.reason = 0xFFFFFFFF;
8636 wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL);
8638 /* Need to check it try to access SDIO */
8639 WL_ERR(("SCAN Timeout(ISCAN)\n"));
8640 wl_notify_iscan_complete(wl_to_iscan(wl), true);
8644 static void wl_iscan_timer(unsigned long data)
8646 struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
8649 iscan->timer_on = 0;
8650 WL_DBG(("timer expired\n"));
8651 wl_wakeup_iscan(iscan);
8655 static s32 wl_invoke_iscan(struct wl_priv *wl)
8657 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
8660 if (wl->iscan_on && !iscan->tsk) {
8661 iscan->state = WL_ISCAN_STATE_IDLE;
8662 sema_init(&iscan->sync, 0);
8663 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
8664 if (IS_ERR(iscan->tsk)) {
8665 WL_ERR(("Could not create iscan thread\n"));
8674 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan)
8676 memset(iscan->iscan_handler, 0, sizeof(iscan->iscan_handler));
8677 iscan->iscan_handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
8678 iscan->iscan_handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
8679 iscan->iscan_handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
8680 iscan->iscan_handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
8681 iscan->iscan_handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
8685 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
8686 unsigned long state,
8689 struct net_device *dev = ndev;
8690 struct wireless_dev *wdev = dev->ieee80211_ptr;
8691 struct wl_priv *wl = wlcfg_drv_priv;
8694 WL_DBG(("Enter \n"));
8695 if (!wdev || !wl || dev == wl_to_prmry_ndev(wl))
8700 int max_wait_timeout = 2;
8701 int max_wait_count = 100;
8702 unsigned long limit = jiffies + max_wait_timeout * HZ;
8703 while (work_pending(&wdev->cleanup_work)) {
8704 if (refcnt%5 == 0) {
8705 WL_ERR(("[NETDEV_DOWN] wait for "
8706 "complete of cleanup_work"
8707 " (%d th)\n", refcnt));
8709 if (!time_before(jiffies, limit)) {
8710 WL_ERR(("[NETDEV_DOWN] cleanup_work"
8711 " of CFG80211 is not"
8712 " completed in %d sec\n",
8716 if (refcnt >= max_wait_count) {
8717 WL_ERR(("[NETDEV_DOWN] cleanup_work"
8718 " of CFG80211 is not"
8719 " completed in %d loop\n",
8723 set_current_state(TASK_INTERRUPTIBLE);
8724 schedule_timeout(100);
8725 set_current_state(TASK_RUNNING);
8731 case NETDEV_UNREGISTER:
8732 /* after calling list_del_rcu(&wdev->list) */
8733 wl_dealloc_netinfo(wl, ndev);
8735 case NETDEV_GOING_DOWN:
8736 /* At NETDEV_DOWN state, wdev_cleanup_work work will be called.
8737 * In front of door, the function checks
8738 * whether current scan is working or not.
8739 * If the scanning is still working, wdev_cleanup_work call WARN_ON and
8740 * make the scan done forcibly.
8742 if (wl_get_drv_status(wl, SCANNING, dev)) {
8744 wl_notify_escan_complete(wl, dev, true, true);
8751 static struct notifier_block wl_cfg80211_netdev_notifier = {
8752 .notifier_call = wl_cfg80211_netdev_notifier_call,
8755 static void wl_cfg80211_scan_abort(struct wl_priv *wl)
8757 wl_scan_params_t *params = NULL;
8758 s32 params_size = 0;
8760 struct net_device *dev = wl_to_prmry_ndev(wl);
8762 /* Our scan params only need space for 1 channel and 0 ssids */
8763 params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size);
8764 if (params == NULL) {
8765 WL_ERR(("scan params allocation failed \n"));
8768 /* Do a scan abort to stop the driver's scan engine */
8769 err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
8771 WL_ERR(("scan abort failed \n"));
8777 static s32 wl_notify_escan_complete(struct wl_priv *wl,
8778 struct net_device *ndev,
8779 bool aborted, bool fw_abort)
8782 unsigned long flags;
8783 struct net_device *dev;
8785 WL_DBG(("Enter \n"));
8787 WL_ERR(("ndev is null\n"));
8792 if (wl->escan_info.ndev != ndev) {
8793 WL_ERR(("ndev is different %p %p\n", wl->escan_info.ndev, ndev));
8798 if (wl->scan_request) {
8799 dev = wl_to_prmry_ndev(wl);
8800 #if defined(WL_ENABLE_P2P_IF)
8801 if (wl->scan_request->dev != wl->p2p_net)
8802 dev = wl->scan_request->dev;
8803 #endif /* WL_ENABLE_P2P_IF */
8806 WL_DBG(("wl->scan_request is NULL may be internal scan."
8807 "doing scan_abort for ndev %p primary %p",
8808 ndev, wl_to_prmry_ndev(wl)));
8811 if (fw_abort && !in_atomic()) {
8812 wl_cfg80211_scan_abort(wl);
8815 if (timer_pending(&wl->scan_timeout))
8816 del_timer_sync(&wl->scan_timeout);
8817 #if defined(ESCAN_RESULT_PATCH)
8818 if (likely(wl->scan_request)) {
8819 wl->bss_list = wl_escan_get_buf(wl, aborted);
8822 #endif /* ESCAN_RESULT_PATCH */
8823 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8824 #ifdef WL_SCHED_SCAN
8825 if (wl->sched_scan_req && !wl->scan_request) {
8826 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
8828 cfg80211_sched_scan_results(wl->sched_scan_req->wiphy);
8829 wl->sched_scan_running = FALSE;
8830 wl->sched_scan_req = NULL;
8832 #endif /* WL_SCHED_SCAN */
8833 if (likely(wl->scan_request)) {
8834 cfg80211_scan_done(wl->scan_request, aborted);
8835 wl->scan_request = NULL;
8838 wl_clr_p2p_status(wl, SCANNING);
8839 wl_clr_drv_status(wl, SCANNING, dev);
8840 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8844 static s32 wl_escan_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8845 const wl_event_msg_t *e, void *data)
8848 s32 status = ntoh32(e->status);
8850 wl_escan_result_t *escan_result;
8851 wl_bss_info_t *bss = NULL;
8852 wl_scan_results_t *list;
8853 wifi_p2p_ie_t * p2p_ie;
8854 struct net_device *ndev = NULL;
8857 u8 *p2p_dev_addr = NULL;
8859 WL_DBG((" enter event type : %d, status : %d \n",
8860 ntoh32(e->event_type), ntoh32(e->status)));
8862 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8864 mutex_lock(&wl->usr_sync);
8865 /* P2P SCAN is coming from primary interface */
8866 if (wl_get_p2p_status(wl, SCANNING)) {
8867 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM))
8868 ndev = wl->afx_hdl->dev;
8870 ndev = wl->escan_info.ndev;
8873 if (!ndev || !wl->escan_on ||
8874 (!wl_get_drv_status(wl, SCANNING, ndev) &&
8875 !wl->sched_scan_running)) {
8876 WL_ERR(("escan is not ready ndev %p wl->escan_on %d"
8877 " drv_status 0x%x e_type %d e_states %d\n",
8878 ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev),
8879 ntoh32(e->event_type), ntoh32(e->status)));
8882 escan_result = (wl_escan_result_t *)data;
8884 if (status == WLC_E_STATUS_PARTIAL) {
8885 WL_INFO(("WLC_E_STATUS_PARTIAL \n"));
8886 if (!escan_result) {
8887 WL_ERR(("Invalid escan result (NULL pointer)\n"));
8890 if (dtoh16(escan_result->bss_count) != 1) {
8891 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
8894 bi = escan_result->bss_info;
8896 WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
8899 bi_length = dtoh32(bi->length);
8900 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
8901 WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
8904 if (wl_escan_check_sync_id(status, escan_result->sync_id,
8905 wl->escan_info.cur_sync_id) < 0)
8908 if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
8909 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
8910 WL_DBG(("Ignoring IBSS result\n"));
8915 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
8916 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
8917 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
8918 wl->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
8919 s32 channel = wf_chspec_ctlchan(
8920 wl_chspec_driver_to_host(bi->chanspec));
8922 if ((channel > MAXCHANNEL) || (channel <= 0))
8923 channel = WL_INVALID;
8925 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
8927 MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet),
8930 wl_clr_p2p_status(wl, SCANNING);
8931 wl->afx_hdl->peer_chan = channel;
8932 complete(&wl->act_frm_scan);
8937 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
8938 list = wl_escan_get_buf(wl, FALSE);
8939 if (scan_req_match(wl)) {
8940 /* p2p scan && allow only probe response */
8941 if ((wl->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
8942 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
8944 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
8945 bi->ie_length)) == NULL) {
8946 WL_ERR(("Couldn't find P2PIE in probe"
8947 " response/beacon\n"));
8951 for (i = 0; i < list->count; i++) {
8952 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
8955 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
8956 (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
8957 == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
8958 bi->SSID_len == bss->SSID_len &&
8959 !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
8961 /* do not allow beacon data to update
8962 *the data recd from a probe response
8964 if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
8965 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
8968 WL_DBG(("%s("MACDBG"), i=%d prev: RSSI %d"
8969 " flags 0x%x, new: RSSI %d flags 0x%x\n",
8970 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
8971 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
8973 if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
8974 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
8975 /* preserve max RSSI if the measurements are
8976 * both on-channel or both off-channel
8978 WL_SCAN(("%s("MACDBG"), same onchan"
8979 ", RSSI: prev %d new %d\n",
8980 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
8981 bss->RSSI, bi->RSSI));
8982 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
8983 } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
8984 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
8985 /* preserve the on-channel rssi measurement
8986 * if the new measurement is off channel
8988 WL_SCAN(("%s("MACDBG"), prev onchan"
8989 ", RSSI: prev %d new %d\n",
8990 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
8991 bss->RSSI, bi->RSSI));
8992 bi->RSSI = bss->RSSI;
8993 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
8995 if (dtoh32(bss->length) != bi_length) {
8996 u32 prev_len = dtoh32(bss->length);
8998 WL_SCAN(("bss info replacement"
8999 " is occured(bcast:%d->probresp%d)\n",
9000 bss->ie_length, bi->ie_length));
9001 WL_DBG(("%s("MACDBG"), replacement!(%d -> %d)\n",
9002 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9003 prev_len, bi_length));
9005 if (list->buflen - prev_len + bi_length
9007 WL_ERR(("Buffer is too small: keep the"
9008 " previous result of this AP\n"));
9009 /* Only update RSSI */
9010 bss->RSSI = bi->RSSI;
9011 bss->flags |= (bi->flags
9012 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
9016 if (i < list->count - 1) {
9017 /* memory copy required by this case only */
9018 memmove((u8 *)bss + bi_length,
9019 (u8 *)bss + prev_len,
9020 list->buflen - cur_len - prev_len);
9022 list->buflen -= prev_len;
9023 list->buflen += bi_length;
9025 list->version = dtoh32(bi->version);
9026 memcpy((u8 *)bss, (u8 *)bi, bi_length);
9029 cur_len += dtoh32(bss->length);
9031 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
9032 WL_ERR(("Buffer is too small: ignoring\n"));
9036 memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
9037 list->version = dtoh32(bi->version);
9038 list->buflen += bi_length;
9044 else if (status == WLC_E_STATUS_SUCCESS) {
9045 #if defined(P2P_DISCOVERY_WAR)
9046 if (scan_req_match(wl) && !wl->p2p->vif_created) {
9047 if (wldev_iovar_setint(wl_to_prmry_ndev(wl), "mpc", 1) < 0) {
9048 WL_ERR(("mpc enabling back failed\n"));
9051 #endif /* defined(P2P_DISCOVERY_WAR) */
9052 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9053 wl_escan_print_sync_id(status, wl->escan_info.cur_sync_id,
9054 escan_result->sync_id);
9056 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9057 WL_INFO(("ACTION FRAME SCAN DONE\n"));
9058 wl_clr_p2p_status(wl, SCANNING);
9059 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9060 if (wl->afx_hdl->peer_chan == WL_INVALID)
9061 complete(&wl->act_frm_scan);
9062 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9063 WL_INFO(("ESCAN COMPLETED\n"));
9064 wl->bss_list = wl_escan_get_buf(wl, FALSE);
9065 if (!scan_req_match(wl)) {
9066 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
9067 wl->bss_list->count));
9070 wl_notify_escan_complete(wl, ndev, false, false);
9072 wl_escan_increment_sync_id(wl, SCAN_BUF_NEXT);
9074 else if (status == WLC_E_STATUS_ABORT) {
9075 #if defined(P2P_DISCOVERY_WAR)
9076 if (scan_req_match(wl) && !wl->p2p->vif_created) {
9077 if (wldev_iovar_setint(wl_to_prmry_ndev(wl), "mpc", 1) < 0) {
9078 WL_ERR(("mpc enabling back failed\n"));
9081 #endif /* defined(P2P_DISCOVERY_WAR) */
9082 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9083 wl_escan_print_sync_id(status, escan_result->sync_id,
9084 wl->escan_info.cur_sync_id);
9085 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9086 WL_INFO(("ACTION FRAME SCAN DONE\n"));
9087 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9088 wl_clr_p2p_status(wl, SCANNING);
9089 if (wl->afx_hdl->peer_chan == WL_INVALID)
9090 complete(&wl->act_frm_scan);
9091 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9092 WL_INFO(("ESCAN ABORTED\n"));
9093 wl->bss_list = wl_escan_get_buf(wl, TRUE);
9094 if (!scan_req_match(wl)) {
9095 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
9096 wl->bss_list->count));
9099 wl_notify_escan_complete(wl, ndev, true, false);
9101 wl_escan_increment_sync_id(wl, SCAN_BUF_CNT);
9102 } else if (status == WLC_E_STATUS_NEWSCAN) {
9103 WL_ERR(("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", wl->scan_request));
9104 WL_ERR(("sync_id[%d], bss_count[%d]\n", escan_result->sync_id,
9105 escan_result->bss_count));
9106 } else if (status == WLC_E_STATUS_TIMEOUT) {
9107 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", wl->scan_request));
9108 WL_ERR(("escan_on[%d], reason[0x%x]\n", wl->escan_on, e->reason));
9109 if (e->reason == 0xFFFFFFFF) {
9110 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
9113 WL_ERR(("unexpected Escan Event %d : abort\n", status));
9114 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9115 wl_escan_print_sync_id(status, escan_result->sync_id,
9116 wl->escan_info.cur_sync_id);
9117 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9118 WL_INFO(("ACTION FRAME SCAN DONE\n"));
9119 wl_clr_p2p_status(wl, SCANNING);
9120 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9121 if (wl->afx_hdl->peer_chan == WL_INVALID)
9122 complete(&wl->act_frm_scan);
9123 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9124 wl->bss_list = wl_escan_get_buf(wl, TRUE);
9125 if (!scan_req_match(wl)) {
9126 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
9127 "scanned AP count=%d\n",
9128 wl->bss_list->count));
9131 wl_notify_escan_complete(wl, ndev, true, false);
9133 wl_escan_increment_sync_id(wl, 2);
9136 mutex_unlock(&wl->usr_sync);
9140 static void wl_cfg80211_concurrent_roam(struct wl_priv *wl, int enable)
9142 u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED);
9143 struct net_info *iter, *next;
9146 if (!wl->roamoff_on_concurrent)
9148 if (enable && connected_cnt > 1) {
9149 for_each_ndev(wl, iter, next) {
9150 /* Save the current roam setting */
9151 if ((err = wldev_iovar_getint(iter->ndev, "roam_off",
9152 (s32 *)&iter->roam_off)) != BCME_OK) {
9153 WL_ERR(("%s:Failed to get current roam setting err %d\n",
9154 iter->ndev->name, err));
9157 if ((err = wldev_iovar_setint(iter->ndev, "roam_off", 1)) != BCME_OK) {
9158 WL_ERR((" %s:failed to set roam_off : %d\n",
9159 iter->ndev->name, err));
9164 for_each_ndev(wl, iter, next) {
9165 if (iter->roam_off != WL_INVALID) {
9166 if ((err = wldev_iovar_setint(iter->ndev, "roam_off",
9167 iter->roam_off)) == BCME_OK)
9168 iter->roam_off = WL_INVALID;
9170 WL_ERR((" %s:failed to set roam_off : %d\n",
9171 iter->ndev->name, err));
9179 static void wl_cfg80211_determine_vsdb_mode(struct wl_priv *wl)
9181 struct net_info *iter, *next;
9184 u32 pre_ctl_chan = 0;
9185 u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED);
9186 wl->vsdb_mode = false;
9188 if (connected_cnt <= 1) {
9191 for_each_ndev(wl, iter, next) {
9194 if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) {
9195 if (wldev_iovar_getint(iter->ndev, "chanspec",
9196 (s32 *)&chanspec) == BCME_OK) {
9197 chanspec = wl_chspec_driver_to_host(chanspec);
9198 ctl_chan = wf_chspec_ctlchan(chanspec);
9199 wl_update_prof(wl, iter->ndev, NULL,
9200 &ctl_chan, WL_PROF_CHAN);
9202 if (!wl->vsdb_mode) {
9203 if (!pre_ctl_chan && ctl_chan)
9204 pre_ctl_chan = ctl_chan;
9205 else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
9206 wl->vsdb_mode = true;
9211 WL_ERR(("%s concurrency is enabled\n", wl->vsdb_mode ? "Multi Channel" : "Same Channel"));
9215 static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
9216 enum wl_status state, bool set)
9222 struct net_info *iter, *next;
9223 struct net_device *primary_dev = wl_to_prmry_ndev(wl);
9224 WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
9225 state, set, _net_info->pm_restore, _net_info->ndev->name));
9227 if (state != WL_STATUS_CONNECTED)
9229 mode = wl_get_mode_by_netdev(wl, _net_info->ndev);
9231 wl_cfg80211_concurrent_roam(wl, 1);
9233 if (mode == WL_MODE_AP) {
9235 if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
9236 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
9238 wl_cfg80211_determine_vsdb_mode(wl);
9239 if (wl->vsdb_mode || _net_info->pm_block) {
9240 /* Delete pm_enable_work */
9241 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_MAINTAIN);
9242 /* save PM_FAST in _net_info to restore this
9243 * if _net_info->pm_block is false
9245 if (!_net_info->pm_block && (mode == WL_MODE_BSS)) {
9246 _net_info->pm = PM_FAST;
9247 _net_info->pm_restore = true;
9250 for_each_ndev(wl, iter, next) {
9251 if (iter->pm_restore)
9253 /* Save the current power mode */
9254 err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm,
9255 sizeof(iter->pm), false);
9256 WL_DBG(("%s:power save %s\n", iter->ndev->name,
9257 iter->pm ? "enabled" : "disabled"));
9258 if (!err && iter->pm) {
9259 iter->pm_restore = true;
9263 for_each_ndev(wl, iter, next) {
9264 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9265 sizeof(pm), true)) != 0) {
9267 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9269 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9271 iter->ndev->ieee80211_ptr->ps = false;
9274 /* add PM Enable timer to go to power save mode
9275 * if supplicant control pm mode, it will be cleared or
9276 * updated by wl_cfg80211_set_power_mgmt() if not - for static IP & HW4 P2P,
9277 * PM will be configured when timer expired
9281 * before calling pm_enable_timer, we need to set PM -1 for all ndev
9285 for_each_ndev(wl, iter, next) {
9286 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9287 sizeof(pm), true)) != 0) {
9289 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9291 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9295 if (wl->pm_enable_work_on) {
9296 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
9299 wl->pm_enable_work_on = true;
9300 wl_add_remove_pm_enable_work(wl, TRUE, WL_HANDLER_NOTUSE);
9305 /* clear chan information when the net device is disconnected */
9306 wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
9307 wl_cfg80211_determine_vsdb_mode(wl);
9308 for_each_ndev(wl, iter, next) {
9309 if (iter->pm_restore && iter->pm) {
9310 WL_DBG(("%s:restoring power save %s\n",
9311 iter->ndev->name, (iter->pm ? "enabled" : "disabled")));
9312 err = wldev_ioctl(iter->ndev,
9313 WLC_SET_PM, &iter->pm, sizeof(iter->pm), true);
9314 if (unlikely(err)) {
9316 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9318 WL_ERR(("%s:error(%d)\n", iter->ndev->name, err));
9321 iter->pm_restore = 0;
9322 iter->ndev->ieee80211_ptr->ps = true;
9325 wl_cfg80211_concurrent_roam(wl, 0);
9329 static s32 wl_init_scan(struct wl_priv *wl)
9331 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
9335 iscan->dev = wl_to_prmry_ndev(wl);
9336 iscan->state = WL_ISCAN_STATE_IDLE;
9337 wl_init_iscan_handler(iscan);
9338 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
9339 init_timer(&iscan->timer);
9340 iscan->timer.data = (unsigned long) iscan;
9341 iscan->timer.function = wl_iscan_timer;
9342 sema_init(&iscan->sync, 0);
9343 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
9344 if (IS_ERR(iscan->tsk)) {
9345 WL_ERR(("Could not create iscan thread\n"));
9350 } else if (wl->escan_on) {
9351 wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
9352 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9353 wl_escan_init_sync_id(wl);
9355 /* Init scan_timeout timer */
9356 init_timer(&wl->scan_timeout);
9357 wl->scan_timeout.data = (unsigned long) wl;
9358 wl->scan_timeout.function = wl_scan_timeout;
9363 static s32 wl_init_priv(struct wl_priv *wl)
9365 struct wiphy *wiphy = wl_to_wiphy(wl);
9366 struct net_device *ndev = wl_to_prmry_ndev(wl);
9369 wl->scan_request = NULL;
9370 wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
9371 wl->iscan_on = false;
9372 wl->escan_on = true;
9373 wl->roam_on = false;
9374 wl->iscan_kickstart = false;
9375 wl->active_scan = true;
9376 wl->rf_blocked = false;
9377 wl->vsdb_mode = false;
9378 wl->wlfc_on = false;
9379 wl->roamoff_on_concurrent = true;
9380 /* register interested state */
9381 set_bit(WL_STATUS_CONNECTED, &wl->interrested_state);
9382 spin_lock_init(&wl->cfgdrv_lock);
9383 mutex_init(&wl->ioctl_buf_sync);
9384 init_waitqueue_head(&wl->netif_change_event);
9385 init_completion(&wl->send_af_done);
9386 init_completion(&wl->iface_disable);
9388 err = wl_init_priv_mem(wl);
9391 if (wl_create_event_handler(wl))
9393 wl_init_event_handler(wl);
9394 mutex_init(&wl->usr_sync);
9395 mutex_init(&wl->event_sync);
9396 err = wl_init_scan(wl);
9399 wl_init_conf(wl->conf);
9400 wl_init_prof(wl, ndev);
9402 DNGL_FUNC(dhd_cfg80211_init, (wl));
9407 static void wl_deinit_priv(struct wl_priv *wl)
9409 DNGL_FUNC(dhd_cfg80211_deinit, (wl));
9410 wl_destroy_event_handler(wl);
9413 del_timer_sync(&wl->scan_timeout);
9415 wl_deinit_priv_mem(wl);
9416 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
9419 #if defined(WL_ENABLE_P2P_IF)
9420 static s32 wl_cfg80211_attach_p2p(void)
9422 struct wl_priv *wl = wlcfg_drv_priv;
9424 WL_TRACE(("Enter \n"));
9426 if (wl_cfgp2p_register_ndev(wl) < 0) {
9427 WL_ERR(("P2P attach failed. \n"));
9434 static s32 wl_cfg80211_detach_p2p(void)
9436 struct wl_priv *wl = wlcfg_drv_priv;
9437 struct wireless_dev *wdev;
9439 WL_DBG(("Enter \n"));
9441 WL_ERR(("Invalid Ptr\n"));
9444 wdev = wl->p2p_wdev;
9447 WL_ERR(("Invalid Ptr\n"));
9451 wl_cfgp2p_unregister_ndev(wl);
9453 wl->p2p_wdev = NULL;
9455 WL_DBG(("Freeing 0x%08x \n", (unsigned int)wdev));
9460 #endif /* WL_ENABLE_P2P_IF */
9462 s32 wl_cfg80211_attach_post(struct net_device *ndev)
9464 struct wl_priv * wl = NULL;
9467 if (unlikely(!ndev)) {
9468 WL_ERR(("ndev is invaild\n"));
9471 wl = wlcfg_drv_priv;
9472 if (unlikely(!wl)) {
9473 WL_ERR(("wl is invaild\n"));
9476 if (!wl_get_drv_status(wl, READY, ndev)) {
9477 if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) {
9478 #if !defined(WL_ENABLE_P2P_IF)
9479 wl->wdev->wiphy->interface_modes |=
9480 (BIT(NL80211_IFTYPE_P2P_CLIENT)|
9481 BIT(NL80211_IFTYPE_P2P_GO));
9482 #endif /* !WL_ENABLE_P2P_IF */
9483 if ((err = wl_cfgp2p_init_priv(wl)) != 0)
9486 #if defined(WL_ENABLE_P2P_IF)
9488 /* Update MAC addr for p2p0 interface here. */
9489 memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
9490 wl->p2p_net->dev_addr[0] |= 0x02;
9491 WL_ERR(("%s: p2p_dev_addr="MACDBG "\n",
9493 MAC2STRDBG(wl->p2p_net->dev_addr)));
9495 WL_ERR(("p2p_net not yet populated."
9496 " Couldn't update the MAC Address for p2p0 \n"));
9499 #endif /* WL_ENABLE_P2P_IF */
9501 wl->p2p_supported = true;
9504 wl_set_drv_status(wl, READY, ndev);
9509 s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
9511 struct wireless_dev *wdev;
9518 WL_ERR(("ndev is invaild\n"));
9521 WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
9522 dev = wl_cfg80211_get_parent_dev();
9524 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
9525 if (unlikely(!wdev)) {
9526 WL_ERR(("Could not allocate wireless device\n"));
9529 err = wl_setup_wiphy(wdev, dev, data);
9530 if (unlikely(err)) {
9534 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
9535 wl = (struct wl_priv *)wiphy_priv(wdev->wiphy);
9538 INIT_LIST_HEAD(&wl->net_list);
9539 ndev->ieee80211_ptr = wdev;
9540 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
9541 wdev->netdev = ndev;
9542 wl->state_notifier = wl_notifier_change_state;
9543 err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS, PM_ENABLE);
9545 WL_ERR(("Failed to alloc net_info (%d)\n", err));
9546 goto cfg80211_attach_out;
9548 err = wl_init_priv(wl);
9550 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
9551 goto cfg80211_attach_out;
9554 err = wl_setup_rfkill(wl, TRUE);
9556 WL_ERR(("Failed to setup rfkill %d\n", err));
9557 goto cfg80211_attach_out;
9559 #ifdef DEBUGFS_CFG80211
9560 err = wl_setup_debugfs(wl);
9562 WL_ERR(("Failed to setup debugfs %d\n", err));
9563 goto cfg80211_attach_out;
9566 err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
9568 WL_ERR(("Failed to register notifierl %d\n", err));
9569 goto cfg80211_attach_out;
9571 #if defined(COEX_DHCP)
9572 err = wl_cfg80211_btcoex_init(wl);
9574 goto cfg80211_attach_out;
9577 wlcfg_drv_priv = wl;
9579 #if defined(WL_ENABLE_P2P_IF)
9580 err = wl_cfg80211_attach_p2p();
9582 goto cfg80211_attach_out;
9583 #endif /* WL_ENABLE_P2P_IF */
9587 cfg80211_attach_out:
9588 wl_setup_rfkill(wl, FALSE);
9593 void wl_cfg80211_detach(void *para)
9598 wl = wlcfg_drv_priv;
9602 #if defined(COEX_DHCP)
9603 wl_cfg80211_btcoex_deinit(wl);
9606 wl_setup_rfkill(wl, FALSE);
9607 #ifdef DEBUGFS_CFG80211
9608 wl_free_debugfs(wl);
9610 if (wl->p2p_supported) {
9611 if (timer_pending(&wl->p2p->listen_timer))
9612 del_timer_sync(&wl->p2p->listen_timer);
9613 wl_cfgp2p_deinit_priv(wl);
9616 #if defined(WL_CFG80211_P2P_DEV_IF)
9617 wl_cfgp2p_del_p2p_disc_if(wl->p2p_wdev);
9618 #elif defined(WL_ENABLE_P2P_IF)
9619 wl_cfg80211_detach_p2p();
9620 #endif /* WL_CFG80211_P2P_DEV_IF */
9622 wl_cfg80211_ibss_vsie_free(wl);
9624 wlcfg_drv_priv = NULL;
9625 wl_cfg80211_clear_parent_dev();
9627 /* PLEASE do NOT call any function after wl_free_wdev, the driver's private structure "wl",
9628 * which is the private part of wiphy, has been freed in wl_free_wdev !!!!!!!!!!!
9632 static void wl_wakeup_event(struct wl_priv *wl)
9634 if (wl->event_tsk.thr_pid >= 0) {
9635 DHD_OS_WAKE_LOCK(wl->pub);
9636 up(&wl->event_tsk.sema);
9640 #if (defined(WL_CFG80211_P2P_DEV_IF) || defined(WL_ENABLE_P2P_IF))
9641 static int wl_is_p2p_event(struct wl_event_q *e)
9644 /* We have to seperate out the P2P events received
9645 * on primary interface so that it can be send up
9646 * via p2p0 interface.
9648 case WLC_E_P2P_PROBREQ_MSG:
9649 case WLC_E_P2P_DISC_LISTEN_COMPLETE:
9650 case WLC_E_ACTION_FRAME_RX:
9651 case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE:
9652 case WLC_E_ACTION_FRAME_COMPLETE:
9654 if (e->emsg.ifidx != 0) {
9655 WL_TRACE(("P2P event(%d) on virtual interface(ifidx:%d)\n",
9656 e->etype, e->emsg.ifidx));
9657 /* We are only bothered about the P2P events received
9658 * on primary interface. For rest of them return false
9659 * so that it is sent over the interface corresponding
9664 WL_TRACE(("P2P event(%d) on interface(ifidx:%d)\n",
9665 e->etype, e->emsg.ifidx));
9671 WL_TRACE(("NON-P2P event(%d) on interface(ifidx:%d)\n",
9672 e->etype, e->emsg.ifidx));
9676 #endif /* BCMDONGLEHOST && (WL_CFG80211_P2P_DEV_IF || WL_ENABLE_P2P_IF) */
9678 static s32 wl_event_handler(void *data)
9680 struct wl_priv *wl = NULL;
9681 struct wl_event_q *e;
9682 tsk_ctl_t *tsk = (tsk_ctl_t *)data;
9683 bcm_struct_cfgdev *cfgdev = NULL;
9684 struct net_device *netdev;
9686 wl = (struct wl_priv *)tsk->parent;
9688 WL_ERR(("tsk Enter, tsk = 0x%08x\n", (unsigned int)tsk));
9690 while (down_interruptible (&tsk->sema) == 0) {
9691 SMP_RD_BARRIER_DEPENDS();
9692 if (tsk->terminated)
9694 while ((e = wl_deq_event(wl))) {
9695 WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx));
9696 /* All P2P device address related events comes on primary interface since
9697 * there is no corresponding bsscfg for P2P interface. Map it to p2p0
9700 #if defined(WL_CFG80211_P2P_DEV_IF)
9701 if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_wdev)) {
9702 cfgdev = wl_to_p2p_wdev(wl);
9704 netdev = dhd_idx2net((struct dhd_pub *)(wl->pub), e->emsg.ifidx);
9706 cfgdev = ndev_to_wdev(netdev);
9708 #elif defined(WL_ENABLE_P2P_IF)
9709 if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) {
9710 cfgdev = wl->p2p_net;
9712 cfgdev = dhd_idx2net((struct dhd_pub *)(wl->pub),
9715 #endif /* WL_CFG80211_P2P_DEV_IF */
9718 #if defined(WL_CFG80211_P2P_DEV_IF)
9719 cfgdev = wl_to_prmry_wdev(wl);
9720 #elif defined(WL_ENABLE_P2P_IF)
9721 cfgdev = wl_to_prmry_ndev(wl);
9722 #endif /* WL_CFG80211_P2P_DEV_IF */
9724 if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
9725 wl->evt_handler[e->etype] (wl, cfgdev, &e->emsg, e->edata);
9727 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
9731 DHD_OS_WAKE_UNLOCK(wl->pub);
9733 WL_ERR(("was terminated\n"));
9734 complete_and_exit(&tsk->completed, 0);
9739 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
9741 u32 event_type = ntoh32(e->event_type);
9742 struct wl_priv *wl = wlcfg_drv_priv;
9744 #if (WL_DBG_LEVEL > 0)
9745 s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
9746 wl_dbg_estr[event_type] : (s8 *) "Unknown";
9747 WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
9748 #endif /* (WL_DBG_LEVEL > 0) */
9750 if (event_type == WLC_E_PFN_NET_FOUND) {
9751 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
9753 else if (event_type == WLC_E_PFN_NET_LOST) {
9754 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
9757 if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
9758 wl_wakeup_event(wl);
9761 static void wl_init_eq(struct wl_priv *wl)
9763 wl_init_eq_lock(wl);
9764 INIT_LIST_HEAD(&wl->eq_list);
9767 static void wl_flush_eq(struct wl_priv *wl)
9769 struct wl_event_q *e;
9770 unsigned long flags;
9772 flags = wl_lock_eq(wl);
9773 while (!list_empty(&wl->eq_list)) {
9774 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
9775 list_del(&e->eq_list);
9778 wl_unlock_eq(wl, flags);
9782 * retrieve first queued event from head
9785 static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
9787 struct wl_event_q *e = NULL;
9788 unsigned long flags;
9790 flags = wl_lock_eq(wl);
9791 if (likely(!list_empty(&wl->eq_list))) {
9792 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
9793 list_del(&e->eq_list);
9795 wl_unlock_eq(wl, flags);
9801 * push event to tail of the queue
9805 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_event_msg_t *msg,
9808 struct wl_event_q *e;
9812 unsigned long flags;
9817 data_len = ntoh32(msg->datalen);
9818 evtq_size = sizeof(struct wl_event_q) + data_len;
9819 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
9820 e = kzalloc(evtq_size, aflags);
9822 WL_ERR(("event alloc failed\n"));
9826 memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
9828 memcpy(e->edata, data, data_len);
9829 flags = wl_lock_eq(wl);
9830 list_add_tail(&e->eq_list, &wl->eq_list);
9831 wl_unlock_eq(wl, flags);
9836 static void wl_put_event(struct wl_event_q *e)
9841 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype)
9847 case NL80211_IFTYPE_MONITOR:
9848 case NL80211_IFTYPE_WDS:
9849 WL_ERR(("type (%d) : currently we do not support this mode\n",
9853 case NL80211_IFTYPE_ADHOC:
9854 mode = WL_MODE_IBSS;
9856 case NL80211_IFTYPE_STATION:
9857 case NL80211_IFTYPE_P2P_CLIENT:
9861 case NL80211_IFTYPE_AP:
9862 case NL80211_IFTYPE_P2P_GO:
9868 WL_ERR(("invalid type (%d)\n", iftype));
9871 infra = htod32(infra);
9872 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
9873 if (unlikely(err)) {
9874 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
9878 wl_set_mode_by_netdev(wl, ndev, mode);
9883 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
9885 if (!ev || (event > WLC_E_LAST))
9888 if (ev->num < MAX_EVENT_BUF_NUM) {
9889 ev->event[ev->num].type = event;
9890 ev->event[ev->num].set = set;
9893 WL_ERR(("evenbuffer doesn't support > %u events. Update"
9894 " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
9899 s32 wl_cfg80211_apply_eventbuffer(
9900 struct net_device *ndev,
9902 wl_eventmsg_buf_t *ev)
9904 char eventmask[WL_EVENTING_MASK_LEN];
9906 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
9908 if (!ev || (!ev->num))
9911 mutex_lock(&wl->event_sync);
9913 /* Read event_msgs mask */
9914 bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
9916 ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
9917 if (unlikely(ret)) {
9918 WL_ERR(("Get event_msgs error (%d)\n", ret));
9921 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
9923 /* apply the set bits */
9924 for (i = 0; i < ev->num; i++) {
9925 if (ev->event[i].set)
9926 setbit(eventmask, ev->event[i].type);
9928 clrbit(eventmask, ev->event[i].type);
9931 /* Write updated Event mask */
9932 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
9934 ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
9935 if (unlikely(ret)) {
9936 WL_ERR(("Set event_msgs error (%d)\n", ret));
9940 mutex_unlock(&wl->event_sync);
9944 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
9946 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
9947 s8 eventmask[WL_EVENTING_MASK_LEN];
9949 struct wl_priv *wl = wlcfg_drv_priv;
9954 mutex_lock(&wl->event_sync);
9956 /* Setup event_msgs */
9957 bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
9959 err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
9960 if (unlikely(err)) {
9961 WL_ERR(("Get event_msgs error (%d)\n", err));
9964 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
9966 setbit(eventmask, event);
9968 clrbit(eventmask, event);
9970 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
9972 err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
9973 if (unlikely(err)) {
9974 WL_ERR(("Set event_msgs error (%d)\n", err));
9979 mutex_unlock(&wl->event_sync);
9983 static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
9985 struct net_device *dev = wl_to_prmry_ndev(wl);
9986 struct ieee80211_channel *band_chan_arr = NULL;
9987 wl_uint32_list_t *list;
9988 u32 i, j, index, n_2g, n_5g, band, channel, array_size;
9995 bool dfs_radar_disabled = FALSE;
9997 #define LOCAL_BUF_LEN 1024
9998 pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
10000 if (pbuf == NULL) {
10001 WL_ERR(("failed to allocate local buf\n"));
10004 list = (wl_uint32_list_t *)(void *)pbuf;
10005 list->count = htod32(WL_NUMCHANSPECS);
10008 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
10009 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync);
10011 WL_ERR(("get chanspecs failed with %d\n", err));
10015 #undef LOCAL_BUF_LEN
10017 list = (wl_uint32_list_t *)(void *)pbuf;
10018 band = array_size = n_2g = n_5g = 0;
10019 for (i = 0; i < dtoh32(list->count); i++) {
10022 ht40_allowed = false;
10023 c = (chanspec_t)dtoh32(list->element[i]);
10024 c = wl_chspec_driver_to_host(c);
10025 channel = CHSPEC_CHANNEL(c);
10026 if (CHSPEC_IS40(c)) {
10027 if (CHSPEC_SB_UPPER(c))
10028 channel += CH_10MHZ_APART;
10030 channel -= CH_10MHZ_APART;
10031 } else if (CHSPEC_IS80(c)) {
10032 WL_DBG(("HT80 center channel : %d\n", channel));
10035 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
10036 (channel <= CH_MAX_2G_CHANNEL)) {
10037 band_chan_arr = __wl_2ghz_channels;
10038 array_size = ARRAYSIZE(__wl_2ghz_channels);
10040 band = IEEE80211_BAND_2GHZ;
10041 ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false;
10042 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
10043 band_chan_arr = __wl_5ghz_a_channels;
10044 array_size = ARRAYSIZE(__wl_5ghz_a_channels);
10046 band = IEEE80211_BAND_5GHZ;
10047 ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
10049 WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
10052 if (!ht40_allowed && CHSPEC_IS40(c))
10054 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
10055 if (band_chan_arr[j].hw_value == channel) {
10064 if (index < array_size) {
10065 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
10066 band_chan_arr[index].center_freq =
10067 ieee80211_channel_to_frequency(channel);
10069 band_chan_arr[index].center_freq =
10070 ieee80211_channel_to_frequency(channel, band);
10072 band_chan_arr[index].hw_value = channel;
10074 if (CHSPEC_IS40(c) && ht40_allowed) {
10075 /* assuming the order is HT20, HT40 Upper,
10076 * HT40 lower from chanspecs
10078 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
10079 if (CHSPEC_SB_UPPER(c)) {
10080 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10081 band_chan_arr[index].flags &=
10082 ~IEEE80211_CHAN_NO_HT40;
10083 band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
10085 /* It should be one of
10086 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
10088 band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
10089 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10090 band_chan_arr[index].flags |=
10091 IEEE80211_CHAN_NO_HT40MINUS;
10094 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
10095 if (!dfs_radar_disabled) {
10096 if (band == IEEE80211_BAND_2GHZ)
10097 channel |= WL_CHANSPEC_BAND_2G;
10099 channel |= WL_CHANSPEC_BAND_5G;
10100 channel |= WL_CHANSPEC_BW_20;
10101 channel = wl_chspec_host_to_driver(channel);
10102 err = wldev_iovar_getint(dev, "per_chan_info", &channel);
10104 if (channel & WL_CHAN_RADAR)
10105 band_chan_arr[index].flags |=
10106 (IEEE80211_CHAN_RADAR |
10107 IEEE80211_CHAN_NO_IBSS);
10108 if (channel & WL_CHAN_PASSIVE)
10109 band_chan_arr[index].flags |=
10110 IEEE80211_CHAN_PASSIVE_SCAN;
10111 } else if (err == BCME_UNSUPPORTED) {
10112 dfs_radar_disabled = TRUE;
10113 WL_ERR(("does not support per_chan_info\n"));
10122 __wl_band_2ghz.n_channels = n_2g;
10123 __wl_band_5ghz_a.n_channels = n_5g;
10128 s32 wl_update_wiphybands(struct wl_priv *wl, bool notify)
10130 struct wiphy *wiphy;
10131 struct net_device *dev;
10138 bool rollback_lock = false;
10141 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
10144 wl = wlcfg_drv_priv;
10145 mutex_lock(&wl->usr_sync);
10146 rollback_lock = true;
10148 dev = wl_to_prmry_ndev(wl);
10150 memset(bandlist, 0, sizeof(bandlist));
10151 err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
10152 sizeof(bandlist), false);
10153 if (unlikely(err)) {
10154 WL_ERR(("error read bandlist (%d)\n", err));
10157 err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
10158 sizeof(s32), false);
10159 if (unlikely(err)) {
10160 WL_ERR(("error (%d)\n", err));
10164 err = wldev_iovar_getint(dev, "nmode", &nmode);
10165 if (unlikely(err)) {
10166 WL_ERR(("error reading nmode (%d)\n", err));
10168 /* For nmodeonly check bw cap */
10169 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
10170 if (unlikely(err)) {
10171 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
10175 err = wl_construct_reginfo(wl, bw_cap);
10177 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
10178 if (err != BCME_UNSUPPORTED)
10182 wiphy = wl_to_wiphy(wl);
10183 nband = bandlist[0];
10185 for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
10187 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
10188 bands[IEEE80211_BAND_5GHZ] =
10190 index = IEEE80211_BAND_5GHZ;
10191 if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
10192 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10194 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
10195 bands[IEEE80211_BAND_2GHZ] =
10197 index = IEEE80211_BAND_2GHZ;
10198 if (bw_cap == WLC_N_BW_40ALL)
10199 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10202 if ((index >= 0) && nmode) {
10203 bands[index]->ht_cap.cap |=
10204 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
10205 bands[index]->ht_cap.ht_supported = TRUE;
10206 bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
10207 bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
10208 /* An HT shall support all EQM rates for one spatial stream */
10209 bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
10214 wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
10215 wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
10217 /* check if any bands populated otherwise makes 2Ghz as default */
10218 if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
10219 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
10220 /* Setup 2Ghz band as default */
10221 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
10225 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
10229 mutex_unlock(&wl->usr_sync);
10233 static s32 __wl_cfg80211_up(struct wl_priv *wl)
10236 struct net_device *ndev = wl_to_prmry_ndev(wl);
10237 struct wireless_dev *wdev = ndev->ieee80211_ptr;
10241 err = dhd_config_dongle(wl, false);
10245 err = wl_config_ifmode(wl, ndev, wdev->iftype);
10246 if (unlikely(err && err != -EINPROGRESS)) {
10247 WL_ERR(("wl_config_ifmode failed\n"));
10249 err = wl_update_wiphybands(wl, true);
10250 if (unlikely(err)) {
10251 WL_ERR(("wl_update_wiphybands failed\n"));
10254 err = dhd_monitor_init(wl->pub);
10255 err = wl_invoke_iscan(wl);
10258 INIT_DELAYED_WORK(&wl->pm_enable_work, wl_cfg80211_work_handler);
10259 wl_set_drv_status(wl, READY, ndev);
10263 static s32 __wl_cfg80211_down(struct wl_priv *wl)
10266 unsigned long flags;
10267 struct net_info *iter, *next;
10268 struct net_device *ndev = wl_to_prmry_ndev(wl);
10269 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10270 struct net_device *p2p_net = wl->p2p_net;
10271 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10273 #ifdef PROP_TXSTATUS_VSDB
10274 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
10275 #endif /* PROP_TXSTATUS_VSDB */
10277 /* Delete pm_enable_work */
10278 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
10280 if (wl->p2p_supported) {
10281 wl_clr_p2p_status(wl, GO_NEG_PHASE);
10282 #ifdef PROP_TXSTATUS_VSDB
10283 if (wl->p2p->vif_created) {
10284 if (dhd-> op_mode != DHD_FLAG_IBSS_MODE &&
10285 dhd->wlfc_enabled && wl->wlfc_on) {
10286 dhd->wlfc_enabled = false;
10287 dhd_wlfc_deinit(dhd);
10288 if (dhd->plat_deinit)
10289 dhd->plat_deinit((void *)dhd);
10290 wl->wlfc_on = false;
10293 #endif /* PROP_TXSTATUS_VSDB */
10297 /* If primary BSS is operational (for e.g SoftAP), bring it down */
10298 if (!(wl_cfgp2p_find_idx(wl, ndev, &bssidx)) &&
10299 wl_cfgp2p_bss_isup(ndev, bssidx)) {
10300 if (wl_cfgp2p_bss(wl, ndev, bssidx, 0) < 0)
10301 WL_ERR(("BSS down failed \n"));
10304 /* Check if cfg80211 interface is already down */
10305 if (!wl_get_drv_status(wl, READY, ndev))
10306 return err; /* it is even not ready */
10307 for_each_ndev(wl, iter, next)
10308 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
10312 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10313 if (wl->scan_request) {
10314 cfg80211_scan_done(wl->scan_request, true);
10315 wl->scan_request = NULL;
10317 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10319 for_each_ndev(wl, iter, next) {
10320 wl_clr_drv_status(wl, READY, iter->ndev);
10321 wl_clr_drv_status(wl, SCANNING, iter->ndev);
10322 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
10323 wl_clr_drv_status(wl, CONNECTING, iter->ndev);
10324 wl_clr_drv_status(wl, CONNECTED, iter->ndev);
10325 wl_clr_drv_status(wl, DISCONNECTING, iter->ndev);
10326 wl_clr_drv_status(wl, AP_CREATED, iter->ndev);
10327 wl_clr_drv_status(wl, AP_CREATING, iter->ndev);
10329 wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype =
10330 NL80211_IFTYPE_STATION;
10331 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10333 dev_close(p2p_net);
10334 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10335 DNGL_FUNC(dhd_cfg80211_down, (wl));
10338 if (wl->p2p_supported)
10339 wl_cfgp2p_down(wl);
10340 dhd_monitor_uninit();
10345 s32 wl_cfg80211_up(void *para)
10347 struct wl_priv *wl;
10354 wl = wlcfg_drv_priv;
10356 if ((err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_VERSION, &val,
10357 sizeof(int), false) < 0)) {
10358 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
10362 if (val != WLC_IOCTL_VERSION && val != 1) {
10363 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
10364 val, WLC_IOCTL_VERSION));
10365 return BCME_VERSION;
10367 ioctl_version = val;
10368 WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
10370 mutex_lock(&wl->usr_sync);
10371 dhd = (dhd_pub_t *)(wl->pub);
10372 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
10373 err = wl_cfg80211_attach_post(wl_to_prmry_ndev(wl));
10377 err = __wl_cfg80211_up(wl);
10379 WL_ERR(("__wl_cfg80211_up failed\n"));
10380 mutex_unlock(&wl->usr_sync);
10384 /* Private Event to Supplicant with indication that chip hangs */
10385 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
10387 struct wl_priv *wl;
10388 wl = wlcfg_drv_priv;
10390 WL_ERR(("In : chip crash eventing\n"));
10391 wl_add_remove_pm_enable_work(wl, FALSE, WL_HANDLER_DEL);
10392 cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL);
10399 s32 wl_cfg80211_down(void *para)
10401 struct wl_priv *wl;
10406 wl = wlcfg_drv_priv;
10407 mutex_lock(&wl->usr_sync);
10408 err = __wl_cfg80211_down(wl);
10409 mutex_unlock(&wl->usr_sync);
10414 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item)
10416 unsigned long flags;
10418 struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10422 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10425 rptr = &profile->sec;
10428 rptr = &profile->active;
10430 case WL_PROF_BSSID:
10431 rptr = profile->bssid;
10434 rptr = &profile->ssid;
10437 rptr = &profile->channel;
10440 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10442 WL_ERR(("invalid item (%d)\n", item));
10447 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
10448 const wl_event_msg_t *e, void *data, s32 item)
10451 struct wlc_ssid *ssid;
10452 unsigned long flags;
10453 struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10457 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10460 ssid = (wlc_ssid_t *) data;
10461 memset(profile->ssid.SSID, 0,
10462 sizeof(profile->ssid.SSID));
10463 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
10464 profile->ssid.SSID_len = ssid->SSID_len;
10466 case WL_PROF_BSSID:
10468 memcpy(profile->bssid, data, ETHER_ADDR_LEN);
10470 memset(profile->bssid, 0, ETHER_ADDR_LEN);
10473 memcpy(&profile->sec, data, sizeof(profile->sec));
10476 profile->active = *(bool *)data;
10478 case WL_PROF_BEACONINT:
10479 profile->beacon_interval = *(u16 *)data;
10481 case WL_PROF_DTIMPERIOD:
10482 profile->dtim_period = *(u8 *)data;
10485 profile->channel = *(u32*)data;
10491 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10493 if (err == -EOPNOTSUPP)
10494 WL_ERR(("unsupported item (%d)\n", item));
10499 void wl_cfg80211_dbg_level(u32 level)
10502 * prohibit to change debug level
10503 * by insmod parameter.
10504 * eventually debug level will be configured
10505 * in compile time by using CONFIG_XXX
10507 /* wl_dbg_level = level; */
10510 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev)
10512 return wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS;
10515 static __used bool wl_is_ibssstarter(struct wl_priv *wl)
10517 return wl->ibss_starter;
10520 static void wl_rst_ie(struct wl_priv *wl)
10522 struct wl_ie *ie = wl_to_ie(wl);
10527 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
10529 struct wl_ie *ie = wl_to_ie(wl);
10532 if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
10533 WL_ERR(("ei crosses buffer boundary\n"));
10536 ie->buf[ie->offset] = t;
10537 ie->buf[ie->offset + 1] = l;
10538 memcpy(&ie->buf[ie->offset + 2], v, l);
10539 ie->offset += l + 2;
10544 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size)
10547 ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
10550 if (ssidie[1] != bi->SSID_len) {
10552 WL_ERR(("%s: Wrong SSID len: %d != %d\n",
10553 __FUNCTION__, ssidie[1], bi->SSID_len));
10556 memmove(ssidie + bi->SSID_len + 2, ssidie + 2, *ie_size - (ssidie + 2 - ie_stream));
10557 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
10558 *ie_size = *ie_size + bi->SSID_len;
10559 ssidie[1] = bi->SSID_len;
10562 if (*(ssidie + 2) == '\0')
10563 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
10567 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size)
10569 struct wl_ie *ie = wl_to_ie(wl);
10572 if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
10573 WL_ERR(("ei_stream crosses buffer boundary\n"));
10576 memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
10577 ie->offset += ie_size;
10582 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size)
10584 struct wl_ie *ie = wl_to_ie(wl);
10587 if (unlikely(ie->offset > dst_size)) {
10588 WL_ERR(("dst_size is not enough\n"));
10591 memcpy(dst, &ie->buf[0], ie->offset);
10596 static u32 wl_get_ielen(struct wl_priv *wl)
10598 struct wl_ie *ie = wl_to_ie(wl);
10603 static void wl_link_up(struct wl_priv *wl)
10605 wl->link_up = true;
10608 static void wl_link_down(struct wl_priv *wl)
10610 struct wl_connect_info *conn_info = wl_to_conn(wl);
10613 wl->link_up = false;
10614 conn_info->req_ie_len = 0;
10615 conn_info->resp_ie_len = 0;
10618 static unsigned long wl_lock_eq(struct wl_priv *wl)
10620 unsigned long flags;
10622 spin_lock_irqsave(&wl->eq_lock, flags);
10626 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags)
10628 spin_unlock_irqrestore(&wl->eq_lock, flags);
10631 static void wl_init_eq_lock(struct wl_priv *wl)
10633 spin_lock_init(&wl->eq_lock);
10636 static void wl_delay(u32 ms)
10638 if (in_atomic() || (ms < jiffies_to_msecs(1))) {
10639 OSL_DELAY(ms*1000);
10645 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
10647 struct wl_priv *wl = wlcfg_drv_priv;
10648 struct ether_addr p2pif_addr;
10649 struct ether_addr primary_mac;
10652 if (!p2p_is_on(wl)) {
10653 get_primary_mac(wl, &primary_mac);
10654 wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr);
10656 memcpy(p2pdev_addr->octet,
10657 wl->p2p->dev_addr.octet, ETHER_ADDR_LEN);
10663 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
10665 struct wl_priv *wl;
10667 wl = wlcfg_drv_priv;
10669 return wl_cfgp2p_set_p2p_noa(wl, net, buf, len);
10672 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
10674 struct wl_priv *wl;
10675 wl = wlcfg_drv_priv;
10677 return wl_cfgp2p_get_p2p_noa(wl, net, buf, len);
10680 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
10682 struct wl_priv *wl;
10683 wl = wlcfg_drv_priv;
10685 return wl_cfgp2p_set_p2p_ps(wl, net, buf, len);
10688 s32 wl_cfg80211_channel_to_freq(u32 channel)
10692 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
10693 freq = ieee80211_channel_to_frequency(channel);
10697 if (channel <= CH_MAX_2G_CHANNEL)
10698 band = IEEE80211_BAND_2GHZ;
10700 band = IEEE80211_BAND_5GHZ;
10701 freq = ieee80211_channel_to_frequency(channel, band);
10710 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
10711 const wl_event_msg_t *e, void *data) {
10713 struct net_device *ndev = NULL;
10714 u32 reason = ntoh32(e->reason);
10717 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
10720 case WLC_E_TDLS_PEER_DISCOVERED :
10721 msg = " TDLS PEER DISCOVERD ";
10723 case WLC_E_TDLS_PEER_CONNECTED :
10724 msg = " TDLS PEER CONNECTED ";
10726 case WLC_E_TDLS_PEER_DISCONNECTED :
10727 msg = "TDLS PEER DISCONNECTED ";
10731 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
10732 (wl_to_prmry_ndev(wl) == ndev) ? "primary" : "secondary"));
10737 #endif /* WLTDLS */
10739 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || 0
10741 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
10742 u8 *peer, enum nl80211_tdls_operation oper)
10746 struct wl_priv *wl = wlcfg_drv_priv;
10749 return ERR_PTR(-EINVAL);
10752 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
10753 memset(&info, 0, sizeof(tdls_iovar_t));
10755 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
10757 case NL80211_TDLS_DISCOVERY_REQ:
10758 if (!dhd->tdls_enable)
10759 ret = dhd_tdls_enable_disable(dhd, 1);
10762 info.mode = TDLS_MANUAL_EP_DISCOVERY;
10764 case NL80211_TDLS_SETUP:
10765 info.mode = TDLS_MANUAL_EP_CREATE;
10767 case NL80211_TDLS_TEARDOWN:
10768 info.mode = TDLS_MANUAL_EP_DELETE;
10771 WL_ERR(("Unsupported operation : %d\n", oper));
10774 ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
10775 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
10777 WL_ERR(("tdls_endpoint error %d\n", ret));
10780 #endif /* WLTDLS */
10785 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
10786 enum wl_management_type type)
10788 struct wl_priv *wl;
10789 struct net_device *ndev = NULL;
10790 struct ether_addr primary_mac;
10794 wl = wlcfg_drv_priv;
10796 if (wl_get_drv_status(wl, AP_CREATING, net)) {
10797 /* Vendor IEs should be set to FW
10798 * after SoftAP interface is brought up
10801 } else if (wl_get_drv_status(wl, AP_CREATED, net)) {
10804 } else if (wl->p2p) {
10805 net = ndev_to_wlc_ndev(net, wl);
10806 if (!wl->p2p->on) {
10807 get_primary_mac(wl, &primary_mac);
10808 wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr,
10809 &wl->p2p->int_addr);
10810 /* In case of p2p_listen command, supplicant send remain_on_channel
10811 * without turning on P2P
10815 ret = wl_cfgp2p_enable_discovery(wl, net, NULL, 0);
10817 if (unlikely(ret)) {
10821 if (net != wl_to_prmry_ndev(wl)) {
10822 if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) {
10823 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
10824 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
10827 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
10828 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
10831 if (ndev != NULL) {
10834 pktflag = VNDR_IE_BEACON_FLAG;
10836 case WL_PROBE_RESP:
10837 pktflag = VNDR_IE_PRBRSP_FLAG;
10839 case WL_ASSOC_RESP:
10840 pktflag = VNDR_IE_ASSOCRSP_FLAG;
10844 ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
10850 #ifdef WL_SUPPORT_AUTO_CHANNEL
10852 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
10855 s32 ret = BCME_ERROR;
10856 struct wl_priv *wl = wlcfg_drv_priv;
10858 /* Disable mpc, to avoid automatic interface down. */
10861 ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
10862 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
10863 &wl->ioctl_buf_sync);
10865 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
10869 /* Set interface up, explicitly. */
10872 ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
10874 WL_ERR(("set interface up failed, error = %d\n", ret));
10878 /* Stop all scan explicitly, till auto channel selection complete. */
10879 wl_set_drv_status(wl, SCANNING, ndev);
10880 ret = wl_notify_escan_complete(wl, ndev, true, true);
10882 WL_ERR(("set scan abort failed, error = %d\n", ret));
10891 wl_cfg80211_valid_chanspec_p2p(chanspec_t chanspec)
10893 bool valid = false;
10895 /* channel 1 to 14 */
10896 if ((chanspec >= 0x2b01) && (chanspec <= 0x2b0e)) {
10899 /* channel 36 to 48 */
10900 else if ((chanspec >= 0x1b24) && (chanspec <= 0x1b30)) {
10903 /* channel 149 to 161 */
10904 else if ((chanspec >= 0x1b95) && (chanspec <= 0x1ba1)) {
10909 WL_INFO(("invalid P2P chanspec, channel = %d, chanspec = %04x\n",
10910 CHSPEC_CHANNEL(chanspec), chanspec));
10917 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
10919 s32 ret = BCME_ERROR;
10920 struct wl_priv *wl = NULL;
10921 wl_uint32_list_t *list = NULL;
10922 chanspec_t chanspec = 0;
10924 memset(buf, 0, buflen);
10926 wl = wlcfg_drv_priv;
10927 list = (wl_uint32_list_t *)buf;
10928 list->count = htod32(WL_NUMCHANSPECS);
10930 /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
10931 chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
10932 WL_CHANSPEC_CTL_SB_NONE);
10933 chanspec = wl_chspec_host_to_driver(chanspec);
10935 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
10936 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
10938 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
10945 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
10948 s32 ret = BCME_ERROR;
10951 struct wl_priv *wl = NULL;
10952 wl_uint32_list_t *list = NULL;
10953 chanspec_t chanspec = 0;
10955 memset(buf, 0, buflen);
10957 wl = wlcfg_drv_priv;
10958 list = (wl_uint32_list_t *)buf;
10959 list->count = htod32(WL_NUMCHANSPECS);
10961 /* Restrict channels to 5GHz, 20MHz BW, no SB. */
10962 chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
10963 WL_CHANSPEC_CTL_SB_NONE);
10964 chanspec = wl_chspec_host_to_driver(chanspec);
10966 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
10967 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
10969 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
10973 /* Skip DFS and inavlid P2P channel. */
10974 for (i = 0, j = 0; i < dtoh32(list->count); i++) {
10975 chanspec = (chanspec_t) dtoh32(list->element[i]);
10976 channel = CHSPEC_CHANNEL(chanspec);
10978 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
10980 WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
10984 if (CHANNEL_IS_RADAR(channel) ||
10985 !(wl_cfg80211_valid_chanspec_p2p(chanspec))) {
10988 list->element[j] = list->element[i];
11001 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
11004 s32 ret = BCME_ERROR;
11008 /* Start auto channel selection scan. */
11009 ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
11011 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
11016 /* Wait for auto channel selection, worst case possible delay is 5250ms. */
11017 retry = CHAN_SEL_RETRY_COUNT;
11020 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
11022 ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
11024 if ((ret == 0) && (dtoh32(chosen) != 0)) {
11025 *channel = (u16)(chosen & 0x00FF);
11026 WL_INFO(("selected channel = %d\n", *channel));
11029 WL_INFO(("attempt = %d, ret = %d, chosen = %d\n",
11030 (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
11034 WL_ERR(("failure, auto channel selection timed out\n"));
11044 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
11047 s32 ret = BCME_ERROR;
11048 struct wl_priv *wl = wlcfg_drv_priv;
11050 /* Clear scan stop driver status. */
11051 wl_clr_drv_status(wl, SCANNING, ndev);
11053 /* Enable mpc back to 1, irrespective of initial state. */
11056 ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
11057 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
11058 &wl->ioctl_buf_sync);
11060 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
11067 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
11070 s32 ret = BCME_ERROR;
11073 struct wl_priv *wl = NULL;
11074 struct net_device *ndev = NULL;
11076 memset(cmd, 0, total_len);
11078 buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
11080 WL_ERR(("failed to allocate chanspec buffer\n"));
11085 * Always use primary interface, irrespective of interface on which
11088 wl = wlcfg_drv_priv;
11089 ndev = wl_to_prmry_ndev(wl);
11092 * Make sure that FW and driver are in right state to do auto channel
11095 ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
11097 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
11101 /* Best channel selection in 2.4GHz band. */
11102 ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
11104 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
11108 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
11111 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
11115 if (CHANNEL_IS_2G(channel)) {
11116 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
11118 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
11122 sprintf(pos, "%04d ", channel);
11125 /* Best channel selection in 5GHz band. */
11126 ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
11128 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
11132 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
11135 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
11139 if (CHANNEL_IS_5G(channel)) {
11140 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
11142 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
11146 sprintf(pos, "%04d ", channel);
11149 /* Set overall best channel same as 5GHz best channel. */
11150 sprintf(pos, "%04d ", channel);
11158 /* Restore FW and driver back to normal state. */
11159 ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
11161 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
11164 return (pos - cmd);
11166 #endif /* WL_SUPPORT_AUTO_CHANNEL */
11168 static const struct rfkill_ops wl_rfkill_ops = {
11169 .set_block = wl_rfkill_set
11172 static int wl_rfkill_set(void *data, bool blocked)
11174 struct wl_priv *wl = (struct wl_priv *)data;
11176 WL_DBG(("Enter \n"));
11177 WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
11182 wl->rf_blocked = blocked;
11187 static int wl_setup_rfkill(struct wl_priv *wl, bool setup)
11191 WL_DBG(("Enter \n"));
11195 wl->rfkill = rfkill_alloc("brcmfmac-wifi",
11196 wl_cfg80211_get_parent_dev(),
11197 RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)wl);
11204 err = rfkill_register(wl->rfkill);
11207 rfkill_destroy(wl->rfkill);
11214 rfkill_unregister(wl->rfkill);
11215 rfkill_destroy(wl->rfkill);
11222 #ifdef DEBUGFS_CFG80211
11224 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
11225 * to turn on SCAN and DBG log.
11226 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
11227 * To see current setting of debug level,
11228 * cat /sys/kernel/debug/dhd/debug_level
11231 wl_debuglevel_write(struct file *file, const char __user *userbuf,
11232 size_t count, loff_t *ppos)
11234 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
11235 char *params, *token, *colon;
11236 uint i, tokens, log_on = 0;
11237 memset(tbuf, 0, sizeof(tbuf));
11238 memset(sublog, 0, sizeof(sublog));
11239 if (copy_from_user(&tbuf, userbuf, min_t(size_t, sizeof(tbuf), count)))
11243 colon = strchr(params, '\n');
11246 while ((token = strsep(¶ms, " ")) != NULL) {
11247 memset(sublog, 0, sizeof(sublog));
11248 if (token == NULL || !*token)
11250 if (*token == '\0')
11252 colon = strchr(token, ':');
11253 if (colon != NULL) {
11256 tokens = sscanf(token, "%s %u", sublog, &log_on);
11261 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
11262 if (!strncmp(sublog, sublogname_map[i].sublogname,
11263 strlen(sublogname_map[i].sublogname))) {
11266 (sublogname_map[i].log_level);
11269 ~(sublogname_map[i].log_level);
11273 WL_ERR(("%s: can't parse '%s' as a "
11274 "SUBMODULE:LEVEL (%d tokens)\n",
11275 tbuf, token, tokens));
11283 wl_debuglevel_read(struct file *file, char __user *user_buf,
11284 size_t count, loff_t *ppos)
11287 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
11289 memset(tbuf, 0, sizeof(tbuf));
11291 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
11292 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
11293 sublogname_map[i].sublogname,
11294 (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
11297 return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
11300 static const struct file_operations fops_debuglevel = {
11302 .write = wl_debuglevel_write,
11303 .read = wl_debuglevel_read,
11304 .owner = THIS_MODULE,
11308 static s32 wl_setup_debugfs(struct wl_priv *wl)
11311 struct dentry *_dentry;
11314 wl->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
11315 if (!wl->debugfs || IS_ERR(wl->debugfs)) {
11316 if (wl->debugfs == ERR_PTR(-ENODEV))
11317 WL_ERR(("Debugfs is not enabled on this kernel\n"));
11319 WL_ERR(("Can not create debugfs directory\n"));
11320 wl->debugfs = NULL;
11324 _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
11325 wl->debugfs, wl, &fops_debuglevel);
11326 if (!_dentry || IS_ERR(_dentry)) {
11327 WL_ERR(("failed to create debug_level debug file\n"));
11328 wl_free_debugfs(wl);
11333 static s32 wl_free_debugfs(struct wl_priv *wl)
11338 debugfs_remove_recursive(wl->debugfs);
11339 wl->debugfs = NULL;
11342 #endif /* DEBUGFS_CFG80211 */
11344 struct device *wl_cfg80211_get_parent_dev(void)
11346 return cfg80211_parent_dev;
11349 void wl_cfg80211_set_parent_dev(void *dev)
11351 cfg80211_parent_dev = dev;
11354 static void wl_cfg80211_clear_parent_dev(void)
11356 cfg80211_parent_dev = NULL;
11359 void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac)
11361 wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL,
11362 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, 0, &wl->ioctl_buf_sync);
11363 memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN);
11365 static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role)
11367 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
11368 if (((dev_role == NL80211_IFTYPE_AP) &&
11369 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
11370 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
11371 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
11373 WL_ERR(("device role select failed\n"));
11379 int wl_cfg80211_do_driver_init(struct net_device *net)
11381 struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net);
11383 if (!wl || !wl->wdev)
11386 if (dhd_do_driver_init(wl->wdev->netdev) < 0)
11392 void wl_cfg80211_enable_trace(bool set, u32 level)
11395 wl_dbg_level = level & WL_DBG_LEVEL;
11397 wl_dbg_level |= (WL_DBG_LEVEL & level);
11399 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
11402 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
11403 bcm_struct_cfgdev *cfgdev, u64 cookie)
11405 /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
11406 * is passed with CMD_FRAME. This callback is supposed to cancel
11407 * the OFFCHANNEL Wait. Since we are already taking care of that
11408 * with the tx_mgmt logic, do nothing here.
11413 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
11418 static void wl_cfg80211_work_handler(struct work_struct * work)
11420 struct wl_priv *wl = NULL;
11421 struct net_info *iter, *next;
11425 wl = container_of(work, struct wl_priv, pm_enable_work.work);
11426 WL_DBG(("Enter \n"));
11427 if (wl->pm_enable_work_on) {
11428 wl->pm_enable_work_on = false;
11429 for_each_ndev(wl, iter, next) {
11430 if (!wl_get_drv_status(wl, CONNECTED, iter->ndev) ||
11431 (wl_get_mode_by_netdev(wl, iter->ndev) != WL_MODE_BSS))
11434 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
11435 &pm, sizeof(pm), true)) != 0) {
11436 if (err == -ENODEV)
11437 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
11439 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
11441 iter->ndev->ieee80211_ptr->ps = true;
11448 wl_get_action_category(void *frame, u32 frame_len)
11451 u8 *ptr = (u8 *)frame;
11453 return DOT11_ACTION_CAT_ERR_MASK;
11454 if (frame_len < DOT11_ACTION_HDR_LEN)
11455 return DOT11_ACTION_CAT_ERR_MASK;
11456 category = ptr[DOT11_ACTION_CAT_OFF];
11457 WL_INFO(("Action Category: %d\n", category));
11462 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
11464 u8 *ptr = (u8 *)frame;
11465 if (frame == NULL || ret_action == NULL)
11467 if (frame_len < DOT11_ACTION_HDR_LEN)
11469 if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
11471 *ret_action = ptr[DOT11_ACTION_ACT_OFF];
11472 WL_INFO(("Public Action : %d\n", *ret_action));
11477 wl_ccx_s69_response(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
11478 const wl_event_msg_t *e, void *data)
11480 struct net_device *ndev = NULL;
11481 u32 event = ntoh32(e->event_type);
11482 u32 datalen = ntoh32(e->datalen);
11485 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
11486 err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
11490 #endif /* BCMCCX_S69 */