2 * Linux cfg80211 driver
4 * Copyright (C) 1999-2017, Broadcom Corporation
6 * Unless you and Broadcom execute a separate written software license
7 * agreement governing use of this software, this software is licensed to you
8 * under the terms of the GNU General Public License version 2 (the "GPL"),
9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the
10 * following added to such license:
12 * As a special exception, the copyright holders of this software give you
13 * permission to link this software with independent modules, and to copy and
14 * distribute the resulting executable under terms of your choice, provided that
15 * you also meet, for each linked independent module, the terms and conditions of
16 * the license of that module. An independent module is a module which is not
17 * derived from this software. The special exception does not apply to any
18 * modifications of the software.
20 * Notwithstanding the above, under no circumstances may you combine this
21 * software in any way with any other Broadcom software provided under a license
22 * other than the GPL, without Broadcom's express prior written consent.
25 * <<Broadcom-WL-IPTag/Open:>>
27 * $Id: wl_cfg80211.c 711110 2017-07-17 04:38:25Z $
33 #include <linux/kernel.h>
35 #include <wlc_types.h>
37 #include <bcmwifi_channels.h>
38 #include <bcmendian.h>
41 #include <linux/if_arp.h>
42 #include <asm/uaccess.h>
45 #include <linux/kernel.h>
46 #include <linux/kthread.h>
47 #include <linux/netdevice.h>
48 #include <linux/sched.h>
49 #include <linux/etherdevice.h>
50 #include <linux/wireless.h>
51 #include <linux/ieee80211.h>
52 #include <linux/wait.h>
53 #include <net/cfg80211.h>
54 #include <net/rtnetlink.h>
57 #include <wldev_common.h>
58 #include <wl_cfg80211.h>
59 #include <wl_cfgp2p.h>
61 #include <wl_android.h>
62 #include <dngl_stats.h>
64 #include <dhd_linux.h>
65 #include <dhd_debug.h>
68 #include <dhd_cfg80211.h>
72 #endif /* PNO_SUPPORT */
73 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
74 #include <wl_cfgvendor.h>
75 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
77 #if !defined(WL_VENDOR_EXT_SUPPORT)
81 #if defined(STAT_REPORT)
82 #include <wl_statreport.h>
83 #endif /* STAT_REPORT */
84 #include <dhd_config.h>
92 #include <dhd_flowring.h>
96 #endif /* RTT_SUPPORT */
100 #ifndef DHD_UNSUPPORT_IF_CNTS
101 #define DHD_SUPPORT_IF_CNTS
102 #endif /* !DHD_UN_SUPPORT_IF_CNTS */
105 #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
107 static struct device
*cfg80211_parent_dev
= NULL
;
108 #ifdef CUSTOMER_HW4_DEBUG
109 u32 wl_dbg_level
= WL_DBG_ERR
| WL_DBG_P2P_ACTION
;
111 u32 wl_dbg_level
= WL_DBG_ERR
;
112 #endif /* CUSTOMER_HW4_DEBUG */
114 #define MAX_WAIT_TIME 1500
116 #define IBSS_IF_NAME "ibss%d"
117 #endif /* WLAIBSS_MCHAN */
120 /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
121 #define DEFAULT_SLEEP_TIME_VSDB 120
122 #define OFF_CHAN_TIME_THRESHOLD_MS 200
123 #define AF_RETRY_DELAY_TIME 40
125 /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
126 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg) \
128 if (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg)) || \
129 wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) { \
130 OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB); \
134 /* if not VSDB, do nothing */
135 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)
138 #ifdef WL_CFG80211_SYNC_GON
139 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) \
140 (wl_get_drv_status_all(cfg, SENDING_ACT_FRM) || \
141 wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN))
143 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) wl_get_drv_status_all(cfg, SENDING_ACT_FRM)
144 #endif /* WL_CFG80211_SYNC_GON */
146 #define DNGL_FUNC(func, parameters) func parameters
149 #define WLAN_EID_SSID 0
150 #define CH_MIN_5G_CHANNEL 34
151 #define CH_MIN_2G_CHANNEL 1
152 #define ACTIVE_SCAN 1
153 #define PASSIVE_SCAN 0
155 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
156 4 && __GNUC_MINOR__ >= 6))
157 #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
158 _Pragma("GCC diagnostic push") \
159 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
160 (entry) = list_first_entry((ptr), type, member); \
161 _Pragma("GCC diagnostic pop") \
163 #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
164 _Pragma("GCC diagnostic push") \
165 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
166 entry = container_of((ptr), type, member); \
167 _Pragma("GCC diagnostic pop") \
170 #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
171 (entry) = list_first_entry((ptr), type, member); \
173 #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
174 entry = container_of((ptr), type, member); \
176 #endif /* STRICT_GCC_WARNINGS */
179 enum rmc_event_type
{
181 RMC_EVENT_LEADER_CHECK_FAIL
183 #endif /* WL_RELMCAST */
186 typedef struct wl_last_event
{
187 uint32 current_time
; /* current tyime */
188 uint32 timestamp
; /* event timestamp */
189 wl_event_msg_t event
; /* Encapsulated event */
191 #endif /* WL_LASTEVT */
193 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
194 * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
195 * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
196 * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
197 * All the chnages in world regulatory domain are to be done here.
199 * this definition reuires disabling missing-field-initializer warning
200 * as the ieee80211_regdomain definition differs in plain linux and in Android
202 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
203 4 && __GNUC_MINOR__ >= 6))
204 _Pragma("GCC diagnostic push")
205 _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
207 static const struct ieee80211_regdomain brcm_regdom
= {
211 /* IEEE 802.11b/g, channels 1..11 */
212 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
214 /* IEEE 802.11 channel 14 - Only JP enables
215 * this and for 802.11b only
217 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
218 /* IEEE 802.11a, channel 36..64 */
219 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
220 /* IEEE 802.11a, channel 100..165 */
221 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
223 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
224 4 && __GNUC_MINOR__ >= 6))
225 _Pragma("GCC diagnostic pop")
229 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
230 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
231 static const struct ieee80211_iface_limit common_if_limits
[] = {
234 * Driver can support up to 2 AP's
237 .types
= BIT(NL80211_IFTYPE_AP
),
241 * During P2P-GO removal, P2P-GO is first changed to STA and later only
242 * removed. So setting maximum possible number of STA interfaces according
245 * less than linux-3.8 - max:3 (wlan0 + p2p0 + group removal of p2p-p2p0-x)
246 * linux-3.8 and above - max:2 (wlan0 + group removal of p2p-wlan0-x)
248 #ifdef WL_ENABLE_P2P_IF
252 #endif /* WL_ENABLE_P2P_IF */
253 .types
= BIT(NL80211_IFTYPE_STATION
),
257 .types
= BIT(NL80211_IFTYPE_P2P_GO
) | BIT(NL80211_IFTYPE_P2P_CLIENT
),
259 #if defined(WL_CFG80211_P2P_DEV_IF)
262 .types
= BIT(NL80211_IFTYPE_P2P_DEVICE
),
264 #endif /* WL_CFG80211_P2P_DEV_IF */
267 .types
= BIT(NL80211_IFTYPE_ADHOC
),
271 #define NUM_DIFF_CHANNELS 1
273 #define NUM_DIFF_CHANNELS 2
275 static const struct ieee80211_iface_combination
276 common_iface_combinations
[] = {
278 .num_different_channels
= NUM_DIFF_CHANNELS
,
281 * The max no of interfaces will be used in dual p2p case.
282 * {STA, P2P Device, P2P Group 1, P2P Group 2}. Though we
283 * will not be using the STA functionality in this case, it
284 * will remain registered as it is the primary interface.
287 .limits
= common_if_limits
,
288 .n_limits
= ARRAY_SIZE(common_if_limits
),
291 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
293 /* Data Element Definitions */
294 #define WPS_ID_CONFIG_METHODS 0x1008
295 #define WPS_ID_REQ_TYPE 0x103A
296 #define WPS_ID_DEVICE_NAME 0x1011
297 #define WPS_ID_VERSION 0x104A
298 #define WPS_ID_DEVICE_PWD_ID 0x1012
299 #define WPS_ID_REQ_DEV_TYPE 0x106A
300 #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
301 #define WPS_ID_PRIM_DEV_TYPE 0x1054
303 /* Device Password ID */
304 #define DEV_PW_DEFAULT 0x0000
305 #define DEV_PW_USER_SPECIFIED 0x0001,
306 #define DEV_PW_MACHINE_SPECIFIED 0x0002
307 #define DEV_PW_REKEY 0x0003
308 #define DEV_PW_PUSHBUTTON 0x0004
309 #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
312 #define WPS_CONFIG_USBA 0x0001
313 #define WPS_CONFIG_ETHERNET 0x0002
314 #define WPS_CONFIG_LABEL 0x0004
315 #define WPS_CONFIG_DISPLAY 0x0008
316 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
317 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
318 #define WPS_CONFIG_NFC_INTERFACE 0x0040
319 #define WPS_CONFIG_PUSHBUTTON 0x0080
320 #define WPS_CONFIG_KEYPAD 0x0100
321 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
322 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
323 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
324 #define WPS_CONFIG_PHY_DISPLAY 0x4008
330 #define WL_AKM_SUITE_SHA256_1X 0x000FAC05
331 #define WL_AKM_SUITE_SHA256_PSK 0x000FAC06
333 #ifndef IBSS_COALESCE_ALLOWED
334 #define IBSS_COALESCE_ALLOWED IBSS_COALESCE_DEFAULT
337 #ifndef IBSS_INITIAL_SCAN_ALLOWED
338 #define IBSS_INITIAL_SCAN_ALLOWED IBSS_INITIAL_SCAN_ALLOWED_DEFAULT
341 #define CUSTOM_RETRY_MASK 0xff000000 /* Mask for retry counter of custom dwell time */
342 #define LONG_LISTEN_TIME 2000
345 #define CMD_WBTEXT_PROFILE_CONFIG "WBTEXT_PROFILE_CONFIG"
346 #define CMD_WBTEXT_WEIGHT_CONFIG "WBTEXT_WEIGHT_CONFIG"
347 #define CMD_WBTEXT_TABLE_CONFIG "WBTEXT_TABLE_CONFIG"
348 #define CMD_WBTEXT_DELTA_CONFIG "WBTEXT_DELTA_CONFIG"
349 #define DEFAULT_WBTEXT_PROFILE_A "a -70 -75 70 10 -75 -128 0 10"
350 #define DEFAULT_WBTEXT_PROFILE_B "b -60 -75 70 10 -75 -128 0 10"
351 #define DEFAULT_WBTEXT_WEIGHT_RSSI_A "RSSI a 65"
352 #define DEFAULT_WBTEXT_WEIGHT_RSSI_B "RSSI b 65"
353 #define DEFAULT_WBTEXT_WEIGHT_CU_A "CU a 35"
354 #define DEFAULT_WBTEXT_WEIGHT_CU_B "CU b 35"
355 #define DEFAULT_WBTEXT_TABLE_RSSI_A "RSSI a 0 55 100 55 60 90 \
356 60 65 70 65 70 50 70 128 20"
357 #define DEFAULT_WBTEXT_TABLE_RSSI_B "RSSI b 0 55 100 55 60 90 \
358 60 65 70 65 70 50 70 128 20"
359 #define DEFAULT_WBTEXT_TABLE_CU_A "CU a 0 30 100 30 50 90 \
360 50 60 70 60 80 50 80 100 20"
361 #define DEFAULT_WBTEXT_TABLE_CU_B "CU b 0 10 100 10 25 90 \
362 25 40 70 40 70 50 70 100 20"
364 typedef struct wl_wbtext_bssid
{
365 struct ether_addr ea
;
366 struct list_head list
;
369 static void wl_cfg80211_wbtext_update_rcc(struct bcm_cfg80211
*cfg
, struct net_device
*dev
);
370 static bool wl_cfg80211_wbtext_check_bssid_list(struct bcm_cfg80211
*cfg
, struct ether_addr
*ea
);
371 static bool wl_cfg80211_wbtext_add_bssid_list(struct bcm_cfg80211
*cfg
, struct ether_addr
*ea
);
372 static void wl_cfg80211_wbtext_clear_bssid_list(struct bcm_cfg80211
*cfg
);
373 static bool wl_cfg80211_wbtext_send_nbr_req(struct bcm_cfg80211
*cfg
, struct net_device
*dev
,
374 struct wl_profile
*profile
);
375 static bool wl_cfg80211_wbtext_send_btm_query(struct bcm_cfg80211
*cfg
, struct net_device
*dev
,
376 struct wl_profile
*profile
);
377 static void wl_cfg80211_wbtext_set_wnm_maxidle(struct bcm_cfg80211
*cfg
, struct net_device
*dev
);
378 static int wl_cfg80211_recv_nbr_resp(struct net_device
*dev
, uint8
*body
, int body_len
);
381 #ifdef SUPPORT_AP_RADIO_PWRSAVE
382 #define RADIO_PWRSAVE_PPS 10
383 #define RADIO_PWRSAVE_QUIET_TIME 10
384 #define RADIO_PWRSAVE_LEVEL 3
385 #define RADIO_PWRSAVE_STAS_ASSOC_CHECK 0
387 #define RADIO_PWRSAVE_LEVEL_MIN 1
388 #define RADIO_PWRSAVE_LEVEL_MAX 5
389 #define RADIO_PWRSAVE_PPS_MIN 1
390 #define RADIO_PWRSAVE_QUIETTIME_MIN 1
391 #define RADIO_PWRSAVE_ASSOCCHECK_MIN 0
392 #define RADIO_PWRSAVE_ASSOCCHECK_MAX 1
394 #define RADIO_PWRSAVE_MAJOR_VER 1
395 #define RADIO_PWRSAVE_MINOR_VER 0
396 #define RADIO_PWRSAVE_MAJOR_VER_SHIFT 8
397 #define RADIO_PWRSAVE_VERSION \
398 ((RADIO_PWRSAVE_MAJOR_VER << RADIO_PWRSAVE_MAJOR_VER_SHIFT)| RADIO_PWRSAVE_MINOR_VER)
399 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
401 #ifdef WLADPS_SEAK_AP_WAR
402 #define ATHEROS_OUI "\x00\x03\x7F"
403 #define CAMEO_MAC_PREFIX "\x00\x18\xE7"
404 #define MAC_PREFIX_LEN 3
406 wl_find_vndr_ies_specific_vender(struct bcm_cfg80211
*cfg
,
407 struct net_device
*ndev
, const u8
*vndr_oui
);
408 static s32
wl_set_adps_mode(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, uint8 enable_mode
);
409 #endif /* WLADPS_SEAK_AP_WAR */
411 #define MAX_VNDR_OUI_STR_LEN 256
412 #define VNDR_OUI_STR_LEN 10
413 static const uchar
*exclude_vndr_oui_list
[] = {
414 "\x00\x50\xf2", /* Microsoft */
415 "\x00\x00\xf0", /* Samsung Elec */
420 typedef struct wl_vndr_oui_entry
{
421 uchar oui
[DOT11_OUI_LEN
];
422 struct list_head list
;
423 } wl_vndr_oui_entry_t
;
425 static int wl_vndr_ies_get_vendor_oui(struct bcm_cfg80211
*cfg
,
426 struct net_device
*ndev
, char *vndr_oui
, u32 vndr_oui_len
);
427 static void wl_vndr_ies_clear_vendor_oui_list(struct bcm_cfg80211
*cfg
);
430 * cfg80211_ops api/callback list
432 static s32
wl_frame_get_mgmt(u16 fc
, const struct ether_addr
*da
,
433 const struct ether_addr
*sa
, const struct ether_addr
*bssid
,
434 u8
**pheader
, u32
*body_len
, u8
*pbody
);
435 static s32
__wl_cfg80211_scan(struct wiphy
*wiphy
, struct net_device
*ndev
,
436 struct cfg80211_scan_request
*request
,
437 struct cfg80211_ssid
*this_ssid
);
438 #if defined(WL_CFG80211_P2P_DEV_IF)
440 wl_cfg80211_scan(struct wiphy
*wiphy
, struct cfg80211_scan_request
*request
);
443 wl_cfg80211_scan(struct wiphy
*wiphy
, struct net_device
*ndev
,
444 struct cfg80211_scan_request
*request
);
445 #endif /* WL_CFG80211_P2P_DEV_IF */
446 static s32
wl_cfg80211_set_wiphy_params(struct wiphy
*wiphy
, u32 changed
);
448 static bcm_struct_cfgdev
* bcm_cfg80211_add_ibss_if(struct wiphy
*wiphy
, char *name
);
449 static s32
bcm_cfg80211_del_ibss_if(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
);
450 #endif /* WLAIBSS_MCHAN */
451 static s32
wl_cfg80211_join_ibss(struct wiphy
*wiphy
, struct net_device
*dev
,
452 struct cfg80211_ibss_params
*params
);
453 static s32
wl_cfg80211_leave_ibss(struct wiphy
*wiphy
,
454 struct net_device
*dev
);
455 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
456 static s32
wl_cfg80211_get_station(struct wiphy
*wiphy
,
457 struct net_device
*dev
, const u8
*mac
,
458 struct station_info
*sinfo
);
460 static s32
wl_cfg80211_get_station(struct wiphy
*wiphy
,
461 struct net_device
*dev
, u8
*mac
,
462 struct station_info
*sinfo
);
464 static s32
wl_cfg80211_set_power_mgmt(struct wiphy
*wiphy
,
465 struct net_device
*dev
, bool enabled
,
467 static int wl_cfg80211_connect(struct wiphy
*wiphy
, struct net_device
*dev
,
468 struct cfg80211_connect_params
*sme
);
469 static s32
wl_cfg80211_disconnect(struct wiphy
*wiphy
, struct net_device
*dev
,
471 #if defined(WL_CFG80211_P2P_DEV_IF)
473 wl_cfg80211_set_tx_power(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
474 enum nl80211_tx_power_setting type
, s32 mbm
);
477 wl_cfg80211_set_tx_power(struct wiphy
*wiphy
,
478 enum nl80211_tx_power_setting type
, s32 dbm
);
479 #endif /* WL_CFG80211_P2P_DEV_IF */
480 #if defined(WL_CFG80211_P2P_DEV_IF)
481 static s32
wl_cfg80211_get_tx_power(struct wiphy
*wiphy
,
482 struct wireless_dev
*wdev
, s32
*dbm
);
484 static s32
wl_cfg80211_get_tx_power(struct wiphy
*wiphy
, s32
*dbm
);
485 #endif /* WL_CFG80211_P2P_DEV_IF */
486 static s32
wl_cfg80211_config_default_key(struct wiphy
*wiphy
,
487 struct net_device
*dev
,
488 u8 key_idx
, bool unicast
, bool multicast
);
489 static s32
wl_cfg80211_add_key(struct wiphy
*wiphy
, struct net_device
*dev
,
490 u8 key_idx
, bool pairwise
, const u8
*mac_addr
,
491 struct key_params
*params
);
492 static s32
wl_cfg80211_del_key(struct wiphy
*wiphy
, struct net_device
*dev
,
493 u8 key_idx
, bool pairwise
, const u8
*mac_addr
);
494 static s32
wl_cfg80211_get_key(struct wiphy
*wiphy
, struct net_device
*dev
,
495 u8 key_idx
, bool pairwise
, const u8
*mac_addr
,
496 void *cookie
, void (*callback
) (void *cookie
,
497 struct key_params
*params
));
498 static s32
wl_cfg80211_config_default_mgmt_key(struct wiphy
*wiphy
,
499 struct net_device
*dev
, u8 key_idx
);
500 static s32
wl_cfg80211_resume(struct wiphy
*wiphy
);
501 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
503 static s32
wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy
*wiphy
,
504 bcm_struct_cfgdev
*cfgdev
, u64 cookie
);
505 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
506 static s32
wl_cfg80211_del_station(
507 struct wiphy
*wiphy
, struct net_device
*ndev
,
508 struct station_del_parameters
*params
);
509 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
510 static s32
wl_cfg80211_del_station(struct wiphy
*wiphy
,
511 struct net_device
*ndev
, const u8
* mac_addr
);
513 static s32
wl_cfg80211_del_station(struct wiphy
*wiphy
,
514 struct net_device
*ndev
, u8
* mac_addr
);
517 static s32
wl_cfg80211_join_mesh(
518 struct wiphy
*wiphy
, struct net_device
*dev
,
519 const struct mesh_config
*conf
,
520 const struct mesh_setup
*setup
);
521 static s32
wl_cfg80211_leave_mesh(struct wiphy
*wiphy
,
522 struct net_device
*dev
);
524 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
525 static s32
wl_cfg80211_change_station(struct wiphy
*wiphy
,
526 struct net_device
*dev
, const u8
*mac
, struct station_parameters
*params
);
528 static s32
wl_cfg80211_change_station(struct wiphy
*wiphy
,
529 struct net_device
*dev
, u8
*mac
, struct station_parameters
*params
);
531 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
532 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
533 static s32
wl_cfg80211_suspend(struct wiphy
*wiphy
, struct cfg80211_wowlan
*wow
);
535 static s32
wl_cfg80211_suspend(struct wiphy
*wiphy
);
537 static s32
wl_cfg80211_set_pmksa(struct wiphy
*wiphy
, struct net_device
*dev
,
538 struct cfg80211_pmksa
*pmksa
);
539 static s32
wl_cfg80211_del_pmksa(struct wiphy
*wiphy
, struct net_device
*dev
,
540 struct cfg80211_pmksa
*pmksa
);
541 static s32
wl_cfg80211_flush_pmksa(struct wiphy
*wiphy
,
542 struct net_device
*dev
);
543 void wl_cfg80211_scan_abort(struct bcm_cfg80211
*cfg
);
544 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211
*cfg
);
545 static s32
wl_notify_escan_complete(struct bcm_cfg80211
*cfg
,
546 struct net_device
*ndev
, bool aborted
, bool fw_abort
);
547 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
548 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
549 KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
550 static s32
wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
551 u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
552 u32 peer_capability
, const u8
*buf
, size_t len
);
553 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
554 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
555 static s32
wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
556 const u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
557 u32 peer_capability
, const u8
*buf
, size_t len
);
558 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
559 static s32
wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
560 const u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
561 u32 peer_capability
, bool initiator
, const u8
*buf
, size_t len
);
562 #else /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
563 static s32
wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
564 u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
565 const u8
*buf
, size_t len
);
566 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
567 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
568 static s32
wl_cfg80211_tdls_oper(struct wiphy
*wiphy
, struct net_device
*dev
,
569 const u8
*peer
, enum nl80211_tdls_operation oper
);
571 static s32
wl_cfg80211_tdls_oper(struct wiphy
*wiphy
, struct net_device
*dev
,
572 u8
*peer
, enum nl80211_tdls_operation oper
);
576 static int wl_cfg80211_sched_scan_stop(struct wiphy
*wiphy
, struct net_device
*dev
577 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
579 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
582 static s32
wl_cfg80211_set_ap_role(struct bcm_cfg80211
*cfg
, struct net_device
*dev
);
583 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
585 wl_cfg80211_create_iface(struct wiphy
*wiphy
, enum nl80211_iftype
586 iface_type
, u8
*mac_addr
, const char *name
);
588 wl_cfg80211_del_iface(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
);
589 #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
591 s32
wl_cfg80211_interface_ops(struct bcm_cfg80211
*cfg
,
592 struct net_device
*ndev
, s32 bsscfg_idx
,
593 enum nl80211_iftype iface_type
, s32 del
, u8
*addr
);
594 s32
wl_cfg80211_add_del_bss(struct bcm_cfg80211
*cfg
,
595 struct net_device
*ndev
, s32 bsscfg_idx
,
596 enum nl80211_iftype iface_type
, s32 del
, u8
*addr
);
597 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
598 static s32
wl_cfg80211_stop_ap(struct wiphy
*wiphy
, struct net_device
*dev
);
599 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */
600 #ifdef GTK_OFFLOAD_SUPPORT
601 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
602 static s32
wl_cfg80211_set_rekey_data(struct wiphy
*wiphy
, struct net_device
*dev
,
603 struct cfg80211_gtk_rekey_data
*data
);
604 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
605 #endif /* GTK_OFFLOAD_SUPPORT */
606 chanspec_t
wl_chspec_driver_to_host(chanspec_t chanspec
);
607 chanspec_t
wl_chspec_host_to_driver(chanspec_t chanspec
);
609 static s32
wl_cfg80211_get_ulb_bw(struct bcm_cfg80211
*cfg
, struct wireless_dev
*wdev
);
610 static chanspec_t
wl_cfg80211_ulb_get_min_bw_chspec(struct bcm_cfg80211
*cfg
,
611 struct wireless_dev
*wdev
, s32 bssidx
);
612 static s32
wl_cfg80211_ulbbw_to_ulbchspec(u32 ulb_bw
);
614 static inline chanspec_t
wl_cfg80211_ulb_get_min_bw_chspec(
615 struct bcm_cfg80211
*cfg
, struct wireless_dev
*wdev
, s32 bssidx
)
617 return WL_CHANSPEC_BW_20
;
620 static void wl_cfg80211_wait_for_disconnection(struct bcm_cfg80211
*cfg
, struct net_device
*dev
);
623 * event & event Q handlers for cfg80211 interfaces
625 static s32
wl_create_event_handler(struct bcm_cfg80211
*cfg
);
626 static void wl_destroy_event_handler(struct bcm_cfg80211
*cfg
);
627 static void wl_event_handler(struct work_struct
*work_data
);
628 static void wl_init_eq(struct bcm_cfg80211
*cfg
);
629 static void wl_flush_eq(struct bcm_cfg80211
*cfg
);
630 static unsigned long wl_lock_eq(struct bcm_cfg80211
*cfg
);
631 static void wl_unlock_eq(struct bcm_cfg80211
*cfg
, unsigned long flags
);
632 static void wl_init_eq_lock(struct bcm_cfg80211
*cfg
);
633 static void wl_init_event_handler(struct bcm_cfg80211
*cfg
);
634 static struct wl_event_q
*wl_deq_event(struct bcm_cfg80211
*cfg
);
635 static s32
wl_enq_event(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, u32 type
,
636 const wl_event_msg_t
*msg
, void *data
);
637 static void wl_put_event(struct wl_event_q
*e
);
638 static s32
wl_notify_connect_status_ap(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
639 const wl_event_msg_t
*e
, void *data
);
640 static s32
wl_notify_connect_status(struct bcm_cfg80211
*cfg
,
641 bcm_struct_cfgdev
*cfgdev
, const wl_event_msg_t
*e
, void *data
);
642 static s32
wl_notify_roaming_status(struct bcm_cfg80211
*cfg
,
643 bcm_struct_cfgdev
*cfgdev
, const wl_event_msg_t
*e
, void *data
);
644 static s32
wl_notify_scan_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
645 const wl_event_msg_t
*e
, void *data
);
646 static s32
wl_bss_connect_done(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
647 const wl_event_msg_t
*e
, void *data
, bool completed
);
648 static s32
wl_bss_roaming_done(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
649 const wl_event_msg_t
*e
, void *data
);
650 static s32
wl_notify_mic_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
651 const wl_event_msg_t
*e
, void *data
);
652 #ifdef BT_WIFI_HANDOVER
653 static s32
wl_notify_bt_wifi_handover_req(struct bcm_cfg80211
*cfg
,
654 bcm_struct_cfgdev
*cfgdev
, const wl_event_msg_t
*e
, void *data
);
655 #endif /* BT_WIFI_HANDOVER */
658 wl_notify_sched_scan_results(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
659 const wl_event_msg_t
*e
, void *data
);
660 #endif /* WL_SCHED_SCAN */
662 static s32
wl_notify_pfn_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
663 const wl_event_msg_t
*e
, void *data
);
664 #endif /* PNO_SUPPORT */
666 static s32
wl_notify_gscan_event(struct bcm_cfg80211
*wl
, bcm_struct_cfgdev
*cfgdev
,
667 const wl_event_msg_t
*e
, void *data
);
668 static s32
wl_handle_roam_exp_event(struct bcm_cfg80211
*wl
, bcm_struct_cfgdev
*cfgdev
,
669 const wl_event_msg_t
*e
, void *data
);
670 #endif /* GSCAN_SUPPORT */
671 #ifdef RSSI_MONITOR_SUPPORT
672 static s32
wl_handle_rssi_monitor_event(struct bcm_cfg80211
*wl
, bcm_struct_cfgdev
*cfgdev
,
673 const wl_event_msg_t
*e
, void *data
);
674 #endif /* RSSI_MONITOR_SUPPORT */
675 static s32
wl_notifier_change_state(struct bcm_cfg80211
*cfg
, struct net_info
*_net_info
,
676 enum wl_status state
, bool set
);
677 #ifdef CUSTOM_EVENT_PM_WAKE
678 static s32
wl_check_pmstatus(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
679 const wl_event_msg_t
*e
, void *data
);
680 #endif /* CUSTOM_EVENT_PM_WAKE */
681 #ifdef ENABLE_TEMP_THROTTLING
682 static s32
wl_check_rx_throttle_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
683 const wl_event_msg_t
*e
, void *data
);
684 #endif /* ENABLE_TEMP_THROTTLING */
685 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
686 static s32
wl_notify_roam_prep_status(struct bcm_cfg80211
*cfg
,
687 bcm_struct_cfgdev
*cfgdev
, const wl_event_msg_t
*e
, void *data
);
688 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
689 #ifdef DHD_LOSSLESS_ROAMING
690 static void wl_del_roam_timeout(struct bcm_cfg80211
*cfg
);
691 #endif /* DHD_LOSSLESS_ROAMING */
694 static s32
wl_cfg80211_tdls_config(struct bcm_cfg80211
*cfg
,
695 enum wl_tdls_config state
, bool tdls_mode
);
696 static s32
wl_tdls_event_handler(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
697 const wl_event_msg_t
*e
, void *data
);
700 * register/deregister parent device
702 static void wl_cfg80211_clear_parent_dev(void);
708 * cfg80211 set_wiphy_params utilities
710 static s32
wl_set_frag(struct net_device
*dev
, u32 frag_threshold
);
711 static s32
wl_set_rts(struct net_device
*dev
, u32 frag_threshold
);
712 static s32
wl_set_retry(struct net_device
*dev
, u32 retry
, bool l
);
715 * cfg profile utilities
717 static s32
wl_update_prof(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
718 const wl_event_msg_t
*e
, const void *data
, s32 item
);
719 static void *wl_read_prof(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 item
);
720 static void wl_init_prof(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
);
723 * cfg80211 connect utilites
725 static s32
wl_set_wpa_version(struct net_device
*dev
,
726 struct cfg80211_connect_params
*sme
);
727 static s32
wl_set_auth_type(struct net_device
*dev
,
728 struct cfg80211_connect_params
*sme
);
729 static s32
wl_set_set_cipher(struct net_device
*dev
,
730 struct cfg80211_connect_params
*sme
);
731 static s32
wl_set_key_mgmt(struct net_device
*dev
,
732 struct cfg80211_connect_params
*sme
);
733 static s32
wl_set_set_sharedkey(struct net_device
*dev
,
734 struct cfg80211_connect_params
*sme
);
735 static s32
wl_get_assoc_ies(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
);
736 static s32
wl_ch_to_chanspec(struct net_device
*dev
, int ch
,
737 struct wl_join_params
*join_params
, size_t *join_params_size
);
738 void wl_cfg80211_clear_security(struct bcm_cfg80211
*cfg
);
741 * information element utilities
743 static void wl_rst_ie(struct bcm_cfg80211
*cfg
);
744 static __used s32
wl_add_ie(struct bcm_cfg80211
*cfg
, u8 t
, u8 l
, u8
*v
);
745 static void wl_update_hidden_ap_ie(struct wl_bss_info
*bi
, const u8
*ie_stream
, u32
*ie_size
,
747 static s32
wl_mrg_ie(struct bcm_cfg80211
*cfg
, u8
*ie_stream
, u16 ie_size
);
748 static s32
wl_cp_ie(struct bcm_cfg80211
*cfg
, u8
*dst
, u16 dst_size
);
749 static u32
wl_get_ielen(struct bcm_cfg80211
*cfg
);
751 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t
*wpa2ie
, u8
** rsn_cap
);
756 wl_cfg80211_find_interworking_ie(const u8
*parse
, u32 len
);
758 wl_cfg80211_clear_iw_ie(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 bssidx
);
760 wl_cfg80211_add_iw_ie(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 bssidx
, s32 pktflag
,
761 uint8 ie_id
, uint8
*data
, uint8 data_len
);
764 static s32
wl_setup_wiphy(struct wireless_dev
*wdev
, struct device
*dev
, dhd_pub_t
*data
);
765 static void wl_free_wdev(struct bcm_cfg80211
*cfg
);
766 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
767 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
771 #endif /* kernel version < 3.10.11 */
772 wl_cfg80211_reg_notifier(struct wiphy
*wiphy
, struct regulatory_request
*request
);
773 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
775 static s32
wl_inform_bss(struct bcm_cfg80211
*cfg
);
776 static s32
wl_inform_single_bss(struct bcm_cfg80211
*cfg
, struct wl_bss_info
*bi
, bool roam
);
777 static s32
wl_update_bss_info(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, bool roam
);
778 static chanspec_t
wl_cfg80211_get_shared_freq(struct wiphy
*wiphy
);
779 s32
wl_cfg80211_channel_to_freq(u32 channel
);
782 static void wl_cfg80211_work_handler(struct work_struct
*work
);
783 static s32
wl_add_keyext(struct wiphy
*wiphy
, struct net_device
*dev
,
784 u8 key_idx
, const u8
*mac_addr
,
785 struct key_params
*params
);
787 * key indianess swap utilities
789 static void swap_key_from_BE(struct wl_wsec_key
*key
);
790 static void swap_key_to_BE(struct wl_wsec_key
*key
);
793 * bcm_cfg80211 memory init/deinit utilities
795 static s32
wl_init_priv_mem(struct bcm_cfg80211
*cfg
);
796 static void wl_deinit_priv_mem(struct bcm_cfg80211
*cfg
);
798 static void wl_delay(u32 ms
);
801 * ibss mode utilities
803 static bool wl_is_ibssmode(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
);
804 static __used
bool wl_is_ibssstarter(struct bcm_cfg80211
*cfg
);
807 * link up/down , default configuration utilities
809 static s32
__wl_cfg80211_up(struct bcm_cfg80211
*cfg
);
810 static s32
__wl_cfg80211_down(struct bcm_cfg80211
*cfg
);
813 static bool wl_is_linkdown(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
, void *data
);
814 #define WL_IS_LINKDOWN(cfg, e, data) wl_is_linkdown(cfg, e, data)
816 static bool wl_is_linkdown(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
);
817 #define WL_IS_LINKDOWN(cfg, e, data) wl_is_linkdown(cfg, e)
818 #endif /* WL_LASTEVT */
820 static bool wl_is_linkup(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
,
821 struct net_device
*ndev
);
822 static bool wl_is_nonetwork(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
);
823 static void wl_link_up(struct bcm_cfg80211
*cfg
);
824 static void wl_link_down(struct bcm_cfg80211
*cfg
);
825 static s32
wl_config_ifmode(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 iftype
);
826 static void wl_init_conf(struct wl_conf
*conf
);
827 static s32
wl_cfg80211_handle_ifdel(struct bcm_cfg80211
*cfg
, wl_if_event_info
*if_event_info
,
828 struct net_device
* ndev
);
829 int wl_cfg80211_get_ioctl_version(void);
832 * find most significant bit set
834 static __used u32
wl_find_msb(u16 bit16
);
839 static int wl_setup_rfkill(struct bcm_cfg80211
*cfg
, bool setup
);
840 static int wl_rfkill_set(void *data
, bool blocked
);
841 #ifdef DEBUGFS_CFG80211
842 static s32
wl_setup_debugfs(struct bcm_cfg80211
*cfg
);
843 static s32
wl_free_debugfs(struct bcm_cfg80211
*cfg
);
845 static wl_scan_params_t
*wl_cfg80211_scan_alloc_params(struct bcm_cfg80211
*cfg
,
846 int channel
, int nprobes
, int *out_params_size
);
847 static bool check_dev_role_integrity(struct bcm_cfg80211
*cfg
, u32 dev_role
);
849 #ifdef WL_CFG80211_ACL
851 static int wl_cfg80211_set_mac_acl(struct wiphy
*wiphy
, struct net_device
*cfgdev
,
852 const struct cfg80211_acl_data
*acl
);
853 #endif /* WL_CFG80211_ACL */
856 * Some external functions, TODO: move them to dhd_linux.h
858 int dhd_add_monitor(const char *name
, struct net_device
**new_ndev
);
859 int dhd_del_monitor(struct net_device
*ndev
);
860 int dhd_monitor_init(void *dhd_pub
);
861 int dhd_monitor_uninit(void);
862 int dhd_start_xmit(struct sk_buff
*skb
, struct net_device
*net
);
865 #ifdef P2P_LISTEN_OFFLOADING
866 s32
wl_cfg80211_p2plo_deinit(struct bcm_cfg80211
*cfg
);
867 #endif /* P2P_LISTEN_OFFLOADING */
869 #ifdef PKT_FILTER_SUPPORT
870 extern uint dhd_pkt_filter_enable
;
871 extern uint dhd_master_mode
;
872 extern void dhd_pktfilter_offload_enable(dhd_pub_t
* dhd
, char *arg
, int enable
, int master_mode
);
873 #endif /* PKT_FILTER_SUPPORT */
875 #ifdef SUPPORT_SET_CAC
876 static void wl_cfg80211_set_cac(struct bcm_cfg80211
*cfg
, int enable
);
877 #endif /* SUPPORT_SET_CAC */
879 static int wl_cfg80211_delayed_roam(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
880 const struct ether_addr
*bssid
);
881 static s32
__wl_update_wiphybands(struct bcm_cfg80211
*cfg
, bool notify
);
883 static int bw2cap
[] = { 0, 0, WLC_BW_CAP_20MHZ
, WLC_BW_CAP_40MHZ
, WLC_BW_CAP_80MHZ
,
884 WLC_BW_CAP_160MHZ
, WLC_BW_CAP_160MHZ
};
886 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) || (defined(CONFIG_ARCH_MSM) && \
887 defined(CFG80211_DISCONNECTED_V2))
888 #define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
889 cfg80211_disconnected(dev, reason, ie, len, loc_gen, gfp);
890 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
891 #define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
892 cfg80211_disconnected(dev, reason, ie, len, gfp);
893 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) */
895 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || (defined(CONFIG_ARCH_MSM) && \
896 defined(CFG80211_DISCONNECTED_V2))
897 #define CFG80211_GET_BSS(wiphy, channel, bssid, ssid, ssid_len) \
898 cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, \
899 IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
901 #define CFG80211_GET_BSS(wiphy, channel, bssid, ssid, ssid_len) \
902 cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, \
903 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
904 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
906 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \
907 (akm) == RSN_AKM_UNSPECIFIED || \
908 (akm) == RSN_AKM_PSK)
911 extern int dhd_wait_pend8021x(struct net_device
*dev
);
912 #ifdef PROP_TXSTATUS_VSDB
913 extern int disable_proptx
;
914 #endif /* PROP_TXSTATUS_VSDB */
915 static int wl_cfg80211_check_in4way(struct bcm_cfg80211
*cfg
,
916 struct net_device
*dev
, uint action
, enum wl_ext_status status
, void *context
);
919 extern int passive_channel_skip
;
922 wl_ap_start_ind(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
923 const wl_event_msg_t
*e
, void *data
);
925 wl_csa_complete_ind(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
926 const wl_event_msg_t
*e
, void *data
);
927 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, \
935 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
936 #define CFG80211_PUT_BSS(wiphy, bss) cfg80211_put_bss(wiphy, bss);
938 #define CFG80211_PUT_BSS(wiphy, bss) cfg80211_put_bss(bss);
939 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
941 #define CHAN2G(_channel, _freq, _flags) { \
942 .band = IEEE80211_BAND_2GHZ, \
943 .center_freq = (_freq), \
944 .hw_value = (_channel), \
946 .max_antenna_gain = 0, \
950 #define CHAN5G(_channel, _flags) { \
951 .band = IEEE80211_BAND_5GHZ, \
952 .center_freq = 5000 + (5 * (_channel)), \
953 .hw_value = (_channel), \
955 .max_antenna_gain = 0, \
959 #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
960 #define RATETAB_ENT(_rateid, _flags) \
962 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
963 .hw_value = (_rateid), \
967 static struct ieee80211_rate __wl_rates
[] = {
968 RATETAB_ENT(DOT11_RATE_1M
, 0),
969 RATETAB_ENT(DOT11_RATE_2M
, IEEE80211_RATE_SHORT_PREAMBLE
),
970 RATETAB_ENT(DOT11_RATE_5M5
, IEEE80211_RATE_SHORT_PREAMBLE
),
971 RATETAB_ENT(DOT11_RATE_11M
, IEEE80211_RATE_SHORT_PREAMBLE
),
972 RATETAB_ENT(DOT11_RATE_6M
, 0),
973 RATETAB_ENT(DOT11_RATE_9M
, 0),
974 RATETAB_ENT(DOT11_RATE_12M
, 0),
975 RATETAB_ENT(DOT11_RATE_18M
, 0),
976 RATETAB_ENT(DOT11_RATE_24M
, 0),
977 RATETAB_ENT(DOT11_RATE_36M
, 0),
978 RATETAB_ENT(DOT11_RATE_48M
, 0),
979 RATETAB_ENT(DOT11_RATE_54M
, 0)
982 #define wl_a_rates (__wl_rates + 4)
983 #define wl_a_rates_size 8
984 #define wl_g_rates (__wl_rates + 0)
985 #define wl_g_rates_size 12
987 static struct ieee80211_channel __wl_2ghz_channels
[] = {
1000 CHAN2G(13, 2472, 0),
1004 static struct ieee80211_channel __wl_5ghz_a_channels
[] = {
1005 CHAN5G(34, 0), CHAN5G(36, 0),
1006 CHAN5G(38, 0), CHAN5G(40, 0),
1007 CHAN5G(42, 0), CHAN5G(44, 0),
1008 CHAN5G(46, 0), CHAN5G(48, 0),
1009 CHAN5G(52, 0), CHAN5G(56, 0),
1010 CHAN5G(60, 0), CHAN5G(64, 0),
1011 CHAN5G(100, 0), CHAN5G(104, 0),
1012 CHAN5G(108, 0), CHAN5G(112, 0),
1013 CHAN5G(116, 0), CHAN5G(120, 0),
1014 CHAN5G(124, 0), CHAN5G(128, 0),
1015 CHAN5G(132, 0), CHAN5G(136, 0),
1016 CHAN5G(140, 0), CHAN5G(144, 0),
1017 CHAN5G(149, 0), CHAN5G(153, 0),
1018 CHAN5G(157, 0), CHAN5G(161, 0),
1022 static struct ieee80211_supported_band __wl_band_2ghz
= {
1023 .band
= IEEE80211_BAND_2GHZ
,
1024 .channels
= __wl_2ghz_channels
,
1025 .n_channels
= ARRAY_SIZE(__wl_2ghz_channels
),
1026 .bitrates
= wl_g_rates
,
1027 .n_bitrates
= wl_g_rates_size
1030 static struct ieee80211_supported_band __wl_band_5ghz_a
= {
1031 .band
= IEEE80211_BAND_5GHZ
,
1032 .channels
= __wl_5ghz_a_channels
,
1033 .n_channels
= ARRAY_SIZE(__wl_5ghz_a_channels
),
1034 .bitrates
= wl_a_rates
,
1035 .n_bitrates
= wl_a_rates_size
1038 static const u32 __wl_cipher_suites
[] = {
1039 WLAN_CIPHER_SUITE_WEP40
,
1040 WLAN_CIPHER_SUITE_WEP104
,
1041 WLAN_CIPHER_SUITE_TKIP
,
1042 WLAN_CIPHER_SUITE_CCMP
,
1045 * Advertising AES_CMAC cipher suite to userspace would imply that we
1046 * are supporting MFP. So advertise only when MFP support is enabled.
1048 WLAN_CIPHER_SUITE_AES_CMAC
,
1052 #ifdef WL_SUPPORT_ACS
1054 * The firmware code required for this feature to work is currently under
1055 * BCMINTERNAL flag. In future if this is to enabled we need to bring the
1056 * required firmware code out of the BCMINTERNAL flag.
1058 struct wl_dump_survey
{
1066 #endif /* WL_SUPPORT_ACS */
1069 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
1070 static int maxrxpktglom
= 0;
1073 /* IOCtl version read from targeted driver */
1075 #ifdef DEBUGFS_CFG80211
1076 #define S_SUBLOGLEVEL 20
1077 static const struct {
1080 } sublogname_map
[] = {
1081 {WL_DBG_ERR
, "ERR"},
1082 {WL_DBG_INFO
, "INFO"},
1083 {WL_DBG_DBG
, "DBG"},
1084 {WL_DBG_SCAN
, "SCAN"},
1085 {WL_DBG_TRACE
, "TRACE"},
1086 {WL_DBG_P2P_ACTION
, "P2PACTION"}
1090 #ifdef CUSTOMER_HW4_DEBUG
1091 uint prev_dhd_console_ms
= 0;
1092 u32 prev_wl_dbg_level
= 0;
1093 bool wl_scan_timeout_dbg_enabled
= 0;
1094 static void wl_scan_timeout_dbg_set(void);
1095 static void wl_scan_timeout_dbg_clear(void);
1097 static void wl_scan_timeout_dbg_set(void)
1099 WL_ERR(("Enter \n"));
1100 prev_dhd_console_ms
= dhd_console_ms
;
1101 prev_wl_dbg_level
= wl_dbg_level
;
1104 wl_dbg_level
|= (WL_DBG_ERR
| WL_DBG_P2P_ACTION
| WL_DBG_SCAN
);
1106 wl_scan_timeout_dbg_enabled
= 1;
1108 static void wl_scan_timeout_dbg_clear(void)
1110 WL_ERR(("Enter \n"));
1111 dhd_console_ms
= prev_dhd_console_ms
;
1112 wl_dbg_level
= prev_wl_dbg_level
;
1114 wl_scan_timeout_dbg_enabled
= 0;
1116 #endif /* CUSTOMER_HW4_DEBUG */
1118 /* watchdog timer for disconnecting when fw is not associated for FW_ASSOC_WATCHDOG_TIME ms */
1119 uint32 fw_assoc_watchdog_ms
= 0;
1120 bool fw_assoc_watchdog_started
= 0;
1121 #define FW_ASSOC_WATCHDOG_TIME 10 * 1000 /* msec */
1123 static void wl_add_remove_pm_enable_work(struct bcm_cfg80211
*cfg
,
1124 enum wl_pm_workq_act_type type
)
1126 u16 wq_duration
= 0;
1127 dhd_pub_t
*dhd
= NULL
;
1132 dhd
= (dhd_pub_t
*)(cfg
->pub
);
1134 mutex_lock(&cfg
->pm_sync
);
1136 * Make cancel and schedule work part mutually exclusive
1137 * so that while cancelling, we are sure that there is no
1138 * work getting scheduled.
1140 if (delayed_work_pending(&cfg
->pm_enable_work
)) {
1141 cancel_delayed_work_sync(&cfg
->pm_enable_work
);
1142 DHD_PM_WAKE_UNLOCK(cfg
->pub
);
1145 if (type
== WL_PM_WORKQ_SHORT
) {
1146 wq_duration
= WL_PM_ENABLE_TIMEOUT
;
1147 } else if (type
== WL_PM_WORKQ_LONG
) {
1148 wq_duration
= (WL_PM_ENABLE_TIMEOUT
*2);
1151 /* It should schedule work item only if driver is up */
1152 if (wq_duration
&& dhd
->up
) {
1153 if (schedule_delayed_work(&cfg
->pm_enable_work
,
1154 msecs_to_jiffies((const unsigned int)wq_duration
))) {
1155 DHD_PM_WAKE_LOCK_TIMEOUT(cfg
->pub
, wq_duration
);
1157 WL_ERR(("Can't schedule pm work handler\n"));
1160 mutex_unlock(&cfg
->pm_sync
);
1163 /* Return a new chanspec given a legacy chanspec
1164 * Returns INVCHANSPEC on error
1167 wl_chspec_from_legacy(chanspec_t legacy_chspec
)
1171 /* get the channel number */
1172 chspec
= LCHSPEC_CHANNEL(legacy_chspec
);
1174 /* convert the band */
1175 if (LCHSPEC_IS2G(legacy_chspec
)) {
1176 chspec
|= WL_CHANSPEC_BAND_2G
;
1178 chspec
|= WL_CHANSPEC_BAND_5G
;
1181 /* convert the bw and sideband */
1182 if (LCHSPEC_IS20(legacy_chspec
)) {
1183 chspec
|= WL_CHANSPEC_BW_20
;
1185 chspec
|= WL_CHANSPEC_BW_40
;
1186 if (LCHSPEC_CTL_SB(legacy_chspec
) == WL_LCHANSPEC_CTL_SB_LOWER
) {
1187 chspec
|= WL_CHANSPEC_CTL_SB_L
;
1189 chspec
|= WL_CHANSPEC_CTL_SB_U
;
1193 if (wf_chspec_malformed(chspec
)) {
1194 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
1202 /* Return a legacy chanspec given a new chanspec
1203 * Returns INVCHANSPEC on error
1206 wl_chspec_to_legacy(chanspec_t chspec
)
1210 if (wf_chspec_malformed(chspec
)) {
1211 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
1216 /* get the channel number */
1217 lchspec
= CHSPEC_CHANNEL(chspec
);
1219 /* convert the band */
1220 if (CHSPEC_IS2G(chspec
)) {
1221 lchspec
|= WL_LCHANSPEC_BAND_2G
;
1223 lchspec
|= WL_LCHANSPEC_BAND_5G
;
1226 /* convert the bw and sideband */
1227 if (CHSPEC_IS20(chspec
)) {
1228 lchspec
|= WL_LCHANSPEC_BW_20
;
1229 lchspec
|= WL_LCHANSPEC_CTL_SB_NONE
;
1230 } else if (CHSPEC_IS40(chspec
)) {
1231 lchspec
|= WL_LCHANSPEC_BW_40
;
1232 if (CHSPEC_CTL_SB(chspec
) == WL_CHANSPEC_CTL_SB_L
) {
1233 lchspec
|= WL_LCHANSPEC_CTL_SB_LOWER
;
1235 lchspec
|= WL_LCHANSPEC_CTL_SB_UPPER
;
1238 /* cannot express the bandwidth */
1239 char chanbuf
[CHANSPEC_STR_LEN
];
1241 "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
1242 "to pre-11ac format\n",
1243 wf_chspec_ntoa(chspec
, chanbuf
), chspec
));
1250 /* given a chanspec value, do the endian and chanspec version conversion to
1251 * a chanspec_t value
1252 * Returns INVCHANSPEC on error
1255 wl_chspec_host_to_driver(chanspec_t chanspec
)
1257 if (ioctl_version
== 1) {
1258 chanspec
= wl_chspec_to_legacy(chanspec
);
1259 if (chanspec
== INVCHANSPEC
) {
1263 chanspec
= htodchanspec(chanspec
);
1268 /* given a channel value, do the endian and chanspec version conversion to
1269 * a chanspec_t value
1270 * Returns INVCHANSPEC on error
1273 wl_ch_host_to_driver(struct bcm_cfg80211
*cfg
, s32 bssidx
, u16 channel
)
1275 chanspec_t chanspec
;
1277 chanspec
= channel
& WL_CHANSPEC_CHAN_MASK
;
1279 if (channel
<= CH_MAX_2G_CHANNEL
)
1280 chanspec
|= WL_CHANSPEC_BAND_2G
;
1282 chanspec
|= WL_CHANSPEC_BAND_5G
;
1284 chanspec
|= wl_cfg80211_ulb_get_min_bw_chspec(cfg
, NULL
, bssidx
);
1286 chanspec
|= WL_CHANSPEC_CTL_SB_NONE
;
1288 return wl_chspec_host_to_driver(chanspec
);
1291 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
1292 * a chanspec_t value
1293 * Returns INVCHANSPEC on error
1296 wl_chspec_driver_to_host(chanspec_t chanspec
)
1298 chanspec
= dtohchanspec(chanspec
);
1299 if (ioctl_version
== 1) {
1300 chanspec
= wl_chspec_from_legacy(chanspec
);
1307 * convert ASCII string to MAC address (colon-delimited format)
1308 * eg: 00:11:22:33:44:55
1311 wl_cfg80211_ether_atoe(const char *a
, struct ether_addr
*n
)
1316 memset(n
, 0, ETHER_ADDR_LEN
);
1318 n
->octet
[count
++] = (uint8
)simple_strtoul(a
, &c
, 16);
1319 if (!*c
++ || count
== ETHER_ADDR_LEN
)
1323 return (count
== ETHER_ADDR_LEN
);
1326 /* There isn't a lot of sense in it, but you can transmit anything you like */
1327 static const struct ieee80211_txrx_stypes
1328 wl_cfg80211_default_mgmt_stypes
[NUM_NL80211_IFTYPES
] = {
1330 [NL80211_IFTYPE_MESH_POINT
] = {
1332 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4) |
1333 BIT(IEEE80211_STYPE_AUTH
>> 4)
1336 [NL80211_IFTYPE_ADHOC
] = {
1338 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4)
1340 [NL80211_IFTYPE_STATION
] = {
1342 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4) |
1343 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4)
1345 [NL80211_IFTYPE_AP
] = {
1347 .rx
= BIT(IEEE80211_STYPE_ASSOC_REQ
>> 4) |
1348 BIT(IEEE80211_STYPE_REASSOC_REQ
>> 4) |
1349 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4) |
1350 BIT(IEEE80211_STYPE_DISASSOC
>> 4) |
1351 BIT(IEEE80211_STYPE_AUTH
>> 4) |
1352 BIT(IEEE80211_STYPE_DEAUTH
>> 4) |
1353 BIT(IEEE80211_STYPE_ACTION
>> 4)
1355 [NL80211_IFTYPE_AP_VLAN
] = {
1358 .rx
= BIT(IEEE80211_STYPE_ASSOC_REQ
>> 4) |
1359 BIT(IEEE80211_STYPE_REASSOC_REQ
>> 4) |
1360 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4) |
1361 BIT(IEEE80211_STYPE_DISASSOC
>> 4) |
1362 BIT(IEEE80211_STYPE_AUTH
>> 4) |
1363 BIT(IEEE80211_STYPE_DEAUTH
>> 4) |
1364 BIT(IEEE80211_STYPE_ACTION
>> 4)
1366 [NL80211_IFTYPE_P2P_CLIENT
] = {
1368 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4) |
1369 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4)
1371 [NL80211_IFTYPE_P2P_GO
] = {
1373 .rx
= BIT(IEEE80211_STYPE_ASSOC_REQ
>> 4) |
1374 BIT(IEEE80211_STYPE_REASSOC_REQ
>> 4) |
1375 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4) |
1376 BIT(IEEE80211_STYPE_DISASSOC
>> 4) |
1377 BIT(IEEE80211_STYPE_AUTH
>> 4) |
1378 BIT(IEEE80211_STYPE_DEAUTH
>> 4) |
1379 BIT(IEEE80211_STYPE_ACTION
>> 4)
1381 #if defined(WL_CFG80211_P2P_DEV_IF)
1382 [NL80211_IFTYPE_P2P_DEVICE
] = {
1384 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4) |
1385 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4)
1387 #endif /* WL_CFG80211_P2P_DEV_IF */
1390 static void swap_key_from_BE(struct wl_wsec_key
*key
)
1392 key
->index
= htod32(key
->index
);
1393 key
->len
= htod32(key
->len
);
1394 key
->algo
= htod32(key
->algo
);
1395 key
->flags
= htod32(key
->flags
);
1396 key
->rxiv
.hi
= htod32(key
->rxiv
.hi
);
1397 key
->rxiv
.lo
= htod16(key
->rxiv
.lo
);
1398 key
->iv_initialized
= htod32(key
->iv_initialized
);
1401 static void swap_key_to_BE(struct wl_wsec_key
*key
)
1403 key
->index
= dtoh32(key
->index
);
1404 key
->len
= dtoh32(key
->len
);
1405 key
->algo
= dtoh32(key
->algo
);
1406 key
->flags
= dtoh32(key
->flags
);
1407 key
->rxiv
.hi
= dtoh32(key
->rxiv
.hi
);
1408 key
->rxiv
.lo
= dtoh16(key
->rxiv
.lo
);
1409 key
->iv_initialized
= dtoh32(key
->iv_initialized
);
1412 /* Dump the contents of the encoded wps ie buffer and get pbc value */
1414 wl_validate_wps_ie(char *wps_ie
, s32 wps_ie_len
, bool *pbc
)
1416 #define WPS_IE_FIXED_LEN 6
1422 u8
*valptr
= (uint8
*) &val
;
1423 if (wps_ie
== NULL
|| wps_ie_len
< WPS_IE_FIXED_LEN
) {
1424 WL_ERR(("invalid argument : NULL\n"));
1427 len
= (s16
)wps_ie
[TLV_LEN_OFF
];
1429 if (len
> wps_ie_len
) {
1430 WL_ERR(("invalid length len %d, wps ie len %d\n", len
, wps_ie_len
));
1433 WL_DBG(("wps_ie len=%d\n", len
));
1434 len
-= 4; /* for the WPS IE's OUI, oui_type fields */
1435 subel
= wps_ie
+ WPS_IE_FIXED_LEN
;
1436 while (len
>= 4) { /* must have attr id, attr len fields */
1437 valptr
[0] = *subel
++;
1438 valptr
[1] = *subel
++;
1439 subelt_id
= HTON16(val
);
1441 valptr
[0] = *subel
++;
1442 valptr
[1] = *subel
++;
1443 subelt_len
= HTON16(val
);
1445 len
-= 4; /* for the attr id, attr len fields */
1446 len
-= (s16
)subelt_len
; /* for the remaining fields in this attribute */
1450 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1451 subel
, subelt_id
, subelt_len
));
1453 if (subelt_id
== WPS_ID_VERSION
) {
1454 WL_DBG((" attr WPS_ID_VERSION: %u\n", *subel
));
1455 } else if (subelt_id
== WPS_ID_REQ_TYPE
) {
1456 WL_DBG((" attr WPS_ID_REQ_TYPE: %u\n", *subel
));
1457 } else if (subelt_id
== WPS_ID_CONFIG_METHODS
) {
1459 valptr
[1] = *(subel
+ 1);
1460 WL_DBG((" attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val
)));
1461 } else if (subelt_id
== WPS_ID_DEVICE_NAME
) {
1463 int namelen
= MIN(subelt_len
, (sizeof(devname
) - 1));
1466 memcpy(devname
, subel
, namelen
);
1467 devname
[namelen
] = '\0';
1468 /* Printing len as rx'ed in the IE */
1469 WL_DBG((" attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1470 devname
, subelt_len
));
1472 } else if (subelt_id
== WPS_ID_DEVICE_PWD_ID
) {
1474 valptr
[1] = *(subel
+ 1);
1475 WL_DBG((" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val
)));
1476 *pbc
= (HTON16(val
) == DEV_PW_PUSHBUTTON
) ? true : false;
1477 } else if (subelt_id
== WPS_ID_PRIM_DEV_TYPE
) {
1479 valptr
[1] = *(subel
+ 1);
1480 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val
)));
1481 valptr
[0] = *(subel
+ 6);
1482 valptr
[1] = *(subel
+ 7);
1483 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val
)));
1484 } else if (subelt_id
== WPS_ID_REQ_DEV_TYPE
) {
1486 valptr
[1] = *(subel
+ 1);
1487 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val
)));
1488 valptr
[0] = *(subel
+ 6);
1489 valptr
[1] = *(subel
+ 7);
1490 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val
)));
1491 } else if (subelt_id
== WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS
) {
1493 valptr
[1] = *(subel
+ 1);
1494 WL_DBG((" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1495 ": cat=%u\n", HTON16(val
)));
1497 WL_DBG((" unknown attr 0x%x\n", subelt_id
));
1500 subel
+= subelt_len
;
1504 s32
wl_set_tx_power(struct net_device
*dev
,
1505 enum nl80211_tx_power_setting type
, s32 dbm
)
1510 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
1512 /* Make sure radio is off or on as far as software is concerned */
1513 disable
= WL_RADIO_SW_DISABLE
<< 16;
1514 disable
= htod32(disable
);
1515 err
= wldev_ioctl_set(dev
, WLC_SET_RADIO
, &disable
, sizeof(disable
));
1516 if (unlikely(err
)) {
1517 WL_ERR(("WLC_SET_RADIO error (%d)\n", err
));
1523 txpwrqdbm
= dbm
* 4;
1524 err
= wldev_iovar_setbuf_bsscfg(dev
, "qtxpower", (void *)&txpwrqdbm
,
1525 sizeof(txpwrqdbm
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, 0,
1526 &cfg
->ioctl_buf_sync
);
1528 WL_ERR(("qtxpower error (%d)\n", err
));
1530 WL_ERR(("dBm=%d, txpwrqdbm=0x%x\n", dbm
, txpwrqdbm
));
1535 s32
wl_get_tx_power(struct net_device
*dev
, s32
*dbm
)
1539 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
1541 err
= wldev_iovar_getbuf_bsscfg(dev
, "qtxpower",
1542 NULL
, 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, 0, &cfg
->ioctl_buf_sync
);
1543 if (unlikely(err
)) {
1544 WL_ERR(("error (%d)\n", err
));
1548 memcpy(&txpwrdbm
, cfg
->ioctl_buf
, sizeof(txpwrdbm
));
1549 txpwrdbm
= dtoh32(txpwrdbm
);
1550 *dbm
= (txpwrdbm
& ~WL_TXPWR_OVERRIDE
) / 4;
1552 WL_INFORM(("dBm=%d, txpwrdbm=0x%x\n", *dbm
, txpwrdbm
));
1557 static chanspec_t
wl_cfg80211_get_shared_freq(struct wiphy
*wiphy
)
1560 int cur_band
, err
= 0;
1561 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1562 struct net_device
*dev
= bcmcfg_to_prmry_ndev(cfg
);
1563 struct ether_addr bssid
;
1564 struct wl_bss_info
*bss
= NULL
;
1565 s32 bssidx
= 0; /* Explicitly set to primary bssidx */
1568 memset(&bssid
, 0, sizeof(bssid
));
1569 if ((err
= wldev_ioctl_get(dev
, WLC_GET_BSSID
, &bssid
, sizeof(bssid
)))) {
1570 /* STA interface is not associated. So start the new interface on a temp
1571 * channel . Later proper channel will be applied by the above framework
1572 * via set_channel (cfg80211 API).
1574 WL_DBG(("Not associated. Return a temp channel. \n"));
1576 err
= wldev_ioctl_get(dev
, WLC_GET_BAND
, &cur_band
, sizeof(int));
1577 if (unlikely(err
)) {
1578 WL_ERR(("Get band failed\n"));
1579 return wl_ch_host_to_driver(cfg
, bssidx
, WL_P2P_TEMP_CHAN
);
1581 if (cur_band
== WLC_BAND_5G
)
1582 return wl_ch_host_to_driver(cfg
, bssidx
, WL_P2P_TEMP_CHAN_5G
);
1584 return wl_ch_host_to_driver(cfg
, bssidx
, WL_P2P_TEMP_CHAN
);
1587 buf
= kzalloc(WL_EXTRA_BUF_MAX
, GFP_KERNEL
);
1589 WL_ERR(("buf alloc failed. use temp channel\n"));
1590 return wl_ch_host_to_driver(cfg
, bssidx
, WL_P2P_TEMP_CHAN
);
1593 *(u32
*)buf
= htod32(WL_EXTRA_BUF_MAX
);
1594 if ((err
= wldev_ioctl_get(dev
, WLC_GET_BSS_INFO
, buf
,
1595 WL_EXTRA_BUF_MAX
))) {
1596 WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1597 chspec
= wl_ch_host_to_driver(cfg
, bssidx
, WL_P2P_TEMP_CHAN
);
1600 bss
= (struct wl_bss_info
*) (buf
+ 4);
1601 chspec
= bss
->chanspec
;
1603 WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec
));
1610 static bcm_struct_cfgdev
*
1611 wl_cfg80211_add_monitor_if(const char *name
)
1613 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1614 WL_INFORM(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1615 return ERR_PTR(-EOPNOTSUPP
);
1617 struct net_device
* ndev
= NULL
;
1619 dhd_add_monitor(name
, &ndev
);
1620 WL_INFORM(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev
));
1621 return ndev_to_cfgdev(ndev
);
1622 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1625 static bcm_struct_cfgdev
*
1626 wl_cfg80211_add_virtual_iface(struct wiphy
*wiphy
,
1627 #if defined(WL_CFG80211_P2P_DEV_IF)
1631 #endif /* WL_CFG80211_P2P_DEV_IF */
1632 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
1633 unsigned char name_assign_type
,
1634 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
1635 enum nl80211_iftype type
,
1636 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
1638 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) */
1639 struct vif_params
*params
)
1649 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1650 struct net_device
*primary_ndev
;
1651 struct net_device
*new_ndev
;
1652 struct ether_addr primary_mac
;
1653 bcm_struct_cfgdev
*new_cfgdev
;
1654 #ifdef PROP_TXSTATUS_VSDB
1655 #if defined(BCMSDIO) || defined(BCMDBUS)
1658 #endif /* BCMSDIO || BCMDBUS */
1659 #endif /* PROP_TXSTATUS_VSDB */
1661 bool hang_required
= false;
1664 return ERR_PTR(-EINVAL
);
1666 dhd
= (dhd_pub_t
*)(cfg
->pub
);
1668 /* Use primary I/F for sending cmds down to firmware */
1669 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
1671 if (unlikely(!wl_get_drv_status(cfg
, READY
, primary_ndev
))) {
1672 WL_ERR(("device is not ready\n"));
1673 return ERR_PTR(-ENODEV
);
1677 WL_ERR(("Interface name not provided \n"));
1678 return ERR_PTR(-EINVAL
);
1682 /* disable TDLS if number of connected interfaces is >= 1 */
1683 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_IF_CREATE
, false);
1686 mutex_lock(&cfg
->if_sync
);
1687 WL_DBG(("if name: %s, type: %d\n", name
, type
));
1689 case NL80211_IFTYPE_ADHOC
:
1690 #ifdef WLAIBSS_MCHAN
1691 new_cfgdev
= bcm_cfg80211_add_ibss_if(wiphy
, (char *)name
);
1692 mutex_unlock(&cfg
->if_sync
);
1694 #endif /* WLAIBSS_MCHAN */
1695 case NL80211_IFTYPE_AP_VLAN
:
1696 case NL80211_IFTYPE_WDS
:
1697 case NL80211_IFTYPE_MESH_POINT
:
1698 WL_ERR(("Unsupported interface type\n"));
1699 mode
= WL_MODE_IBSS
;
1702 case NL80211_IFTYPE_MONITOR
:
1703 new_cfgdev
= wl_cfg80211_add_monitor_if(name
);
1704 mutex_unlock(&cfg
->if_sync
);
1706 #if defined(WL_CFG80211_P2P_DEV_IF)
1707 case NL80211_IFTYPE_P2P_DEVICE
:
1708 cfg
->down_disc_if
= FALSE
;
1709 new_cfgdev
= wl_cfgp2p_add_p2p_disc_if(cfg
);
1710 mutex_unlock(&cfg
->if_sync
);
1712 #endif /* WL_CFG80211_P2P_DEV_IF */
1713 case NL80211_IFTYPE_STATION
:
1714 #ifdef WL_VIRTUAL_APSTA
1715 #ifdef WLAIBSS_MCHAN
1716 if (cfg
->ibss_cfgdev
) {
1717 WL_ERR(("AIBSS is already operational. "
1718 " AIBSS & DUALSTA can't be used together \n"));
1722 #endif /* WLAIBSS_MCHAN */
1724 if (wl_cfgp2p_vif_created(cfg
)) {
1725 WL_ERR(("Could not create new iface."
1726 "Already one p2p interface is running"));
1730 new_cfgdev
= wl_cfg80211_create_iface(cfg
->wdev
->wiphy
,
1731 NL80211_IFTYPE_STATION
, NULL
, name
);
1736 mutex_unlock(&cfg
->if_sync
);
1739 #endif /* WL_VIRTUAL_APSTA */
1740 case NL80211_IFTYPE_P2P_CLIENT
:
1741 wlif_type
= WL_P2P_IF_CLIENT
;
1744 case NL80211_IFTYPE_P2P_GO
:
1745 wlif_type
= WL_P2P_IF_GO
;
1748 #ifdef WL_VIRTUAL_APSTA
1749 case NL80211_IFTYPE_AP
:
1750 dhd
->op_mode
= DHD_FLAG_HOSTAP_MODE
;
1751 new_cfgdev
= wl_cfg80211_create_iface(cfg
->wdev
->wiphy
,
1752 NL80211_IFTYPE_AP
, NULL
, name
);
1757 mutex_unlock(&cfg
->if_sync
);
1760 #endif /* WL_VIRTUAL_APSTA */
1762 WL_ERR(("Unsupported interface type\n"));
1767 if (cfg
->p2p_supported
&& (wlif_type
!= -1)) {
1768 ASSERT(cfg
->p2p
); /* ensure expectation of p2p initialization */
1770 #ifdef PROP_TXSTATUS_VSDB
1771 #if defined(BCMSDIO)
1777 #endif /* PROP_TXSTATUS_VSDB */
1780 WL_ERR(("Failed to start p2p"));
1785 if (cfg
->p2p
&& !cfg
->p2p
->on
&& strstr(name
, WL_P2P_INTERFACE_PREFIX
)) {
1787 wl_cfgp2p_set_firm_p2p(cfg
);
1788 wl_cfgp2p_init_discovery(cfg
);
1789 get_primary_mac(cfg
, &primary_mac
);
1790 wl_cfgp2p_generate_bss_mac(cfg
, &primary_mac
);
1793 strncpy(cfg
->p2p
->vir_ifname
, name
, IFNAMSIZ
- 1);
1794 cfg
->p2p
->vir_ifname
[IFNAMSIZ
- 1] = '\0';
1796 wl_cfg80211_scan_abort(cfg
);
1797 #ifdef PROP_TXSTATUS_VSDB
1798 #if defined(BCMSDIO) || defined(BCMDBUS)
1799 if (!cfg
->wlfc_on
&& !disable_proptx
) {
1800 dhd_wlfc_get_enable(dhd
, &enabled
);
1801 if (!enabled
&& dhd
->op_mode
!= DHD_FLAG_HOSTAP_MODE
&&
1802 dhd
->op_mode
!= DHD_FLAG_IBSS_MODE
) {
1804 err
= wldev_ioctl_set(primary_ndev
, WLC_UP
, &up
, sizeof(s32
));
1806 WL_ERR(("WLC_UP return err:%d\n", err
));
1808 cfg
->wlfc_on
= true;
1810 #endif /* BCMSDIO || BCMDBUS */
1811 #endif /* PROP_TXSTATUS_VSDB */
1813 /* Dual p2p doesn't support multiple P2PGO interfaces,
1814 * p2p_go_count is the counter for GO creation
1817 if ((cfg
->p2p
->p2p_go_count
> 0) && (type
== NL80211_IFTYPE_P2P_GO
)) {
1818 WL_ERR(("Fw does not support multiple Go\n"));
1822 /* In concurrency case, STA may be already associated in a particular channel.
1823 * so retrieve the current channel of primary interface and then start the virtual
1824 * interface on that.
1826 chspec
= wl_cfg80211_get_shared_freq(wiphy
);
1828 /* For P2P mode, use P2P-specific driver features to create the
1829 * bss: "cfg p2p_ifadd"
1831 wl_set_p2p_status(cfg
, IF_ADDING
);
1832 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
1833 cfg_type
= wl_cfgp2p_get_conn_idx(cfg
);
1834 if (cfg_type
== BCME_ERROR
) {
1835 wl_clr_p2p_status(cfg
, IF_ADDING
);
1836 WL_ERR(("Failed to get connection idx for p2p interface\n"));
1840 err
= wl_cfgp2p_ifadd(cfg
, wl_to_p2p_bss_macaddr(cfg
, cfg_type
),
1841 htod32(wlif_type
), chspec
);
1842 if (unlikely(err
)) {
1843 wl_clr_p2p_status(cfg
, IF_ADDING
);
1844 WL_ERR((" virtual iface add failed (%d) \n", err
));
1849 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
1850 ((wl_get_p2p_status(cfg
, IF_ADDING
) == false) &&
1851 (cfg
->if_event_info
.valid
)),
1852 msecs_to_jiffies(MAX_WAIT_TIME
));
1854 if (timeout
> 0 && !wl_get_p2p_status(cfg
, IF_ADDING
) && cfg
->if_event_info
.valid
) {
1855 struct wireless_dev
*vwdev
;
1856 int pm_mode
= PM_ENABLE
;
1857 wl_if_event_info
*event
= &cfg
->if_event_info
;
1858 /* IF_ADD event has come back, we can proceed to to register
1859 * the new interface now, use the interface name provided by caller (thus
1860 * ignore the one from wlc)
1862 new_ndev
= wl_cfg80211_allocate_if(cfg
, event
->ifidx
, cfg
->p2p
->vir_ifname
,
1863 event
->mac
, event
->bssidx
, event
->name
);
1864 if (new_ndev
== NULL
) {
1869 wl_to_p2p_bss_ndev(cfg
, cfg_type
) = new_ndev
;
1870 wl_to_p2p_bss_bssidx(cfg
, cfg_type
) = event
->bssidx
;
1871 vwdev
= kzalloc(sizeof(*vwdev
), GFP_KERNEL
);
1872 if (unlikely(!vwdev
)) {
1873 WL_ERR(("Could not allocate wireless device\n"));
1877 vwdev
->wiphy
= cfg
->wdev
->wiphy
;
1878 WL_INFORM(("virtual interface(%s) is created\n", cfg
->p2p
->vir_ifname
));
1879 if (type
== NL80211_IFTYPE_P2P_GO
) {
1880 cfg
->p2p
->p2p_go_count
++;
1882 vwdev
->iftype
= type
;
1883 vwdev
->netdev
= new_ndev
;
1884 new_ndev
->ieee80211_ptr
= vwdev
;
1885 SET_NETDEV_DEV(new_ndev
, wiphy_dev(vwdev
->wiphy
));
1886 wl_set_drv_status(cfg
, READY
, new_ndev
);
1887 if (wl_config_ifmode(cfg
, new_ndev
, type
) < 0) {
1888 WL_ERR(("conf ifmode failed\n"));
1894 if (wl_cfg80211_register_if(cfg
,
1895 event
->ifidx
, new_ndev
, FALSE
) != BCME_OK
) {
1896 wl_cfg80211_remove_if(cfg
, event
->ifidx
, new_ndev
, FALSE
);
1900 err
= wl_alloc_netinfo(cfg
, new_ndev
, vwdev
, mode
, pm_mode
, event
->bssidx
);
1901 if (unlikely(err
!= 0)) {
1902 wl_cfg80211_remove_if(cfg
, event
->ifidx
, new_ndev
, FALSE
);
1903 WL_ERR(("Allocation of netinfo failed (%d) \n", err
));
1907 /* Disable firmware roaming for P2P interface */
1908 wldev_iovar_setint(new_ndev
, "roam_off", val
);
1909 wldev_iovar_setint(new_ndev
, "bcn_timeout", dhd
->conf
->bcn_timeout
);
1911 if (cfg
->p2p_wdev
&& is_p2p_group_iface(new_ndev
->ieee80211_ptr
)) {
1912 u32 ulb_bw
= wl_cfg80211_get_ulb_bw(cfg
, cfg
->p2p_wdev
);
1914 /* Apply ULB BW settings on the newly spawned interface */
1915 WL_DBG(("[ULB] Applying ULB BW for the newly"
1916 "created P2P interface \n"));
1917 if (wl_cfg80211_set_ulb_bw(new_ndev
,
1918 ulb_bw
, new_ndev
->name
) < 0) {
1920 * If ulb_bw set failed, fail the iface creation.
1921 * wl_dealloc_netinfo_by_wdev will be called by the
1922 * unregister notifier.
1924 wl_cfg80211_remove_if(cfg
,
1925 event
->ifidx
, new_ndev
, FALSE
);
1931 #endif /* WL11ULB */
1933 if (mode
!= WL_MODE_AP
)
1934 wldev_iovar_setint(new_ndev
, "buf_key_b4_m4", 1);
1936 WL_ERR((" virtual interface(%s) is "
1937 "created net attach done\n", cfg
->p2p
->vir_ifname
));
1938 if (mode
== WL_MODE_AP
)
1939 wl_set_drv_status(cfg
, CONNECTED
, new_ndev
);
1940 #ifdef SUPPORT_AP_POWERSAVE
1941 if (mode
== WL_MODE_AP
) {
1942 dhd_set_ap_powersave(dhd
, 0, TRUE
);
1944 #endif /* SUPPORT_AP_POWERSAVE */
1945 if (type
== NL80211_IFTYPE_P2P_CLIENT
)
1946 dhd_mode
= DHD_FLAG_P2P_GC_MODE
;
1947 else if (type
== NL80211_IFTYPE_P2P_GO
)
1948 dhd_mode
= DHD_FLAG_P2P_GO_MODE
;
1949 DNGL_FUNC(dhd_cfg80211_set_p2p_info
, (cfg
, dhd_mode
));
1950 /* reinitialize completion to clear previous count */
1951 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
1952 INIT_COMPLETION(cfg
->iface_disable
);
1954 init_completion(&cfg
->iface_disable
);
1955 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */
1956 #ifdef SUPPORT_SET_CAC
1957 wl_cfg80211_set_cac(cfg
, 0);
1958 #endif /* SUPPORT_SET_CAC */
1959 mutex_unlock(&cfg
->if_sync
);
1960 return ndev_to_cfgdev(new_ndev
);
1962 wl_clr_p2p_status(cfg
, IF_ADDING
);
1963 WL_ERR((" virtual interface(%s) is not created \n", cfg
->p2p
->vir_ifname
));
1965 WL_ERR(("left timeout : %d\n", timeout
));
1966 WL_ERR(("IF_ADDING status : %d\n", wl_get_p2p_status(cfg
, IF_ADDING
)));
1967 WL_ERR(("event valid : %d\n", cfg
->if_event_info
.valid
));
1969 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
1970 wl_set_p2p_status(cfg
, IF_DELETING
);
1972 hang_required
= true;
1973 if ((err
= wl_cfgp2p_ifdel(cfg
,
1974 wl_to_p2p_bss_macaddr(cfg
,
1975 cfg_type
))) == BCME_OK
) {
1976 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
1977 ((wl_get_p2p_status(cfg
, IF_DELETING
) == false) &&
1978 (cfg
->if_event_info
.valid
)),
1979 msecs_to_jiffies(MAX_WAIT_TIME
));
1980 if (timeout
> 0 && !wl_get_p2p_status(cfg
, IF_DELETING
) &&
1981 cfg
->if_event_info
.valid
) {
1982 hang_required
= false;
1983 WL_ERR(("IFDEL operation done\n"));
1985 WL_ERR(("IFDEL didn't complete properly\n"));
1988 #ifdef SUPPORT_SET_CAC
1989 wl_cfg80211_set_cac(cfg
, 1);
1990 #endif /* SUPPORT_SET_CAC */
1992 WL_ERR(("IFDEL operation failed, error code = %d\n", err
));
1995 memset(cfg
->p2p
->vir_ifname
, '\0', IFNAMSIZ
);
1996 wl_to_p2p_bss_bssidx(cfg
, cfg_type
) = -1;
1997 #ifdef PROP_TXSTATUS_VSDB
1998 #if defined(BCMSDIO) || defined(BCMDBUS)
1999 dhd_wlfc_get_enable(dhd
, &enabled
);
2000 if (enabled
&& cfg
->wlfc_on
&& dhd
->op_mode
!= DHD_FLAG_HOSTAP_MODE
&&
2001 dhd
->op_mode
!= DHD_FLAG_IBSS_MODE
&& dhd
->conf
->disable_proptx
!=0) {
2002 dhd_wlfc_deinit(dhd
);
2003 cfg
->wlfc_on
= false;
2005 #endif /* BCMSDIO || BCMDBUS */
2006 #endif /* PROP_TXSTATUS_VSDB */
2011 mutex_unlock(&cfg
->if_sync
);
2014 /* Enable back TDLS on failure */
2015 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_IF_DELETE
, false);
2017 if (err
!= -ENOTSUPP
) {
2018 #if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2019 if (dhd
->memdump_enabled
) {
2020 /* Load the dongle side dump to host
2021 * memory and then BUG_ON()
2023 dhd
->memdump_type
= DUMP_TYPE_HANG_ON_IFACE_OP_FAIL
;
2024 dhd_bus_mem_dump(dhd
);
2026 #endif /* BCMPCIE && DHD_FW_COREDUMP */
2027 if (hang_required
) {
2028 /* Notify the user space to recover */
2029 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
2030 WL_ERR(("if add failed, error %d, sent HANG event to %s\n",
2032 dhd
->hang_reason
= HANG_REASON_IFACE_OP_FAILURE
;
2033 net_os_send_hang_message(ndev
);
2037 return ERR_PTR(err
);
2041 wl_cfg80211_del_virtual_iface(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
)
2043 struct net_device
*dev
= NULL
;
2044 struct ether_addr p2p_mac
;
2045 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2050 #if defined(CUSTOM_SET_CPUCORE) || defined(DHD_HANG_SEND_UP_TEST)
2051 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
2052 #endif /* CUSTOM_SET_CPUCORE || DHD_HANG_SEND_UP_TEST */
2053 WL_DBG(("Enter\n"));
2055 memset(&p2p_mac
, 0, sizeof(struct ether_addr
));
2056 #ifdef CUSTOM_SET_CPUCORE
2057 dhd
->chan_isvht80
&= ~DHD_FLAG_P2P_MODE
;
2058 if (!(dhd
->chan_isvht80
))
2059 dhd_set_cpucore(dhd
, FALSE
);
2060 #endif /* CUSTOM_SET_CPUCORE */
2061 mutex_lock(&cfg
->if_sync
);
2062 #ifdef WL_CFG80211_P2P_DEV_IF
2063 if (cfgdev
->iftype
== NL80211_IFTYPE_P2P_DEVICE
) {
2064 if (dhd_download_fw_on_driverload
) {
2065 ret
= wl_cfgp2p_del_p2p_disc_if(cfgdev
, cfg
);
2067 cfg
->down_disc_if
= TRUE
;
2070 mutex_unlock(&cfg
->if_sync
);
2073 #endif /* WL_CFG80211_P2P_DEV_IF */
2074 dev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
2076 #ifdef WLAIBSS_MCHAN
2077 if (cfgdev
== cfg
->ibss_cfgdev
) {
2078 ret
= bcm_cfg80211_del_ibss_if(wiphy
, cfgdev
);
2081 #endif /* WLAIBSS_MCHAN */
2083 if ((index
= wl_get_bssidx_by_wdev(cfg
, cfgdev_to_wdev(cfgdev
))) < 0) {
2084 WL_ERR(("Find p2p index from wdev failed\n"));
2088 if ((cfg
->p2p_supported
) && index
&& (wl_cfgp2p_find_type(cfg
, index
, &type
) == BCME_OK
)) {
2089 /* Handle P2P Interace del */
2090 memcpy(p2p_mac
.octet
, wl_to_p2p_bss_macaddr(cfg
, type
).octet
, ETHER_ADDR_LEN
);
2092 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
2094 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
2095 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
2096 if (wl_cfgp2p_vif_created(cfg
)) {
2097 if (wl_get_drv_status(cfg
, SCANNING
, dev
)) {
2098 wl_notify_escan_complete(cfg
, dev
, true, true);
2100 /* Delete pm_enable_work */
2101 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_DEL
);
2104 if (wl_get_drv_status(cfg
, DISCONNECTING
, dev
) &&
2105 (wl_get_mode_by_netdev(cfg
, dev
) != WL_MODE_AP
)) {
2106 WL_ERR(("Wait for Link Down event for GC !\n"));
2107 wait_for_completion_timeout
2108 (&cfg
->iface_disable
, msecs_to_jiffies(500));
2111 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
2112 wl_set_p2p_status(cfg
, IF_DELETING
);
2113 DNGL_FUNC(dhd_cfg80211_clean_p2p_info
, (cfg
));
2116 if (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
) {
2117 wl_add_remove_eventmsg(dev
, WLC_E_PROBREQ_MSG
, false);
2118 cfg
->p2p
->p2p_go_count
--;
2119 /* disable interface before bsscfg free */
2120 ret
= wl_cfgp2p_ifdisable(cfg
, &p2p_mac
);
2121 /* if fw doesn't support "ifdis",
2122 do not wait for link down of ap mode
2125 WL_ERR(("Wait for Link Down event for GO !!!\n"));
2126 wait_for_completion_timeout(&cfg
->iface_disable
,
2127 msecs_to_jiffies(500));
2128 } else if (ret
!= BCME_UNSUPPORTED
) {
2132 wl_cfg80211_clear_per_bss_ies(cfg
, index
);
2134 if (wl_get_mode_by_netdev(cfg
, dev
) != WL_MODE_AP
)
2135 wldev_iovar_setint(dev
, "buf_key_b4_m4", 0);
2136 memcpy(p2p_mac
.octet
, wl_to_p2p_bss_macaddr(cfg
, type
).octet
,
2138 CFGP2P_INFO(("primary idx %d : cfg p2p_ifdis "MACDBG
"\n",
2139 dev
->ifindex
, MAC2STRDBG(p2p_mac
.octet
)));
2141 /* delete interface after link down */
2142 ret
= wl_cfgp2p_ifdel(cfg
, &p2p_mac
);
2143 #if defined(DHD_HANG_SEND_UP_TEST)
2144 if (ret
!= BCME_OK
||
2145 dhd
->req_hang_type
== HANG_REASON_IFACE_OP_FAILURE
)
2146 #else /* DHD_HANG_SEND_UP_TEST */
2148 #endif /* DHD_HANG_SEND_UP_TEST */
2150 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
2151 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
2153 WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
2155 #if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2156 if (dhd
->memdump_enabled
) {
2157 /* Load the dongle side dump to host
2158 * memory and then BUG_ON()
2160 dhd
->memdump_type
= DUMP_TYPE_HANG_ON_IFACE_OP_FAIL
;
2161 dhd_bus_mem_dump(dhd
);
2163 #endif /* BCMPCIE && DHD_FW_COREDUMP */
2164 dhd
->hang_reason
= HANG_REASON_IFACE_OP_FAILURE
;
2165 net_os_send_hang_message(ndev
);
2167 /* Wait for IF_DEL operation to be finished */
2168 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
2169 ((wl_get_p2p_status(cfg
, IF_DELETING
) == false) &&
2170 (cfg
->if_event_info
.valid
)),
2171 msecs_to_jiffies(MAX_WAIT_TIME
));
2172 if (timeout
> 0 && !wl_get_p2p_status(cfg
, IF_DELETING
) &&
2173 cfg
->if_event_info
.valid
) {
2175 WL_DBG(("IFDEL operation done\n"));
2176 wl_cfg80211_handle_ifdel(cfg
, &cfg
->if_event_info
, dev
);
2178 WL_ERR(("IFDEL didn't complete properly\n"));
2180 #ifdef SUPPORT_SET_CAC
2181 wl_cfg80211_set_cac(cfg
, 1);
2182 #endif /* SUPPORT_SET_CAC */
2185 ret
= dhd_del_monitor(dev
);
2186 if (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
) {
2187 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL((dhd_pub_t
*)(cfg
->pub
));
2190 } else if ((dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) ||
2191 (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_STATION
)) {
2192 #ifdef WL_VIRTUAL_APSTA
2193 ret
= wl_cfg80211_del_iface(wiphy
, cfgdev
);
2195 WL_ERR(("Virtual APSTA not supported!\n"));
2196 #endif /* WL_VIRTUAL_APSTA */
2200 mutex_unlock(&cfg
->if_sync
);
2202 if (ret
== BCME_OK
) {
2203 /* If interface del is success, try enabling back TDLS */
2204 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_IF_DELETE
, false);
2211 wl_cfg80211_change_virtual_iface(struct wiphy
*wiphy
, struct net_device
*ndev
,
2212 enum nl80211_iftype type
,
2213 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
2215 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) */
2216 struct vif_params
*params
)
2226 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2227 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
2229 mutex_lock(&cfg
->if_sync
);
2230 WL_DBG(("Enter type %d\n", type
));
2232 case NL80211_IFTYPE_MONITOR
:
2233 case NL80211_IFTYPE_WDS
:
2235 case NL80211_IFTYPE_MESH_POINT
:
2238 WL_ERR(("type (%d) : currently we do not support this type\n",
2242 case NL80211_IFTYPE_MESH_POINT
:
2243 infra_ibss
= WL_BSSTYPE_MESH
;
2246 case NL80211_IFTYPE_ADHOC
:
2247 mode
= WL_MODE_IBSS
;
2250 case NL80211_IFTYPE_STATION
:
2251 case NL80211_IFTYPE_P2P_CLIENT
:
2252 if (ndev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
2253 s32 bssidx
= wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
);
2255 /* validate bssidx */
2256 WL_ERR(("Wrong bssidx! \n"));
2260 WL_DBG(("del interface. bssidx:%d", bssidx
));
2261 /* Downgrade role from AP to STA */
2262 if ((err
= wl_cfg80211_add_del_bss(cfg
, ndev
,
2263 bssidx
, NL80211_IFTYPE_STATION
, 0, NULL
)) < 0) {
2264 WL_ERR(("AP-STA Downgrade failed \n"));
2271 case NL80211_IFTYPE_AP
:
2272 dhd
->op_mode
|= DHD_FLAG_HOSTAP_MODE
;
2273 /* intentional fall through */
2274 case NL80211_IFTYPE_AP_VLAN
:
2275 case NL80211_IFTYPE_P2P_GO
:
2289 wl_set_mode_by_netdev(cfg
, ndev
, mode
);
2290 if (is_p2p_group_iface(ndev
->ieee80211_ptr
) &&
2291 cfg
->p2p
&& wl_cfgp2p_vif_created(cfg
)) {
2292 WL_DBG(("p2p_vif_created p2p_on (%d)\n", p2p_on(cfg
)));
2293 wl_notify_escan_complete(cfg
, ndev
, true, true);
2295 /* Dual p2p doesn't support multiple P2PGO interfaces,
2296 * p2p_go_count is the counter for GO creation
2299 if ((cfg
->p2p
->p2p_go_count
> 0) && (type
== NL80211_IFTYPE_P2P_GO
)) {
2300 wl_set_mode_by_netdev(cfg
, ndev
, WL_MODE_BSS
);
2301 WL_ERR(("Fw does not support multiple GO\n"));
2305 /* In concurrency case, STA may be already associated in a particular
2306 * channel. so retrieve the current channel of primary interface and
2307 * then start the virtual interface on that.
2309 chspec
= wl_cfg80211_get_shared_freq(wiphy
);
2310 index
= wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
);
2312 WL_ERR(("Find p2p index from ndev(%p) failed\n", ndev
));
2316 if (wl_cfgp2p_find_type(cfg
, index
, &conn_idx
) != BCME_OK
) {
2321 wlif_type
= WL_P2P_IF_GO
;
2322 printf("%s: %s ap (%d), infra_ibss (%d), iftype (%d) conn_idx (%d)\n",
2323 __FUNCTION__
, ndev
->name
, ap
, infra_ibss
, type
, conn_idx
);
2324 wl_set_p2p_status(cfg
, IF_CHANGING
);
2325 wl_clr_p2p_status(cfg
, IF_CHANGED
);
2326 wl_cfgp2p_ifchange(cfg
, wl_to_p2p_bss_macaddr(cfg
, conn_idx
),
2327 htod32(wlif_type
), chspec
, conn_idx
);
2328 wait_event_interruptible_timeout(cfg
->netif_change_event
,
2329 (wl_get_p2p_status(cfg
, IF_CHANGED
) == true),
2330 msecs_to_jiffies(MAX_WAIT_TIME
));
2331 wl_set_mode_by_netdev(cfg
, ndev
, mode
);
2332 dhd
->op_mode
&= ~DHD_FLAG_P2P_GC_MODE
;
2333 dhd
->op_mode
|= DHD_FLAG_P2P_GO_MODE
;
2334 wl_clr_p2p_status(cfg
, IF_CHANGING
);
2335 wl_clr_p2p_status(cfg
, IF_CHANGED
);
2336 if (mode
== WL_MODE_AP
)
2337 wl_set_drv_status(cfg
, CONNECTED
, ndev
);
2338 #ifdef SUPPORT_AP_POWERSAVE
2339 dhd_set_ap_powersave(dhd
, 0, TRUE
);
2340 #endif /* SUPPORT_AP_POWERSAVE */
2341 } else if ((type
== NL80211_IFTYPE_AP
) &&
2342 !wl_get_drv_status(cfg
, AP_CREATED
, ndev
)) {
2344 err
= wl_cfg80211_set_ap_role(cfg
, ndev
);
2345 if (unlikely(err
)) {
2346 WL_ERR(("set ap role failed!\n"));
2350 wl_set_drv_status(cfg
, AP_CREATING
, ndev
);
2353 WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
2358 /* P2P GO interface deletion is handled on the basis of role type (AP).
2359 * So avoid changing role for p2p type.
2361 if (ndev
->ieee80211_ptr
->iftype
!= NL80211_IFTYPE_P2P_GO
)
2362 wl_set_mode_by_netdev(cfg
, ndev
, mode
);
2363 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA\n"));
2364 #ifdef SUPPORT_AP_POWERSAVE
2365 dhd_set_ap_powersave(dhd
, 0, FALSE
);
2366 #endif /* SUPPORT_AP_POWERSAVE */
2370 err
= wldev_ioctl_set(ndev
, WLC_SET_INFRA
, &infra_ibss
, sizeof(s32
));
2372 WL_ERR(("SET INFRA/IBSS error %d\n", err
));
2378 WL_DBG(("Setting iftype to %d \n", type
));
2379 ndev
->ieee80211_ptr
->iftype
= type
;
2381 mutex_unlock(&cfg
->if_sync
);
2386 wl_cfg80211_notify_ifadd(struct net_device
*dev
, int ifidx
, char *name
, uint8
*mac
, uint8 bssidx
)
2388 bool ifadd_expected
= FALSE
;
2389 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
2391 /* P2P may send WLC_E_IF_ADD and/or WLC_E_IF_CHANGE during IF updating ("p2p_ifupd")
2392 * redirect the IF_ADD event to ifchange as it is not a real "new" interface
2394 if (wl_get_p2p_status(cfg
, IF_CHANGING
))
2395 return wl_cfg80211_notify_ifchange(dev
, ifidx
, name
, mac
, bssidx
);
2397 /* Okay, we are expecting IF_ADD (as IF_ADDING is true) */
2398 if (wl_get_p2p_status(cfg
, IF_ADDING
)) {
2399 ifadd_expected
= TRUE
;
2400 wl_clr_p2p_status(cfg
, IF_ADDING
);
2401 } else if (cfg
->bss_pending_op
) {
2402 ifadd_expected
= TRUE
;
2403 cfg
->bss_pending_op
= FALSE
;
2406 if (ifadd_expected
) {
2407 wl_if_event_info
*if_event_info
= &cfg
->if_event_info
;
2409 if_event_info
->valid
= TRUE
;
2410 if_event_info
->ifidx
= ifidx
;
2411 if_event_info
->bssidx
= bssidx
;
2412 strncpy(if_event_info
->name
, name
, IFNAMSIZ
);
2413 if_event_info
->name
[IFNAMSIZ
] = '\0';
2415 memcpy(if_event_info
->mac
, mac
, ETHER_ADDR_LEN
);
2416 wake_up_interruptible(&cfg
->netif_change_event
);
2424 wl_cfg80211_notify_ifdel(struct net_device
*dev
, int ifidx
, char *name
, uint8
*mac
, uint8 bssidx
)
2426 bool ifdel_expected
= FALSE
;
2427 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
2428 wl_if_event_info
*if_event_info
= &cfg
->if_event_info
;
2430 if (wl_get_p2p_status(cfg
, IF_DELETING
)) {
2431 ifdel_expected
= TRUE
;
2432 wl_clr_p2p_status(cfg
, IF_DELETING
);
2433 } else if (cfg
->bss_pending_op
) {
2434 ifdel_expected
= TRUE
;
2435 cfg
->bss_pending_op
= FALSE
;
2438 if (ifdel_expected
) {
2439 if_event_info
->valid
= TRUE
;
2440 if_event_info
->ifidx
= ifidx
;
2441 if_event_info
->bssidx
= bssidx
;
2442 wake_up_interruptible(&cfg
->netif_change_event
);
2450 wl_cfg80211_notify_ifchange(struct net_device
* dev
, int ifidx
, char *name
, uint8
*mac
,
2453 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
2455 if (wl_get_p2p_status(cfg
, IF_CHANGING
)) {
2456 wl_set_p2p_status(cfg
, IF_CHANGED
);
2457 wake_up_interruptible(&cfg
->netif_change_event
);
2464 static s32
wl_cfg80211_handle_ifdel(struct bcm_cfg80211
*cfg
, wl_if_event_info
*if_event_info
,
2465 struct net_device
* ndev
)
2469 #ifdef PROP_TXSTATUS_VSDB
2470 #if defined(BCMSDIO) || defined(BCMDBUS)
2471 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
2473 #endif /* BCMSDIO || BCMDBUS */
2474 #endif /* PROP_TXSTATUS_VSDB */
2476 bssidx
= if_event_info
->bssidx
;
2477 if (bssidx
!= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_CONNECTION1
) &&
2478 bssidx
!= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_CONNECTION2
)) {
2479 WL_ERR(("got IF_DEL for if %d, not owned by cfg driver\n", bssidx
));
2483 if (p2p_is_on(cfg
) && wl_cfgp2p_vif_created(cfg
)) {
2484 if (cfg
->scan_request
&& (cfg
->escan_info
.ndev
== ndev
)) {
2485 /* Abort any pending scan requests */
2486 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
2487 WL_DBG(("ESCAN COMPLETED\n"));
2488 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, true, false);
2491 memset(cfg
->p2p
->vir_ifname
, '\0', IFNAMSIZ
);
2492 if (wl_cfgp2p_find_type(cfg
, bssidx
, &type
) == BCME_OK
) {
2493 /* Update P2P data */
2494 wl_clr_drv_status(cfg
, CONNECTED
, wl_to_p2p_bss_ndev(cfg
, type
));
2495 wl_to_p2p_bss_ndev(cfg
, type
) = NULL
;
2496 wl_to_p2p_bss_bssidx(cfg
, type
) = -1;
2497 } else if (wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
) < 0) {
2498 WL_ERR(("bssidx not known for the given ndev as per net_info data \n"));
2502 #ifdef PROP_TXSTATUS_VSDB
2503 #if defined(BCMSDIO) || defined(BCMDBUS)
2504 dhd_wlfc_get_enable(dhd
, &enabled
);
2505 if (enabled
&& cfg
->wlfc_on
&& dhd
->op_mode
!= DHD_FLAG_HOSTAP_MODE
&&
2506 dhd
->op_mode
!= DHD_FLAG_IBSS_MODE
&& dhd
->conf
->disable_proptx
!=0) {
2507 dhd_wlfc_deinit(dhd
);
2508 cfg
->wlfc_on
= false;
2510 #endif /* BCMSDIO || BCMDBUS */
2511 #endif /* PROP_TXSTATUS_VSDB */
2514 dhd_net_if_lock(ndev
);
2515 wl_cfg80211_remove_if(cfg
, if_event_info
->ifidx
, ndev
, FALSE
);
2516 dhd_net_if_unlock(ndev
);
2521 /* Find listen channel */
2522 static s32
wl_find_listen_channel(struct bcm_cfg80211
*cfg
,
2523 const u8
*ie
, u32 ie_len
)
2525 wifi_p2p_ie_t
*p2p_ie
;
2529 /* unfortunately const cast required here - function is
2530 * a callback so its signature must not be changed
2531 * and cascade of changing wl_cfgp2p_find_p2pie
2532 * causes need for const cast in other places
2534 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2535 4 && __GNUC_MINOR__ >= 6))
2536 _Pragma("GCC diagnostic push")
2537 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
2540 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2541 4 && __GNUC_MINOR__ >= 6))
2542 _Pragma("GCC diagnostic pop")
2544 p2p_ie
= wl_cfgp2p_find_p2pie(pos
, ie_len
);
2549 pos
= p2p_ie
->subelts
;
2550 end
= p2p_ie
->subelts
+ (p2p_ie
->len
- 4);
2552 CFGP2P_DBG((" found p2p ie ! lenth %d \n",
2557 if (pos
+ 2 >= end
) {
2558 CFGP2P_DBG((" -- Invalid P2P attribute"));
2561 attr_len
= ((uint16
) (((pos
+ 1)[1] << 8) | (pos
+ 1)[0]));
2563 if (pos
+ 3 + attr_len
> end
) {
2564 CFGP2P_DBG(("P2P: Attribute underflow "
2566 attr_len
, (int) (end
- pos
- 3)));
2570 /* if Listen Channel att id is 6 and the vailue is valid,
2571 * return the listen channel
2574 /* listen channel subel length format
2575 * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
2577 listen_channel
= pos
[1 + 2 + 3 + 1];
2579 if (listen_channel
== SOCIAL_CHAN_1
||
2580 listen_channel
== SOCIAL_CHAN_2
||
2581 listen_channel
== SOCIAL_CHAN_3
) {
2582 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel
));
2583 return listen_channel
;
2586 pos
+= 3 + attr_len
;
2591 static void wl_scan_prep(struct bcm_cfg80211
*cfg
, struct wl_scan_params
*params
,
2592 struct cfg80211_scan_request
*request
)
2597 chanspec_t chanspec
;
2598 s32 i
= 0, j
= 0, offset
;
2601 struct wireless_dev
*wdev
;
2603 memcpy(¶ms
->bssid
, ðer_bcast
, ETHER_ADDR_LEN
);
2604 params
->bss_type
= DOT11_BSSTYPE_ANY
;
2605 params
->scan_type
= 0;
2606 params
->nprobes
= -1;
2607 params
->active_time
= -1;
2608 params
->passive_time
= -1;
2609 params
->home_time
= -1;
2610 params
->channel_num
= 0;
2611 memset(¶ms
->ssid
, 0, sizeof(wlc_ssid_t
));
2613 WL_SCAN(("Preparing Scan request\n"));
2614 WL_SCAN(("nprobes=%d\n", params
->nprobes
));
2615 WL_SCAN(("active_time=%d\n", params
->active_time
));
2616 WL_SCAN(("passive_time=%d\n", params
->passive_time
));
2617 WL_SCAN(("home_time=%d\n", params
->home_time
));
2618 WL_SCAN(("scan_type=%d\n", params
->scan_type
));
2620 params
->nprobes
= htod32(params
->nprobes
);
2621 params
->active_time
= htod32(params
->active_time
);
2622 params
->passive_time
= htod32(params
->passive_time
);
2623 params
->home_time
= htod32(params
->home_time
);
2625 /* if request is null just exit so it will be all channel broadcast scan */
2629 n_ssids
= request
->n_ssids
;
2630 n_channels
= request
->n_channels
;
2632 /* Copy channel array if applicable */
2633 WL_SCAN(("### List of channelspecs to scan ###\n"));
2634 if (n_channels
> 0) {
2635 for (i
= 0; i
< n_channels
; i
++) {
2636 channel
= ieee80211_frequency_to_channel(request
->channels
[i
]->center_freq
);
2637 /* SKIP DFS channels for Secondary interface */
2638 if ((cfg
->escan_info
.ndev
!= bcmcfg_to_prmry_ndev(cfg
)) &&
2639 (request
->channels
[i
]->flags
&
2640 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
2641 (IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_PASSIVE_SCAN
)))
2643 (IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IR
)))
2644 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
2646 if (!dhd_conf_match_channel(cfg
->pub
, channel
))
2649 #if defined(WL_CFG80211_P2P_DEV_IF)
2650 wdev
= request
->wdev
;
2652 wdev
= request
->dev
->ieee80211_ptr
;
2653 #endif /* WL_CFG80211_P2P_DEV_IF */
2654 chanspec
= wl_cfg80211_ulb_get_min_bw_chspec(cfg
, wdev
, -1);
2655 if (chanspec
== INVCHANSPEC
) {
2656 WL_ERR(("Invalid chanspec! Skipping channel\n"));
2660 if (request
->channels
[i
]->band
== IEEE80211_BAND_2GHZ
) {
2661 chanspec
|= WL_CHANSPEC_BAND_2G
;
2663 chanspec
|= WL_CHANSPEC_BAND_5G
;
2665 params
->channel_list
[j
] = channel
;
2666 params
->channel_list
[j
] &= WL_CHANSPEC_CHAN_MASK
;
2667 params
->channel_list
[j
] |= chanspec
;
2668 WL_SCAN(("Chan : %d, Channel spec: %x \n",
2669 channel
, params
->channel_list
[j
]));
2670 params
->channel_list
[j
] = wl_chspec_host_to_driver(params
->channel_list
[j
]);
2674 WL_SCAN(("Scanning all channels\n"));
2677 /* Copy ssid array if applicable */
2678 WL_SCAN(("### List of SSIDs to scan ###\n"));
2680 offset
= offsetof(wl_scan_params_t
, channel_list
) + n_channels
* sizeof(u16
);
2681 offset
= roundup(offset
, sizeof(u32
));
2682 ptr
= (char*)params
+ offset
;
2683 for (i
= 0; i
< n_ssids
; i
++) {
2684 memset(&ssid
, 0, sizeof(wlc_ssid_t
));
2685 ssid
.SSID_len
= MIN(request
->ssids
[i
].ssid_len
, DOT11_MAX_SSID_LEN
);
2686 memcpy(ssid
.SSID
, request
->ssids
[i
].ssid
, ssid
.SSID_len
);
2688 WL_SCAN(("%d: Broadcast scan\n", i
));
2690 WL_SCAN(("%d: scan for %s size =%d\n", i
,
2691 ssid
.SSID
, ssid
.SSID_len
));
2692 memcpy(ptr
, &ssid
, sizeof(wlc_ssid_t
));
2693 ptr
+= sizeof(wlc_ssid_t
);
2696 WL_SCAN(("Broadcast scan\n"));
2698 /* Adding mask to channel numbers */
2699 params
->channel_num
=
2700 htod32((n_ssids
<< WL_SCAN_PARAMS_NSSID_SHIFT
) |
2701 (n_channels
& WL_SCAN_PARAMS_COUNT_MASK
));
2703 if (n_channels
== 1) {
2704 params
->active_time
= htod32(WL_SCAN_CONNECT_DWELL_TIME_MS
);
2705 params
->nprobes
= htod32(params
->active_time
/ WL_SCAN_JOIN_PROBE_INTERVAL_MS
);
2710 wl_get_valid_channels(struct net_device
*ndev
, u8
*valid_chan_list
, s32 size
)
2712 wl_uint32_list_t
*list
;
2714 if (valid_chan_list
== NULL
|| size
<= 0)
2717 memset(valid_chan_list
, 0, size
);
2718 list
= (wl_uint32_list_t
*)(void *) valid_chan_list
;
2719 list
->count
= htod32(WL_NUMCHANNELS
);
2720 err
= wldev_ioctl_get(ndev
, WLC_GET_VALID_CHANNELS
, valid_chan_list
, size
);
2722 WL_ERR(("get channels failed with %d\n", err
));
2728 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2729 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
2730 bool g_first_broadcast_scan
= TRUE
;
2734 wl_run_escan(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
2735 struct cfg80211_scan_request
*request
, uint16 action
)
2740 s32 params_size
= (WL_SCAN_PARAMS_FIXED_SIZE
+ OFFSETOF(wl_escan_params_t
, params
));
2741 wl_escan_params_t
*params
= NULL
;
2742 u8 chan_buf
[sizeof(u32
)*(WL_NUMCHANNELS
+ 1)];
2746 s32 search_state
= WL_P2P_DISC_ST_SCAN
;
2747 u32 i
, j
, n_nodfs
= 0;
2748 u16
*default_chan_list
= NULL
;
2749 wl_uint32_list_t
*list
;
2751 struct net_device
*dev
= NULL
;
2752 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2753 bool is_first_init_2g_scan
= false;
2755 p2p_scan_purpose_t p2p_scan_purpose
= P2P_SCAN_PURPOSE_MIN
;
2759 WL_DBG(("Enter \n"));
2761 /* scan request can come with empty request : perform all default scan */
2766 if (!cfg
->p2p_supported
|| !p2p_scan(cfg
)) {
2767 /* LEGACY SCAN TRIGGER */
2768 WL_SCAN((" LEGACY E-SCAN START\n"));
2770 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2775 if (ndev
== bcmcfg_to_prmry_ndev(cfg
) && g_first_broadcast_scan
== true) {
2776 is_first_init_2g_scan
= true;
2777 g_first_broadcast_scan
= false;
2781 /* if scan request is not empty parse scan request paramters */
2782 if (request
!= NULL
) {
2783 n_channels
= request
->n_channels
;
2784 n_ssids
= request
->n_ssids
;
2786 /* If n_channels is odd, add a padd of u16 */
2787 params_size
+= sizeof(u16
) * (n_channels
+ 1);
2789 params_size
+= sizeof(u16
) * n_channels
;
2791 /* Allocate space for populating ssids in wl_escan_params_t struct */
2792 params_size
+= sizeof(struct wlc_ssid
) * n_ssids
;
2794 params
= (wl_escan_params_t
*) kzalloc(params_size
, GFP_KERNEL
);
2795 if (params
== NULL
) {
2799 wl_scan_prep(cfg
, ¶ms
->params
, request
);
2801 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2802 /* Override active_time to reduce scan time if it's first bradcast scan. */
2803 if (is_first_init_2g_scan
)
2804 params
->params
.active_time
= FIRST_SCAN_ACTIVE_DWELL_TIME_MS
;
2807 params
->version
= htod32(ESCAN_REQ_VERSION
);
2808 params
->action
= htod16(action
);
2809 wl_escan_set_sync_id(params
->sync_id
, cfg
);
2810 wl_escan_set_type(cfg
, WL_SCANTYPE_LEGACY
);
2811 if (params_size
+ sizeof("escan") >= WLC_IOCTL_MEDLEN
) {
2812 WL_ERR(("ioctl buffer length not sufficient\n"));
2817 if (cfg
->active_scan
== PASSIVE_SCAN
) {
2818 params
->params
.scan_type
= DOT11_SCANTYPE_PASSIVE
;
2819 WL_DBG(("Passive scan_type %d \n", params
->params
.scan_type
));
2822 bssidx
= wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
);
2824 err
= wldev_iovar_setbuf(ndev
, "escan", params
, params_size
,
2825 cfg
->escan_ioctl_buf
, WLC_IOCTL_MEDLEN
, NULL
);
2826 printf("%s: LEGACY_SCAN sync ID: %d, bssidx: %d\n", __FUNCTION__
, params
->sync_id
, bssidx
);
2827 if (unlikely(err
)) {
2828 if (err
== BCME_EPERM
)
2829 /* Scan Not permitted at this point of time */
2830 WL_DBG((" Escan not permitted at this time (%d)\n", err
));
2832 WL_ERR((" Escan set error (%d)\n", err
));
2834 DBG_EVENT_LOG((dhd_pub_t
*)cfg
->pub
, WIFI_EVENT_DRIVER_SCAN_REQUESTED
);
2838 else if (p2p_is_on(cfg
) && p2p_scan(cfg
)) {
2839 /* P2P SCAN TRIGGER */
2842 if (request
&& request
->n_channels
) {
2843 num_chans
= request
->n_channels
;
2844 WL_SCAN((" chann number : %d\n", num_chans
));
2845 default_chan_list
= kzalloc(num_chans
* sizeof(*default_chan_list
),
2847 if (default_chan_list
== NULL
) {
2848 WL_ERR(("channel list allocation failed \n"));
2852 if (!wl_get_valid_channels(ndev
, chan_buf
, sizeof(chan_buf
))) {
2854 int is_printed
= false;
2855 #endif /* P2P_SKIP_DFS */
2856 list
= (wl_uint32_list_t
*) chan_buf
;
2857 n_valid_chan
= dtoh32(list
->count
);
2858 if (n_valid_chan
> WL_NUMCHANNELS
) {
2859 WL_ERR(("wrong n_valid_chan:%d\n", n_valid_chan
));
2860 kfree(default_chan_list
);
2865 for (i
= 0; i
< num_chans
; i
++)
2867 _freq
= request
->channels
[i
]->center_freq
;
2868 channel
= ieee80211_frequency_to_channel(_freq
);
2870 /* ignore DFS channels */
2871 if (request
->channels
[i
]->flags
&
2872 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2873 (IEEE80211_CHAN_NO_IR
2874 | IEEE80211_CHAN_RADAR
))
2876 (IEEE80211_CHAN_RADAR
2877 | IEEE80211_CHAN_PASSIVE_SCAN
))
2881 if (channel
>= 52 && channel
<= 144) {
2882 if (is_printed
== false) {
2883 WL_ERR(("SKIP DFS CHANs(52~144)\n"));
2888 #endif /* P2P_SKIP_DFS */
2890 for (j
= 0; j
< n_valid_chan
; j
++) {
2891 /* allows only supported channel on
2894 if (n_nodfs
>= num_chans
) {
2897 if (channel
== (dtoh32(list
->element
[j
]))) {
2898 default_chan_list
[n_nodfs
++] =
2905 if (num_chans
== SOCIAL_CHAN_CNT
&& (
2906 (default_chan_list
[0] == SOCIAL_CHAN_1
) &&
2907 (default_chan_list
[1] == SOCIAL_CHAN_2
) &&
2908 (default_chan_list
[2] == SOCIAL_CHAN_3
))) {
2909 /* SOCIAL CHANNELS 1, 6, 11 */
2910 search_state
= WL_P2P_DISC_ST_SEARCH
;
2911 p2p_scan_purpose
= P2P_SCAN_SOCIAL_CHANNEL
;
2912 WL_INFORM(("P2P SEARCH PHASE START \n"));
2913 } else if (((dev
= wl_to_p2p_bss_ndev(cfg
, P2PAPI_BSSCFG_CONNECTION1
)) &&
2914 (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
)) ||
2915 ((dev
= wl_to_p2p_bss_ndev(cfg
, P2PAPI_BSSCFG_CONNECTION2
)) &&
2916 (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
))) {
2917 /* If you are already a GO, then do SEARCH only */
2918 WL_INFORM(("Already a GO. Do SEARCH Only"));
2919 search_state
= WL_P2P_DISC_ST_SEARCH
;
2920 num_chans
= n_nodfs
;
2921 p2p_scan_purpose
= P2P_SCAN_NORMAL
;
2923 } else if (num_chans
== 1) {
2924 p2p_scan_purpose
= P2P_SCAN_CONNECT_TRY
;
2925 } else if (num_chans
== SOCIAL_CHAN_CNT
+ 1) {
2926 /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2929 p2p_scan_purpose
= P2P_SCAN_SOCIAL_CHANNEL
;
2931 WL_INFORM(("P2P SCAN STATE START \n"));
2932 num_chans
= n_nodfs
;
2933 p2p_scan_purpose
= P2P_SCAN_NORMAL
;
2939 err
= wl_cfgp2p_escan(cfg
, ndev
, ACTIVE_SCAN
, num_chans
, default_chan_list
,
2940 search_state
, action
,
2941 wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
), NULL
,
2945 cfg
->p2p
->search_state
= search_state
;
2947 kfree(default_chan_list
);
2950 if (unlikely(err
)) {
2952 wldev_ioctl(dev
, WLC_GET_SCANSUPPRESS
, &suppressed
, sizeof(int), false);
2953 /* Don't print Error incase of Scan suppress */
2954 if ((err
== BCME_EPERM
) && (cfg
->scan_suppressed
|| suppressed
)) {
2956 WL_DBG(("Escan failed: Scan Suppressed \n"));
2959 WL_ERR(("error (%d), cnt=%d\n", err
, cnt
));
2960 // terence 20140111: send disassoc to firmware
2962 dev
= bcmcfg_to_prmry_ndev(cfg
);
2963 memset(&scbval
, 0, sizeof(scb_val_t
));
2964 wldev_ioctl(dev
, WLC_DISASSOC
, &scbval
, sizeof(scb_val_t
), true);
2965 WL_ERR(("Send disassoc to break the busy dev=%p\n", dev
));
2977 wl_do_escan(struct bcm_cfg80211
*cfg
, struct wiphy
*wiphy
, struct net_device
*ndev
,
2978 struct cfg80211_scan_request
*request
)
2981 s32 passive_scan
= 0;
2982 s32 passive_scan_time
= 0;
2983 s32 passive_scan_time_org
= 0;
2984 wl_scan_results_t
*results
;
2985 WL_SCAN(("Enter \n"));
2987 results
= wl_escan_get_buf(cfg
, FALSE
);
2988 results
->version
= 0;
2990 results
->buflen
= WL_SCAN_RESULTS_FIXED_SIZE
;
2992 cfg
->escan_info
.ndev
= ndev
;
2993 cfg
->escan_info
.wiphy
= wiphy
;
2994 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_SCANING
;
2995 passive_scan
= cfg
->active_scan
? 0 : 1;
2996 err
= wldev_ioctl_set(ndev
, WLC_SET_PASSIVE_SCAN
,
2997 &passive_scan
, sizeof(passive_scan
));
2998 if (unlikely(err
)) {
2999 WL_ERR(("error (%d)\n", err
));
3003 if (passive_channel_skip
) {
3005 err
= wldev_ioctl_get(ndev
, WLC_GET_SCAN_PASSIVE_TIME
,
3006 &passive_scan_time_org
, sizeof(passive_scan_time_org
));
3007 if (unlikely(err
)) {
3008 WL_ERR(("== error (%d)\n", err
));
3012 WL_SCAN(("PASSIVE SCAN time : %d \n", passive_scan_time_org
));
3014 passive_scan_time
= 0;
3015 err
= wldev_ioctl_set(ndev
, WLC_SET_SCAN_PASSIVE_TIME
,
3016 &passive_scan_time
, sizeof(passive_scan_time
));
3017 if (unlikely(err
)) {
3018 WL_ERR(("== error (%d)\n", err
));
3022 WL_SCAN(("PASSIVE SCAN SKIPED!! (passive_channel_skip:%d) \n",
3023 passive_channel_skip
));
3026 err
= wl_run_escan(cfg
, ndev
, request
, WL_SCAN_ACTION_START
);
3028 if (passive_channel_skip
) {
3029 err
= wldev_ioctl_set(ndev
, WLC_SET_SCAN_PASSIVE_TIME
,
3030 &passive_scan_time_org
, sizeof(passive_scan_time_org
));
3031 if (unlikely(err
)) {
3032 WL_ERR(("== error (%d)\n", err
));
3036 WL_SCAN(("PASSIVE SCAN RECOVERED!! (passive_scan_time_org:%d) \n",
3037 passive_scan_time_org
));
3045 __wl_cfg80211_scan(struct wiphy
*wiphy
, struct net_device
*ndev
,
3046 struct cfg80211_scan_request
*request
,
3047 struct cfg80211_ssid
*this_ssid
)
3049 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3050 struct cfg80211_ssid
*ssids
;
3051 struct ether_addr primary_mac
;
3054 bcm_tlv_t
*interworking_ie
;
3060 unsigned long flags
;
3061 static s32 busy_count
= 0;
3062 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
3063 struct net_device
*remain_on_channel_ndev
= NULL
;
3065 uint scan_timer_interval_ms
= WL_SCAN_TIMER_INTERVAL_MS
;
3068 * Hostapd triggers scan before starting automatic channel selection
3069 * to collect channel characteristics. However firmware scan engine
3070 * doesn't support any channel characteristics collection along with
3071 * scan. Hence return scan success.
3073 if (request
&& (scan_req_iftype(request
) == NL80211_IFTYPE_AP
)) {
3074 WL_INFORM(("Scan Command on SoftAP Interface. Ignoring...\n"));
3075 // terence 20161023: let it scan in SoftAP mode
3079 ndev
= ndev_to_wlc_ndev(ndev
, cfg
);
3081 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg
)) {
3082 WL_ERR(("Sending Action Frames. Try it again.\n"));
3086 WL_DBG(("Enter wiphy (%p)\n", wiphy
));
3087 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
3088 if (cfg
->scan_request
== NULL
) {
3089 wl_clr_drv_status_all(cfg
, SCANNING
);
3090 WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
3092 WL_ERR(("Scanning already\n"));
3096 if (wl_get_drv_status(cfg
, SCAN_ABORTING
, ndev
)) {
3097 WL_ERR(("Scanning being aborted\n"));
3100 if (request
&& request
->n_ssids
> WL_SCAN_PARAMS_SSID_MAX
) {
3101 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
3105 #ifdef P2P_LISTEN_OFFLOADING
3106 if (wl_get_p2p_status(cfg
, DISC_IN_PROGRESS
)) {
3107 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
3110 #endif /* P2P_LISTEN_OFFLOADING */
3112 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
3113 remain_on_channel_ndev
= wl_cfg80211_get_remain_on_channel_ndev(cfg
);
3114 if (remain_on_channel_ndev
) {
3115 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
3116 wl_notify_escan_complete(cfg
, remain_on_channel_ndev
, true, true);
3118 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
3121 /* Arm scan timeout timer */
3122 mod_timer(&cfg
->scan_timeout
, jiffies
+ msecs_to_jiffies(scan_timer_interval_ms
));
3123 if (request
) { /* scan bss */
3124 ssids
= request
->ssids
;
3126 for (i
= 0; i
< request
->n_ssids
; i
++) {
3127 if (ssids
[i
].ssid_len
&&
3128 IS_P2P_SSID(ssids
[i
].ssid
, ssids
[i
].ssid_len
)) {
3134 if (cfg
->p2p_supported
) {
3135 /* p2p scan trigger */
3136 if (p2p_on(cfg
) == false) {
3137 /* p2p on at the first time */
3139 wl_cfgp2p_set_firm_p2p(cfg
);
3140 get_primary_mac(cfg
, &primary_mac
);
3141 wl_cfgp2p_generate_bss_mac(cfg
, &primary_mac
);
3142 #if defined(P2P_IE_MISSING_FIX)
3143 cfg
->p2p_prb_noti
= false;
3146 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
3147 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
3148 p2p_scan(cfg
) = true;
3151 /* legacy scan trigger
3152 * So, we have to disable p2p discovery if p2p discovery is on
3154 if (cfg
->p2p_supported
) {
3155 p2p_scan(cfg
) = false;
3156 /* If Netdevice is not equals to primary and p2p is on
3157 * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
3160 if (p2p_scan(cfg
) == false) {
3161 if (wl_get_p2p_status(cfg
, DISCOVERY_ON
)) {
3162 err
= wl_cfgp2p_discover_enable_search(cfg
,
3164 if (unlikely(err
)) {
3171 if (!cfg
->p2p_supported
|| !p2p_scan(cfg
)) {
3172 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
,
3173 ndev
->ieee80211_ptr
)) < 0) {
3174 WL_ERR(("Find p2p index from ndev(%p) failed\n",
3180 if (request
&& (interworking_ie
=
3181 wl_cfg80211_find_interworking_ie(
3182 request
->ie
, request
->ie_len
)) != NULL
) {
3183 if ((err
= wl_cfg80211_add_iw_ie(cfg
, ndev
, bssidx
,
3184 VNDR_IE_CUSTOM_FLAG
, interworking_ie
->id
,
3185 interworking_ie
->data
,
3186 interworking_ie
->len
)) != BCME_OK
) {
3187 WL_ERR(("Failed to add interworking IE"));
3189 } else if (cfg
->wl11u
) {
3190 /* we have to clear IW IE and disable gratuitous APR */
3191 wl_cfg80211_clear_iw_ie(cfg
, ndev
, bssidx
);
3192 err
= wldev_iovar_setint_bsscfg(ndev
, "grat_arp",
3194 /* we don't care about error here
3195 * because the only failure case is unsupported,
3198 if (unlikely(err
)) {
3199 WL_ERR(("Set grat_arp failed:(%d) Ignore!\n", err
));
3205 err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
,
3206 ndev_to_cfgdev(ndev
),
3207 bssidx
, VNDR_IE_PRBREQ_FLAG
, request
->ie
,
3211 if (unlikely(err
)) {
3212 // terence 20161023: let it scan in SoftAP mode
3218 } else { /* scan in ibss */
3222 if (request
&& cfg
->p2p_supported
) {
3223 WL_TRACE_HW4(("START SCAN\n"));
3224 DHD_OS_SCAN_WAKE_LOCK_TIMEOUT((dhd_pub_t
*)(cfg
->pub
),
3225 SCAN_WAKE_LOCK_TIMEOUT
);
3226 DHD_DISABLE_RUNTIME_PM((dhd_pub_t
*)(cfg
->pub
));
3229 if (cfg
->p2p_supported
) {
3230 if (request
&& p2p_on(cfg
) && p2p_scan(cfg
)) {
3232 /* find my listen channel */
3233 cfg
->afx_hdl
->my_listen_chan
=
3234 wl_find_listen_channel(cfg
, request
->ie
,
3236 err
= wl_cfgp2p_enable_discovery(cfg
, ndev
,
3237 request
->ie
, request
->ie_len
);
3239 if (unlikely(err
)) {
3244 err
= wl_do_escan(cfg
, wiphy
, ndev
, request
);
3252 cfg
->scan_request
= request
;
3253 wl_set_drv_status(cfg
, SCANNING
, ndev
);
3258 if (err
== BCME_BUSY
|| err
== BCME_NOTREADY
) {
3259 WL_ERR(("Scan err = (%d), busy?%d", err
, -EBUSY
));
3261 } else if ((err
== BCME_EPERM
) && cfg
->scan_suppressed
) {
3262 WL_ERR(("Scan not permitted due to scan suppress\n"));
3265 /* For all other fw errors, use a generic error code as return
3266 * value to cfg80211 stack
3271 #define SCAN_EBUSY_RETRY_LIMIT 20
3272 if (err
== -EBUSY
) {
3273 if (busy_count
++ > SCAN_EBUSY_RETRY_LIMIT
) {
3274 struct ether_addr bssid
;
3276 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
3277 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
3278 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
3280 WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
3281 wl_get_drv_status(cfg
, SCANNING
, ndev
),
3282 wl_get_drv_status(cfg
, SCAN_ABORTING
, ndev
),
3283 wl_get_drv_status(cfg
, CONNECTING
, ndev
),
3284 wl_get_drv_status(cfg
, CONNECTED
, ndev
),
3285 wl_get_drv_status(cfg
, DISCONNECTING
, ndev
),
3286 wl_get_drv_status(cfg
, AP_CREATING
, ndev
),
3287 wl_get_drv_status(cfg
, AP_CREATED
, ndev
),
3288 wl_get_drv_status(cfg
, SENDING_ACT_FRM
, ndev
),
3289 wl_get_drv_status(cfg
, SENDING_ACT_FRM
, ndev
)));
3291 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
3292 if (dhdp
->memdump_enabled
) {
3293 dhdp
->memdump_type
= DUMP_TYPE_SCAN_BUSY
;
3294 dhd_bus_mem_dump(dhdp
);
3296 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
3298 bzero(&bssid
, sizeof(bssid
));
3299 if ((ret
= wldev_ioctl_get(ndev
, WLC_GET_BSSID
,
3300 &bssid
, ETHER_ADDR_LEN
)) == 0)
3301 WL_ERR(("FW is connected with " MACDBG
"/n",
3302 MAC2STRDBG(bssid
.octet
)));
3304 WL_ERR(("GET BSSID failed with %d\n", ret
));
3306 wl_cfg80211_scan_abort(cfg
);
3309 /* Hold the context for 400msec, so that 10 subsequent scans
3310 * can give a buffer of 4sec which is enough to
3311 * cover any on-going scan in the firmware
3313 WL_DBG(("Enforcing delay for EBUSY case \n"));
3320 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
3321 if (timer_pending(&cfg
->scan_timeout
))
3322 del_timer_sync(&cfg
->scan_timeout
);
3323 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t
*)(cfg
->pub
));
3324 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
3325 cfg
->scan_request
= NULL
;
3326 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
3332 #if defined(WL_CFG80211_P2P_DEV_IF)
3333 wl_cfg80211_scan(struct wiphy
*wiphy
, struct cfg80211_scan_request
*request
)
3335 wl_cfg80211_scan(struct wiphy
*wiphy
, struct net_device
*ndev
,
3336 struct cfg80211_scan_request
*request
)
3337 #endif /* WL_CFG80211_P2P_DEV_IF */
3340 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3341 #if defined(WL_CFG80211_P2P_DEV_IF)
3342 struct net_device
*ndev
= wdev_to_wlc_ndev(request
->wdev
, cfg
);
3343 #endif /* WL_CFG80211_P2P_DEV_IF */
3345 WL_DBG(("Enter\n"));
3346 RETURN_EIO_IF_NOT_UP(cfg
);
3349 #ifdef WL_CFG80211_P2P_DEV_IF
3350 PRINT_WDEV_INFO(request
->wdev
);
3352 PRINT_WDEV_INFO(ndev
);
3353 #endif /* WL_CFG80211_P2P_DEV_IF */
3354 #endif /* DHD_IFDEBUG */
3356 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
3357 if (wl_cfg_multip2p_operational(cfg
)) {
3358 WL_ERR(("wlan0 scan failed, p2p devices are operational"));
3362 err
= wl_cfg80211_check_in4way(cfg
, ndev
, NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
,
3363 WL_EXT_STATUS_SCAN
, NULL
);
3367 mutex_lock(&cfg
->usr_sync
);
3368 err
= __wl_cfg80211_scan(wiphy
, ndev
, request
, NULL
);
3369 if (unlikely(err
)) {
3370 WL_ERR(("scan error (%d)\n", err
));
3372 mutex_unlock(&cfg
->usr_sync
);
3373 #ifdef WL_DRV_AVOID_SCANCACHE
3374 /* Reset roam cache after successful scan request */
3375 #endif /* WL_DRV_AVOID_SCANCACHE */
3379 static s32
wl_set_rts(struct net_device
*dev
, u32 rts_threshold
)
3383 err
= wldev_iovar_setint(dev
, "rtsthresh", rts_threshold
);
3384 if (unlikely(err
)) {
3385 WL_ERR(("Error (%d)\n", err
));
3391 static s32
wl_set_frag(struct net_device
*dev
, u32 frag_threshold
)
3395 err
= wldev_iovar_setint_bsscfg(dev
, "fragthresh", frag_threshold
, 0);
3396 if (unlikely(err
)) {
3397 WL_ERR(("Error (%d)\n", err
));
3403 static s32
wl_set_retry(struct net_device
*dev
, u32 retry
, bool l
)
3406 u32 cmd
= (l
? WLC_SET_LRL
: WLC_SET_SRL
);
3408 retry
= htod32(retry
);
3409 err
= wldev_ioctl_set(dev
, cmd
, &retry
, sizeof(retry
));
3410 if (unlikely(err
)) {
3411 WL_ERR(("cmd (%d) , error (%d)\n", cmd
, err
));
3417 static s32
wl_cfg80211_set_wiphy_params(struct wiphy
*wiphy
, u32 changed
)
3419 struct bcm_cfg80211
*cfg
= (struct bcm_cfg80211
*)wiphy_priv(wiphy
);
3420 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
3423 RETURN_EIO_IF_NOT_UP(cfg
);
3424 WL_DBG(("Enter\n"));
3425 if (changed
& WIPHY_PARAM_RTS_THRESHOLD
&&
3426 (cfg
->conf
->rts_threshold
!= wiphy
->rts_threshold
)) {
3427 cfg
->conf
->rts_threshold
= wiphy
->rts_threshold
;
3428 err
= wl_set_rts(ndev
, cfg
->conf
->rts_threshold
);
3432 if (changed
& WIPHY_PARAM_FRAG_THRESHOLD
&&
3433 (cfg
->conf
->frag_threshold
!= wiphy
->frag_threshold
)) {
3434 cfg
->conf
->frag_threshold
= wiphy
->frag_threshold
;
3435 err
= wl_set_frag(ndev
, cfg
->conf
->frag_threshold
);
3439 if (changed
& WIPHY_PARAM_RETRY_LONG
&&
3440 (cfg
->conf
->retry_long
!= wiphy
->retry_long
)) {
3441 cfg
->conf
->retry_long
= wiphy
->retry_long
;
3442 err
= wl_set_retry(ndev
, cfg
->conf
->retry_long
, true);
3446 if (changed
& WIPHY_PARAM_RETRY_SHORT
&&
3447 (cfg
->conf
->retry_short
!= wiphy
->retry_short
)) {
3448 cfg
->conf
->retry_short
= wiphy
->retry_short
;
3449 err
= wl_set_retry(ndev
, cfg
->conf
->retry_short
, false);
3450 if (err
!= BCME_OK
) {
3458 channel_to_chanspec(struct wiphy
*wiphy
, struct net_device
*dev
, u32 channel
, u32 bw_cap
)
3460 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3462 wl_uint32_list_t
*list
;
3464 chanspec_t c
= 0, ret_c
= 0;
3465 int bw
= 0, tmp_bw
= 0;
3468 u16 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
3469 #define LOCAL_BUF_SIZE 1024
3470 buf
= (u8
*) kzalloc(LOCAL_BUF_SIZE
, kflags
);
3472 WL_ERR(("buf memory alloc failed\n"));
3476 err
= wldev_iovar_getbuf_bsscfg(dev
, "chanspecs", NULL
,
3477 0, buf
, LOCAL_BUF_SIZE
, 0, &cfg
->ioctl_buf_sync
);
3478 if (err
!= BCME_OK
) {
3479 WL_ERR(("get chanspecs failed with %d\n", err
));
3483 list
= (wl_uint32_list_t
*)(void *)buf
;
3484 for (i
= 0; i
< dtoh32(list
->count
); i
++) {
3485 c
= dtoh32(list
->element
[i
]);
3486 if (channel
<= CH_MAX_2G_CHANNEL
) {
3487 if (!CHSPEC_IS20(c
))
3489 if (channel
== CHSPEC_CHANNEL(c
)) {
3495 tmp_c
= wf_chspec_ctlchan(c
);
3496 tmp_bw
= bw2cap
[CHSPEC_BW(c
) >> WL_CHANSPEC_BW_SHIFT
];
3497 if (tmp_c
!= channel
)
3500 if ((tmp_bw
> bw
) && (tmp_bw
<= bw_cap
)) {
3510 #undef LOCAL_BUF_SIZE
3511 WL_INFORM(("return chanspec %x %d\n", ret_c
, bw
));
3516 wl_cfg80211_ibss_vsie_set_buffer(struct net_device
*dev
, vndr_ie_setbuf_t
*ibss_vsie
,
3519 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
3521 if (cfg
!= NULL
&& ibss_vsie
!= NULL
) {
3522 if (cfg
->ibss_vsie
!= NULL
) {
3523 kfree(cfg
->ibss_vsie
);
3525 cfg
->ibss_vsie
= ibss_vsie
;
3526 cfg
->ibss_vsie_len
= ibss_vsie_len
;
3531 wl_cfg80211_ibss_vsie_free(struct bcm_cfg80211
*cfg
)
3533 /* free & initiralize VSIE (Vendor Specific IE) */
3534 if (cfg
->ibss_vsie
!= NULL
) {
3535 kfree(cfg
->ibss_vsie
);
3536 cfg
->ibss_vsie
= NULL
;
3537 cfg
->ibss_vsie_len
= 0;
3542 wl_cfg80211_ibss_vsie_delete(struct net_device
*dev
)
3544 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
3545 char *ioctl_buf
= NULL
;
3546 s32 ret
= BCME_OK
, bssidx
;
3548 if (cfg
!= NULL
&& cfg
->ibss_vsie
!= NULL
) {
3549 ioctl_buf
= kmalloc(WLC_IOCTL_MEDLEN
, GFP_KERNEL
);
3551 WL_ERR(("ioctl memory alloc failed\n"));
3555 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
3556 WL_ERR(("Find index failed\n"));
3560 /* change the command from "add" to "del" */
3561 strncpy(cfg
->ibss_vsie
->cmd
, "del", VNDR_IE_CMD_LEN
- 1);
3562 cfg
->ibss_vsie
->cmd
[VNDR_IE_CMD_LEN
- 1] = '\0';
3564 ret
= wldev_iovar_setbuf_bsscfg(dev
, "vndr_ie",
3565 cfg
->ibss_vsie
, cfg
->ibss_vsie_len
,
3566 ioctl_buf
, WLC_IOCTL_MEDLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
3567 WL_ERR(("ret=%d\n", ret
));
3569 if (ret
== BCME_OK
) {
3570 /* free & initiralize VSIE */
3571 kfree(cfg
->ibss_vsie
);
3572 cfg
->ibss_vsie
= NULL
;
3573 cfg
->ibss_vsie_len
= 0;
3584 #ifdef WLAIBSS_MCHAN
3585 static bcm_struct_cfgdev
*
3586 bcm_cfg80211_add_ibss_if(struct wiphy
*wiphy
, char *name
)
3589 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3590 struct wireless_dev
* wdev
= NULL
;
3591 struct net_device
*new_ndev
= NULL
;
3592 struct net_device
*primary_ndev
= NULL
;
3594 wl_aibss_if_t aibss_if
;
3595 wl_if_event_info
*event
= NULL
;
3597 if (cfg
->ibss_cfgdev
!= NULL
) {
3598 WL_ERR(("IBSS interface %s already exists\n", name
));
3602 WL_ERR(("Try to create IBSS interface %s\n", name
));
3603 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
3604 /* generate a new MAC address for the IBSS interface */
3605 get_primary_mac(cfg
, &cfg
->ibss_if_addr
);
3606 cfg
->ibss_if_addr
.octet
[4] ^= 0x40;
3607 memset(&aibss_if
, sizeof(aibss_if
), 0);
3608 memcpy(&aibss_if
.addr
, &cfg
->ibss_if_addr
, sizeof(aibss_if
.addr
));
3609 aibss_if
.chspec
= 0;
3610 aibss_if
.len
= sizeof(aibss_if
);
3612 cfg
->bss_pending_op
= TRUE
;
3613 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
3614 err
= wldev_iovar_setbuf(primary_ndev
, "aibss_ifadd", &aibss_if
,
3615 sizeof(aibss_if
), cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
3617 WL_ERR(("IOVAR aibss_ifadd failed with error %d\n", err
));
3620 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
3621 !cfg
->bss_pending_op
, msecs_to_jiffies(MAX_WAIT_TIME
));
3622 if (timeout
<= 0 || cfg
->bss_pending_op
)
3625 event
= &cfg
->if_event_info
;
3626 /* By calling wl_cfg80211_allocate_if (dhd_allocate_if eventually) we give the control
3627 * over this net_device interface to dhd_linux, hence the interface is managed by dhd_liux
3628 * and will be freed by dhd_detach unless it gets unregistered before that. The
3629 * wireless_dev instance new_ndev->ieee80211_ptr associated with this net_device will
3630 * be freed by wl_dealloc_netinfo
3632 new_ndev
= wl_cfg80211_allocate_if(cfg
, event
->ifidx
, event
->name
,
3633 event
->mac
, event
->bssidx
, event
->name
);
3634 if (new_ndev
== NULL
)
3636 wdev
= kzalloc(sizeof(*wdev
), GFP_KERNEL
);
3639 wdev
->wiphy
= wiphy
;
3640 wdev
->iftype
= NL80211_IFTYPE_ADHOC
;
3641 wdev
->netdev
= new_ndev
;
3642 new_ndev
->ieee80211_ptr
= wdev
;
3643 SET_NETDEV_DEV(new_ndev
, wiphy_dev(wdev
->wiphy
));
3645 /* rtnl lock must have been acquired, if this is not the case, wl_cfg80211_register_if
3646 * needs to be modified to take one parameter (bool need_rtnl_lock)
3649 if (wl_cfg80211_register_if(cfg
, event
->ifidx
, new_ndev
, FALSE
) != BCME_OK
)
3652 wl_alloc_netinfo(cfg
, new_ndev
, wdev
, WL_MODE_IBSS
, PM_ENABLE
, event
->bssidx
);
3653 cfg
->ibss_cfgdev
= ndev_to_cfgdev(new_ndev
);
3654 WL_ERR(("IBSS interface %s created\n", new_ndev
->name
));
3655 return cfg
->ibss_cfgdev
;
3658 WL_ERR(("failed to create IBSS interface %s \n", name
));
3659 cfg
->bss_pending_op
= FALSE
;
3661 wl_cfg80211_remove_if(cfg
, event
->ifidx
, new_ndev
, FALSE
);
3668 bcm_cfg80211_del_ibss_if(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
)
3671 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3672 struct net_device
*ndev
= NULL
;
3673 struct net_device
*primary_ndev
= NULL
;
3676 if (!cfgdev
|| cfg
->ibss_cfgdev
!= cfgdev
|| ETHER_ISNULLADDR(&cfg
->ibss_if_addr
.octet
))
3678 ndev
= (struct net_device
*)cfgdev_to_ndev(cfg
->ibss_cfgdev
);
3679 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
3681 cfg
->bss_pending_op
= TRUE
;
3682 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
3683 err
= wldev_iovar_setbuf(primary_ndev
, "aibss_ifdel", &cfg
->ibss_if_addr
,
3684 sizeof(cfg
->ibss_if_addr
), cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
3686 WL_ERR(("IOVAR aibss_ifdel failed with error %d\n", err
));
3689 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
3690 !cfg
->bss_pending_op
, msecs_to_jiffies(MAX_WAIT_TIME
));
3691 if (timeout
<= 0 || cfg
->bss_pending_op
) {
3692 WL_ERR(("timeout in waiting IF_DEL event\n"));
3696 wl_cfg80211_remove_if(cfg
, cfg
->if_event_info
.ifidx
, ndev
, FALSE
);
3697 cfg
->ibss_cfgdev
= NULL
;
3701 cfg
->bss_pending_op
= FALSE
;
3704 #endif /* WLAIBSS_MCHAN */
3708 wl_cfg80211_interface_ops(struct bcm_cfg80211
*cfg
,
3709 struct net_device
*ndev
, s32 bsscfg_idx
,
3710 enum nl80211_iftype iface_type
, s32 del
, u8
*addr
)
3712 wl_interface_create_t iface
;
3714 wl_interface_info_t
*info
;
3716 bzero(&iface
, sizeof(wl_interface_create_t
));
3718 iface
.ver
= WL_INTERFACE_CREATE_VER
;
3720 if (iface_type
== NL80211_IFTYPE_AP
)
3721 iface
.flags
= WL_INTERFACE_CREATE_AP
;
3723 iface
.flags
= WL_INTERFACE_CREATE_STA
;
3726 ret
= wldev_iovar_setbuf(ndev
, "interface_remove",
3727 NULL
, 0, cfg
->ioctl_buf
, WLC_IOCTL_MEDLEN
, NULL
);
3730 memcpy(&iface
.mac_addr
.octet
, addr
, ETH_ALEN
);
3731 iface
.flags
|= WL_INTERFACE_MAC_USE
;
3733 ret
= wldev_iovar_getbuf(ndev
, "interface_create",
3734 &iface
, sizeof(wl_interface_create_t
),
3735 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
3738 info
= (wl_interface_info_t
*)cfg
->ioctl_buf
;
3739 WL_DBG(("wl interface create success!! bssidx:%d \n",
3745 WL_ERR(("Interface %s failed!! ret %d\n",
3746 del
? "remove" : "create", ret
));
3752 wl_cfg80211_interface_ops(struct bcm_cfg80211
*cfg
,
3753 struct net_device
*ndev
, s32 bsscfg_idx
,
3754 enum nl80211_iftype iface_type
, s32 del
, u8
*addr
)
3757 struct wl_interface_create_v2 iface
;
3758 wl_interface_create_v3_t iface_v3
;
3759 struct wl_interface_info_v1
*info
;
3760 wl_interface_info_v2_t
*info_v2
;
3761 enum wl_interface_type iftype
;
3763 bool use_iface_info_v2
= false;
3764 u8 ioctl_buf
[WLC_IOCTL_SMLEN
];
3767 ret
= wldev_iovar_setbuf(ndev
, "interface_remove",
3768 NULL
, 0, ioctl_buf
, sizeof(ioctl_buf
), NULL
);
3770 WL_ERR(("Interface remove failed!! ret %d\n", ret
));
3774 /* Interface create */
3775 bzero(&iface
, sizeof(iface
));
3777 * flags field is still used along with iftype inorder to support the old version of the
3778 * FW work with the latest app changes.
3780 if (iface_type
== NL80211_IFTYPE_AP
) {
3781 iftype
= WL_INTERFACE_TYPE_AP
;
3782 ifflags
= WL_INTERFACE_CREATE_AP
;
3784 iftype
= WL_INTERFACE_TYPE_STA
;
3785 ifflags
= WL_INTERFACE_CREATE_STA
;
3788 ifflags
|= WL_INTERFACE_MAC_USE
;
3791 /* Pass ver = 0 for fetching the interface_create iovar version */
3792 ret
= wldev_iovar_getbuf(ndev
, "interface_create",
3793 &iface
, sizeof(struct wl_interface_create_v2
),
3794 ioctl_buf
, sizeof(ioctl_buf
), NULL
);
3795 if (ret
== BCME_UNSUPPORTED
) {
3796 WL_ERR(("interface_create iovar not supported\n"));
3798 } else if ((ret
== 0) && *((uint32
*)ioctl_buf
) == WL_INTERFACE_CREATE_VER_3
) {
3799 WL_DBG(("interface_create version 3\n"));
3800 use_iface_info_v2
= true;
3801 bzero(&iface_v3
, sizeof(wl_interface_create_v3_t
));
3802 iface_v3
.ver
= WL_INTERFACE_CREATE_VER_3
;
3803 iface_v3
.iftype
= iftype
;
3804 iface_v3
.flags
= ifflags
;
3806 memcpy(&iface_v3
.mac_addr
.octet
, addr
, ETH_ALEN
);
3808 ret
= wldev_iovar_getbuf(ndev
, "interface_create",
3809 &iface_v3
, sizeof(wl_interface_create_v3_t
),
3810 ioctl_buf
, sizeof(ioctl_buf
), NULL
);
3813 /* On any other error, attempt with iovar version 2 */
3814 WL_DBG(("interface_create version 2. get_ver:%d\n", ret
));
3815 iface
.ver
= WL_INTERFACE_CREATE_VER_2
;
3816 iface
.iftype
= iftype
;
3817 iface
.flags
= ifflags
;
3819 memcpy(&iface
.mac_addr
.octet
, addr
, ETH_ALEN
);
3821 ret
= wldev_iovar_getbuf(ndev
, "interface_create",
3822 &iface
, sizeof(struct wl_interface_create_v2
),
3823 ioctl_buf
, sizeof(ioctl_buf
), NULL
);
3827 if (unlikely(ret
)) {
3828 WL_ERR(("Interface create failed!! ret %d\n", ret
));
3833 if (use_iface_info_v2
== true) {
3834 info_v2
= (wl_interface_info_v2_t
*)ioctl_buf
;
3835 ret
= info_v2
->bsscfgidx
;
3838 info
= (struct wl_interface_info_v1
*)ioctl_buf
;
3839 ret
= info
->bsscfgidx
;
3842 WL_DBG(("wl interface create success!! bssidx:%d \n", ret
));
3848 wl_customer6_legacy_chip_check(struct bcm_cfg80211
*cfg
,
3849 struct net_device
*ndev
)
3852 wlc_rev_info_t revinfo
;
3855 /* Get the device rev info */
3856 memset(&revinfo
, 0, sizeof(revinfo
));
3857 ret
= wldev_ioctl_get(ndev
, WLC_GET_REVINFO
, &revinfo
, sizeof(revinfo
));
3859 WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__
, ret
));
3864 WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__
,
3865 dtoh32(revinfo
.deviceid
), dtoh32(revinfo
.vendorid
), dtoh32(revinfo
.chipnum
)));
3866 chipnum
= revinfo
.chipnum
;
3867 if ((chipnum
== BCM4350_CHIP_ID
) || (chipnum
== BCM4355_CHIP_ID
) ||
3868 (chipnum
== BCM4345_CHIP_ID
) || (chipnum
== BCM43430_CHIP_ID
) ||
3869 (chipnum
== BCM43362_CHIP_ID
)) {
3878 wl_bss_iovar_war(struct bcm_cfg80211
*cfg
,
3879 struct net_device
*ndev
, s32
*val
)
3882 wlc_rev_info_t revinfo
;
3884 bool need_war
= false;
3886 /* Get the device rev info */
3887 memset(&revinfo
, 0, sizeof(revinfo
));
3888 ret
= wldev_ioctl_get(ndev
, WLC_GET_REVINFO
, &revinfo
, sizeof(revinfo
));
3890 WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__
, ret
));
3892 WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__
,
3893 dtoh32(revinfo
.deviceid
), dtoh32(revinfo
.vendorid
), dtoh32(revinfo
.chipnum
)));
3894 chipnum
= revinfo
.chipnum
;
3895 if ((chipnum
== BCM4359_CHIP_ID
) || (chipnum
== BCM43596_CHIP_ID
)) {
3901 if (wl_customer6_legacy_chip_check(cfg
, ndev
) || need_war
) {
3902 /* Few firmware branches have issues in bss iovar handling and
3903 * that can't be changed since they are in production.
3905 if (*val
== WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE
) {
3906 *val
= WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE
;
3907 } else if (*val
== WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE
) {
3908 *val
= WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE
;
3910 /* Ignore for other bss enums */
3913 WL_ERR(("wl bss %d\n", *val
));
3918 wl_cfg80211_add_del_bss(struct bcm_cfg80211
*cfg
,
3919 struct net_device
*ndev
, s32 bsscfg_idx
,
3920 enum nl80211_iftype iface_type
, s32 del
, u8
*addr
)
3928 struct ether_addr ea
;
3931 WL_INFORM(("iface_type:%d del:%d \n", iface_type
, del
));
3933 bzero(&bss_setbuf
, sizeof(bss_setbuf
));
3935 /* AP=2, STA=3, up=1, down=0, val=-1 */
3937 val
= WLC_AP_IOV_OP_DELETE
;
3938 } else if (iface_type
== NL80211_IFTYPE_AP
) {
3939 /* Add/role change to AP Interface */
3940 WL_DBG(("Adding AP Interface \n"));
3941 val
= WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE
;
3942 } else if (iface_type
== NL80211_IFTYPE_STATION
) {
3943 /* Add/role change to STA Interface */
3944 WL_DBG(("Adding STA Interface \n"));
3945 val
= WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE
;
3947 WL_ERR((" add_del_bss NOT supported for IFACE type:0x%x", iface_type
));
3952 wl_bss_iovar_war(cfg
, ndev
, &val
);
3955 bss_setbuf
.cfg
= htod32(bsscfg_idx
);
3956 bss_setbuf
.val
= htod32(val
);
3959 memcpy(&bss_setbuf
.ea
.octet
, addr
, ETH_ALEN
);
3962 WL_DBG(("wl bss %d bssidx:%d iface:%s \n", val
, bsscfg_idx
, ndev
->name
));
3963 ret
= wldev_iovar_setbuf(ndev
, "bss", &bss_setbuf
, sizeof(bss_setbuf
),
3964 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
3966 WL_ERR(("'bss %d' failed with %d\n", val
, ret
));
3972 wl_cfg80211_bss_up(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 bsscfg_idx
, s32 bss_up
)
3975 s32 val
= bss_up
? 1 : 0;
3982 bss_setbuf
.cfg
= htod32(bsscfg_idx
);
3983 bss_setbuf
.val
= htod32(val
);
3985 WL_DBG(("wl bss -C %d %s\n", bsscfg_idx
, bss_up
? "up" : "down"));
3986 ret
= wldev_iovar_setbuf(ndev
, "bss", &bss_setbuf
, sizeof(bss_setbuf
),
3987 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
3990 WL_ERR(("'bss %d' failed with %d\n", bss_up
, ret
));
3997 wl_cfg80211_bss_isup(struct net_device
*ndev
, int bsscfg_idx
)
4003 /* Check if the BSS is up */
4005 result
= wldev_iovar_getbuf_bsscfg(ndev
, "bss", &bsscfg_idx
,
4006 sizeof(bsscfg_idx
), getbuf
, sizeof(getbuf
), 0, NULL
);
4008 WL_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx
, result
));
4009 WL_ERR(("NOTE: this ioctl error is normal "
4010 "when the BSS has not been created yet.\n"));
4012 val
= *(int*)getbuf
;
4014 WL_DBG(("wl bss -C %d = %d\n", bsscfg_idx
, val
));
4015 isup
= (val
? TRUE
: FALSE
);
4021 cfg80211_to_wl_iftype(uint16 type
, uint16
*role
, uint16
*mode
)
4024 case NL80211_IFTYPE_STATION
:
4025 *role
= WLC_E_IF_ROLE_STA
;
4026 *mode
= WL_MODE_BSS
;
4028 case NL80211_IFTYPE_AP
:
4029 *role
= WLC_E_IF_ROLE_AP
;
4032 case NL80211_IFTYPE_P2P_GO
:
4033 *role
= WLC_E_IF_ROLE_P2P_GO
;
4036 case NL80211_IFTYPE_P2P_CLIENT
:
4037 *role
= WLC_E_IF_ROLE_P2P_CLIENT
;
4038 *mode
= WL_MODE_BSS
;
4040 case NL80211_IFTYPE_MONITOR
:
4041 WL_ERR(("Unsupported mode \n"));
4042 return BCME_UNSUPPORTED
;
4043 case NL80211_IFTYPE_ADHOC
:
4044 *role
= WLC_E_IF_ROLE_IBSS
;
4045 *mode
= WL_MODE_IBSS
;
4048 WL_ERR(("Unknown interface type:0x%x\n", type
));
4055 wl_if_to_cfg80211_type(uint16 role
)
4058 case WLC_E_IF_ROLE_STA
:
4059 return NL80211_IFTYPE_STATION
;
4060 case WLC_E_IF_ROLE_AP
:
4061 return NL80211_IFTYPE_AP
;
4062 case WLC_E_IF_ROLE_P2P_GO
:
4063 return NL80211_IFTYPE_P2P_GO
;
4064 case WLC_E_IF_ROLE_P2P_CLIENT
:
4065 return NL80211_IFTYPE_P2P_CLIENT
;
4066 case WLC_E_IF_ROLE_IBSS
:
4067 return NL80211_IFTYPE_ADHOC
;
4069 WL_ERR(("Unknown interface role:0x%x. Forcing type station\n", role
));
4075 wl_cfg80211_post_ifcreate(struct net_device
*ndev
,
4076 wl_if_event_info
*event
, u8
*addr
,
4077 const char *name
, bool rtnl_lock_reqd
)
4079 struct bcm_cfg80211
*cfg
;
4080 struct net_device
*primary_ndev
;
4081 struct net_device
*new_ndev
= NULL
;
4082 struct wireless_dev
*wdev
= NULL
;
4087 u8 mac_addr
[ETH_ALEN
];
4089 if (!ndev
|| !event
) {
4090 WL_ERR(("Wrong arg\n"));
4094 cfg
= wl_get_cfg(ndev
);
4096 WL_ERR(("cfg null\n"));
4100 WL_DBG(("Enter. role:%d ifidx:%d bssidx:%d\n",
4101 event
->role
, event
->ifidx
, event
->bssidx
));
4102 if (!event
->ifidx
|| !event
->bssidx
) {
4103 /* Fw returned primary idx (0) for virtual interface */
4104 WL_ERR(("Wrong index. ifidx:%d bssidx:%d \n",
4105 event
->ifidx
, event
->bssidx
));
4109 iface_type
= wl_if_to_cfg80211_type(event
->role
);
4110 if (iface_type
< 0) {
4111 /* Unknown iface type */
4112 WL_ERR(("Wrong iface type \n"));
4116 if (cfg80211_to_wl_iftype(iface_type
, &role
, &mode
) < 0) {
4117 /* Unsupported operating mode */
4118 WL_ERR(("Unsupported operating mode \n"));
4122 WL_DBG(("mac_ptr:%p name:%s role:%d nl80211_iftype:%d " MACDBG
"\n",
4123 addr
, name
, event
->role
, iface_type
, MAC2STRDBG(event
->mac
)));
4125 /* If iface name is not provided, use dongle ifname */
4130 /* If mac address is not set, use primary mac with locally administered
4133 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
4134 memcpy(mac_addr
, primary_ndev
->dev_addr
, ETH_ALEN
);
4135 #ifndef CUSTOMER_HW6
4136 /* For customer6 builds, use primary mac address for virtual interface */
4137 mac_addr
[0] |= 0x02;
4138 #endif /* CUSTOMER_HW6 */
4142 new_ndev
= wl_cfg80211_allocate_if(cfg
, event
->ifidx
,
4143 name
, addr
, event
->bssidx
, event
->name
);
4145 WL_ERR(("I/F allocation failed! \n"));
4148 WL_DBG(("I/F allocation succeeded! ifidx:0x%x bssidx:0x%x \n",
4149 event
->ifidx
, event
->bssidx
));
4152 wdev
= kzalloc(sizeof(*wdev
), GFP_KERNEL
);
4154 WL_ERR(("wireless_dev alloc failed! \n"));
4158 wdev
->wiphy
= bcmcfg_to_wiphy(cfg
);
4159 wdev
->iftype
= iface_type
;
4160 new_ndev
->ieee80211_ptr
= wdev
;
4161 SET_NETDEV_DEV(new_ndev
, wiphy_dev(wdev
->wiphy
));
4163 /* Check whether mac addr is in sync with fw. If not,
4164 * apply it using cur_etheraddr.
4166 if (memcmp(addr
, event
->mac
, ETH_ALEN
) != 0) {
4167 ret
= wldev_iovar_setbuf_bsscfg(new_ndev
, "cur_etheraddr",
4168 addr
, ETH_ALEN
, cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
,
4169 event
->bssidx
, &cfg
->ioctl_buf_sync
);
4170 if (unlikely(ret
)) {
4171 WL_ERR(("set cur_etheraddr Error (%d)\n", ret
));
4174 memcpy(new_ndev
->dev_addr
, addr
, ETH_ALEN
);
4175 WL_ERR(("Applying updated mac address to firmware\n"));
4178 if (wl_cfg80211_register_if(cfg
, event
->ifidx
, new_ndev
, rtnl_lock_reqd
) != BCME_OK
) {
4179 WL_ERR(("IFACE register failed \n"));
4183 /* Initialize with the station mode params */
4184 ret
= wl_alloc_netinfo(cfg
, new_ndev
, wdev
, mode
,
4185 PM_ENABLE
, event
->bssidx
);
4186 if (unlikely(ret
)) {
4187 WL_ERR(("wl_alloc_netinfo Error (%d)\n", ret
));
4191 /* Apply the mode & infra setting based on iftype */
4192 if ((ret
= wl_config_ifmode(cfg
, new_ndev
, iface_type
)) < 0) {
4193 WL_ERR(("config ifmode failure (%d)\n", ret
));
4197 if (mode
== WL_MODE_AP
) {
4198 wl_set_drv_status(cfg
, AP_CREATING
, new_ndev
);
4201 WL_INFORM(("Host Network Interface (%s) for Secondary I/F created."
4202 " cfg_iftype:%d wl_role:%d\n", new_ndev
->name
, iface_type
, event
->role
));
4210 wl_cfg80211_remove_if(cfg
, event
->ifidx
, new_ndev
, rtnl_lock_reqd
);
4216 wl_cfg80211_cleanup_virtual_ifaces(struct net_device
*dev
, bool rtnl_lock_reqd
)
4218 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
4219 struct net_info
*iter
, *next
;
4220 struct net_device
*primary_ndev
;
4222 /* Note: This function will clean up only the network interface and host
4223 * data structures. The firmware interface clean up will happen in the
4224 * during chip reset (ifconfig wlan0 down for built-in drivers/rmmod
4225 * context for the module case).
4227 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
4228 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4229 #pragma GCC diagnostic push
4230 #pragma GCC diagnostic ignored "-Wcast-qual"
4232 for_each_ndev(cfg
, iter
, next
) {
4233 if (iter
->ndev
&& (iter
->ndev
!= primary_ndev
)) {
4234 WL_DBG(("Cleaning up iface:%s \n", iter
->ndev
->name
));
4235 wl_cfg80211_post_ifdel(iter
->ndev
, rtnl_lock_reqd
);
4238 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4239 #pragma GCC diagnostic pop
4244 wl_cfg80211_post_ifdel(struct net_device
*ndev
, bool rtnl_lock_reqd
)
4247 struct bcm_cfg80211
*cfg
;
4249 if (!ndev
|| !ndev
->ieee80211_ptr
) {
4250 /* No wireless dev done for this interface */
4254 cfg
= wl_get_cfg(ndev
);
4256 WL_ERR(("cfg null\n"));
4259 ifidx
= dhd_net2idx(((struct dhd_pub
*)(cfg
->pub
))->info
, ndev
);
4260 BCM_REFERENCE(ifidx
);
4262 WL_ERR(("Invalid IF idx for iface:%s\n", ndev
->name
));
4266 WL_DBG(("cfg80211_remove for iface:%s \n", ndev
->name
));
4267 wl_cfg80211_remove_if(cfg
, ifidx
, ndev
, rtnl_lock_reqd
);
4268 cfg
->bss_pending_op
= FALSE
;
4273 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
4274 /* Create a Generic Network Interface and initialize it depending up on
4275 * the interface type
4278 wl_cfg80211_create_iface(struct wiphy
*wiphy
,
4279 enum nl80211_iftype iface_type
,
4280 u8
*mac_addr
, const char *name
)
4282 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4283 struct net_device
*new_ndev
= NULL
;
4284 struct net_device
*primary_ndev
= NULL
;
4288 wl_if_event_info
*event
= NULL
;
4290 struct net_info
*iter
, *next
;
4292 u16 role
= 0, mode
= 0;
4295 WL_DBG(("Enter\n"));
4297 WL_ERR(("Interface name not provided\n"));
4301 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4302 #pragma GCC diagnostic push
4303 #pragma GCC diagnostic ignored "-Wcast-qual"
4305 for_each_ndev(cfg
, iter
, next
) {
4307 if (strcmp(iter
->ndev
->name
, name
) == 0) {
4308 WL_ERR(("Interface name, %s exists !\n", iter
->ndev
->name
));
4313 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4314 #pragma GCC diagnostic pop
4317 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
4319 if (likely(!mac_addr
)) {
4320 /* Use primary MAC with the locally administered bit for the
4323 memcpy(addr
, primary_ndev
->dev_addr
, ETH_ALEN
);
4326 /* Use the application provided mac address (if any) */
4327 memcpy(addr
, mac_addr
, ETH_ALEN
);
4330 if ((iface_type
!= NL80211_IFTYPE_STATION
) && (iface_type
!= NL80211_IFTYPE_AP
)) {
4331 WL_ERR(("IFACE type:%d not supported. STA "
4332 "or AP IFACE is only supported\n", iface_type
));
4336 cfg
->bss_pending_op
= TRUE
;
4337 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
4339 /* De-initialize the p2p discovery interface, if operational */
4340 if (p2p_is_on(cfg
)) {
4341 WL_DBG(("Disabling P2P Discovery Interface \n"));
4342 #ifdef WL_CFG80211_P2P_DEV_IF
4343 ret
= wl_cfg80211_scan_stop(cfg
, bcmcfg_to_p2p_wdev(cfg
));
4345 ret
= wl_cfg80211_scan_stop(cfg
, cfg
->p2p_net
);
4347 if (unlikely(ret
< 0)) {
4348 CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret
));
4351 wl_cfgp2p_disable_discovery(cfg
);
4352 wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
) = 0;
4353 p2p_on(cfg
) = false;
4357 * Intialize the firmware I/F.
4359 if (wl_customer6_legacy_chip_check(cfg
, primary_ndev
)) {
4360 /* Use bss iovar instead of interface_create iovar */
4361 ret
= BCME_UNSUPPORTED
;
4363 ret
= wl_cfg80211_interface_ops(cfg
, primary_ndev
, bsscfg_idx
,
4364 iface_type
, 0, addr
);
4366 if (ret
== BCME_UNSUPPORTED
) {
4367 /* Use bssidx 1 by default */
4369 if ((ret
= wl_cfg80211_add_del_bss(cfg
, primary_ndev
,
4370 bsscfg_idx
, iface_type
, 0, addr
)) < 0) {
4373 } else if (ret
< 0) {
4374 WL_ERR(("Interface create failed!! ret:%d \n", ret
));
4381 WL_DBG(("Interface created!! bssidx:%d \n", bsscfg_idx
));
4384 * Wait till the firmware send a confirmation event back.
4386 WL_DBG(("Wait for the FW I/F Event\n"));
4387 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
4388 !cfg
->bss_pending_op
, msecs_to_jiffies(MAX_WAIT_TIME
));
4389 if (timeout
<= 0 || cfg
->bss_pending_op
) {
4390 WL_ERR(("ADD_IF event, didn't come. Return \n"));
4394 event
= &cfg
->if_event_info
;
4396 cfg80211_to_wl_iftype(iface_type
, &role
, &mode
);
4401 * Since FW operation is successful,we can go ahead with the
4402 * the host interface creation.
4404 if ((new_ndev
= wl_cfg80211_post_ifcreate(primary_ndev
,
4405 event
, mac_addr
, name
, false))) {
4406 /* Iface post ops successful. Return ndev/wdev ptr */
4407 return ndev_to_cfgdev(new_ndev
);
4411 cfg
->bss_pending_op
= FALSE
;
4416 wl_cfg80211_del_iface(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
)
4418 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4419 struct net_device
*ndev
= NULL
;
4423 enum nl80211_iftype iface_type
= NL80211_IFTYPE_STATION
;
4425 WL_DBG(("Enter\n"));
4427 /* If any scan is going on, abort it */
4428 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
4429 WL_DBG(("Scan in progress. Aborting the scan!\n"));
4430 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, true, true);
4433 ndev
= (struct net_device
*)cfgdev_to_ndev(cfgdev
);
4434 cfg
->bss_pending_op
= TRUE
;
4435 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
4437 /* Delete the firmware interface. "interface_remove" command
4438 * should go on the interface to be deleted
4440 bsscfg_idx
= wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
);
4441 if (bsscfg_idx
<= 0) {
4442 /* validate bsscfgidx */
4443 WL_ERR(("Wrong bssidx! \n"));
4446 WL_DBG(("del interface. bssidx:%d", bsscfg_idx
));
4447 ret
= wl_cfg80211_interface_ops(cfg
, ndev
, bsscfg_idx
,
4448 NL80211_IFTYPE_STATION
, 1, NULL
);
4449 if (ret
== BCME_UNSUPPORTED
) {
4450 if ((ret
= wl_cfg80211_add_del_bss(cfg
, ndev
,
4451 bsscfg_idx
, iface_type
, true, NULL
)) < 0) {
4452 WL_ERR(("DEL bss failed ret:%d \n", ret
));
4455 } else if (ret
< 0) {
4456 WL_ERR(("Interface DEL failed ret:%d \n", ret
));
4460 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
4461 !cfg
->bss_pending_op
, msecs_to_jiffies(MAX_WAIT_TIME
));
4462 if (timeout
<= 0 || cfg
->bss_pending_op
) {
4463 WL_ERR(("timeout in waiting IF_DEL event\n"));
4467 ret
= wl_cfg80211_post_ifdel(ndev
, false);
4468 if (unlikely(ret
)) {
4469 WL_ERR(("post_ifdel failed\n"));
4474 #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
4477 s32
wl_cfg80211_set_sae_password(struct net_device
*dev
, char* buf
, int len
)
4479 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
4481 sscanf(buf
, "%s %d", cfg
->sae_password
, &cfg
->sae_password_len
);
4485 static s32
wl_cfg80211_join_mesh(
4486 struct wiphy
*wiphy
, struct net_device
*dev
,
4487 const struct mesh_config
*conf
,
4488 const struct mesh_setup
*setup
)
4490 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4491 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
4492 struct ieee80211_channel
*chan
= setup
->chandef
.chan
;
4493 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0))
4494 struct ieee80211_channel
*chan
= setup
->channel
;
4496 u32 param
[2] = {0, 0};
4499 u32 beacon_interval
= setup
->beacon_interval
;
4500 u32 dtim_period
= setup
->dtim_period
;
4501 size_t join_params_size
;
4502 struct wl_join_params join_params
;
4503 chanspec_t chanspec
= 0;
4505 cfg
->channel
= ieee80211_frequency_to_channel(chan
->center_freq
);
4507 if (wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
4508 struct wlc_ssid
*lssid
= (struct wlc_ssid
*)wl_read_prof(cfg
, dev
, WL_PROF_SSID
);
4509 u8
*bssid
= (u8
*)wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
4510 u32
*channel
= (u32
*)wl_read_prof(cfg
, dev
, WL_PROF_CHAN
);
4511 if ((memcmp(setup
->mesh_id
, lssid
->SSID
, lssid
->SSID_len
) == 0) &&
4512 (*channel
== cfg
->channel
)) {
4513 WL_ERR(("MESH connection already existed to " MACDBG
"\n",
4514 MAC2STRDBG((u8
*)wl_read_prof(cfg
, dev
, WL_PROF_BSSID
))));
4517 WL_ERR(("Previous connecton existed, please disconnect mesh %s (" MACDBG
") first\n",
4518 lssid
->SSID
, MAC2STRDBG(bssid
)));
4523 if (chan
->band
== IEEE80211_BAND_5GHZ
)
4524 param
[0] = WLC_BAND_5G
;
4525 else if (chan
->band
== IEEE80211_BAND_2GHZ
)
4526 param
[0] = WLC_BAND_2G
;
4527 err
= wldev_iovar_getint(dev
, "bw_cap", param
);
4528 if (unlikely(err
)) {
4529 WL_ERR(("Get bw_cap Failed (%d)\n", err
));
4533 chanspec
= channel_to_chanspec(wiphy
, dev
, cfg
->channel
, bw_cap
);
4536 memset(&join_params
, 0, sizeof(join_params
));
4537 memcpy((void *)join_params
.ssid
.SSID
, (void *)setup
->mesh_id
,
4538 setup
->mesh_id_len
);
4540 join_params
.ssid
.SSID_len
= htod32(setup
->mesh_id_len
);
4541 join_params
.params
.chanspec_list
[0] = chanspec
;
4542 join_params
.params
.chanspec_num
= 1;
4543 wldev_iovar_setint(dev
, "chanspec", chanspec
);
4544 join_params_size
= sizeof(join_params
);
4546 wldev_iovar_setint(dev
, "wpa_auth", WPA_AUTH_DISABLED
);
4547 wldev_iovar_setint(dev
, "wsec", 0);
4549 if (cfg
->sae_password_len
> 0) {
4550 wldev_iovar_setint(dev
, "mesh_auth_proto", 1);
4551 wldev_iovar_setint(dev
, "wpa_auth", WPA2_AUTH_PSK
);
4552 wldev_iovar_setint(dev
, "wsec", AES_ENABLED
);
4553 wldev_iovar_setint(dev
, "mfp", WL_MFP_REQUIRED
);
4554 printf("%s: password=%s, len=%d\n", __FUNCTION__
,
4555 cfg
->sae_password
, cfg
->sae_password_len
);
4556 wldev_iovar_setbuf(dev
, "sae_password", cfg
->sae_password
, cfg
->sae_password_len
,
4557 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, NULL
);
4559 wldev_iovar_setint(dev
, "mesh_auth_proto", 0);
4560 wldev_iovar_setint(dev
, "mfp", WL_MFP_NONE
);
4563 if (beacon_interval
) {
4564 if ((err
= wldev_ioctl_set(dev
, WLC_SET_BCNPRD
,
4565 &beacon_interval
, sizeof(s32
))) < 0) {
4566 WL_ERR(("Beacon Interval Set Error, %d\n", err
));
4572 if ((err
= wldev_ioctl_set(dev
, WLC_SET_DTIMPRD
,
4573 &dtim_period
, sizeof(s32
))) < 0) {
4574 WL_ERR(("DTIM Interval Set Error, %d\n", err
));
4578 wldev_iovar_setint(dev
, "mpc", 0);
4580 WL_ERR(("JOIN %s on channel %d with chanspec 0x%4x\n",
4581 join_params
.ssid
.SSID
, cfg
->channel
, chanspec
));
4583 err
= wldev_ioctl_set(dev
, WLC_SET_SSID
, &join_params
,
4586 if (unlikely(err
)) {
4587 WL_ERR(("Error (%d)\n", err
));
4591 wl_update_prof(cfg
, dev
, NULL
, &join_params
.ssid
, WL_PROF_SSID
);
4592 wl_update_prof(cfg
, dev
, NULL
, &cfg
->channel
, WL_PROF_CHAN
);
4597 static s32
wl_cfg80211_leave_mesh(
4598 struct wiphy
*wiphy
, struct net_device
*dev
)
4600 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4605 RETURN_EIO_IF_NOT_UP(cfg
);
4608 WL_ERR(("Leave MESH\n"));
4609 curbssid
= wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
4610 wl_set_drv_status(cfg
, DISCONNECTING
, dev
);
4612 memcpy(&scbval
.ea
, curbssid
, ETHER_ADDR_LEN
);
4613 err
= wldev_ioctl_set(dev
, WLC_DISASSOC
, &scbval
,
4615 if (unlikely(err
)) {
4616 wl_clr_drv_status(cfg
, DISCONNECTING
, dev
);
4617 WL_ERR(("error(%d)\n", err
));
4620 memset(cfg
->sae_password
, 0, SAE_MAX_PASSWD_LEN
);
4621 cfg
->sae_password_len
= 0;
4628 wl_cfg80211_join_ibss(struct wiphy
*wiphy
, struct net_device
*dev
,
4629 struct cfg80211_ibss_params
*params
)
4631 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4632 struct cfg80211_bss
*bss
;
4633 struct ieee80211_channel
*chan
;
4634 struct wl_join_params join_params
;
4636 struct cfg80211_ssid ssid
;
4639 size_t join_params_size
;
4640 chanspec_t chanspec
= 0;
4641 u32 param
[2] = {0, 0};
4645 RETURN_EIO_IF_NOT_UP(cfg
);
4646 WL_INFORM(("JOIN BSSID:" MACDBG
"\n", MAC2STRDBG(params
->bssid
)));
4647 if (!params
->ssid
|| params
->ssid_len
<= 0 ||
4648 params
->ssid_len
> DOT11_MAX_SSID_LEN
) {
4649 WL_ERR(("Invalid parameter\n"));
4652 #if defined(WL_CFG80211_P2P_DEV_IF)
4653 chan
= params
->chandef
.chan
;
4655 chan
= params
->channel
;
4656 #endif /* WL_CFG80211_P2P_DEV_IF */
4658 cfg
->channel
= ieee80211_frequency_to_channel(chan
->center_freq
);
4659 if (wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
4660 struct wlc_ssid
*lssid
= (struct wlc_ssid
*)wl_read_prof(cfg
, dev
, WL_PROF_SSID
);
4661 u8
*bssid
= (u8
*)wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
4662 u32
*channel
= (u32
*)wl_read_prof(cfg
, dev
, WL_PROF_CHAN
);
4663 if (!params
->bssid
|| ((memcmp(params
->bssid
, bssid
, ETHER_ADDR_LEN
) == 0) &&
4664 (memcmp(params
->ssid
, lssid
->SSID
, lssid
->SSID_len
) == 0) &&
4665 (*channel
== cfg
->channel
))) {
4666 WL_ERR(("Connection already existed to " MACDBG
"\n",
4667 MAC2STRDBG((u8
*)wl_read_prof(cfg
, dev
, WL_PROF_BSSID
))));
4670 WL_ERR(("Ignore Previous connecton to %s (" MACDBG
")\n",
4671 lssid
->SSID
, MAC2STRDBG(bssid
)));
4674 /* remove the VSIE */
4675 wl_cfg80211_ibss_vsie_delete(dev
);
4677 bss
= cfg80211_get_ibss(wiphy
, NULL
, params
->ssid
, params
->ssid_len
);
4679 if (IBSS_INITIAL_SCAN_ALLOWED
== TRUE
) {
4680 memcpy(ssid
.ssid
, params
->ssid
, params
->ssid_len
);
4681 ssid
.ssid_len
= params
->ssid_len
;
4684 (__wl_cfg80211_scan(wiphy
, dev
, NULL
, &ssid
) ==
4690 } while (++scan_retry
< WL_SCAN_RETRY_MAX
);
4692 /* rtnl lock code is removed here. don't see why rtnl lock
4693 * needs to be released.
4696 /* wait 4 secons till scan done.... */
4697 schedule_timeout_interruptible(msecs_to_jiffies(4000));
4699 bss
= cfg80211_get_ibss(wiphy
, NULL
,
4700 params
->ssid
, params
->ssid_len
);
4703 if (bss
&& ((IBSS_COALESCE_ALLOWED
== TRUE
) ||
4704 ((IBSS_COALESCE_ALLOWED
== FALSE
) && params
->bssid
&&
4705 !memcmp(bss
->bssid
, params
->bssid
, ETHER_ADDR_LEN
)))) {
4706 cfg
->ibss_starter
= false;
4707 WL_DBG(("Found IBSS\n"));
4709 cfg
->ibss_starter
= true;
4713 CFG80211_PUT_BSS(wiphy
, bss
);
4717 if (chan
->band
== IEEE80211_BAND_5GHZ
)
4718 param
[0] = WLC_BAND_5G
;
4719 else if (chan
->band
== IEEE80211_BAND_2GHZ
)
4720 param
[0] = WLC_BAND_2G
;
4721 err
= wldev_iovar_getint(dev
, "bw_cap", param
);
4722 if (unlikely(err
)) {
4723 WL_ERR(("Get bw_cap Failed (%d)\n", err
));
4727 chanspec
= channel_to_chanspec(wiphy
, dev
, cfg
->channel
, bw_cap
);
4730 * Join with specific BSSID and cached SSID
4731 * If SSID is zero join based on BSSID only
4733 memset(&join_params
, 0, sizeof(join_params
));
4734 memcpy((void *)join_params
.ssid
.SSID
, (void *)params
->ssid
,
4736 join_params
.ssid
.SSID_len
= htod32(params
->ssid_len
);
4737 if (params
->bssid
) {
4738 memcpy(&join_params
.params
.bssid
, params
->bssid
, ETHER_ADDR_LEN
);
4739 err
= wldev_ioctl_set(dev
, WLC_SET_DESIRED_BSSID
, &join_params
.params
.bssid
,
4741 if (unlikely(err
)) {
4742 WL_ERR(("Error (%d)\n", err
));
4746 memset(&join_params
.params
.bssid
, 0, ETHER_ADDR_LEN
);
4748 if (IBSS_INITIAL_SCAN_ALLOWED
== FALSE
) {
4749 scan_suppress
= TRUE
;
4750 /* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
4751 err
= wldev_ioctl_set(dev
, WLC_SET_SCANSUPPRESS
,
4752 &scan_suppress
, sizeof(int));
4753 if (unlikely(err
)) {
4754 WL_ERR(("Scan Suppress Setting Failed (%d)\n", err
));
4759 join_params
.params
.chanspec_list
[0] = chanspec
;
4760 join_params
.params
.chanspec_num
= 1;
4761 wldev_iovar_setint(dev
, "chanspec", chanspec
);
4762 join_params_size
= sizeof(join_params
);
4764 /* Disable Authentication, IBSS will add key if it required */
4765 wldev_iovar_setint(dev
, "wpa_auth", WPA_AUTH_DISABLED
);
4766 wldev_iovar_setint(dev
, "wsec", 0);
4768 err
= wldev_ioctl_set(dev
, WLC_SET_SSID
, &join_params
,
4770 if (unlikely(err
)) {
4771 WL_ERR(("Error (%d)\n", err
));
4775 if (IBSS_INITIAL_SCAN_ALLOWED
== FALSE
) {
4776 scan_suppress
= FALSE
;
4777 /* Reset the SCAN SUPPRESS Flag */
4778 err
= wldev_ioctl_set(dev
, WLC_SET_SCANSUPPRESS
,
4779 &scan_suppress
, sizeof(int));
4780 if (unlikely(err
)) {
4781 WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err
));
4785 wl_update_prof(cfg
, dev
, NULL
, &join_params
.ssid
, WL_PROF_SSID
);
4786 wl_update_prof(cfg
, dev
, NULL
, &cfg
->channel
, WL_PROF_CHAN
);
4788 cfg
->rmc_event_seq
= 0; /* initialize rmcfail sequence */
4789 #endif /* WL_RELMCAST */
4793 static s32
wl_cfg80211_leave_ibss(struct wiphy
*wiphy
, struct net_device
*dev
)
4795 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4800 RETURN_EIO_IF_NOT_UP(cfg
);
4803 WL_ERR(("Leave IBSS\n"));
4804 curbssid
= wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
4805 wl_set_drv_status(cfg
, DISCONNECTING
, dev
);
4807 memcpy(&scbval
.ea
, curbssid
, ETHER_ADDR_LEN
);
4808 err
= wldev_ioctl_set(dev
, WLC_DISASSOC
, &scbval
,
4810 if (unlikely(err
)) {
4811 wl_clr_drv_status(cfg
, DISCONNECTING
, dev
);
4812 WL_ERR(("error(%d)\n", err
));
4816 /* remove the VSIE */
4817 wl_cfg80211_ibss_vsie_delete(dev
);
4823 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t
*wpa2ie
, u8
** rsn_cap
)
4826 wpa_suite_mcast_t
*mcast
;
4827 wpa_suite_ucast_t
*ucast
;
4829 wpa_suite_auth_key_mgmt_t
*mgmt
;
4835 mcast
= (wpa_suite_mcast_t
*)&wpa2ie
->data
[WPA2_VERSION_LEN
];
4836 if ((len
-= WPA_SUITE_LEN
) <= 0)
4838 ucast
= (wpa_suite_ucast_t
*)&mcast
[1];
4839 suite_count
= ltoh16_ua(&ucast
->count
);
4840 if ((suite_count
> NL80211_MAX_NR_CIPHER_SUITES
) ||
4841 (len
-= (WPA_IE_SUITE_COUNT_LEN
+
4842 (WPA_SUITE_LEN
* suite_count
))) <= 0)
4845 mgmt
= (wpa_suite_auth_key_mgmt_t
*)&ucast
->list
[suite_count
];
4846 suite_count
= ltoh16_ua(&mgmt
->count
);
4848 if ((suite_count
> NL80211_MAX_NR_CIPHER_SUITES
) ||
4849 (len
-= (WPA_IE_SUITE_COUNT_LEN
+
4850 (WPA_SUITE_LEN
* suite_count
))) >= RSN_CAP_LEN
) {
4851 rsn_cap
[0] = (u8
*)&mgmt
->list
[suite_count
];
4860 wl_set_wpa_version(struct net_device
*dev
, struct cfg80211_connect_params
*sme
)
4862 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
4863 struct wl_security
*sec
;
4868 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
4869 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
4873 if (sme
->crypto
.wpa_versions
& NL80211_WPA_VERSION_1
)
4874 val
= WPA_AUTH_PSK
|
4875 WPA_AUTH_UNSPECIFIED
;
4876 else if (sme
->crypto
.wpa_versions
& NL80211_WPA_VERSION_2
)
4877 val
= WPA2_AUTH_PSK
|
4878 WPA2_AUTH_UNSPECIFIED
;
4880 val
= WPA_AUTH_DISABLED
;
4882 if (is_wps_conn(sme
))
4883 val
= WPA_AUTH_DISABLED
;
4885 WL_DBG(("setting wpa_auth to 0x%0x\n", val
));
4886 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", val
, bssidx
);
4887 if (unlikely(err
)) {
4888 WL_ERR(("set wpa_auth failed (%d)\n", err
));
4891 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
4892 sec
->wpa_versions
= sme
->crypto
.wpa_versions
;
4898 wl_set_auth_type(struct net_device
*dev
, struct cfg80211_connect_params
*sme
)
4900 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
4901 struct wl_security
*sec
;
4906 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
4907 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
4911 switch (sme
->auth_type
) {
4912 case NL80211_AUTHTYPE_OPEN_SYSTEM
:
4913 val
= WL_AUTH_OPEN_SYSTEM
;
4914 WL_DBG(("open system\n"));
4916 case NL80211_AUTHTYPE_SHARED_KEY
:
4917 val
= WL_AUTH_SHARED_KEY
;
4918 WL_DBG(("shared key\n"));
4920 case NL80211_AUTHTYPE_AUTOMATIC
:
4921 val
= WL_AUTH_OPEN_SHARED
;
4922 WL_DBG(("automatic\n"));
4926 WL_ERR(("invalid auth type (%d)\n", sme
->auth_type
));
4930 err
= wldev_iovar_setint_bsscfg(dev
, "auth", val
, bssidx
);
4931 if (unlikely(err
)) {
4932 WL_ERR(("set auth failed (%d)\n", err
));
4935 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
4936 sec
->auth_type
= sme
->auth_type
;
4941 wl_set_set_cipher(struct net_device
*dev
, struct cfg80211_connect_params
*sme
)
4943 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
4944 struct wl_security
*sec
;
4951 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
4952 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
4956 if (sme
->crypto
.n_ciphers_pairwise
) {
4957 switch (sme
->crypto
.ciphers_pairwise
[0]) {
4958 case WLAN_CIPHER_SUITE_WEP40
:
4959 case WLAN_CIPHER_SUITE_WEP104
:
4962 case WLAN_CIPHER_SUITE_TKIP
:
4963 pval
= TKIP_ENABLED
;
4965 case WLAN_CIPHER_SUITE_CCMP
:
4966 case WLAN_CIPHER_SUITE_AES_CMAC
:
4970 WL_ERR(("invalid cipher pairwise (%d)\n",
4971 sme
->crypto
.ciphers_pairwise
[0]));
4975 if (sme
->crypto
.cipher_group
) {
4976 switch (sme
->crypto
.cipher_group
) {
4977 case WLAN_CIPHER_SUITE_WEP40
:
4978 case WLAN_CIPHER_SUITE_WEP104
:
4981 case WLAN_CIPHER_SUITE_TKIP
:
4982 gval
= TKIP_ENABLED
;
4984 case WLAN_CIPHER_SUITE_CCMP
:
4987 case WLAN_CIPHER_SUITE_AES_CMAC
:
4991 WL_ERR(("invalid cipher group (%d)\n",
4992 sme
->crypto
.cipher_group
));
4997 WL_DBG(("pval (%d) gval (%d)\n", pval
, gval
));
4999 if (is_wps_conn(sme
)) {
5001 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", 4, bssidx
);
5003 /* WPS-2.0 allows no security */
5004 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", 0, bssidx
);
5006 WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
5007 wsec_val
= pval
| gval
;
5009 WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val
));
5010 err
= wldev_iovar_setint_bsscfg(dev
, "wsec",
5013 if (unlikely(err
)) {
5014 WL_ERR(("error (%d)\n", err
));
5018 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
5019 sec
->cipher_pairwise
= sme
->crypto
.ciphers_pairwise
[0];
5020 sec
->cipher_group
= sme
->crypto
.cipher_group
;
5027 wl_cfg80211_set_mfp(struct bcm_cfg80211
*cfg
,
5028 struct net_device
*dev
,
5029 struct cfg80211_connect_params
*sme
)
5031 s32 mfp
= WL_MFP_NONE
;
5032 s32 current_mfp
= WL_MFP_NONE
;
5035 bool fw_support
= false;
5037 u8
*eptr
= NULL
, *ptr
= NULL
;
5038 u8
* group_mgmt_cs
= NULL
;
5039 wpa_pmkid_list_t
* pmkid
= NULL
;
5042 /* No connection params from userspace, Do nothing. */
5046 /* Check fw support and retreive current mfp val */
5047 err
= wldev_iovar_getint(dev
, "mfp", ¤t_mfp
);
5052 /* Parse the wpa2ie to decode the MFP capablity */
5053 if (((wpa2_ie
= bcm_parse_tlvs((u8
*)sme
->ie
, sme
->ie_len
,
5054 DOT11_MNG_RSN_ID
)) != NULL
) &&
5055 (wl_cfg80211_get_rsn_capa(wpa2_ie
, &rsn_cap
) == 0)) {
5056 /* Check for MFP cap in the RSN capability field */
5057 if (rsn_cap
[0] & RSN_CAP_MFPR
) {
5058 mfp
= WL_MFP_REQUIRED
;
5059 } else if (rsn_cap
[0] & RSN_CAP_MFPC
) {
5060 mfp
= WL_MFP_CAPABLE
;
5064 * eptr --> end/last byte addr of wpa2_ie
5065 * ptr --> to keep track of current/required byte addr
5067 eptr
= (u8
*)wpa2_ie
+ (wpa2_ie
->len
+ TLV_HDR_LEN
);
5068 /* pointing ptr to the next byte after rns_cap */
5069 ptr
= (u8
*)rsn_cap
+ RSN_CAP_LEN
;
5070 if (mfp
&& (eptr
- ptr
) >= WPA2_PMKID_COUNT_LEN
) {
5071 /* pmkid now to point to 1st byte addr of pmkid in wpa2_ie */
5072 pmkid
= (wpa_pmkid_list_t
*)ptr
;
5073 count
= pmkid
->count
.low
| (pmkid
->count
.high
<< 8);
5074 /* ptr now to point to last byte addr of pmkid */
5075 ptr
= (u8
*)pmkid
+ (count
* WPA2_PMKID_LEN
5076 + WPA2_PMKID_COUNT_LEN
);
5077 if ((eptr
- ptr
) >= WPA_SUITE_LEN
) {
5078 /* group_mgmt_cs now to point to first byte addr of bip */
5079 group_mgmt_cs
= ptr
;
5084 WL_DBG((" mfp:%d wpa2_ie ptr:%p rsn_cap 0x%x%x fw mfp support:%d\n",
5085 mfp
, wpa2_ie
, rsn_cap
[0], rsn_cap
[1], fw_support
));
5087 if (fw_support
== false) {
5088 if (mfp
== WL_MFP_REQUIRED
) {
5089 /* if mfp > 0, mfp capability set in wpa ie, but
5090 * FW indicated error for mfp. Propagate the error up.
5092 WL_ERR(("mfp capability found in wpaie. But fw doesn't "
5093 "seem to support MFP\n"));
5096 /* Firmware doesn't support mfp. But since connection request
5097 * is for non-mfp case, don't bother.
5101 } else if (mfp
!= current_mfp
) {
5102 err
= wldev_iovar_setint(dev
, "mfp", mfp
);
5103 if (unlikely(err
)) {
5104 WL_ERR(("mfp (%d) set failed ret:%d \n", mfp
, err
));
5107 WL_DBG(("mfp set to 0x%x \n", mfp
));
5110 if (group_mgmt_cs
&& bcmp((const uint8
*)WPA2_OUI
,
5111 group_mgmt_cs
, (WPA_SUITE_LEN
- 1)) == 0) {
5112 WL_DBG(("BIP is found\n"));
5113 err
= wldev_iovar_setbuf(dev
, "bip",
5114 group_mgmt_cs
, WPA_SUITE_LEN
, cfg
->ioctl_buf
,
5115 WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
);
5117 * Dont return failure for unsupported cases
5118 * of bip iovar for backward compatibility
5120 if (err
!= BCME_UNSUPPORTED
&& err
< 0) {
5121 WL_ERR(("bip set error (%d)\n", err
));
5131 wl_set_key_mgmt(struct net_device
*dev
, struct cfg80211_connect_params
*sme
)
5133 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
5134 struct wl_security
*sec
;
5139 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5140 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
5144 if (sme
->crypto
.n_akm_suites
) {
5145 err
= wldev_iovar_getint(dev
, "wpa_auth", &val
);
5146 if (unlikely(err
)) {
5147 WL_ERR(("could not get wpa_auth (%d)\n", err
));
5150 if (val
& (WPA_AUTH_PSK
|
5151 WPA_AUTH_UNSPECIFIED
)) {
5152 switch (sme
->crypto
.akm_suites
[0]) {
5153 case WLAN_AKM_SUITE_8021X
:
5154 val
= WPA_AUTH_UNSPECIFIED
;
5156 case WLAN_AKM_SUITE_PSK
:
5160 WL_ERR(("invalid akm suite (0x%x)\n",
5161 sme
->crypto
.akm_suites
[0]));
5164 } else if (val
& (WPA2_AUTH_PSK
|
5165 WPA2_AUTH_UNSPECIFIED
)) {
5166 switch (sme
->crypto
.akm_suites
[0]) {
5167 case WLAN_AKM_SUITE_8021X
:
5168 val
= WPA2_AUTH_UNSPECIFIED
;
5172 case WL_AKM_SUITE_SHA256_1X
:
5173 if (wl_customer6_legacy_chip_check(cfg
, dev
)) {
5174 val
= WPA2_AUTH_UNSPECIFIED
;
5176 val
= WPA2_AUTH_1X_SHA256
;
5179 case WL_AKM_SUITE_SHA256_PSK
:
5180 if (wl_customer6_legacy_chip_check(cfg
, dev
)) {
5181 val
= WPA2_AUTH_PSK
;
5183 val
= WPA2_AUTH_PSK_SHA256
;
5187 case WL_AKM_SUITE_SHA256_1X
:
5188 val
= WPA2_AUTH_1X_SHA256
;
5190 case WL_AKM_SUITE_SHA256_PSK
:
5191 val
= WPA2_AUTH_PSK_SHA256
;
5193 #endif /* CUSTOMER_HW6 */
5195 case WLAN_AKM_SUITE_PSK
:
5196 val
= WPA2_AUTH_PSK
;
5199 WL_ERR(("invalid akm suite (0x%x)\n",
5200 sme
->crypto
.akm_suites
[0]));
5206 if ((err
= wl_cfg80211_set_mfp(cfg
, dev
, sme
)) < 0) {
5207 WL_ERR(("MFP set failed err:%d\n", err
));
5212 WL_DBG(("setting wpa_auth to 0x%x\n", val
));
5213 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", val
, bssidx
);
5214 if (unlikely(err
)) {
5215 WL_ERR(("could not set wpa_auth (0x%x)\n", err
));
5219 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
5220 sec
->wpa_auth
= sme
->crypto
.akm_suites
[0];
5226 wl_set_set_sharedkey(struct net_device
*dev
,
5227 struct cfg80211_connect_params
*sme
)
5229 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
5230 struct wl_security
*sec
;
5231 struct wl_wsec_key key
;
5236 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5237 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
5241 WL_DBG(("key len (%d)\n", sme
->key_len
));
5243 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
5244 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
5245 sec
->wpa_versions
, sec
->cipher_pairwise
));
5246 if (!(sec
->wpa_versions
& (NL80211_WPA_VERSION_1
|
5247 NL80211_WPA_VERSION_2
)) &&
5248 (sec
->cipher_pairwise
& (WLAN_CIPHER_SUITE_WEP40
|
5249 WLAN_CIPHER_SUITE_WEP104
)))
5251 memset(&key
, 0, sizeof(key
));
5252 key
.len
= (u32
) sme
->key_len
;
5253 key
.index
= (u32
) sme
->key_idx
;
5254 if (unlikely(key
.len
> sizeof(key
.data
))) {
5255 WL_ERR(("Too long key length (%u)\n", key
.len
));
5258 memcpy(key
.data
, sme
->key
, key
.len
);
5259 key
.flags
= WL_PRIMARY_KEY
;
5260 switch (sec
->cipher_pairwise
) {
5261 case WLAN_CIPHER_SUITE_WEP40
:
5262 key
.algo
= CRYPTO_ALGO_WEP1
;
5264 case WLAN_CIPHER_SUITE_WEP104
:
5265 key
.algo
= CRYPTO_ALGO_WEP128
;
5268 WL_ERR(("Invalid algorithm (%d)\n",
5269 sme
->crypto
.ciphers_pairwise
[0]));
5272 /* Set the new key/index */
5273 WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
5274 key
.len
, key
.index
, key
.algo
));
5275 WL_DBG(("key \"%s\"\n", key
.data
));
5276 swap_key_from_BE(&key
);
5277 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &key
, sizeof(key
),
5278 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
5279 if (unlikely(err
)) {
5280 WL_ERR(("WLC_SET_KEY error (%d)\n", err
));
5283 if (sec
->auth_type
== NL80211_AUTHTYPE_SHARED_KEY
) {
5284 WL_DBG(("set auth_type to shared key\n"));
5285 val
= WL_AUTH_SHARED_KEY
; /* shared key */
5286 err
= wldev_iovar_setint_bsscfg(dev
, "auth", val
, bssidx
);
5287 if (unlikely(err
)) {
5288 WL_ERR(("set auth failed (%d)\n", err
));
5297 #if defined(ESCAN_RESULT_PATCH)
5298 static u8 connect_req_bssid
[6];
5299 static u8 broad_bssid
[6];
5300 #endif /* ESCAN_RESULT_PATCH */
5304 #if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
5305 static bool wl_get_chan_isvht80(struct net_device
*net
, dhd_pub_t
*dhd
)
5310 if (wldev_iovar_getint(net
, "chanspec", (s32
*)&chanspec
) == BCME_OK
)
5311 chanspec
= wl_chspec_driver_to_host(chanspec
);
5313 isvht80
= chanspec
& WL_CHANSPEC_BW_80
;
5314 WL_INFORM(("%s: chanspec(%x:%d)\n", __FUNCTION__
, chanspec
, isvht80
));
5318 #endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
5320 int wl_cfg80211_cleanup_mismatch_status(struct net_device
*dev
, struct bcm_cfg80211
*cfg
,
5328 WL_ERR(("Disassociate previous connection!\n"));
5329 wl_set_drv_status(cfg
, DISCONNECTING
, dev
);
5330 scbval
.val
= DOT11_RC_DISASSOC_LEAVING
;
5331 scbval
.val
= htod32(scbval
.val
);
5333 err
= wldev_ioctl_set(dev
, WLC_DISASSOC
, &scbval
,
5335 if (unlikely(err
)) {
5336 wl_clr_drv_status(cfg
, DISCONNECTING
, dev
);
5337 WL_ERR(("error (%d)\n", err
));
5343 WL_ERR(("Waiting for previous DISCONNECTING status!\n"));
5344 if (wl_get_drv_status(cfg
, DISCONNECTING
, dev
)) {
5345 wl_clr_drv_status(cfg
, DISCONNECTING
, dev
);
5349 while (wl_get_drv_status(cfg
, DISCONNECTING
, dev
) && wait_cnt
) {
5350 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
5356 if (wait_cnt
== 0) {
5357 WL_ERR(("DISCONNECING clean up failed!\n"));
5358 return BCME_NOTREADY
;
5363 #define MAX_SCAN_ABORT_WAIT_CNT 20
5364 #define WAIT_SCAN_ABORT_OSL_SLEEP_TIME 10
5367 wl_cfg80211_connect(struct wiphy
*wiphy
, struct net_device
*dev
,
5368 struct cfg80211_connect_params
*sme
)
5370 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5371 struct ieee80211_channel
*chan
= sme
->channel
;
5372 wl_extjoin_params_t
*ext_join_params
;
5373 struct wl_join_params join_params
;
5374 size_t join_params_size
;
5375 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
5377 wpa_ie_fixed_t
*wpa_ie
;
5382 struct ether_addr bssid
;
5384 #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
5389 BCM_REFERENCE(dhdp
);
5392 wl_config_ifmode(cfg
, dev
, dev
->ieee80211_ptr
->iftype
);
5394 #if defined(SUPPORT_RANDOM_MAC_SCAN)
5395 wl_cfg80211_set_random_mac(dev
, FALSE
);
5396 #endif /* SUPPORT_RANDOM_MAC_SCAN */
5398 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
5399 if (sme
->channel_hint
) {
5400 chan
= sme
->channel_hint
;
5401 WL_DBG(("channel_hint (%d), channel_hint center_freq (%d)\n",
5402 ieee80211_frequency_to_channel(sme
->channel_hint
->center_freq
),
5403 sme
->channel_hint
->center_freq
));
5405 if (sme
->bssid_hint
) {
5406 sme
->bssid
= sme
->bssid_hint
;
5407 WL_DBG(("bssid_hint "MACDBG
" \n", MAC2STRDBG(sme
->bssid_hint
)));
5409 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
5411 if (unlikely(!sme
->ssid
)) {
5412 WL_ERR(("Invalid ssid\n"));
5416 if (unlikely(sme
->ssid_len
> DOT11_MAX_SSID_LEN
)) {
5417 WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
5418 sme
->ssid
, sme
->ssid_len
));
5422 WL_DBG(("SME IE : len=%zu\n", sme
->ie_len
));
5423 if (sme
->ie
!= NULL
&& sme
->ie_len
> 0 && (wl_dbg_level
& WL_DBG_DBG
)) {
5424 prhex(NULL
, (uchar
*)sme
->ie
, sme
->ie_len
);
5427 RETURN_EIO_IF_NOT_UP(cfg
);
5430 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
5432 #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
5433 if (cfg
->scan_request
) {
5434 WL_TRACE_HW4(("Aborting the scan! \n"));
5435 wl_cfg80211_scan_abort(cfg
);
5436 wait_cnt
= MAX_SCAN_ABORT_WAIT_CNT
;
5437 while (wl_get_drv_status(cfg
, SCANNING
, dev
) && wait_cnt
) {
5438 WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt
));
5440 OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME
);
5442 if (wl_get_drv_status(cfg
, SCANNING
, dev
)) {
5443 wl_notify_escan_complete(cfg
, dev
, true, true);
5447 #ifdef WL_SCHED_SCAN
5448 /* Locks are taken in wl_cfg80211_sched_scan_stop()
5449 * A start scan occuring during connect is unlikely
5451 if (cfg
->sched_scan_req
) {
5452 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
5453 wl_cfg80211_sched_scan_stop(wiphy
, bcmcfg_to_prmry_ndev(cfg
), 0);
5455 wl_cfg80211_sched_scan_stop(wiphy
, bcmcfg_to_prmry_ndev(cfg
));
5456 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
5459 #if defined(ESCAN_RESULT_PATCH)
5461 memcpy(connect_req_bssid
, sme
->bssid
, ETHER_ADDR_LEN
);
5463 bzero(connect_req_bssid
, ETHER_ADDR_LEN
);
5464 bzero(broad_bssid
, ETHER_ADDR_LEN
);
5466 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5469 if (wl_get_drv_status(cfg
, CONNECTING
, dev
) || wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
5470 /* set nested connect bit to identify the context */
5471 wl_set_drv_status(cfg
, NESTED_CONNECT
, dev
);
5472 /* DHD prev status is CONNECTING/CONNECTED */
5473 err
= wl_cfg80211_cleanup_mismatch_status(dev
, cfg
, TRUE
);
5474 } else if (wl_get_drv_status(cfg
, DISCONNECTING
, dev
)) {
5475 /* DHD prev status is DISCONNECTING */
5476 err
= wl_cfg80211_cleanup_mismatch_status(dev
, cfg
, FALSE
);
5477 } else if (!wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
5478 /* DHD previous status is not connected and FW connected */
5479 if (wldev_ioctl_get(dev
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
) == 0) {
5480 /* set nested connect bit to identify the context */
5481 wl_set_drv_status(cfg
, NESTED_CONNECT
, dev
);
5482 err
= wl_cfg80211_cleanup_mismatch_status(dev
, cfg
, TRUE
);
5486 /* 'connect' request received */
5487 wl_set_drv_status(cfg
, CONNECTING
, dev
);
5488 /* clear nested connect bit on proceeding for connection */
5489 wl_clr_drv_status(cfg
, NESTED_CONNECT
, dev
);
5492 bzero(&bssid
, sizeof(bssid
));
5493 if (!wl_get_drv_status(cfg
, DISCONNECTING
, dev
))
5494 wl_update_prof(cfg
, dev
, NULL
, (void *)&bssid
, WL_PROF_BSSID
);
5496 if (p2p_is_on(cfg
) && (dev
!= bcmcfg_to_prmry_ndev(cfg
))) {
5497 /* we only allow to connect using virtual interface in case of P2P */
5498 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5499 WL_ERR(("Find p2p index from wdev(%p) failed\n",
5500 dev
->ieee80211_ptr
));
5504 wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
5505 VNDR_IE_ASSOCREQ_FLAG
, sme
->ie
, sme
->ie_len
);
5506 } else if (dev
== bcmcfg_to_prmry_ndev(cfg
)) {
5507 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5508 WL_ERR(("Find wlan index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
5513 /* find the RSN_IE */
5514 if ((wpa2_ie
= bcm_parse_tlvs((u8
*)sme
->ie
, sme
->ie_len
,
5515 DOT11_MNG_RSN_ID
)) != NULL
) {
5516 WL_DBG((" WPA2 IE is found\n"));
5518 /* find the WPA_IE */
5519 if ((wpa_ie
= wl_cfgp2p_find_wpaie((u8
*)sme
->ie
,
5520 sme
->ie_len
)) != NULL
) {
5521 WL_DBG((" WPA IE is found\n"));
5523 if (wpa_ie
!= NULL
|| wpa2_ie
!= NULL
) {
5524 wpaie
= (wpa_ie
!= NULL
) ? (u8
*)wpa_ie
: (u8
*)wpa2_ie
;
5525 wpaie_len
= (wpa_ie
!= NULL
) ? wpa_ie
->length
: wpa2_ie
->len
;
5526 wpaie_len
+= WPA_RSN_IE_TAG_FIXED_LEN
;
5527 err
= wldev_iovar_setbuf(dev
, "wpaie", wpaie
, wpaie_len
,
5528 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
5529 if (unlikely(err
)) {
5530 WL_ERR(("wpaie set error (%d)\n", err
));
5534 err
= wldev_iovar_setbuf(dev
, "wpaie", NULL
, 0,
5535 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
5536 if (unlikely(err
)) {
5537 WL_ERR(("wpaie set error (%d)\n", err
));
5541 err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
5542 VNDR_IE_ASSOCREQ_FLAG
, (const u8
*)sme
->ie
, sme
->ie_len
);
5543 if (unlikely(err
)) {
5549 cfg
->channel
= ieee80211_frequency_to_channel(chan
->center_freq
);
5551 WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg
->channel
,
5552 chan
->center_freq
, chan_cnt
));
5554 WL_DBG(("No channel info from user space\n"));
5559 WL_DBG(("3. set wpa version \n"));
5561 err
= wl_set_wpa_version(dev
, sme
);
5562 if (unlikely(err
)) {
5563 WL_ERR(("Invalid wpa_version\n"));
5566 err
= wl_set_auth_type(dev
, sme
);
5567 if (unlikely(err
)) {
5568 WL_ERR(("Invalid auth type\n"));
5572 err
= wl_set_set_cipher(dev
, sme
);
5573 if (unlikely(err
)) {
5574 WL_ERR(("Invalid ciper\n"));
5578 err
= wl_set_key_mgmt(dev
, sme
);
5579 if (unlikely(err
)) {
5580 WL_ERR(("Invalid key mgmt\n"));
5584 err
= wl_set_set_sharedkey(dev
, sme
);
5585 if (unlikely(err
)) {
5586 WL_ERR(("Invalid shared key\n"));
5591 * Join with specific BSSID and cached SSID
5592 * If SSID is zero join based on BSSID only
5594 join_params_size
= WL_EXTJOIN_PARAMS_FIXED_SIZE
+
5595 chan_cnt
* sizeof(chanspec_t
);
5596 ext_join_params
= (wl_extjoin_params_t
*)kzalloc(join_params_size
, GFP_KERNEL
);
5597 if (ext_join_params
== NULL
) {
5599 wl_clr_drv_status(cfg
, CONNECTING
, dev
);
5602 ext_join_params
->ssid
.SSID_len
= min(sizeof(ext_join_params
->ssid
.SSID
), sme
->ssid_len
);
5603 memcpy(&ext_join_params
->ssid
.SSID
, sme
->ssid
, ext_join_params
->ssid
.SSID_len
);
5604 wl_update_prof(cfg
, dev
, NULL
, &ext_join_params
->ssid
, WL_PROF_SSID
);
5605 ext_join_params
->ssid
.SSID_len
= htod32(ext_join_params
->ssid
.SSID_len
);
5606 /* increate dwell time to receive probe response or detect Beacon
5607 * from target AP at a noisy air only during connect command
5609 ext_join_params
->scan
.active_time
= chan_cnt
? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS
: -1;
5610 ext_join_params
->scan
.passive_time
= chan_cnt
? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS
: -1;
5611 /* Set up join scan parameters */
5612 ext_join_params
->scan
.scan_type
= -1;
5613 ext_join_params
->scan
.nprobes
= chan_cnt
?
5614 (ext_join_params
->scan
.active_time
/WL_SCAN_JOIN_PROBE_INTERVAL_MS
) : -1;
5615 ext_join_params
->scan
.home_time
= -1;
5618 memcpy(&ext_join_params
->assoc
.bssid
, sme
->bssid
, ETH_ALEN
);
5620 memcpy(&ext_join_params
->assoc
.bssid
, ðer_bcast
, ETH_ALEN
);
5621 ext_join_params
->assoc
.chanspec_num
= chan_cnt
;
5625 * Use the channel provided by userspace
5627 u16 channel
, band
, bw
, ctl_sb
;
5629 channel
= cfg
->channel
;
5630 band
= (channel
<= CH_MAX_2G_CHANNEL
) ? WL_CHANSPEC_BAND_2G
5631 : WL_CHANSPEC_BAND_5G
;
5633 /* Get min_bw set for the interface */
5634 bw
= wl_cfg80211_ulb_get_min_bw_chspec(cfg
, dev
->ieee80211_ptr
, bssidx
);
5635 if (bw
== INVCHANSPEC
) {
5636 WL_ERR(("Invalid chanspec \n"));
5637 kfree(ext_join_params
);
5642 ctl_sb
= WL_CHANSPEC_CTL_SB_NONE
;
5643 chspec
= (channel
| band
| bw
| ctl_sb
);
5644 ext_join_params
->assoc
.chanspec_list
[0] &= WL_CHANSPEC_CHAN_MASK
;
5645 ext_join_params
->assoc
.chanspec_list
[0] |= chspec
;
5646 ext_join_params
->assoc
.chanspec_list
[0] =
5647 wl_chspec_host_to_driver(ext_join_params
->assoc
.chanspec_list
[0]);
5650 ext_join_params
->assoc
.chanspec_num
= htod32(ext_join_params
->assoc
.chanspec_num
);
5651 if (ext_join_params
->ssid
.SSID_len
< IEEE80211_MAX_SSID_LEN
) {
5652 WL_INFORM(("ssid \"%s\", len (%d)\n", ext_join_params
->ssid
.SSID
,
5653 ext_join_params
->ssid
.SSID_len
));
5656 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5657 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
5658 kfree(ext_join_params
);
5662 #if defined(CUSTOMER_HW2)
5663 DHD_DISABLE_RUNTIME_PM((dhd_pub_t
*)cfg
->pub
);
5664 #endif /* BCMDONGLEHOST && CUSTOMER_HW2 */
5665 #ifdef WL_EXT_IAPSTA
5666 wl_ext_iapsta_update_channel(dev
, cfg
->channel
);
5668 err
= wldev_iovar_setbuf_bsscfg(dev
, "join", ext_join_params
, join_params_size
,
5669 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
5671 if (cfg
->rcc_enabled
) {
5672 printf("Connecting with " MACDBG
" ssid \"%s\", len (%d) with rcc channels \n\n",
5673 MAC2STRDBG((u8
*)(&ext_join_params
->assoc
.bssid
)),
5674 ext_join_params
->ssid
.SSID
, ext_join_params
->ssid
.SSID_len
);
5676 printf("Connecting with " MACDBG
" ssid \"%s\", len (%d) channel=%d\n\n",
5677 MAC2STRDBG((u8
*)(&ext_join_params
->assoc
.bssid
)),
5678 ext_join_params
->ssid
.SSID
, ext_join_params
->ssid
.SSID_len
, cfg
->channel
);
5681 kfree(ext_join_params
);
5683 wl_clr_drv_status(cfg
, CONNECTING
, dev
);
5684 if (err
== BCME_UNSUPPORTED
) {
5685 WL_DBG(("join iovar is not supported\n"));
5688 WL_ERR(("error (%d)\n", err
));
5695 memset(&join_params
, 0, sizeof(join_params
));
5696 join_params_size
= sizeof(join_params
.ssid
);
5698 join_params
.ssid
.SSID_len
= min(sizeof(join_params
.ssid
.SSID
), sme
->ssid_len
);
5699 memcpy(&join_params
.ssid
.SSID
, sme
->ssid
, join_params
.ssid
.SSID_len
);
5700 join_params
.ssid
.SSID_len
= htod32(join_params
.ssid
.SSID_len
);
5701 wl_update_prof(cfg
, dev
, NULL
, &join_params
.ssid
, WL_PROF_SSID
);
5703 memcpy(&join_params
.params
.bssid
, sme
->bssid
, ETH_ALEN
);
5705 memcpy(&join_params
.params
.bssid
, ðer_bcast
, ETH_ALEN
);
5707 if (wl_ch_to_chanspec(dev
, cfg
->channel
, &join_params
, &join_params_size
) < 0) {
5708 WL_ERR(("Invalid chanspec\n"));
5712 WL_DBG(("join_param_size %zu\n", join_params_size
));
5714 if (join_params
.ssid
.SSID_len
< IEEE80211_MAX_SSID_LEN
) {
5715 WL_INFORM(("ssid \"%s\", len (%d)\n", join_params
.ssid
.SSID
,
5716 join_params
.ssid
.SSID_len
));
5718 err
= wldev_ioctl_set(dev
, WLC_SET_SSID
, &join_params
, join_params_size
);
5721 WL_ERR(("error (%d)\n", err
));
5722 wl_clr_drv_status(cfg
, CONNECTING
, dev
);
5725 wl_cfg80211_check_in4way(cfg
, dev
, NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
,
5726 WL_EXT_STATUS_CONNECTING
, NULL
);
5729 /* disable TDLS if number of connected interfaces is >= 1 */
5730 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_CONNECT
, false);
5734 if ((dev
== bcmcfg_to_prmry_ndev(cfg
)) && !err
) {
5735 DHD_DBG_PKT_MON_START(dhdp
);
5737 #endif /* DBG_PKT_MON */
5741 #define WAIT_FOR_DISCONNECT_MAX 10
5742 static void wl_cfg80211_wait_for_disconnection(struct bcm_cfg80211
*cfg
, struct net_device
*dev
)
5746 wait_cnt
= WAIT_FOR_DISCONNECT_MAX
;
5747 while (wl_get_drv_status(cfg
, DISCONNECTING
, dev
) && wait_cnt
) {
5748 WL_DBG(("Waiting for disconnection, wait_cnt: %d\n", wait_cnt
));
5757 wl_cfg80211_disconnect(struct wiphy
*wiphy
, struct net_device
*dev
,
5760 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5765 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
5766 WL_ERR(("Reason %d\n", reason_code
));
5767 RETURN_EIO_IF_NOT_UP(cfg
);
5768 act
= *(bool *) wl_read_prof(cfg
, dev
, WL_PROF_ACT
);
5769 curbssid
= wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
5771 BCM_REFERENCE(dhdp
);
5773 #ifdef ESCAN_RESULT_PATCH
5774 if (wl_get_drv_status(cfg
, CONNECTING
, dev
) && curbssid
&&
5775 (memcmp(curbssid
, connect_req_bssid
, ETHER_ADDR_LEN
) == 0)) {
5776 WL_ERR(("Disconnecting from connecting device: " MACDBG
"\n",
5777 MAC2STRDBG(curbssid
)));
5780 #endif /* ESCAN_RESULT_PATCH */
5784 if (dev
== bcmcfg_to_prmry_ndev(cfg
)) {
5785 DHD_DBG_PKT_MON_STOP(dhdp
);
5787 #endif /* DBG_PKT_MON */
5789 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
5791 #if !defined(ESCAN_RESULT_PATCH)
5792 /* Let scan aborted by F/W */
5793 if (cfg
->scan_request
) {
5794 WL_TRACE_HW4(("Aborting the scan! \n"));
5795 wl_notify_escan_complete(cfg
, dev
, true, true);
5797 #endif /* ESCAN_RESULT_PATCH */
5798 if (wl_get_drv_status(cfg
, CONNECTING
, dev
) ||
5799 wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
5800 wl_set_drv_status(cfg
, DISCONNECTING
, dev
);
5801 scbval
.val
= reason_code
;
5802 memcpy(&scbval
.ea
, curbssid
, ETHER_ADDR_LEN
);
5803 scbval
.val
= htod32(scbval
.val
);
5804 err
= wldev_ioctl_set(dev
, WLC_DISASSOC
, &scbval
,
5806 if (unlikely(err
)) {
5807 wl_clr_drv_status(cfg
, DISCONNECTING
, dev
);
5808 WL_ERR(("error (%d)\n", err
));
5811 wl_cfg80211_wait_for_disconnection(cfg
, dev
);
5814 #ifdef CUSTOM_SET_CPUCORE
5815 /* set default cpucore */
5816 if (dev
== bcmcfg_to_prmry_ndev(cfg
)) {
5817 dhdp
->chan_isvht80
&= ~DHD_FLAG_STA_MODE
;
5818 if (!(dhdp
->chan_isvht80
))
5819 dhd_set_cpucore(dhdp
, FALSE
);
5821 #endif /* CUSTOM_SET_CPUCORE */
5827 #if defined(WL_CFG80211_P2P_DEV_IF)
5828 wl_cfg80211_set_tx_power(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
5829 enum nl80211_tx_power_setting type
, s32 mbm
)
5831 wl_cfg80211_set_tx_power(struct wiphy
*wiphy
,
5832 enum nl80211_tx_power_setting type
, s32 dbm
)
5833 #endif /* WL_CFG80211_P2P_DEV_IF */
5836 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5837 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
5839 #if defined(WL_CFG80211_P2P_DEV_IF)
5840 s32 dbm
= MBM_TO_DBM(mbm
);
5841 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
5842 defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
5843 dbm
= MBM_TO_DBM(dbm
);
5844 #endif /* WL_CFG80211_P2P_DEV_IF */
5846 RETURN_EIO_IF_NOT_UP(cfg
);
5848 case NL80211_TX_POWER_AUTOMATIC
:
5850 case NL80211_TX_POWER_LIMITED
:
5852 WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
5856 case NL80211_TX_POWER_FIXED
:
5858 WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
5864 err
= wl_set_tx_power(ndev
, type
, dbm
);
5865 if (unlikely(err
)) {
5866 WL_ERR(("error (%d)\n", err
));
5870 cfg
->conf
->tx_power
= dbm
;
5876 #if defined(WL_CFG80211_P2P_DEV_IF)
5877 wl_cfg80211_get_tx_power(struct wiphy
*wiphy
,
5878 struct wireless_dev
*wdev
, s32
*dbm
)
5880 wl_cfg80211_get_tx_power(struct wiphy
*wiphy
, s32
*dbm
)
5881 #endif /* WL_CFG80211_P2P_DEV_IF */
5883 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5884 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
5887 RETURN_EIO_IF_NOT_UP(cfg
);
5888 err
= wl_get_tx_power(ndev
, dbm
);
5890 WL_ERR(("error (%d)\n", err
));
5896 wl_cfg80211_config_default_key(struct wiphy
*wiphy
, struct net_device
*dev
,
5897 u8 key_idx
, bool unicast
, bool multicast
)
5899 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5905 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5906 WL_ERR(("Find p2p index from dev(%p) failed\n", dev
->ieee80211_ptr
));
5910 WL_DBG(("key index (%d)\n", key_idx
));
5911 RETURN_EIO_IF_NOT_UP(cfg
);
5912 err
= wldev_iovar_getint_bsscfg(dev
, "wsec", &wsec
, bssidx
);
5913 if (unlikely(err
)) {
5914 WL_ERR(("WLC_GET_WSEC error (%d)\n", err
));
5917 if (wsec
== WEP_ENABLED
) {
5918 /* Just select a new current key */
5919 index
= (u32
) key_idx
;
5920 index
= htod32(index
);
5921 err
= wldev_ioctl_set(dev
, WLC_SET_KEY_PRIMARY
, &index
,
5923 if (unlikely(err
)) {
5924 WL_ERR(("error (%d)\n", err
));
5931 wl_add_keyext(struct wiphy
*wiphy
, struct net_device
*dev
,
5932 u8 key_idx
, const u8
*mac_addr
, struct key_params
*params
)
5934 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5935 struct wl_wsec_key key
;
5938 s32 mode
= wl_get_mode_by_netdev(cfg
, dev
);
5940 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5941 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
5944 memset(&key
, 0, sizeof(key
));
5945 key
.index
= (u32
) key_idx
;
5947 if (!ETHER_ISMULTI(mac_addr
))
5948 memcpy((char *)&key
.ea
, (const void *)mac_addr
, ETHER_ADDR_LEN
);
5949 key
.len
= (u32
) params
->key_len
;
5951 /* check for key index change */
5954 swap_key_from_BE(&key
);
5955 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &key
, sizeof(key
),
5956 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
5957 if (unlikely(err
)) {
5958 WL_ERR(("key delete error (%d)\n", err
));
5962 if (key
.len
> sizeof(key
.data
)) {
5963 WL_ERR(("Invalid key length (%d)\n", key
.len
));
5966 WL_DBG(("Setting the key index %d\n", key
.index
));
5967 memcpy(key
.data
, params
->key
, key
.len
);
5969 if ((mode
== WL_MODE_BSS
) &&
5970 (params
->cipher
== WLAN_CIPHER_SUITE_TKIP
)) {
5972 memcpy(keybuf
, &key
.data
[24], sizeof(keybuf
));
5973 memcpy(&key
.data
[24], &key
.data
[16], sizeof(keybuf
));
5974 memcpy(&key
.data
[16], keybuf
, sizeof(keybuf
));
5977 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
5978 if (params
->seq
&& params
->seq_len
== 6) {
5981 ivptr
= (u8
*) params
->seq
;
5982 key
.rxiv
.hi
= (ivptr
[5] << 24) | (ivptr
[4] << 16) |
5983 (ivptr
[3] << 8) | ivptr
[2];
5984 key
.rxiv
.lo
= (ivptr
[1] << 8) | ivptr
[0];
5985 key
.iv_initialized
= true;
5988 switch (params
->cipher
) {
5989 case WLAN_CIPHER_SUITE_WEP40
:
5990 key
.algo
= CRYPTO_ALGO_WEP1
;
5991 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
5993 case WLAN_CIPHER_SUITE_WEP104
:
5994 key
.algo
= CRYPTO_ALGO_WEP128
;
5995 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
5997 case WLAN_CIPHER_SUITE_TKIP
:
5998 key
.algo
= CRYPTO_ALGO_TKIP
;
5999 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6001 case WLAN_CIPHER_SUITE_AES_CMAC
:
6002 key
.algo
= CRYPTO_ALGO_AES_CCM
;
6003 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
6005 case WLAN_CIPHER_SUITE_CCMP
:
6006 key
.algo
= CRYPTO_ALGO_AES_CCM
;
6007 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
6010 WL_ERR(("Invalid cipher (0x%x)\n", params
->cipher
));
6013 swap_key_from_BE(&key
);
6014 /* need to guarantee EAPOL 4/4 send out before set key */
6015 dhd_wait_pend8021x(dev
);
6016 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &key
, sizeof(key
),
6017 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
6018 if (unlikely(err
)) {
6019 WL_ERR(("WLC_SET_KEY error (%d)\n", err
));
6027 wl_cfg80211_enable_roam_offload(struct net_device
*dev
, int enable
)
6030 wl_eventmsg_buf_t ev_buf
;
6031 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6033 if (dev
!= bcmcfg_to_prmry_ndev(cfg
)) {
6034 /* roam offload is only for the primary device */
6037 err
= wldev_iovar_setint(dev
, "roam_offload", enable
);
6041 bzero(&ev_buf
, sizeof(wl_eventmsg_buf_t
));
6042 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_PSK_SUP
, !enable
);
6043 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_ASSOC_REQ_IE
, !enable
);
6044 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_ASSOC_RESP_IE
, !enable
);
6045 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_REASSOC
, !enable
);
6046 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_JOIN
, !enable
);
6047 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_ROAM
, !enable
);
6048 err
= wl_cfg80211_apply_eventbuffer(dev
, cfg
, &ev_buf
);
6050 cfg
->roam_offload
= enable
;
6055 #if defined(WL_VIRTUAL_APSTA)
6057 wl_cfg80211_interface_create(struct net_device
*dev
, char *name
)
6059 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6060 bcm_struct_cfgdev
*new_cfgdev
;
6061 char ifname
[IFNAMSIZ
];
6062 char iftype
[IFNAMSIZ
];
6063 enum nl80211_iftype iface_type
= NL80211_IFTYPE_STATION
;
6065 sscanf(name
, "%s %s", ifname
, iftype
);
6067 if (strnicmp(iftype
, "AP", strlen("AP")) == 0) {
6068 iface_type
= NL80211_IFTYPE_AP
;
6071 new_cfgdev
= wl_cfg80211_create_iface(cfg
->wdev
->wiphy
,
6072 iface_type
, NULL
, ifname
);
6077 WL_DBG(("Iface %s created successfuly\n", name
));
6083 wl_cfg80211_interface_delete(struct net_device
*dev
, char *name
)
6085 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6086 struct net_info
*iter
, *next
;
6087 int err
= BCME_ERROR
;
6093 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
6094 #pragma GCC diagnostic push
6095 #pragma GCC diagnostic ignored "-Wcast-qual"
6097 for_each_ndev(cfg
, iter
, next
) {
6099 if (strcmp(iter
->ndev
->name
, name
) == 0) {
6100 err
= wl_cfg80211_del_iface(cfg
->wdev
->wiphy
,
6101 ndev_to_cfgdev(iter
->ndev
));
6106 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
6107 #pragma GCC diagnostic pop
6110 WL_DBG(("Iface %s deleted successfuly", name
));
6115 #if defined(PKT_FILTER_SUPPORT) && defined(APSTA_BLOCK_ARP_DURING_DHCP)
6117 wl_cfg80211_block_arp(struct net_device
*dev
, int enable
)
6119 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6120 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
6122 if (!dhd_pkt_filter_enable
) {
6123 WL_INFORM(("Packet filter isn't enabled\n"));
6127 /* Block/Unblock ARP frames only if STA is connected to
6128 * the upstream AP in case of STA+SoftAP Concurrenct mode
6130 if (!wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
6131 WL_INFORM(("STA doesn't connected to upstream AP\n"));
6136 WL_DBG(("Enable ARP Filter\n"));
6137 /* Add ARP filter */
6138 dhd_packet_filter_add_remove(dhdp
, TRUE
, DHD_BROADCAST_ARP_FILTER_NUM
);
6140 /* Enable ARP packet filter - blacklist */
6141 dhd_master_mode
= FALSE
;
6142 dhd_pktfilter_offload_enable(dhdp
, dhdp
->pktfilter
[DHD_BROADCAST_ARP_FILTER_NUM
],
6143 TRUE
, dhd_master_mode
);
6145 WL_DBG(("Disable ARP Filter\n"));
6146 /* Disable ARP packet filter */
6147 dhd_master_mode
= TRUE
;
6148 dhd_pktfilter_offload_enable(dhdp
, dhdp
->pktfilter
[DHD_BROADCAST_ARP_FILTER_NUM
],
6149 FALSE
, dhd_master_mode
);
6151 /* Delete ARP filter */
6152 dhd_packet_filter_add_remove(dhdp
, FALSE
, DHD_BROADCAST_ARP_FILTER_NUM
);
6155 #endif /* PKT_FILTER_SUPPORT && APSTA_BLOCK_ARP_DURING_DHCP */
6156 #endif /* defined (WL_VIRTUAL_APSTA) */
6159 wl_cfg80211_add_key(struct wiphy
*wiphy
, struct net_device
*dev
,
6160 u8 key_idx
, bool pairwise
, const u8
*mac_addr
,
6161 struct key_params
*params
)
6163 struct wl_wsec_key key
;
6169 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6170 s32 mode
= wl_get_mode_by_netdev(cfg
, dev
);
6172 WL_DBG(("key index (%d)\n", key_idx
));
6173 RETURN_EIO_IF_NOT_UP(cfg
);
6175 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
6176 WL_ERR(("Find p2p index from dev(%p) failed\n", dev
->ieee80211_ptr
));
6179 wl_cfg80211_check_in4way(cfg
, dev
, NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
,
6180 WL_EXT_STATUS_4WAY_DONE
, NULL
);
6183 ((params
->cipher
!= WLAN_CIPHER_SUITE_WEP40
) &&
6184 (params
->cipher
!= WLAN_CIPHER_SUITE_WEP104
))) {
6185 wl_add_keyext(wiphy
, dev
, key_idx
, mac_addr
, params
);
6188 memset(&key
, 0, sizeof(key
));
6189 /* Clear any buffered wep key */
6190 memset(&cfg
->wep_key
, 0, sizeof(struct wl_wsec_key
));
6192 key
.len
= (u32
) params
->key_len
;
6193 key
.index
= (u32
) key_idx
;
6195 if (unlikely(key
.len
> sizeof(key
.data
))) {
6196 WL_ERR(("Too long key length (%u)\n", key
.len
));
6199 memcpy(key
.data
, params
->key
, key
.len
);
6201 key
.flags
= WL_PRIMARY_KEY
;
6202 switch (params
->cipher
) {
6203 case WLAN_CIPHER_SUITE_WEP40
:
6204 key
.algo
= CRYPTO_ALGO_WEP1
;
6206 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
6208 case WLAN_CIPHER_SUITE_WEP104
:
6209 key
.algo
= CRYPTO_ALGO_WEP128
;
6211 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
6213 case WLAN_CIPHER_SUITE_TKIP
:
6214 key
.algo
= CRYPTO_ALGO_TKIP
;
6216 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
6217 if (mode
== WL_MODE_BSS
) {
6218 bcopy(&key
.data
[24], keybuf
, sizeof(keybuf
));
6219 bcopy(&key
.data
[16], &key
.data
[24], sizeof(keybuf
));
6220 bcopy(keybuf
, &key
.data
[16], sizeof(keybuf
));
6222 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6224 case WLAN_CIPHER_SUITE_AES_CMAC
:
6225 key
.algo
= CRYPTO_ALGO_AES_CCM
;
6227 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
6229 case WLAN_CIPHER_SUITE_CCMP
:
6230 key
.algo
= CRYPTO_ALGO_AES_CCM
;
6232 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
6235 WL_ERR(("Invalid cipher (0x%x)\n", params
->cipher
));
6239 /* Set the new key/index */
6240 if ((mode
== WL_MODE_IBSS
) && (val
& (TKIP_ENABLED
| AES_ENABLED
))) {
6241 WL_ERR(("IBSS KEY setted\n"));
6242 wldev_iovar_setint(dev
, "wpa_auth", WPA_AUTH_NONE
);
6244 swap_key_from_BE(&key
);
6245 if ((params
->cipher
== WLAN_CIPHER_SUITE_WEP40
) ||
6246 (params
->cipher
== WLAN_CIPHER_SUITE_WEP104
)) {
6248 * For AP role, since we are doing a wl down before bringing up AP,
6249 * the plumbed keys will be lost. So for AP once we bring up AP, we
6250 * need to plumb keys again. So buffer the keys for future use. This
6251 * is more like a WAR. If firmware later has the capability to do
6252 * interface upgrade without doing a "wl down" and "wl apsta 0", then
6253 * this will not be required.
6255 WL_DBG(("Buffering WEP Keys \n"));
6256 memcpy(&cfg
->wep_key
, &key
, sizeof(struct wl_wsec_key
));
6258 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &key
, sizeof(key
), cfg
->ioctl_buf
,
6259 WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
6260 if (unlikely(err
)) {
6261 WL_ERR(("WLC_SET_KEY error (%d)\n", err
));
6266 err
= wldev_iovar_getint_bsscfg(dev
, "wsec", &wsec
, bssidx
);
6267 if (unlikely(err
)) {
6268 WL_ERR(("get wsec error (%d)\n", err
));
6273 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", wsec
, bssidx
);
6274 if (unlikely(err
)) {
6275 WL_ERR(("set wsec error (%d)\n", err
));
6283 wl_cfg80211_del_key(struct wiphy
*wiphy
, struct net_device
*dev
,
6284 u8 key_idx
, bool pairwise
, const u8
*mac_addr
)
6286 struct wl_wsec_key key
;
6287 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6291 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
6292 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
6295 WL_DBG(("Enter\n"));
6298 if ((key_idx
>= DOT11_MAX_DEFAULT_KEYS
) && (key_idx
< DOT11_MAX_DEFAULT_KEYS
+2))
6302 RETURN_EIO_IF_NOT_UP(cfg
);
6303 memset(&key
, 0, sizeof(key
));
6305 key
.flags
= WL_PRIMARY_KEY
;
6306 key
.algo
= CRYPTO_ALGO_OFF
;
6307 key
.index
= (u32
) key_idx
;
6309 WL_DBG(("key index (%d)\n", key_idx
));
6310 /* Set the new key/index */
6311 swap_key_from_BE(&key
);
6312 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &key
, sizeof(key
), cfg
->ioctl_buf
,
6313 WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
6314 if (unlikely(err
)) {
6315 if (err
== -EINVAL
) {
6316 if (key
.index
>= DOT11_MAX_DEFAULT_KEYS
) {
6317 /* we ignore this key index in this case */
6318 WL_DBG(("invalid key index (%d)\n", key_idx
));
6321 WL_ERR(("WLC_SET_KEY error (%d)\n", err
));
6329 wl_cfg80211_get_key(struct wiphy
*wiphy
, struct net_device
*dev
,
6330 u8 key_idx
, bool pairwise
, const u8
*mac_addr
, void *cookie
,
6331 void (*callback
) (void *cookie
, struct key_params
* params
))
6333 struct key_params params
;
6334 struct wl_wsec_key key
;
6335 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6336 struct wl_security
*sec
;
6341 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
6342 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
6345 WL_DBG(("key index (%d)\n", key_idx
));
6346 RETURN_EIO_IF_NOT_UP(cfg
);
6347 memset(&key
, 0, sizeof(key
));
6348 key
.index
= key_idx
;
6349 swap_key_to_BE(&key
);
6350 memset(¶ms
, 0, sizeof(params
));
6351 params
.key_len
= (u8
) min_t(u8
, DOT11_MAX_KEY_SIZE
, key
.len
);
6352 memcpy((void *)params
.key
, key
.data
, params
.key_len
);
6354 err
= wldev_iovar_getint_bsscfg(dev
, "wsec", &wsec
, bssidx
);
6355 if (unlikely(err
)) {
6356 WL_ERR(("WLC_GET_WSEC error (%d)\n", err
));
6359 switch (WSEC_ENABLED(wsec
)) {
6361 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
6362 if (sec
->cipher_pairwise
& WLAN_CIPHER_SUITE_WEP40
) {
6363 params
.cipher
= WLAN_CIPHER_SUITE_WEP40
;
6364 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
6365 } else if (sec
->cipher_pairwise
& WLAN_CIPHER_SUITE_WEP104
) {
6366 params
.cipher
= WLAN_CIPHER_SUITE_WEP104
;
6367 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
6371 params
.cipher
= WLAN_CIPHER_SUITE_TKIP
;
6372 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6375 params
.cipher
= WLAN_CIPHER_SUITE_AES_CMAC
;
6376 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
6378 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
6379 /* to connect to mixed mode AP */
6380 case (AES_ENABLED
| TKIP_ENABLED
): /* TKIP CCMP */
6381 params
.cipher
= WLAN_CIPHER_SUITE_AES_CMAC
;
6382 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6386 WL_ERR(("Invalid algo (0x%x)\n", wsec
));
6390 callback(cookie
, ¶ms
);
6395 wl_cfg80211_config_default_mgmt_key(struct wiphy
*wiphy
,
6396 struct net_device
*dev
, u8 key_idx
)
6401 WL_INFORM(("Not supported\n"));
6407 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
6408 wl_cfg80211_get_station(struct wiphy
*wiphy
, struct net_device
*dev
,
6409 const u8
*mac
, struct station_info
*sinfo
)
6411 wl_cfg80211_get_station(struct wiphy
*wiphy
, struct net_device
*dev
,
6412 u8
*mac
, struct station_info
*sinfo
)
6415 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6421 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
6422 s8 eabuf
[ETHER_ADDR_STR_LEN
];
6424 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
6425 bool fw_assoc_state
= FALSE
;
6426 u32 dhd_assoc_state
= 0;
6427 static int err_cnt
= 0;
6429 RETURN_EIO_IF_NOT_UP(cfg
);
6430 if (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
) {
6431 err
= wldev_iovar_getbuf(dev
, "sta_info", (struct ether_addr
*)mac
,
6432 ETHER_ADDR_LEN
, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
);
6434 WL_ERR(("GET STA INFO failed, %d\n", err
));
6437 sinfo
->filled
= STA_INFO_BIT(INFO_INACTIVE_TIME
);
6438 sta
= (sta_info_t
*)cfg
->ioctl_buf
;
6439 sta
->len
= dtoh16(sta
->len
);
6440 sta
->cap
= dtoh16(sta
->cap
);
6441 sta
->flags
= dtoh32(sta
->flags
);
6442 sta
->idle
= dtoh32(sta
->idle
);
6443 sta
->in
= dtoh32(sta
->in
);
6444 sinfo
->inactive_time
= sta
->idle
* 1000;
6445 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
6446 if (sta
->flags
& WL_STA_ASSOC
) {
6447 sinfo
->filled
|= STA_INFO_BIT(INFO_CONNECTED_TIME
);
6448 sinfo
->connected_time
= sta
->in
;
6450 WL_INFORM(("STA %s : idle time : %d sec, connected time :%d ms\n",
6451 bcm_ether_ntoa((const struct ether_addr
*)mac
, eabuf
), sinfo
->inactive_time
,
6454 } else if (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_BSS
||
6455 wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_IBSS
) {
6456 get_pktcnt_t pktcnt
;
6457 #ifdef DHD_SUPPORT_IF_CNTS
6458 wl_if_stats_t
*if_stats
= NULL
;
6459 #endif /* DHD_SUPPORT_IF_CNTS */
6462 if (cfg
->roam_offload
) {
6463 struct ether_addr bssid
;
6464 memset(&bssid
, 0, sizeof(bssid
));
6465 err
= wldev_ioctl_get(dev
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
);
6467 WL_ERR(("Failed to get current BSSID\n"));
6469 if (memcmp(mac
, &bssid
.octet
, ETHER_ADDR_LEN
) != 0) {
6470 /* roaming is detected */
6471 err
= wl_cfg80211_delayed_roam(cfg
, dev
, &bssid
);
6473 WL_ERR(("Failed to handle the delayed roam, "
6475 mac
= (u8
*)bssid
.octet
;
6479 dhd_assoc_state
= wl_get_drv_status(cfg
, CONNECTED
, dev
);
6480 DHD_OS_WAKE_LOCK(dhd
);
6481 fw_assoc_state
= dhd_is_associated(dhd
, 0, &err
);
6482 DHD_OS_WAKE_UNLOCK(dhd
);
6483 if (!dhd_assoc_state
|| !fw_assoc_state
) {
6484 WL_ERR(("NOT assoc\n"));
6485 if (err
== -ENODATA
)
6487 if (!dhd_assoc_state
) {
6488 WL_TRACE_HW4(("drv state is not connected \n"));
6490 if (!fw_assoc_state
) {
6491 WL_TRACE_HW4(("fw state is not associated \n"));
6493 /* Disconnect due to fw is not associated for FW_ASSOC_WATCHDOG_TIME ms.
6494 * 'err == 0' of dhd_is_associated() and '!fw_assoc_state'
6495 * means that BSSID is null.
6497 if (dhd_assoc_state
&& !fw_assoc_state
&& !err
) {
6498 if (!fw_assoc_watchdog_started
) {
6499 fw_assoc_watchdog_ms
= OSL_SYSUPTIME();
6500 fw_assoc_watchdog_started
= TRUE
;
6501 WL_TRACE_HW4(("fw_assoc_watchdog_started \n"));
6503 if (OSL_SYSUPTIME() - fw_assoc_watchdog_ms
>
6504 FW_ASSOC_WATCHDOG_TIME
) {
6505 fw_assoc_watchdog_started
= FALSE
;
6507 WL_TRACE_HW4(("fw is not associated for %d ms \n",
6508 (OSL_SYSUPTIME() - fw_assoc_watchdog_ms
)));
6509 goto get_station_err
;
6516 fw_assoc_watchdog_started
= FALSE
;
6517 curmacp
= wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
6518 if (memcmp(mac
, curmacp
, ETHER_ADDR_LEN
)) {
6519 WL_ERR(("Wrong Mac address: "MACDBG
" != "MACDBG
"\n",
6520 MAC2STRDBG(mac
), MAC2STRDBG(curmacp
)));
6523 /* Report the current tx rate */
6525 err
= wldev_ioctl_get(dev
, WLC_GET_RATE
, &rate
, sizeof(rate
));
6527 WL_ERR(("Could not get rate (%d)\n", err
));
6529 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
6532 rate
= dtoh32(rate
);
6533 sinfo
->filled
|= STA_INFO_BIT(INFO_TX_BITRATE
);
6534 sinfo
->txrate
.legacy
= rate
* 5;
6535 WL_DBG(("Rate %d Mbps\n", (rate
/ 2)));
6536 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
6537 rxpktglom
= ((rate
/2) > 150) ? 20 : 10;
6539 if (maxrxpktglom
!= rxpktglom
) {
6540 maxrxpktglom
= rxpktglom
;
6541 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate
/2),
6543 err
= wldev_iovar_setbuf(dev
, "bus:maxtxpktglom",
6544 (char*)&maxrxpktglom
, 4, cfg
->ioctl_buf
,
6545 WLC_IOCTL_MAXLEN
, NULL
);
6547 WL_ERR(("set bus:maxtxpktglom failed, %d\n", err
));
6553 memset(&scb_val
, 0, sizeof(scb_val
));
6555 err
= wldev_ioctl_get(dev
, WLC_GET_RSSI
, &scb_val
,
6558 WL_ERR(("Could not get rssi (%d)\n", err
));
6559 goto get_station_err
;
6561 rssi
= dtoh32(scb_val
.val
);
6562 #if defined(RSSIAVG)
6563 err
= wl_update_connected_rssi_cache(dev
, &cfg
->g_connected_rssi_cache_ctrl
, &rssi
);
6565 WL_ERR(("Could not get rssi (%d)\n", err
));
6566 goto get_station_err
;
6568 wl_delete_dirty_rssi_cache(&cfg
->g_connected_rssi_cache_ctrl
);
6569 wl_reset_rssi_cache(&cfg
->g_connected_rssi_cache_ctrl
);
6571 #if defined(RSSIOFFSET)
6572 rssi
= wl_update_rssi_offset(dev
, rssi
);
6574 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
6575 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
6576 rssi
= MIN(rssi
, RSSI_MAXVAL
);
6578 sinfo
->filled
|= STA_INFO_BIT(INFO_SIGNAL
);
6579 sinfo
->signal
= rssi
;
6580 WL_DBG(("RSSI %d dBm\n", rssi
));
6582 #ifdef DHD_SUPPORT_IF_CNTS
6583 if ((if_stats
= kmalloc(sizeof(*if_stats
), GFP_KERNEL
)) == NULL
) {
6584 WL_ERR(("%s(%d): kmalloc failed\n", __FUNCTION__
, __LINE__
));
6587 memset(if_stats
, 0, sizeof(*if_stats
));
6589 err
= wldev_iovar_getbuf(dev
, "if_counters", NULL
, 0,
6590 (char *)if_stats
, sizeof(*if_stats
), NULL
);
6592 sinfo
->rx_packets
= (uint32
)dtoh64(if_stats
->rxframe
);
6593 sinfo
->rx_dropped_misc
= 0;
6594 sinfo
->tx_packets
= (uint32
)dtoh64(if_stats
->txfrmsnt
);
6595 sinfo
->tx_failed
= (uint32
)dtoh64(if_stats
->txnobuf
) +
6596 (uint32
)dtoh64(if_stats
->txrunt
) +
6597 (uint32
)dtoh64(if_stats
->txfail
);
6599 // WL_ERR(("%s: if_counters not supported ret=%d\n",
6600 // __FUNCTION__, err));
6601 #endif /* DHD_SUPPORT_IF_CNTS */
6603 err
= wldev_ioctl_get(dev
, WLC_GET_PKTCNTS
, &pktcnt
,
6606 WL_ERR(("Could not get WLC_GET_PKTCNTS (%d)\n", err
));
6607 goto get_station_err
;
6609 sinfo
->rx_packets
= pktcnt
.rx_good_pkt
;
6610 sinfo
->rx_dropped_misc
= pktcnt
.rx_bad_pkt
;
6611 sinfo
->tx_packets
= pktcnt
.tx_good_pkt
;
6612 sinfo
->tx_failed
= pktcnt
.tx_bad_pkt
;
6613 #ifdef DHD_SUPPORT_IF_CNTS
6615 #endif /* DHD_SUPPORT_IF_CNTS */
6617 sinfo
->filled
|= (STA_INFO_BIT(INFO_RX_PACKETS
) |
6618 STA_INFO_BIT(INFO_RX_DROP_MISC
) |
6619 STA_INFO_BIT(INFO_TX_PACKETS
) |
6620 STA_INFO_BIT(INFO_TX_FAILED
));
6627 if (err_cnt
>= 3 && (err
!= -ENODATA
)) {
6628 /* Disconnect due to zero BSSID or error to get RSSI */
6630 scbval
.val
= htod32(DOT11_RC_DISASSOC_LEAVING
);
6631 err
= wldev_ioctl_set(dev
, WLC_DISASSOC
, &scbval
, sizeof(scb_val_t
));
6632 if (unlikely(err
)) {
6633 WL_ERR(("disassoc error (%d)\n", err
));
6636 WL_ERR(("force cfg80211_disconnected: %d\n", err
));
6637 wl_clr_drv_status(cfg
, CONNECTED
, dev
);
6638 CFG80211_DISCONNECTED(dev
, 0, NULL
, 0, false, GFP_KERNEL
);
6641 #ifdef DHD_SUPPORT_IF_CNTS
6646 #endif /* DHD_SUPPORT_IF_CNTS */
6649 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg
, dev
)));
6656 wl_cfg80211_set_power_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
6657 bool enabled
, s32 timeout
)
6661 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6662 struct net_info
*_net_info
= wl_get_netinfo_by_netdev(cfg
, dev
);
6664 rtt_status_info_t
*rtt_status
;
6665 #endif /* RTT_SUPPORT */
6666 dhd_pub_t
*dhd
= cfg
->pub
;
6668 RETURN_EIO_IF_NOT_UP(cfg
);
6669 WL_DBG(("Enter\n"));
6670 if (cfg
->p2p_net
== dev
|| _net_info
== NULL
||
6671 !wl_get_drv_status(cfg
, CONNECTED
, dev
) ||
6672 (wl_get_mode_by_netdev(cfg
, dev
) != WL_MODE_BSS
&&
6673 wl_get_mode_by_netdev(cfg
, dev
) != WL_MODE_IBSS
)) {
6677 /* Enlarge pm_enable_work */
6678 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_LONG
);
6680 pm
= enabled
? PM_FAST
: PM_OFF
;
6681 if (_net_info
->pm_block
) {
6682 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
6683 dev
->name
, _net_info
->pm_block
));
6686 if (enabled
&& dhd_conf_get_pm(dhd
) >= 0)
6687 pm
= dhd_conf_get_pm(dhd
);
6689 WL_DBG(("%s:power save %s\n", dev
->name
, (pm
? "enabled" : "disabled")));
6691 rtt_status
= GET_RTTSTATE(dhd
);
6692 if (rtt_status
->status
!= RTT_ENABLED
) {
6693 #endif /* RTT_SUPPORT */
6694 err
= wldev_ioctl_set(dev
, WLC_SET_PM
, &pm
, sizeof(pm
));
6695 if (unlikely(err
)) {
6697 WL_DBG(("net_device is not ready yet\n"));
6699 WL_ERR(("error (%d)\n", err
));
6704 #endif /* RTT_SUPPORT */
6705 wl_cfg80211_update_power_mode(dev
);
6709 void wl_cfg80211_update_power_mode(struct net_device
*dev
)
6713 err
= wldev_ioctl_get(dev
, WLC_GET_PM
, &pm
, sizeof(pm
));
6715 WL_ERR(("%s:error (%d)\n", __FUNCTION__
, err
));
6716 else if (pm
!= -1 && dev
->ieee80211_ptr
)
6717 dev
->ieee80211_ptr
->ps
= (pm
== PM_OFF
) ? false : true;
6720 void wl_cfg80211_set_passive_scan(struct net_device
*dev
, char *command
)
6722 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6724 if (strcmp(command
, "SCAN-ACTIVE") == 0) {
6725 cfg
->active_scan
= 1;
6726 } else if (strcmp(command
, "SCAN-PASSIVE") == 0) {
6727 cfg
->active_scan
= 0;
6729 WL_ERR(("Unknown command \n"));
6732 static __used u32
wl_find_msb(u16 bit16
)
6736 if (bit16
& 0xff00) {
6759 static s32
wl_cfg80211_resume(struct wiphy
*wiphy
)
6761 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6762 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
6765 if (unlikely(!wl_get_drv_status(cfg
, READY
, ndev
))) {
6766 WL_INFORM(("device is not ready\n"));
6776 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
6777 wl_cfg80211_suspend(struct wiphy
*wiphy
, struct cfg80211_wowlan
*wow
)
6779 wl_cfg80211_suspend(struct wiphy
*wiphy
)
6780 #endif /* KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES */
6783 #ifdef DHD_CLEAR_ON_SUSPEND
6784 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6785 struct net_info
*iter
, *next
;
6786 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
6787 unsigned long flags
;
6788 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
6789 struct cfg80211_scan_info info
;
6792 if (unlikely(!wl_get_drv_status(cfg
, READY
, ndev
))) {
6793 WL_INFORM(("device is not ready : status (%d)\n",
6797 for_each_ndev(cfg
, iter
, next
) {
6798 /* p2p discovery iface doesn't have a ndev associated with it (for kernel > 3.8) */
6800 wl_set_drv_status(cfg
, SCAN_ABORTING
, iter
->ndev
);
6802 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
6803 if (cfg
->scan_request
) {
6804 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
6805 info
.aborted
= true;
6806 cfg80211_scan_done(cfg
->scan_request
, &info
);
6808 cfg80211_scan_done(cfg
->scan_request
, true);
6810 cfg
->scan_request
= NULL
;
6812 for_each_ndev(cfg
, iter
, next
) {
6814 wl_clr_drv_status(cfg
, SCANNING
, iter
->ndev
);
6815 wl_clr_drv_status(cfg
, SCAN_ABORTING
, iter
->ndev
);
6818 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
6819 for_each_ndev(cfg
, iter
, next
) {
6821 if (wl_get_drv_status(cfg
, CONNECTING
, iter
->ndev
)) {
6822 wl_bss_connect_done(cfg
, iter
->ndev
, NULL
, NULL
, false);
6826 #endif /* DHD_CLEAR_ON_SUSPEND */
6833 wl_update_pmklist(struct net_device
*dev
, struct wl_pmk_list
*pmk_list
,
6837 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6838 struct net_device
*primary_dev
= bcmcfg_to_prmry_ndev(cfg
);
6841 printf("pmk_list is NULL\n");
6844 /* pmk list is supported only for STA interface i.e. primary interface
6845 * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
6847 if (primary_dev
!= dev
) {
6848 WL_INFORM(("Not supporting Flushing pmklist on virtual"
6849 " interfaces than primary interface\n"));
6853 WL_DBG(("No of elements %d\n", pmk_list
->pmkids
.npmkid
));
6854 for (i
= 0; i
< pmk_list
->pmkids
.npmkid
; i
++) {
6855 WL_DBG(("PMKID[%d]: %pM =\n", i
,
6856 &pmk_list
->pmkids
.pmkid
[i
].BSSID
));
6857 for (j
= 0; j
< WPA2_PMKID_LEN
; j
++) {
6858 WL_DBG(("%02x\n", pmk_list
->pmkids
.pmkid
[i
].PMKID
[j
]));
6862 err
= wldev_iovar_setbuf(dev
, "pmkid_info", (char *)pmk_list
,
6863 sizeof(*pmk_list
), cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
6870 wl_cfg80211_set_pmksa(struct wiphy
*wiphy
, struct net_device
*dev
,
6871 struct cfg80211_pmksa
*pmksa
)
6873 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6877 RETURN_EIO_IF_NOT_UP(cfg
);
6878 for (i
= 0; i
< cfg
->pmk_list
->pmkids
.npmkid
; i
++)
6879 if (!memcmp(pmksa
->bssid
, &cfg
->pmk_list
->pmkids
.pmkid
[i
].BSSID
,
6882 if (i
< WL_NUM_PMKIDS_MAX
) {
6883 memcpy(&cfg
->pmk_list
->pmkids
.pmkid
[i
].BSSID
, pmksa
->bssid
,
6885 memcpy(&cfg
->pmk_list
->pmkids
.pmkid
[i
].PMKID
, pmksa
->pmkid
,
6887 if (i
== cfg
->pmk_list
->pmkids
.npmkid
)
6888 cfg
->pmk_list
->pmkids
.npmkid
++;
6892 WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
6893 &cfg
->pmk_list
->pmkids
.pmkid
[cfg
->pmk_list
->pmkids
.npmkid
- 1].BSSID
));
6894 for (i
= 0; i
< WPA2_PMKID_LEN
; i
++) {
6896 cfg
->pmk_list
->pmkids
.pmkid
[cfg
->pmk_list
->pmkids
.npmkid
- 1].
6900 err
= wl_update_pmklist(dev
, cfg
->pmk_list
, err
);
6906 wl_cfg80211_del_pmksa(struct wiphy
*wiphy
, struct net_device
*dev
,
6907 struct cfg80211_pmksa
*pmksa
)
6909 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6911 struct _pmkid_list pmkid
= {.npmkid
= 0};
6915 RETURN_EIO_IF_NOT_UP(cfg
);
6916 memcpy(&pmkid
.pmkid
[0].BSSID
, pmksa
->bssid
, ETHER_ADDR_LEN
);
6917 memcpy(pmkid
.pmkid
[0].PMKID
, pmksa
->pmkid
, WPA2_PMKID_LEN
);
6919 WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
6920 &pmkid
.pmkid
[0].BSSID
));
6921 for (i
= 0; i
< WPA2_PMKID_LEN
; i
++) {
6922 WL_DBG(("%02x\n", pmkid
.pmkid
[0].PMKID
[i
]));
6925 for (i
= 0; i
< cfg
->pmk_list
->pmkids
.npmkid
; i
++)
6927 (pmksa
->bssid
, &cfg
->pmk_list
->pmkids
.pmkid
[i
].BSSID
,
6931 if ((cfg
->pmk_list
->pmkids
.npmkid
> 0) &&
6932 (i
< cfg
->pmk_list
->pmkids
.npmkid
)) {
6933 memset(&cfg
->pmk_list
->pmkids
.pmkid
[i
], 0, sizeof(pmkid_t
));
6934 for (; i
< (cfg
->pmk_list
->pmkids
.npmkid
- 1); i
++) {
6935 memcpy(&cfg
->pmk_list
->pmkids
.pmkid
[i
].BSSID
,
6936 &cfg
->pmk_list
->pmkids
.pmkid
[i
+ 1].BSSID
,
6938 memcpy(&cfg
->pmk_list
->pmkids
.pmkid
[i
].PMKID
,
6939 &cfg
->pmk_list
->pmkids
.pmkid
[i
+ 1].PMKID
,
6942 cfg
->pmk_list
->pmkids
.npmkid
--;
6947 err
= wl_update_pmklist(dev
, cfg
->pmk_list
, err
);
6954 wl_cfg80211_flush_pmksa(struct wiphy
*wiphy
, struct net_device
*dev
)
6956 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6958 RETURN_EIO_IF_NOT_UP(cfg
);
6959 memset(cfg
->pmk_list
, 0, sizeof(*cfg
->pmk_list
));
6960 err
= wl_update_pmklist(dev
, cfg
->pmk_list
, err
);
6964 static wl_scan_params_t
*
6965 wl_cfg80211_scan_alloc_params(struct bcm_cfg80211
*cfg
, int channel
, int nprobes
,
6966 int *out_params_size
)
6968 wl_scan_params_t
*params
;
6973 *out_params_size
= 0;
6975 /* Our scan params only need space for 1 channel and 0 ssids */
6976 params_size
= WL_SCAN_PARAMS_FIXED_SIZE
+ 1 * sizeof(uint16
);
6977 params
= (wl_scan_params_t
*) kzalloc(params_size
, GFP_KERNEL
);
6978 if (params
== NULL
) {
6979 WL_ERR(("mem alloc failed (%d bytes)\n", params_size
));
6982 memset(params
, 0, params_size
);
6983 params
->nprobes
= nprobes
;
6985 num_chans
= (channel
== 0) ? 0 : 1;
6987 memcpy(¶ms
->bssid
, ðer_bcast
, ETHER_ADDR_LEN
);
6988 params
->bss_type
= DOT11_BSSTYPE_ANY
;
6989 params
->scan_type
= DOT11_SCANTYPE_ACTIVE
;
6990 params
->nprobes
= htod32(1);
6991 params
->active_time
= htod32(-1);
6992 params
->passive_time
= htod32(-1);
6993 params
->home_time
= htod32(10);
6995 params
->channel_list
[0] = htodchanspec(channel
);
6997 params
->channel_list
[0] = wl_ch_host_to_driver(cfg
, bssidx
, channel
);
6999 /* Our scan params have 1 channel and 0 ssids */
7000 params
->channel_num
= htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT
) |
7001 (num_chans
& WL_SCAN_PARAMS_COUNT_MASK
));
7003 *out_params_size
= params_size
; /* rtn size to the caller */
7008 #if defined(WL_CFG80211_P2P_DEV_IF)
7009 wl_cfg80211_remain_on_channel(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
,
7010 struct ieee80211_channel
*channel
, unsigned int duration
, u64
*cookie
)
7012 wl_cfg80211_remain_on_channel(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
,
7013 struct ieee80211_channel
* channel
,
7014 enum nl80211_channel_type channel_type
,
7015 unsigned int duration
, u64
*cookie
)
7016 #endif /* WL_CFG80211_P2P_DEV_IF */
7021 struct ether_addr primary_mac
;
7022 struct net_device
*ndev
= NULL
;
7023 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7026 PRINT_WDEV_INFO(cfgdev
);
7027 #endif /* DHD_IFDEBUG */
7029 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
7031 WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
7032 ieee80211_frequency_to_channel(channel
->center_freq
),
7033 duration
, (wl_get_drv_status(cfg
, SCANNING
, ndev
)) ? "YES":"NO"));
7036 WL_ERR(("cfg->p2p is not initialized\n"));
7041 #ifdef P2P_LISTEN_OFFLOADING
7042 if (wl_get_p2p_status(cfg
, DISC_IN_PROGRESS
)) {
7043 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
7046 #endif /* P2P_LISTEN_OFFLOADING */
7048 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7049 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
7050 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, true, true);
7052 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7054 target_channel
= ieee80211_frequency_to_channel(channel
->center_freq
);
7055 memcpy(&cfg
->remain_on_chan
, channel
, sizeof(struct ieee80211_channel
));
7056 #if defined(WL_ENABLE_P2P_IF)
7057 cfg
->remain_on_chan_type
= channel_type
;
7058 #endif /* WL_ENABLE_P2P_IF */
7059 id
= ++cfg
->last_roc_id
;
7061 id
= ++cfg
->last_roc_id
;
7064 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7065 if (wl_get_drv_status(cfg
, SCANNING
, ndev
)) {
7066 struct timer_list
*_timer
;
7067 WL_DBG(("scan is running. go to fake listen state\n"));
7069 if (duration
> LONG_LISTEN_TIME
) {
7070 wl_cfg80211_scan_abort(cfg
);
7072 wl_set_drv_status(cfg
, FAKE_REMAINING_ON_CHANNEL
, ndev
);
7074 if (timer_pending(&cfg
->p2p
->listen_timer
)) {
7075 WL_DBG(("cancel current listen timer \n"));
7076 del_timer_sync(&cfg
->p2p
->listen_timer
);
7079 _timer
= &cfg
->p2p
->listen_timer
;
7080 wl_clr_p2p_status(cfg
, LISTEN_EXPIRED
);
7082 INIT_TIMER(_timer
, wl_cfgp2p_listen_expired
, duration
, 0);
7088 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7090 #ifdef WL_CFG80211_SYNC_GON
7091 if (wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM_LISTEN
)) {
7092 /* do not enter listen mode again if we are in listen mode already for next af.
7093 * remain on channel completion will be returned by waiting next af completion.
7095 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7096 wl_set_drv_status(cfg
, FAKE_REMAINING_ON_CHANNEL
, ndev
);
7098 wl_set_drv_status(cfg
, REMAINING_ON_CHANNEL
, ndev
);
7099 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7102 #endif /* WL_CFG80211_SYNC_GON */
7103 if (cfg
->p2p
&& !cfg
->p2p
->on
) {
7104 /* In case of p2p_listen command, supplicant send remain_on_channel
7105 * without turning on P2P
7107 get_primary_mac(cfg
, &primary_mac
);
7108 wl_cfgp2p_generate_bss_mac(cfg
, &primary_mac
);
7112 if (p2p_is_on(cfg
)) {
7113 err
= wl_cfgp2p_enable_discovery(cfg
, ndev
, NULL
, 0);
7114 if (unlikely(err
)) {
7117 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7118 wl_set_drv_status(cfg
, REMAINING_ON_CHANNEL
, ndev
);
7119 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7120 err
= wl_cfgp2p_discover_listen(cfg
, target_channel
, duration
);
7122 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7123 if (err
== BCME_OK
) {
7124 wl_set_drv_status(cfg
, REMAINING_ON_CHANNEL
, ndev
);
7126 /* if failed, firmware may be internal scanning state.
7127 * so other scan request shall not abort it
7129 wl_set_drv_status(cfg
, FAKE_REMAINING_ON_CHANNEL
, ndev
);
7131 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7132 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
7133 * and expire timer will send a completion to the upper layer
7139 if (err
== BCME_OK
) {
7140 WL_INFORM(("Success\n"));
7141 #if defined(WL_CFG80211_P2P_DEV_IF)
7142 cfg80211_ready_on_channel(cfgdev
, *cookie
, channel
,
7143 duration
, GFP_KERNEL
);
7145 cfg80211_ready_on_channel(cfgdev
, *cookie
, channel
,
7146 channel_type
, duration
, GFP_KERNEL
);
7147 #endif /* WL_CFG80211_P2P_DEV_IF */
7149 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err
, *cookie
));
7155 wl_cfg80211_cancel_remain_on_channel(struct wiphy
*wiphy
,
7156 bcm_struct_cfgdev
*cfgdev
, u64 cookie
)
7160 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7162 #ifdef P2PLISTEN_AP_SAMECHN
7163 struct net_device
*dev
;
7164 #endif /* P2PLISTEN_AP_SAMECHN */
7166 RETURN_EIO_IF_NOT_UP(cfg
);
7169 PRINT_WDEV_INFO(cfgdev
);
7170 #endif /* DHD_IFDEBUG */
7172 #if defined(WL_CFG80211_P2P_DEV_IF)
7173 if (cfgdev
->iftype
== NL80211_IFTYPE_P2P_DEVICE
) {
7174 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
7177 WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev
->ifindex
));
7178 #endif /* WL_CFG80211_P2P_DEV_IF */
7180 #ifdef P2PLISTEN_AP_SAMECHN
7181 if (cfg
&& cfg
->p2p_resp_apchn_status
) {
7182 dev
= bcmcfg_to_prmry_ndev(cfg
);
7183 wl_cfg80211_set_p2p_resp_ap_chn(dev
, 0);
7184 cfg
->p2p_resp_apchn_status
= false;
7185 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
7187 #endif /* P2PLISTEN_AP_SAMECHN */
7189 if (cfg
->last_roc_id
== cookie
) {
7190 wl_cfgp2p_set_p2p_mode(cfg
, WL_P2P_DISC_ST_SCAN
, 0, 0,
7191 wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
));
7193 WL_ERR(("%s : ignore, request cookie(%llu) is not matched. (cur : %llu)\n",
7194 __FUNCTION__
, cookie
, cfg
->last_roc_id
));
7201 wl_cfg80211_afx_handler(struct work_struct
*work
)
7203 struct afx_hdl
*afx_instance
;
7204 struct bcm_cfg80211
*cfg
;
7207 BCM_SET_CONTAINER_OF(afx_instance
, work
, struct afx_hdl
, work
);
7208 if (!afx_instance
) {
7209 WL_ERR(("afx_instance is NULL\n"));
7212 cfg
= wl_get_cfg(afx_instance
->dev
);
7214 if (cfg
->afx_hdl
->is_active
) {
7215 if (cfg
->afx_hdl
->is_listen
&& cfg
->afx_hdl
->my_listen_chan
) {
7216 ret
= wl_cfgp2p_discover_listen(cfg
, cfg
->afx_hdl
->my_listen_chan
,
7217 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
7219 ret
= wl_cfgp2p_act_frm_search(cfg
, cfg
->afx_hdl
->dev
,
7220 cfg
->afx_hdl
->bssidx
, cfg
->afx_hdl
->peer_listen_chan
,
7223 if (unlikely(ret
!= BCME_OK
)) {
7224 WL_ERR(("ERROR occurred! returned value is (%d)\n", ret
));
7225 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
))
7226 complete(&cfg
->act_frm_scan
);
7233 wl_cfg80211_af_searching_channel(struct bcm_cfg80211
*cfg
, struct net_device
*dev
)
7235 u32 max_retry
= WL_CHANNEL_SYNC_RETRY
;
7236 bool is_p2p_gas
= false;
7241 WL_DBG((" enter ) \n"));
7243 wl_set_drv_status(cfg
, FINDING_COMMON_CHANNEL
, dev
);
7244 cfg
->afx_hdl
->is_active
= TRUE
;
7246 if (cfg
->afx_hdl
->pending_tx_act_frm
) {
7247 wl_action_frame_t
*action_frame
;
7248 action_frame
= &(cfg
->afx_hdl
->pending_tx_act_frm
->action_frame
);
7249 if (wl_cfgp2p_is_p2p_gas_action(action_frame
->data
, action_frame
->len
))
7253 /* Loop to wait until we find a peer's channel or the
7254 * pending action frame tx is cancelled.
7256 while ((cfg
->afx_hdl
->retry
< max_retry
) &&
7257 (cfg
->afx_hdl
->peer_chan
== WL_INVALID
)) {
7258 cfg
->afx_hdl
->is_listen
= FALSE
;
7259 wl_set_drv_status(cfg
, SCANNING
, dev
);
7260 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
7261 cfg
->afx_hdl
->retry
));
7262 /* search peer on peer's listen channel */
7263 schedule_work(&cfg
->afx_hdl
->work
);
7264 wait_for_completion_timeout(&cfg
->act_frm_scan
,
7265 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX
));
7267 if ((cfg
->afx_hdl
->peer_chan
!= WL_INVALID
) ||
7268 !(wl_get_drv_status(cfg
, FINDING_COMMON_CHANNEL
, dev
)))
7274 if (cfg
->afx_hdl
->my_listen_chan
) {
7275 WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
7276 cfg
->afx_hdl
->my_listen_chan
));
7277 /* listen on my listen channel */
7278 cfg
->afx_hdl
->is_listen
= TRUE
;
7279 schedule_work(&cfg
->afx_hdl
->work
);
7280 wait_for_completion_timeout(&cfg
->act_frm_scan
,
7281 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX
));
7283 if ((cfg
->afx_hdl
->peer_chan
!= WL_INVALID
) ||
7284 !(wl_get_drv_status(cfg
, FINDING_COMMON_CHANNEL
, dev
)))
7287 cfg
->afx_hdl
->retry
++;
7289 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg
);
7292 cfg
->afx_hdl
->is_active
= FALSE
;
7294 wl_clr_drv_status(cfg
, SCANNING
, dev
);
7295 wl_clr_drv_status(cfg
, FINDING_COMMON_CHANNEL
, dev
);
7297 return (cfg
->afx_hdl
->peer_chan
);
7300 struct p2p_config_af_params
{
7301 s32 max_tx_retry
; /* max tx retry count if tx no ack */
7302 #ifdef WL_CFG80211_SYNC_GON
7305 bool search_channel
; /* 1: search peer's channel to send af */
7309 wl_cfg80211_config_p2p_pub_af_tx(struct wiphy
*wiphy
,
7310 wl_action_frame_t
*action_frame
, wl_af_params_t
*af_params
,
7311 struct p2p_config_af_params
*config_af_params
)
7314 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7315 wifi_p2p_pub_act_frame_t
*act_frm
=
7316 (wifi_p2p_pub_act_frame_t
*) (action_frame
->data
);
7318 /* initialize default value */
7319 #ifdef WL_CFG80211_SYNC_GON
7320 config_af_params
->extra_listen
= true;
7322 config_af_params
->search_channel
= false;
7323 config_af_params
->max_tx_retry
= WL_AF_TX_MAX_RETRY
;
7324 cfg
->next_af_subtype
= P2P_PAF_SUBTYPE_INVALID
;
7326 switch (act_frm
->subtype
) {
7327 case P2P_PAF_GON_REQ
: {
7328 WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
7329 wl_set_p2p_status(cfg
, GO_NEG_PHASE
);
7331 config_af_params
->search_channel
= true;
7332 cfg
->next_af_subtype
= act_frm
->subtype
+ 1;
7334 /* increase dwell time to wait for RESP frame */
7335 af_params
->dwell_time
= WL_MED_DWELL_TIME
;
7339 case P2P_PAF_GON_RSP
: {
7340 cfg
->next_af_subtype
= act_frm
->subtype
+ 1;
7341 /* increase dwell time to wait for CONF frame */
7342 af_params
->dwell_time
= WL_MED_DWELL_TIME
+ 100;
7345 case P2P_PAF_GON_CONF
: {
7346 /* If we reached till GO Neg confirmation reset the filter */
7347 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
7348 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
7350 /* minimize dwell time */
7351 af_params
->dwell_time
= WL_MIN_DWELL_TIME
;
7353 #ifdef WL_CFG80211_SYNC_GON
7354 config_af_params
->extra_listen
= false;
7355 #endif /* WL_CFG80211_SYNC_GON */
7358 case P2P_PAF_INVITE_REQ
: {
7359 config_af_params
->search_channel
= true;
7360 cfg
->next_af_subtype
= act_frm
->subtype
+ 1;
7362 /* increase dwell time */
7363 af_params
->dwell_time
= WL_MED_DWELL_TIME
;
7366 case P2P_PAF_INVITE_RSP
:
7367 /* minimize dwell time */
7368 af_params
->dwell_time
= WL_MIN_DWELL_TIME
;
7369 #ifdef WL_CFG80211_SYNC_GON
7370 config_af_params
->extra_listen
= false;
7371 #endif /* WL_CFG80211_SYNC_GON */
7373 case P2P_PAF_DEVDIS_REQ
: {
7374 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm
->elts
[0],
7375 action_frame
->len
)) {
7376 config_af_params
->search_channel
= true;
7379 cfg
->next_af_subtype
= act_frm
->subtype
+ 1;
7380 /* maximize dwell time to wait for RESP frame */
7381 af_params
->dwell_time
= WL_LONG_DWELL_TIME
;
7384 case P2P_PAF_DEVDIS_RSP
:
7385 /* minimize dwell time */
7386 af_params
->dwell_time
= WL_MIN_DWELL_TIME
;
7387 #ifdef WL_CFG80211_SYNC_GON
7388 config_af_params
->extra_listen
= false;
7389 #endif /* WL_CFG80211_SYNC_GON */
7391 case P2P_PAF_PROVDIS_REQ
: {
7392 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm
->elts
[0],
7393 action_frame
->len
)) {
7394 config_af_params
->search_channel
= true;
7397 cfg
->next_af_subtype
= act_frm
->subtype
+ 1;
7398 /* increase dwell time to wait for RESP frame */
7399 af_params
->dwell_time
= WL_MED_DWELL_TIME
;
7402 case P2P_PAF_PROVDIS_RSP
: {
7403 cfg
->next_af_subtype
= P2P_PAF_GON_REQ
;
7404 af_params
->dwell_time
= WL_MED_DWELL_TIME
;
7405 #ifdef WL_CFG80211_SYNC_GON
7406 config_af_params
->extra_listen
= false;
7407 #endif /* WL_CFG80211_SYNC_GON */
7411 WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
7420 wl_cfg80211_check_DFS_channel(struct bcm_cfg80211
*cfg
, wl_af_params_t
*af_params
,
7421 void *frame
, u16 frame_len
)
7423 struct wl_scan_results
*bss_list
;
7424 struct wl_bss_info
*bi
= NULL
;
7425 bool result
= false;
7427 chanspec_t chanspec
;
7429 /* If DFS channel is 52~148, check to block it or not */
7431 (af_params
->channel
>= 52 && af_params
->channel
<= 148)) {
7432 if (!wl_cfgp2p_is_p2p_action(frame
, frame_len
)) {
7433 bss_list
= cfg
->bss_list
;
7434 bi
= next_bss(bss_list
, bi
);
7435 for_each_bss(bss_list
, bi
, i
) {
7436 chanspec
= wl_chspec_driver_to_host(bi
->chanspec
);
7437 if (CHSPEC_IS5G(chanspec
) &&
7438 ((bi
->ctl_ch
? bi
->ctl_ch
: CHSPEC_CHANNEL(chanspec
))
7439 == af_params
->channel
)) {
7440 result
= true; /* do not block the action frame */
7450 WL_DBG(("result=%s", result
?"true":"false"));
7455 wl_cfg80211_check_dwell_overflow(int32 requested_dwell
, ulong dwell_jiffies
)
7457 if ((requested_dwell
& CUSTOM_RETRY_MASK
) &&
7458 (jiffies_to_msecs(jiffies
- dwell_jiffies
) >
7459 (requested_dwell
& ~CUSTOM_RETRY_MASK
))) {
7460 WL_ERR(("Action frame TX retry time over dwell time!\n"));
7467 wl_cfg80211_send_action_frame(struct wiphy
*wiphy
, struct net_device
*dev
,
7468 bcm_struct_cfgdev
*cfgdev
, wl_af_params_t
*af_params
,
7469 wl_action_frame_t
*action_frame
, u16 action_frame_len
, s32 bssidx
)
7472 struct net_device
*ndev
= NULL
;
7474 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7476 u8 category
, action
;
7478 struct p2p_config_af_params config_af_params
;
7479 struct net_info
*netinfo
;
7481 ulong off_chan_started_jiffies
= 0;
7483 ulong dwell_jiffies
= 0;
7484 bool dwell_overflow
= false;
7485 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
7486 bool miss_gon_cfm
= false;
7488 int32 requested_dwell
= af_params
->dwell_time
;
7490 /* Add the default dwell time
7491 * Dwell time to stay off-channel to wait for a response action frame
7492 * after transmitting an GO Negotiation action frame
7494 af_params
->dwell_time
= WL_DWELL_TIME
;
7497 #if defined(WL_CFG80211_P2P_DEV_IF)
7500 ndev
= ndev_to_cfgdev(cfgdev
);
7501 #endif /* WL_CFG80211_P2P_DEV_IF */
7504 category
= action_frame
->data
[DOT11_ACTION_CAT_OFF
];
7505 action
= action_frame
->data
[DOT11_ACTION_ACT_OFF
];
7507 /* initialize variables */
7509 cfg
->next_af_subtype
= P2P_PAF_SUBTYPE_INVALID
;
7510 config_af_params
.max_tx_retry
= WL_AF_TX_MAX_RETRY
;
7511 config_af_params
.search_channel
= false;
7512 #ifdef WL_CFG80211_SYNC_GON
7513 config_af_params
.extra_listen
= false;
7516 /* config parameters */
7517 /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
7518 if (category
== DOT11_ACTION_CAT_PUBLIC
) {
7519 if ((action
== P2P_PUB_AF_ACTION
) &&
7520 (action_frame_len
>= sizeof(wifi_p2p_pub_act_frame_t
))) {
7521 /* p2p public action frame process */
7522 if (BCME_OK
!= wl_cfg80211_config_p2p_pub_af_tx(wiphy
,
7523 action_frame
, af_params
, &config_af_params
)) {
7524 WL_DBG(("Unknown subtype.\n"));
7527 } else if (action_frame_len
>= sizeof(wifi_p2psd_gas_pub_act_frame_t
)) {
7528 /* service discovery process */
7529 if (action
== P2PSD_ACTION_ID_GAS_IREQ
||
7530 action
== P2PSD_ACTION_ID_GAS_CREQ
) {
7531 /* configure service discovery query frame */
7533 config_af_params
.search_channel
= true;
7535 /* save next af suptype to cancel remained dwell time */
7536 cfg
->next_af_subtype
= action
+ 1;
7538 af_params
->dwell_time
= WL_MED_DWELL_TIME
;
7539 if (requested_dwell
& CUSTOM_RETRY_MASK
) {
7540 config_af_params
.max_tx_retry
=
7541 (requested_dwell
& CUSTOM_RETRY_MASK
) >> 24;
7542 af_params
->dwell_time
=
7543 (requested_dwell
& ~CUSTOM_RETRY_MASK
);
7544 WL_DBG(("Custom retry(%d) and dwell time(%d) is set.\n",
7545 config_af_params
.max_tx_retry
,
7546 af_params
->dwell_time
));
7548 } else if (action
== P2PSD_ACTION_ID_GAS_IRESP
||
7549 action
== P2PSD_ACTION_ID_GAS_CRESP
) {
7550 /* configure service discovery response frame */
7551 af_params
->dwell_time
= WL_MIN_DWELL_TIME
;
7553 WL_DBG(("Unknown action type: %d\n", action
));
7556 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
7557 category
, action
, action_frame_len
));
7559 } else if (category
== P2P_AF_CATEGORY
) {
7560 /* do not configure anything. it will be sent with a default configuration */
7562 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
7564 if (dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
) {
7565 wl_clr_drv_status(cfg
, SENDING_ACT_FRM
, dev
);
7569 netinfo
= wl_get_netinfo_by_bssidx(cfg
, bssidx
);
7570 /* validate channel and p2p ies */
7571 if (config_af_params
.search_channel
&& IS_P2P_SOCIAL(af_params
->channel
) &&
7572 netinfo
&& netinfo
->bss
.ies
.probe_req_ie_len
) {
7573 config_af_params
.search_channel
= true;
7575 config_af_params
.search_channel
= false;
7578 if (ndev
== bcmcfg_to_prmry_ndev(cfg
))
7579 config_af_params
.search_channel
= false;
7583 /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
7584 if (wl_get_drv_status(cfg
, CONNECTING
, bcmcfg_to_prmry_ndev(cfg
))) {
7589 /* if scan is ongoing, abort current scan. */
7590 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
7591 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, true, true);
7594 /* Abort P2P listen */
7595 if (discover_cfgdev(cfgdev
, cfg
)) {
7596 if (cfg
->p2p_supported
&& cfg
->p2p
) {
7597 wl_cfgp2p_set_p2p_mode(cfg
, WL_P2P_DISC_ST_SCAN
, 0, 0,
7598 wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
));
7603 /* handling DFS channel exceptions */
7604 if (!wl_cfg80211_check_DFS_channel(cfg
, af_params
, action_frame
->data
, action_frame
->len
)) {
7605 return false; /* the action frame was blocked */
7609 /* set status and destination address before sending af */
7610 if (cfg
->next_af_subtype
!= P2P_PAF_SUBTYPE_INVALID
) {
7611 /* set this status to cancel the remained dwell time in rx process */
7612 wl_set_drv_status(cfg
, WAITING_NEXT_ACT_FRM
, dev
);
7614 wl_set_drv_status(cfg
, SENDING_ACT_FRM
, dev
);
7615 memcpy(cfg
->afx_hdl
->tx_dst_addr
.octet
,
7616 af_params
->action_frame
.da
.octet
,
7617 sizeof(cfg
->afx_hdl
->tx_dst_addr
.octet
));
7619 /* save af_params for rx process */
7620 cfg
->afx_hdl
->pending_tx_act_frm
= af_params
;
7622 if (wl_cfgp2p_is_p2p_gas_action(action_frame
->data
, action_frame
->len
)) {
7623 WL_DBG(("Set GAS action frame config.\n"));
7624 config_af_params
.search_channel
= false;
7625 config_af_params
.max_tx_retry
= 1;
7628 /* search peer's channel */
7629 if (config_af_params
.search_channel
) {
7630 /* initialize afx_hdl */
7631 if ((cfg
->afx_hdl
->bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
7632 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
7635 cfg
->afx_hdl
->dev
= dev
;
7636 cfg
->afx_hdl
->retry
= 0;
7637 cfg
->afx_hdl
->peer_chan
= WL_INVALID
;
7639 if (wl_cfg80211_af_searching_channel(cfg
, dev
) == WL_INVALID
) {
7640 WL_ERR(("couldn't find peer's channel.\n"));
7641 wl_cfgp2p_print_actframe(true, action_frame
->data
, action_frame
->len
,
7642 af_params
->channel
);
7643 /* Even if we couldn't find peer channel, try to send the frame
7644 * out. P2P cert 5.1.14 testbed device (realtek) doesn't seem to
7645 * respond to probe request (Ideally it has to be in listen and
7646 * responsd to probe request). However if we send Go neg req, the
7647 * peer is sending GO-neg resp. So instead of giving up here, just
7648 * proceed and attempt sending out the action frame.
7652 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
7654 * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
7655 * but after the check of piggyback algorithm.
7656 * To take care of current piggback algo, lets abort the scan here itself.
7658 wl_notify_escan_complete(cfg
, dev
, true, true);
7659 /* Suspend P2P discovery's search-listen to prevent it from
7660 * starting a scan or changing the channel.
7662 if ((wl_cfgp2p_discover_enable_search(cfg
, false)) < 0) {
7663 WL_ERR(("Can not disable discovery mode\n"));
7667 /* update channel */
7668 if (cfg
->afx_hdl
->peer_chan
!= WL_INVALID
) {
7669 af_params
->channel
= cfg
->afx_hdl
->peer_chan
;
7670 WL_ERR(("Attempt tx on peer listen channel:%d ",
7671 cfg
->afx_hdl
->peer_chan
));
7673 WL_ERR(("Attempt tx with the channel provided by userspace."
7674 "Channel: %d\n", af_params
->channel
));
7679 off_chan_started_jiffies
= jiffies
;
7682 wl_cfgp2p_print_actframe(true, action_frame
->data
, action_frame
->len
, af_params
->channel
);
7684 wl_cfgp2p_need_wait_actfrmae(cfg
, action_frame
->data
, action_frame
->len
, true);
7686 dwell_jiffies
= jiffies
;
7687 /* Now send a tx action frame */
7688 ack
= wl_cfgp2p_tx_action_frame(cfg
, dev
, af_params
, bssidx
) ? false : true;
7689 dwell_overflow
= wl_cfg80211_check_dwell_overflow(requested_dwell
, dwell_jiffies
);
7691 if (ack
&& (wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM
))) {
7692 wifi_p2p_pub_act_frame_t
*pact_frm
;
7693 pact_frm
= (wifi_p2p_pub_act_frame_t
*)(action_frame
->data
);
7694 if (pact_frm
->subtype
== P2P_PAF_GON_RSP
) {
7695 WL_ERR(("Miss GO Nego cfm after P2P_PAF_GON_RSP\n"));
7696 miss_gon_cfm
= true;
7700 /* if failed, retry it. tx_retry_max value is configure by .... */
7701 while ((miss_gon_cfm
|| (ack
== false)) && (tx_retry
++ < config_af_params
.max_tx_retry
) &&
7704 if (af_params
->channel
) {
7705 if (jiffies_to_msecs(jiffies
- off_chan_started_jiffies
) >
7706 OFF_CHAN_TIME_THRESHOLD_MS
) {
7707 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg
);
7708 off_chan_started_jiffies
= jiffies
;
7710 OSL_SLEEP(AF_RETRY_DELAY_TIME
);
7713 ack
= wl_cfgp2p_tx_action_frame(cfg
, dev
, af_params
, bssidx
) ?
7715 if (miss_gon_cfm
&& !wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM
)) {
7716 WL_ERR(("Received GO Nego cfm after P2P_PAF_GON_RSP\n"));
7717 miss_gon_cfm
= false;
7719 dwell_overflow
= wl_cfg80211_check_dwell_overflow(requested_dwell
, dwell_jiffies
);
7723 WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry
));
7725 WL_DBG(("Complete to send action frame\n"));
7727 /* Clear SENDING_ACT_FRM after all sending af is done */
7728 wl_clr_drv_status(cfg
, SENDING_ACT_FRM
, dev
);
7730 #ifdef WL_CFG80211_SYNC_GON
7731 /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
7732 * if we coundn't get the next action response frame and dongle does not keep
7733 * the dwell time, go to listen state again to get next action response frame.
7735 if (ack
&& config_af_params
.extra_listen
&&
7736 wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM
) &&
7737 cfg
->af_sent_channel
== cfg
->afx_hdl
->my_listen_chan
) {
7738 s32 extar_listen_time
;
7740 extar_listen_time
= af_params
->dwell_time
-
7741 jiffies_to_msecs(jiffies
- cfg
->af_tx_sent_jiffies
);
7743 if (extar_listen_time
> 50) {
7744 wl_set_drv_status(cfg
, WAITING_NEXT_ACT_FRM_LISTEN
, dev
);
7745 WL_DBG(("Wait more time! actual af time:%d,"
7746 "calculated extar listen:%d\n",
7747 af_params
->dwell_time
, extar_listen_time
));
7748 if (wl_cfgp2p_discover_listen(cfg
, cfg
->af_sent_channel
,
7749 extar_listen_time
+ 100) == BCME_OK
) {
7750 wait_for_completion_timeout(&cfg
->wait_next_af
,
7751 msecs_to_jiffies(extar_listen_time
+ 100 + 300));
7753 wl_clr_drv_status(cfg
, WAITING_NEXT_ACT_FRM_LISTEN
, dev
);
7756 #endif /* WL_CFG80211_SYNC_GON */
7757 wl_clr_drv_status(cfg
, WAITING_NEXT_ACT_FRM
, dev
);
7758 cfg
->afx_hdl
->pending_tx_act_frm
= NULL
;
7760 WL_INFORM(("-- sending Action Frame is %s, listen chan: %d\n",
7761 (ack
) ? "Succeeded!!":"Failed!!", cfg
->afx_hdl
->my_listen_chan
));
7766 #define MAX_NUM_OF_ASSOCIATED_DEV 64
7768 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7769 wl_cfg80211_mgmt_tx(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
,
7770 struct cfg80211_mgmt_tx_params
*params
, u64
*cookie
)
7772 wl_cfg80211_mgmt_tx(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
,
7773 struct ieee80211_channel
*channel
, bool offchan
,
7774 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0))
7775 enum nl80211_channel_type channel_type
,
7776 bool channel_type_valid
,
7777 #endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0) */
7778 unsigned int wait
, const u8
* buf
, size_t len
,
7779 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
7782 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
7783 bool dont_wait_for_ack
,
7786 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
7788 wl_action_frame_t
*action_frame
;
7789 wl_af_params_t
*af_params
;
7791 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7792 struct ieee80211_channel
*channel
= params
->chan
;
7793 const u8
*buf
= params
->buf
;
7794 size_t len
= params
->len
;
7796 const struct ieee80211_mgmt
*mgmt
;
7797 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7798 struct net_device
*dev
= NULL
;
7803 s8 eabuf
[ETHER_ADDR_STR_LEN
];
7805 WL_DBG(("Enter \n"));
7807 if (len
> ACTION_FRAME_SIZE
) {
7808 WL_ERR(("bad length:%zu\n", len
));
7812 PRINT_WDEV_INFO(cfgdev
);
7813 #endif /* DHD_IFDEBUG */
7815 dev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
7818 WL_ERR(("dev is NULL\n"));
7822 /* set bsscfg idx for iovar (wlan0: P2PAPI_BSSCFG_PRIMARY, p2p: P2PAPI_BSSCFG_DEVICE) */
7823 if (discover_cfgdev(cfgdev
, cfg
)) {
7824 if (!cfg
->p2p_supported
|| !cfg
->p2p
) {
7825 WL_ERR(("P2P doesn't setup completed yet\n"));
7828 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
7831 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, cfgdev_to_wdev(cfgdev
))) < 0) {
7832 WL_ERR(("Find p2p index failed\n"));
7837 WL_DBG(("TX target bssidx=%d\n", bssidx
));
7839 if (p2p_is_on(cfg
)) {
7840 /* Suspend P2P discovery search-listen to prevent it from changing the
7843 if ((err
= wl_cfgp2p_discover_enable_search(cfg
, false)) < 0) {
7844 WL_ERR(("Can not disable discovery mode\n"));
7849 id
= cfg
->send_action_id
++;
7851 id
= cfg
->send_action_id
++;
7853 mgmt
= (const struct ieee80211_mgmt
*)buf
;
7854 if (ieee80211_is_mgmt(mgmt
->frame_control
)) {
7855 if (ieee80211_is_probe_resp(mgmt
->frame_control
)) {
7856 s32 ie_offset
= DOT11_MGMT_HDR_LEN
+ DOT11_BCN_PRB_FIXED_LEN
;
7857 s32 ie_len
= len
- ie_offset
;
7858 if ((dev
== bcmcfg_to_prmry_ndev(cfg
)) && cfg
->p2p
) {
7859 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
7861 wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
7862 VNDR_IE_PRBRSP_FLAG
, (const u8
*)(buf
+ ie_offset
), ie_len
);
7863 cfg80211_mgmt_tx_status(cfgdev
, *cookie
, buf
, len
, true, GFP_KERNEL
);
7864 #if defined(P2P_IE_MISSING_FIX)
7865 if (!cfg
->p2p_prb_noti
) {
7866 cfg
->p2p_prb_noti
= true;
7867 WL_DBG(("%s: TX 802_1X Probe Response first time.\n",
7872 } else if (ieee80211_is_disassoc(mgmt
->frame_control
) ||
7873 ieee80211_is_deauth(mgmt
->frame_control
)) {
7874 char mac_buf
[MAX_NUM_OF_ASSOCIATED_DEV
*
7875 sizeof(struct ether_addr
) + sizeof(uint
)] = {0};
7876 int num_associated
= 0;
7877 struct maclist
*assoc_maclist
= (struct maclist
*)mac_buf
;
7878 if (!bcmp((const uint8
*)BSSID_BROADCAST
,
7879 (const struct ether_addr
*)mgmt
->da
, ETHER_ADDR_LEN
)) {
7880 assoc_maclist
->count
= MAX_NUM_OF_ASSOCIATED_DEV
;
7881 err
= wldev_ioctl_get(dev
, WLC_GET_ASSOCLIST
,
7882 assoc_maclist
, sizeof(mac_buf
));
7884 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err
));
7886 num_associated
= assoc_maclist
->count
;
7888 memcpy(scb_val
.ea
.octet
, mgmt
->da
, ETH_ALEN
);
7889 scb_val
.val
= mgmt
->u
.disassoc
.reason_code
;
7890 err
= wldev_ioctl_set(dev
, WLC_SCB_DEAUTHENTICATE_FOR_REASON
, &scb_val
,
7893 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err
));
7894 WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
7895 bcm_ether_ntoa((const struct ether_addr
*)mgmt
->da
, eabuf
),
7898 if (num_associated
> 0 && ETHER_ISBCAST(mgmt
->da
))
7901 cfg80211_mgmt_tx_status(cfgdev
, *cookie
, buf
, len
, true, GFP_KERNEL
);
7904 } else if (ieee80211_is_action(mgmt
->frame_control
)) {
7905 /* Abort the dwell time of any previous off-channel
7906 * action frame that may be still in effect. Sending
7907 * off-channel action frames relies on the driver's
7908 * scan engine. If a previous off-channel action frame
7909 * tx is still in progress (including the dwell time),
7910 * then this new action frame will not be sent out.
7912 /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
7913 * And previous off-channel action frame must be ended before new af tx.
7915 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7916 wl_notify_escan_complete(cfg
, dev
, true, true);
7917 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7921 WL_ERR(("Driver only allows MGMT packet type\n"));
7925 af_params
= (wl_af_params_t
*) kzalloc(WL_WIFI_AF_PARAMS_SIZE
, GFP_KERNEL
);
7927 if (af_params
== NULL
)
7929 WL_ERR(("unable to allocate frame\n"));
7933 action_frame
= &af_params
->action_frame
;
7935 /* Add the packet Id */
7936 action_frame
->packetId
= *cookie
;
7937 WL_DBG(("action frame %d\n", action_frame
->packetId
));
7939 memcpy(&action_frame
->da
, &mgmt
->da
[0], ETHER_ADDR_LEN
);
7940 memcpy(&af_params
->BSSID
, &mgmt
->bssid
[0], ETHER_ADDR_LEN
);
7942 /* Add the length exepted for 802.11 header */
7943 action_frame
->len
= len
- DOT11_MGMT_HDR_LEN
;
7944 WL_DBG(("action_frame->len: %d\n", action_frame
->len
));
7946 /* Add the channel */
7947 af_params
->channel
=
7948 ieee80211_frequency_to_channel(channel
->center_freq
);
7949 /* Save listen_chan for searching common channel */
7950 cfg
->afx_hdl
->peer_listen_chan
= af_params
->channel
;
7951 WL_DBG(("channel from upper layer %d\n", cfg
->afx_hdl
->peer_listen_chan
));
7953 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7954 af_params
->dwell_time
= params
->wait
;
7956 af_params
->dwell_time
= wait
;
7959 memcpy(action_frame
->data
, &buf
[DOT11_MGMT_HDR_LEN
], action_frame
->len
);
7961 ack
= wl_cfg80211_send_action_frame(wiphy
, dev
, cfgdev
, af_params
,
7962 action_frame
, action_frame
->len
, bssidx
);
7963 cfg80211_mgmt_tx_status(cfgdev
, *cookie
, buf
, len
, ack
, GFP_KERNEL
);
7972 wl_cfg80211_mgmt_frame_register(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
,
7973 u16 frame
, bool reg
)
7976 WL_DBG(("frame_type: %x, reg: %d\n", frame
, reg
));
7978 if (frame
!= (IEEE80211_FTYPE_MGMT
| IEEE80211_STYPE_PROBE_REQ
))
7986 wl_cfg80211_change_bss(struct wiphy
*wiphy
,
7987 struct net_device
*dev
,
7988 struct bss_parameters
*params
)
7992 #ifdef PCIE_FULL_DONGLE
7993 s32 ifidx
= DHD_BAD_IF
;
7995 #if defined(PCIE_FULL_DONGLE)
7997 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7998 dhd
= (dhd_pub_t
*)(cfg
->pub
);
7999 #if defined(WL_ENABLE_P2P_IF)
8000 if (cfg
->p2p_net
== dev
)
8001 dev
= bcmcfg_to_prmry_ndev(cfg
);
8005 if (params
->use_cts_prot
>= 0) {
8008 if (params
->use_short_preamble
>= 0) {
8011 if (params
->use_short_slot_time
>= 0) {
8014 if (params
->basic_rates
) {
8017 if (params
->ap_isolate
>= 0) {
8018 ap_isolate
= params
->ap_isolate
;
8019 #ifdef PCIE_FULL_DONGLE
8020 ifidx
= dhd_net2idx(dhd
->info
, dev
);
8022 if (ifidx
!= DHD_BAD_IF
) {
8023 err
= dhd_set_ap_isolate(dhd
, ifidx
, ap_isolate
);
8025 WL_ERR(("Failed to set ap_isolate\n"));
8028 err
= wldev_iovar_setint(dev
, "ap_isolate", ap_isolate
);
8031 WL_ERR(("set ap_isolate Error (%d)\n", err
));
8033 #endif /* PCIE_FULL_DONGLE */
8036 if (params
->ht_opmode
>= 0) {
8044 wl_cfg80211_set_channel(struct wiphy
*wiphy
, struct net_device
*dev
,
8045 struct ieee80211_channel
*chan
,
8046 enum nl80211_channel_type channel_type
)
8049 chanspec_t chspec
= 0;
8050 chanspec_t fw_chspec
= 0;
8051 u32 bw
= WL_CHANSPEC_BW_20
;
8053 u32 ulb_bw
= wl_cfg80211_get_ulb_bw(wl_get_cfg(dev
), dev
->ieee80211_ptr
);
8054 #endif /* WL11ULB */
8062 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
8063 #if defined(CUSTOM_SET_CPUCORE) || (defined(WL_VIRTUAL_APSTA) && \
8064 defined(APSTA_RESTRICTED_CHANNEL))
8065 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
8066 #endif /* CUSTOM_SET_CPUCORE || (WL_VIRTUAL_APSTA && APSTA_RESTRICTED_CHANNEL) */
8068 dev
= ndev_to_wlc_ndev(dev
, cfg
);
8069 _chan
= ieee80211_frequency_to_channel(chan
->center_freq
);
8070 #ifdef WL_EXT_IAPSTA
8071 _chan
= wl_ext_iapsta_update_channel(dev
, _chan
);
8073 printf("%s: netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
8074 __FUNCTION__
, dev
->ifindex
, channel_type
, _chan
);
8077 #if defined(WL_VIRTUAL_APSTA) && defined(APSTA_RESTRICTED_CHANNEL)
8078 #define DEFAULT_2G_SOFTAP_CHANNEL 1
8079 #define DEFAULT_5G_SOFTAP_CHANNEL 149
8080 if (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
&&
8081 (dhd
->op_mode
& DHD_FLAG_CONCURR_STA_HOSTAP_MODE
) ==
8082 DHD_FLAG_CONCURR_STA_HOSTAP_MODE
&&
8083 wl_get_drv_status(cfg
, CONNECTED
, bcmcfg_to_prmry_ndev(cfg
))) {
8084 u32
*sta_chan
= (u32
*)wl_read_prof(cfg
,
8085 bcmcfg_to_prmry_ndev(cfg
), WL_PROF_CHAN
);
8086 u32 sta_band
= (*sta_chan
> CH_MAX_2G_CHANNEL
) ?
8087 IEEE80211_BAND_5GHZ
: IEEE80211_BAND_2GHZ
;
8088 if (chan
->band
== sta_band
) {
8089 /* Do not try SCC in 5GHz if channel is not CH149 */
8090 _chan
= (sta_band
== IEEE80211_BAND_5GHZ
&&
8091 *sta_chan
!= DEFAULT_5G_SOFTAP_CHANNEL
) ?
8092 DEFAULT_2G_SOFTAP_CHANNEL
: *sta_chan
;
8093 WL_ERR(("target channel will be changed to %d\n", _chan
));
8094 if (_chan
<= CH_MAX_2G_CHANNEL
) {
8095 bw
= WL_CHANSPEC_BW_20
;
8100 #undef DEFAULT_2G_SOFTAP_CHANNEL
8101 #undef DEFAULT_5G_SOFTAP_CHANNEL
8102 #endif /* WL_VIRTUAL_APSTA && APSTA_RESTRICTED_CHANNEL */
8106 WL_DBG(("[ULB] setting AP/GO BW to ulb_bw 0x%x \n", ulb_bw
));
8107 bw
= wl_cfg80211_ulbbw_to_ulbchspec(ulb_bw
);
8110 #endif /* WL11ULB */
8111 if (chan
->band
== IEEE80211_BAND_5GHZ
) {
8112 param
.band
= WLC_BAND_5G
;
8113 err
= wldev_iovar_getbuf(dev
, "bw_cap", ¶m
, sizeof(param
),
8114 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
);
8116 if (err
!= BCME_UNSUPPORTED
) {
8117 WL_ERR(("bw_cap failed, %d\n", err
));
8120 err
= wldev_iovar_getint(dev
, "mimo_bw_cap", &bw_cap
);
8122 WL_ERR(("error get mimo_bw_cap (%d)\n", err
));
8124 if (bw_cap
!= WLC_N_BW_20ALL
)
8125 bw
= WL_CHANSPEC_BW_40
;
8128 if (WL_BW_CAP_80MHZ(cfg
->ioctl_buf
[0]))
8129 bw
= WL_CHANSPEC_BW_80
;
8130 else if (WL_BW_CAP_40MHZ(cfg
->ioctl_buf
[0]))
8131 bw
= WL_CHANSPEC_BW_40
;
8133 bw
= WL_CHANSPEC_BW_20
;
8137 } else if (chan
->band
== IEEE80211_BAND_2GHZ
)
8138 bw
= WL_CHANSPEC_BW_20
;
8140 chspec
= wf_channel2chspec(_chan
, bw
);
8141 if (wf_chspec_valid(chspec
)) {
8142 fw_chspec
= wl_chspec_host_to_driver(chspec
);
8143 if (fw_chspec
!= INVCHANSPEC
) {
8144 if ((err
= wldev_iovar_setint(dev
, "chanspec",
8145 fw_chspec
)) == BCME_BADCHAN
) {
8146 if (bw
== WL_CHANSPEC_BW_80
)
8148 err
= wldev_ioctl_set(dev
, WLC_SET_CHANNEL
,
8149 &_chan
, sizeof(_chan
));
8151 WL_ERR(("WLC_SET_CHANNEL error %d"
8152 "chip may not be supporting this channel\n", err
));
8155 WL_ERR(("failed to set chanspec error %d\n", err
));
8158 WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
8163 if (bw
== WL_CHANSPEC_BW_80
)
8164 bw
= WL_CHANSPEC_BW_40
;
8165 else if (bw
== WL_CHANSPEC_BW_40
)
8166 bw
= WL_CHANSPEC_BW_20
;
8171 WL_ERR(("Invalid chanspec 0x%x\n", chspec
));
8174 #ifdef CUSTOM_SET_CPUCORE
8175 if (dhd
->op_mode
== DHD_FLAG_HOSTAP_MODE
) {
8176 WL_DBG(("SoftAP mode do not need to set cpucore\n"));
8177 } else if (chspec
& WL_CHANSPEC_BW_80
) {
8178 /* SoftAp only mode do not need to set cpucore */
8179 if ((dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) &&
8180 dev
!= bcmcfg_to_prmry_ndev(cfg
)) {
8181 /* Soft AP on virtual Iface (AP+STA case) */
8182 dhd
->chan_isvht80
|= DHD_FLAG_HOSTAP_MODE
;
8183 dhd_set_cpucore(dhd
, TRUE
);
8184 } else if (is_p2p_group_iface(dev
->ieee80211_ptr
)) {
8185 /* If P2P IF is vht80 */
8186 dhd
->chan_isvht80
|= DHD_FLAG_P2P_MODE
;
8187 dhd_set_cpucore(dhd
, TRUE
);
8190 #endif /* CUSTOM_SET_CPUCORE */
8191 if (!err
&& (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
)) {
8192 /* Update AP/GO operating channel */
8193 cfg
->ap_oper_channel
= ieee80211_frequency_to_channel(chan
->center_freq
);
8198 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
8200 wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211
*cfg
)
8202 struct net_info
*_net_info
, *next
;
8203 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
8204 #pragma GCC diagnostic push
8205 #pragma GCC diagnostic ignored "-Wcast-qual"
8207 list_for_each_entry_safe(_net_info
, next
, &cfg
->net_list
, list
) {
8208 if (_net_info
->ndev
&&
8209 test_bit(WL_STATUS_REMAINING_ON_CHANNEL
, &_net_info
->sme_state
))
8210 return _net_info
->ndev
;
8212 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
8213 #pragma GCC diagnostic pop
8217 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
8220 wl_validate_opensecurity(struct net_device
*dev
, s32 bssidx
, bool privacy
)
8227 err
= wldev_iovar_setint_bsscfg(dev
, "auth", 0, bssidx
);
8229 WL_ERR(("auth error %d\n", err
));
8234 /* If privacy bit is set in open mode, then WEP would be enabled */
8236 WL_DBG(("Setting wsec to %d for WEP \n", wsec
));
8240 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", wsec
, bssidx
);
8242 WL_ERR(("wsec error %d\n", err
));
8246 /* set upper-layer auth */
8247 if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_ADHOC
)
8248 wpa_val
= WPA_AUTH_NONE
;
8250 wpa_val
= WPA_AUTH_DISABLED
;
8251 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", wpa_val
, bssidx
);
8253 WL_ERR(("wpa_auth error %d\n", err
));
8261 wl_validate_wpa2ie(struct net_device
*dev
, bcm_tlv_t
*wpa2ie
, s32 bssidx
)
8265 u16 auth
= 0; /* d11 open authentication */
8270 wpa_suite_mcast_t
*mcast
;
8271 wpa_suite_ucast_t
*ucast
;
8272 wpa_suite_auth_key_mgmt_t
*mgmt
;
8273 wpa_pmkid_list_t
*pmkid
;
8277 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
8282 u32 wme_bss_disable
;
8287 WL_DBG(("Enter \n"));
8288 len
= wpa2ie
->len
- WPA2_VERSION_LEN
;
8289 /* check the mcast cipher */
8290 mcast
= (wpa_suite_mcast_t
*)&wpa2ie
->data
[WPA2_VERSION_LEN
];
8291 switch (mcast
->type
) {
8292 case WPA_CIPHER_NONE
:
8295 case WPA_CIPHER_WEP_40
:
8296 case WPA_CIPHER_WEP_104
:
8299 case WPA_CIPHER_TKIP
:
8300 gval
= TKIP_ENABLED
;
8302 case WPA_CIPHER_AES_CCM
:
8306 WL_ERR(("No Security Info\n"));
8309 if ((len
-= WPA_SUITE_LEN
) <= 0)
8312 /* check the unicast cipher */
8313 ucast
= (wpa_suite_ucast_t
*)&mcast
[1];
8314 suite_count
= ltoh16_ua(&ucast
->count
);
8315 switch (ucast
->list
[0].type
) {
8316 case WPA_CIPHER_NONE
:
8319 case WPA_CIPHER_WEP_40
:
8320 case WPA_CIPHER_WEP_104
:
8323 case WPA_CIPHER_TKIP
:
8324 pval
= TKIP_ENABLED
;
8326 case WPA_CIPHER_AES_CCM
:
8330 WL_ERR(("No Security Info\n"));
8332 if ((len
-= (WPA_IE_SUITE_COUNT_LEN
+ (WPA_SUITE_LEN
* suite_count
))) <= 0)
8335 /* FOR WPS , set SEC_OW_ENABLED */
8336 wsec
= (pval
| gval
| SES_OW_ENABLED
);
8338 mgmt
= (wpa_suite_auth_key_mgmt_t
*)&ucast
->list
[suite_count
];
8339 suite_count
= cnt
= ltoh16_ua(&mgmt
->count
);
8341 switch (mgmt
->list
[cnt
].type
) {
8343 wpa_auth
|= WPA_AUTH_NONE
;
8345 case RSN_AKM_UNSPECIFIED
:
8346 wpa_auth
|= WPA2_AUTH_UNSPECIFIED
;
8349 wpa_auth
|= WPA2_AUTH_PSK
;
8352 case RSN_AKM_MFP_PSK
:
8353 wpa_auth
|= WPA2_AUTH_PSK_SHA256
;
8355 case RSN_AKM_MFP_1X
:
8356 wpa_auth
|= WPA2_AUTH_1X_SHA256
;
8360 WL_ERR(("No Key Mgmt Info\n"));
8364 if ((len
-= (WPA_IE_SUITE_COUNT_LEN
+ (WPA_SUITE_LEN
* suite_count
))) >= RSN_CAP_LEN
) {
8365 rsn_cap
[0] = *(u8
*)&mgmt
->list
[suite_count
];
8366 rsn_cap
[1] = *((u8
*)&mgmt
->list
[suite_count
] + 1);
8368 if (rsn_cap
[0] & (RSN_CAP_16_REPLAY_CNTRS
<< RSN_CAP_PTK_REPLAY_CNTR_SHIFT
)) {
8369 wme_bss_disable
= 0;
8371 wme_bss_disable
= 1;
8375 if (rsn_cap
[0] & RSN_CAP_MFPR
) {
8376 WL_DBG(("MFP Required \n"));
8377 mfp
= WL_MFP_REQUIRED
;
8378 /* Our firmware has requirement that WPA2_AUTH_PSK/WPA2_AUTH_UNSPECIFIED
8379 * be set, if SHA256 OUI is to be included in the rsn ie.
8381 if (wpa_auth
& WPA2_AUTH_PSK_SHA256
) {
8382 wpa_auth
|= WPA2_AUTH_PSK
;
8383 } else if (wpa_auth
& WPA2_AUTH_1X_SHA256
) {
8384 wpa_auth
|= WPA2_AUTH_UNSPECIFIED
;
8386 } else if (rsn_cap
[0] & RSN_CAP_MFPC
) {
8387 WL_DBG(("MFP Capable \n"));
8388 mfp
= WL_MFP_CAPABLE
;
8392 /* set wme_bss_disable to sync RSN Capabilities */
8393 err
= wldev_iovar_setint_bsscfg(dev
, "wme_bss_disable", wme_bss_disable
, bssidx
);
8395 WL_ERR(("wme_bss_disable error %d\n", err
));
8399 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len
));
8403 if (len
>= WPA2_PMKID_COUNT_LEN
) {
8404 pmkid
= (wpa_pmkid_list_t
*)((u8
*)&mgmt
->list
[suite_count
] + RSN_CAP_LEN
);
8405 cnt
= ltoh16_ua(&pmkid
->count
);
8407 WL_ERR(("AP has non-zero PMKID count. Wrong!\n"));
8410 /* since PMKID cnt is known to be 0 for AP, */
8411 /* so don't bother to send down this info to firmware */
8415 len
-= WPA2_PMKID_COUNT_LEN
;
8416 if (len
>= WPA_SUITE_LEN
) {
8417 cfg
->bip_pos
= (u8
*)&mgmt
->list
[suite_count
] + RSN_CAP_LEN
+ WPA2_PMKID_COUNT_LEN
;
8419 cfg
->bip_pos
= NULL
;
8424 err
= wldev_iovar_setint_bsscfg(dev
, "auth", auth
, bssidx
);
8426 WL_ERR(("auth error %d\n", err
));
8431 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", wsec
, bssidx
);
8433 WL_ERR(("wsec error %d\n", err
));
8438 cfg
->mfp_mode
= mfp
;
8441 /* set upper-layer auth */
8442 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", wpa_auth
, bssidx
);
8444 WL_ERR(("wpa_auth error %d\n", err
));
8452 wl_validate_wpaie(struct net_device
*dev
, wpa_ie_fixed_t
*wpaie
, s32 bssidx
)
8454 wpa_suite_mcast_t
*mcast
;
8455 wpa_suite_ucast_t
*ucast
;
8456 wpa_suite_auth_key_mgmt_t
*mgmt
;
8457 u16 auth
= 0; /* d11 open authentication */
8470 WL_DBG(("Enter \n"));
8471 len
= wpaie
->length
; /* value length */
8472 len
-= WPA_IE_TAG_FIXED_LEN
;
8473 /* check for multicast cipher suite */
8474 if (len
< WPA_SUITE_LEN
) {
8475 WL_INFORM(("no multicast cipher suite\n"));
8479 /* pick up multicast cipher */
8480 mcast
= (wpa_suite_mcast_t
*)&wpaie
[1];
8481 len
-= WPA_SUITE_LEN
;
8482 if (!bcmp(mcast
->oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8483 if (IS_WPA_CIPHER(mcast
->type
)) {
8485 switch (mcast
->type
) {
8486 case WPA_CIPHER_NONE
:
8489 case WPA_CIPHER_WEP_40
:
8490 case WPA_CIPHER_WEP_104
:
8493 case WPA_CIPHER_TKIP
:
8496 case WPA_CIPHER_AES_CCM
:
8500 WL_ERR(("No Security Info\n"));
8505 /* Check for unicast suite(s) */
8506 if (len
< WPA_IE_SUITE_COUNT_LEN
) {
8507 WL_INFORM(("no unicast suite\n"));
8510 /* walk thru unicast cipher list and pick up what we recognize */
8511 ucast
= (wpa_suite_ucast_t
*)&mcast
[1];
8512 count
= ltoh16_ua(&ucast
->count
);
8513 len
-= WPA_IE_SUITE_COUNT_LEN
;
8514 for (i
= 0; i
< count
&& len
>= WPA_SUITE_LEN
;
8515 i
++, len
-= WPA_SUITE_LEN
) {
8516 if (!bcmp(ucast
->list
[i
].oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8517 if (IS_WPA_CIPHER(ucast
->list
[i
].type
)) {
8519 switch (ucast
->list
[i
].type
) {
8520 case WPA_CIPHER_NONE
:
8523 case WPA_CIPHER_WEP_40
:
8524 case WPA_CIPHER_WEP_104
:
8527 case WPA_CIPHER_TKIP
:
8530 case WPA_CIPHER_AES_CCM
:
8534 WL_ERR(("No Security Info\n"));
8540 len
-= (count
- i
) * WPA_SUITE_LEN
;
8541 /* Check for auth key management suite(s) */
8542 if (len
< WPA_IE_SUITE_COUNT_LEN
) {
8543 WL_INFORM((" no auth key mgmt suite\n"));
8546 /* walk thru auth management suite list and pick up what we recognize */
8547 mgmt
= (wpa_suite_auth_key_mgmt_t
*)&ucast
->list
[count
];
8548 count
= ltoh16_ua(&mgmt
->count
);
8549 len
-= WPA_IE_SUITE_COUNT_LEN
;
8550 for (i
= 0; i
< count
&& len
>= WPA_SUITE_LEN
;
8551 i
++, len
-= WPA_SUITE_LEN
) {
8552 if (!bcmp(mgmt
->list
[i
].oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8553 if (IS_WPA_AKM(mgmt
->list
[i
].type
)) {
8555 switch (mgmt
->list
[i
].type
) {
8557 tmp
= WPA_AUTH_NONE
;
8559 case RSN_AKM_UNSPECIFIED
:
8560 tmp
= WPA_AUTH_UNSPECIFIED
;
8566 WL_ERR(("No Key Mgmt Info\n"));
8573 /* FOR WPS , set SEC_OW_ENABLED */
8574 wsec
= (pval
| gval
| SES_OW_ENABLED
);
8576 err
= wldev_iovar_setint_bsscfg(dev
, "auth", auth
, bssidx
);
8578 WL_ERR(("auth error %d\n", err
));
8582 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", wsec
, bssidx
);
8584 WL_ERR(("wsec error %d\n", err
));
8587 /* set upper-layer auth */
8588 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", wpa_auth
, bssidx
);
8590 WL_ERR(("wpa_auth error %d\n", err
));
8597 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8598 static u32
wl_get_cipher_type(uint8 type
)
8602 case WPA_CIPHER_NONE
:
8605 case WPA_CIPHER_WEP_40
:
8606 case WPA_CIPHER_WEP_104
:
8609 case WPA_CIPHER_TKIP
:
8612 case WPA_CIPHER_AES_CCM
:
8616 case WAPI_CIPHER_SMS4
:
8621 WL_ERR(("No Security Info\n"));
8626 static u32
wl_get_suite_auth_key_mgmt_type(uint8 type
)
8631 ret
= WPA_AUTH_NONE
;
8633 case RSN_AKM_UNSPECIFIED
:
8634 ret
= WPA_AUTH_UNSPECIFIED
;
8640 WL_ERR(("No Key Mgmt Info\n"));
8645 static u32
wl_get_suite_auth2_key_mgmt_type(uint8 type
)
8650 ret
= WPA_AUTH_NONE
;
8652 case RSN_AKM_UNSPECIFIED
:
8653 ret
= WPA2_AUTH_UNSPECIFIED
;
8656 ret
= WPA2_AUTH_PSK
;
8659 WL_ERR(("No Key Mgmt Info\n"));
8665 wl_validate_wpaie_wpa2ie(struct net_device
*dev
, wpa_ie_fixed_t
*wpaie
,
8666 bcm_tlv_t
*wpa2ie
, s32 bssidx
)
8668 wpa_suite_mcast_t
*mcast
;
8669 wpa_suite_ucast_t
*ucast
;
8670 wpa_suite_auth_key_mgmt_t
*mgmt
;
8671 u16 auth
= 0; /* d11 open authentication */
8674 u32 wme_bss_disable
;
8679 u32 wsec1
, wsec2
, wsec
;
8687 if (wpaie
== NULL
|| wpa2ie
== NULL
)
8690 WL_DBG(("Enter \n"));
8691 len
= wpaie
->length
; /* value length */
8692 len
-= WPA_IE_TAG_FIXED_LEN
;
8693 /* check for multicast cipher suite */
8694 if (len
< WPA_SUITE_LEN
) {
8695 WL_INFORM(("no multicast cipher suite\n"));
8699 /* pick up multicast cipher */
8700 mcast
= (wpa_suite_mcast_t
*)&wpaie
[1];
8701 len
-= WPA_SUITE_LEN
;
8702 if (!bcmp(mcast
->oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8703 if (IS_WPA_CIPHER(mcast
->type
)) {
8704 gval
|= wl_get_cipher_type(mcast
->type
);
8707 WL_ERR(("\nwpa ie validate\n"));
8708 WL_ERR(("wpa ie mcast cipher = 0x%X\n", gval
));
8710 /* Check for unicast suite(s) */
8711 if (len
< WPA_IE_SUITE_COUNT_LEN
) {
8712 WL_INFORM(("no unicast suite\n"));
8716 /* walk thru unicast cipher list and pick up what we recognize */
8717 ucast
= (wpa_suite_ucast_t
*)&mcast
[1];
8718 count
= ltoh16_ua(&ucast
->count
);
8719 len
-= WPA_IE_SUITE_COUNT_LEN
;
8720 for (i
= 0; i
< count
&& len
>= WPA_SUITE_LEN
;
8721 i
++, len
-= WPA_SUITE_LEN
) {
8722 if (!bcmp(ucast
->list
[i
].oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8723 if (IS_WPA_CIPHER(ucast
->list
[i
].type
)) {
8724 pval
|= wl_get_cipher_type(ucast
->list
[i
].type
);
8728 WL_ERR(("wpa ie ucast count =%d, cipher = 0x%X\n", count
, pval
));
8730 /* FOR WPS , set SEC_OW_ENABLED */
8731 wsec1
= (pval
| gval
| SES_OW_ENABLED
);
8732 WL_ERR(("wpa ie wsec = 0x%X\n", wsec1
));
8734 len
-= (count
- i
) * WPA_SUITE_LEN
;
8735 /* Check for auth key management suite(s) */
8736 if (len
< WPA_IE_SUITE_COUNT_LEN
) {
8737 WL_INFORM((" no auth key mgmt suite\n"));
8740 /* walk thru auth management suite list and pick up what we recognize */
8741 mgmt
= (wpa_suite_auth_key_mgmt_t
*)&ucast
->list
[count
];
8742 count
= ltoh16_ua(&mgmt
->count
);
8743 len
-= WPA_IE_SUITE_COUNT_LEN
;
8744 for (i
= 0; i
< count
&& len
>= WPA_SUITE_LEN
;
8745 i
++, len
-= WPA_SUITE_LEN
) {
8746 if (!bcmp(mgmt
->list
[i
].oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8747 if (IS_WPA_AKM(mgmt
->list
[i
].type
)) {
8749 wpa_auth1
|= wl_get_suite_auth_key_mgmt_type(mgmt
->list
[i
].type
);
8754 WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count
, wpa_auth1
));
8755 WL_ERR(("\nwpa2 ie validate\n"));
8760 /* check the mcast cipher */
8761 mcast
= (wpa_suite_mcast_t
*)&wpa2ie
->data
[WPA2_VERSION_LEN
];
8763 gval
= wl_get_cipher_type(ptmp
[DOT11_OUI_LEN
]);
8765 WL_ERR(("wpa2 ie mcast cipher = 0x%X\n", gval
));
8766 if ((len
-= WPA_SUITE_LEN
) <= 0)
8768 WL_ERR(("P:wpa2 ie len[%d]", len
));
8772 /* check the unicast cipher */
8773 ucast
= (wpa_suite_ucast_t
*)&mcast
[1];
8774 suite_count
= ltoh16_ua(&ucast
->count
);
8775 WL_ERR((" WPA2 ucast cipher count=%d\n", suite_count
));
8776 pval
|= wl_get_cipher_type(ucast
->list
[0].type
);
8778 if ((len
-= (WPA_IE_SUITE_COUNT_LEN
+ (WPA_SUITE_LEN
* suite_count
))) <= 0)
8781 WL_ERR(("wpa2 ie ucast cipher = 0x%X\n", pval
));
8783 /* FOR WPS , set SEC_OW_ENABLED */
8784 wsec2
= (pval
| gval
| SES_OW_ENABLED
);
8785 WL_ERR(("wpa2 ie wsec = 0x%X\n", wsec2
));
8788 mgmt
= (wpa_suite_auth_key_mgmt_t
*)&ucast
->list
[suite_count
];
8789 suite_count
= ltoh16_ua(&mgmt
->count
);
8790 ptmp
= (u8
*)&mgmt
->list
[0];
8791 wpa_auth2
= wl_get_suite_auth2_key_mgmt_type(ptmp
[DOT11_OUI_LEN
]);
8792 WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count
, wpa_auth2
));
8794 if ((len
-= (WPA_IE_SUITE_COUNT_LEN
+ (WPA_SUITE_LEN
* suite_count
))) >= RSN_CAP_LEN
) {
8795 rsn_cap
[0] = *(u8
*)&mgmt
->list
[suite_count
];
8796 rsn_cap
[1] = *((u8
*)&mgmt
->list
[suite_count
] + 1);
8797 if (rsn_cap
[0] & (RSN_CAP_16_REPLAY_CNTRS
<< RSN_CAP_PTK_REPLAY_CNTR_SHIFT
)) {
8798 wme_bss_disable
= 0;
8800 wme_bss_disable
= 1;
8802 WL_DBG(("P:rsn_cap[0]=[0x%X]:wme_bss_disabled[%d]\n", rsn_cap
[0], wme_bss_disable
));
8804 /* set wme_bss_disable to sync RSN Capabilities */
8805 err
= wldev_iovar_setint_bsscfg(dev
, "wme_bss_disable", wme_bss_disable
, bssidx
);
8807 WL_ERR(("wme_bss_disable error %d\n", err
));
8811 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len
));
8814 wsec
= (wsec1
| wsec2
);
8815 wpa_auth
= (wpa_auth1
| wpa_auth2
);
8816 WL_ERR(("wpa_wpa2 wsec=0x%X wpa_auth=0x%X\n", wsec
, wpa_auth
));
8819 err
= wldev_iovar_setint_bsscfg(dev
, "auth", auth
, bssidx
);
8821 WL_ERR(("auth error %d\n", err
));
8825 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", wsec
, bssidx
);
8827 WL_ERR(("wsec error %d\n", err
));
8830 /* set upper-layer auth */
8831 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", wpa_auth
, bssidx
);
8833 WL_ERR(("wpa_auth error %d\n", err
));
8839 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8842 wl_cfg80211_bcn_validate_sec(
8843 struct net_device
*dev
,
8844 struct parsed_ies
*ies
,
8849 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
8850 wl_cfgbss_t
*bss
= wl_get_cfgbss_by_wdev(cfg
, dev
->ieee80211_ptr
);
8853 WL_ERR(("cfgbss is NULL \n"));
8857 if (dev_role
== NL80211_IFTYPE_P2P_GO
&& (ies
->wpa2_ie
)) {
8858 /* For P2P GO, the sec type is WPA2-PSK */
8859 WL_DBG(("P2P GO: validating wpa2_ie"));
8860 if (wl_validate_wpa2ie(dev
, ies
->wpa2_ie
, bssidx
) < 0)
8863 } else if (dev_role
== NL80211_IFTYPE_AP
) {
8865 WL_DBG(("SoftAP: validating security"));
8866 /* If wpa2_ie or wpa_ie is present validate it */
8868 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8869 if ((ies
->wpa_ie
!= NULL
&& ies
->wpa2_ie
!= NULL
)) {
8870 if (wl_validate_wpaie_wpa2ie(dev
, ies
->wpa_ie
, ies
->wpa2_ie
, bssidx
) < 0) {
8871 bss
->security_mode
= false;
8876 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8877 if ((ies
->wpa2_ie
|| ies
->wpa_ie
) &&
8878 ((wl_validate_wpa2ie(dev
, ies
->wpa2_ie
, bssidx
) < 0 ||
8879 wl_validate_wpaie(dev
, ies
->wpa_ie
, bssidx
) < 0))) {
8880 bss
->security_mode
= false;
8884 bss
->security_mode
= true;
8897 if (ies
->wpa_ie
!= NULL
) {
8900 bss
->wpa_ie
= kmemdup(ies
->wpa_ie
,
8901 ies
->wpa_ie
->length
+ WPA_RSN_IE_TAG_FIXED_LEN
,
8903 } else if (ies
->wpa2_ie
!= NULL
) {
8906 bss
->rsn_ie
= kmemdup(ies
->wpa2_ie
,
8907 ies
->wpa2_ie
->len
+ WPA_RSN_IE_TAG_FIXED_LEN
,
8910 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8912 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8913 if (!ies
->wpa2_ie
&& !ies
->wpa_ie
) {
8914 wl_validate_opensecurity(dev
, bssidx
, privacy
);
8915 bss
->security_mode
= false;
8919 bss
->wps_ie
= kmemdup(ies
->wps_ie
, ies
->wps_ie_len
, GFP_KERNEL
);
8927 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
8928 static s32
wl_cfg80211_bcn_set_params(
8929 struct cfg80211_ap_settings
*info
,
8930 struct net_device
*dev
,
8931 u32 dev_role
, s32 bssidx
)
8933 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
8936 WL_DBG(("interval (%d) \ndtim_period (%d) \n",
8937 info
->beacon_interval
, info
->dtim_period
));
8939 if (info
->beacon_interval
) {
8940 if ((err
= wldev_ioctl_set(dev
, WLC_SET_BCNPRD
,
8941 &info
->beacon_interval
, sizeof(s32
))) < 0) {
8942 WL_ERR(("Beacon Interval Set Error, %d\n", err
));
8947 if (info
->dtim_period
) {
8948 if ((err
= wldev_ioctl_set(dev
, WLC_SET_DTIMPRD
,
8949 &info
->dtim_period
, sizeof(s32
))) < 0) {
8950 WL_ERR(("DTIM Interval Set Error, %d\n", err
));
8955 if ((info
->ssid
) && (info
->ssid_len
> 0) &&
8956 (info
->ssid_len
<= DOT11_MAX_SSID_LEN
)) {
8957 WL_DBG(("SSID (%s) len:%zd \n", info
->ssid
, info
->ssid_len
));
8958 if (dev_role
== NL80211_IFTYPE_AP
) {
8959 /* Store the hostapd SSID */
8960 memset(cfg
->hostapd_ssid
.SSID
, 0x00, DOT11_MAX_SSID_LEN
);
8961 memcpy(cfg
->hostapd_ssid
.SSID
, info
->ssid
, info
->ssid_len
);
8962 cfg
->hostapd_ssid
.SSID_len
= info
->ssid_len
;
8965 memset(cfg
->p2p
->ssid
.SSID
, 0x00, DOT11_MAX_SSID_LEN
);
8966 memcpy(cfg
->p2p
->ssid
.SSID
, info
->ssid
, info
->ssid_len
);
8967 cfg
->p2p
->ssid
.SSID_len
= info
->ssid_len
;
8971 if (info
->hidden_ssid
!= NL80211_HIDDEN_SSID_NOT_IN_USE
) {
8972 if ((err
= wldev_iovar_setint(dev
, "closednet", 1)) < 0)
8973 WL_ERR(("failed to set hidden : %d\n", err
));
8974 WL_DBG(("hidden_ssid_enum_val: %d \n", info
->hidden_ssid
));
8982 wl_cfg80211_parse_ies(u8
*ptr
, u32 len
, struct parsed_ies
*ies
)
8986 memset(ies
, 0, sizeof(struct parsed_ies
));
8988 /* find the WPSIE */
8989 if ((ies
->wps_ie
= wl_cfgp2p_find_wpsie(ptr
, len
)) != NULL
) {
8990 WL_DBG(("WPSIE in beacon \n"));
8991 ies
->wps_ie_len
= ies
->wps_ie
->length
+ WPA_RSN_IE_TAG_FIXED_LEN
;
8993 WL_DBG(("No WPSIE in beacon \n"));
8996 /* find the RSN_IE */
8997 if ((ies
->wpa2_ie
= bcm_parse_tlvs(ptr
, len
,
8998 DOT11_MNG_RSN_ID
)) != NULL
) {
8999 WL_DBG((" WPA2 IE found\n"));
9000 ies
->wpa2_ie_len
= ies
->wpa2_ie
->len
;
9003 /* find the WPA_IE */
9004 if ((ies
->wpa_ie
= wl_cfgp2p_find_wpaie(ptr
, len
)) != NULL
) {
9005 WL_DBG((" WPA found\n"));
9006 ies
->wpa_ie_len
= ies
->wpa_ie
->length
;
9013 wl_cfg80211_set_ap_role(
9014 struct bcm_cfg80211
*cfg
,
9015 struct net_device
*dev
)
9021 s32 is_rsdb_supported
= BCME_ERROR
;
9025 is_rsdb_supported
= DHD_OPMODE_SUPPORTED(cfg
->pub
, DHD_FLAG_RSDB_MODE
);
9026 if (is_rsdb_supported
< 0)
9029 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
9030 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
9034 /* AP on primary Interface */
9036 if (is_rsdb_supported
) {
9037 if ((err
= wl_cfg80211_add_del_bss(cfg
, dev
, bssidx
,
9038 NL80211_IFTYPE_AP
, 0, NULL
)) < 0) {
9039 WL_ERR(("wl add_del_bss returned error:%d\n", err
));
9042 } else if (is_rsdb_supported
== 0) {
9043 /* AP mode switch not supported. Try setting up AP explicitly */
9044 err
= wldev_iovar_getint(dev
, "apsta", (s32
*)&apsta
);
9045 if (unlikely(err
)) {
9046 WL_ERR(("Could not get apsta %d\n", err
));
9048 if (1) { // terence: fix me
9049 /* If apsta is not set, set it */
9050 err
= wldev_ioctl_set(dev
, WLC_DOWN
, &ap
, sizeof(s32
));
9052 WL_ERR(("WLC_DOWN error %d\n", err
));
9055 err
= wldev_iovar_setint(dev
, "apsta", 0);
9057 WL_ERR(("wl apsta 0 error %d\n", err
));
9060 if ((err
= wldev_ioctl_set(dev
,
9061 WLC_SET_AP
, &ap
, sizeof(s32
))) < 0) {
9062 WL_ERR(("setting AP mode failed %d \n", err
));
9069 if ((err
= wldev_ioctl_set(dev
, WLC_SET_PM
, &pm
, sizeof(pm
))) != 0) {
9070 WL_ERR(("wl PM 0 returned error:%d\n", err
));
9071 /* Ignore error, if any */
9074 err
= wldev_ioctl_set(dev
, WLC_SET_INFRA
, &infra
, sizeof(s32
));
9076 WL_ERR(("SET INFRA error %d\n", err
));
9080 WL_DBG(("Bringup SoftAP on virtual Interface bssidx:%d \n", bssidx
));
9081 if ((err
= wl_cfg80211_add_del_bss(cfg
, dev
,
9082 bssidx
, NL80211_IFTYPE_AP
, 0, NULL
)) < 0) {
9083 WL_ERR(("wl bss ap returned error:%d\n", err
));
9088 /* On success, mark AP creation in progress. */
9089 wl_set_drv_status(cfg
, AP_CREATING
, dev
);
9094 /* In RSDB downgrade cases, the link up event can get delayed upto 7-8 secs */
9095 #define MAX_AP_LINK_WAIT_TIME 10000
9097 wl_cfg80211_bcn_bringup_ap(
9098 struct net_device
*dev
,
9099 struct parsed_ies
*ies
,
9100 u32 dev_role
, s32 bssidx
)
9102 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
9103 struct wl_join_params join_params
;
9104 bool is_bssup
= false;
9106 s32 join_params_size
= 0;
9110 bool retried
= false;
9112 #ifdef SOFTAP_UAPSD_OFF
9113 uint32 wme_apsd
= 0;
9114 #endif /* SOFTAP_UAPSD_OFF */
9116 s32 is_rsdb_supported
= BCME_ERROR
;
9118 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
9119 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
9120 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
9122 is_rsdb_supported
= DHD_OPMODE_SUPPORTED(cfg
->pub
, DHD_FLAG_RSDB_MODE
);
9123 if (is_rsdb_supported
< 0)
9126 WL_DBG(("Enter dev_role:%d bssidx:%d ifname:%s\n", dev_role
, bssidx
, dev
->name
));
9128 /* Common code for SoftAP and P2P GO */
9129 wl_clr_drv_status(cfg
, AP_CREATED
, dev
);
9131 /* Make sure INFRA is set for AP/GO */
9132 err
= wldev_ioctl_set(dev
, WLC_SET_INFRA
, &infra
, sizeof(s32
));
9134 WL_ERR(("SET INFRA error %d\n", err
));
9138 /* Do abort scan before creating GO */
9139 wl_cfg80211_scan_abort(cfg
);
9141 if (dev_role
== NL80211_IFTYPE_P2P_GO
) {
9142 is_bssup
= wl_cfg80211_bss_isup(dev
, bssidx
);
9143 if (!is_bssup
&& (ies
->wpa2_ie
!= NULL
)) {
9145 err
= wldev_iovar_setbuf_bsscfg(dev
, "ssid", &cfg
->p2p
->ssid
,
9146 sizeof(cfg
->p2p
->ssid
), cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
,
9147 bssidx
, &cfg
->ioctl_buf_sync
);
9149 WL_ERR(("GO SSID setting error %d\n", err
));
9153 if ((err
= wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 1)) < 0) {
9154 WL_ERR(("GO Bring up error %d\n", err
));
9158 WL_DBG(("Bss is already up\n"));
9159 } else if (dev_role
== NL80211_IFTYPE_AP
) {
9161 // if (!wl_get_drv_status(cfg, AP_CREATING, dev)) {
9162 /* Make sure fw is in proper state */
9163 err
= wl_cfg80211_set_ap_role(cfg
, dev
);
9164 if (unlikely(err
)) {
9165 WL_ERR(("set ap role failed!\n"));
9170 /* Device role SoftAP */
9171 WL_DBG(("Creating AP bssidx:%d dev_role:%d\n", bssidx
, dev_role
));
9172 /* Clear the status bit after use */
9173 wl_clr_drv_status(cfg
, AP_CREATING
, dev
);
9176 #ifdef SOFTAP_UAPSD_OFF
9177 err
= wldev_iovar_setbuf_bsscfg(dev
, "wme_apsd", &wme_apsd
, sizeof(wme_apsd
),
9178 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
9180 WL_ERR(("failed to disable uapsd, error=%d\n", err
));
9182 #endif /* SOFTAP_UAPSD_OFF */
9183 dhd_conf_set_wme(cfg
->pub
, 1);
9185 err
= wldev_ioctl_set(dev
, WLC_UP
, &ap
, sizeof(s32
));
9186 if (unlikely(err
)) {
9187 WL_ERR(("WLC_UP error (%d)\n", err
));
9193 err
= wldev_iovar_setbuf_bsscfg(dev
, "bip",
9194 (void *)(cfg
->bip_pos
), WPA_SUITE_LEN
, cfg
->ioctl_buf
,
9195 WLC_IOCTL_SMLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
9197 WL_ERR(("bip set error %d\n", err
));
9198 if (wl_customer6_legacy_chip_check(cfg
,
9199 bcmcfg_to_prmry_ndev(cfg
))) {
9200 /* Ignore bip error: Some older firmwares doesn't
9201 * support bip iovar/ return BCME_NOTUP while trying
9202 * to set bip from AP bring up context. These firmares
9203 * include bip in RSNIE by default. So its okay to ignore
9214 err
= wldev_iovar_getint(dev
, "wsec", (s32
*)&wsec
);
9215 if (unlikely(err
)) {
9216 WL_ERR(("Could not get wsec %d\n", err
));
9219 if ((wsec
== WEP_ENABLED
) && cfg
->wep_key
.len
) {
9220 WL_DBG(("Applying buffered WEP KEY \n"));
9221 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &cfg
->wep_key
,
9222 sizeof(struct wl_wsec_key
), cfg
->ioctl_buf
,
9223 WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
9224 /* clear the key after use */
9225 memset(&cfg
->wep_key
, 0, sizeof(struct wl_wsec_key
));
9226 if (unlikely(err
)) {
9227 WL_ERR(("WLC_SET_KEY error (%d)\n", err
));
9233 if (cfg
->mfp_mode
) {
9234 /* This needs to go after wsec otherwise the wsec command will
9235 * overwrite the values set by MFP
9237 err
= wldev_iovar_setint_bsscfg(dev
, "mfp", cfg
->mfp_mode
, bssidx
);
9239 WL_ERR(("MFP Setting failed. ret = %d \n", err
));
9240 /* If fw doesn't support mfp, Ignore the error */
9241 if (err
!= BCME_UNSUPPORTED
) {
9251 memset(&join_params
, 0, sizeof(join_params
));
9252 /* join parameters starts with ssid */
9253 join_params_size
= sizeof(join_params
.ssid
);
9254 join_params
.ssid
.SSID_len
= MIN(cfg
->hostapd_ssid
.SSID_len
,
9255 (uint32
)DOT11_MAX_SSID_LEN
);
9256 memcpy(join_params
.ssid
.SSID
, cfg
->hostapd_ssid
.SSID
,
9257 join_params
.ssid
.SSID_len
);
9258 join_params
.ssid
.SSID_len
= htod32(join_params
.ssid
.SSID_len
);
9261 if ((err
= wldev_ioctl_set(dev
, WLC_SET_SSID
, &join_params
,
9262 join_params_size
)) != 0) {
9263 WL_ERR(("SoftAP/GO set ssid failed! %d\n", err
));
9266 WL_DBG((" SoftAP SSID \"%s\" \n", join_params
.ssid
.SSID
));
9270 /* AP on Virtual Interface */
9271 if ((err
= wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 1)) < 0) {
9272 WL_ERR(("AP Bring up error %d\n", err
));
9279 /* Wait for Linkup event to mark successful AP/GO bring up */
9280 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
9281 wl_get_drv_status(cfg
, AP_CREATED
, dev
), msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME
));
9282 if (timeout
<= 0 || !wl_get_drv_status(cfg
, AP_CREATED
, dev
)) {
9286 WL_ERR(("Link up didn't come for AP interface. Try to set ssid again to recover it! \n"));
9290 WL_ERR(("Link up didn't come for AP interface. AP/GO creation failed! \n"));
9291 if (timeout
== -ERESTARTSYS
) {
9292 WL_ERR(("waitqueue was interrupted by a signal, returns -ERESTARTSYS\n"));
9296 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
9297 if (dhdp
->memdump_enabled
) {
9298 dhdp
->memdump_type
= DUMP_TYPE_AP_LINKUP_FAILURE
;
9299 dhd_bus_mem_dump(dhdp
);
9301 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
9307 if (cfg
->wep_key
.len
) {
9308 memset(&cfg
->wep_key
, 0, sizeof(struct wl_wsec_key
));
9312 if (cfg
->mfp_mode
) {
9317 cfg
->bip_pos
= NULL
;
9324 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9326 wl_cfg80211_parse_ap_ies(
9327 struct net_device
*dev
,
9328 struct cfg80211_beacon_data
*info
,
9329 struct parsed_ies
*ies
)
9331 struct parsed_ies prb_ies
;
9332 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
9333 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
9334 const u8
*vndr
= NULL
;
9335 u32 vndr_ie_len
= 0;
9338 /* Parse Beacon IEs */
9339 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9340 #pragma GCC diagnostic push
9341 #pragma GCC diagnostic ignored "-Wcast-qual"
9343 if (wl_cfg80211_parse_ies((u8
*)info
->tail
,
9344 info
->tail_len
, ies
) < 0) {
9345 WL_ERR(("Beacon get IEs failed \n"));
9349 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9350 #pragma GCC diagnostic pop
9352 vndr
= (const u8
*)info
->proberesp_ies
;
9353 vndr_ie_len
= info
->proberesp_ies_len
;
9355 if (dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
) {
9357 const struct ieee80211_mgmt
*mgmt
;
9358 mgmt
= (const struct ieee80211_mgmt
*)info
->probe_resp
;
9360 vndr
= (const u8
*)&mgmt
->u
.probe_resp
.variable
;
9361 vndr_ie_len
= info
->probe_resp_len
-
9362 offsetof(const struct ieee80211_mgmt
, u
.probe_resp
.variable
);
9365 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9366 #pragma GCC diagnostic push
9367 #pragma GCC diagnostic ignored "-Wcast-qual"
9369 /* Parse Probe Response IEs */
9370 if (wl_cfg80211_parse_ies((u8
*)vndr
, vndr_ie_len
, &prb_ies
) < 0) {
9371 WL_ERR(("PROBE RESP get IEs failed \n"));
9374 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9375 #pragma GCC diagnostic pop
9383 wl_cfg80211_set_ies(
9384 struct net_device
*dev
,
9385 struct cfg80211_beacon_data
*info
,
9388 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
9389 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
9390 const u8
*vndr
= NULL
;
9391 u32 vndr_ie_len
= 0;
9394 /* Set Beacon IEs to FW */
9395 if ((err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
9396 VNDR_IE_BEACON_FLAG
, (const u8
*)info
->tail
,
9397 info
->tail_len
)) < 0) {
9398 WL_ERR(("Set Beacon IE Failed \n"));
9400 WL_DBG(("Applied Vndr IEs for Beacon \n"));
9403 vndr
= (const u8
*)info
->proberesp_ies
;
9404 vndr_ie_len
= info
->proberesp_ies_len
;
9406 if (dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
) {
9408 const struct ieee80211_mgmt
*mgmt
;
9409 mgmt
= (const struct ieee80211_mgmt
*)info
->probe_resp
;
9411 vndr
= (const u8
*)&mgmt
->u
.probe_resp
.variable
;
9412 vndr_ie_len
= info
->probe_resp_len
-
9413 offsetof(struct ieee80211_mgmt
, u
.probe_resp
.variable
);
9417 /* Set Probe Response IEs to FW */
9418 if ((err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
9419 VNDR_IE_PRBRSP_FLAG
, vndr
, vndr_ie_len
)) < 0) {
9420 WL_ERR(("Set Probe Resp IE Failed \n"));
9422 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
9429 static s32
wl_cfg80211_hostapd_sec(
9430 struct net_device
*dev
,
9431 struct parsed_ies
*ies
,
9434 bool update_bss
= 0;
9435 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
9436 wl_cfgbss_t
*bss
= wl_get_cfgbss_by_wdev(cfg
, dev
->ieee80211_ptr
);
9439 WL_ERR(("cfgbss is NULL \n"));
9445 memcmp(bss
->wps_ie
, ies
->wps_ie
, ies
->wps_ie_len
)) {
9446 WL_DBG((" WPS IE is changed\n"));
9448 bss
->wps_ie
= kmemdup(ies
->wps_ie
, ies
->wps_ie_len
, GFP_KERNEL
);
9449 } else if (bss
->wps_ie
== NULL
) {
9450 WL_DBG((" WPS IE is added\n"));
9451 bss
->wps_ie
= kmemdup(ies
->wps_ie
, ies
->wps_ie_len
, GFP_KERNEL
);
9454 if ((ies
->wpa_ie
!= NULL
|| ies
->wpa2_ie
!= NULL
)) {
9455 if (!bss
->security_mode
) {
9456 /* change from open mode to security mode */
9458 if (ies
->wpa_ie
!= NULL
) {
9459 bss
->wpa_ie
= kmemdup(ies
->wpa_ie
,
9460 ies
->wpa_ie
->length
+ WPA_RSN_IE_TAG_FIXED_LEN
,
9463 bss
->rsn_ie
= kmemdup(ies
->wpa2_ie
,
9464 ies
->wpa2_ie
->len
+ WPA_RSN_IE_TAG_FIXED_LEN
,
9467 } else if (bss
->wpa_ie
) {
9468 /* change from WPA2 mode to WPA mode */
9469 if (ies
->wpa_ie
!= NULL
) {
9473 bss
->wpa_ie
= kmemdup(ies
->wpa_ie
,
9474 ies
->wpa_ie
->length
+ WPA_RSN_IE_TAG_FIXED_LEN
,
9476 } else if (memcmp(bss
->rsn_ie
,
9477 ies
->wpa2_ie
, ies
->wpa2_ie
->len
9478 + WPA_RSN_IE_TAG_FIXED_LEN
)) {
9481 bss
->rsn_ie
= kmemdup(ies
->wpa2_ie
,
9482 ies
->wpa2_ie
->len
+ WPA_RSN_IE_TAG_FIXED_LEN
,
9488 bss
->security_mode
= true;
9489 wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 0);
9490 if (wl_validate_wpa2ie(dev
, ies
->wpa2_ie
, bssidx
) < 0 ||
9491 wl_validate_wpaie(dev
, ies
->wpa_ie
, bssidx
) < 0) {
9494 wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 1);
9498 WL_ERR(("No WPSIE in beacon \n"));
9503 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
9506 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9507 wl_cfg80211_del_station(
9508 struct wiphy
*wiphy
, struct net_device
*ndev
,
9509 struct station_del_parameters
*params
)
9510 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9511 wl_cfg80211_del_station(
9512 struct wiphy
*wiphy
,
9513 struct net_device
*ndev
,
9516 wl_cfg80211_del_station(
9517 struct wiphy
*wiphy
,
9518 struct net_device
*ndev
,
9520 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9522 struct net_device
*dev
;
9523 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
9525 s8 eabuf
[ETHER_ADDR_STR_LEN
];
9527 char mac_buf
[MAX_NUM_OF_ASSOCIATED_DEV
*
9528 sizeof(struct ether_addr
) + sizeof(uint
)] = {0};
9529 struct maclist
*assoc_maclist
= (struct maclist
*)mac_buf
;
9530 int num_associated
= 0;
9532 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9533 const u8
*mac_addr
= params
->mac
;
9534 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9535 u16 rc
= params
->reason_code
;
9536 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9537 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9539 WL_DBG(("Entry\n"));
9540 if (mac_addr
== NULL
) {
9541 WL_DBG(("mac_addr is NULL ignore it\n"));
9545 dev
= ndev_to_wlc_ndev(ndev
, cfg
);
9547 if (p2p_is_on(cfg
)) {
9548 /* Suspend P2P discovery search-listen to prevent it from changing the
9551 if ((wl_cfgp2p_discover_enable_search(cfg
, false)) < 0) {
9552 WL_ERR(("Can not disable discovery mode\n"));
9556 err
= wl_cfg80211_check_in4way(cfg
, ndev
, DONT_DELETE_GC_AFTER_WPS
,
9557 WL_EXT_STATUS_DELETE_GC
, (void *)mac_addr
);
9562 assoc_maclist
->count
= MAX_NUM_OF_ASSOCIATED_DEV
;
9563 err
= wldev_ioctl_get(ndev
, WLC_GET_ASSOCLIST
,
9564 assoc_maclist
, sizeof(mac_buf
));
9566 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err
));
9568 num_associated
= assoc_maclist
->count
;
9570 memcpy(scb_val
.ea
.octet
, mac_addr
, ETHER_ADDR_LEN
);
9571 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9572 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9573 if (rc
== DOT11_RC_8021X_AUTH_FAIL
) {
9574 WL_ERR(("deauth will be sent at F/W\n"));
9575 scb_val
.val
= DOT11_RC_8021X_AUTH_FAIL
;
9577 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9578 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9580 dhd_wait_pend8021x(dev
);
9581 #endif /* !BCMDBUS */
9582 scb_val
.val
= DOT11_RC_DEAUTH_LEAVING
;
9583 err
= wldev_ioctl_set(dev
, WLC_SCB_DEAUTHENTICATE_FOR_REASON
, &scb_val
,
9586 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err
));
9587 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9588 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9590 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9591 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9592 printf("%s: Disconnect STA : %s scb_val.val %d\n", __FUNCTION__
,
9593 bcm_ether_ntoa((const struct ether_addr
*)mac_addr
, eabuf
),
9596 if (num_associated
> 0 && ETHER_ISBCAST(mac_addr
))
9603 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9604 wl_cfg80211_change_station(
9605 struct wiphy
*wiphy
,
9606 struct net_device
*dev
,
9608 struct station_parameters
*params
)
9610 wl_cfg80211_change_station(
9611 struct wiphy
*wiphy
,
9612 struct net_device
*dev
,
9614 struct station_parameters
*params
)
9618 #if defined(WL_ENABLE_P2P_IF)
9619 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
9621 struct net_device
*ndev
= ndev_to_wlc_ndev(dev
, cfg
);
9623 WL_DBG(("SCB_AUTHORIZE mac_addr:"MACDBG
" sta_flags_mask:0x%x "
9624 "sta_flags_set:0x%x iface:%s \n", MAC2STRDBG(mac
),
9625 params
->sta_flags_mask
, params
->sta_flags_set
, ndev
->name
));
9627 /* Processing only authorize/de-authorize flag for now */
9628 if (!(params
->sta_flags_mask
& BIT(NL80211_STA_FLAG_AUTHORIZED
))) {
9629 WL_ERR(("WLC_SCB_AUTHORIZE sta_flags_mask not set \n"));
9633 if (!(params
->sta_flags_set
& BIT(NL80211_STA_FLAG_AUTHORIZED
))) {
9634 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9635 err
= wldev_ioctl_set(ndev
, WLC_SCB_DEAUTHORIZE
, (u8
*)mac
, ETH_ALEN
);
9637 err
= wldev_ioctl_set(ndev
, WLC_SCB_DEAUTHORIZE
, mac
, ETH_ALEN
);
9640 WL_ERR(("WLC_SCB_DEAUTHORIZE error (%d)\n", err
));
9644 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9645 err
= wldev_ioctl_set(ndev
, WLC_SCB_AUTHORIZE
, (u8
*)mac
, ETH_ALEN
);
9647 err
= wldev_ioctl_set(ndev
, WLC_SCB_AUTHORIZE
, mac
, ETH_ALEN
);
9650 WL_ERR(("WLC_SCB_AUTHORIZE error (%d)\n", err
));
9651 #ifdef DHD_LOSSLESS_ROAMING
9652 wl_del_roam_timeout(cfg
);
9656 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
9659 wl_cfg80211_set_scb_timings(
9660 struct bcm_cfg80211
*cfg
,
9661 struct net_device
*dev
)
9665 wl_scb_probe_t scb_probe
;
9667 bzero(&scb_probe
, sizeof(wl_scb_probe_t
));
9668 scb_probe
.scb_timeout
= WL_SCB_TIMEOUT
;
9669 scb_probe
.scb_activity_time
= WL_SCB_ACTIVITY_TIME
;
9670 scb_probe
.scb_max_probe
= WL_SCB_MAX_PROBE
;
9671 err
= wldev_iovar_setbuf(dev
, "scb_probe", (void *)&scb_probe
,
9672 sizeof(wl_scb_probe_t
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
9673 &cfg
->ioctl_buf_sync
);
9674 if (unlikely(err
)) {
9675 WL_ERR(("set 'scb_probe' failed, error = %d\n", err
));
9679 ps_pretend
= MAX(WL_SCB_MAX_PROBE
/ 2, WL_MIN_PSPRETEND_THRESHOLD
);
9680 err
= wldev_iovar_setint(dev
, "pspretend_threshold", ps_pretend
);
9681 if (unlikely(err
)) {
9682 if (err
== BCME_UNSUPPORTED
) {
9683 /* Ignore error if fw doesn't support the iovar */
9684 WL_DBG(("wl pspretend_threshold %d set error %d\n",
9687 WL_ERR(("wl pspretend_threshold %d set error %d\n",
9696 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9698 wl_cfg80211_start_ap(
9699 struct wiphy
*wiphy
,
9700 struct net_device
*dev
,
9701 struct cfg80211_ap_settings
*info
)
9703 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
9705 struct parsed_ies ies
;
9708 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
9710 struct wl_join_params join_params
;
9711 s32 join_params_size
= 0;
9714 WL_DBG(("Enter \n"));
9716 #if defined(SUPPORT_RANDOM_MAC_SCAN)
9717 wl_cfg80211_set_random_mac(dev
, FALSE
);
9718 #endif /* SUPPORT_RANDOM_MAC_SCAN */
9720 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
9721 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
9725 if (p2p_is_on(cfg
) && (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
)) {
9726 dev_role
= NL80211_IFTYPE_P2P_GO
;
9727 } else if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
9728 dev_role
= NL80211_IFTYPE_AP
;
9729 dhd
->op_mode
|= DHD_FLAG_HOSTAP_MODE
;
9730 err
= dhd_ndo_enable(dhd
, FALSE
);
9731 WL_DBG(("%s: Disabling NDO on Hostapd mode %d\n", __FUNCTION__
, err
));
9733 WL_ERR(("%s: Disabling NDO Failed %d\n", __FUNCTION__
, err
));
9735 #ifdef PKT_FILTER_SUPPORT
9736 /* Disable packet filter */
9737 if (dhd
->early_suspended
) {
9738 WL_ERR(("Disable pkt_filter\n"));
9739 dhd_enable_packet_filter(0, dhd
);
9741 #endif /* PKT_FILTER_SUPPORT */
9742 #ifdef ARP_OFFLOAD_SUPPORT
9743 /* IF SoftAP is enabled, disable arpoe */
9744 if (dhd
->op_mode
& DHD_FLAG_STA_MODE
) {
9745 dhd_arp_offload_set(dhd
, 0);
9746 dhd_arp_offload_enable(dhd
, FALSE
);
9748 #endif /* ARP_OFFLOAD_SUPPORT */
9749 #ifdef SUPPORT_SET_CAC
9750 wl_cfg80211_set_cac(cfg
, 0);
9751 #endif /* SUPPORT_SET_CAC */
9753 /* only AP or GO role need to be handled here. */
9761 /* Disable TDLS for primary Iface. For virtual interface,
9762 * tdls disable will happen from interface create context
9764 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_AP_CREATE
, false);
9768 if (!check_dev_role_integrity(cfg
, dev_role
)) {
9773 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9774 if ((err
= wl_cfg80211_set_channel(wiphy
, dev
,
9775 dev
->ieee80211_ptr
->preset_chandef
.chan
,
9776 NL80211_CHAN_HT20
) < 0)) {
9777 WL_ERR(("Set channel failed \n"));
9782 if ((err
= wl_cfg80211_bcn_set_params(info
, dev
,
9783 dev_role
, bssidx
)) < 0) {
9784 WL_ERR(("Beacon params set failed \n"));
9789 if ((err
= wl_cfg80211_parse_ap_ies(dev
, &info
->beacon
, &ies
)) < 0) {
9790 WL_ERR(("Set IEs failed \n"));
9794 if ((err
= wl_cfg80211_bcn_validate_sec(dev
, &ies
,
9795 dev_role
, bssidx
, info
->privacy
)) < 0)
9797 WL_ERR(("Beacon set security failed \n"));
9801 if ((err
= wl_cfg80211_bcn_bringup_ap(dev
, &ies
,
9802 dev_role
, bssidx
)) < 0) {
9803 WL_ERR(("Beacon bring up AP/GO failed \n"));
9807 /* Set GC/STA SCB expiry timings. */
9808 if ((err
= wl_cfg80211_set_scb_timings(cfg
, dev
))) {
9809 WL_ERR(("scb setting failed \n"));
9815 if ((dev_role
== NL80211_IFTYPE_P2P_GO
) || (dev_role
== NL80211_IFTYPE_AP
)) {
9816 memset(&join_params
, 0, sizeof(join_params
));
9817 /* join parameters starts with ssid */
9818 join_params_size
= sizeof(join_params
.ssid
);
9819 if (dev_role
== NL80211_IFTYPE_P2P_GO
) {
9820 join_params
.ssid
.SSID_len
= min(cfg
->p2p
->ssid
.SSID_len
,
9821 (uint32
)DOT11_MAX_SSID_LEN
);
9822 memcpy(join_params
.ssid
.SSID
, cfg
->p2p
->ssid
.SSID
,
9823 join_params
.ssid
.SSID_len
);
9824 } else if (dev_role
== NL80211_IFTYPE_AP
) {
9825 join_params
.ssid
.SSID_len
= min(cfg
->hostapd_ssid
.SSID_len
,
9826 (uint32
)DOT11_MAX_SSID_LEN
);
9827 memcpy(join_params
.ssid
.SSID
, cfg
->hostapd_ssid
.SSID
,
9828 join_params
.ssid
.SSID_len
);
9830 join_params
.ssid
.SSID_len
= htod32(join_params
.ssid
.SSID_len
);
9832 if ((err
= wldev_ioctl_set(dev
, WLC_SET_SSID
, &join_params
,
9833 join_params_size
)) != 0) {
9834 WL_ERR(("SoftAP/GO set ssid failed! \n"));
9837 WL_DBG((" SoftAP SSID \"%s\" \n", join_params
.ssid
.SSID
));
9842 WL_DBG(("** AP/GO Created **\n"));
9844 #ifdef WL_CFG80211_ACL
9845 /* Enfoce Admission Control. */
9846 if ((err
= wl_cfg80211_set_mac_acl(wiphy
, dev
, info
->acl
)) < 0) {
9847 WL_ERR(("Set ACL failed\n"));
9849 #endif /* WL_CFG80211_ACL */
9852 if ((err
= wl_cfg80211_set_ies(dev
, &info
->beacon
, bssidx
)) < 0)
9853 WL_ERR(("Set IEs failed \n"));
9855 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
9856 if ((dev_role
== NL80211_IFTYPE_AP
) && (ies
.wps_ie
!= NULL
)) {
9858 wl_validate_wps_ie((char *) ies
.wps_ie
, ies
.wps_ie_len
, &pbc
);
9860 WL_DBG(("set WLC_E_PROBREQ_MSG\n"));
9861 wl_add_remove_eventmsg(dev
, WLC_E_PROBREQ_MSG
, true);
9865 #ifdef SUPPORT_AP_RADIO_PWRSAVE
9866 if ((dev_role
== NL80211_IFTYPE_AP
)) {
9867 wl_set_ap_rps(dev
, FALSE
, dev
->name
);
9868 wl_cfg80211_init_ap_rps(cfg
);
9870 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
9873 WL_ERR(("ADD/SET beacon failed\n"));
9874 wl_cfg80211_stop_ap(wiphy
, dev
);
9875 if (dev_role
== NL80211_IFTYPE_AP
) {
9876 dhd
->op_mode
&= ~DHD_FLAG_HOSTAP_MODE
;
9877 #ifdef PKT_FILTER_SUPPORT
9878 /* Enable packet filter */
9879 if (dhd
->early_suspended
) {
9880 WL_ERR(("Enable pkt_filter\n"));
9881 dhd_enable_packet_filter(1, dhd
);
9883 #endif /* PKT_FILTER_SUPPORT */
9884 #ifdef ARP_OFFLOAD_SUPPORT
9885 /* IF SoftAP is disabled, enable arpoe back for STA mode. */
9886 if (dhd
->op_mode
& DHD_FLAG_STA_MODE
) {
9887 dhd_arp_offload_set(dhd
, dhd_arp_mode
);
9888 dhd_arp_offload_enable(dhd
, TRUE
);
9890 #endif /* ARP_OFFLOAD_SUPPORT */
9894 /* Since AP creation failed, re-enable TDLS */
9895 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_AP_DELETE
, false);
9905 wl_cfg80211_stop_ap(
9906 struct wiphy
*wiphy
,
9907 struct net_device
*dev
)
9913 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
9914 s32 is_rsdb_supported
= BCME_ERROR
;
9915 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
9917 WL_DBG(("Enter \n"));
9919 is_rsdb_supported
= DHD_OPMODE_SUPPORTED(cfg
->pub
, DHD_FLAG_RSDB_MODE
);
9920 if (is_rsdb_supported
< 0)
9923 wl_clr_drv_status(cfg
, AP_CREATING
, dev
);
9924 wl_clr_drv_status(cfg
, AP_CREATED
, dev
);
9925 cfg
->ap_oper_channel
= 0;
9927 if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
9928 dev_role
= NL80211_IFTYPE_AP
;
9929 WL_DBG(("stopping AP operation\n"));
9930 } else if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
) {
9931 dev_role
= NL80211_IFTYPE_P2P_GO
;
9932 WL_DBG(("stopping P2P GO operation\n"));
9934 WL_ERR(("no AP/P2P GO interface is operational.\n"));
9938 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
9939 WL_ERR(("find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
9943 if (!check_dev_role_integrity(cfg
, dev_role
)) {
9944 WL_ERR(("role integrity check failed \n"));
9949 /* Clear AP/GO connected status */
9950 wl_clr_drv_status(cfg
, CONNECTED
, dev
);
9951 if ((err
= wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 0)) < 0) {
9952 WL_ERR(("bss down error %d\n", err
));
9955 if (dev_role
== NL80211_IFTYPE_AP
) {
9956 #ifdef PKT_FILTER_SUPPORT
9957 /* Enable packet filter */
9958 if (dhd
->early_suspended
) {
9959 WL_ERR(("Enable pkt_filter\n"));
9960 dhd_enable_packet_filter(1, dhd
);
9962 #endif /* PKT_FILTER_SUPPORT */
9963 #ifdef ARP_OFFLOAD_SUPPORT
9964 /* IF SoftAP is disabled, enable arpoe back for STA mode. */
9965 if (dhd
->op_mode
& DHD_FLAG_STA_MODE
) {
9966 dhd_arp_offload_set(dhd
, dhd_arp_mode
);
9967 dhd_arp_offload_enable(dhd
, TRUE
);
9969 #endif /* ARP_OFFLOAD_SUPPORT */
9971 if (is_rsdb_supported
== 0) {
9972 if (dhd_download_fw_on_driverload
&& bssidx
== 0) {
9973 wldev_ioctl_set(dev
, WLC_DOWN
, &ap
, sizeof(s32
));
9974 wldev_iovar_setint(dev
, "apsta", 1);
9976 /* For non-rsdb chips, we use stand alone AP. Do wl down on stop AP */
9977 err
= wldev_ioctl_set(dev
, WLC_UP
, &ap
, sizeof(s32
));
9978 if (unlikely(err
)) {
9979 WL_ERR(("WLC_UP error (%d)\n", err
));
9985 wl_cfg80211_clear_per_bss_ies(cfg
, bssidx
);
9986 #ifdef SUPPORT_AP_RADIO_PWRSAVE
9987 wl_set_ap_rps(dev
, FALSE
, dev
->name
);
9988 wl_cfg80211_init_ap_rps(cfg
);
9989 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
9991 WL_DBG(("Stopping P2P GO \n"));
9992 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t
*)(cfg
->pub
),
9993 DHD_EVENT_TIMEOUT_MS
*3);
9994 DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t
*)(cfg
->pub
));
9999 /* re-enable TDLS if the number of connected interfaces is less than 2 */
10000 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_AP_DELETE
, false);
10002 #endif /* WLTDLS */
10004 if (dev_role
== NL80211_IFTYPE_AP
) {
10005 /* clear the AP mode */
10006 dhd
->op_mode
&= ~DHD_FLAG_HOSTAP_MODE
;
10008 #ifdef SUPPORT_SET_CAC
10009 wl_cfg80211_set_cac(cfg
, 1);
10010 #endif /* SUPPORT_SET_CAC */
10015 wl_cfg80211_change_beacon(
10016 struct wiphy
*wiphy
,
10017 struct net_device
*dev
,
10018 struct cfg80211_beacon_data
*info
)
10021 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10022 struct parsed_ies ies
;
10027 WL_DBG(("Enter \n"));
10029 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
10030 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
10034 if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
) {
10035 dev_role
= NL80211_IFTYPE_P2P_GO
;
10036 } else if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
10037 dev_role
= NL80211_IFTYPE_AP
;
10043 if (!check_dev_role_integrity(cfg
, dev_role
)) {
10048 if ((dev_role
== NL80211_IFTYPE_P2P_GO
) && (cfg
->p2p_wdev
== NULL
)) {
10049 WL_ERR(("P2P already down status!\n"));
10055 if ((err
= wl_cfg80211_parse_ap_ies(dev
, info
, &ies
)) < 0) {
10056 WL_ERR(("Parse IEs failed \n"));
10060 /* Set IEs to FW */
10061 if ((err
= wl_cfg80211_set_ies(dev
, info
, bssidx
)) < 0) {
10062 WL_ERR(("Set IEs failed \n"));
10066 if (dev_role
== NL80211_IFTYPE_AP
) {
10067 if (wl_cfg80211_hostapd_sec(dev
, &ies
, bssidx
) < 0) {
10068 WL_ERR(("Hostapd update sec failed \n"));
10072 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
10073 if ((dev_role
== NL80211_IFTYPE_AP
) && (ies
.wps_ie
!= NULL
)) {
10074 wl_validate_wps_ie((char *) ies
.wps_ie
, ies
.wps_ie_len
, &pbc
);
10075 WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc
));
10077 wl_add_remove_eventmsg(dev
, WLC_E_PROBREQ_MSG
, true);
10079 wl_add_remove_eventmsg(dev
, WLC_E_PROBREQ_MSG
, false);
10088 wl_cfg80211_add_set_beacon(struct wiphy
*wiphy
, struct net_device
*dev
,
10089 struct beacon_parameters
*info
)
10092 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10095 u32 dev_role
= NL80211_IFTYPE_AP
;
10096 struct parsed_ies ies
;
10097 bcm_tlv_t
*ssid_ie
;
10100 bool is_bss_up
= 0;
10101 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
10103 WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
10104 info
->interval
, info
->dtim_period
, info
->head_len
, info
->tail_len
));
10106 if (dev
== bcmcfg_to_prmry_ndev(cfg
)) {
10107 dev_role
= NL80211_IFTYPE_AP
;
10109 #if defined(WL_ENABLE_P2P_IF)
10110 else if (dev
== cfg
->p2p_net
) {
10111 /* Group Add request on p2p0 */
10112 dev
= bcmcfg_to_prmry_ndev(cfg
);
10113 dev_role
= NL80211_IFTYPE_P2P_GO
;
10115 #endif /* WL_ENABLE_P2P_IF */
10117 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
10118 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
10122 if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
) {
10123 dev_role
= NL80211_IFTYPE_P2P_GO
;
10124 } else if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
10125 dhd
->op_mode
|= DHD_FLAG_HOSTAP_MODE
;
10128 if (!check_dev_role_integrity(cfg
, dev_role
)) {
10133 if ((dev_role
== NL80211_IFTYPE_P2P_GO
) && (cfg
->p2p_wdev
== NULL
)) {
10134 WL_ERR(("P2P already down status!\n"));
10139 ie_offset
= DOT11_MGMT_HDR_LEN
+ DOT11_BCN_PRB_FIXED_LEN
;
10140 /* find the SSID */
10141 if ((ssid_ie
= bcm_parse_tlvs((u8
*)&info
->head
[ie_offset
],
10142 info
->head_len
- ie_offset
,
10143 DOT11_MNG_SSID_ID
)) != NULL
) {
10144 if (dev_role
== NL80211_IFTYPE_AP
) {
10145 /* Store the hostapd SSID */
10146 memset(&cfg
->hostapd_ssid
.SSID
[0], 0x00, DOT11_MAX_SSID_LEN
);
10147 cfg
->hostapd_ssid
.SSID_len
= MIN(ssid_ie
->len
, DOT11_MAX_SSID_LEN
);
10148 memcpy(&cfg
->hostapd_ssid
.SSID
[0], ssid_ie
->data
,
10149 cfg
->hostapd_ssid
.SSID_len
);
10152 memset(&cfg
->p2p
->ssid
.SSID
[0], 0x00, DOT11_MAX_SSID_LEN
);
10153 cfg
->p2p
->ssid
.SSID_len
= MIN(ssid_ie
->len
, DOT11_MAX_SSID_LEN
);
10154 memcpy(cfg
->p2p
->ssid
.SSID
, ssid_ie
->data
,
10155 cfg
->p2p
->ssid
.SSID_len
);
10159 if (wl_cfg80211_parse_ies((u8
*)info
->tail
,
10160 info
->tail_len
, &ies
) < 0) {
10161 WL_ERR(("Beacon get IEs failed \n"));
10166 if ((err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
10167 VNDR_IE_BEACON_FLAG
, (u8
*)info
->tail
,
10168 info
->tail_len
)) < 0) {
10169 WL_ERR(("Beacon set IEs failed \n"));
10172 WL_DBG(("Applied Vndr IEs for Beacon \n"));
10175 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10176 if ((err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
10177 VNDR_IE_PRBRSP_FLAG
, (u8
*)info
->proberesp_ies
,
10178 info
->proberesp_ies_len
)) < 0) {
10179 WL_ERR(("ProbeRsp set IEs failed \n"));
10182 WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
10186 is_bss_up
= wl_cfg80211_bss_isup(dev
, bssidx
);
10188 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10189 privacy
= info
->privacy
;
10194 (wl_cfg80211_bcn_validate_sec(dev
, &ies
, dev_role
, bssidx
, privacy
) < 0))
10196 WL_ERR(("Beacon set security failed \n"));
10201 /* Set BI and DTIM period */
10202 if (info
->interval
) {
10203 if ((err
= wldev_ioctl_set(dev
, WLC_SET_BCNPRD
,
10204 &info
->interval
, sizeof(s32
))) < 0) {
10205 WL_ERR(("Beacon Interval Set Error, %d\n", err
));
10209 if (info
->dtim_period
) {
10210 if ((err
= wldev_ioctl_set(dev
, WLC_SET_DTIMPRD
,
10211 &info
->dtim_period
, sizeof(s32
))) < 0) {
10212 WL_ERR(("DTIM Interval Set Error, %d\n", err
));
10217 /* If bss is already up, skip bring up */
10219 (err
= wl_cfg80211_bcn_bringup_ap(dev
, &ies
, dev_role
, bssidx
)) < 0)
10221 WL_ERR(("Beacon bring up AP/GO failed \n"));
10225 /* Set GC/STA SCB expiry timings. */
10226 if ((err
= wl_cfg80211_set_scb_timings(cfg
, dev
))) {
10227 WL_ERR(("scb setting failed \n"));
10231 if (wl_get_drv_status(cfg
, AP_CREATED
, dev
)) {
10232 /* Soft AP already running. Update changed params */
10233 if (wl_cfg80211_hostapd_sec(dev
, &ies
, bssidx
) < 0) {
10234 WL_ERR(("Hostapd update sec failed \n"));
10240 /* Enable Probe Req filter */
10241 if (((dev_role
== NL80211_IFTYPE_P2P_GO
) ||
10242 (dev_role
== NL80211_IFTYPE_AP
)) && (ies
.wps_ie
!= NULL
)) {
10243 wl_validate_wps_ie((char *) ies
.wps_ie
, ies
.wps_ie_len
, &pbc
);
10245 wl_add_remove_eventmsg(dev
, WLC_E_PROBREQ_MSG
, true);
10248 WL_DBG(("** ADD/SET beacon done **\n"));
10252 WL_ERR(("ADD/SET beacon failed\n"));
10253 if (dev_role
== NL80211_IFTYPE_AP
) {
10254 /* clear the AP mode */
10255 dhd
->op_mode
&= ~DHD_FLAG_HOSTAP_MODE
;
10263 wl_cfg80211_del_beacon(struct wiphy
*wiphy
, struct net_device
*dev
)
10268 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
10269 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10270 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
10272 WL_DBG(("Enter. \n"));
10275 WL_ERR(("wdev null \n"));
10279 if ((wdev
->iftype
!= NL80211_IFTYPE_P2P_GO
) && (wdev
->iftype
!= NL80211_IFTYPE_AP
)) {
10280 WL_ERR(("Unspported iface type iftype:%d \n", wdev
->iftype
));
10283 wl_clr_drv_status(cfg
, AP_CREATING
, dev
);
10284 wl_clr_drv_status(cfg
, AP_CREATED
, dev
);
10286 /* Clear AP/GO connected status */
10287 wl_clr_drv_status(cfg
, CONNECTED
, dev
);
10289 cfg
->ap_oper_channel
= 0;
10292 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
10293 WL_ERR(("find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
10298 if ((err
= wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 0)) < 0) {
10299 WL_ERR(("bss down error %d\n", err
));
10302 /* fall through is intentional */
10303 err
= wldev_ioctl_set(dev
, WLC_SET_INFRA
, &infra
, sizeof(s32
));
10305 WL_ERR(("SET INFRA error %d\n", err
));
10307 wl_cfg80211_clear_per_bss_ies(cfg
, bssidx
);
10309 if (wdev
->iftype
== NL80211_IFTYPE_AP
) {
10310 /* clear the AP mode */
10311 dhd
->op_mode
&= ~DHD_FLAG_HOSTAP_MODE
;
10318 #ifdef WL_SCHED_SCAN
10319 #define PNO_TIME 30
10320 #define PNO_REPEAT 4
10321 #define PNO_FREQ_EXPO_MAX 2
10323 is_ssid_in_list(struct cfg80211_ssid
*ssid
, struct cfg80211_ssid
*ssid_list
, int count
)
10327 if (!ssid
|| !ssid_list
)
10330 for (i
= 0; i
< count
; i
++) {
10331 if (ssid
->ssid_len
== ssid_list
[i
].ssid_len
) {
10332 if (strncmp(ssid
->ssid
, ssid_list
[i
].ssid
, ssid
->ssid_len
) == 0)
10340 wl_cfg80211_sched_scan_start(struct wiphy
*wiphy
,
10341 struct net_device
*dev
,
10342 struct cfg80211_sched_scan_request
*request
)
10344 ushort pno_time
= PNO_TIME
;
10345 int pno_repeat
= PNO_REPEAT
;
10346 int pno_freq_expo_max
= PNO_FREQ_EXPO_MAX
;
10347 wlc_ssid_ext_t ssids_local
[MAX_PFN_LIST_COUNT
];
10348 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10349 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
10350 struct cfg80211_ssid
*ssid
= NULL
;
10351 struct cfg80211_ssid
*hidden_ssid_list
= NULL
;
10352 log_conn_event_t
*event_data
= NULL
;
10353 tlv_log
*tlv_data
= NULL
;
10354 u32 alloc_len
, tlv_len
;
10359 unsigned long flags
;
10362 WL_ERR(("Sched scan request was NULL\n"));
10366 WL_DBG(("Enter \n"));
10367 WL_PNO((">>> SCHED SCAN START\n"));
10368 WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
10369 request
->n_match_sets
, request
->n_ssids
));
10370 WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
10371 request
->n_ssids
, pno_time
, pno_repeat
, pno_freq_expo_max
));
10374 if (!request
->n_ssids
|| !request
->n_match_sets
) {
10375 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request
->n_ssids
));
10379 memset(&ssids_local
, 0, sizeof(ssids_local
));
10381 if (request
->n_ssids
> 0) {
10382 hidden_ssid_list
= request
->ssids
;
10385 if (DBG_RING_ACTIVE(dhdp
, DHD_EVENT_RING_ID
)) {
10386 alloc_len
= sizeof(log_conn_event_t
) + DOT11_MAX_SSID_LEN
;
10387 event_data
= MALLOC(dhdp
->osh
, alloc_len
);
10389 WL_ERR(("%s: failed to allocate log_conn_event_t with "
10390 "length(%d)\n", __func__
, alloc_len
));
10393 memset(event_data
, 0, alloc_len
);
10394 event_data
->tlvs
= NULL
;
10395 tlv_len
= sizeof(tlv_log
);
10396 event_data
->tlvs
= (tlv_log
*)MALLOC(dhdp
->osh
, tlv_len
);
10397 if (!event_data
->tlvs
) {
10398 WL_ERR(("%s: failed to allocate log_tlv with "
10399 "length(%d)\n", __func__
, tlv_len
));
10400 MFREE(dhdp
->osh
, event_data
, alloc_len
);
10404 for (i
= 0; i
< request
->n_match_sets
&& ssid_cnt
< MAX_PFN_LIST_COUNT
; i
++) {
10405 ssid
= &request
->match_sets
[i
].ssid
;
10406 /* No need to include null ssid */
10407 if (ssid
->ssid_len
) {
10408 ssids_local
[ssid_cnt
].SSID_len
= MIN(ssid
->ssid_len
,
10409 (uint32
)DOT11_MAX_SSID_LEN
);
10410 memcpy(ssids_local
[ssid_cnt
].SSID
, ssid
->ssid
,
10411 ssids_local
[ssid_cnt
].SSID_len
);
10412 if (is_ssid_in_list(ssid
, hidden_ssid_list
, request
->n_ssids
)) {
10413 ssids_local
[ssid_cnt
].hidden
= TRUE
;
10414 WL_PNO((">>> PNO hidden SSID (%s) \n", ssid
->ssid
));
10416 ssids_local
[ssid_cnt
].hidden
= FALSE
;
10417 WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid
->ssid
));
10419 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0))
10420 if (request
->match_sets
[i
].rssi_thold
!= NL80211_SCAN_RSSI_THOLD_OFF
) {
10421 ssids_local
[ssid_cnt
].rssi_thresh
=
10422 (int8
)request
->match_sets
[i
].rssi_thold
;
10424 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0)) */
10430 if ((ret
= dhd_dev_pno_set_for_ssid(dev
, ssids_local
, ssid_cnt
,
10431 pno_time
, pno_repeat
, pno_freq_expo_max
, NULL
, 0)) < 0) {
10432 WL_ERR(("PNO setup failed!! ret=%d \n", ret
));
10437 if (DBG_RING_ACTIVE(dhdp
, DHD_EVENT_RING_ID
)) {
10438 for (i
= 0; i
< ssid_cnt
; i
++) {
10439 payload_len
= sizeof(log_conn_event_t
);
10440 event_data
->event
= WIFI_EVENT_DRIVER_PNO_ADD
;
10441 tlv_data
= event_data
->tlvs
;
10443 tlv_data
->tag
= WIFI_TAG_SSID
;
10444 tlv_data
->len
= ssids_local
[i
].SSID_len
;
10445 memcpy(tlv_data
->value
, ssids_local
[i
].SSID
,
10446 ssids_local
[i
].SSID_len
);
10447 payload_len
+= TLV_LOG_SIZE(tlv_data
);
10449 dhd_os_push_push_ring_data(dhdp
, DHD_EVENT_RING_ID
,
10450 event_data
, payload_len
);
10454 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
10455 cfg
->sched_scan_req
= request
;
10456 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
10462 MFREE(dhdp
->osh
, event_data
->tlvs
, tlv_len
);
10463 MFREE(dhdp
->osh
, event_data
, alloc_len
);
10469 wl_cfg80211_sched_scan_stop(struct wiphy
*wiphy
, struct net_device
*dev
10470 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
10472 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
10475 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10476 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
10477 unsigned long flags
;
10479 WL_DBG(("Enter \n"));
10480 WL_PNO((">>> SCHED SCAN STOP\n"));
10482 BCM_REFERENCE(dhdp
);
10483 if (dhd_dev_pno_stop_for_ssid(dev
) < 0) {
10484 WL_ERR(("PNO Stop for SSID failed"));
10486 DBG_EVENT_LOG(dhdp
, WIFI_EVENT_DRIVER_PNO_REMOVE
);
10489 if (cfg
->scan_request
&& cfg
->sched_scan_running
) {
10490 WL_PNO((">>> Sched scan running. Aborting it..\n"));
10491 wl_notify_escan_complete(cfg
, dev
, true, true);
10493 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
10494 cfg
->sched_scan_req
= NULL
;
10495 cfg
->sched_scan_running
= FALSE
;
10496 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
10499 #endif /* WL_SCHED_SCAN */
10501 #ifdef WL_SUPPORT_ACS
10503 * Currently the dump_obss IOVAR is returning string as output so we need to
10504 * parse the output buffer in an unoptimized way. Going forward if we get the
10505 * IOVAR output in binary format this method can be optimized
10507 static int wl_parse_dump_obss(char *buf
, struct wl_dump_survey
*survey
)
10511 char delim
[] = " \n";
10513 token
= strsep(&buf
, delim
);
10514 while (token
!= NULL
) {
10515 if (!strcmp(token
, "OBSS")) {
10516 for (i
= 0; i
< OBSS_TOKEN_IDX
; i
++)
10517 token
= strsep(&buf
, delim
);
10518 survey
->obss
= simple_strtoul(token
, NULL
, 10);
10521 if (!strcmp(token
, "IBSS")) {
10522 for (i
= 0; i
< IBSS_TOKEN_IDX
; i
++)
10523 token
= strsep(&buf
, delim
);
10524 survey
->ibss
= simple_strtoul(token
, NULL
, 10);
10527 if (!strcmp(token
, "TXDur")) {
10528 for (i
= 0; i
< TX_TOKEN_IDX
; i
++)
10529 token
= strsep(&buf
, delim
);
10530 survey
->tx
= simple_strtoul(token
, NULL
, 10);
10533 if (!strcmp(token
, "Category")) {
10534 for (i
= 0; i
< CTG_TOKEN_IDX
; i
++)
10535 token
= strsep(&buf
, delim
);
10536 survey
->no_ctg
= simple_strtoul(token
, NULL
, 10);
10539 if (!strcmp(token
, "Packet")) {
10540 for (i
= 0; i
< PKT_TOKEN_IDX
; i
++)
10541 token
= strsep(&buf
, delim
);
10542 survey
->no_pckt
= simple_strtoul(token
, NULL
, 10);
10545 if (!strcmp(token
, "Opp(time):")) {
10546 for (i
= 0; i
< IDLE_TOKEN_IDX
; i
++)
10547 token
= strsep(&buf
, delim
);
10548 survey
->idle
= simple_strtoul(token
, NULL
, 10);
10551 token
= strsep(&buf
, delim
);
10557 static int wl_dump_obss(struct net_device
*ndev
, cca_msrmnt_query req
,
10558 struct wl_dump_survey
*survey
)
10560 cca_stats_n_flags
*results
;
10564 buf
= kzalloc(sizeof(char) * WLC_IOCTL_MAXLEN
, GFP_KERNEL
);
10565 if (unlikely(!buf
)) {
10566 WL_ERR(("%s: buf alloc failed\n", __func__
));
10570 retry
= IOCTL_RETRY_COUNT
;
10572 err
= wldev_iovar_getbuf(ndev
, "dump_obss", &req
, sizeof(req
),
10573 buf
, WLC_IOCTL_MAXLEN
, NULL
);
10577 WL_DBG(("attempt = %d, err = %d, \n",
10578 (IOCTL_RETRY_COUNT
- retry
), err
));
10582 WL_ERR(("failure, dump_obss IOVAR failed\n"));
10587 results
= (cca_stats_n_flags
*)(buf
);
10588 wl_parse_dump_obss(results
->buf
, survey
);
10597 static int wl_cfg80211_dump_survey(struct wiphy
*wiphy
, struct net_device
*ndev
,
10598 int idx
, struct survey_info
*info
)
10600 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10601 struct wl_dump_survey
*survey
;
10602 struct ieee80211_supported_band
*band
;
10603 struct ieee80211_channel
*chan
;
10604 cca_msrmnt_query req
;
10605 int val
, err
, noise
, retry
;
10607 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
10608 if (!(dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
10611 band
= wiphy
->bands
[IEEE80211_BAND_2GHZ
];
10612 if (band
&& idx
>= band
->n_channels
) {
10613 idx
-= band
->n_channels
;
10617 if (!band
|| idx
>= band
->n_channels
) {
10618 /* Move to 5G band */
10619 band
= wiphy
->bands
[IEEE80211_BAND_5GHZ
];
10620 if (idx
>= band
->n_channels
) {
10625 chan
= &band
->channels
[idx
];
10626 /* Setting current channel to the requested channel */
10627 if ((err
= wl_cfg80211_set_channel(wiphy
, ndev
, chan
,
10628 NL80211_CHAN_HT20
) < 0)) {
10629 WL_ERR(("Set channel failed \n"));
10633 /* Set interface up, explicitly. */
10635 err
= wldev_ioctl_set(ndev
, WLC_UP
, (void *)&val
, sizeof(val
));
10637 WL_ERR(("set interface up failed, error = %d\n", err
));
10641 /* Get noise value */
10642 retry
= IOCTL_RETRY_COUNT
;
10645 err
= wldev_ioctl_get(ndev
, WLC_GET_PHY_NOISE
, &noise
,
10650 WL_DBG(("attempt = %d, err = %d, \n",
10651 (IOCTL_RETRY_COUNT
- retry
), err
));
10655 WL_ERR(("Get Phy Noise failed, error = %d\n", err
));
10656 noise
= CHAN_NOISE_DUMMY
;
10659 survey
= (struct wl_dump_survey
*) kzalloc(sizeof(struct wl_dump_survey
),
10661 if (unlikely(!survey
)) {
10662 WL_ERR(("%s: alloc failed\n", __func__
));
10666 /* Start Measurement for obss stats on current channel */
10667 req
.msrmnt_query
= 0;
10668 req
.time_req
= ACS_MSRMNT_DELAY
;
10669 if ((err
= wl_dump_obss(ndev
, req
, survey
)) < 0) {
10674 * Wait for the meaurement to complete, adding a buffer value of 10 to take
10675 * into consideration any delay in IOVAR completion
10677 msleep(ACS_MSRMNT_DELAY
+ 10);
10679 /* Issue IOVAR to collect measurement results */
10680 req
.msrmnt_query
= 1;
10681 if ((err
= wl_dump_obss(ndev
, req
, survey
)) < 0) {
10685 info
->channel
= chan
;
10686 info
->noise
= noise
;
10687 info
->channel_time
= ACS_MSRMNT_DELAY
;
10688 info
->channel_time_busy
= ACS_MSRMNT_DELAY
- survey
->idle
;
10689 info
->channel_time_rx
= survey
->obss
+ survey
->ibss
+ survey
->no_ctg
+
10691 info
->channel_time_tx
= survey
->tx
;
10692 info
->filled
= SURVEY_INFO_NOISE_DBM
|SURVEY_INFO_CHANNEL_TIME
|
10693 SURVEY_INFO_CHANNEL_TIME_BUSY
| SURVEY_INFO_CHANNEL_TIME_RX
|
10694 SURVEY_INFO_CHANNEL_TIME_TX
;
10702 #endif /* WL_SUPPORT_ACS */
10704 static struct cfg80211_ops wl_cfg80211_ops
= {
10705 .add_virtual_intf
= wl_cfg80211_add_virtual_iface
,
10706 .del_virtual_intf
= wl_cfg80211_del_virtual_iface
,
10707 .change_virtual_intf
= wl_cfg80211_change_virtual_iface
,
10708 #if defined(WL_CFG80211_P2P_DEV_IF)
10709 .start_p2p_device
= wl_cfgp2p_start_p2p_device
,
10710 .stop_p2p_device
= wl_cfgp2p_stop_p2p_device
,
10711 #endif /* WL_CFG80211_P2P_DEV_IF */
10712 .scan
= wl_cfg80211_scan
,
10713 .set_wiphy_params
= wl_cfg80211_set_wiphy_params
,
10714 .join_ibss
= wl_cfg80211_join_ibss
,
10715 .leave_ibss
= wl_cfg80211_leave_ibss
,
10716 .get_station
= wl_cfg80211_get_station
,
10717 .set_tx_power
= wl_cfg80211_set_tx_power
,
10718 .get_tx_power
= wl_cfg80211_get_tx_power
,
10719 .add_key
= wl_cfg80211_add_key
,
10720 .del_key
= wl_cfg80211_del_key
,
10721 .get_key
= wl_cfg80211_get_key
,
10722 .set_default_key
= wl_cfg80211_config_default_key
,
10723 .set_default_mgmt_key
= wl_cfg80211_config_default_mgmt_key
,
10724 .set_power_mgmt
= wl_cfg80211_set_power_mgmt
,
10725 .connect
= wl_cfg80211_connect
,
10726 .disconnect
= wl_cfg80211_disconnect
,
10727 .suspend
= wl_cfg80211_suspend
,
10728 .resume
= wl_cfg80211_resume
,
10729 .set_pmksa
= wl_cfg80211_set_pmksa
,
10730 .del_pmksa
= wl_cfg80211_del_pmksa
,
10731 .flush_pmksa
= wl_cfg80211_flush_pmksa
,
10732 .remain_on_channel
= wl_cfg80211_remain_on_channel
,
10733 .cancel_remain_on_channel
= wl_cfg80211_cancel_remain_on_channel
,
10734 .mgmt_tx
= wl_cfg80211_mgmt_tx
,
10735 .mgmt_frame_register
= wl_cfg80211_mgmt_frame_register
,
10736 .change_bss
= wl_cfg80211_change_bss
,
10737 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
10738 .set_channel
= wl_cfg80211_set_channel
,
10740 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
10741 .set_beacon
= wl_cfg80211_add_set_beacon
,
10742 .add_beacon
= wl_cfg80211_add_set_beacon
,
10743 .del_beacon
= wl_cfg80211_del_beacon
,
10745 .change_beacon
= wl_cfg80211_change_beacon
,
10746 .start_ap
= wl_cfg80211_start_ap
,
10747 .stop_ap
= wl_cfg80211_stop_ap
,
10749 #ifdef WL_SCHED_SCAN
10750 .sched_scan_start
= wl_cfg80211_sched_scan_start
,
10751 .sched_scan_stop
= wl_cfg80211_sched_scan_stop
,
10752 #endif /* WL_SCHED_SCAN */
10753 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
10755 .del_station
= wl_cfg80211_del_station
,
10756 .change_station
= wl_cfg80211_change_station
,
10757 .mgmt_tx_cancel_wait
= wl_cfg80211_mgmt_tx_cancel_wait
,
10758 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
10760 .join_mesh
= wl_cfg80211_join_mesh
,
10761 .leave_mesh
= wl_cfg80211_leave_mesh
,
10762 #endif /* WLMESH */
10763 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
10764 .tdls_mgmt
= wl_cfg80211_tdls_mgmt
,
10765 .tdls_oper
= wl_cfg80211_tdls_oper
,
10767 #ifdef WL_SUPPORT_ACS
10768 .dump_survey
= wl_cfg80211_dump_survey
,
10769 #endif /* WL_SUPPORT_ACS */
10770 #ifdef WL_CFG80211_ACL
10771 .set_mac_acl
= wl_cfg80211_set_mac_acl
,
10772 #endif /* WL_CFG80211_ACL */
10773 #ifdef GTK_OFFLOAD_SUPPORT
10774 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
10775 .set_rekey_data
= wl_cfg80211_set_rekey_data
,
10776 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
10777 #endif /* GTK_OFFLOAD_SUPPORT */
10780 s32
wl_mode_to_nl80211_iftype(s32 mode
)
10786 return NL80211_IFTYPE_STATION
;
10788 return NL80211_IFTYPE_ADHOC
;
10790 return NL80211_IFTYPE_AP
;
10793 return NL80211_IFTYPE_MESH_POINT
;
10796 return NL80211_IFTYPE_UNSPECIFIED
;
10802 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
10803 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
10804 #define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
10806 #define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
10807 #endif /* kernel version < 3.9.0 */
10810 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
10811 WL_CFG80211_REG_NOTIFIER()
10813 struct bcm_cfg80211
*cfg
= (struct bcm_cfg80211
*)wiphy_priv(wiphy
);
10817 if (!request
|| !cfg
) {
10818 WL_ERR(("Invalid arg\n"));
10819 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
10823 #endif /* kernel version < 3.10.11 */
10826 WL_DBG(("ccode: %c%c Initiator: %d\n",
10827 request
->alpha2
[0], request
->alpha2
[1], request
->initiator
));
10829 /* We support only REGDOM_SET_BY_USER as of now */
10830 if ((request
->initiator
!= NL80211_REGDOM_SET_BY_USER
) &&
10831 (request
->initiator
!= NL80211_REGDOM_SET_BY_COUNTRY_IE
)) {
10832 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
10833 request
->initiator
));
10834 /* in case of no supported country by regdb
10835 lets driver setup platform default Locale
10839 WL_ERR(("Set country code %c%c from %s\n",
10840 request
->alpha2
[0], request
->alpha2
[1],
10841 ((request
->initiator
== NL80211_REGDOM_SET_BY_COUNTRY_IE
) ? " 11d AP" : "User")));
10843 if ((ret
= wldev_set_country(bcmcfg_to_prmry_ndev(cfg
), request
->alpha2
,
10844 false, (request
->initiator
== NL80211_REGDOM_SET_BY_USER
? true : false),
10846 WL_ERR(("set country Failed :%d\n", ret
));
10849 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
10853 #endif /* kernel version < 3.10.11 */
10855 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
10858 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
10859 static const struct wiphy_wowlan_support brcm_wowlan_support
= {
10860 .flags
= WIPHY_WOWLAN_ANY
,
10861 .n_patterns
= WL_WOWLAN_MAX_PATTERNS
,
10862 .pattern_min_len
= WL_WOWLAN_MIN_PATTERN_LEN
,
10863 .pattern_max_len
= WL_WOWLAN_MAX_PATTERN_LEN
,
10864 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
10865 .max_pkt_offset
= WL_WOWLAN_MAX_PATTERN_LEN
,
10866 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
10868 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
10869 #endif /* CONFIG_PM */
10871 static s32
wl_setup_wiphy(struct wireless_dev
*wdev
, struct device
*sdiofunc_dev
, dhd_pub_t
*context
)
10875 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10876 struct cfg80211_wowlan
*brcm_wowlan_config
= NULL
;
10877 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
10878 #endif /* CONFIG_PM */
10880 //#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
10881 dhd_pub_t
*dhd
= (dhd_pub_t
*)context
;
10882 BCM_REFERENCE(dhd
);
10885 WL_ERR(("DHD is NULL!!"));
10892 wiphy_new(&wl_cfg80211_ops
, sizeof(struct bcm_cfg80211
));
10893 if (unlikely(!wdev
->wiphy
)) {
10894 WL_ERR(("Couldn not allocate wiphy device\n"));
10898 set_wiphy_dev(wdev
->wiphy
, sdiofunc_dev
);
10899 wdev
->wiphy
->max_scan_ie_len
= WL_SCAN_IE_LEN_MAX
;
10900 /* Report how many SSIDs Driver can support per Scan request */
10901 wdev
->wiphy
->max_scan_ssids
= WL_SCAN_PARAMS_SSID_MAX
;
10902 wdev
->wiphy
->max_num_pmkids
= WL_NUM_PMKIDS_MAX
;
10903 #ifdef WL_SCHED_SCAN
10904 wdev
->wiphy
->max_sched_scan_ssids
= MAX_PFN_LIST_COUNT
;
10905 wdev
->wiphy
->max_match_sets
= MAX_PFN_LIST_COUNT
;
10906 wdev
->wiphy
->max_sched_scan_ie_len
= WL_SCAN_IE_LEN_MAX
;
10907 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
10908 wdev
->wiphy
->max_sched_scan_plan_interval
= PNO_SCAN_MAX_FW_SEC
;
10910 wdev
->wiphy
->flags
|= WIPHY_FLAG_SUPPORTS_SCHED_SCAN
;
10911 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
10912 #endif /* WL_SCHED_SCAN */
10914 wdev
->wiphy
->flags
|= WIPHY_FLAG_MESH_AUTH
;
10916 wdev
->wiphy
->interface_modes
=
10917 BIT(NL80211_IFTYPE_STATION
)
10918 | BIT(NL80211_IFTYPE_ADHOC
)
10919 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
10920 | BIT(NL80211_IFTYPE_MONITOR
)
10921 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
10922 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
10923 | BIT(NL80211_IFTYPE_P2P_CLIENT
)
10924 | BIT(NL80211_IFTYPE_P2P_GO
)
10925 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
10926 #if defined(WL_CFG80211_P2P_DEV_IF)
10927 | BIT(NL80211_IFTYPE_P2P_DEVICE
)
10928 #endif /* WL_CFG80211_P2P_DEV_IF */
10930 | BIT(NL80211_IFTYPE_MESH_POINT
)
10931 #endif /* WLMESH */
10932 | BIT(NL80211_IFTYPE_AP
);
10934 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
10935 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
10936 WL_DBG(("Setting interface combinations for common mode\n"));
10937 wdev
->wiphy
->iface_combinations
= common_iface_combinations
;
10938 wdev
->wiphy
->n_iface_combinations
=
10939 ARRAY_SIZE(common_iface_combinations
);
10940 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
10942 wdev
->wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &__wl_band_2ghz
;
10944 wdev
->wiphy
->signal_type
= CFG80211_SIGNAL_TYPE_MBM
;
10945 wdev
->wiphy
->cipher_suites
= __wl_cipher_suites
;
10946 wdev
->wiphy
->n_cipher_suites
= ARRAY_SIZE(__wl_cipher_suites
);
10947 wdev
->wiphy
->max_remain_on_channel_duration
= 5000;
10948 wdev
->wiphy
->mgmt_stypes
= wl_cfg80211_default_mgmt_stypes
;
10949 #ifndef WL_POWERSAVE_DISABLED
10950 wdev
->wiphy
->flags
|= WIPHY_FLAG_PS_ON_BY_DEFAULT
;
10952 wdev
->wiphy
->flags
&= ~WIPHY_FLAG_PS_ON_BY_DEFAULT
;
10953 #endif /* !WL_POWERSAVE_DISABLED */
10954 wdev
->wiphy
->flags
|= WIPHY_FLAG_NETNS_OK
|
10955 WIPHY_FLAG_4ADDR_AP
|
10956 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
10957 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS
|
10959 WIPHY_FLAG_4ADDR_STATION
;
10960 #if ((defined(ROAM_ENABLE) || defined(BCMFW_ROAM_ENABLE)) && (LINUX_VERSION_CODE >= \
10961 KERNEL_VERSION(3, 2, 0)))
10963 * If FW ROAM flag is advertised, upper layer wouldn't provide
10964 * the bssid & freq in the connect command. This will result a
10965 * delay in initial connection time due to firmware doing a full
10966 * channel scan to figure out the channel & bssid. However kernel
10967 * ver >= 3.15, provides bssid_hint & freq_hint and hence kernel
10968 * ver >= 3.15 won't have any issue. So if this flags need to be
10969 * advertised for kernel < 3.15, suggest to use RCC along with it
10970 * to avoid the initial connection delay.
10972 wdev
->wiphy
->flags
|= WIPHY_FLAG_SUPPORTS_FW_ROAM
;
10974 #ifdef UNSET_FW_ROAM_WIPHY_FLAG
10975 wdev
->wiphy
->flags
&= ~WIPHY_FLAG_SUPPORTS_FW_ROAM
;
10976 #endif /* UNSET_FW_ROAM_WIPHY_FLAG */
10977 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
10978 wdev
->wiphy
->flags
|= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
|
10979 WIPHY_FLAG_OFFCHAN_TX
;
10981 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
10983 /* From 3.4 kernel ownards AP_SME flag can be advertised
10984 * to remove the patch from supplicant
10986 wdev
->wiphy
->flags
|= WIPHY_FLAG_HAVE_AP_SME
;
10988 #ifdef WL_CFG80211_ACL
10989 /* Configure ACL capabilities. */
10990 wdev
->wiphy
->max_acl_mac_addrs
= MAX_NUM_MAC_FILT
;
10993 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
10994 /* Supplicant distinguish between the SoftAP mode and other
10995 * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
10996 * response frame from Supplicant MR1 and Kernel 3.4.0 or
10997 * later version. To add Vendor specific IE into the
10998 * probe response frame in case of SoftAP mode,
10999 * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
11001 if (dhd_get_fw_mode(dhd
->info
) == DHD_FLAG_HOSTAP_MODE
) {
11002 wdev
->wiphy
->flags
|= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
;
11003 wdev
->wiphy
->probe_resp_offload
= 0;
11006 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
11008 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
11009 wdev
->wiphy
->flags
|= WIPHY_FLAG_SUPPORTS_TDLS
;
11012 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
11014 * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
11015 * disconnection of connected network before suspend. So a dummy wowlan
11016 * filter is configured for kernels linux-3.8 and above.
11019 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
11020 wdev
->wiphy
->wowlan
= &brcm_wowlan_support
;
11021 /* If this is not provided cfg stack will get disconnect
11024 brcm_wowlan_config
= kmalloc(sizeof(struct cfg80211_wowlan
), GFP_KERNEL
);
11025 if (brcm_wowlan_config
) {
11026 brcm_wowlan_config
->disconnect
= true;
11027 brcm_wowlan_config
->gtk_rekey_failure
= true;
11028 brcm_wowlan_config
->eap_identity_req
= true;
11029 brcm_wowlan_config
->four_way_handshake
= true;
11030 brcm_wowlan_config
->patterns
= NULL
;
11031 brcm_wowlan_config
->n_patterns
= 0;
11032 brcm_wowlan_config
->tcp
= NULL
;
11033 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
11034 brcm_wowlan_config
->nd_config
= NULL
;
11037 WL_ERR(("Can not allocate memory for brcm_wowlan_config,"
11038 " So wiphy->wowlan_config is set to NULL\n"));
11040 wdev
->wiphy
->wowlan_config
= brcm_wowlan_config
;
11042 wdev
->wiphy
->wowlan
.flags
= WIPHY_WOWLAN_ANY
;
11043 wdev
->wiphy
->wowlan
.n_patterns
= WL_WOWLAN_MAX_PATTERNS
;
11044 wdev
->wiphy
->wowlan
.pattern_min_len
= WL_WOWLAN_MIN_PATTERN_LEN
;
11045 wdev
->wiphy
->wowlan
.pattern_max_len
= WL_WOWLAN_MAX_PATTERN_LEN
;
11046 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
11047 wdev
->wiphy
->wowlan
.max_pkt_offset
= WL_WOWLAN_MAX_PATTERN_LEN
;
11048 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
11049 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
11050 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
11052 WL_DBG(("Registering custom regulatory)\n"));
11053 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
11054 wdev
->wiphy
->regulatory_flags
|= REGULATORY_CUSTOM_REG
;
11056 wdev
->wiphy
->flags
|= WIPHY_FLAG_CUSTOM_REGULATORY
;
11058 wiphy_apply_custom_regulatory(wdev
->wiphy
, &brcm_regdom
);
11060 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
11061 WL_ERR(("Registering Vendor80211\n"));
11062 err
= wl_cfgvendor_attach(wdev
->wiphy
, dhd
);
11063 if (unlikely(err
< 0)) {
11064 WL_ERR(("Couldn not attach vendor commands (%d)\n", err
));
11066 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
11068 /* Now we can register wiphy with cfg80211 module */
11069 err
= wiphy_register(wdev
->wiphy
);
11070 if (unlikely(err
< 0)) {
11071 WL_ERR(("Couldn not register wiphy device (%d)\n", err
));
11072 wiphy_free(wdev
->wiphy
);
11075 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
11076 KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
11077 wdev
->wiphy
->flags
&= ~WIPHY_FLAG_ENFORCE_COMBINATIONS
;
11083 static void wl_free_wdev(struct bcm_cfg80211
*cfg
)
11085 struct wireless_dev
*wdev
= cfg
->wdev
;
11086 struct wiphy
*wiphy
= NULL
;
11088 WL_ERR(("wdev is invalid\n"));
11092 wiphy
= wdev
->wiphy
;
11094 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
11095 wl_cfgvendor_detach(wdev
->wiphy
);
11096 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
11097 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
11098 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
11099 /* Reset wowlan & wowlan_config before Unregister to avoid Kernel Panic */
11100 WL_DBG(("wl_free_wdev Clearing wowlan Config \n"));
11101 wdev
->wiphy
->wowlan
= NULL
;
11102 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
11103 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
11104 wiphy_unregister(wdev
->wiphy
);
11105 wdev
->wiphy
->dev
.parent
= NULL
;
11106 wdev
->wiphy
= NULL
;
11109 wl_delete_all_netinfo(cfg
);
11113 /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
11114 * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
11118 static s32
wl_inform_bss(struct bcm_cfg80211
*cfg
)
11120 struct wl_scan_results
*bss_list
;
11121 struct wl_bss_info
*bi
= NULL
; /* must be initialized */
11124 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
11125 #if defined(RSSIAVG)
11128 #if defined(BSSCACHE)
11129 wl_bss_cache_t
*node
;
11132 bss_list
= cfg
->bss_list
;
11134 /* Free cache in p2p scanning*/
11135 if (p2p_is_on(cfg
) && p2p_scan(cfg
)) {
11136 #if defined(RSSIAVG)
11137 wl_free_rssi_cache(&cfg
->g_rssi_cache_ctrl
);
11139 #if defined(BSSCACHE)
11140 wl_free_bss_cache(&cfg
->g_bss_cache_ctrl
);
11144 /* Delete disconnected cache */
11145 #if defined(BSSCACHE)
11146 wl_delete_disconnected_bss_cache(&cfg
->g_bss_cache_ctrl
, (u8
*)&cfg
->disconnected_bssid
);
11147 #if defined(RSSIAVG)
11148 wl_delete_disconnected_rssi_cache(&cfg
->g_rssi_cache_ctrl
, (u8
*)&cfg
->disconnected_bssid
);
11150 if (cfg
->p2p_disconnected
== 0)
11151 memset(&cfg
->disconnected_bssid
, 0, ETHER_ADDR_LEN
);
11155 #if defined(RSSIAVG)
11156 wl_update_rssi_cache(&cfg
->g_rssi_cache_ctrl
, bss_list
);
11158 wl_update_connected_rssi_cache(ndev
, &cfg
->g_rssi_cache_ctrl
, &rssi
);
11160 #if defined(BSSCACHE)
11161 wl_update_bss_cache(&cfg
->g_bss_cache_ctrl
,
11162 #if defined(RSSIAVG)
11163 &cfg
->g_rssi_cache_ctrl
,
11168 /* delete dirty cache */
11169 #if defined(RSSIAVG)
11170 wl_delete_dirty_rssi_cache(&cfg
->g_rssi_cache_ctrl
);
11171 wl_reset_rssi_cache(&cfg
->g_rssi_cache_ctrl
);
11173 #if defined(BSSCACHE)
11174 wl_delete_dirty_bss_cache(&cfg
->g_bss_cache_ctrl
);
11175 wl_reset_bss_cache(&cfg
->g_bss_cache_ctrl
);
11178 #if defined(BSSCACHE)
11179 if (cfg
->p2p_disconnected
> 0) {
11180 // terence 20130703: Fix for wrong group_capab (timing issue)
11181 wl_delete_disconnected_bss_cache(&cfg
->g_bss_cache_ctrl
, (u8
*)&cfg
->disconnected_bssid
);
11182 #if defined(RSSIAVG)
11183 wl_delete_disconnected_rssi_cache(&cfg
->g_rssi_cache_ctrl
, (u8
*)&cfg
->disconnected_bssid
);
11186 WL_SCAN(("scanned AP count (%d)\n", bss_list
->count
));
11187 node
= cfg
->g_bss_cache_ctrl
.m_cache_head
;
11188 for (i
=0; node
&& i
<WL_AP_MAX
; i
++) {
11189 bi
= node
->results
.bss_info
;
11190 err
= wl_inform_single_bss(cfg
, bi
, false);
11193 if (cfg
->autochannel
)
11194 wl_ext_get_best_channel(ndev
, &cfg
->g_bss_cache_ctrl
, ioctl_version
,
11195 &cfg
->best_2g_ch
, &cfg
->best_5g_ch
);
11197 WL_SCAN(("scanned AP count (%d)\n", bss_list
->count
));
11199 bi
= next_bss(bss_list
, bi
);
11200 for_each_bss(bss_list
, bi
, i
) {
11201 if (cfg
->p2p_disconnected
> 0 && !memcmp(&bi
->BSSID
, &cfg
->disconnected_bssid
, ETHER_ADDR_LEN
))
11203 err
= wl_inform_single_bss(cfg
, bi
, false);
11206 if (cfg
->autochannel
)
11207 wl_ext_get_best_channel(ndev
, bss_list
, ioctl_version
,
11208 &cfg
->best_2g_ch
, &cfg
->best_5g_ch
);
11211 if (cfg
->p2p_disconnected
> 0) {
11212 // terence 20130703: Fix for wrong group_capab (timing issue)
11213 cfg
->p2p_disconnected
++;
11214 if (cfg
->p2p_disconnected
>= REPEATED_SCAN_RESULT_CNT
+1) {
11215 cfg
->p2p_disconnected
= 0;
11216 memset(&cfg
->disconnected_bssid
, 0, ETHER_ADDR_LEN
);
11223 static s32
wl_inform_single_bss(struct bcm_cfg80211
*cfg
, struct wl_bss_info
*bi
, bool roam
)
11225 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
11226 struct ieee80211_mgmt
*mgmt
;
11227 struct ieee80211_channel
*channel
;
11228 struct ieee80211_supported_band
*band
;
11229 struct wl_cfg80211_bss_info
*notif_bss_info
;
11230 struct wl_scan_req
*sr
= wl_to_sr(cfg
);
11231 struct beacon_proberesp
*beacon_proberesp
;
11232 struct cfg80211_bss
*cbss
= NULL
;
11233 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
11234 log_conn_event_t
*event_data
= NULL
;
11235 tlv_log
*tlv_data
= NULL
;
11236 u32 alloc_len
, tlv_len
;
11243 chanspec_t chanspec
;
11245 if (unlikely(dtoh32(bi
->length
) > WL_BSS_INFO_MAX
)) {
11246 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
11249 aflags
= (in_atomic()) ? GFP_ATOMIC
: GFP_KERNEL
;
11250 notif_bss_info
= kzalloc(sizeof(*notif_bss_info
) + sizeof(*mgmt
)
11251 - sizeof(u8
) + WL_BSS_INFO_MAX
, aflags
);
11252 if (unlikely(!notif_bss_info
)) {
11253 WL_ERR(("notif_bss_info alloc failed\n"));
11256 mgmt
= (struct ieee80211_mgmt
*)notif_bss_info
->frame_buf
;
11257 chanspec
= wl_chspec_driver_to_host(bi
->chanspec
);
11258 notif_bss_info
->channel
= wf_chspec_ctlchan(chanspec
);
11260 if (notif_bss_info
->channel
<= CH_MAX_2G_CHANNEL
)
11261 band
= wiphy
->bands
[IEEE80211_BAND_2GHZ
];
11263 band
= wiphy
->bands
[IEEE80211_BAND_5GHZ
];
11265 WL_ERR(("No valid band\n"));
11266 kfree(notif_bss_info
);
11269 notif_bss_info
->rssi
= dtoh16(bi
->RSSI
);
11270 #if defined(RSSIAVG)
11271 notif_bss_info
->rssi
= wl_get_avg_rssi(&cfg
->g_rssi_cache_ctrl
, &bi
->BSSID
);
11272 if (notif_bss_info
->rssi
== RSSI_MINVAL
)
11273 notif_bss_info
->rssi
= MIN(dtoh16(bi
->RSSI
), RSSI_MAXVAL
);
11275 #if defined(RSSIOFFSET)
11276 notif_bss_info
->rssi
= wl_update_rssi_offset(bcmcfg_to_prmry_ndev(cfg
), notif_bss_info
->rssi
);
11278 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
11279 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
11280 notif_bss_info
->rssi
= MIN(notif_bss_info
->rssi
, RSSI_MAXVAL
);
11282 memcpy(mgmt
->bssid
, &bi
->BSSID
, ETHER_ADDR_LEN
);
11283 mgmt_type
= cfg
->active_scan
?
11284 IEEE80211_STYPE_PROBE_RESP
: IEEE80211_STYPE_BEACON
;
11285 if (!memcmp(bi
->SSID
, sr
->ssid
.SSID
, bi
->SSID_len
)) {
11286 mgmt
->frame_control
= cpu_to_le16(IEEE80211_FTYPE_MGMT
| mgmt_type
);
11288 beacon_proberesp
= cfg
->active_scan
?
11289 (struct beacon_proberesp
*)&mgmt
->u
.probe_resp
:
11290 (struct beacon_proberesp
*)&mgmt
->u
.beacon
;
11291 beacon_proberesp
->timestamp
= 0;
11292 beacon_proberesp
->beacon_int
= cpu_to_le16(bi
->beacon_period
);
11293 beacon_proberesp
->capab_info
= cpu_to_le16(bi
->capability
);
11295 wl_update_hidden_ap_ie(bi
, ((u8
*) bi
) + bi
->ie_offset
, &bi
->ie_length
, roam
);
11296 wl_mrg_ie(cfg
, ((u8
*) bi
) + bi
->ie_offset
, bi
->ie_length
);
11297 wl_cp_ie(cfg
, beacon_proberesp
->variable
, WL_BSS_INFO_MAX
-
11298 offsetof(struct wl_cfg80211_bss_info
, frame_buf
));
11299 notif_bss_info
->frame_len
= offsetof(struct ieee80211_mgmt
,
11300 u
.beacon
.variable
) + wl_get_ielen(cfg
);
11301 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11302 freq
= ieee80211_channel_to_frequency(notif_bss_info
->channel
);
11305 freq
= ieee80211_channel_to_frequency(notif_bss_info
->channel
, band
->band
);
11308 WL_ERR(("Invalid channel, fail to change channel to freq\n"));
11309 kfree(notif_bss_info
);
11312 channel
= ieee80211_get_channel(wiphy
, freq
);
11313 WL_SCAN(("BSSID %pM, channel %2d(%2d %sMHz), rssi %3d, capa 0x04%x, mgmt_type %d, "
11314 "frame_len %d, SSID \"%s\"\n",
11315 &bi
->BSSID
, notif_bss_info
->channel
, CHSPEC_CHANNEL(chanspec
),
11316 CHSPEC_IS20(chanspec
)?"20":
11317 CHSPEC_IS40(chanspec
)?"40":
11318 CHSPEC_IS80(chanspec
)?"80":"160",
11319 notif_bss_info
->rssi
, mgmt
->u
.beacon
.capab_info
, mgmt_type
,
11320 notif_bss_info
->frame_len
, bi
->SSID
));
11321 if (unlikely(!channel
)) {
11322 WL_ERR(("ieee80211_get_channel error, freq=%d, channel=%d\n",
11323 freq
, notif_bss_info
->channel
));
11324 kfree(notif_bss_info
);
11328 signal
= notif_bss_info
->rssi
* 100;
11329 if (!mgmt
->u
.probe_resp
.timestamp
) {
11330 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
11331 struct timespec ts
;
11332 get_monotonic_boottime(&ts
);
11333 mgmt
->u
.probe_resp
.timestamp
= ((u64
)ts
.tv_sec
*1000000)
11334 + ts
.tv_nsec
/ 1000;
11337 do_gettimeofday(&tv
);
11338 mgmt
->u
.probe_resp
.timestamp
= ((u64
)tv
.tv_sec
*1000000)
11344 cbss
= cfg80211_inform_bss_frame(wiphy
, channel
, mgmt
,
11345 le16_to_cpu(notif_bss_info
->frame_len
), signal
, aflags
);
11346 if (unlikely(!cbss
)) {
11347 WL_ERR(("cfg80211_inform_bss_frame error\n"));
11352 CFG80211_PUT_BSS(wiphy
, cbss
);
11354 if (DBG_RING_ACTIVE(dhdp
, DHD_EVENT_RING_ID
) &&
11355 (cfg
->sched_scan_req
&& !cfg
->scan_request
)) {
11356 alloc_len
= sizeof(log_conn_event_t
) + IEEE80211_MAX_SSID_LEN
+ sizeof(uint16
) +
11358 event_data
= MALLOCZ(dhdp
->osh
, alloc_len
);
11360 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
11361 "length(%d)\n", __func__
, alloc_len
));
11364 tlv_len
= 3 * sizeof(tlv_log
);
11365 event_data
->tlvs
= MALLOC(dhdp
->osh
, tlv_len
);
11366 if (!event_data
->tlvs
) {
11367 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
11368 "length(%d)\n", __func__
, tlv_len
));
11372 payload_len
= sizeof(log_conn_event_t
);
11373 event_data
->event
= WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND
;
11374 tlv_data
= event_data
->tlvs
;
11377 tlv_data
->tag
= WIFI_TAG_SSID
;
11378 tlv_data
->len
= bi
->SSID_len
;
11379 memcpy(tlv_data
->value
, bi
->SSID
, bi
->SSID_len
);
11380 payload_len
+= TLV_LOG_SIZE(tlv_data
);
11381 tlv_data
= TLV_LOG_NEXT(tlv_data
);
11384 tlv_data
->tag
= WIFI_TAG_CHANNEL
;
11385 tlv_data
->len
= sizeof(uint16
);
11386 memcpy(tlv_data
->value
, ¬if_bss_info
->channel
, sizeof(uint16
));
11387 payload_len
+= TLV_LOG_SIZE(tlv_data
);
11388 tlv_data
= TLV_LOG_NEXT(tlv_data
);
11391 tlv_data
->tag
= WIFI_TAG_RSSI
;
11392 tlv_data
->len
= sizeof(int16
);
11393 memcpy(tlv_data
->value
, ¬if_bss_info
->rssi
, sizeof(int16
));
11394 payload_len
+= TLV_LOG_SIZE(tlv_data
);
11395 tlv_data
= TLV_LOG_NEXT(tlv_data
);
11397 dhd_os_push_push_ring_data(dhdp
, DHD_EVENT_RING_ID
,
11398 event_data
, payload_len
);
11399 MFREE(dhdp
->osh
, event_data
->tlvs
, tlv_len
);
11400 MFREE(dhdp
->osh
, event_data
, alloc_len
);
11404 kfree(notif_bss_info
);
11408 static bool wl_is_linkup(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
, struct net_device
*ndev
)
11410 u32 event
= ntoh32(e
->event_type
);
11411 u32 status
= ntoh32(e
->status
);
11412 u16 flags
= ntoh16(e
->flags
);
11413 #if defined(CUSTOM_SET_ANTNPM) || defined(CUSTOM_SET_OCLOFF)
11415 dhd
= (dhd_pub_t
*)(cfg
->pub
);
11416 #endif /* CUSTOM_SET_ANTNPM */
11418 WL_DBG(("event %d, status %d flags %x\n", event
, status
, flags
));
11419 if (event
== WLC_E_SET_SSID
) {
11420 if (status
== WLC_E_STATUS_SUCCESS
) {
11421 #ifdef CUSTOM_SET_ANTNPM
11422 if (dhd
->mimo_ant_set
) {
11425 WL_ERR(("[WIFI_SEC] mimo_ant_set = %d\n", dhd
->mimo_ant_set
));
11426 err
= wldev_iovar_setint(ndev
, "txchain", dhd
->mimo_ant_set
);
11428 WL_ERR(("[WIFI_SEC] Fail set txchain\n"));
11430 err
= wldev_iovar_setint(ndev
, "rxchain", dhd
->mimo_ant_set
);
11432 WL_ERR(("[WIFI_SEC] Fail set rxchain\n"));
11435 #endif /* CUSTOM_SET_ANTNPM */
11436 #ifdef CUSTOM_SET_OCLOFF
11437 if (dhd
->ocl_off
) {
11439 int ocl_enable
= 0;
11440 err
= wldev_iovar_setint(ndev
, "ocl_enable", ocl_enable
);
11442 WL_ERR(("[WIFI_SEC] %s: Set ocl_enable %d failed %d\n",
11443 __FUNCTION__
, ocl_enable
, err
));
11445 WL_ERR(("[WIFI_SEC] %s: Set ocl_enable %d succeeded %d\n",
11446 __FUNCTION__
, ocl_enable
, err
));
11449 #endif /* CUSTOM_SET_OCLOFF */
11450 if (!wl_is_ibssmode(cfg
, ndev
))
11453 } else if (event
== WLC_E_LINK
) {
11454 if (flags
& WLC_EVENT_MSG_LINK
)
11458 WL_DBG(("wl_is_linkup false\n"));
11463 static bool wl_is_linkdown(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
, void *data
)
11465 u32 event
= ntoh32(e
->event_type
);
11466 u16 flags
= ntoh16(e
->flags
);
11467 wl_last_event_t
*last_event
= (wl_last_event_t
*)data
;
11468 u32 len
= ntoh32(e
->datalen
);
11470 if (event
== WLC_E_DEAUTH_IND
||
11471 event
== WLC_E_DISASSOC_IND
||
11472 event
== WLC_E_DISASSOC
||
11473 event
== WLC_E_DEAUTH
) {
11474 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event
)));
11476 } else if (event
== WLC_E_LINK
) {
11477 if (!(flags
& WLC_EVENT_MSG_LINK
)) {
11478 if (last_event
&& len
> 0) {
11479 u32 current_time
= last_event
->current_time
;
11480 u32 timestamp
= last_event
->timestamp
;
11481 u32 event_type
= last_event
->event
.event_type
;
11482 u32 status
= last_event
->event
.status
;
11483 u32 reason
= last_event
->event
.reason
;
11485 WL_ERR(("Last roam event before disconnection : current_time %d,"
11486 " time %d, type %d, status %d, reason %d\n",
11487 current_time
, timestamp
, event_type
, status
, reason
));
11489 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event
)));
11497 static bool wl_is_linkdown(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
)
11499 u32 event
= ntoh32(e
->event_type
);
11500 u16 flags
= ntoh16(e
->flags
);
11502 if (event
== WLC_E_DEAUTH_IND
||
11503 event
== WLC_E_DISASSOC_IND
||
11504 event
== WLC_E_DISASSOC
||
11505 event
== WLC_E_DEAUTH
) {
11506 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event
)));
11508 } else if (event
== WLC_E_LINK
) {
11509 if (!(flags
& WLC_EVENT_MSG_LINK
)) {
11510 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event
)));
11517 #endif /* WL_LASTEVT */
11519 static bool wl_is_nonetwork(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
)
11521 u32 event
= ntoh32(e
->event_type
);
11522 u32 status
= ntoh32(e
->status
);
11524 if (event
== WLC_E_LINK
&& status
== WLC_E_STATUS_NO_NETWORKS
)
11526 if (event
== WLC_E_SET_SSID
&& status
!= WLC_E_STATUS_SUCCESS
)
11532 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
11533 * to AP/P2P GO via events. If this change is backported to kernel for which
11534 * this driver is being built, then define WL_CFG80211_STA_EVENT. You
11535 * should use this new/del sta event mechanism for BRCM supplicant >= 22.
11538 wl_notify_connect_status_ap(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
11539 const wl_event_msg_t
*e
, void *data
)
11542 u32 event
= ntoh32(e
->event_type
);
11543 u32 reason
= ntoh32(e
->reason
);
11544 u32 len
= ntoh32(e
->datalen
);
11545 u32 status
= ntoh32(e
->status
);
11547 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
11548 bool isfree
= false;
11550 u8 bsscfgidx
= e
->bsscfgidx
;
11556 struct ieee80211_supported_band
*band
;
11557 struct ether_addr da
;
11558 struct ether_addr bssid
;
11559 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
11562 struct station_info sinfo
;
11565 WL_DBG(("event %d status %d reason %d\n", event
, ntoh32(e
->status
), reason
));
11566 /* if link down, bsscfg is disabled. */
11567 if (event
== WLC_E_LINK
&& reason
== WLC_E_LINK_BSSCFG_DIS
&&
11568 wl_get_p2p_status(cfg
, IF_DELETING
) && (ndev
!= bcmcfg_to_prmry_ndev(cfg
))) {
11569 wl_add_remove_eventmsg(ndev
, WLC_E_PROBREQ_MSG
, false);
11570 WL_INFORM(("AP mode link down !! \n"));
11571 complete(&cfg
->iface_disable
);
11575 if ((event
== WLC_E_LINK
) && (status
== WLC_E_STATUS_SUCCESS
) &&
11576 (reason
== WLC_E_REASON_INITIAL_ASSOC
) &&
11577 (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_AP
)) {
11578 if (!wl_get_drv_status(cfg
, AP_CREATED
, ndev
)) {
11579 /* AP/GO brought up successfull in firmware */
11580 printf("%s: ** AP/GO Link up event **\n", __FUNCTION__
);
11581 wl_set_drv_status(cfg
, AP_CREATED
, ndev
);
11582 wake_up_interruptible(&cfg
->netif_change_event
);
11583 if (!memcmp(ndev
->name
, WL_P2P_INTERFACE_PREFIX
, strlen(WL_P2P_INTERFACE_PREFIX
))) {
11584 dhd_conf_set_mchan_bw(cfg
->pub
, WL_P2P_IF_GO
, -1);
11590 if (event
== WLC_E_DISASSOC_IND
|| event
== WLC_E_DEAUTH_IND
|| event
== WLC_E_DEAUTH
) {
11591 printf("%s: event %s(%d) status %d reason %d\n", __FUNCTION__
,
11592 bcmevent_get_name(event
), event
, ntoh32(e
->status
), reason
);
11595 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
11596 WL_DBG(("Enter \n"));
11597 if (!len
&& (event
== WLC_E_DEAUTH
)) {
11598 len
= 2; /* reason code field */
11602 body
= kzalloc(len
, GFP_KERNEL
);
11604 if (body
== NULL
) {
11605 WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
11609 memset(&bssid
, 0, ETHER_ADDR_LEN
);
11610 WL_DBG(("Enter event %d ndev %p\n", event
, ndev
));
11611 if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_INVALID
) {
11616 memcpy(body
, data
, len
);
11618 wldev_iovar_getbuf_bsscfg(ndev
, "cur_etheraddr",
11619 NULL
, 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, bsscfgidx
, &cfg
->ioctl_buf_sync
);
11620 memcpy(da
.octet
, cfg
->ioctl_buf
, ETHER_ADDR_LEN
);
11621 memset(&bssid
, 0, sizeof(bssid
));
11622 err
= wldev_ioctl_get(ndev
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
);
11624 case WLC_E_ASSOC_IND
:
11627 case WLC_E_REASSOC_IND
:
11628 fc
= FC_REASSOC_REQ
;
11630 case WLC_E_DISASSOC_IND
:
11633 case WLC_E_DEAUTH_IND
:
11643 memset(&ci
, 0, sizeof(ci
));
11644 if ((err
= wldev_ioctl_get(ndev
, WLC_GET_CHANNEL
, &ci
, sizeof(ci
)))) {
11649 channel
= dtoh32(ci
.hw_channel
);
11650 if (channel
<= CH_MAX_2G_CHANNEL
)
11651 band
= wiphy
->bands
[IEEE80211_BAND_2GHZ
];
11653 band
= wiphy
->bands
[IEEE80211_BAND_5GHZ
];
11655 WL_ERR(("No valid band\n"));
11660 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11661 freq
= ieee80211_channel_to_frequency(channel
);
11664 freq
= ieee80211_channel_to_frequency(channel
, band
->band
);
11667 err
= wl_frame_get_mgmt(fc
, &da
, &e
->addr
, &bssid
,
11668 &mgmt_frame
, &len
, body
);
11673 if ((event
== WLC_E_ASSOC_IND
&& reason
== DOT11_SC_SUCCESS
) ||
11674 (event
== WLC_E_DISASSOC_IND
) ||
11675 ((event
== WLC_E_DEAUTH_IND
) || (event
== WLC_E_DEAUTH
))) {
11676 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
11677 cfg80211_rx_mgmt(ndev
, freq
, 0, mgmt_frame
, len
, 0);
11678 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
11679 cfg80211_rx_mgmt(ndev
, freq
, 0, mgmt_frame
, len
, 0, GFP_ATOMIC
);
11680 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
11681 defined(WL_COMPAT_WIRELESS)
11682 cfg80211_rx_mgmt(ndev
, freq
, 0, mgmt_frame
, len
, GFP_ATOMIC
);
11684 cfg80211_rx_mgmt(ndev
, freq
, mgmt_frame
, len
, GFP_ATOMIC
);
11693 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
11695 if (((event
== WLC_E_ASSOC_IND
) || (event
== WLC_E_REASSOC_IND
)) &&
11696 reason
== DOT11_SC_SUCCESS
) {
11697 /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
11698 * STATION_INFO_ASSOC_REQ_IES flag
11700 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
11701 sinfo
.filled
= STA_INFO_BIT(INFO_ASSOC_REQ_IES
);
11702 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
11704 WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
11707 sinfo
.assoc_req_ies
= data
;
11708 sinfo
.assoc_req_ies_len
= len
;
11709 printf("%s: connected device "MACDBG
"\n", __FUNCTION__
, MAC2STRDBG(e
->addr
.octet
));
11710 wl_cfg80211_check_in4way(cfg
, ndev
, DONT_DELETE_GC_AFTER_WPS
,
11711 WL_EXT_STATUS_GC_CONNECTED
, NULL
);
11712 cfg80211_new_sta(ndev
, e
->addr
.octet
, &sinfo
, GFP_ATOMIC
);
11713 } else if (event
== WLC_E_DISASSOC_IND
) {
11714 printf("%s: disassociated device "MACDBG
"\n", __FUNCTION__
, MAC2STRDBG(e
->addr
.octet
));
11715 wl_cfg80211_check_in4way(cfg
, ndev
, DONT_DELETE_GC_AFTER_WPS
,
11716 WL_EXT_STATUS_GC_DISCONNECTED
, NULL
);
11717 cfg80211_del_sta(ndev
, e
->addr
.octet
, GFP_ATOMIC
);
11718 } else if ((event
== WLC_E_DEAUTH_IND
) ||
11719 ((event
== WLC_E_DEAUTH
) && (reason
!= DOT11_RC_RESERVED
))) {
11720 printf("%s: deauthenticated device "MACDBG
"\n", __FUNCTION__
, MAC2STRDBG(e
->addr
.octet
));
11721 wl_cfg80211_check_in4way(cfg
, ndev
, DONT_DELETE_GC_AFTER_WPS
,
11722 WL_EXT_STATUS_GC_DISCONNECTED
, NULL
);
11723 cfg80211_del_sta(ndev
, e
->addr
.octet
, GFP_ATOMIC
);
11729 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11730 #define MAX_ASSOC_REJECT_ERR_STATUS 5
11731 int wl_get_connect_failed_status(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
)
11733 u32 status
= ntoh32(e
->status
);
11735 cfg
->assoc_reject_status
= 0;
11737 if (status
== WLC_E_STATUS_FAIL
) {
11738 WL_ERR(("auth assoc status event=%d e->status %d e->reason %d \n",
11739 ntoh32(cfg
->event_auth_assoc
.event_type
),
11740 (int)ntoh32(cfg
->event_auth_assoc
.status
),
11741 (int)ntoh32(cfg
->event_auth_assoc
.reason
)));
11743 switch ((int)ntoh32(cfg
->event_auth_assoc
.status
)) {
11744 case WLC_E_STATUS_NO_ACK
:
11745 cfg
->assoc_reject_status
= 1;
11747 case WLC_E_STATUS_FAIL
:
11748 cfg
->assoc_reject_status
= 2;
11750 case WLC_E_STATUS_UNSOLICITED
:
11751 cfg
->assoc_reject_status
= 3;
11753 case WLC_E_STATUS_TIMEOUT
:
11754 cfg
->assoc_reject_status
= 4;
11756 case WLC_E_STATUS_ABORT
:
11757 cfg
->assoc_reject_status
= 5;
11762 if (cfg
->assoc_reject_status
) {
11763 if (ntoh32(cfg
->event_auth_assoc
.event_type
) == WLC_E_ASSOC
) {
11764 cfg
->assoc_reject_status
+= MAX_ASSOC_REJECT_ERR_STATUS
;
11769 WL_ERR(("assoc_reject_status %d \n", cfg
->assoc_reject_status
));
11774 s32
wl_cfg80211_get_connect_failed_status(struct net_device
*dev
, char* cmd
, int total_len
)
11776 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
11777 int bytes_written
= 0;
11783 memset(cmd
, 0, total_len
);
11784 bytes_written
= snprintf(cmd
, 30, "assoc_reject.status %d", cfg
->assoc_reject_status
);
11786 WL_ERR(("cmd: %s \n", cmd
));
11788 return bytes_written
;
11790 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
11793 wl_get_auth_assoc_status(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
11794 const wl_event_msg_t
*e
)
11796 u32 reason
= ntoh32(e
->reason
);
11797 u32 event
= ntoh32(e
->event_type
);
11798 struct wl_security
*sec
= wl_read_prof(cfg
, ndev
, WL_PROF_SEC
);
11799 WL_DBG(("event type : %d, reason : %d\n", event
, reason
));
11801 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11802 memcpy(&cfg
->event_auth_assoc
, e
, sizeof(wl_event_msg_t
));
11803 WL_ERR(("event=%d status %d reason %d \n",
11804 ntoh32(cfg
->event_auth_assoc
.event_type
),
11805 ntoh32(cfg
->event_auth_assoc
.status
),
11806 ntoh32(cfg
->event_auth_assoc
.reason
)));
11807 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
11812 sec
->auth_assoc_res_status
= reason
;
11817 WL_ERR(("sec is NULL\n"));
11822 wl_notify_connect_status_ibss(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
11823 const wl_event_msg_t
*e
, void *data
)
11826 u32 event
= ntoh32(e
->event_type
);
11827 u16 flags
= ntoh16(e
->flags
);
11828 u32 status
= ntoh32(e
->status
);
11830 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11831 struct ieee80211_channel
*channel
= NULL
;
11832 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
11833 u32 chanspec
, chan
;
11835 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
11837 if (event
== WLC_E_JOIN
) {
11838 WL_DBG(("joined in IBSS network\n"));
11840 if (event
== WLC_E_START
) {
11841 WL_DBG(("started IBSS network\n"));
11843 if (event
== WLC_E_JOIN
|| event
== WLC_E_START
||
11844 (event
== WLC_E_LINK
&& (flags
== WLC_EVENT_MSG_LINK
))) {
11845 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11846 err
= wldev_iovar_getint(ndev
, "chanspec", (s32
*)&chanspec
);
11847 if (unlikely(err
)) {
11848 WL_ERR(("Could not get chanspec %d\n", err
));
11851 chan
= wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec
));
11852 band
= (chan
<= CH_MAX_2G_CHANNEL
) ? IEEE80211_BAND_2GHZ
: IEEE80211_BAND_5GHZ
;
11853 freq
= ieee80211_channel_to_frequency(chan
, band
);
11854 channel
= ieee80211_get_channel(wiphy
, freq
);
11855 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
11856 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
11857 /* ROAM or Redundant */
11858 u8
*cur_bssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
11859 if (memcmp(cur_bssid
, &e
->addr
, ETHER_ADDR_LEN
) == 0) {
11860 WL_DBG(("IBSS connected event from same BSSID("
11861 MACDBG
"), ignore it\n", MAC2STRDBG(cur_bssid
)));
11864 WL_INFORM(("IBSS BSSID is changed from " MACDBG
" to " MACDBG
"\n",
11865 MAC2STRDBG(cur_bssid
), MAC2STRDBG((const u8
*)&e
->addr
)));
11866 wl_get_assoc_ies(cfg
, ndev
);
11867 wl_update_prof(cfg
, ndev
, NULL
, (const void *)&e
->addr
, WL_PROF_BSSID
);
11868 wl_update_bss_info(cfg
, ndev
, false);
11869 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11870 cfg80211_ibss_joined(ndev
, (const s8
*)&e
->addr
, channel
, GFP_KERNEL
);
11872 cfg80211_ibss_joined(ndev
, (const s8
*)&e
->addr
, GFP_KERNEL
);
11876 /* New connection */
11877 WL_INFORM(("IBSS connected to " MACDBG
"\n",
11878 MAC2STRDBG((const u8
*)&e
->addr
)));
11880 wl_get_assoc_ies(cfg
, ndev
);
11881 wl_update_prof(cfg
, ndev
, NULL
, (const void *)&e
->addr
, WL_PROF_BSSID
);
11882 wl_update_bss_info(cfg
, ndev
, false);
11883 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11884 cfg80211_ibss_joined(ndev
, (const s8
*)&e
->addr
, channel
, GFP_KERNEL
);
11886 cfg80211_ibss_joined(ndev
, (const s8
*)&e
->addr
, GFP_KERNEL
);
11888 wl_set_drv_status(cfg
, CONNECTED
, ndev
);
11890 wl_update_prof(cfg
, ndev
, NULL
, (const void *)&active
, WL_PROF_ACT
);
11892 } else if ((event
== WLC_E_LINK
&& !(flags
& WLC_EVENT_MSG_LINK
)) ||
11893 event
== WLC_E_DEAUTH_IND
|| event
== WLC_E_DISASSOC_IND
) {
11894 wl_clr_drv_status(cfg
, CONNECTED
, ndev
);
11896 wl_init_prof(cfg
, ndev
);
11898 else if (event
== WLC_E_SET_SSID
&& status
== WLC_E_STATUS_NO_NETWORKS
) {
11899 WL_DBG(("no action - join fail (IBSS mode)\n"));
11902 WL_DBG(("no action (IBSS mode)\n"));
11907 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11908 #define WiFiALL_OUI "\x50\x6F\x9A" /* Wi-FiAll OUI */
11909 #define WiFiALL_OUI_LEN 3
11910 #define WiFiALL_OUI_TYPE 16
11912 int wl_get_bss_info(struct bcm_cfg80211
*cfg
, struct net_device
*dev
, uint8
*mac
)
11915 struct wl_bss_info
*bi
;
11916 uint8 eabuf
[ETHER_ADDR_LEN
];
11917 u32 rate
, channel
, freq
, supported_rate
, nss
= 0, mcs_map
, mode_80211
= 0;
11921 struct wiphy
*wiphy
;
11922 struct cfg80211_bss
*bss
;
11923 bcm_tlv_t
*interworking_ie
= NULL
;
11924 bcm_tlv_t
*tlv_ie
= NULL
;
11925 bcm_tlv_t
*vht_ie
= NULL
;
11927 int16 ie_11u_rel_num
= -1, ie_mu_mimo_cap
= -1;
11928 u32 i
, remained_len
, count
= 0;
11929 char roam_count_str
[4], akm_str
[4];
11932 /* get BSS information */
11934 strncpy(cfg
->bss_info
, "x x x x x x x x x x x x x", GET_BSS_INFO_LEN
);
11936 memset(cfg
->extra_buf
, 0, WL_EXTRA_BUF_MAX
);
11937 *(u32
*) cfg
->extra_buf
= htod32(WL_EXTRA_BUF_MAX
);
11939 err
= wldev_ioctl_get(dev
, WLC_GET_BSS_INFO
, cfg
->extra_buf
, WL_EXTRA_BUF_MAX
);
11940 if (unlikely(err
)) {
11941 WL_ERR(("Could not get bss info %d\n", err
));
11942 cfg
->roam_count
= 0;
11947 WL_ERR(("mac is null \n"));
11948 cfg
->roam_count
= 0;
11952 memcpy(eabuf
, mac
, ETHER_ADDR_LEN
);
11954 bi
= (struct wl_bss_info
*)(cfg
->extra_buf
+ 4);
11955 channel
= wf_chspec_ctlchan(bi
->chanspec
);
11957 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11958 freq
= ieee80211_channel_to_frequency(channel
);
11960 if (channel
> 14) {
11961 freq
= ieee80211_channel_to_frequency(channel
, IEEE80211_BAND_5GHZ
);
11963 freq
= ieee80211_channel_to_frequency(channel
, IEEE80211_BAND_2GHZ
);
11967 err
= wldev_ioctl_get(dev
, WLC_GET_RATE
, &rate
, sizeof(rate
));
11969 WL_ERR(("Could not get rate (%d)\n", err
));
11970 snprintf(rate_str
, sizeof(rate_str
), "x"); // Unknown
11973 rate
= dtoh32(rate
);
11974 snprintf(rate_str
, sizeof(rate_str
), "%d", (rate
/2));
11977 //supported maximum rate
11978 supported_rate
= (bi
->rateset
.rates
[bi
->rateset
.count
- 1] & 0x7f) / 2;
11980 if (supported_rate
< 12) {
11981 mode_80211
= 0; //11b maximum rate is 11Mbps. 11b mode
11983 //It's not HT Capable case.
11984 if (channel
> 14) {
11985 mode_80211
= 3; // 11a mode
11987 mode_80211
= 1; // 11g mode
11992 /* check Rx MCS Map for HT */
11995 for (i
= 0; i
< MAX_STREAMS_SUPPORTED
; i
++) {
11996 int8 bitmap
= 0xFF;
11997 if (i
== MAX_STREAMS_SUPPORTED
-1) {
12000 if (bi
->basic_mcs
[i
] & bitmap
) {
12009 for (i
= 1; i
<= VHT_CAP_MCS_MAP_NSS_MAX
; i
++) {
12010 mcs_map
= VHT_MCS_MAP_GET_MCS_PER_SS(i
, dtoh16(bi
->vht_rxmcsmap
));
12011 if (mcs_map
!= VHT_CAP_MCS_MAP_NONE
) {
12021 wiphy
= bcmcfg_to_wiphy(cfg
);
12022 bss
= CFG80211_GET_BSS(wiphy
, NULL
, eabuf
, bi
->SSID
, bi
->SSID_len
);
12024 WL_ERR(("Could not find the AP\n"));
12026 #if defined(WL_CFG80211_P2P_DEV_IF)
12027 ie
= (u8
*)bss
->ies
->data
;
12028 ie_len
= bss
->ies
->len
;
12030 ie
= bss
->information_elements
;
12031 ie_len
= bss
->len_information_elements
;
12032 #endif /* WL_CFG80211_P2P_DEV_IF */
12036 ie_mu_mimo_cap
= 0;
12037 ie_11u_rel_num
= 0;
12040 if ((vht_ie
= bcm_parse_tlvs(ie
, (u32
)ie_len
,
12041 DOT11_MNG_VHT_CAP_ID
)) != NULL
) {
12042 ie_mu_mimo_cap
= (vht_ie
->data
[2] & 0x08) >> 3;
12046 if ((interworking_ie
= bcm_parse_tlvs(ie
, (u32
)ie_len
,
12047 DOT11_MNG_INTERWORKING_ID
)) != NULL
) {
12048 if ((tlv_ie
= bcm_parse_tlvs(ie
, (u32
)ie_len
, DOT11_MNG_VS_ID
)) != NULL
) {
12049 remained_len
= ie_len
;
12052 if (count
> MAX_VNDR_IE_NUMBER
)
12055 if (tlv_ie
->id
== DOT11_MNG_VS_ID
) {
12056 vndrie
= (vndr_ie_t
*) tlv_ie
;
12058 if (vndrie
->len
< (VNDR_IE_MIN_LEN
+ 1)) {
12059 WL_ERR(("%s: invalid vndr ie."
12060 "length is too small %d\n",
12061 __FUNCTION__
, vndrie
->len
));
12065 if (!bcmp(vndrie
->oui
,
12066 (u8
*)WiFiALL_OUI
, WiFiALL_OUI_LEN
) &&
12067 (vndrie
->data
[0] == WiFiALL_OUI_TYPE
))
12069 WL_ERR(("Found Wi-FiAll OUI oui.\n"));
12070 ie_11u_rel_num
= vndrie
->data
[1];
12071 ie_11u_rel_num
= (ie_11u_rel_num
& 0xf0)>>4;
12072 ie_11u_rel_num
+= 1;
12078 tlv_ie
= bcm_next_tlv(tlv_ie
, &remained_len
);
12084 for (i
= 0; i
< bi
->SSID_len
; i
++) {
12085 if (bi
->SSID
[i
] == ' ') {
12090 //0 : None, 1 : OKC, 2 : FT, 3 : CCKM
12091 err
= wldev_iovar_getint(dev
, "wpa_auth", &val
);
12092 if (unlikely(err
)) {
12093 WL_ERR(("could not get wpa_auth (%d)\n", err
));
12094 snprintf(akm_str
, sizeof(akm_str
), "x"); // Unknown
12096 WL_ERR(("wpa_auth val %d \n", val
));
12097 #if defined(BCMEXTCCX)
12098 if (val
& (WPA_AUTH_CCKM
| WPA2_AUTH_CCKM
)) {
12099 snprintf(akm_str
, sizeof(akm_str
), "3");
12102 if (val
& WPA2_AUTH_FT
) {
12103 snprintf(akm_str
, sizeof(akm_str
), "2");
12104 } else if (val
& (WPA_AUTH_UNSPECIFIED
| WPA2_AUTH_UNSPECIFIED
)) {
12105 snprintf(akm_str
, sizeof(akm_str
), "1");
12107 snprintf(akm_str
, sizeof(akm_str
), "0");
12111 if (cfg
->roam_offload
) {
12112 snprintf(roam_count_str
, sizeof(roam_count_str
), "x"); // Unknown
12114 snprintf(roam_count_str
, sizeof(roam_count_str
), "%d", cfg
->roam_count
);
12116 cfg
->roam_count
= 0;
12118 WL_ERR(("BSSID:" MACDBG
" SSID %s \n", MAC2STRDBG(eabuf
), bi
->SSID
));
12119 WL_ERR(("freq:%d, BW:%s, RSSI:%d dBm, Rate:%d Mbps, 11mode:%d, stream:%d,"
12120 "MU-MIMO:%d, Passpoint:%d, SNR:%d, Noise:%d, \n"
12121 "akm:%s roam:%s \n",
12122 freq
, wf_chspec_to_bw_str(bi
->chanspec
),
12123 dtoh32(bi
->RSSI
), (rate
/ 2), mode_80211
, nss
,
12124 ie_mu_mimo_cap
, ie_11u_rel_num
, bi
->SNR
, bi
->phy_noise
,
12125 akm_str
, roam_count_str
));
12128 snprintf(cfg
->bss_info
, GET_BSS_INFO_LEN
,
12129 "%02x:%02x:%02x %d %s %d %s %d %d %d %d %d %d %s %s",
12130 eabuf
[0], eabuf
[1], eabuf
[2],
12131 freq
, wf_chspec_to_bw_str(bi
->chanspec
),
12132 dtoh32(bi
->RSSI
), rate_str
, mode_80211
, nss
,
12133 ie_mu_mimo_cap
, ie_11u_rel_num
,
12134 bi
->SNR
, bi
->phy_noise
, akm_str
, roam_count_str
);
12136 //ie_mu_mimo_cap and ie_11u_rel_num is unknow.
12137 snprintf(cfg
->bss_info
, GET_BSS_INFO_LEN
,
12138 "%02x:%02x:%02x %d %s %d %s %d %d x x %d %d %s %s",
12139 eabuf
[0], eabuf
[1], eabuf
[2],
12140 freq
, wf_chspec_to_bw_str(bi
->chanspec
),
12141 dtoh32(bi
->RSSI
), rate_str
, mode_80211
, nss
,
12142 bi
->SNR
, bi
->phy_noise
, akm_str
, roam_count_str
);
12145 CFG80211_PUT_BSS(wiphy
, bss
);
12150 s32
wl_cfg80211_get_bss_info(struct net_device
*dev
, char* cmd
, int total_len
)
12152 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
12158 memset(cmd
, 0, total_len
);
12159 memcpy(cmd
, cfg
->bss_info
, GET_BSS_INFO_LEN
);
12161 WL_ERR(("cmd: %s \n", cmd
));
12163 return GET_BSS_INFO_LEN
;
12166 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12169 wl_notify_connect_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12170 const wl_event_msg_t
*e
, void *data
)
12173 struct net_device
*ndev
= NULL
;
12175 u32 event
= ntoh32(e
->event_type
);
12176 struct wiphy
*wiphy
= NULL
;
12177 struct cfg80211_bss
*bss
= NULL
;
12178 struct wlc_ssid
*ssid
= NULL
;
12181 int vndr_oui_num
= 0;
12182 char vndr_oui
[MAX_VNDR_OUI_STR_LEN
] = {0, };
12184 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12185 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
12186 BCM_REFERENCE(dhdp
);
12188 if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_AP
) {
12189 err
= wl_notify_connect_status_ap(cfg
, ndev
, e
, data
);
12190 } else if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_IBSS
) {
12191 err
= wl_notify_connect_status_ibss(cfg
, ndev
, e
, data
);
12192 } else if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_BSS
) {
12193 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
12194 ntoh32(e
->event_type
), ntoh32(e
->status
), ndev
));
12195 if (event
== WLC_E_ASSOC
|| event
== WLC_E_AUTH
) {
12196 wl_get_auth_assoc_status(cfg
, ndev
, e
);
12199 DHD_DISABLE_RUNTIME_PM((dhd_pub_t
*)cfg
->pub
);
12200 if (wl_is_linkup(cfg
, e
, ndev
)) {
12203 if (!wl_get_drv_status(cfg
, DISCONNECTING
, ndev
)) {
12204 if (event
== WLC_E_LINK
&&
12205 #ifdef DHD_LOSSLESS_ROAMING
12206 !cfg
->roam_offload
&&
12207 #endif /* DHD_LOSSLESS_ROAMING */
12208 wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
12209 wl_bss_roaming_done(cfg
, ndev
, e
, data
);
12212 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
12213 vndr_oui_num
= wl_vndr_ies_get_vendor_oui(cfg
,
12214 ndev
, vndr_oui
, ARRAYSIZE(vndr_oui
));
12215 #if defined(STAT_REPORT)
12216 /* notify STA connection only */
12217 wl_stat_report_notify_connected(cfg
);
12218 #endif /* STAT_REPORT */
12221 printf("wl_bss_connect_done succeeded with "
12222 MACDBG
" %s%s\n", MAC2STRDBG((const u8
*)(&e
->addr
)),
12223 vndr_oui_num
> 0 ? "vndr_oui: " : "",
12224 vndr_oui_num
> 0 ? vndr_oui
: "");
12226 wl_bss_connect_done(cfg
, ndev
, e
, data
, true);
12227 dhd_conf_set_intiovar(cfg
->pub
, WLC_SET_VAR
, "phy_oclscdenable", cfg
->pub
->conf
->phy_oclscdenable
, 0, FALSE
);
12228 WL_DBG(("joined in BSS network \"%s\"\n",
12229 ((struct wlc_ssid
*)
12230 wl_read_prof(cfg
, ndev
, WL_PROF_SSID
))->SSID
));
12233 if (ndev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_STATION
&&
12234 dhdp
->wbtext_support
&&
12235 event
== WLC_E_SET_SSID
) {
12236 /* set wnm_keepalives_max_idle after association */
12237 wl_cfg80211_wbtext_set_wnm_maxidle(cfg
, ndev
);
12238 /* send nbr request or BTM query to update RCC */
12239 wl_cfg80211_wbtext_update_rcc(cfg
, ndev
);
12241 #endif /* WBTEXT */
12243 wl_update_prof(cfg
, ndev
, e
, &act
, WL_PROF_ACT
);
12244 wl_update_prof(cfg
, ndev
, NULL
, (const void *)&e
->addr
, WL_PROF_BSSID
);
12245 dhd_conf_set_wme(cfg
->pub
, 0);
12246 if (!memcmp(ndev
->name
, WL_P2P_INTERFACE_PREFIX
, strlen(WL_P2P_INTERFACE_PREFIX
))) {
12247 dhd_conf_set_mchan_bw(cfg
->pub
, WL_P2P_IF_CLIENT
, -1);
12249 } else if (WL_IS_LINKDOWN(cfg
, e
, data
) ||
12250 ((event
== WLC_E_SET_SSID
) &&
12251 (ntoh32(e
->status
) != WLC_E_STATUS_SUCCESS
) &&
12252 (wl_get_drv_status(cfg
, CONNECTED
, ndev
)))) {
12254 WL_INFORM(("connection state bit status: [%d:%d:%d:%d]\n",
12255 wl_get_drv_status(cfg
, CONNECTING
, ndev
),
12256 wl_get_drv_status(cfg
, CONNECTED
, ndev
),
12257 wl_get_drv_status(cfg
, DISCONNECTING
, ndev
),
12258 wl_get_drv_status(cfg
, NESTED_CONNECT
, ndev
)));
12260 if (wl_get_drv_status(cfg
, DISCONNECTING
, ndev
) &&
12261 (wl_get_drv_status(cfg
, NESTED_CONNECT
, ndev
) ||
12262 wl_get_drv_status(cfg
, CONNECTING
, ndev
))) {
12263 /* wl_cfg80211_connect was called before 'DISCONNECTING' was
12264 * cleared. Deauth/Link down event is caused by WLC_DISASSOC
12265 * command issued from the wl_cfg80211_connect context. Ignore
12266 * the event to avoid pre-empting the current connection
12268 WL_INFORM(("Nested connection case. Drop event. \n"));
12269 wl_clr_drv_status(cfg
, NESTED_CONNECT
, ndev
);
12270 wl_clr_drv_status(cfg
, DISCONNECTING
, ndev
);
12271 /* Not in 'CONNECTED' state, clear it */
12272 wl_clr_drv_status(cfg
, CONNECTED
, ndev
);
12276 #ifdef DHD_LOSSLESS_ROAMING
12277 wl_del_roam_timeout(cfg
);
12279 #ifdef P2PLISTEN_AP_SAMECHN
12280 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
12281 wl_cfg80211_set_p2p_resp_ap_chn(ndev
, 0);
12282 cfg
->p2p_resp_apchn_status
= false;
12283 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
12285 #endif /* P2PLISTEN_AP_SAMECHN */
12286 wl_cfg80211_cancel_scan(cfg
);
12288 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
12289 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
12290 wl_get_bss_info(cfg
, ndev
, (u8
*)(&e
->addr
));
12292 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12293 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
12294 u8
*curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
12295 if (memcmp(curbssid
, &e
->addr
, ETHER_ADDR_LEN
) != 0) {
12296 bool fw_assoc_state
= TRUE
;
12297 dhd_pub_t
*dhd
= (dhd_pub_t
*)cfg
->pub
;
12298 fw_assoc_state
= dhd_is_associated(dhd
, e
->ifidx
, &err
);
12299 if (!fw_assoc_state
) {
12300 WL_ERR(("Event sends up even different BSSID"
12301 " cur: " MACDBG
" event: " MACDBG
"\n",
12302 MAC2STRDBG(curbssid
),
12303 MAC2STRDBG((const u8
*)(&e
->addr
))));
12305 WL_ERR(("BSSID of event is not the connected BSSID"
12306 "(ignore it) cur: " MACDBG
12307 " event: " MACDBG
"\n",
12308 MAC2STRDBG(curbssid
),
12309 MAC2STRDBG((const u8
*)(&e
->addr
))));
12314 /* Explicitly calling unlink to remove BSS in CFG */
12315 wiphy
= bcmcfg_to_wiphy(cfg
);
12316 ssid
= (struct wlc_ssid
*)wl_read_prof(cfg
, ndev
, WL_PROF_SSID
);
12317 bssid
= (u8
*)wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
12318 if (ssid
&& bssid
) {
12319 bss
= CFG80211_GET_BSS(wiphy
, NULL
, bssid
,
12320 ssid
->SSID
, ssid
->SSID_len
);
12322 cfg80211_unlink_bss(wiphy
, bss
);
12323 CFG80211_PUT_BSS(wiphy
, bss
);
12327 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
12329 u8
*curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
12331 struct ether_addr bssid_dongle
= {{0, 0, 0, 0, 0, 0}};
12332 struct ether_addr bssid_null
= {{0, 0, 0, 0, 0, 0}};
12334 if (event
== WLC_E_DEAUTH_IND
|| event
== WLC_E_DISASSOC_IND
)
12335 reason
= ntoh32(e
->reason
);
12336 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
12337 reason
= (reason
== WLAN_REASON_UNSPECIFIED
)? 0 : reason
;
12339 printf("link down if %s may call cfg80211_disconnected. "
12340 "event : %d, reason=%d from " MACDBG
"\n",
12341 ndev
->name
, event
, ntoh32(e
->reason
),
12342 MAC2STRDBG((const u8
*)(&e
->addr
)));
12343 wl_cfg80211_check_in4way(cfg
, ndev
, NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
,
12344 WL_EXT_STATUS_DISCONNECTED
, NULL
);
12346 /* roam offload does not sync BSSID always, get it from dongle */
12347 if (cfg
->roam_offload
) {
12348 memset(&bssid_dongle
, 0, sizeof(bssid_dongle
));
12349 if (wldev_ioctl_get(ndev
, WLC_GET_BSSID
, &bssid_dongle
,
12350 sizeof(bssid_dongle
)) == BCME_OK
) {
12351 /* if not roam case, it would return null bssid */
12352 if (memcmp(&bssid_dongle
, &bssid_null
,
12353 ETHER_ADDR_LEN
) != 0) {
12354 curbssid
= (u8
*)&bssid_dongle
;
12358 if (memcmp(curbssid
, &e
->addr
, ETHER_ADDR_LEN
) != 0) {
12359 bool fw_assoc_state
= TRUE
;
12360 dhd_pub_t
*dhd
= (dhd_pub_t
*)cfg
->pub
;
12361 fw_assoc_state
= dhd_is_associated(dhd
, e
->ifidx
, &err
);
12362 if (!fw_assoc_state
) {
12363 WL_ERR(("Event sends up even different BSSID"
12364 " cur: " MACDBG
" event: " MACDBG
"\n",
12365 MAC2STRDBG(curbssid
),
12366 MAC2STRDBG((const u8
*)(&e
->addr
))));
12368 WL_ERR(("BSSID of event is not the connected BSSID"
12369 "(ignore it) cur: " MACDBG
12370 " event: " MACDBG
"\n",
12371 MAC2STRDBG(curbssid
),
12372 MAC2STRDBG((const u8
*)(&e
->addr
))));
12378 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
12379 DHD_DBG_PKT_MON_STOP(dhdp
);
12381 #endif /* DBG_PKT_MON */
12383 /* clear RSSI monitor, framework will set new cfg */
12384 #ifdef RSSI_MONITOR_SUPPORT
12385 dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg
),
12387 #endif /* RSSI_MONITOR_SUPPORT */
12388 if (!memcmp(ndev
->name
, WL_P2P_INTERFACE_PREFIX
, strlen(WL_P2P_INTERFACE_PREFIX
))) {
12389 // terence 20130703: Fix for wrong group_capab (timing issue)
12390 cfg
->p2p_disconnected
= 1;
12392 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
12393 if (wl_get_drv_status(cfg
, DISCONNECTING
, ndev
)) {
12394 CFG80211_DISCONNECTED(ndev
, reason
, NULL
, 0, false, GFP_KERNEL
);
12397 memcpy(&cfg
->disconnected_bssid
, curbssid
, ETHER_ADDR_LEN
);
12398 wl_clr_drv_status(cfg
, CONNECTED
, ndev
);
12400 if (!wl_get_drv_status(cfg
, DISCONNECTING
, ndev
)) {
12401 /* To make sure disconnect, explictly send dissassoc
12402 * for BSSID 00:00:00:00:00:00 issue
12404 scbval
.val
= WLAN_REASON_DEAUTH_LEAVING
;
12406 memcpy(&scbval
.ea
, curbssid
, ETHER_ADDR_LEN
);
12407 scbval
.val
= htod32(scbval
.val
);
12408 err
= wldev_ioctl_set(ndev
, WLC_DISASSOC
, &scbval
,
12409 sizeof(scb_val_t
));
12411 WL_ERR(("WLC_DISASSOC error %d\n", err
));
12416 /* Send up deauth and clear states */
12417 CFG80211_DISCONNECTED(ndev
, reason
, NULL
, 0,
12418 false, GFP_KERNEL
);
12420 wl_init_prof(cfg
, ndev
);
12422 /* when STA was disconnected, clear join pref and set wbtext */
12423 if (ndev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_STATION
) {
12424 char smbuf
[WLC_IOCTL_SMLEN
];
12425 char clear
[] = { 0x01, 0x02, 0x00, 0x00, 0x03,
12426 0x02, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00 };
12427 if ((err
= wldev_iovar_setbuf(ndev
, "join_pref",
12428 clear
, sizeof(clear
), smbuf
,
12429 sizeof(smbuf
), NULL
))
12431 if ((err
= wldev_iovar_setint(ndev
,
12432 "wnm_bsstrans_resp",
12433 WL_BSSTRANS_POLICY_PRODUCT_WBTEXT
))
12435 wl_cfg80211_wbtext_set_default(ndev
);
12437 WL_ERR(("%s: Failed to set wbtext = %d\n",
12438 __FUNCTION__
, err
));
12441 WL_ERR(("%s: Failed to clear join pref = %d\n",
12442 __FUNCTION__
, err
));
12444 wl_cfg80211_wbtext_clear_bssid_list(cfg
);
12446 #endif /* WBTEXT */
12447 wl_vndr_ies_clear_vendor_oui_list(cfg
);
12449 else if (wl_get_drv_status(cfg
, CONNECTING
, ndev
)) {
12450 printf("link down, during connecting\n");
12451 wl_cfg80211_check_in4way(cfg
, ndev
, NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
,
12452 WL_EXT_STATUS_DISCONNECTED
, NULL
);
12453 /* Issue WLC_DISASSOC to prevent FW roam attempts */
12454 err
= wldev_ioctl_set(ndev
, WLC_DISASSOC
, NULL
, 0);
12456 WL_ERR(("CONNECTING state, WLC_DISASSOC error %d\n", err
));
12459 WL_INFORM(("Clear drv CONNECTING status\n"));
12460 wl_clr_drv_status(cfg
, CONNECTING
, ndev
);
12461 #ifdef ESCAN_RESULT_PATCH
12462 if ((memcmp(connect_req_bssid
, broad_bssid
, ETHER_ADDR_LEN
) == 0) ||
12463 (memcmp(&e
->addr
, broad_bssid
, ETHER_ADDR_LEN
) == 0) ||
12464 (memcmp(&e
->addr
, connect_req_bssid
, ETHER_ADDR_LEN
) == 0))
12465 /* In case this event comes while associating another AP */
12466 #endif /* ESCAN_RESULT_PATCH */
12467 wl_bss_connect_done(cfg
, ndev
, e
, data
, false);
12469 wl_clr_drv_status(cfg
, DISCONNECTING
, ndev
);
12471 /* if link down, bsscfg is diabled */
12472 if (ndev
!= bcmcfg_to_prmry_ndev(cfg
))
12473 complete(&cfg
->iface_disable
);
12475 /* re-enable TDLS if the number of connected interfaces
12478 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_DISCONNECT
, false);
12479 #endif /* WLTDLS */
12480 } else if (wl_is_nonetwork(cfg
, e
)) {
12481 printf("connect failed event=%d e->status %d e->reason %d \n",
12482 event
, (int)ntoh32(e
->status
), (int)ntoh32(e
->reason
));
12483 wl_cfg80211_check_in4way(cfg
, ndev
, NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
,
12484 WL_EXT_STATUS_DISCONNECTED
, NULL
);
12485 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
12486 if (event
== WLC_E_SET_SSID
) {
12487 wl_get_connect_failed_status(cfg
, e
);
12489 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12491 if (wl_get_drv_status(cfg
, DISCONNECTING
, ndev
) &&
12492 wl_get_drv_status(cfg
, CONNECTING
, ndev
)) {
12493 wl_clr_drv_status(cfg
, DISCONNECTING
, ndev
);
12494 wl_clr_drv_status(cfg
, CONNECTING
, ndev
);
12495 wl_cfg80211_scan_abort(cfg
);
12496 DHD_ENABLE_RUNTIME_PM((dhd_pub_t
*)cfg
->pub
);
12499 /* Clean up any pending scan request */
12500 wl_cfg80211_cancel_scan(cfg
);
12502 if (wl_get_drv_status(cfg
, CONNECTING
, ndev
))
12503 wl_bss_connect_done(cfg
, ndev
, e
, data
, false);
12505 WL_DBG(("%s nothing\n", __FUNCTION__
));
12507 DHD_ENABLE_RUNTIME_PM((dhd_pub_t
*)cfg
->pub
);
12510 printf("wl_notify_connect_status : Invalid %s mode %d event %d status %d\n",
12511 ndev
->name
, wl_get_mode_by_netdev(cfg
, ndev
), ntoh32(e
->event_type
),
12512 ntoh32(e
->status
));
12518 void wl_cfg80211_set_rmc_pid(struct net_device
*dev
, int pid
)
12520 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
12522 cfg
->rmc_event_pid
= pid
;
12523 WL_DBG(("set pid for rmc event : pid=%d\n", pid
));
12525 #endif /* WL_RELMCAST */
12529 wl_notify_rmc_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12530 const wl_event_msg_t
*e
, void *data
)
12532 u32 evt
= ntoh32(e
->event_type
);
12533 u32 reason
= ntoh32(e
->reason
);
12537 case WLC_E_REASON_RMC_AR_LOST
:
12538 case WLC_E_REASON_RMC_AR_NO_ACK
:
12539 if (cfg
->rmc_event_pid
!= 0) {
12540 ret
= wl_netlink_send_msg(cfg
->rmc_event_pid
,
12541 RMC_EVENT_LEADER_CHECK_FAIL
,
12542 cfg
->rmc_event_seq
++, NULL
, 0);
12548 WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt
, cfg
->rmc_event_pid
, ret
));
12551 #endif /* WL_RELMCAST */
12553 #ifdef GSCAN_SUPPORT
12555 wl_handle_roam_exp_event(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12556 const wl_event_msg_t
*e
, void *data
)
12558 struct net_device
*ndev
= NULL
;
12559 u32 datalen
= be32_to_cpu(e
->datalen
);
12562 wl_roam_exp_event_t
*evt_data
= (wl_roam_exp_event_t
*)data
;
12563 if (evt_data
->version
== ROAM_EXP_EVENT_VERSION
) {
12564 wlc_ssid_t
*ssid
= &evt_data
->cur_ssid
;
12565 struct wireless_dev
*wdev
;
12566 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12568 wdev
= ndev
->ieee80211_ptr
;
12569 wdev
->ssid_len
= min(ssid
->SSID_len
, (uint32
)DOT11_MAX_SSID_LEN
);
12570 memcpy(wdev
->ssid
, ssid
->SSID
, wdev
->ssid_len
);
12571 WL_ERR(("SSID is %s\n", ssid
->SSID
));
12572 wl_update_prof(cfg
, ndev
, NULL
, ssid
, WL_PROF_SSID
);
12574 WL_ERR(("NULL ndev!\n"));
12577 WL_ERR(("Version mismatch %d, expected %d", evt_data
->version
,
12578 ROAM_EXP_EVENT_VERSION
));
12583 #endif /* GSCAN_SUPPORT */
12585 #ifdef RSSI_MONITOR_SUPPORT
12586 static s32
wl_handle_rssi_monitor_event(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12587 const wl_event_msg_t
*e
, void *data
)
12590 #if defined(WL_VENDOR_EXT_SUPPORT) || defined(CONFIG_BCMDHD_VENDOR_EXT)
12591 u32 datalen
= be32_to_cpu(e
->datalen
);
12592 struct net_device
*ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12593 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
12596 wl_rssi_monitor_evt_t
*evt_data
= (wl_rssi_monitor_evt_t
*)data
;
12597 if (evt_data
->version
== RSSI_MONITOR_VERSION
) {
12598 dhd_rssi_monitor_evt_t monitor_data
;
12599 monitor_data
.version
= DHD_RSSI_MONITOR_EVT_VERSION
;
12600 monitor_data
.cur_rssi
= evt_data
->cur_rssi
;
12601 memcpy(&monitor_data
.BSSID
, &e
->addr
, ETHER_ADDR_LEN
);
12602 wl_cfgvendor_send_async_event(wiphy
, ndev
,
12603 GOOGLE_RSSI_MONITOR_EVENT
,
12604 &monitor_data
, sizeof(monitor_data
));
12606 WL_ERR(("Version mismatch %d, expected %d", evt_data
->version
,
12607 RSSI_MONITOR_VERSION
));
12610 #endif /* WL_VENDOR_EXT_SUPPORT || CONFIG_BCMDHD_VENDOR_EXT */
12613 #endif /* RSSI_MONITOR_SUPPORT */
12616 wl_notify_roaming_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12617 const wl_event_msg_t
*e
, void *data
)
12620 struct net_device
*ndev
= NULL
;
12622 u32 event
= be32_to_cpu(e
->event_type
);
12623 u32 status
= be32_to_cpu(e
->status
);
12624 #ifdef DHD_LOSSLESS_ROAMING
12625 struct wl_security
*sec
;
12627 WL_DBG(("Enter \n"));
12629 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12631 if ((!cfg
->disable_roam_event
) && (event
== WLC_E_BSSID
)) {
12632 wl_add_remove_eventmsg(ndev
, WLC_E_ROAM
, false);
12633 cfg
->disable_roam_event
= TRUE
;
12636 if ((cfg
->disable_roam_event
) && (event
== WLC_E_ROAM
))
12639 if ((event
== WLC_E_ROAM
|| event
== WLC_E_BSSID
) && status
== WLC_E_STATUS_SUCCESS
) {
12640 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
12641 #ifdef DHD_LOSSLESS_ROAMING
12642 sec
= wl_read_prof(cfg
, ndev
, WL_PROF_SEC
);
12643 /* In order to reduce roaming delay, wl_bss_roaming_done is
12644 * early called with WLC_E_LINK event. It is called from
12645 * here only if WLC_E_LINK event is blocked for specific
12648 if (IS_AKM_SUITE_FT(sec
)) {
12649 wl_bss_roaming_done(cfg
, ndev
, e
, data
);
12651 /* Roam timer is deleted mostly from wl_cfg80211_change_station
12652 * after roaming is finished successfully. We need to delete
12653 * the timer from here only for some security types that aren't
12654 * using wl_cfg80211_change_station to authorize SCB
12656 if (IS_AKM_SUITE_FT(sec
) || IS_AKM_SUITE_CCKM(sec
)) {
12657 wl_del_roam_timeout(cfg
);
12660 wl_bss_roaming_done(cfg
, ndev
, e
, data
);
12661 #endif /* DHD_LOSSLESS_ROAMING */
12663 wl_bss_connect_done(cfg
, ndev
, e
, data
, true);
12666 wl_update_prof(cfg
, ndev
, e
, &act
, WL_PROF_ACT
);
12667 wl_update_prof(cfg
, ndev
, NULL
, (const void *)&e
->addr
, WL_PROF_BSSID
);
12669 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
12670 wl_vndr_ies_get_vendor_oui(cfg
, ndev
, NULL
, 0);
12673 #ifdef DHD_LOSSLESS_ROAMING
12674 else if ((event
== WLC_E_ROAM
|| event
== WLC_E_BSSID
) && status
!= WLC_E_STATUS_SUCCESS
) {
12675 wl_del_roam_timeout(cfg
);
12681 #ifdef CUSTOM_EVENT_PM_WAKE
12682 uint32 last_dpm_upd_time
= 0; /* ms */
12683 #define DPM_UPD_LMT_TIME 25000 /* ms */
12684 #define DPM_UPD_LMT_RSSI -85 /* dbm */
12687 wl_check_pmstatus(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12688 const wl_event_msg_t
*e
, void *data
)
12691 struct net_device
*ndev
= NULL
;
12693 uint32 cur_dpm_upd_time
= 0;
12694 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
12698 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12700 pbuf
= kzalloc(WLC_IOCTL_MEDLEN
, GFP_KERNEL
);
12701 if (pbuf
== NULL
) {
12702 WL_ERR(("failed to allocate local pbuf\n"));
12706 err
= wldev_iovar_getbuf_bsscfg(ndev
, "dump",
12707 "pm", strlen("pm"), pbuf
, WLC_IOCTL_MEDLEN
, 0, &cfg
->ioctl_buf_sync
);
12710 WL_ERR(("dump ioctl err = %d", err
));
12712 WL_ERR(("PM status : %s\n", pbuf
));
12719 if (dhd
->early_suspended
) {
12721 memset(&scb_val
, 0, sizeof(scb_val_t
));
12723 err
= wldev_ioctl_get(ndev
, WLC_GET_RSSI
, &scb_val
, sizeof(scb_val_t
));
12725 WL_ERR(("Could not get rssi (%d)\n", err
));
12727 rssi
= wl_rssi_offset(dtoh32(scb_val
.val
));
12728 WL_ERR(("[%s] RSSI %d dBm\n", ndev
->name
, rssi
));
12729 if (rssi
> DPM_UPD_LMT_RSSI
) {
12737 if (last_dpm_upd_time
== 0) {
12738 last_dpm_upd_time
= OSL_SYSUPTIME();
12740 cur_dpm_upd_time
= OSL_SYSUPTIME();
12741 if (cur_dpm_upd_time
- last_dpm_upd_time
< DPM_UPD_LMT_TIME
) {
12743 bzero(&scbval
, sizeof(scb_val_t
));
12745 err
= wldev_ioctl_set(ndev
, WLC_DISASSOC
, &scbval
, sizeof(scb_val_t
));
12747 WL_ERR(("%s: Disassoc error %d\n", __FUNCTION__
, err
));
12750 WL_ERR(("%s: Force Disassoc due to updated DPM event.\n", __FUNCTION__
));
12752 last_dpm_upd_time
= 0;
12754 last_dpm_upd_time
= cur_dpm_upd_time
;
12760 #endif /* CUSTOM_EVENT_PM_WAKE */
12763 /* get user priority table */
12765 wl_get_up_table(dhd_pub_t
* dhdp
, int idx
)
12767 struct net_device
*ndev
;
12768 struct bcm_cfg80211
*cfg
;
12770 ndev
= dhd_idx2net(dhdp
, idx
);
12772 cfg
= wl_get_cfg(ndev
);
12774 return (uint8
*)(cfg
->up_table
);
12779 #endif /* QOS_MAP_SET */
12781 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
12783 wl_notify_roam_prep_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12784 const wl_event_msg_t
*e
, void *data
)
12786 struct wl_security
*sec
;
12787 struct net_device
*ndev
;
12788 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
12789 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
12790 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
12791 u32 status
= ntoh32(e
->status
);
12792 u32 reason
= ntoh32(e
->reason
);
12794 BCM_REFERENCE(sec
);
12796 if (status
== WLC_E_STATUS_SUCCESS
&& reason
!= WLC_E_REASON_INITIAL_ASSOC
) {
12797 WL_ERR(("Attempting roam with reason code : %d\n", reason
));
12800 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12803 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
12804 DHD_DBG_PKT_MON_STOP(dhdp
);
12805 DHD_DBG_PKT_MON_START(dhdp
);
12807 #endif /* DBG_PKT_MON */
12809 #ifdef DHD_LOSSLESS_ROAMING
12810 sec
= wl_read_prof(cfg
, ndev
, WL_PROF_SEC
);
12811 /* Disable Lossless Roaming for specific AKM suite
12812 * Any other AKM suite can be added below if transition time
12813 * is delayed because of Lossless Roaming
12814 * and it causes any certication failure
12816 if (IS_AKM_SUITE_FT(sec
)) {
12819 dhdp
->dequeue_prec_map
= 1 << PRIO_8021D_NC
;
12820 /* Restore flow control */
12821 dhd_txflowcontrol(dhdp
, ALL_INTERFACES
, OFF
);
12823 mod_timer(&cfg
->roam_timeout
, jiffies
+ msecs_to_jiffies(WL_ROAM_TIMEOUT_MS
));
12824 #endif /* DHD_LOSSLESS_ROAMING */
12828 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
12829 #ifdef ENABLE_TEMP_THROTTLING
12831 wl_check_rx_throttle_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12832 const wl_event_msg_t
*e
, void *data
)
12835 u32 status
= ntoh32(e
->status
);
12836 u32 reason
= ntoh32(e
->reason
);
12838 WL_ERR_EX(("RX THROTTLE : status=%d, reason=0x%x\n", status
, reason
));
12842 #endif /* ENABLE_TEMP_THROTTLING */
12844 static s32
wl_get_assoc_ies(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
)
12846 wl_assoc_info_t assoc_info
;
12847 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
12850 bcm_tlv_t
* qos_map_ie
= NULL
;
12851 #endif /* QOS_MAP_SET */
12853 WL_DBG(("Enter \n"));
12854 err
= wldev_iovar_getbuf(ndev
, "assoc_info", NULL
, 0, cfg
->extra_buf
,
12855 WL_ASSOC_INFO_MAX
, NULL
);
12856 if (unlikely(err
)) {
12857 WL_ERR(("could not get assoc info (%d)\n", err
));
12860 memcpy(&assoc_info
, cfg
->extra_buf
, sizeof(wl_assoc_info_t
));
12861 assoc_info
.req_len
= htod32(assoc_info
.req_len
);
12862 assoc_info
.resp_len
= htod32(assoc_info
.resp_len
);
12863 assoc_info
.flags
= htod32(assoc_info
.flags
);
12864 if (conn_info
->req_ie_len
) {
12865 conn_info
->req_ie_len
= 0;
12866 bzero(conn_info
->req_ie
, sizeof(conn_info
->req_ie
));
12868 if (conn_info
->resp_ie_len
) {
12869 conn_info
->resp_ie_len
= 0;
12870 bzero(conn_info
->resp_ie
, sizeof(conn_info
->resp_ie
));
12872 if (assoc_info
.req_len
) {
12873 err
= wldev_iovar_getbuf(ndev
, "assoc_req_ies", NULL
, 0, cfg
->extra_buf
,
12874 WL_ASSOC_INFO_MAX
, NULL
);
12875 if (unlikely(err
)) {
12876 WL_ERR(("could not get assoc req (%d)\n", err
));
12879 conn_info
->req_ie_len
= assoc_info
.req_len
- sizeof(struct dot11_assoc_req
);
12880 if (assoc_info
.flags
& WLC_ASSOC_REQ_IS_REASSOC
) {
12881 conn_info
->req_ie_len
-= ETHER_ADDR_LEN
;
12883 if (conn_info
->req_ie_len
<= MAX_REQ_LINE
)
12884 memcpy(conn_info
->req_ie
, cfg
->extra_buf
, conn_info
->req_ie_len
);
12886 WL_ERR(("IE size %d above max %d size \n",
12887 conn_info
->req_ie_len
, MAX_REQ_LINE
));
12891 conn_info
->req_ie_len
= 0;
12893 if (assoc_info
.resp_len
) {
12894 err
= wldev_iovar_getbuf(ndev
, "assoc_resp_ies", NULL
, 0, cfg
->extra_buf
,
12895 WL_ASSOC_INFO_MAX
, NULL
);
12896 if (unlikely(err
)) {
12897 WL_ERR(("could not get assoc resp (%d)\n", err
));
12900 conn_info
->resp_ie_len
= assoc_info
.resp_len
-sizeof(struct dot11_assoc_resp
);
12901 if (conn_info
->resp_ie_len
<= MAX_REQ_LINE
) {
12902 memcpy(conn_info
->resp_ie
, cfg
->extra_buf
, conn_info
->resp_ie_len
);
12904 WL_ERR(("IE size %d above max %d size \n",
12905 conn_info
->resp_ie_len
, MAX_REQ_LINE
));
12910 /* find qos map set ie */
12911 if ((qos_map_ie
= bcm_parse_tlvs(conn_info
->resp_ie
, conn_info
->resp_ie_len
,
12912 DOT11_MNG_QOS_MAP_ID
)) != NULL
) {
12913 WL_DBG((" QoS map set IE found in assoc response\n"));
12914 if (!cfg
->up_table
) {
12915 cfg
->up_table
= kmalloc(UP_TABLE_MAX
, GFP_KERNEL
);
12917 wl_set_up_table(cfg
->up_table
, qos_map_ie
);
12919 kfree(cfg
->up_table
);
12920 cfg
->up_table
= NULL
;
12922 #endif /* QOS_MAP_SET */
12924 conn_info
->resp_ie_len
= 0;
12926 WL_DBG(("req len (%d) resp len (%d)\n", conn_info
->req_ie_len
,
12927 conn_info
->resp_ie_len
));
12932 static s32
wl_ch_to_chanspec(struct net_device
*dev
, int ch
, struct wl_join_params
*join_params
,
12933 size_t *join_params_size
)
12936 chanspec_t chanspec
= 0, chspec
;
12939 struct bcm_cfg80211
*cfg
=
12940 (struct bcm_cfg80211
*)wiphy_priv(dev
->ieee80211_ptr
->wiphy
);
12941 join_params
->params
.chanspec_num
= 1;
12942 join_params
->params
.chanspec_list
[0] = ch
;
12944 if (join_params
->params
.chanspec_list
[0] <= CH_MAX_2G_CHANNEL
)
12945 chanspec
|= WL_CHANSPEC_BAND_2G
;
12947 chanspec
|= WL_CHANSPEC_BAND_5G
;
12949 /* Get the min_bw set for the interface */
12950 chspec
= wl_cfg80211_ulb_get_min_bw_chspec(cfg
, dev
->ieee80211_ptr
, bssidx
);
12951 if (chspec
== INVCHANSPEC
) {
12952 WL_ERR(("Invalid chanspec \n"));
12955 chanspec
|= chspec
;
12956 chanspec
|= WL_CHANSPEC_CTL_SB_NONE
;
12958 *join_params_size
+= WL_ASSOC_PARAMS_FIXED_SIZE
+
12959 join_params
->params
.chanspec_num
* sizeof(chanspec_t
);
12961 join_params
->params
.chanspec_list
[0] &= WL_CHANSPEC_CHAN_MASK
;
12962 join_params
->params
.chanspec_list
[0] |= chanspec
;
12963 join_params
->params
.chanspec_list
[0] =
12964 wl_chspec_host_to_driver(join_params
->params
.chanspec_list
[0]);
12966 join_params
->params
.chanspec_num
=
12967 htod32(join_params
->params
.chanspec_num
);
12969 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
12970 join_params
->params
.chanspec_list
[0],
12971 join_params
->params
.chanspec_num
));
12976 static s32
wl_update_bss_info(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, bool roam
)
12978 struct cfg80211_bss
*bss
;
12979 struct wl_bss_info
*bi
;
12980 struct wlc_ssid
*ssid
;
12981 struct bcm_tlv
*tim
;
12982 s32 beacon_interval
;
12988 struct wiphy
*wiphy
;
12993 wiphy
= bcmcfg_to_wiphy(cfg
);
12995 ssid
= (struct wlc_ssid
*)wl_read_prof(cfg
, ndev
, WL_PROF_SSID
);
12996 curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
12997 bss
= CFG80211_GET_BSS(wiphy
, NULL
, curbssid
,
12998 ssid
->SSID
, ssid
->SSID_len
);
12999 buf
= kzalloc(WL_EXTRA_BUF_MAX
, GFP_ATOMIC
);
13001 WL_ERR(("buffer alloc failed.\n"));
13004 mutex_lock(&cfg
->usr_sync
);
13005 *(u32
*)buf
= htod32(WL_EXTRA_BUF_MAX
);
13006 err
= wldev_ioctl_get(ndev
, WLC_GET_BSS_INFO
, buf
, WL_EXTRA_BUF_MAX
);
13007 if (unlikely(err
)) {
13008 WL_ERR(("Could not get bss info %d\n", err
));
13009 goto update_bss_info_out
;
13011 bi
= (struct wl_bss_info
*)(buf
+ 4);
13012 channel
= wf_chspec_ctlchan(wl_chspec_driver_to_host(bi
->chanspec
));
13013 wl_update_prof(cfg
, ndev
, NULL
, &channel
, WL_PROF_CHAN
);
13016 WL_DBG(("Could not find the AP\n"));
13017 if (memcmp(bi
->BSSID
.octet
, curbssid
, ETHER_ADDR_LEN
)) {
13018 WL_ERR(("Bssid doesn't match\n"));
13020 goto update_bss_info_out
;
13022 err
= wl_inform_single_bss(cfg
, bi
, roam
);
13024 goto update_bss_info_out
;
13026 ie
= ((u8
*)bi
) + bi
->ie_offset
;
13027 ie_len
= bi
->ie_length
;
13028 beacon_interval
= cpu_to_le16(bi
->beacon_period
);
13030 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss
->bssid
));
13031 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
13032 freq
= ieee80211_channel_to_frequency(channel
);
13034 band
= (channel
<= CH_MAX_2G_CHANNEL
) ? IEEE80211_BAND_2GHZ
: IEEE80211_BAND_5GHZ
;
13035 freq
= ieee80211_channel_to_frequency(channel
, band
);
13037 bss
->channel
= ieee80211_get_channel(wiphy
, freq
);
13038 #if defined(WL_CFG80211_P2P_DEV_IF)
13039 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
13040 #pragma GCC diagnostic push
13041 #pragma GCC diagnostic ignored "-Wcast-qual"
13043 ie
= (u8
*)bss
->ies
->data
;
13044 ie_len
= bss
->ies
->len
;
13045 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
13046 #pragma GCC diagnostic pop
13049 ie
= bss
->information_elements
;
13050 ie_len
= bss
->len_information_elements
;
13051 #endif /* WL_CFG80211_P2P_DEV_IF */
13052 beacon_interval
= bss
->beacon_interval
;
13054 CFG80211_PUT_BSS(wiphy
, bss
);
13057 tim
= bcm_parse_tlvs(ie
, ie_len
, WLAN_EID_TIM
);
13059 dtim_period
= tim
->data
[1];
13062 * active scan was done so we could not get dtim
13063 * information out of probe response.
13064 * so we speficially query dtim information.
13067 err
= wldev_ioctl_get(ndev
, WLC_GET_DTIMPRD
,
13068 &dtim_period
, sizeof(dtim_period
));
13069 if (unlikely(err
)) {
13070 WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err
));
13071 goto update_bss_info_out
;
13075 wl_update_prof(cfg
, ndev
, NULL
, &beacon_interval
, WL_PROF_BEACONINT
);
13076 wl_update_prof(cfg
, ndev
, NULL
, &dtim_period
, WL_PROF_DTIMPERIOD
);
13078 update_bss_info_out
:
13079 if (unlikely(err
)) {
13080 WL_ERR(("Failed with error %d\n", err
));
13084 mutex_unlock(&cfg
->usr_sync
);
13089 wl_bss_roaming_done(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
13090 const wl_event_msg_t
*e
, void *data
)
13092 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
13096 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13097 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
13098 struct ieee80211_supported_band
*band
;
13099 struct ieee80211_channel
*notify_channel
= NULL
;
13101 #ifdef BCM4359_CHIP
13102 struct channel_info ci
;
13104 #endif /* BCM4359_CHIP */
13106 #if defined(WLADPS_SEAK_AP_WAR) || defined(WBTEXT)
13107 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
13108 #endif /* WLADPS_SEAK_AP_WAR || WBTEXT */
13109 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13110 struct cfg80211_roam_info roam_info
= {};
13111 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13113 #ifdef WLADPS_SEAK_AP_WAR
13114 BCM_REFERENCE(dhdp
);
13115 #endif /* WLADPS_SEAK_AP_WAR */
13117 curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
13118 channel
= (u32
*)wl_read_prof(cfg
, ndev
, WL_PROF_CHAN
);
13119 #ifdef BCM4359_CHIP
13120 /* Skip calling cfg80211_roamed If the channels are same and
13121 * the current bssid/last_roamed_bssid & the new bssid are same
13122 * Also clear timer roam_timeout.
13123 * Only used on BCM4359 devices.
13125 memset(&ci
, 0, sizeof(ci
));
13126 if ((wldev_ioctl_get(ndev
, WLC_GET_CHANNEL
, &ci
,
13127 sizeof(ci
))) < 0) {
13128 WL_ERR(("Failed to get current channel !"));
13131 cur_channel
= dtoh32(ci
.hw_channel
);
13132 if ((*channel
== cur_channel
) && ((memcmp(curbssid
, &e
->addr
,
13133 ETHER_ADDR_LEN
) == 0) || (memcmp(&cfg
->last_roamed_addr
,
13134 &e
->addr
, ETHER_ADDR_LEN
) == 0))) {
13135 WL_ERR(("BSS already present, Skipping roamed event to"
13136 " upper layer\n"));
13137 #ifdef DHD_LOSSLESS_ROAMING
13138 wl_del_roam_timeout(cfg
);
13139 #endif /* DHD_LOSSLESS_ROAMING */
13142 #endif /* BCM4359_CHIP */
13144 wl_get_assoc_ies(cfg
, ndev
);
13145 wl_update_prof(cfg
, ndev
, NULL
, (const void *)(e
->addr
.octet
), WL_PROF_BSSID
);
13146 curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
13147 wl_update_bss_info(cfg
, ndev
, true);
13148 wl_update_pmklist(ndev
, cfg
->pmk_list
, err
);
13150 channel
= (u32
*)wl_read_prof(cfg
, ndev
, WL_PROF_CHAN
);
13151 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13152 /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
13153 if (*channel
<= CH_MAX_2G_CHANNEL
)
13154 band
= wiphy
->bands
[IEEE80211_BAND_2GHZ
];
13156 band
= wiphy
->bands
[IEEE80211_BAND_5GHZ
];
13157 freq
= ieee80211_channel_to_frequency(*channel
, band
->band
);
13158 notify_channel
= ieee80211_get_channel(wiphy
, freq
);
13160 #ifdef WLADPS_SEAK_AP_WAR
13161 if ((dhdp
->op_mode
& DHD_FLAG_STA_MODE
) &&
13162 (!dhdp
->disabled_adps
)) {
13165 if (!memcmp(curbssid
, (u8
*)CAMEO_MAC_PREFIX
, MAC_PREFIX_LEN
)) {
13166 find
= wl_find_vndr_ies_specific_vender(cfg
, ndev
, ATHEROS_OUI
);
13168 enable_mode
= (find
== TRUE
) ? OFF
: ON
;
13169 wl_set_adps_mode(cfg
, ndev
, enable_mode
);
13171 #endif /* WLADPS_SEAK_AP_WAR */
13172 printf("%s succeeded to " MACDBG
" (ch:%d)\n", __FUNCTION__
,
13173 MAC2STRDBG((const u8
*)(&e
->addr
)), *channel
);
13174 dhd_conf_set_wme(cfg
->pub
, 0);
13176 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13177 roam_info
.channel
= notify_channel
;
13178 roam_info
.bssid
= curbssid
;
13179 roam_info
.req_ie
= conn_info
->req_ie
;
13180 roam_info
.req_ie_len
= conn_info
->req_ie_len
;
13181 roam_info
.resp_ie
= conn_info
->resp_ie
;
13182 roam_info
.resp_ie_len
= conn_info
->resp_ie_len
;
13183 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13185 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13186 cfg80211_roamed(ndev
, &roam_info
, GFP_KERNEL
);
13188 cfg80211_roamed(ndev
,
13189 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13193 conn_info
->req_ie
, conn_info
->req_ie_len
,
13194 conn_info
->resp_ie
, conn_info
->resp_ie_len
, GFP_KERNEL
);
13195 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13196 WL_DBG(("Report roaming result\n"));
13198 memcpy(&cfg
->last_roamed_addr
, &e
->addr
, ETHER_ADDR_LEN
);
13199 wl_set_drv_status(cfg
, CONNECTED
, ndev
);
13201 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
13203 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
13206 if (dhdp
->wbtext_support
) {
13207 /* set wnm_keepalives_max_idle after association */
13208 wl_cfg80211_wbtext_set_wnm_maxidle(cfg
, ndev
);
13209 /* send nbr request or BTM query to update RCC */
13210 wl_cfg80211_wbtext_update_rcc(cfg
, ndev
);
13212 #endif /* WBTEXT */
13218 wl_cfg80211_verify_bss(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
)
13220 struct cfg80211_bss
*bss
;
13221 struct wiphy
*wiphy
;
13222 struct wlc_ssid
*ssid
;
13227 wiphy
= bcmcfg_to_wiphy(cfg
);
13228 ssid
= (struct wlc_ssid
*)wl_read_prof(cfg
, ndev
, WL_PROF_SSID
);
13229 curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
13231 WL_ERR(("No SSID found in the saved profile \n"));
13236 bss
= CFG80211_GET_BSS(wiphy
, NULL
, curbssid
,
13237 ssid
->SSID
, ssid
->SSID_len
);
13238 if (bss
|| (count
> 5)) {
13244 } while (bss
== NULL
);
13246 WL_DBG(("cfg80211 bss_ptr:%p loop_cnt:%d\n", bss
, count
));
13248 /* Update the reference count after use */
13249 CFG80211_PUT_BSS(wiphy
, bss
);
13257 wl_bss_connect_done(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
13258 const wl_event_msg_t
*e
, void *data
, bool completed
)
13260 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
13261 struct wl_security
*sec
= wl_read_prof(cfg
, ndev
, WL_PROF_SEC
);
13263 u8
*curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
13266 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
13267 BCM_REFERENCE(dhdp
);
13270 WL_ERR(("sec is NULL\n"));
13273 WL_DBG((" enter\n"));
13274 #ifdef ESCAN_RESULT_PATCH
13275 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
13276 if (memcmp(curbssid
, connect_req_bssid
, ETHER_ADDR_LEN
) == 0) {
13277 WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
13278 ntoh32(e
->event_type
), ntoh32(e
->status
)));
13282 if (memcmp(curbssid
, broad_bssid
, ETHER_ADDR_LEN
) == 0 &&
13283 memcmp(broad_bssid
, connect_req_bssid
, ETHER_ADDR_LEN
) != 0) {
13284 WL_DBG(("copy bssid\n"));
13285 memcpy(curbssid
, connect_req_bssid
, ETHER_ADDR_LEN
);
13289 if (cfg
->scan_request
) {
13290 wl_notify_escan_complete(cfg
, ndev
, true, true);
13292 #endif /* ESCAN_RESULT_PATCH */
13293 if (wl_get_drv_status(cfg
, CONNECTING
, ndev
)) {
13294 wl_cfg80211_scan_abort(cfg
);
13295 wl_clr_drv_status(cfg
, CONNECTING
, ndev
);
13297 wl_get_assoc_ies(cfg
, ndev
);
13298 wl_update_prof(cfg
, ndev
, NULL
, (const void *)(e
->addr
.octet
),
13300 curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
13301 wl_update_bss_info(cfg
, ndev
, false);
13302 wl_update_pmklist(ndev
, cfg
->pmk_list
, err
);
13303 wl_set_drv_status(cfg
, CONNECTED
, ndev
);
13304 #ifdef WLADPS_SEAK_AP_WAR
13305 if ((dhdp
->op_mode
& DHD_FLAG_STA_MODE
) &&
13306 (!dhdp
->disabled_adps
)) {
13309 if (!memcmp(curbssid
, (u8
*)CAMEO_MAC_PREFIX
, MAC_PREFIX_LEN
)) {
13310 find
= wl_find_vndr_ies_specific_vender(cfg
,
13311 ndev
, ATHEROS_OUI
);
13313 enable_mode
= (find
== TRUE
) ? OFF
: ON
;
13314 wl_set_adps_mode(cfg
, ndev
, enable_mode
);
13316 #endif /* WLADPS_SEAK_AP_WAR */
13317 if (ndev
!= bcmcfg_to_prmry_ndev(cfg
)) {
13318 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
13319 init_completion(&cfg
->iface_disable
);
13321 /* reinitialize completion to clear previous count */
13322 INIT_COMPLETION(cfg
->iface_disable
);
13325 #ifdef CUSTOM_SET_CPUCORE
13326 if (wl_get_chan_isvht80(ndev
, dhdp
)) {
13327 if (ndev
== bcmcfg_to_prmry_ndev(cfg
))
13328 dhdp
->chan_isvht80
|= DHD_FLAG_STA_MODE
; /* STA mode */
13329 else if (is_p2p_group_iface(ndev
->ieee80211_ptr
))
13330 dhdp
->chan_isvht80
|= DHD_FLAG_P2P_MODE
; /* p2p mode */
13331 dhd_set_cpucore(dhdp
, TRUE
);
13333 #endif /* CUSTOM_SET_CPUCORE */
13334 memset(&cfg
->last_roamed_addr
, 0, ETHER_ADDR_LEN
);
13337 if (completed
&& (wl_cfg80211_verify_bss(cfg
, ndev
) != true)) {
13338 /* If bss entry is not available in the cfg80211 bss cache
13339 * the wireless stack will complain and won't populate
13340 * wdev->current_bss ptr
13342 WL_ERR(("BSS entry not found. Indicate assoc event failure\n"));
13344 sec
->auth_assoc_res_status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
13346 cfg80211_connect_result(ndev
,
13349 conn_info
->req_ie_len
,
13350 conn_info
->resp_ie
,
13351 conn_info
->resp_ie_len
,
13352 completed
? WLAN_STATUS_SUCCESS
:
13353 (sec
->auth_assoc_res_status
) ?
13354 sec
->auth_assoc_res_status
:
13355 WLAN_STATUS_UNSPECIFIED_FAILURE
,
13358 WL_INFORM(("Report connect result - connection succeeded\n"));
13359 dhd_conf_set_wme(cfg
->pub
, 0);
13361 WL_ERR(("Report connect result - connection failed\n"));
13362 wl_cfg80211_check_in4way(cfg
, ndev
, NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
,
13363 WL_EXT_STATUS_DISCONNECTED
, NULL
);
13366 #ifdef CONFIG_TCPACK_FASTTX
13367 if (wl_get_chan_isvht80(ndev
, dhdp
))
13368 wldev_iovar_setint(ndev
, "tcpack_fast_tx", 0);
13370 wldev_iovar_setint(ndev
, "tcpack_fast_tx", 1);
13371 #endif /* CONFIG_TCPACK_FASTTX */
13377 wl_notify_mic_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13378 const wl_event_msg_t
*e
, void *data
)
13380 struct net_device
*ndev
= NULL
;
13381 u16 flags
= ntoh16(e
->flags
);
13382 enum nl80211_key_type key_type
;
13384 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13386 mutex_lock(&cfg
->usr_sync
);
13387 if (flags
& WLC_EVENT_MSG_GROUP
)
13388 key_type
= NL80211_KEYTYPE_GROUP
;
13390 key_type
= NL80211_KEYTYPE_PAIRWISE
;
13392 cfg80211_michael_mic_failure(ndev
, (const u8
*)&e
->addr
, key_type
, -1,
13394 mutex_unlock(&cfg
->usr_sync
);
13399 #ifdef BT_WIFI_HANDOVER
13401 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13402 const wl_event_msg_t
*e
, void *data
)
13404 struct net_device
*ndev
= NULL
;
13405 u32 event
= ntoh32(e
->event_type
);
13406 u32 datalen
= ntoh32(e
->datalen
);
13409 WL_ERR(("wl_notify_bt_wifi_handover_req: event_type : %d, datalen : %d\n", event
, datalen
));
13410 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13411 err
= wl_genl_send_msg(ndev
, event
, data
, (u16
)datalen
, 0, 0);
13415 #endif /* BT_WIFI_HANDOVER */
13419 wl_notify_pfn_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13420 const wl_event_msg_t
*e
, void *data
)
13422 struct net_device
*ndev
= NULL
;
13423 #ifdef GSCAN_SUPPORT
13425 int send_evt_bytes
= 0;
13426 u32 event
= be32_to_cpu(e
->event_type
);
13427 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
13428 #endif /* GSCAN_SUPPORT */
13430 WL_ERR((">>> PNO Event\n"));
13432 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13433 #ifdef GSCAN_SUPPORT
13434 ptr
= dhd_dev_process_epno_result(ndev
, data
, event
, &send_evt_bytes
);
13436 wl_cfgvendor_send_async_event(wiphy
, ndev
,
13437 GOOGLE_SCAN_EPNO_EVENT
, ptr
, send_evt_bytes
);
13440 if (!dhd_dev_is_legacy_pno_enabled(ndev
))
13442 #endif /* GSCAN_SUPPORT */
13445 #ifndef WL_SCHED_SCAN
13446 mutex_lock(&cfg
->usr_sync
);
13447 /* TODO: Use cfg80211_sched_scan_results(wiphy); */
13448 CFG80211_DISCONNECTED(ndev
, 0, NULL
, 0, false, GFP_KERNEL
);
13449 mutex_unlock(&cfg
->usr_sync
);
13451 /* If cfg80211 scheduled scan is supported, report the pno results via sched
13454 wl_notify_sched_scan_results(cfg
, ndev
, e
, data
);
13455 #endif /* WL_SCHED_SCAN */
13458 #endif /* PNO_SUPPORT */
13460 #ifdef GSCAN_SUPPORT
13462 wl_notify_gscan_event(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13463 const wl_event_msg_t
*e
, void *data
)
13466 u32 event
= be32_to_cpu(e
->event_type
);
13468 int send_evt_bytes
= 0;
13470 struct net_device
*ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13471 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
13472 u32 len
= ntoh32(e
->datalen
);
13475 case WLC_E_PFN_BEST_BATCHING
:
13476 err
= dhd_dev_retrieve_batch_scan(ndev
);
13478 WL_ERR(("Batch retrieval already in progress %d\n", err
));
13480 event_type
= WIFI_SCAN_THRESHOLD_NUM_SCANS
;
13482 event_type
= *((int *)data
);
13484 wl_cfgvendor_send_async_event(wiphy
, ndev
,
13485 GOOGLE_GSCAN_BATCH_SCAN_EVENT
,
13486 &event_type
, sizeof(int));
13489 case WLC_E_PFN_SCAN_COMPLETE
:
13490 event_type
= WIFI_SCAN_COMPLETE
;
13491 wl_cfgvendor_send_async_event(wiphy
, ndev
,
13492 GOOGLE_SCAN_COMPLETE_EVENT
,
13493 &event_type
, sizeof(int));
13495 case WLC_E_PFN_BSSID_NET_FOUND
:
13496 ptr
= dhd_dev_hotlist_scan_event(ndev
, data
, &send_evt_bytes
,
13499 wl_cfgvendor_send_hotlist_event(wiphy
, ndev
,
13500 ptr
, send_evt_bytes
, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT
);
13501 dhd_dev_gscan_hotlist_cache_cleanup(ndev
, HOTLIST_FOUND
);
13506 case WLC_E_PFN_BSSID_NET_LOST
:
13507 /* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
13508 * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
13511 ptr
= dhd_dev_hotlist_scan_event(ndev
, data
, &send_evt_bytes
,
13514 wl_cfgvendor_send_hotlist_event(wiphy
, ndev
,
13515 ptr
, send_evt_bytes
, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT
);
13516 dhd_dev_gscan_hotlist_cache_cleanup(ndev
, HOTLIST_LOST
);
13524 case WLC_E_PFN_GSCAN_FULL_RESULT
:
13525 ptr
= dhd_dev_process_full_gscan_result(ndev
, data
, len
, &send_evt_bytes
);
13527 wl_cfgvendor_send_async_event(wiphy
, ndev
,
13528 GOOGLE_SCAN_FULL_RESULTS_EVENT
, ptr
, send_evt_bytes
);
13534 case WLC_E_PFN_SSID_EXT
:
13535 ptr
= dhd_dev_process_epno_result(ndev
, data
, event
, &send_evt_bytes
);
13537 wl_cfgvendor_send_async_event(wiphy
, ndev
,
13538 GOOGLE_SCAN_EPNO_EVENT
, ptr
, send_evt_bytes
);
13545 WL_ERR(("Unknown event %d\n", event
));
13550 #endif /* GSCAN_SUPPORT */
13553 wl_notify_scan_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13554 const wl_event_msg_t
*e
, void *data
)
13556 struct channel_info channel_inform
;
13557 struct wl_scan_results
*bss_list
;
13558 struct net_device
*ndev
= NULL
;
13559 u32 len
= WL_SCAN_BUF_MAX
;
13561 unsigned long flags
;
13562 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
13563 struct cfg80211_scan_info info
;
13566 WL_DBG(("Enter \n"));
13567 if (!wl_get_drv_status(cfg
, SCANNING
, ndev
)) {
13568 WL_ERR(("scan is not ready \n"));
13571 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13573 mutex_lock(&cfg
->usr_sync
);
13574 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
13575 memset(&channel_inform
, 0, sizeof(channel_inform
));
13576 err
= wldev_ioctl_get(ndev
, WLC_GET_CHANNEL
, &channel_inform
,
13577 sizeof(channel_inform
));
13578 if (unlikely(err
)) {
13579 WL_ERR(("scan busy (%d)\n", err
));
13580 goto scan_done_out
;
13582 channel_inform
.scan_channel
= dtoh32(channel_inform
.scan_channel
);
13583 if (unlikely(channel_inform
.scan_channel
)) {
13585 WL_DBG(("channel_inform.scan_channel (%d)\n",
13586 channel_inform
.scan_channel
));
13588 cfg
->bss_list
= cfg
->scan_results
;
13589 bss_list
= cfg
->bss_list
;
13590 memset(bss_list
, 0, len
);
13591 bss_list
->buflen
= htod32(len
);
13592 err
= wldev_ioctl_get(ndev
, WLC_SCAN_RESULTS
, bss_list
, len
);
13593 if (unlikely(err
) && unlikely(!cfg
->scan_suppressed
)) {
13594 WL_ERR(("%s Scan_results error (%d)\n", ndev
->name
, err
));
13596 goto scan_done_out
;
13598 bss_list
->buflen
= dtoh32(bss_list
->buflen
);
13599 bss_list
->version
= dtoh32(bss_list
->version
);
13600 bss_list
->count
= dtoh32(bss_list
->count
);
13602 err
= wl_inform_bss(cfg
);
13605 del_timer_sync(&cfg
->scan_timeout
);
13606 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
13607 if (cfg
->scan_request
) {
13608 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
13609 info
.aborted
= false;
13610 cfg80211_scan_done(cfg
->scan_request
, &info
);
13612 cfg80211_scan_done(cfg
->scan_request
, false);
13614 cfg
->scan_request
= NULL
;
13616 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
13617 WL_DBG(("cfg80211_scan_done\n"));
13618 mutex_unlock(&cfg
->usr_sync
);
13623 wl_frame_get_mgmt(u16 fc
, const struct ether_addr
*da
,
13624 const struct ether_addr
*sa
, const struct ether_addr
*bssid
,
13625 u8
**pheader
, u32
*body_len
, u8
*pbody
)
13627 struct dot11_management_header
*hdr
;
13631 u32 prebody_len
= *body_len
;
13634 /* capability , listen interval */
13635 totlen
= DOT11_ASSOC_REQ_FIXED_LEN
;
13636 *body_len
+= DOT11_ASSOC_REQ_FIXED_LEN
;
13639 case FC_REASSOC_REQ
:
13640 /* capability, listen inteval, ap address */
13641 totlen
= DOT11_REASSOC_REQ_FIXED_LEN
;
13642 *body_len
+= DOT11_REASSOC_REQ_FIXED_LEN
;
13645 totlen
+= DOT11_MGMT_HDR_LEN
+ prebody_len
;
13646 *pheader
= kzalloc(totlen
, GFP_KERNEL
);
13647 if (*pheader
== NULL
) {
13648 WL_ERR(("memory alloc failed \n"));
13651 hdr
= (struct dot11_management_header
*) (*pheader
);
13652 hdr
->fc
= htol16(fc
);
13655 offset
= (u8
*)(hdr
+ 1) + (totlen
- DOT11_MGMT_HDR_LEN
- prebody_len
);
13656 bcopy((const char*)da
, (u8
*)&hdr
->da
, ETHER_ADDR_LEN
);
13657 bcopy((const char*)sa
, (u8
*)&hdr
->sa
, ETHER_ADDR_LEN
);
13658 bcopy((const char*)bssid
, (u8
*)&hdr
->bssid
, ETHER_ADDR_LEN
);
13659 if ((pbody
!= NULL
) && prebody_len
)
13660 bcopy((const char*)pbody
, offset
, prebody_len
);
13661 *body_len
= totlen
;
13667 wl_stop_wait_next_action_frame(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, u8 bsscfgidx
)
13671 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
)) {
13672 if (timer_pending(&cfg
->p2p
->listen_timer
)) {
13673 del_timer_sync(&cfg
->p2p
->listen_timer
);
13675 if (cfg
->afx_hdl
!= NULL
) {
13676 if (cfg
->afx_hdl
->dev
!= NULL
) {
13677 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
13678 wl_clr_drv_status(cfg
, FINDING_COMMON_CHANNEL
, cfg
->afx_hdl
->dev
);
13680 cfg
->afx_hdl
->peer_chan
= WL_INVALID
;
13682 complete(&cfg
->act_frm_scan
);
13683 WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
13684 } else if (wl_get_drv_status_all(cfg
, SENDING_ACT_FRM
)) {
13685 if (!(wl_get_p2p_status(cfg
, ACTION_TX_COMPLETED
) ||
13686 wl_get_p2p_status(cfg
, ACTION_TX_NOACK
)))
13687 wl_set_p2p_status(cfg
, ACTION_TX_COMPLETED
);
13689 WL_DBG(("*** Wake UP ** abort actframe iovar on bsscfxidx %d\n", bsscfgidx
));
13690 /* if channel is not zero, "actfame" uses off channel scan.
13691 * So abort scan for off channel completion.
13693 if (cfg
->af_sent_channel
) {
13694 /* Scan engine is not used for sending action frames in the latest driver
13695 * branches. So, actframe_abort is used in the latest driver branches
13696 * instead of scan abort.
13697 * New driver branches:
13698 * Issue actframe_abort and it succeeded. So, don't execute scan abort.
13699 * Old driver branches:
13700 * Issue actframe_abort and it fails. So, execute scan abort.
13702 err
= wldev_iovar_setint_bsscfg(ndev
, "actframe_abort", 1, bsscfgidx
);
13704 wl_cfg80211_scan_abort(cfg
);
13708 #ifdef WL_CFG80211_SYNC_GON
13709 else if (wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM_LISTEN
)) {
13710 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
13711 /* So abort scan to cancel listen */
13712 wl_cfg80211_scan_abort(cfg
);
13714 #endif /* WL_CFG80211_SYNC_GON */
13717 #if defined(WLTDLS)
13718 bool wl_cfg80211_is_tdls_tunneled_frame(void *frame
, u32 frame_len
)
13720 unsigned char *data
;
13722 if (frame
== NULL
) {
13723 WL_ERR(("Invalid frame \n"));
13727 if (frame_len
< 5) {
13728 WL_ERR(("Invalid frame length [%d] \n", frame_len
));
13734 if (!memcmp(data
, TDLS_TUNNELED_PRB_REQ
, 5) ||
13735 !memcmp(data
, TDLS_TUNNELED_PRB_RESP
, 5)) {
13736 WL_DBG(("TDLS Vendor Specific Received type\n"));
13742 #endif /* WLTDLS */
13745 int wl_cfg80211_get_ioctl_version(void)
13747 return ioctl_version
;
13751 wl_notify_rx_mgmt_frame(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13752 const wl_event_msg_t
*e
, void *data
)
13754 struct ieee80211_supported_band
*band
;
13755 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
13756 struct ether_addr da
;
13757 struct ether_addr bssid
;
13758 bool isfree
= false;
13761 #if defined(TDLS_MSG_ONLY_WFD)
13762 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
13763 #endif /* TDLS_MSG_ONLY_WFD && BCMDONGLEHOST */
13764 struct net_device
*ndev
= NULL
;
13765 wifi_p2p_pub_act_frame_t
*act_frm
= NULL
;
13766 wifi_p2p_action_frame_t
*p2p_act_frm
= NULL
;
13767 wifi_p2psd_gas_pub_act_frame_t
*sd_act_frm
= NULL
;
13768 wl_event_rx_frame_data_t
*rxframe
;
13772 u32 mgmt_frame_len
;
13774 if (ntoh32(e
->datalen
) < sizeof(wl_event_rx_frame_data_t
)) {
13775 WL_ERR(("wrong datalen:%d\n", ntoh32(e
->datalen
)));
13778 mgmt_frame_len
= ntoh32(e
->datalen
) - sizeof(wl_event_rx_frame_data_t
);
13779 event
= ntoh32(e
->event_type
);
13780 bsscfgidx
= e
->bsscfgidx
;
13781 rxframe
= (wl_event_rx_frame_data_t
*)data
;
13783 WL_ERR(("rxframe: NULL\n"));
13786 channel
= (ntoh16(rxframe
->channel
) & WL_CHANSPEC_CHAN_MASK
);
13787 memset(&bssid
, 0, ETHER_ADDR_LEN
);
13788 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13789 if ((ndev
->ieee80211_ptr
->iftype
!= NL80211_IFTYPE_AP
) &&
13790 (event
== WLC_E_PROBREQ_MSG
)) {
13791 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
13792 4 && __GNUC_MINOR__ >= 6))
13793 _Pragma("GCC diagnostic push")
13794 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
13796 struct net_info
*iter
, *next
;
13797 for_each_ndev(cfg
, iter
, next
) {
13798 if (iter
->ndev
&& iter
->wdev
&&
13799 iter
->wdev
->iftype
== NL80211_IFTYPE_AP
) {
13801 cfgdev
= ndev_to_cfgdev(ndev
);
13805 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
13806 4 && __GNUC_MINOR__ >= 6))
13807 _Pragma("GCC diagnostic pop")
13811 if (channel
<= CH_MAX_2G_CHANNEL
)
13812 band
= wiphy
->bands
[IEEE80211_BAND_2GHZ
];
13814 band
= wiphy
->bands
[IEEE80211_BAND_5GHZ
];
13816 WL_ERR(("No valid band\n"));
13819 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
13820 freq
= ieee80211_channel_to_frequency(channel
);
13823 freq
= ieee80211_channel_to_frequency(channel
, band
->band
);
13825 if (event
== WLC_E_ACTION_FRAME_RX
) {
13826 if ((err
= wldev_iovar_getbuf_bsscfg(ndev
, "cur_etheraddr",
13827 NULL
, 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, bsscfgidx
,
13828 &cfg
->ioctl_buf_sync
)) != BCME_OK
) {
13829 WL_ERR(("WLC_GET_CUR_ETHERADDR failed, error %d\n", err
));
13833 err
= wldev_ioctl_get(ndev
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
);
13835 WL_ERR(("WLC_GET_BSSID error %d\n", err
));
13836 memcpy(da
.octet
, cfg
->ioctl_buf
, ETHER_ADDR_LEN
);
13837 err
= wl_frame_get_mgmt(FC_ACTION
, &da
, &e
->addr
, &bssid
,
13838 &mgmt_frame
, &mgmt_frame_len
,
13839 (u8
*)((wl_event_rx_frame_data_t
*)rxframe
+ 1));
13841 WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
13842 mgmt_frame_len
, channel
, freq
));
13846 if (wl_cfgp2p_is_pub_action(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13847 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
)) {
13848 act_frm
= (wifi_p2p_pub_act_frame_t
*)
13849 (&mgmt_frame
[DOT11_MGMT_HDR_LEN
]);
13850 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13851 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
)) {
13852 p2p_act_frm
= (wifi_p2p_action_frame_t
*)
13853 (&mgmt_frame
[DOT11_MGMT_HDR_LEN
]);
13854 (void) p2p_act_frm
;
13855 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13856 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
)) {
13858 sd_act_frm
= (wifi_p2psd_gas_pub_act_frame_t
*)
13859 (&mgmt_frame
[DOT11_MGMT_HDR_LEN
]);
13860 if (sd_act_frm
&& wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM
)) {
13861 if (cfg
->next_af_subtype
== sd_act_frm
->action
) {
13862 WL_DBG(("We got a right next frame of SD!(%d)\n",
13863 sd_act_frm
->action
));
13864 wl_clr_drv_status(cfg
, WAITING_NEXT_ACT_FRM
, ndev
);
13866 /* Stop waiting for next AF. */
13867 wl_stop_wait_next_action_frame(cfg
, ndev
, bsscfgidx
);
13872 } else if ((mgmt_frame
[DOT11_MGMT_HDR_LEN
] == TDLS_AF_CATEGORY
) ||
13873 (wl_cfg80211_is_tdls_tunneled_frame(
13874 &mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13875 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
))) {
13876 if (mgmt_frame
[DOT11_MGMT_HDR_LEN
] == TDLS_AF_CATEGORY
) {
13877 WL_ERR((" TDLS Action Frame Received type = %d \n",
13878 mgmt_frame
[DOT11_MGMT_HDR_LEN
+ 1]));
13880 #ifdef TDLS_MSG_ONLY_WFD
13881 if (!dhdp
->tdls_mode
) {
13882 WL_DBG((" TDLS Frame filtered \n"));
13886 if (mgmt_frame
[DOT11_MGMT_HDR_LEN
+ 1] == TDLS_ACTION_SETUP_RESP
) {
13887 cfg
->tdls_mgmt_frame
= mgmt_frame
;
13888 cfg
->tdls_mgmt_frame_len
= mgmt_frame_len
;
13889 cfg
->tdls_mgmt_freq
= freq
;
13892 #endif /* TDLS_MSG_ONLY_WFD */
13893 #endif /* WLTDLS */
13895 } else if (mgmt_frame
[DOT11_MGMT_HDR_LEN
] == DOT11_ACTION_CAT_QOS
) {
13896 /* update QoS map set table */
13897 bcm_tlv_t
* qos_map_ie
= NULL
;
13898 if ((qos_map_ie
= bcm_parse_tlvs(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13899 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
,
13900 DOT11_MNG_QOS_MAP_ID
)) != NULL
) {
13901 WL_DBG((" QoS map set IE found in QoS action frame\n"));
13902 if (!cfg
->up_table
) {
13903 cfg
->up_table
= kmalloc(UP_TABLE_MAX
, GFP_KERNEL
);
13905 wl_set_up_table(cfg
->up_table
, qos_map_ie
);
13907 kfree(cfg
->up_table
);
13908 cfg
->up_table
= NULL
;
13910 #endif /* QOS_MAP_SET */
13912 } else if (mgmt_frame
[DOT11_MGMT_HDR_LEN
] == DOT11_ACTION_CAT_RRM
) {
13913 /* radio measurement category */
13914 switch (mgmt_frame
[DOT11_MGMT_HDR_LEN
+1]) {
13915 case DOT11_RM_ACTION_NR_REP
:
13916 if (wl_cfg80211_recv_nbr_resp(ndev
,
13917 &mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13918 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
)
13920 WL_DBG(("RCC updated by nbr response\n"));
13926 #endif /* WBTEXT */
13929 * if we got normal action frame and ndev is p2p0,
13930 * we have to change ndev from p2p0 to wlan0
13934 if (cfg
->next_af_subtype
!= P2P_PAF_SUBTYPE_INVALID
) {
13936 if (wl_get_public_action(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13937 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
, &action
) != BCME_OK
) {
13938 WL_DBG(("Recived action is not public action frame\n"));
13939 } else if (cfg
->next_af_subtype
== action
) {
13940 WL_DBG(("Recived action is the waiting action(%d)\n",
13942 wl_clr_drv_status(cfg
, WAITING_NEXT_ACT_FRM
, ndev
);
13944 /* Stop waiting for next AF. */
13945 wl_stop_wait_next_action_frame(cfg
, ndev
, bsscfgidx
);
13952 if (wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM
)) {
13953 if (cfg
->next_af_subtype
== act_frm
->subtype
) {
13954 WL_DBG(("We got a right next frame!(%d)\n",
13955 act_frm
->subtype
));
13956 wl_clr_drv_status(cfg
, WAITING_NEXT_ACT_FRM
, ndev
);
13958 if (cfg
->next_af_subtype
== P2P_PAF_GON_CONF
) {
13962 /* Stop waiting for next AF. */
13963 wl_stop_wait_next_action_frame(cfg
, ndev
, bsscfgidx
);
13968 wl_cfgp2p_print_actframe(false, &mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13969 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
, channel
);
13970 if (act_frm
&& (act_frm
->subtype
== P2P_PAF_GON_CONF
)) {
13971 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
13972 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
13974 } else if (event
== WLC_E_PROBREQ_MSG
) {
13976 /* Handle probe reqs frame
13977 * WPS-AP certification 4.2.13
13979 struct parsed_ies prbreq_ies
;
13980 u32 prbreq_ie_len
= 0;
13983 WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
13984 mgmt_frame
= (u8
*)(data
);
13985 mgmt_frame_len
= ntoh32(e
->datalen
);
13986 if (mgmt_frame_len
< DOT11_MGMT_HDR_LEN
) {
13987 WL_ERR(("wrong datalen:%d\n", mgmt_frame_len
));
13990 prbreq_ie_len
= mgmt_frame_len
- DOT11_MGMT_HDR_LEN
;
13992 /* Parse prob_req IEs */
13993 if (wl_cfg80211_parse_ies(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13994 prbreq_ie_len
, &prbreq_ies
) < 0) {
13995 WL_ERR(("Prob req get IEs failed\n"));
13998 if (prbreq_ies
.wps_ie
!= NULL
) {
13999 wl_validate_wps_ie((char *)prbreq_ies
.wps_ie
, prbreq_ies
.wps_ie_len
, &pbc
);
14000 WL_DBG((" wps_ie exist pbc = %d\n", pbc
));
14001 /* if pbc method, send prob_req mgmt frame to upper layer */
14007 mgmt_frame
= (u8
*)((wl_event_rx_frame_data_t
*)rxframe
+ 1);
14009 /* wpa supplicant use probe request event for restarting another GON Req.
14010 * but it makes GON Req repetition.
14011 * so if src addr of prb req is same as my target device,
14012 * do not send probe request event during sending action frame.
14014 if (event
== WLC_E_P2P_PROBREQ_MSG
) {
14015 WL_DBG((" Event %s\n", (event
== WLC_E_P2P_PROBREQ_MSG
) ?
14016 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
14019 /* Filter any P2P probe reqs arriving during the
14023 #if defined(P2P_IE_MISSING_FIX)
14024 cfg
->p2p_prb_noti
&&
14026 wl_get_p2p_status(cfg
, GO_NEG_PHASE
)) {
14027 WL_DBG(("Filtering P2P probe_req while "
14028 "being in GO-Neg state\n"));
14034 if (discover_cfgdev(cfgdev
, cfg
))
14035 WL_DBG(("Rx Managment frame For P2P Discovery Interface \n"));
14037 WL_DBG(("Rx Managment frame For Iface (%s) \n", ndev
->name
));
14038 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
14039 cfg80211_rx_mgmt(cfgdev
, freq
, 0, mgmt_frame
, mgmt_frame_len
, 0);
14040 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14041 cfg80211_rx_mgmt(cfgdev
, freq
, 0, mgmt_frame
, mgmt_frame_len
, 0, GFP_ATOMIC
);
14042 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
14043 defined(WL_COMPAT_WIRELESS)
14044 cfg80211_rx_mgmt(cfgdev
, freq
, 0, mgmt_frame
, mgmt_frame_len
, GFP_ATOMIC
);
14046 cfg80211_rx_mgmt(cfgdev
, freq
, mgmt_frame
, mgmt_frame_len
, GFP_ATOMIC
);
14047 #endif /* LINUX_VERSION >= VERSION(3, 18, 0) */
14049 WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
14050 mgmt_frame_len
, ntoh32(e
->datalen
), channel
, freq
));
14057 #ifdef WL_SCHED_SCAN
14058 /* If target scan is not reliable, set the below define to "1" to do a
14061 #define FULL_ESCAN_ON_PFN_NET_FOUND 0
14063 wl_notify_sched_scan_results(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
14064 const wl_event_msg_t
*e
, void *data
)
14066 wl_pfn_net_info_v2_t
*netinfo
, *pnetinfo
;
14067 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
14068 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
14070 struct cfg80211_scan_request
*request
= NULL
;
14071 struct cfg80211_ssid ssid
[MAX_PFN_LIST_COUNT
];
14072 struct ieee80211_channel
*channel
= NULL
;
14073 int channel_req
= 0;
14075 wl_pfn_scanresults_t
*pfn_result
= (wl_pfn_scanresults_t
*)data
;
14076 int n_pfn_results
= pfn_result
->count
;
14077 log_conn_event_t
*event_data
= NULL
;
14078 tlv_log
*tlv_data
= NULL
;
14079 u32 alloc_len
, tlv_len
;
14082 WL_DBG(("Enter\n"));
14084 if (pfn_result
->version
!= PFN_SCANRESULT_VERSION
) {
14085 WL_ERR(("Incorrect version %d, expected %d\n", pfn_result
->version
,
14086 PFN_SCANRESULT_VERSION
));
14087 return BCME_VERSION
;
14090 if (e
->event_type
== WLC_E_PFN_NET_LOST
) {
14091 WL_PNO(("PFN NET LOST event. Do Nothing\n"));
14095 WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results
));
14096 if (n_pfn_results
> 0) {
14099 if (n_pfn_results
> MAX_PFN_LIST_COUNT
)
14100 n_pfn_results
= MAX_PFN_LIST_COUNT
;
14101 pnetinfo
= (wl_pfn_net_info_v2_t
*)((char *)data
+ sizeof(wl_pfn_scanresults_v2_t
)
14102 - sizeof(wl_pfn_net_info_v2_t
));
14104 memset(&ssid
, 0x00, sizeof(ssid
));
14106 request
= kzalloc(sizeof(*request
)
14107 + sizeof(*request
->channels
) * n_pfn_results
,
14109 channel
= (struct ieee80211_channel
*)kzalloc(
14110 (sizeof(struct ieee80211_channel
) * n_pfn_results
),
14112 if (!request
|| !channel
) {
14113 WL_ERR(("No memory"));
14118 request
->wiphy
= wiphy
;
14120 if (DBG_RING_ACTIVE(dhdp
, DHD_EVENT_RING_ID
)) {
14121 alloc_len
= sizeof(log_conn_event_t
) + DOT11_MAX_SSID_LEN
+ sizeof(uint16
) +
14123 event_data
= MALLOC(dhdp
->osh
, alloc_len
);
14125 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
14126 "length(%d)\n", __func__
, alloc_len
));
14129 tlv_len
= 3 * sizeof(tlv_log
);
14130 event_data
->tlvs
= MALLOC(dhdp
->osh
, tlv_len
);
14131 if (!event_data
->tlvs
) {
14132 WL_ERR(("%s: failed to allocate the tlv_log with "
14133 "length(%d)\n", __func__
, tlv_len
));
14138 for (i
= 0; i
< n_pfn_results
; i
++) {
14139 netinfo
= &pnetinfo
[i
];
14141 WL_ERR(("Invalid netinfo ptr. index:%d", i
));
14145 WL_PNO((">>> SSID:%s Channel:%d \n",
14146 netinfo
->pfnsubnet
.u
.SSID
, netinfo
->pfnsubnet
.channel
));
14147 /* PFN result doesn't have all the info which are required by the supplicant
14148 * (For e.g IEs) Do a target Escan so that sched scan results are reported
14149 * via wl_inform_single_bss in the required format. Escan does require the
14150 * scan request in the form of cfg80211_scan_request. For timebeing, create
14151 * cfg80211_scan_request one out of the received PNO event.
14153 ssid
[i
].ssid_len
= MIN(DOT11_MAX_SSID_LEN
, netinfo
->pfnsubnet
.SSID_len
);
14154 memcpy(ssid
[i
].ssid
, netinfo
->pfnsubnet
.u
.SSID
,
14156 request
->n_ssids
++;
14158 channel_req
= netinfo
->pfnsubnet
.channel
;
14159 band
= (channel_req
<= CH_MAX_2G_CHANNEL
) ? NL80211_BAND_2GHZ
14160 : NL80211_BAND_5GHZ
;
14161 channel
[i
].center_freq
= ieee80211_channel_to_frequency(channel_req
, band
);
14162 channel
[i
].band
= band
;
14163 channel
[i
].flags
|= IEEE80211_CHAN_NO_HT40
;
14164 request
->channels
[i
] = &channel
[i
];
14165 request
->n_channels
++;
14167 if (DBG_RING_ACTIVE(dhdp
, DHD_EVENT_RING_ID
)) {
14168 payload_len
= sizeof(log_conn_event_t
);
14169 event_data
->event
= WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND
;
14170 tlv_data
= event_data
->tlvs
;
14173 tlv_data
->tag
= WIFI_TAG_SSID
;
14174 tlv_data
->len
= netinfo
->pfnsubnet
.SSID_len
;
14175 memcpy(tlv_data
->value
, ssid
[i
].ssid
, ssid
[i
].ssid_len
);
14176 payload_len
+= TLV_LOG_SIZE(tlv_data
);
14177 tlv_data
= TLV_LOG_NEXT(tlv_data
);
14180 tlv_data
->tag
= WIFI_TAG_CHANNEL
;
14181 tlv_data
->len
= sizeof(uint16
);
14182 memcpy(tlv_data
->value
, &channel_req
, sizeof(uint16
));
14183 payload_len
+= TLV_LOG_SIZE(tlv_data
);
14184 tlv_data
= TLV_LOG_NEXT(tlv_data
);
14187 tlv_data
->tag
= WIFI_TAG_RSSI
;
14188 tlv_data
->len
= sizeof(int16
);
14189 memcpy(tlv_data
->value
, &netinfo
->RSSI
, sizeof(int16
));
14190 payload_len
+= TLV_LOG_SIZE(tlv_data
);
14191 tlv_data
= TLV_LOG_NEXT(tlv_data
);
14193 dhd_os_push_push_ring_data(dhdp
, DHD_EVENT_RING_ID
,
14194 &event_data
->event
, payload_len
);
14198 /* assign parsed ssid array */
14199 if (request
->n_ssids
)
14200 request
->ssids
= &ssid
[0];
14202 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
14203 /* Abort any on-going scan */
14204 wl_notify_escan_complete(cfg
, ndev
, true, true);
14207 if (wl_get_p2p_status(cfg
, DISCOVERY_ON
)) {
14208 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
14209 err
= wl_cfgp2p_discover_enable_search(cfg
, false);
14210 if (unlikely(err
)) {
14211 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
14214 p2p_scan(cfg
) = false;
14217 wl_set_drv_status(cfg
, SCANNING
, ndev
);
14218 #if FULL_ESCAN_ON_PFN_NET_FOUND
14219 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
14220 err
= wl_do_escan(cfg
, wiphy
, ndev
, NULL
);
14222 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
14223 err
= wl_do_escan(cfg
, wiphy
, ndev
, request
);
14226 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
14229 DBG_EVENT_LOG(dhdp
, WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED
);
14230 cfg
->sched_scan_running
= TRUE
;
14233 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
14242 MFREE(dhdp
->osh
, event_data
->tlvs
, tlv_len
);
14243 MFREE(dhdp
->osh
, event_data
, alloc_len
);
14247 #endif /* WL_SCHED_SCAN */
14249 static void wl_init_conf(struct wl_conf
*conf
)
14251 WL_DBG(("Enter \n"));
14252 conf
->frag_threshold
= (u32
)-1;
14253 conf
->rts_threshold
= (u32
)-1;
14254 conf
->retry_short
= (u32
)-1;
14255 conf
->retry_long
= (u32
)-1;
14256 conf
->tx_power
= -1;
14259 static void wl_init_prof(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
)
14261 unsigned long flags
;
14262 struct wl_profile
*profile
= wl_get_profile_by_netdev(cfg
, ndev
);
14265 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
14266 memset(profile
, 0, sizeof(struct wl_profile
));
14267 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
14269 WL_ERR(("%s: No profile\n", __FUNCTION__
));
14274 static void wl_init_event_handler(struct bcm_cfg80211
*cfg
)
14276 memset(cfg
->evt_handler
, 0, sizeof(cfg
->evt_handler
));
14278 cfg
->evt_handler
[WLC_E_SCAN_COMPLETE
] = wl_notify_scan_status
;
14279 cfg
->evt_handler
[WLC_E_AUTH
] = wl_notify_connect_status
;
14280 cfg
->evt_handler
[WLC_E_ASSOC
] = wl_notify_connect_status
;
14281 cfg
->evt_handler
[WLC_E_LINK
] = wl_notify_connect_status
;
14282 cfg
->evt_handler
[WLC_E_DEAUTH_IND
] = wl_notify_connect_status
;
14283 cfg
->evt_handler
[WLC_E_DEAUTH
] = wl_notify_connect_status
;
14284 cfg
->evt_handler
[WLC_E_DISASSOC_IND
] = wl_notify_connect_status
;
14285 cfg
->evt_handler
[WLC_E_ASSOC_IND
] = wl_notify_connect_status
;
14286 cfg
->evt_handler
[WLC_E_REASSOC_IND
] = wl_notify_connect_status
;
14287 cfg
->evt_handler
[WLC_E_ROAM
] = wl_notify_roaming_status
;
14288 cfg
->evt_handler
[WLC_E_MIC_ERROR
] = wl_notify_mic_status
;
14289 cfg
->evt_handler
[WLC_E_SET_SSID
] = wl_notify_connect_status
;
14290 cfg
->evt_handler
[WLC_E_ACTION_FRAME_RX
] = wl_notify_rx_mgmt_frame
;
14291 cfg
->evt_handler
[WLC_E_PROBREQ_MSG
] = wl_notify_rx_mgmt_frame
;
14292 cfg
->evt_handler
[WLC_E_P2P_PROBREQ_MSG
] = wl_notify_rx_mgmt_frame
;
14293 cfg
->evt_handler
[WLC_E_P2P_DISC_LISTEN_COMPLETE
] = wl_cfgp2p_listen_complete
;
14294 cfg
->evt_handler
[WLC_E_ACTION_FRAME_COMPLETE
] = wl_cfgp2p_action_tx_complete
;
14295 cfg
->evt_handler
[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE
] = wl_cfgp2p_action_tx_complete
;
14296 cfg
->evt_handler
[WLC_E_JOIN
] = wl_notify_connect_status
;
14297 cfg
->evt_handler
[WLC_E_START
] = wl_notify_connect_status
;
14299 cfg
->evt_handler
[WLC_E_PFN_NET_FOUND
] = wl_notify_pfn_status
;
14300 #endif /* PNO_SUPPORT */
14301 #ifdef GSCAN_SUPPORT
14302 cfg
->evt_handler
[WLC_E_PFN_BEST_BATCHING
] = wl_notify_gscan_event
;
14303 cfg
->evt_handler
[WLC_E_PFN_SCAN_COMPLETE
] = wl_notify_gscan_event
;
14304 cfg
->evt_handler
[WLC_E_PFN_GSCAN_FULL_RESULT
] = wl_notify_gscan_event
;
14305 cfg
->evt_handler
[WLC_E_PFN_BSSID_NET_FOUND
] = wl_notify_gscan_event
;
14306 cfg
->evt_handler
[WLC_E_PFN_BSSID_NET_LOST
] = wl_notify_gscan_event
;
14307 cfg
->evt_handler
[WLC_E_PFN_SSID_EXT
] = wl_notify_gscan_event
;
14308 cfg
->evt_handler
[WLC_E_GAS_FRAGMENT_RX
] = wl_notify_gscan_event
;
14309 cfg
->evt_handler
[WLC_E_ROAM_EXP_EVENT
] = wl_handle_roam_exp_event
;
14310 #endif /* GSCAN_SUPPORT */
14311 #ifdef RSSI_MONITOR_SUPPORT
14312 cfg
->evt_handler
[WLC_E_RSSI_LQM
] = wl_handle_rssi_monitor_event
;
14313 #endif /* RSSI_MONITOR_SUPPORT */
14315 cfg
->evt_handler
[WLC_E_TDLS_PEER_EVENT
] = wl_tdls_event_handler
;
14316 #endif /* WLTDLS */
14317 cfg
->evt_handler
[WLC_E_BSSID
] = wl_notify_roaming_status
;
14319 cfg
->evt_handler
[WLC_E_RMC_EVENT
] = wl_notify_rmc_status
;
14320 #endif /* WL_RELMCAST */
14321 #ifdef BT_WIFI_HANDOVER
14322 cfg
->evt_handler
[WLC_E_BT_WIFI_HANDOVER_REQ
] = wl_notify_bt_wifi_handover_req
;
14324 cfg
->evt_handler
[WLC_E_CSA_COMPLETE_IND
] = wl_csa_complete_ind
;
14325 cfg
->evt_handler
[WLC_E_AP_STARTED
] = wl_ap_start_ind
;
14326 #ifdef CUSTOM_EVENT_PM_WAKE
14327 cfg
->evt_handler
[WLC_E_EXCESS_PM_WAKE_EVENT
] = wl_check_pmstatus
;
14328 #endif /* CUSTOM_EVENT_PM_WAKE */
14329 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
14330 cfg
->evt_handler
[WLC_E_ROAM_PREP
] = wl_notify_roam_prep_status
;
14331 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
14332 #ifdef ENABLE_TEMP_THROTTLING
14333 cfg
->evt_handler
[WLC_E_TEMP_THROTTLE
] = wl_check_rx_throttle_status
;
14334 #endif /* ENABLE_TEMP_THROTTLING */
14338 #if defined(STATIC_WL_PRIV_STRUCT)
14340 wl_init_escan_result_buf(struct bcm_cfg80211
*cfg
)
14342 cfg
->escan_info
.escan_buf
= DHD_OS_PREALLOC(cfg
->pub
,
14343 DHD_PREALLOC_WIPHY_ESCAN0
, ESCAN_BUF_SIZE
);
14344 if (cfg
->escan_info
.escan_buf
== NULL
) {
14345 WL_ERR(("Failed to alloc ESCAN_BUF\n"));
14348 bzero(cfg
->escan_info
.escan_buf
, ESCAN_BUF_SIZE
);
14354 wl_deinit_escan_result_buf(struct bcm_cfg80211
*cfg
)
14356 if (cfg
->escan_info
.escan_buf
!= NULL
) {
14357 cfg
->escan_info
.escan_buf
= NULL
;
14360 #endif /* STATIC_WL_PRIV_STRUCT */
14362 static s32
wl_init_priv_mem(struct bcm_cfg80211
*cfg
)
14364 WL_DBG(("Enter \n"));
14366 cfg
->scan_results
= (void *)kzalloc(WL_SCAN_BUF_MAX
, GFP_KERNEL
);
14367 if (unlikely(!cfg
->scan_results
)) {
14368 WL_ERR(("Scan results alloc failed\n"));
14369 goto init_priv_mem_out
;
14371 cfg
->conf
= (void *)kzalloc(sizeof(*cfg
->conf
), GFP_KERNEL
);
14372 if (unlikely(!cfg
->conf
)) {
14373 WL_ERR(("wl_conf alloc failed\n"));
14374 goto init_priv_mem_out
;
14376 cfg
->scan_req_int
=
14377 (void *)kzalloc(sizeof(*cfg
->scan_req_int
), GFP_KERNEL
);
14378 if (unlikely(!cfg
->scan_req_int
)) {
14379 WL_ERR(("Scan req alloc failed\n"));
14380 goto init_priv_mem_out
;
14382 cfg
->ioctl_buf
= (void *)kzalloc(WLC_IOCTL_MAXLEN
, GFP_KERNEL
);
14383 if (unlikely(!cfg
->ioctl_buf
)) {
14384 WL_ERR(("Ioctl buf alloc failed\n"));
14385 goto init_priv_mem_out
;
14387 cfg
->escan_ioctl_buf
= (void *)kzalloc(WLC_IOCTL_MAXLEN
, GFP_KERNEL
);
14388 if (unlikely(!cfg
->escan_ioctl_buf
)) {
14389 WL_ERR(("Ioctl buf alloc failed\n"));
14390 goto init_priv_mem_out
;
14392 cfg
->extra_buf
= (void *)kzalloc(WL_EXTRA_BUF_MAX
, GFP_KERNEL
);
14393 if (unlikely(!cfg
->extra_buf
)) {
14394 WL_ERR(("Extra buf alloc failed\n"));
14395 goto init_priv_mem_out
;
14397 cfg
->pmk_list
= (void *)kzalloc(sizeof(*cfg
->pmk_list
), GFP_KERNEL
);
14398 if (unlikely(!cfg
->pmk_list
)) {
14399 WL_ERR(("pmk list alloc failed\n"));
14400 goto init_priv_mem_out
;
14402 #if defined(STATIC_WL_PRIV_STRUCT)
14403 cfg
->conn_info
= (void *)kzalloc(sizeof(*cfg
->conn_info
), GFP_KERNEL
);
14404 if (unlikely(!cfg
->conn_info
)) {
14405 WL_ERR(("cfg->conn_info alloc failed\n"));
14406 goto init_priv_mem_out
;
14408 cfg
->ie
= (void *)kzalloc(sizeof(*cfg
->ie
), GFP_KERNEL
);
14409 if (unlikely(!cfg
->ie
)) {
14410 WL_ERR(("cfg->ie alloc failed\n"));
14411 goto init_priv_mem_out
;
14413 if (unlikely(wl_init_escan_result_buf(cfg
))) {
14414 WL_ERR(("Failed to init escan resul buf\n"));
14415 goto init_priv_mem_out
;
14417 #endif /* STATIC_WL_PRIV_STRUCT */
14418 cfg
->afx_hdl
= (void *)kzalloc(sizeof(*cfg
->afx_hdl
), GFP_KERNEL
);
14419 if (unlikely(!cfg
->afx_hdl
)) {
14420 WL_ERR(("afx hdl alloc failed\n"));
14421 goto init_priv_mem_out
;
14423 init_completion(&cfg
->act_frm_scan
);
14424 init_completion(&cfg
->wait_next_af
);
14426 INIT_WORK(&cfg
->afx_hdl
->work
, wl_cfg80211_afx_handler
);
14429 if (cfg
->tdls_mgmt_frame
) {
14430 kfree(cfg
->tdls_mgmt_frame
);
14431 cfg
->tdls_mgmt_frame
= NULL
;
14433 #endif /* WLTDLS */
14437 wl_deinit_priv_mem(cfg
);
14442 static void wl_deinit_priv_mem(struct bcm_cfg80211
*cfg
)
14444 kfree(cfg
->scan_results
);
14445 cfg
->scan_results
= NULL
;
14448 kfree(cfg
->scan_req_int
);
14449 cfg
->scan_req_int
= NULL
;
14450 kfree(cfg
->ioctl_buf
);
14451 cfg
->ioctl_buf
= NULL
;
14452 kfree(cfg
->escan_ioctl_buf
);
14453 cfg
->escan_ioctl_buf
= NULL
;
14454 kfree(cfg
->extra_buf
);
14455 cfg
->extra_buf
= NULL
;
14456 kfree(cfg
->pmk_list
);
14457 cfg
->pmk_list
= NULL
;
14458 #if defined(STATIC_WL_PRIV_STRUCT)
14459 kfree(cfg
->conn_info
);
14460 cfg
->conn_info
= NULL
;
14463 wl_deinit_escan_result_buf(cfg
);
14464 #endif /* STATIC_WL_PRIV_STRUCT */
14465 if (cfg
->afx_hdl
) {
14466 cancel_work_sync(&cfg
->afx_hdl
->work
);
14467 kfree(cfg
->afx_hdl
);
14468 cfg
->afx_hdl
= NULL
;
14473 static s32
wl_create_event_handler(struct bcm_cfg80211
*cfg
)
14476 WL_DBG(("Enter \n"));
14478 /* Allocate workqueue for event */
14479 if (!cfg
->event_workq
) {
14480 cfg
->event_workq
= alloc_workqueue("dhd_eventd", WQ_MEM_RECLAIM
| WQ_HIGHPRI
, 0);
14483 if (!cfg
->event_workq
) {
14484 WL_ERR(("event_workq alloc_workqueue failed\n"));
14487 INIT_WORK(&cfg
->event_work
, wl_event_handler
);
14492 static void wl_destroy_event_handler(struct bcm_cfg80211
*cfg
)
14494 if (cfg
&& cfg
->event_workq
) {
14495 cancel_work_sync(&cfg
->event_work
);
14496 destroy_workqueue(cfg
->event_workq
);
14497 cfg
->event_workq
= NULL
;
14501 void wl_terminate_event_handler(struct net_device
*dev
)
14503 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
14506 wl_destroy_event_handler(cfg
);
14511 static void wl_scan_timeout(
14512 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
14513 struct timer_list
*t
14519 wl_event_msg_t msg
;
14520 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
14521 struct bcm_cfg80211
*cfg
= from_timer(cfg
, t
, scan_timeout
);
14523 struct bcm_cfg80211
*cfg
= (struct bcm_cfg80211
*)data
;
14525 struct wireless_dev
*wdev
= NULL
;
14526 struct net_device
*ndev
= NULL
;
14527 struct wl_scan_results
*bss_list
;
14528 struct wl_bss_info
*bi
= NULL
;
14532 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
14533 uint32 prev_memdump_mode
= dhdp
->memdump_enabled
;
14534 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
14536 if (!(cfg
->scan_request
)) {
14537 WL_ERR(("timer expired but no scan request\n"));
14541 bss_list
= wl_escan_get_buf(cfg
, FALSE
);
14543 WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
14545 WL_ERR(("scanned AP count (%d)\n", bss_list
->count
));
14547 bi
= next_bss(bss_list
, bi
);
14548 for_each_bss(bss_list
, bi
, i
) {
14549 if (bi
!= NULL
&& &(bi
->chanspec
) != NULL
&& (bi
->SSID
)) {
14550 channel
= wf_chspec_ctlchan(wl_chspec_driver_to_host(bi
->chanspec
));
14551 WL_ERR(("SSID :%s SSID_LEN :%d Channel :%d\n", bi
->SSID
, bi
->SSID_len
, channel
));
14552 if (bi
->SSID
[0] == '\0') {
14553 WL_ERR(("SSID :%s is null ssid_len:%d ,need return\n", bi
->SSID
, bi
->SSID_len
));
14557 WL_ERR(("SSID or Channel is null\n"));
14563 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
14564 if (cfg
->scan_request
->dev
)
14565 wdev
= cfg
->scan_request
->dev
->ieee80211_ptr
;
14567 if (cfg
->scan_request
)
14568 wdev
= cfg
->scan_request
->wdev
;
14569 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
14571 WL_ERR(("No wireless_dev present\n"));
14574 ndev
= wdev_to_wlc_ndev(wdev
, cfg
);
14576 bzero(&msg
, sizeof(wl_event_msg_t
));
14577 WL_ERR(("timer expired\n"));
14579 if (dhdp
->memdump_enabled
) {
14580 dhdp
->memdump_enabled
= DUMP_MEMFILE
;
14581 dhdp
->memdump_type
= DUMP_TYPE_SCAN_TIMEOUT
;
14582 dhd_bus_mem_dump(dhdp
);
14583 dhdp
->memdump_enabled
= prev_memdump_mode
;
14585 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
14586 msg
.event_type
= hton32(WLC_E_ESCAN_RESULT
);
14587 msg
.status
= hton32(WLC_E_STATUS_TIMEOUT
);
14588 msg
.reason
= 0xFFFFFFFF;
14589 wl_cfg80211_event(ndev
, &msg
, NULL
);
14590 #ifdef CUSTOMER_HW4_DEBUG
14591 if (!wl_scan_timeout_dbg_enabled
)
14592 wl_scan_timeout_dbg_set();
14593 #endif /* CUSTOMER_HW4_DEBUG */
14595 // terence 20130729: workaround to fix out of memory in firmware
14596 // if (dhd_conf_get_chip(dhd_get_pub(ndev)) == BCM43362_CHIP_ID) {
14597 // WL_ERR(("Send hang event\n"));
14598 // net_os_send_hang_message(ndev);
14602 #ifdef DHD_LOSSLESS_ROAMING
14603 static void wl_del_roam_timeout(struct bcm_cfg80211
*cfg
)
14605 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
14607 /* restore prec_map to ALLPRIO */
14608 dhdp
->dequeue_prec_map
= ALLPRIO
;
14609 if (timer_pending(&cfg
->roam_timeout
)) {
14610 del_timer_sync(&cfg
->roam_timeout
);
14615 static void wl_roam_timeout(
14616 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
14617 struct timer_list
*t
14623 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
14624 struct bcm_cfg80211
*cfg
= from_timer(cfg
, t
, roam_timeout
);
14626 struct bcm_cfg80211
*cfg
= (struct bcm_cfg80211
*)data
;
14628 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
14630 WL_ERR(("roam timer expired\n"));
14632 /* restore prec_map to ALLPRIO */
14633 dhdp
->dequeue_prec_map
= ALLPRIO
;
14636 #endif /* DHD_LOSSLESS_ROAMING */
14639 wl_cfg80211_netdev_notifier_call(struct notifier_block
* nb
,
14640 unsigned long state
, void *ptr
)
14642 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
14643 struct net_device
*dev
= ptr
;
14645 struct net_device
*dev
= netdev_notifier_info_to_dev(ptr
);
14646 #endif /* LINUX_VERSION < VERSION(3, 11, 0) */
14647 struct wireless_dev
*wdev
= ndev_to_wdev(dev
);
14648 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
14650 WL_DBG(("Enter \n"));
14652 if (!wdev
|| !cfg
|| dev
== bcmcfg_to_prmry_ndev(cfg
))
14653 return NOTIFY_DONE
;
14658 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
14659 int max_wait_timeout
= 2;
14660 int max_wait_count
= 100;
14662 unsigned long limit
= jiffies
+ max_wait_timeout
* HZ
;
14663 while (work_pending(&wdev
->cleanup_work
)) {
14664 if (refcnt
%5 == 0) {
14665 WL_ERR(("[NETDEV_DOWN] wait for "
14666 "complete of cleanup_work"
14667 " (%d th)\n", refcnt
));
14669 if (!time_before(jiffies
, limit
)) {
14670 WL_ERR(("[NETDEV_DOWN] cleanup_work"
14671 " of CFG80211 is not"
14672 " completed in %d sec\n",
14673 max_wait_timeout
));
14676 if (refcnt
>= max_wait_count
) {
14677 WL_ERR(("[NETDEV_DOWN] cleanup_work"
14678 " of CFG80211 is not"
14679 " completed in %d loop\n",
14683 set_current_state(TASK_INTERRUPTIBLE
);
14684 (void)schedule_timeout(100);
14685 set_current_state(TASK_RUNNING
);
14688 #endif /* LINUX_VERSION < VERSION(3, 14, 0) */
14691 case NETDEV_UNREGISTER
:
14692 /* after calling list_del_rcu(&wdev->list) */
14693 wl_cfg80211_clear_per_bss_ies(cfg
,
14694 wl_get_bssidx_by_wdev(cfg
, wdev
));
14695 wl_dealloc_netinfo_by_wdev(cfg
, wdev
);
14697 case NETDEV_GOING_DOWN
:
14699 * At NETDEV_DOWN state, wdev_cleanup_work work will be called.
14700 * In front of door, the function checks whether current scan
14701 * is working or not. If the scanning is still working,
14702 * wdev_cleanup_work call WARN_ON and make the scan done forcibly.
14704 if (wl_get_drv_status(cfg
, SCANNING
, dev
))
14705 wl_notify_escan_complete(cfg
, dev
, true, true);
14708 return NOTIFY_DONE
;
14711 static struct notifier_block wl_cfg80211_netdev_notifier
= {
14712 .notifier_call
= wl_cfg80211_netdev_notifier_call
,
14716 * to make sure we won't register the same notifier twice, otherwise a loop is likely to be
14717 * created in kernel notifier link list (with 'next' pointing to itself)
14719 static bool wl_cfg80211_netdev_notifier_registered
= FALSE
;
14721 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211
*cfg
)
14723 struct wireless_dev
*wdev
= NULL
;
14724 struct net_device
*ndev
= NULL
;
14726 if (!cfg
->scan_request
)
14729 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
14730 if (cfg
->scan_request
->dev
)
14731 wdev
= cfg
->scan_request
->dev
->ieee80211_ptr
;
14733 wdev
= cfg
->scan_request
->wdev
;
14734 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
14737 WL_ERR(("No wireless_dev present\n"));
14741 ndev
= wdev_to_wlc_ndev(wdev
, cfg
);
14742 wl_notify_escan_complete(cfg
, ndev
, true, true);
14743 WL_ERR(("Scan aborted! \n"));
14746 void wl_cfg80211_scan_abort(struct bcm_cfg80211
*cfg
)
14748 wl_scan_params_t
*params
= NULL
;
14749 s32 params_size
= 0;
14751 struct net_device
*dev
= bcmcfg_to_prmry_ndev(cfg
);
14752 if (!in_atomic()) {
14753 /* Our scan params only need space for 1 channel and 0 ssids */
14754 params
= wl_cfg80211_scan_alloc_params(cfg
, -1, 0, ¶ms_size
);
14755 if (params
== NULL
) {
14756 WL_ERR(("scan params allocation failed \n"));
14759 /* Do a scan abort to stop the driver's scan engine */
14760 err
= wldev_ioctl_set(dev
, WLC_SCAN
, params
, params_size
);
14762 WL_ERR(("scan abort failed \n"));
14768 if (cfg
->tdls_mgmt_frame
) {
14769 kfree(cfg
->tdls_mgmt_frame
);
14770 cfg
->tdls_mgmt_frame
= NULL
;
14772 #endif /* WLTDLS */
14775 static s32
wl_notify_escan_complete(struct bcm_cfg80211
*cfg
,
14776 struct net_device
*ndev
,
14777 bool aborted
, bool fw_abort
)
14780 unsigned long flags
;
14781 struct net_device
*dev
;
14782 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
14783 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
14784 struct cfg80211_scan_info info
;
14785 info
.aborted
= aborted
;
14788 WL_DBG(("Enter \n"));
14789 BCM_REFERENCE(dhdp
);
14791 mutex_lock(&cfg
->scan_complete
);
14794 WL_ERR(("ndev is null\n"));
14799 if (cfg
->escan_info
.ndev
!= ndev
) {
14800 WL_ERR(("ndev is different %p %p\n", cfg
->escan_info
.ndev
, ndev
));
14805 if (cfg
->scan_request
) {
14806 dev
= bcmcfg_to_prmry_ndev(cfg
);
14807 #if defined(WL_ENABLE_P2P_IF)
14808 if (cfg
->scan_request
->dev
!= cfg
->p2p_net
)
14809 dev
= cfg
->scan_request
->dev
;
14810 #elif defined(WL_CFG80211_P2P_DEV_IF)
14811 if (cfg
->scan_request
->wdev
->iftype
!= NL80211_IFTYPE_P2P_DEVICE
)
14812 dev
= cfg
->scan_request
->wdev
->netdev
;
14813 #endif /* WL_ENABLE_P2P_IF */
14816 WL_DBG(("cfg->scan_request is NULL may be internal scan."
14817 "doing scan_abort for ndev %p primary %p",
14818 ndev
, bcmcfg_to_prmry_ndev(cfg
)));
14821 if (fw_abort
&& !in_atomic())
14822 wl_cfg80211_scan_abort(cfg
);
14823 if (timer_pending(&cfg
->scan_timeout
))
14824 del_timer_sync(&cfg
->scan_timeout
);
14825 #if defined(ESCAN_RESULT_PATCH)
14826 if (likely(cfg
->scan_request
)) {
14827 cfg
->bss_list
= wl_escan_get_buf(cfg
, aborted
);
14828 wl_inform_bss(cfg
);
14830 #endif /* ESCAN_RESULT_PATCH */
14831 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
14832 #ifdef WL_SCHED_SCAN
14833 if (cfg
->sched_scan_req
&& !cfg
->scan_request
) {
14834 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
14836 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
14837 cfg80211_sched_scan_results(cfg
->sched_scan_req
->wiphy
, 0);
14839 cfg80211_sched_scan_results(cfg
->sched_scan_req
->wiphy
);
14840 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
14843 DBG_EVENT_LOG(dhdp
, WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE
);
14844 cfg
->sched_scan_running
= FALSE
;
14846 #endif /* WL_SCHED_SCAN */
14847 if (likely(cfg
->scan_request
)) {
14848 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
14849 cfg80211_scan_done(cfg
->scan_request
, &info
);
14851 cfg80211_scan_done(cfg
->scan_request
, aborted
);
14853 cfg
->scan_request
= NULL
;
14854 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t
*)(cfg
->pub
));
14855 DHD_ENABLE_RUNTIME_PM((dhd_pub_t
*)(cfg
->pub
));
14857 if (p2p_is_on(cfg
))
14858 wl_clr_p2p_status(cfg
, SCANNING
);
14859 wl_clr_drv_status(cfg
, SCANNING
, dev
);
14860 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
14863 mutex_unlock(&cfg
->scan_complete
);
14867 #ifdef ESCAN_BUF_OVERFLOW_MGMT
14868 #ifndef WL_DRV_AVOID_SCANCACHE
14870 wl_cfg80211_find_removal_candidate(wl_bss_info_t
*bss
, removal_element_t
*candidate
)
14873 for (idx
= 0; idx
< BUF_OVERFLOW_MGMT_COUNT
; idx
++) {
14874 int len
= BUF_OVERFLOW_MGMT_COUNT
- idx
- 1;
14875 if (bss
->RSSI
< candidate
[idx
].RSSI
) {
14877 memcpy(&candidate
[idx
+ 1], &candidate
[idx
],
14878 sizeof(removal_element_t
) * len
);
14879 candidate
[idx
].RSSI
= bss
->RSSI
;
14880 candidate
[idx
].length
= bss
->length
;
14881 memcpy(&candidate
[idx
].BSSID
, &bss
->BSSID
, ETHER_ADDR_LEN
);
14888 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t
*list
, removal_element_t
*candidate
,
14892 int total_delete_len
= 0;
14893 for (idx1
= 0; idx1
< BUF_OVERFLOW_MGMT_COUNT
; idx1
++) {
14894 int cur_len
= WL_SCAN_RESULTS_FIXED_SIZE
;
14895 wl_bss_info_t
*bss
= NULL
;
14896 if (candidate
[idx1
].RSSI
>= bi
->RSSI
)
14898 for (idx2
= 0; idx2
< list
->count
; idx2
++) {
14899 bss
= bss
? (wl_bss_info_t
*)((uintptr
)bss
+ dtoh32(bss
->length
)) :
14901 if (!bcmp(&candidate
[idx1
].BSSID
, &bss
->BSSID
, ETHER_ADDR_LEN
) &&
14902 candidate
[idx1
].RSSI
== bss
->RSSI
&&
14903 candidate
[idx1
].length
== dtoh32(bss
->length
)) {
14904 u32 delete_len
= dtoh32(bss
->length
);
14905 WL_DBG(("delete scan info of " MACDBG
" to add new AP\n",
14906 MAC2STRDBG(bss
->BSSID
.octet
)));
14907 if (idx2
< list
->count
-1) {
14908 memmove((u8
*)bss
, (u8
*)bss
+ delete_len
,
14909 list
->buflen
- cur_len
- delete_len
);
14911 list
->buflen
-= delete_len
;
14913 total_delete_len
+= delete_len
;
14914 /* if delete_len is greater than or equal to result length */
14915 if (total_delete_len
>= bi
->length
) {
14920 cur_len
+= dtoh32(bss
->length
);
14924 #endif /* WL_DRV_AVOID_SCANCACHE */
14925 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
14927 #ifdef WL_DRV_AVOID_SCANCACHE
14928 static u32
wl_p2p_find_peer_channel(struct bcm_cfg80211
*cfg
, s32 status
, wl_bss_info_t
*bi
,
14932 u8
*p2p_dev_addr
= NULL
;
14934 ret
= wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
);
14938 if (status
== WLC_E_STATUS_PARTIAL
) {
14939 p2p_dev_addr
= wl_cfgp2p_retreive_p2p_dev_addr(bi
, bi_length
);
14940 if (p2p_dev_addr
&& !memcmp(p2p_dev_addr
,
14941 cfg
->afx_hdl
->tx_dst_addr
.octet
, ETHER_ADDR_LEN
)) {
14942 s32 channel
= wf_chspec_ctlchan(
14943 wl_chspec_driver_to_host(bi
->chanspec
));
14945 if ((channel
> MAXCHANNEL
) || (channel
<= 0))
14946 channel
= WL_INVALID
;
14948 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG
" found,"
14950 MAC2STRDBG(cfg
->afx_hdl
->tx_dst_addr
.octet
),
14953 wl_clr_p2p_status(cfg
, SCANNING
);
14954 cfg
->afx_hdl
->peer_chan
= channel
;
14955 complete(&cfg
->act_frm_scan
);
14958 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
14959 wl_clr_p2p_status(cfg
, SCANNING
);
14960 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
14961 if (cfg
->afx_hdl
->peer_chan
== WL_INVALID
)
14962 complete(&cfg
->act_frm_scan
);
14968 static s32
wl_escan_without_scan_cache(struct bcm_cfg80211
*cfg
, wl_escan_result_t
*escan_result
,
14969 struct net_device
*ndev
, const wl_event_msg_t
*e
, s32 status
)
14974 bool aborted
= false;
14975 bool fw_abort
= false;
14976 bool notify_escan_complete
= false;
14978 if (wl_escan_check_sync_id(status
, escan_result
->sync_id
,
14979 cfg
->escan_info
.cur_sync_id
) < 0) {
14983 wl_escan_print_sync_id(status
, escan_result
->sync_id
,
14984 cfg
->escan_info
.cur_sync_id
);
14986 if (!(status
== WLC_E_STATUS_TIMEOUT
) || !(status
== WLC_E_STATUS_PARTIAL
)) {
14987 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
14990 if ((likely(cfg
->scan_request
)) || (cfg
->sched_scan_running
)) {
14991 notify_escan_complete
= true;
14994 if (status
== WLC_E_STATUS_PARTIAL
) {
14995 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
14996 DBG_EVENT_LOG((dhd_pub_t
*)cfg
->pub
, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND
);
14997 if ((!escan_result
) || (dtoh16(escan_result
->bss_count
) != 1)) {
14998 WL_ERR(("Invalid escan result (NULL pointer) or invalid bss_count\n"));
15002 bi
= escan_result
->bss_info
;
15003 bi_length
= dtoh32(bi
->length
);
15005 (bi_length
!= (dtoh32(escan_result
->buflen
) - WL_ESCAN_RESULTS_FIXED_SIZE
))) {
15006 WL_ERR(("Invalid escan bss info (NULL pointer)"
15007 "or invalid bss_info length\n"));
15011 if (!(bcmcfg_to_wiphy(cfg
)->interface_modes
& BIT(NL80211_IFTYPE_ADHOC
))) {
15012 if (dtoh16(bi
->capability
) & DOT11_CAP_IBSS
) {
15013 WL_DBG(("Ignoring IBSS result\n"));
15018 if (wl_p2p_find_peer_channel(cfg
, status
, bi
, bi_length
)) {
15021 if (scan_req_match(cfg
)) {
15022 /* p2p scan && allow only probe response */
15023 if ((cfg
->p2p
->search_state
!= WL_P2P_DISC_ST_SCAN
) &&
15024 (bi
->flags
& WL_BSS_FLAGS_FROM_BEACON
))
15027 err
= wl_inform_single_bss(cfg
, bi
, false);
15030 * !Broadcast && number of ssid = 1 && number of channels =1
15031 * means specific scan to association
15033 if (wl_cfgp2p_is_p2p_specific_scan(cfg
->scan_request
)) {
15034 WL_ERR(("P2P assoc scan fast aborted.\n"));
15038 /* Directly exit from function here and
15039 * avoid sending notify completion to cfg80211
15043 } else if (status
== WLC_E_STATUS_SUCCESS
) {
15044 if (wl_p2p_find_peer_channel(cfg
, status
, NULL
, 0)) {
15047 WL_INFORM(("ESCAN COMPLETED\n"));
15048 DBG_EVENT_LOG((dhd_pub_t
*)cfg
->pub
, WIFI_EVENT_DRIVER_SCAN_COMPLETE
);
15050 /* Update escan complete status */
15054 #ifdef CUSTOMER_HW4_DEBUG
15055 if (wl_scan_timeout_dbg_enabled
)
15056 wl_scan_timeout_dbg_clear();
15057 #endif /* CUSTOMER_HW4_DEBUG */
15058 } else if ((status
== WLC_E_STATUS_ABORT
) || (status
== WLC_E_STATUS_NEWSCAN
) ||
15059 (status
== WLC_E_STATUS_11HQUIET
) || (status
== WLC_E_STATUS_CS_ABORT
) ||
15060 (status
== WLC_E_STATUS_NEWASSOC
)) {
15061 /* Handle all cases of scan abort */
15063 WL_DBG(("ESCAN ABORT reason: %d\n", status
));
15064 if (wl_p2p_find_peer_channel(cfg
, status
, NULL
, 0)) {
15067 WL_INFORM(("ESCAN ABORTED\n"));
15069 /* Update escan complete status */
15073 } else if (status
== WLC_E_STATUS_TIMEOUT
) {
15074 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg
->scan_request
));
15075 WL_ERR(("reason[0x%x]\n", e
->reason
));
15076 if (e
->reason
== 0xFFFFFFFF) {
15077 /* Update escan complete status */
15082 WL_ERR(("unexpected Escan Event %d : abort\n", status
));
15084 if (wl_p2p_find_peer_channel(cfg
, status
, NULL
, 0)) {
15087 /* Update escan complete status */
15092 /* Notify escan complete status */
15093 if (notify_escan_complete
) {
15094 wl_notify_escan_complete(cfg
, ndev
, aborted
, fw_abort
);
15101 #endif /* WL_DRV_AVOID_SCANCACHE */
15103 static s32
wl_escan_handler(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
15104 const wl_event_msg_t
*e
, void *data
)
15107 s32 status
= ntoh32(e
->status
);
15108 wl_escan_result_t
*escan_result
;
15109 struct net_device
*ndev
= NULL
;
15110 #ifndef WL_DRV_AVOID_SCANCACHE
15113 wifi_p2p_ie_t
* p2p_ie
;
15114 u8
*p2p_dev_addr
= NULL
;
15115 wl_scan_results_t
*list
;
15116 wl_bss_info_t
*bss
= NULL
;
15118 #endif /* WL_DRV_AVOID_SCANCACHE */
15120 struct ieee80211_supported_band
*band
;
15122 WL_DBG((" enter event type : %d, status : %d \n",
15123 ntoh32(e
->event_type
), ntoh32(e
->status
)));
15125 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
15127 mutex_lock(&cfg
->usr_sync
);
15128 /* P2P SCAN is coming from primary interface */
15129 if (wl_get_p2p_status(cfg
, SCANNING
)) {
15130 if (wl_get_drv_status_all(cfg
, SENDING_ACT_FRM
))
15131 ndev
= cfg
->afx_hdl
->dev
;
15133 ndev
= cfg
->escan_info
.ndev
;
15136 if (!ndev
|| (!wl_get_drv_status(cfg
, SCANNING
, ndev
) && !cfg
->sched_scan_running
)) {
15137 WL_ERR(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n",
15138 ndev
, wl_get_drv_status(cfg
, SCANNING
, ndev
),
15139 ntoh32(e
->event_type
), ntoh32(e
->status
)));
15142 escan_result
= (wl_escan_result_t
*)data
;
15144 #ifndef WL_DRV_AVOID_SCANCACHE
15145 if (status
== WLC_E_STATUS_PARTIAL
) {
15146 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
15147 DBG_EVENT_LOG((dhd_pub_t
*)cfg
->pub
, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND
);
15148 if (!escan_result
) {
15149 WL_ERR(("Invalid escan result (NULL pointer)\n"));
15152 if ((dtoh32(escan_result
->buflen
) > (int)ESCAN_BUF_SIZE
) ||
15153 (dtoh32(escan_result
->buflen
) < sizeof(wl_escan_result_t
))) {
15154 WL_ERR(("Invalid escan buffer len:%d\n", dtoh32(escan_result
->buflen
)));
15157 if (dtoh16(escan_result
->bss_count
) != 1) {
15158 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result
->bss_count
));
15161 bi
= escan_result
->bss_info
;
15163 WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
15166 bi_length
= dtoh32(bi
->length
);
15167 if (bi_length
!= (dtoh32(escan_result
->buflen
) - WL_ESCAN_RESULTS_FIXED_SIZE
)) {
15168 WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length
));
15172 /* +++++ terence 20130524: skip invalid bss */
15174 bi
->ctl_ch
? bi
->ctl_ch
: CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi
->chanspec
));
15175 if (channel
<= CH_MAX_2G_CHANNEL
)
15176 band
= bcmcfg_to_wiphy(cfg
)->bands
[IEEE80211_BAND_2GHZ
];
15178 band
= bcmcfg_to_wiphy(cfg
)->bands
[IEEE80211_BAND_5GHZ
];
15180 WL_ERR(("No valid band\n"));
15183 if (!dhd_conf_match_channel(cfg
->pub
, channel
))
15185 /* ----- terence 20130524: skip invalid bss */
15187 if (wl_escan_check_sync_id(status
, escan_result
->sync_id
,
15188 cfg
->escan_info
.cur_sync_id
) < 0)
15191 if (!(bcmcfg_to_wiphy(cfg
)->interface_modes
& BIT(NL80211_IFTYPE_ADHOC
))) {
15192 if (dtoh16(bi
->capability
) & DOT11_CAP_IBSS
) {
15193 WL_DBG(("Ignoring IBSS result\n"));
15198 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
)) {
15199 p2p_dev_addr
= wl_cfgp2p_retreive_p2p_dev_addr(bi
, bi_length
);
15200 if (p2p_dev_addr
&& !memcmp(p2p_dev_addr
,
15201 cfg
->afx_hdl
->tx_dst_addr
.octet
, ETHER_ADDR_LEN
)) {
15202 s32 channel
= wf_chspec_ctlchan(
15203 wl_chspec_driver_to_host(bi
->chanspec
));
15205 if ((channel
> MAXCHANNEL
) || (channel
<= 0))
15206 channel
= WL_INVALID
;
15208 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG
" found,"
15210 MAC2STRDBG(cfg
->afx_hdl
->tx_dst_addr
.octet
),
15213 wl_clr_p2p_status(cfg
, SCANNING
);
15214 cfg
->afx_hdl
->peer_chan
= channel
;
15215 complete(&cfg
->act_frm_scan
);
15220 int cur_len
= WL_SCAN_RESULTS_FIXED_SIZE
;
15221 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15222 removal_element_t candidate
[BUF_OVERFLOW_MGMT_COUNT
];
15223 int remove_lower_rssi
= FALSE
;
15225 bzero(candidate
, sizeof(removal_element_t
)*BUF_OVERFLOW_MGMT_COUNT
);
15226 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15228 list
= wl_escan_get_buf(cfg
, FALSE
);
15229 if (scan_req_match(cfg
)) {
15230 /* p2p scan && allow only probe response */
15231 if ((cfg
->p2p
->search_state
!= WL_P2P_DISC_ST_SCAN
) &&
15232 (bi
->flags
& WL_BSS_FLAGS_FROM_BEACON
))
15234 if ((p2p_ie
= wl_cfgp2p_find_p2pie(((u8
*) bi
) + bi
->ie_offset
,
15235 bi
->ie_length
)) == NULL
) {
15236 WL_ERR(("Couldn't find P2PIE in probe"
15237 " response/beacon\n"));
15241 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15242 if (bi_length
> ESCAN_BUF_SIZE
- list
->buflen
)
15243 remove_lower_rssi
= TRUE
;
15244 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15246 WL_SCAN(("%s("MACDBG
") RSSI %d flags 0x%x length %d\n", bi
->SSID
,
15247 MAC2STRDBG(bi
->BSSID
.octet
), bi
->RSSI
, bi
->flags
, bi
->length
));
15248 for (i
= 0; i
< list
->count
; i
++) {
15249 bss
= bss
? (wl_bss_info_t
*)((uintptr
)bss
+ dtoh32(bss
->length
))
15252 WL_ERR(("bss is NULL\n"));
15255 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15256 WL_SCAN(("%s("MACDBG
"), i=%d bss: RSSI %d list->count %d\n",
15257 bss
->SSID
, MAC2STRDBG(bss
->BSSID
.octet
),
15258 i
, bss
->RSSI
, list
->count
));
15260 if (remove_lower_rssi
)
15261 wl_cfg80211_find_removal_candidate(bss
, candidate
);
15262 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15264 if (!bcmp(&bi
->BSSID
, &bss
->BSSID
, ETHER_ADDR_LEN
) &&
15265 (CHSPEC_BAND(wl_chspec_driver_to_host(bi
->chanspec
))
15266 == CHSPEC_BAND(wl_chspec_driver_to_host(bss
->chanspec
))) &&
15267 bi
->SSID_len
== bss
->SSID_len
&&
15268 !bcmp(bi
->SSID
, bss
->SSID
, bi
->SSID_len
)) {
15270 /* do not allow beacon data to update
15271 *the data recd from a probe response
15273 if (!(bss
->flags
& WL_BSS_FLAGS_FROM_BEACON
) &&
15274 (bi
->flags
& WL_BSS_FLAGS_FROM_BEACON
))
15277 WL_SCAN(("%s("MACDBG
"), i=%d prev: RSSI %d"
15278 " flags 0x%x, new: RSSI %d flags 0x%x\n",
15279 bss
->SSID
, MAC2STRDBG(bi
->BSSID
.octet
), i
,
15280 bss
->RSSI
, bss
->flags
, bi
->RSSI
, bi
->flags
));
15282 if ((bss
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
) ==
15283 (bi
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
)) {
15284 /* preserve max RSSI if the measurements are
15285 * both on-channel or both off-channel
15287 WL_SCAN(("%s("MACDBG
"), same onchan"
15288 ", RSSI: prev %d new %d\n",
15289 bss
->SSID
, MAC2STRDBG(bi
->BSSID
.octet
),
15290 bss
->RSSI
, bi
->RSSI
));
15291 bi
->RSSI
= MAX(bss
->RSSI
, bi
->RSSI
);
15292 } else if ((bss
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
) &&
15293 (bi
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
) == 0) {
15294 /* preserve the on-channel rssi measurement
15295 * if the new measurement is off channel
15297 WL_SCAN(("%s("MACDBG
"), prev onchan"
15298 ", RSSI: prev %d new %d\n",
15299 bss
->SSID
, MAC2STRDBG(bi
->BSSID
.octet
),
15300 bss
->RSSI
, bi
->RSSI
));
15301 bi
->RSSI
= bss
->RSSI
;
15302 bi
->flags
|= WL_BSS_FLAGS_RSSI_ONCHANNEL
;
15304 if (dtoh32(bss
->length
) != bi_length
) {
15305 u32 prev_len
= dtoh32(bss
->length
);
15307 WL_SCAN(("bss info replacement"
15308 " is occured(bcast:%d->probresp%d)\n",
15309 bss
->ie_length
, bi
->ie_length
));
15310 WL_SCAN(("%s("MACDBG
"), replacement!(%d -> %d)\n",
15311 bss
->SSID
, MAC2STRDBG(bi
->BSSID
.octet
),
15312 prev_len
, bi_length
));
15314 if (list
->buflen
- prev_len
+ bi_length
15315 > ESCAN_BUF_SIZE
) {
15316 WL_ERR(("Buffer is too small: keep the"
15317 " previous result of this AP\n"));
15318 /* Only update RSSI */
15319 bss
->RSSI
= bi
->RSSI
;
15320 bss
->flags
|= (bi
->flags
15321 & WL_BSS_FLAGS_RSSI_ONCHANNEL
);
15325 if (i
< list
->count
- 1) {
15326 /* memory copy required by this case only */
15327 memmove((u8
*)bss
+ bi_length
,
15328 (u8
*)bss
+ prev_len
,
15329 list
->buflen
- cur_len
- prev_len
);
15331 list
->buflen
-= prev_len
;
15332 list
->buflen
+= bi_length
;
15334 list
->version
= dtoh32(bi
->version
);
15335 memcpy((u8
*)bss
, (u8
*)bi
, bi_length
);
15338 cur_len
+= dtoh32(bss
->length
);
15340 if (bi_length
> ESCAN_BUF_SIZE
- list
->buflen
) {
15341 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15342 wl_cfg80211_remove_lowRSSI_info(list
, candidate
, bi
);
15343 if (bi_length
> ESCAN_BUF_SIZE
- list
->buflen
) {
15344 WL_DBG(("RSSI(" MACDBG
") is too low(%d) to add Buffer\n",
15345 MAC2STRDBG(bi
->BSSID
.octet
), bi
->RSSI
));
15349 WL_ERR(("Buffer is too small: ignoring\n"));
15351 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15354 memcpy(&(((char *)list
)[list
->buflen
]), bi
, bi_length
);
15355 list
->version
= dtoh32(bi
->version
);
15356 list
->buflen
+= bi_length
;
15360 * !Broadcast && number of ssid = 1 && number of channels =1
15361 * means specific scan to association
15363 if (wl_cfgp2p_is_p2p_specific_scan(cfg
->scan_request
)) {
15364 WL_ERR(("P2P assoc scan fast aborted.\n"));
15365 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, false, true);
15370 else if (status
== WLC_E_STATUS_SUCCESS
) {
15371 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
15372 wl_escan_print_sync_id(status
, cfg
->escan_info
.cur_sync_id
,
15373 escan_result
->sync_id
);
15375 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
)) {
15376 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15377 wl_clr_p2p_status(cfg
, SCANNING
);
15378 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
15379 if (cfg
->afx_hdl
->peer_chan
== WL_INVALID
)
15380 complete(&cfg
->act_frm_scan
);
15381 } else if ((likely(cfg
->scan_request
)) || (cfg
->sched_scan_running
)) {
15382 WL_INFORM(("ESCAN COMPLETED\n"));
15383 DBG_EVENT_LOG((dhd_pub_t
*)cfg
->pub
, WIFI_EVENT_DRIVER_SCAN_COMPLETE
);
15384 cfg
->bss_list
= wl_escan_get_buf(cfg
, FALSE
);
15385 if (!scan_req_match(cfg
)) {
15386 WL_SCAN(("SCAN COMPLETED: scanned AP count=%d\n",
15387 cfg
->bss_list
->count
));
15389 wl_inform_bss(cfg
);
15390 wl_notify_escan_complete(cfg
, ndev
, false, false);
15392 wl_escan_increment_sync_id(cfg
, SCAN_BUF_NEXT
);
15393 #ifdef CUSTOMER_HW4_DEBUG
15394 if (wl_scan_timeout_dbg_enabled
)
15395 wl_scan_timeout_dbg_clear();
15396 #endif /* CUSTOMER_HW4_DEBUG */
15397 } else if ((status
== WLC_E_STATUS_ABORT
) || (status
== WLC_E_STATUS_NEWSCAN
) ||
15398 (status
== WLC_E_STATUS_11HQUIET
) || (status
== WLC_E_STATUS_CS_ABORT
) ||
15399 (status
== WLC_E_STATUS_NEWASSOC
)) {
15400 /* Handle all cases of scan abort */
15401 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
15402 wl_escan_print_sync_id(status
, escan_result
->sync_id
,
15403 cfg
->escan_info
.cur_sync_id
);
15404 WL_DBG(("ESCAN ABORT reason: %d\n", status
));
15405 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
)) {
15406 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15407 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
15408 wl_clr_p2p_status(cfg
, SCANNING
);
15409 if (cfg
->afx_hdl
->peer_chan
== WL_INVALID
)
15410 complete(&cfg
->act_frm_scan
);
15411 } else if ((likely(cfg
->scan_request
)) || (cfg
->sched_scan_running
)) {
15412 WL_INFORM(("ESCAN ABORTED\n"));
15413 cfg
->bss_list
= wl_escan_get_buf(cfg
, TRUE
);
15414 if (!scan_req_match(cfg
)) {
15415 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
15416 cfg
->bss_list
->count
));
15418 wl_inform_bss(cfg
);
15419 wl_notify_escan_complete(cfg
, ndev
, true, false);
15421 /* If there is no pending host initiated scan, do nothing */
15422 WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
15424 wl_escan_increment_sync_id(cfg
, SCAN_BUF_CNT
);
15425 } else if (status
== WLC_E_STATUS_TIMEOUT
) {
15426 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg
->scan_request
));
15427 WL_ERR(("reason[0x%x]\n", e
->reason
));
15428 if (e
->reason
== 0xFFFFFFFF) {
15429 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, true, true);
15432 WL_ERR(("unexpected Escan Event %d : abort\n", status
));
15433 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
15434 wl_escan_print_sync_id(status
, escan_result
->sync_id
,
15435 cfg
->escan_info
.cur_sync_id
);
15436 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
)) {
15437 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15438 wl_clr_p2p_status(cfg
, SCANNING
);
15439 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
15440 if (cfg
->afx_hdl
->peer_chan
== WL_INVALID
)
15441 complete(&cfg
->act_frm_scan
);
15442 } else if ((likely(cfg
->scan_request
)) || (cfg
->sched_scan_running
)) {
15443 cfg
->bss_list
= wl_escan_get_buf(cfg
, TRUE
);
15444 if (!scan_req_match(cfg
)) {
15445 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
15446 "scanned AP count=%d\n",
15447 cfg
->bss_list
->count
));
15449 wl_inform_bss(cfg
);
15450 wl_notify_escan_complete(cfg
, ndev
, true, false);
15452 wl_escan_increment_sync_id(cfg
, 2);
15454 #else /* WL_DRV_AVOID_SCANCACHE */
15455 err
= wl_escan_without_scan_cache(cfg
, escan_result
, ndev
, e
, status
);
15456 #endif /* WL_DRV_AVOID_SCANCACHE */
15458 mutex_unlock(&cfg
->usr_sync
);
15462 static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211
*cfg
, int enable
)
15464 u32 connected_cnt
= wl_get_drv_status_all(cfg
, CONNECTED
);
15465 bool p2p_connected
= wl_cfgp2p_vif_created(cfg
);
15466 struct net_info
*iter
, *next
;
15468 if (!(cfg
->roam_flags
& WL_ROAM_OFF_ON_CONCURRENT
))
15471 WL_DBG(("roam off:%d p2p_connected:%d connected_cnt:%d \n",
15472 enable
, p2p_connected
, connected_cnt
));
15473 /* Disable FW roam when we have a concurrent P2P connection */
15474 if (enable
&& p2p_connected
&& connected_cnt
> 1) {
15476 /* Mark it as to be reverted */
15477 cfg
->roam_flags
|= WL_ROAM_REVERT_STATUS
;
15478 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15479 4 && __GNUC_MINOR__ >= 6))
15480 _Pragma("GCC diagnostic push")
15481 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15483 for_each_ndev(cfg
, iter
, next
) {
15484 if (iter
->ndev
&& iter
->wdev
&&
15485 iter
->wdev
->iftype
== NL80211_IFTYPE_STATION
) {
15486 if (wldev_iovar_setint(iter
->ndev
, "roam_off", TRUE
)
15488 iter
->roam_off
= TRUE
;
15491 WL_ERR(("error to enable roam_off\n"));
15495 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15496 4 && __GNUC_MINOR__ >= 6))
15497 _Pragma("GCC diagnostic pop")
15500 else if (!enable
&& (cfg
->roam_flags
& WL_ROAM_REVERT_STATUS
)) {
15501 cfg
->roam_flags
&= ~WL_ROAM_REVERT_STATUS
;
15502 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15503 4 && __GNUC_MINOR__ >= 6))
15504 _Pragma("GCC diagnostic push")
15505 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15507 for_each_ndev(cfg
, iter
, next
) {
15508 if (iter
->ndev
&& iter
->wdev
&&
15509 iter
->wdev
->iftype
== NL80211_IFTYPE_STATION
) {
15510 if (iter
->roam_off
!= WL_INVALID
) {
15511 if (wldev_iovar_setint(iter
->ndev
, "roam_off", FALSE
)
15513 iter
->roam_off
= FALSE
;
15516 WL_ERR(("error to disable roam_off\n"));
15521 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15522 4 && __GNUC_MINOR__ >= 6))
15523 _Pragma("GCC diagnostic pop")
15530 static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211
*cfg
)
15532 struct net_info
*iter
, *next
;
15535 u32 pre_ctl_chan
= 0;
15536 u32 connected_cnt
= wl_get_drv_status_all(cfg
, CONNECTED
);
15537 cfg
->vsdb_mode
= false;
15539 if (connected_cnt
<= 1) {
15542 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15543 4 && __GNUC_MINOR__ >= 6))
15544 _Pragma("GCC diagnostic push")
15545 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15547 for_each_ndev(cfg
, iter
, next
) {
15548 /* p2p discovery iface ndev could be null */
15552 if (wl_get_drv_status(cfg
, CONNECTED
, iter
->ndev
)) {
15553 if (wldev_iovar_getint(iter
->ndev
, "chanspec",
15554 (s32
*)&chanspec
) == BCME_OK
) {
15555 chanspec
= wl_chspec_driver_to_host(chanspec
);
15556 ctl_chan
= wf_chspec_ctlchan(chanspec
);
15557 wl_update_prof(cfg
, iter
->ndev
, NULL
,
15558 &ctl_chan
, WL_PROF_CHAN
);
15560 if (!cfg
->vsdb_mode
) {
15561 if (!pre_ctl_chan
&& ctl_chan
)
15562 pre_ctl_chan
= ctl_chan
;
15563 else if (pre_ctl_chan
&& (pre_ctl_chan
!= ctl_chan
)) {
15564 cfg
->vsdb_mode
= true;
15570 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15571 4 && __GNUC_MINOR__ >= 6))
15572 _Pragma("GCC diagnostic pop")
15574 printf("%s concurrency is enabled\n", cfg
->vsdb_mode
? "Multi Channel" : "Same Channel");
15578 #if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF)
15579 extern int g_frameburst
;
15580 #endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */
15582 static s32
wl_notifier_change_state(struct bcm_cfg80211
*cfg
, struct net_info
*_net_info
,
15583 enum wl_status state
, bool set
)
15589 struct net_device
*primary_dev
= bcmcfg_to_prmry_ndev(cfg
);
15590 dhd_pub_t
*dhd
= cfg
->pub
;
15592 rtt_status_info_t
*rtt_status
;
15593 #endif /* RTT_SUPPORT */
15594 if (dhd
->busstate
== DHD_BUS_DOWN
) {
15595 WL_ERR(("%s : busstate is DHD_BUS_DOWN!\n", __FUNCTION__
));
15598 WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
15599 state
, set
, _net_info
->pm_restore
, _net_info
->ndev
->name
));
15601 if (state
!= WL_STATUS_CONNECTED
)
15603 mode
= wl_get_mode_by_netdev(cfg
, _net_info
->ndev
);
15605 wl_cfg80211_concurrent_roam(cfg
, 1);
15606 wl_cfg80211_determine_vsdb_mode(cfg
);
15607 if (mode
== WL_MODE_AP
) {
15608 if (wl_add_remove_eventmsg(primary_dev
, WLC_E_P2P_PROBREQ_MSG
, false))
15609 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
15612 if ((err
= wldev_ioctl_set(_net_info
->ndev
, WLC_SET_PM
, &pm
,
15613 sizeof(pm
))) != 0) {
15614 if (err
== -ENODEV
)
15615 WL_DBG(("%s:netdev not ready\n",
15616 _net_info
->ndev
->name
));
15618 WL_ERR(("%s:error (%d)\n",
15619 _net_info
->ndev
->name
, err
));
15621 wl_cfg80211_update_power_mode(_net_info
->ndev
);
15623 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_SHORT
);
15625 } else { /* clear */
15627 /* clear chan information when the net device is disconnected */
15628 wl_update_prof(cfg
, _net_info
->ndev
, NULL
, &chan
, WL_PROF_CHAN
);
15629 wl_cfg80211_determine_vsdb_mode(cfg
);
15630 if (primary_dev
== _net_info
->ndev
) {
15633 rtt_status
= GET_RTTSTATE(dhd
);
15634 if (rtt_status
->status
!= RTT_ENABLED
) {
15635 #endif /* RTT_SUPPORT */
15636 if (dhd_conf_get_pm(dhd
) >= 0)
15637 pm
= dhd_conf_get_pm(dhd
);
15638 if ((err
= wldev_ioctl_set(_net_info
->ndev
, WLC_SET_PM
, &pm
,
15639 sizeof(pm
))) != 0) {
15640 if (err
== -ENODEV
)
15641 WL_DBG(("%s:netdev not ready\n",
15642 _net_info
->ndev
->name
));
15644 WL_ERR(("%s:error (%d)\n",
15645 _net_info
->ndev
->name
, err
));
15647 wl_cfg80211_update_power_mode(_net_info
->ndev
);
15651 #endif /* RTT_SUPPORT */
15653 wl_cfg80211_concurrent_roam(cfg
, 0);
15659 static s32
wl_init_scan(struct bcm_cfg80211
*cfg
)
15663 cfg
->evt_handler
[WLC_E_ESCAN_RESULT
] = wl_escan_handler
;
15664 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
15665 wl_escan_init_sync_id(cfg
);
15667 /* Init scan_timeout timer */
15668 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
15669 timer_setup(&cfg
->scan_timeout
, wl_scan_timeout
, 0);
15671 init_timer(&cfg
->scan_timeout
);
15672 cfg
->scan_timeout
.data
= (unsigned long) cfg
;
15673 cfg
->scan_timeout
.function
= wl_scan_timeout
;
15679 #ifdef DHD_LOSSLESS_ROAMING
15680 static s32
wl_init_roam_timeout(struct bcm_cfg80211
*cfg
)
15684 /* Init roam timer */
15685 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
15686 timer_setup(&cfg
->roam_timeout
, wl_roam_timeout
, 0);
15688 init_timer(&cfg
->roam_timeout
);
15689 cfg
->roam_timeout
.data
= (unsigned long) cfg
;
15690 cfg
->roam_timeout
.function
= wl_roam_timeout
;
15695 #endif /* DHD_LOSSLESS_ROAMING */
15697 static s32
wl_init_priv(struct bcm_cfg80211
*cfg
)
15699 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
15700 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
15703 cfg
->scan_request
= NULL
;
15704 cfg
->pwr_save
= !!(wiphy
->flags
& WIPHY_FLAG_PS_ON_BY_DEFAULT
);
15705 #ifdef DISABLE_BUILTIN_ROAM
15706 cfg
->roam_on
= false;
15708 cfg
->roam_on
= true;
15709 #endif /* DISABLE_BUILTIN_ROAM */
15710 cfg
->active_scan
= true;
15711 cfg
->rf_blocked
= false;
15712 cfg
->vsdb_mode
= false;
15713 #if defined(BCMSDIO) || defined(BCMDBUS)
15714 cfg
->wlfc_on
= false;
15715 #endif /* BCMSDIO || BCMDBUS */
15716 cfg
->roam_flags
|= WL_ROAM_OFF_ON_CONCURRENT
;
15717 cfg
->disable_roam_event
= false;
15718 /* register interested state */
15719 set_bit(WL_STATUS_CONNECTED
, &cfg
->interrested_state
);
15720 spin_lock_init(&cfg
->cfgdrv_lock
);
15721 mutex_init(&cfg
->ioctl_buf_sync
);
15722 init_waitqueue_head(&cfg
->netif_change_event
);
15723 init_waitqueue_head(&cfg
->wps_done_event
);
15724 init_completion(&cfg
->send_af_done
);
15725 init_completion(&cfg
->iface_disable
);
15726 mutex_init(&cfg
->usr_sync
);
15727 mutex_init(&cfg
->event_sync
);
15728 mutex_init(&cfg
->scan_complete
);
15729 mutex_init(&cfg
->if_sync
);
15730 mutex_init(&cfg
->pm_sync
);
15731 mutex_init(&cfg
->in4way_sync
);
15733 mutex_init(&cfg
->tdls_sync
);
15734 #endif /* WLTDLS */
15736 err
= wl_init_priv_mem(cfg
);
15739 if (wl_create_event_handler(cfg
))
15741 wl_init_event_handler(cfg
);
15742 err
= wl_init_scan(cfg
);
15745 #ifdef DHD_LOSSLESS_ROAMING
15746 err
= wl_init_roam_timeout(cfg
);
15750 #endif /* DHD_LOSSLESS_ROAMING */
15751 wl_init_conf(cfg
->conf
);
15752 wl_init_prof(cfg
, ndev
);
15754 DNGL_FUNC(dhd_cfg80211_init
, (cfg
));
15756 cfg
->nan_dp_state
= NAN_DP_STATE_DISABLED
;
15757 init_waitqueue_head(&cfg
->ndp_if_change_event
);
15758 #endif /* NAN_DP */
15762 static void wl_deinit_priv(struct bcm_cfg80211
*cfg
)
15764 DNGL_FUNC(dhd_cfg80211_deinit
, (cfg
));
15765 wl_destroy_event_handler(cfg
);
15768 if (cfg
->scan_timeout
.function
)
15769 del_timer_sync(&cfg
->scan_timeout
);
15770 #ifdef DHD_LOSSLESS_ROAMING
15771 if (cfg
->roam_timeout
.function
)
15772 del_timer_sync(&cfg
->roam_timeout
);
15774 wl_deinit_priv_mem(cfg
);
15775 if (wl_cfg80211_netdev_notifier_registered
) {
15776 wl_cfg80211_netdev_notifier_registered
= FALSE
;
15777 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier
);
15781 #if defined(WL_ENABLE_P2P_IF)
15782 static s32
wl_cfg80211_attach_p2p(struct bcm_cfg80211
*cfg
)
15784 WL_TRACE(("Enter \n"));
15786 if (wl_cfgp2p_register_ndev(cfg
) < 0) {
15787 WL_ERR(("P2P attach failed. \n"));
15794 static s32
wl_cfg80211_detach_p2p(struct bcm_cfg80211
*cfg
)
15796 struct wireless_dev
*wdev
;
15798 WL_DBG(("Enter \n"));
15800 WL_ERR(("Invalid Ptr\n"));
15804 wdev
= cfg
->p2p_wdev
;
15806 WL_ERR(("Invalid Ptr\n"));
15811 wl_cfgp2p_unregister_ndev(cfg
);
15813 cfg
->p2p_wdev
= NULL
;
15814 cfg
->p2p_net
= NULL
;
15815 WL_DBG(("Freeing 0x%p \n", wdev
));
15822 static s32
wl_cfg80211_attach_post(struct net_device
*ndev
)
15824 struct bcm_cfg80211
* cfg
;
15827 WL_TRACE(("In\n"));
15828 if (unlikely(!ndev
)) {
15829 WL_ERR(("ndev is invaild\n"));
15832 cfg
= wl_get_cfg(ndev
);
15833 if (unlikely(!cfg
)) {
15834 WL_ERR(("cfg is invaild\n"));
15837 if (!wl_get_drv_status(cfg
, READY
, ndev
)) {
15839 ret
= wl_cfgp2p_supported(cfg
, ndev
);
15841 #if !defined(WL_ENABLE_P2P_IF)
15842 cfg
->wdev
->wiphy
->interface_modes
|=
15843 (BIT(NL80211_IFTYPE_P2P_CLIENT
)|
15844 BIT(NL80211_IFTYPE_P2P_GO
));
15845 #endif /* !WL_ENABLE_P2P_IF */
15846 if ((err
= wl_cfgp2p_init_priv(cfg
)) != 0)
15849 #if defined(WL_ENABLE_P2P_IF)
15850 if (cfg
->p2p_net
) {
15851 /* Update MAC addr for p2p0 interface here. */
15852 memcpy(cfg
->p2p_net
->dev_addr
, ndev
->dev_addr
, ETH_ALEN
);
15853 cfg
->p2p_net
->dev_addr
[0] |= 0x02;
15854 printf("%s: p2p_dev_addr="MACDBG
"\n",
15855 cfg
->p2p_net
->name
,
15856 MAC2STRDBG(cfg
->p2p_net
->dev_addr
));
15858 WL_ERR(("p2p_net not yet populated."
15859 " Couldn't update the MAC Address for p2p0 \n"));
15862 #endif /* WL_ENABLE_P2P_IF */
15863 cfg
->p2p_supported
= true;
15864 } else if (ret
== 0) {
15865 if ((err
= wl_cfgp2p_init_priv(cfg
)) != 0)
15868 /* SDIO bus timeout */
15874 wl_set_drv_status(cfg
, READY
, ndev
);
15879 struct bcm_cfg80211
*wl_get_cfg(struct net_device
*ndev
)
15881 struct wireless_dev
*wdev
= ndev
->ieee80211_ptr
;
15883 if (!wdev
|| !wdev
->wiphy
)
15886 return wiphy_priv(wdev
->wiphy
);
15889 s32
wl_cfg80211_attach(struct net_device
*ndev
, void *context
)
15891 struct wireless_dev
*wdev
;
15892 struct bcm_cfg80211
*cfg
;
15894 struct device
*dev
;
15896 WL_TRACE(("In\n"));
15898 WL_ERR(("ndev is invaild\n"));
15901 WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
15902 dev
= wl_cfg80211_get_parent_dev();
15904 wdev
= kzalloc(sizeof(*wdev
), GFP_KERNEL
);
15905 if (unlikely(!wdev
)) {
15906 WL_ERR(("Could not allocate wireless device\n"));
15909 err
= wl_setup_wiphy(wdev
, dev
, context
);
15910 if (unlikely(err
)) {
15915 wdev
->iftype
= wl_mode_to_nl80211_iftype(WL_MODE_MESH
);
15917 wdev
->iftype
= wl_mode_to_nl80211_iftype(WL_MODE_BSS
);
15919 cfg
= wiphy_priv(wdev
->wiphy
);
15921 cfg
->pub
= context
;
15922 INIT_LIST_HEAD(&cfg
->net_list
);
15924 INIT_LIST_HEAD(&cfg
->wbtext_bssid_list
);
15925 #endif /* WBTEXT */
15926 INIT_LIST_HEAD(&cfg
->vndr_oui_list
);
15927 spin_lock_init(&cfg
->net_list_sync
);
15928 ndev
->ieee80211_ptr
= wdev
;
15929 SET_NETDEV_DEV(ndev
, wiphy_dev(wdev
->wiphy
));
15930 wdev
->netdev
= ndev
;
15931 cfg
->state_notifier
= wl_notifier_change_state
;
15932 err
= wl_init_priv(cfg
);
15934 WL_ERR(("Failed to init iwm_priv (%d)\n", err
));
15935 goto cfg80211_attach_out
;
15937 err
= wl_alloc_netinfo(cfg
, ndev
, wdev
, wdev
->iftype
, PM_ENABLE
, 0);
15939 WL_ERR(("Failed to alloc net_info (%d)\n", err
));
15940 goto cfg80211_attach_out
;
15943 err
= wl_setup_rfkill(cfg
, TRUE
);
15945 WL_ERR(("Failed to setup rfkill %d\n", err
));
15946 goto cfg80211_attach_out
;
15948 #ifdef DEBUGFS_CFG80211
15949 err
= wl_setup_debugfs(cfg
);
15951 WL_ERR(("Failed to setup debugfs %d\n", err
));
15952 goto cfg80211_attach_out
;
15955 if (!wl_cfg80211_netdev_notifier_registered
) {
15956 wl_cfg80211_netdev_notifier_registered
= TRUE
;
15957 err
= register_netdevice_notifier(&wl_cfg80211_netdev_notifier
);
15959 wl_cfg80211_netdev_notifier_registered
= FALSE
;
15960 WL_ERR(("Failed to register notifierl %d\n", err
));
15961 goto cfg80211_attach_out
;
15964 #if defined(COEX_DHCP)
15965 cfg
->btcoex_info
= wl_cfg80211_btcoex_init(cfg
->wdev
->netdev
);
15966 if (!cfg
->btcoex_info
)
15967 goto cfg80211_attach_out
;
15969 #if defined(SUPPORT_RANDOM_MAC_SCAN)
15970 cfg
->random_mac_enabled
= FALSE
;
15971 #endif /* SUPPORT_RANDOM_MAC_SCAN */
15973 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
15974 wdev
->wiphy
->reg_notifier
= wl_cfg80211_reg_notifier
;
15975 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
15977 #if defined(WL_ENABLE_P2P_IF)
15978 err
= wl_cfg80211_attach_p2p(cfg
);
15980 goto cfg80211_attach_out
;
15983 INIT_DELAYED_WORK(&cfg
->pm_enable_work
, wl_cfg80211_work_handler
);
15985 #if defined(STAT_REPORT)
15986 err
= wl_attach_stat_report(cfg
);
15988 goto cfg80211_attach_out
;
15990 #endif /* STAT_REPORT */
15993 cfg80211_attach_out
:
15994 wl_cfg80211_detach(cfg
);
15998 void wl_cfg80211_detach(struct bcm_cfg80211
*cfg
)
16001 WL_TRACE(("In\n"));
16005 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_DEL
);
16007 #if defined(COEX_DHCP)
16008 wl_cfg80211_btcoex_deinit();
16009 cfg
->btcoex_info
= NULL
;
16012 wl_setup_rfkill(cfg
, FALSE
);
16013 #ifdef DEBUGFS_CFG80211
16014 wl_free_debugfs(cfg
);
16016 if (cfg
->p2p_supported
) {
16017 if (timer_pending(&cfg
->p2p
->listen_timer
))
16018 del_timer_sync(&cfg
->p2p
->listen_timer
);
16019 wl_cfgp2p_deinit_priv(cfg
);
16022 if (timer_pending(&cfg
->scan_timeout
))
16023 del_timer_sync(&cfg
->scan_timeout
);
16024 #ifdef DHD_LOSSLESS_ROAMING
16025 if (timer_pending(&cfg
->roam_timeout
)) {
16026 del_timer_sync(&cfg
->roam_timeout
);
16028 #endif /* DHD_LOSSLESS_ROAMING */
16030 #if defined(WL_CFG80211_P2P_DEV_IF)
16032 wl_cfgp2p_del_p2p_disc_if(cfg
->p2p_wdev
, cfg
);
16033 #endif /* WL_CFG80211_P2P_DEV_IF */
16034 #if defined(WL_ENABLE_P2P_IF)
16035 wl_cfg80211_detach_p2p(cfg
);
16037 #if defined(STAT_REPORT)
16038 wl_detach_stat_report(cfg
);
16039 #endif /* STAT_REPORT */
16041 wl_cfg80211_ibss_vsie_free(cfg
);
16042 wl_cfg80211_clear_mgmt_vndr_ies(cfg
);
16043 wl_deinit_priv(cfg
);
16044 wl_cfg80211_clear_parent_dev();
16045 #if defined(RSSIAVG)
16046 wl_free_rssi_cache(&cfg
->g_rssi_cache_ctrl
);
16047 wl_free_rssi_cache(&cfg
->g_connected_rssi_cache_ctrl
);
16049 #if defined(BSSCACHE)
16050 wl_release_bss_cache_ctrl(&cfg
->g_bss_cache_ctrl
);
16053 /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
16054 * structure "cfg", which is the private part of wiphy, has been freed in
16055 * wl_free_wdev !!!!!!!!!!!
16059 static void wl_event_handler(struct work_struct
*work_data
)
16061 struct bcm_cfg80211
*cfg
= NULL
;
16062 struct wl_event_q
*e
;
16063 struct wireless_dev
*wdev
= NULL
;
16065 BCM_SET_CONTAINER_OF(cfg
, work_data
, struct bcm_cfg80211
, event_work
);
16066 DHD_EVENT_WAKE_LOCK(cfg
->pub
);
16067 while ((e
= wl_deq_event(cfg
))) {
16068 WL_DBG(("event type (%d), ifidx: %d bssidx: %d \n",
16069 e
->etype
, e
->emsg
.ifidx
, e
->emsg
.bsscfgidx
));
16071 if (e
->emsg
.ifidx
> WL_MAX_IFS
) {
16072 WL_ERR((" Event ifidx not in range. val:%d \n", e
->emsg
.ifidx
));
16076 /* Make sure iface operations, don't creat race conditions */
16077 mutex_lock(&cfg
->if_sync
);
16078 if (!(wdev
= wl_get_wdev_by_bssidx(cfg
, e
->emsg
.bsscfgidx
))) {
16079 /* For WLC_E_IF would be handled by wl_host_event */
16080 if (e
->etype
!= WLC_E_IF
)
16081 WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"
16082 " Ignoring event.\n", e
->emsg
.bsscfgidx
));
16083 } else if (e
->etype
< WLC_E_LAST
&& cfg
->evt_handler
[e
->etype
]) {
16084 dhd_pub_t
*dhd
= (struct dhd_pub
*)(cfg
->pub
);
16085 if (dhd
->busstate
== DHD_BUS_DOWN
) {
16086 WL_ERR((": BUS is DOWN.\n"));
16088 cfg
->evt_handler
[e
->etype
](cfg
, wdev_to_cfgdev(wdev
),
16089 &e
->emsg
, e
->edata
);
16091 WL_DBG(("Unknown Event (%d): ignoring\n", e
->etype
));
16093 mutex_unlock(&cfg
->if_sync
);
16097 DHD_EVENT_WAKE_UNLOCK(cfg
->pub
);
16101 wl_cfg80211_event(struct net_device
*ndev
, const wl_event_msg_t
* e
, void *data
)
16103 u32 event_type
= ntoh32(e
->event_type
);
16104 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
16105 struct net_info
*netinfo
;
16107 WL_DBG(("event_type (%d): %s\n", event_type
, bcmevent_get_name(event_type
)));
16109 if ((cfg
== NULL
) || (cfg
->p2p_supported
&& cfg
->p2p
== NULL
)) {
16110 WL_ERR(("Stale event ignored\n"));
16114 if (cfg
->event_workq
== NULL
) {
16115 WL_ERR(("Event handler is not created\n"));
16119 if (wl_get_p2p_status(cfg
, IF_CHANGING
) || wl_get_p2p_status(cfg
, IF_ADDING
)) {
16120 WL_ERR(("during IF change, ignore event %d\n", event_type
));
16124 netinfo
= wl_get_netinfo_by_bssidx(cfg
, e
->bsscfgidx
);
16126 /* Since the netinfo entry is not there, the netdev entry is not
16127 * created via cfg80211 interface. so the event is not of interest
16128 * to the cfg80211 layer.
16130 WL_ERR(("ignore event %d, not interested\n", event_type
));
16134 if (event_type
== WLC_E_PFN_NET_FOUND
) {
16135 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
16137 else if (event_type
== WLC_E_PFN_NET_LOST
) {
16138 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
16141 if (likely(!wl_enq_event(cfg
, ndev
, event_type
, e
, data
))) {
16142 queue_work(cfg
->event_workq
, &cfg
->event_work
);
16146 static void wl_init_eq(struct bcm_cfg80211
*cfg
)
16148 wl_init_eq_lock(cfg
);
16149 INIT_LIST_HEAD(&cfg
->eq_list
);
16152 static void wl_flush_eq(struct bcm_cfg80211
*cfg
)
16154 struct wl_event_q
*e
;
16155 unsigned long flags
;
16157 flags
= wl_lock_eq(cfg
);
16158 while (!list_empty_careful(&cfg
->eq_list
)) {
16159 BCM_SET_LIST_FIRST_ENTRY(e
, &cfg
->eq_list
, struct wl_event_q
, eq_list
);
16160 list_del(&e
->eq_list
);
16163 wl_unlock_eq(cfg
, flags
);
16167 * retrieve first queued event from head
16170 static struct wl_event_q
*wl_deq_event(struct bcm_cfg80211
*cfg
)
16172 struct wl_event_q
*e
= NULL
;
16173 unsigned long flags
;
16175 flags
= wl_lock_eq(cfg
);
16176 if (likely(!list_empty(&cfg
->eq_list
))) {
16177 BCM_SET_LIST_FIRST_ENTRY(e
, &cfg
->eq_list
, struct wl_event_q
, eq_list
);
16178 list_del(&e
->eq_list
);
16180 wl_unlock_eq(cfg
, flags
);
16186 * push event to tail of the queue
16190 wl_enq_event(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, u32 event
,
16191 const wl_event_msg_t
*msg
, void *data
)
16193 struct wl_event_q
*e
;
16197 unsigned long flags
;
16202 data_len
= ntoh32(msg
->datalen
);
16203 evtq_size
= sizeof(struct wl_event_q
) + data_len
;
16204 aflags
= (in_atomic()) ? GFP_ATOMIC
: GFP_KERNEL
;
16205 e
= kzalloc(evtq_size
, aflags
);
16206 if (unlikely(!e
)) {
16207 WL_ERR(("event alloc failed\n"));
16211 memcpy(&e
->emsg
, msg
, sizeof(wl_event_msg_t
));
16213 memcpy(e
->edata
, data
, data_len
);
16214 flags
= wl_lock_eq(cfg
);
16215 list_add_tail(&e
->eq_list
, &cfg
->eq_list
);
16216 wl_unlock_eq(cfg
, flags
);
16221 static void wl_put_event(struct wl_event_q
*e
)
16226 static s32
wl_config_ifmode(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 iftype
)
16232 case NL80211_IFTYPE_MONITOR
:
16233 case NL80211_IFTYPE_WDS
:
16234 WL_ERR(("type (%d) : currently we do not support this mode\n",
16238 case NL80211_IFTYPE_ADHOC
:
16239 mode
= WL_MODE_IBSS
;
16241 case NL80211_IFTYPE_STATION
:
16242 case NL80211_IFTYPE_P2P_CLIENT
:
16243 mode
= WL_MODE_BSS
;
16247 case NL80211_IFTYPE_MESH_POINT
:
16248 mode
= WL_MODE_MESH
;
16249 infra
= WL_BSSTYPE_MESH
;
16251 #endif /* WLMESH */
16252 case NL80211_IFTYPE_AP
:
16253 case NL80211_IFTYPE_P2P_GO
:
16259 WL_ERR(("invalid type (%d)\n", iftype
));
16262 infra
= htod32(infra
);
16263 err
= wldev_ioctl_set(ndev
, WLC_SET_INFRA
, &infra
, sizeof(infra
));
16264 if (unlikely(err
)) {
16265 WL_ERR(("WLC_SET_INFRA error (%d)\n", err
));
16269 wl_set_mode_by_netdev(cfg
, ndev
, mode
);
16274 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf
*ev
, u16 event
, bool set
)
16276 if (!ev
|| (event
> WLC_E_LAST
))
16279 if (ev
->num
< MAX_EVENT_BUF_NUM
) {
16280 ev
->event
[ev
->num
].type
= event
;
16281 ev
->event
[ev
->num
].set
= set
;
16284 WL_ERR(("evenbuffer doesn't support > %u events. Update"
16285 " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM
));
16290 s32
wl_cfg80211_apply_eventbuffer(
16291 struct net_device
*ndev
,
16292 struct bcm_cfg80211
*cfg
,
16293 wl_eventmsg_buf_t
*ev
)
16295 char eventmask
[WL_EVENTING_MASK_LEN
];
16297 s8 iovbuf
[WL_EVENTING_MASK_LEN
+ 12];
16299 if (!ev
|| (!ev
->num
))
16302 mutex_lock(&cfg
->event_sync
);
16304 /* Read event_msgs mask */
16305 ret
= wldev_iovar_getbuf(ndev
, "event_msgs", NULL
, 0, iovbuf
, sizeof(iovbuf
), NULL
);
16306 if (unlikely(ret
)) {
16307 WL_ERR(("Get event_msgs error (%d)\n", ret
));
16310 memcpy(eventmask
, iovbuf
, WL_EVENTING_MASK_LEN
);
16312 /* apply the set bits */
16313 for (i
= 0; i
< ev
->num
; i
++) {
16314 if (ev
->event
[i
].set
)
16315 setbit(eventmask
, ev
->event
[i
].type
);
16317 clrbit(eventmask
, ev
->event
[i
].type
);
16320 /* Write updated Event mask */
16321 ret
= wldev_iovar_setbuf(ndev
, "event_msgs", eventmask
, sizeof(eventmask
), iovbuf
,
16322 sizeof(iovbuf
), NULL
);
16323 if (unlikely(ret
)) {
16324 WL_ERR(("Set event_msgs error (%d)\n", ret
));
16328 mutex_unlock(&cfg
->event_sync
);
16332 s32
wl_add_remove_eventmsg(struct net_device
*ndev
, u16 event
, bool add
)
16334 s8 iovbuf
[WL_EVENTING_MASK_LEN
+ 12];
16335 s8 eventmask
[WL_EVENTING_MASK_LEN
];
16337 struct bcm_cfg80211
*cfg
;
16342 cfg
= wl_get_cfg(ndev
);
16346 mutex_lock(&cfg
->event_sync
);
16348 /* Setup event_msgs */
16349 err
= wldev_iovar_getbuf(ndev
, "event_msgs", NULL
, 0, iovbuf
, sizeof(iovbuf
), NULL
);
16350 if (unlikely(err
)) {
16351 WL_ERR(("Get event_msgs error (%d)\n", err
));
16354 memcpy(eventmask
, iovbuf
, WL_EVENTING_MASK_LEN
);
16356 setbit(eventmask
, event
);
16358 clrbit(eventmask
, event
);
16360 err
= wldev_iovar_setbuf(ndev
, "event_msgs", eventmask
, WL_EVENTING_MASK_LEN
, iovbuf
,
16361 sizeof(iovbuf
), NULL
);
16362 if (unlikely(err
)) {
16363 WL_ERR(("Set event_msgs error (%d)\n", err
));
16368 mutex_unlock(&cfg
->event_sync
);
16372 static int wl_construct_reginfo(struct bcm_cfg80211
*cfg
, s32 bw_cap
)
16374 struct net_device
*dev
= bcmcfg_to_prmry_ndev(cfg
);
16375 struct ieee80211_channel
*band_chan_arr
= NULL
;
16376 wl_uint32_list_t
*list
;
16377 u32 i
, j
, index
, n_2g
, n_5g
, band
, channel
, array_size
;
16384 bool dfs_radar_disabled
= FALSE
;
16386 #define LOCAL_BUF_LEN 1024
16387 pbuf
= kzalloc(LOCAL_BUF_LEN
, GFP_KERNEL
);
16389 if (pbuf
== NULL
) {
16390 WL_ERR(("failed to allocate local buf\n"));
16394 err
= wldev_iovar_getbuf_bsscfg(dev
, "chanspecs", NULL
,
16395 0, pbuf
, LOCAL_BUF_LEN
, 0, &cfg
->ioctl_buf_sync
);
16397 WL_ERR(("get chanspecs failed with %d\n", err
));
16401 #undef LOCAL_BUF_LEN
16403 list
= (wl_uint32_list_t
*)(void *)pbuf
;
16404 band
= array_size
= n_2g
= n_5g
= 0;
16405 for (i
= 0; i
< dtoh32(list
->count
); i
++) {
16408 ht40_allowed
= false;
16409 c
= (chanspec_t
)dtoh32(list
->element
[i
]);
16410 c
= wl_chspec_driver_to_host(c
);
16411 channel
= wf_chspec_ctlchan(c
);
16413 if (!CHSPEC_IS40(c
) && ! CHSPEC_IS20(c
)) {
16414 WL_DBG(("HT80/160/80p80 center channel : %d\n", channel
));
16417 if (CHSPEC_IS2G(c
) && (channel
>= CH_MIN_2G_CHANNEL
) &&
16418 (channel
<= CH_MAX_2G_CHANNEL
)) {
16419 band_chan_arr
= __wl_2ghz_channels
;
16420 array_size
= ARRAYSIZE(__wl_2ghz_channels
);
16422 band
= IEEE80211_BAND_2GHZ
;
16423 ht40_allowed
= (bw_cap
== WLC_N_BW_40ALL
)? true : false;
16424 } else if (CHSPEC_IS5G(c
) && channel
>= CH_MIN_5G_CHANNEL
) {
16425 band_chan_arr
= __wl_5ghz_a_channels
;
16426 array_size
= ARRAYSIZE(__wl_5ghz_a_channels
);
16428 band
= IEEE80211_BAND_5GHZ
;
16429 ht40_allowed
= (bw_cap
== WLC_N_BW_20ALL
)? false : true;
16431 WL_ERR(("Invalid channel Sepc. 0x%x.\n", c
));
16434 if (!ht40_allowed
&& CHSPEC_IS40(c
))
16436 for (j
= 0; (j
< *n_cnt
&& (*n_cnt
< array_size
)); j
++) {
16437 if (band_chan_arr
[j
].hw_value
== channel
) {
16446 if (!dhd_conf_match_channel(cfg
->pub
, channel
))
16448 if (index
< array_size
) {
16449 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
16450 band_chan_arr
[index
].center_freq
=
16451 ieee80211_channel_to_frequency(channel
);
16453 band_chan_arr
[index
].center_freq
=
16454 ieee80211_channel_to_frequency(channel
, band
);
16456 band_chan_arr
[index
].hw_value
= channel
;
16457 band_chan_arr
[index
].beacon_found
= false;
16459 if (CHSPEC_IS40(c
) && ht40_allowed
) {
16460 /* assuming the order is HT20, HT40 Upper,
16461 * HT40 lower from chanspecs
16463 u32 ht40_flag
= band_chan_arr
[index
].flags
& IEEE80211_CHAN_NO_HT40
;
16464 if (CHSPEC_SB_UPPER(c
)) {
16465 if (ht40_flag
== IEEE80211_CHAN_NO_HT40
)
16466 band_chan_arr
[index
].flags
&=
16467 ~IEEE80211_CHAN_NO_HT40
;
16468 band_chan_arr
[index
].flags
|= IEEE80211_CHAN_NO_HT40PLUS
;
16470 /* It should be one of
16471 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
16473 band_chan_arr
[index
].flags
&= ~IEEE80211_CHAN_NO_HT40
;
16474 if (ht40_flag
== IEEE80211_CHAN_NO_HT40
)
16475 band_chan_arr
[index
].flags
|=
16476 IEEE80211_CHAN_NO_HT40MINUS
;
16479 band_chan_arr
[index
].flags
= IEEE80211_CHAN_NO_HT40
;
16480 if (!dfs_radar_disabled
) {
16481 if (band
== IEEE80211_BAND_2GHZ
)
16482 channel
|= WL_CHANSPEC_BAND_2G
;
16484 channel
|= WL_CHANSPEC_BAND_5G
;
16485 channel
|= WL_CHANSPEC_BW_20
;
16486 channel
= wl_chspec_host_to_driver(channel
);
16487 err
= wldev_iovar_getint(dev
, "per_chan_info", &channel
);
16489 if (channel
& WL_CHAN_RADAR
) {
16490 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
16491 band_chan_arr
[index
].flags
|=
16492 (IEEE80211_CHAN_RADAR
16493 | IEEE80211_CHAN_NO_IBSS
);
16495 band_chan_arr
[index
].flags
|=
16496 IEEE80211_CHAN_RADAR
;
16500 if (channel
& WL_CHAN_PASSIVE
)
16501 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
16502 band_chan_arr
[index
].flags
|=
16503 IEEE80211_CHAN_PASSIVE_SCAN
;
16505 band_chan_arr
[index
].flags
|=
16506 IEEE80211_CHAN_NO_IR
;
16508 } else if (err
== BCME_UNSUPPORTED
) {
16509 dfs_radar_disabled
= TRUE
;
16510 WL_ERR(("does not support per_chan_info\n"));
16519 __wl_band_2ghz
.n_channels
= n_2g
;
16520 __wl_band_5ghz_a
.n_channels
= n_5g
;
16525 static s32
__wl_update_wiphybands(struct bcm_cfg80211
*cfg
, bool notify
)
16527 struct wiphy
*wiphy
;
16528 struct net_device
*dev
= bcmcfg_to_prmry_ndev(cfg
);
16535 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16543 s32 txbf_bfe_cap
= 0;
16544 s32 txbf_bfr_cap
= 0;
16548 struct ieee80211_supported_band
*bands
[IEEE80211_NUM_BANDS
] = {NULL
, };
16550 memset(bandlist
, 0, sizeof(bandlist
));
16551 err
= wldev_ioctl_get(dev
, WLC_GET_BANDLIST
, bandlist
,
16553 if (unlikely(err
)) {
16554 WL_ERR(("error read bandlist (%d)\n", err
));
16557 err
= wldev_ioctl_get(dev
, WLC_GET_BAND
, &cur_band
,
16559 if (unlikely(err
)) {
16560 WL_ERR(("error (%d)\n", err
));
16564 err
= wldev_iovar_getint(dev
, "nmode", &nmode
);
16565 if (unlikely(err
)) {
16566 WL_ERR(("error reading nmode (%d)\n", err
));
16569 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16570 err
= wldev_iovar_getint(dev
, "vhtmode", &vhtmode
);
16571 if (unlikely(err
)) {
16572 WL_ERR(("error reading vhtmode (%d)\n", err
));
16576 err
= wldev_iovar_getint(dev
, "txstreams", &txstreams
);
16577 if (unlikely(err
)) {
16578 WL_ERR(("error reading txstreams (%d)\n", err
));
16581 err
= wldev_iovar_getint(dev
, "rxstreams", &rxstreams
);
16582 if (unlikely(err
)) {
16583 WL_ERR(("error reading rxstreams (%d)\n", err
));
16586 err
= wldev_iovar_getint(dev
, "ldpc_cap", &ldpc_cap
);
16587 if (unlikely(err
)) {
16588 WL_ERR(("error reading ldpc_cap (%d)\n", err
));
16591 err
= wldev_iovar_getint(dev
, "stbc_rx", &stbc_rx
);
16592 if (unlikely(err
)) {
16593 WL_ERR(("error reading stbc_rx (%d)\n", err
));
16596 err
= wldev_iovar_getint(dev
, "stbc_tx", &stbc_tx
);
16597 if (unlikely(err
)) {
16598 WL_ERR(("error reading stbc_tx (%d)\n", err
));
16601 err
= wldev_iovar_getint(dev
, "txbf_bfe_cap", &txbf_bfe_cap
);
16602 if (unlikely(err
)) {
16603 WL_ERR(("error reading txbf_bfe_cap (%d)\n", err
));
16606 err
= wldev_iovar_getint(dev
, "txbf_bfr_cap", &txbf_bfr_cap
);
16607 if (unlikely(err
)) {
16608 WL_ERR(("error reading txbf_bfr_cap (%d)\n", err
));
16613 /* For nmode and vhtmode check bw cap */
16615 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16619 err
= wldev_iovar_getint(dev
, "mimo_bw_cap", &bw_cap
);
16620 if (unlikely(err
)) {
16621 WL_ERR(("error get mimo_bw_cap (%d)\n", err
));
16625 err
= wl_construct_reginfo(cfg
, bw_cap
);
16627 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err
));
16628 if (err
!= BCME_UNSUPPORTED
)
16632 wiphy
= bcmcfg_to_wiphy(cfg
);
16633 nband
= bandlist
[0];
16635 for (i
= 1; i
<= nband
&& i
< ARRAYSIZE(bandlist
); i
++) {
16637 if (bandlist
[i
] == WLC_BAND_5G
&& __wl_band_5ghz_a
.n_channels
> 0) {
16638 bands
[IEEE80211_BAND_5GHZ
] =
16640 index
= IEEE80211_BAND_5GHZ
;
16641 if (nmode
&& (bw_cap
== WLC_N_BW_40ALL
|| bw_cap
== WLC_N_BW_20IN2G_40IN5G
))
16642 bands
[index
]->ht_cap
.cap
|= IEEE80211_HT_CAP_SGI_40
;
16644 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16645 /* VHT capabilities. */
16648 bands
[index
]->vht_cap
.vht_supported
= TRUE
;
16650 for (j
= 1; j
<= VHT_CAP_MCS_MAP_NSS_MAX
; j
++) {
16651 /* TX stream rates. */
16652 if (j
<= txstreams
) {
16653 VHT_MCS_MAP_SET_MCS_PER_SS(j
, VHT_CAP_MCS_MAP_0_9
,
16654 bands
[index
]->vht_cap
.vht_mcs
.tx_mcs_map
);
16656 VHT_MCS_MAP_SET_MCS_PER_SS(j
, VHT_CAP_MCS_MAP_NONE
,
16657 bands
[index
]->vht_cap
.vht_mcs
.tx_mcs_map
);
16660 /* RX stream rates. */
16661 if (j
<= rxstreams
) {
16662 VHT_MCS_MAP_SET_MCS_PER_SS(j
, VHT_CAP_MCS_MAP_0_9
,
16663 bands
[index
]->vht_cap
.vht_mcs
.rx_mcs_map
);
16665 VHT_MCS_MAP_SET_MCS_PER_SS(j
, VHT_CAP_MCS_MAP_NONE
,
16666 bands
[index
]->vht_cap
.vht_mcs
.rx_mcs_map
);
16672 /* 80 MHz is mandatory */
16673 bands
[index
]->vht_cap
.cap
|=
16674 IEEE80211_VHT_CAP_SHORT_GI_80
;
16676 if (WL_BW_CAP_160MHZ(bw_cap
)) {
16677 bands
[index
]->vht_cap
.cap
|=
16678 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ
;
16679 bands
[index
]->vht_cap
.cap
|=
16680 IEEE80211_VHT_CAP_SHORT_GI_160
;
16683 bands
[index
]->vht_cap
.cap
|=
16684 IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454
;
16687 bands
[index
]->vht_cap
.cap
|=
16688 IEEE80211_VHT_CAP_RXLDPC
;
16691 bands
[index
]->vht_cap
.cap
|=
16692 IEEE80211_VHT_CAP_TXSTBC
;
16695 bands
[index
]->vht_cap
.cap
|=
16696 (stbc_rx
<< VHT_CAP_INFO_RX_STBC_SHIFT
);
16699 bands
[index
]->vht_cap
.cap
|=
16700 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
;
16702 if (txbf_bfr_cap
) {
16703 bands
[index
]->vht_cap
.cap
|=
16704 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
;
16707 if (txbf_bfe_cap
|| txbf_bfr_cap
) {
16708 bands
[index
]->vht_cap
.cap
|=
16709 (2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT
);
16710 bands
[index
]->vht_cap
.cap
|=
16711 ((txstreams
- 1) <<
16712 VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT
);
16713 bands
[index
]->vht_cap
.cap
|=
16714 IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB
;
16717 /* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
16718 bands
[index
]->vht_cap
.cap
|=
16719 (7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT
);
16720 WL_INFORM(("%s band[%d] vht_enab=%d vht_cap=%08x "
16721 "vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
16722 __FUNCTION__
, index
,
16723 bands
[index
]->vht_cap
.vht_supported
,
16724 bands
[index
]->vht_cap
.cap
,
16725 bands
[index
]->vht_cap
.vht_mcs
.rx_mcs_map
,
16726 bands
[index
]->vht_cap
.vht_mcs
.tx_mcs_map
));
16730 else if (bandlist
[i
] == WLC_BAND_2G
&& __wl_band_2ghz
.n_channels
> 0) {
16731 bands
[IEEE80211_BAND_2GHZ
] =
16733 index
= IEEE80211_BAND_2GHZ
;
16734 if (bw_cap
== WLC_N_BW_40ALL
)
16735 bands
[index
]->ht_cap
.cap
|= IEEE80211_HT_CAP_SGI_40
;
16738 if ((index
>= 0) && nmode
) {
16739 bands
[index
]->ht_cap
.cap
|=
16740 (IEEE80211_HT_CAP_SGI_20
| IEEE80211_HT_CAP_DSSSCCK40
);
16741 bands
[index
]->ht_cap
.ht_supported
= TRUE
;
16742 bands
[index
]->ht_cap
.ampdu_factor
= IEEE80211_HT_MAX_AMPDU_64K
;
16743 bands
[index
]->ht_cap
.ampdu_density
= IEEE80211_HT_MPDU_DENSITY_16
;
16744 /* An HT shall support all EQM rates for one spatial stream */
16745 bands
[index
]->ht_cap
.mcs
.rx_mask
[0] = 0xff;
16750 wiphy
->bands
[IEEE80211_BAND_2GHZ
] = bands
[IEEE80211_BAND_2GHZ
];
16751 wiphy
->bands
[IEEE80211_BAND_5GHZ
] = bands
[IEEE80211_BAND_5GHZ
];
16753 /* check if any bands populated otherwise makes 2Ghz as default */
16754 if (wiphy
->bands
[IEEE80211_BAND_2GHZ
] == NULL
&&
16755 wiphy
->bands
[IEEE80211_BAND_5GHZ
] == NULL
) {
16756 /* Setup 2Ghz band as default */
16757 wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &__wl_band_2ghz
;
16761 wiphy_apply_custom_regulatory(wiphy
, &brcm_regdom
);
16766 s32
wl_update_wiphybands(struct bcm_cfg80211
*cfg
, bool notify
)
16770 mutex_lock(&cfg
->usr_sync
);
16771 err
= __wl_update_wiphybands(cfg
, notify
);
16772 mutex_unlock(&cfg
->usr_sync
);
16777 static s32
__wl_cfg80211_up(struct bcm_cfg80211
*cfg
)
16780 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
16781 struct wireless_dev
*wdev
= ndev
->ieee80211_ptr
;
16783 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
16784 #endif /* WBTEXT */
16787 #endif /* WLTDLS */
16791 if (!dhd_download_fw_on_driverload
) {
16792 err
= wl_create_event_handler(cfg
);
16794 WL_ERR(("wl_create_event_handler failed\n"));
16797 wl_init_event_handler(cfg
);
16800 err
= dhd_config_dongle(cfg
);
16804 err
= wl_config_ifmode(cfg
, ndev
, wdev
->iftype
);
16805 if (unlikely(err
&& err
!= -EINPROGRESS
)) {
16806 WL_ERR(("wl_config_ifmode failed\n"));
16808 WL_ERR(("return error %d\n", err
));
16813 err
= wl_init_scan(cfg
);
16815 WL_ERR(("wl_init_scan failed\n"));
16818 err
= __wl_update_wiphybands(cfg
, true);
16819 if (unlikely(err
)) {
16820 WL_ERR(("wl_update_wiphybands failed\n"));
16822 WL_ERR(("return error %d\n", err
));
16827 #ifdef DHD_LOSSLESS_ROAMING
16828 if (timer_pending(&cfg
->roam_timeout
)) {
16829 del_timer_sync(&cfg
->roam_timeout
);
16831 #endif /* DHD_LOSSLESS_ROAMING */
16833 err
= dhd_monitor_init(cfg
->pub
);
16836 /* when wifi up, set roam_prof to default value */
16837 if (dhd
->wbtext_support
) {
16838 if (dhd
->op_mode
& DHD_FLAG_STA_MODE
) {
16839 wl_cfg80211_wbtext_set_default(ndev
);
16840 wl_cfg80211_wbtext_clear_bssid_list(cfg
);
16843 #endif /* WBTEXT */
16845 if (wldev_iovar_getint(ndev
, "tdls_enable", &tdls
) == 0) {
16846 WL_DBG(("TDLS supported in fw\n"));
16847 cfg
->tdls_supported
= true;
16849 #endif /* WLTDLS */
16850 INIT_DELAYED_WORK(&cfg
->pm_enable_work
, wl_cfg80211_work_handler
);
16851 wl_set_drv_status(cfg
, READY
, ndev
);
16855 static s32
__wl_cfg80211_down(struct bcm_cfg80211
*cfg
)
16858 unsigned long flags
;
16859 struct net_info
*iter
, *next
;
16860 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
16861 #if defined(WL_CFG80211) && (defined(WL_ENABLE_P2P_IF) || \
16862 defined(WL_NEW_CFG_PRIVCMD_SUPPORT)) && !defined(PLATFORM_SLP)
16863 struct net_device
*p2p_net
= cfg
->p2p_net
;
16865 #ifdef PROP_TXSTATUS_VSDB
16866 #if defined(BCMSDIO) || defined(BCMDBUS)
16867 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
16868 #endif /* BCMSDIO || BCMDBUS */
16869 #endif /* PROP_TXSTATUS_VSDB */
16870 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
16871 struct cfg80211_scan_info info
;
16876 /* Check if cfg80211 interface is already down */
16877 if (!wl_get_drv_status(cfg
, READY
, ndev
)) {
16878 WL_DBG(("cfg80211 interface is already down\n"));
16879 return err
; /* it is even not ready */
16883 cfg
->tdls_supported
= false;
16884 #endif /* WLTDLS */
16886 /* Delete pm_enable_work */
16887 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_DEL
);
16889 /* clear all the security setting on primary Interface */
16890 wl_cfg80211_clear_security(cfg
);
16893 if (cfg
->p2p_supported
) {
16894 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
16895 #ifdef PROP_TXSTATUS_VSDB
16896 #if defined(BCMSDIO) || defined(BCMDBUS)
16897 if (wl_cfgp2p_vif_created(cfg
)) {
16898 bool enabled
= false;
16899 dhd_wlfc_get_enable(dhd
, &enabled
);
16900 if (enabled
&& cfg
->wlfc_on
&& dhd
->op_mode
!= DHD_FLAG_HOSTAP_MODE
&&
16901 dhd
->op_mode
!= DHD_FLAG_IBSS_MODE
) {
16902 dhd_wlfc_deinit(dhd
);
16903 cfg
->wlfc_on
= false;
16906 #endif /* BCMSDIO || BCMDBUS */
16907 #endif /* PROP_TXSTATUS_VSDB */
16911 /* clean up any left over interfaces */
16912 wl_cfg80211_cleanup_virtual_ifaces(ndev
, false);
16914 /* If primary BSS is operational (for e.g SoftAP), bring it down */
16915 if (wl_cfg80211_bss_isup(ndev
, 0)) {
16916 if (wl_cfg80211_bss_up(cfg
, ndev
, 0, 0) < 0)
16917 WL_ERR(("BSS down failed \n"));
16920 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16921 4 && __GNUC_MINOR__ >= 6))
16922 _Pragma("GCC diagnostic push")
16923 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16925 for_each_ndev(cfg
, iter
, next
) {
16926 if (iter
->ndev
) /* p2p discovery iface is null */
16927 wl_set_drv_status(cfg
, SCAN_ABORTING
, iter
->ndev
);
16929 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16930 4 && __GNUC_MINOR__ >= 6))
16931 _Pragma("GCC diagnostic pop")
16934 #ifdef P2P_LISTEN_OFFLOADING
16935 wl_cfg80211_p2plo_deinit(cfg
);
16936 #endif /* P2P_LISTEN_OFFLOADING */
16938 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
16939 if (cfg
->scan_request
) {
16940 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
16941 info
.aborted
= true;
16942 cfg80211_scan_done(cfg
->scan_request
, &info
);
16944 cfg80211_scan_done(cfg
->scan_request
, true);
16946 cfg
->scan_request
= NULL
;
16948 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
16949 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16950 4 && __GNUC_MINOR__ >= 6))
16951 _Pragma("GCC diagnostic push")
16952 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16954 for_each_ndev(cfg
, iter
, next
) {
16955 /* p2p discovery iface ndev ptr could be null */
16956 if (iter
->ndev
== NULL
)
16958 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
16959 if (wl_get_drv_status(cfg
, CONNECTED
, iter
->ndev
)) {
16960 CFG80211_DISCONNECTED(iter
->ndev
, 0, NULL
, 0, false, GFP_KERNEL
);
16962 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) */
16963 wl_clr_drv_status(cfg
, READY
, iter
->ndev
);
16964 wl_clr_drv_status(cfg
, SCANNING
, iter
->ndev
);
16965 wl_clr_drv_status(cfg
, SCAN_ABORTING
, iter
->ndev
);
16966 wl_clr_drv_status(cfg
, CONNECTING
, iter
->ndev
);
16967 wl_clr_drv_status(cfg
, CONNECTED
, iter
->ndev
);
16968 wl_clr_drv_status(cfg
, DISCONNECTING
, iter
->ndev
);
16969 wl_clr_drv_status(cfg
, AP_CREATED
, iter
->ndev
);
16970 wl_clr_drv_status(cfg
, AP_CREATING
, iter
->ndev
);
16972 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16973 4 && __GNUC_MINOR__ >= 6))
16974 _Pragma("GCC diagnostic pop")
16976 bcmcfg_to_prmry_ndev(cfg
)->ieee80211_ptr
->iftype
=
16977 NL80211_IFTYPE_STATION
;
16978 #if defined(WL_CFG80211) && (defined(WL_ENABLE_P2P_IF) || \
16979 defined(WL_NEW_CFG_PRIVCMD_SUPPORT)) && !defined(PLATFORM_SLP)
16981 dev_close(p2p_net
);
16984 /* Avoid deadlock from wl_cfg80211_down */
16985 if (!dhd_download_fw_on_driverload
) {
16986 mutex_unlock(&cfg
->usr_sync
);
16987 wl_destroy_event_handler(cfg
);
16988 mutex_lock(&cfg
->usr_sync
);
16992 if (cfg
->link_up
) { //army fix wifi stop call trace issue
16993 CFG80211_DISCONNECTED(ndev
, 0, NULL
, 0, false, GFP_KERNEL
);
16996 if (cfg
->p2p_supported
) {
16997 if (timer_pending(&cfg
->p2p
->listen_timer
))
16998 del_timer_sync(&cfg
->p2p
->listen_timer
);
16999 wl_cfgp2p_down(cfg
);
17002 if (timer_pending(&cfg
->scan_timeout
)) {
17003 del_timer_sync(&cfg
->scan_timeout
);
17006 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t
*)(cfg
->pub
));
17008 dhd_monitor_uninit();
17009 #ifdef WLAIBSS_MCHAN
17010 bcm_cfg80211_del_ibss_if(cfg
->wdev
->wiphy
, cfg
->ibss_cfgdev
);
17011 #endif /* WLAIBSS_MCHAN */
17015 /* Clear interworking element. */
17017 cfg
->wl11u
= FALSE
;
17021 #ifdef CUSTOMER_HW4_DEBUG
17022 if (wl_scan_timeout_dbg_enabled
) {
17023 wl_scan_timeout_dbg_clear();
17025 #endif /* CUSTOMER_HW4_DEBUG */
17027 cfg
->disable_roam_event
= false;
17029 DNGL_FUNC(dhd_cfg80211_down
, (cfg
));
17032 /* Printout all netinfo entries */
17033 wl_probe_wdev_all(cfg
);
17034 #endif /* DHD_IFDEBUG */
17039 s32
wl_cfg80211_up(struct net_device
*net
)
17041 struct bcm_cfg80211
*cfg
;
17045 #ifdef DISABLE_PM_BCNRX
17048 s8 iovbuf
[WLC_IOCTL_SMLEN
];
17049 #endif /* DISABLE_PM_BCNRX */
17052 cfg
= wl_get_cfg(net
);
17054 if ((err
= wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg
), WLC_GET_VERSION
, &val
,
17055 sizeof(int)) < 0)) {
17056 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err
));
17060 if (val
!= WLC_IOCTL_VERSION
&& val
!= 1) {
17061 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
17062 val
, WLC_IOCTL_VERSION
));
17063 return BCME_VERSION
;
17065 ioctl_version
= val
;
17066 wl_cfg80211_check_in4way(cfg
, net
, NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
,
17067 WL_EXT_STATUS_DISCONNECTED
, NULL
);
17068 WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version
));
17070 mutex_lock(&cfg
->usr_sync
);
17071 dhd
= (dhd_pub_t
*)(cfg
->pub
);
17072 if (!(dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
17073 err
= wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg
));
17074 if (unlikely(err
)) {
17075 mutex_unlock(&cfg
->usr_sync
);
17080 cfg
->wdev
->wiphy
->features
|= NL80211_FEATURE_USERSPACE_MPM
;
17081 #endif /* WLMESH */
17083 err
= __wl_cfg80211_up(cfg
);
17085 WL_ERR(("__wl_cfg80211_up failed\n"));
17089 /* IOVAR configurations with 'up' condition */
17090 #ifdef DISABLE_PM_BCNRX
17091 interr
= wldev_iovar_setbuf(bcmcfg_to_prmry_ndev(cfg
), "pm_bcnrx", (char *)¶m
,
17092 sizeof(param
), iovbuf
, sizeof(iovbuf
), NULL
);
17093 if (unlikely(interr
)) {
17094 WL_ERR(("Set pm_bcnrx returned (%d)\n", interr
));
17096 #endif /* DISABLE_PM_BCNRX */
17098 mutex_unlock(&cfg
->usr_sync
);
17100 #ifdef WLAIBSS_MCHAN
17101 bcm_cfg80211_add_ibss_if(cfg
->wdev
->wiphy
, IBSS_IF_NAME
);
17102 #endif /* WLAIBSS_MCHAN */
17104 #ifdef DUAL_STA_STATIC_IF
17105 #ifdef WL_VIRTUAL_APSTA
17106 #error "Both DUAL STA and DUAL_STA_STATIC_IF can't be enabled together"
17108 /* Static Interface support is currently supported only for STA only builds (without P2P) */
17109 wl_cfg80211_create_iface(cfg
->wdev
->wiphy
, NL80211_IFTYPE_STATION
, NULL
, "wlan%d");
17110 #endif /* DUAL_STA_STATIC_IF */
17115 /* Private Event to Supplicant with indication that chip hangs */
17116 int wl_cfg80211_hang(struct net_device
*dev
, u16 reason
)
17118 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
17120 #if defined(SOFTAP_SEND_HANGEVT)
17121 /* specifc mac address used for hang event */
17122 uint8 hang_mac
[ETHER_ADDR_LEN
] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
17123 #endif /* SOFTAP_SEND_HANGEVT */
17128 dhd
= (dhd_pub_t
*)(cfg
->pub
);
17129 #if defined(DHD_HANG_SEND_UP_TEST)
17130 if (dhd
->req_hang_type
) {
17131 WL_ERR(("%s, Clear HANG test request 0x%x\n",
17132 __FUNCTION__
, dhd
->req_hang_type
));
17133 dhd
->req_hang_type
= 0;
17135 #endif /* DHD_HANG_SEND_UP_TEST */
17136 if ((dhd
->hang_reason
<= HANG_REASON_MASK
) || (dhd
->hang_reason
>= HANG_REASON_MAX
)) {
17137 WL_ERR(("%s, Invalid hang reason 0x%x\n",
17138 __FUNCTION__
, dhd
->hang_reason
));
17139 dhd
->hang_reason
= HANG_REASON_UNKNOWN
;
17141 #ifdef DHD_USE_EXTENDED_HANG_REASON
17142 if (dhd
->hang_reason
!= 0) {
17143 reason
= dhd
->hang_reason
;
17145 #endif /* DHD_USE_EXTENDED_HANG_REASON */
17146 WL_ERR(("In : chip crash eventing, reason=0x%x\n", (uint32
)(dhd
->hang_reason
)));
17148 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_DEL
);
17149 #ifdef SOFTAP_SEND_HANGEVT
17150 if (dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
) {
17151 cfg80211_del_sta(dev
, hang_mac
, GFP_ATOMIC
);
17153 #endif /* SOFTAP_SEND_HANGEVT */
17155 CFG80211_DISCONNECTED(dev
, reason
, NULL
, 0, false, GFP_KERNEL
);
17157 #if defined(RSSIAVG)
17158 wl_free_rssi_cache(&cfg
->g_rssi_cache_ctrl
);
17160 #if defined(BSSCACHE)
17161 wl_free_bss_cache(&cfg
->g_bss_cache_ctrl
);
17169 s32
wl_cfg80211_down(struct net_device
*dev
)
17171 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
17177 mutex_lock(&cfg
->usr_sync
);
17178 #if defined(RSSIAVG)
17179 wl_free_rssi_cache(&cfg
->g_rssi_cache_ctrl
);
17181 #if defined(BSSCACHE)
17182 wl_free_bss_cache(&cfg
->g_bss_cache_ctrl
);
17184 err
= __wl_cfg80211_down(cfg
);
17185 mutex_unlock(&cfg
->usr_sync
);
17190 static void *wl_read_prof(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 item
)
17192 unsigned long flags
;
17194 struct wl_profile
*profile
= wl_get_profile_by_netdev(cfg
, ndev
);
17198 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
17201 rptr
= &profile
->sec
;
17204 rptr
= &profile
->active
;
17206 case WL_PROF_BSSID
:
17207 rptr
= profile
->bssid
;
17210 rptr
= &profile
->ssid
;
17213 rptr
= &profile
->channel
;
17216 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
17218 WL_ERR(("invalid item (%d)\n", item
));
17223 wl_update_prof(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
17224 const wl_event_msg_t
*e
, const void *data
, s32 item
)
17227 const struct wlc_ssid
*ssid
;
17228 unsigned long flags
;
17229 struct wl_profile
*profile
= wl_get_profile_by_netdev(cfg
, ndev
);
17233 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
17236 ssid
= (const wlc_ssid_t
*) data
;
17237 memset(profile
->ssid
.SSID
, 0,
17238 sizeof(profile
->ssid
.SSID
));
17239 profile
->ssid
.SSID_len
= MIN(ssid
->SSID_len
, DOT11_MAX_SSID_LEN
);
17240 memcpy(profile
->ssid
.SSID
, ssid
->SSID
, profile
->ssid
.SSID_len
);
17242 case WL_PROF_BSSID
:
17244 memcpy(profile
->bssid
, data
, ETHER_ADDR_LEN
);
17246 memset(profile
->bssid
, 0, ETHER_ADDR_LEN
);
17249 memcpy(&profile
->sec
, data
, sizeof(profile
->sec
));
17252 profile
->active
= *(const bool *)data
;
17254 case WL_PROF_BEACONINT
:
17255 profile
->beacon_interval
= *(const u16
*)data
;
17257 case WL_PROF_DTIMPERIOD
:
17258 profile
->dtim_period
= *(const u8
*)data
;
17261 profile
->channel
= *(const u32
*)data
;
17267 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
17269 if (err
== -EOPNOTSUPP
)
17270 WL_ERR(("unsupported item (%d)\n", item
));
17275 void wl_cfg80211_dbg_level(u32 level
)
17278 * prohibit to change debug level
17279 * by insmod parameter.
17280 * eventually debug level will be configured
17281 * in compile time by using CONFIG_XXX
17283 /* wl_dbg_level = level; */
17286 static bool wl_is_ibssmode(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
)
17288 return wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_IBSS
;
17291 static __used
bool wl_is_ibssstarter(struct bcm_cfg80211
*cfg
)
17293 return cfg
->ibss_starter
;
17296 static void wl_rst_ie(struct bcm_cfg80211
*cfg
)
17298 struct wl_ie
*ie
= wl_to_ie(cfg
);
17303 static __used s32
wl_add_ie(struct bcm_cfg80211
*cfg
, u8 t
, u8 l
, u8
*v
)
17305 struct wl_ie
*ie
= wl_to_ie(cfg
);
17308 if (unlikely(ie
->offset
+ l
+ 2 > WL_TLV_INFO_MAX
)) {
17309 WL_ERR(("ei crosses buffer boundary\n"));
17312 ie
->buf
[ie
->offset
] = t
;
17313 ie
->buf
[ie
->offset
+ 1] = l
;
17314 memcpy(&ie
->buf
[ie
->offset
+ 2], v
, l
);
17315 ie
->offset
+= l
+ 2;
17320 static void wl_update_hidden_ap_ie(struct wl_bss_info
*bi
, const u8
*ie_stream
, u32
*ie_size
,
17324 int32 ssid_len
= MIN(bi
->SSID_len
, DOT11_MAX_SSID_LEN
);
17325 int32 remaining_ie_buf_len
, available_buffer_len
;
17326 /* cfg80211_find_ie defined in kernel returning const u8 */
17327 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
17328 4 && __GNUC_MINOR__ >= 6))
17329 _Pragma("GCC diagnostic push")
17330 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
17332 ssidie
= (u8
*)cfg80211_find_ie(WLAN_EID_SSID
, ie_stream
, *ie_size
);
17333 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
17334 4 && __GNUC_MINOR__ >= 6))
17335 _Pragma("GCC diagnostic pop")
17338 * 1. No ssid IE is FOUND or
17339 * 2. New ssid length is > what was allocated for existing ssid (as
17340 * we do not want to overwrite the rest of the IEs) or
17341 * 3. If in case of erroneous buffer input where ssid length doesnt match the space
17347 available_buffer_len
= ((int)(*ie_size
)) - (ssidie
+ 2 - ie_stream
);
17348 remaining_ie_buf_len
= available_buffer_len
- (int)ssidie
[1];
17349 if ((ssid_len
> ssidie
[1]) ||
17350 (ssidie
[1] > available_buffer_len
)) {
17355 if (ssidie
[1] != ssid_len
) {
17357 WL_ERR(("%s: Wrong SSID len: %d != %d\n",
17358 __FUNCTION__
, ssidie
[1], bi
->SSID_len
));
17361 WL_ERR(("Changing the SSID Info.\n"));
17362 memmove(ssidie
+ ssid_len
+ 2,
17363 (ssidie
+ 2) + ssidie
[1],
17364 remaining_ie_buf_len
);
17365 memcpy(ssidie
+ 2, bi
->SSID
, ssid_len
);
17366 *ie_size
= *ie_size
+ ssid_len
- ssidie
[1];
17367 ssidie
[1] = ssid_len
;
17371 if (*(ssidie
+ 2) == '\0')
17372 memcpy(ssidie
+ 2, bi
->SSID
, ssid_len
);
17376 static s32
wl_mrg_ie(struct bcm_cfg80211
*cfg
, u8
*ie_stream
, u16 ie_size
)
17378 struct wl_ie
*ie
= wl_to_ie(cfg
);
17381 if (unlikely(ie
->offset
+ ie_size
> WL_TLV_INFO_MAX
)) {
17382 WL_ERR(("ei_stream crosses buffer boundary\n"));
17385 memcpy(&ie
->buf
[ie
->offset
], ie_stream
, ie_size
);
17386 ie
->offset
+= ie_size
;
17391 static s32
wl_cp_ie(struct bcm_cfg80211
*cfg
, u8
*dst
, u16 dst_size
)
17393 struct wl_ie
*ie
= wl_to_ie(cfg
);
17396 if (unlikely(ie
->offset
> dst_size
)) {
17397 WL_ERR(("dst_size is not enough\n"));
17400 memcpy(dst
, &ie
->buf
[0], ie
->offset
);
17405 static u32
wl_get_ielen(struct bcm_cfg80211
*cfg
)
17407 struct wl_ie
*ie
= wl_to_ie(cfg
);
17412 static void wl_link_up(struct bcm_cfg80211
*cfg
)
17414 cfg
->link_up
= true;
17417 static void wl_link_down(struct bcm_cfg80211
*cfg
)
17419 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
17422 cfg
->link_up
= false;
17424 conn_info
->req_ie_len
= 0;
17425 conn_info
->resp_ie_len
= 0;
17429 static unsigned long wl_lock_eq(struct bcm_cfg80211
*cfg
)
17431 unsigned long flags
;
17433 spin_lock_irqsave(&cfg
->eq_lock
, flags
);
17437 static void wl_unlock_eq(struct bcm_cfg80211
*cfg
, unsigned long flags
)
17439 spin_unlock_irqrestore(&cfg
->eq_lock
, flags
);
17442 static void wl_init_eq_lock(struct bcm_cfg80211
*cfg
)
17444 spin_lock_init(&cfg
->eq_lock
);
17447 static void wl_delay(u32 ms
)
17449 if (in_atomic() || (ms
< jiffies_to_msecs(1))) {
17450 OSL_DELAY(ms
*1000);
17456 s32
wl_cfg80211_get_p2p_dev_addr(struct net_device
*net
, struct ether_addr
*p2pdev_addr
)
17458 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17459 struct ether_addr primary_mac
;
17462 if (!p2p_is_on(cfg
)) {
17463 get_primary_mac(cfg
, &primary_mac
);
17464 wl_cfgp2p_generate_bss_mac(cfg
, &primary_mac
);
17466 memcpy(p2pdev_addr
->octet
, wl_to_p2p_bss_macaddr(cfg
, P2PAPI_BSSCFG_DEVICE
).octet
,
17472 s32
wl_cfg80211_set_p2p_noa(struct net_device
*net
, char* buf
, int len
)
17474 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17476 return wl_cfgp2p_set_p2p_noa(cfg
, net
, buf
, len
);
17479 s32
wl_cfg80211_get_p2p_noa(struct net_device
*net
, char* buf
, int len
)
17481 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17483 return wl_cfgp2p_get_p2p_noa(cfg
, net
, buf
, len
);
17486 s32
wl_cfg80211_set_p2p_ps(struct net_device
*net
, char* buf
, int len
)
17488 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17490 return wl_cfgp2p_set_p2p_ps(cfg
, net
, buf
, len
);
17493 s32
wl_cfg80211_set_p2p_ecsa(struct net_device
*net
, char* buf
, int len
)
17495 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17497 return wl_cfgp2p_set_p2p_ecsa(cfg
, net
, buf
, len
);
17500 s32
wl_cfg80211_increase_p2p_bw(struct net_device
*net
, char* buf
, int len
)
17502 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17504 return wl_cfgp2p_increase_p2p_bw(cfg
, net
, buf
, len
);
17507 #ifdef P2PLISTEN_AP_SAMECHN
17508 s32
wl_cfg80211_set_p2p_resp_ap_chn(struct net_device
*net
, s32 enable
)
17510 s32 ret
= wldev_iovar_setint(net
, "p2p_resp_ap_chn", enable
);
17512 if ((ret
== 0) && enable
) {
17513 /* disable PM for p2p responding on infra AP channel */
17516 ret
= wldev_ioctl_set(net
, WLC_SET_PM
, &pm
, sizeof(pm
));
17521 #endif /* P2PLISTEN_AP_SAMECHN */
17523 s32
wl_cfg80211_channel_to_freq(u32 channel
)
17527 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
17528 freq
= ieee80211_channel_to_frequency(channel
);
17532 if (channel
<= CH_MAX_2G_CHANNEL
)
17533 band
= IEEE80211_BAND_2GHZ
;
17535 band
= IEEE80211_BAND_5GHZ
;
17536 freq
= ieee80211_channel_to_frequency(channel
, band
);
17545 wl_tdls_event_handler(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
17546 const wl_event_msg_t
*e
, void *data
) {
17548 struct net_device
*ndev
= NULL
;
17549 u32 reason
= ntoh32(e
->reason
);
17552 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
17555 case WLC_E_TDLS_PEER_DISCOVERED
:
17556 msg
= " TDLS PEER DISCOVERD ";
17558 case WLC_E_TDLS_PEER_CONNECTED
:
17559 if (cfg
->tdls_mgmt_frame
) {
17560 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
17561 cfg80211_rx_mgmt(cfgdev
, cfg
->tdls_mgmt_freq
, 0,
17562 cfg
->tdls_mgmt_frame
, cfg
->tdls_mgmt_frame_len
, 0);
17563 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
17564 cfg80211_rx_mgmt(cfgdev
, cfg
->tdls_mgmt_freq
, 0,
17565 cfg
->tdls_mgmt_frame
, cfg
->tdls_mgmt_frame_len
, 0,
17567 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
17568 defined(WL_COMPAT_WIRELESS)
17569 cfg80211_rx_mgmt(cfgdev
, cfg
->tdls_mgmt_freq
, 0,
17570 cfg
->tdls_mgmt_frame
, cfg
->tdls_mgmt_frame_len
,
17573 cfg80211_rx_mgmt(cfgdev
, cfg
->tdls_mgmt_freq
,
17574 cfg
->tdls_mgmt_frame
, cfg
->tdls_mgmt_frame_len
, GFP_ATOMIC
);
17577 msg
= " TDLS PEER CONNECTED ";
17578 #ifdef SUPPORT_SET_CAC
17579 /* TDLS connect reset CAC */
17580 wl_cfg80211_set_cac(cfg
, 0);
17581 #endif /* SUPPORT_SET_CAC */
17583 case WLC_E_TDLS_PEER_DISCONNECTED
:
17584 if (cfg
->tdls_mgmt_frame
) {
17585 kfree(cfg
->tdls_mgmt_frame
);
17586 cfg
->tdls_mgmt_frame
= NULL
;
17587 cfg
->tdls_mgmt_freq
= 0;
17589 msg
= "TDLS PEER DISCONNECTED ";
17590 #ifdef SUPPORT_SET_CAC
17591 /* TDLS disconnec, set CAC */
17592 wl_cfg80211_set_cac(cfg
, 1);
17593 #endif /* SUPPORT_SET_CAC */
17597 WL_ERR(("%s: " MACDBG
" on %s ndev\n", msg
, MAC2STRDBG((const u8
*)(&e
->addr
)),
17598 (bcmcfg_to_prmry_ndev(cfg
) == ndev
) ? "primary" : "secondary"));
17603 #endif /* WLTDLS */
17605 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
17607 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
17608 KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
17609 wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
17610 u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
17611 u32 peer_capability
, const u8
*buf
, size_t len
)
17612 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
17613 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
17614 wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
17615 const u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
17616 u32 peer_capability
, const u8
*buf
, size_t len
)
17617 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
17618 wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
17619 const u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
17620 u32 peer_capability
, bool initiator
, const u8
*buf
, size_t len
)
17621 #else /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17622 wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
17623 u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
17624 const u8
*buf
, size_t len
)
17625 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17629 struct bcm_cfg80211
*cfg
;
17630 tdls_wfd_ie_iovar_t info
;
17631 memset(&info
, 0, sizeof(tdls_wfd_ie_iovar_t
));
17632 cfg
= wl_get_cfg(dev
);
17634 #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
17635 /* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
17636 * and that cuases build error
17638 BCM_REFERENCE(peer_capability
);
17639 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17641 switch (action_code
) {
17642 /* We need to set TDLS Wifi Display IE to firmware
17643 * using tdls_wfd_ie iovar
17645 case WLAN_TDLS_SET_PROBE_WFD_IE
:
17646 WL_ERR(("%s WLAN_TDLS_SET_PROBE_WFD_IE\n", __FUNCTION__
));
17647 info
.mode
= TDLS_WFD_PROBE_IE_TX
;
17648 memcpy(&info
.data
, buf
, len
);
17651 case WLAN_TDLS_SET_SETUP_WFD_IE
:
17652 WL_ERR(("%s WLAN_TDLS_SET_SETUP_WFD_IE\n", __FUNCTION__
));
17653 info
.mode
= TDLS_WFD_IE_TX
;
17654 memcpy(&info
.data
, buf
, len
);
17657 case WLAN_TDLS_SET_WFD_ENABLED
:
17658 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_ENABLED\n", __FUNCTION__
));
17659 dhd_tdls_set_mode((dhd_pub_t
*)(cfg
->pub
), true);
17661 case WLAN_TDLS_SET_WFD_DISABLED
:
17662 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_DISABLED\n", __FUNCTION__
));
17663 dhd_tdls_set_mode((dhd_pub_t
*)(cfg
->pub
), false);
17666 WL_ERR(("Unsupported action code : %d\n", action_code
));
17669 ret
= wldev_iovar_setbuf(dev
, "tdls_wfd_ie", &info
, sizeof(info
),
17670 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
17673 WL_ERR(("tdls_wfd_ie error %d\n", ret
));
17677 #endif /* WLTDLS */
17682 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
17683 wl_cfg80211_tdls_oper(struct wiphy
*wiphy
, struct net_device
*dev
,
17684 const u8
*peer
, enum nl80211_tdls_operation oper
)
17686 wl_cfg80211_tdls_oper(struct wiphy
*wiphy
, struct net_device
*dev
,
17687 u8
*peer
, enum nl80211_tdls_operation oper
)
17692 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
17695 bool tdls_auto_mode
= false;
17696 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
17697 memset(&info
, 0, sizeof(tdls_iovar_t
));
17699 memcpy(&info
.ea
, peer
, ETHER_ADDR_LEN
);
17704 case NL80211_TDLS_DISCOVERY_REQ
:
17705 /* If the discovery request is broadcast then we need to set
17706 * info.mode to Tunneled Probe Request
17708 if (memcmp(peer
, (const uint8
*)BSSID_BROADCAST
, ETHER_ADDR_LEN
) == 0) {
17709 info
.mode
= TDLS_MANUAL_EP_WFD_TPQ
;
17710 WL_ERR(("%s TDLS TUNNELED PRBOBE REQUEST\n", __FUNCTION__
));
17712 info
.mode
= TDLS_MANUAL_EP_DISCOVERY
;
17715 case NL80211_TDLS_SETUP
:
17716 if (dhdp
->tdls_mode
== true) {
17717 info
.mode
= TDLS_MANUAL_EP_CREATE
;
17718 tdls_auto_mode
= false;
17719 /* Do tear down and create a fresh one */
17720 ret
= wl_cfg80211_tdls_config(cfg
, TDLS_STATE_TEARDOWN
, tdls_auto_mode
);
17725 tdls_auto_mode
= true;
17728 case NL80211_TDLS_TEARDOWN
:
17729 info
.mode
= TDLS_MANUAL_EP_DELETE
;
17732 WL_ERR(("Unsupported operation : %d\n", oper
));
17736 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_SETUP
, tdls_auto_mode
);
17741 ret
= wldev_iovar_setbuf(dev
, "tdls_endpoint", &info
, sizeof(info
),
17742 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
17744 WL_ERR(("tdls_endpoint error %d\n", ret
));
17751 #endif /* WLTDLS */
17757 * This function returns no of bytes written
17758 * In case of failure return zero, not bcme_error
17760 s32
wl_cfg80211_set_wps_p2p_ie(struct net_device
*ndev
, char *buf
, int len
,
17761 enum wl_management_type type
)
17763 struct bcm_cfg80211
*cfg
;
17765 struct ether_addr primary_mac
;
17768 cfg
= wl_get_cfg(ndev
);
17770 if (wl_get_drv_status(cfg
, AP_CREATING
, ndev
)) {
17771 /* Vendor IEs should be set to FW
17772 * after SoftAP interface is brought up
17774 WL_DBG(("Skipping set IE since AP is not up \n"));
17776 } else if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
17777 /* Either stand alone AP case or P2P discovery */
17778 if (wl_get_drv_status(cfg
, AP_CREATED
, ndev
)) {
17779 /* Stand alone AP case on primary interface */
17780 WL_DBG(("Apply IEs for Primary AP Interface \n"));
17784 /* If p2p not initialized, return failure */
17785 WL_ERR(("P2P not initialized \n"));
17788 /* P2P Discovery case (p2p listen) */
17789 if (!cfg
->p2p
->on
) {
17790 /* Turn on Discovery interface */
17791 get_primary_mac(cfg
, &primary_mac
);
17792 wl_cfgp2p_generate_bss_mac(cfg
, &primary_mac
);
17793 p2p_on(cfg
) = true;
17794 ret
= wl_cfgp2p_enable_discovery(cfg
, ndev
, NULL
, 0);
17795 if (unlikely(ret
)) {
17796 WL_ERR(("Enable discovery failed \n"));
17800 WL_DBG(("Apply IEs for P2P Discovery Iface \n"));
17801 ndev
= wl_to_p2p_bss_ndev(cfg
, P2PAPI_BSSCFG_PRIMARY
);
17802 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
17805 /* Virtual AP/ P2P Group Interface */
17806 WL_DBG(("Apply IEs for iface:%s\n", ndev
->name
));
17807 bssidx
= wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
);
17810 if (ndev
!= NULL
) {
17813 pktflag
= VNDR_IE_BEACON_FLAG
;
17815 case WL_PROBE_RESP
:
17816 pktflag
= VNDR_IE_PRBRSP_FLAG
;
17818 case WL_ASSOC_RESP
:
17819 pktflag
= VNDR_IE_ASSOCRSP_FLAG
;
17823 ret
= wl_cfg80211_set_mgmt_vndr_ies(cfg
,
17824 ndev_to_cfgdev(ndev
), bssidx
, pktflag
, buf
, len
);
17831 #ifdef WL_SUPPORT_AUTO_CHANNEL
17833 wl_cfg80211_set_auto_channel_scan_state(struct net_device
*ndev
)
17836 s32 ret
= BCME_ERROR
;
17837 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
17838 /* Set interface up, explicitly. */
17841 ret
= wldev_ioctl_set(ndev
, WLC_UP
, (void *)&val
, sizeof(val
));
17843 WL_ERR(("set interface up failed, error = %d\n", ret
));
17847 /* Stop all scan explicitly, till auto channel selection complete. */
17848 wl_set_drv_status(cfg
, SCANNING
, ndev
);
17849 if (cfg
->escan_info
.ndev
== NULL
) {
17853 ret
= wl_notify_escan_complete(cfg
, ndev
, true, true);
17855 WL_ERR(("set scan abort failed, error = %d\n", ret
));
17856 ret
= BCME_OK
; // terence 20140115: fix escan_complete error
17865 wl_cfg80211_valid_channel_p2p(int channel
)
17867 bool valid
= false;
17869 /* channel 1 to 14 */
17870 if ((channel
>= 1) && (channel
<= 14)) {
17873 /* channel 36 to 48 */
17874 else if ((channel
>= 36) && (channel
<= 48)) {
17877 /* channel 149 to 161 */
17878 else if ((channel
>= 149) && (channel
<= 161)) {
17883 WL_INFORM(("invalid P2P chanspec, channel = %d\n", channel
));
17890 wl_cfg80211_get_chanspecs_2g(struct net_device
*ndev
, void *buf
, s32 buflen
)
17892 s32 ret
= BCME_ERROR
;
17893 struct bcm_cfg80211
*cfg
= NULL
;
17894 chanspec_t chanspec
= 0;
17896 cfg
= wl_get_cfg(ndev
);
17898 /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
17899 chanspec
|= (WL_CHANSPEC_BAND_2G
| WL_CHANSPEC_BW_20
|
17900 WL_CHANSPEC_CTL_SB_NONE
);
17901 chanspec
= wl_chspec_host_to_driver(chanspec
);
17903 ret
= wldev_iovar_getbuf_bsscfg(ndev
, "chanspecs", (void *)&chanspec
,
17904 sizeof(chanspec
), buf
, buflen
, 0, &cfg
->ioctl_buf_sync
);
17906 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret
));
17913 wl_cfg80211_get_chanspecs_5g(struct net_device
*ndev
, void *buf
, s32 buflen
)
17916 s32 ret
= BCME_ERROR
;
17919 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
17920 wl_uint32_list_t
*list
= NULL
;
17921 chanspec_t chanspec
= 0;
17923 /* Restrict channels to 5GHz, 20MHz BW, no SB. */
17924 chanspec
|= (WL_CHANSPEC_BAND_5G
| WL_CHANSPEC_BW_20
|
17925 WL_CHANSPEC_CTL_SB_NONE
);
17926 chanspec
= wl_chspec_host_to_driver(chanspec
);
17928 ret
= wldev_iovar_getbuf_bsscfg(ndev
, "chanspecs", (void *)&chanspec
,
17929 sizeof(chanspec
), buf
, buflen
, 0, &cfg
->ioctl_buf_sync
);
17931 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret
));
17935 list
= (wl_uint32_list_t
*)buf
;
17936 /* Skip DFS and inavlid P2P channel. */
17937 for (i
= 0, j
= 0; i
< dtoh32(list
->count
); i
++) {
17938 chanspec
= (chanspec_t
) dtoh32(list
->element
[i
]);
17939 channel
= CHSPEC_CHANNEL(chanspec
);
17941 ret
= wldev_iovar_getint(ndev
, "per_chan_info", &channel
);
17943 WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret
));
17947 if (CHANNEL_IS_RADAR(channel
) ||
17948 !(wl_cfg80211_valid_channel_p2p(CHSPEC_CHANNEL(chanspec
)))) {
17951 list
->element
[j
] = list
->element
[i
];
17964 wl_cfg80211_get_best_channel(struct net_device
*ndev
, void *buf
, int buflen
,
17967 s32 ret
= BCME_ERROR
;
17972 /* Start auto channel selection scan. */
17973 ret
= wldev_ioctl_set(ndev
, WLC_START_CHANNEL_SEL
, buf
, buflen
);
17975 WL_ERR(("can't start auto channel scan, error = %d\n", ret
));
17980 /* Wait for auto channel selection, worst case possible delay is 5250ms. */
17981 retry
= CHAN_SEL_RETRY_COUNT
;
17984 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY
);
17986 ret
= wldev_ioctl_get(ndev
, WLC_GET_CHANNEL_SEL
, &chosen
, sizeof(chosen
));
17987 if ((ret
== 0) && (dtoh32(chosen
) != 0)) {
17988 chip
= dhd_conf_get_chip(dhd_get_pub(ndev
));
17989 if (chip
!= BCM43362_CHIP_ID
&& chip
!= BCM4330_CHIP_ID
&&
17990 chip
!= BCM43143_CHIP_ID
) {
17993 chanspec
= wl_chspec_driver_to_host(chosen
);
17994 WL_INFORM(("selected chanspec = 0x%x\n", chanspec
));
17995 ctl_chan
= wf_chspec_ctlchan(chanspec
);
17996 WL_INFORM(("selected ctl_chan = %d\n", ctl_chan
));
17997 *channel
= (u16
)(ctl_chan
& 0x00FF);
17999 *channel
= (u16
)(chosen
& 0x00FF);
18000 WL_INFORM(("selected channel = %d\n", *channel
));
18003 WL_INFORM(("attempt = %d, ret = %d, chosen = %d\n",
18004 (CHAN_SEL_RETRY_COUNT
- retry
), ret
, dtoh32(chosen
)));
18008 WL_ERR(("failure, auto channel selection timed out\n"));
18012 WL_INFORM(("selected channel = %d\n", *channel
));
18019 wl_cfg80211_restore_auto_channel_scan_state(struct net_device
*ndev
)
18021 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
18022 /* Clear scan stop driver status. */
18023 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
18029 wl_cfg80211_get_best_channels(struct net_device
*dev
, char* cmd
, int total_len
)
18031 int channel
= 0, band
, band_cur
;
18032 s32 ret
= BCME_ERROR
;
18035 struct bcm_cfg80211
*cfg
= NULL
;
18036 struct net_device
*ndev
= NULL
;
18038 memset(cmd
, 0, total_len
);
18040 buf
= kmalloc(CHANSPEC_BUF_SIZE
, GFP_KERNEL
);
18042 WL_ERR(("failed to allocate chanspec buffer\n"));
18047 * Always use primary interface, irrespective of interface on which
18050 cfg
= wl_get_cfg(dev
);
18051 ndev
= bcmcfg_to_prmry_ndev(cfg
);
18054 * Make sure that FW and driver are in right state to do auto channel
18057 ret
= wl_cfg80211_set_auto_channel_scan_state(ndev
);
18059 WL_ERR(("can't set auto channel scan state, error = %d\n", ret
));
18063 ret
= wldev_ioctl(dev
, WLC_GET_BAND
, &band_cur
, sizeof(band_cur
), false);
18064 if (band_cur
!= WLC_BAND_5G
) {
18065 /* Best channel selection in 2.4GHz band. */
18066 ret
= wl_cfg80211_get_chanspecs_2g(ndev
, (void *)buf
, CHANSPEC_BUF_SIZE
);
18068 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret
));
18072 ret
= wl_cfg80211_get_best_channel(ndev
, (void *)buf
, CHANSPEC_BUF_SIZE
,
18075 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret
));
18079 if (CHANNEL_IS_2G(channel
)) {
18081 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
18082 channel
= ieee80211_channel_to_frequency(channel
);
18084 channel
= ieee80211_channel_to_frequency(channel
, IEEE80211_BAND_2GHZ
);
18088 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel
));
18091 pos
+= snprintf(pos
, total_len
, "2g=%d ", channel
);
18094 if (band_cur
!= WLC_BAND_2G
) {
18095 // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
18096 band
= band_cur
==WLC_BAND_2G
? band_cur
: WLC_BAND_5G
;
18097 ret
= wldev_ioctl(dev
, WLC_SET_BAND
, &band
, sizeof(band
), true);
18099 WL_ERR(("WLC_SET_BAND error %d\n", ret
));
18103 /* Best channel selection in 5GHz band. */
18104 ret
= wl_cfg80211_get_chanspecs_5g(ndev
, (void *)buf
, CHANSPEC_BUF_SIZE
);
18106 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret
));
18110 ret
= wl_cfg80211_get_best_channel(ndev
, (void *)buf
, CHANSPEC_BUF_SIZE
,
18113 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret
));
18117 if (CHANNEL_IS_5G(channel
)) {
18119 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
18120 channel
= ieee80211_channel_to_frequency(channel
);
18122 channel
= ieee80211_channel_to_frequency(channel
, IEEE80211_BAND_5GHZ
);
18126 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel
));
18130 ret
= wldev_ioctl(dev
, WLC_SET_BAND
, &band_cur
, sizeof(band_cur
), true);
18132 WL_ERR(("WLC_SET_BAND error %d\n", ret
));
18133 pos
+= snprintf(pos
, total_len
, "5g=%d ", channel
);
18141 /* Restore FW and driver back to normal state. */
18142 ret
= wl_cfg80211_restore_auto_channel_scan_state(ndev
);
18144 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret
));
18147 printf("%s: %s\n", __FUNCTION__
, cmd
);
18149 return (pos
- cmd
);
18151 #endif /* WL_SUPPORT_AUTO_CHANNEL */
18153 static const struct rfkill_ops wl_rfkill_ops
= {
18154 .set_block
= wl_rfkill_set
18157 static int wl_rfkill_set(void *data
, bool blocked
)
18159 struct bcm_cfg80211
*cfg
= (struct bcm_cfg80211
*)data
;
18161 WL_DBG(("Enter \n"));
18162 WL_DBG(("RF %s\n", blocked
? "blocked" : "unblocked"));
18167 cfg
->rf_blocked
= blocked
;
18172 static int wl_setup_rfkill(struct bcm_cfg80211
*cfg
, bool setup
)
18176 WL_DBG(("Enter \n"));
18180 cfg
->rfkill
= rfkill_alloc("brcmfmac-wifi",
18181 wl_cfg80211_get_parent_dev(),
18182 RFKILL_TYPE_WLAN
, &wl_rfkill_ops
, (void *)cfg
);
18184 if (!cfg
->rfkill
) {
18189 err
= rfkill_register(cfg
->rfkill
);
18192 rfkill_destroy(cfg
->rfkill
);
18194 if (!cfg
->rfkill
) {
18199 rfkill_unregister(cfg
->rfkill
);
18200 rfkill_destroy(cfg
->rfkill
);
18207 #ifdef DEBUGFS_CFG80211
18209 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
18210 * to turn on SCAN and DBG log.
18211 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
18212 * To see current setting of debug level,
18213 * cat /sys/kernel/debug/dhd/debug_level
18216 wl_debuglevel_write(struct file
*file
, const char __user
*userbuf
,
18217 size_t count
, loff_t
*ppos
)
18219 char tbuf
[S_SUBLOGLEVEL
* ARRAYSIZE(sublogname_map
)], sublog
[S_SUBLOGLEVEL
];
18220 char *params
, *token
, *colon
;
18221 uint i
, tokens
, log_on
= 0;
18222 size_t minsize
= min_t(size_t, (sizeof(tbuf
) - 1), count
);
18224 memset(tbuf
, 0, sizeof(tbuf
));
18225 memset(sublog
, 0, sizeof(sublog
));
18226 if (copy_from_user(&tbuf
, userbuf
, minsize
)) {
18230 tbuf
[minsize
+ 1] = '\0';
18232 colon
= strchr(params
, '\n');
18235 while ((token
= strsep(¶ms
, " ")) != NULL
) {
18236 memset(sublog
, 0, sizeof(sublog
));
18237 if (token
== NULL
|| !*token
)
18239 if (*token
== '\0')
18241 colon
= strchr(token
, ':');
18242 if (colon
!= NULL
) {
18245 tokens
= sscanf(token
, "%s %u", sublog
, &log_on
);
18250 for (i
= 0; i
< ARRAYSIZE(sublogname_map
); i
++) {
18251 if (!strncmp(sublog
, sublogname_map
[i
].sublogname
,
18252 strlen(sublogname_map
[i
].sublogname
))) {
18255 (sublogname_map
[i
].log_level
);
18258 ~(sublogname_map
[i
].log_level
);
18262 WL_ERR(("%s: can't parse '%s' as a "
18263 "SUBMODULE:LEVEL (%d tokens)\n",
18264 tbuf
, token
, tokens
));
18272 wl_debuglevel_read(struct file
*file
, char __user
*user_buf
,
18273 size_t count
, loff_t
*ppos
)
18276 char tbuf
[S_SUBLOGLEVEL
* ARRAYSIZE(sublogname_map
)];
18278 memset(tbuf
, 0, sizeof(tbuf
));
18280 for (i
= 0; i
< ARRAYSIZE(sublogname_map
); i
++) {
18281 param
+= snprintf(param
, sizeof(tbuf
) - 1, "%s:%d ",
18282 sublogname_map
[i
].sublogname
,
18283 (wl_dbg_level
& sublogname_map
[i
].log_level
) ? 1 : 0);
18286 return simple_read_from_buffer(user_buf
, count
, ppos
, tbuf
, strlen(&tbuf
[0]));
18289 static const struct file_operations fops_debuglevel
= {
18291 .write
= wl_debuglevel_write
,
18292 .read
= wl_debuglevel_read
,
18293 .owner
= THIS_MODULE
,
18297 static s32
wl_setup_debugfs(struct bcm_cfg80211
*cfg
)
18300 struct dentry
*_dentry
;
18303 cfg
->debugfs
= debugfs_create_dir(KBUILD_MODNAME
, NULL
);
18304 if (!cfg
->debugfs
|| IS_ERR(cfg
->debugfs
)) {
18305 if (cfg
->debugfs
== ERR_PTR(-ENODEV
))
18306 WL_ERR(("Debugfs is not enabled on this kernel\n"));
18308 WL_ERR(("Can not create debugfs directory\n"));
18309 cfg
->debugfs
= NULL
;
18313 _dentry
= debugfs_create_file("debug_level", S_IRUSR
| S_IWUSR
,
18314 cfg
->debugfs
, cfg
, &fops_debuglevel
);
18315 if (!_dentry
|| IS_ERR(_dentry
)) {
18316 WL_ERR(("failed to create debug_level debug file\n"));
18317 wl_free_debugfs(cfg
);
18322 static s32
wl_free_debugfs(struct bcm_cfg80211
*cfg
)
18327 debugfs_remove_recursive(cfg
->debugfs
);
18328 cfg
->debugfs
= NULL
;
18331 #endif /* DEBUGFS_CFG80211 */
18333 struct device
*wl_cfg80211_get_parent_dev(void)
18335 return cfg80211_parent_dev
;
18338 void wl_cfg80211_set_parent_dev(void *dev
)
18340 cfg80211_parent_dev
= dev
;
18343 static void wl_cfg80211_clear_parent_dev(void)
18345 cfg80211_parent_dev
= NULL
;
18348 void get_primary_mac(struct bcm_cfg80211
*cfg
, struct ether_addr
*mac
)
18350 if (wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg
), "cur_etheraddr", NULL
,
18351 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, 0, &cfg
->ioctl_buf_sync
) == BCME_OK
) {
18352 memcpy(mac
->octet
, cfg
->ioctl_buf
, ETHER_ADDR_LEN
);
18354 memset(mac
->octet
, 0, ETHER_ADDR_LEN
);
18357 static bool check_dev_role_integrity(struct bcm_cfg80211
*cfg
, u32 dev_role
)
18359 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
18360 if (((dev_role
== NL80211_IFTYPE_AP
) &&
18361 !(dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) ||
18362 ((dev_role
== NL80211_IFTYPE_P2P_GO
) &&
18363 !(dhd
->op_mode
& DHD_FLAG_P2P_GO_MODE
)))
18365 WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role
, dhd
->op_mode
));
18371 int wl_cfg80211_do_driver_init(struct net_device
*net
)
18373 struct bcm_cfg80211
*cfg
= *(struct bcm_cfg80211
**)netdev_priv(net
);
18375 if (!cfg
|| !cfg
->wdev
)
18378 if (dhd_do_driver_init(cfg
->wdev
->netdev
) < 0)
18384 void wl_cfg80211_enable_trace(u32 level
)
18386 wl_dbg_level
= level
;
18387 printf("%s: wl_dbg_level = 0x%x\n", __FUNCTION__
, wl_dbg_level
);
18390 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
18393 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy
*wiphy
,
18394 bcm_struct_cfgdev
*cfgdev
, u64 cookie
)
18396 /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
18397 * is passed with CMD_FRAME. This callback is supposed to cancel
18398 * the OFFCHANNEL Wait. Since we are already taking care of that
18399 * with the tx_mgmt logic, do nothing here.
18404 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
18408 wl_cfg80211_find_interworking_ie(const u8
*parse
, u32 len
)
18412 /* unfortunately it's too much work to dispose the const cast - bcm_parse_tlvs
18413 * is used everywhere and changing its prototype to take const qualifier needs
18414 * a massive change to all its callers...
18416 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
18417 4 && __GNUC_MINOR__ >= 6))
18418 _Pragma("GCC diagnostic push")
18419 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
18421 if ((ie
= bcm_parse_tlvs((void *)parse
, (int)len
, DOT11_MNG_INTERWORKING_ID
))) {
18424 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
18425 4 && __GNUC_MINOR__ >= 6))
18426 _Pragma("GCC diagnostic pop")
18432 wl_cfg80211_clear_iw_ie(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 bssidx
)
18434 ie_setbuf_t ie_setbuf
;
18436 WL_DBG(("clear interworking IE\n"));
18438 memset(&ie_setbuf
, 0, sizeof(ie_setbuf_t
));
18440 ie_setbuf
.ie_buffer
.iecount
= htod32(1);
18441 ie_setbuf
.ie_buffer
.ie_list
[0].ie_data
.id
= DOT11_MNG_INTERWORKING_ID
;
18442 ie_setbuf
.ie_buffer
.ie_list
[0].ie_data
.len
= 0;
18444 return wldev_iovar_setbuf_bsscfg(ndev
, "ie", &ie_setbuf
, sizeof(ie_setbuf
),
18445 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
18449 wl_cfg80211_add_iw_ie(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 bssidx
, s32 pktflag
,
18450 uint8 ie_id
, uint8
*data
, uint8 data_len
)
18454 ie_setbuf_t
*ie_setbuf
;
18455 ie_getbuf_t ie_getbufp
;
18456 char getbuf
[WLC_IOCTL_SMLEN
];
18458 if (ie_id
!= DOT11_MNG_INTERWORKING_ID
) {
18459 WL_ERR(("unsupported (id=%d)\n", ie_id
));
18460 return BCME_UNSUPPORTED
;
18463 /* access network options (1 octet) is the mandatory field */
18464 if (!data
|| data_len
== 0 || data_len
> IW_IES_MAX_BUF_LEN
) {
18465 WL_ERR(("wrong interworking IE (len=%d)\n", data_len
));
18466 return BCME_BADARG
;
18469 /* Validate the pktflag parameter */
18470 if ((pktflag
& ~(VNDR_IE_BEACON_FLAG
| VNDR_IE_PRBRSP_FLAG
|
18471 VNDR_IE_ASSOCRSP_FLAG
| VNDR_IE_AUTHRSP_FLAG
|
18472 VNDR_IE_PRBREQ_FLAG
| VNDR_IE_ASSOCREQ_FLAG
|
18473 VNDR_IE_CUSTOM_FLAG
))) {
18474 WL_ERR(("invalid packet flag 0x%x\n", pktflag
));
18475 return BCME_BADARG
;
18478 buf_len
= sizeof(ie_setbuf_t
) + data_len
- 1;
18480 ie_getbufp
.id
= DOT11_MNG_INTERWORKING_ID
;
18481 if (wldev_iovar_getbuf_bsscfg(ndev
, "ie", (void *)&ie_getbufp
,
18482 sizeof(ie_getbufp
), getbuf
, WLC_IOCTL_SMLEN
, bssidx
, &cfg
->ioctl_buf_sync
)
18484 if (!memcmp(&getbuf
[TLV_HDR_LEN
], data
, data_len
)) {
18485 WL_DBG(("skip to set interworking IE\n"));
18490 /* if already set with previous values, delete it first */
18492 if ((err
= wl_cfg80211_clear_iw_ie(cfg
, ndev
, bssidx
)) != BCME_OK
) {
18497 ie_setbuf
= (ie_setbuf_t
*) kzalloc(buf_len
, GFP_KERNEL
);
18499 WL_ERR(("Error allocating buffer for IE\n"));
18502 strncpy(ie_setbuf
->cmd
, "add", sizeof(ie_setbuf
->cmd
));
18503 ie_setbuf
->cmd
[sizeof(ie_setbuf
->cmd
) - 1] = '\0';
18505 /* Buffer contains only 1 IE */
18506 ie_setbuf
->ie_buffer
.iecount
= htod32(1);
18507 /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
18508 ie_setbuf
->ie_buffer
.ie_list
[0].pktflag
= htod32(pktflag
);
18510 /* Now, add the IE to the buffer */
18511 ie_setbuf
->ie_buffer
.ie_list
[0].ie_data
.id
= DOT11_MNG_INTERWORKING_ID
;
18512 ie_setbuf
->ie_buffer
.ie_list
[0].ie_data
.len
= data_len
;
18513 memcpy((uchar
*)&ie_setbuf
->ie_buffer
.ie_list
[0].ie_data
.data
[0], data
, data_len
);
18515 if ((err
= wldev_iovar_setbuf_bsscfg(ndev
, "ie", ie_setbuf
, buf_len
,
18516 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
))
18518 WL_DBG(("set interworking IE\n"));
18520 err
= wldev_iovar_setint_bsscfg(ndev
, "grat_arp", 1, bssidx
);
18530 wl_cfg80211_set_if_band(struct net_device
*ndev
, int band
)
18532 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
18533 int ret
= 0, wait_cnt
;
18534 char ioctl_buf
[32];
18536 if ((band
< WLC_BAND_AUTO
) || (band
> WLC_BAND_2G
)) {
18537 WL_ERR(("Invalid band\n"));
18540 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
) ||
18541 wl_get_drv_status(cfg
, CONNECTING
, ndev
)) {
18542 /* if driver is connected or connecting status, try to disconnect first.
18543 * if dongle is associated, iovar 'if_band' would be rejected.
18545 wl_set_drv_status(cfg
, DISCONNECTING
, ndev
);
18546 ret
= wldev_ioctl_set(ndev
, WLC_DISASSOC
, NULL
, 0);
18548 WL_ERR(("WLC_DISASSOC error %d\n", ret
));
18549 /* continue to set 'if_band' */
18552 /* This is to ensure that 'if_band' iovar is issued only after
18553 * disconnection is completed
18555 wait_cnt
= WAIT_FOR_DISCONNECT_MAX
;
18556 while (wl_get_drv_status(cfg
, DISCONNECTING
, ndev
) && wait_cnt
) {
18557 WL_DBG(("Wait until disconnected. wait_cnt: %d\n", wait_cnt
));
18563 if ((ret
= wldev_iovar_setbuf(ndev
, "if_band", &band
,
18564 sizeof(int), ioctl_buf
, sizeof(ioctl_buf
), NULL
)) < 0) {
18565 WL_ERR(("seting if_band failed ret=%d\n", ret
));
18566 /* issue 'WLC_SET_BAND' if if_band is not supported */
18567 if (ret
== BCME_UNSUPPORTED
) {
18568 ret
= wldev_set_band(ndev
, band
);
18570 WL_ERR(("seting band failed ret=%d\n", ret
));
18578 wl_cfg80211_dfs_ap_move(struct net_device
*ndev
, char *data
, char *command
, int total_len
)
18580 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
18581 char ioctl_buf
[50];
18584 chanspec_t chanspec
= 0;
18586 int bytes_written
= 0;
18587 wl_dfs_ap_move_status_t
*status
;
18588 char chanbuf
[CHANSPEC_STR_LEN
];
18589 const char *dfs_state_str
[DFS_SCAN_S_MAX
] = {
18590 "Radar Free On Channel",
18591 "Radar Found On Channel",
18592 "Radar Scan In Progress",
18593 "Radar Scan Aborted",
18594 "RSDB Mode switch in Progress For Scan"
18596 if (ndev
->ieee80211_ptr
->iftype
!= NL80211_IFTYPE_AP
) {
18597 bytes_written
= snprintf(command
, total_len
, "AP is not up\n");
18598 return bytes_written
;
18601 if ((err
= wldev_iovar_getbuf(ndev
, "dfs_ap_move", NULL
, 0,
18602 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
18603 WL_ERR(("setting dfs_ap_move failed with err=%d \n", err
));
18606 status
= (wl_dfs_ap_move_status_t
*)cfg
->ioctl_buf
;
18608 if (status
->version
!= WL_DFS_AP_MOVE_VERSION
) {
18609 err
= BCME_UNSUPPORTED
;
18610 WL_ERR(("err=%d version=%d\n", err
, status
->version
));
18614 if (status
->move_status
!= (int8
) DFS_SCAN_S_IDLE
) {
18615 chanspec
= wl_chspec_driver_to_host(status
->chanspec
);
18616 if (chanspec
!= 0 && chanspec
!= INVCHANSPEC
) {
18617 wf_chspec_ntoa(chanspec
, chanbuf
);
18618 bytes_written
= snprintf(command
, total_len
,
18619 "AP Target Chanspec %s (0x%x)\n", chanbuf
, chanspec
);
18622 bytes_written
+= snprintf(command
+ bytes_written
, total_len
,
18623 "%s\n", dfs_state_str
[status
->move_status
]);
18624 return bytes_written
;
18626 bytes_written
= snprintf(command
, total_len
, "dfs AP move in IDLE state\n");
18627 return bytes_written
;
18632 abort
= bcm_atoi(data
);
18634 if ((err
= wldev_iovar_setbuf(ndev
, "dfs_ap_move", &abort
,
18635 sizeof(int), ioctl_buf
, sizeof(ioctl_buf
), NULL
)) < 0) {
18636 WL_ERR(("seting dfs_ap_move failed with err %d\n", err
));
18640 chanspec
= wf_chspec_aton(data
);
18641 if (chanspec
!= 0) {
18642 val
= wl_chspec_host_to_driver(chanspec
);
18643 if (val
!= INVCHANSPEC
) {
18644 if ((err
= wldev_iovar_setbuf(ndev
, "dfs_ap_move", &val
,
18645 sizeof(int), ioctl_buf
, sizeof(ioctl_buf
), NULL
)) < 0) {
18646 WL_ERR(("seting dfs_ap_move failed with err %d\n", err
));
18649 WL_DBG((" set dfs_ap_move successfull"));
18651 err
= BCME_USAGE_ERROR
;
18660 wl_cfg80211_wbtext_set_default(struct net_device
*ndev
)
18662 char commandp
[WLC_IOCTL_SMLEN
];
18666 WL_DBG(("set wbtext to default\n"));
18668 /* set roam profile */
18669 memset(commandp
, 0, sizeof(commandp
));
18670 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18671 CMD_WBTEXT_PROFILE_CONFIG
, DEFAULT_WBTEXT_PROFILE_A
);
18672 data
= (commandp
+ strlen(CMD_WBTEXT_PROFILE_CONFIG
) + 1);
18673 ret
= wl_cfg80211_wbtext_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18674 if (ret
!= BCME_OK
) {
18675 WL_ERR(("%s: Failed to set roam_prof %s error = %d\n",
18676 __FUNCTION__
, data
, ret
));
18680 memset(commandp
, 0, sizeof(commandp
));
18681 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18682 CMD_WBTEXT_PROFILE_CONFIG
, DEFAULT_WBTEXT_PROFILE_B
);
18683 data
= (commandp
+ strlen(CMD_WBTEXT_PROFILE_CONFIG
) + 1);
18684 ret
= wl_cfg80211_wbtext_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18685 if (ret
!= BCME_OK
) {
18686 WL_ERR(("%s: Failed to set roam_prof %s error = %d\n",
18687 __FUNCTION__
, data
, ret
));
18691 /* set RSSI weight */
18692 memset(commandp
, 0, sizeof(commandp
));
18693 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18694 CMD_WBTEXT_WEIGHT_CONFIG
, DEFAULT_WBTEXT_WEIGHT_RSSI_A
);
18695 data
= (commandp
+ strlen(CMD_WBTEXT_WEIGHT_CONFIG
) + 1);
18696 ret
= wl_cfg80211_wbtext_weight_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18697 if (ret
!= BCME_OK
) {
18698 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18699 __FUNCTION__
, data
, ret
));
18703 memset(commandp
, 0, sizeof(commandp
));
18704 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18705 CMD_WBTEXT_WEIGHT_CONFIG
, DEFAULT_WBTEXT_WEIGHT_RSSI_B
);
18706 data
= (commandp
+ strlen(CMD_WBTEXT_WEIGHT_CONFIG
) + 1);
18707 ret
= wl_cfg80211_wbtext_weight_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18708 if (ret
!= BCME_OK
) {
18709 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18710 __FUNCTION__
, data
, ret
));
18714 /* set CU weight */
18715 memset(commandp
, 0, sizeof(commandp
));
18716 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18717 CMD_WBTEXT_WEIGHT_CONFIG
, DEFAULT_WBTEXT_WEIGHT_CU_A
);
18718 data
= (commandp
+ strlen(CMD_WBTEXT_WEIGHT_CONFIG
) + 1);
18719 ret
= wl_cfg80211_wbtext_weight_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18720 if (ret
!= BCME_OK
) {
18721 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18722 __FUNCTION__
, data
, ret
));
18726 memset(commandp
, 0, sizeof(commandp
));
18727 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18728 CMD_WBTEXT_WEIGHT_CONFIG
, DEFAULT_WBTEXT_WEIGHT_CU_B
);
18729 data
= (commandp
+ strlen(CMD_WBTEXT_WEIGHT_CONFIG
) + 1);
18730 ret
= wl_cfg80211_wbtext_weight_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18731 if (ret
!= BCME_OK
) {
18732 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18733 __FUNCTION__
, data
, ret
));
18737 /* set RSSI table */
18738 memset(commandp
, 0, sizeof(commandp
));
18739 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18740 CMD_WBTEXT_TABLE_CONFIG
, DEFAULT_WBTEXT_TABLE_RSSI_A
);
18741 data
= (commandp
+ strlen(CMD_WBTEXT_TABLE_CONFIG
) + 1);
18742 ret
= wl_cfg80211_wbtext_table_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18743 if (ret
!= BCME_OK
) {
18744 WL_ERR(("%s: Failed to set RSSI table %s error = %d\n",
18745 __FUNCTION__
, data
, ret
));
18749 memset(commandp
, 0, sizeof(commandp
));
18750 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18751 CMD_WBTEXT_TABLE_CONFIG
, DEFAULT_WBTEXT_TABLE_RSSI_B
);
18752 data
= (commandp
+ strlen(CMD_WBTEXT_TABLE_CONFIG
) + 1);
18753 ret
= wl_cfg80211_wbtext_table_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18754 if (ret
!= BCME_OK
) {
18755 WL_ERR(("%s: Failed to set RSSI table %s error = %d\n",
18756 __FUNCTION__
, data
, ret
));
18761 memset(commandp
, 0, sizeof(commandp
));
18762 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18763 CMD_WBTEXT_TABLE_CONFIG
, DEFAULT_WBTEXT_TABLE_CU_A
);
18764 data
= (commandp
+ strlen(CMD_WBTEXT_TABLE_CONFIG
) + 1);
18765 ret
= wl_cfg80211_wbtext_table_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18766 if (ret
!= BCME_OK
) {
18767 WL_ERR(("%s: Failed to set CU table %s error = %d\n",
18768 __FUNCTION__
, data
, ret
));
18772 memset(commandp
, 0, sizeof(commandp
));
18773 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18774 CMD_WBTEXT_TABLE_CONFIG
, DEFAULT_WBTEXT_TABLE_CU_B
);
18775 data
= (commandp
+ strlen(CMD_WBTEXT_TABLE_CONFIG
) + 1);
18776 ret
= wl_cfg80211_wbtext_table_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18777 if (ret
!= BCME_OK
) {
18778 WL_ERR(("%s: Failed to set CU table %s error = %d\n",
18779 __FUNCTION__
, data
, ret
));
18787 wl_cfg80211_wbtext_config(struct net_device
*ndev
, char *data
, char *command
, int total_len
)
18790 long int rssi_lower
, roam_trigger
;
18791 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
18792 wl_roam_prof_band_t
*rp
;
18793 int err
= -EINVAL
, bytes_written
= 0;
18794 size_t len
= strlen(data
);
18797 rp
= (wl_roam_prof_band_t
*) kzalloc(sizeof(*rp
)
18798 * WL_MAX_ROAM_PROF_BRACKETS
, GFP_KERNEL
);
18799 if (unlikely(!rp
)) {
18800 WL_ERR(("%s: failed to allocate memory\n", __func__
));
18804 rp
->ver
= WL_MAX_ROAM_PROF_VER
;
18805 if (*data
&& (!strncmp(data
, "b", 1))) {
18806 rp
->band
= WLC_BAND_2G
;
18807 } else if (*data
&& (!strncmp(data
, "a", 1))) {
18808 rp
->band
= WLC_BAND_5G
;
18810 err
= snprintf(command
, total_len
, "Missing band\n");
18815 /* Getting roam profile from fw */
18816 if ((err
= wldev_iovar_getbuf(ndev
, "roam_prof", rp
, sizeof(*rp
),
18817 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
18818 WL_ERR(("Getting roam_profile failed with err=%d \n", err
));
18821 memcpy(rp
, cfg
->ioctl_buf
, sizeof(*rp
) * WL_MAX_ROAM_PROF_BRACKETS
);
18822 /* roam_prof version get */
18823 if (rp
->ver
!= WL_MAX_ROAM_PROF_VER
) {
18824 WL_ERR(("bad version (=%d) in return data\n", rp
->ver
));
18828 if ((rp
->len
% sizeof(wl_roam_prof_t
)) != 0) {
18829 WL_ERR(("bad length (=%d) in return data\n", rp
->len
));
18835 for (i
= 0; i
< WL_MAX_ROAM_PROF_BRACKETS
; i
++) {
18836 /* printing contents of roam profile data from fw and exits
18837 * if code hits any of one of the below condtion. If remaining
18838 * length of buffer is less than roam profile size or
18839 * if there is no valid entry.
18841 if (((i
* sizeof(wl_roam_prof_t
)) > rp
->len
) ||
18842 (rp
->roam_prof
[i
].fullscan_period
== 0)) {
18845 bytes_written
+= snprintf(command
+bytes_written
,
18846 total_len
, "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)\n",
18847 rp
->roam_prof
[i
].roam_trigger
, rp
->roam_prof
[i
].rssi_lower
,
18848 rp
->roam_prof
[i
].channel_usage
,
18849 rp
->roam_prof
[i
].cu_avg_calc_dur
);
18851 err
= bytes_written
;
18854 for (i
= 0; i
< WL_MAX_ROAM_PROF_BRACKETS
; i
++) {
18855 /* reading contents of roam profile data from fw and exits
18856 * if code hits any of one of the below condtion, If remaining
18857 * length of buffer is less than roam profile size or if there
18858 * is no valid entry.
18860 if (((i
* sizeof(wl_roam_prof_t
)) > rp
->len
) ||
18861 (rp
->roam_prof
[i
].fullscan_period
== 0)) {
18865 /* Do not set roam_prof from upper layer if fw doesn't have 2 rows */
18867 WL_ERR(("FW must have 2 rows to fill roam_prof\n"));
18871 /* setting roam profile to fw */
18873 for (i
= 0; i
< WL_MAX_ROAM_PROF_BRACKETS
; i
++) {
18874 roam_trigger
= simple_strtol(data
, &data
, 10);
18875 if (roam_trigger
>= 0) {
18876 WL_ERR(("roam trigger[%d] value must be negative\n", i
));
18880 rp
->roam_prof
[i
].roam_trigger
= roam_trigger
;
18882 rssi_lower
= simple_strtol(data
, &data
, 10);
18883 if (rssi_lower
>= 0) {
18884 WL_ERR(("rssi lower[%d] value must be negative\n", i
));
18888 rp
->roam_prof
[i
].rssi_lower
= rssi_lower
;
18890 rp
->roam_prof
[i
].channel_usage
= simple_strtol(data
, &data
, 10);
18892 rp
->roam_prof
[i
].cu_avg_calc_dur
= simple_strtol(data
, &data
, 10);
18894 rp_len
+= sizeof(wl_roam_prof_t
);
18896 if (*data
== '\0') {
18902 WL_ERR(("Only two roam_prof rows supported.\n"));
18907 if ((err
= wldev_iovar_setbuf(ndev
, "roam_prof", rp
,
18908 sizeof(*rp
), cfg
->ioctl_buf
, WLC_IOCTL_MEDLEN
,
18909 &cfg
->ioctl_buf_sync
)) < 0) {
18910 WL_ERR(("seting roam_profile failed with err %d\n", err
));
18925 int wl_cfg80211_wbtext_weight_config(struct net_device
*ndev
, char *data
,
18926 char *command
, int total_len
)
18928 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
18929 int bytes_written
= 0, err
= -EINVAL
, argc
= 0;
18930 char rssi
[BUFSZ
], band
[BUFSZ
], weight
[BUFSZ
];
18931 char *endptr
= NULL
;
18932 wnm_bss_select_weight_cfg_t
*bwcfg
;
18934 bwcfg
= kzalloc(sizeof(*bwcfg
), GFP_KERNEL
);
18935 if (unlikely(!bwcfg
)) {
18936 WL_ERR(("%s: failed to allocate memory\n", __func__
));
18940 bwcfg
->version
= WNM_BSSLOAD_MONITOR_VERSION
;
18944 argc
= sscanf(data
, "%"S(BUFSZ
)"s %"S(BUFSZ
)"s %"S(BUFSZ
)"s", rssi
, band
, weight
);
18946 if (!strcasecmp(rssi
, "rssi"))
18947 bwcfg
->type
= WNM_BSS_SELECT_TYPE_RSSI
;
18948 else if (!strcasecmp(rssi
, "cu"))
18949 bwcfg
->type
= WNM_BSS_SELECT_TYPE_CU
;
18951 /* Usage DRIVER WBTEXT_WEIGHT_CONFIG <rssi/cu> <band> <weight> */
18952 WL_ERR(("%s: Command usage error\n", __func__
));
18956 if (!strcasecmp(band
, "a"))
18957 bwcfg
->band
= WLC_BAND_5G
;
18958 else if (!strcasecmp(band
, "b"))
18959 bwcfg
->band
= WLC_BAND_2G
;
18960 else if (!strcasecmp(band
, "all"))
18961 bwcfg
->band
= WLC_BAND_ALL
;
18963 WL_ERR(("%s: Command usage error\n", __func__
));
18968 /* If there is no data after band, getting wnm_bss_select_weight from fw */
18969 if (bwcfg
->band
== WLC_BAND_ALL
) {
18970 WL_ERR(("band option \"all\" is for set only, not get\n"));
18973 if ((err
= wldev_iovar_getbuf(ndev
, "wnm_bss_select_weight", bwcfg
,
18975 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
18976 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d \n", err
));
18979 memcpy(bwcfg
, cfg
->ioctl_buf
, sizeof(*bwcfg
));
18980 bytes_written
= snprintf(command
, total_len
, "%s %s weight = %d\n",
18981 (bwcfg
->type
== WNM_BSS_SELECT_TYPE_RSSI
) ? "RSSI" : "CU",
18982 (bwcfg
->band
== WLC_BAND_2G
) ? "2G" : "5G", bwcfg
->weight
);
18983 err
= bytes_written
;
18986 /* if weight is non integer returns command usage error */
18987 bwcfg
->weight
= simple_strtol(weight
, &endptr
, 0);
18988 if (*endptr
!= '\0') {
18989 WL_ERR(("%s: Command usage error", __func__
));
18992 /* setting weight for iovar wnm_bss_select_weight to fw */
18993 if ((err
= wldev_iovar_setbuf(ndev
, "wnm_bss_select_weight", bwcfg
,
18995 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
18996 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d\n", err
));
19006 /* WBTEXT_TUPLE_MIN_LEN_CHECK :strlen(low)+" "+strlen(high)+" "+strlen(factor) */
19007 #define WBTEXT_TUPLE_MIN_LEN_CHECK 5
19009 int wl_cfg80211_wbtext_table_config(struct net_device
*ndev
, char *data
,
19010 char *command
, int total_len
)
19012 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
19013 int bytes_written
= 0, err
= -EINVAL
;
19014 char rssi
[BUFSZ
], band
[BUFSZ
];
19015 int btcfg_len
= 0, i
= 0, parsed_len
= 0;
19016 wnm_bss_select_factor_cfg_t
*btcfg
;
19017 size_t slen
= strlen(data
);
19018 char *start_addr
= NULL
;
19021 btcfg
= kzalloc((sizeof(*btcfg
) + sizeof(*btcfg
) *
19022 WL_FACTOR_TABLE_MAX_LIMIT
), GFP_KERNEL
);
19023 if (unlikely(!btcfg
)) {
19024 WL_ERR(("%s: failed to allocate memory\n", __func__
));
19029 btcfg
->version
= WNM_BSS_SELECT_FACTOR_VERSION
;
19030 btcfg
->band
= WLC_BAND_AUTO
;
19034 sscanf(data
, "%"S(BUFSZ
)"s %"S(BUFSZ
)"s", rssi
, band
);
19036 if (!strcasecmp(rssi
, "rssi")) {
19037 btcfg
->type
= WNM_BSS_SELECT_TYPE_RSSI
;
19039 else if (!strcasecmp(rssi
, "cu")) {
19040 btcfg
->type
= WNM_BSS_SELECT_TYPE_CU
;
19043 WL_ERR(("%s: Command usage error\n", __func__
));
19047 if (!strcasecmp(band
, "a")) {
19048 btcfg
->band
= WLC_BAND_5G
;
19050 else if (!strcasecmp(band
, "b")) {
19051 btcfg
->band
= WLC_BAND_2G
;
19053 else if (!strcasecmp(band
, "all")) {
19054 btcfg
->band
= WLC_BAND_ALL
;
19057 WL_ERR(("%s: Command usage, Wrong band\n", __func__
));
19061 if ((slen
- 1) == (strlen(rssi
) + strlen(band
))) {
19062 /* Getting factor table using iovar 'wnm_bss_select_table' from fw */
19063 if ((err
= wldev_iovar_getbuf(ndev
, "wnm_bss_select_table", btcfg
,
19065 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
19066 WL_ERR(("Getting wnm_bss_select_table failed with err=%d \n", err
));
19069 memcpy(btcfg
, cfg
->ioctl_buf
, sizeof(*btcfg
));
19070 memcpy(btcfg
, cfg
->ioctl_buf
, (btcfg
->count
+1) * sizeof(*btcfg
));
19072 bytes_written
+= snprintf(command
+ bytes_written
, total_len
,
19073 "No of entries in table: %d\n", btcfg
->count
);
19074 bytes_written
+= snprintf(command
+ bytes_written
, total_len
, "%s factor table\n",
19075 (btcfg
->type
== WNM_BSS_SELECT_TYPE_RSSI
) ? "RSSI" : "CU");
19076 bytes_written
+= snprintf(command
+ bytes_written
, total_len
,
19077 "low\thigh\tfactor\n");
19078 for (i
= 0; i
<= btcfg
->count
-1; i
++) {
19079 bytes_written
+= snprintf(command
+ bytes_written
, total_len
,
19080 "%d\t%d\t%d\n", btcfg
->params
[i
].low
, btcfg
->params
[i
].high
,
19081 btcfg
->params
[i
].factor
);
19083 err
= bytes_written
;
19086 memset(btcfg
->params
, 0, sizeof(wnm_bss_select_factor_params_t
)
19087 * WL_FACTOR_TABLE_MAX_LIMIT
);
19088 data
+= (strlen(rssi
) + strlen(band
) + 2);
19090 slen
= slen
- (strlen(rssi
) + strlen(band
) + 2);
19091 for (i
= 0; i
< WL_FACTOR_TABLE_MAX_LIMIT
; i
++) {
19092 if (parsed_len
+ WBTEXT_TUPLE_MIN_LEN_CHECK
<= slen
) {
19093 btcfg
->params
[i
].low
= simple_strtol(data
, &data
, 10);
19095 btcfg
->params
[i
].high
= simple_strtol(data
, &data
, 10);
19097 btcfg
->params
[i
].factor
= simple_strtol(data
, &data
, 10);
19099 if (*data
== '\0') {
19103 parsed_len
= data
- start_addr
;
19105 WL_ERR(("%s:Command usage:less no of args\n", __func__
));
19109 btcfg_len
= sizeof(*btcfg
) + ((btcfg
->count
) * sizeof(*btcfg
));
19110 if ((err
= wldev_iovar_setbuf(ndev
, "wnm_bss_select_table", btcfg
, btcfg_len
,
19111 cfg
->ioctl_buf
, WLC_IOCTL_MEDLEN
, &cfg
->ioctl_buf_sync
)) < 0) {
19112 WL_ERR(("seting wnm_bss_select_table failed with err %d\n", err
));
19124 wl_cfg80211_wbtext_delta_config(struct net_device
*ndev
, char *data
, char *command
, int total_len
)
19127 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
19128 int err
= -EINVAL
, bytes_written
= 0, argc
= 0, val
, len
= 0;
19129 char delta
[BUFSZ
], band
[BUFSZ
], *endptr
= NULL
;
19130 wl_roam_prof_band_t
*rp
;
19132 rp
= (wl_roam_prof_band_t
*) kzalloc(sizeof(*rp
)
19133 * WL_MAX_ROAM_PROF_BRACKETS
, GFP_KERNEL
);
19134 if (unlikely(!rp
)) {
19135 WL_ERR(("%s: failed to allocate memory\n", __func__
));
19140 argc
= sscanf(data
, "%"S(BUFSZ
)"s %"S(BUFSZ
)"s", band
, delta
);
19141 if (!strcasecmp(band
, "a"))
19142 rp
->band
= WLC_BAND_5G
;
19143 else if (!strcasecmp(band
, "b"))
19144 rp
->band
= WLC_BAND_2G
;
19146 WL_ERR(("%s: Missing band\n", __func__
));
19149 /* Getting roam profile from fw */
19150 if ((err
= wldev_iovar_getbuf(ndev
, "roam_prof", rp
, sizeof(*rp
),
19151 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
19152 WL_ERR(("Getting roam_profile failed with err=%d \n", err
));
19155 memcpy(rp
, cfg
->ioctl_buf
, sizeof(wl_roam_prof_band_t
));
19156 if (rp
->ver
!= WL_MAX_ROAM_PROF_VER
) {
19157 WL_ERR(("bad version (=%d) in return data\n", rp
->ver
));
19161 if ((rp
->len
% sizeof(wl_roam_prof_t
)) != 0) {
19162 WL_ERR(("bad length (=%d) in return data\n", rp
->len
));
19168 /* if delta is non integer returns command usage error */
19169 val
= simple_strtol(delta
, &endptr
, 0);
19170 if (*endptr
!= '\0') {
19171 WL_ERR(("%s: Command usage error", __func__
));
19174 for (i
= 0; i
< WL_MAX_ROAM_PROF_BRACKETS
; i
++) {
19176 * Checking contents of roam profile data from fw and exits
19177 * if code hits below condtion. If remaining length of buffer is
19178 * less than roam profile size or if there is no valid entry.
19180 if (((i
* sizeof(wl_roam_prof_t
)) > rp
->len
) ||
19181 (rp
->roam_prof
[i
].fullscan_period
== 0)) {
19184 if (rp
->roam_prof
[i
].channel_usage
!= 0) {
19185 rp
->roam_prof
[i
].roam_delta
= val
;
19187 len
+= sizeof(wl_roam_prof_t
);
19191 if (rp
->roam_prof
[i
].channel_usage
!= 0) {
19192 bytes_written
= snprintf(command
, total_len
,
19193 "%s Delta %d\n", (rp
->band
== WLC_BAND_2G
) ? "2G" : "5G",
19194 rp
->roam_prof
[0].roam_delta
);
19196 err
= bytes_written
;
19200 if ((err
= wldev_iovar_setbuf(ndev
, "roam_prof", rp
,
19201 sizeof(*rp
), cfg
->ioctl_buf
, WLC_IOCTL_MEDLEN
, &cfg
->ioctl_buf_sync
)) < 0) {
19202 WL_ERR(("seting roam_profile failed with err %d\n", err
));
19210 #endif /* WBTEXT */
19213 int wl_cfg80211_scan_stop(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
)
19215 struct net_device
*ndev
= NULL
;
19216 unsigned long flags
;
19217 int clear_flag
= 0;
19219 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
19220 struct cfg80211_scan_info info
;
19223 WL_TRACE(("Enter\n"));
19228 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
19230 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
19231 #ifdef WL_CFG80211_P2P_DEV_IF
19232 if (cfg
->scan_request
&& cfg
->scan_request
->wdev
== cfgdev
)
19234 if (cfg
->scan_request
&& cfg
->scan_request
->dev
== cfgdev
)
19237 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
19238 info
.aborted
= true;
19239 cfg80211_scan_done(cfg
->scan_request
, &info
);
19241 cfg80211_scan_done(cfg
->scan_request
, true);
19243 cfg
->scan_request
= NULL
;
19246 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
19249 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
19254 bool wl_cfg80211_is_concurrent_mode(struct net_device
*dev
)
19256 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
19257 if ((cfg
) && (wl_get_drv_status_all(cfg
, CONNECTED
) > 1)) {
19264 void* wl_cfg80211_get_dhdp(struct net_device
*dev
)
19266 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
19271 bool wl_cfg80211_is_p2p_active(struct net_device
*dev
)
19273 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
19274 return (cfg
&& cfg
->p2p
);
19277 bool wl_cfg80211_is_roam_offload(struct net_device
* dev
)
19279 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
19280 return (cfg
&& cfg
->roam_offload
);
19283 bool wl_cfg80211_is_event_from_connected_bssid(struct net_device
* dev
, const wl_event_msg_t
*e
,
19286 u8
*curbssid
= NULL
;
19287 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
19290 /* When interface is created using wl
19291 * ndev->ieee80211_ptr will be NULL.
19295 curbssid
= wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
19301 if (memcmp(curbssid
, &e
->addr
, ETHER_ADDR_LEN
) == 0) {
19307 static void wl_cfg80211_work_handler(struct work_struct
* work
)
19309 struct bcm_cfg80211
*cfg
= NULL
;
19310 struct net_info
*iter
, *next
;
19314 BCM_SET_CONTAINER_OF(cfg
, work
, struct bcm_cfg80211
, pm_enable_work
.work
);
19315 WL_DBG(("Enter \n"));
19316 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19317 4 && __GNUC_MINOR__ >= 6))
19318 _Pragma("GCC diagnostic push")
19319 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19321 for_each_ndev(cfg
, iter
, next
) {
19322 /* p2p discovery iface ndev could be null */
19324 if (!wl_get_drv_status(cfg
, CONNECTED
, iter
->ndev
) ||
19325 (wl_get_mode_by_netdev(cfg
, iter
->ndev
) != WL_MODE_BSS
&&
19326 wl_get_mode_by_netdev(cfg
, iter
->ndev
) != WL_MODE_IBSS
))
19329 dhd
= (dhd_pub_t
*)(cfg
->pub
);
19330 if (dhd_conf_get_pm(dhd
) >= 0)
19331 pm
= dhd_conf_get_pm(dhd
);
19332 if ((err
= wldev_ioctl_set(iter
->ndev
, WLC_SET_PM
,
19333 &pm
, sizeof(pm
))) != 0) {
19334 if (err
== -ENODEV
)
19335 WL_DBG(("%s:netdev not ready\n",
19336 iter
->ndev
->name
));
19338 WL_ERR(("%s:error (%d)\n",
19339 iter
->ndev
->name
, err
));
19341 wl_cfg80211_update_power_mode(iter
->ndev
);
19345 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19346 4 && __GNUC_MINOR__ >= 6))
19347 _Pragma("GCC diagnostic pop")
19349 DHD_PM_WAKE_UNLOCK(cfg
->pub
);
19353 wl_get_action_category(void *frame
, u32 frame_len
)
19356 u8
*ptr
= (u8
*)frame
;
19358 return DOT11_ACTION_CAT_ERR_MASK
;
19359 if (frame_len
< DOT11_ACTION_HDR_LEN
)
19360 return DOT11_ACTION_CAT_ERR_MASK
;
19361 category
= ptr
[DOT11_ACTION_CAT_OFF
];
19362 WL_INFORM(("Action Category: %d\n", category
));
19367 wl_get_public_action(void *frame
, u32 frame_len
, u8
*ret_action
)
19369 u8
*ptr
= (u8
*)frame
;
19370 if (frame
== NULL
|| ret_action
== NULL
)
19372 if (frame_len
< DOT11_ACTION_HDR_LEN
)
19374 if (DOT11_ACTION_CAT_PUBLIC
!= wl_get_action_category(frame
, frame_len
))
19376 *ret_action
= ptr
[DOT11_ACTION_ACT_OFF
];
19377 WL_INFORM(("Public Action : %d\n", *ret_action
));
19383 wl_cfg80211_delayed_roam(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
19384 const struct ether_addr
*bssid
)
19389 bzero(&e
, sizeof(e
));
19390 e
.event_type
= cpu_to_be32(WLC_E_ROAM
);
19391 memcpy(&e
.addr
, bssid
, ETHER_ADDR_LEN
);
19392 /* trigger the roam event handler */
19393 err
= wl_notify_roaming_status(cfg
, ndev_to_cfgdev(ndev
), &e
, NULL
);
19399 wl_cfg80211_parse_vndr_ies(u8
*parse
, u32 len
,
19400 struct parsed_vndr_ies
*vndr_ies
)
19405 struct parsed_vndr_ie_info
*parsed_info
;
19409 remained_len
= (s32
)len
;
19410 memset(vndr_ies
, 0, sizeof(*vndr_ies
));
19412 WL_DBG(("---> len %d\n", len
));
19413 ie
= (bcm_tlv_t
*) parse
;
19414 if (!bcm_valid_tlv(ie
, remained_len
))
19417 if (count
>= MAX_VNDR_IE_NUMBER
)
19419 if (ie
->id
== DOT11_MNG_VS_ID
) {
19420 vndrie
= (vndr_ie_t
*) ie
;
19421 /* len should be bigger than OUI length + one data length at least */
19422 if (vndrie
->len
< (VNDR_IE_MIN_LEN
+ 1)) {
19423 WL_ERR(("%s: invalid vndr ie. length is too small %d\n",
19424 __FUNCTION__
, vndrie
->len
));
19427 /* if wpa or wme ie, do not add ie */
19428 if (!bcmp(vndrie
->oui
, (u8
*)WPA_OUI
, WPA_OUI_LEN
) &&
19429 ((vndrie
->data
[0] == WPA_OUI_TYPE
) ||
19430 (vndrie
->data
[0] == WME_OUI_TYPE
))) {
19431 WL_DBG(("Found WPA/WME oui. Do not add it\n"));
19435 parsed_info
= &vndr_ies
->ie_info
[count
++];
19437 /* save vndr ie information */
19438 parsed_info
->ie_ptr
= (char *)vndrie
;
19439 parsed_info
->ie_len
= (vndrie
->len
+ TLV_HDR_LEN
);
19440 memcpy(&parsed_info
->vndrie
, vndrie
, sizeof(vndr_ie_t
));
19441 vndr_ies
->count
= count
;
19443 WL_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x len:%d\n",
19444 parsed_info
->vndrie
.oui
[0], parsed_info
->vndrie
.oui
[1],
19445 parsed_info
->vndrie
.oui
[2], parsed_info
->vndrie
.data
[0],
19446 parsed_info
->ie_len
));
19449 ie
= bcm_next_tlv(ie
, &remained_len
);
19454 #ifdef WLADPS_SEAK_AP_WAR
19456 wl_find_vndr_ies_specific_vender(struct bcm_cfg80211
*cfg
,
19457 struct net_device
*ndev
, const u8
*vndr_oui
)
19459 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
19460 struct parsed_vndr_ie_info
*vndr_info_list
;
19461 struct parsed_vndr_ies vndr_ies
;
19465 if (conn_info
->resp_ie_len
) {
19466 if ((wl_cfg80211_parse_vndr_ies((u8
*)conn_info
->resp_ie
,
19467 conn_info
->resp_ie_len
, &vndr_ies
)) == BCME_OK
) {
19468 for (i
= 0; i
< vndr_ies
.count
; i
++) {
19469 vndr_info_list
= &vndr_ies
.ie_info
[i
];
19470 if (!bcmp(vndr_info_list
->vndrie
.oui
,
19471 (u8
*)vndr_oui
, DOT11_OUI_LEN
)) {
19472 WL_ERR(("Find OUI %02x %02x %02x\n",
19473 vndr_info_list
->vndrie
.oui
[0],
19474 vndr_info_list
->vndrie
.oui
[1],
19475 vndr_info_list
->vndrie
.oui
[2]));
19486 wl_set_adps_mode(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, uint8 enable_mode
)
19492 bcm_iov_buf_t
*iov_buf
= NULL
;
19493 wl_adps_params_v1_t
*data
= NULL
;
19495 len
= OFFSETOF(bcm_iov_buf_t
, data
) + sizeof(*data
);
19496 iov_buf
= kmalloc(len
, GFP_KERNEL
);
19497 if (iov_buf
== NULL
) {
19498 WL_ERR(("%s - failed to allocate %d bytes for iov_buf\n", __FUNCTION__
, len
));
19503 iov_buf
->version
= WL_ADPS_IOV_VER
;
19504 iov_buf
->len
= sizeof(*data
);
19505 iov_buf
->id
= WL_ADPS_IOV_MODE
;
19507 data
= (wl_adps_params_v1_t
*)iov_buf
->data
;
19508 data
->version
= ADPS_SUB_IOV_VERSION_1
;
19509 data
->length
= sizeof(*data
);
19510 data
->mode
= enable_mode
;
19512 for (i
= 1; i
<= MAX_BANDS
; i
++) {
19514 ret
= wldev_iovar_setbuf(ndev
, "adps", iov_buf
, len
,
19515 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, NULL
);
19525 #endif /* WLADPS_SEAK_AP_WAR */
19528 wl_vndr_ies_exclude_vndr_oui(struct parsed_vndr_ie_info
*vndr_info
)
19532 while (exclude_vndr_oui_list
[i
]) {
19533 if (!memcmp(vndr_info
->vndrie
.oui
,
19534 exclude_vndr_oui_list
[i
],
19545 wl_vndr_ies_check_duplicate_vndr_oui(struct bcm_cfg80211
*cfg
,
19546 struct parsed_vndr_ie_info
*vndr_info
)
19548 wl_vndr_oui_entry_t
*oui_entry
= NULL
;
19550 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19551 #pragma GCC diagnostic push
19552 #pragma GCC diagnostic ignored "-Wcast-qual"
19554 list_for_each_entry(oui_entry
, &cfg
->vndr_oui_list
, list
) {
19555 if (!memcmp(oui_entry
->oui
, vndr_info
->vndrie
.oui
, DOT11_OUI_LEN
)) {
19559 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19560 #pragma GCC diagnostic pop
19567 wl_vndr_ies_add_vendor_oui_list(struct bcm_cfg80211
*cfg
,
19568 struct parsed_vndr_ie_info
*vndr_info
)
19570 wl_vndr_oui_entry_t
*oui_entry
= NULL
;
19572 oui_entry
= kmalloc(sizeof(*oui_entry
), GFP_KERNEL
);
19573 if (oui_entry
== NULL
) {
19574 WL_ERR(("alloc failed\n"));
19578 memcpy(oui_entry
->oui
, vndr_info
->vndrie
.oui
, DOT11_OUI_LEN
);
19580 INIT_LIST_HEAD(&oui_entry
->list
);
19581 list_add_tail(&oui_entry
->list
, &cfg
->vndr_oui_list
);
19587 wl_vndr_ies_clear_vendor_oui_list(struct bcm_cfg80211
*cfg
)
19589 wl_vndr_oui_entry_t
*oui_entry
= NULL
;
19591 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19592 #pragma GCC diagnostic push
19593 #pragma GCC diagnostic ignored "-Wcast-qual"
19595 while (!list_empty(&cfg
->vndr_oui_list
)) {
19596 oui_entry
= list_entry(cfg
->vndr_oui_list
.next
, wl_vndr_oui_entry_t
, list
);
19598 list_del(&oui_entry
->list
);
19602 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19603 #pragma GCC diagnostic pop
19608 wl_vndr_ies_get_vendor_oui(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
19609 char *vndr_oui
, u32 vndr_oui_len
)
19612 int vndr_oui_num
= 0;
19614 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
19615 wl_vndr_oui_entry_t
*oui_entry
= NULL
;
19616 struct parsed_vndr_ie_info
*vndr_info
;
19617 struct parsed_vndr_ies vndr_ies
;
19619 char *pos
= vndr_oui
;
19620 u32 remained_buf_len
= vndr_oui_len
;
19622 if (!conn_info
->resp_ie_len
) {
19626 wl_vndr_ies_clear_vendor_oui_list(cfg
);
19628 if ((wl_cfg80211_parse_vndr_ies((u8
*)conn_info
->resp_ie
,
19629 conn_info
->resp_ie_len
, &vndr_ies
)) == BCME_OK
) {
19630 for (i
= 0; i
< vndr_ies
.count
; i
++) {
19631 vndr_info
= &vndr_ies
.ie_info
[i
];
19632 if (wl_vndr_ies_exclude_vndr_oui(vndr_info
)) {
19636 if (wl_vndr_ies_check_duplicate_vndr_oui(cfg
, vndr_info
)) {
19640 wl_vndr_ies_add_vendor_oui_list(cfg
, vndr_info
);
19646 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19647 #pragma GCC diagnostic push
19648 #pragma GCC diagnostic ignored "-Wcast-qual"
19650 list_for_each_entry(oui_entry
, &cfg
->vndr_oui_list
, list
) {
19651 if (remained_buf_len
< VNDR_OUI_STR_LEN
) {
19654 pos
+= snprintf(pos
, VNDR_OUI_STR_LEN
, "%02X-%02X-%02X ",
19655 oui_entry
->oui
[0], oui_entry
->oui
[1], oui_entry
->oui
[2]);
19656 remained_buf_len
-= VNDR_OUI_STR_LEN
;
19658 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19659 #pragma GCC diagnostic pop
19663 return vndr_oui_num
;
19667 wl_cfg80211_get_vndr_ouilist(struct bcm_cfg80211
*cfg
, uint8
*buf
, int max_cnt
)
19669 wl_vndr_oui_entry_t
*oui_entry
= NULL
;
19672 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19673 #pragma GCC diagnostic push
19674 #pragma GCC diagnostic ignored "-Wcast-qual"
19676 list_for_each_entry(oui_entry
, &cfg
->vndr_oui_list
, list
) {
19677 memcpy(buf
, oui_entry
->oui
, DOT11_OUI_LEN
);
19679 if (cnt
>= max_cnt
) {
19682 buf
+= DOT11_OUI_LEN
;
19684 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19685 #pragma GCC diagnostic pop
19691 wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211
*cfg
, s32 bssidx
)
19694 struct net_info
*netinfo
;
19695 s32 vndrie_flag
[] = {VNDR_IE_BEACON_FLAG
, VNDR_IE_PRBRSP_FLAG
,
19696 VNDR_IE_ASSOCRSP_FLAG
, VNDR_IE_PRBREQ_FLAG
, VNDR_IE_ASSOCREQ_FLAG
};
19698 netinfo
= wl_get_netinfo_by_bssidx(cfg
, bssidx
);
19699 if (!netinfo
|| !netinfo
->wdev
) {
19700 WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
19704 WL_DBG(("clear management vendor IEs for bssidx:%d \n", bssidx
));
19705 /* Clear the IEs set in the firmware so that host is in sync with firmware */
19706 for (index
= 0; index
< ARRAYSIZE(vndrie_flag
); index
++) {
19707 if (wl_cfg80211_set_mgmt_vndr_ies(cfg
, wdev_to_cfgdev(netinfo
->wdev
),
19708 bssidx
, vndrie_flag
[index
], NULL
, 0) < 0)
19709 WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
19716 wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211
*cfg
)
19718 struct net_info
*iter
, *next
;
19720 WL_DBG(("clear management vendor IEs \n"));
19721 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19722 4 && __GNUC_MINOR__ >= 6))
19723 _Pragma("GCC diagnostic push")
19724 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19726 for_each_ndev(cfg
, iter
, next
) {
19727 wl_cfg80211_clear_per_bss_ies(cfg
, iter
->bssidx
);
19729 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19730 4 && __GNUC_MINOR__ >= 6))
19731 _Pragma("GCC diagnostic pop")
19736 #define WL_VNDR_IE_MAXLEN 2048
19737 static s8 g_mgmt_ie_buf
[WL_VNDR_IE_MAXLEN
];
19739 wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
19740 s32 bssidx
, s32 pktflag
, const u8
*vndr_ie
, u32 vndr_ie_len
)
19742 struct net_device
*ndev
= NULL
;
19744 u8
*curr_ie_buf
= NULL
;
19745 u8
*mgmt_ie_buf
= NULL
;
19746 u32 mgmt_ie_buf_len
= 0;
19747 u32
*mgmt_ie_len
= 0;
19748 u32 del_add_ie_buf_len
= 0;
19749 u32 total_ie_buf_len
= 0;
19750 u32 parsed_ie_buf_len
= 0;
19751 struct parsed_vndr_ies old_vndr_ies
;
19752 struct parsed_vndr_ies new_vndr_ies
;
19755 s32 remained_buf_len
;
19756 wl_bss_vndr_ies_t
*ies
= NULL
;
19757 struct net_info
*netinfo
;
19759 WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d \n",
19760 pktflag
, bssidx
, vndr_ie_len
));
19762 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
19764 if (bssidx
> WL_MAX_IFS
) {
19765 WL_ERR(("bssidx > supported concurrent Ifaces \n"));
19769 netinfo
= wl_get_netinfo_by_bssidx(cfg
, bssidx
);
19771 WL_ERR(("net_info ptr is NULL \n"));
19775 /* Clear the global buffer */
19776 memset(g_mgmt_ie_buf
, 0, sizeof(g_mgmt_ie_buf
));
19777 curr_ie_buf
= g_mgmt_ie_buf
;
19778 ies
= &netinfo
->bss
.ies
;
19781 case VNDR_IE_PRBRSP_FLAG
:
19782 mgmt_ie_buf
= ies
->probe_res_ie
;
19783 mgmt_ie_len
= &ies
->probe_res_ie_len
;
19784 mgmt_ie_buf_len
= sizeof(ies
->probe_res_ie
);
19786 case VNDR_IE_ASSOCRSP_FLAG
:
19787 mgmt_ie_buf
= ies
->assoc_res_ie
;
19788 mgmt_ie_len
= &ies
->assoc_res_ie_len
;
19789 mgmt_ie_buf_len
= sizeof(ies
->assoc_res_ie
);
19791 case VNDR_IE_BEACON_FLAG
:
19792 mgmt_ie_buf
= ies
->beacon_ie
;
19793 mgmt_ie_len
= &ies
->beacon_ie_len
;
19794 mgmt_ie_buf_len
= sizeof(ies
->beacon_ie
);
19796 case VNDR_IE_PRBREQ_FLAG
:
19797 mgmt_ie_buf
= ies
->probe_req_ie
;
19798 mgmt_ie_len
= &ies
->probe_req_ie_len
;
19799 mgmt_ie_buf_len
= sizeof(ies
->probe_req_ie
);
19801 case VNDR_IE_ASSOCREQ_FLAG
:
19802 mgmt_ie_buf
= ies
->assoc_req_ie
;
19803 mgmt_ie_len
= &ies
->assoc_req_ie_len
;
19804 mgmt_ie_buf_len
= sizeof(ies
->assoc_req_ie
);
19807 mgmt_ie_buf
= NULL
;
19808 mgmt_ie_len
= NULL
;
19809 WL_ERR(("not suitable packet type (%d)\n", pktflag
));
19813 if (vndr_ie_len
> mgmt_ie_buf_len
) {
19814 WL_ERR(("extra IE size too big\n"));
19817 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
19818 if (vndr_ie
&& vndr_ie_len
&& curr_ie_buf
) {
19820 /* must discard vndr_ie constness, attempt to change vndr_ie arg to non-const
19821 * causes cascade of errors in other places, fix involves const casts there
19823 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19824 4 && __GNUC_MINOR__ >= 6))
19825 _Pragma("GCC diagnostic push")
19826 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19828 if ((ret
= wl_cfg80211_parse_vndr_ies((u8
*)vndr_ie
,
19829 vndr_ie_len
, &new_vndr_ies
)) < 0) {
19830 WL_ERR(("parse vndr ie failed \n"));
19833 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19834 4 && __GNUC_MINOR__ >= 6))
19835 _Pragma("GCC diagnostic pop")
19837 for (i
= 0; i
< new_vndr_ies
.count
; i
++) {
19838 struct parsed_vndr_ie_info
*vndrie_info
=
19839 &new_vndr_ies
.ie_info
[i
];
19841 if ((parsed_ie_buf_len
+ vndrie_info
->ie_len
) > WL_VNDR_IE_MAXLEN
) {
19842 WL_ERR(("IE size is too big (%d > %d)\n",
19843 parsed_ie_buf_len
, WL_VNDR_IE_MAXLEN
));
19848 memcpy(ptr
+ parsed_ie_buf_len
, vndrie_info
->ie_ptr
,
19849 vndrie_info
->ie_len
);
19850 parsed_ie_buf_len
+= vndrie_info
->ie_len
;
19854 if (mgmt_ie_buf
!= NULL
) {
19855 if (parsed_ie_buf_len
&& (parsed_ie_buf_len
== *mgmt_ie_len
) &&
19856 (memcmp(mgmt_ie_buf
, curr_ie_buf
, parsed_ie_buf_len
) == 0)) {
19857 WL_INFORM(("Previous mgmt IE is equals to current IE"));
19861 /* parse old vndr_ie */
19862 if ((ret
= wl_cfg80211_parse_vndr_ies(mgmt_ie_buf
, *mgmt_ie_len
,
19863 &old_vndr_ies
)) < 0) {
19864 WL_ERR(("parse vndr ie failed \n"));
19867 /* make a command to delete old ie */
19868 for (i
= 0; i
< old_vndr_ies
.count
; i
++) {
19869 struct parsed_vndr_ie_info
*vndrie_info
=
19870 &old_vndr_ies
.ie_info
[i
];
19872 WL_INFORM(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
19873 vndrie_info
->vndrie
.id
, vndrie_info
->vndrie
.len
,
19874 vndrie_info
->vndrie
.oui
[0], vndrie_info
->vndrie
.oui
[1],
19875 vndrie_info
->vndrie
.oui
[2]));
19877 del_add_ie_buf_len
= wl_cfgp2p_vndr_ie(cfg
, curr_ie_buf
,
19878 pktflag
, vndrie_info
->vndrie
.oui
,
19879 vndrie_info
->vndrie
.id
,
19880 vndrie_info
->ie_ptr
+ VNDR_IE_FIXED_LEN
,
19881 vndrie_info
->ie_len
- VNDR_IE_FIXED_LEN
,
19884 curr_ie_buf
+= del_add_ie_buf_len
;
19885 total_ie_buf_len
+= del_add_ie_buf_len
;
19890 /* Add if there is any extra IE */
19891 if (mgmt_ie_buf
&& parsed_ie_buf_len
) {
19894 remained_buf_len
= mgmt_ie_buf_len
;
19896 /* make a command to add new ie */
19897 for (i
= 0; i
< new_vndr_ies
.count
; i
++) {
19898 struct parsed_vndr_ie_info
*vndrie_info
=
19899 &new_vndr_ies
.ie_info
[i
];
19901 WL_INFORM(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
19902 vndrie_info
->vndrie
.id
, vndrie_info
->vndrie
.len
,
19903 vndrie_info
->ie_len
- 2,
19904 vndrie_info
->vndrie
.oui
[0], vndrie_info
->vndrie
.oui
[1],
19905 vndrie_info
->vndrie
.oui
[2]));
19907 del_add_ie_buf_len
= wl_cfgp2p_vndr_ie(cfg
, curr_ie_buf
,
19908 pktflag
, vndrie_info
->vndrie
.oui
,
19909 vndrie_info
->vndrie
.id
,
19910 vndrie_info
->ie_ptr
+ VNDR_IE_FIXED_LEN
,
19911 vndrie_info
->ie_len
- VNDR_IE_FIXED_LEN
,
19914 /* verify remained buf size before copy data */
19915 if (remained_buf_len
>= vndrie_info
->ie_len
) {
19916 remained_buf_len
-= vndrie_info
->ie_len
;
19918 WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
19919 "found vndr ies # = %d(cur %d), remained len %d, "
19920 "cur mgmt_ie_len %d, new ie len = %d\n",
19921 pktflag
, new_vndr_ies
.count
, i
, remained_buf_len
,
19922 *mgmt_ie_len
, vndrie_info
->ie_len
));
19926 /* save the parsed IE in cfg struct */
19927 memcpy(ptr
+ (*mgmt_ie_len
), vndrie_info
->ie_ptr
,
19928 vndrie_info
->ie_len
);
19929 *mgmt_ie_len
+= vndrie_info
->ie_len
;
19930 curr_ie_buf
+= del_add_ie_buf_len
;
19931 total_ie_buf_len
+= del_add_ie_buf_len
;
19935 if (total_ie_buf_len
&& cfg
->ioctl_buf
!= NULL
) {
19936 ret
= wldev_iovar_setbuf_bsscfg(ndev
, "vndr_ie", g_mgmt_ie_buf
,
19937 total_ie_buf_len
, cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
,
19938 bssidx
, &cfg
->ioctl_buf_sync
);
19940 WL_ERR(("vndr ie set error : %d\n", ret
));
19948 #ifdef WL_CFG80211_ACL
19950 wl_cfg80211_set_mac_acl(struct wiphy
*wiphy
, struct net_device
*cfgdev
,
19951 const struct cfg80211_acl_data
*acl
)
19956 int macmode
= MACLIST_MODE_DISABLED
;
19957 struct maclist
*list
;
19959 /* get the MAC filter mode */
19960 if (acl
&& acl
->acl_policy
== NL80211_ACL_POLICY_DENY_UNLESS_LISTED
) {
19961 macmode
= MACLIST_MODE_ALLOW
;
19962 } else if (acl
&& acl
->acl_policy
== NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED
&&
19963 acl
->n_acl_entries
) {
19964 macmode
= MACLIST_MODE_DENY
;
19967 /* if acl == NULL, macmode is still disabled.. */
19968 if (macmode
== MACLIST_MODE_DISABLED
) {
19969 if ((ret
= wl_android_set_ap_mac_list(cfgdev
, macmode
, NULL
)) != 0)
19970 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__
, ret
));
19975 macnum
= acl
->n_acl_entries
;
19976 if (macnum
< 0 || macnum
> MAX_NUM_MAC_FILT
) {
19977 WL_ERR(("%s : invalid number of MAC address entries %d\n",
19978 __FUNCTION__
, macnum
));
19982 /* allocate memory for the MAC list */
19983 list
= (struct maclist
*)kmalloc(sizeof(int) +
19984 sizeof(struct ether_addr
) * macnum
, GFP_KERNEL
);
19986 WL_ERR(("%s : failed to allocate memory\n", __FUNCTION__
));
19990 /* prepare the MAC list */
19991 list
->count
= htod32(macnum
);
19992 for (i
= 0; i
< macnum
; i
++) {
19993 memcpy(&list
->ea
[i
], &acl
->mac_addrs
[i
], ETHER_ADDR_LEN
);
19996 if ((ret
= wl_android_set_ap_mac_list(cfgdev
, macmode
, list
)) != 0)
19997 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__
, ret
));
20003 #endif /* WL_CFG80211_ACL */
20005 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
20006 int wl_chspec_chandef(chanspec_t chanspec
,
20007 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
20008 struct cfg80211_chan_def
*chandef
,
20009 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
20010 struct chan_info
*chaninfo
,
20011 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
20012 struct wiphy
*wiphy
)
20018 struct ieee80211_channel
*chan
;
20023 channel
= CHSPEC_CHANNEL(chanspec
);
20025 switch (CHSPEC_BW(chanspec
)) {
20026 case WL_CHANSPEC_BW_20
:
20027 chan_type
= NL80211_CHAN_HT20
;
20029 case WL_CHANSPEC_BW_40
:
20031 if (CHSPEC_SB_UPPER(chanspec
)) {
20032 channel
+= CH_10MHZ_APART
;
20034 channel
-= CH_10MHZ_APART
;
20037 chan_type
= NL80211_CHAN_HT40PLUS
;
20040 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20041 case WL_CHANSPEC_BW_80
:
20042 case WL_CHANSPEC_BW_8080
:
20044 uint16 sb
= CHSPEC_CTL_SB(chanspec
);
20046 if (sb
== WL_CHANSPEC_CTL_SB_LL
) {
20047 channel
-= (CH_10MHZ_APART
+ CH_20MHZ_APART
);
20048 } else if (sb
== WL_CHANSPEC_CTL_SB_LU
) {
20049 channel
-= CH_10MHZ_APART
;
20050 } else if (sb
== WL_CHANSPEC_CTL_SB_UL
) {
20051 channel
+= CH_10MHZ_APART
;
20053 /* WL_CHANSPEC_CTL_SB_UU */
20054 channel
+= (CH_10MHZ_APART
+ CH_20MHZ_APART
);
20057 if (sb
== WL_CHANSPEC_CTL_SB_LL
|| sb
== WL_CHANSPEC_CTL_SB_LU
)
20058 chan_type
= NL80211_CHAN_HT40MINUS
;
20059 else if (sb
== WL_CHANSPEC_CTL_SB_UL
|| sb
== WL_CHANSPEC_CTL_SB_UU
)
20060 chan_type
= NL80211_CHAN_HT40PLUS
;
20063 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20065 chan_type
= NL80211_CHAN_HT20
;
20070 if (CHSPEC_IS5G(chanspec
))
20071 freq
= ieee80211_channel_to_frequency(channel
, NL80211_BAND_5GHZ
);
20073 freq
= ieee80211_channel_to_frequency(channel
, NL80211_BAND_2GHZ
);
20075 chan
= ieee80211_get_channel(wiphy
, freq
);
20076 WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
20077 channel
, freq
, chan_type
, chan
));
20079 if (unlikely(!chan
)) {
20080 /* fw and cfg80211 channel lists are not in sync */
20081 WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
20086 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20087 cfg80211_chandef_create(chandef
, chan
, chan_type
);
20088 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
20093 chaninfo
->freq
= freq
;
20094 chaninfo
->chan_type
= chan_type
;
20095 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20100 wl_cfg80211_ch_switch_notify(struct net_device
*dev
, uint16 chanspec
, struct wiphy
*wiphy
)
20103 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20104 struct cfg80211_chan_def chandef
;
20105 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
20110 struct chan_info chaninfo
;
20111 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20114 printf("wiphy is null\n");
20117 #ifndef ALLOW_CHSW_EVT
20118 /* Channel switch support is only for AP/GO/ADHOC/MESH */
20119 if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_STATION
||
20120 dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_CLIENT
) {
20121 WL_ERR(("No channel switch notify support for STA/GC\n"));
20124 #endif /* !ALLOW_CHSW_EVT */
20125 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20126 if (wl_chspec_chandef(chanspec
, &chandef
, wiphy
))
20127 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
20128 if (wl_chspec_chandef(chanspec
, &chaninfo
, wiphy
))
20129 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20131 WL_ERR(("chspec_chandef failed\n"));
20134 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20135 freq
= chandef
.chan
? chandef
.chan
->center_freq
: chandef
.center_freq1
;
20136 cfg80211_ch_switch_notify(dev
, &chandef
);
20137 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
20138 freq
= chan_info
.freq
;
20139 cfg80211_ch_switch_notify(dev
, freq
, chan_info
.chan_type
);
20140 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20142 WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq
, chanspec
));
20145 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20149 wl_cfg80211_set_ulb_mode(struct net_device
*dev
, int mode
)
20154 ret
= wldev_iovar_getint(dev
, "ulb_mode", &cur_mode
);
20155 if (unlikely(ret
)) {
20156 WL_ERR(("[ULB] ulb_mode get failed. ret:%d \n", ret
));
20160 if (cur_mode
== mode
) {
20161 /* If request mode is same as that of the current mode, then
20162 * do nothing (Avoid unnecessary wl down and up).
20164 WL_INFORM(("[ULB] No change in ulb_mode. Do nothing.\n"));
20168 /* setting of ulb_mode requires wl to be down */
20169 ret
= wldev_ioctl_set(dev
, WLC_DOWN
, NULL
, 0);
20170 if (unlikely(ret
)) {
20171 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret
));
20175 if (mode
>= MAX_SUPP_ULB_MODES
) {
20176 WL_ERR(("[ULB] unsupported ulb_mode :[%d]\n", mode
));
20180 ret
= wldev_iovar_setint(dev
, "ulb_mode", mode
);
20181 if (unlikely(ret
)) {
20182 WL_ERR(("[ULB] ulb_mode set failed. ret:%d \n", ret
));
20186 ret
= wldev_ioctl_set(dev
, WLC_UP
, NULL
, 0);
20187 if (unlikely(ret
)) {
20188 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret
));
20192 WL_DBG(("[ULB] ulb_mode set to %d successfully \n", mode
));
20198 wl_cfg80211_ulbbw_to_ulbchspec(u32 bw
)
20200 if (bw
== ULB_BW_DISABLED
) {
20201 return WL_CHANSPEC_BW_20
;
20202 } else if (bw
== ULB_BW_10MHZ
) {
20203 return WL_CHANSPEC_BW_10
;
20204 } else if (bw
== ULB_BW_5MHZ
) {
20205 return WL_CHANSPEC_BW_5
;
20206 } else if (bw
== ULB_BW_2P5MHZ
) {
20207 return WL_CHANSPEC_BW_2P5
;
20209 WL_ERR(("[ULB] unsupported value for ulb_bw \n"));
20215 wl_cfg80211_ulb_get_min_bw_chspec(struct bcm_cfg80211
*cfg
, struct wireless_dev
*wdev
, s32 bssidx
)
20217 struct net_info
*_netinfo
;
20220 * Return the chspec value corresponding to the
20221 * BW setting for a particular interface
20224 /* if wdev is provided, use it */
20225 _netinfo
= wl_get_netinfo_by_wdev(cfg
, wdev
);
20226 } else if (bssidx
>= 0) {
20227 /* if wdev is not provided, use it */
20228 _netinfo
= wl_get_netinfo_by_bssidx(cfg
, bssidx
);
20230 WL_ERR(("[ULB] wdev/bssidx not provided\n"));
20231 return INVCHANSPEC
;
20234 if (unlikely(!_netinfo
)) {
20235 WL_ERR(("[ULB] net_info is null \n"));
20236 return INVCHANSPEC
;
20239 if (_netinfo
->ulb_bw
) {
20240 WL_DBG(("[ULB] wdev_ptr:%p ulb_bw:0x%x \n", _netinfo
->wdev
, _netinfo
->ulb_bw
));
20241 return wl_cfg80211_ulbbw_to_ulbchspec(_netinfo
->ulb_bw
);
20243 return WL_CHANSPEC_BW_20
;
20248 wl_cfg80211_get_ulb_bw(struct bcm_cfg80211
*cfg
, struct wireless_dev
*wdev
)
20250 struct net_info
*_netinfo
= wl_get_netinfo_by_wdev(cfg
, wdev
);
20253 * Return the ulb_bw setting for a
20254 * particular interface
20256 if (unlikely(!_netinfo
)) {
20257 WL_ERR(("[ULB] net_info is null \n"));
20261 return _netinfo
->ulb_bw
;
20265 wl_cfg80211_set_ulb_bw(struct net_device
*dev
,
20266 u32 ulb_bw
, char *ifname
)
20268 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20271 struct net_info
*_netinfo
= NULL
, *iter
, *next
;
20277 WL_DBG(("[ULB] Enter. bw_type:%d \n", ulb_bw
));
20279 ret
= wldev_iovar_getint(dev
, "ulb_mode", &mode
);
20280 if (unlikely(ret
)) {
20281 WL_ERR(("[ULB] ulb_mode not supported \n"));
20285 if (mode
!= ULB_MODE_STD_ALONE_MODE
) {
20286 WL_ERR(("[ULB] ulb bw modification allowed only in stand-alone mode\n"));
20290 if (ulb_bw
>= MAX_SUPP_ULB_BW
) {
20291 WL_ERR(("[ULB] unsupported value (%d) for ulb_bw \n", ulb_bw
));
20295 #ifdef WL_CFG80211_P2P_DEV_IF
20296 if (strcmp(ifname
, "p2p-dev-wlan0") == 0) {
20297 /* Use wdev corresponding to the dedicated p2p discovery interface */
20298 if (likely(cfg
->p2p_wdev
)) {
20299 _netinfo
= wl_get_netinfo_by_wdev(cfg
, cfg
->p2p_wdev
);
20304 #endif /* WL_CFG80211_P2P_DEV_IF */
20306 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20307 #pragma GCC diagnostic push
20308 #pragma GCC diagnostic ignored "-Wcast-qual"
20310 for_each_ndev(cfg
, iter
, next
) {
20312 if (strncmp(iter
->ndev
->name
, ifname
, strlen(ifname
)) == 0) {
20313 _netinfo
= wl_get_netinfo_by_netdev(cfg
, iter
->ndev
);
20317 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20318 #pragma GCC diagnostic pop
20324 bssidx
= _netinfo
->bssidx
;
20325 _netinfo
->ulb_bw
= ulb_bw
;
20328 WL_DBG(("[ULB] Applying ulb_bw:%d for bssidx:%d \n", ulb_bw
, bssidx
));
20329 ret
= wldev_iovar_setbuf_bsscfg(dev
, "ulb_bw", (void *)&ulb_bw
, 4,
20330 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, bssidx
,
20331 &cfg
->ioctl_buf_sync
);
20332 if (unlikely(ret
)) {
20333 WL_ERR(("[ULB] ulb_bw set failed. ret:%d \n", ret
));
20339 #endif /* WL11ULB */
20342 wl_ap_channel_ind(struct bcm_cfg80211
*cfg
,
20343 struct net_device
*ndev
,
20344 chanspec_t chanspec
)
20346 u32 channel
= LCHSPEC_CHANNEL(chanspec
);
20348 WL_DBG(("(%s) AP channel:%d chspec:0x%x \n",
20349 ndev
->name
, channel
, chanspec
));
20350 if (cfg
->ap_oper_channel
&& (cfg
->ap_oper_channel
!= channel
)) {
20352 * If cached channel is different from the channel indicated
20353 * by the event, notify user space about the channel switch.
20355 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
20356 wl_cfg80211_ch_switch_notify(ndev
, chanspec
, bcmcfg_to_wiphy(cfg
));
20357 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20358 cfg
->ap_oper_channel
= channel
;
20363 wl_ap_start_ind(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
20364 const wl_event_msg_t
*e
, void *data
)
20366 struct net_device
*ndev
= NULL
;
20367 chanspec_t chanspec
;
20369 WL_DBG(("Enter\n"));
20370 if (unlikely(e
->status
)) {
20371 WL_ERR(("status:0x%x \n", e
->status
));
20379 if (likely(cfgdev
)) {
20380 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
20381 chanspec
= *((chanspec_t
*)data
);
20383 if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_AP
) {
20384 /* For AP/GO role */
20385 wl_ap_channel_ind(cfg
, ndev
, chanspec
);
20393 wl_csa_complete_ind(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
20394 const wl_event_msg_t
*e
, void *data
)
20398 struct net_device
*ndev
= NULL
;
20400 WL_DBG(("Enter\n"));
20401 if (unlikely(e
->status
)) {
20402 WL_ERR(("status:0x%x \n", e
->status
));
20406 if (likely(cfgdev
)) {
20407 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
20408 error
= wldev_iovar_getint(ndev
, "chanspec", &chanspec
);
20409 if (unlikely(error
)) {
20410 WL_ERR(("Get chanspec error: %d \n", error
));
20414 if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_AP
) {
20415 /* For AP/GO role */
20416 wl_ap_channel_ind(cfg
, ndev
, chanspec
);
20418 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
20419 wl_cfg80211_ch_switch_notify(ndev
, chanspec
, bcmcfg_to_wiphy(cfg
));
20420 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20429 void wl_cfg80211_clear_security(struct bcm_cfg80211
*cfg
)
20431 struct net_device
*dev
= bcmcfg_to_prmry_ndev(cfg
);
20434 /* Clear the security settings on the primary Interface */
20435 err
= wldev_iovar_setint(dev
, "wsec", 0);
20436 if (unlikely(err
)) {
20437 WL_ERR(("wsec clear failed \n"));
20439 err
= wldev_iovar_setint(dev
, "auth", 0);
20440 if (unlikely(err
)) {
20441 WL_ERR(("auth clear failed \n"));
20443 err
= wldev_iovar_setint(dev
, "wpa_auth", WPA_AUTH_DISABLED
);
20444 if (unlikely(err
)) {
20445 WL_ERR(("wpa_auth clear failed \n"));
20449 #ifdef WL_CFG80211_P2P_DEV_IF
20450 void wl_cfg80211_del_p2p_wdev(struct net_device
*dev
)
20452 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20453 struct wireless_dev
*wdev
= NULL
;
20455 WL_DBG(("Enter \n"));
20457 WL_ERR(("Invalid Ptr\n"));
20460 wdev
= cfg
->p2p_wdev
;
20463 if (wdev
&& cfg
->down_disc_if
) {
20464 wl_cfgp2p_del_p2p_disc_if(wdev
, cfg
);
20465 cfg
->down_disc_if
= FALSE
;
20468 #endif /* WL_CFG80211_P2P_DEV_IF */
20470 #ifdef GTK_OFFLOAD_SUPPORT
20471 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
20473 wl_cfg80211_set_rekey_data(struct wiphy
*wiphy
, struct net_device
*dev
,
20474 struct cfg80211_gtk_rekey_data
*data
)
20476 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
20478 gtk_keyinfo_t keyinfo
;
20480 WL_DBG(("Enter\n"));
20481 if (data
== NULL
|| cfg
->p2p_net
== dev
) {
20482 WL_ERR(("data is NULL or wrong net device\n"));
20485 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
20486 prhex("kck", (uchar
*) (data
->kck
), RSN_KCK_LENGTH
);
20487 prhex("kek", (uchar
*) (data
->kek
), RSN_KEK_LENGTH
);
20488 prhex("replay_ctr", (uchar
*) (data
->replay_ctr
), RSN_REPLAY_LEN
);
20490 prhex("kck", (uchar
*)data
->kck
, RSN_KCK_LENGTH
);
20491 prhex("kek", (uchar
*)data
->kek
, RSN_KEK_LENGTH
);
20492 prhex("replay_ctr", (uchar
*)data
->replay_ctr
, RSN_REPLAY_LEN
);
20493 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) */
20494 bcopy(data
->kck
, keyinfo
.KCK
, RSN_KCK_LENGTH
);
20495 bcopy(data
->kek
, keyinfo
.KEK
, RSN_KEK_LENGTH
);
20496 bcopy(data
->replay_ctr
, keyinfo
.ReplayCounter
, RSN_REPLAY_LEN
);
20498 if ((err
= wldev_iovar_setbuf(dev
, "gtk_key_info", &keyinfo
, sizeof(keyinfo
),
20499 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
)) < 0) {
20500 WL_ERR(("seting gtk_key_info failed code=%d\n", err
));
20503 WL_DBG(("Exit\n"));
20506 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
20507 #endif /* GTK_OFFLOAD_SUPPORT */
20509 #if defined(WL_SUPPORT_AUTO_CHANNEL)
20511 wl_cfg80211_set_spect(struct net_device
*dev
, int spect
)
20513 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20518 if (!wl_get_drv_status_all(cfg
, CONNECTED
)) {
20519 err
= wldev_ioctl_set(dev
, WLC_DOWN
, &wlc_down
, sizeof(wlc_down
));
20521 WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__
, err
));
20525 err
= wldev_ioctl_set(dev
, WLC_SET_SPECT_MANAGMENT
, &spect
, sizeof(spect
));
20527 WL_ERR(("%s: error setting spect: code: %d\n", __func__
, err
));
20531 err
= wldev_ioctl_set(dev
, WLC_UP
, &wlc_up
, sizeof(wlc_up
));
20533 WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__
, err
));
20541 wl_cfg80211_get_sta_channel(struct net_device
*dev
)
20543 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20546 if (wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
20547 channel
= cfg
->channel
;
20551 #endif /* WL_SUPPORT_AUTO_CHANNEL */
20552 #ifdef P2P_LISTEN_OFFLOADING
20554 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211
*cfg
)
20558 int p2plo_pause
= 0;
20559 if (!cfg
|| !cfg
->p2p
) {
20560 WL_ERR(("Wl %p or cfg->p2p %p is null\n",
20561 cfg
, cfg
? cfg
->p2p
: 0));
20565 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
20566 ret
= wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg
),
20567 "p2po_stop", (void*)&p2plo_pause
, sizeof(p2plo_pause
),
20568 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
20570 WL_ERR(("p2po_stop Failed :%d\n", ret
));
20576 wl_cfg80211_p2plo_listen_start(struct net_device
*dev
, u8
*buf
, int len
)
20578 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20579 s32 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
20580 wl_p2plo_listen_t p2plo_listen
;
20586 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg
)) {
20587 WL_ERR(("Sending Action Frames. Try it again.\n"));
20591 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
20592 WL_ERR(("Scanning already\n"));
20596 if (wl_get_drv_status(cfg
, SCAN_ABORTING
, dev
)) {
20597 WL_ERR(("Scanning being aborted\n"));
20601 if (wl_get_p2p_status(cfg
, DISC_IN_PROGRESS
)) {
20602 WL_ERR(("p2p listen offloading already running\n"));
20606 /* Just in case if it is not enabled */
20607 if ((ret
= wl_cfgp2p_enable_discovery(cfg
, dev
, NULL
, 0)) < 0) {
20608 WL_ERR(("cfgp2p_enable discovery failed"));
20612 bzero(&p2plo_listen
, sizeof(wl_p2plo_listen_t
));
20615 sscanf(buf
, " %10d %10d %10d %10d", &channel
, &period
, &interval
, &count
);
20616 if ((channel
== 0) || (period
== 0) ||
20617 (interval
== 0) || (count
== 0)) {
20618 WL_ERR(("Wrong argument %d/%d/%d/%d \n",
20619 channel
, period
, interval
, count
));
20623 p2plo_listen
.period
= period
;
20624 p2plo_listen
.interval
= interval
;
20625 p2plo_listen
.count
= count
;
20627 WL_ERR(("channel:%d period:%d, interval:%d count:%d\n",
20628 channel
, period
, interval
, count
));
20630 WL_ERR(("Argument len is wrong.\n"));
20635 if ((ret
= wldev_iovar_setbuf_bsscfg(dev
, "p2po_listen_channel", (void*)&channel
,
20636 sizeof(channel
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
20637 bssidx
, &cfg
->ioctl_buf_sync
)) < 0) {
20638 WL_ERR(("p2po_listen_channel Failed :%d\n", ret
));
20642 if ((ret
= wldev_iovar_setbuf_bsscfg(dev
, "p2po_listen", (void*)&p2plo_listen
,
20643 sizeof(wl_p2plo_listen_t
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
20644 bssidx
, &cfg
->ioctl_buf_sync
)) < 0) {
20645 WL_ERR(("p2po_listen Failed :%d\n", ret
));
20649 wl_set_p2p_status(cfg
, DISC_IN_PROGRESS
);
20654 wl_cfg80211_p2plo_listen_stop(struct net_device
*dev
)
20656 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20657 s32 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
20660 if ((ret
= wldev_iovar_setbuf_bsscfg(dev
, "p2po_stop", NULL
,
20661 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
20662 bssidx
, &cfg
->ioctl_buf_sync
)) < 0) {
20663 WL_ERR(("p2po_stop Failed :%d\n", ret
));
20670 #endif /* P2P_LISTEN_OFFLOADING */
20673 wl_cfg80211_get_new_roc_id(struct bcm_cfg80211
*cfg
)
20676 id
= ++cfg
->last_roc_id
;
20677 #ifdef P2P_LISTEN_OFFLOADING
20678 if (id
== P2PO_COOKIE
) {
20679 id
= ++cfg
->last_roc_id
;
20681 #endif /* P2P_LISTEN_OFFLOADING */
20683 id
= ++cfg
->last_roc_id
;
20687 #if defined(SUPPORT_RANDOM_MAC_SCAN)
20689 wl_cfg80211_set_random_mac(struct net_device
*dev
, bool enable
)
20691 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20694 if (cfg
->random_mac_enabled
== enable
) {
20695 WL_ERR(("Random MAC already %s\n", enable
? "Enabled" : "Disabled"));
20700 ret
= wl_cfg80211_random_mac_enable(dev
);
20702 ret
= wl_cfg80211_random_mac_disable(dev
);
20706 cfg
->random_mac_enabled
= enable
;
20713 wl_cfg80211_random_mac_enable(struct net_device
*dev
)
20715 u8 random_mac
[ETH_ALEN
] = {0, };
20716 u8 rand_bytes
[3] = {0, };
20717 s32 err
= BCME_ERROR
;
20718 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20720 if (wl_get_drv_status_all(cfg
, CONNECTED
) || wl_get_drv_status_all(cfg
, CONNECTING
) ||
20721 wl_get_drv_status_all(cfg
, AP_CREATED
) || wl_get_drv_status_all(cfg
, AP_CREATING
)) {
20722 WL_ERR(("fail to Set random mac, current state is wrong\n"));
20726 memcpy(random_mac
, bcmcfg_to_prmry_ndev(cfg
)->dev_addr
, ETH_ALEN
);
20727 get_random_bytes(&rand_bytes
, sizeof(rand_bytes
));
20729 if (rand_bytes
[2] == 0x0 || rand_bytes
[2] == 0xff) {
20730 rand_bytes
[2] = 0xf0;
20733 memcpy(&random_mac
[3], rand_bytes
, sizeof(rand_bytes
));
20735 err
= wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg
), "cur_etheraddr",
20736 random_mac
, ETH_ALEN
, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, 0, &cfg
->ioctl_buf_sync
);
20738 if (err
!= BCME_OK
) {
20739 WL_ERR(("failed to set random generate MAC address\n"));
20741 WL_ERR(("set mac " MACDBG
" to " MACDBG
"\n",
20742 MAC2STRDBG((const u8
*)bcmcfg_to_prmry_ndev(cfg
)->dev_addr
),
20743 MAC2STRDBG((const u8
*)&random_mac
)));
20744 WL_ERR(("random MAC enable done"));
20751 wl_cfg80211_random_mac_disable(struct net_device
*dev
)
20753 s32 err
= BCME_ERROR
;
20754 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20756 WL_ERR(("set original mac " MACDBG
"\n",
20757 MAC2STRDBG((const u8
*)bcmcfg_to_prmry_ndev(cfg
)->dev_addr
)));
20759 err
= wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg
), "cur_etheraddr",
20760 bcmcfg_to_prmry_ndev(cfg
)->dev_addr
, ETH_ALEN
,
20761 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, 0, &cfg
->ioctl_buf_sync
);
20763 if (err
!= BCME_OK
) {
20764 WL_ERR(("failed to set original MAC address\n"));
20766 WL_ERR(("random MAC disable done\n"));
20771 #endif /* SUPPORT_RANDOM_MAC_SCAN */
20775 wl_cfg80211_tdls_config(struct bcm_cfg80211
*cfg
, enum wl_tdls_config state
, bool auto_mode
)
20777 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
20779 struct net_info
*iter
, *next
;
20780 int update_reqd
= 0;
20783 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
20786 * TDLS need to be enabled only if we have a single STA/GC
20790 WL_DBG(("Enter state:%d\n", state
));
20792 if (!cfg
->tdls_supported
) {
20793 /* FW doesn't support tdls. Do nothing */
20797 /* Protect tdls config session */
20798 mutex_lock(&cfg
->tdls_sync
);
20800 if ((state
== TDLS_STATE_TEARDOWN
)) {
20801 /* Host initiated TDLS tear down */
20802 err
= dhd_tdls_enable(ndev
, false, auto_mode
, NULL
);
20804 } else if (state
== TDLS_STATE_AP_CREATE
) {
20805 /* We don't support tdls while AP/GO is operational */
20806 update_reqd
= true;
20808 } else if ((state
== TDLS_STATE_CONNECT
) || (state
== TDLS_STATE_IF_CREATE
)) {
20809 if (wl_get_drv_status_all(cfg
,
20810 CONNECTED
) >= TDLS_MAX_IFACE_FOR_ENABLE
) {
20811 /* For STA/GC connect command request, disable
20812 * tdls if we have any concurrent interfaces
20815 WL_DBG(("Interface limit restriction. disable tdls.\n"));
20816 update_reqd
= true;
20819 } else if ((state
== TDLS_STATE_DISCONNECT
) ||
20820 (state
== TDLS_STATE_AP_DELETE
) ||
20821 (state
== TDLS_STATE_SETUP
) ||
20822 (state
== TDLS_STATE_IF_DELETE
)) {
20823 /* Enable back the tdls connection only if we have less than
20824 * or equal to a single STA/GC connection.
20826 if (wl_get_drv_status_all(cfg
,
20828 /* If there are no interfaces connected, enable tdls */
20829 update_reqd
= true;
20831 } else if (wl_get_drv_status_all(cfg
,
20832 CONNECTED
) == TDLS_MAX_IFACE_FOR_ENABLE
) {
20833 /* We have one interface in CONNECTED state.
20834 * Verify whether its a non-AP interface before
20835 * we enable back tdls.
20837 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20838 #pragma GCC diagnostic push
20839 #pragma GCC diagnostic ignored "-Wcast-qual"
20841 for_each_ndev(cfg
, iter
, next
) {
20842 if ((iter
->ndev
) && (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) &&
20843 wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_AP
) {
20844 WL_DBG(("AP/GO operational. Can't enable tdls. \n"));
20849 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20850 #pragma GCC diagnostic pop
20852 /* No AP/GO found. Enable back tdls */
20853 update_reqd
= true;
20856 WL_DBG(("Concurrent connection mode. Can't enable tdls. \n"));
20861 WL_ERR(("Unknown tdls state:%d \n", state
));
20866 if (update_reqd
== true) {
20867 if (dhdp
->tdls_enable
== enable
) {
20868 WL_ERR(("No change in tdls state. Do nothing."
20869 " tdls_enable:%d\n", enable
));
20872 err
= wldev_iovar_setint(ndev
, "tdls_enable", enable
);
20873 if (unlikely(err
)) {
20874 WL_ERR(("tdls_enable setting failed. err:%d\n", err
));
20877 WL_DBG(("set tdls_enable: %d done\n", enable
));
20878 /* Update the dhd state variable to be in sync */
20879 dhdp
->tdls_enable
= enable
;
20880 if (state
== TDLS_STATE_SETUP
) {
20881 /* For host initiated setup, apply TDLS params
20882 * Don't propagate errors up for param config
20885 dhd_tdls_enable(ndev
, true, auto_mode
, NULL
);
20890 WL_DBG(("Skip tdls config. state:%d update_reqd:%d "
20891 "current_status:%d \n",
20892 state
, update_reqd
, dhdp
->tdls_enable
));
20896 mutex_unlock(&cfg
->tdls_sync
);
20900 #endif /* WLTDLS */
20902 struct net_device
* wl_get_ap_netdev(struct bcm_cfg80211
*cfg
, char *ifname
)
20904 struct net_info
*iter
, *next
;
20905 struct net_device
*ndev
= NULL
;
20907 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20908 #pragma GCC diagnostic push
20909 #pragma GCC diagnostic ignored "-Wcast-qual"
20911 for_each_ndev(cfg
, iter
, next
) {
20913 if (strncmp(iter
->ndev
->name
, ifname
, strlen(iter
->ndev
->name
)) == 0) {
20914 if (iter
->ndev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
20921 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20922 #pragma GCC diagnostic pop
20929 wl_get_netdev_by_name(struct bcm_cfg80211
*cfg
, char *ifname
)
20931 struct net_info
*iter
, *next
;
20932 struct net_device
*ndev
= NULL
;
20934 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20935 #pragma GCC diagnostic push
20936 #pragma GCC diagnostic ignored "-Wcast-qual"
20938 for_each_ndev(cfg
, iter
, next
) {
20940 if (strncmp(iter
->ndev
->name
, ifname
, IFNAMSIZ
) == 0) {
20946 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20947 #pragma GCC diagnostic pop
20953 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
20954 #define WLC_RATE_FLAG 0x80
20955 #define RATE_MASK 0x7f
20957 int wl_set_ap_beacon_rate(struct net_device
*dev
, int val
, char *ifname
)
20959 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20961 wl_rateset_args_t rs
;
20962 int error
= BCME_ERROR
, i
;
20963 struct net_device
*ndev
= NULL
;
20965 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
20967 if (dhdp
&& !(dhdp
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
20968 WL_ERR(("Not Hostapd mode\n"));
20972 ndev
= wl_get_ap_netdev(cfg
, ifname
);
20974 if (ndev
== NULL
) {
20975 WL_ERR(("No softAP interface named %s\n", ifname
));
20979 bzero(&rs
, sizeof(wl_rateset_args_t
));
20980 error
= wldev_iovar_getbuf(ndev
, "rateset", NULL
, 0,
20981 &rs
, sizeof(wl_rateset_args_t
), NULL
);
20983 WL_ERR(("get rateset failed = %d\n", error
));
20987 if (rs
.count
< 1) {
20988 WL_ERR(("Failed to get rate count\n"));
20992 /* Host delivers target rate in the unit of 500kbps */
20993 /* To make it to 1mbps unit, atof should be implemented for 5.5mbps basic rate */
20994 for (i
= 0; i
< rs
.count
&& i
< WL_NUMRATES
; i
++)
20995 if (rs
.rates
[i
] & WLC_RATE_FLAG
)
20996 if ((rs
.rates
[i
] & RATE_MASK
) == val
)
20999 /* Valid rate has been delivered as an argument */
21000 if (i
< rs
.count
&& i
< WL_NUMRATES
) {
21001 error
= wldev_iovar_setint(ndev
, "force_bcn_rspec", val
);
21003 WL_ERR(("set beacon rate failed = %d\n", error
));
21007 WL_ERR(("Rate is invalid"));
21008 return BCME_BADARG
;
21015 wl_get_ap_basic_rate(struct net_device
*dev
, char* command
, char *ifname
, int total_len
)
21017 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21019 wl_rateset_args_t rs
;
21020 int error
= BCME_ERROR
;
21021 int i
, bytes_written
= 0;
21022 struct net_device
*ndev
= NULL
;
21024 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
21026 if (!(dhdp
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
21027 WL_ERR(("Not Hostapd mode\n"));
21031 ndev
= wl_get_ap_netdev(cfg
, ifname
);
21033 if (ndev
== NULL
) {
21034 WL_ERR(("No softAP interface named %s\n", ifname
));
21038 bzero(&rs
, sizeof(wl_rateset_args_t
));
21039 error
= wldev_iovar_getbuf(ndev
, "rateset", NULL
, 0,
21040 &rs
, sizeof(wl_rateset_args_t
), NULL
);
21042 WL_ERR(("get rateset failed = %d\n", error
));
21046 if (rs
.count
< 1) {
21047 WL_ERR(("Failed to get rate count\n"));
21051 /* Delivers basic rate in the unit of 500kbps to host */
21052 for (i
= 0; i
< rs
.count
&& i
< WL_NUMRATES
; i
++)
21053 if (rs
.rates
[i
] & WLC_RATE_FLAG
)
21054 bytes_written
+= snprintf(command
+ bytes_written
, total_len
,
21055 "%d ", rs
.rates
[i
] & RATE_MASK
);
21057 /* Remove last space in the command buffer */
21058 if (bytes_written
) {
21059 command
[bytes_written
- 1] = '\0';
21063 return bytes_written
;
21066 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
21068 #ifdef SUPPORT_AP_RADIO_PWRSAVE
21070 _wl_update_ap_rps_params(struct net_device
*dev
)
21072 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21073 rpsnoa_iovar_params_t iovar
;
21074 u8 smbuf
[WLC_IOCTL_SMLEN
];
21077 return BCME_BADARG
;
21079 memset(&iovar
, 0, sizeof(iovar
));
21080 memset(smbuf
, 0, sizeof(smbuf
));
21082 iovar
.hdr
.ver
= RADIO_PWRSAVE_VERSION
;
21083 iovar
.hdr
.subcmd
= WL_RPSNOA_CMD_PARAMS
;
21084 iovar
.hdr
.len
= sizeof(iovar
);
21085 iovar
.param
->band
= WLC_BAND_ALL
;
21086 iovar
.param
->level
= cfg
->ap_rps_info
.level
;
21087 iovar
.param
->stas_assoc_check
= cfg
->ap_rps_info
.sta_assoc_check
;
21088 iovar
.param
->pps
= cfg
->ap_rps_info
.pps
;
21089 iovar
.param
->quiet_time
= cfg
->ap_rps_info
.quiet_time
;
21091 if (wldev_iovar_setbuf(dev
, "rpsnoa", &iovar
, sizeof(iovar
),
21092 smbuf
, sizeof(smbuf
), NULL
)) {
21093 WL_ERR(("Failed to set rpsnoa params"));
21101 wl_get_ap_rps(struct net_device
*dev
, char* command
, char *ifname
, int total_len
)
21103 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21105 int error
= BCME_ERROR
;
21106 int bytes_written
= 0;
21107 struct net_device
*ndev
= NULL
;
21108 rpsnoa_iovar_t iovar
;
21109 u8 smbuf
[WLC_IOCTL_SMLEN
];
21114 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
21117 error
= BCME_NOTUP
;
21121 if (!(dhdp
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
21122 WL_ERR(("Not Hostapd mode\n"));
21123 error
= BCME_NOTAP
;
21127 ndev
= wl_get_ap_netdev(cfg
, ifname
);
21129 if (ndev
== NULL
) {
21130 WL_ERR(("No softAP interface named %s\n", ifname
));
21131 error
= BCME_NOTAP
;
21135 memset(&iovar
, 0, sizeof(iovar
));
21136 memset(smbuf
, 0, sizeof(smbuf
));
21138 iovar
.hdr
.ver
= RADIO_PWRSAVE_VERSION
;
21139 iovar
.hdr
.subcmd
= WL_RPSNOA_CMD_STATUS
;
21140 iovar
.hdr
.len
= sizeof(iovar
);
21141 iovar
.data
->band
= WLC_BAND_ALL
;
21143 error
= wldev_iovar_getbuf(ndev
, "rpsnoa", &iovar
, sizeof(iovar
),
21144 smbuf
, sizeof(smbuf
), NULL
);
21146 WL_ERR(("get ap radio pwrsave failed = %d\n", error
));
21150 /* RSDB event doesn't seem to be handled correctly.
21151 * So check chanspec of AP directly from the firmware
21153 error
= wldev_iovar_getint(ndev
, "chanspec", (s32
*)&chanspec
);
21155 WL_ERR(("get chanspec from AP failed = %d\n", error
));
21159 chanspec
= wl_chspec_driver_to_host(chanspec
);
21160 if (CHSPEC_IS2G(chanspec
))
21162 else if (CHSPEC_IS5G(chanspec
))
21165 error
= BCME_BADCHAN
;
21169 val
= ((rpsnoa_iovar_t
*)smbuf
)->data
[idx
].value
;
21170 bytes_written
+= snprintf(command
+ bytes_written
, total_len
, "%d", val
);
21171 error
= bytes_written
;
21178 wl_set_ap_rps(struct net_device
*dev
, bool enable
, char *ifname
)
21180 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21182 struct net_device
*ndev
= NULL
;
21183 rpsnoa_iovar_t iovar
;
21184 u8 smbuf
[WLC_IOCTL_SMLEN
];
21187 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
21194 if (!(dhdp
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
21195 WL_ERR(("Not Hostapd mode\n"));
21200 ndev
= wl_get_ap_netdev(cfg
, ifname
);
21202 if (ndev
== NULL
) {
21203 WL_ERR(("No softAP interface named %s\n", ifname
));
21208 if (cfg
->ap_rps_info
.enable
!= enable
) {
21209 cfg
->ap_rps_info
.enable
= enable
;
21211 ret
= _wl_update_ap_rps_params(ndev
);
21213 WL_ERR(("Filed to update rpsnoa params\n"));
21217 memset(&iovar
, 0, sizeof(iovar
));
21218 memset(smbuf
, 0, sizeof(smbuf
));
21220 iovar
.hdr
.ver
= RADIO_PWRSAVE_VERSION
;
21221 iovar
.hdr
.subcmd
= WL_RPSNOA_CMD_ENABLE
;
21222 iovar
.hdr
.len
= sizeof(iovar
);
21223 iovar
.data
->band
= WLC_BAND_ALL
;
21224 iovar
.data
->value
= (int16
)enable
;
21226 ret
= wldev_iovar_setbuf(ndev
, "rpsnoa", &iovar
, sizeof(iovar
),
21227 smbuf
, sizeof(smbuf
), NULL
);
21229 WL_ERR(("Failed to enable AP radio power save"));
21232 cfg
->ap_rps_info
.enable
= enable
;
21239 wl_update_ap_rps_params(struct net_device
*dev
, ap_rps_info_t
* rps
, char *ifname
)
21241 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21243 struct net_device
*ndev
= NULL
;
21245 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
21250 if (!(dhdp
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
21251 WL_ERR(("Not Hostapd mode\n"));
21255 ndev
= wl_get_ap_netdev(cfg
, ifname
);
21257 if (ndev
== NULL
) {
21258 WL_ERR(("No softAP interface named %s\n", ifname
));
21263 return BCME_BADARG
;
21265 if (rps
->pps
< RADIO_PWRSAVE_PPS_MIN
)
21266 return BCME_BADARG
;
21268 if (rps
->level
< RADIO_PWRSAVE_LEVEL_MIN
||
21269 rps
->level
> RADIO_PWRSAVE_LEVEL_MAX
)
21270 return BCME_BADARG
;
21272 if (rps
->quiet_time
< RADIO_PWRSAVE_QUIETTIME_MIN
)
21273 return BCME_BADARG
;
21275 if (rps
->sta_assoc_check
> RADIO_PWRSAVE_ASSOCCHECK_MAX
||
21276 rps
->sta_assoc_check
< RADIO_PWRSAVE_ASSOCCHECK_MIN
)
21277 return BCME_BADARG
;
21279 cfg
->ap_rps_info
.pps
= rps
->pps
;
21280 cfg
->ap_rps_info
.level
= rps
->level
;
21281 cfg
->ap_rps_info
.quiet_time
= rps
->quiet_time
;
21282 cfg
->ap_rps_info
.sta_assoc_check
= rps
->sta_assoc_check
;
21284 if (cfg
->ap_rps_info
.enable
) {
21285 if (_wl_update_ap_rps_params(ndev
)) {
21286 WL_ERR(("Failed to update rpsnoa params"));
21295 wl_cfg80211_init_ap_rps(struct bcm_cfg80211
*cfg
)
21297 cfg
->ap_rps_info
.enable
= FALSE
;
21298 cfg
->ap_rps_info
.sta_assoc_check
= RADIO_PWRSAVE_STAS_ASSOC_CHECK
;
21299 cfg
->ap_rps_info
.pps
= RADIO_PWRSAVE_PPS
;
21300 cfg
->ap_rps_info
.quiet_time
= RADIO_PWRSAVE_QUIET_TIME
;
21301 cfg
->ap_rps_info
.level
= RADIO_PWRSAVE_LEVEL
;
21303 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
21306 wl_cfg80211_iface_count(struct net_device
*dev
)
21308 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21309 struct net_info
*iter
, *next
;
21310 int iface_count
= 0;
21312 /* Return the count of network interfaces (skip netless p2p discovery
21315 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21316 #pragma GCC diagnostic push
21317 #pragma GCC diagnostic ignored "-Wcast-qual"
21319 for_each_ndev(cfg
, iter
, next
) {
21324 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21325 #pragma GCC diagnostic pop
21327 return iface_count
;
21331 static bool wl_cfg80211_wbtext_check_bssid_list(struct bcm_cfg80211
*cfg
, struct ether_addr
*ea
)
21333 wl_wbtext_bssid_t
*bssid
= NULL
;
21334 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21335 #pragma GCC diagnostic push
21336 #pragma GCC diagnostic ignored "-Wcast-qual"
21339 /* check duplicate */
21340 list_for_each_entry(bssid
, &cfg
->wbtext_bssid_list
, list
) {
21341 if (!memcmp(bssid
->ea
.octet
, ea
, ETHER_ADDR_LEN
)) {
21349 static bool wl_cfg80211_wbtext_add_bssid_list(struct bcm_cfg80211
*cfg
, struct ether_addr
*ea
)
21351 wl_wbtext_bssid_t
*bssid
= NULL
;
21352 char eabuf
[ETHER_ADDR_STR_LEN
];
21354 bssid
= kmalloc(sizeof(wl_wbtext_bssid_t
), GFP_KERNEL
);
21355 if (bssid
== NULL
) {
21356 WL_ERR(("alloc failed\n"));
21360 memcpy(bssid
->ea
.octet
, ea
, ETHER_ADDR_LEN
);
21362 INIT_LIST_HEAD(&bssid
->list
);
21363 list_add_tail(&bssid
->list
, &cfg
->wbtext_bssid_list
);
21365 WL_DBG(("add wbtext bssid : %s\n", bcm_ether_ntoa(ea
, eabuf
)));
21370 static void wl_cfg80211_wbtext_clear_bssid_list(struct bcm_cfg80211
*cfg
)
21372 wl_wbtext_bssid_t
*bssid
= NULL
;
21373 char eabuf
[ETHER_ADDR_STR_LEN
];
21375 while (!list_empty(&cfg
->wbtext_bssid_list
)) {
21376 bssid
= list_entry(cfg
->wbtext_bssid_list
.next
, wl_wbtext_bssid_t
, list
);
21378 WL_DBG(("clear wbtext bssid : %s\n", bcm_ether_ntoa(&bssid
->ea
, eabuf
)));
21379 list_del(&bssid
->list
);
21385 static void wl_cfg80211_wbtext_update_rcc(struct bcm_cfg80211
*cfg
, struct net_device
*dev
)
21387 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
21388 bcm_tlv_t
* cap_ie
= NULL
;
21389 bool req_sent
= FALSE
;
21390 struct wl_profile
*profile
;
21392 WL_DBG(("Enter\n"));
21394 profile
= wl_get_profile_by_netdev(cfg
, dev
);
21396 WL_ERR(("no profile exists\n"));
21400 if (wl_cfg80211_wbtext_check_bssid_list(cfg
,
21401 (struct ether_addr
*)&profile
->bssid
) == FALSE
) {
21402 WL_DBG(("already updated\n"));
21406 /* first, check NBR bit in RRM IE */
21407 if ((cap_ie
= bcm_parse_tlvs(conn_info
->resp_ie
, conn_info
->resp_ie_len
,
21408 DOT11_MNG_RRM_CAP_ID
)) != NULL
) {
21409 if (isset(cap_ie
->data
, DOT11_RRM_CAP_NEIGHBOR_REPORT
)) {
21410 req_sent
= wl_cfg80211_wbtext_send_nbr_req(cfg
, dev
, profile
);
21414 /* if RRM nbr was not supported, check BTM bit in extend cap. IE */
21416 if ((cap_ie
= bcm_parse_tlvs(conn_info
->resp_ie
, conn_info
->resp_ie_len
,
21417 DOT11_MNG_EXT_CAP_ID
)) != NULL
) {
21418 if (cap_ie
->len
>= DOT11_EXTCAP_LEN_BSSTRANS
&&
21419 isset(cap_ie
->data
, DOT11_EXT_CAP_BSSTRANS_MGMT
)) {
21420 wl_cfg80211_wbtext_send_btm_query(cfg
, dev
, profile
);
21426 static bool wl_cfg80211_wbtext_send_nbr_req(struct bcm_cfg80211
*cfg
, struct net_device
*dev
,
21427 struct wl_profile
*profile
)
21430 char *smbuf
= NULL
;
21431 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
21432 bcm_tlv_t
* rrm_cap_ie
= NULL
;
21433 wlc_ssid_t
*ssid
= NULL
;
21436 WL_DBG(("Enter\n"));
21438 /* check RRM nbr bit in extend cap. IE of assoc response */
21439 if ((rrm_cap_ie
= bcm_parse_tlvs(conn_info
->resp_ie
, conn_info
->resp_ie_len
,
21440 DOT11_MNG_RRM_CAP_ID
)) != NULL
) {
21441 if (!isset(rrm_cap_ie
->data
, DOT11_RRM_CAP_NEIGHBOR_REPORT
)) {
21442 WL_DBG(("AP doesn't support neighbor report\n"));
21447 smbuf
= (char *) kmalloc(WLC_IOCTL_MAXLEN
, GFP_KERNEL
);
21448 if (smbuf
== NULL
) {
21449 WL_ERR(("failed to allocated memory\n"));
21453 ssid
= (wlc_ssid_t
*) kzalloc(sizeof(wlc_ssid_t
), GFP_KERNEL
);
21454 if (ssid
== NULL
) {
21455 WL_ERR(("failed to allocated memory\n"));
21459 ssid
->SSID_len
= MIN(profile
->ssid
.SSID_len
, DOT11_MAX_SSID_LEN
);
21460 memcpy(ssid
->SSID
, profile
->ssid
.SSID
, ssid
->SSID_len
);
21462 error
= wldev_iovar_setbuf(dev
, "rrm_nbr_req", ssid
,
21463 sizeof(wlc_ssid_t
), smbuf
, WLC_IOCTL_MAXLEN
, NULL
);
21464 if (error
== BCME_OK
) {
21465 ret
= wl_cfg80211_wbtext_add_bssid_list(cfg
,
21466 (struct ether_addr
*)&profile
->bssid
);
21468 WL_ERR(("failed to send neighbor report request, error=%d\n", error
));
21482 static bool wl_cfg80211_wbtext_send_btm_query(struct bcm_cfg80211
*cfg
, struct net_device
*dev
,
21483 struct wl_profile
*profile
)
21489 WL_DBG(("Enter\n"));
21491 error
= wldev_iovar_setbuf(dev
, "wnm_bsstrans_query", NULL
,
21492 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
);
21493 if (error
== BCME_OK
) {
21494 ret
= wl_cfg80211_wbtext_add_bssid_list(cfg
,
21495 (struct ether_addr
*)&profile
->bssid
);
21497 WL_ERR(("%s: failed to set BTM query, error=%d\n", __FUNCTION__
, error
));
21502 static void wl_cfg80211_wbtext_set_wnm_maxidle(struct bcm_cfg80211
*cfg
, struct net_device
*dev
)
21504 keepalives_max_idle_t keepalive
= {0, 0, 0, 0};
21506 int wnm_maxidle
= 0;
21507 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
21509 /* AP supports wnm max idle ? */
21510 if (bcm_parse_tlvs(conn_info
->resp_ie
, conn_info
->resp_ie_len
,
21511 DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID
) != NULL
) {
21512 error
= wldev_iovar_getint(dev
, "wnm_maxidle", &wnm_maxidle
);
21514 WL_ERR(("failed to get wnm max idle period : %d\n", error
));
21518 WL_DBG(("wnm max idle period : %d\n", wnm_maxidle
));
21520 /* if wnm maxidle has valid period, set it as keep alive */
21521 if (wnm_maxidle
> 0) {
21522 keepalive
.keepalive_count
= 1;
21525 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) >= 0) {
21526 error
= wldev_iovar_setbuf_bsscfg(dev
, "wnm_keepalives_max_idle", &keepalive
,
21527 sizeof(keepalives_max_idle_t
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
21528 bssidx
, &cfg
->ioctl_buf_sync
);
21530 WL_ERR(("set wnm_keepalives_max_idle failed : %d\n", error
));
21536 wl_cfg80211_recv_nbr_resp(struct net_device
*dev
, uint8
*body
, int body_len
)
21538 dot11_rm_action_t
*rm_rep
;
21540 int tlv_len
, i
, error
;
21541 dot11_neighbor_rep_ie_t
*nbr_rep_ie
;
21543 wl_roam_channel_list_t channel_list
;
21544 char iobuf
[WLC_IOCTL_SMLEN
];
21546 if (body_len
< DOT11_RM_ACTION_LEN
) {
21547 WL_ERR(("Received Neighbor Report frame with incorrect length %d\n",
21552 rm_rep
= (dot11_rm_action_t
*)body
;
21553 WL_DBG(("received neighbor report (token = %d)\n", rm_rep
->token
));
21555 tlvs
= (bcm_tlv_t
*)&rm_rep
->data
[0];
21557 tlv_len
= body_len
- DOT11_RM_ACTION_LEN
;
21559 while (tlvs
&& tlvs
->id
== DOT11_MNG_NEIGHBOR_REP_ID
) {
21560 nbr_rep_ie
= (dot11_neighbor_rep_ie_t
*)tlvs
;
21562 if (nbr_rep_ie
->len
< DOT11_NEIGHBOR_REP_IE_FIXED_LEN
) {
21563 WL_ERR(("malformed Neighbor Report element with length %d\n",
21565 tlvs
= bcm_next_tlv(tlvs
, &tlv_len
);
21569 ch
= CH20MHZ_CHSPEC(nbr_rep_ie
->channel
);
21570 WL_DBG(("ch:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x\n",
21571 ch
, nbr_rep_ie
->bssid
.octet
[0], nbr_rep_ie
->bssid
.octet
[1],
21572 nbr_rep_ie
->bssid
.octet
[2], nbr_rep_ie
->bssid
.octet
[3],
21573 nbr_rep_ie
->bssid
.octet
[4], nbr_rep_ie
->bssid
.octet
[5]));
21576 error
= wldev_iovar_getbuf(dev
, "roamscan_channels", 0, 0,
21577 (void *)&channel_list
, sizeof(channel_list
), NULL
);
21579 WL_ERR(("Failed to get roamscan channels, error = %d\n", error
));
21584 if (channel_list
.n
< MAX_ROAM_CHANNEL
) {
21585 for (i
= 0; i
< channel_list
.n
; i
++) {
21586 if (channel_list
.channels
[i
] == ch
) {
21590 if (i
== channel_list
.n
) {
21591 channel_list
.channels
[channel_list
.n
] = ch
;
21597 error
= wldev_iovar_setbuf(dev
, "roamscan_channels", &channel_list
,
21598 sizeof(channel_list
), iobuf
, sizeof(iobuf
), NULL
);
21600 WL_DBG(("Failed to set roamscan channels, error = %d\n", error
));
21603 tlvs
= bcm_next_tlv(tlvs
, &tlv_len
);
21608 #endif /* WBTEXT */
21610 #ifdef SUPPORT_SET_CAC
21612 wl_cfg80211_set_cac(struct bcm_cfg80211
*cfg
, int enable
)
21615 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
21617 WL_DBG(("cac enable %d, op_mode 0x%04x\n", enable
, dhd
->op_mode
));
21619 WL_ERR(("dhd is NULL\n"));
21622 if (enable
&& ((dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
) ||
21623 (dhd
->op_mode
& DHD_FLAG_P2P_GC_MODE
) ||
21624 (dhd
->op_mode
& DHD_FLAG_P2P_GO_MODE
))) {
21625 WL_ERR(("op_mode 0x%04x\n", dhd
->op_mode
));
21628 if ((ret
= dhd_wl_ioctl_set_intiovar(dhd
, "cac", enable
,
21629 WLC_SET_VAR
, TRUE
, 0)) < 0) {
21630 WL_ERR(("Failed set CAC, ret=%d\n", ret
));
21632 WL_DBG(("CAC set successfully\n"));
21636 #endif /* SUPPORT_SET_CAC */
21638 #ifdef SUPPORT_RSSI_LOGGING
21640 wl_get_rssi_per_ant(struct net_device
*dev
, char *ifname
, char *peer_mac
, void *param
)
21642 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21643 wl_rssi_ant_mimo_t
*get_param
= (wl_rssi_ant_mimo_t
*)param
;
21644 rssi_ant_param_t
*set_param
= NULL
;
21645 struct net_device
*ifdev
= NULL
;
21646 char iobuf
[WLC_IOCTL_SMLEN
];
21650 memset(iobuf
, 0, WLC_IOCTL_SMLEN
);
21652 /* Check the interface type */
21653 ifdev
= wl_get_netdev_by_name(cfg
, ifname
);
21654 if (ifdev
== NULL
) {
21655 WL_ERR(("Could not find net_device for ifname:%s\n", ifname
));
21660 iftype
= ifdev
->ieee80211_ptr
->iftype
;
21661 if (iftype
== NL80211_IFTYPE_AP
|| iftype
== NL80211_IFTYPE_P2P_GO
) {
21663 set_param
= (rssi_ant_param_t
*)kzalloc(sizeof(rssi_ant_param_t
),
21665 err
= wl_cfg80211_ether_atoe(peer_mac
, &set_param
->ea
);
21667 WL_ERR(("Invalid Peer MAC format\n"));
21672 WL_ERR(("Peer MAC is not provided for iftype %d\n", iftype
));
21678 err
= wldev_iovar_getbuf(ifdev
, "phy_rssi_ant", peer_mac
?
21679 (void *)&(set_param
->ea
) : NULL
, peer_mac
? ETHER_ADDR_LEN
: 0,
21680 (void *)iobuf
, sizeof(iobuf
), NULL
);
21681 if (unlikely(err
)) {
21682 WL_ERR(("Failed to get rssi info, err=%d\n", err
));
21684 memcpy(get_param
, iobuf
, sizeof(wl_rssi_ant_mimo_t
));
21685 if (get_param
->count
== 0) {
21686 WL_ERR(("Not supported on this chip\n"));
21687 err
= BCME_UNSUPPORTED
;
21700 wl_get_rssi_logging(struct net_device
*dev
, void *param
)
21702 rssilog_get_param_t
*get_param
= (rssilog_get_param_t
*)param
;
21703 char iobuf
[WLC_IOCTL_SMLEN
];
21706 memset(iobuf
, 0, WLC_IOCTL_SMLEN
);
21707 memset(get_param
, 0, sizeof(*get_param
));
21708 err
= wldev_iovar_getbuf(dev
, "rssilog", NULL
, 0, (void *)iobuf
,
21709 sizeof(iobuf
), NULL
);
21711 WL_ERR(("Failed to get rssi logging info, err=%d\n", err
));
21713 memcpy(get_param
, iobuf
, sizeof(*get_param
));
21720 wl_set_rssi_logging(struct net_device
*dev
, void *param
)
21722 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21723 rssilog_set_param_t
*set_param
= (rssilog_set_param_t
*)param
;
21726 err
= wldev_iovar_setbuf(dev
, "rssilog", set_param
,
21727 sizeof(*set_param
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
21728 &cfg
->ioctl_buf_sync
);
21730 WL_ERR(("Failed to set rssi logging param, err=%d\n", err
));
21735 #endif /* SUPPORT_RSSI_LOGGING */
21738 wl_cfg80211_autochannel(struct net_device
*dev
, char* command
, int total_len
)
21740 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21742 int bytes_written
= -1;
21744 sscanf(command
, "%*s %d", &cfg
->autochannel
);
21746 if (cfg
->autochannel
== 0) {
21747 cfg
->best_2g_ch
= 0;
21748 cfg
->best_5g_ch
= 0;
21749 } else if (cfg
->autochannel
== 2) {
21750 bytes_written
= snprintf(command
, total_len
, "2g=%d 5g=%d",
21751 cfg
->best_2g_ch
, cfg
->best_5g_ch
);
21752 ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__
, command
));
21753 ret
= bytes_written
;
21760 wl_cfg80211_check_in4way(struct bcm_cfg80211
*cfg
,
21761 struct net_device
*dev
, uint action
, enum wl_ext_status status
, void *context
)
21763 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
21764 struct wl_security
*sec
;
21767 int max_wait_gc_time
= dhdp
->conf
->max_wait_gc_time
;
21769 if (!(dhdp
->conf
->in4way
& action
))
21772 mutex_lock(&cfg
->in4way_sync
);
21773 WL_DBG(("status=%d, action=0x%x\n", status
, action
));
21776 case WL_EXT_STATUS_SCAN
:
21777 if (action
& (NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
)) {
21778 if (cfg
->handshaking
> 0 && cfg
->handshaking
<= 3) {
21779 WL_ERR(("%s: return -EBUSY cnt %d\n",
21780 __FUNCTION__
, cfg
->handshaking
));
21781 cfg
->handshaking
++;
21787 case WL_EXT_STATUS_CONNECTING
:
21788 if (action
& (NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
)) {
21789 bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
);
21790 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
21791 if ((sec
->wpa_versions
& (NL80211_WPA_VERSION_1
| NL80211_WPA_VERSION_2
)) &&
21793 cfg
->handshaking
= 1;
21794 if (action
& NO_BTC_IN4WAY
)
21795 wldev_iovar_setint(dev
, "btc_mode", 0);
21799 case WL_EXT_STATUS_DELETE_GC
:
21800 if ((action
& DONT_DELETE_GC_AFTER_WPS
) &&
21801 (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
)) {
21802 u8
* mac_addr
= context
;
21803 if (memcmp(ðer_bcast
, mac_addr
, ETHER_ADDR_LEN
) &&
21804 dhdp
->conf
->eapol_status
== EAPOL_STATUS_WPS_DONE
) {
21806 WL_TRACE(("status=%d, wps_done=%d, waiting %dms ...\n",
21807 status
, cfg
->wps_done
, max_wait_gc_time
));
21808 mutex_unlock(&cfg
->in4way_sync
);
21809 timeout
= wait_event_interruptible_timeout(cfg
->wps_done_event
,
21810 cfg
->wps_done
, msecs_to_jiffies(max_wait_gc_time
));
21811 mutex_lock(&cfg
->in4way_sync
);
21812 WL_TRACE(("status=%d, wps_done=%d, timeout=%d\n",
21813 status
, cfg
->wps_done
, timeout
));
21819 WL_TRACE(("status=%d, wps_done=%d => 0\n", status
, cfg
->wps_done
));
21820 cfg
->wps_done
= FALSE
;
21821 dhdp
->conf
->eapol_status
= EAPOL_STATUS_NONE
;
21825 case WL_EXT_STATUS_GC_DISCONNECTED
:
21826 if ((action
& DONT_DELETE_GC_AFTER_WPS
) &&
21827 (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
) &&
21828 dhdp
->conf
->eapol_status
== EAPOL_STATUS_WPS_DONE
) {
21829 WL_TRACE(("status=%d, wps_done=%d => 0\n", status
, cfg
->wps_done
));
21830 cfg
->wps_done
= FALSE
;
21833 case WL_EXT_STATUS_GC_CONNECTED
:
21834 if ((action
& DONT_DELETE_GC_AFTER_WPS
) &&
21835 (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
) &&
21836 dhdp
->conf
->eapol_status
== EAPOL_STATUS_WPS_DONE
) {
21837 WL_TRACE(("status=%d, wps_done=%d => 1\n", status
, cfg
->wps_done
));
21838 cfg
->wps_done
= TRUE
;
21839 wake_up_interruptible(&cfg
->wps_done_event
);
21842 case WL_EXT_STATUS_DISCONNECTED
:
21843 case WL_EXT_STATUS_4WAY_DONE
:
21844 if (action
& (NO_SCAN_IN4WAY
|NO_BTC_IN4WAY
)) {
21845 if (cfg
->handshaking
) {
21846 if (action
& NO_BTC_IN4WAY
)
21847 wldev_iovar_setint(dev
, "btc_mode", 1);
21848 cfg
->handshaking
= 0;
21853 WL_ERR(("Unknown action=0x%x, status=%d\n", action
, status
));
21856 mutex_unlock(&cfg
->in4way_sync
);