3 * Linux cfg80211 driver
5 * $Copyright Open Broadcom Corporation$
7 * $Id: wl_cfg80211.c 419844 2013-08-23 00:07:03Z $
13 #include <linux/kernel.h>
16 #include <bcmwifi_channels.h>
17 #include <bcmendian.h>
18 #include <proto/ethernet.h>
19 #include <proto/802.11.h>
20 #include <linux/if_arp.h>
21 #include <asm/uaccess.h>
23 #include <dngl_stats.h>
27 #include <dhd_cfg80211.h>
30 #endif /* PNO_SUPPORT */
32 #include <proto/ethernet.h>
33 #include <linux/kernel.h>
34 #include <linux/kthread.h>
35 #include <linux/netdevice.h>
36 #include <linux/sched.h>
37 #include <linux/etherdevice.h>
38 #include <linux/wireless.h>
39 #include <linux/ieee80211.h>
40 #include <linux/wait.h>
41 #include <net/cfg80211.h>
42 #include <net/rtnetlink.h>
45 #include <wldev_common.h>
46 #include <wl_cfg80211.h>
47 #include <wl_cfgp2p.h>
48 #include <wl_android.h>
49 #include <dhd_config.h>
56 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
57 #error You should enable 'WL_ENABLE_P2P_IF' or 'WL_CFG80211_P2P_DEV_IF' \
58 according to Kernel version and is supported only in Android-JB
59 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
63 /* these items should evetually go into wireless.h of the linux system headfile dir */
64 #ifndef IW_ENCODE_ALG_SM4
65 #define IW_ENCODE_ALG_SM4 0x20
68 #ifndef IW_AUTH_WAPI_ENABLED
69 #define IW_AUTH_WAPI_ENABLED 0x20
72 #ifndef IW_AUTH_WAPI_VERSION_1
73 #define IW_AUTH_WAPI_VERSION_1 0x00000008
76 #ifndef IW_AUTH_CIPHER_SMS4
77 #define IW_AUTH_CIPHER_SMS4 0x00000020
80 #ifndef IW_AUTH_KEY_MGMT_WAPI_PSK
81 #define IW_AUTH_KEY_MGMT_WAPI_PSK 4
84 #ifndef IW_AUTH_KEY_MGMT_WAPI_CERT
85 #define IW_AUTH_KEY_MGMT_WAPI_CERT 8
87 #endif /* BCMWAPI_WPI */
90 #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED))
91 #else /* BCMWAPI_WPI */
92 #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
93 #endif /* BCMWAPI_WPI */
95 static struct device *cfg80211_parent_dev = NULL;
96 struct wl_priv *wlcfg_drv_priv = NULL;
97 u32 wl_dbg_level = WL_DBG_ERR;
99 #define MAX_WAIT_TIME 1500
102 /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
103 #define DEFAULT_SLEEP_TIME_VSDB 120
104 #define OFF_CHAN_TIME_THRESHOLD_MS 200
105 #define AF_RETRY_DELAY_TIME 40
107 /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
108 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl) \
110 if (wl_get_drv_status(wl, CONNECTED, wl_to_prmry_ndev(wl)) || \
111 wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) { \
112 OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB); \
116 /* if not VSDB, do nothing */
117 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl)
120 #ifdef WL_CFG80211_SYNC_GON
121 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl) \
122 (wl_get_drv_status_all(wl, SENDING_ACT_FRM) || \
123 wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN))
125 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl) wl_get_drv_status_all(wl, SENDING_ACT_FRM)
126 #endif /* WL_CFG80211_SYNC_GON */
128 #define WL_CHANSPEC_CTL_SB_NONE WL_CHANSPEC_CTL_SB_LLL
131 #define DNGL_FUNC(func, parameters) func parameters;
134 #define WLAN_EID_SSID 0
135 #define CH_MIN_5G_CHANNEL 34
136 #define CH_MIN_2G_CHANNEL 1
138 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
139 * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
140 * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
141 * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
142 * All the chnages in world regulatory domain are to be done here.
144 static const struct ieee80211_regdomain brcm_regdom = {
148 /* IEEE 802.11b/g, channels 1..11 */
149 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
151 /* IEEE 802.11 channel 14 - Only JP enables
152 * this and for 802.11b only
154 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
155 /* IEEE 802.11a, channel 36..64 */
156 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
157 /* IEEE 802.11a, channel 100..165 */
158 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
161 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
162 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
164 * Possible interface combinations supported by driver
166 * ADHOC Mode - #ADHOC <= 1 on channels = 1
167 * SoftAP Mode - #AP <= 1 on channels = 1
168 * STA + P2P Mode - #STA <= 2, #{P2P-GO, P2P-client} <= 1, #P2P-device <= 1
171 static const struct ieee80211_iface_limit softap_limits[] = {
174 .types = BIT(NL80211_IFTYPE_AP),
178 static const struct ieee80211_iface_limit sta_p2p_limits[] = {
180 * During P2P-GO removal, P2P-GO is first changed to STA and later only
181 * removed. So setting maximum possible number of STA interfaces as 2 to
182 * accommodate the above behaviour.
186 .types = BIT(NL80211_IFTYPE_STATION),
190 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
192 #if defined(WL_CFG80211_P2P_DEV_IF)
195 .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
197 #endif /* WL_CFG80211_P2P_DEV_IF */
200 .types = BIT(NL80211_IFTYPE_ADHOC),
204 static const struct ieee80211_iface_combination
205 softap_iface_combinations[] = {
207 .num_different_channels = 1,
209 .limits = softap_limits,
210 .n_limits = ARRAY_SIZE(softap_limits),
214 static const struct ieee80211_iface_combination
215 sta_p2p_iface_combinations[] = {
217 .num_different_channels = 2,
219 .limits = sta_p2p_limits,
220 .n_limits = ARRAY_SIZE(sta_p2p_limits),
223 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
225 /* Data Element Definitions */
226 #define WPS_ID_CONFIG_METHODS 0x1008
227 #define WPS_ID_REQ_TYPE 0x103A
228 #define WPS_ID_DEVICE_NAME 0x1011
229 #define WPS_ID_VERSION 0x104A
230 #define WPS_ID_DEVICE_PWD_ID 0x1012
231 #define WPS_ID_REQ_DEV_TYPE 0x106A
232 #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
233 #define WPS_ID_PRIM_DEV_TYPE 0x1054
235 /* Device Password ID */
236 #define DEV_PW_DEFAULT 0x0000
237 #define DEV_PW_USER_SPECIFIED 0x0001,
238 #define DEV_PW_MACHINE_SPECIFIED 0x0002
239 #define DEV_PW_REKEY 0x0003
240 #define DEV_PW_PUSHBUTTON 0x0004
241 #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
244 #define WPS_CONFIG_USBA 0x0001
245 #define WPS_CONFIG_ETHERNET 0x0002
246 #define WPS_CONFIG_LABEL 0x0004
247 #define WPS_CONFIG_DISPLAY 0x0008
248 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
249 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
250 #define WPS_CONFIG_NFC_INTERFACE 0x0040
251 #define WPS_CONFIG_PUSHBUTTON 0x0080
252 #define WPS_CONFIG_KEYPAD 0x0100
253 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
254 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
255 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
256 #define WPS_CONFIG_PHY_DISPLAY 0x4008
262 #ifndef WLAN_AKM_SUITE_CCKM
263 #define WLAN_AKM_SUITE_CCKM 0x00409600
265 #define DOT11_LEAP_AUTH 0x80 /* LEAP auth frame paylod constants */
269 #define WL_AKM_SUITE_MFP_1X 0x000FAC05
270 #define WL_AKM_SUITE_MFP_PSK 0x000FAC06
273 #ifndef IBSS_COALESCE_ALLOWED
274 #define IBSS_COALESCE_ALLOWED 0
277 #ifndef IBSS_INITIAL_SCAN_ALLOWED
278 #define IBSS_INITIAL_SCAN_ALLOWED 0
281 * cfg80211_ops api/callback list
283 static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
284 const struct ether_addr *sa, const struct ether_addr *bssid,
285 u8 **pheader, u32 *body_len, u8 *pbody);
286 static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
287 struct cfg80211_scan_request *request,
288 struct cfg80211_ssid *this_ssid);
290 #if defined(WL_CFG80211_P2P_DEV_IF)
291 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
293 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
294 struct cfg80211_scan_request *request);
295 #endif /* WL_CFG80211_P2P_DEV_IF */
296 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
297 static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
298 struct cfg80211_ibss_params *params);
299 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
300 struct net_device *dev);
301 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
302 struct net_device *dev, u8 *mac,
303 struct station_info *sinfo);
304 static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
305 struct net_device *dev, bool enabled,
307 static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
308 struct cfg80211_connect_params *sme);
309 static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
312 #if defined(WL_CFG80211_P2P_DEV_IF)
313 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
314 enum nl80211_tx_power_setting type, s32 mbm);
316 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
317 enum nl80211_tx_power_setting type, s32 dbm);
318 #endif /* WL_CFG80211_P2P_DEV_IF */
320 #if defined(WL_CFG80211_P2P_DEV_IF)
321 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
322 struct wireless_dev *wdev, s32 *dbm);
324 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
325 #endif /* WL_CFG80211_P2P_DEV_IF */
326 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
327 struct net_device *dev,
328 u8 key_idx, bool unicast, bool multicast);
329 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
330 u8 key_idx, bool pairwise, const u8 *mac_addr,
331 struct key_params *params);
332 static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
333 u8 key_idx, bool pairwise, const u8 *mac_addr);
334 static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
335 u8 key_idx, bool pairwise, const u8 *mac_addr,
336 void *cookie, void (*callback) (void *cookie,
337 struct key_params *params));
338 static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
339 struct net_device *dev, u8 key_idx);
340 static s32 wl_cfg80211_resume(struct wiphy *wiphy);
341 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
343 static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
344 bcm_struct_cfgdev *cfgdev, u64 cookie);
345 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
346 struct net_device *ndev, u8* mac_addr);
347 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
349 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
350 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
352 wl_cfg80211_suspend(struct wiphy *wiphy);
354 static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
355 struct cfg80211_pmksa *pmksa);
356 static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
357 struct cfg80211_pmksa *pmksa);
358 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
359 struct net_device *dev);
360 static void wl_cfg80211_scan_abort(struct wl_priv *wl);
361 static s32 wl_notify_escan_complete(struct wl_priv *wl,
362 struct net_device *ndev, bool aborted, bool fw_abort);
363 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
364 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
365 u8 *peer, enum nl80211_tdls_operation oper);
366 #endif /* LINUX_VERSION > KERNEL_VERSION(3,2,0) || WL_COMPAT_WIRELESS */
369 * event & event Q handlers for cfg80211 interfaces
371 static s32 wl_create_event_handler(struct wl_priv *wl);
372 static void wl_destroy_event_handler(struct wl_priv *wl);
373 static s32 wl_event_handler(void *data);
374 static void wl_init_eq(struct wl_priv *wl);
375 static void wl_flush_eq(struct wl_priv *wl);
376 static unsigned long wl_lock_eq(struct wl_priv *wl);
377 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags);
378 static void wl_init_eq_lock(struct wl_priv *wl);
379 static void wl_init_event_handler(struct wl_priv *wl);
380 static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
381 static s32 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 type,
382 const wl_event_msg_t *msg, void *data);
383 static void wl_put_event(struct wl_event_q *e);
384 static void wl_wakeup_event(struct wl_priv *wl);
385 static s32 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
386 const wl_event_msg_t *e, void *data);
387 static s32 wl_notify_connect_status(struct wl_priv *wl,
388 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
389 static s32 wl_notify_roaming_status(struct wl_priv *wl,
390 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
391 static s32 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
392 const wl_event_msg_t *e, void *data);
393 static s32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
394 const wl_event_msg_t *e, void *data, bool completed);
395 static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
396 const wl_event_msg_t *e, void *data);
397 static s32 wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
398 const wl_event_msg_t *e, void *data);
401 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
402 const wl_event_msg_t *e, void *data);
403 #endif /* WL_SCHED_SCAN */
405 static s32 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
406 const wl_event_msg_t *e, void *data);
407 #endif /* PNO_SUPPORT */
408 static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
409 enum wl_status state, bool set);
411 static s32 wl_svc_resp_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
412 const wl_event_msg_t *e, void *data);
413 static s32 wl_notify_device_discovery(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
414 const wl_event_msg_t *e, void *data);
418 static s32 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
419 const wl_event_msg_t *e, void *data);
422 * register/deregister parent device
424 static void wl_cfg80211_clear_parent_dev(void);
431 * cfg80211 set_wiphy_params utilities
433 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
434 static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
435 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
438 * wl profile utilities
440 static s32 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
441 const wl_event_msg_t *e, void *data, s32 item);
442 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item);
443 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev);
446 * cfg80211 connect utilites
448 static s32 wl_set_wpa_version(struct net_device *dev,
449 struct cfg80211_connect_params *sme);
450 static s32 wl_set_auth_type(struct net_device *dev,
451 struct cfg80211_connect_params *sme);
452 static s32 wl_set_set_cipher(struct net_device *dev,
453 struct cfg80211_connect_params *sme);
454 static s32 wl_set_key_mgmt(struct net_device *dev,
455 struct cfg80211_connect_params *sme);
456 static s32 wl_set_set_sharedkey(struct net_device *dev,
457 struct cfg80211_connect_params *sme);
459 static s32 wl_set_set_wapi_ie(struct net_device *dev,
460 struct cfg80211_connect_params *sme);
462 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev);
463 static void wl_ch_to_chanspec(int ch,
464 struct wl_join_params *join_params, size_t *join_params_size);
467 * information element utilities
469 static void wl_rst_ie(struct wl_priv *wl);
470 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v);
471 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size);
472 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size);
473 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size);
474 static u32 wl_get_ielen(struct wl_priv *wl);
476 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8* capa);
481 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len);
483 wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag,
484 uint8 ie_id, uint8 *data, uint8 data_len);
487 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data);
488 static void wl_free_wdev(struct wl_priv *wl);
489 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
491 wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
492 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
494 static s32 wl_inform_bss(struct wl_priv *wl);
495 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi);
496 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev);
497 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
498 s32 wl_cfg80211_channel_to_freq(u32 channel);
500 #if defined(DHCP_SCAN_SUPPRESS)
501 static void wl_cfg80211_work_handler(struct work_struct *work);
502 static void wl_cfg80211_scan_supp_timerfunc(ulong data);
503 #endif /* DHCP_SCAN_SUPPRESS */
505 static void wl_cfg80211_work_handler(struct work_struct *work);
506 static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
507 u8 key_idx, const u8 *mac_addr,
508 struct key_params *params);
510 * key indianess swap utilities
512 static void swap_key_from_BE(struct wl_wsec_key *key);
513 static void swap_key_to_BE(struct wl_wsec_key *key);
516 * wl_priv memory init/deinit utilities
518 static s32 wl_init_priv_mem(struct wl_priv *wl);
519 static void wl_deinit_priv_mem(struct wl_priv *wl);
521 static void wl_delay(u32 ms);
524 * ibss mode utilities
526 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev);
527 static __used bool wl_is_ibssstarter(struct wl_priv *wl);
530 * link up/down , default configuration utilities
532 static s32 __wl_cfg80211_up(struct wl_priv *wl);
533 static s32 __wl_cfg80211_down(struct wl_priv *wl);
534 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
535 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev);
536 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
537 static void wl_link_up(struct wl_priv *wl);
538 static void wl_link_down(struct wl_priv *wl);
539 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype);
540 static void wl_init_conf(struct wl_conf *conf);
545 static void wl_iscan_timer(unsigned long data);
546 static void wl_term_iscan(struct wl_priv *wl);
547 static s32 wl_init_scan(struct wl_priv *wl);
548 static s32 wl_iscan_thread(void *data);
549 static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request,
551 static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request);
552 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan);
553 static s32 wl_invoke_iscan(struct wl_priv *wl);
554 static s32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
555 struct wl_scan_results **bss_list);
556 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted);
557 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan);
558 static s32 wl_iscan_done(struct wl_priv *wl);
559 static s32 wl_iscan_pending(struct wl_priv *wl);
560 static s32 wl_iscan_inprogress(struct wl_priv *wl);
561 static s32 wl_iscan_aborted(struct wl_priv *wl);
564 * find most significant bit set
566 static __used u32 wl_find_msb(u16 bit16);
571 static int wl_setup_rfkill(struct wl_priv *wl, bool setup);
572 static int wl_rfkill_set(void *data, bool blocked);
573 #ifdef DEBUGFS_CFG80211
574 static s32 wl_setup_debugfs(struct wl_priv *wl);
575 static s32 wl_free_debugfs(struct wl_priv *wl);
578 static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel,
579 int nprobes, int *out_params_size);
580 static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role);
583 * Some external functions, TODO: move them to dhd_linux.h
585 int dhd_add_monitor(char *name, struct net_device **new_ndev);
586 int dhd_del_monitor(struct net_device *ndev);
587 int dhd_monitor_init(void *dhd_pub);
588 int dhd_monitor_uninit(void);
589 int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
593 s32 wl_cfg80211_sdo_init(struct wl_priv *wl);
594 s32 wl_cfg80211_sdo_deinit(struct wl_priv *wl);
595 #define MAX_SDO_PROTO 5
596 wl_sdo_proto_t wl_sdo_protos [] = {
597 { "all", SVC_RPOTYPE_ALL },
598 { "upnp", SVC_RPOTYPE_UPNP },
599 { "bonjour", SVC_RPOTYPE_BONJOUR },
600 { "wsd", SVC_RPOTYPE_WSD },
601 { "vendor", SVC_RPOTYPE_VENDOR },
605 #define RETURN_EIO_IF_NOT_UP(wlpriv) \
607 struct net_device *checkSysUpNDev = wl_to_prmry_ndev(wlpriv); \
608 if (unlikely(!wl_get_drv_status(wlpriv, READY, checkSysUpNDev))) { \
609 WL_INFO(("device is not ready\n")); \
615 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \
616 (akm) == RSN_AKM_UNSPECIFIED || \
617 (akm) == RSN_AKM_PSK)
620 extern int dhd_wait_pend8021x(struct net_device *dev);
621 #ifdef PROP_TXSTATUS_VSDB
622 extern int disable_proptx;
623 extern int dhd_wlfc_init(dhd_pub_t *dhd);
624 extern void dhd_wlfc_deinit(dhd_pub_t *dhd);
625 #endif /* PROP_TXSTATUS_VSDB */
627 #if (WL_DBG_LEVEL > 0)
628 #define WL_DBG_ESTR_MAX 50
629 static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
630 "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
631 "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
632 "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
633 "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
634 "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
635 "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
636 "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
638 "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
640 "RADIO", "PSM_WATCHDOG", "WLC_E_CCX_ASSOC_START", "WLC_E_CCX_ASSOC_ABORT",
642 "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
643 "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
644 "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
645 "WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE",
646 "RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG",
647 "ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND",
648 "WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED",
649 "WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT",
650 "WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE",
651 "WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP",
652 "WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE"
654 #endif /* WL_DBG_LEVEL */
656 #define CHAN2G(_channel, _freq, _flags) { \
657 .band = IEEE80211_BAND_2GHZ, \
658 .center_freq = (_freq), \
659 .hw_value = (_channel), \
661 .max_antenna_gain = 0, \
665 #define CHAN5G(_channel, _flags) { \
666 .band = IEEE80211_BAND_5GHZ, \
667 .center_freq = 5000 + (5 * (_channel)), \
668 .hw_value = (_channel), \
670 .max_antenna_gain = 0, \
674 #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
675 #define RATETAB_ENT(_rateid, _flags) \
677 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
678 .hw_value = (_rateid), \
682 static struct ieee80211_rate __wl_rates[] = {
683 RATETAB_ENT(DOT11_RATE_1M, 0),
684 RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
685 RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
686 RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
687 RATETAB_ENT(DOT11_RATE_6M, 0),
688 RATETAB_ENT(DOT11_RATE_9M, 0),
689 RATETAB_ENT(DOT11_RATE_12M, 0),
690 RATETAB_ENT(DOT11_RATE_18M, 0),
691 RATETAB_ENT(DOT11_RATE_24M, 0),
692 RATETAB_ENT(DOT11_RATE_36M, 0),
693 RATETAB_ENT(DOT11_RATE_48M, 0),
694 RATETAB_ENT(DOT11_RATE_54M, 0)
697 #define wl_a_rates (__wl_rates + 4)
698 #define wl_a_rates_size 8
699 #define wl_g_rates (__wl_rates + 0)
700 #define wl_g_rates_size 12
702 static struct ieee80211_channel __wl_2ghz_channels[] = {
719 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
720 CHAN5G(34, 0), CHAN5G(36, 0),
721 CHAN5G(38, 0), CHAN5G(40, 0),
722 CHAN5G(42, 0), CHAN5G(44, 0),
723 CHAN5G(46, 0), CHAN5G(48, 0),
724 CHAN5G(52, 0), CHAN5G(56, 0),
725 CHAN5G(60, 0), CHAN5G(64, 0),
726 CHAN5G(100, 0), CHAN5G(104, 0),
727 CHAN5G(108, 0), CHAN5G(112, 0),
728 CHAN5G(116, 0), CHAN5G(120, 0),
729 CHAN5G(124, 0), CHAN5G(128, 0),
730 CHAN5G(132, 0), CHAN5G(136, 0),
731 CHAN5G(140, 0), CHAN5G(149, 0),
732 CHAN5G(153, 0), CHAN5G(157, 0),
733 CHAN5G(161, 0), CHAN5G(165, 0)
736 static struct ieee80211_supported_band __wl_band_2ghz = {
737 .band = IEEE80211_BAND_2GHZ,
738 .channels = __wl_2ghz_channels,
739 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
740 .bitrates = wl_g_rates,
741 .n_bitrates = wl_g_rates_size
744 static struct ieee80211_supported_band __wl_band_5ghz_a = {
745 .band = IEEE80211_BAND_5GHZ,
746 .channels = __wl_5ghz_a_channels,
747 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
748 .bitrates = wl_a_rates,
749 .n_bitrates = wl_a_rates_size
752 static const u32 __wl_cipher_suites[] = {
753 WLAN_CIPHER_SUITE_WEP40,
754 WLAN_CIPHER_SUITE_WEP104,
755 WLAN_CIPHER_SUITE_TKIP,
756 WLAN_CIPHER_SUITE_CCMP,
757 WLAN_CIPHER_SUITE_AES_CMAC,
759 WLAN_CIPHER_SUITE_SMS4,
761 #if defined(WLFBT) && defined(WLAN_CIPHER_SUITE_PMK)
762 WLAN_CIPHER_SUITE_PMK,
767 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
768 static int maxrxpktglom = 0;
771 /* IOCtl version read from targeted driver */
772 static int ioctl_version;
773 #ifdef DEBUGFS_CFG80211
774 #define S_SUBLOGLEVEL 20
775 static const struct {
778 } sublogname_map[] = {
780 {WL_DBG_INFO, "INFO"},
782 {WL_DBG_SCAN, "SCAN"},
783 {WL_DBG_TRACE, "TRACE"},
784 {WL_DBG_P2P_ACTION, "P2PACTION"}
789 /* Return a new chanspec given a legacy chanspec
790 * Returns INVCHANSPEC on error
793 wl_chspec_from_legacy(chanspec_t legacy_chspec)
797 /* get the channel number */
798 chspec = LCHSPEC_CHANNEL(legacy_chspec);
800 /* convert the band */
801 if (LCHSPEC_IS2G(legacy_chspec)) {
802 chspec |= WL_CHANSPEC_BAND_2G;
804 chspec |= WL_CHANSPEC_BAND_5G;
807 /* convert the bw and sideband */
808 if (LCHSPEC_IS20(legacy_chspec)) {
809 chspec |= WL_CHANSPEC_BW_20;
811 chspec |= WL_CHANSPEC_BW_40;
812 if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
813 chspec |= WL_CHANSPEC_CTL_SB_L;
815 chspec |= WL_CHANSPEC_CTL_SB_U;
819 if (wf_chspec_malformed(chspec)) {
820 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
828 /* Return a legacy chanspec given a new chanspec
829 * Returns INVCHANSPEC on error
832 wl_chspec_to_legacy(chanspec_t chspec)
836 if (wf_chspec_malformed(chspec)) {
837 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
842 /* get the channel number */
843 lchspec = CHSPEC_CHANNEL(chspec);
845 /* convert the band */
846 if (CHSPEC_IS2G(chspec)) {
847 lchspec |= WL_LCHANSPEC_BAND_2G;
849 lchspec |= WL_LCHANSPEC_BAND_5G;
852 /* convert the bw and sideband */
853 if (CHSPEC_IS20(chspec)) {
854 lchspec |= WL_LCHANSPEC_BW_20;
855 lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
856 } else if (CHSPEC_IS40(chspec)) {
857 lchspec |= WL_LCHANSPEC_BW_40;
858 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
859 lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
861 lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
864 /* cannot express the bandwidth */
865 char chanbuf[CHANSPEC_STR_LEN];
867 "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
868 "to pre-11ac format\n",
869 wf_chspec_ntoa(chspec, chanbuf), chspec));
876 /* given a chanspec value, do the endian and chanspec version conversion to
878 * Returns INVCHANSPEC on error
881 wl_chspec_host_to_driver(chanspec_t chanspec)
883 if (ioctl_version == 1) {
884 chanspec = wl_chspec_to_legacy(chanspec);
885 if (chanspec == INVCHANSPEC) {
889 chanspec = htodchanspec(chanspec);
894 /* given a channel value, do the endian and chanspec version conversion to
896 * Returns INVCHANSPEC on error
899 wl_ch_host_to_driver(u16 channel)
904 chanspec = channel & WL_CHANSPEC_CHAN_MASK;
906 if (channel <= CH_MAX_2G_CHANNEL)
907 chanspec |= WL_CHANSPEC_BAND_2G;
909 chanspec |= WL_CHANSPEC_BAND_5G;
911 chanspec |= WL_CHANSPEC_BW_20;
912 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
914 return wl_chspec_host_to_driver(chanspec);
917 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
919 * Returns INVCHANSPEC on error
922 wl_chspec_driver_to_host(chanspec_t chanspec)
924 chanspec = dtohchanspec(chanspec);
925 if (ioctl_version == 1) {
926 chanspec = wl_chspec_from_legacy(chanspec);
932 /* There isn't a lot of sense in it, but you can transmit anything you like */
933 static const struct ieee80211_txrx_stypes
934 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
935 [NL80211_IFTYPE_ADHOC] = {
937 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
939 [NL80211_IFTYPE_STATION] = {
941 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
942 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
944 [NL80211_IFTYPE_AP] = {
946 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
947 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
948 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
949 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
950 BIT(IEEE80211_STYPE_AUTH >> 4) |
951 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
952 BIT(IEEE80211_STYPE_ACTION >> 4)
954 [NL80211_IFTYPE_AP_VLAN] = {
957 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
958 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
959 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
960 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
961 BIT(IEEE80211_STYPE_AUTH >> 4) |
962 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
963 BIT(IEEE80211_STYPE_ACTION >> 4)
965 [NL80211_IFTYPE_P2P_CLIENT] = {
967 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
968 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
970 [NL80211_IFTYPE_P2P_GO] = {
972 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
973 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
974 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
975 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
976 BIT(IEEE80211_STYPE_AUTH >> 4) |
977 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
978 BIT(IEEE80211_STYPE_ACTION >> 4)
980 #if defined(WL_CFG80211_P2P_DEV_IF)
981 [NL80211_IFTYPE_P2P_DEVICE] = {
983 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
984 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
986 #endif /* WL_CFG80211_P2P_DEV_IF */
989 static void swap_key_from_BE(struct wl_wsec_key *key)
991 key->index = htod32(key->index);
992 key->len = htod32(key->len);
993 key->algo = htod32(key->algo);
994 key->flags = htod32(key->flags);
995 key->rxiv.hi = htod32(key->rxiv.hi);
996 key->rxiv.lo = htod16(key->rxiv.lo);
997 key->iv_initialized = htod32(key->iv_initialized);
1000 static void swap_key_to_BE(struct wl_wsec_key *key)
1002 key->index = dtoh32(key->index);
1003 key->len = dtoh32(key->len);
1004 key->algo = dtoh32(key->algo);
1005 key->flags = dtoh32(key->flags);
1006 key->rxiv.hi = dtoh32(key->rxiv.hi);
1007 key->rxiv.lo = dtoh16(key->rxiv.lo);
1008 key->iv_initialized = dtoh32(key->iv_initialized);
1011 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(WL_COMPAT_WIRELESS)
1012 /* For debug: Dump the contents of the encoded wps ie buffe */
1014 wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
1016 #define WPS_IE_FIXED_LEN 6
1022 u8 *valptr = (uint8*) &val;
1023 if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
1024 WL_ERR(("invalid argument : NULL\n"));
1027 len = (u16)wps_ie[TLV_LEN_OFF];
1029 if (len > wps_ie_len) {
1030 WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
1033 WL_DBG(("wps_ie len=%d\n", len));
1034 len -= 4; /* for the WPS IE's OUI, oui_type fields */
1035 subel = wps_ie + WPS_IE_FIXED_LEN;
1036 while (len >= 4) { /* must have attr id, attr len fields */
1037 valptr[0] = *subel++;
1038 valptr[1] = *subel++;
1039 subelt_id = HTON16(val);
1041 valptr[0] = *subel++;
1042 valptr[1] = *subel++;
1043 subelt_len = HTON16(val);
1045 len -= 4; /* for the attr id, attr len fields */
1046 len -= subelt_len; /* for the remaining fields in this attribute */
1047 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1048 subel, subelt_id, subelt_len));
1050 if (subelt_id == WPS_ID_VERSION) {
1051 WL_DBG((" attr WPS_ID_VERSION: %u\n", *subel));
1052 } else if (subelt_id == WPS_ID_REQ_TYPE) {
1053 WL_DBG((" attr WPS_ID_REQ_TYPE: %u\n", *subel));
1054 } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
1056 valptr[1] = *(subel + 1);
1057 WL_DBG((" attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
1058 } else if (subelt_id == WPS_ID_DEVICE_NAME) {
1060 memcpy(devname, subel, subelt_len);
1061 devname[subelt_len] = '\0';
1062 WL_DBG((" attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1063 devname, subelt_len));
1064 } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
1066 valptr[1] = *(subel + 1);
1067 WL_DBG((" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
1068 *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
1069 } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
1071 valptr[1] = *(subel + 1);
1072 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
1073 valptr[0] = *(subel + 6);
1074 valptr[1] = *(subel + 7);
1075 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
1076 } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
1078 valptr[1] = *(subel + 1);
1079 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
1080 valptr[0] = *(subel + 6);
1081 valptr[1] = *(subel + 7);
1082 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
1083 } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
1085 valptr[1] = *(subel + 1);
1086 WL_DBG((" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1087 ": cat=%u\n", HTON16(val)));
1089 WL_DBG((" unknown attr 0x%x\n", subelt_id));
1092 subel += subelt_len;
1095 #endif /* LINUX_VERSION < VERSION(3, 4, 0) && !WL_COMPAT_WIRELESS */
1097 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
1101 struct wl_priv *wl = wiphy_priv(wiphy);
1102 struct net_device *dev = wl_to_prmry_ndev(wl);
1103 struct ether_addr bssid;
1104 struct wl_bss_info *bss = NULL;
1106 if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) {
1107 /* STA interface is not associated. So start the new interface on a temp
1108 * channel . Later proper channel will be applied by the above framework
1109 * via set_channel (cfg80211 API).
1111 WL_DBG(("Not associated. Return a temp channel. \n"));
1112 return wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1116 *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
1117 if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, wl->extra_buf,
1118 WL_EXTRA_BUF_MAX, false))) {
1119 WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1120 chspec = wl_ch_host_to_driver(WL_P2P_TEMP_CHAN);
1123 bss = (struct wl_bss_info *) (wl->extra_buf + 4);
1124 chspec = bss->chanspec;
1126 WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
1131 static bcm_struct_cfgdev *
1132 wl_cfg80211_add_monitor_if(char *name)
1134 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1135 WL_INFO(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1136 return ERR_PTR(-EOPNOTSUPP);
1138 struct net_device* ndev = NULL;
1140 dhd_add_monitor(name, &ndev);
1141 WL_INFO(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
1142 return ndev_to_cfgdev(ndev);
1143 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1146 static bcm_struct_cfgdev *
1147 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
1148 #if defined(WL_CFG80211_P2P_DEV_IF)
1152 #endif /* WL_CFG80211_P2P_DEV_IF */
1153 enum nl80211_iftype type, u32 *flags,
1154 struct vif_params *params)
1163 struct wl_priv *wl = wiphy_priv(wiphy);
1164 struct net_device *_ndev;
1165 struct ether_addr primary_mac;
1166 int (*net_attach)(void *dhdp, int ifidx);
1167 bool rollback_lock = false;
1168 #ifdef PROP_TXSTATUS_VSDB
1171 #endif /* PROP_TXSTATUS_VSDB */
1174 return ERR_PTR(-EINVAL);
1176 #ifdef PROP_TXSTATUS_VSDB
1177 dhd = (dhd_pub_t *)(wl->pub);
1178 #endif /* PROP_TXSTATUS_VSDB */
1180 /* Use primary I/F for sending cmds down to firmware */
1181 _ndev = wl_to_prmry_ndev(wl);
1183 WL_DBG(("if name: %s, type: %d\n", name, type));
1185 case NL80211_IFTYPE_ADHOC:
1186 case NL80211_IFTYPE_AP_VLAN:
1187 case NL80211_IFTYPE_WDS:
1188 case NL80211_IFTYPE_MESH_POINT:
1189 WL_ERR(("Unsupported interface type\n"));
1190 mode = WL_MODE_IBSS;
1192 case NL80211_IFTYPE_MONITOR:
1193 return wl_cfg80211_add_monitor_if((char *)name);
1194 #if defined(WL_CFG80211_P2P_DEV_IF)
1195 case NL80211_IFTYPE_P2P_DEVICE:
1196 return wl_cfgp2p_add_p2p_disc_if();
1197 #endif /* WL_CFG80211_P2P_DEV_IF */
1198 case NL80211_IFTYPE_P2P_CLIENT:
1199 case NL80211_IFTYPE_STATION:
1200 wlif_type = WL_P2P_IF_CLIENT;
1203 case NL80211_IFTYPE_P2P_GO:
1204 case NL80211_IFTYPE_AP:
1205 wlif_type = WL_P2P_IF_GO;
1209 WL_ERR(("Unsupported interface type\n"));
1215 WL_ERR(("name is NULL\n"));
1218 if (wl->p2p_supported && (wlif_type != -1)) {
1219 ASSERT(wl->p2p); /* ensure expectation of p2p initialization */
1220 if (wl_get_p2p_status(wl, IF_DELETING)) {
1221 /* wait till IF_DEL is complete
1222 * release the lock for the unregister to proceed
1224 if (rtnl_is_locked()) {
1226 rollback_lock = true;
1228 WL_INFO(("Released the lock and wait till IF_DEL is complete\n"));
1229 timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1230 (wl_get_p2p_status(wl, IF_DELETING) == false),
1231 msecs_to_jiffies(MAX_WAIT_TIME));
1233 /* put back the rtnl_lock again */
1234 if (rollback_lock) {
1236 rollback_lock = false;
1239 WL_ERR(("IF DEL is Success\n"));
1242 WL_ERR(("timeount < 0, return -EAGAIN\n"));
1243 return ERR_PTR(-EAGAIN);
1245 /* It should be now be safe to put this check here since we are sure
1246 * by now netdev_notifier (unregister) would have been called
1248 if (wl->iface_cnt == IFACE_MAX_CNT)
1249 return ERR_PTR(-ENOMEM);
1252 #ifdef PROP_TXSTATUS_VSDB
1254 return ERR_PTR(-ENODEV);
1255 #endif /* PROP_TXSTATUS_VSDB */
1257 return ERR_PTR(-ENODEV);
1259 if (wl->p2p && !wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
1261 wl_cfgp2p_set_firm_p2p(wl);
1262 wl_cfgp2p_init_discovery(wl);
1263 get_primary_mac(wl, &primary_mac);
1264 wl_cfgp2p_generate_bss_mac(&primary_mac,
1265 &wl->p2p->dev_addr, &wl->p2p->int_addr);
1268 memset(wl->p2p->vir_ifname, 0, IFNAMSIZ);
1269 strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1);
1271 wl_cfg80211_scan_abort(wl);
1272 #ifdef PROP_TXSTATUS_VSDB
1273 if (!wl->wlfc_on && !disable_proptx) {
1274 dhd->wlfc_enabled = true;
1276 err = wldev_ioctl(_ndev, WLC_UP, &up, sizeof(s32), true);
1278 WL_ERR(("WLC_UP return err:%d\n", err));
1281 #endif /* PROP_TXSTATUS_VSDB */
1283 /* In concurrency case, STA may be already associated in a particular channel.
1284 * so retrieve the current channel of primary interface and then start the virtual
1285 * interface on that.
1287 chspec = wl_cfg80211_get_shared_freq(wiphy);
1289 /* For P2P mode, use P2P-specific driver features to create the
1290 * bss: "wl p2p_ifadd"
1292 wl_set_p2p_status(wl, IF_ADD);
1293 if (wlif_type == WL_P2P_IF_GO)
1294 wldev_iovar_setint(_ndev, "mpc", 0);
1295 err = wl_cfgp2p_ifadd(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
1297 if (unlikely(err)) {
1298 WL_ERR((" virtual iface add failed (%d) \n", err));
1299 return ERR_PTR(-ENOMEM);
1302 timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1303 (wl_get_p2p_status(wl, IF_ADD) == false),
1304 msecs_to_jiffies(MAX_WAIT_TIME));
1305 if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) {
1307 struct wireless_dev *vwdev;
1308 vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
1309 if (unlikely(!vwdev)) {
1310 WL_ERR(("Could not allocate wireless device\n"));
1311 return ERR_PTR(-ENOMEM);
1313 vwdev->wiphy = wl->wdev->wiphy;
1314 WL_INFO((" virtual interface(%s) is created memalloc done \n",
1315 wl->p2p->vir_ifname));
1316 vwdev->iftype = type;
1317 _ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
1318 _ndev->ieee80211_ptr = vwdev;
1319 SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy));
1320 vwdev->netdev = _ndev;
1321 wl_set_drv_status(wl, READY, _ndev);
1322 wl->p2p->vif_created = true;
1323 wl_set_mode_by_netdev(wl, _ndev, mode);
1324 net_attach = wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION);
1325 if (rtnl_is_locked()) {
1327 rollback_lock = true;
1329 if (net_attach && !net_attach(wl->pub, _ndev->ifindex)) {
1330 wl_alloc_netinfo(wl, _ndev, vwdev, mode, PM_ENABLE);
1332 /* Disable firmware roaming for P2P interface */
1333 wldev_iovar_setint(_ndev, "roam_off", val);
1335 if (mode != WL_MODE_AP)
1336 wldev_iovar_setint(_ndev, "buf_key_b4_m4", 1);
1338 WL_ERR((" virtual interface(%s) is "
1339 "created net attach done\n", wl->p2p->vir_ifname));
1340 if (mode == WL_MODE_AP)
1341 wl_set_drv_status(wl, CONNECTED, _ndev);
1342 if (type == NL80211_IFTYPE_P2P_CLIENT)
1343 dhd_mode = DHD_FLAG_P2P_GC_MODE;
1344 else if (type == NL80211_IFTYPE_P2P_GO)
1345 dhd_mode = DHD_FLAG_P2P_GO_MODE;
1346 DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode));
1347 #ifdef PROP_TXSTATUS_VSDB
1348 if (dhd->plat_enable)
1349 dhd->plat_enable((void *)dhd);
1350 #endif /* PROP_TXSTATUS_VSDB */
1351 /* reinitialize completion to clear previous count */
1352 INIT_COMPLETION(wl->iface_disable);
1354 /* put back the rtnl_lock again */
1359 /* put back the rtnl_lock again */
1362 return ndev_to_cfgdev(_ndev);
1364 wl_clr_p2p_status(wl, IF_ADD);
1365 WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname));
1366 memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
1367 wl->p2p->vif_created = false;
1368 #ifdef PROP_TXSTATUS_VSDB
1369 if (dhd->wlfc_enabled && wl->wlfc_on) {
1370 dhd->wlfc_enabled = false;
1371 dhd_wlfc_deinit(dhd);
1372 if (dhd->plat_deinit)
1373 dhd->plat_deinit((void *)dhd);
1374 wl->wlfc_on = false;
1376 #endif /* PROP_TXSTATUS_VSDB */
1380 if (wlif_type == WL_P2P_IF_GO)
1381 wldev_iovar_setint(_ndev, "mpc", 1);
1382 return ERR_PTR(-ENODEV);
1386 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
1388 struct net_device *dev = NULL;
1389 struct ether_addr p2p_mac;
1390 struct wl_priv *wl = wiphy_priv(wiphy);
1394 WL_DBG(("Enter\n"));
1396 #if defined(WL_CFG80211_P2P_DEV_IF)
1397 if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
1398 return wl_cfgp2p_del_p2p_disc_if(cfgdev);
1400 #endif /* WL_CFG80211_P2P_DEV_IF */
1401 dev = cfgdev_to_wlc_ndev(cfgdev, wl);
1403 if (wl_cfgp2p_find_idx(wl, dev, &index) != BCME_OK) {
1404 WL_ERR(("Find p2p index from ndev(%p) failed\n", dev));
1407 if (wl->p2p_supported) {
1408 memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN);
1410 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
1412 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
1413 wl_clr_p2p_status(wl, GO_NEG_PHASE);
1414 if (wl->p2p->vif_created) {
1415 if (wl_get_drv_status(wl, SCANNING, dev)) {
1416 wl_notify_escan_complete(wl, dev, true, true);
1418 wldev_iovar_setint(dev, "mpc", 1);
1420 if (wl->pm_enable_work_on) {
1421 cancel_delayed_work_sync(&wl->pm_enable_work);
1422 wl->pm_enable_work_on = false;
1426 if (wl_get_drv_status(wl, DISCONNECTING, dev) &&
1427 (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)) {
1428 WL_ERR(("Wait for Link Down event for GC !\n"));
1429 wait_for_completion_timeout
1430 (&wl->iface_disable, msecs_to_jiffies(500));
1432 wl_set_p2p_status(wl, IF_DELETING);
1433 DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (wl));
1436 if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
1437 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
1438 /* disable interface before bsscfg free */
1439 ret = wl_cfgp2p_ifdisable(wl, &p2p_mac);
1440 /* if fw doesn't support "ifdis",
1441 do not wait for link down of ap mode
1444 WL_ERR(("Wait for Link Down event for GO !!!\n"));
1445 wait_for_completion_timeout(&wl->iface_disable,
1446 msecs_to_jiffies(500));
1449 wl_cfgp2p_clear_management_ie(wl, index);
1451 if (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP)
1452 wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
1454 /* delete interface after link down */
1455 ret = wl_cfgp2p_ifdel(wl, &p2p_mac);
1456 /* Firmware could not delete the interface so we will not get WLC_E_IF
1457 * event for cleaning the dhd virtual nw interace
1458 * So lets do it here. Failures from fw will ensure the application to do
1459 * ifconfig <inter> down and up sequnce, which will reload the fw
1460 * however we should cleanup the linux network virtual interfaces
1462 /* Request framework to RESET and clean up */
1464 struct net_device *ndev = wl_to_prmry_ndev(wl);
1465 WL_ERR(("Firmware returned an error (%d) from p2p_ifdel"
1466 "HANG Notification sent to %s\n", ret, ndev->name));
1467 net_os_send_hang_message(ndev);
1469 /* Wait for IF_DEL operation to be finished in firmware */
1470 timeout = wait_event_interruptible_timeout(wl->netif_change_event,
1471 (wl->p2p->vif_created == false),
1472 msecs_to_jiffies(MAX_WAIT_TIME));
1473 if (timeout > 0 && (wl->p2p->vif_created == false)) {
1474 WL_DBG(("IFDEL operation done\n"));
1476 WL_ERR(("IFDEL didn't complete properly\n"));
1478 ret = dhd_del_monitor(dev);
1485 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
1486 enum nl80211_iftype type, u32 *flags,
1487 struct vif_params *params)
1496 struct wl_priv *wl = wiphy_priv(wiphy);
1497 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
1498 WL_DBG(("Enter type %d\n", type));
1500 case NL80211_IFTYPE_MONITOR:
1501 case NL80211_IFTYPE_WDS:
1502 case NL80211_IFTYPE_MESH_POINT:
1504 WL_ERR(("type (%d) : currently we do not support this type\n",
1507 case NL80211_IFTYPE_ADHOC:
1508 mode = WL_MODE_IBSS;
1511 case NL80211_IFTYPE_STATION:
1512 case NL80211_IFTYPE_P2P_CLIENT:
1516 case NL80211_IFTYPE_AP:
1517 case NL80211_IFTYPE_AP_VLAN:
1518 case NL80211_IFTYPE_P2P_GO:
1528 wl_set_mode_by_netdev(wl, ndev, mode);
1529 if (wl->p2p_supported && wl->p2p->vif_created) {
1530 WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created,
1532 wldev_iovar_setint(ndev, "mpc", 0);
1533 wl_notify_escan_complete(wl, ndev, true, true);
1535 /* In concurrency case, STA may be already associated in a particular
1536 * channel. so retrieve the current channel of primary interface and
1537 * then start the virtual interface on that.
1539 chspec = wl_cfg80211_get_shared_freq(wiphy);
1541 wlif_type = WL_P2P_IF_GO;
1542 printk("%s : ap (%d), infra (%d), iftype: (%d)\n",
1543 ndev->name, ap, infra, type);
1544 wl_set_p2p_status(wl, IF_CHANGING);
1545 wl_clr_p2p_status(wl, IF_CHANGED);
1546 wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
1547 wait_event_interruptible_timeout(wl->netif_change_event,
1548 (wl_get_p2p_status(wl, IF_CHANGED) == true),
1549 msecs_to_jiffies(MAX_WAIT_TIME));
1550 wl_set_mode_by_netdev(wl, ndev, mode);
1551 dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
1552 dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
1553 wl_clr_p2p_status(wl, IF_CHANGING);
1554 wl_clr_p2p_status(wl, IF_CHANGED);
1555 if (mode == WL_MODE_AP)
1556 wl_set_drv_status(wl, CONNECTED, ndev);
1557 } else if (ndev == wl_to_prmry_ndev(wl) &&
1558 !wl_get_drv_status(wl, AP_CREATED, ndev)) {
1559 wl_set_drv_status(wl, AP_CREATING, ndev);
1561 !(wl->ap_info = kzalloc(sizeof(struct ap_info), GFP_KERNEL))) {
1562 WL_ERR(("struct ap_saved_ie allocation failed\n"));
1566 WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
1570 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA"));
1575 wl_set_mode_by_netdev(wl, ndev, mode);
1576 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
1578 WL_ERR(("SET Adhoc error %d\n", err));
1583 ndev->ieee80211_ptr->iftype = type;
1588 wl_cfg80211_notify_ifadd(struct net_device *ndev, s32 idx, s32 bssidx,
1591 struct wl_priv *wl = wlcfg_drv_priv;
1595 WL_ERR(("net is NULL\n"));
1598 if (wl->p2p_supported && wl_get_p2p_status(wl, IF_ADD)) {
1599 WL_DBG(("IF_ADD event called from dongle, old interface name: %s,"
1600 "new name: %s\n", ndev->name, wl->p2p->vir_ifname));
1601 /* Assign the net device to CONNECT BSSCFG */
1602 strncpy(ndev->name, wl->p2p->vir_ifname, IFNAMSIZ - 1);
1603 wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = ndev;
1604 wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = bssidx;
1605 wl_to_p2p_bss_private(wl, P2PAPI_BSSCFG_CONNECTION) = _net_attach;
1606 ndev->ifindex = idx;
1607 wl_clr_p2p_status(wl, IF_ADD);
1609 wake_up_interruptible(&wl->netif_change_event);
1611 ret = BCME_NOTREADY;
1617 wl_cfg80211_notify_ifdel(void)
1619 struct wl_priv *wl = wlcfg_drv_priv;
1621 WL_DBG(("Enter \n"));
1622 wl_clr_p2p_status(wl, IF_DELETING);
1623 wake_up_interruptible(&wl->netif_change_event);
1628 wl_cfg80211_ifdel_ops(struct net_device *ndev)
1630 struct wl_priv *wl = wlcfg_drv_priv;
1631 bool rollback_lock = false;
1635 #ifdef PROP_TXSTATUS_VSDB
1636 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
1637 #endif /* PROP_TXSTATUS_VSDB */
1638 if (!ndev || (strlen(ndev->name) == 0)) {
1639 WL_ERR(("net is NULL\n"));
1643 if (p2p_is_on(wl) && wl->p2p->vif_created &&
1644 wl_get_p2p_status(wl, IF_DELETING)) {
1645 if (wl->scan_request &&
1646 (wl->escan_info.ndev == ndev)) {
1647 /* Abort any pending scan requests */
1648 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
1649 if (!rtnl_is_locked()) {
1651 rollback_lock = true;
1653 WL_DBG(("ESCAN COMPLETED\n"));
1654 wl_notify_escan_complete(wl, ndev, true, false);
1658 WL_ERR(("IF_DEL event called from dongle, net %p, vif name: %s\n",
1659 ndev, wl->p2p->vir_ifname));
1661 memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
1662 if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) {
1663 WL_ERR(("Find p2p bssidx from ndev(%p) failed\n", ndev));
1666 if (wl_cfgp2p_find_type(wl, bssidx, &type) != BCME_OK) {
1667 WL_ERR(("Find p2p type from bssidx(%d) failed\n", bssidx));
1670 wl_to_p2p_bss_ndev(wl, type) = NULL;
1671 wl_to_p2p_bss_bssidx(wl, type) = WL_INVALID;
1672 wl->p2p->vif_created = false;
1674 WL_DBG(("type : %d\n", type));
1675 #ifdef PROP_TXSTATUS_VSDB
1676 if (dhd->wlfc_enabled && wl->wlfc_on) {
1677 dhd->wlfc_enabled = false;
1678 dhd_wlfc_deinit(dhd);
1679 if (dhd->plat_deinit)
1680 dhd->plat_deinit((void *)dhd);
1681 wl->wlfc_on = false;
1683 #endif /* PROP_TXSTATUS_VSDB */
1684 wl_clr_drv_status(wl, CONNECTED, ndev);
1686 /* Wake up any waiting thread */
1687 wake_up_interruptible(&wl->netif_change_event);
1693 wl_cfg80211_is_progress_ifadd(void)
1695 s32 is_progress = 0;
1696 struct wl_priv *wl = wlcfg_drv_priv;
1697 if (wl_get_p2p_status(wl, IF_ADD))
1703 wl_cfg80211_is_progress_ifchange(void)
1705 s32 is_progress = 0;
1706 struct wl_priv *wl = wlcfg_drv_priv;
1707 if (wl_get_p2p_status(wl, IF_CHANGING))
1714 wl_cfg80211_notify_ifchange(void)
1716 struct wl_priv *wl = wlcfg_drv_priv;
1717 if (wl_get_p2p_status(wl, IF_CHANGING)) {
1718 wl_set_p2p_status(wl, IF_CHANGED);
1719 wake_up_interruptible(&wl->netif_change_event);
1724 /* Find listen channel */
1725 static s32 wl_find_listen_channel(struct wl_priv *wl,
1726 const u8 *ie, u32 ie_len)
1728 wifi_p2p_ie_t *p2p_ie;
1733 p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
1738 pos = p2p_ie->subelts;
1739 end = p2p_ie->subelts + (p2p_ie->len - 4);
1741 CFGP2P_DBG((" found p2p ie ! lenth %d \n",
1746 if (pos + 2 >= end) {
1747 CFGP2P_DBG((" -- Invalid P2P attribute"));
1750 attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
1752 if (pos + 3 + attr_len > end) {
1753 CFGP2P_DBG(("P2P: Attribute underflow "
1755 attr_len, (int) (end - pos - 3)));
1759 /* if Listen Channel att id is 6 and the vailue is valid,
1760 * return the listen channel
1763 /* listen channel subel length format
1764 * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
1766 listen_channel = pos[1 + 2 + 3 + 1];
1768 if (listen_channel == SOCIAL_CHAN_1 ||
1769 listen_channel == SOCIAL_CHAN_2 ||
1770 listen_channel == SOCIAL_CHAN_3) {
1771 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
1772 return listen_channel;
1775 pos += 3 + attr_len;
1780 static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
1785 chanspec_t chanspec;
1786 s32 i = 0, j = 0, offset;
1789 struct wl_priv *wl = wlcfg_drv_priv;
1791 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
1792 params->bss_type = DOT11_BSSTYPE_ANY;
1793 params->scan_type = 0;
1794 params->nprobes = -1;
1795 params->active_time = -1;
1796 params->passive_time = -1;
1797 params->home_time = -1;
1798 params->channel_num = 0;
1799 memset(¶ms->ssid, 0, sizeof(wlc_ssid_t));
1801 WL_SCAN(("Preparing Scan request\n"));
1802 WL_SCAN(("nprobes=%d\n", params->nprobes));
1803 WL_SCAN(("active_time=%d\n", params->active_time));
1804 WL_SCAN(("passive_time=%d\n", params->passive_time));
1805 WL_SCAN(("home_time=%d\n", params->home_time));
1806 WL_SCAN(("scan_type=%d\n", params->scan_type));
1808 params->nprobes = htod32(params->nprobes);
1809 params->active_time = htod32(params->active_time);
1810 params->passive_time = htod32(params->passive_time);
1811 params->home_time = htod32(params->home_time);
1813 /* if request is null just exit so it will be all channel broadcast scan */
1817 n_ssids = request->n_ssids;
1818 n_channels = request->n_channels;
1820 /* Copy channel array if applicable */
1821 WL_SCAN(("### List of channelspecs to scan ###\n"));
1822 if (n_channels > 0) {
1823 for (i = 0; i < n_channels; i++) {
1825 channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
1826 /* SKIP DFS channels for Secondary interface */
1827 if ((wl->escan_info.ndev != wl_to_prmry_ndev(wl)) &&
1828 (request->channels[i]->flags &
1829 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
1832 if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
1833 #ifdef WL_HOST_BAND_MGMT
1834 if (wl->curr_band == WLC_BAND_5G) {
1835 WL_DBG(("In 5G only mode, omit 2G channel:%d\n", channel));
1838 #endif /* WL_HOST_BAND_MGMT */
1839 chanspec |= WL_CHANSPEC_BAND_2G;
1841 #ifdef WL_HOST_BAND_MGMT
1842 if (wl->curr_band == WLC_BAND_2G) {
1843 WL_DBG(("In 2G only mode, omit 5G channel:%d\n", channel));
1846 #endif /* WL_HOST_BAND_MGMT */
1847 chanspec |= WL_CHANSPEC_BAND_5G;
1850 chanspec |= WL_CHANSPEC_BW_20;
1851 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1853 params->channel_list[j] = channel;
1854 params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
1855 params->channel_list[j] |= chanspec;
1856 WL_SCAN(("Chan : %d, Channel spec: %x \n",
1857 channel, params->channel_list[j]));
1858 params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
1862 WL_SCAN(("Scanning all channels\n"));
1865 /* Copy ssid array if applicable */
1866 WL_SCAN(("### List of SSIDs to scan ###\n"));
1868 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
1869 offset = roundup(offset, sizeof(u32));
1870 ptr = (char*)params + offset;
1871 for (i = 0; i < n_ssids; i++) {
1872 memset(&ssid, 0, sizeof(wlc_ssid_t));
1873 ssid.SSID_len = request->ssids[i].ssid_len;
1874 memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
1876 WL_SCAN(("%d: Broadcast scan\n", i));
1878 WL_SCAN(("%d: scan for %s size =%d\n", i,
1879 ssid.SSID, ssid.SSID_len));
1880 memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
1881 ptr += sizeof(wlc_ssid_t);
1884 WL_SCAN(("Broadcast scan\n"));
1886 /* Adding mask to channel numbers */
1887 params->channel_num =
1888 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
1889 (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
1891 if (n_channels == 1) {
1892 params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
1893 params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
1898 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct cfg80211_scan_request *request, u16 action)
1903 (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
1904 struct wl_iscan_params *params = NULL;
1907 if (request != NULL) {
1908 n_channels = request->n_channels;
1909 n_ssids = request->n_ssids;
1910 /* Allocate space for populating ssids in wl_iscan_params struct */
1912 /* If n_channels is odd, add a padd of u16 */
1913 params_size += sizeof(u16) * (n_channels + 1);
1915 params_size += sizeof(u16) * n_channels;
1917 /* Allocate space for populating ssids in wl_iscan_params struct */
1918 params_size += sizeof(struct wlc_ssid) * n_ssids;
1920 params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
1925 wl_scan_prep(¶ms->params, request);
1927 params->version = htod32(ISCAN_REQ_VERSION);
1928 params->action = htod16(action);
1929 params->scan_duration = htod16(0);
1931 if (params_size + sizeof("iscan") >= WLC_IOCTL_MEDLEN) {
1932 WL_ERR(("ioctl buffer length is not sufficient\n"));
1936 err = wldev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
1937 iscan->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
1938 if (unlikely(err)) {
1939 if (err == -EBUSY) {
1940 WL_ERR(("system busy : iscan canceled\n"));
1942 WL_ERR(("error (%d)\n", err));
1952 static s32 wl_do_iscan(struct wl_priv *wl, struct cfg80211_scan_request *request)
1954 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
1955 struct net_device *ndev = wl_to_prmry_ndev(wl);
1959 iscan->state = WL_ISCAN_STATE_SCANING;
1961 passive_scan = wl->active_scan ? 0 : 1;
1962 err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
1963 &passive_scan, sizeof(passive_scan), true);
1964 if (unlikely(err)) {
1965 WL_DBG(("error (%d)\n", err));
1968 wl->iscan_kickstart = true;
1969 wl_run_iscan(iscan, request, WL_SCAN_ACTION_START);
1970 mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
1971 iscan->timer_on = 1;
1977 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
1979 wl_uint32_list_t *list;
1981 if (valid_chan_list == NULL || size <= 0)
1984 memset(valid_chan_list, 0, size);
1985 list = (wl_uint32_list_t *)(void *) valid_chan_list;
1986 list->count = htod32(WL_NUMCHANNELS);
1987 err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
1989 WL_ERR(("get channels failed with %d\n", err));
1995 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
1996 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
1998 g_first_broadcast_scan = TRUE;
2002 wl_run_escan(struct wl_priv *wl, struct net_device *ndev,
2003 struct cfg80211_scan_request *request, uint16 action)
2008 s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
2009 wl_escan_params_t *params = NULL;
2010 u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
2014 s32 search_state = WL_P2P_DISC_ST_SCAN;
2015 u32 i, j, n_nodfs = 0;
2016 u16 *default_chan_list = NULL;
2017 wl_uint32_list_t *list;
2018 struct net_device *dev = NULL;
2020 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2021 bool is_first_init_2g_scan = false;
2023 p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
2026 WL_DBG(("Enter \n"));
2028 /* scan request can come with empty request : perform all default scan */
2033 if (!wl->p2p_supported || !p2p_scan(wl)) {
2034 /* LEGACY SCAN TRIGGER */
2035 WL_SCAN((" LEGACY E-SCAN START\n"));
2037 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2042 if (ndev == wl_to_prmry_ndev(wl) && g_first_broadcast_scan == true) {
2043 is_first_init_2g_scan = true;
2044 g_first_broadcast_scan = false;
2048 /* if scan request is not empty parse scan request paramters */
2049 if (request != NULL) {
2050 n_channels = request->n_channels;
2051 n_ssids = request->n_ssids;
2052 /* Allocate space for populating ssids in wl_iscan_params struct */
2054 /* If n_channels is odd, add a padd of u16 */
2055 params_size += sizeof(u16) * (n_channels + 1);
2057 params_size += sizeof(u16) * n_channels;
2059 /* Allocate space for populating ssids in wl_iscan_params struct */
2060 params_size += sizeof(struct wlc_ssid) * n_ssids;
2062 params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
2063 if (params == NULL) {
2067 wl_scan_prep(¶ms->params, request);
2069 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2070 /* Override active_time to reduce scan time if it's first bradcast scan. */
2071 if (is_first_init_2g_scan)
2072 params->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
2075 params->version = htod32(ESCAN_REQ_VERSION);
2076 params->action = htod16(action);
2077 wl_escan_set_sync_id(params->sync_id, wl);
2078 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
2079 WL_ERR(("ioctl buffer length not sufficient\n"));
2084 err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
2085 wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2086 if (unlikely(err)) {
2087 if (err == BCME_EPERM)
2088 /* Scan Not permitted at this point of time */
2089 WL_DBG((" Escan not permitted at this time (%d)\n", err));
2091 WL_ERR((" Escan set error (%d)\n", err));
2095 else if (p2p_is_on(wl) && p2p_scan(wl)) {
2096 /* P2P SCAN TRIGGER */
2099 if (request && request->n_channels) {
2100 num_chans = request->n_channels;
2101 WL_SCAN((" chann number : %d\n", num_chans));
2102 default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
2104 if (default_chan_list == NULL) {
2105 WL_ERR(("channel list allocation failed \n"));
2109 if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
2110 list = (wl_uint32_list_t *) chan_buf;
2111 n_valid_chan = dtoh32(list->count);
2112 for (i = 0; i < num_chans; i++)
2114 #ifdef WL_HOST_BAND_MGMT
2115 int channel_band = 0;
2116 #endif /* WL_HOST_BAND_MGMT */
2117 _freq = request->channels[i]->center_freq;
2118 channel = ieee80211_frequency_to_channel(_freq);
2119 #ifdef WL_HOST_BAND_MGMT
2120 channel_band = (channel > CH_MAX_2G_CHANNEL) ?
2121 WLC_BAND_5G : WLC_BAND_2G;
2122 if ((wl->curr_band != WLC_BAND_AUTO) &&
2123 (wl->curr_band != channel_band) &&
2124 !IS_P2P_SOCIAL_CHANNEL(channel))
2126 #endif /* WL_HOST_BAND_MGMT */
2128 /* ignore DFS channels */
2129 if (request->channels[i]->flags &
2130 (IEEE80211_CHAN_RADAR
2131 | IEEE80211_CHAN_PASSIVE_SCAN))
2134 for (j = 0; j < n_valid_chan; j++) {
2135 /* allows only supported channel on
2138 if (channel == (dtoh32(list->element[j])))
2139 default_chan_list[n_nodfs++] =
2145 if (num_chans == SOCIAL_CHAN_CNT && (
2146 (default_chan_list[0] == SOCIAL_CHAN_1) &&
2147 (default_chan_list[1] == SOCIAL_CHAN_2) &&
2148 (default_chan_list[2] == SOCIAL_CHAN_3))) {
2149 /* SOCIAL CHANNELS 1, 6, 11 */
2150 search_state = WL_P2P_DISC_ST_SEARCH;
2151 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2152 WL_INFO(("P2P SEARCH PHASE START \n"));
2153 } else if ((dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION)) &&
2154 (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP)) {
2155 /* If you are already a GO, then do SEARCH only */
2156 WL_INFO(("Already a GO. Do SEARCH Only"));
2157 search_state = WL_P2P_DISC_ST_SEARCH;
2158 num_chans = n_nodfs;
2159 p2p_scan_purpose = P2P_SCAN_NORMAL;
2161 } else if (num_chans == 1) {
2162 p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
2163 } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
2164 /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2167 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2169 WL_INFO(("P2P SCAN STATE START \n"));
2170 num_chans = n_nodfs;
2171 p2p_scan_purpose = P2P_SCAN_NORMAL;
2177 err = wl_cfgp2p_escan(wl, ndev, wl->active_scan, num_chans, default_chan_list,
2178 search_state, action,
2179 wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE), NULL,
2183 wl->p2p->search_state = search_state;
2185 kfree(default_chan_list);
2188 if (unlikely(err)) {
2189 /* Don't print Error incase of Scan suppress */
2190 if ((err == BCME_EPERM) && wl->scan_suppressed)
2191 WL_DBG(("Escan failed: Scan Suppressed \n"));
2194 WL_ERR(("error (%d), cnt=%d\n", err, cnt));
2195 // terence 20140111: send disassoc to firmware
2197 dev = wl_to_prmry_ndev(wl);
2198 memset(&scbval, 0, sizeof(scb_val_t));
2199 wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true);
2200 WL_ERR(("Send disassoc to break the busy dev=%p\n", dev));
2212 wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev,
2213 struct cfg80211_scan_request *request)
2217 wl_scan_results_t *results;
2218 WL_SCAN(("Enter \n"));
2219 mutex_lock(&wl->usr_sync);
2221 results = wl_escan_get_buf(wl, FALSE);
2222 results->version = 0;
2224 results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
2226 wl->escan_info.ndev = ndev;
2227 wl->escan_info.wiphy = wiphy;
2228 wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
2229 passive_scan = wl->active_scan ? 0 : 1;
2230 err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2231 &passive_scan, sizeof(passive_scan), true);
2232 if (unlikely(err)) {
2233 WL_ERR(("error (%d)\n", err));
2237 err = wl_run_escan(wl, ndev, request, WL_SCAN_ACTION_START);
2239 mutex_unlock(&wl->usr_sync);
2244 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2245 struct cfg80211_scan_request *request,
2246 struct cfg80211_ssid *this_ssid)
2248 struct wl_priv *wl = wiphy_priv(wiphy);
2249 struct cfg80211_ssid *ssids;
2250 struct wl_scan_req *sr = wl_to_sr(wl);
2251 struct ether_addr primary_mac;
2254 bool escan_req = false;
2257 bcm_tlv_t *interworking_ie;
2263 unsigned long flags;
2264 static s32 busy_count = 0;
2268 dhd = (dhd_pub_t *)(wl->pub);
2269 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
2270 WL_ERR(("Invalid Scan Command at SoftAP mode\n"));
2274 ndev = ndev_to_wlc_ndev(ndev, wl);
2276 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(wl)) {
2277 WL_ERR(("Sending Action Frames. Try it again.\n"));
2281 WL_DBG(("Enter wiphy (%p)\n", wiphy));
2282 if (wl_get_drv_status_all(wl, SCANNING)) {
2283 if (wl->scan_request == NULL) {
2284 wl_clr_drv_status_all(wl, SCANNING);
2285 WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
2287 WL_ERR(("Scanning already\n"));
2291 if (wl_get_drv_status(wl, SCAN_ABORTING, ndev)) {
2292 WL_ERR(("Scanning being aborted\n"));
2295 if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
2296 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
2299 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2300 if (wl_get_drv_status_all(wl, REMAINING_ON_CHANNEL)) {
2301 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
2302 wl_notify_escan_complete(wl, ndev, true, true);
2304 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
2307 if (wl_get_p2p_status(wl, DISC_IN_PROGRESS)) {
2308 wl_cfg80211_pause_sdo(ndev, wl);
2312 /* Arm scan timeout timer */
2313 mod_timer(&wl->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
2315 if (request) { /* scan bss */
2316 ssids = request->ssids;
2317 if (wl->iscan_on && (!ssids || !ssids->ssid_len || request->n_ssids != 1)) {
2319 } else if (wl->escan_on) {
2322 for (i = 0; i < request->n_ssids; i++) {
2323 if (ssids[i].ssid_len &&
2324 IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
2330 if (wl->p2p_supported) {
2331 /* p2p scan trigger */
2332 if (p2p_on(wl) == false) {
2333 /* p2p on at the first time */
2335 wl_cfgp2p_set_firm_p2p(wl);
2336 get_primary_mac(wl, &primary_mac);
2337 wl_cfgp2p_generate_bss_mac(&primary_mac,
2338 &wl->p2p->dev_addr, &wl->p2p->int_addr);
2340 wl_clr_p2p_status(wl, GO_NEG_PHASE);
2341 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
2342 p2p_scan(wl) = true;
2345 /* legacy scan trigger
2346 * So, we have to disable p2p discovery if p2p discovery is on
2348 if (wl->p2p_supported) {
2349 p2p_scan(wl) = false;
2350 /* If Netdevice is not equals to primary and p2p is on
2351 * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
2354 if (p2p_scan(wl) == false) {
2355 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
2356 err = wl_cfgp2p_discover_enable_search(wl,
2358 if (unlikely(err)) {
2365 if (!wl->p2p_supported || !p2p_scan(wl)) {
2367 if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) {
2368 WL_ERR(("Find p2p index from ndev(%p) failed\n",
2374 if ((interworking_ie = wl_cfg80211_find_interworking_ie(
2375 (u8 *)request->ie, request->ie_len)) != NULL) {
2376 err = wl_cfg80211_add_iw_ie(wl, ndev, bssidx,
2377 VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
2378 interworking_ie->data, interworking_ie->len);
2380 if (unlikely(err)) {
2383 } else if (wl->iw_ie_len != 0) {
2384 /* we have to clear IW IE and disable gratuitous APR */
2385 wl_cfg80211_add_iw_ie(wl, ndev, bssidx,
2386 VNDR_IE_CUSTOM_FLAG,
2387 DOT11_MNG_INTERWORKING_ID,
2390 wldev_iovar_setint_bsscfg(ndev, "grat_arp", 0,
2393 /* we don't care about error */
2396 err = wl_cfgp2p_set_management_ie(wl, ndev, bssidx,
2397 VNDR_IE_PRBREQ_FLAG, (u8 *)request->ie,
2400 if (unlikely(err)) {
2407 } else { /* scan in ibss */
2408 /* we don't do iscan in ibss */
2411 if (request && !p2p_scan(wl))
2412 WL_TRACE_HW4(("START SCAN\n"));
2413 wl->scan_request = request;
2414 wl_set_drv_status(wl, SCANNING, ndev);
2416 err = wl_do_iscan(wl, request);
2421 } else if (escan_req) {
2422 if (wl->p2p_supported) {
2423 if (p2p_on(wl) && p2p_scan(wl)) {
2426 if (wl_get_p2p_status(wl, DISC_IN_PROGRESS)) {
2427 /* We shouldn't be getting p2p_find while discovery
2428 * offload is in progress
2430 WL_SD(("P2P_FIND: Discovery offload is in progress."
2436 /* find my listen channel */
2437 wl->afx_hdl->my_listen_chan =
2438 wl_find_listen_channel(wl, request->ie,
2440 err = wl_cfgp2p_enable_discovery(wl, ndev,
2441 request->ie, request->ie_len);
2443 if (unlikely(err)) {
2448 err = wl_do_escan(wl, wiphy, ndev, request);
2456 memset(&sr->ssid, 0, sizeof(sr->ssid));
2458 min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
2459 if (sr->ssid.SSID_len) {
2460 memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
2461 sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
2462 WL_SCAN(("Specific scan ssid=\"%s\" len=%d\n",
2463 sr->ssid.SSID, sr->ssid.SSID_len));
2465 WL_SCAN(("Broadcast scan\n"));
2467 WL_SCAN(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
2468 passive_scan = wl->active_scan ? 0 : 1;
2469 err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2470 &passive_scan, sizeof(passive_scan), true);
2471 if (unlikely(err)) {
2472 WL_SCAN(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
2475 err = wldev_ioctl(ndev, WLC_SCAN, &sr->ssid,
2476 sizeof(sr->ssid), false);
2478 if (err == -EBUSY) {
2479 WL_ERR(("system busy : scan for \"%s\" "
2480 "canceled\n", sr->ssid.SSID));
2482 WL_ERR(("WLC_SCAN error (%d)\n", err));
2494 if (err == BCME_BUSY || err == BCME_NOTREADY) {
2495 WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
2499 #define SCAN_EBUSY_RETRY_LIMIT 10
2500 if (err == -EBUSY) {
2501 if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
2502 struct ether_addr bssid;
2505 WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
2506 wl_get_drv_status(wl, SCANNING, ndev),
2507 wl_get_drv_status(wl, SCAN_ABORTING, ndev),
2508 wl_get_drv_status(wl, CONNECTING, ndev),
2509 wl_get_drv_status(wl, CONNECTED, ndev),
2510 wl_get_drv_status(wl, DISCONNECTING, ndev),
2511 wl_get_drv_status(wl, AP_CREATING, ndev),
2512 wl_get_drv_status(wl, AP_CREATED, ndev),
2513 wl_get_drv_status(wl, SENDING_ACT_FRM, ndev),
2514 wl_get_drv_status(wl, SENDING_ACT_FRM, ndev)));
2516 bzero(&bssid, sizeof(bssid));
2517 if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID,
2518 &bssid, ETHER_ADDR_LEN, false)) == 0)
2519 WL_ERR(("FW is connected with " MACDBG "/n",
2520 MAC2STRDBG(bssid.octet)));
2522 WL_ERR(("GET BSSID failed with %d\n", ret));
2524 wl_cfg80211_scan_abort(wl);
2530 wl_clr_drv_status(wl, SCANNING, ndev);
2531 if (timer_pending(&wl->scan_timeout))
2532 del_timer_sync(&wl->scan_timeout);
2533 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
2534 wl->scan_request = NULL;
2535 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
2538 if (wl_get_p2p_status(wl, DISC_IN_PROGRESS)) {
2539 wl_cfg80211_resume_sdo(ndev, wl);
2546 #if defined(WL_CFG80211_P2P_DEV_IF)
2547 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
2549 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2550 struct cfg80211_scan_request *request)
2551 #endif /* WL_CFG80211_P2P_DEV_IF */
2554 struct wl_priv *wl = wiphy_priv(wiphy);
2555 #if defined(WL_CFG80211_P2P_DEV_IF)
2556 struct net_device *ndev = wl_to_prmry_ndev(wl);
2557 #endif /* WL_CFG80211_P2P_DEV_IF */
2559 WL_DBG(("Enter \n"));
2560 RETURN_EIO_IF_NOT_UP(wl);
2562 err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
2563 if (unlikely(err)) {
2564 if ((err == BCME_EPERM) && wl->scan_suppressed)
2565 WL_DBG(("scan not permitted at this time (%d)\n", err));
2567 WL_ERR(("scan error (%d)\n", err));
2574 static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
2578 err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
2579 if (unlikely(err)) {
2580 WL_ERR(("Error (%d)\n", err));
2586 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
2590 err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
2591 if (unlikely(err)) {
2592 WL_ERR(("Error (%d)\n", err));
2598 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
2601 u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
2603 retry = htod32(retry);
2604 err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true);
2605 if (unlikely(err)) {
2606 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
2612 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
2614 struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
2615 struct net_device *ndev = wl_to_prmry_ndev(wl);
2618 RETURN_EIO_IF_NOT_UP(wl);
2619 WL_DBG(("Enter\n"));
2620 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
2621 (wl->conf->rts_threshold != wiphy->rts_threshold)) {
2622 wl->conf->rts_threshold = wiphy->rts_threshold;
2623 err = wl_set_rts(ndev, wl->conf->rts_threshold);
2627 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
2628 (wl->conf->frag_threshold != wiphy->frag_threshold)) {
2629 wl->conf->frag_threshold = wiphy->frag_threshold;
2630 err = wl_set_frag(ndev, wl->conf->frag_threshold);
2634 if (changed & WIPHY_PARAM_RETRY_LONG &&
2635 (wl->conf->retry_long != wiphy->retry_long)) {
2636 wl->conf->retry_long = wiphy->retry_long;
2637 err = wl_set_retry(ndev, wl->conf->retry_long, true);
2641 if (changed & WIPHY_PARAM_RETRY_SHORT &&
2642 (wl->conf->retry_short != wiphy->retry_short)) {
2643 wl->conf->retry_short = wiphy->retry_short;
2644 err = wl_set_retry(ndev, wl->conf->retry_short, false);
2652 static chanspec_t channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel)
2654 struct wl_priv *wl = wiphy_priv(wiphy);
2656 wl_uint32_list_t *list;
2658 chanspec_t c = 0, ret_c = 0;
2659 int bw = 0, tmp_bw = 0;
2662 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
2663 #define LOCAL_BUF_SIZE 1024
2664 buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
2666 WL_ERR(("buf memory alloc failed\n"));
2669 list = (wl_uint32_list_t *)(void *)buf;
2670 list->count = htod32(WL_NUMCHANSPECS);
2671 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
2672 0, buf, LOCAL_BUF_SIZE, 0, &wl->ioctl_buf_sync);
2673 if (err != BCME_OK) {
2674 WL_ERR(("get chanspecs failed with %d\n", err));
2677 for (i = 0; i < dtoh32(list->count); i++) {
2678 c = dtoh32(list->element[i]);
2679 if (channel <= CH_MAX_2G_CHANNEL) {
2680 if (!CHSPEC_IS20(c))
2682 if (channel == CHSPEC_CHANNEL(c)) {
2688 if (CHSPEC_IS20(c)) {
2689 tmp_c = CHSPEC_CHANNEL(c);
2692 else if (CHSPEC_IS40(c)) {
2693 tmp_c = CHSPEC_CHANNEL(c);
2694 if (CHSPEC_SB_UPPER(c)) {
2695 tmp_c += CH_10MHZ_APART;
2697 tmp_c -= CH_10MHZ_APART;
2702 tmp_c = CHSPEC_CHANNEL(c);
2703 sb = c & WL_CHANSPEC_CTL_SB_MASK;
2704 if (sb == WL_CHANSPEC_CTL_SB_LL) {
2705 tmp_c -= (CH_10MHZ_APART + CH_20MHZ_APART);
2706 } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
2707 tmp_c -= CH_10MHZ_APART;
2708 } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
2709 tmp_c += CH_10MHZ_APART;
2711 /* WL_CHANSPEC_CTL_SB_UU */
2712 tmp_c += (CH_10MHZ_APART + CH_20MHZ_APART);
2716 if (tmp_c != channel)
2727 #undef LOCAL_BUF_SIZE
2728 WL_INFO(("return chanspec %x %d\n", ret_c, bw));
2733 wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len)
2735 struct wl_priv *wl = wlcfg_drv_priv;
2737 if (wl != NULL && ibss_vsie != NULL) {
2738 if (wl->ibss_vsie != NULL) {
2739 kfree(wl->ibss_vsie);
2741 wl->ibss_vsie = ibss_vsie;
2742 wl->ibss_vsie_len = ibss_vsie_len;
2747 wl_cfg80211_ibss_vsie_free(struct wl_priv *wl)
2749 /* free & initiralize VSIE (Vendor Specific IE) */
2750 if (wl->ibss_vsie != NULL) {
2751 kfree(wl->ibss_vsie);
2752 wl->ibss_vsie = NULL;
2753 wl->ibss_vsie_len = 0;
2758 wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
2760 struct wl_priv *wl = wlcfg_drv_priv;
2761 char *ioctl_buf = NULL;
2764 if (wl != NULL && wl->ibss_vsie != NULL) {
2765 ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
2767 WL_ERR(("ioctl memory alloc failed\n"));
2771 /* change the command from "add" to "del" */
2772 strncpy(wl->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
2773 wl->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
2775 ret = wldev_iovar_setbuf(dev, "ie",
2776 wl->ibss_vsie, wl->ibss_vsie_len,
2777 ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2778 WL_ERR(("ret=%d\n", ret));
2780 if (ret == BCME_OK) {
2781 /* free & initiralize VSIE */
2782 kfree(wl->ibss_vsie);
2783 wl->ibss_vsie = NULL;
2784 wl->ibss_vsie_len = 0;
2796 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
2797 struct cfg80211_ibss_params *params)
2799 struct wl_priv *wl = wiphy_priv(wiphy);
2800 struct cfg80211_bss *bss;
2801 struct ieee80211_channel *chan;
2802 struct wl_join_params join_params;
2803 struct cfg80211_ssid ssid;
2806 int scan_suppress = 1;
2807 size_t join_params_size;
2808 chanspec_t chanspec;
2811 RETURN_EIO_IF_NOT_UP(wl);
2812 WL_INFO(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
2813 if (!params->ssid || params->ssid_len <= 0) {
2814 WL_ERR(("Invalid parameter\n"));
2817 if (wl_get_drv_status(wl, CONNECTED, dev)) {
2818 struct wlc_ssid *ssid = (struct wlc_ssid *)wl_read_prof(wl, dev, WL_PROF_SSID);
2819 u8 *bssid = (u8 *)wl_read_prof(wl, dev, WL_PROF_BSSID);
2820 if (!params->bssid || (memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0 &&
2821 memcmp(params->ssid, ssid->SSID, ssid->SSID_len) == 0)) {
2822 WL_ERR(("Connection already existed to " MACDBG "\n",
2823 MAC2STRDBG((u8 *)wl_read_prof(wl, dev, WL_PROF_BSSID))));
2826 WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
2827 ssid->SSID, MAC2STRDBG(bssid)));
2830 /* remove the VSIE */
2831 wl_cfg80211_ibss_vsie_delete(dev);
2833 bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
2835 if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
2836 memcpy(ssid.ssid, params->ssid, params->ssid_len);
2837 ssid.ssid_len = params->ssid_len;
2840 (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
2846 } while (++scan_retry < WL_SCAN_RETRY_MAX);
2848 /* wait 4 secons till scan done.... */
2849 schedule_timeout_interruptible(msecs_to_jiffies(4000));
2850 bss = cfg80211_get_ibss(wiphy, NULL,
2851 params->ssid, params->ssid_len);
2854 if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
2855 ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
2856 !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
2857 wl->ibss_starter = false;
2858 WL_DBG(("Found IBSS\n"));
2860 wl->ibss_starter = true;
2862 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
2863 chan = params->chandef.chan;
2865 chan = params->channel;
2866 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0)) */
2868 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
2869 chanspec = channel_to_chanspec(wiphy, dev, wl->channel);
2871 * Join with specific BSSID and cached SSID
2872 * If SSID is zero join based on BSSID only
2874 memset(&join_params, 0, sizeof(join_params));
2875 memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
2877 join_params.ssid.SSID_len = htod32(params->ssid_len);
2878 if (params->bssid) {
2879 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
2880 err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
2881 ETHER_ADDR_LEN, true);
2882 if (unlikely(err)) {
2883 WL_ERR(("Error (%d)\n", err));
2887 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
2889 wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED);
2891 if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
2892 scan_suppress = TRUE;
2893 /* Set the SCAN SUPRESS Flag in the firmware to skip join scan */
2894 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS, &scan_suppress, sizeof(int), true);
2895 if (unlikely(err)) {
2896 WL_ERR(("Scan Supress Setting failed(%d)\n", err));
2901 join_params.params.chanspec_list[0] = chanspec;
2902 join_params.params.chanspec_num = 1;
2903 wldev_iovar_setint(dev, "chanspec", chanspec);
2904 join_params_size = sizeof(join_params);
2906 /* Disable Authentication, IBSS will add key if it required */
2907 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
2908 wldev_iovar_setint(dev, "wsec", 0);
2910 err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
2911 join_params_size, true);
2912 if (unlikely(err)) {
2913 WL_ERR(("Error (%d)\n", err));
2917 if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
2918 scan_suppress = FALSE;
2919 /* Restore the SCAN SUPPRESS Falg */
2920 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
2921 &scan_suppress, sizeof(int), true);
2922 if (unlikely(err)) {
2923 WL_ERR(("Reset SCAN Suppress Flag failed (%d)\n", err));
2927 wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID);
2931 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
2933 struct wl_priv *wl = wiphy_priv(wiphy);
2938 RETURN_EIO_IF_NOT_UP(wl);
2940 WL_ERR(("Leave IBSS\n"));
2941 curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
2942 wl_set_drv_status(wl, DISCONNECTING, dev);
2944 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
2945 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
2946 sizeof(scb_val_t), true);
2947 if (unlikely(err)) {
2948 wl_clr_drv_status(wl, DISCONNECTING, dev);
2949 WL_ERR(("error(%d)\n", err));
2953 /* remove the VSIE */
2954 wl_cfg80211_ibss_vsie_delete(dev);
2960 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8* capa)
2963 wpa_suite_mcast_t *mcast;
2964 wpa_suite_ucast_t *ucast;
2966 wpa_suite_auth_key_mgmt_t *mgmt;
2972 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
2973 if ((len -= WPA_SUITE_LEN) <= 0)
2975 ucast = (wpa_suite_ucast_t *)&mcast[1];
2976 suite_count = ltoh16_ua(&ucast->count);
2977 if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
2978 (len -= (WPA_IE_SUITE_COUNT_LEN +
2979 (WPA_SUITE_LEN * suite_count))) <= 0)
2982 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
2983 suite_count = ltoh16_ua(&mgmt->count);
2985 if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
2986 (len -= (WPA_IE_SUITE_COUNT_LEN +
2987 (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
2988 capa[0] = *(u8 *)&mgmt->list[suite_count];
2989 capa[1] = *((u8 *)&mgmt->list[suite_count] + 1);
2998 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
3000 struct wl_priv *wl = wlcfg_drv_priv;
3001 struct wl_security *sec;
3005 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3006 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3010 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
3011 val = WPA_AUTH_PSK |
3015 WPA_AUTH_UNSPECIFIED;
3016 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
3017 val = WPA2_AUTH_PSK|
3021 WPA2_AUTH_UNSPECIFIED;
3023 val = WPA_AUTH_DISABLED;
3025 if (is_wps_conn(sme))
3026 val = WPA_AUTH_DISABLED;
3029 if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) {
3030 WL_DBG((" * wl_set_wpa_version, set wpa_auth"
3031 " to WPA_AUTH_WAPI 0x400"));
3032 val = WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED;
3035 WL_DBG(("setting wpa_auth to 0x%0x\n", val));
3036 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
3037 if (unlikely(err)) {
3038 WL_ERR(("set wpa_auth failed (%d)\n", err));
3041 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3042 sec->wpa_versions = sme->crypto.wpa_versions;
3048 wl_set_set_wapi_ie(struct net_device *dev, struct cfg80211_connect_params *sme)
3050 struct wl_priv *wl = wlcfg_drv_priv;
3053 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3054 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3058 WL_DBG((" %s \n", __FUNCTION__));
3060 if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) {
3061 err = wldev_iovar_setbuf_bsscfg(dev, "wapiie", sme->ie,
3062 sme->ie_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3064 if (unlikely(err)) {
3065 WL_ERR(("===> set_wapi_ie Error (%d)\n", err));
3069 WL_DBG((" * skip \n"));
3072 #endif /* BCMWAPI_WPI */
3075 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
3077 struct wl_priv *wl = wlcfg_drv_priv;
3078 struct wl_security *sec;
3082 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3083 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3087 switch (sme->auth_type) {
3088 case NL80211_AUTHTYPE_OPEN_SYSTEM:
3089 val = WL_AUTH_OPEN_SYSTEM;
3090 WL_DBG(("open system\n"));
3092 case NL80211_AUTHTYPE_SHARED_KEY:
3093 val = WL_AUTH_SHARED_KEY;
3094 WL_DBG(("shared key\n"));
3096 case NL80211_AUTHTYPE_AUTOMATIC:
3097 val = WL_AUTH_OPEN_SHARED;
3098 WL_DBG(("automatic\n"));
3101 case NL80211_AUTHTYPE_NETWORK_EAP:
3102 WL_DBG(("network eap\n"));
3103 val = DOT11_LEAP_AUTH;
3108 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
3112 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
3113 if (unlikely(err)) {
3114 WL_ERR(("set auth failed (%d)\n", err));
3117 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3118 sec->auth_type = sme->auth_type;
3123 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
3125 struct wl_priv *wl = wlcfg_drv_priv;
3126 struct wl_security *sec;
3141 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3142 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3146 if (sme->crypto.n_ciphers_pairwise) {
3147 switch (sme->crypto.ciphers_pairwise[0]) {
3148 case WLAN_CIPHER_SUITE_WEP40:
3149 case WLAN_CIPHER_SUITE_WEP104:
3152 case WLAN_CIPHER_SUITE_TKIP:
3153 pval = TKIP_ENABLED;
3155 case WLAN_CIPHER_SUITE_CCMP:
3156 case WLAN_CIPHER_SUITE_AES_CMAC:
3160 case WLAN_CIPHER_SUITE_SMS4:
3162 pval = SMS4_ENABLED;
3166 WL_ERR(("invalid cipher pairwise (%d)\n",
3167 sme->crypto.ciphers_pairwise[0]));
3171 #if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X)
3172 /* Ensure in-dongle supplicant is turned on when FBT wants to do the 4-way
3174 * Note that the FW feature flag only exists on kernels that support the
3177 if (wl->wdev->wiphy->features & NL80211_FEATURE_FW_4WAY_HANDSHAKE) {
3178 if (pval == AES_ENABLED)
3179 err = wldev_iovar_setint_bsscfg(dev, "sup_wpa", 1, bssidx);
3181 err = wldev_iovar_setint_bsscfg(dev, "sup_wpa", 0, bssidx);
3184 WL_ERR(("FBT: Error setting sup_wpa (%d)\n", err));
3188 #endif /* BCMSUP_4WAY_HANDSHAKE && WLAN_AKM_SUITE_FT_8021X */
3189 if (sme->crypto.cipher_group) {
3190 switch (sme->crypto.cipher_group) {
3191 case WLAN_CIPHER_SUITE_WEP40:
3192 case WLAN_CIPHER_SUITE_WEP104:
3195 case WLAN_CIPHER_SUITE_TKIP:
3196 gval = TKIP_ENABLED;
3198 case WLAN_CIPHER_SUITE_CCMP:
3201 case WLAN_CIPHER_SUITE_AES_CMAC:
3205 case WLAN_CIPHER_SUITE_SMS4:
3207 gval = SMS4_ENABLED;
3211 WL_ERR(("invalid cipher group (%d)\n",
3212 sme->crypto.cipher_group));
3217 WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
3219 if (is_wps_conn(sme)) {
3221 err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
3223 /* WPS-2.0 allows no security */
3224 err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
3227 if (sme->crypto.cipher_group == WLAN_CIPHER_SUITE_SMS4) {
3228 WL_DBG((" NO, is_wps_conn, WAPI set to SMS4_ENABLED"));
3229 err = wldev_iovar_setint_bsscfg(dev, "wsec", val, bssidx);
3232 WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
3233 wsec_val = pval | gval;
3236 if (pval == AES_ENABLED) {
3237 if (((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
3238 DOT11_MNG_RSN_ID)) != NULL) &&
3239 (wl_cfg80211_get_rsn_capa(wpa2_ie, rsn_cap) == 0)) {
3241 if (rsn_cap[0] & RSN_CAP_MFPC) {
3242 /* MFP Capability advertised by supplicant. Check
3243 * whether MFP is supported in the firmware
3245 if ((err = wldev_iovar_getint_bsscfg(dev,
3246 "mfp", &mfp, bssidx)) < 0) {
3247 WL_ERR(("Get MFP failed! "
3248 "Check MFP support in FW \n"));
3252 if ((sme->crypto.n_akm_suites == 1) &&
3253 ((sme->crypto.akm_suites[0] ==
3254 WL_AKM_SUITE_MFP_PSK) ||
3255 (sme->crypto.akm_suites[0] ==
3256 WL_AKM_SUITE_MFP_1X))) {
3257 wsec_val |= MFP_SHA256;
3258 } else if (sme->crypto.n_akm_suites > 1) {
3259 WL_ERR(("Multiple AKM Specified \n"));
3263 wsec_val |= MFP_CAPABLE;
3264 if (rsn_cap[0] & RSN_CAP_MFPR)
3265 wsec_val |= MFP_REQUIRED;
3270 WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
3271 err = wldev_iovar_setint_bsscfg(dev, "wsec",
3277 if (unlikely(err)) {
3278 WL_ERR(("error (%d)\n", err));
3282 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3283 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
3284 sec->cipher_group = sme->crypto.cipher_group;
3290 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
3292 struct wl_priv *wl = wlcfg_drv_priv;
3293 struct wl_security *sec;
3297 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3298 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3302 if (sme->crypto.n_akm_suites) {
3303 err = wldev_iovar_getint(dev, "wpa_auth", &val);
3304 if (unlikely(err)) {
3305 WL_ERR(("could not get wpa_auth (%d)\n", err));
3308 if (val & (WPA_AUTH_PSK |
3312 WPA_AUTH_UNSPECIFIED)) {
3313 switch (sme->crypto.akm_suites[0]) {
3314 case WLAN_AKM_SUITE_8021X:
3315 val = WPA_AUTH_UNSPECIFIED;
3317 case WLAN_AKM_SUITE_PSK:
3321 case WLAN_AKM_SUITE_CCKM:
3322 val = WPA_AUTH_CCKM;
3326 WL_ERR(("invalid cipher group (%d)\n",
3327 sme->crypto.cipher_group));
3330 } else if (val & (WPA2_AUTH_PSK |
3334 WPA2_AUTH_UNSPECIFIED)) {
3335 switch (sme->crypto.akm_suites[0]) {
3336 case WLAN_AKM_SUITE_8021X:
3337 val = WPA2_AUTH_UNSPECIFIED;
3340 case WL_AKM_SUITE_MFP_1X:
3341 val = WPA2_AUTH_UNSPECIFIED;
3343 case WL_AKM_SUITE_MFP_PSK:
3344 val = WPA2_AUTH_PSK;
3347 case WLAN_AKM_SUITE_PSK:
3348 val = WPA2_AUTH_PSK;
3350 #if defined(WLFBT) && defined(WLAN_AKM_SUITE_FT_8021X)
3351 case WLAN_AKM_SUITE_FT_8021X:
3352 val = WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_FT;
3355 #if defined(WLFBT) && defined(WLAN_AKM_SUITE_FT_PSK)
3356 case WLAN_AKM_SUITE_FT_PSK:
3357 val = WPA2_AUTH_PSK | WPA2_AUTH_FT;
3361 case WLAN_AKM_SUITE_CCKM:
3362 val = WPA2_AUTH_CCKM;
3366 WL_ERR(("invalid cipher group (%d)\n",
3367 sme->crypto.cipher_group));
3372 else if (val & (WAPI_AUTH_PSK | WAPI_AUTH_UNSPECIFIED)) {
3373 switch (sme->crypto.akm_suites[0]) {
3374 case WLAN_AKM_SUITE_WAPI_CERT:
3375 val = WAPI_AUTH_UNSPECIFIED;
3377 case WLAN_AKM_SUITE_WAPI_PSK:
3378 val = WAPI_AUTH_PSK;
3381 WL_ERR(("invalid cipher group (%d)\n",
3382 sme->crypto.cipher_group));
3387 WL_DBG(("setting wpa_auth to %d\n", val));
3390 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
3391 if (unlikely(err)) {
3392 WL_ERR(("could not set wpa_auth (%d)\n", err));
3396 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3397 sec->wpa_auth = sme->crypto.akm_suites[0];
3403 wl_set_set_sharedkey(struct net_device *dev,
3404 struct cfg80211_connect_params *sme)
3406 struct wl_priv *wl = wlcfg_drv_priv;
3407 struct wl_security *sec;
3408 struct wl_wsec_key key;
3412 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3413 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3417 WL_DBG(("key len (%d)\n", sme->key_len));
3419 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
3420 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
3421 sec->wpa_versions, sec->cipher_pairwise));
3422 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
3424 NL80211_WPA_VERSION_2 | NL80211_WAPI_VERSION_1)) &&
3426 NL80211_WPA_VERSION_2)) &&
3428 (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
3430 WLAN_CIPHER_SUITE_WEP104 | WLAN_CIPHER_SUITE_SMS4)))
3432 WLAN_CIPHER_SUITE_WEP104)))
3435 memset(&key, 0, sizeof(key));
3436 key.len = (u32) sme->key_len;
3437 key.index = (u32) sme->key_idx;
3438 if (unlikely(key.len > sizeof(key.data))) {
3439 WL_ERR(("Too long key length (%u)\n", key.len));
3442 memcpy(key.data, sme->key, key.len);
3443 key.flags = WL_PRIMARY_KEY;
3444 switch (sec->cipher_pairwise) {
3445 case WLAN_CIPHER_SUITE_WEP40:
3446 key.algo = CRYPTO_ALGO_WEP1;
3448 case WLAN_CIPHER_SUITE_WEP104:
3449 key.algo = CRYPTO_ALGO_WEP128;
3452 case WLAN_CIPHER_SUITE_SMS4:
3453 key.algo = CRYPTO_ALGO_SMS4;
3457 WL_ERR(("Invalid algorithm (%d)\n",
3458 sme->crypto.ciphers_pairwise[0]));
3461 /* Set the new key/index */
3462 WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
3463 key.len, key.index, key.algo));
3464 WL_DBG(("key \"%s\"\n", key.data));
3465 swap_key_from_BE(&key);
3466 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
3467 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3468 if (unlikely(err)) {
3469 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3472 if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
3473 WL_DBG(("set auth_type to shared key\n"));
3474 val = WL_AUTH_SHARED_KEY; /* shared key */
3475 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
3476 if (unlikely(err)) {
3477 WL_ERR(("set auth failed (%d)\n", err));
3486 #if defined(ESCAN_RESULT_PATCH)
3487 static u8 connect_req_bssid[6];
3488 static u8 broad_bssid[6];
3489 #endif /* ESCAN_RESULT_PATCH */
3494 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
3495 struct cfg80211_connect_params *sme)
3497 struct wl_priv *wl = wiphy_priv(wiphy);
3498 struct ieee80211_channel *chan = sme->channel;
3499 wl_extjoin_params_t *ext_join_params;
3500 struct wl_join_params join_params;
3501 size_t join_params_size;
3503 wpa_ie_fixed_t *wpa_ie;
3508 struct ether_addr bssid;
3515 if (unlikely(!sme->ssid)) {
3516 WL_ERR(("Invalid ssid\n"));
3520 if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
3521 WL_ERR(("Invalid SSID info: SSID=%s, length=%d\n",
3522 sme->ssid, sme->ssid_len));
3526 RETURN_EIO_IF_NOT_UP(wl);
3529 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
3531 #if !defined(ESCAN_RESULT_PATCH)
3532 if (wl->scan_request) {
3533 wl_notify_escan_complete(wl, dev, true, true);
3536 #if defined(ESCAN_RESULT_PATCH)
3538 memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
3540 bzero(connect_req_bssid, ETHER_ADDR_LEN);
3541 bzero(broad_bssid, ETHER_ADDR_LEN);
3543 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
3546 bzero(&bssid, sizeof(bssid));
3547 if (!wl_get_drv_status(wl, CONNECTED, dev)&&
3548 (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
3549 if (!ETHER_ISNULLADDR(&bssid)) {
3551 wl_set_drv_status(wl, DISCONNECTING, dev);
3552 scbval.val = DOT11_RC_DISASSOC_LEAVING;
3553 memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
3554 scbval.val = htod32(scbval.val);
3556 WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n",
3557 MAC2STRDBG(bssid.octet)));
3558 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3559 sizeof(scb_val_t), true);
3560 if (unlikely(err)) {
3561 wl_clr_drv_status(wl, DISCONNECTING, dev);
3562 WL_ERR(("error (%d)\n", err));
3566 while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) {
3567 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
3573 WL_DBG(("Currently not associated!\n"));
3575 /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */
3577 while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) {
3578 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt));
3585 bzero(&bssid, sizeof(bssid));
3586 if (!wl_get_drv_status(wl, DISCONNECTING, dev))
3587 wl_update_prof(wl, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
3589 if (p2p_is_on(wl) && (dev != wl_to_prmry_ndev(wl))) {
3590 /* we only allow to connect using virtual interface in case of P2P */
3591 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3592 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3595 wl_cfgp2p_set_management_ie(wl, dev, bssidx,
3596 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
3597 } else if (dev == wl_to_prmry_ndev(wl)) {
3598 /* find the RSN_IE */
3599 if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
3600 DOT11_MNG_RSN_ID)) != NULL) {
3601 WL_DBG((" WPA2 IE is found\n"));
3603 /* find the WPA_IE */
3604 if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
3605 sme->ie_len)) != NULL) {
3606 WL_DBG((" WPA IE is found\n"));
3608 if (wpa_ie != NULL || wpa2_ie != NULL) {
3609 wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
3610 wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
3611 wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
3612 wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
3613 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
3615 wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
3616 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
3619 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3620 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3623 err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
3624 VNDR_IE_ASSOCREQ_FLAG, (u8 *)sme->ie, sme->ie_len);
3625 if (unlikely(err)) {
3630 wl->channel = ieee80211_frequency_to_channel(chan->center_freq);
3632 WL_DBG(("channel (%d), center_req (%d), %d channels\n", wl->channel,
3633 chan->center_freq, chan_cnt));
3637 WL_DBG(("1. enable wapi auth\n"));
3638 if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) {
3639 WL_DBG(("2. set wapi ie \n"));
3640 err = wl_set_set_wapi_ie(dev, sme);
3644 WL_DBG(("2. Not wapi ie \n"));
3646 WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
3647 WL_DBG(("3. set wapi version \n"));
3648 err = wl_set_wpa_version(dev, sme);
3649 if (unlikely(err)) {
3650 WL_ERR(("Invalid wpa_version\n"));
3654 if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1)
3655 WL_DBG(("4. WAPI Dont Set wl_set_auth_type\n"));
3657 WL_DBG(("4. wl_set_auth_type\n"));
3659 err = wl_set_auth_type(dev, sme);
3660 if (unlikely(err)) {
3661 WL_ERR(("Invalid auth type\n"));
3668 err = wl_set_set_cipher(dev, sme);
3669 if (unlikely(err)) {
3670 WL_ERR(("Invalid ciper\n"));
3674 err = wl_set_key_mgmt(dev, sme);
3675 if (unlikely(err)) {
3676 WL_ERR(("Invalid key mgmt\n"));
3680 err = wl_set_set_sharedkey(dev, sme);
3681 if (unlikely(err)) {
3682 WL_ERR(("Invalid shared key\n"));
3687 * Join with specific BSSID and cached SSID
3688 * If SSID is zero join based on BSSID only
3690 join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
3691 chan_cnt * sizeof(chanspec_t);
3692 ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
3693 if (ext_join_params == NULL) {
3695 wl_clr_drv_status(wl, CONNECTING, dev);
3698 ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
3699 memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
3700 wl_update_prof(wl, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
3701 ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
3702 /* increate dwell time to receive probe response or detect Beacon
3703 * from target AP at a noisy air only when channel info is provided in connect command
3705 ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
3706 ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
3707 /* Set up join scan parameters */
3708 ext_join_params->scan.scan_type = -1;
3709 ext_join_params->scan.nprobes = chan_cnt ?
3710 (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
3711 ext_join_params->scan.home_time = -1;
3714 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
3716 memcpy(&ext_join_params->assoc.bssid, ðer_bcast, ETH_ALEN);
3717 ext_join_params->assoc.chanspec_num = chan_cnt;
3719 u16 channel, band, bw, ctl_sb;
3721 channel = wl->channel;
3722 band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
3723 : WL_CHANSPEC_BAND_5G;
3724 bw = WL_CHANSPEC_BW_20;
3725 ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
3726 chspec = (channel | band | bw | ctl_sb);
3727 ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
3728 ext_join_params->assoc.chanspec_list[0] |= chspec;
3729 ext_join_params->assoc.chanspec_list[0] =
3730 wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
3732 ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
3733 if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
3734 WL_INFO(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
3735 ext_join_params->ssid.SSID_len));
3737 wl_set_drv_status(wl, CONNECTING, dev);
3739 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3740 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3743 err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
3744 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3745 kfree(ext_join_params);
3747 wl_clr_drv_status(wl, CONNECTING, dev);
3748 if (err == BCME_UNSUPPORTED) {
3749 WL_DBG(("join iovar is not supported\n"));
3752 WL_ERR(("error (%d)\n", err));
3757 memset(&join_params, 0, sizeof(join_params));
3758 join_params_size = sizeof(join_params.ssid);
3760 join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
3761 memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
3762 join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
3763 wl_update_prof(wl, dev, NULL, &join_params.ssid, WL_PROF_SSID);
3765 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
3767 memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN);
3769 wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
3770 WL_DBG(("join_param_size %zu\n", join_params_size));
3772 if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
3773 WL_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
3774 join_params.ssid.SSID_len));
3776 wl_set_drv_status(wl, CONNECTING, dev);
3777 err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
3779 WL_ERR(("error (%d)\n", err));
3780 wl_clr_drv_status(wl, CONNECTING, dev);
3787 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
3790 struct wl_priv *wl = wiphy_priv(wiphy);
3795 WL_ERR(("Reason %d\n", reason_code));
3796 RETURN_EIO_IF_NOT_UP(wl);
3797 act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT);
3798 curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID);
3801 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
3803 #if !defined(ESCAN_RESULT_PATCH)
3804 /* Let scan aborted by F/W */
3805 if (wl->scan_request) {
3806 wl_notify_escan_complete(wl, dev, true, true);
3808 #endif /* ESCAN_RESULT_PATCH */
3809 wl_set_drv_status(wl, DISCONNECTING, dev);
3810 scbval.val = reason_code;
3811 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
3812 scbval.val = htod32(scbval.val);
3813 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3814 sizeof(scb_val_t), true);
3815 if (unlikely(err)) {
3816 wl_clr_drv_status(wl, DISCONNECTING, dev);
3817 WL_ERR(("error (%d)\n", err));
3826 #if defined(WL_CFG80211_P2P_DEV_IF)
3827 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
3828 enum nl80211_tx_power_setting type, s32 mbm)
3830 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
3831 enum nl80211_tx_power_setting type, s32 dbm)
3832 #endif /* WL_CFG80211_P2P_DEV_IF */
3835 struct wl_priv *wl = wiphy_priv(wiphy);
3836 struct net_device *ndev = wl_to_prmry_ndev(wl);
3841 #if defined(WL_CFG80211_P2P_DEV_IF)
3842 s32 dbm = MBM_TO_DBM(mbm);
3843 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
3844 defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
3845 dbm = MBM_TO_DBM(dbm);
3846 #endif /* WL_CFG80211_P2P_DEV_IF */
3848 RETURN_EIO_IF_NOT_UP(wl);
3850 case NL80211_TX_POWER_AUTOMATIC:
3852 case NL80211_TX_POWER_LIMITED:
3854 WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
3858 case NL80211_TX_POWER_FIXED:
3860 WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
3865 /* Make sure radio is off or on as far as software is concerned */
3866 disable = WL_RADIO_SW_DISABLE << 16;
3867 disable = htod32(disable);
3868 err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), true);
3869 if (unlikely(err)) {
3870 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
3877 txpwrmw = (u16) dbm;
3878 txpwrqdbm = (s32)bcm_mw_to_qdbm(txpwrmw);
3879 #ifdef SUPPORT_WL_TXPOWER
3880 if (type == NL80211_TX_POWER_AUTOMATIC)
3882 txpwrqdbm |= WL_TXPWR_OVERRIDE;
3883 #endif /* SUPPORT_WL_TXPOWER */
3884 err = wldev_iovar_setint(ndev, "qtxpower", txpwrqdbm);
3885 if (unlikely(err)) {
3886 WL_ERR(("qtxpower error (%d)\n", err));
3889 wl->conf->tx_power = dbm;
3895 #if defined(WL_CFG80211_P2P_DEV_IF)
3896 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
3897 struct wireless_dev *wdev, s32 *dbm)
3899 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
3900 #endif /* WL_CFG80211_P2P_DEV_IF */
3902 struct wl_priv *wl = wiphy_priv(wiphy);
3903 struct net_device *ndev = wl_to_prmry_ndev(wl);
3908 RETURN_EIO_IF_NOT_UP(wl);
3909 err = wldev_iovar_getint(ndev, "qtxpower", &txpwrdbm);
3910 if (unlikely(err)) {
3911 WL_ERR(("error (%d)\n", err));
3914 result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
3915 *dbm = (s32) bcm_qdbm_to_mw(result);
3921 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
3922 u8 key_idx, bool unicast, bool multicast)
3924 struct wl_priv *wl = wiphy_priv(wiphy);
3929 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3930 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3934 WL_DBG(("key index (%d)\n", key_idx));
3935 RETURN_EIO_IF_NOT_UP(wl);
3936 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
3937 if (unlikely(err)) {
3938 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
3941 /* fix IOT issue with Apple Airport */
3942 if (wsec == WEP_ENABLED) {
3943 /* Just select a new current key */
3944 index = (u32) key_idx;
3945 index = htod32(index);
3946 err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
3947 sizeof(index), true);
3948 if (unlikely(err)) {
3949 WL_ERR(("error (%d)\n", err));
3956 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
3957 u8 key_idx, const u8 *mac_addr, struct key_params *params)
3959 struct wl_priv *wl = wiphy_priv(wiphy);
3960 struct wl_wsec_key key;
3963 s32 mode = wl_get_mode_by_netdev(wl, dev);
3964 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
3965 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
3968 memset(&key, 0, sizeof(key));
3969 key.index = (u32) key_idx;
3971 if (!ETHER_ISMULTI(mac_addr))
3972 memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN);
3973 key.len = (u32) params->key_len;
3975 /* check for key index change */
3978 swap_key_from_BE(&key);
3979 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
3980 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
3981 if (unlikely(err)) {
3982 WL_ERR(("key delete error (%d)\n", err));
3986 if (key.len > sizeof(key.data)) {
3987 WL_ERR(("Invalid key length (%d)\n", key.len));
3990 WL_DBG(("Setting the key index %d\n", key.index));
3991 memcpy(key.data, params->key, key.len);
3993 if ((mode == WL_MODE_BSS) &&
3994 (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
3996 memcpy(keybuf, &key.data[24], sizeof(keybuf));
3997 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
3998 memcpy(&key.data[16], keybuf, sizeof(keybuf));
4001 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
4002 if (params->seq && params->seq_len == 6) {
4005 ivptr = (u8 *) params->seq;
4006 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
4007 (ivptr[3] << 8) | ivptr[2];
4008 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
4009 key.iv_initialized = true;
4012 switch (params->cipher) {
4013 case WLAN_CIPHER_SUITE_WEP40:
4014 key.algo = CRYPTO_ALGO_WEP1;
4015 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4017 case WLAN_CIPHER_SUITE_WEP104:
4018 key.algo = CRYPTO_ALGO_WEP128;
4019 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4021 case WLAN_CIPHER_SUITE_TKIP:
4022 key.algo = CRYPTO_ALGO_TKIP;
4023 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4025 case WLAN_CIPHER_SUITE_AES_CMAC:
4026 key.algo = CRYPTO_ALGO_AES_CCM;
4027 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4029 case WLAN_CIPHER_SUITE_CCMP:
4030 key.algo = CRYPTO_ALGO_AES_CCM;
4031 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
4034 case WLAN_CIPHER_SUITE_SMS4:
4035 key.algo = CRYPTO_ALGO_SMS4;
4036 WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n"));
4040 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
4043 swap_key_from_BE(&key);
4044 /* need to guarantee EAPOL 4/4 send out before set key */
4045 dhd_wait_pend8021x(dev);
4046 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4047 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
4048 if (unlikely(err)) {
4049 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4057 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
4058 u8 key_idx, bool pairwise, const u8 *mac_addr,
4059 struct key_params *params)
4061 struct wl_wsec_key key;
4067 struct wl_priv *wl = wiphy_priv(wiphy);
4068 s32 mode = wl_get_mode_by_netdev(wl, dev);
4069 WL_DBG(("key index (%d)\n", key_idx));
4070 RETURN_EIO_IF_NOT_UP(wl);
4072 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
4073 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4078 ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
4079 (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
4080 wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
4083 memset(&key, 0, sizeof(key));
4085 key.len = (u32) params->key_len;
4086 key.index = (u32) key_idx;
4088 if (unlikely(key.len > sizeof(key.data))) {
4089 WL_ERR(("Too long key length (%u)\n", key.len));
4092 memcpy(key.data, params->key, key.len);
4094 key.flags = WL_PRIMARY_KEY;
4095 switch (params->cipher) {
4096 case WLAN_CIPHER_SUITE_WEP40:
4097 key.algo = CRYPTO_ALGO_WEP1;
4099 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4101 case WLAN_CIPHER_SUITE_WEP104:
4102 key.algo = CRYPTO_ALGO_WEP128;
4104 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4106 case WLAN_CIPHER_SUITE_TKIP:
4107 key.algo = CRYPTO_ALGO_TKIP;
4109 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
4110 if (mode == WL_MODE_BSS) {
4111 bcopy(&key.data[24], keybuf, sizeof(keybuf));
4112 bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
4113 bcopy(keybuf, &key.data[16], sizeof(keybuf));
4115 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4117 case WLAN_CIPHER_SUITE_AES_CMAC:
4118 key.algo = CRYPTO_ALGO_AES_CCM;
4120 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4122 case WLAN_CIPHER_SUITE_CCMP:
4123 key.algo = CRYPTO_ALGO_AES_CCM;
4125 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
4128 case WLAN_CIPHER_SUITE_SMS4:
4129 key.algo = CRYPTO_ALGO_SMS4;
4130 WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n"));
4133 #endif /* BCMWAPI_WPI */
4134 #if defined(WLFBT) && defined(WLAN_CIPHER_SUITE_PMK)
4135 case WLAN_CIPHER_SUITE_PMK: {
4138 char keystring[WSEC_MAX_PSK_LEN + 1];
4139 char* charptr = keystring;
4142 /* copy the raw hex key to the appropriate format */
4143 for (j = 0; j < (WSEC_MAX_PSK_LEN / 2); j++) {
4144 sprintf(charptr, "%02x", params->key[j]);
4147 len = strlen(keystring);
4148 pmk.key_len = htod16(len);
4149 bcopy(keystring, pmk.key, len);
4150 pmk.flags = htod16(WSEC_PASSPHRASE);
4152 err = wldev_ioctl(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk), true);
4156 #endif /* WLFBT && WLAN_CIPHER_SUITE_PMK */
4158 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
4162 /* Set the new key/index */
4163 if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
4164 WL_ERR(("IBSS KEY setted\n"));
4165 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
4167 swap_key_from_BE(&key);
4168 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf,
4169 WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
4170 if (unlikely(err)) {
4171 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4176 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4177 if (unlikely(err)) {
4178 WL_ERR(("get wsec error (%d)\n", err));
4183 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
4184 if (unlikely(err)) {
4185 WL_ERR(("set wsec error (%d)\n", err));
4193 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
4194 u8 key_idx, bool pairwise, const u8 *mac_addr)
4196 struct wl_wsec_key key;
4197 struct wl_priv *wl = wiphy_priv(wiphy);
4200 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
4201 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4204 WL_DBG(("Enter\n"));
4207 if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
4211 RETURN_EIO_IF_NOT_UP(wl);
4212 memset(&key, 0, sizeof(key));
4214 key.flags = WL_PRIMARY_KEY;
4215 key.algo = CRYPTO_ALGO_OFF;
4216 key.index = (u32) key_idx;
4218 WL_DBG(("key index (%d)\n", key_idx));
4219 /* Set the new key/index */
4220 swap_key_from_BE(&key);
4221 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), wl->ioctl_buf,
4222 WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
4223 if (unlikely(err)) {
4224 if (err == -EINVAL) {
4225 if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
4226 /* we ignore this key index in this case */
4227 WL_DBG(("invalid key index (%d)\n", key_idx));
4230 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4238 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
4239 u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
4240 void (*callback) (void *cookie, struct key_params * params))
4242 struct key_params params;
4243 struct wl_wsec_key key;
4244 struct wl_priv *wl = wiphy_priv(wiphy);
4245 struct wl_security *sec;
4249 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
4250 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
4253 WL_DBG(("key index (%d)\n", key_idx));
4254 RETURN_EIO_IF_NOT_UP(wl);
4255 memset(&key, 0, sizeof(key));
4256 key.index = key_idx;
4257 swap_key_to_BE(&key);
4258 memset(¶ms, 0, sizeof(params));
4259 params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
4260 memcpy(params.key, key.data, params.key_len);
4262 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4263 if (unlikely(err)) {
4264 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
4267 switch (wsec & ~SES_OW_ENABLED) {
4269 sec = wl_read_prof(wl, dev, WL_PROF_SEC);
4270 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
4271 params.cipher = WLAN_CIPHER_SUITE_WEP40;
4272 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4273 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
4274 params.cipher = WLAN_CIPHER_SUITE_WEP104;
4275 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4279 params.cipher = WLAN_CIPHER_SUITE_TKIP;
4280 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4283 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
4284 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4287 case WLAN_CIPHER_SUITE_SMS4:
4288 key.algo = CRYPTO_ALGO_SMS4;
4289 WL_DBG(("WLAN_CIPHER_SUITE_SMS4\n"));
4293 WL_ERR(("Invalid algo (0x%x)\n", wsec));
4297 callback(cookie, ¶ms);
4301 // terence 20130703: Fix for wrong group_capab (timing issue)
4302 int p2p_disconnected = 0;
4303 struct ether_addr p2p_disconnected_bssid;
4305 #if defined(RSSIAVG)
4306 static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
4307 static wl_rssi_cache_ctrl_t g_rssi2_cache_ctrl;
4309 #if defined(BSSCACHE)
4310 static wl_bss_cache_ctrl_t g_bss_cache_ctrl;
4314 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
4315 struct net_device *dev, u8 key_idx)
4317 WL_INFO(("Not supported\n"));
4322 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
4323 u8 *mac, struct station_info *sinfo)
4325 struct wl_priv *wl = wiphy_priv(wiphy);
4331 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) || defined(WL_COMPAT_WIRELESS)
4332 s8 eabuf[ETHER_ADDR_STR_LEN];
4334 static int err_cnt = 0;
4335 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
4336 RETURN_EIO_IF_NOT_UP(wl);
4337 if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) {
4338 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
4339 ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync);
4341 WL_ERR(("GET STA INFO failed, %d\n", err));
4344 sinfo->filled = STATION_INFO_INACTIVE_TIME;
4345 sta = (sta_info_t *)wl->ioctl_buf;
4346 sta->len = dtoh16(sta->len);
4347 sta->cap = dtoh16(sta->cap);
4348 sta->flags = dtoh32(sta->flags);
4349 sta->idle = dtoh32(sta->idle);
4350 sta->in = dtoh32(sta->in);
4351 sinfo->inactive_time = sta->idle * 1000;
4352 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) || defined(WL_COMPAT_WIRELESS)
4353 if (sta->flags & WL_STA_ASSOC) {
4354 sinfo->filled |= STATION_INFO_CONNECTED_TIME;
4355 sinfo->connected_time = sta->in;
4357 WL_INFO(("STA %s : idle time : %d sec, connected time :%d ms\n",
4358 bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
4361 } else if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_BSS ||
4362 wl_get_mode_by_netdev(wl, dev) == WL_MODE_IBSS) {
4363 get_pktcnt_t pktcnt;
4364 u8 *curmacp = wl_read_prof(wl, dev, WL_PROF_BSSID);
4365 if (!wl_get_drv_status(wl, CONNECTED, dev) ||
4366 (dhd_is_associated(dhd, NULL, &err) == FALSE)) {
4367 WL_ERR(("NOT assoc\n"));
4368 if (err == -ERESTARTSYS)
4373 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
4374 WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
4375 MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
4378 /* Report the current tx rate */
4379 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
4381 WL_ERR(("Could not get rate (%d)\n", err));
4383 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4386 rate = dtoh32(rate);
4387 sinfo->filled |= STATION_INFO_TX_BITRATE;
4388 sinfo->txrate.legacy = rate * 5;
4389 WL_DBG(("Rate %d Mbps\n", (rate / 2)));
4390 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4391 rxpktglom = ((rate/2) > 150) ? 20 : 10;
4393 if (maxrxpktglom != rxpktglom) {
4394 maxrxpktglom = rxpktglom;
4395 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
4397 err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
4398 (char*)&maxrxpktglom, 4, wl->ioctl_buf,
4399 WLC_IOCTL_MAXLEN, NULL);
4401 WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
4407 memset(&scb_val, 0, sizeof(scb_val));
4409 err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
4410 sizeof(scb_val_t), false);
4412 WL_ERR(("Could not get rssi (%d)\n", err));
4413 goto get_station_err;
4415 rssi = dtoh32(scb_val.val);
4416 #if defined(RSSIAVG)
4417 err = wl_update_connected_rssi_cache(dev, &g_rssi2_cache_ctrl, &rssi);
4419 WL_ERR(("Could not get rssi (%d)\n", err));
4420 goto get_station_err;
4422 wl_delete_dirty_rssi_cache(&g_rssi2_cache_ctrl);
4423 wl_reset_rssi_cache(&g_rssi2_cache_ctrl);
4425 #if defined(RSSIOFFSET)
4426 rssi = wl_update_rssi_offset(rssi);
4428 sinfo->filled |= STATION_INFO_SIGNAL;
4429 sinfo->signal = rssi;
4430 WL_DBG(("RSSI %d dBm\n", rssi));
4431 err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt,
4432 sizeof(pktcnt), false);
4434 sinfo->filled |= (STATION_INFO_RX_PACKETS |
4435 STATION_INFO_RX_DROP_MISC |
4436 STATION_INFO_TX_PACKETS |
4437 STATION_INFO_TX_FAILED);
4438 sinfo->rx_packets = pktcnt.rx_good_pkt;
4439 sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
4440 sinfo->tx_packets = pktcnt.tx_good_pkt;
4441 sinfo->tx_failed = pktcnt.tx_bad_pkt;
4448 if (err_cnt >= 3 && (err != -ERESTARTSYS)) {
4449 /* Disconnect due to zero BSSID or error to get RSSI */
4450 WL_ERR(("force cfg80211_disconnected: %d\n", err));
4451 wl_clr_drv_status(wl, CONNECTED, dev);
4452 cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL);
4457 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(wl, dev)));
4463 /* Function to update sta power save mode for Kernel wifi stack */
4464 int wl_cfg80211_update_power_mode(struct net_device *dev)
4469 err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), false);
4470 if (err || (pm == -1)) {
4471 WL_ERR(("error (%d)\n", err));
4473 pm = (pm == PM_OFF) ? false : true;
4474 WL_DBG(("%s: %d\n", __func__, pm));
4475 if (dev->ieee80211_ptr)
4476 dev->ieee80211_ptr->ps = pm;
4482 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
4483 bool enabled, s32 timeout)
4487 struct wl_priv *wl = wiphy_priv(wiphy);
4488 struct net_info *_net_info = wl_get_netinfo_by_netdev(wl, dev);
4489 #if !defined(SUPPORT_PM2_ONLY)
4490 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
4491 #endif /* (OEM_ANDROID) */
4492 RETURN_EIO_IF_NOT_UP(wl);
4493 WL_DBG(("Enter\n"));
4494 #if defined(WL_ENABLE_P2P_IF)
4495 if (wl->p2p_net == dev || _net_info == NULL || wl->vsdb_mode ||
4496 !wl_get_drv_status(wl, CONNECTED, dev))
4498 if (_net_info == NULL || wl->vsdb_mode ||
4499 !wl_get_drv_status(wl, CONNECTED, dev))
4500 #endif /* WL_ENABLE_P2P_IF */
4504 WL_DBG(("%s: Enter power save enabled %d\n", dev->name, enabled));
4506 /* Delete pm_enable_work */
4507 if (wl->pm_enable_work_on) {
4508 cancel_delayed_work_sync(&wl->pm_enable_work);
4509 wl->pm_enable_work_on = false;
4512 #if !defined(SUPPORT_PM2_ONLY)
4513 /* android has special hooks to change pm when kernel suspended */
4514 pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF;
4516 pm = enabled ? PM_FAST : PM_OFF;
4517 #endif /* SUPPORT_PM2_ONLY */
4518 if (_net_info->pm_block) {
4519 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
4520 dev->name, _net_info->pm_block));
4524 WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
4525 err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
4526 if (unlikely(err)) {
4528 WL_DBG(("net_device is not ready yet\n"));
4530 WL_ERR(("error (%d)\n", err));
4536 static __used u32 wl_find_msb(u16 bit16)
4540 if (bit16 & 0xff00) {
4563 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
4565 struct wl_priv *wl = wiphy_priv(wiphy);
4566 struct net_device *ndev = wl_to_prmry_ndev(wl);
4569 if (unlikely(!wl_get_drv_status(wl, READY, ndev))) {
4570 WL_INFO(("device is not ready\n"));
4574 wl_invoke_iscan(wl);
4580 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
4581 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
4583 wl_cfg80211_suspend(struct wiphy *wiphy)
4586 #ifdef DHD_CLEAR_ON_SUSPEND
4587 struct wl_priv *wl = wiphy_priv(wiphy);
4588 struct net_info *iter, *next;
4589 struct net_device *ndev = wl_to_prmry_ndev(wl);
4590 unsigned long flags;
4591 if (unlikely(!wl_get_drv_status(wl, READY, ndev))) {
4592 WL_INFO(("device is not ready : status (%d)\n",
4596 for_each_ndev(wl, iter, next)
4597 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
4599 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
4600 if (wl->scan_request) {
4601 cfg80211_scan_done(wl->scan_request, true);
4602 wl->scan_request = NULL;
4604 for_each_ndev(wl, iter, next) {
4605 wl_clr_drv_status(wl, SCANNING, iter->ndev);
4606 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
4608 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
4609 for_each_ndev(wl, iter, next) {
4610 if (wl_get_drv_status(wl, CONNECTING, iter->ndev)) {
4611 wl_bss_connect_done(wl, iter->ndev, NULL, NULL, false);
4614 #endif /* DHD_CLEAR_ON_SUSPEND */
4619 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
4623 struct wl_priv *wl = wlcfg_drv_priv;
4624 struct net_device *primary_dev = wl_to_prmry_ndev(wl);
4627 printk("pmk_list is NULL\n");
4630 /* pmk list is supported only for STA interface i.e. primary interface
4631 * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
4633 if (primary_dev != dev) {
4634 WL_INFO(("Not supporting Flushing pmklist on virtual"
4635 " interfaces than primary interface\n"));
4639 WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
4640 for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
4641 WL_DBG(("PMKID[%d]: %pM =\n", i,
4642 &pmk_list->pmkids.pmkid[i].BSSID));
4643 for (j = 0; j < WPA2_PMKID_LEN; j++) {
4644 WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
4648 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
4649 sizeof(*pmk_list), wl->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
4656 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
4657 struct cfg80211_pmksa *pmksa)
4659 struct wl_priv *wl = wiphy_priv(wiphy);
4663 RETURN_EIO_IF_NOT_UP(wl);
4664 for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
4665 if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
4668 if (i < WL_NUM_PMKIDS_MAX) {
4669 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
4671 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
4673 if (i == wl->pmk_list->pmkids.npmkid)
4674 wl->pmk_list->pmkids.npmkid++;
4678 WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
4679 &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].BSSID));
4680 for (i = 0; i < WPA2_PMKID_LEN; i++) {
4682 wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid - 1].
4686 err = wl_update_pmklist(dev, wl->pmk_list, err);
4692 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
4693 struct cfg80211_pmksa *pmksa)
4695 struct wl_priv *wl = wiphy_priv(wiphy);
4696 struct _pmkid_list pmkid = {0};
4700 RETURN_EIO_IF_NOT_UP(wl);
4701 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
4702 memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
4704 WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
4705 &pmkid.pmkid[0].BSSID));
4706 for (i = 0; i < WPA2_PMKID_LEN; i++) {
4707 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
4710 for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++)
4712 (pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID,
4716 if ((wl->pmk_list->pmkids.npmkid > 0) &&
4717 (i < wl->pmk_list->pmkids.npmkid)) {
4718 memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
4719 for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) {
4720 memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID,
4721 &wl->pmk_list->pmkids.pmkid[i + 1].BSSID,
4723 memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
4724 &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
4727 wl->pmk_list->pmkids.npmkid--;
4732 err = wl_update_pmklist(dev, wl->pmk_list, err);
4739 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
4741 struct wl_priv *wl = wiphy_priv(wiphy);
4743 RETURN_EIO_IF_NOT_UP(wl);
4744 memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
4745 err = wl_update_pmklist(dev, wl->pmk_list, err);
4750 static wl_scan_params_t *
4751 wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
4753 wl_scan_params_t *params;
4757 *out_params_size = 0;
4759 /* Our scan params only need space for 1 channel and 0 ssids */
4760 params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
4761 params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
4762 if (params == NULL) {
4763 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
4766 memset(params, 0, params_size);
4767 params->nprobes = nprobes;
4769 num_chans = (channel == 0) ? 0 : 1;
4771 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
4772 params->bss_type = DOT11_BSSTYPE_ANY;
4773 params->scan_type = DOT11_SCANTYPE_ACTIVE;
4774 params->nprobes = htod32(1);
4775 params->active_time = htod32(-1);
4776 params->passive_time = htod32(-1);
4777 params->home_time = htod32(10);
4779 params->channel_list[0] = htodchanspec(channel);
4781 params->channel_list[0] = wl_ch_host_to_driver(channel);
4783 /* Our scan params have 1 channel and 0 ssids */
4784 params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
4785 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
4787 *out_params_size = params_size; /* rtn size to the caller */
4792 #if defined(WL_CFG80211_P2P_DEV_IF)
4793 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4794 struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
4796 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
4797 struct ieee80211_channel * channel,
4798 enum nl80211_channel_type channel_type,
4799 unsigned int duration, u64 *cookie)
4800 #endif /* WL_CFG80211_P2P_DEV_IF */
4805 struct ether_addr primary_mac;
4806 struct net_device *ndev = NULL;
4807 struct wl_priv *wl = wiphy_priv(wiphy);
4809 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
4811 WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
4812 ieee80211_frequency_to_channel(channel->center_freq),
4813 duration, (wl_get_drv_status(wl, SCANNING, ndev)) ? "YES":"NO"));
4816 WL_ERR(("wl->p2p is not initialized\n"));
4821 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4822 if (wl_get_drv_status_all(wl, SCANNING)) {
4823 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
4825 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4827 target_channel = ieee80211_frequency_to_channel(channel->center_freq);
4828 memcpy(&wl->remain_on_chan, channel, sizeof(struct ieee80211_channel));
4829 #if defined(WL_ENABLE_P2P_IF)
4830 wl->remain_on_chan_type = channel_type;
4831 #endif /* WL_ENABLE_P2P_IF */
4832 id = ++wl->last_roc_id;
4834 id = ++wl->last_roc_id;
4837 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4838 if (wl_get_drv_status(wl, SCANNING, ndev)) {
4839 struct timer_list *_timer;
4840 WL_DBG(("scan is running. go to fake listen state\n"));
4842 wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4844 if (timer_pending(&wl->p2p->listen_timer)) {
4845 WL_DBG(("cancel current listen timer \n"));
4846 del_timer_sync(&wl->p2p->listen_timer);
4849 _timer = &wl->p2p->listen_timer;
4850 wl_clr_p2p_status(wl, LISTEN_EXPIRED);
4852 INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
4857 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4859 #ifdef WL_CFG80211_SYNC_GON
4860 if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) {
4861 /* do not enter listen mode again if we are in listen mode already for next af.
4862 * remain on channel completion will be returned by waiting next af completion.
4864 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4865 wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4867 wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4868 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4871 #endif /* WL_CFG80211_SYNC_GON */
4872 if (wl->p2p && !wl->p2p->on) {
4873 /* In case of p2p_listen command, supplicant send remain_on_channel
4874 * without turning on P2P
4876 get_primary_mac(wl, &primary_mac);
4877 wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
4881 if (p2p_is_on(wl)) {
4882 err = wl_cfgp2p_enable_discovery(wl, ndev, NULL, 0);
4883 if (unlikely(err)) {
4886 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4887 wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4888 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4889 err = wl_cfgp2p_discover_listen(wl, target_channel, duration);
4891 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
4892 if (err == BCME_OK) {
4893 wl_set_drv_status(wl, REMAINING_ON_CHANNEL, ndev);
4895 /* if failed, firmware may be internal scanning state.
4896 * so other scan request shall not abort it
4898 wl_set_drv_status(wl, FAKE_REMAINING_ON_CHANNEL, ndev);
4900 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
4901 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
4902 * and expire timer will send a completion to the upper layer
4908 if (err == BCME_OK) {
4909 WL_INFO(("Success\n"));
4910 #if defined(WL_CFG80211_P2P_DEV_IF)
4911 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
4912 duration, GFP_KERNEL);
4914 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
4915 channel_type, duration, GFP_KERNEL);
4916 #endif /* WL_CFG80211_P2P_DEV_IF */
4918 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
4924 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
4925 bcm_struct_cfgdev *cfgdev, u64 cookie)
4929 #if defined(WL_CFG80211_P2P_DEV_IF)
4930 if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
4931 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
4934 WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
4935 #endif /* WL_CFG80211_P2P_DEV_IF */
4940 wl_cfg80211_afx_handler(struct work_struct *work)
4942 struct afx_hdl *afx_instance;
4943 struct wl_priv *wl = wlcfg_drv_priv;
4946 afx_instance = container_of(work, struct afx_hdl, work);
4947 if (afx_instance != NULL && wl->afx_hdl->is_active) {
4948 if (wl->afx_hdl->is_listen && wl->afx_hdl->my_listen_chan) {
4949 ret = wl_cfgp2p_discover_listen(wl, wl->afx_hdl->my_listen_chan,
4950 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
4952 ret = wl_cfgp2p_act_frm_search(wl, wl->afx_hdl->dev,
4953 wl->afx_hdl->bssidx, wl->afx_hdl->peer_listen_chan,
4956 if (unlikely(ret != BCME_OK)) {
4957 WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
4958 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL))
4959 complete(&wl->act_frm_scan);
4965 wl_cfg80211_af_searching_channel(struct wl_priv *wl, struct net_device *dev)
4967 u32 max_retry = WL_CHANNEL_SYNC_RETRY;
4972 WL_DBG((" enter ) \n"));
4974 wl_set_drv_status(wl, FINDING_COMMON_CHANNEL, dev);
4975 wl->afx_hdl->is_active = TRUE;
4977 /* Loop to wait until we find a peer's channel or the
4978 * pending action frame tx is cancelled.
4980 while ((wl->afx_hdl->retry < max_retry) &&
4981 (wl->afx_hdl->peer_chan == WL_INVALID)) {
4982 wl->afx_hdl->is_listen = FALSE;
4983 wl_set_drv_status(wl, SCANNING, dev);
4984 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
4985 wl->afx_hdl->retry));
4986 /* search peer on peer's listen channel */
4987 schedule_work(&wl->afx_hdl->work);
4988 wait_for_completion_timeout(&wl->act_frm_scan,
4989 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
4991 if ((wl->afx_hdl->peer_chan != WL_INVALID) ||
4992 !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)))
4995 if (wl->afx_hdl->my_listen_chan) {
4996 WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
4997 wl->afx_hdl->my_listen_chan));
4998 /* listen on my listen channel */
4999 wl->afx_hdl->is_listen = TRUE;
5000 schedule_work(&wl->afx_hdl->work);
5001 wait_for_completion_timeout(&wl->act_frm_scan,
5002 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
5004 if ((wl->afx_hdl->peer_chan != WL_INVALID) ||
5005 !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)))
5008 wl->afx_hdl->retry++;
5010 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
5013 wl->afx_hdl->is_active = FALSE;
5015 wl_clr_drv_status(wl, SCANNING, dev);
5016 wl_clr_drv_status(wl, FINDING_COMMON_CHANNEL, dev);
5018 return (wl->afx_hdl->peer_chan);
5021 struct p2p_config_af_params {
5022 s32 max_tx_retry; /* max tx retry count if tx no ack */
5023 /* To make sure to send successfully action frame, we have to turn off mpc
5024 * 0: off, 1: on, (-1): do nothing
5027 #ifdef WL_CFG80211_SYNC_GON
5030 bool search_channel; /* 1: search peer's channel to send af */
5034 wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
5035 wl_action_frame_t *action_frame, wl_af_params_t *af_params,
5036 struct p2p_config_af_params *config_af_params)
5039 struct wl_priv *wl = wiphy_priv(wiphy);
5040 wifi_p2p_pub_act_frame_t *act_frm =
5041 (wifi_p2p_pub_act_frame_t *) (action_frame->data);
5043 /* initialize default value */
5044 #ifdef WL_CFG80211_SYNC_GON
5045 config_af_params->extra_listen = true;
5047 config_af_params->search_channel = false;
5048 config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
5049 config_af_params->mpc_onoff = -1;
5050 wl->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
5052 switch (act_frm->subtype) {
5053 case P2P_PAF_GON_REQ: {
5054 WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
5055 wl_set_p2p_status(wl, GO_NEG_PHASE);
5057 config_af_params->mpc_onoff = 0;
5058 config_af_params->search_channel = true;
5059 wl->next_af_subtype = act_frm->subtype + 1;
5061 /* increase dwell time to wait for RESP frame */
5062 af_params->dwell_time = WL_MED_DWELL_TIME;
5066 case P2P_PAF_GON_RSP: {
5067 wl->next_af_subtype = act_frm->subtype + 1;
5068 /* increase dwell time to wait for CONF frame */
5069 af_params->dwell_time = WL_MED_DWELL_TIME + 100;
5072 case P2P_PAF_GON_CONF: {
5073 /* If we reached till GO Neg confirmation reset the filter */
5074 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
5075 wl_clr_p2p_status(wl, GO_NEG_PHASE);
5077 /* turn on mpc again if go nego is done */
5078 config_af_params->mpc_onoff = 1;
5080 /* minimize dwell time */
5081 af_params->dwell_time = WL_MIN_DWELL_TIME;
5083 #ifdef WL_CFG80211_SYNC_GON
5084 config_af_params->extra_listen = false;
5085 #endif /* WL_CFG80211_SYNC_GON */
5088 case P2P_PAF_INVITE_REQ: {
5089 config_af_params->search_channel = true;
5090 wl->next_af_subtype = act_frm->subtype + 1;
5092 /* increase dwell time */
5093 af_params->dwell_time = WL_MED_DWELL_TIME;
5096 case P2P_PAF_INVITE_RSP:
5097 /* minimize dwell time */
5098 af_params->dwell_time = WL_MIN_DWELL_TIME;
5099 #ifdef WL_CFG80211_SYNC_GON
5100 config_af_params->extra_listen = false;
5101 #endif /* WL_CFG80211_SYNC_GON */
5103 case P2P_PAF_DEVDIS_REQ: {
5104 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
5105 action_frame->len)) {
5106 config_af_params->search_channel = true;
5109 wl->next_af_subtype = act_frm->subtype + 1;
5110 /* maximize dwell time to wait for RESP frame */
5111 af_params->dwell_time = WL_LONG_DWELL_TIME;
5114 case P2P_PAF_DEVDIS_RSP:
5115 /* minimize dwell time */
5116 af_params->dwell_time = WL_MIN_DWELL_TIME;
5117 #ifdef WL_CFG80211_SYNC_GON
5118 config_af_params->extra_listen = false;
5119 #endif /* WL_CFG80211_SYNC_GON */
5121 case P2P_PAF_PROVDIS_REQ: {
5122 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
5123 action_frame->len)) {
5124 config_af_params->search_channel = true;
5127 config_af_params->mpc_onoff = 0;
5128 wl->next_af_subtype = act_frm->subtype + 1;
5129 /* increase dwell time to wait for RESP frame */
5130 af_params->dwell_time = WL_MED_DWELL_TIME;
5133 case P2P_PAF_PROVDIS_RSP: {
5134 wl->next_af_subtype = P2P_PAF_GON_REQ;
5135 af_params->dwell_time = WL_MIN_DWELL_TIME;
5136 #ifdef WL_CFG80211_SYNC_GON
5137 config_af_params->extra_listen = false;
5138 #endif /* WL_CFG80211_SYNC_GON */
5142 WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
5151 wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
5152 bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
5153 wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
5156 struct net_device *ndev = NULL;
5158 struct wl_priv *wl = wiphy_priv(wiphy);
5160 u8 category, action;
5162 struct p2p_config_af_params config_af_params;
5164 ulong off_chan_started_jiffies = 0;
5166 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
5169 #if defined(WL_CFG80211_P2P_DEV_IF)
5172 ndev = ndev_to_cfgdev(cfgdev);
5173 #endif /* WL_CFG80211_P2P_DEV_IF */
5176 category = action_frame->data[DOT11_ACTION_CAT_OFF];
5177 action = action_frame->data[DOT11_ACTION_ACT_OFF];
5179 /* initialize variables */
5181 wl->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
5182 config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
5183 config_af_params.mpc_onoff = -1;
5184 config_af_params.search_channel = false;
5185 #ifdef WL_CFG80211_SYNC_GON
5186 config_af_params.extra_listen = false;
5189 /* config parameters */
5190 /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
5191 if (category == DOT11_ACTION_CAT_PUBLIC) {
5192 if ((action == P2P_PUB_AF_ACTION) &&
5193 (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
5194 /* p2p public action frame process */
5195 if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
5196 action_frame, af_params, &config_af_params)) {
5197 WL_DBG(("Unknown subtype.\n"));
5200 } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
5201 /* service discovery process */
5202 if (action == P2PSD_ACTION_ID_GAS_IREQ ||
5203 action == P2PSD_ACTION_ID_GAS_CREQ) {
5204 /* configure service discovery query frame */
5206 config_af_params.search_channel = true;
5208 /* save next af suptype to cancel remained dwell time */
5209 wl->next_af_subtype = action + 1;
5211 af_params->dwell_time = WL_MED_DWELL_TIME;
5212 } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
5213 action == P2PSD_ACTION_ID_GAS_CRESP) {
5214 /* configure service discovery response frame */
5215 af_params->dwell_time = WL_MIN_DWELL_TIME;
5217 WL_DBG(("Unknown action type: %d\n", action));
5220 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
5221 category, action, action_frame_len));
5223 } else if (category == P2P_AF_CATEGORY) {
5224 /* do not configure anything. it will be sent with a default configuration */
5226 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
5228 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
5229 wl_clr_drv_status(wl, SENDING_ACT_FRM, dev);
5234 /* To make sure to send successfully action frame, we have to turn off mpc */
5235 if (config_af_params.mpc_onoff == 0) {
5236 wldev_iovar_setint(dev, "mpc", 0);
5239 /* validate channel and p2p ies */
5240 if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
5241 wl_to_p2p_bss_saved_ie(wl, P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len) {
5242 config_af_params.search_channel = true;
5244 config_af_params.search_channel = false;
5248 if (ndev == wl_to_prmry_ndev(wl))
5249 config_af_params.search_channel = false;
5253 /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
5254 if (wl_get_drv_status(wl, CONNECTING, wl_to_prmry_ndev(wl))) {
5259 /* if scan is ongoing, abort current scan. */
5260 if (wl_get_drv_status_all(wl, SCANNING)) {
5261 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
5264 /* set status and destination address before sending af */
5265 if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
5266 /* set this status to cancel the remained dwell time in rx process */
5267 wl_set_drv_status(wl, WAITING_NEXT_ACT_FRM, dev);
5269 wl_set_drv_status(wl, SENDING_ACT_FRM, dev);
5270 memcpy(wl->afx_hdl->tx_dst_addr.octet,
5271 af_params->action_frame.da.octet,
5272 sizeof(wl->afx_hdl->tx_dst_addr.octet));
5274 /* save af_params for rx process */
5275 wl->afx_hdl->pending_tx_act_frm = af_params;
5277 /* search peer's channel */
5278 if (config_af_params.search_channel) {
5279 /* initialize afx_hdl */
5280 if (wl_cfgp2p_find_idx(wl, dev, &wl->afx_hdl->bssidx) != BCME_OK) {
5281 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
5284 wl->afx_hdl->dev = dev;
5285 wl->afx_hdl->retry = 0;
5286 wl->afx_hdl->peer_chan = WL_INVALID;
5288 if (wl_cfg80211_af_searching_channel(wl, dev) == WL_INVALID) {
5289 WL_ERR(("couldn't find peer's channel.\n"));
5290 wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
5291 af_params->channel);
5295 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
5297 * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
5298 * but after the check of piggyback algorithm.
5299 * To take care of current piggback algo, lets abort the scan here itself.
5301 wl_notify_escan_complete(wl, dev, true, true);
5302 /* Suspend P2P discovery's search-listen to prevent it from
5303 * starting a scan or changing the channel.
5305 wl_cfgp2p_discover_enable_search(wl, false);
5307 /* update channel */
5308 af_params->channel = wl->afx_hdl->peer_chan;
5312 off_chan_started_jiffies = jiffies;
5315 wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
5317 /* Now send a tx action frame */
5318 ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ? false : true;
5320 /* if failed, retry it. tx_retry_max value is configure by .... */
5321 while ((ack == false) && (tx_retry++ < config_af_params.max_tx_retry)) {
5323 if (af_params->channel) {
5324 if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
5325 OFF_CHAN_TIME_THRESHOLD_MS) {
5326 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl);
5327 off_chan_started_jiffies = jiffies;
5329 OSL_SLEEP(AF_RETRY_DELAY_TIME);
5332 ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ?
5336 WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
5339 /* Clear SENDING_ACT_FRM after all sending af is done */
5340 wl_clr_drv_status(wl, SENDING_ACT_FRM, dev);
5342 #ifdef WL_CFG80211_SYNC_GON
5343 /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
5344 * if we coundn't get the next action response frame and dongle does not keep
5345 * the dwell time, go to listen state again to get next action response frame.
5347 if (ack && config_af_params.extra_listen &&
5348 wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM) &&
5349 wl->af_sent_channel == wl->afx_hdl->my_listen_chan) {
5350 s32 extar_listen_time;
5352 extar_listen_time = af_params->dwell_time -
5353 jiffies_to_msecs(jiffies - wl->af_tx_sent_jiffies);
5355 if (extar_listen_time > 50) {
5356 wl_set_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, dev);
5357 WL_DBG(("Wait more time! actual af time:%d,"
5358 "calculated extar listen:%d\n",
5359 af_params->dwell_time, extar_listen_time));
5360 if (wl_cfgp2p_discover_listen(wl, wl->af_sent_channel,
5361 extar_listen_time + 100) == BCME_OK) {
5362 wait_for_completion_timeout(&wl->wait_next_af,
5363 msecs_to_jiffies(extar_listen_time + 100 + 300));
5365 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM_LISTEN, dev);
5368 #endif /* WL_CFG80211_SYNC_GON */
5369 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, dev);
5371 if (wl->afx_hdl->pending_tx_act_frm)
5372 wl->afx_hdl->pending_tx_act_frm = NULL;
5374 WL_INFO(("-- sending Action Frame is %s, listen chan: %d\n",
5375 (ack) ? "Succeeded!!":"Failed!!", wl->afx_hdl->my_listen_chan));
5378 /* if all done, turn mpc on again */
5379 if (config_af_params.mpc_onoff == 1) {
5380 wldev_iovar_setint(dev, "mpc", 1);
5386 #define MAX_NUM_OF_ASSOCIATED_DEV 64
5388 #if defined(WL_CFG80211_P2P_DEV_IF)
5389 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5390 struct ieee80211_channel *channel, bool offchan,
5391 unsigned int wait, const u8* buf, size_t len, bool no_cck,
5392 bool dont_wait_for_ack, u64 *cookie)
5394 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5395 struct ieee80211_channel *channel, bool offchan,
5396 enum nl80211_channel_type channel_type,
5397 bool channel_type_valid, unsigned int wait,
5398 const u8* buf, size_t len,
5399 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
5402 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || defined(WL_COMPAT_WIRELESS)
5403 bool dont_wait_for_ack,
5406 #endif /* WL_CFG80211_P2P_DEV_IF */
5408 wl_action_frame_t *action_frame;
5409 wl_af_params_t *af_params;
5411 const struct ieee80211_mgmt *mgmt;
5412 struct wl_priv *wl = wiphy_priv(wiphy);
5413 struct net_device *dev = NULL;
5418 s8 eabuf[ETHER_ADDR_STR_LEN];
5420 WL_DBG(("Enter \n"));
5422 dev = cfgdev_to_wlc_ndev(cfgdev, wl);
5424 /* find bssidx based on dev */
5425 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
5426 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
5429 if (p2p_is_on(wl)) {
5430 /* Suspend P2P discovery search-listen to prevent it from changing the
5433 if ((err = wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
5434 WL_ERR(("Can not disable discovery mode\n"));
5439 id = wl->send_action_id++;
5441 id = wl->send_action_id++;
5443 mgmt = (const struct ieee80211_mgmt *)buf;
5444 if (ieee80211_is_mgmt(mgmt->frame_control)) {
5445 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
5446 s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
5447 s32 ie_len = len - ie_offset;
5448 if (dev == wl_to_prmry_ndev(wl))
5449 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
5450 wl_cfgp2p_set_management_ie(wl, dev, bssidx,
5451 VNDR_IE_PRBRSP_FLAG, (u8 *)(buf + ie_offset), ie_len);
5452 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
5454 } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
5455 ieee80211_is_deauth(mgmt->frame_control)) {
5456 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
5457 sizeof(struct ether_addr) + sizeof(uint)] = {0};
5458 int num_associated = 0;
5459 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
5460 if (!bcmp((const uint8 *)BSSID_BROADCAST,
5461 (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
5462 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
5463 err = wldev_ioctl(dev, WLC_GET_ASSOCLIST,
5464 assoc_maclist, sizeof(mac_buf), false);
5466 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
5468 num_associated = assoc_maclist->count;
5470 memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
5471 scb_val.val = mgmt->u.disassoc.reason_code;
5472 err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
5473 sizeof(scb_val_t), true);
5475 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
5476 WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
5477 bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
5480 if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
5483 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
5486 } else if (ieee80211_is_action(mgmt->frame_control)) {
5487 /* Abort the dwell time of any previous off-channel
5488 * action frame that may be still in effect. Sending
5489 * off-channel action frames relies on the driver's
5490 * scan engine. If a previous off-channel action frame
5491 * tx is still in progress (including the dwell time),
5492 * then this new action frame will not be sent out.
5494 /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
5495 * And previous off-channel action frame must be ended before new af tx.
5497 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5498 wl_notify_escan_complete(wl, dev, true, true);
5499 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5503 WL_ERR(("Driver only allows MGMT packet type\n"));
5507 af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
5509 if (af_params == NULL)
5511 WL_ERR(("unable to allocate frame\n"));
5515 action_frame = &af_params->action_frame;
5517 /* Add the packet Id */
5518 action_frame->packetId = *cookie;
5519 WL_DBG(("action frame %d\n", action_frame->packetId));
5521 memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
5522 memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
5524 /* Add the length exepted for 802.11 header */
5525 action_frame->len = len - DOT11_MGMT_HDR_LEN;
5526 WL_DBG(("action_frame->len: %d\n", action_frame->len));
5528 /* Add the channel */
5529 af_params->channel =
5530 ieee80211_frequency_to_channel(channel->center_freq);
5532 /* Save listen_chan for searching common channel */
5533 wl->afx_hdl->peer_listen_chan = af_params->channel;
5534 WL_DBG(("channel from upper layer %d\n", wl->afx_hdl->peer_listen_chan));
5536 /* Add the default dwell time
5537 * Dwell time to stay off-channel to wait for a response action frame
5538 * after transmitting an GO Negotiation action frame
5540 af_params->dwell_time = WL_DWELL_TIME;
5542 memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
5544 ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
5545 action_frame, action_frame->len, bssidx);
5546 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
5555 wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5556 u16 frame_type, bool reg)
5559 WL_DBG(("frame_type: %x, reg: %d\n", frame_type, reg));
5561 if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
5569 wl_cfg80211_change_bss(struct wiphy *wiphy,
5570 struct net_device *dev,
5571 struct bss_parameters *params)
5573 if (params->use_cts_prot >= 0) {
5576 if (params->use_short_preamble >= 0) {
5579 if (params->use_short_slot_time >= 0) {
5582 if (params->basic_rates) {
5585 if (params->ap_isolate >= 0) {
5588 if (params->ht_opmode >= 0) {
5595 wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
5596 struct ieee80211_channel *chan,
5597 enum nl80211_channel_type channel_type)
5600 chanspec_t chspec = 0;
5601 chanspec_t fw_chspec = 0;
5602 u32 bw = WL_CHANSPEC_BW_20;
5610 struct wl_priv *wl = wiphy_priv(wiphy);
5612 dev = ndev_to_wlc_ndev(dev, wl);
5613 _chan = ieee80211_frequency_to_channel(chan->center_freq);
5614 printk("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
5615 dev->ifindex, channel_type, _chan);
5618 if (chan->band == IEEE80211_BAND_5GHZ) {
5619 param.band = WLC_BAND_5G;
5620 err = wldev_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param),
5621 wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync);
5623 if (err != BCME_UNSUPPORTED) {
5624 WL_ERR(("bw_cap failed, %d\n", err));
5627 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
5629 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
5631 if (bw_cap != WLC_N_BW_20ALL)
5632 bw = WL_CHANSPEC_BW_40;
5635 if (WL_BW_CAP_80MHZ(wl->ioctl_buf[0]))
5636 bw = WL_CHANSPEC_BW_80;
5637 else if (WL_BW_CAP_40MHZ(wl->ioctl_buf[0]))
5638 bw = WL_CHANSPEC_BW_40;
5640 bw = WL_CHANSPEC_BW_20;
5644 } else if (chan->band == IEEE80211_BAND_2GHZ)
5645 bw = WL_CHANSPEC_BW_20;
5647 chspec = wf_channel2chspec(_chan, bw);
5648 if (wf_chspec_valid(chspec)) {
5649 fw_chspec = wl_chspec_host_to_driver(chspec);
5650 if (fw_chspec != INVCHANSPEC) {
5651 if ((err = wldev_iovar_setint(dev, "chanspec",
5652 fw_chspec)) == BCME_BADCHAN) {
5653 if (bw == WL_CHANSPEC_BW_80)
5655 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
5656 &_chan, sizeof(_chan), true);
5658 WL_ERR(("WLC_SET_CHANNEL error %d"
5659 "chip may not be supporting this channel\n", err));
5662 WL_ERR(("failed to set chanspec error %d\n", err));
5665 WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
5670 if (bw == WL_CHANSPEC_BW_80)
5671 bw = WL_CHANSPEC_BW_40;
5672 else if (bw == WL_CHANSPEC_BW_40)
5673 bw = WL_CHANSPEC_BW_20;
5678 WL_ERR(("Invalid chanspec 0x%x\n", chspec));
5685 wl_validate_opensecurity(struct net_device *dev, s32 bssidx)
5690 err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
5692 WL_ERR(("auth error %d\n", err));
5696 err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
5698 WL_ERR(("wsec error %d\n", err));
5701 /* set upper-layer auth */
5702 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", WPA_AUTH_NONE, bssidx);
5704 WL_ERR(("wpa_auth error %d\n", err));
5712 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
5716 u16 auth = 0; /* d11 open authentication */
5721 wpa_suite_mcast_t *mcast;
5722 wpa_suite_ucast_t *ucast;
5723 wpa_suite_auth_key_mgmt_t *mgmt;
5727 u32 wme_bss_disable;
5732 WL_DBG(("Enter \n"));
5734 /* check the mcast cipher */
5735 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
5736 switch (mcast->type) {
5737 case WPA_CIPHER_NONE:
5740 case WPA_CIPHER_WEP_40:
5741 case WPA_CIPHER_WEP_104:
5744 case WPA_CIPHER_TKIP:
5745 gval = TKIP_ENABLED;
5747 case WPA_CIPHER_AES_CCM:
5751 case WAPI_CIPHER_SMS4:
5752 gval = SMS4_ENABLED;
5756 WL_ERR(("No Security Info\n"));
5759 if ((len -= WPA_SUITE_LEN) <= 0)
5762 /* check the unicast cipher */
5763 ucast = (wpa_suite_ucast_t *)&mcast[1];
5764 suite_count = ltoh16_ua(&ucast->count);
5765 switch (ucast->list[0].type) {
5766 case WPA_CIPHER_NONE:
5769 case WPA_CIPHER_WEP_40:
5770 case WPA_CIPHER_WEP_104:
5773 case WPA_CIPHER_TKIP:
5774 pval = TKIP_ENABLED;
5776 case WPA_CIPHER_AES_CCM:
5780 case WAPI_CIPHER_SMS4:
5781 pval = SMS4_ENABLED;
5785 WL_ERR(("No Security Info\n"));
5787 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
5790 /* FOR WPS , set SEC_OW_ENABLED */
5791 wsec = (pval | gval | SES_OW_ENABLED);
5793 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
5794 suite_count = ltoh16_ua(&mgmt->count);
5795 switch (mgmt->list[0].type) {
5797 wpa_auth = WPA_AUTH_NONE;
5799 case RSN_AKM_UNSPECIFIED:
5800 wpa_auth = WPA2_AUTH_UNSPECIFIED;
5803 wpa_auth = WPA2_AUTH_PSK;
5806 WL_ERR(("No Key Mgmt Info\n"));
5809 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
5810 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
5811 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
5813 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
5814 wme_bss_disable = 0;
5816 wme_bss_disable = 1;
5819 /* set wme_bss_disable to sync RSN Capabilities */
5820 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
5822 WL_ERR(("wme_bss_disable error %d\n", err));
5826 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
5830 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5832 WL_ERR(("auth error %d\n", err));
5836 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5838 WL_ERR(("wsec error %d\n", err));
5841 /* set upper-layer auth */
5842 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5844 WL_ERR(("wpa_auth error %d\n", err));
5852 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
5854 wpa_suite_mcast_t *mcast;
5855 wpa_suite_ucast_t *ucast;
5856 wpa_suite_auth_key_mgmt_t *mgmt;
5857 u16 auth = 0; /* d11 open authentication */
5870 WL_DBG(("Enter \n"));
5871 len = wpaie->length; /* value length */
5872 len -= WPA_IE_TAG_FIXED_LEN;
5873 /* check for multicast cipher suite */
5874 if (len < WPA_SUITE_LEN) {
5875 WL_INFO(("no multicast cipher suite\n"));
5879 /* pick up multicast cipher */
5880 mcast = (wpa_suite_mcast_t *)&wpaie[1];
5881 len -= WPA_SUITE_LEN;
5882 if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
5883 if (IS_WPA_CIPHER(mcast->type)) {
5885 switch (mcast->type) {
5886 case WPA_CIPHER_NONE:
5889 case WPA_CIPHER_WEP_40:
5890 case WPA_CIPHER_WEP_104:
5893 case WPA_CIPHER_TKIP:
5896 case WPA_CIPHER_AES_CCM:
5900 WL_ERR(("No Security Info\n"));
5905 /* Check for unicast suite(s) */
5906 if (len < WPA_IE_SUITE_COUNT_LEN) {
5907 WL_INFO(("no unicast suite\n"));
5910 /* walk thru unicast cipher list and pick up what we recognize */
5911 ucast = (wpa_suite_ucast_t *)&mcast[1];
5912 count = ltoh16_ua(&ucast->count);
5913 len -= WPA_IE_SUITE_COUNT_LEN;
5914 for (i = 0; i < count && len >= WPA_SUITE_LEN;
5915 i++, len -= WPA_SUITE_LEN) {
5916 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5917 if (IS_WPA_CIPHER(ucast->list[i].type)) {
5919 switch (ucast->list[i].type) {
5920 case WPA_CIPHER_NONE:
5923 case WPA_CIPHER_WEP_40:
5924 case WPA_CIPHER_WEP_104:
5927 case WPA_CIPHER_TKIP:
5930 case WPA_CIPHER_AES_CCM:
5934 WL_ERR(("No Security Info\n"));
5940 len -= (count - i) * WPA_SUITE_LEN;
5941 /* Check for auth key management suite(s) */
5942 if (len < WPA_IE_SUITE_COUNT_LEN) {
5943 WL_INFO((" no auth key mgmt suite\n"));
5946 /* walk thru auth management suite list and pick up what we recognize */
5947 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
5948 count = ltoh16_ua(&mgmt->count);
5949 len -= WPA_IE_SUITE_COUNT_LEN;
5950 for (i = 0; i < count && len >= WPA_SUITE_LEN;
5951 i++, len -= WPA_SUITE_LEN) {
5952 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
5953 if (IS_WPA_AKM(mgmt->list[i].type)) {
5955 switch (mgmt->list[i].type) {
5957 tmp = WPA_AUTH_NONE;
5959 case RSN_AKM_UNSPECIFIED:
5960 tmp = WPA_AUTH_UNSPECIFIED;
5966 WL_ERR(("No Key Mgmt Info\n"));
5973 /* FOR WPS , set SEC_OW_ENABLED */
5974 wsec = (pval | gval | SES_OW_ENABLED);
5976 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
5978 WL_ERR(("auth error %d\n", err));
5982 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5984 WL_ERR(("wsec error %d\n", err));
5987 /* set upper-layer auth */
5988 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
5990 WL_ERR(("wpa_auth error %d\n", err));
5998 wl_cfg80211_bcn_validate_sec(
5999 struct net_device *dev,
6000 struct parsed_ies *ies,
6004 struct wl_priv *wl = wlcfg_drv_priv;
6006 if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
6007 /* For P2P GO, the sec type is WPA2-PSK */
6008 WL_DBG(("P2P GO: validating wpa2_ie"));
6009 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0)
6012 } else if (dev_role == NL80211_IFTYPE_AP) {
6014 WL_DBG(("SoftAP: validating security"));
6015 /* If wpa2_ie or wpa_ie is present validate it */
6016 if ((ies->wpa2_ie || ies->wpa_ie) &&
6017 ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
6018 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
6019 wl->ap_info->security_mode = false;
6023 wl->ap_info->security_mode = true;
6024 if (wl->ap_info->rsn_ie) {
6025 kfree(wl->ap_info->rsn_ie);
6026 wl->ap_info->rsn_ie = NULL;
6028 if (wl->ap_info->wpa_ie) {
6029 kfree(wl->ap_info->wpa_ie);
6030 wl->ap_info->wpa_ie = NULL;
6032 if (wl->ap_info->wps_ie) {
6033 kfree(wl->ap_info->wps_ie);
6034 wl->ap_info->wps_ie = NULL;
6036 if (ies->wpa_ie != NULL) {
6038 wl->ap_info->rsn_ie = NULL;
6039 wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
6040 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
6042 } else if (ies->wpa2_ie != NULL) {
6044 wl->ap_info->wpa_ie = NULL;
6045 wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
6046 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
6050 if (!ies->wpa2_ie && !ies->wpa_ie) {
6051 wl_validate_opensecurity(dev, bssidx);
6052 wl->ap_info->security_mode = false;
6056 wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
6064 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
6065 static s32 wl_cfg80211_bcn_set_params(
6066 struct cfg80211_ap_settings *info,
6067 struct net_device *dev,
6068 u32 dev_role, s32 bssidx)
6070 struct wl_priv *wl = wlcfg_drv_priv;
6073 WL_DBG(("interval (%d) \ndtim_period (%d) \n",
6074 info->beacon_interval, info->dtim_period));
6076 if (info->beacon_interval) {
6077 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
6078 &info->beacon_interval, sizeof(s32), true)) < 0) {
6079 WL_ERR(("Beacon Interval Set Error, %d\n", err));
6084 if (info->dtim_period) {
6085 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
6086 &info->dtim_period, sizeof(s32), true)) < 0) {
6087 WL_ERR(("DTIM Interval Set Error, %d\n", err));
6092 if ((info->ssid) && (info->ssid_len > 0) &&
6093 (info->ssid_len <= 32)) {
6094 WL_DBG(("SSID (%s) len:%d \n", info->ssid, info->ssid_len));
6095 if (dev_role == NL80211_IFTYPE_AP) {
6096 /* Store the hostapd SSID */
6097 memset(wl->hostapd_ssid.SSID, 0x00, 32);
6098 memcpy(wl->hostapd_ssid.SSID, info->ssid, info->ssid_len);
6099 wl->hostapd_ssid.SSID_len = info->ssid_len;
6102 memset(wl->p2p->ssid.SSID, 0x00, 32);
6103 memcpy(wl->p2p->ssid.SSID, info->ssid, info->ssid_len);
6104 wl->p2p->ssid.SSID_len = info->ssid_len;
6108 if (info->hidden_ssid) {
6109 if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
6110 WL_ERR(("failed to set hidden : %d\n", err));
6111 WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
6116 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
6119 wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
6123 memset(ies, 0, sizeof(struct parsed_ies));
6125 /* find the WPSIE */
6126 if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
6127 WL_DBG(("WPSIE in beacon \n"));
6128 ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
6130 WL_ERR(("No WPSIE in beacon \n"));
6133 /* find the RSN_IE */
6134 if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
6135 DOT11_MNG_RSN_ID)) != NULL) {
6136 WL_DBG((" WPA2 IE found\n"));
6137 ies->wpa2_ie_len = ies->wpa2_ie->len;
6140 /* find the WPA_IE */
6141 if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
6142 WL_DBG((" WPA found\n"));
6143 ies->wpa_ie_len = ies->wpa_ie->length;
6151 wl_cfg80211_bcn_bringup_ap(
6152 struct net_device *dev,
6153 struct parsed_ies *ies,
6154 u32 dev_role, s32 bssidx)
6156 struct wl_priv *wl = wlcfg_drv_priv;
6157 struct wl_join_params join_params;
6158 bool is_bssup = false;
6160 s32 join_params_size = 0;
6162 #ifdef DISABLE_11H_SOFTAP
6164 #endif /* DISABLE_11H_SOFTAP */
6167 WL_DBG(("Enter dev_role: %d\n", dev_role));
6169 /* Common code for SoftAP and P2P GO */
6170 wldev_iovar_setint(dev, "mpc", 0);
6172 if (dev_role == NL80211_IFTYPE_P2P_GO) {
6173 is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
6174 if (!is_bssup && (ies->wpa2_ie != NULL)) {
6176 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
6178 WL_ERR(("SET INFRA error %d\n", err));
6182 err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid,
6183 sizeof(wl->p2p->ssid), wl->ioctl_buf, WLC_IOCTL_MAXLEN,
6184 bssidx, &wl->ioctl_buf_sync);
6186 WL_ERR(("GO SSID setting error %d\n", err));
6190 /* Do abort scan before creating GO */
6191 wl_cfg80211_scan_abort(wl);
6193 if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) {
6194 WL_ERR(("GO Bring up error %d\n", err));
6198 WL_DBG(("Bss is already up\n"));
6199 } else if ((dev_role == NL80211_IFTYPE_AP) &&
6200 (wl_get_drv_status(wl, AP_CREATING, dev))) {
6201 /* Device role SoftAP */
6202 err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
6204 WL_ERR(("WLC_DOWN error %d\n", err));
6207 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
6209 WL_ERR(("SET INFRA error %d\n", err));
6212 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
6213 WL_ERR(("setting AP mode failed %d \n", err));
6216 #ifdef DISABLE_11H_SOFTAP
6217 err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT,
6218 &spect, sizeof(s32), true);
6220 WL_ERR(("SET SPECT_MANAGMENT error %d\n", err));
6223 #endif /* DISABLE_11H_SOFTAP */
6225 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
6226 if (unlikely(err)) {
6227 WL_ERR(("WLC_UP error (%d)\n", err));
6231 memset(&join_params, 0, sizeof(join_params));
6232 /* join parameters starts with ssid */
6233 join_params_size = sizeof(join_params.ssid);
6234 memcpy(join_params.ssid.SSID, wl->hostapd_ssid.SSID,
6235 wl->hostapd_ssid.SSID_len);
6236 join_params.ssid.SSID_len = htod32(wl->hostapd_ssid.SSID_len);
6239 if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
6240 join_params_size, true)) == 0) {
6241 WL_DBG(("SoftAP set SSID (%s) success\n", join_params.ssid.SSID));
6242 wl_clr_drv_status(wl, AP_CREATING, dev);
6243 wl_set_drv_status(wl, AP_CREATED, dev);
6252 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
6254 wl_cfg80211_parse_ap_ies(
6255 struct net_device *dev,
6256 struct cfg80211_beacon_data *info,
6257 struct parsed_ies *ies)
6259 struct parsed_ies prb_ies;
6260 struct wl_priv *wl = wlcfg_drv_priv;
6261 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
6263 u32 vndr_ie_len = 0;
6266 /* Parse Beacon IEs */
6267 if (wl_cfg80211_parse_ies((u8 *)info->tail,
6268 info->tail_len, ies) < 0) {
6269 WL_ERR(("Beacon get IEs failed \n"));
6274 vndr = (u8 *)info->proberesp_ies;
6275 vndr_ie_len = info->proberesp_ies_len;
6277 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
6279 struct ieee80211_mgmt *mgmt;
6280 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
6282 vndr = (u8 *)&mgmt->u.probe_resp.variable;
6283 vndr_ie_len = info->probe_resp_len -
6284 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
6288 /* Parse Probe Response IEs */
6289 if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) {
6290 WL_ERR(("PROBE RESP get IEs failed \n"));
6300 wl_cfg80211_set_ies(
6301 struct net_device *dev,
6302 struct cfg80211_beacon_data *info,
6305 struct wl_priv *wl = wlcfg_drv_priv;
6306 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
6308 u32 vndr_ie_len = 0;
6311 /* Set Beacon IEs to FW */
6312 if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
6313 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
6314 info->tail_len)) < 0) {
6315 WL_ERR(("Set Beacon IE Failed \n"));
6317 WL_DBG(("Applied Vndr IEs for Beacon \n"));
6320 vndr = (u8 *)info->proberesp_ies;
6321 vndr_ie_len = info->proberesp_ies_len;
6323 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
6325 struct ieee80211_mgmt *mgmt;
6326 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
6328 vndr = (u8 *)&mgmt->u.probe_resp.variable;
6329 vndr_ie_len = info->probe_resp_len -
6330 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
6334 /* Set Probe Response IEs to FW */
6335 if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx,
6336 VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
6337 WL_ERR(("Set Probe Resp IE Failed \n"));
6339 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
6344 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
6346 static s32 wl_cfg80211_hostapd_sec(
6347 struct net_device *dev,
6348 struct parsed_ies *ies,
6351 bool update_bss = 0;
6352 struct wl_priv *wl = wlcfg_drv_priv;
6356 if (wl->ap_info->wps_ie &&
6357 memcmp(wl->ap_info->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
6358 WL_DBG((" WPS IE is changed\n"));
6359 kfree(wl->ap_info->wps_ie);
6360 wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
6361 } else if (wl->ap_info->wps_ie == NULL) {
6362 WL_DBG((" WPS IE is added\n"));
6363 wl->ap_info->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
6365 if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
6366 if (!wl->ap_info->security_mode) {
6367 /* change from open mode to security mode */
6369 if (ies->wpa_ie != NULL) {
6370 wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
6371 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
6374 wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
6375 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
6378 } else if (wl->ap_info->wpa_ie) {
6379 /* change from WPA2 mode to WPA mode */
6380 if (ies->wpa_ie != NULL) {
6382 kfree(wl->ap_info->rsn_ie);
6383 wl->ap_info->rsn_ie = NULL;
6384 wl->ap_info->wpa_ie = kmemdup(ies->wpa_ie,
6385 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
6387 } else if (memcmp(wl->ap_info->rsn_ie,
6388 ies->wpa2_ie, ies->wpa2_ie->len
6389 + WPA_RSN_IE_TAG_FIXED_LEN)) {
6391 kfree(wl->ap_info->rsn_ie);
6392 wl->ap_info->rsn_ie = kmemdup(ies->wpa2_ie,
6393 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
6395 wl->ap_info->wpa_ie = NULL;
6399 wl->ap_info->security_mode = true;
6400 wl_cfgp2p_bss(wl, dev, bssidx, 0);
6401 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
6402 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
6405 wl_cfgp2p_bss(wl, dev, bssidx, 1);
6409 WL_ERR(("No WPSIE in beacon \n"));
6414 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6417 wl_cfg80211_del_station(
6418 struct wiphy *wiphy,
6419 struct net_device *ndev,
6422 struct net_device *dev;
6423 struct wl_priv *wl = wiphy_priv(wiphy);
6425 s8 eabuf[ETHER_ADDR_STR_LEN];
6427 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
6428 sizeof(struct ether_addr) + sizeof(uint)] = {0};
6429 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
6430 int num_associated = 0;
6432 WL_DBG(("Entry\n"));
6433 if (mac_addr == NULL) {
6434 WL_DBG(("mac_addr is NULL ignore it\n"));
6438 dev = ndev_to_wlc_ndev(ndev, wl);
6440 if (p2p_is_on(wl)) {
6441 /* Suspend P2P discovery search-listen to prevent it from changing the
6444 if ((wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
6445 WL_ERR(("Can not disable discovery mode\n"));
6450 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
6451 err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST,
6452 assoc_maclist, sizeof(mac_buf), false);
6454 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
6456 num_associated = assoc_maclist->count;
6458 memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
6459 scb_val.val = DOT11_RC_DEAUTH_LEAVING;
6460 err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
6461 sizeof(scb_val_t), true);
6463 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
6464 printk("Disconnect STA : %s scb_val.val %d\n",
6465 bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
6468 if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
6473 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
6475 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
6477 wl_cfg80211_start_ap(
6478 struct wiphy *wiphy,
6479 struct net_device *dev,
6480 struct cfg80211_ap_settings *info)
6482 struct wl_priv *wl = wiphy_priv(wiphy);
6484 struct parsed_ies ies;
6488 WL_DBG(("Enter \n"));
6489 if (dev == wl_to_prmry_ndev(wl)) {
6490 WL_DBG(("Start AP req on primary iface: Softap\n"));
6491 dev_role = NL80211_IFTYPE_AP;
6493 #if defined(WL_ENABLE_P2P_IF)
6494 else if (dev == wl->p2p_net) {
6495 /* Group Add request on p2p0 */
6496 WL_DBG(("Start AP req on P2P iface: GO\n"));
6497 dev = wl_to_prmry_ndev(wl);
6498 dev_role = NL80211_IFTYPE_P2P_GO;
6500 #endif /* WL_ENABLE_P2P_IF */
6501 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6502 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6505 if (p2p_is_on(wl) &&
6506 (bssidx == wl_to_p2p_bss_bssidx(wl,
6507 P2PAPI_BSSCFG_CONNECTION))) {
6508 dev_role = NL80211_IFTYPE_P2P_GO;
6509 WL_DBG(("Start AP req on P2P connection iface\n"));
6512 if (!check_dev_role_integrity(wl, dev_role))
6515 #if defined(WL_CFG80211_P2P_DEV_IF) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
6516 if ((err = wl_cfg80211_set_channel(wiphy, dev,
6517 dev->ieee80211_ptr->preset_chandef.chan,
6518 NL80211_CHAN_HT20) < 0)) {
6519 WL_ERR(("Set channel failed \n"));
6522 #endif /* WL_CFG80211_P2P_DEV_IF || (LINUX_VERSION >= VERSION(3, 6, 0)) */
6524 if ((err = wl_cfg80211_bcn_set_params(info, dev,
6525 dev_role, bssidx)) < 0) {
6526 WL_ERR(("Beacon params set failed \n"));
6531 if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
6532 WL_ERR(("Set IEs failed \n"));
6536 if ((wl_cfg80211_bcn_validate_sec(dev, &ies,
6537 dev_role, bssidx)) < 0)
6539 WL_ERR(("Beacon set security failed \n"));
6543 if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
6544 dev_role, bssidx)) < 0) {
6545 WL_ERR(("Beacon bring up AP/GO failed \n"));
6549 WL_DBG(("** AP/GO Created **\n"));
6552 if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
6553 WL_ERR(("Set IEs failed \n"));
6557 WL_ERR(("ADD/SET beacon failed\n"));
6558 wldev_iovar_setint(dev, "mpc", 1);
6565 wl_cfg80211_stop_ap(
6566 struct wiphy *wiphy,
6567 struct net_device *dev)
6574 struct wl_priv *wl = wiphy_priv(wiphy);
6576 WL_DBG(("Enter \n"));
6577 if (dev == wl_to_prmry_ndev(wl)) {
6578 dev_role = NL80211_IFTYPE_AP;
6580 #if defined(WL_ENABLE_P2P_IF)
6581 else if (dev == wl->p2p_net) {
6582 /* Group Add request on p2p0 */
6583 dev = wl_to_prmry_ndev(wl);
6584 dev_role = NL80211_IFTYPE_P2P_GO;
6586 #endif /* WL_ENABLE_P2P_IF */
6587 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6588 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6591 if (p2p_is_on(wl) &&
6592 (bssidx == wl_to_p2p_bss_bssidx(wl,
6593 P2PAPI_BSSCFG_CONNECTION))) {
6594 dev_role = NL80211_IFTYPE_P2P_GO;
6597 if (!check_dev_role_integrity(wl, dev_role))
6600 if (dev_role == NL80211_IFTYPE_AP) {
6601 /* SoftAp on primary Interface.
6602 * Shut down AP and turn on MPC
6604 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
6605 WL_ERR(("setting AP mode failed %d \n", err));
6609 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
6611 WL_ERR(("SET INFRA error %d\n", err));
6616 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
6617 if (unlikely(err)) {
6618 WL_ERR(("WLC_UP error (%d)\n", err));
6623 wl_clr_drv_status(wl, AP_CREATED, dev);
6624 /* Turn on the MPC */
6625 wldev_iovar_setint(dev, "mpc", 1);
6627 WL_DBG(("Stopping P2P GO \n"));
6635 wl_cfg80211_change_beacon(
6636 struct wiphy *wiphy,
6637 struct net_device *dev,
6638 struct cfg80211_beacon_data *info)
6641 struct wl_priv *wl = wiphy_priv(wiphy);
6642 struct parsed_ies ies;
6646 WL_DBG(("Enter \n"));
6648 if (dev == wl_to_prmry_ndev(wl)) {
6649 dev_role = NL80211_IFTYPE_AP;
6651 #if defined(WL_ENABLE_P2P_IF)
6652 else if (dev == wl->p2p_net) {
6653 /* Group Add request on p2p0 */
6654 dev = wl_to_prmry_ndev(wl);
6655 dev_role = NL80211_IFTYPE_P2P_GO;
6657 #endif /* WL_ENABLE_P2P_IF */
6658 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6659 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6662 if (p2p_is_on(wl) &&
6663 (bssidx == wl_to_p2p_bss_bssidx(wl,
6664 P2PAPI_BSSCFG_CONNECTION))) {
6665 dev_role = NL80211_IFTYPE_P2P_GO;
6668 if (!check_dev_role_integrity(wl, dev_role))
6672 if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
6673 WL_ERR(("Parse IEs failed \n"));
6678 if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
6679 WL_ERR(("Set IEs failed \n"));
6683 if (dev_role == NL80211_IFTYPE_AP) {
6684 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6685 WL_ERR(("Hostapd update sec failed \n"));
6694 #else /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */
6696 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
6697 struct beacon_parameters *info)
6700 struct wl_priv *wl = wiphy_priv(wiphy);
6703 u32 dev_role = NL80211_IFTYPE_AP;
6704 struct parsed_ies ies;
6708 WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
6709 info->interval, info->dtim_period, info->head_len, info->tail_len));
6711 if (dev == wl_to_prmry_ndev(wl)) {
6712 dev_role = NL80211_IFTYPE_AP;
6714 #if defined(WL_ENABLE_P2P_IF)
6715 else if (dev == wl->p2p_net) {
6716 /* Group Add request on p2p0 */
6717 dev = wl_to_prmry_ndev(wl);
6718 dev_role = NL80211_IFTYPE_P2P_GO;
6720 #endif /* WL_ENABLE_P2P_IF */
6721 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
6722 WL_ERR(("Find p2p index from dev(%p) failed\n", dev));
6725 if (p2p_is_on(wl) &&
6726 (bssidx == wl_to_p2p_bss_bssidx(wl,
6727 P2PAPI_BSSCFG_CONNECTION))) {
6728 dev_role = NL80211_IFTYPE_P2P_GO;
6731 if (!check_dev_role_integrity(wl, dev_role))
6734 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
6736 if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
6737 info->head_len - ie_offset,
6738 DOT11_MNG_SSID_ID)) != NULL) {
6739 if (dev_role == NL80211_IFTYPE_AP) {
6740 /* Store the hostapd SSID */
6741 memset(&wl->hostapd_ssid.SSID[0], 0x00, 32);
6742 memcpy(&wl->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
6743 wl->hostapd_ssid.SSID_len = ssid_ie->len;
6746 memset(&wl->p2p->ssid.SSID[0], 0x00, 32);
6747 memcpy(wl->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
6748 wl->p2p->ssid.SSID_len = ssid_ie->len;
6752 if (wl_cfg80211_parse_ies((u8 *)info->tail,
6753 info->tail_len, &ies) < 0) {
6754 WL_ERR(("Beacon get IEs failed \n"));
6759 if (wl_cfgp2p_set_management_ie(wl, dev, bssidx,
6760 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
6761 info->tail_len) < 0) {
6762 WL_ERR(("Beacon set IEs failed \n"));
6765 WL_DBG(("Applied Vndr IEs for Beacon \n"));
6767 if (!wl_cfgp2p_bss_isup(dev, bssidx) &&
6768 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx) < 0))
6770 WL_ERR(("Beacon set security failed \n"));
6774 /* Set BI and DTIM period */
6775 if (info->interval) {
6776 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
6777 &info->interval, sizeof(s32), true)) < 0) {
6778 WL_ERR(("Beacon Interval Set Error, %d\n", err));
6782 if (info->dtim_period) {
6783 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
6784 &info->dtim_period, sizeof(s32), true)) < 0) {
6785 WL_ERR(("DTIM Interval Set Error, %d\n", err));
6790 if (wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx) < 0) {
6791 WL_ERR(("Beacon bring up AP/GO failed \n"));
6795 if (wl_get_drv_status(wl, AP_CREATED, dev)) {
6796 /* Soft AP already running. Update changed params */
6797 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
6798 WL_ERR(("Hostapd update sec failed \n"));
6804 /* Enable Probe Req filter */
6805 if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
6806 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
6807 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
6809 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
6812 WL_DBG(("** ADD/SET beacon done **\n"));
6816 WL_ERR(("ADD/SET beacon failed\n"));
6817 wldev_iovar_setint(dev, "mpc", 1);
6822 #endif /* LINUX_VERSION < VERSION(3,4,0) || WL_COMPAT_WIRELESS */
6824 #ifdef WL_SCHED_SCAN
6826 #define PNO_REPEAT 4
6827 #define PNO_FREQ_EXPO_MAX 2
6828 int wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
6829 struct net_device *dev,
6830 struct cfg80211_sched_scan_request *request)
6832 ushort pno_time = PNO_TIME;
6833 int pno_repeat = PNO_REPEAT;
6834 int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
6835 wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT];
6836 struct wl_priv *wl = wiphy_priv(wiphy);
6837 struct cfg80211_ssid *ssid = NULL;
6842 WL_DBG(("Enter \n"));
6843 WL_PNO((">>> SCHED SCAN START\n"));
6844 WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
6845 request->n_match_sets, request->n_ssids));
6846 WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
6847 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
6850 if (!request || !request->n_ssids || !request->n_match_sets) {
6851 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
6855 memset(&ssids_local, 0, sizeof(ssids_local));
6857 if (request->n_match_sets > 0) {
6858 for (i = 0; i < request->n_match_sets; i++) {
6859 ssid = &request->match_sets[i].ssid;
6860 memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len);
6861 ssids_local[i].SSID_len = ssid->ssid_len;
6862 WL_PNO((">>> PNO filter set for ssid (%s) \n", ssid->ssid));
6867 if (request->n_ssids > 0) {
6868 for (i = 0; i < request->n_ssids; i++) {
6869 /* Active scan req for ssids */
6870 WL_PNO((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid));
6872 /* match_set ssids is a supert set of n_ssid list, so we need
6873 * not add these set seperately
6879 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, request->n_match_sets,
6880 pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
6881 WL_ERR(("PNO setup failed!! ret=%d \n", ret));
6884 wl->sched_scan_req = request;
6892 int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
6894 struct wl_priv *wl = wiphy_priv(wiphy);
6896 WL_DBG(("Enter \n"));
6897 WL_PNO((">>> SCHED SCAN STOP\n"));
6899 if (dhd_dev_pno_stop_for_ssid(dev) < 0)
6900 WL_ERR(("PNO Stop for SSID failed"));
6902 if (wl->scan_request && wl->sched_scan_running) {
6903 WL_PNO((">>> Sched scan running. Aborting it..\n"));
6904 wl_notify_escan_complete(wl, dev, true, true);
6907 wl->sched_scan_req = NULL;
6908 wl->sched_scan_running = FALSE;
6912 #endif /* WL_SCHED_SCAN */
6914 static struct cfg80211_ops wl_cfg80211_ops = {
6915 .add_virtual_intf = wl_cfg80211_add_virtual_iface,
6916 .del_virtual_intf = wl_cfg80211_del_virtual_iface,
6917 .change_virtual_intf = wl_cfg80211_change_virtual_iface,
6918 #if defined(WL_CFG80211_P2P_DEV_IF)
6919 .start_p2p_device = wl_cfgp2p_start_p2p_device,
6920 .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
6921 #endif /* WL_CFG80211_P2P_DEV_IF */
6922 .scan = wl_cfg80211_scan,
6923 .set_wiphy_params = wl_cfg80211_set_wiphy_params,
6924 .join_ibss = wl_cfg80211_join_ibss,
6925 .leave_ibss = wl_cfg80211_leave_ibss,
6926 .get_station = wl_cfg80211_get_station,
6927 .set_tx_power = wl_cfg80211_set_tx_power,
6928 .get_tx_power = wl_cfg80211_get_tx_power,
6929 .add_key = wl_cfg80211_add_key,
6930 .del_key = wl_cfg80211_del_key,
6931 .get_key = wl_cfg80211_get_key,
6932 .set_default_key = wl_cfg80211_config_default_key,
6933 .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
6934 .set_power_mgmt = wl_cfg80211_set_power_mgmt,
6935 .connect = wl_cfg80211_connect,
6936 .disconnect = wl_cfg80211_disconnect,
6937 .suspend = wl_cfg80211_suspend,
6938 .resume = wl_cfg80211_resume,
6939 .set_pmksa = wl_cfg80211_set_pmksa,
6940 .del_pmksa = wl_cfg80211_del_pmksa,
6941 .flush_pmksa = wl_cfg80211_flush_pmksa,
6942 .remain_on_channel = wl_cfg80211_remain_on_channel,
6943 .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
6944 .mgmt_tx = wl_cfg80211_mgmt_tx,
6945 .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
6946 .change_bss = wl_cfg80211_change_bss,
6947 #if !defined(WL_CFG80211_P2P_DEV_IF) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
6948 .set_channel = wl_cfg80211_set_channel,
6949 #endif /* !WL_CFG80211_P2P_DEV_IF && (LINUX_VERSION < VERSION(3, 6, 0)) */
6950 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)) && !defined(WL_COMPAT_WIRELESS)
6951 .set_beacon = wl_cfg80211_add_set_beacon,
6952 .add_beacon = wl_cfg80211_add_set_beacon,
6954 .change_beacon = wl_cfg80211_change_beacon,
6955 .start_ap = wl_cfg80211_start_ap,
6956 .stop_ap = wl_cfg80211_stop_ap,
6957 #endif /* LINUX_VERSION < KERNEL_VERSION(3,4,0) && !WL_COMPAT_WIRELESS */
6958 #ifdef WL_SCHED_SCAN
6959 .sched_scan_start = wl_cfg80211_sched_scan_start,
6960 .sched_scan_stop = wl_cfg80211_sched_scan_stop,
6961 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */
6962 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
6964 .del_station = wl_cfg80211_del_station,
6965 .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
6966 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
6967 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
6968 .tdls_oper = wl_cfg80211_tdls_oper
6969 #endif /* LINUX_VERSION > VERSION(3, 2, 0) || WL_COMPAT_WIRELESS */
6972 s32 wl_mode_to_nl80211_iftype(s32 mode)
6978 return NL80211_IFTYPE_STATION;
6980 return NL80211_IFTYPE_ADHOC;
6982 return NL80211_IFTYPE_AP;
6984 return NL80211_IFTYPE_UNSPECIFIED;
6990 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
6991 /* Kernel Network Support->Wireless->Regulatory rules database
6992 options should be enabled and regulatory CRDA regdb table populated in Kernel
6993 for proper country reg notification
6996 wl_cfg80211_reg_notifier(
6997 struct wiphy *wiphy,
6998 struct regulatory_request *request)
7000 struct wl_priv *wl = (struct wl_priv *)wiphy_priv(wiphy);
7003 if (!request || !wl) {
7004 WL_ERR(("Invalid arg\n"));
7008 WL_DBG(("ccode: %c%c Initiator: %d\n",
7009 request->alpha2[0], request->alpha2[1], request->initiator));
7011 /* We support only REGDOM_SET_BY_USER as of now */
7012 if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
7013 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
7014 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
7015 request->initiator));
7016 /* in case of no supported country by regdb
7017 lets driver setup platform default Locale
7021 WL_ERR(("Set country code %c%c from %s\n",
7022 request->alpha2[0], request->alpha2[1],
7023 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
7025 if ((ret = wldev_set_country(wl_to_prmry_ndev(wl), request->alpha2,
7026 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false))) < 0) {
7027 WL_ERR(("set country Failed :%d\n", ret));
7032 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
7034 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *data)
7037 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
7038 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
7039 dhd_pub_t *dhd = (dhd_pub_t *)data;
7040 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
7043 wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv));
7044 if (unlikely(!wdev->wiphy)) {
7045 WL_ERR(("Couldn not allocate wiphy device\n"));
7049 set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
7050 wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
7051 /* Report how many SSIDs Driver can support per Scan request */
7052 wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
7053 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
7054 #ifdef WL_SCHED_SCAN
7055 wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
7056 wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
7057 wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
7058 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
7059 #endif /* WL_SCHED_SCAN */
7060 wdev->wiphy->interface_modes =
7061 BIT(NL80211_IFTYPE_STATION)
7062 | BIT(NL80211_IFTYPE_ADHOC)
7063 #if !defined(WL_ENABLE_P2P_IF)
7064 | BIT(NL80211_IFTYPE_MONITOR)
7065 #endif /* !WL_ENABLE_P2P_IF */
7066 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
7067 | BIT(NL80211_IFTYPE_P2P_CLIENT)
7068 | BIT(NL80211_IFTYPE_P2P_GO)
7069 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
7070 #if defined(WL_CFG80211_P2P_DEV_IF)
7071 | BIT(NL80211_IFTYPE_P2P_DEVICE)
7072 #endif /* WL_CFG80211_P2P_DEV_IF */
7073 | BIT(NL80211_IFTYPE_AP);
7075 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
7076 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
7077 if (dhd && dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
7078 WL_DBG(("Setting interface combinations for SoftAP mode\n"));
7079 wdev->wiphy->iface_combinations = softap_iface_combinations;
7080 wdev->wiphy->n_iface_combinations =
7081 ARRAY_SIZE(softap_iface_combinations);
7083 WL_DBG(("Setting interface combinations for STA+P2P mode\n"));
7084 wdev->wiphy->iface_combinations = sta_p2p_iface_combinations;
7085 wdev->wiphy->n_iface_combinations =
7086 ARRAY_SIZE(sta_p2p_iface_combinations);
7088 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
7090 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
7092 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
7093 wdev->wiphy->cipher_suites = __wl_cipher_suites;
7094 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
7095 wdev->wiphy->max_remain_on_channel_duration = 5000;
7096 wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
7097 #ifndef WL_POWERSAVE_DISABLED
7098 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
7100 wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
7101 #endif /* !WL_POWERSAVE_DISABLED */
7102 wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
7103 WIPHY_FLAG_4ADDR_AP |
7104 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39)) && !defined(WL_COMPAT_WIRELESS)
7105 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
7107 WIPHY_FLAG_4ADDR_STATION;
7108 /* If driver advertises FW_ROAM, the supplicant wouldn't
7109 * send the BSSID & Freq in the connect command allowing the
7110 * the driver to choose the AP to connect to. But unless we
7111 * support ROAM_CACHE in firware this will delay the ASSOC as
7112 * as the FW need to do a full scan before attempting to connect
7113 * So that feature will just increase assoc. The better approach
7114 * to let Supplicant to provide channel info and FW letter may roam
7115 * if needed so DON'T advertise that featur eto Supplicant.
7117 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
7118 /* wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */
7120 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || defined(WL_COMPAT_WIRELESS)
7121 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
7122 WIPHY_FLAG_OFFCHAN_TX;
7124 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
7126 /* From 3.4 kernel ownards AP_SME flag can be advertised
7127 * to remove the patch from supplicant
7129 wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
7130 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
7132 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
7133 wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
7134 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
7136 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
7137 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
7139 WL_DBG(("Registering custom regulatory)\n"));
7140 wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
7141 wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
7142 /* Now we can register wiphy with cfg80211 module */
7143 err = wiphy_register(wdev->wiphy);
7144 if (unlikely(err < 0)) {
7145 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
7146 wiphy_free(wdev->wiphy);
7149 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
7150 KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
7151 wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
7152 #endif /* ((LINUX_VER >= 3.0) && (LINUX_VER <= 3.3)) && WL_IFACE_COMB_NUM_CHANNELS */
7157 static void wl_free_wdev(struct wl_priv *wl)
7159 struct wireless_dev *wdev = wl->wdev;
7160 struct wiphy *wiphy;
7162 WL_ERR(("wdev is invalid\n"));
7165 wiphy = wdev->wiphy;
7166 wiphy_unregister(wdev->wiphy);
7167 wdev->wiphy->dev.parent = NULL;
7169 wl_delete_all_netinfo(wl);
7171 /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "wl",
7172 * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
7176 static s32 wl_inform_bss(struct wl_priv *wl)
7178 struct wl_scan_results *bss_list;
7179 struct wl_bss_info *bi = NULL; /* must be initialized */
7182 #if defined(RSSIAVG)
7183 struct net_device *ndev = wl_to_prmry_ndev(wl);
7186 #if defined(BSSCACHE)
7187 wl_bss_cache_t *node;
7190 bss_list = wl->bss_list;
7192 #if defined(BSSCACHE)
7193 if (g_bss_cache_ctrl.m_timer_expired || (p2p_is_on(wl) && p2p_scan(wl))) {
7194 #if defined(RSSIAVG)
7195 wl_free_rssi_cache(&g_rssi_cache_ctrl);
7197 wl_free_bss_cache(&g_bss_cache_ctrl);
7198 g_bss_cache_ctrl.m_timer_expired ^= 1;
7200 wl_update_bss_cache(&g_bss_cache_ctrl, bss_list);
7201 wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
7202 wl_reset_bss_cache(&g_bss_cache_ctrl);
7205 #if defined(RSSIAVG)
7206 #if defined(BSSCACHE)
7207 node = g_bss_cache_ctrl.m_cache_head;
7209 wl_update_rssi_cache(&g_rssi_cache_ctrl, &node->results);
7213 wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
7216 wl_update_connected_rssi_cache(ndev, &g_rssi_cache_ctrl, &rssi);
7217 wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
7218 wl_reset_rssi_cache(&g_rssi_cache_ctrl);
7221 #if defined(BSSCACHE)
7222 if (p2p_disconnected > 0) {
7223 // terence 20130703: Fix for wrong group_capab (timing issue)
7224 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&p2p_disconnected_bssid);
7225 #if defined(RSSIAVG)
7226 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&p2p_disconnected_bssid);
7229 WL_SCAN(("Inform cached AP list\n"));
7230 node = g_bss_cache_ctrl.m_cache_head;
7231 for (i=0; node && i<WL_AP_MAX; i++) {
7232 if (node->dirty > 1) {
7233 // just inform dirty bss
7234 bi = node->results.bss_info;
7235 err = wl_inform_single_bss(wl, bi);
7239 wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0);
7240 wl_run_bss_cache_timer(&g_bss_cache_ctrl, 1);
7244 WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
7245 bi = next_bss(bss_list, bi);
7246 for_each_bss(bss_list, bi, i) {
7247 if (p2p_disconnected > 0 && !memcmp(&bi->BSSID, &p2p_disconnected_bssid, ETHER_ADDR_LEN))
7249 err = wl_inform_single_bss(wl, bi);
7252 if (p2p_disconnected > 0) {
7253 // terence 20130703: Fix for wrong group_capab (timing issue)
7255 if (p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1)
7256 p2p_disconnected = 0;
7262 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
7264 struct wiphy *wiphy = wl_to_wiphy(wl);
7265 struct ieee80211_mgmt *mgmt;
7266 struct ieee80211_channel *channel;
7267 struct ieee80211_supported_band *band;
7268 struct wl_cfg80211_bss_info *notif_bss_info;
7269 struct wl_scan_req *sr = wl_to_sr(wl);
7270 struct beacon_proberesp *beacon_proberesp;
7271 struct cfg80211_bss *cbss = NULL;
7278 if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
7279 WL_ERR(("Beacon is larger than buffer. Discarding\n"));
7282 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
7283 notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
7284 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
7285 if (unlikely(!notif_bss_info)) {
7286 WL_ERR(("notif_bss_info alloc failed\n"));
7289 mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
7290 notif_bss_info->channel =
7291 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
7293 if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
7294 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7296 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7298 WL_DBG(("No valid band\n"));
7299 kfree(notif_bss_info);
7302 notif_bss_info->rssi = dtoh16(bi->RSSI);
7303 #if defined(RSSIAVG)
7304 notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
7305 if (notif_bss_info->rssi == RSSI_MINVAL)
7306 notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
7308 #if defined(RSSIOFFSET)
7309 notif_bss_info->rssi = wl_update_rssi_offset(notif_bss_info->rssi);
7311 memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
7312 mgmt_type = wl->active_scan ?
7313 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
7314 if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
7315 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
7317 beacon_proberesp = wl->active_scan ?
7318 (struct beacon_proberesp *)&mgmt->u.probe_resp :
7319 (struct beacon_proberesp *)&mgmt->u.beacon;
7320 beacon_proberesp->timestamp = 0;
7321 beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
7322 beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
7324 wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length);
7325 wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
7326 wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX -
7327 offsetof(struct wl_cfg80211_bss_info, frame_buf));
7328 notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
7329 u.beacon.variable) + wl_get_ielen(wl);
7330 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
7331 freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
7334 freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
7337 WL_ERR(("Invalid channel, fail to change channel to freq\n"));
7338 kfree(notif_bss_info);
7341 channel = ieee80211_get_channel(wiphy, freq);
7342 if (unlikely(!channel)) {
7343 WL_ERR(("ieee80211_get_channel error, freq=%d, channel=%d\n",
7344 freq, notif_bss_info->channel));
7345 kfree(notif_bss_info);
7348 WL_SCAN(("BSSID %pM, channel %d, rssi %d, capa 0x04%x, mgmt_type %d, "
7349 "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel,
7350 notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
7351 notif_bss_info->frame_len, bi->SSID));
7353 signal = notif_bss_info->rssi * 100;
7354 if (!mgmt->u.probe_resp.timestamp) {
7355 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
7357 get_monotonic_boottime(&ts);
7358 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
7359 + ts.tv_nsec / 1000;
7362 do_gettimeofday(&tv);
7363 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
7368 cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
7369 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
7370 if (unlikely(!cbss)) {
7371 WL_ERR(("cfg80211_inform_bss_frame error\n"));
7372 kfree(notif_bss_info);
7376 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
7377 cfg80211_put_bss(wiphy, cbss);
7379 cfg80211_put_bss(cbss);
7380 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
7381 kfree(notif_bss_info);
7385 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
7387 u32 event = ntoh32(e->event_type);
7388 u32 status = ntoh32(e->status);
7389 u16 flags = ntoh16(e->flags);
7391 WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
7392 if (event == WLC_E_SET_SSID) {
7393 if (status == WLC_E_STATUS_SUCCESS) {
7394 if (!wl_is_ibssmode(wl, ndev))
7397 } else if (event == WLC_E_LINK) {
7398 if (flags & WLC_EVENT_MSG_LINK)
7402 WL_DBG(("wl_is_linkup false\n"));
7406 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
7408 u32 event = ntoh32(e->event_type);
7409 u16 flags = ntoh16(e->flags);
7411 if (event == WLC_E_DEAUTH_IND ||
7412 event == WLC_E_DISASSOC_IND ||
7413 event == WLC_E_DISASSOC ||
7414 event == WLC_E_DEAUTH) {
7415 #if (WL_DBG_LEVEL > 0)
7416 WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
7417 #endif /* (WL_DBG_LEVEL > 0) */
7419 } else if (event == WLC_E_LINK) {
7420 if (!(flags & WLC_EVENT_MSG_LINK)) {
7421 #if (WL_DBG_LEVEL > 0)
7422 WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
7423 #endif /* (WL_DBG_LEVEL > 0) */
7431 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
7433 u32 event = ntoh32(e->event_type);
7434 u32 status = ntoh32(e->status);
7436 if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
7438 if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
7444 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
7445 * to AP/P2P GO via events. If this change is backported to kernel for which
7446 * this driver is being built, then define WL_CFG80211_STA_EVENT. You
7447 * should use this new/del sta event mechanism for BRCM supplicant >= 22.
7450 wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev,
7451 const wl_event_msg_t *e, void *data)
7454 u32 event = ntoh32(e->event_type);
7455 u32 reason = ntoh32(e->reason);
7456 u32 len = ntoh32(e->datalen);
7458 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7459 && !defined(WL_COMPAT_WIRELESS)
7460 bool isfree = false;
7462 u8 bsscfgidx = e->bsscfgidx;
7468 struct ieee80211_supported_band *band;
7469 struct ether_addr da;
7470 struct ether_addr bssid;
7471 struct wiphy *wiphy = wl_to_wiphy(wl);
7474 struct station_info sinfo;
7475 #endif /* (LINUX_VERSION < VERSION(3,2,0)) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
7477 WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
7478 /* if link down, bsscfg is disabled. */
7479 if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
7480 wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) {
7481 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
7482 WL_INFO(("AP mode link down !! \n"));
7483 complete(&wl->iface_disable);
7487 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) \
7488 && !defined(WL_COMPAT_WIRELESS)
7489 WL_DBG(("Enter \n"));
7490 if (!len && (event == WLC_E_DEAUTH)) {
7491 len = 2; /* reason code field */
7495 body = kzalloc(len, GFP_KERNEL);
7498 WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
7502 memset(&bssid, 0, ETHER_ADDR_LEN);
7503 WL_DBG(("Enter event %d ndev %p\n", event, ndev));
7504 if (wl_get_mode_by_netdev(wl, ndev) == WL_INVALID) {
7509 memcpy(body, data, len);
7511 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
7512 NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
7513 memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
7514 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
7516 case WLC_E_ASSOC_IND:
7519 case WLC_E_REASSOC_IND:
7520 fc = FC_REASSOC_REQ;
7522 case WLC_E_DISASSOC_IND:
7525 case WLC_E_DEAUTH_IND:
7535 if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
7540 channel = dtoh32(ci.hw_channel);
7541 if (channel <= CH_MAX_2G_CHANNEL)
7542 band = wiphy->bands[IEEE80211_BAND_2GHZ];
7544 band = wiphy->bands[IEEE80211_BAND_5GHZ];
7546 WL_DBG(("No valid band\n"));
7551 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
7552 freq = ieee80211_channel_to_frequency(channel);
7555 freq = ieee80211_channel_to_frequency(channel, band->band);
7558 err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
7559 &mgmt_frame, &len, body);
7564 if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
7565 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
7566 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7568 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7569 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
7570 } else if (event == WLC_E_DISASSOC_IND) {
7571 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
7572 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7574 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7575 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
7576 } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7577 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
7578 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
7580 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
7581 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
7589 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
7591 if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
7592 reason == DOT11_SC_SUCCESS) {
7593 sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
7595 WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
7598 sinfo.assoc_req_ies = data;
7599 sinfo.assoc_req_ies_len = len;
7600 printk("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
7601 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
7602 } else if (event == WLC_E_DISASSOC_IND) {
7603 printk("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
7604 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7605 } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
7606 printk("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
7607 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
7609 #endif /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
7614 wl_get_auth_assoc_status(struct wl_priv *wl, struct net_device *ndev,
7615 const wl_event_msg_t *e)
7617 u32 reason = ntoh32(e->reason);
7618 u32 event = ntoh32(e->event_type);
7619 struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
7620 WL_DBG(("event type : %d, reason : %d\n", event, reason));
7625 sec->auth_assoc_res_status = reason;
7630 WL_ERR(("sec is NULL\n"));
7635 wl_notify_connect_status_ibss(struct wl_priv *wl, struct net_device *ndev,
7636 const wl_event_msg_t *e, void *data)
7639 u32 event = ntoh32(e->event_type);
7640 u16 flags = ntoh16(e->flags);
7641 u32 status = ntoh32(e->status);
7644 if (event == WLC_E_JOIN) {
7645 WL_DBG(("joined in IBSS network\n"));
7647 if (event == WLC_E_START) {
7648 WL_DBG(("started IBSS network\n"));
7650 if (event == WLC_E_JOIN || event == WLC_E_START ||
7651 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
7652 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7653 /* ROAM or Redundant */
7654 u8 *cur_bssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7655 if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
7656 WL_DBG(("IBSS connected event from same BSSID("
7657 MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
7660 WL_INFO(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
7661 MAC2STRDBG(cur_bssid), MAC2STRDBG((u8 *)&e->addr)));
7662 wl_get_assoc_ies(wl, ndev);
7663 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7664 wl_update_bss_info(wl, ndev);
7665 cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7668 /* New connection */
7669 WL_INFO(("IBSS connected to " MACDBG "\n", MAC2STRDBG((u8 *)&e->addr)));
7671 wl_get_assoc_ies(wl, ndev);
7672 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7673 wl_update_bss_info(wl, ndev);
7674 cfg80211_ibss_joined(ndev, (s8 *)&e->addr, GFP_KERNEL);
7675 wl_set_drv_status(wl, CONNECTED, ndev);
7677 wl_update_prof(wl, ndev, NULL, (void *)&active, WL_PROF_ACT);
7679 } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
7680 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
7681 wl_clr_drv_status(wl, CONNECTED, ndev);
7683 wl_init_prof(wl, ndev);
7685 else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
7686 WL_DBG(("no action - join fail (IBSS mode)\n"));
7689 WL_DBG(("no action (IBSS mode)\n"));
7695 wl_notify_connect_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7696 const wl_event_msg_t *e, void *data)
7699 struct net_device *ndev = NULL;
7701 u32 event = ntoh32(e->event_type);
7703 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7705 if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
7706 err = wl_notify_connect_status_ap(wl, ndev, e, data);
7707 } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS) {
7708 err = wl_notify_connect_status_ibss(wl, ndev, e, data);
7709 } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) {
7710 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
7711 ntoh32(e->event_type), ntoh32(e->status), ndev));
7712 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
7713 wl_get_auth_assoc_status(wl, ndev, e);
7716 if (wl_is_linkup(wl, e, ndev)) {
7719 if (!wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7720 printk("wl_bss_connect_done succeeded with " MACDBG "\n",
7721 MAC2STRDBG((u8*)(&e->addr)));
7722 wl_bss_connect_done(wl, ndev, e, data, true);
7723 dhd_conf_set_phyoclscdenable((dhd_pub_t *)wl->pub);
7724 WL_DBG(("joined in BSS network \"%s\"\n",
7725 ((struct wlc_ssid *)
7726 wl_read_prof(wl, ndev, WL_PROF_SSID))->SSID));
7728 wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7729 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7730 dhd_conf_set_wme((dhd_pub_t *)wl->pub);
7731 } else if (wl_is_linkdown(wl, e)) {
7732 if (wl->scan_request) {
7734 wl_notify_escan_complete(wl, ndev, true, true);
7736 del_timer_sync(&wl->scan_timeout);
7737 wl_iscan_aborted(wl);
7740 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
7742 u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7744 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
7745 reason = ntoh32(e->reason);
7746 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
7747 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
7749 printk("link down if %s may call cfg80211_disconnected. "
7750 "event : %d, reason=%d from " MACDBG "\n",
7751 ndev->name, event, ntoh32(e->reason),
7752 MAC2STRDBG((u8*)(&e->addr)));
7753 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
7754 WL_ERR(("BSSID of event is not the connected BSSID"
7755 "(ignore it) cur: " MACDBG " event: " MACDBG"\n",
7756 MAC2STRDBG(curbssid), MAC2STRDBG((u8*)(&e->addr))));
7759 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
7760 // terence 20130703: Fix for wrong group_capab (timing issue)
7761 p2p_disconnected = 1;
7762 memcpy(&p2p_disconnected_bssid, curbssid, ETHER_ADDR_LEN);
7764 wl_clr_drv_status(wl, CONNECTED, ndev);
7765 if (! wl_get_drv_status(wl, DISCONNECTING, ndev)) {
7766 /* To make sure disconnect, explictly send dissassoc
7767 * for BSSID 00:00:00:00:00:00 issue
7769 scbval.val = WLAN_REASON_DEAUTH_LEAVING;
7771 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
7772 scbval.val = htod32(scbval.val);
7773 err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
7774 sizeof(scb_val_t), true);
7776 WL_ERR(("WLC_DISASSOC error %d\n", err));
7779 cfg80211_disconnected(ndev, reason, NULL, 0, GFP_KERNEL);
7781 wl_init_prof(wl, ndev);
7784 else if (wl_get_drv_status(wl, CONNECTING, ndev)) {
7786 printk("link down, during connecting\n");
7787 #ifdef ESCAN_RESULT_PATCH
7788 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7789 (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
7790 (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
7791 /* In case this event comes while associating another AP */
7792 #endif /* ESCAN_RESULT_PATCH */
7793 wl_bss_connect_done(wl, ndev, e, data, false);
7795 wl_clr_drv_status(wl, DISCONNECTING, ndev);
7797 /* if link down, bsscfg is diabled */
7798 if (ndev != wl_to_prmry_ndev(wl))
7799 complete(&wl->iface_disable);
7801 } else if (wl_is_nonetwork(wl, e)) {
7802 printk("connect failed event=%d e->status %d e->reason %d \n",
7803 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
7804 /* Clean up any pending scan request */
7805 if (wl->scan_request) {
7807 wl_notify_escan_complete(wl, ndev, true, true);
7809 del_timer_sync(&wl->scan_timeout);
7810 wl_iscan_aborted(wl);
7813 if (wl_get_drv_status(wl, CONNECTING, ndev))
7814 wl_bss_connect_done(wl, ndev, e, data, false);
7816 printk("%s nothing\n", __FUNCTION__);
7819 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(wl, ndev)));
7825 wl_notify_roaming_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
7826 const wl_event_msg_t *e, void *data)
7829 struct net_device *ndev = NULL;
7831 u32 event = be32_to_cpu(e->event_type);
7832 u32 status = be32_to_cpu(e->status);
7834 WL_DBG(("Enter \n"));
7836 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
7838 if (event == WLC_E_ROAM && status == WLC_E_STATUS_SUCCESS) {
7839 if (wl_get_drv_status(wl, CONNECTED, ndev))
7840 wl_bss_roaming_done(wl, ndev, e, data);
7842 wl_bss_connect_done(wl, ndev, e, data, true);
7844 wl_update_prof(wl, ndev, e, &act, WL_PROF_ACT);
7845 wl_update_prof(wl, ndev, NULL, (void *)&e->addr, WL_PROF_BSSID);
7846 dhd_conf_set_wme((dhd_pub_t *)wl->pub);
7851 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
7853 wl_assoc_info_t assoc_info;
7854 struct wl_connect_info *conn_info = wl_to_conn(wl);
7857 WL_DBG(("Enter \n"));
7858 err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, wl->extra_buf,
7859 WL_ASSOC_INFO_MAX, NULL);
7860 if (unlikely(err)) {
7861 WL_ERR(("could not get assoc info (%d)\n", err));
7864 memcpy(&assoc_info, wl->extra_buf, sizeof(wl_assoc_info_t));
7865 assoc_info.req_len = htod32(assoc_info.req_len);
7866 assoc_info.resp_len = htod32(assoc_info.resp_len);
7867 assoc_info.flags = htod32(assoc_info.flags);
7868 if (conn_info->req_ie_len) {
7869 conn_info->req_ie_len = 0;
7870 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
7872 if (conn_info->resp_ie_len) {
7873 conn_info->resp_ie_len = 0;
7874 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
7876 if (assoc_info.req_len) {
7877 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, wl->extra_buf,
7878 WL_ASSOC_INFO_MAX, NULL);
7879 if (unlikely(err)) {
7880 WL_ERR(("could not get assoc req (%d)\n", err));
7883 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
7884 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
7885 conn_info->req_ie_len -= ETHER_ADDR_LEN;
7887 if (conn_info->req_ie_len <= MAX_REQ_LINE)
7888 memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len);
7890 WL_ERR(("IE size %d above max %d size \n",
7891 conn_info->req_ie_len, MAX_REQ_LINE));
7895 conn_info->req_ie_len = 0;
7897 if (assoc_info.resp_len) {
7898 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, wl->extra_buf,
7899 WL_ASSOC_INFO_MAX, NULL);
7900 if (unlikely(err)) {
7901 WL_ERR(("could not get assoc resp (%d)\n", err));
7904 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
7905 if (conn_info->resp_ie_len <= MAX_REQ_LINE)
7906 memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len);
7908 WL_ERR(("IE size %d above max %d size \n",
7909 conn_info->resp_ie_len, MAX_REQ_LINE));
7913 conn_info->resp_ie_len = 0;
7915 WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
7916 conn_info->resp_ie_len));
7921 static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
7922 size_t *join_params_size)
7924 chanspec_t chanspec = 0;
7926 join_params->params.chanspec_num = 1;
7927 join_params->params.chanspec_list[0] = ch;
7929 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
7930 chanspec |= WL_CHANSPEC_BAND_2G;
7932 chanspec |= WL_CHANSPEC_BAND_5G;
7934 chanspec |= WL_CHANSPEC_BW_20;
7935 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
7937 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
7938 join_params->params.chanspec_num * sizeof(chanspec_t);
7940 join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
7941 join_params->params.chanspec_list[0] |= chanspec;
7942 join_params->params.chanspec_list[0] =
7943 wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
7945 join_params->params.chanspec_num =
7946 htod32(join_params->params.chanspec_num);
7947 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
7948 join_params->params.chanspec_list[0],
7949 join_params->params.chanspec_num));
7953 static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
7955 struct cfg80211_bss *bss;
7956 struct wl_bss_info *bi;
7957 struct wlc_ssid *ssid;
7958 struct bcm_tlv *tim;
7959 s32 beacon_interval;
7965 struct wiphy *wiphy;
7967 wiphy = wl_to_wiphy(wl);
7969 ssid = (struct wlc_ssid *)wl_read_prof(wl, ndev, WL_PROF_SSID);
7970 curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
7971 bss = cfg80211_get_bss(wiphy, NULL, curbssid,
7972 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
7973 WLAN_CAPABILITY_ESS);
7975 mutex_lock(&wl->usr_sync);
7977 WL_DBG(("Could not find the AP\n"));
7978 *(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
7979 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
7980 wl->extra_buf, WL_EXTRA_BUF_MAX, false);
7981 if (unlikely(err)) {
7982 WL_ERR(("Could not get bss info %d\n", err));
7983 goto update_bss_info_out;
7985 bi = (struct wl_bss_info *)(wl->extra_buf + 4);
7986 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
7987 WL_ERR(("Bssid doesn't match\n"));
7989 goto update_bss_info_out;
7991 err = wl_inform_single_bss(wl, bi);
7993 goto update_bss_info_out;
7995 ie = ((u8 *)bi) + bi->ie_offset;
7996 ie_len = bi->ie_length;
7997 beacon_interval = cpu_to_le16(bi->beacon_period);
7999 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
8000 #if defined(WL_CFG80211_P2P_DEV_IF)
8001 ie = (u8 *)bss->ies->data;
8002 ie_len = bss->ies->len;
8004 ie = bss->information_elements;
8005 ie_len = bss->len_information_elements;
8006 #endif /* WL_CFG80211_P2P_DEV_IF */
8007 beacon_interval = bss->beacon_interval;
8008 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
8009 cfg80211_put_bss(wiphy, bss);
8011 cfg80211_put_bss(bss);
8012 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
8015 tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
8017 dtim_period = tim->data[1];
8020 * active scan was done so we could not get dtim
8021 * information out of probe response.
8022 * so we speficially query dtim information.
8024 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
8025 &dtim_period, sizeof(dtim_period), false);
8026 if (unlikely(err)) {
8027 WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
8028 goto update_bss_info_out;
8032 wl_update_prof(wl, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
8033 wl_update_prof(wl, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
8035 update_bss_info_out:
8036 if (unlikely(err)) {
8037 WL_ERR(("Failed with error %d\n", err));
8039 mutex_unlock(&wl->usr_sync);
8044 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
8045 const wl_event_msg_t *e, void *data)
8047 struct wl_connect_info *conn_info = wl_to_conn(wl);
8050 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
8051 struct wl_bss_info *bss_info;
8052 struct wiphy *wiphy = wl_to_wiphy(wl);
8053 struct ieee80211_supported_band *band;
8054 struct ieee80211_channel *notify_channel = NULL;
8058 #endif /* LINUX_VERSION > 2.6.39 || WL_COMPAT_WIRELESS */
8060 wl_get_assoc_ies(wl, ndev);
8061 wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
8062 curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
8063 wl_update_bss_info(wl, ndev);
8064 wl_update_pmklist(ndev, wl->pmk_list, err);
8066 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
8067 /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
8068 buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
8072 *(__le32 *)buf = htod32(WL_EXTRA_BUF_MAX);
8073 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX, false);
8077 bss_info = (struct wl_bss_info *)(buf + 4);
8078 channel = bss_info->ctl_ch ? bss_info->ctl_ch :
8079 CHSPEC_CHANNEL(wl_chspec_driver_to_host(bss_info->chanspec));
8080 if (channel <= CH_MAX_2G_CHANNEL)
8081 band = wiphy->bands[IEEE80211_BAND_2GHZ];
8083 band = wiphy->bands[IEEE80211_BAND_5GHZ];
8084 freq = ieee80211_channel_to_frequency(channel, band->band);
8085 notify_channel = ieee80211_get_channel(wiphy, freq);
8088 #endif /* LINUX_VERSION > 2.6.39 || WL_COMPAT_WIRELESS */
8090 printk("wl_bss_roaming_done succeeded to " MACDBG "\n",
8091 MAC2STRDBG((u8*)(&e->addr)));
8092 dhd_conf_set_wme((dhd_pub_t *)wl->pub);
8094 cfg80211_roamed(ndev,
8095 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)) || defined(WL_COMPAT_WIRELESS)
8099 conn_info->req_ie, conn_info->req_ie_len,
8100 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
8101 WL_DBG(("Report roaming result\n"));
8103 wl_set_drv_status(wl, CONNECTED, ndev);
8109 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
8110 const wl_event_msg_t *e, void *data, bool completed)
8112 struct wl_connect_info *conn_info = wl_to_conn(wl);
8113 struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC);
8115 u8 *curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
8117 WL_ERR(("sec is NULL\n"));
8120 WL_DBG((" enter\n"));
8121 #ifdef ESCAN_RESULT_PATCH
8122 if (wl_get_drv_status(wl, CONNECTED, ndev)) {
8123 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
8124 WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
8125 ntoh32(e->event_type), ntoh32(e->status)));
8129 if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
8130 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
8131 WL_DBG(("copy bssid\n"));
8132 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
8136 if (wl->scan_request) {
8137 wl_notify_escan_complete(wl, ndev, true, true);
8139 #endif /* ESCAN_RESULT_PATCH */
8140 if (wl_get_drv_status(wl, CONNECTING, ndev)) {
8141 wl_cfg80211_scan_abort(wl);
8142 wl_clr_drv_status(wl, CONNECTING, ndev);
8144 wl_get_assoc_ies(wl, ndev);
8145 wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID);
8146 curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID);
8147 wl_update_bss_info(wl, ndev);
8148 wl_update_pmklist(ndev, wl->pmk_list, err);
8149 wl_set_drv_status(wl, CONNECTED, ndev);
8150 if (ndev != wl_to_prmry_ndev(wl)) {
8151 /* reinitialize completion to clear previous count */
8152 INIT_COMPLETION(wl->iface_disable);
8155 cfg80211_connect_result(ndev,
8158 conn_info->req_ie_len,
8160 conn_info->resp_ie_len,
8161 completed ? WLAN_STATUS_SUCCESS :
8162 (sec->auth_assoc_res_status) ?
8163 sec->auth_assoc_res_status :
8164 WLAN_STATUS_UNSPECIFIED_FAILURE,
8167 WL_INFO(("Report connect result - connection succeeded\n"));
8168 dhd_conf_set_wme((dhd_pub_t *)wl->pub);
8170 WL_ERR(("Report connect result - connection failed\n"));
8176 wl_notify_mic_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8177 const wl_event_msg_t *e, void *data)
8179 struct net_device *ndev = NULL;
8180 u16 flags = ntoh16(e->flags);
8181 enum nl80211_key_type key_type;
8183 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8185 mutex_lock(&wl->usr_sync);
8186 if (flags & WLC_EVENT_MSG_GROUP)
8187 key_type = NL80211_KEYTYPE_GROUP;
8189 key_type = NL80211_KEYTYPE_PAIRWISE;
8191 cfg80211_michael_mic_failure(ndev, (u8 *)&e->addr, key_type, -1,
8193 mutex_unlock(&wl->usr_sync);
8200 wl_notify_pfn_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8201 const wl_event_msg_t *e, void *data)
8203 struct net_device *ndev = NULL;
8205 WL_ERR((">>> PNO Event\n"));
8207 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8209 #ifndef WL_SCHED_SCAN
8210 mutex_lock(&wl->usr_sync);
8211 /* TODO: Use cfg80211_sched_scan_results(wiphy); */
8212 cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
8213 mutex_unlock(&wl->usr_sync);
8215 /* If cfg80211 scheduled scan is supported, report the pno results via sched
8218 wl_notify_sched_scan_results(wl, ndev, e, data);
8219 #endif /* WL_SCHED_SCAN */
8222 #endif /* PNO_SUPPORT */
8225 wl_notify_scan_status(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8226 const wl_event_msg_t *e, void *data)
8228 struct channel_info channel_inform;
8229 struct wl_scan_results *bss_list;
8230 struct net_device *ndev = NULL;
8231 u32 len = WL_SCAN_BUF_MAX;
8233 unsigned long flags;
8235 WL_DBG(("Enter \n"));
8236 if (!wl_get_drv_status(wl, SCANNING, ndev)) {
8237 WL_ERR(("scan is not ready \n"));
8240 if (wl->iscan_on && wl->iscan_kickstart)
8241 return wl_wakeup_iscan(wl_to_iscan(wl));
8243 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8245 mutex_lock(&wl->usr_sync);
8246 wl_clr_drv_status(wl, SCANNING, ndev);
8247 err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
8248 sizeof(channel_inform), false);
8249 if (unlikely(err)) {
8250 WL_ERR(("scan busy (%d)\n", err));
8253 channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
8254 if (unlikely(channel_inform.scan_channel)) {
8256 WL_DBG(("channel_inform.scan_channel (%d)\n",
8257 channel_inform.scan_channel));
8259 wl->bss_list = wl->scan_results;
8260 bss_list = wl->bss_list;
8261 memset(bss_list, 0, len);
8262 bss_list->buflen = htod32(len);
8263 err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
8264 if (unlikely(err) && unlikely(!wl->scan_suppressed)) {
8265 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
8269 bss_list->buflen = dtoh32(bss_list->buflen);
8270 bss_list->version = dtoh32(bss_list->version);
8271 bss_list->count = dtoh32(bss_list->count);
8273 err = wl_inform_bss(wl);
8276 del_timer_sync(&wl->scan_timeout);
8277 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8278 if (wl->scan_request) {
8279 cfg80211_scan_done(wl->scan_request, false);
8280 wl->scan_request = NULL;
8282 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8283 WL_DBG(("cfg80211_scan_done\n"));
8284 mutex_unlock(&wl->usr_sync);
8289 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
8290 const struct ether_addr *sa, const struct ether_addr *bssid,
8291 u8 **pheader, u32 *body_len, u8 *pbody)
8293 struct dot11_management_header *hdr;
8297 u32 prebody_len = *body_len;
8300 /* capability , listen interval */
8301 totlen = DOT11_ASSOC_REQ_FIXED_LEN;
8302 *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
8305 case FC_REASSOC_REQ:
8306 /* capability, listen inteval, ap address */
8307 totlen = DOT11_REASSOC_REQ_FIXED_LEN;
8308 *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
8311 totlen += DOT11_MGMT_HDR_LEN + prebody_len;
8312 *pheader = kzalloc(totlen, GFP_KERNEL);
8313 if (*pheader == NULL) {
8314 WL_ERR(("memory alloc failed \n"));
8317 hdr = (struct dot11_management_header *) (*pheader);
8318 hdr->fc = htol16(fc);
8321 offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
8322 bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
8323 bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
8324 bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
8325 if ((pbody != NULL) && prebody_len)
8326 bcopy((const char*)pbody, offset, prebody_len);
8333 wl_stop_wait_next_action_frame(struct wl_priv *wl)
8335 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) {
8336 if (!(wl_get_p2p_status(wl, ACTION_TX_COMPLETED) ||
8337 wl_get_p2p_status(wl, ACTION_TX_NOACK)))
8338 wl_set_p2p_status(wl, ACTION_TX_COMPLETED);
8340 WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
8341 /* if channel is not zero, "actfame" uses off channel scan.
8342 * So abort scan for off channel completion.
8344 if (wl->af_sent_channel)
8345 wl_cfg80211_scan_abort(wl);
8347 #ifdef WL_CFG80211_SYNC_GON
8348 else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) {
8349 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
8350 /* So abort scan to cancel listen */
8351 wl_cfg80211_scan_abort(wl);
8353 #endif /* WL_CFG80211_SYNC_GON */
8357 int wl_cfg80211_get_ioctl_version(void)
8359 return ioctl_version;
8363 wl_notify_rx_mgmt_frame(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
8364 const wl_event_msg_t *e, void *data)
8366 struct ieee80211_supported_band *band;
8367 struct wiphy *wiphy = wl_to_wiphy(wl);
8368 struct ether_addr da;
8369 struct ether_addr bssid;
8370 bool isfree = false;
8373 struct net_device *ndev = NULL;
8374 wifi_p2p_pub_act_frame_t *act_frm = NULL;
8375 wifi_p2p_action_frame_t *p2p_act_frm = NULL;
8376 wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
8377 wl_event_rx_frame_data_t *rxframe =
8378 (wl_event_rx_frame_data_t*)data;
8379 u32 event = ntoh32(e->event_type);
8381 u8 bsscfgidx = e->bsscfgidx;
8382 u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
8383 u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
8385 memset(&bssid, 0, ETHER_ADDR_LEN);
8387 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
8389 if (channel <= CH_MAX_2G_CHANNEL)
8390 band = wiphy->bands[IEEE80211_BAND_2GHZ];
8392 band = wiphy->bands[IEEE80211_BAND_5GHZ];
8394 WL_DBG(("No valid band\n"));
8397 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
8398 freq = ieee80211_channel_to_frequency(channel);
8401 freq = ieee80211_channel_to_frequency(channel, band->band);
8403 if (event == WLC_E_ACTION_FRAME_RX) {
8404 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
8405 NULL, 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &wl->ioctl_buf_sync);
8407 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
8409 WL_ERR(("WLC_GET_BSSID error %d\n", err));
8410 memcpy(da.octet, wl->ioctl_buf, ETHER_ADDR_LEN);
8411 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
8412 &mgmt_frame, &mgmt_frame_len,
8413 (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
8415 WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
8416 mgmt_frame_len, channel, freq));
8420 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8421 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8422 act_frm = (wifi_p2p_pub_act_frame_t *)
8423 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8424 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8425 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8426 p2p_act_frm = (wifi_p2p_action_frame_t *)
8427 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8429 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8430 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
8432 if (wl_get_p2p_status(wl, DISC_IN_PROGRESS)) {
8433 WL_ERR(("SD offload is in progress. Don't report the"
8434 "frame via rx_mgmt path\n"));
8439 sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
8440 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
8441 if (sd_act_frm && wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8442 if (wl->next_af_subtype == sd_act_frm->action) {
8443 WL_DBG(("We got a right next frame of SD!(%d)\n",
8444 sd_act_frm->action));
8445 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8447 /* Stop waiting for next AF. */
8448 wl_stop_wait_next_action_frame(wl);
8454 * if we got normal action frame and ndev is p2p0,
8455 * we have to change ndev from p2p0 to wlan0
8457 #if defined(WL_ENABLE_P2P_IF)
8458 if (wl->p2p_net == cfgdev)
8459 cfgdev = wl_to_prmry_ndev(wl);
8460 #endif /* WL_ENABLE_P2P_IF */
8462 if (wl->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
8464 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
8465 mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
8466 WL_DBG(("Recived action is not public action frame\n"));
8467 } else if (wl->next_af_subtype == action) {
8468 WL_DBG(("Recived action is the waiting action(%d)\n",
8470 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8472 /* Stop waiting for next AF. */
8473 wl_stop_wait_next_action_frame(wl);
8480 if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) {
8481 if (wl->next_af_subtype == act_frm->subtype) {
8482 WL_DBG(("We got a right next frame!(%d)\n",
8484 wl_clr_drv_status(wl, WAITING_NEXT_ACT_FRM, ndev);
8486 /* Stop waiting for next AF. */
8487 wl_stop_wait_next_action_frame(wl);
8492 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
8493 mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
8495 * After complete GO Negotiation, roll back to mpc mode
8497 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
8498 (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
8499 wldev_iovar_setint(ndev, "mpc", 1);
8501 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
8502 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
8503 wl_clr_p2p_status(wl, GO_NEG_PHASE);
8506 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
8508 /* wpa supplicant use probe request event for restarting another GON Req.
8509 * but it makes GON Req repetition.
8510 * so if src addr of prb req is same as my target device,
8511 * do not send probe request event during sending action frame.
8513 if (event == WLC_E_P2P_PROBREQ_MSG) {
8514 WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
8515 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
8518 /* Filter any P2P probe reqs arriving during the
8522 wl_get_p2p_status(wl, GO_NEG_PHASE)) {
8523 WL_DBG(("Filtering P2P probe_req while "
8524 "being in GO-Neg state\n"));
8530 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || defined(WL_COMPAT_WIRELESS)
8531 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8533 cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
8534 #endif /* LINUX_VERSION >= VERSION(3, 4, 0) || WL_COMPAT_WIRELESS */
8536 WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
8537 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
8544 #ifdef WL_SCHED_SCAN
8545 /* If target scan is not reliable, set the below define to "1" to do a
8548 #define FULL_ESCAN_ON_PFN_NET_FOUND 0
8550 wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev,
8551 const wl_event_msg_t *e, void *data)
8553 wl_pfn_net_info_t *netinfo, *pnetinfo;
8554 struct wiphy *wiphy = wl_to_wiphy(wl);
8556 struct cfg80211_scan_request *request = NULL;
8557 struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
8558 struct ieee80211_channel *channel = NULL;
8559 int channel_req = 0;
8561 struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
8562 int n_pfn_results = pfn_result->count;
8564 WL_DBG(("Enter\n"));
8566 if (e->event_type == WLC_E_PFN_NET_LOST) {
8567 WL_PNO(("PFN NET LOST event. Do Nothing \n"));
8570 WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
8571 if (n_pfn_results > 0) {
8574 if (n_pfn_results > MAX_PFN_LIST_COUNT)
8575 n_pfn_results = MAX_PFN_LIST_COUNT;
8576 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
8577 - sizeof(wl_pfn_net_info_t));
8579 memset(&ssid, 0x00, sizeof(ssid));
8581 request = kzalloc(sizeof(*request)
8582 + sizeof(*request->channels) * n_pfn_results,
8584 channel = (struct ieee80211_channel *)kzalloc(
8585 (sizeof(struct ieee80211_channel) * n_pfn_results),
8587 if (!request || !channel) {
8588 WL_ERR(("No memory"));
8593 request->wiphy = wiphy;
8595 for (i = 0; i < n_pfn_results; i++) {
8596 netinfo = &pnetinfo[i];
8598 WL_ERR(("Invalid netinfo ptr. index:%d", i));
8602 WL_PNO((">>> SSID:%s Channel:%d \n",
8603 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
8604 /* PFN result doesn't have all the info which are required by the supplicant
8605 * (For e.g IEs) Do a target Escan so that sched scan results are reported
8606 * via wl_inform_single_bss in the required format. Escan does require the
8607 * scan request in the form of cfg80211_scan_request. For timebeing, create
8608 * cfg80211_scan_request one out of the received PNO event.
8610 memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
8611 netinfo->pfnsubnet.SSID_len);
8612 ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
8615 channel_req = netinfo->pfnsubnet.channel;
8616 band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
8617 : NL80211_BAND_5GHZ;
8618 channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
8619 channel[i].band = band;
8620 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
8621 request->channels[i] = &channel[i];
8622 request->n_channels++;
8625 /* assign parsed ssid array */
8626 if (request->n_ssids)
8627 request->ssids = &ssid[0];
8629 if (wl_get_drv_status_all(wl, SCANNING)) {
8630 /* Abort any on-going scan */
8631 wl_notify_escan_complete(wl, ndev, true, true);
8634 if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
8635 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
8636 err = wl_cfgp2p_discover_enable_search(wl, false);
8637 if (unlikely(err)) {
8638 wl_clr_drv_status(wl, SCANNING, ndev);
8643 wl_set_drv_status(wl, SCANNING, ndev);
8644 #if FULL_ESCAN_ON_PFN_NET_FOUND
8645 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
8646 err = wl_do_escan(wl, wiphy, ndev, NULL);
8648 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
8649 err = wl_do_escan(wl, wiphy, ndev, request);
8652 wl_clr_drv_status(wl, SCANNING, ndev);
8655 wl->sched_scan_running = TRUE;
8658 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
8667 #endif /* WL_SCHED_SCAN */
8669 static void wl_init_conf(struct wl_conf *conf)
8671 WL_DBG(("Enter \n"));
8672 conf->frag_threshold = (u32)-1;
8673 conf->rts_threshold = (u32)-1;
8674 conf->retry_short = (u32)-1;
8675 conf->retry_long = (u32)-1;
8676 conf->tx_power = -1;
8679 static void wl_init_prof(struct wl_priv *wl, struct net_device *ndev)
8681 unsigned long flags;
8682 struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
8684 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8685 memset(profile, 0, sizeof(struct wl_profile));
8686 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8689 static void wl_init_event_handler(struct wl_priv *wl)
8691 memset(wl->evt_handler, 0, sizeof(wl->evt_handler));
8693 wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
8694 wl->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
8695 wl->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
8696 wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
8697 wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
8698 wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
8699 wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
8700 wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
8701 wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
8702 wl->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
8703 wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
8704 wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
8705 wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
8706 wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8707 wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
8708 wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
8709 wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
8710 wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
8711 wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
8712 wl->evt_handler[WLC_E_START] = wl_notify_connect_status;
8714 wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
8715 #endif /* PNO_SUPPORT */
8717 wl->evt_handler[WLC_E_SERVICE_FOUND] = wl_svc_resp_handler;
8718 wl->evt_handler[WLC_E_P2PO_ADD_DEVICE] = wl_notify_device_discovery;
8719 wl->evt_handler[WLC_E_P2PO_DEL_DEVICE] = wl_notify_device_discovery;
8722 wl->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
8726 #if defined(STATIC_WL_PRIV_STRUCT)
8728 wl_init_escan_result_buf(struct wl_priv *wl)
8730 wl->escan_info.escan_buf = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0);
8731 bzero(wl->escan_info.escan_buf, ESCAN_BUF_SIZE);
8735 wl_deinit_escan_result_buf(struct wl_priv *wl)
8737 wl->escan_info.escan_buf = NULL;
8740 #endif /* STATIC_WL_PRIV_STRUCT */
8742 static s32 wl_init_priv_mem(struct wl_priv *wl)
8744 WL_DBG(("Enter \n"));
8745 wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
8746 if (unlikely(!wl->scan_results)) {
8747 WL_ERR(("Scan results alloc failed\n"));
8748 goto init_priv_mem_out;
8750 wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL);
8751 if (unlikely(!wl->conf)) {
8752 WL_ERR(("wl_conf alloc failed\n"));
8753 goto init_priv_mem_out;
8756 (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL);
8757 if (unlikely(!wl->scan_req_int)) {
8758 WL_ERR(("Scan req alloc failed\n"));
8759 goto init_priv_mem_out;
8761 wl->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8762 if (unlikely(!wl->ioctl_buf)) {
8763 WL_ERR(("Ioctl buf alloc failed\n"));
8764 goto init_priv_mem_out;
8766 wl->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
8767 if (unlikely(!wl->escan_ioctl_buf)) {
8768 WL_ERR(("Ioctl buf alloc failed\n"));
8769 goto init_priv_mem_out;
8771 wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
8772 if (unlikely(!wl->extra_buf)) {
8773 WL_ERR(("Extra buf alloc failed\n"));
8774 goto init_priv_mem_out;
8776 wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL);
8777 if (unlikely(!wl->iscan)) {
8778 WL_ERR(("Iscan buf alloc failed\n"));
8779 goto init_priv_mem_out;
8781 wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL);
8782 if (unlikely(!wl->pmk_list)) {
8783 WL_ERR(("pmk list alloc failed\n"));
8784 goto init_priv_mem_out;
8786 wl->sta_info = (void *)kzalloc(sizeof(*wl->sta_info), GFP_KERNEL);
8787 if (unlikely(!wl->sta_info)) {
8788 WL_ERR(("sta info alloc failed\n"));
8789 goto init_priv_mem_out;
8792 #if defined(STATIC_WL_PRIV_STRUCT)
8793 wl->conn_info = (void *)kzalloc(sizeof(*wl->conn_info), GFP_KERNEL);
8794 if (unlikely(!wl->conn_info)) {
8795 WL_ERR(("wl->conn_info alloc failed\n"));
8796 goto init_priv_mem_out;
8798 wl->ie = (void *)kzalloc(sizeof(*wl->ie), GFP_KERNEL);
8799 if (unlikely(!wl->ie)) {
8800 WL_ERR(("wl->ie alloc failed\n"));
8801 goto init_priv_mem_out;
8803 wl_init_escan_result_buf(wl);
8804 #endif /* STATIC_WL_PRIV_STRUCT */
8805 wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL);
8806 if (unlikely(!wl->afx_hdl)) {
8807 WL_ERR(("afx hdl alloc failed\n"));
8808 goto init_priv_mem_out;
8810 init_completion(&wl->act_frm_scan);
8811 init_completion(&wl->wait_next_af);
8813 INIT_WORK(&wl->afx_hdl->work, wl_cfg80211_afx_handler);
8818 wl_deinit_priv_mem(wl);
8823 static void wl_deinit_priv_mem(struct wl_priv *wl)
8825 kfree(wl->scan_results);
8826 wl->scan_results = NULL;
8829 kfree(wl->scan_req_int);
8830 wl->scan_req_int = NULL;
8831 kfree(wl->ioctl_buf);
8832 wl->ioctl_buf = NULL;
8833 kfree(wl->escan_ioctl_buf);
8834 wl->escan_ioctl_buf = NULL;
8835 kfree(wl->extra_buf);
8836 wl->extra_buf = NULL;
8839 kfree(wl->pmk_list);
8840 wl->pmk_list = NULL;
8841 kfree(wl->sta_info);
8842 wl->sta_info = NULL;
8843 #if defined(STATIC_WL_PRIV_STRUCT)
8844 kfree(wl->conn_info);
8845 wl->conn_info = NULL;
8848 wl_deinit_escan_result_buf(wl);
8849 #endif /* STATIC_WL_PRIV_STRUCT */
8851 cancel_work_sync(&wl->afx_hdl->work);
8857 kfree(wl->ap_info->wpa_ie);
8858 kfree(wl->ap_info->rsn_ie);
8859 kfree(wl->ap_info->wps_ie);
8865 static s32 wl_create_event_handler(struct wl_priv *wl)
8868 WL_DBG(("Enter \n"));
8870 /* Do not use DHD in cfg driver */
8871 wl->event_tsk.thr_pid = -1;
8873 PROC_START(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler");
8874 if (wl->event_tsk.thr_pid < 0)
8879 static void wl_destroy_event_handler(struct wl_priv *wl)
8881 if (wl->event_tsk.thr_pid >= 0)
8882 PROC_STOP(&wl->event_tsk);
8885 static void wl_term_iscan(struct wl_priv *wl)
8887 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
8889 if (wl->iscan_on && iscan->tsk) {
8890 iscan->state = WL_ISCAN_STATE_IDLE;
8891 WL_INFO(("SIGTERM\n"));
8892 send_sig(SIGTERM, iscan->tsk, 1);
8893 WL_DBG(("kthread_stop\n"));
8894 kthread_stop(iscan->tsk);
8899 static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
8901 struct wl_priv *wl = iscan_to_wl(iscan);
8902 struct net_device *ndev = wl_to_prmry_ndev(wl);
8903 unsigned long flags;
8905 WL_DBG(("Enter \n"));
8906 if (!wl_get_drv_status(wl, SCANNING, ndev)) {
8907 wl_clr_drv_status(wl, SCANNING, ndev);
8908 WL_ERR(("Scan complete while device not scanning\n"));
8911 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
8912 wl_clr_drv_status(wl, SCANNING, ndev);
8913 if (likely(wl->scan_request)) {
8914 cfg80211_scan_done(wl->scan_request, aborted);
8915 wl->scan_request = NULL;
8917 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
8918 wl->iscan_kickstart = false;
8921 static s32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan)
8923 if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) {
8924 WL_DBG(("wake up iscan\n"));
8933 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
8934 struct wl_scan_results **bss_list)
8936 struct wl_iscan_results list;
8937 struct wl_scan_results *results;
8938 struct wl_iscan_results *list_buf;
8941 WL_DBG(("Enter \n"));
8942 memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX);
8943 list_buf = (struct wl_iscan_results *)iscan->scan_buf;
8944 results = &list_buf->results;
8945 results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE;
8946 results->version = 0;
8949 memset(&list, 0, sizeof(list));
8950 list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
8951 err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list,
8952 WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
8953 WL_ISCAN_BUF_MAX, NULL);
8954 if (unlikely(err)) {
8955 WL_ERR(("error (%d)\n", err));
8958 results->buflen = dtoh32(results->buflen);
8959 results->version = dtoh32(results->version);
8960 results->count = dtoh32(results->count);
8961 WL_DBG(("results->count = %d\n", results->count));
8962 WL_DBG(("results->buflen = %d\n", results->buflen));
8963 *status = dtoh32(list_buf->status);
8964 *bss_list = results;
8969 static s32 wl_iscan_done(struct wl_priv *wl)
8971 struct wl_iscan_ctrl *iscan = wl->iscan;
8974 iscan->state = WL_ISCAN_STATE_IDLE;
8975 mutex_lock(&wl->usr_sync);
8977 wl_notify_iscan_complete(iscan, false);
8978 mutex_unlock(&wl->usr_sync);
8983 static s32 wl_iscan_pending(struct wl_priv *wl)
8985 struct wl_iscan_ctrl *iscan = wl->iscan;
8988 /* Reschedule the timer */
8989 mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
8990 iscan->timer_on = 1;
8995 static s32 wl_iscan_inprogress(struct wl_priv *wl)
8997 struct wl_iscan_ctrl *iscan = wl->iscan;
9000 mutex_lock(&wl->usr_sync);
9002 wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE);
9003 mutex_unlock(&wl->usr_sync);
9004 /* Reschedule the timer */
9005 mod_timer(&iscan->timer, jiffies + msecs_to_jiffies(iscan->timer_ms));
9006 iscan->timer_on = 1;
9011 static s32 wl_iscan_aborted(struct wl_priv *wl)
9013 struct wl_iscan_ctrl *iscan = wl->iscan;
9016 iscan->state = WL_ISCAN_STATE_IDLE;
9017 mutex_lock(&wl->usr_sync);
9018 wl_notify_iscan_complete(iscan, true);
9019 mutex_unlock(&wl->usr_sync);
9024 static s32 wl_iscan_thread(void *data)
9026 struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
9027 struct wl_priv *wl = iscan_to_wl(iscan);
9031 allow_signal(SIGTERM);
9032 status = WL_SCAN_RESULTS_PARTIAL;
9033 while (likely(!down_interruptible(&iscan->sync))) {
9034 if (kthread_should_stop())
9036 if (iscan->timer_on) {
9037 del_timer_sync(&iscan->timer);
9038 iscan->timer_on = 0;
9040 mutex_lock(&wl->usr_sync);
9041 err = wl_get_iscan_results(iscan, &status, &wl->bss_list);
9042 if (unlikely(err)) {
9043 status = WL_SCAN_RESULTS_ABORTED;
9044 WL_ERR(("Abort iscan\n"));
9046 mutex_unlock(&wl->usr_sync);
9047 iscan->iscan_handler[status] (wl);
9049 if (iscan->timer_on) {
9050 del_timer_sync(&iscan->timer);
9051 iscan->timer_on = 0;
9053 WL_DBG(("was terminated\n"));
9058 static void wl_scan_timeout(unsigned long data)
9061 struct wl_priv *wl = (struct wl_priv *)data;
9062 struct net_device *ndev = wl_to_prmry_ndev(wl);
9064 if (!(wl->scan_request)) {
9065 WL_ERR(("timer expired but no scan request\n"));
9068 bzero(&msg, sizeof(wl_event_msg_t));
9069 WL_ERR(("timer expired\n"));
9071 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
9072 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
9073 msg.reason = 0xFFFFFFFF;
9074 wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL);
9076 /* Need to check it try to access SDIO */
9077 WL_ERR(("SCAN Timeout(ISCAN)\n"));
9078 wl_notify_iscan_complete(wl_to_iscan(wl), true);
9080 // terence 20130729: work around to fix out of memory in firmware
9081 WL_ERR(("Send hang event\n"));
9082 net_os_send_hang_message(ndev);
9085 static void wl_iscan_timer(unsigned long data)
9087 struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data;
9090 iscan->timer_on = 0;
9091 WL_DBG(("timer expired\n"));
9092 wl_wakeup_iscan(iscan);
9096 static s32 wl_invoke_iscan(struct wl_priv *wl)
9098 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
9101 if (wl->iscan_on && !iscan->tsk) {
9102 iscan->state = WL_ISCAN_STATE_IDLE;
9103 sema_init(&iscan->sync, 0);
9104 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
9105 if (IS_ERR(iscan->tsk)) {
9106 WL_ERR(("Could not create iscan thread\n"));
9115 static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan)
9117 memset(iscan->iscan_handler, 0, sizeof(iscan->iscan_handler));
9118 iscan->iscan_handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done;
9119 iscan->iscan_handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress;
9120 iscan->iscan_handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending;
9121 iscan->iscan_handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted;
9122 iscan->iscan_handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted;
9126 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
9127 unsigned long state,
9130 struct net_device *dev = ndev;
9131 struct wireless_dev *wdev = dev->ieee80211_ptr;
9132 struct wl_priv *wl = wlcfg_drv_priv;
9135 WL_DBG(("Enter \n"));
9136 if (!wdev || !wl || dev == wl_to_prmry_ndev(wl))
9141 int max_wait_timeout = 2;
9142 int max_wait_count = 100;
9143 unsigned long limit = jiffies + max_wait_timeout * HZ;
9144 while (work_pending(&wdev->cleanup_work)) {
9145 if (refcnt%5 == 0) {
9146 WL_ERR(("[NETDEV_DOWN] wait for "
9147 "complete of cleanup_work"
9148 " (%d th)\n", refcnt));
9150 if (!time_before(jiffies, limit)) {
9151 WL_ERR(("[NETDEV_DOWN] cleanup_work"
9152 " of CFG80211 is not"
9153 " completed in %d sec\n",
9157 if (refcnt >= max_wait_count) {
9158 WL_ERR(("[NETDEV_DOWN] cleanup_work"
9159 " of CFG80211 is not"
9160 " completed in %d loop\n",
9164 set_current_state(TASK_INTERRUPTIBLE);
9165 schedule_timeout(100);
9166 set_current_state(TASK_RUNNING);
9172 case NETDEV_UNREGISTER:
9173 /* after calling list_del_rcu(&wdev->list) */
9174 wl_dealloc_netinfo(wl, ndev);
9176 case NETDEV_GOING_DOWN:
9177 /* At NETDEV_DOWN state, wdev_cleanup_work work will be called.
9178 * In front of door, the function checks
9179 * whether current scan is working or not.
9180 * If the scanning is still working, wdev_cleanup_work call WARN_ON and
9181 * make the scan done forcibly.
9183 if (wl_get_drv_status(wl, SCANNING, dev)) {
9185 wl_notify_escan_complete(wl, dev, true, true);
9192 static struct notifier_block wl_cfg80211_netdev_notifier = {
9193 .notifier_call = wl_cfg80211_netdev_notifier_call,
9196 static void wl_cfg80211_scan_abort(struct wl_priv *wl)
9198 wl_scan_params_t *params = NULL;
9199 s32 params_size = 0;
9201 struct net_device *dev = wl_to_prmry_ndev(wl);
9203 /* Our scan params only need space for 1 channel and 0 ssids */
9204 params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size);
9205 if (params == NULL) {
9206 WL_ERR(("scan params allocation failed \n"));
9209 /* Do a scan abort to stop the driver's scan engine */
9210 err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
9212 WL_ERR(("scan abort failed \n"));
9219 static s32 wl_notify_escan_complete(struct wl_priv *wl,
9220 struct net_device *ndev,
9221 bool aborted, bool fw_abort)
9224 unsigned long flags;
9225 struct net_device *dev;
9227 WL_DBG(("Enter \n"));
9229 WL_ERR(("ndev is null\n"));
9234 if (wl->escan_info.ndev != ndev) {
9235 WL_ERR(("ndev is different %p %p\n", wl->escan_info.ndev, ndev));
9240 if (wl->scan_request) {
9241 dev = wl_to_prmry_ndev(wl);
9242 #if defined(WL_ENABLE_P2P_IF)
9243 if (wl->scan_request->dev != wl->p2p_net)
9244 dev = wl->scan_request->dev;
9245 #endif /* WL_ENABLE_P2P_IF */
9248 WL_DBG(("wl->scan_request is NULL may be internal scan."
9249 "doing scan_abort for ndev %p primary %p",
9250 ndev, wl_to_prmry_ndev(wl)));
9253 if (fw_abort && !in_atomic()) {
9254 wl_cfg80211_scan_abort(wl);
9257 if (timer_pending(&wl->scan_timeout))
9258 del_timer_sync(&wl->scan_timeout);
9259 #if defined(ESCAN_RESULT_PATCH)
9260 if (likely(wl->scan_request)) {
9261 wl->bss_list = wl_escan_get_buf(wl, aborted);
9264 #endif /* ESCAN_RESULT_PATCH */
9265 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
9266 #ifdef WL_SCHED_SCAN
9267 if (wl->sched_scan_req && !wl->scan_request) {
9268 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
9270 cfg80211_sched_scan_results(wl->sched_scan_req->wiphy);
9271 wl->sched_scan_running = FALSE;
9272 wl->sched_scan_req = NULL;
9274 #endif /* WL_SCHED_SCAN */
9275 if (likely(wl->scan_request)) {
9276 cfg80211_scan_done(wl->scan_request, aborted);
9277 wl->scan_request = NULL;
9280 wl_clr_p2p_status(wl, SCANNING);
9281 wl_clr_drv_status(wl, SCANNING, dev);
9282 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
9284 if (wl_get_p2p_status(wl, DISC_IN_PROGRESS) && !in_atomic()) {
9285 wl_cfg80211_resume_sdo(ndev, wl);
9291 static s32 wl_escan_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
9292 const wl_event_msg_t *e, void *data)
9295 s32 status = ntoh32(e->status);
9297 wl_escan_result_t *escan_result;
9298 wl_bss_info_t *bss = NULL;
9299 wl_scan_results_t *list;
9300 wifi_p2p_ie_t * p2p_ie;
9301 struct net_device *ndev = NULL;
9304 u8 *p2p_dev_addr = NULL;
9305 struct wiphy *wiphy = wl_to_wiphy(wl);
9307 struct ieee80211_supported_band *band;
9309 WL_DBG((" enter event type : %d, status : %d \n",
9310 ntoh32(e->event_type), ntoh32(e->status)));
9312 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
9314 mutex_lock(&wl->usr_sync);
9315 /* P2P SCAN is coming from primary interface */
9316 if (wl_get_p2p_status(wl, SCANNING)) {
9317 if (wl_get_drv_status_all(wl, SENDING_ACT_FRM))
9318 ndev = wl->afx_hdl->dev;
9320 ndev = wl->escan_info.ndev;
9323 if (!ndev || !wl->escan_on ||
9324 (!wl_get_drv_status(wl, SCANNING, ndev) &&
9325 !wl->sched_scan_running)) {
9326 WL_ERR(("escan is not ready ndev %p wl->escan_on %d"
9327 " drv_status 0x%x e_type %d e_states %d\n",
9328 ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev),
9329 ntoh32(e->event_type), ntoh32(e->status)));
9332 escan_result = (wl_escan_result_t *)data;
9334 if (status == WLC_E_STATUS_PARTIAL) {
9335 WL_INFO(("WLC_E_STATUS_PARTIAL \n"));
9336 if (!escan_result) {
9337 WL_ERR(("Invalid escan result (NULL pointer)\n"));
9340 if (dtoh16(escan_result->bss_count) != 1) {
9341 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
9344 bi = escan_result->bss_info;
9346 WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
9349 bi_length = dtoh32(bi->length);
9350 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
9351 WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
9355 /* +++++ terence 20130524: skip invalid bss */
9357 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
9358 if (channel <= CH_MAX_2G_CHANNEL)
9359 band = wiphy->bands[IEEE80211_BAND_2GHZ];
9361 band = wiphy->bands[IEEE80211_BAND_5GHZ];
9363 WL_DBG(("No valid band\n"));
9366 if (!dhd_conf_match_channel((dhd_pub_t *)wl->pub, channel))
9368 /* ----- terence 20130524: skip invalid bss */
9370 if (wl_escan_check_sync_id(status, escan_result->sync_id,
9371 wl->escan_info.cur_sync_id) < 0)
9374 if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
9375 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
9376 WL_DBG(("Ignoring IBSS result\n"));
9381 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9382 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
9383 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
9384 wl->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
9385 s32 channel = wf_chspec_ctlchan(
9386 wl_chspec_driver_to_host(bi->chanspec));
9388 if ((channel > MAXCHANNEL) || (channel <= 0))
9389 channel = WL_INVALID;
9391 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
9393 MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet),
9396 wl_clr_p2p_status(wl, SCANNING);
9397 wl->afx_hdl->peer_chan = channel;
9398 complete(&wl->act_frm_scan);
9403 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
9404 list = wl_escan_get_buf(wl, FALSE);
9405 if (scan_req_match(wl)) {
9406 #ifdef WL_HOST_BAND_MGMT
9408 s32 channel_band = 0;
9409 #endif /* WL_HOST_BAND_MGMT */
9410 /* p2p scan && allow only probe response */
9411 if ((wl->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
9412 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
9414 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
9415 bi->ie_length)) == NULL) {
9416 WL_INFO(("Couldn't find P2PIE in probe"
9417 " response/beacon\n"));
9420 #ifdef WL_HOST_BAND_MGMT
9421 channel = CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
9422 channel_band = (channel > CH_MAX_2G_CHANNEL) ?
9423 WLC_BAND_5G : WLC_BAND_2G;
9426 if ((wl->curr_band == WLC_BAND_5G) &&
9427 (channel_band == WLC_BAND_2G)) {
9428 /* Avoid sending the GO results in band conflict */
9429 if (wl_cfgp2p_retreive_p2pattrib(p2p_ie,
9430 P2P_SEID_GROUP_ID) != NULL)
9433 #endif /* WL_HOST_BAND_MGMT */
9435 WL_SCAN(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID,
9436 MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length));
9437 for (i = 0; i < list->count; i++) {
9438 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
9441 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
9442 (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
9443 == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
9444 bi->SSID_len == bss->SSID_len &&
9445 !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
9447 /* do not allow beacon data to update
9448 *the data recd from a probe response
9450 if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
9451 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
9454 WL_SCAN(("%s("MACDBG"), i=%d prev: RSSI %d"
9455 " flags 0x%x, new: RSSI %d flags 0x%x\n",
9456 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
9457 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
9459 if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
9460 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
9461 /* preserve max RSSI if the measurements are
9462 * both on-channel or both off-channel
9464 WL_SCAN(("%s("MACDBG"), same onchan"
9465 ", RSSI: prev %d new %d\n",
9466 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9467 bss->RSSI, bi->RSSI));
9468 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
9469 } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
9470 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
9471 /* preserve the on-channel rssi measurement
9472 * if the new measurement is off channel
9474 WL_SCAN(("%s("MACDBG"), prev onchan"
9475 ", RSSI: prev %d new %d\n",
9476 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9477 bss->RSSI, bi->RSSI));
9478 bi->RSSI = bss->RSSI;
9479 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
9481 if (dtoh32(bss->length) != bi_length) {
9482 u32 prev_len = dtoh32(bss->length);
9484 WL_SCAN(("bss info replacement"
9485 " is occured(bcast:%d->probresp%d)\n",
9486 bss->ie_length, bi->ie_length));
9487 WL_SCAN(("%s("MACDBG"), replacement!(%d -> %d)\n",
9488 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
9489 prev_len, bi_length));
9491 if (list->buflen - prev_len + bi_length
9493 WL_ERR(("Buffer is too small: keep the"
9494 " previous result of this AP\n"));
9495 /* Only update RSSI */
9496 bss->RSSI = bi->RSSI;
9497 bss->flags |= (bi->flags
9498 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
9502 if (i < list->count - 1) {
9503 /* memory copy required by this case only */
9504 memmove((u8 *)bss + bi_length,
9505 (u8 *)bss + prev_len,
9506 list->buflen - cur_len - prev_len);
9508 list->buflen -= prev_len;
9509 list->buflen += bi_length;
9511 list->version = dtoh32(bi->version);
9512 memcpy((u8 *)bss, (u8 *)bi, bi_length);
9515 cur_len += dtoh32(bss->length);
9517 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
9518 WL_ERR(("Buffer is too small: ignoring\n"));
9521 if (strlen(bi->SSID) == 0) { // terence: fix for hidden SSID
9522 WL_SCAN(("Skip hidden SSID %pM\n", &bi->BSSID));
9526 memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
9527 list->version = dtoh32(bi->version);
9528 list->buflen += bi_length;
9534 else if (status == WLC_E_STATUS_SUCCESS) {
9535 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9536 wl_escan_print_sync_id(status, wl->escan_info.cur_sync_id,
9537 escan_result->sync_id);
9539 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9540 WL_INFO(("ACTION FRAME SCAN DONE\n"));
9541 wl_clr_p2p_status(wl, SCANNING);
9542 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9543 if (wl->afx_hdl->peer_chan == WL_INVALID)
9544 complete(&wl->act_frm_scan);
9545 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9546 WL_INFO(("ESCAN COMPLETED\n"));
9547 wl->bss_list = wl_escan_get_buf(wl, FALSE);
9548 if (!scan_req_match(wl)) {
9549 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
9550 wl->bss_list->count));
9553 wl_notify_escan_complete(wl, ndev, false, false);
9555 wl_escan_increment_sync_id(wl, SCAN_BUF_NEXT);
9557 else if (status == WLC_E_STATUS_ABORT) {
9558 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9559 wl_escan_print_sync_id(status, escan_result->sync_id,
9560 wl->escan_info.cur_sync_id);
9561 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9562 WL_INFO(("ACTION FRAME SCAN DONE\n"));
9563 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9564 wl_clr_p2p_status(wl, SCANNING);
9565 if (wl->afx_hdl->peer_chan == WL_INVALID)
9566 complete(&wl->act_frm_scan);
9567 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9568 WL_INFO(("ESCAN ABORTED\n"));
9569 wl->bss_list = wl_escan_get_buf(wl, TRUE);
9570 if (!scan_req_match(wl)) {
9571 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
9572 wl->bss_list->count));
9575 wl_notify_escan_complete(wl, ndev, true, false);
9577 wl_escan_increment_sync_id(wl, SCAN_BUF_CNT);
9578 } else if (status == WLC_E_STATUS_NEWSCAN) {
9579 WL_ERR(("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", wl->scan_request));
9580 WL_ERR(("sync_id[%d], bss_count[%d]\n", escan_result->sync_id,
9581 escan_result->bss_count));
9582 } else if (status == WLC_E_STATUS_TIMEOUT) {
9583 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", wl->scan_request));
9584 WL_ERR(("escan_on[%d], reason[0x%x]\n", wl->escan_on, e->reason));
9585 if (e->reason == 0xFFFFFFFF) {
9586 wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true);
9589 WL_ERR(("unexpected Escan Event %d : abort\n", status));
9590 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9591 wl_escan_print_sync_id(status, escan_result->sync_id,
9592 wl->escan_info.cur_sync_id);
9593 if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) {
9594 WL_INFO(("ACTION FRAME SCAN DONE\n"));
9595 wl_clr_p2p_status(wl, SCANNING);
9596 wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev);
9597 if (wl->afx_hdl->peer_chan == WL_INVALID)
9598 complete(&wl->act_frm_scan);
9599 } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) {
9600 wl->bss_list = wl_escan_get_buf(wl, TRUE);
9601 if (!scan_req_match(wl)) {
9602 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
9603 "scanned AP count=%d\n",
9604 wl->bss_list->count));
9607 wl_notify_escan_complete(wl, ndev, true, false);
9609 wl_escan_increment_sync_id(wl, 2);
9612 mutex_unlock(&wl->usr_sync);
9616 static void wl_cfg80211_concurrent_roam(struct wl_priv *wl, int enable)
9618 u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED);
9619 struct net_info *iter, *next;
9622 if (!wl->roamoff_on_concurrent)
9624 if (enable && connected_cnt > 1) {
9625 for_each_ndev(wl, iter, next) {
9626 /* Save the current roam setting */
9627 if ((err = wldev_iovar_getint(iter->ndev, "roam_off",
9628 (s32 *)&iter->roam_off)) != BCME_OK) {
9629 WL_ERR(("%s:Failed to get current roam setting err %d\n",
9630 iter->ndev->name, err));
9633 if ((err = wldev_iovar_setint(iter->ndev, "roam_off", 1)) != BCME_OK) {
9634 WL_ERR((" %s:failed to set roam_off : %d\n",
9635 iter->ndev->name, err));
9640 for_each_ndev(wl, iter, next) {
9641 if (iter->roam_off != WL_INVALID) {
9642 if ((err = wldev_iovar_setint(iter->ndev, "roam_off",
9643 iter->roam_off)) == BCME_OK)
9644 iter->roam_off = WL_INVALID;
9646 WL_ERR((" %s:failed to set roam_off : %d\n",
9647 iter->ndev->name, err));
9655 static void wl_cfg80211_determine_vsdb_mode(struct wl_priv *wl)
9657 struct net_info *iter, *next;
9660 u32 pre_ctl_chan = 0;
9661 u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED);
9662 wl->vsdb_mode = false;
9664 if (connected_cnt <= 1) {
9667 for_each_ndev(wl, iter, next) {
9670 if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) {
9671 if (wldev_iovar_getint(iter->ndev, "chanspec",
9672 (s32 *)&chanspec) == BCME_OK) {
9673 chanspec = wl_chspec_driver_to_host(chanspec);
9674 ctl_chan = wf_chspec_ctlchan(chanspec);
9675 wl_update_prof(wl, iter->ndev, NULL,
9676 &ctl_chan, WL_PROF_CHAN);
9678 if (!wl->vsdb_mode) {
9679 if (!pre_ctl_chan && ctl_chan)
9680 pre_ctl_chan = ctl_chan;
9681 else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
9682 wl->vsdb_mode = true;
9687 printk("%s concurrency is enabled\n", wl->vsdb_mode ? "Multi Channel" : "Same Channel");
9691 static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info,
9692 enum wl_status state, bool set)
9698 struct net_info *iter, *next;
9699 struct net_device *primary_dev = wl_to_prmry_ndev(wl);
9700 WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
9701 state, set, _net_info->pm_restore, _net_info->ndev->name));
9703 if (state != WL_STATUS_CONNECTED)
9705 mode = wl_get_mode_by_netdev(wl, _net_info->ndev);
9707 wl_cfg80211_concurrent_roam(wl, 1);
9709 if (mode == WL_MODE_AP) {
9711 if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
9712 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
9714 wl_cfg80211_determine_vsdb_mode(wl);
9715 if (wl->vsdb_mode || _net_info->pm_block) {
9716 if (wl->pm_enable_work_on) {
9717 cancel_delayed_work_sync(&wl->pm_enable_work);
9718 wl->pm_enable_work_on = false;
9720 /* save PM_FAST in _net_info to restore this
9721 * if _net_info->pm_block is false
9723 if (!_net_info->pm_block && (mode == WL_MODE_BSS)) {
9724 _net_info->pm = PM_FAST;
9725 _net_info->pm_restore = true;
9728 for_each_ndev(wl, iter, next) {
9729 if (iter->pm_restore)
9731 /* Save the current power mode */
9732 err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm,
9733 sizeof(iter->pm), false);
9734 WL_DBG(("%s:power save %s\n", iter->ndev->name,
9735 iter->pm ? "enabled" : "disabled"));
9736 if (!err && iter->pm) {
9737 iter->pm_restore = true;
9741 for_each_ndev(wl, iter, next) {
9742 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9743 sizeof(pm), true)) != 0) {
9745 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9747 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9749 iter->ndev->ieee80211_ptr->ps = false;
9752 /* add PM Enable timer to go to power save mode
9753 * if supplicant control pm mode, it will be cleared or
9754 * updated by wl_cfg80211_set_power_mgmt() if not - for static IP & HW4 P2P,
9755 * PM will be configured when timer expired
9759 * before calling pm_enable_timer, we need to set PM -1 for all ndev
9763 for_each_ndev(wl, iter, next) {
9764 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm,
9765 sizeof(pm), true)) != 0) {
9767 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9769 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
9772 wl->pm_enable_work_on = true;
9773 schedule_delayed_work(&wl->pm_enable_work,
9774 msecs_to_jiffies(WL_PM_ENABLE_TIMEOUT));
9779 /* clear chan information when the net device is disconnected */
9780 wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
9781 wl_cfg80211_determine_vsdb_mode(wl);
9782 for_each_ndev(wl, iter, next) {
9783 if (iter->pm_restore && iter->pm) {
9784 WL_DBG(("%s:restoring power save %s\n",
9785 iter->ndev->name, (iter->pm ? "enabled" : "disabled")));
9786 err = wldev_ioctl(iter->ndev,
9787 WLC_SET_PM, &iter->pm, sizeof(iter->pm), true);
9788 if (unlikely(err)) {
9790 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
9792 WL_ERR(("%s:error(%d)\n", iter->ndev->name, err));
9795 iter->pm_restore = 0;
9796 iter->ndev->ieee80211_ptr->ps = true;
9799 wl_cfg80211_concurrent_roam(wl, 0);
9804 static s32 wl_init_scan(struct wl_priv *wl)
9806 struct wl_iscan_ctrl *iscan = wl_to_iscan(wl);
9810 iscan->dev = wl_to_prmry_ndev(wl);
9811 iscan->state = WL_ISCAN_STATE_IDLE;
9812 wl_init_iscan_handler(iscan);
9813 iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS;
9814 init_timer(&iscan->timer);
9815 iscan->timer.data = (unsigned long) iscan;
9816 iscan->timer.function = wl_iscan_timer;
9817 sema_init(&iscan->sync, 0);
9818 iscan->tsk = kthread_run(wl_iscan_thread, iscan, "wl_iscan");
9819 if (IS_ERR(iscan->tsk)) {
9820 WL_ERR(("Could not create iscan thread\n"));
9825 } else if (wl->escan_on) {
9826 wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
9827 wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
9828 wl_escan_init_sync_id(wl);
9830 /* Init scan_timeout timer */
9831 init_timer(&wl->scan_timeout);
9832 wl->scan_timeout.data = (unsigned long) wl;
9833 wl->scan_timeout.function = wl_scan_timeout;
9838 static s32 wl_init_priv(struct wl_priv *wl)
9840 struct wiphy *wiphy = wl_to_wiphy(wl);
9841 struct net_device *ndev = wl_to_prmry_ndev(wl);
9844 wl->scan_request = NULL;
9845 wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
9846 wl->iscan_on = false;
9847 wl->escan_on = true;
9848 wl->roam_on = false;
9849 wl->iscan_kickstart = false;
9850 wl->active_scan = true;
9851 wl->rf_blocked = false;
9852 wl->vsdb_mode = false;
9853 wl->wlfc_on = false;
9854 wl->roamoff_on_concurrent = true;
9855 /* register interested state */
9856 set_bit(WL_STATUS_CONNECTED, &wl->interrested_state);
9857 spin_lock_init(&wl->cfgdrv_lock);
9858 mutex_init(&wl->ioctl_buf_sync);
9859 init_waitqueue_head(&wl->netif_change_event);
9860 init_completion(&wl->send_af_done);
9861 init_completion(&wl->iface_disable);
9863 err = wl_init_priv_mem(wl);
9866 if (wl_create_event_handler(wl))
9868 wl_init_event_handler(wl);
9869 mutex_init(&wl->usr_sync);
9870 mutex_init(&wl->event_sync);
9871 err = wl_init_scan(wl);
9874 wl_init_conf(wl->conf);
9875 wl_init_prof(wl, ndev);
9877 DNGL_FUNC(dhd_cfg80211_init, (wl));
9882 static void wl_deinit_priv(struct wl_priv *wl)
9884 DNGL_FUNC(dhd_cfg80211_deinit, (wl));
9885 wl_destroy_event_handler(wl);
9888 del_timer_sync(&wl->scan_timeout);
9890 wl_deinit_priv_mem(wl);
9891 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
9894 #if defined(WL_ENABLE_P2P_IF)
9895 static s32 wl_cfg80211_attach_p2p(void)
9897 struct wl_priv *wl = wlcfg_drv_priv;
9899 WL_TRACE(("Enter \n"));
9901 if (wl_cfgp2p_register_ndev(wl) < 0) {
9902 WL_ERR(("P2P attach failed. \n"));
9909 static s32 wl_cfg80211_detach_p2p(void)
9911 struct wl_priv *wl = wlcfg_drv_priv;
9912 struct wireless_dev *wdev;
9914 WL_DBG(("Enter \n"));
9916 WL_ERR(("Invalid Ptr\n"));
9919 wdev = wl->p2p_wdev;
9922 WL_ERR(("Invalid Ptr\n"));
9926 wl_cfgp2p_unregister_ndev(wl);
9928 wl->p2p_wdev = NULL;
9930 WL_DBG(("Freeing 0x%08x \n", (unsigned int)wdev));
9935 #endif /* WL_ENABLE_P2P_IF */
9937 s32 wl_cfg80211_attach_post(struct net_device *ndev)
9939 struct wl_priv * wl = NULL;
9942 if (unlikely(!ndev)) {
9943 WL_ERR(("ndev is invaild\n"));
9946 wl = wlcfg_drv_priv;
9947 if (unlikely(!wl)) {
9948 WL_ERR(("wl is invaild\n"));
9951 if (!wl_get_drv_status(wl, READY, ndev)) {
9952 if (wl->wdev && wl_cfgp2p_supported(wl, ndev)) {
9953 #if !defined(WL_ENABLE_P2P_IF)
9954 wl->wdev->wiphy->interface_modes |=
9955 (BIT(NL80211_IFTYPE_P2P_CLIENT)|
9956 BIT(NL80211_IFTYPE_P2P_GO));
9957 #endif /* !WL_ENABLE_P2P_IF */
9958 if ((err = wl_cfgp2p_init_priv(wl)) != 0)
9961 #if defined(WL_ENABLE_P2P_IF)
9963 /* Update MAC addr for p2p0 interface here. */
9964 memcpy(wl->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
9965 wl->p2p_net->dev_addr[0] |= 0x02;
9966 printk("%s: %s p2p_dev_addr="MACDBG "\n", __FUNCTION__,
9968 MAC2STRDBG(wl->p2p_net->dev_addr));
9970 WL_ERR(("p2p_net not yet populated."
9971 " Couldn't update the MAC Address for p2p0 \n"));
9974 #endif /* WL_ENABLE_P2P_IF */
9976 wl->p2p_supported = true;
9979 wl_set_drv_status(wl, READY, ndev);
9984 s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
9986 struct wireless_dev *wdev;
9993 WL_ERR(("ndev is invaild\n"));
9996 WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
9997 dev = wl_cfg80211_get_parent_dev();
9999 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
10000 if (unlikely(!wdev)) {
10001 WL_ERR(("Could not allocate wireless device\n"));
10004 err = wl_setup_wiphy(wdev, dev, data);
10005 if (unlikely(err)) {
10009 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
10010 wl = (struct wl_priv *)wiphy_priv(wdev->wiphy);
10013 INIT_LIST_HEAD(&wl->net_list);
10014 ndev->ieee80211_ptr = wdev;
10015 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
10016 wdev->netdev = ndev;
10017 wl->state_notifier = wl_notifier_change_state;
10018 err = wl_alloc_netinfo(wl, ndev, wdev, WL_MODE_BSS, PM_ENABLE);
10020 WL_ERR(("Failed to alloc net_info (%d)\n", err));
10021 goto cfg80211_attach_out;
10023 err = wl_init_priv(wl);
10025 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
10026 goto cfg80211_attach_out;
10029 err = wl_setup_rfkill(wl, TRUE);
10031 WL_ERR(("Failed to setup rfkill %d\n", err));
10032 goto cfg80211_attach_out;
10034 #ifdef DEBUGFS_CFG80211
10035 err = wl_setup_debugfs(wl);
10037 WL_ERR(("Failed to setup debugfs %d\n", err));
10038 goto cfg80211_attach_out;
10041 err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
10043 WL_ERR(("Failed to register notifierl %d\n", err));
10044 goto cfg80211_attach_out;
10046 #if defined(COEX_DHCP)
10047 err = wl_cfg80211_btcoex_init(wl);
10049 goto cfg80211_attach_out;
10051 #if defined(BSSCACHE)
10052 if (wl_init_bss_cache_ctrl(&g_bss_cache_ctrl))
10053 goto cfg80211_attach_out;
10056 wlcfg_drv_priv = wl;
10058 #if defined(WL_ENABLE_P2P_IF)
10059 err = wl_cfg80211_attach_p2p();
10061 goto cfg80211_attach_out;
10062 #endif /* WL_ENABLE_P2P_IF */
10066 cfg80211_attach_out:
10067 wl_setup_rfkill(wl, FALSE);
10072 void wl_cfg80211_detach(void *para)
10074 struct wl_priv *wl;
10077 wl = wlcfg_drv_priv;
10079 WL_TRACE(("In\n"));
10081 #if defined(COEX_DHCP)
10082 wl_cfg80211_btcoex_deinit(wl);
10085 wl_setup_rfkill(wl, FALSE);
10086 #ifdef DEBUGFS_CFG80211
10087 wl_free_debugfs(wl);
10089 if (wl->p2p_supported) {
10090 if (timer_pending(&wl->p2p->listen_timer))
10091 del_timer_sync(&wl->p2p->listen_timer);
10092 wl_cfgp2p_deinit_priv(wl);
10095 #if defined(WL_CFG80211_P2P_DEV_IF)
10096 wl_cfgp2p_del_p2p_disc_if(wl->p2p_wdev);
10097 #elif defined(WL_ENABLE_P2P_IF)
10098 wl_cfg80211_detach_p2p();
10099 #endif /* WL_CFG80211_P2P_DEV_IF */
10101 wl_cfg80211_ibss_vsie_free(wl);
10102 wl_deinit_priv(wl);
10103 wlcfg_drv_priv = NULL;
10104 wl_cfg80211_clear_parent_dev();
10106 #if defined(RSSIAVG)
10107 wl_free_rssi_cache(&g_rssi_cache_ctrl);
10108 wl_free_rssi_cache(&g_rssi2_cache_ctrl);
10110 #if defined(BSSCACHE)
10111 wl_release_bss_cache_ctrl(&g_bss_cache_ctrl);
10113 /* PLEASE do NOT call any function after wl_free_wdev, the driver's private structure "wl",
10114 * which is the private part of wiphy, has been freed in wl_free_wdev !!!!!!!!!!!
10118 static void wl_wakeup_event(struct wl_priv *wl)
10120 if (wl->event_tsk.thr_pid >= 0) {
10121 DHD_OS_WAKE_LOCK(wl->pub);
10122 up(&wl->event_tsk.sema);
10126 #if (defined(WL_CFG80211_P2P_DEV_IF) || defined(WL_ENABLE_P2P_IF))
10127 static int wl_is_p2p_event(struct wl_event_q *e)
10129 switch (e->etype) {
10130 /* We have to seperate out the P2P events received
10131 * on primary interface so that it can be send up
10132 * via p2p0 interface.
10134 case WLC_E_P2P_PROBREQ_MSG:
10135 case WLC_E_P2P_DISC_LISTEN_COMPLETE:
10136 case WLC_E_ACTION_FRAME_RX:
10137 case WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE:
10138 case WLC_E_ACTION_FRAME_COMPLETE:
10140 if (e->emsg.ifidx != 0) {
10141 WL_TRACE(("P2P event(%d) on virtual interface(ifidx:%d)\n",
10142 e->etype, e->emsg.ifidx));
10143 /* We are only bothered about the P2P events received
10144 * on primary interface. For rest of them return false
10145 * so that it is sent over the interface corresponding
10150 WL_TRACE(("P2P event(%d) on interface(ifidx:%d)\n",
10151 e->etype, e->emsg.ifidx));
10157 WL_TRACE(("NON-P2P event(%d) on interface(ifidx:%d)\n",
10158 e->etype, e->emsg.ifidx));
10162 #endif /* BCMDONGLEHOST && (WL_CFG80211_P2P_DEV_IF || WL_ENABLE_P2P_IF) */
10164 static s32 wl_event_handler(void *data)
10166 struct wl_priv *wl = NULL;
10167 struct wl_event_q *e;
10168 tsk_ctl_t *tsk = (tsk_ctl_t *)data;
10169 bcm_struct_cfgdev *cfgdev = NULL;
10171 wl = (struct wl_priv *)tsk->parent;
10173 printk("tsk Enter, tsk = 0x%08x\n", (unsigned int)tsk);
10175 while (down_interruptible (&tsk->sema) == 0) {
10176 SMP_RD_BARRIER_DEPENDS();
10177 if (tsk->terminated)
10179 while ((e = wl_deq_event(wl))) {
10180 WL_DBG(("event type (%d), if idx: %d\n", e->etype, e->emsg.ifidx));
10181 /* All P2P device address related events comes on primary interface since
10182 * there is no corresponding bsscfg for P2P interface. Map it to p2p0
10185 #if defined(WL_CFG80211_P2P_DEV_IF)
10186 if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_wdev)) {
10187 cfgdev = wl_to_p2p_wdev(wl);
10189 cfgdev = ndev_to_wdev(dhd_idx2net((struct dhd_pub *)(wl->pub),
10192 #elif defined(WL_ENABLE_P2P_IF)
10193 if ((wl_is_p2p_event(e) == TRUE) && (wl->p2p_net)) {
10194 cfgdev = wl->p2p_net;
10196 cfgdev = dhd_idx2net((struct dhd_pub *)(wl->pub),
10199 #endif /* WL_CFG80211_P2P_DEV_IF */
10202 #if defined(WL_CFG80211_P2P_DEV_IF)
10203 cfgdev = wl_to_prmry_wdev(wl);
10204 #elif defined(WL_ENABLE_P2P_IF)
10205 cfgdev = wl_to_prmry_ndev(wl);
10206 #endif /* WL_CFG80211_P2P_DEV_IF */
10208 if (e->etype < WLC_E_LAST && wl->evt_handler[e->etype]) {
10209 wl->evt_handler[e->etype] (wl, cfgdev, &e->emsg, e->edata);
10211 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
10215 DHD_OS_WAKE_UNLOCK(wl->pub);
10217 WL_ERR(("was terminated\n"));
10218 complete_and_exit(&tsk->completed, 0);
10223 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
10225 u32 event_type = ntoh32(e->event_type);
10226 struct wl_priv *wl = wlcfg_drv_priv;
10228 #if (WL_DBG_LEVEL > 0)
10229 s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
10230 wl_dbg_estr[event_type] : (s8 *) "Unknown";
10231 WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
10232 #endif /* (WL_DBG_LEVEL > 0) */
10234 if (event_type == WLC_E_PFN_NET_FOUND) {
10235 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
10237 else if (event_type == WLC_E_PFN_NET_LOST) {
10238 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
10241 if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
10242 wl_wakeup_event(wl);
10245 static void wl_init_eq(struct wl_priv *wl)
10247 wl_init_eq_lock(wl);
10248 INIT_LIST_HEAD(&wl->eq_list);
10251 static void wl_flush_eq(struct wl_priv *wl)
10253 struct wl_event_q *e;
10254 unsigned long flags;
10256 flags = wl_lock_eq(wl);
10257 while (!list_empty(&wl->eq_list)) {
10258 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
10259 list_del(&e->eq_list);
10262 wl_unlock_eq(wl, flags);
10266 * retrieve first queued event from head
10269 static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
10271 struct wl_event_q *e = NULL;
10272 unsigned long flags;
10274 flags = wl_lock_eq(wl);
10275 if (likely(!list_empty(&wl->eq_list))) {
10276 e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list);
10277 list_del(&e->eq_list);
10279 wl_unlock_eq(wl, flags);
10285 * push event to tail of the queue
10289 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_event_msg_t *msg,
10292 struct wl_event_q *e;
10296 unsigned long flags;
10301 data_len = ntoh32(msg->datalen);
10302 evtq_size = sizeof(struct wl_event_q) + data_len;
10303 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
10304 e = kzalloc(evtq_size, aflags);
10305 if (unlikely(!e)) {
10306 WL_ERR(("event alloc failed\n"));
10310 memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
10312 memcpy(e->edata, data, data_len);
10313 flags = wl_lock_eq(wl);
10314 list_add_tail(&e->eq_list, &wl->eq_list);
10315 wl_unlock_eq(wl, flags);
10320 static void wl_put_event(struct wl_event_q *e)
10325 static s32 wl_config_ifmode(struct wl_priv *wl, struct net_device *ndev, s32 iftype)
10331 case NL80211_IFTYPE_MONITOR:
10332 case NL80211_IFTYPE_WDS:
10333 WL_ERR(("type (%d) : currently we do not support this mode\n",
10337 case NL80211_IFTYPE_ADHOC:
10338 mode = WL_MODE_IBSS;
10340 case NL80211_IFTYPE_STATION:
10341 case NL80211_IFTYPE_P2P_CLIENT:
10342 mode = WL_MODE_BSS;
10345 case NL80211_IFTYPE_AP:
10346 case NL80211_IFTYPE_P2P_GO:
10352 WL_ERR(("invalid type (%d)\n", iftype));
10355 infra = htod32(infra);
10356 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
10357 if (unlikely(err)) {
10358 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
10362 wl_set_mode_by_netdev(wl, ndev, mode);
10367 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
10369 if (!ev || (event > WLC_E_LAST))
10372 if (ev->num < MAX_EVENT_BUF_NUM) {
10373 ev->event[ev->num].type = event;
10374 ev->event[ev->num].set = set;
10377 WL_ERR(("evenbuffer doesn't support > %u events. Update"
10378 " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
10383 s32 wl_cfg80211_apply_eventbuffer(
10384 struct net_device *ndev,
10385 struct wl_priv *wl,
10386 wl_eventmsg_buf_t *ev)
10388 char eventmask[WL_EVENTING_MASK_LEN];
10390 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
10392 if (!ev || (!ev->num))
10395 mutex_lock(&wl->event_sync);
10397 /* Read event_msgs mask */
10398 bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
10400 ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
10401 if (unlikely(ret)) {
10402 WL_ERR(("Get event_msgs error (%d)\n", ret));
10405 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
10407 /* apply the set bits */
10408 for (i = 0; i < ev->num; i++) {
10409 if (ev->event[i].set)
10410 setbit(eventmask, ev->event[i].type);
10412 clrbit(eventmask, ev->event[i].type);
10415 /* Write updated Event mask */
10416 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
10418 ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
10419 if (unlikely(ret)) {
10420 WL_ERR(("Set event_msgs error (%d)\n", ret));
10424 mutex_unlock(&wl->event_sync);
10428 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
10430 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
10431 s8 eventmask[WL_EVENTING_MASK_LEN];
10433 struct wl_priv *wl = wlcfg_drv_priv;
10438 mutex_lock(&wl->event_sync);
10440 /* Setup event_msgs */
10441 bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
10443 err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
10444 if (unlikely(err)) {
10445 WL_ERR(("Get event_msgs error (%d)\n", err));
10448 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
10450 setbit(eventmask, event);
10452 clrbit(eventmask, event);
10454 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
10456 err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
10457 if (unlikely(err)) {
10458 WL_ERR(("Set event_msgs error (%d)\n", err));
10463 mutex_unlock(&wl->event_sync);
10467 static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap)
10469 struct net_device *dev = wl_to_prmry_ndev(wl);
10470 struct ieee80211_channel *band_chan_arr = NULL;
10471 wl_uint32_list_t *list;
10472 u32 i, j, index, n_2g, n_5g, band, channel, array_size;
10479 bool dfs_radar_disabled = FALSE;
10481 #define LOCAL_BUF_LEN 1024
10482 pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
10484 if (pbuf == NULL) {
10485 WL_ERR(("failed to allocate local buf\n"));
10488 list = (wl_uint32_list_t *)(void *)pbuf;
10489 list->count = htod32(WL_NUMCHANSPECS);
10492 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
10493 0, pbuf, LOCAL_BUF_LEN, 0, &wl->ioctl_buf_sync);
10495 WL_ERR(("get chanspecs failed with %d\n", err));
10499 #undef LOCAL_BUF_LEN
10501 list = (wl_uint32_list_t *)(void *)pbuf;
10502 band = array_size = n_2g = n_5g = 0;
10503 for (i = 0; i < dtoh32(list->count); i++) {
10506 ht40_allowed = false;
10507 c = (chanspec_t)dtoh32(list->element[i]);
10508 c = wl_chspec_driver_to_host(c);
10509 channel = CHSPEC_CHANNEL(c);
10510 if (!dhd_conf_match_channel((dhd_pub_t *)wl->pub, channel))
10512 if (CHSPEC_IS40(c)) {
10513 if (CHSPEC_SB_UPPER(c))
10514 channel += CH_10MHZ_APART;
10516 channel -= CH_10MHZ_APART;
10517 } else if (CHSPEC_IS80(c)) {
10518 WL_DBG(("HT80 center channel : %d\n", channel));
10521 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
10522 (channel <= CH_MAX_2G_CHANNEL)) {
10523 band_chan_arr = __wl_2ghz_channels;
10524 array_size = ARRAYSIZE(__wl_2ghz_channels);
10526 band = IEEE80211_BAND_2GHZ;
10527 ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false;
10528 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
10529 band_chan_arr = __wl_5ghz_a_channels;
10530 array_size = ARRAYSIZE(__wl_5ghz_a_channels);
10532 band = IEEE80211_BAND_5GHZ;
10533 ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
10535 WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
10538 if (!ht40_allowed && CHSPEC_IS40(c))
10540 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
10541 if (band_chan_arr[j].hw_value == channel) {
10550 if (index < array_size) {
10551 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
10552 band_chan_arr[index].center_freq =
10553 ieee80211_channel_to_frequency(channel);
10555 band_chan_arr[index].center_freq =
10556 ieee80211_channel_to_frequency(channel, band);
10558 band_chan_arr[index].hw_value = channel;
10560 if (CHSPEC_IS40(c) && ht40_allowed) {
10561 /* assuming the order is HT20, HT40 Upper,
10562 * HT40 lower from chanspecs
10564 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
10565 if (CHSPEC_SB_UPPER(c)) {
10566 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10567 band_chan_arr[index].flags &=
10568 ~IEEE80211_CHAN_NO_HT40;
10569 band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
10571 /* It should be one of
10572 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
10574 band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
10575 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
10576 band_chan_arr[index].flags |=
10577 IEEE80211_CHAN_NO_HT40MINUS;
10580 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
10581 if (!dfs_radar_disabled) {
10582 if (band == IEEE80211_BAND_2GHZ)
10583 channel |= WL_CHANSPEC_BAND_2G;
10585 channel |= WL_CHANSPEC_BAND_5G;
10586 channel |= WL_CHANSPEC_BW_20;
10587 channel = wl_chspec_host_to_driver(channel);
10588 err = wldev_iovar_getint(dev, "per_chan_info", &channel);
10590 if (channel & WL_CHAN_RADAR)
10591 band_chan_arr[index].flags |=
10592 (IEEE80211_CHAN_RADAR |
10593 IEEE80211_CHAN_NO_IBSS);
10594 if (channel & WL_CHAN_PASSIVE)
10595 band_chan_arr[index].flags |=
10596 IEEE80211_CHAN_PASSIVE_SCAN;
10597 } else if (err == BCME_UNSUPPORTED) {
10598 dfs_radar_disabled = TRUE;
10599 WL_ERR(("does not support per_chan_info\n"));
10608 __wl_band_2ghz.n_channels = n_2g;
10609 __wl_band_5ghz_a.n_channels = n_5g;
10614 s32 wl_update_wiphybands(struct wl_priv *wl, bool notify)
10616 struct wiphy *wiphy;
10617 struct net_device *dev;
10624 bool rollback_lock = false;
10627 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
10630 wl = wlcfg_drv_priv;
10631 mutex_lock(&wl->usr_sync);
10632 rollback_lock = true;
10634 dev = wl_to_prmry_ndev(wl);
10636 memset(bandlist, 0, sizeof(bandlist));
10637 err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
10638 sizeof(bandlist), false);
10639 if (unlikely(err)) {
10640 WL_ERR(("error read bandlist (%d)\n", err));
10643 err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
10644 sizeof(s32), false);
10645 if (unlikely(err)) {
10646 WL_ERR(("error (%d)\n", err));
10650 err = wldev_iovar_getint(dev, "nmode", &nmode);
10651 if (unlikely(err)) {
10652 WL_ERR(("error reading nmode (%d)\n", err));
10654 /* For nmodeonly check bw cap */
10655 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
10656 if (unlikely(err)) {
10657 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
10661 err = wl_construct_reginfo(wl, bw_cap);
10663 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
10664 if (err != BCME_UNSUPPORTED)
10668 wiphy = wl_to_wiphy(wl);
10669 nband = bandlist[0];
10671 for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
10673 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
10674 bands[IEEE80211_BAND_5GHZ] =
10676 index = IEEE80211_BAND_5GHZ;
10677 if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G)
10678 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10680 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
10681 bands[IEEE80211_BAND_2GHZ] =
10683 index = IEEE80211_BAND_2GHZ;
10684 if (bw_cap == WLC_N_BW_40ALL)
10685 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
10688 if ((index >= 0) && nmode) {
10689 bands[index]->ht_cap.cap |=
10690 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
10691 bands[index]->ht_cap.ht_supported = TRUE;
10692 bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
10693 bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
10694 /* An HT shall support all EQM rates for one spatial stream */
10695 bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
10700 wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
10701 wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
10703 /* check if any bands populated otherwise makes 2Ghz as default */
10704 if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
10705 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
10706 /* Setup 2Ghz band as default */
10707 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
10711 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
10715 mutex_unlock(&wl->usr_sync);
10719 static s32 __wl_cfg80211_up(struct wl_priv *wl)
10722 #ifdef WL_HOST_BAND_MGMT
10724 #endif /* WL_HOST_BAND_MGMT */
10725 struct net_device *ndev = wl_to_prmry_ndev(wl);
10726 struct wireless_dev *wdev = ndev->ieee80211_ptr;
10730 err = dhd_config_dongle(wl, false);
10734 err = wl_config_ifmode(wl, ndev, wdev->iftype);
10735 if (unlikely(err && err != -EINPROGRESS)) {
10736 WL_ERR(("wl_config_ifmode failed\n"));
10738 err = wl_update_wiphybands(wl, true);
10739 if (unlikely(err)) {
10740 WL_ERR(("wl_update_wiphybands failed\n"));
10743 err = dhd_monitor_init(wl->pub);
10744 err = wl_invoke_iscan(wl);
10746 #ifdef WL_HOST_BAND_MGMT
10747 /* By default the curr_band is initialized to BAND_AUTO */
10748 if ((ret = wl_cfg80211_set_band(ndev, WLC_BAND_AUTO)) < 0) {
10749 if (ret == BCME_UNSUPPORTED) {
10750 /* Don't fail the initialization, lets just
10751 * fall back to the original method
10753 WL_ERR(("WL_HOST_BAND_MGMT defined, "
10754 "but roam_band iovar not supported \n"));
10756 WL_ERR(("roam_band failed. ret=%d", ret));
10760 #endif /* WL_HOST_BAND_MGMT */
10762 #if defined(DHCP_SCAN_SUPPRESS)
10763 /* wlan scan_supp timer and work thread info */
10764 init_timer(&wl->scan_supp_timer);
10765 wl->scan_supp_timer.data = (ulong)wl;
10766 wl->scan_supp_timer.function = wl_cfg80211_scan_supp_timerfunc;
10767 INIT_WORK(&wl->wlan_work, wl_cfg80211_work_handler);
10768 #endif /* DHCP_SCAN_SUPPRESS */
10769 INIT_DELAYED_WORK(&wl->pm_enable_work, wl_cfg80211_work_handler);
10770 wl_set_drv_status(wl, READY, ndev);
10774 static s32 __wl_cfg80211_down(struct wl_priv *wl)
10777 unsigned long flags;
10778 struct net_info *iter, *next;
10779 struct net_device *ndev = wl_to_prmry_ndev(wl);
10780 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10781 // struct net_device *p2p_net = wl->p2p_net;
10782 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10784 #ifdef PROP_TXSTATUS_VSDB
10785 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
10786 #endif /* PROP_TXSTATUS_VSDB */
10788 if (wl->pm_enable_work_on) {
10789 cancel_delayed_work_sync(&wl->pm_enable_work);
10790 wl->pm_enable_work_on = false;
10793 if (wl->p2p_supported) {
10794 wl_clr_p2p_status(wl, GO_NEG_PHASE);
10795 #ifdef PROP_TXSTATUS_VSDB
10796 if (wl->p2p->vif_created) {
10797 if (dhd->wlfc_enabled && wl->wlfc_on) {
10798 dhd->wlfc_enabled = false;
10799 dhd_wlfc_deinit(dhd);
10800 if (dhd->plat_deinit)
10801 dhd->plat_deinit((void *)dhd);
10802 wl->wlfc_on = false;
10805 #endif /* PROP_TXSTATUS_VSDB */
10808 #if defined(DHCP_SCAN_SUPPRESS)
10809 /* Force clear of scan_suppress */
10810 if (wl->scan_suppressed)
10811 wl_cfg80211_scan_suppress(ndev, 0);
10812 if (timer_pending(&wl->scan_supp_timer))
10813 del_timer_sync(&wl->scan_supp_timer);
10814 cancel_work_sync(&wl->wlan_work);
10815 #endif /* DHCP_SCAN_SUPPRESS */
10817 /* If primary BSS is operational (for e.g SoftAP), bring it down */
10818 if (!(wl_cfgp2p_find_idx(wl, ndev, &bssidx)) &&
10819 wl_cfgp2p_bss_isup(ndev, bssidx)) {
10820 if (wl_cfgp2p_bss(wl, ndev, bssidx, 0) < 0)
10821 WL_ERR(("BSS down failed \n"));
10824 /* Check if cfg80211 interface is already down */
10825 if (!wl_get_drv_status(wl, READY, ndev))
10826 return err; /* it is even not ready */
10827 for_each_ndev(wl, iter, next)
10828 wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev);
10831 wl_cfg80211_sdo_deinit(wl);
10835 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10836 if (wl->scan_request) {
10837 cfg80211_scan_done(wl->scan_request, true);
10838 wl->scan_request = NULL;
10840 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10842 for_each_ndev(wl, iter, next) {
10843 wl_clr_drv_status(wl, READY, iter->ndev);
10844 wl_clr_drv_status(wl, SCANNING, iter->ndev);
10845 wl_clr_drv_status(wl, SCAN_ABORTING, iter->ndev);
10846 wl_clr_drv_status(wl, CONNECTING, iter->ndev);
10847 wl_clr_drv_status(wl, CONNECTED, iter->ndev);
10848 wl_clr_drv_status(wl, DISCONNECTING, iter->ndev);
10849 wl_clr_drv_status(wl, AP_CREATED, iter->ndev);
10850 wl_clr_drv_status(wl, AP_CREATING, iter->ndev);
10852 wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype =
10853 NL80211_IFTYPE_STATION;
10854 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
10855 // if (p2p_net) // terence 20131219: don't close p2p0 or p2p0 never go back anymore
10856 // dev_close(p2p_net);
10857 #endif /* WL_CFG80211 && WL_ENABLE_P2P_IF */
10858 DNGL_FUNC(dhd_cfg80211_down, (wl));
10861 if (wl->p2p_supported)
10862 wl_cfgp2p_down(wl);
10863 dhd_monitor_uninit();
10868 s32 wl_cfg80211_up(void *para)
10870 struct wl_priv *wl;
10877 wl = wlcfg_drv_priv;
10879 if ((err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_VERSION, &val,
10880 sizeof(int), false) < 0)) {
10881 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
10885 if (val != WLC_IOCTL_VERSION && val != 1) {
10886 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
10887 val, WLC_IOCTL_VERSION));
10888 return BCME_VERSION;
10890 ioctl_version = val;
10891 WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
10893 mutex_lock(&wl->usr_sync);
10894 dhd = (dhd_pub_t *)(wl->pub);
10895 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
10896 err = wl_cfg80211_attach_post(wl_to_prmry_ndev(wl));
10900 #if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X)
10901 if (dhd->fw_4way_handshake)
10902 wl->wdev->wiphy->features |= NL80211_FEATURE_FW_4WAY_HANDSHAKE;
10904 err = __wl_cfg80211_up(wl);
10906 WL_ERR(("__wl_cfg80211_up failed\n"));
10907 mutex_unlock(&wl->usr_sync);
10911 /* Private Event to Supplicant with indication that chip hangs */
10912 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
10914 struct wl_priv *wl;
10915 wl = wlcfg_drv_priv;
10917 WL_ERR(("In : chip crash eventing\n"));
10918 cfg80211_disconnected(dev, reason, NULL, 0, GFP_KERNEL);
10919 #if defined(RSSIAVG)
10920 wl_free_rssi_cache(&g_rssi_cache_ctrl);
10922 #if defined(BSSCACHE)
10923 wl_free_bss_cache(&g_bss_cache_ctrl);
10924 wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0);
10932 s32 wl_cfg80211_down(void *para)
10934 struct wl_priv *wl;
10939 wl = wlcfg_drv_priv;
10940 mutex_lock(&wl->usr_sync);
10941 #if defined(RSSIAVG)
10942 wl_free_rssi_cache(&g_rssi_cache_ctrl);
10944 #if defined(BSSCACHE)
10945 wl_free_bss_cache(&g_bss_cache_ctrl);
10946 wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0);
10948 err = __wl_cfg80211_down(wl);
10949 mutex_unlock(&wl->usr_sync);
10954 static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item)
10956 unsigned long flags;
10958 struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10962 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
10965 rptr = &profile->sec;
10968 rptr = &profile->active;
10970 case WL_PROF_BSSID:
10971 rptr = profile->bssid;
10974 rptr = &profile->ssid;
10977 rptr = &profile->channel;
10980 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
10982 WL_ERR(("invalid item (%d)\n", item));
10987 wl_update_prof(struct wl_priv *wl, struct net_device *ndev,
10988 const wl_event_msg_t *e, void *data, s32 item)
10991 struct wlc_ssid *ssid;
10992 unsigned long flags;
10993 struct wl_profile *profile = wl_get_profile_by_netdev(wl, ndev);
10997 spin_lock_irqsave(&wl->cfgdrv_lock, flags);
11000 ssid = (wlc_ssid_t *) data;
11001 memset(profile->ssid.SSID, 0,
11002 sizeof(profile->ssid.SSID));
11003 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
11004 profile->ssid.SSID_len = ssid->SSID_len;
11006 case WL_PROF_BSSID:
11008 memcpy(profile->bssid, data, ETHER_ADDR_LEN);
11010 memset(profile->bssid, 0, ETHER_ADDR_LEN);
11013 memcpy(&profile->sec, data, sizeof(profile->sec));
11016 profile->active = *(bool *)data;
11018 case WL_PROF_BEACONINT:
11019 profile->beacon_interval = *(u16 *)data;
11021 case WL_PROF_DTIMPERIOD:
11022 profile->dtim_period = *(u8 *)data;
11025 profile->channel = *(u32*)data;
11031 spin_unlock_irqrestore(&wl->cfgdrv_lock, flags);
11033 if (err == -EOPNOTSUPP)
11034 WL_ERR(("unsupported item (%d)\n", item));
11039 void wl_cfg80211_dbg_level(u32 level)
11042 * prohibit to change debug level
11043 * by insmod parameter.
11044 * eventually debug level will be configured
11045 * in compile time by using CONFIG_XXX
11047 /* wl_dbg_level = level; */
11050 static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev)
11052 return wl_get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS;
11055 static __used bool wl_is_ibssstarter(struct wl_priv *wl)
11057 return wl->ibss_starter;
11060 static void wl_rst_ie(struct wl_priv *wl)
11062 struct wl_ie *ie = wl_to_ie(wl);
11067 static __used s32 wl_add_ie(struct wl_priv *wl, u8 t, u8 l, u8 *v)
11069 struct wl_ie *ie = wl_to_ie(wl);
11072 if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
11073 WL_ERR(("ei crosses buffer boundary\n"));
11076 ie->buf[ie->offset] = t;
11077 ie->buf[ie->offset + 1] = l;
11078 memcpy(&ie->buf[ie->offset + 2], v, l);
11079 ie->offset += l + 2;
11084 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, u8 *ie_stream, u32 *ie_size)
11087 ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
11090 if (ssidie[1] != bi->SSID_len) {
11092 WL_ERR(("%s: Wrong SSID len: %d != %d\n",
11093 __FUNCTION__, ssidie[1], bi->SSID_len));
11096 memmove(ssidie + bi->SSID_len + 2, ssidie + 2, *ie_size - (ssidie + 2 - ie_stream));
11097 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
11098 *ie_size = *ie_size + bi->SSID_len;
11099 ssidie[1] = bi->SSID_len;
11102 if (*(ssidie + 2) == '\0')
11103 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
11107 static s32 wl_mrg_ie(struct wl_priv *wl, u8 *ie_stream, u16 ie_size)
11109 struct wl_ie *ie = wl_to_ie(wl);
11112 if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
11113 WL_ERR(("ei_stream crosses buffer boundary\n"));
11116 memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
11117 ie->offset += ie_size;
11122 static s32 wl_cp_ie(struct wl_priv *wl, u8 *dst, u16 dst_size)
11124 struct wl_ie *ie = wl_to_ie(wl);
11127 if (unlikely(ie->offset > dst_size)) {
11128 WL_ERR(("dst_size is not enough\n"));
11131 memcpy(dst, &ie->buf[0], ie->offset);
11136 static u32 wl_get_ielen(struct wl_priv *wl)
11138 struct wl_ie *ie = wl_to_ie(wl);
11143 static void wl_link_up(struct wl_priv *wl)
11145 wl->link_up = true;
11148 static void wl_link_down(struct wl_priv *wl)
11150 struct wl_connect_info *conn_info = wl_to_conn(wl);
11153 wl->link_up = false;
11154 conn_info->req_ie_len = 0;
11155 conn_info->resp_ie_len = 0;
11158 static unsigned long wl_lock_eq(struct wl_priv *wl)
11160 unsigned long flags;
11162 spin_lock_irqsave(&wl->eq_lock, flags);
11166 static void wl_unlock_eq(struct wl_priv *wl, unsigned long flags)
11168 spin_unlock_irqrestore(&wl->eq_lock, flags);
11171 static void wl_init_eq_lock(struct wl_priv *wl)
11173 spin_lock_init(&wl->eq_lock);
11176 static void wl_delay(u32 ms)
11178 if (in_atomic() || (ms < jiffies_to_msecs(1))) {
11179 OSL_DELAY(ms*1000);
11185 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
11187 struct wl_priv *wl = wlcfg_drv_priv;
11188 struct ether_addr p2pif_addr;
11189 struct ether_addr primary_mac;
11192 if (!p2p_is_on(wl)) {
11193 get_primary_mac(wl, &primary_mac);
11194 wl_cfgp2p_generate_bss_mac(&primary_mac, p2pdev_addr, &p2pif_addr);
11196 memcpy(p2pdev_addr->octet,
11197 wl->p2p->dev_addr.octet, ETHER_ADDR_LEN);
11203 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
11205 struct wl_priv *wl;
11207 wl = wlcfg_drv_priv;
11209 return wl_cfgp2p_set_p2p_noa(wl, net, buf, len);
11212 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
11214 struct wl_priv *wl;
11215 wl = wlcfg_drv_priv;
11217 return wl_cfgp2p_get_p2p_noa(wl, net, buf, len);
11220 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
11222 struct wl_priv *wl;
11223 wl = wlcfg_drv_priv;
11225 return wl_cfgp2p_set_p2p_ps(wl, net, buf, len);
11228 s32 wl_cfg80211_channel_to_freq(u32 channel)
11232 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
11233 freq = ieee80211_channel_to_frequency(channel);
11237 if (channel <= CH_MAX_2G_CHANNEL)
11238 band = IEEE80211_BAND_2GHZ;
11240 band = IEEE80211_BAND_5GHZ;
11241 freq = ieee80211_channel_to_frequency(channel, band);
11248 #define MAX_QR_LEN NLMSG_GOODSIZE
11250 typedef struct wl_cfg80211_dev_info {
11255 u8 bssid[ETH_ALEN];
11256 } wl_cfg80211_dev_info_t;
11259 wl_notify_device_discovery(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
11260 const wl_event_msg_t *e, void *data)
11263 u32 event = ntoh32(e->event_type);
11264 wl_cfg80211_dev_info_t info;
11265 struct wl_bss_info *bi = NULL;
11266 struct net_device *ndev = NULL;
11270 wl_escan_result_t *escan_result;
11272 WL_SD(("Enter. type:%d \n", event));
11274 if ((event != WLC_E_P2PO_ADD_DEVICE) && (event != WLC_E_P2PO_DEL_DEVICE)) {
11275 WL_ERR(("Unknown Event\n"));
11279 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
11281 mutex_lock(&wl->usr_sync);
11282 if (event == WLC_E_P2PO_DEL_DEVICE) {
11283 WL_SD(("DEV_LOST MAC:"MACDBG" \n", MAC2STRDBG(e->addr.octet)));
11284 err = wl_genl_send_msg(ndev, event, (u8 *)e->addr.octet, ETH_ALEN, 0, 0);
11287 escan_result = (wl_escan_result_t *) data;
11289 if (dtoh16(escan_result->bss_count) != 1) {
11290 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
11295 bi = escan_result->bss_info;
11296 buflen = dtoh32(bi->length);
11297 if (unlikely(buflen > WL_BSS_INFO_MAX)) {
11298 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
11303 /* Update sub-header */
11304 bzero(&info, sizeof(wl_cfg80211_dev_info_t));
11305 channel = bi->ctl_ch ? bi->ctl_ch :
11306 CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
11307 info.freq = wl_cfg80211_channel_to_freq(channel);
11308 info.rssi = dtoh16(bi->RSSI);
11309 #if defined(RSSIOFFSET)
11310 info.rssi = wl_update_rssi_offset(info.rssi);
11312 memcpy(info.bssid, &bi->BSSID, ETH_ALEN);
11313 info.ie_len = buflen;
11315 WL_SD(("DEV_FOUND band:%x Freq:%d rssi:%x "MACDBG" \n",
11316 info.band, info.freq, info.rssi, MAC2STRDBG(info.bssid)));
11318 buf = ((u8 *) bi) + bi->ie_offset;
11319 err = wl_genl_send_msg(ndev, event, buf,
11320 buflen, (u8 *)&info, sizeof(wl_cfg80211_dev_info_t));
11323 mutex_unlock(&wl->usr_sync);
11328 wl_cfg80211_sdo_init(struct wl_priv *wl)
11330 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
11333 WL_SD(("SDO already initialized\n"));
11337 wl->sdo = kzalloc(sizeof(sd_offload_t), kflags);
11339 WL_ERR(("malloc failed for SDO \n"));
11347 wl_cfg80211_sdo_deinit(struct wl_priv *wl)
11352 if (!wl || !wl->p2p) {
11353 WL_ERR(("Wl %p or wl->p2p %p is null\n",
11354 wl, wl ? wl->p2p : 0));
11358 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11360 WL_DBG(("SDO Not Initialized. Do nothing. \n"));
11363 if (wl->sdo->dd_state &&
11364 (ret = wldev_iovar_setbuf_bsscfg(wl_to_prmry_ndev(wl),
11365 "p2po_stop", (void*)&sdo_pause, sizeof(sdo_pause),
11366 wl->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL)) < 0) {
11367 WL_ERR(("p2po_stop Failed :%d\n", ret));
11372 WL_SD(("SDO Deinit Done \n"));
11378 wl_cfg80211_resume_sdo(struct net_device *dev, struct wl_priv *wl)
11380 wl_sd_listen_t sd_listen;
11382 s32 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11384 WL_DBG(("Enter\n"));
11391 dev = wl_to_prmry_ndev(wl);
11393 /* Disable back the ESCAN events for the offload */
11394 wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, false);
11396 /* Resume according to the saved state */
11397 if (wl->sdo->dd_state == WL_DD_STATE_SEARCH) {
11398 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_find", NULL, 0,
11399 wl->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL)) < 0) {
11400 WL_ERR(("p2po_find Failed :%d\n", ret));
11402 } else if (wl->sdo->dd_state == WL_DD_STATE_LISTEN) {
11403 sd_listen.interval = wl->sdo->sd_listen.interval;
11404 sd_listen.period = wl->sdo->sd_listen.period;
11406 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&sd_listen,
11407 sizeof(wl_sd_listen_t), wl->ioctl_buf, WLC_IOCTL_SMLEN,
11408 bssidx, NULL)) < 0) {
11409 WL_ERR(("p2po_listen Failed :%d\n", ret));
11414 /* p2po_stop clears of the eventmask for GAS. Set it back */
11415 wl_add_remove_eventmsg(dev, WLC_E_SERVICE_FOUND, true);
11416 wl_add_remove_eventmsg(dev, WLC_E_GAS_FRAGMENT_RX, true);
11417 wl_add_remove_eventmsg(dev, WLC_E_GAS_COMPLETE, true);
11419 WL_SD(("SDO Resumed \n"));
11424 s32 wl_cfg80211_pause_sdo(struct net_device *dev, struct wl_priv *wl)
11428 s32 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11431 WL_DBG(("Enter \n"));
11434 WL_ERR(("SDO not initialized \n"));
11439 dev = wl_to_prmry_ndev(wl);
11441 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop",
11442 (void*)&sdo_pause, sizeof(sdo_pause),
11443 wl->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &wl->ioctl_buf_sync)) < 0) {
11444 WL_ERR(("p2po_stop Failed :%d\n", ret));
11447 /* Enable back the ESCAN events for the SCAN */
11448 wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, true);
11450 WL_SD(("SDO Paused \n"));
11456 wl_svc_resp_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
11457 const wl_event_msg_t *e, void *data)
11459 u32 event = ntoh32(e->event_type);
11460 struct net_device *ndev = NULL;
11461 u8 *dst_mac = (u8 *)e->addr.octet;
11463 wl_event_sd_t *gas = NULL;
11464 int status = ntoh32(e->status);
11465 sdo_event_t sdo_hdr;
11466 u32 data_len = ntoh32(e->datalen);
11467 u8 *data_ptr = NULL;
11471 WL_SD(("Enter event_type:%d status:%d\n", event, status));
11474 WL_ERR(("SDO Not initialized \n"));
11478 if (!(wl->sdo->sd_state & WL_SD_SEARCH_SVC)) {
11479 /* We are not searching for any service. Drop
11482 WL_ERR(("Bogus SDO Event. Do nothing.. \n"));
11486 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
11488 mutex_lock(&wl->usr_sync);
11489 if (event == WLC_E_SERVICE_FOUND) {
11491 if ((status != WLC_E_STATUS_SUCCESS) && (status != WLC_E_STATUS_PARTIAL)) {
11492 WL_ERR(("WLC_E_SERVICE_FOUND: unknown status \n"));
11496 gas = (wl_event_sd_t *)data;
11502 bzero(&sdo_hdr, sizeof(sdo_event_t));
11503 sdo_hdr.freq = wl_cfg80211_channel_to_freq(gas->channel);
11504 sdo_hdr.count = gas->count;
11505 memcpy(sdo_hdr.addr, dst_mac, ETH_ALEN);
11506 data_ptr = (char *)gas->tlv;
11507 tot_len = data_len - (sizeof(wl_event_sd_t) - sizeof(wl_sd_tlv_t));
11509 WL_SD(("WLC_E_SERVICE_FOUND "MACDBG" data_len:%d tlv_count:%d \n",
11510 MAC2STRDBG(dst_mac), data_len, sdo_hdr.count));
11512 if (tot_len > NLMSG_DEFAULT_SIZE) {
11513 WL_ERR(("size(%u) > %lu not supported \n", tot_len, NLMSG_DEFAULT_SIZE));
11518 if (wl_genl_send_msg(ndev, event, data_ptr,
11519 tot_len, (u8 *)&sdo_hdr, sizeof(sdo_event_t)) < 0)
11520 WL_ERR(("Couldn't send up the NETLINK Event \n"));
11522 WL_SD(("GAS event sent up \n"));
11524 WL_ERR(("Unsupported Event: %d \n", event));
11528 mutex_unlock(&wl->usr_sync);
11532 s32 wl_cfg80211_DsdOffloadParseProto(char* proto_str, u8* proto)
11537 for (i = 0; i < MAX_SDO_PROTO; i++) {
11538 if (strncmp(proto_str, wl_sdo_protos[i].str, strlen(wl_sdo_protos[i].str)) == 0) {
11539 WL_SD(("Matching proto (%d) found \n", wl_sdo_protos[i].val));
11540 *proto = wl_sdo_protos[i].val;
11541 len = strlen(wl_sdo_protos[i].str);
11549 * register to search for a UPnP service
11550 * ./DRIVER P2P_SD_REQ upnp 0x10urn:schemas-upnporg:device:InternetGatewayDevice:1
11555 #define UPNP_QUERY_VER_OFFSET 3
11556 s32 wl_sd_handle_sd_req(
11557 struct net_device *dev,
11561 struct wl_priv *wl = wlcfg_drv_priv;
11566 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
11567 u32 tot_len = len + sizeof(wl_sd_qr_t);
11570 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
11571 WL_ERR(("find_idx failed\n"));
11574 /* Check for the least arg length expected */
11575 if (!buf || (len < strlen("all"))) {
11576 WL_ERR(("Wrong Arg\n"));
11580 if (tot_len > WLC_IOCTL_MAXLEN) {
11581 WL_ERR(("Length > %lu not supported \n", MAX_QR_LEN));
11585 sdreq = kzalloc(tot_len, kflags);
11587 WL_ERR(("malloc failed\n"));
11591 WL_SD(("%s Len: %d\n", buf, len));
11592 if ((ret = wl_cfg80211_DsdOffloadParseProto(buf, &proto)) < 0) {
11593 WL_ERR(("Unknown proto \n"));
11597 sdreq->protocol = proto;
11599 buf++; /* skip the space */
11600 sdreq->transaction_id = simple_strtoul(buf, NULL, 16);
11601 WL_SD(("transaction_id:%d\n", sdreq->transaction_id));
11602 buf += sizeof(sdreq->transaction_id);
11604 if (*buf == '\0') {
11605 WL_SD(("No Query present. Proto:%d \n", proto));
11606 sdreq->query_len = 0;
11608 buf++; /* skip the space */
11609 /* UPNP version needs to put as binary val */
11610 if (sdreq->protocol == SVC_RPOTYPE_UPNP) {
11611 /* Extract UPNP version */
11612 version = simple_strtoul(buf, NULL, 16);
11613 buf = buf + UPNP_QUERY_VER_OFFSET;
11615 WL_SD(("Upnp version: 0x%x \n", version));
11619 WL_SD(("Len after stripping proto: %d Query: %s\n", len, buf));
11620 /* copy the query part */
11621 memcpy(sdreq->qrbuf, buf, len);
11622 sdreq->query_len = len;
11625 /* Enable discovery */
11626 if ((ret = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0)) < 0) {
11627 WL_ERR(("cfgp2p_enable discovery failed"));
11631 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_sd_req_resp", (void*)sdreq,
11632 tot_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN,
11633 bssidx, &wl->ioctl_buf_sync)) < 0) {
11634 WL_ERR(("Find SVC Failed \n"));
11638 wl->sdo->sd_state |= WL_SD_SEARCH_SVC;
11645 s32 wl_sd_handle_sd_cancel_req(
11646 struct net_device *dev,
11649 struct wl_priv *wl = wlcfg_drv_priv;
11650 s32 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11652 if (wldev_iovar_setbuf_bsscfg(dev, "p2po_sd_cancel", NULL,
11653 0, wl->ioctl_buf, WLC_IOCTL_SMLEN,
11654 bssidx, &wl->ioctl_buf_sync) < 0) {
11655 WL_ERR(("Cancel SD Failed \n"));
11659 wl->sdo->sd_state &= ~WL_SD_SEARCH_SVC;
11665 * register a UPnP service to be discovered
11666 * ./wl P2P_SD_SVC_ADD upnp 0x10urn:schemas-upnporg:device:InternetGatewayDevice:1 0x10uu
11667 * id:6859dede-8574-59ab-9332-123456789012::urn:schemas-upnporg:device:InternetGate
11670 s32 wl_sd_handle_sd_add_svc(
11671 struct net_device *dev,
11675 struct wl_priv *wl = wlcfg_drv_priv;
11683 u32 tot_len = len + sizeof(wl_sd_qr_t);
11684 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
11689 WL_SD(("%s Len: %d\n", buf, len));
11690 if (tot_len > WLC_IOCTL_MAXLEN) {
11691 WL_ERR(("Query-Resp length > %d not supported \n", WLC_IOCTL_MAXLEN));
11695 sdreq = kzalloc(tot_len, kflags);
11697 WL_ERR(("malloc failed\n"));
11701 if ((ret = wl_cfg80211_DsdOffloadParseProto(buf, &proto)) < 0) {
11702 WL_ERR(("Unknown Proto \n"));
11706 sdreq->protocol = proto;
11709 if (*buf == '\0') {
11710 WL_ERR(("No Query Resp pair present \n"));
11715 buf++; /* Skip the space */
11717 query = strsep((char **)&buf, " ");
11718 if (!query || !buf) {
11719 WL_ERR(("No Query RESP Present\n"));
11725 if (sdreq->protocol == SVC_RPOTYPE_UPNP) {
11726 /* Extract UPNP version */
11727 version = simple_strtoul(query, NULL, 16);
11728 query = query + UPNP_QUERY_VER_OFFSET;
11729 resp = resp + UPNP_QUERY_VER_OFFSET;
11730 query[0] = version;
11732 WL_SD(("Upnp version: 0x%x \n", version));
11735 sdreq->query_len = strlen(query);
11736 sdreq->response_len = strlen(buf);
11737 WL_SD(("query:%s len:%u \n", query, sdreq->query_len));
11738 WL_SD(("resp:%s len:%u \n", buf, sdreq->response_len));
11740 memcpy(sdreq->qrbuf, query, sdreq->query_len);
11741 memcpy((sdreq->qrbuf + sdreq->query_len), resp, sdreq->response_len);
11743 /* Enable discovery */
11744 if ((ret = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0)) < 0) {
11745 WL_ERR(("cfgp2p_enable discovery failed"));
11749 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_addsvc", (void*)sdreq,
11750 tot_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN,
11751 bssidx, &wl->ioctl_buf_sync)) < 0) {
11752 WL_ERR(("FW Failed in doing p2po_addsvc. RET:%d \n", ret));
11756 wl->sdo->sd_state |= WL_SD_ADV_SVC;
11763 s32 wl_sd_handle_sd_del_svc(
11764 struct net_device *dev,
11768 struct wl_priv *wl = wlcfg_drv_priv;
11773 u32 tot_len = len + sizeof(wl_sd_qr_t);
11774 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
11777 if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) {
11778 WL_ERR(("find_idx failed\n"));
11782 sdreq = (wl_sd_qr_t *)kzalloc(tot_len, kflags);
11784 WL_ERR(("malloc failed\n"));
11789 /* Check for the least arg length expected */
11790 if (buf && len >= strlen("all")) {
11791 WL_DBG(("%s Len: %d\n", buf, len));
11792 if ((ret = wl_cfg80211_DsdOffloadParseProto(buf, &proto)) < 0) {
11793 WL_ERR(("Unknown Proto \n"));
11796 sdreq->protocol = proto;
11800 /* Query present */
11801 buf++; /* Skip the space */
11802 /* UPNP version needs to put as binary val */
11803 if (sdreq->protocol == SVC_RPOTYPE_UPNP) {
11804 /* Extract UPNP version */
11805 version = simple_strtoul(buf, NULL, 16);
11806 buf = buf + UPNP_QUERY_VER_OFFSET;
11808 WL_SD(("Upnp version: 0x%x \n", version));
11810 memcpy(sdreq->qrbuf, buf, strlen(buf));
11811 sdreq->query_len = strlen(buf);
11812 WL_SD(("Query to be deleted:%s len:%d\n", buf, sdreq->query_len));
11819 sdreq->protocol = proto;
11820 WL_SD(("Proto: %d \n", proto));
11822 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_delsvc", (void*)sdreq,
11823 tot_len, wl->ioctl_buf, WLC_IOCTL_MAXLEN,
11824 bssidx, &wl->ioctl_buf_sync)) < 0) {
11825 WL_ERR(("FW Failed in doing sd_delsvc. ret=%d \n", ret));
11829 wl->sdo->sd_state &= ~WL_SD_ADV_SVC;
11838 s32 wl_sd_handle_sd_stop_discovery(
11839 struct net_device *dev,
11843 struct wl_priv *wl = wlcfg_drv_priv;
11844 s32 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11848 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop", (void*)&sdo_pause,
11849 sizeof(sdo_pause), wl->ioctl_buf, WLC_IOCTL_SMLEN,
11850 bssidx, &wl->ioctl_buf_sync)) < 0) {
11851 WL_ERR(("p2po_stop Failed :%d\n", ret));
11855 if (wldev_iovar_setint(dev, "mpc", 1) < 0) {
11856 /* Setting of MPC failed */
11857 WL_ERR(("mpc enabling back failed\n"));
11861 /* clear the states */
11862 wl->sdo->dd_state = WL_DD_STATE_IDLE;
11863 wl_clr_p2p_status(wl, DISC_IN_PROGRESS);
11865 bzero(&wl->sdo->sd_listen, sizeof(wl_sd_listen_t));
11867 /* Remove ESCAN from waking up the host if ofind/olisten is enabled */
11868 wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, true);
11873 s32 wl_sd_handle_sd_find(
11874 struct net_device *dev,
11878 struct wl_priv *wl = wlcfg_drv_priv;
11879 s32 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11881 s32 disc_bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11882 vndr_ie_setbuf_t *ie_setbuf;
11884 vndr_ie_buf_t *vndriebuf;
11885 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
11890 0x09, 0x02, 0x02, 0x00, 0x27, 0x0c, 0x06, 0x05, 0x00,
11891 0x55, 0x53, 0x04, 0x51, 0x0b, 0x11, 0x05, 0x00, 0x55,
11892 0x53, 0x04, 0x51, 0x0b
11895 /* Enable discovery */
11896 if ((ret = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0)) < 0) {
11897 WL_ERR(("cfgp2p_enable discovery failed"));
11901 if (buf && strncmp(buf, "chan=", strlen("chan=")) == 0) {
11902 buf += strlen("chan=");
11903 channel = simple_strtol(buf, NULL, 10);
11904 WL_SD(("listen_chan to be set:%d\n", channel));
11905 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
11906 sizeof(channel), wl->ioctl_buf, WLC_IOCTL_SMLEN,
11907 bssidx, &wl->ioctl_buf_sync)) < 0) {
11908 WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
11913 tot_len = sizeof(vndr_ie_setbuf_t) + sizeof(p2pie_buf);
11914 ie_setbuf = (vndr_ie_setbuf_t *) kzalloc(tot_len, kflags);
11916 WL_ERR(("IE memory alloc failed\n"));
11920 /* Apply the p2p_ie for p2po_find */
11921 strcpy(ie_setbuf->cmd, "add");
11923 vndriebuf = &ie_setbuf->vndr_ie_buffer;
11924 vndriebuf->iecount = htod32(1);
11925 vndriebuf->vndr_ie_list[0].pktflag = htod32(16);
11927 vndrie = &vndriebuf->vndr_ie_list[0].vndr_ie_data;
11929 vndrie->id = (uchar) DOT11_MNG_PROPR_ID;
11930 vndrie->len = sizeof(p2pie_buf);
11931 memcpy(vndrie->oui, WFA_OUI, WFA_OUI_LEN);
11932 memcpy(vndrie->data, p2pie_buf, sizeof(p2pie_buf));
11934 /* Remove ESCAN from waking up the host if SDO is enabled */
11935 wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, false);
11937 if (wldev_iovar_setbuf_bsscfg(dev, "ie", (void*)ie_setbuf,
11938 tot_len, wl->ioctl_buf, WLC_IOCTL_SMLEN,
11939 disc_bssidx, &wl->ioctl_buf_sync) < 0) {
11940 WL_ERR(("p2p add_ie failed \n"));
11944 WL_SD(("p2p add_ie applied successfully len:%d \n", tot_len));
11946 if (wldev_iovar_setint(dev, "mpc", 0) < 0) {
11947 /* Setting of MPC failed */
11948 WL_ERR(("mpc disabling faild\n"));
11953 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_find", NULL, 0,
11954 wl->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &wl->ioctl_buf_sync)) < 0) {
11955 WL_ERR(("p2po_find Failed :%d\n", ret));
11960 /* set the states */
11961 wl->sdo->dd_state = WL_DD_STATE_SEARCH;
11962 wl_set_p2p_status(wl, DISC_IN_PROGRESS);
11968 /* Incase of failure enable back the ESCAN event */
11970 wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, true);
11975 s32 wl_sd_handle_sd_listen(
11976 struct net_device *dev,
11980 struct wl_priv *wl = wlcfg_drv_priv;
11981 s32 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
11982 wl_sd_listen_t sd_listen;
11987 /* Just in case if it is not enabled */
11988 if ((ret = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0)) < 0) {
11989 WL_ERR(("cfgp2p_enable discovery failed"));
11993 if (wldev_iovar_setint(dev, "mpc", 0) < 0) {
11994 /* Setting of MPC failed */
11995 WL_ERR(("mpc disabling faild\n"));
11999 bzero(&sd_listen, sizeof(wl_sd_listen_t));
12002 ptr = strsep((char **)&buf, " ");
12004 /* period and duration given wrongly */
12005 WL_ERR(("Arguments in wrong format \n"));
12008 else if (strncmp(ptr, "chan=", strlen("chan=")) == 0) {
12009 sd_listen.interval = 65535;
12010 sd_listen.period = 65535;
12011 ptr += strlen("chan=");
12012 channel = simple_strtol(ptr, NULL, 10);
12015 sd_listen.period = simple_strtol(ptr, NULL, 10);
12016 ptr = strsep((char **)&buf, " ");
12018 WL_ERR(("Arguments in wrong format \n"));
12021 sd_listen.interval = simple_strtol(ptr, NULL, 10);
12022 if (buf && strncmp(buf, "chan=", strlen("chan=")) == 0) {
12023 buf += strlen("chan=");
12024 channel = simple_strtol(buf, NULL, 10);
12027 WL_SD(("listen_period:%d, listen_interval:%d and listen_channel:%d\n",
12028 sd_listen.period, sd_listen.interval, channel));
12030 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
12031 sizeof(channel), wl->ioctl_buf, WLC_IOCTL_SMLEN,
12032 bssidx, &wl->ioctl_buf_sync)) < 0) {
12033 WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
12037 WL_SD(("p2po_listen period:%d interval:%d \n",
12038 sd_listen.period, sd_listen.interval));
12039 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&sd_listen,
12040 sizeof(wl_sd_listen_t), wl->ioctl_buf, WLC_IOCTL_SMLEN,
12041 bssidx, &wl->ioctl_buf_sync)) < 0) {
12042 WL_ERR(("p2po_listen Failed :%d\n", ret));
12046 /* Remove ESCAN from waking up the host if ofind/olisten is enabled */
12047 wl_add_remove_eventmsg(dev, WLC_E_ESCAN_RESULT, false);
12049 /* Store the extended listen values for use in sdo_resume */
12050 wl->sdo->sd_listen.interval = sd_listen.interval;
12051 wl->sdo->sd_listen.period = sd_listen.period;
12053 /* set the states */
12054 wl->sdo->dd_state = WL_DD_STATE_LISTEN;
12055 wl_set_p2p_status(wl, DISC_IN_PROGRESS);
12060 s32 wl_cfg80211_sd_offload(struct net_device *dev, char *cmd, char* buf, int len)
12063 struct wl_priv *wl = wlcfg_drv_priv;
12065 WL_SD(("Entry cmd:%s arg_len:%d \n", cmd, len));
12068 WL_SD(("Initializing SDO \n"));
12069 if ((ret = wl_cfg80211_sdo_init(wl)) < 0)
12073 if (strncmp(cmd, "P2P_SD_REQ", strlen("P2P_SD_REQ")) == 0) {
12074 ret = wl_sd_handle_sd_req(dev, buf, len);
12075 } else if (strncmp(cmd, "P2P_SD_CANCEL_REQ", strlen("P2P_SD_CANCEL_REQ")) == 0) {
12076 ret = wl_sd_handle_sd_cancel_req(dev, buf);
12077 } else if (strncmp(cmd, "P2P_SD_SVC_ADD", strlen("P2P_SD_SVC_ADD")) == 0) {
12078 ret = wl_sd_handle_sd_add_svc(dev, buf, len);
12079 } else if (strncmp(cmd, "P2P_SD_SVC_DEL", strlen("P2P_SD_SVC_DEL")) == 0) {
12080 ret = wl_sd_handle_sd_del_svc(dev, buf, len);
12081 } else if (strncmp(cmd, "P2P_SD_FIND", strlen("P2P_SD_FIND")) == 0) {
12082 ret = wl_sd_handle_sd_find(dev, buf, len);
12083 } else if (strncmp(cmd, "P2P_SD_LISTEN", strlen("P2P_SD_LISTEN")) == 0) {
12084 ret = wl_sd_handle_sd_listen(dev, buf, len);
12085 } else if (strncmp(cmd, "P2P_SD_STOP", strlen("P2P_STOP")) == 0) {
12086 ret = wl_sd_handle_sd_stop_discovery(dev, buf, len);
12088 WL_ERR(("Request for Unsupported CMD:%s \n", buf));
12095 #endif /* WL_SDO */
12099 wl_tdls_event_handler(struct wl_priv *wl, bcm_struct_cfgdev *cfgdev,
12100 const wl_event_msg_t *e, void *data) {
12102 struct net_device *ndev = NULL;
12103 u32 reason = ntoh32(e->reason);
12106 ndev = cfgdev_to_wlc_ndev(cfgdev, wl);
12109 case WLC_E_TDLS_PEER_DISCOVERED :
12110 msg = " TDLS PEER DISCOVERD ";
12112 case WLC_E_TDLS_PEER_CONNECTED :
12113 msg = " TDLS PEER CONNECTED ";
12115 case WLC_E_TDLS_PEER_DISCONNECTED :
12116 msg = "TDLS PEER DISCONNECTED ";
12120 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
12121 (wl_to_prmry_ndev(wl) == ndev) ? "primary" : "secondary"));
12126 #endif /* WLTDLS */
12128 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
12130 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
12131 u8 *peer, enum nl80211_tdls_operation oper)
12135 struct wl_priv *wl = wlcfg_drv_priv;
12137 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
12138 memset(&info, 0, sizeof(tdls_iovar_t));
12140 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
12142 case NL80211_TDLS_DISCOVERY_REQ:
12143 if (!dhd->tdls_enable)
12144 ret = dhd_tdls_enable_disable(dhd, 1);
12147 info.mode = TDLS_MANUAL_EP_DISCOVERY;
12149 case NL80211_TDLS_SETUP:
12150 info.mode = TDLS_MANUAL_EP_CREATE;
12152 case NL80211_TDLS_TEARDOWN:
12153 info.mode = TDLS_MANUAL_EP_DELETE;
12156 WL_ERR(("Unsupported operation : %d\n", oper));
12159 ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
12160 wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync);
12162 WL_ERR(("tdls_endpoint error %d\n", ret));
12165 #endif /* WLTDLS */
12168 #endif /* LINUX_VERSION > VERSION(3,2,0) || WL_COMPAT_WIRELESS */
12170 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len,
12171 enum wl_management_type type)
12173 struct wl_priv *wl;
12174 struct net_device *ndev = NULL;
12175 struct ether_addr primary_mac;
12179 wl = wlcfg_drv_priv;
12181 if (wl_get_drv_status(wl, AP_CREATING, net)) {
12182 /* Vendor IEs should be set to FW
12183 * after SoftAP interface is brought up
12186 } else if (wl_get_drv_status(wl, AP_CREATED, net)) {
12189 } else if (wl->p2p) {
12190 net = ndev_to_wlc_ndev(net, wl);
12191 if (!wl->p2p->on) {
12192 get_primary_mac(wl, &primary_mac);
12193 wl_cfgp2p_generate_bss_mac(&primary_mac, &wl->p2p->dev_addr,
12194 &wl->p2p->int_addr);
12195 /* In case of p2p_listen command, supplicant send remain_on_channel
12196 * without turning on P2P
12200 ret = wl_cfgp2p_enable_discovery(wl, net, NULL, 0);
12202 if (unlikely(ret)) {
12206 if (net != wl_to_prmry_ndev(wl)) {
12207 if (wl_get_mode_by_netdev(wl, net) == WL_MODE_AP) {
12208 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
12209 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION);
12212 ndev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
12213 bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
12216 if (ndev != NULL) {
12219 pktflag = VNDR_IE_BEACON_FLAG;
12221 case WL_PROBE_RESP:
12222 pktflag = VNDR_IE_PRBRSP_FLAG;
12224 case WL_ASSOC_RESP:
12225 pktflag = VNDR_IE_ASSOCRSP_FLAG;
12229 ret = wl_cfgp2p_set_management_ie(wl, ndev, bssidx, pktflag, buf, len);
12235 #ifdef WL_SUPPORT_AUTO_CHANNEL
12237 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
12240 s32 ret = BCME_ERROR;
12241 struct wl_priv *wl = wlcfg_drv_priv;
12243 /* Disable mpc, to avoid automatic interface down. */
12246 ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
12247 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
12248 &wl->ioctl_buf_sync);
12250 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
12254 /* Set interface up, explicitly. */
12257 ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
12259 WL_ERR(("set interface up failed, error = %d\n", ret));
12263 /* Stop all scan explicitly, till auto channel selection complete. */
12264 wl_set_drv_status(wl, SCANNING, ndev);
12265 ret = wl_notify_escan_complete(wl, ndev, true, true);
12267 WL_ERR(("set scan abort failed, error = %d\n", ret));
12268 ret = BCME_OK; // terence 20140115: fix escan_complete error
12277 wl_cfg80211_valid_chanspec_p2p(chanspec_t chanspec)
12279 bool valid = false;
12281 /* channel 1 to 14 */
12282 if ((chanspec >= 0x2b01) && (chanspec <= 0x2b0e)) {
12285 /* channel 36 to 48 */
12286 else if ((chanspec >= 0x1b24) && (chanspec <= 0x1b30)) {
12289 /* channel 149 to 161 */
12290 else if ((chanspec >= 0x1b95) && (chanspec <= 0x1ba1)) {
12295 WL_INFO(("invalid P2P chanspec, channel = %d, chanspec = %04x\n",
12296 CHSPEC_CHANNEL(chanspec), chanspec));
12303 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
12305 s32 ret = BCME_ERROR;
12306 struct wl_priv *wl = NULL;
12307 wl_uint32_list_t *list = NULL;
12308 chanspec_t chanspec = 0;
12310 memset(buf, 0, buflen);
12312 wl = wlcfg_drv_priv;
12313 list = (wl_uint32_list_t *)buf;
12314 list->count = htod32(WL_NUMCHANSPECS);
12316 /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
12317 chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
12318 WL_CHANSPEC_CTL_SB_NONE);
12319 chanspec = wl_chspec_host_to_driver(chanspec);
12321 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
12322 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
12324 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
12331 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
12334 s32 ret = BCME_ERROR;
12337 struct wl_priv *wl = NULL;
12338 wl_uint32_list_t *list = NULL;
12339 chanspec_t chanspec = 0;
12341 memset(buf, 0, buflen);
12343 wl = wlcfg_drv_priv;
12344 list = (wl_uint32_list_t *)buf;
12345 list->count = htod32(WL_NUMCHANSPECS);
12347 /* Restrict channels to 5GHz, 20MHz BW, no SB. */
12348 chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
12349 WL_CHANSPEC_CTL_SB_NONE);
12350 chanspec = wl_chspec_host_to_driver(chanspec);
12352 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
12353 sizeof(chanspec), buf, buflen, 0, &wl->ioctl_buf_sync);
12355 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
12359 /* Skip DFS and inavlid P2P channel. */
12360 for (i = 0, j = 0; i < dtoh32(list->count); i++) {
12361 chanspec = (chanspec_t) dtoh32(list->element[i]);
12362 channel = CHSPEC_CHANNEL(chanspec);
12364 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
12366 WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
12370 if (CHANNEL_IS_RADAR(channel) ||
12371 !(wl_cfg80211_valid_chanspec_p2p(chanspec))) {
12374 list->element[j] = list->element[i];
12387 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
12390 s32 ret = BCME_ERROR;
12394 /* Start auto channel selection scan. */
12395 ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
12397 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
12402 /* Wait for auto channel selection, worst case possible delay is 5250ms. */
12403 retry = CHAN_SEL_RETRY_COUNT;
12406 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
12408 ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
12410 if ((ret == 0) && (dtoh32(chosen) != 0)) {
12411 if (dhd_bus_chip_id(bcmsdh_get_drvdata()) != BCM43362_CHIP_ID &&
12412 dhd_bus_chip_id(bcmsdh_get_drvdata()) != BCM4330_CHIP_ID) {
12415 chanspec = wl_chspec_driver_to_host(chosen);
12416 printf("selected chanspec = 0x%x\n", chanspec);
12417 ctl_chan = wf_chspec_ctlchan(chanspec);
12418 printf("selected ctl_chan = 0x%x\n", ctl_chan);
12419 *channel = (u16)(ctl_chan & 0x00FF);
12421 *channel = (u16)(chosen & 0x00FF);
12422 WL_INFO(("selected channel = %d\n", *channel));
12425 WL_INFO(("attempt = %d, ret = %d, chosen = %d\n",
12426 (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
12430 WL_ERR(("failure, auto channel selection timed out\n"));
12440 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
12443 s32 ret = BCME_ERROR;
12444 struct wl_priv *wl = wlcfg_drv_priv;
12446 /* Clear scan stop driver status. */
12447 wl_clr_drv_status(wl, SCANNING, ndev);
12449 /* Enable mpc back to 1, irrespective of initial state. */
12452 ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
12453 sizeof(val), wl->ioctl_buf, WLC_IOCTL_SMLEN, 0,
12454 &wl->ioctl_buf_sync);
12456 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
12463 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
12465 int channel = 0, band, band_cur;
12466 s32 ret = BCME_ERROR;
12469 struct wl_priv *wl = NULL;
12470 struct net_device *ndev = NULL;
12472 memset(cmd, 0, total_len);
12474 buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
12476 WL_ERR(("failed to allocate chanspec buffer\n"));
12481 * Always use primary interface, irrespective of interface on which
12484 wl = wlcfg_drv_priv;
12485 ndev = wl_to_prmry_ndev(wl);
12488 * Make sure that FW and driver are in right state to do auto channel
12491 ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
12493 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
12497 /* Best channel selection in 2.4GHz band. */
12498 ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
12500 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
12504 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
12507 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
12511 if (CHANNEL_IS_2G(channel)) {
12512 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
12514 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
12518 sprintf(pos, "%04d ", channel);
12521 // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
12522 ret = wldev_ioctl(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur), false);
12523 band = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
12524 ret = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
12526 WL_ERR(("WLC_SET_BAND error %d\n", ret));
12528 /* Best channel selection in 5GHz band. */
12529 ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
12531 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
12535 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
12538 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
12542 if (CHANNEL_IS_5G(channel)) {
12543 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
12545 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
12549 ret = wldev_ioctl(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur), true);
12551 WL_ERR(("WLC_SET_BAND error %d\n", ret));
12553 sprintf(pos, "%04d ", channel);
12556 /* Set overall best channel same as 5GHz best channel. */
12557 sprintf(pos, "%04d ", channel);
12565 /* Restore FW and driver back to normal state. */
12566 ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
12568 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
12571 printf("%s: channel %s\n", __FUNCTION__, cmd);
12573 return (pos - cmd);
12575 #endif /* WL_SUPPORT_AUTO_CHANNEL */
12577 static const struct rfkill_ops wl_rfkill_ops = {
12578 .set_block = wl_rfkill_set
12581 static int wl_rfkill_set(void *data, bool blocked)
12583 struct wl_priv *wl = (struct wl_priv *)data;
12585 WL_DBG(("Enter \n"));
12586 WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
12591 wl->rf_blocked = blocked;
12596 static int wl_setup_rfkill(struct wl_priv *wl, bool setup)
12600 WL_DBG(("Enter \n"));
12604 wl->rfkill = rfkill_alloc("brcmfmac-wifi",
12605 wl_cfg80211_get_parent_dev(),
12606 RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)wl);
12613 err = rfkill_register(wl->rfkill);
12616 rfkill_destroy(wl->rfkill);
12623 rfkill_unregister(wl->rfkill);
12624 rfkill_destroy(wl->rfkill);
12631 #ifdef DEBUGFS_CFG80211
12633 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
12634 * to turn on SCAN and DBG log.
12635 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
12636 * To see current setting of debug level,
12637 * cat /sys/kernel/debug/dhd/debug_level
12640 wl_debuglevel_write(struct file *file, const char __user *userbuf,
12641 size_t count, loff_t *ppos)
12643 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
12644 char *params, *token, *colon;
12645 uint i, tokens, log_on = 0;
12646 memset(tbuf, 0, sizeof(tbuf));
12647 memset(sublog, 0, sizeof(sublog));
12648 if (copy_from_user(&tbuf, userbuf, min_t(size_t, sizeof(tbuf), count)))
12652 colon = strchr(params, '\n');
12655 while ((token = strsep(¶ms, " ")) != NULL) {
12656 memset(sublog, 0, sizeof(sublog));
12657 if (token == NULL || !*token)
12659 if (*token == '\0')
12661 colon = strchr(token, ':');
12662 if (colon != NULL) {
12665 tokens = sscanf(token, "%s %u", sublog, &log_on);
12670 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
12671 if (!strncmp(sublog, sublogname_map[i].sublogname,
12672 strlen(sublogname_map[i].sublogname))) {
12675 (sublogname_map[i].log_level);
12678 ~(sublogname_map[i].log_level);
12682 WL_ERR(("%s: can't parse '%s' as a "
12683 "SUBMODULE:LEVEL (%d tokens)\n",
12684 tbuf, token, tokens));
12692 wl_debuglevel_read(struct file *file, char __user *user_buf,
12693 size_t count, loff_t *ppos)
12696 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
12698 memset(tbuf, 0, sizeof(tbuf));
12700 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
12701 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
12702 sublogname_map[i].sublogname,
12703 (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
12706 return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
12709 static const struct file_operations fops_debuglevel = {
12711 .write = wl_debuglevel_write,
12712 .read = wl_debuglevel_read,
12713 .owner = THIS_MODULE,
12717 static s32 wl_setup_debugfs(struct wl_priv *wl)
12720 struct dentry *_dentry;
12723 wl->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
12724 if (!wl->debugfs || IS_ERR(wl->debugfs)) {
12725 if (wl->debugfs == ERR_PTR(-ENODEV))
12726 WL_ERR(("Debugfs is not enabled on this kernel\n"));
12728 WL_ERR(("Can not create debugfs directory\n"));
12729 wl->debugfs = NULL;
12733 _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
12734 wl->debugfs, wl, &fops_debuglevel);
12735 if (!_dentry || IS_ERR(_dentry)) {
12736 WL_ERR(("failed to create debug_level debug file\n"));
12737 wl_free_debugfs(wl);
12742 static s32 wl_free_debugfs(struct wl_priv *wl)
12747 debugfs_remove_recursive(wl->debugfs);
12748 wl->debugfs = NULL;
12751 #endif /* DEBUGFS_CFG80211 */
12753 struct device *wl_cfg80211_get_parent_dev(void)
12755 return cfg80211_parent_dev;
12758 void wl_cfg80211_set_parent_dev(void *dev)
12760 cfg80211_parent_dev = dev;
12763 static void wl_cfg80211_clear_parent_dev(void)
12765 cfg80211_parent_dev = NULL;
12768 void get_primary_mac(struct wl_priv *wl, struct ether_addr *mac)
12770 wldev_iovar_getbuf_bsscfg(wl_to_prmry_ndev(wl), "cur_etheraddr", NULL,
12771 0, wl->ioctl_buf, WLC_IOCTL_SMLEN, 0, &wl->ioctl_buf_sync);
12772 memcpy(mac->octet, wl->ioctl_buf, ETHER_ADDR_LEN);
12774 static bool check_dev_role_integrity(struct wl_priv *wl, u32 dev_role)
12776 dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
12777 if (((dev_role == NL80211_IFTYPE_AP) &&
12778 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
12779 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
12780 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
12782 WL_ERR(("device role select failed\n"));
12788 int wl_cfg80211_do_driver_init(struct net_device *net)
12790 struct wl_priv *wl = *(struct wl_priv **)netdev_priv(net);
12792 if (!wl || !wl->wdev)
12795 if (dhd_do_driver_init(wl->wdev->netdev) < 0)
12801 void wl_cfg80211_enable_trace(u32 level)
12803 wl_dbg_level = level;
12804 printk("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level);
12807 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
12810 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
12811 bcm_struct_cfgdev *cfgdev, u64 cookie)
12813 /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
12814 * is passed with CMD_FRAME. This callback is supposed to cancel
12815 * the OFFCHANNEL Wait. Since we are already taking care of that
12816 * with the tx_mgmt logic, do nothing here.
12821 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL >= 3.2.0 */
12825 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len)
12829 while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_INTERWORKING_ID))) {
12830 return (bcm_tlv_t *)ie;
12836 wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s32 pktflag,
12837 uint8 ie_id, uint8 *data, uint8 data_len)
12842 ie_setbuf_t *ie_setbuf;
12844 if (ie_id != DOT11_MNG_INTERWORKING_ID)
12845 return BCME_UNSUPPORTED;
12847 /* Validate the pktflag parameter */
12848 if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
12849 VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
12850 VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
12851 VNDR_IE_CUSTOM_FLAG))) {
12852 WL_ERR(("cfg80211 Add IE: Invalid packet flag 0x%x\n", pktflag));
12856 /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
12857 pktflag = htod32(pktflag);
12859 buf_len = sizeof(ie_setbuf_t) + data_len - 1;
12860 ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL);
12863 WL_ERR(("Error allocating buffer for IE\n"));
12867 if (wl->iw_ie_len == data_len && !memcmp(wl->iw_ie, data, data_len)) {
12868 WL_ERR(("Previous IW IE is equals to current IE\n"));
12873 strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
12874 ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
12876 /* Buffer contains only 1 IE */
12877 iecount = htod32(1);
12878 memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int));
12879 memcpy((void *)&ie_setbuf->ie_buffer.ie_list[0].pktflag, &pktflag, sizeof(uint32));
12881 /* Now, add the IE to the buffer */
12882 ie_setbuf->ie_buffer.ie_list[0].ie_data.id = ie_id;
12884 /* if already set with previous values, delete it first */
12885 if (wl->iw_ie_len != 0) {
12886 WL_DBG(("Different IW_IE was already set. clear first\n"));
12888 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = 0;
12890 err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
12891 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
12893 if (err != BCME_OK)
12897 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
12898 memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len);
12900 err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
12901 wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync);
12903 if (err == BCME_OK) {
12904 memcpy(wl->iw_ie, data, data_len);
12905 wl->iw_ie_len = data_len;
12908 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
12918 #ifdef WL_HOST_BAND_MGMT
12920 wl_cfg80211_set_band(struct net_device *ndev, int band)
12922 struct wl_priv *wl = wlcfg_drv_priv;
12924 char ioctl_buf[50];
12926 if ((band < WLC_BAND_AUTO) || (band > WLC_BAND_2G)) {
12927 WL_ERR(("Invalid band\n"));
12931 if ((ret = wldev_iovar_setbuf(ndev, "roam_band", &band,
12932 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
12933 WL_ERR(("seting roam_band failed code=%d\n", ret));
12937 WL_DBG(("Setting band to %d\n", band));
12938 wl->curr_band = band;
12942 #endif /* WL_HOST_BAND_MGMT */
12944 #if defined(DHCP_SCAN_SUPPRESS)
12945 static void wl_cfg80211_scan_supp_timerfunc(ulong data)
12947 struct wl_priv *wl = (struct wl_priv *)data;
12949 WL_DBG(("Enter \n"));
12950 schedule_work(&wl->wlan_work);
12953 int wl_cfg80211_scan_suppress(struct net_device *dev, int suppress)
12956 struct wireless_dev *wdev;
12957 struct wl_priv *wl;
12958 if (!dev || ((suppress != 0) && (suppress != 1))) {
12962 wdev = ndev_to_wdev(dev);
12967 wl = (struct wl_priv *)wiphy_priv(wdev->wiphy);
12973 if (suppress == wl->scan_suppressed) {
12974 WL_DBG(("No change in scan_suppress state. Ignoring cmd..\n"));
12978 if (timer_pending(&wl->scan_supp_timer))
12979 del_timer_sync(&wl->scan_supp_timer);
12981 if ((ret = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
12982 &suppress, sizeof(int), true)) < 0) {
12983 WL_ERR(("Scan suppress setting failed ret:%d \n", ret));
12985 WL_DBG(("Scan suppress %s \n", suppress ? "Enabled" : "Disabled"));
12986 wl->scan_suppressed = suppress;
12989 /* If scan_suppress is set, Start a timer to monitor it (just incase) */
12990 if (wl->scan_suppressed) {
12992 WL_ERR(("Retry scan_suppress reset at a later time \n"));
12993 mod_timer(&wl->scan_supp_timer,
12994 jiffies + msecs_to_jiffies(WL_SCAN_SUPPRESS_RETRY));
12996 WL_DBG(("Start wlan_timer to clear of scan_suppress \n"));
12997 mod_timer(&wl->scan_supp_timer,
12998 jiffies + msecs_to_jiffies(WL_SCAN_SUPPRESS_TIMEOUT));
13004 #endif /* DHCP_SCAN_SUPPRESS */
13006 static void wl_cfg80211_work_handler(struct work_struct * work)
13008 struct wl_priv *wl = NULL;
13009 struct net_info *iter, *next;
13013 wl = container_of(work, struct wl_priv, pm_enable_work.work);
13014 WL_DBG(("Enter \n"));
13015 if (wl->pm_enable_work_on) {
13016 wl->pm_enable_work_on = false;
13017 for_each_ndev(wl, iter, next) {
13018 if (!wl_get_drv_status(wl, CONNECTED, iter->ndev) ||
13019 (wl_get_mode_by_netdev(wl, iter->ndev) != WL_MODE_BSS))
13022 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
13023 &pm, sizeof(pm), true)) != 0) {
13024 if (err == -ENODEV)
13025 WL_DBG(("%s:netdev not ready\n", iter->ndev->name));
13027 WL_ERR(("%s:error (%d)\n", iter->ndev->name, err));
13029 iter->ndev->ieee80211_ptr->ps = true;
13034 #if defined(DHCP_SCAN_SUPPRESS)
13035 else if (wl->scan_suppressed) {
13036 /* There is pending scan_suppress. Clean it */
13037 WL_ERR(("Clean up from timer after %d msec\n", WL_SCAN_SUPPRESS_TIMEOUT));
13038 wl_cfg80211_scan_suppress(wl_to_prmry_ndev(wl), 0);
13040 #endif /* DHCP_SCAN_SUPPRESS */
13044 wl_get_action_category(void *frame, u32 frame_len)
13047 u8 *ptr = (u8 *)frame;
13049 return DOT11_ACTION_CAT_ERR_MASK;
13050 if (frame_len < DOT11_ACTION_HDR_LEN)
13051 return DOT11_ACTION_CAT_ERR_MASK;
13052 category = ptr[DOT11_ACTION_CAT_OFF];
13053 WL_INFO(("Action Category: %d\n", category));
13058 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
13060 u8 *ptr = (u8 *)frame;
13061 if (frame == NULL || ret_action == NULL)
13063 if (frame_len < DOT11_ACTION_HDR_LEN)
13065 if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
13067 *ret_action = ptr[DOT11_ACTION_ACT_OFF];
13068 WL_INFO(("Public Action : %d\n", *ret_action));
13072 #ifdef POWER_OFF_IN_SUSPEND
13073 static void wl_scan_complete(struct wl_priv *wl)
13075 wl_event_msg_t msg;
13076 WL_TRACE(("In\n"));
13078 if (!(wl->scan_request)) {
13079 WL_ERR(("timer expired but no scan request\n"));
13082 bzero(&msg, sizeof(wl_event_msg_t));
13083 if (wl->escan_on && wl->escan_info.escan_state == WL_ESCAN_STATE_SCANING) {
13084 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
13085 msg.status = hton32(WLC_E_STATUS_SUCCESS);
13087 wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL);
13091 void wl_cfg80211_stop(void)
13093 struct wl_priv *wl;
13095 wl = wlcfg_drv_priv;
13097 WL_TRACE(("In\n"));
13099 wl_scan_complete(wl);
13101 if (wl->btcoex_info && wl->btcoex_info->timer_on) {
13102 wl->btcoex_info->timer_on = 0;
13103 del_timer_sync(&wl->btcoex_info->timer);
13106 if (wl->p2p_supported) {
13107 if (timer_pending(&wl->p2p->listen_timer))
13108 del_timer_sync(&wl->p2p->listen_timer);
13111 del_timer_sync(&wl->scan_timeout);
13113 #if defined(RSSIAVG)
13114 wl_free_rssi_cache(&g_rssi_cache_ctrl);
13115 wl_free_rssi_cache(&g_rssi2_cache_ctrl);
13117 #if defined(BSSCACHE)
13118 wl_free_bss_cache(&g_bss_cache_ctrl);
13119 wl_run_bss_cache_timer(&g_bss_cache_ctrl, 0);
13123 void wl_cfg80211_send_disconnect(void)
13125 struct wl_priv *wl;
13127 wl = wlcfg_drv_priv;
13129 WL_TRACE(("In\n"));
13130 cfg80211_disconnected(wl_to_prmry_ndev(wl), 0, NULL, 0, GFP_KERNEL);
13133 void wl_cfg80211_user_sync(bool lock)
13135 struct wl_priv *wl;
13137 wl = wlcfg_drv_priv;
13139 mutex_lock(&wl->usr_sync);
13141 mutex_unlock(&wl->usr_sync);