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 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 */
917 extern int passive_channel_skip
;
920 wl_ap_start_ind(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
921 const wl_event_msg_t
*e
, void *data
);
923 wl_csa_complete_ind(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
924 const wl_event_msg_t
*e
, void *data
);
925 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, \
933 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
934 #define CFG80211_PUT_BSS(wiphy, bss) cfg80211_put_bss(wiphy, bss);
936 #define CFG80211_PUT_BSS(wiphy, bss) cfg80211_put_bss(bss);
937 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
939 #define CHAN2G(_channel, _freq, _flags) { \
940 .band = IEEE80211_BAND_2GHZ, \
941 .center_freq = (_freq), \
942 .hw_value = (_channel), \
944 .max_antenna_gain = 0, \
948 #define CHAN5G(_channel, _flags) { \
949 .band = IEEE80211_BAND_5GHZ, \
950 .center_freq = 5000 + (5 * (_channel)), \
951 .hw_value = (_channel), \
953 .max_antenna_gain = 0, \
957 #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
958 #define RATETAB_ENT(_rateid, _flags) \
960 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
961 .hw_value = (_rateid), \
965 static struct ieee80211_rate __wl_rates
[] = {
966 RATETAB_ENT(DOT11_RATE_1M
, 0),
967 RATETAB_ENT(DOT11_RATE_2M
, IEEE80211_RATE_SHORT_PREAMBLE
),
968 RATETAB_ENT(DOT11_RATE_5M5
, IEEE80211_RATE_SHORT_PREAMBLE
),
969 RATETAB_ENT(DOT11_RATE_11M
, IEEE80211_RATE_SHORT_PREAMBLE
),
970 RATETAB_ENT(DOT11_RATE_6M
, 0),
971 RATETAB_ENT(DOT11_RATE_9M
, 0),
972 RATETAB_ENT(DOT11_RATE_12M
, 0),
973 RATETAB_ENT(DOT11_RATE_18M
, 0),
974 RATETAB_ENT(DOT11_RATE_24M
, 0),
975 RATETAB_ENT(DOT11_RATE_36M
, 0),
976 RATETAB_ENT(DOT11_RATE_48M
, 0),
977 RATETAB_ENT(DOT11_RATE_54M
, 0)
980 #define wl_a_rates (__wl_rates + 4)
981 #define wl_a_rates_size 8
982 #define wl_g_rates (__wl_rates + 0)
983 #define wl_g_rates_size 12
985 static struct ieee80211_channel __wl_2ghz_channels
[] = {
1002 static struct ieee80211_channel __wl_5ghz_a_channels
[] = {
1003 CHAN5G(34, 0), CHAN5G(36, 0),
1004 CHAN5G(38, 0), CHAN5G(40, 0),
1005 CHAN5G(42, 0), CHAN5G(44, 0),
1006 CHAN5G(46, 0), CHAN5G(48, 0),
1007 CHAN5G(52, 0), CHAN5G(56, 0),
1008 CHAN5G(60, 0), CHAN5G(64, 0),
1009 CHAN5G(100, 0), CHAN5G(104, 0),
1010 CHAN5G(108, 0), CHAN5G(112, 0),
1011 CHAN5G(116, 0), CHAN5G(120, 0),
1012 CHAN5G(124, 0), CHAN5G(128, 0),
1013 CHAN5G(132, 0), CHAN5G(136, 0),
1014 CHAN5G(140, 0), CHAN5G(144, 0),
1015 CHAN5G(149, 0), CHAN5G(153, 0),
1016 CHAN5G(157, 0), CHAN5G(161, 0),
1020 static struct ieee80211_supported_band __wl_band_2ghz
= {
1021 .band
= IEEE80211_BAND_2GHZ
,
1022 .channels
= __wl_2ghz_channels
,
1023 .n_channels
= ARRAY_SIZE(__wl_2ghz_channels
),
1024 .bitrates
= wl_g_rates
,
1025 .n_bitrates
= wl_g_rates_size
1028 static struct ieee80211_supported_band __wl_band_5ghz_a
= {
1029 .band
= IEEE80211_BAND_5GHZ
,
1030 .channels
= __wl_5ghz_a_channels
,
1031 .n_channels
= ARRAY_SIZE(__wl_5ghz_a_channels
),
1032 .bitrates
= wl_a_rates
,
1033 .n_bitrates
= wl_a_rates_size
1036 static const u32 __wl_cipher_suites
[] = {
1037 WLAN_CIPHER_SUITE_WEP40
,
1038 WLAN_CIPHER_SUITE_WEP104
,
1039 WLAN_CIPHER_SUITE_TKIP
,
1040 WLAN_CIPHER_SUITE_CCMP
,
1043 * Advertising AES_CMAC cipher suite to userspace would imply that we
1044 * are supporting MFP. So advertise only when MFP support is enabled.
1046 WLAN_CIPHER_SUITE_AES_CMAC
,
1050 #ifdef WL_SUPPORT_ACS
1052 * The firmware code required for this feature to work is currently under
1053 * BCMINTERNAL flag. In future if this is to enabled we need to bring the
1054 * required firmware code out of the BCMINTERNAL flag.
1056 struct wl_dump_survey
{
1064 #endif /* WL_SUPPORT_ACS */
1067 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
1068 static int maxrxpktglom
= 0;
1071 /* IOCtl version read from targeted driver */
1073 #ifdef DEBUGFS_CFG80211
1074 #define S_SUBLOGLEVEL 20
1075 static const struct {
1078 } sublogname_map
[] = {
1079 {WL_DBG_ERR
, "ERR"},
1080 {WL_DBG_INFO
, "INFO"},
1081 {WL_DBG_DBG
, "DBG"},
1082 {WL_DBG_SCAN
, "SCAN"},
1083 {WL_DBG_TRACE
, "TRACE"},
1084 {WL_DBG_P2P_ACTION
, "P2PACTION"}
1088 #ifdef CUSTOMER_HW4_DEBUG
1089 uint prev_dhd_console_ms
= 0;
1090 u32 prev_wl_dbg_level
= 0;
1091 bool wl_scan_timeout_dbg_enabled
= 0;
1092 static void wl_scan_timeout_dbg_set(void);
1093 static void wl_scan_timeout_dbg_clear(void);
1095 static void wl_scan_timeout_dbg_set(void)
1097 WL_ERR(("Enter \n"));
1098 prev_dhd_console_ms
= dhd_console_ms
;
1099 prev_wl_dbg_level
= wl_dbg_level
;
1102 wl_dbg_level
|= (WL_DBG_ERR
| WL_DBG_P2P_ACTION
| WL_DBG_SCAN
);
1104 wl_scan_timeout_dbg_enabled
= 1;
1106 static void wl_scan_timeout_dbg_clear(void)
1108 WL_ERR(("Enter \n"));
1109 dhd_console_ms
= prev_dhd_console_ms
;
1110 wl_dbg_level
= prev_wl_dbg_level
;
1112 wl_scan_timeout_dbg_enabled
= 0;
1114 #endif /* CUSTOMER_HW4_DEBUG */
1116 /* watchdog timer for disconnecting when fw is not associated for FW_ASSOC_WATCHDOG_TIME ms */
1117 uint32 fw_assoc_watchdog_ms
= 0;
1118 bool fw_assoc_watchdog_started
= 0;
1119 #define FW_ASSOC_WATCHDOG_TIME 10 * 1000 /* msec */
1121 static void wl_add_remove_pm_enable_work(struct bcm_cfg80211
*cfg
,
1122 enum wl_pm_workq_act_type type
)
1124 u16 wq_duration
= 0;
1125 dhd_pub_t
*dhd
= NULL
;
1130 dhd
= (dhd_pub_t
*)(cfg
->pub
);
1132 mutex_lock(&cfg
->pm_sync
);
1134 * Make cancel and schedule work part mutually exclusive
1135 * so that while cancelling, we are sure that there is no
1136 * work getting scheduled.
1138 if (delayed_work_pending(&cfg
->pm_enable_work
)) {
1139 cancel_delayed_work_sync(&cfg
->pm_enable_work
);
1140 DHD_PM_WAKE_UNLOCK(cfg
->pub
);
1143 if (type
== WL_PM_WORKQ_SHORT
) {
1144 wq_duration
= WL_PM_ENABLE_TIMEOUT
;
1145 } else if (type
== WL_PM_WORKQ_LONG
) {
1146 wq_duration
= (WL_PM_ENABLE_TIMEOUT
*2);
1149 /* It should schedule work item only if driver is up */
1150 if (wq_duration
&& dhd
->up
) {
1151 if (schedule_delayed_work(&cfg
->pm_enable_work
,
1152 msecs_to_jiffies((const unsigned int)wq_duration
))) {
1153 DHD_PM_WAKE_LOCK_TIMEOUT(cfg
->pub
, wq_duration
);
1155 WL_ERR(("Can't schedule pm work handler\n"));
1158 mutex_unlock(&cfg
->pm_sync
);
1161 /* Return a new chanspec given a legacy chanspec
1162 * Returns INVCHANSPEC on error
1165 wl_chspec_from_legacy(chanspec_t legacy_chspec
)
1169 /* get the channel number */
1170 chspec
= LCHSPEC_CHANNEL(legacy_chspec
);
1172 /* convert the band */
1173 if (LCHSPEC_IS2G(legacy_chspec
)) {
1174 chspec
|= WL_CHANSPEC_BAND_2G
;
1176 chspec
|= WL_CHANSPEC_BAND_5G
;
1179 /* convert the bw and sideband */
1180 if (LCHSPEC_IS20(legacy_chspec
)) {
1181 chspec
|= WL_CHANSPEC_BW_20
;
1183 chspec
|= WL_CHANSPEC_BW_40
;
1184 if (LCHSPEC_CTL_SB(legacy_chspec
) == WL_LCHANSPEC_CTL_SB_LOWER
) {
1185 chspec
|= WL_CHANSPEC_CTL_SB_L
;
1187 chspec
|= WL_CHANSPEC_CTL_SB_U
;
1191 if (wf_chspec_malformed(chspec
)) {
1192 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
1200 /* Return a legacy chanspec given a new chanspec
1201 * Returns INVCHANSPEC on error
1204 wl_chspec_to_legacy(chanspec_t chspec
)
1208 if (wf_chspec_malformed(chspec
)) {
1209 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
1214 /* get the channel number */
1215 lchspec
= CHSPEC_CHANNEL(chspec
);
1217 /* convert the band */
1218 if (CHSPEC_IS2G(chspec
)) {
1219 lchspec
|= WL_LCHANSPEC_BAND_2G
;
1221 lchspec
|= WL_LCHANSPEC_BAND_5G
;
1224 /* convert the bw and sideband */
1225 if (CHSPEC_IS20(chspec
)) {
1226 lchspec
|= WL_LCHANSPEC_BW_20
;
1227 lchspec
|= WL_LCHANSPEC_CTL_SB_NONE
;
1228 } else if (CHSPEC_IS40(chspec
)) {
1229 lchspec
|= WL_LCHANSPEC_BW_40
;
1230 if (CHSPEC_CTL_SB(chspec
) == WL_CHANSPEC_CTL_SB_L
) {
1231 lchspec
|= WL_LCHANSPEC_CTL_SB_LOWER
;
1233 lchspec
|= WL_LCHANSPEC_CTL_SB_UPPER
;
1236 /* cannot express the bandwidth */
1237 char chanbuf
[CHANSPEC_STR_LEN
];
1239 "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
1240 "to pre-11ac format\n",
1241 wf_chspec_ntoa(chspec
, chanbuf
), chspec
));
1248 /* given a chanspec value, do the endian and chanspec version conversion to
1249 * a chanspec_t value
1250 * Returns INVCHANSPEC on error
1253 wl_chspec_host_to_driver(chanspec_t chanspec
)
1255 if (ioctl_version
== 1) {
1256 chanspec
= wl_chspec_to_legacy(chanspec
);
1257 if (chanspec
== INVCHANSPEC
) {
1261 chanspec
= htodchanspec(chanspec
);
1266 /* given a channel value, do the endian and chanspec version conversion to
1267 * a chanspec_t value
1268 * Returns INVCHANSPEC on error
1271 wl_ch_host_to_driver(struct bcm_cfg80211
*cfg
, s32 bssidx
, u16 channel
)
1273 chanspec_t chanspec
;
1275 chanspec
= channel
& WL_CHANSPEC_CHAN_MASK
;
1277 if (channel
<= CH_MAX_2G_CHANNEL
)
1278 chanspec
|= WL_CHANSPEC_BAND_2G
;
1280 chanspec
|= WL_CHANSPEC_BAND_5G
;
1282 chanspec
|= wl_cfg80211_ulb_get_min_bw_chspec(cfg
, NULL
, bssidx
);
1284 chanspec
|= WL_CHANSPEC_CTL_SB_NONE
;
1286 return wl_chspec_host_to_driver(chanspec
);
1289 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
1290 * a chanspec_t value
1291 * Returns INVCHANSPEC on error
1294 wl_chspec_driver_to_host(chanspec_t chanspec
)
1296 chanspec
= dtohchanspec(chanspec
);
1297 if (ioctl_version
== 1) {
1298 chanspec
= wl_chspec_from_legacy(chanspec
);
1305 * convert ASCII string to MAC address (colon-delimited format)
1306 * eg: 00:11:22:33:44:55
1309 wl_cfg80211_ether_atoe(const char *a
, struct ether_addr
*n
)
1314 memset(n
, 0, ETHER_ADDR_LEN
);
1316 n
->octet
[count
++] = (uint8
)simple_strtoul(a
, &c
, 16);
1317 if (!*c
++ || count
== ETHER_ADDR_LEN
)
1321 return (count
== ETHER_ADDR_LEN
);
1324 /* There isn't a lot of sense in it, but you can transmit anything you like */
1325 static const struct ieee80211_txrx_stypes
1326 wl_cfg80211_default_mgmt_stypes
[NUM_NL80211_IFTYPES
] = {
1328 [NL80211_IFTYPE_MESH_POINT
] = {
1330 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4) |
1331 BIT(IEEE80211_STYPE_AUTH
>> 4)
1334 [NL80211_IFTYPE_ADHOC
] = {
1336 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4)
1338 [NL80211_IFTYPE_STATION
] = {
1340 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4) |
1341 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4)
1343 [NL80211_IFTYPE_AP
] = {
1345 .rx
= BIT(IEEE80211_STYPE_ASSOC_REQ
>> 4) |
1346 BIT(IEEE80211_STYPE_REASSOC_REQ
>> 4) |
1347 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4) |
1348 BIT(IEEE80211_STYPE_DISASSOC
>> 4) |
1349 BIT(IEEE80211_STYPE_AUTH
>> 4) |
1350 BIT(IEEE80211_STYPE_DEAUTH
>> 4) |
1351 BIT(IEEE80211_STYPE_ACTION
>> 4)
1353 [NL80211_IFTYPE_AP_VLAN
] = {
1356 .rx
= BIT(IEEE80211_STYPE_ASSOC_REQ
>> 4) |
1357 BIT(IEEE80211_STYPE_REASSOC_REQ
>> 4) |
1358 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4) |
1359 BIT(IEEE80211_STYPE_DISASSOC
>> 4) |
1360 BIT(IEEE80211_STYPE_AUTH
>> 4) |
1361 BIT(IEEE80211_STYPE_DEAUTH
>> 4) |
1362 BIT(IEEE80211_STYPE_ACTION
>> 4)
1364 [NL80211_IFTYPE_P2P_CLIENT
] = {
1366 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4) |
1367 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4)
1369 [NL80211_IFTYPE_P2P_GO
] = {
1371 .rx
= BIT(IEEE80211_STYPE_ASSOC_REQ
>> 4) |
1372 BIT(IEEE80211_STYPE_REASSOC_REQ
>> 4) |
1373 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4) |
1374 BIT(IEEE80211_STYPE_DISASSOC
>> 4) |
1375 BIT(IEEE80211_STYPE_AUTH
>> 4) |
1376 BIT(IEEE80211_STYPE_DEAUTH
>> 4) |
1377 BIT(IEEE80211_STYPE_ACTION
>> 4)
1379 #if defined(WL_CFG80211_P2P_DEV_IF)
1380 [NL80211_IFTYPE_P2P_DEVICE
] = {
1382 .rx
= BIT(IEEE80211_STYPE_ACTION
>> 4) |
1383 BIT(IEEE80211_STYPE_PROBE_REQ
>> 4)
1385 #endif /* WL_CFG80211_P2P_DEV_IF */
1388 static void swap_key_from_BE(struct wl_wsec_key
*key
)
1390 key
->index
= htod32(key
->index
);
1391 key
->len
= htod32(key
->len
);
1392 key
->algo
= htod32(key
->algo
);
1393 key
->flags
= htod32(key
->flags
);
1394 key
->rxiv
.hi
= htod32(key
->rxiv
.hi
);
1395 key
->rxiv
.lo
= htod16(key
->rxiv
.lo
);
1396 key
->iv_initialized
= htod32(key
->iv_initialized
);
1399 static void swap_key_to_BE(struct wl_wsec_key
*key
)
1401 key
->index
= dtoh32(key
->index
);
1402 key
->len
= dtoh32(key
->len
);
1403 key
->algo
= dtoh32(key
->algo
);
1404 key
->flags
= dtoh32(key
->flags
);
1405 key
->rxiv
.hi
= dtoh32(key
->rxiv
.hi
);
1406 key
->rxiv
.lo
= dtoh16(key
->rxiv
.lo
);
1407 key
->iv_initialized
= dtoh32(key
->iv_initialized
);
1410 /* Dump the contents of the encoded wps ie buffer and get pbc value */
1412 wl_validate_wps_ie(char *wps_ie
, s32 wps_ie_len
, bool *pbc
)
1414 #define WPS_IE_FIXED_LEN 6
1420 u8
*valptr
= (uint8
*) &val
;
1421 if (wps_ie
== NULL
|| wps_ie_len
< WPS_IE_FIXED_LEN
) {
1422 WL_ERR(("invalid argument : NULL\n"));
1425 len
= (s16
)wps_ie
[TLV_LEN_OFF
];
1427 if (len
> wps_ie_len
) {
1428 WL_ERR(("invalid length len %d, wps ie len %d\n", len
, wps_ie_len
));
1431 WL_DBG(("wps_ie len=%d\n", len
));
1432 len
-= 4; /* for the WPS IE's OUI, oui_type fields */
1433 subel
= wps_ie
+ WPS_IE_FIXED_LEN
;
1434 while (len
>= 4) { /* must have attr id, attr len fields */
1435 valptr
[0] = *subel
++;
1436 valptr
[1] = *subel
++;
1437 subelt_id
= HTON16(val
);
1439 valptr
[0] = *subel
++;
1440 valptr
[1] = *subel
++;
1441 subelt_len
= HTON16(val
);
1443 len
-= 4; /* for the attr id, attr len fields */
1444 len
-= (s16
)subelt_len
; /* for the remaining fields in this attribute */
1448 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1449 subel
, subelt_id
, subelt_len
));
1451 if (subelt_id
== WPS_ID_VERSION
) {
1452 WL_DBG((" attr WPS_ID_VERSION: %u\n", *subel
));
1453 } else if (subelt_id
== WPS_ID_REQ_TYPE
) {
1454 WL_DBG((" attr WPS_ID_REQ_TYPE: %u\n", *subel
));
1455 } else if (subelt_id
== WPS_ID_CONFIG_METHODS
) {
1457 valptr
[1] = *(subel
+ 1);
1458 WL_DBG((" attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val
)));
1459 } else if (subelt_id
== WPS_ID_DEVICE_NAME
) {
1461 int namelen
= MIN(subelt_len
, (sizeof(devname
) - 1));
1464 memcpy(devname
, subel
, namelen
);
1465 devname
[namelen
] = '\0';
1466 /* Printing len as rx'ed in the IE */
1467 WL_DBG((" attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1468 devname
, subelt_len
));
1470 } else if (subelt_id
== WPS_ID_DEVICE_PWD_ID
) {
1472 valptr
[1] = *(subel
+ 1);
1473 WL_DBG((" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val
)));
1474 *pbc
= (HTON16(val
) == DEV_PW_PUSHBUTTON
) ? true : false;
1475 } else if (subelt_id
== WPS_ID_PRIM_DEV_TYPE
) {
1477 valptr
[1] = *(subel
+ 1);
1478 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val
)));
1479 valptr
[0] = *(subel
+ 6);
1480 valptr
[1] = *(subel
+ 7);
1481 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val
)));
1482 } else if (subelt_id
== WPS_ID_REQ_DEV_TYPE
) {
1484 valptr
[1] = *(subel
+ 1);
1485 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val
)));
1486 valptr
[0] = *(subel
+ 6);
1487 valptr
[1] = *(subel
+ 7);
1488 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val
)));
1489 } else if (subelt_id
== WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS
) {
1491 valptr
[1] = *(subel
+ 1);
1492 WL_DBG((" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1493 ": cat=%u\n", HTON16(val
)));
1495 WL_DBG((" unknown attr 0x%x\n", subelt_id
));
1498 subel
+= subelt_len
;
1502 s32
wl_set_tx_power(struct net_device
*dev
,
1503 enum nl80211_tx_power_setting type
, s32 dbm
)
1508 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
1510 /* Make sure radio is off or on as far as software is concerned */
1511 disable
= WL_RADIO_SW_DISABLE
<< 16;
1512 disable
= htod32(disable
);
1513 err
= wldev_ioctl_set(dev
, WLC_SET_RADIO
, &disable
, sizeof(disable
));
1514 if (unlikely(err
)) {
1515 WL_ERR(("WLC_SET_RADIO error (%d)\n", err
));
1521 txpwrqdbm
= dbm
* 4;
1522 err
= wldev_iovar_setbuf_bsscfg(dev
, "qtxpower", (void *)&txpwrqdbm
,
1523 sizeof(txpwrqdbm
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, 0,
1524 &cfg
->ioctl_buf_sync
);
1526 WL_ERR(("qtxpower error (%d)\n", err
));
1528 WL_ERR(("dBm=%d, txpwrqdbm=0x%x\n", dbm
, txpwrqdbm
));
1533 s32
wl_get_tx_power(struct net_device
*dev
, s32
*dbm
)
1537 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
1539 err
= wldev_iovar_getbuf_bsscfg(dev
, "qtxpower",
1540 NULL
, 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, 0, &cfg
->ioctl_buf_sync
);
1541 if (unlikely(err
)) {
1542 WL_ERR(("error (%d)\n", err
));
1546 memcpy(&txpwrdbm
, cfg
->ioctl_buf
, sizeof(txpwrdbm
));
1547 txpwrdbm
= dtoh32(txpwrdbm
);
1548 *dbm
= (txpwrdbm
& ~WL_TXPWR_OVERRIDE
) / 4;
1550 WL_INFORM(("dBm=%d, txpwrdbm=0x%x\n", *dbm
, txpwrdbm
));
1555 static chanspec_t
wl_cfg80211_get_shared_freq(struct wiphy
*wiphy
)
1558 int cur_band
, err
= 0;
1559 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1560 struct net_device
*dev
= bcmcfg_to_prmry_ndev(cfg
);
1561 struct ether_addr bssid
;
1562 struct wl_bss_info
*bss
= NULL
;
1563 s32 bssidx
= 0; /* Explicitly set to primary bssidx */
1566 memset(&bssid
, 0, sizeof(bssid
));
1567 if ((err
= wldev_ioctl_get(dev
, WLC_GET_BSSID
, &bssid
, sizeof(bssid
)))) {
1568 /* STA interface is not associated. So start the new interface on a temp
1569 * channel . Later proper channel will be applied by the above framework
1570 * via set_channel (cfg80211 API).
1572 WL_DBG(("Not associated. Return a temp channel. \n"));
1574 err
= wldev_ioctl_get(dev
, WLC_GET_BAND
, &cur_band
, sizeof(int));
1575 if (unlikely(err
)) {
1576 WL_ERR(("Get band failed\n"));
1577 return wl_ch_host_to_driver(cfg
, bssidx
, WL_P2P_TEMP_CHAN
);
1579 if (cur_band
== WLC_BAND_5G
)
1580 return wl_ch_host_to_driver(cfg
, bssidx
, WL_P2P_TEMP_CHAN_5G
);
1582 return wl_ch_host_to_driver(cfg
, bssidx
, WL_P2P_TEMP_CHAN
);
1585 buf
= kzalloc(WL_EXTRA_BUF_MAX
, GFP_KERNEL
);
1587 WL_ERR(("buf alloc failed. use temp channel\n"));
1588 return wl_ch_host_to_driver(cfg
, bssidx
, WL_P2P_TEMP_CHAN
);
1591 *(u32
*)buf
= htod32(WL_EXTRA_BUF_MAX
);
1592 if ((err
= wldev_ioctl_get(dev
, WLC_GET_BSS_INFO
, buf
,
1593 WL_EXTRA_BUF_MAX
))) {
1594 WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1595 chspec
= wl_ch_host_to_driver(cfg
, bssidx
, WL_P2P_TEMP_CHAN
);
1598 bss
= (struct wl_bss_info
*) (buf
+ 4);
1599 chspec
= bss
->chanspec
;
1601 WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec
));
1608 static bcm_struct_cfgdev
*
1609 wl_cfg80211_add_monitor_if(const char *name
)
1611 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1612 WL_INFORM(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1613 return ERR_PTR(-EOPNOTSUPP
);
1615 struct net_device
* ndev
= NULL
;
1617 dhd_add_monitor(name
, &ndev
);
1618 WL_INFORM(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev
));
1619 return ndev_to_cfgdev(ndev
);
1620 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1623 static bcm_struct_cfgdev
*
1624 wl_cfg80211_add_virtual_iface(struct wiphy
*wiphy
,
1625 #if defined(WL_CFG80211_P2P_DEV_IF)
1629 #endif /* WL_CFG80211_P2P_DEV_IF */
1630 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
1631 unsigned char name_assign_type
,
1632 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
1633 enum nl80211_iftype type
,
1634 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
1636 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) */
1637 struct vif_params
*params
)
1647 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
1648 struct net_device
*primary_ndev
;
1649 struct net_device
*new_ndev
;
1650 struct ether_addr primary_mac
;
1651 bcm_struct_cfgdev
*new_cfgdev
;
1652 #ifdef PROP_TXSTATUS_VSDB
1653 #if defined(BCMSDIO) || defined(BCMDBUS)
1656 #endif /* BCMSDIO || BCMDBUS */
1657 #endif /* PROP_TXSTATUS_VSDB */
1659 bool hang_required
= false;
1662 return ERR_PTR(-EINVAL
);
1664 dhd
= (dhd_pub_t
*)(cfg
->pub
);
1666 /* Use primary I/F for sending cmds down to firmware */
1667 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
1669 if (unlikely(!wl_get_drv_status(cfg
, READY
, primary_ndev
))) {
1670 WL_ERR(("device is not ready\n"));
1671 return ERR_PTR(-ENODEV
);
1675 WL_ERR(("Interface name not provided \n"));
1676 return ERR_PTR(-EINVAL
);
1680 /* disable TDLS if number of connected interfaces is >= 1 */
1681 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_IF_CREATE
, false);
1684 mutex_lock(&cfg
->if_sync
);
1685 WL_DBG(("if name: %s, type: %d\n", name
, type
));
1687 case NL80211_IFTYPE_ADHOC
:
1688 #ifdef WLAIBSS_MCHAN
1689 new_cfgdev
= bcm_cfg80211_add_ibss_if(wiphy
, (char *)name
);
1690 mutex_unlock(&cfg
->if_sync
);
1692 #endif /* WLAIBSS_MCHAN */
1693 case NL80211_IFTYPE_AP_VLAN
:
1694 case NL80211_IFTYPE_WDS
:
1695 case NL80211_IFTYPE_MESH_POINT
:
1696 WL_ERR(("Unsupported interface type\n"));
1697 mode
= WL_MODE_IBSS
;
1700 case NL80211_IFTYPE_MONITOR
:
1701 new_cfgdev
= wl_cfg80211_add_monitor_if(name
);
1702 mutex_unlock(&cfg
->if_sync
);
1704 #if defined(WL_CFG80211_P2P_DEV_IF)
1705 case NL80211_IFTYPE_P2P_DEVICE
:
1706 cfg
->down_disc_if
= FALSE
;
1707 new_cfgdev
= wl_cfgp2p_add_p2p_disc_if(cfg
);
1708 mutex_unlock(&cfg
->if_sync
);
1710 #endif /* WL_CFG80211_P2P_DEV_IF */
1711 case NL80211_IFTYPE_STATION
:
1712 #ifdef WL_VIRTUAL_APSTA
1713 #ifdef WLAIBSS_MCHAN
1714 if (cfg
->ibss_cfgdev
) {
1715 WL_ERR(("AIBSS is already operational. "
1716 " AIBSS & DUALSTA can't be used together \n"));
1720 #endif /* WLAIBSS_MCHAN */
1722 if (wl_cfgp2p_vif_created(cfg
)) {
1723 WL_ERR(("Could not create new iface."
1724 "Already one p2p interface is running"));
1728 new_cfgdev
= wl_cfg80211_create_iface(cfg
->wdev
->wiphy
,
1729 NL80211_IFTYPE_STATION
, NULL
, name
);
1734 mutex_unlock(&cfg
->if_sync
);
1737 #endif /* WL_VIRTUAL_APSTA */
1738 case NL80211_IFTYPE_P2P_CLIENT
:
1739 wlif_type
= WL_P2P_IF_CLIENT
;
1742 case NL80211_IFTYPE_P2P_GO
:
1743 wlif_type
= WL_P2P_IF_GO
;
1746 #ifdef WL_VIRTUAL_APSTA
1747 case NL80211_IFTYPE_AP
:
1748 dhd
->op_mode
= DHD_FLAG_HOSTAP_MODE
;
1749 new_cfgdev
= wl_cfg80211_create_iface(cfg
->wdev
->wiphy
,
1750 NL80211_IFTYPE_AP
, NULL
, name
);
1755 mutex_unlock(&cfg
->if_sync
);
1758 #endif /* WL_VIRTUAL_APSTA */
1760 WL_ERR(("Unsupported interface type\n"));
1765 if (cfg
->p2p_supported
&& (wlif_type
!= -1)) {
1766 ASSERT(cfg
->p2p
); /* ensure expectation of p2p initialization */
1768 #ifdef PROP_TXSTATUS_VSDB
1769 #if defined(BCMSDIO)
1775 #endif /* PROP_TXSTATUS_VSDB */
1778 WL_ERR(("Failed to start p2p"));
1783 if (cfg
->p2p
&& !cfg
->p2p
->on
&& strstr(name
, WL_P2P_INTERFACE_PREFIX
)) {
1785 wl_cfgp2p_set_firm_p2p(cfg
);
1786 wl_cfgp2p_init_discovery(cfg
);
1787 get_primary_mac(cfg
, &primary_mac
);
1788 wl_cfgp2p_generate_bss_mac(cfg
, &primary_mac
);
1791 strncpy(cfg
->p2p
->vir_ifname
, name
, IFNAMSIZ
- 1);
1792 cfg
->p2p
->vir_ifname
[IFNAMSIZ
- 1] = '\0';
1794 wl_cfg80211_scan_abort(cfg
);
1795 #ifdef PROP_TXSTATUS_VSDB
1796 #if defined(BCMSDIO) || defined(BCMDBUS)
1797 if (!cfg
->wlfc_on
&& !disable_proptx
) {
1798 dhd_wlfc_get_enable(dhd
, &enabled
);
1799 if (!enabled
&& dhd
->op_mode
!= DHD_FLAG_HOSTAP_MODE
&&
1800 dhd
->op_mode
!= DHD_FLAG_IBSS_MODE
) {
1802 err
= wldev_ioctl_set(primary_ndev
, WLC_UP
, &up
, sizeof(s32
));
1804 WL_ERR(("WLC_UP return err:%d\n", err
));
1806 cfg
->wlfc_on
= true;
1808 #endif /* BCMSDIO || BCMDBUS */
1809 #endif /* PROP_TXSTATUS_VSDB */
1811 /* Dual p2p doesn't support multiple P2PGO interfaces,
1812 * p2p_go_count is the counter for GO creation
1815 if ((cfg
->p2p
->p2p_go_count
> 0) && (type
== NL80211_IFTYPE_P2P_GO
)) {
1816 WL_ERR(("Fw doesnot support multiple Go"));
1820 /* In concurrency case, STA may be already associated in a particular channel.
1821 * so retrieve the current channel of primary interface and then start the virtual
1822 * interface on that.
1824 chspec
= wl_cfg80211_get_shared_freq(wiphy
);
1826 /* For P2P mode, use P2P-specific driver features to create the
1827 * bss: "cfg p2p_ifadd"
1829 wl_set_p2p_status(cfg
, IF_ADDING
);
1830 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
1831 cfg_type
= wl_cfgp2p_get_conn_idx(cfg
);
1832 if (cfg_type
== BCME_ERROR
) {
1833 wl_clr_p2p_status(cfg
, IF_ADDING
);
1834 WL_ERR(("Failed to get connection idx for p2p interface"));
1838 err
= wl_cfgp2p_ifadd(cfg
, wl_to_p2p_bss_macaddr(cfg
, cfg_type
),
1839 htod32(wlif_type
), chspec
);
1840 if (unlikely(err
)) {
1841 wl_clr_p2p_status(cfg
, IF_ADDING
);
1842 WL_ERR((" virtual iface add failed (%d) \n", err
));
1847 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
1848 ((wl_get_p2p_status(cfg
, IF_ADDING
) == false) &&
1849 (cfg
->if_event_info
.valid
)),
1850 msecs_to_jiffies(MAX_WAIT_TIME
));
1852 if (timeout
> 0 && !wl_get_p2p_status(cfg
, IF_ADDING
) && cfg
->if_event_info
.valid
) {
1853 struct wireless_dev
*vwdev
;
1854 int pm_mode
= PM_ENABLE
;
1855 wl_if_event_info
*event
= &cfg
->if_event_info
;
1856 /* IF_ADD event has come back, we can proceed to to register
1857 * the new interface now, use the interface name provided by caller (thus
1858 * ignore the one from wlc)
1860 new_ndev
= wl_cfg80211_allocate_if(cfg
, event
->ifidx
, cfg
->p2p
->vir_ifname
,
1861 event
->mac
, event
->bssidx
, event
->name
);
1862 if (new_ndev
== NULL
) {
1867 wl_to_p2p_bss_ndev(cfg
, cfg_type
) = new_ndev
;
1868 wl_to_p2p_bss_bssidx(cfg
, cfg_type
) = event
->bssidx
;
1869 vwdev
= kzalloc(sizeof(*vwdev
), GFP_KERNEL
);
1870 if (unlikely(!vwdev
)) {
1871 WL_ERR(("Could not allocate wireless device\n"));
1875 vwdev
->wiphy
= cfg
->wdev
->wiphy
;
1876 WL_INFORM(("virtual interface(%s) is created\n", cfg
->p2p
->vir_ifname
));
1877 if (type
== NL80211_IFTYPE_P2P_GO
) {
1878 cfg
->p2p
->p2p_go_count
++;
1880 vwdev
->iftype
= type
;
1881 vwdev
->netdev
= new_ndev
;
1882 new_ndev
->ieee80211_ptr
= vwdev
;
1883 SET_NETDEV_DEV(new_ndev
, wiphy_dev(vwdev
->wiphy
));
1884 wl_set_drv_status(cfg
, READY
, new_ndev
);
1885 if (wl_config_ifmode(cfg
, new_ndev
, type
) < 0) {
1886 WL_ERR(("conf ifmode failed\n"));
1892 if (wl_cfg80211_register_if(cfg
,
1893 event
->ifidx
, new_ndev
, FALSE
) != BCME_OK
) {
1894 wl_cfg80211_remove_if(cfg
, event
->ifidx
, new_ndev
, FALSE
);
1898 err
= wl_alloc_netinfo(cfg
, new_ndev
, vwdev
, mode
, pm_mode
, event
->bssidx
);
1899 if (unlikely(err
!= 0)) {
1900 wl_cfg80211_remove_if(cfg
, event
->ifidx
, new_ndev
, FALSE
);
1901 WL_ERR(("Allocation of netinfo failed (%d) \n", err
));
1905 /* Disable firmware roaming for P2P interface */
1906 wldev_iovar_setint(new_ndev
, "roam_off", val
);
1907 wldev_iovar_setint(new_ndev
, "bcn_timeout", dhd
->conf
->bcn_timeout
);
1909 if (cfg
->p2p_wdev
&& is_p2p_group_iface(new_ndev
->ieee80211_ptr
)) {
1910 u32 ulb_bw
= wl_cfg80211_get_ulb_bw(cfg
, cfg
->p2p_wdev
);
1912 /* Apply ULB BW settings on the newly spawned interface */
1913 WL_DBG(("[ULB] Applying ULB BW for the newly"
1914 "created P2P interface \n"));
1915 if (wl_cfg80211_set_ulb_bw(new_ndev
,
1916 ulb_bw
, new_ndev
->name
) < 0) {
1918 * If ulb_bw set failed, fail the iface creation.
1919 * wl_dealloc_netinfo_by_wdev will be called by the
1920 * unregister notifier.
1922 wl_cfg80211_remove_if(cfg
,
1923 event
->ifidx
, new_ndev
, FALSE
);
1929 #endif /* WL11ULB */
1931 if (mode
!= WL_MODE_AP
)
1932 wldev_iovar_setint(new_ndev
, "buf_key_b4_m4", 1);
1934 WL_ERR((" virtual interface(%s) is "
1935 "created net attach done\n", cfg
->p2p
->vir_ifname
));
1936 if (mode
== WL_MODE_AP
)
1937 wl_set_drv_status(cfg
, CONNECTED
, new_ndev
);
1938 #ifdef SUPPORT_AP_POWERSAVE
1939 if (mode
== WL_MODE_AP
) {
1940 dhd_set_ap_powersave(dhd
, 0, TRUE
);
1942 #endif /* SUPPORT_AP_POWERSAVE */
1943 if (type
== NL80211_IFTYPE_P2P_CLIENT
)
1944 dhd_mode
= DHD_FLAG_P2P_GC_MODE
;
1945 else if (type
== NL80211_IFTYPE_P2P_GO
)
1946 dhd_mode
= DHD_FLAG_P2P_GO_MODE
;
1947 DNGL_FUNC(dhd_cfg80211_set_p2p_info
, (cfg
, dhd_mode
));
1948 /* reinitialize completion to clear previous count */
1949 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
1950 INIT_COMPLETION(cfg
->iface_disable
);
1952 init_completion(&cfg
->iface_disable
);
1953 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */
1954 #ifdef SUPPORT_SET_CAC
1955 wl_cfg80211_set_cac(cfg
, 0);
1956 #endif /* SUPPORT_SET_CAC */
1957 mutex_unlock(&cfg
->if_sync
);
1958 return ndev_to_cfgdev(new_ndev
);
1960 wl_clr_p2p_status(cfg
, IF_ADDING
);
1961 WL_ERR((" virtual interface(%s) is not created \n", cfg
->p2p
->vir_ifname
));
1963 WL_ERR(("left timeout : %d\n", timeout
));
1964 WL_ERR(("IF_ADDING status : %d\n", wl_get_p2p_status(cfg
, IF_ADDING
)));
1965 WL_ERR(("event valid : %d\n", cfg
->if_event_info
.valid
));
1967 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
1968 wl_set_p2p_status(cfg
, IF_DELETING
);
1970 hang_required
= true;
1971 if ((err
= wl_cfgp2p_ifdel(cfg
,
1972 wl_to_p2p_bss_macaddr(cfg
,
1973 cfg_type
))) == BCME_OK
) {
1974 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
1975 ((wl_get_p2p_status(cfg
, IF_DELETING
) == false) &&
1976 (cfg
->if_event_info
.valid
)),
1977 msecs_to_jiffies(MAX_WAIT_TIME
));
1978 if (timeout
> 0 && !wl_get_p2p_status(cfg
, IF_DELETING
) &&
1979 cfg
->if_event_info
.valid
) {
1980 hang_required
= false;
1981 WL_ERR(("IFDEL operation done\n"));
1983 WL_ERR(("IFDEL didn't complete properly\n"));
1986 #ifdef SUPPORT_SET_CAC
1987 wl_cfg80211_set_cac(cfg
, 1);
1988 #endif /* SUPPORT_SET_CAC */
1990 WL_ERR(("IFDEL operation failed, error code = %d\n", err
));
1993 memset(cfg
->p2p
->vir_ifname
, '\0', IFNAMSIZ
);
1994 wl_to_p2p_bss_bssidx(cfg
, cfg_type
) = -1;
1995 #ifdef PROP_TXSTATUS_VSDB
1996 #if defined(BCMSDIO) || defined(BCMDBUS)
1997 dhd_wlfc_get_enable(dhd
, &enabled
);
1998 if (enabled
&& cfg
->wlfc_on
&& dhd
->op_mode
!= DHD_FLAG_HOSTAP_MODE
&&
1999 dhd
->op_mode
!= DHD_FLAG_IBSS_MODE
&& dhd
->conf
->disable_proptx
!=0) {
2000 dhd_wlfc_deinit(dhd
);
2001 cfg
->wlfc_on
= false;
2003 #endif /* BCMSDIO || BCMDBUS */
2004 #endif /* PROP_TXSTATUS_VSDB */
2009 mutex_unlock(&cfg
->if_sync
);
2012 /* Enable back TDLS on failure */
2013 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_IF_DELETE
, false);
2015 if (err
!= -ENOTSUPP
) {
2016 #if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2017 if (dhd
->memdump_enabled
) {
2018 /* Load the dongle side dump to host
2019 * memory and then BUG_ON()
2021 dhd
->memdump_type
= DUMP_TYPE_HANG_ON_IFACE_OP_FAIL
;
2022 dhd_bus_mem_dump(dhd
);
2024 #endif /* BCMPCIE && DHD_FW_COREDUMP */
2025 if (hang_required
) {
2026 /* Notify the user space to recover */
2027 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
2028 WL_ERR(("if add failed, error %d, sent HANG event to %s\n",
2030 dhd
->hang_reason
= HANG_REASON_IFACE_OP_FAILURE
;
2031 net_os_send_hang_message(ndev
);
2035 return ERR_PTR(err
);
2039 wl_cfg80211_del_virtual_iface(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
)
2041 struct net_device
*dev
= NULL
;
2042 struct ether_addr p2p_mac
;
2043 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2048 #if defined(CUSTOM_SET_CPUCORE) || defined(DHD_HANG_SEND_UP_TEST)
2049 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
2050 #endif /* CUSTOM_SET_CPUCORE || DHD_HANG_SEND_UP_TEST */
2051 WL_DBG(("Enter\n"));
2053 memset(&p2p_mac
, 0, sizeof(struct ether_addr
));
2054 #ifdef CUSTOM_SET_CPUCORE
2055 dhd
->chan_isvht80
&= ~DHD_FLAG_P2P_MODE
;
2056 if (!(dhd
->chan_isvht80
))
2057 dhd_set_cpucore(dhd
, FALSE
);
2058 #endif /* CUSTOM_SET_CPUCORE */
2059 mutex_lock(&cfg
->if_sync
);
2060 #ifdef WL_CFG80211_P2P_DEV_IF
2061 if (cfgdev
->iftype
== NL80211_IFTYPE_P2P_DEVICE
) {
2062 if (dhd_download_fw_on_driverload
) {
2063 ret
= wl_cfgp2p_del_p2p_disc_if(cfgdev
, cfg
);
2065 cfg
->down_disc_if
= TRUE
;
2068 mutex_unlock(&cfg
->if_sync
);
2071 #endif /* WL_CFG80211_P2P_DEV_IF */
2072 dev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
2074 #ifdef WLAIBSS_MCHAN
2075 if (cfgdev
== cfg
->ibss_cfgdev
) {
2076 ret
= bcm_cfg80211_del_ibss_if(wiphy
, cfgdev
);
2079 #endif /* WLAIBSS_MCHAN */
2081 if ((index
= wl_get_bssidx_by_wdev(cfg
, cfgdev_to_wdev(cfgdev
))) < 0) {
2082 WL_ERR(("Find p2p index from wdev failed\n"));
2086 if ((cfg
->p2p_supported
) && index
&& (wl_cfgp2p_find_type(cfg
, index
, &type
) == BCME_OK
)) {
2087 /* Handle P2P Interace del */
2088 memcpy(p2p_mac
.octet
, wl_to_p2p_bss_macaddr(cfg
, type
).octet
, ETHER_ADDR_LEN
);
2090 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
2092 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
2093 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
2094 if (wl_cfgp2p_vif_created(cfg
)) {
2095 if (wl_get_drv_status(cfg
, SCANNING
, dev
)) {
2096 wl_notify_escan_complete(cfg
, dev
, true, true);
2098 /* Delete pm_enable_work */
2099 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_DEL
);
2102 if (wl_get_drv_status(cfg
, DISCONNECTING
, dev
) &&
2103 (wl_get_mode_by_netdev(cfg
, dev
) != WL_MODE_AP
)) {
2104 WL_ERR(("Wait for Link Down event for GC !\n"));
2105 wait_for_completion_timeout
2106 (&cfg
->iface_disable
, msecs_to_jiffies(500));
2109 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
2110 wl_set_p2p_status(cfg
, IF_DELETING
);
2111 DNGL_FUNC(dhd_cfg80211_clean_p2p_info
, (cfg
));
2114 if (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
) {
2115 wl_add_remove_eventmsg(dev
, WLC_E_PROBREQ_MSG
, false);
2116 cfg
->p2p
->p2p_go_count
--;
2117 /* disable interface before bsscfg free */
2118 ret
= wl_cfgp2p_ifdisable(cfg
, &p2p_mac
);
2119 /* if fw doesn't support "ifdis",
2120 do not wait for link down of ap mode
2123 WL_ERR(("Wait for Link Down event for GO !!!\n"));
2124 wait_for_completion_timeout(&cfg
->iface_disable
,
2125 msecs_to_jiffies(500));
2126 } else if (ret
!= BCME_UNSUPPORTED
) {
2130 wl_cfg80211_clear_per_bss_ies(cfg
, index
);
2132 if (wl_get_mode_by_netdev(cfg
, dev
) != WL_MODE_AP
)
2133 wldev_iovar_setint(dev
, "buf_key_b4_m4", 0);
2134 memcpy(p2p_mac
.octet
, wl_to_p2p_bss_macaddr(cfg
, type
).octet
,
2136 CFGP2P_INFO(("primary idx %d : cfg p2p_ifdis "MACDBG
"\n",
2137 dev
->ifindex
, MAC2STRDBG(p2p_mac
.octet
)));
2139 /* delete interface after link down */
2140 ret
= wl_cfgp2p_ifdel(cfg
, &p2p_mac
);
2141 #if defined(DHD_HANG_SEND_UP_TEST)
2142 if (ret
!= BCME_OK
||
2143 dhd
->req_hang_type
== HANG_REASON_IFACE_OP_FAILURE
)
2144 #else /* DHD_HANG_SEND_UP_TEST */
2146 #endif /* DHD_HANG_SEND_UP_TEST */
2148 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
2149 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
2151 WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
2153 #if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2154 if (dhd
->memdump_enabled
) {
2155 /* Load the dongle side dump to host
2156 * memory and then BUG_ON()
2158 dhd
->memdump_type
= DUMP_TYPE_HANG_ON_IFACE_OP_FAIL
;
2159 dhd_bus_mem_dump(dhd
);
2161 #endif /* BCMPCIE && DHD_FW_COREDUMP */
2162 dhd
->hang_reason
= HANG_REASON_IFACE_OP_FAILURE
;
2163 net_os_send_hang_message(ndev
);
2165 /* Wait for IF_DEL operation to be finished */
2166 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
2167 ((wl_get_p2p_status(cfg
, IF_DELETING
) == false) &&
2168 (cfg
->if_event_info
.valid
)),
2169 msecs_to_jiffies(MAX_WAIT_TIME
));
2170 if (timeout
> 0 && !wl_get_p2p_status(cfg
, IF_DELETING
) &&
2171 cfg
->if_event_info
.valid
) {
2173 WL_DBG(("IFDEL operation done\n"));
2174 wl_cfg80211_handle_ifdel(cfg
, &cfg
->if_event_info
, dev
);
2176 WL_ERR(("IFDEL didn't complete properly\n"));
2178 #ifdef SUPPORT_SET_CAC
2179 wl_cfg80211_set_cac(cfg
, 1);
2180 #endif /* SUPPORT_SET_CAC */
2183 ret
= dhd_del_monitor(dev
);
2184 if (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
) {
2185 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL((dhd_pub_t
*)(cfg
->pub
));
2188 } else if ((dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) ||
2189 (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_STATION
)) {
2190 #ifdef WL_VIRTUAL_APSTA
2191 ret
= wl_cfg80211_del_iface(wiphy
, cfgdev
);
2193 WL_ERR(("Virtual APSTA not supported!\n"));
2194 #endif /* WL_VIRTUAL_APSTA */
2198 mutex_unlock(&cfg
->if_sync
);
2200 if (ret
== BCME_OK
) {
2201 /* If interface del is success, try enabling back TDLS */
2202 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_IF_DELETE
, false);
2209 wl_cfg80211_change_virtual_iface(struct wiphy
*wiphy
, struct net_device
*ndev
,
2210 enum nl80211_iftype type
,
2211 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
2213 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) */
2214 struct vif_params
*params
)
2224 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
2225 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
2227 mutex_lock(&cfg
->if_sync
);
2228 WL_DBG(("Enter type %d\n", type
));
2230 case NL80211_IFTYPE_MONITOR
:
2231 case NL80211_IFTYPE_WDS
:
2233 case NL80211_IFTYPE_MESH_POINT
:
2236 WL_ERR(("type (%d) : currently we do not support this type\n",
2240 case NL80211_IFTYPE_MESH_POINT
:
2241 infra_ibss
= WL_BSSTYPE_MESH
;
2244 case NL80211_IFTYPE_ADHOC
:
2245 mode
= WL_MODE_IBSS
;
2248 case NL80211_IFTYPE_STATION
:
2249 case NL80211_IFTYPE_P2P_CLIENT
:
2250 if (ndev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
2251 s32 bssidx
= wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
);
2253 /* validate bssidx */
2254 WL_ERR(("Wrong bssidx! \n"));
2258 WL_DBG(("del interface. bssidx:%d", bssidx
));
2259 /* Downgrade role from AP to STA */
2260 if ((err
= wl_cfg80211_add_del_bss(cfg
, ndev
,
2261 bssidx
, NL80211_IFTYPE_STATION
, 0, NULL
)) < 0) {
2262 WL_ERR(("AP-STA Downgrade failed \n"));
2269 case NL80211_IFTYPE_AP
:
2270 dhd
->op_mode
|= DHD_FLAG_HOSTAP_MODE
;
2271 /* intentional fall through */
2272 case NL80211_IFTYPE_AP_VLAN
:
2273 case NL80211_IFTYPE_P2P_GO
:
2287 wl_set_mode_by_netdev(cfg
, ndev
, mode
);
2288 if (is_p2p_group_iface(ndev
->ieee80211_ptr
) &&
2289 cfg
->p2p
&& wl_cfgp2p_vif_created(cfg
)) {
2290 WL_DBG(("p2p_vif_created p2p_on (%d)\n", p2p_on(cfg
)));
2291 wl_notify_escan_complete(cfg
, ndev
, true, true);
2293 /* Dual p2p doesn't support multiple P2PGO interfaces,
2294 * p2p_go_count is the counter for GO creation
2297 if ((cfg
->p2p
->p2p_go_count
> 0) && (type
== NL80211_IFTYPE_P2P_GO
)) {
2298 wl_set_mode_by_netdev(cfg
, ndev
, WL_MODE_BSS
);
2299 WL_ERR(("Fw doesnot support multiple GO "));
2303 /* In concurrency case, STA may be already associated in a particular
2304 * channel. so retrieve the current channel of primary interface and
2305 * then start the virtual interface on that.
2307 chspec
= wl_cfg80211_get_shared_freq(wiphy
);
2308 index
= wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
);
2310 WL_ERR(("Find p2p index from ndev(%p) failed\n", ndev
));
2314 if (wl_cfgp2p_find_type(cfg
, index
, &conn_idx
) != BCME_OK
) {
2319 wlif_type
= WL_P2P_IF_GO
;
2320 printf("%s: %s ap (%d), infra_ibss (%d), iftype (%d) conn_idx (%d)\n",
2321 __FUNCTION__
, ndev
->name
, ap
, infra_ibss
, type
, conn_idx
);
2322 wl_set_p2p_status(cfg
, IF_CHANGING
);
2323 wl_clr_p2p_status(cfg
, IF_CHANGED
);
2324 wl_cfgp2p_ifchange(cfg
, wl_to_p2p_bss_macaddr(cfg
, conn_idx
),
2325 htod32(wlif_type
), chspec
, conn_idx
);
2326 wait_event_interruptible_timeout(cfg
->netif_change_event
,
2327 (wl_get_p2p_status(cfg
, IF_CHANGED
) == true),
2328 msecs_to_jiffies(MAX_WAIT_TIME
));
2329 wl_set_mode_by_netdev(cfg
, ndev
, mode
);
2330 dhd
->op_mode
&= ~DHD_FLAG_P2P_GC_MODE
;
2331 dhd
->op_mode
|= DHD_FLAG_P2P_GO_MODE
;
2332 wl_clr_p2p_status(cfg
, IF_CHANGING
);
2333 wl_clr_p2p_status(cfg
, IF_CHANGED
);
2334 if (mode
== WL_MODE_AP
)
2335 wl_set_drv_status(cfg
, CONNECTED
, ndev
);
2336 #ifdef SUPPORT_AP_POWERSAVE
2337 dhd_set_ap_powersave(dhd
, 0, TRUE
);
2338 #endif /* SUPPORT_AP_POWERSAVE */
2339 } else if ((type
== NL80211_IFTYPE_AP
) &&
2340 !wl_get_drv_status(cfg
, AP_CREATED
, ndev
)) {
2342 err
= wl_cfg80211_set_ap_role(cfg
, ndev
);
2343 if (unlikely(err
)) {
2344 WL_ERR(("set ap role failed!\n"));
2348 wl_set_drv_status(cfg
, AP_CREATING
, ndev
);
2351 WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
2356 /* P2P GO interface deletion is handled on the basis of role type (AP).
2357 * So avoid changing role for p2p type.
2359 if (ndev
->ieee80211_ptr
->iftype
!= NL80211_IFTYPE_P2P_GO
)
2360 wl_set_mode_by_netdev(cfg
, ndev
, mode
);
2361 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA\n"));
2362 #ifdef SUPPORT_AP_POWERSAVE
2363 dhd_set_ap_powersave(dhd
, 0, FALSE
);
2364 #endif /* SUPPORT_AP_POWERSAVE */
2368 err
= wldev_ioctl_set(ndev
, WLC_SET_INFRA
, &infra_ibss
, sizeof(s32
));
2370 WL_ERR(("SET INFRA/IBSS error %d\n", err
));
2376 WL_DBG(("Setting iftype to %d \n", type
));
2377 ndev
->ieee80211_ptr
->iftype
= type
;
2379 mutex_unlock(&cfg
->if_sync
);
2384 wl_cfg80211_notify_ifadd(struct net_device
*dev
, int ifidx
, char *name
, uint8
*mac
, uint8 bssidx
)
2386 bool ifadd_expected
= FALSE
;
2387 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
2389 /* P2P may send WLC_E_IF_ADD and/or WLC_E_IF_CHANGE during IF updating ("p2p_ifupd")
2390 * redirect the IF_ADD event to ifchange as it is not a real "new" interface
2392 if (wl_get_p2p_status(cfg
, IF_CHANGING
))
2393 return wl_cfg80211_notify_ifchange(dev
, ifidx
, name
, mac
, bssidx
);
2395 /* Okay, we are expecting IF_ADD (as IF_ADDING is true) */
2396 if (wl_get_p2p_status(cfg
, IF_ADDING
)) {
2397 ifadd_expected
= TRUE
;
2398 wl_clr_p2p_status(cfg
, IF_ADDING
);
2399 } else if (cfg
->bss_pending_op
) {
2400 ifadd_expected
= TRUE
;
2401 cfg
->bss_pending_op
= FALSE
;
2404 if (ifadd_expected
) {
2405 wl_if_event_info
*if_event_info
= &cfg
->if_event_info
;
2407 if_event_info
->valid
= TRUE
;
2408 if_event_info
->ifidx
= ifidx
;
2409 if_event_info
->bssidx
= bssidx
;
2410 strncpy(if_event_info
->name
, name
, IFNAMSIZ
);
2411 if_event_info
->name
[IFNAMSIZ
] = '\0';
2413 memcpy(if_event_info
->mac
, mac
, ETHER_ADDR_LEN
);
2414 wake_up_interruptible(&cfg
->netif_change_event
);
2422 wl_cfg80211_notify_ifdel(struct net_device
*dev
, int ifidx
, char *name
, uint8
*mac
, uint8 bssidx
)
2424 bool ifdel_expected
= FALSE
;
2425 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
2426 wl_if_event_info
*if_event_info
= &cfg
->if_event_info
;
2428 if (wl_get_p2p_status(cfg
, IF_DELETING
)) {
2429 ifdel_expected
= TRUE
;
2430 wl_clr_p2p_status(cfg
, IF_DELETING
);
2431 } else if (cfg
->bss_pending_op
) {
2432 ifdel_expected
= TRUE
;
2433 cfg
->bss_pending_op
= FALSE
;
2436 if (ifdel_expected
) {
2437 if_event_info
->valid
= TRUE
;
2438 if_event_info
->ifidx
= ifidx
;
2439 if_event_info
->bssidx
= bssidx
;
2440 wake_up_interruptible(&cfg
->netif_change_event
);
2448 wl_cfg80211_notify_ifchange(struct net_device
* dev
, int ifidx
, char *name
, uint8
*mac
,
2451 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
2453 if (wl_get_p2p_status(cfg
, IF_CHANGING
)) {
2454 wl_set_p2p_status(cfg
, IF_CHANGED
);
2455 wake_up_interruptible(&cfg
->netif_change_event
);
2462 static s32
wl_cfg80211_handle_ifdel(struct bcm_cfg80211
*cfg
, wl_if_event_info
*if_event_info
,
2463 struct net_device
* ndev
)
2467 #ifdef PROP_TXSTATUS_VSDB
2468 #if defined(BCMSDIO) || defined(BCMDBUS)
2469 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
2471 #endif /* BCMSDIO || BCMDBUS */
2472 #endif /* PROP_TXSTATUS_VSDB */
2474 bssidx
= if_event_info
->bssidx
;
2475 if (bssidx
!= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_CONNECTION1
) &&
2476 bssidx
!= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_CONNECTION2
)) {
2477 WL_ERR(("got IF_DEL for if %d, not owned by cfg driver\n", bssidx
));
2481 if (p2p_is_on(cfg
) && wl_cfgp2p_vif_created(cfg
)) {
2482 if (cfg
->scan_request
&& (cfg
->escan_info
.ndev
== ndev
)) {
2483 /* Abort any pending scan requests */
2484 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
2485 WL_DBG(("ESCAN COMPLETED\n"));
2486 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, true, false);
2489 memset(cfg
->p2p
->vir_ifname
, '\0', IFNAMSIZ
);
2490 if (wl_cfgp2p_find_type(cfg
, bssidx
, &type
) == BCME_OK
) {
2491 /* Update P2P data */
2492 wl_clr_drv_status(cfg
, CONNECTED
, wl_to_p2p_bss_ndev(cfg
, type
));
2493 wl_to_p2p_bss_ndev(cfg
, type
) = NULL
;
2494 wl_to_p2p_bss_bssidx(cfg
, type
) = -1;
2495 } else if (wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
) < 0) {
2496 WL_ERR(("bssidx not known for the given ndev as per net_info data \n"));
2500 #ifdef PROP_TXSTATUS_VSDB
2501 #if defined(BCMSDIO) || defined(BCMDBUS)
2502 dhd_wlfc_get_enable(dhd
, &enabled
);
2503 if (enabled
&& cfg
->wlfc_on
&& dhd
->op_mode
!= DHD_FLAG_HOSTAP_MODE
&&
2504 dhd
->op_mode
!= DHD_FLAG_IBSS_MODE
&& dhd
->conf
->disable_proptx
!=0) {
2505 dhd_wlfc_deinit(dhd
);
2506 cfg
->wlfc_on
= false;
2508 #endif /* BCMSDIO || BCMDBUS */
2509 #endif /* PROP_TXSTATUS_VSDB */
2512 dhd_net_if_lock(ndev
);
2513 wl_cfg80211_remove_if(cfg
, if_event_info
->ifidx
, ndev
, FALSE
);
2514 dhd_net_if_unlock(ndev
);
2519 /* Find listen channel */
2520 static s32
wl_find_listen_channel(struct bcm_cfg80211
*cfg
,
2521 const u8
*ie
, u32 ie_len
)
2523 wifi_p2p_ie_t
*p2p_ie
;
2527 /* unfortunately const cast required here - function is
2528 * a callback so its signature must not be changed
2529 * and cascade of changing wl_cfgp2p_find_p2pie
2530 * causes need for const cast in other places
2532 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2533 4 && __GNUC_MINOR__ >= 6))
2534 _Pragma("GCC diagnostic push")
2535 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
2538 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2539 4 && __GNUC_MINOR__ >= 6))
2540 _Pragma("GCC diagnostic pop")
2542 p2p_ie
= wl_cfgp2p_find_p2pie(pos
, ie_len
);
2547 pos
= p2p_ie
->subelts
;
2548 end
= p2p_ie
->subelts
+ (p2p_ie
->len
- 4);
2550 CFGP2P_DBG((" found p2p ie ! lenth %d \n",
2555 if (pos
+ 2 >= end
) {
2556 CFGP2P_DBG((" -- Invalid P2P attribute"));
2559 attr_len
= ((uint16
) (((pos
+ 1)[1] << 8) | (pos
+ 1)[0]));
2561 if (pos
+ 3 + attr_len
> end
) {
2562 CFGP2P_DBG(("P2P: Attribute underflow "
2564 attr_len
, (int) (end
- pos
- 3)));
2568 /* if Listen Channel att id is 6 and the vailue is valid,
2569 * return the listen channel
2572 /* listen channel subel length format
2573 * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
2575 listen_channel
= pos
[1 + 2 + 3 + 1];
2577 if (listen_channel
== SOCIAL_CHAN_1
||
2578 listen_channel
== SOCIAL_CHAN_2
||
2579 listen_channel
== SOCIAL_CHAN_3
) {
2580 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel
));
2581 return listen_channel
;
2584 pos
+= 3 + attr_len
;
2589 static void wl_scan_prep(struct bcm_cfg80211
*cfg
, struct wl_scan_params
*params
,
2590 struct cfg80211_scan_request
*request
)
2595 chanspec_t chanspec
;
2596 s32 i
= 0, j
= 0, offset
;
2599 struct wireless_dev
*wdev
;
2601 memcpy(¶ms
->bssid
, ðer_bcast
, ETHER_ADDR_LEN
);
2602 params
->bss_type
= DOT11_BSSTYPE_ANY
;
2603 params
->scan_type
= 0;
2604 params
->nprobes
= -1;
2605 params
->active_time
= -1;
2606 params
->passive_time
= -1;
2607 params
->home_time
= -1;
2608 params
->channel_num
= 0;
2609 memset(¶ms
->ssid
, 0, sizeof(wlc_ssid_t
));
2611 WL_SCAN(("Preparing Scan request\n"));
2612 WL_SCAN(("nprobes=%d\n", params
->nprobes
));
2613 WL_SCAN(("active_time=%d\n", params
->active_time
));
2614 WL_SCAN(("passive_time=%d\n", params
->passive_time
));
2615 WL_SCAN(("home_time=%d\n", params
->home_time
));
2616 WL_SCAN(("scan_type=%d\n", params
->scan_type
));
2618 params
->nprobes
= htod32(params
->nprobes
);
2619 params
->active_time
= htod32(params
->active_time
);
2620 params
->passive_time
= htod32(params
->passive_time
);
2621 params
->home_time
= htod32(params
->home_time
);
2623 /* if request is null just exit so it will be all channel broadcast scan */
2627 n_ssids
= request
->n_ssids
;
2628 n_channels
= request
->n_channels
;
2630 /* Copy channel array if applicable */
2631 WL_SCAN(("### List of channelspecs to scan ###\n"));
2632 if (n_channels
> 0) {
2633 for (i
= 0; i
< n_channels
; i
++) {
2634 channel
= ieee80211_frequency_to_channel(request
->channels
[i
]->center_freq
);
2635 /* SKIP DFS channels for Secondary interface */
2636 if ((cfg
->escan_info
.ndev
!= bcmcfg_to_prmry_ndev(cfg
)) &&
2637 (request
->channels
[i
]->flags
&
2638 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
2639 (IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_PASSIVE_SCAN
)))
2641 (IEEE80211_CHAN_RADAR
| IEEE80211_CHAN_NO_IR
)))
2642 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
2644 if (!dhd_conf_match_channel(cfg
->pub
, channel
))
2647 #if defined(WL_CFG80211_P2P_DEV_IF)
2648 wdev
= request
->wdev
;
2650 wdev
= request
->dev
->ieee80211_ptr
;
2651 #endif /* WL_CFG80211_P2P_DEV_IF */
2652 chanspec
= wl_cfg80211_ulb_get_min_bw_chspec(cfg
, wdev
, -1);
2653 if (chanspec
== INVCHANSPEC
) {
2654 WL_ERR(("Invalid chanspec! Skipping channel\n"));
2658 if (request
->channels
[i
]->band
== IEEE80211_BAND_2GHZ
) {
2659 chanspec
|= WL_CHANSPEC_BAND_2G
;
2661 chanspec
|= WL_CHANSPEC_BAND_5G
;
2663 params
->channel_list
[j
] = channel
;
2664 params
->channel_list
[j
] &= WL_CHANSPEC_CHAN_MASK
;
2665 params
->channel_list
[j
] |= chanspec
;
2666 WL_SCAN(("Chan : %d, Channel spec: %x \n",
2667 channel
, params
->channel_list
[j
]));
2668 params
->channel_list
[j
] = wl_chspec_host_to_driver(params
->channel_list
[j
]);
2672 WL_SCAN(("Scanning all channels\n"));
2675 /* Copy ssid array if applicable */
2676 WL_SCAN(("### List of SSIDs to scan ###\n"));
2678 offset
= offsetof(wl_scan_params_t
, channel_list
) + n_channels
* sizeof(u16
);
2679 offset
= roundup(offset
, sizeof(u32
));
2680 ptr
= (char*)params
+ offset
;
2681 for (i
= 0; i
< n_ssids
; i
++) {
2682 memset(&ssid
, 0, sizeof(wlc_ssid_t
));
2683 ssid
.SSID_len
= MIN(request
->ssids
[i
].ssid_len
, DOT11_MAX_SSID_LEN
);
2684 memcpy(ssid
.SSID
, request
->ssids
[i
].ssid
, ssid
.SSID_len
);
2686 WL_SCAN(("%d: Broadcast scan\n", i
));
2688 WL_SCAN(("%d: scan for %s size =%d\n", i
,
2689 ssid
.SSID
, ssid
.SSID_len
));
2690 memcpy(ptr
, &ssid
, sizeof(wlc_ssid_t
));
2691 ptr
+= sizeof(wlc_ssid_t
);
2694 WL_SCAN(("Broadcast scan\n"));
2696 /* Adding mask to channel numbers */
2697 params
->channel_num
=
2698 htod32((n_ssids
<< WL_SCAN_PARAMS_NSSID_SHIFT
) |
2699 (n_channels
& WL_SCAN_PARAMS_COUNT_MASK
));
2701 if (n_channels
== 1) {
2702 params
->active_time
= htod32(WL_SCAN_CONNECT_DWELL_TIME_MS
);
2703 params
->nprobes
= htod32(params
->active_time
/ WL_SCAN_JOIN_PROBE_INTERVAL_MS
);
2708 wl_get_valid_channels(struct net_device
*ndev
, u8
*valid_chan_list
, s32 size
)
2710 wl_uint32_list_t
*list
;
2712 if (valid_chan_list
== NULL
|| size
<= 0)
2715 memset(valid_chan_list
, 0, size
);
2716 list
= (wl_uint32_list_t
*)(void *) valid_chan_list
;
2717 list
->count
= htod32(WL_NUMCHANNELS
);
2718 err
= wldev_ioctl_get(ndev
, WLC_GET_VALID_CHANNELS
, valid_chan_list
, size
);
2720 WL_ERR(("get channels failed with %d\n", err
));
2726 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2727 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
2728 bool g_first_broadcast_scan
= TRUE
;
2732 wl_run_escan(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
2733 struct cfg80211_scan_request
*request
, uint16 action
)
2738 s32 params_size
= (WL_SCAN_PARAMS_FIXED_SIZE
+ OFFSETOF(wl_escan_params_t
, params
));
2739 wl_escan_params_t
*params
= NULL
;
2740 u8 chan_buf
[sizeof(u32
)*(WL_NUMCHANNELS
+ 1)];
2744 s32 search_state
= WL_P2P_DISC_ST_SCAN
;
2745 u32 i
, j
, n_nodfs
= 0;
2746 u16
*default_chan_list
= NULL
;
2747 wl_uint32_list_t
*list
;
2749 struct net_device
*dev
= NULL
;
2750 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2751 bool is_first_init_2g_scan
= false;
2753 p2p_scan_purpose_t p2p_scan_purpose
= P2P_SCAN_PURPOSE_MIN
;
2757 WL_DBG(("Enter \n"));
2759 /* scan request can come with empty request : perform all default scan */
2764 if (!cfg
->p2p_supported
|| !p2p_scan(cfg
)) {
2765 /* LEGACY SCAN TRIGGER */
2766 WL_SCAN((" LEGACY E-SCAN START\n"));
2768 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2773 if (ndev
== bcmcfg_to_prmry_ndev(cfg
) && g_first_broadcast_scan
== true) {
2774 is_first_init_2g_scan
= true;
2775 g_first_broadcast_scan
= false;
2779 /* if scan request is not empty parse scan request paramters */
2780 if (request
!= NULL
) {
2781 n_channels
= request
->n_channels
;
2782 n_ssids
= request
->n_ssids
;
2784 /* If n_channels is odd, add a padd of u16 */
2785 params_size
+= sizeof(u16
) * (n_channels
+ 1);
2787 params_size
+= sizeof(u16
) * n_channels
;
2789 /* Allocate space for populating ssids in wl_escan_params_t struct */
2790 params_size
+= sizeof(struct wlc_ssid
) * n_ssids
;
2792 params
= (wl_escan_params_t
*) kzalloc(params_size
, GFP_KERNEL
);
2793 if (params
== NULL
) {
2797 wl_scan_prep(cfg
, ¶ms
->params
, request
);
2799 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2800 /* Override active_time to reduce scan time if it's first bradcast scan. */
2801 if (is_first_init_2g_scan
)
2802 params
->params
.active_time
= FIRST_SCAN_ACTIVE_DWELL_TIME_MS
;
2805 params
->version
= htod32(ESCAN_REQ_VERSION
);
2806 params
->action
= htod16(action
);
2807 wl_escan_set_sync_id(params
->sync_id
, cfg
);
2808 wl_escan_set_type(cfg
, WL_SCANTYPE_LEGACY
);
2809 if (params_size
+ sizeof("escan") >= WLC_IOCTL_MEDLEN
) {
2810 WL_ERR(("ioctl buffer length not sufficient\n"));
2815 if (cfg
->active_scan
== PASSIVE_SCAN
) {
2816 params
->params
.scan_type
= DOT11_SCANTYPE_PASSIVE
;
2817 WL_DBG(("Passive scan_type %d \n", params
->params
.scan_type
));
2820 bssidx
= wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
);
2822 err
= wldev_iovar_setbuf(ndev
, "escan", params
, params_size
,
2823 cfg
->escan_ioctl_buf
, WLC_IOCTL_MEDLEN
, NULL
);
2824 printf("%s: LEGACY_SCAN sync ID: %d, bssidx: %d\n", __FUNCTION__
, params
->sync_id
, bssidx
);
2825 if (unlikely(err
)) {
2826 if (err
== BCME_EPERM
)
2827 /* Scan Not permitted at this point of time */
2828 WL_DBG((" Escan not permitted at this time (%d)\n", err
));
2830 WL_ERR((" Escan set error (%d)\n", err
));
2832 DBG_EVENT_LOG((dhd_pub_t
*)cfg
->pub
, WIFI_EVENT_DRIVER_SCAN_REQUESTED
);
2836 else if (p2p_is_on(cfg
) && p2p_scan(cfg
)) {
2837 /* P2P SCAN TRIGGER */
2840 if (request
&& request
->n_channels
) {
2841 num_chans
= request
->n_channels
;
2842 WL_SCAN((" chann number : %d\n", num_chans
));
2843 default_chan_list
= kzalloc(num_chans
* sizeof(*default_chan_list
),
2845 if (default_chan_list
== NULL
) {
2846 WL_ERR(("channel list allocation failed \n"));
2850 if (!wl_get_valid_channels(ndev
, chan_buf
, sizeof(chan_buf
))) {
2852 int is_printed
= false;
2853 #endif /* P2P_SKIP_DFS */
2854 list
= (wl_uint32_list_t
*) chan_buf
;
2855 n_valid_chan
= dtoh32(list
->count
);
2856 if (n_valid_chan
> WL_NUMCHANNELS
) {
2857 WL_ERR(("wrong n_valid_chan:%d\n", n_valid_chan
));
2858 kfree(default_chan_list
);
2863 for (i
= 0; i
< num_chans
; i
++)
2865 _freq
= request
->channels
[i
]->center_freq
;
2866 channel
= ieee80211_frequency_to_channel(_freq
);
2868 /* ignore DFS channels */
2869 if (request
->channels
[i
]->flags
&
2870 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2871 (IEEE80211_CHAN_NO_IR
2872 | IEEE80211_CHAN_RADAR
))
2874 (IEEE80211_CHAN_RADAR
2875 | IEEE80211_CHAN_PASSIVE_SCAN
))
2879 if (channel
>= 52 && channel
<= 144) {
2880 if (is_printed
== false) {
2881 WL_ERR(("SKIP DFS CHANs(52~144)\n"));
2886 #endif /* P2P_SKIP_DFS */
2888 for (j
= 0; j
< n_valid_chan
; j
++) {
2889 /* allows only supported channel on
2892 if (n_nodfs
>= num_chans
) {
2895 if (channel
== (dtoh32(list
->element
[j
]))) {
2896 default_chan_list
[n_nodfs
++] =
2903 if (num_chans
== SOCIAL_CHAN_CNT
&& (
2904 (default_chan_list
[0] == SOCIAL_CHAN_1
) &&
2905 (default_chan_list
[1] == SOCIAL_CHAN_2
) &&
2906 (default_chan_list
[2] == SOCIAL_CHAN_3
))) {
2907 /* SOCIAL CHANNELS 1, 6, 11 */
2908 search_state
= WL_P2P_DISC_ST_SEARCH
;
2909 p2p_scan_purpose
= P2P_SCAN_SOCIAL_CHANNEL
;
2910 WL_INFORM(("P2P SEARCH PHASE START \n"));
2911 } else if (((dev
= wl_to_p2p_bss_ndev(cfg
, P2PAPI_BSSCFG_CONNECTION1
)) &&
2912 (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
)) ||
2913 ((dev
= wl_to_p2p_bss_ndev(cfg
, P2PAPI_BSSCFG_CONNECTION2
)) &&
2914 (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
))) {
2915 /* If you are already a GO, then do SEARCH only */
2916 WL_INFORM(("Already a GO. Do SEARCH Only"));
2917 search_state
= WL_P2P_DISC_ST_SEARCH
;
2918 num_chans
= n_nodfs
;
2919 p2p_scan_purpose
= P2P_SCAN_NORMAL
;
2921 } else if (num_chans
== 1) {
2922 p2p_scan_purpose
= P2P_SCAN_CONNECT_TRY
;
2923 } else if (num_chans
== SOCIAL_CHAN_CNT
+ 1) {
2924 /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2927 p2p_scan_purpose
= P2P_SCAN_SOCIAL_CHANNEL
;
2929 WL_INFORM(("P2P SCAN STATE START \n"));
2930 num_chans
= n_nodfs
;
2931 p2p_scan_purpose
= P2P_SCAN_NORMAL
;
2937 err
= wl_cfgp2p_escan(cfg
, ndev
, ACTIVE_SCAN
, num_chans
, default_chan_list
,
2938 search_state
, action
,
2939 wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
), NULL
,
2943 cfg
->p2p
->search_state
= search_state
;
2945 kfree(default_chan_list
);
2948 if (unlikely(err
)) {
2949 /* Don't print Error incase of Scan suppress */
2950 if ((err
== BCME_EPERM
) && cfg
->scan_suppressed
)
2951 WL_DBG(("Escan failed: Scan Suppressed \n"));
2954 WL_ERR(("error (%d), cnt=%d\n", err
, cnt
));
2955 // terence 20140111: send disassoc to firmware
2957 dev
= bcmcfg_to_prmry_ndev(cfg
);
2958 memset(&scbval
, 0, sizeof(scb_val_t
));
2959 wldev_ioctl(dev
, WLC_DISASSOC
, &scbval
, sizeof(scb_val_t
), true);
2960 WL_ERR(("Send disassoc to break the busy dev=%p\n", dev
));
2972 wl_do_escan(struct bcm_cfg80211
*cfg
, struct wiphy
*wiphy
, struct net_device
*ndev
,
2973 struct cfg80211_scan_request
*request
)
2976 s32 passive_scan
= 0;
2977 s32 passive_scan_time
= 0;
2978 s32 passive_scan_time_org
= 0;
2979 wl_scan_results_t
*results
;
2980 WL_SCAN(("Enter \n"));
2982 results
= wl_escan_get_buf(cfg
, FALSE
);
2983 results
->version
= 0;
2985 results
->buflen
= WL_SCAN_RESULTS_FIXED_SIZE
;
2987 cfg
->escan_info
.ndev
= ndev
;
2988 cfg
->escan_info
.wiphy
= wiphy
;
2989 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_SCANING
;
2990 passive_scan
= cfg
->active_scan
? 0 : 1;
2991 err
= wldev_ioctl_set(ndev
, WLC_SET_PASSIVE_SCAN
,
2992 &passive_scan
, sizeof(passive_scan
));
2993 if (unlikely(err
)) {
2994 WL_ERR(("error (%d)\n", err
));
2998 if (passive_channel_skip
) {
3000 err
= wldev_ioctl_get(ndev
, WLC_GET_SCAN_PASSIVE_TIME
,
3001 &passive_scan_time_org
, sizeof(passive_scan_time_org
));
3002 if (unlikely(err
)) {
3003 WL_ERR(("== error (%d)\n", err
));
3007 WL_SCAN(("PASSIVE SCAN time : %d \n", passive_scan_time_org
));
3009 passive_scan_time
= 0;
3010 err
= wldev_ioctl_set(ndev
, WLC_SET_SCAN_PASSIVE_TIME
,
3011 &passive_scan_time
, sizeof(passive_scan_time
));
3012 if (unlikely(err
)) {
3013 WL_ERR(("== error (%d)\n", err
));
3017 WL_SCAN(("PASSIVE SCAN SKIPED!! (passive_channel_skip:%d) \n",
3018 passive_channel_skip
));
3021 err
= wl_run_escan(cfg
, ndev
, request
, WL_SCAN_ACTION_START
);
3023 if (passive_channel_skip
) {
3024 err
= wldev_ioctl_set(ndev
, WLC_SET_SCAN_PASSIVE_TIME
,
3025 &passive_scan_time_org
, sizeof(passive_scan_time_org
));
3026 if (unlikely(err
)) {
3027 WL_ERR(("== error (%d)\n", err
));
3031 WL_SCAN(("PASSIVE SCAN RECOVERED!! (passive_scan_time_org:%d) \n",
3032 passive_scan_time_org
));
3040 __wl_cfg80211_scan(struct wiphy
*wiphy
, struct net_device
*ndev
,
3041 struct cfg80211_scan_request
*request
,
3042 struct cfg80211_ssid
*this_ssid
)
3044 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3045 struct cfg80211_ssid
*ssids
;
3046 struct ether_addr primary_mac
;
3049 bcm_tlv_t
*interworking_ie
;
3055 unsigned long flags
;
3056 static s32 busy_count
= 0;
3057 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
3058 struct net_device
*remain_on_channel_ndev
= NULL
;
3060 uint scan_timer_interval_ms
= WL_SCAN_TIMER_INTERVAL_MS
;
3063 * Hostapd triggers scan before starting automatic channel selection
3064 * to collect channel characteristics. However firmware scan engine
3065 * doesn't support any channel characteristics collection along with
3066 * scan. Hence return scan success.
3068 if (request
&& (scan_req_iftype(request
) == NL80211_IFTYPE_AP
)) {
3069 WL_INFORM(("Scan Command on SoftAP Interface. Ignoring...\n"));
3070 // terence 20161023: let it scan in SoftAP mode
3074 ndev
= ndev_to_wlc_ndev(ndev
, cfg
);
3076 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg
)) {
3077 WL_ERR(("Sending Action Frames. Try it again.\n"));
3081 WL_DBG(("Enter wiphy (%p)\n", wiphy
));
3082 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
3083 if (cfg
->scan_request
== NULL
) {
3084 wl_clr_drv_status_all(cfg
, SCANNING
);
3085 WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
3087 WL_ERR(("Scanning already\n"));
3091 if (wl_get_drv_status(cfg
, SCAN_ABORTING
, ndev
)) {
3092 WL_ERR(("Scanning being aborted\n"));
3095 if (request
&& request
->n_ssids
> WL_SCAN_PARAMS_SSID_MAX
) {
3096 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
3100 #ifdef P2P_LISTEN_OFFLOADING
3101 if (wl_get_p2p_status(cfg
, DISC_IN_PROGRESS
)) {
3102 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
3105 #endif /* P2P_LISTEN_OFFLOADING */
3107 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
3108 remain_on_channel_ndev
= wl_cfg80211_get_remain_on_channel_ndev(cfg
);
3109 if (remain_on_channel_ndev
) {
3110 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
3111 wl_notify_escan_complete(cfg
, remain_on_channel_ndev
, true, true);
3113 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
3116 /* Arm scan timeout timer */
3117 mod_timer(&cfg
->scan_timeout
, jiffies
+ msecs_to_jiffies(scan_timer_interval_ms
));
3118 if (request
) { /* scan bss */
3119 ssids
= request
->ssids
;
3121 for (i
= 0; i
< request
->n_ssids
; i
++) {
3122 if (ssids
[i
].ssid_len
&&
3123 IS_P2P_SSID(ssids
[i
].ssid
, ssids
[i
].ssid_len
)) {
3129 if (cfg
->p2p_supported
) {
3130 /* p2p scan trigger */
3131 if (p2p_on(cfg
) == false) {
3132 /* p2p on at the first time */
3134 wl_cfgp2p_set_firm_p2p(cfg
);
3135 get_primary_mac(cfg
, &primary_mac
);
3136 wl_cfgp2p_generate_bss_mac(cfg
, &primary_mac
);
3137 #if defined(P2P_IE_MISSING_FIX)
3138 cfg
->p2p_prb_noti
= false;
3141 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
3142 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
3143 p2p_scan(cfg
) = true;
3146 /* legacy scan trigger
3147 * So, we have to disable p2p discovery if p2p discovery is on
3149 if (cfg
->p2p_supported
) {
3150 p2p_scan(cfg
) = false;
3151 /* If Netdevice is not equals to primary and p2p is on
3152 * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
3155 if (p2p_scan(cfg
) == false) {
3156 if (wl_get_p2p_status(cfg
, DISCOVERY_ON
)) {
3157 err
= wl_cfgp2p_discover_enable_search(cfg
,
3159 if (unlikely(err
)) {
3166 if (!cfg
->p2p_supported
|| !p2p_scan(cfg
)) {
3167 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
,
3168 ndev
->ieee80211_ptr
)) < 0) {
3169 WL_ERR(("Find p2p index from ndev(%p) failed\n",
3175 if (request
&& (interworking_ie
=
3176 wl_cfg80211_find_interworking_ie(
3177 request
->ie
, request
->ie_len
)) != NULL
) {
3178 if ((err
= wl_cfg80211_add_iw_ie(cfg
, ndev
, bssidx
,
3179 VNDR_IE_CUSTOM_FLAG
, interworking_ie
->id
,
3180 interworking_ie
->data
,
3181 interworking_ie
->len
)) != BCME_OK
) {
3182 WL_ERR(("Failed to add interworking IE"));
3184 } else if (cfg
->wl11u
) {
3185 /* we have to clear IW IE and disable gratuitous APR */
3186 wl_cfg80211_clear_iw_ie(cfg
, ndev
, bssidx
);
3187 err
= wldev_iovar_setint_bsscfg(ndev
, "grat_arp",
3189 /* we don't care about error here
3190 * because the only failure case is unsupported,
3193 if (unlikely(err
)) {
3194 WL_ERR(("Set grat_arp failed:(%d) Ignore!\n", err
));
3200 err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
,
3201 ndev_to_cfgdev(ndev
),
3202 bssidx
, VNDR_IE_PRBREQ_FLAG
, request
->ie
,
3206 if (unlikely(err
)) {
3207 // terence 20161023: let it scan in SoftAP mode
3213 } else { /* scan in ibss */
3217 if (request
&& cfg
->p2p_supported
) {
3218 WL_TRACE_HW4(("START SCAN\n"));
3219 DHD_OS_SCAN_WAKE_LOCK_TIMEOUT((dhd_pub_t
*)(cfg
->pub
),
3220 SCAN_WAKE_LOCK_TIMEOUT
);
3221 DHD_DISABLE_RUNTIME_PM((dhd_pub_t
*)(cfg
->pub
));
3224 if (cfg
->p2p_supported
) {
3225 if (request
&& p2p_on(cfg
) && p2p_scan(cfg
)) {
3227 /* find my listen channel */
3228 cfg
->afx_hdl
->my_listen_chan
=
3229 wl_find_listen_channel(cfg
, request
->ie
,
3231 err
= wl_cfgp2p_enable_discovery(cfg
, ndev
,
3232 request
->ie
, request
->ie_len
);
3234 if (unlikely(err
)) {
3239 err
= wl_do_escan(cfg
, wiphy
, ndev
, request
);
3247 cfg
->scan_request
= request
;
3248 wl_set_drv_status(cfg
, SCANNING
, ndev
);
3253 if (err
== BCME_BUSY
|| err
== BCME_NOTREADY
) {
3254 WL_ERR(("Scan err = (%d), busy?%d", err
, -EBUSY
));
3256 } else if ((err
== BCME_EPERM
) && cfg
->scan_suppressed
) {
3257 WL_ERR(("Scan not permitted due to scan suppress\n"));
3260 /* For all other fw errors, use a generic error code as return
3261 * value to cfg80211 stack
3266 #define SCAN_EBUSY_RETRY_LIMIT 20
3267 if (err
== -EBUSY
) {
3268 if (busy_count
++ > SCAN_EBUSY_RETRY_LIMIT
) {
3269 struct ether_addr bssid
;
3271 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
3272 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
3273 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
3275 WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
3276 wl_get_drv_status(cfg
, SCANNING
, ndev
),
3277 wl_get_drv_status(cfg
, SCAN_ABORTING
, ndev
),
3278 wl_get_drv_status(cfg
, CONNECTING
, ndev
),
3279 wl_get_drv_status(cfg
, CONNECTED
, ndev
),
3280 wl_get_drv_status(cfg
, DISCONNECTING
, ndev
),
3281 wl_get_drv_status(cfg
, AP_CREATING
, ndev
),
3282 wl_get_drv_status(cfg
, AP_CREATED
, ndev
),
3283 wl_get_drv_status(cfg
, SENDING_ACT_FRM
, ndev
),
3284 wl_get_drv_status(cfg
, SENDING_ACT_FRM
, ndev
)));
3286 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
3287 if (dhdp
->memdump_enabled
) {
3288 dhdp
->memdump_type
= DUMP_TYPE_SCAN_BUSY
;
3289 dhd_bus_mem_dump(dhdp
);
3291 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
3293 bzero(&bssid
, sizeof(bssid
));
3294 if ((ret
= wldev_ioctl_get(ndev
, WLC_GET_BSSID
,
3295 &bssid
, ETHER_ADDR_LEN
)) == 0)
3296 WL_ERR(("FW is connected with " MACDBG
"/n",
3297 MAC2STRDBG(bssid
.octet
)));
3299 WL_ERR(("GET BSSID failed with %d\n", ret
));
3301 wl_cfg80211_scan_abort(cfg
);
3304 /* Hold the context for 400msec, so that 10 subsequent scans
3305 * can give a buffer of 4sec which is enough to
3306 * cover any on-going scan in the firmware
3308 WL_DBG(("Enforcing delay for EBUSY case \n"));
3315 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
3316 if (timer_pending(&cfg
->scan_timeout
))
3317 del_timer_sync(&cfg
->scan_timeout
);
3318 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t
*)(cfg
->pub
));
3319 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
3320 cfg
->scan_request
= NULL
;
3321 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
3327 #if defined(WL_CFG80211_P2P_DEV_IF)
3328 wl_cfg80211_scan(struct wiphy
*wiphy
, struct cfg80211_scan_request
*request
)
3330 wl_cfg80211_scan(struct wiphy
*wiphy
, struct net_device
*ndev
,
3331 struct cfg80211_scan_request
*request
)
3332 #endif /* WL_CFG80211_P2P_DEV_IF */
3335 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3336 #if defined(WL_CFG80211_P2P_DEV_IF)
3337 struct net_device
*ndev
= wdev_to_wlc_ndev(request
->wdev
, cfg
);
3338 #endif /* WL_CFG80211_P2P_DEV_IF */
3340 WL_DBG(("Enter\n"));
3341 RETURN_EIO_IF_NOT_UP(cfg
);
3344 #ifdef WL_CFG80211_P2P_DEV_IF
3345 PRINT_WDEV_INFO(request
->wdev
);
3347 PRINT_WDEV_INFO(ndev
);
3348 #endif /* WL_CFG80211_P2P_DEV_IF */
3349 #endif /* DHD_IFDEBUG */
3351 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
3352 if (wl_cfg_multip2p_operational(cfg
)) {
3353 WL_ERR(("wlan0 scan failed, p2p devices are operational"));
3358 mutex_lock(&cfg
->usr_sync
);
3359 err
= __wl_cfg80211_scan(wiphy
, ndev
, request
, NULL
);
3360 if (unlikely(err
)) {
3361 WL_ERR(("scan error (%d)\n", err
));
3363 mutex_unlock(&cfg
->usr_sync
);
3364 #ifdef WL_DRV_AVOID_SCANCACHE
3365 /* Reset roam cache after successful scan request */
3366 #endif /* WL_DRV_AVOID_SCANCACHE */
3370 static s32
wl_set_rts(struct net_device
*dev
, u32 rts_threshold
)
3374 err
= wldev_iovar_setint(dev
, "rtsthresh", rts_threshold
);
3375 if (unlikely(err
)) {
3376 WL_ERR(("Error (%d)\n", err
));
3382 static s32
wl_set_frag(struct net_device
*dev
, u32 frag_threshold
)
3386 err
= wldev_iovar_setint_bsscfg(dev
, "fragthresh", frag_threshold
, 0);
3387 if (unlikely(err
)) {
3388 WL_ERR(("Error (%d)\n", err
));
3394 static s32
wl_set_retry(struct net_device
*dev
, u32 retry
, bool l
)
3397 u32 cmd
= (l
? WLC_SET_LRL
: WLC_SET_SRL
);
3399 retry
= htod32(retry
);
3400 err
= wldev_ioctl_set(dev
, cmd
, &retry
, sizeof(retry
));
3401 if (unlikely(err
)) {
3402 WL_ERR(("cmd (%d) , error (%d)\n", cmd
, err
));
3408 static s32
wl_cfg80211_set_wiphy_params(struct wiphy
*wiphy
, u32 changed
)
3410 struct bcm_cfg80211
*cfg
= (struct bcm_cfg80211
*)wiphy_priv(wiphy
);
3411 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
3414 RETURN_EIO_IF_NOT_UP(cfg
);
3415 WL_DBG(("Enter\n"));
3416 if (changed
& WIPHY_PARAM_RTS_THRESHOLD
&&
3417 (cfg
->conf
->rts_threshold
!= wiphy
->rts_threshold
)) {
3418 cfg
->conf
->rts_threshold
= wiphy
->rts_threshold
;
3419 err
= wl_set_rts(ndev
, cfg
->conf
->rts_threshold
);
3423 if (changed
& WIPHY_PARAM_FRAG_THRESHOLD
&&
3424 (cfg
->conf
->frag_threshold
!= wiphy
->frag_threshold
)) {
3425 cfg
->conf
->frag_threshold
= wiphy
->frag_threshold
;
3426 err
= wl_set_frag(ndev
, cfg
->conf
->frag_threshold
);
3430 if (changed
& WIPHY_PARAM_RETRY_LONG
&&
3431 (cfg
->conf
->retry_long
!= wiphy
->retry_long
)) {
3432 cfg
->conf
->retry_long
= wiphy
->retry_long
;
3433 err
= wl_set_retry(ndev
, cfg
->conf
->retry_long
, true);
3437 if (changed
& WIPHY_PARAM_RETRY_SHORT
&&
3438 (cfg
->conf
->retry_short
!= wiphy
->retry_short
)) {
3439 cfg
->conf
->retry_short
= wiphy
->retry_short
;
3440 err
= wl_set_retry(ndev
, cfg
->conf
->retry_short
, false);
3441 if (err
!= BCME_OK
) {
3449 channel_to_chanspec(struct wiphy
*wiphy
, struct net_device
*dev
, u32 channel
, u32 bw_cap
)
3451 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3453 wl_uint32_list_t
*list
;
3455 chanspec_t c
= 0, ret_c
= 0;
3456 int bw
= 0, tmp_bw
= 0;
3459 u16 kflags
= in_atomic() ? GFP_ATOMIC
: GFP_KERNEL
;
3460 #define LOCAL_BUF_SIZE 1024
3461 buf
= (u8
*) kzalloc(LOCAL_BUF_SIZE
, kflags
);
3463 WL_ERR(("buf memory alloc failed\n"));
3467 err
= wldev_iovar_getbuf_bsscfg(dev
, "chanspecs", NULL
,
3468 0, buf
, LOCAL_BUF_SIZE
, 0, &cfg
->ioctl_buf_sync
);
3469 if (err
!= BCME_OK
) {
3470 WL_ERR(("get chanspecs failed with %d\n", err
));
3474 list
= (wl_uint32_list_t
*)(void *)buf
;
3475 for (i
= 0; i
< dtoh32(list
->count
); i
++) {
3476 c
= dtoh32(list
->element
[i
]);
3477 if (channel
<= CH_MAX_2G_CHANNEL
) {
3478 if (!CHSPEC_IS20(c
))
3480 if (channel
== CHSPEC_CHANNEL(c
)) {
3486 tmp_c
= wf_chspec_ctlchan(c
);
3487 tmp_bw
= bw2cap
[CHSPEC_BW(c
) >> WL_CHANSPEC_BW_SHIFT
];
3488 if (tmp_c
!= channel
)
3491 if ((tmp_bw
> bw
) && (tmp_bw
<= bw_cap
)) {
3501 #undef LOCAL_BUF_SIZE
3502 WL_INFORM(("return chanspec %x %d\n", ret_c
, bw
));
3507 wl_cfg80211_ibss_vsie_set_buffer(struct net_device
*dev
, vndr_ie_setbuf_t
*ibss_vsie
,
3510 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
3512 if (cfg
!= NULL
&& ibss_vsie
!= NULL
) {
3513 if (cfg
->ibss_vsie
!= NULL
) {
3514 kfree(cfg
->ibss_vsie
);
3516 cfg
->ibss_vsie
= ibss_vsie
;
3517 cfg
->ibss_vsie_len
= ibss_vsie_len
;
3522 wl_cfg80211_ibss_vsie_free(struct bcm_cfg80211
*cfg
)
3524 /* free & initiralize VSIE (Vendor Specific IE) */
3525 if (cfg
->ibss_vsie
!= NULL
) {
3526 kfree(cfg
->ibss_vsie
);
3527 cfg
->ibss_vsie
= NULL
;
3528 cfg
->ibss_vsie_len
= 0;
3533 wl_cfg80211_ibss_vsie_delete(struct net_device
*dev
)
3535 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
3536 char *ioctl_buf
= NULL
;
3537 s32 ret
= BCME_OK
, bssidx
;
3539 if (cfg
!= NULL
&& cfg
->ibss_vsie
!= NULL
) {
3540 ioctl_buf
= kmalloc(WLC_IOCTL_MEDLEN
, GFP_KERNEL
);
3542 WL_ERR(("ioctl memory alloc failed\n"));
3546 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
3547 WL_ERR(("Find index failed\n"));
3551 /* change the command from "add" to "del" */
3552 strncpy(cfg
->ibss_vsie
->cmd
, "del", VNDR_IE_CMD_LEN
- 1);
3553 cfg
->ibss_vsie
->cmd
[VNDR_IE_CMD_LEN
- 1] = '\0';
3555 ret
= wldev_iovar_setbuf_bsscfg(dev
, "vndr_ie",
3556 cfg
->ibss_vsie
, cfg
->ibss_vsie_len
,
3557 ioctl_buf
, WLC_IOCTL_MEDLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
3558 WL_ERR(("ret=%d\n", ret
));
3560 if (ret
== BCME_OK
) {
3561 /* free & initiralize VSIE */
3562 kfree(cfg
->ibss_vsie
);
3563 cfg
->ibss_vsie
= NULL
;
3564 cfg
->ibss_vsie_len
= 0;
3575 #ifdef WLAIBSS_MCHAN
3576 static bcm_struct_cfgdev
*
3577 bcm_cfg80211_add_ibss_if(struct wiphy
*wiphy
, char *name
)
3580 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3581 struct wireless_dev
* wdev
= NULL
;
3582 struct net_device
*new_ndev
= NULL
;
3583 struct net_device
*primary_ndev
= NULL
;
3585 wl_aibss_if_t aibss_if
;
3586 wl_if_event_info
*event
= NULL
;
3588 if (cfg
->ibss_cfgdev
!= NULL
) {
3589 WL_ERR(("IBSS interface %s already exists\n", name
));
3593 WL_ERR(("Try to create IBSS interface %s\n", name
));
3594 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
3595 /* generate a new MAC address for the IBSS interface */
3596 get_primary_mac(cfg
, &cfg
->ibss_if_addr
);
3597 cfg
->ibss_if_addr
.octet
[4] ^= 0x40;
3598 memset(&aibss_if
, sizeof(aibss_if
), 0);
3599 memcpy(&aibss_if
.addr
, &cfg
->ibss_if_addr
, sizeof(aibss_if
.addr
));
3600 aibss_if
.chspec
= 0;
3601 aibss_if
.len
= sizeof(aibss_if
);
3603 cfg
->bss_pending_op
= TRUE
;
3604 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
3605 err
= wldev_iovar_setbuf(primary_ndev
, "aibss_ifadd", &aibss_if
,
3606 sizeof(aibss_if
), cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
3608 WL_ERR(("IOVAR aibss_ifadd failed with error %d\n", err
));
3611 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
3612 !cfg
->bss_pending_op
, msecs_to_jiffies(MAX_WAIT_TIME
));
3613 if (timeout
<= 0 || cfg
->bss_pending_op
)
3616 event
= &cfg
->if_event_info
;
3617 /* By calling wl_cfg80211_allocate_if (dhd_allocate_if eventually) we give the control
3618 * over this net_device interface to dhd_linux, hence the interface is managed by dhd_liux
3619 * and will be freed by dhd_detach unless it gets unregistered before that. The
3620 * wireless_dev instance new_ndev->ieee80211_ptr associated with this net_device will
3621 * be freed by wl_dealloc_netinfo
3623 new_ndev
= wl_cfg80211_allocate_if(cfg
, event
->ifidx
, event
->name
,
3624 event
->mac
, event
->bssidx
, event
->name
);
3625 if (new_ndev
== NULL
)
3627 wdev
= kzalloc(sizeof(*wdev
), GFP_KERNEL
);
3630 wdev
->wiphy
= wiphy
;
3631 wdev
->iftype
= NL80211_IFTYPE_ADHOC
;
3632 wdev
->netdev
= new_ndev
;
3633 new_ndev
->ieee80211_ptr
= wdev
;
3634 SET_NETDEV_DEV(new_ndev
, wiphy_dev(wdev
->wiphy
));
3636 /* rtnl lock must have been acquired, if this is not the case, wl_cfg80211_register_if
3637 * needs to be modified to take one parameter (bool need_rtnl_lock)
3640 if (wl_cfg80211_register_if(cfg
, event
->ifidx
, new_ndev
, FALSE
) != BCME_OK
)
3643 wl_alloc_netinfo(cfg
, new_ndev
, wdev
, WL_MODE_IBSS
, PM_ENABLE
, event
->bssidx
);
3644 cfg
->ibss_cfgdev
= ndev_to_cfgdev(new_ndev
);
3645 WL_ERR(("IBSS interface %s created\n", new_ndev
->name
));
3646 return cfg
->ibss_cfgdev
;
3649 WL_ERR(("failed to create IBSS interface %s \n", name
));
3650 cfg
->bss_pending_op
= FALSE
;
3652 wl_cfg80211_remove_if(cfg
, event
->ifidx
, new_ndev
, FALSE
);
3659 bcm_cfg80211_del_ibss_if(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
)
3662 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
3663 struct net_device
*ndev
= NULL
;
3664 struct net_device
*primary_ndev
= NULL
;
3667 if (!cfgdev
|| cfg
->ibss_cfgdev
!= cfgdev
|| ETHER_ISNULLADDR(&cfg
->ibss_if_addr
.octet
))
3669 ndev
= (struct net_device
*)cfgdev_to_ndev(cfg
->ibss_cfgdev
);
3670 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
3672 cfg
->bss_pending_op
= TRUE
;
3673 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
3674 err
= wldev_iovar_setbuf(primary_ndev
, "aibss_ifdel", &cfg
->ibss_if_addr
,
3675 sizeof(cfg
->ibss_if_addr
), cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
3677 WL_ERR(("IOVAR aibss_ifdel failed with error %d\n", err
));
3680 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
3681 !cfg
->bss_pending_op
, msecs_to_jiffies(MAX_WAIT_TIME
));
3682 if (timeout
<= 0 || cfg
->bss_pending_op
) {
3683 WL_ERR(("timeout in waiting IF_DEL event\n"));
3687 wl_cfg80211_remove_if(cfg
, cfg
->if_event_info
.ifidx
, ndev
, FALSE
);
3688 cfg
->ibss_cfgdev
= NULL
;
3692 cfg
->bss_pending_op
= FALSE
;
3695 #endif /* WLAIBSS_MCHAN */
3699 wl_cfg80211_interface_ops(struct bcm_cfg80211
*cfg
,
3700 struct net_device
*ndev
, s32 bsscfg_idx
,
3701 enum nl80211_iftype iface_type
, s32 del
, u8
*addr
)
3703 wl_interface_create_t iface
;
3705 wl_interface_info_t
*info
;
3707 bzero(&iface
, sizeof(wl_interface_create_t
));
3709 iface
.ver
= WL_INTERFACE_CREATE_VER
;
3711 if (iface_type
== NL80211_IFTYPE_AP
)
3712 iface
.flags
= WL_INTERFACE_CREATE_AP
;
3714 iface
.flags
= WL_INTERFACE_CREATE_STA
;
3717 ret
= wldev_iovar_setbuf(ndev
, "interface_remove",
3718 NULL
, 0, cfg
->ioctl_buf
, WLC_IOCTL_MEDLEN
, NULL
);
3721 memcpy(&iface
.mac_addr
.octet
, addr
, ETH_ALEN
);
3722 iface
.flags
|= WL_INTERFACE_MAC_USE
;
3724 ret
= wldev_iovar_getbuf(ndev
, "interface_create",
3725 &iface
, sizeof(wl_interface_create_t
),
3726 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
3729 info
= (wl_interface_info_t
*)cfg
->ioctl_buf
;
3730 WL_DBG(("wl interface create success!! bssidx:%d \n",
3736 WL_ERR(("Interface %s failed!! ret %d\n",
3737 del
? "remove" : "create", ret
));
3743 wl_cfg80211_interface_ops(struct bcm_cfg80211
*cfg
,
3744 struct net_device
*ndev
, s32 bsscfg_idx
,
3745 enum nl80211_iftype iface_type
, s32 del
, u8
*addr
)
3748 struct wl_interface_create_v2 iface
;
3749 wl_interface_create_v3_t iface_v3
;
3750 struct wl_interface_info_v1
*info
;
3751 wl_interface_info_v2_t
*info_v2
;
3752 enum wl_interface_type iftype
;
3754 bool use_iface_info_v2
= false;
3755 u8 ioctl_buf
[WLC_IOCTL_SMLEN
];
3758 ret
= wldev_iovar_setbuf(ndev
, "interface_remove",
3759 NULL
, 0, ioctl_buf
, sizeof(ioctl_buf
), NULL
);
3761 WL_ERR(("Interface remove failed!! ret %d\n", ret
));
3765 /* Interface create */
3766 bzero(&iface
, sizeof(iface
));
3768 * flags field is still used along with iftype inorder to support the old version of the
3769 * FW work with the latest app changes.
3771 if (iface_type
== NL80211_IFTYPE_AP
) {
3772 iftype
= WL_INTERFACE_TYPE_AP
;
3773 ifflags
= WL_INTERFACE_CREATE_AP
;
3775 iftype
= WL_INTERFACE_TYPE_STA
;
3776 ifflags
= WL_INTERFACE_CREATE_STA
;
3779 ifflags
|= WL_INTERFACE_MAC_USE
;
3782 /* Pass ver = 0 for fetching the interface_create iovar version */
3783 ret
= wldev_iovar_getbuf(ndev
, "interface_create",
3784 &iface
, sizeof(struct wl_interface_create_v2
),
3785 ioctl_buf
, sizeof(ioctl_buf
), NULL
);
3786 if (ret
== BCME_UNSUPPORTED
) {
3787 WL_ERR(("interface_create iovar not supported\n"));
3789 } else if ((ret
== 0) && *((uint32
*)ioctl_buf
) == WL_INTERFACE_CREATE_VER_3
) {
3790 WL_DBG(("interface_create version 3\n"));
3791 use_iface_info_v2
= true;
3792 bzero(&iface_v3
, sizeof(wl_interface_create_v3_t
));
3793 iface_v3
.ver
= WL_INTERFACE_CREATE_VER_3
;
3794 iface_v3
.iftype
= iftype
;
3795 iface_v3
.flags
= ifflags
;
3797 memcpy(&iface_v3
.mac_addr
.octet
, addr
, ETH_ALEN
);
3799 ret
= wldev_iovar_getbuf(ndev
, "interface_create",
3800 &iface_v3
, sizeof(wl_interface_create_v3_t
),
3801 ioctl_buf
, sizeof(ioctl_buf
), NULL
);
3804 /* On any other error, attempt with iovar version 2 */
3805 WL_DBG(("interface_create version 2. get_ver:%d\n", ret
));
3806 iface
.ver
= WL_INTERFACE_CREATE_VER_2
;
3807 iface
.iftype
= iftype
;
3808 iface
.flags
= ifflags
;
3810 memcpy(&iface
.mac_addr
.octet
, addr
, ETH_ALEN
);
3812 ret
= wldev_iovar_getbuf(ndev
, "interface_create",
3813 &iface
, sizeof(struct wl_interface_create_v2
),
3814 ioctl_buf
, sizeof(ioctl_buf
), NULL
);
3818 if (unlikely(ret
)) {
3819 WL_ERR(("Interface create failed!! ret %d\n", ret
));
3824 if (use_iface_info_v2
== true) {
3825 info_v2
= (wl_interface_info_v2_t
*)ioctl_buf
;
3826 ret
= info_v2
->bsscfgidx
;
3829 info
= (struct wl_interface_info_v1
*)ioctl_buf
;
3830 ret
= info
->bsscfgidx
;
3833 WL_DBG(("wl interface create success!! bssidx:%d \n", ret
));
3839 wl_customer6_legacy_chip_check(struct bcm_cfg80211
*cfg
,
3840 struct net_device
*ndev
)
3843 wlc_rev_info_t revinfo
;
3846 /* Get the device rev info */
3847 memset(&revinfo
, 0, sizeof(revinfo
));
3848 ret
= wldev_ioctl_get(ndev
, WLC_GET_REVINFO
, &revinfo
, sizeof(revinfo
));
3850 WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__
, ret
));
3855 WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__
,
3856 dtoh32(revinfo
.deviceid
), dtoh32(revinfo
.vendorid
), dtoh32(revinfo
.chipnum
)));
3857 chipnum
= revinfo
.chipnum
;
3858 if ((chipnum
== BCM4350_CHIP_ID
) || (chipnum
== BCM4355_CHIP_ID
) ||
3859 (chipnum
== BCM4345_CHIP_ID
) || (chipnum
== BCM43430_CHIP_ID
)) {
3868 wl_bss_iovar_war(struct bcm_cfg80211
*cfg
,
3869 struct net_device
*ndev
, s32
*val
)
3871 if (wl_customer6_legacy_chip_check(cfg
, ndev
)) {
3872 /* Few firmware branches have issues in bss iovar handling and
3873 * that can't be changed since they are in production.
3875 if (*val
== WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE
) {
3876 *val
= WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE
;
3877 } else if (*val
== WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE
) {
3878 *val
= WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE
;
3880 /* Ignore for other bss enums */
3883 WL_ERR(("wl bss %d\n", *val
));
3888 wl_cfg80211_add_del_bss(struct bcm_cfg80211
*cfg
,
3889 struct net_device
*ndev
, s32 bsscfg_idx
,
3890 enum nl80211_iftype iface_type
, s32 del
, u8
*addr
)
3898 struct ether_addr ea
;
3901 WL_INFORM(("iface_type:%d del:%d \n", iface_type
, del
));
3903 bzero(&bss_setbuf
, sizeof(bss_setbuf
));
3905 /* AP=2, STA=3, up=1, down=0, val=-1 */
3907 val
= WLC_AP_IOV_OP_DELETE
;
3908 } else if (iface_type
== NL80211_IFTYPE_AP
) {
3909 /* Add/role change to AP Interface */
3910 WL_DBG(("Adding AP Interface \n"));
3911 val
= WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE
;
3912 } else if (iface_type
== NL80211_IFTYPE_STATION
) {
3913 /* Add/role change to STA Interface */
3914 WL_DBG(("Adding STA Interface \n"));
3915 val
= WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE
;
3917 WL_ERR((" add_del_bss NOT supported for IFACE type:0x%x", iface_type
));
3922 wl_bss_iovar_war(cfg
, ndev
, &val
);
3925 bss_setbuf
.cfg
= htod32(bsscfg_idx
);
3926 bss_setbuf
.val
= htod32(val
);
3929 memcpy(&bss_setbuf
.ea
.octet
, addr
, ETH_ALEN
);
3932 WL_DBG(("wl bss %d bssidx:%d iface:%s \n", val
, bsscfg_idx
, ndev
->name
));
3933 ret
= wldev_iovar_setbuf(ndev
, "bss", &bss_setbuf
, sizeof(bss_setbuf
),
3934 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
3936 WL_ERR(("'bss %d' failed with %d\n", val
, ret
));
3942 wl_cfg80211_bss_up(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 bsscfg_idx
, s32 bss_up
)
3945 s32 val
= bss_up
? 1 : 0;
3952 bss_setbuf
.cfg
= htod32(bsscfg_idx
);
3953 bss_setbuf
.val
= htod32(val
);
3955 WL_DBG(("wl bss -C %d %s\n", bsscfg_idx
, bss_up
? "up" : "down"));
3956 ret
= wldev_iovar_setbuf(ndev
, "bss", &bss_setbuf
, sizeof(bss_setbuf
),
3957 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
3960 WL_ERR(("'bss %d' failed with %d\n", bss_up
, ret
));
3967 wl_cfg80211_bss_isup(struct net_device
*ndev
, int bsscfg_idx
)
3973 /* Check if the BSS is up */
3975 result
= wldev_iovar_getbuf_bsscfg(ndev
, "bss", &bsscfg_idx
,
3976 sizeof(bsscfg_idx
), getbuf
, sizeof(getbuf
), 0, NULL
);
3978 WL_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx
, result
));
3979 WL_ERR(("NOTE: this ioctl error is normal "
3980 "when the BSS has not been created yet.\n"));
3982 val
= *(int*)getbuf
;
3984 WL_DBG(("wl bss -C %d = %d\n", bsscfg_idx
, val
));
3985 isup
= (val
? TRUE
: FALSE
);
3991 cfg80211_to_wl_iftype(uint16 type
, uint16
*role
, uint16
*mode
)
3994 case NL80211_IFTYPE_STATION
:
3995 *role
= WLC_E_IF_ROLE_STA
;
3996 *mode
= WL_MODE_BSS
;
3998 case NL80211_IFTYPE_AP
:
3999 *role
= WLC_E_IF_ROLE_AP
;
4002 case NL80211_IFTYPE_P2P_GO
:
4003 *role
= WLC_E_IF_ROLE_P2P_GO
;
4006 case NL80211_IFTYPE_P2P_CLIENT
:
4007 *role
= WLC_E_IF_ROLE_P2P_CLIENT
;
4008 *mode
= WL_MODE_BSS
;
4010 case NL80211_IFTYPE_MONITOR
:
4011 WL_ERR(("Unsupported mode \n"));
4012 return BCME_UNSUPPORTED
;
4013 case NL80211_IFTYPE_ADHOC
:
4014 *role
= WLC_E_IF_ROLE_IBSS
;
4015 *mode
= WL_MODE_IBSS
;
4018 WL_ERR(("Unknown interface type:0x%x\n", type
));
4025 wl_if_to_cfg80211_type(uint16 role
)
4028 case WLC_E_IF_ROLE_STA
:
4029 return NL80211_IFTYPE_STATION
;
4030 case WLC_E_IF_ROLE_AP
:
4031 return NL80211_IFTYPE_AP
;
4032 case WLC_E_IF_ROLE_P2P_GO
:
4033 return NL80211_IFTYPE_P2P_GO
;
4034 case WLC_E_IF_ROLE_P2P_CLIENT
:
4035 return NL80211_IFTYPE_P2P_CLIENT
;
4036 case WLC_E_IF_ROLE_IBSS
:
4037 return NL80211_IFTYPE_ADHOC
;
4039 WL_ERR(("Unknown interface role:0x%x. Forcing type station\n", role
));
4045 wl_cfg80211_post_ifcreate(struct net_device
*ndev
,
4046 wl_if_event_info
*event
, u8
*addr
,
4047 const char *name
, bool rtnl_lock_reqd
)
4049 struct bcm_cfg80211
*cfg
;
4050 struct net_device
*primary_ndev
;
4051 struct net_device
*new_ndev
= NULL
;
4052 struct wireless_dev
*wdev
= NULL
;
4057 u8 mac_addr
[ETH_ALEN
];
4059 if (!ndev
|| !event
) {
4060 WL_ERR(("Wrong arg\n"));
4064 cfg
= wl_get_cfg(ndev
);
4066 WL_ERR(("cfg null\n"));
4070 WL_DBG(("Enter. role:%d ifidx:%d bssidx:%d\n",
4071 event
->role
, event
->ifidx
, event
->bssidx
));
4072 if (!event
->ifidx
|| !event
->bssidx
) {
4073 /* Fw returned primary idx (0) for virtual interface */
4074 WL_ERR(("Wrong index. ifidx:%d bssidx:%d \n",
4075 event
->ifidx
, event
->bssidx
));
4079 iface_type
= wl_if_to_cfg80211_type(event
->role
);
4080 if (iface_type
< 0) {
4081 /* Unknown iface type */
4082 WL_ERR(("Wrong iface type \n"));
4086 if (cfg80211_to_wl_iftype(iface_type
, &role
, &mode
) < 0) {
4087 /* Unsupported operating mode */
4088 WL_ERR(("Unsupported operating mode \n"));
4092 WL_DBG(("mac_ptr:%p name:%s role:%d nl80211_iftype:%d " MACDBG
"\n",
4093 addr
, name
, event
->role
, iface_type
, MAC2STRDBG(event
->mac
)));
4095 /* If iface name is not provided, use dongle ifname */
4100 /* If mac address is not set, use primary mac with locally administered
4103 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
4104 memcpy(mac_addr
, primary_ndev
->dev_addr
, ETH_ALEN
);
4105 #ifndef CUSTOMER_HW6
4106 /* For customer6 builds, use primary mac address for virtual interface */
4107 mac_addr
[0] |= 0x02;
4108 #endif /* CUSTOMER_HW6 */
4112 new_ndev
= wl_cfg80211_allocate_if(cfg
, event
->ifidx
,
4113 name
, addr
, event
->bssidx
, event
->name
);
4115 WL_ERR(("I/F allocation failed! \n"));
4118 WL_DBG(("I/F allocation succeeded! ifidx:0x%x bssidx:0x%x \n",
4119 event
->ifidx
, event
->bssidx
));
4122 wdev
= kzalloc(sizeof(*wdev
), GFP_KERNEL
);
4124 WL_ERR(("wireless_dev alloc failed! \n"));
4128 wdev
->wiphy
= bcmcfg_to_wiphy(cfg
);
4129 wdev
->iftype
= iface_type
;
4130 new_ndev
->ieee80211_ptr
= wdev
;
4131 SET_NETDEV_DEV(new_ndev
, wiphy_dev(wdev
->wiphy
));
4133 /* Check whether mac addr is in sync with fw. If not,
4134 * apply it using cur_etheraddr.
4136 if (memcmp(addr
, event
->mac
, ETH_ALEN
) != 0) {
4137 ret
= wldev_iovar_setbuf_bsscfg(new_ndev
, "cur_etheraddr",
4138 addr
, ETH_ALEN
, cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
,
4139 event
->bssidx
, &cfg
->ioctl_buf_sync
);
4140 if (unlikely(ret
)) {
4141 WL_ERR(("set cur_etheraddr Error (%d)\n", ret
));
4144 memcpy(new_ndev
->dev_addr
, addr
, ETH_ALEN
);
4145 WL_ERR(("Applying updated mac address to firmware\n"));
4148 if (wl_cfg80211_register_if(cfg
, event
->ifidx
, new_ndev
, rtnl_lock_reqd
) != BCME_OK
) {
4149 WL_ERR(("IFACE register failed \n"));
4153 /* Initialize with the station mode params */
4154 ret
= wl_alloc_netinfo(cfg
, new_ndev
, wdev
, mode
,
4155 PM_ENABLE
, event
->bssidx
);
4156 if (unlikely(ret
)) {
4157 WL_ERR(("wl_alloc_netinfo Error (%d)\n", ret
));
4161 /* Apply the mode & infra setting based on iftype */
4162 if ((ret
= wl_config_ifmode(cfg
, new_ndev
, iface_type
)) < 0) {
4163 WL_ERR(("config ifmode failure (%d)\n", ret
));
4167 if (mode
== WL_MODE_AP
) {
4168 wl_set_drv_status(cfg
, AP_CREATING
, new_ndev
);
4171 WL_INFORM(("Host Network Interface (%s) for Secondary I/F created."
4172 " cfg_iftype:%d wl_role:%d\n", new_ndev
->name
, iface_type
, event
->role
));
4180 wl_cfg80211_remove_if(cfg
, event
->ifidx
, new_ndev
, rtnl_lock_reqd
);
4186 wl_cfg80211_cleanup_virtual_ifaces(struct net_device
*dev
, bool rtnl_lock_reqd
)
4188 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
4189 struct net_info
*iter
, *next
;
4190 struct net_device
*primary_ndev
;
4192 /* Note: This function will clean up only the network interface and host
4193 * data structures. The firmware interface clean up will happen in the
4194 * during chip reset (ifconfig wlan0 down for built-in drivers/rmmod
4195 * context for the module case).
4197 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
4198 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4199 #pragma GCC diagnostic push
4200 #pragma GCC diagnostic ignored "-Wcast-qual"
4202 for_each_ndev(cfg
, iter
, next
) {
4203 if (iter
->ndev
&& (iter
->ndev
!= primary_ndev
)) {
4204 WL_DBG(("Cleaning up iface:%s \n", iter
->ndev
->name
));
4205 wl_cfg80211_post_ifdel(iter
->ndev
, rtnl_lock_reqd
);
4208 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4209 #pragma GCC diagnostic pop
4214 wl_cfg80211_post_ifdel(struct net_device
*ndev
, bool rtnl_lock_reqd
)
4217 struct bcm_cfg80211
*cfg
;
4219 if (!ndev
|| !ndev
->ieee80211_ptr
) {
4220 /* No wireless dev done for this interface */
4224 cfg
= wl_get_cfg(ndev
);
4226 WL_ERR(("cfg null\n"));
4229 ifidx
= dhd_net2idx(((struct dhd_pub
*)(cfg
->pub
))->info
, ndev
);
4230 BCM_REFERENCE(ifidx
);
4232 WL_ERR(("Invalid IF idx for iface:%s\n", ndev
->name
));
4236 WL_DBG(("cfg80211_remove for iface:%s \n", ndev
->name
));
4237 wl_cfg80211_remove_if(cfg
, ifidx
, ndev
, rtnl_lock_reqd
);
4238 cfg
->bss_pending_op
= FALSE
;
4243 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
4244 /* Create a Generic Network Interface and initialize it depending up on
4245 * the interface type
4248 wl_cfg80211_create_iface(struct wiphy
*wiphy
,
4249 enum nl80211_iftype iface_type
,
4250 u8
*mac_addr
, const char *name
)
4252 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4253 struct net_device
*new_ndev
= NULL
;
4254 struct net_device
*primary_ndev
= NULL
;
4258 wl_if_event_info
*event
= NULL
;
4260 struct net_info
*iter
, *next
;
4262 u16 role
= 0, mode
= 0;
4265 WL_DBG(("Enter\n"));
4267 WL_ERR(("Interface name not provided\n"));
4271 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4272 #pragma GCC diagnostic push
4273 #pragma GCC diagnostic ignored "-Wcast-qual"
4275 for_each_ndev(cfg
, iter
, next
) {
4277 if (strcmp(iter
->ndev
->name
, name
) == 0) {
4278 WL_ERR(("Interface name, %s exists !\n", iter
->ndev
->name
));
4283 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4284 #pragma GCC diagnostic pop
4287 primary_ndev
= bcmcfg_to_prmry_ndev(cfg
);
4289 if (likely(!mac_addr
)) {
4290 /* Use primary MAC with the locally administered bit for the
4293 memcpy(addr
, primary_ndev
->dev_addr
, ETH_ALEN
);
4296 /* Use the application provided mac address (if any) */
4297 memcpy(addr
, mac_addr
, ETH_ALEN
);
4300 if ((iface_type
!= NL80211_IFTYPE_STATION
) && (iface_type
!= NL80211_IFTYPE_AP
)) {
4301 WL_ERR(("IFACE type:%d not supported. STA "
4302 "or AP IFACE is only supported\n", iface_type
));
4306 cfg
->bss_pending_op
= TRUE
;
4307 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
4309 /* De-initialize the p2p discovery interface, if operational */
4310 if (p2p_is_on(cfg
)) {
4311 WL_DBG(("Disabling P2P Discovery Interface \n"));
4312 #ifdef WL_CFG80211_P2P_DEV_IF
4313 ret
= wl_cfg80211_scan_stop(cfg
, bcmcfg_to_p2p_wdev(cfg
));
4315 ret
= wl_cfg80211_scan_stop(cfg
, cfg
->p2p_net
);
4317 if (unlikely(ret
< 0)) {
4318 CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret
));
4321 wl_cfgp2p_disable_discovery(cfg
);
4322 wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
) = 0;
4323 p2p_on(cfg
) = false;
4327 * Intialize the firmware I/F.
4329 if (wl_customer6_legacy_chip_check(cfg
, primary_ndev
)) {
4330 /* Use bss iovar instead of interface_create iovar */
4331 ret
= BCME_UNSUPPORTED
;
4333 ret
= wl_cfg80211_interface_ops(cfg
, primary_ndev
, bsscfg_idx
,
4334 iface_type
, 0, addr
);
4336 if (ret
== BCME_UNSUPPORTED
) {
4337 /* Use bssidx 1 by default */
4339 if ((ret
= wl_cfg80211_add_del_bss(cfg
, primary_ndev
,
4340 bsscfg_idx
, iface_type
, 0, addr
)) < 0) {
4343 } else if (ret
< 0) {
4344 WL_ERR(("Interface create failed!! ret:%d \n", ret
));
4351 WL_DBG(("Interface created!! bssidx:%d \n", bsscfg_idx
));
4354 * Wait till the firmware send a confirmation event back.
4356 WL_DBG(("Wait for the FW I/F Event\n"));
4357 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
4358 !cfg
->bss_pending_op
, msecs_to_jiffies(MAX_WAIT_TIME
));
4359 if (timeout
<= 0 || cfg
->bss_pending_op
) {
4360 WL_ERR(("ADD_IF event, didn't come. Return \n"));
4364 event
= &cfg
->if_event_info
;
4366 cfg80211_to_wl_iftype(iface_type
, &role
, &mode
);
4371 * Since FW operation is successful,we can go ahead with the
4372 * the host interface creation.
4374 if ((new_ndev
= wl_cfg80211_post_ifcreate(primary_ndev
,
4375 event
, mac_addr
, name
, false))) {
4376 /* Iface post ops successful. Return ndev/wdev ptr */
4377 return ndev_to_cfgdev(new_ndev
);
4381 cfg
->bss_pending_op
= FALSE
;
4386 wl_cfg80211_del_iface(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
)
4388 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4389 struct net_device
*ndev
= NULL
;
4393 enum nl80211_iftype iface_type
= NL80211_IFTYPE_STATION
;
4395 WL_DBG(("Enter\n"));
4397 /* If any scan is going on, abort it */
4398 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
4399 WL_DBG(("Scan in progress. Aborting the scan!\n"));
4400 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, true, true);
4403 ndev
= (struct net_device
*)cfgdev_to_ndev(cfgdev
);
4404 cfg
->bss_pending_op
= TRUE
;
4405 memset(&cfg
->if_event_info
, 0, sizeof(cfg
->if_event_info
));
4407 /* Delete the firmware interface. "interface_remove" command
4408 * should go on the interface to be deleted
4410 bsscfg_idx
= wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
);
4411 if (bsscfg_idx
<= 0) {
4412 /* validate bsscfgidx */
4413 WL_ERR(("Wrong bssidx! \n"));
4416 WL_DBG(("del interface. bssidx:%d", bsscfg_idx
));
4417 ret
= wl_cfg80211_interface_ops(cfg
, ndev
, bsscfg_idx
,
4418 NL80211_IFTYPE_STATION
, 1, NULL
);
4419 if (ret
== BCME_UNSUPPORTED
) {
4420 if ((ret
= wl_cfg80211_add_del_bss(cfg
, ndev
,
4421 bsscfg_idx
, iface_type
, true, NULL
)) < 0) {
4422 WL_ERR(("DEL bss failed ret:%d \n", ret
));
4425 } else if (ret
< 0) {
4426 WL_ERR(("Interface DEL failed ret:%d \n", ret
));
4430 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
4431 !cfg
->bss_pending_op
, msecs_to_jiffies(MAX_WAIT_TIME
));
4432 if (timeout
<= 0 || cfg
->bss_pending_op
) {
4433 WL_ERR(("timeout in waiting IF_DEL event\n"));
4437 ret
= wl_cfg80211_post_ifdel(ndev
, false);
4438 if (unlikely(ret
)) {
4439 WL_ERR(("post_ifdel failed\n"));
4444 #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
4447 s32
wl_cfg80211_set_sae_password(struct net_device
*dev
, char* buf
, int len
)
4449 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
4451 sscanf(buf
, "%s %d", cfg
->sae_password
, &cfg
->sae_password_len
);
4455 static s32
wl_cfg80211_join_mesh(
4456 struct wiphy
*wiphy
, struct net_device
*dev
,
4457 const struct mesh_config
*conf
,
4458 const struct mesh_setup
*setup
)
4460 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4461 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
4462 struct ieee80211_channel
*chan
= setup
->chandef
.chan
;
4463 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0))
4464 struct ieee80211_channel
*chan
= setup
->channel
;
4466 u32 param
[2] = {0, 0};
4469 u32 beacon_interval
= setup
->beacon_interval
;
4470 u32 dtim_period
= setup
->dtim_period
;
4471 size_t join_params_size
;
4472 struct wl_join_params join_params
;
4473 chanspec_t chanspec
= 0;
4475 cfg
->channel
= ieee80211_frequency_to_channel(chan
->center_freq
);
4477 if (wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
4478 struct wlc_ssid
*lssid
= (struct wlc_ssid
*)wl_read_prof(cfg
, dev
, WL_PROF_SSID
);
4479 u8
*bssid
= (u8
*)wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
4480 u32
*channel
= (u32
*)wl_read_prof(cfg
, dev
, WL_PROF_CHAN
);
4481 if ((memcmp(setup
->mesh_id
, lssid
->SSID
, lssid
->SSID_len
) == 0) &&
4482 (*channel
== cfg
->channel
)) {
4483 WL_ERR(("MESH connection already existed to " MACDBG
"\n",
4484 MAC2STRDBG((u8
*)wl_read_prof(cfg
, dev
, WL_PROF_BSSID
))));
4487 WL_ERR(("Previous connecton existed, please disconnect mesh %s (" MACDBG
") first\n",
4488 lssid
->SSID
, MAC2STRDBG(bssid
)));
4493 if (chan
->band
== IEEE80211_BAND_5GHZ
)
4494 param
[0] = WLC_BAND_5G
;
4495 else if (chan
->band
== IEEE80211_BAND_2GHZ
)
4496 param
[0] = WLC_BAND_2G
;
4497 err
= wldev_iovar_getint(dev
, "bw_cap", param
);
4498 if (unlikely(err
)) {
4499 WL_ERR(("Get bw_cap Failed (%d)\n", err
));
4503 chanspec
= channel_to_chanspec(wiphy
, dev
, cfg
->channel
, bw_cap
);
4506 memset(&join_params
, 0, sizeof(join_params
));
4507 memcpy((void *)join_params
.ssid
.SSID
, (void *)setup
->mesh_id
,
4508 setup
->mesh_id_len
);
4510 join_params
.ssid
.SSID_len
= htod32(setup
->mesh_id_len
);
4511 join_params
.params
.chanspec_list
[0] = chanspec
;
4512 join_params
.params
.chanspec_num
= 1;
4513 wldev_iovar_setint(dev
, "chanspec", chanspec
);
4514 join_params_size
= sizeof(join_params
);
4516 wldev_iovar_setint(dev
, "wpa_auth", WPA_AUTH_DISABLED
);
4517 wldev_iovar_setint(dev
, "wsec", 0);
4519 if (cfg
->sae_password_len
> 0) {
4520 wldev_iovar_setint(dev
, "mesh_auth_proto", 1);
4521 wldev_iovar_setint(dev
, "wpa_auth", WPA2_AUTH_PSK
);
4522 wldev_iovar_setint(dev
, "wsec", AES_ENABLED
);
4523 wldev_iovar_setint(dev
, "mfp", WL_MFP_REQUIRED
);
4524 printf("%s: password=%s, len=%d\n", __FUNCTION__
,
4525 cfg
->sae_password
, cfg
->sae_password_len
);
4526 wldev_iovar_setbuf(dev
, "sae_password", cfg
->sae_password
, cfg
->sae_password_len
,
4527 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, NULL
);
4529 wldev_iovar_setint(dev
, "mesh_auth_proto", 0);
4530 wldev_iovar_setint(dev
, "mfp", WL_MFP_NONE
);
4533 if (beacon_interval
) {
4534 if ((err
= wldev_ioctl_set(dev
, WLC_SET_BCNPRD
,
4535 &beacon_interval
, sizeof(s32
))) < 0) {
4536 WL_ERR(("Beacon Interval Set Error, %d\n", err
));
4542 if ((err
= wldev_ioctl_set(dev
, WLC_SET_DTIMPRD
,
4543 &dtim_period
, sizeof(s32
))) < 0) {
4544 WL_ERR(("DTIM Interval Set Error, %d\n", err
));
4548 wldev_iovar_setint(dev
, "mpc", 0);
4550 WL_ERR(("JOIN %s on channel %d with chanspec 0x%4x\n",
4551 join_params
.ssid
.SSID
, cfg
->channel
, chanspec
));
4553 err
= wldev_ioctl_set(dev
, WLC_SET_SSID
, &join_params
,
4556 if (unlikely(err
)) {
4557 WL_ERR(("Error (%d)\n", err
));
4561 wl_update_prof(cfg
, dev
, NULL
, &join_params
.ssid
, WL_PROF_SSID
);
4562 wl_update_prof(cfg
, dev
, NULL
, &cfg
->channel
, WL_PROF_CHAN
);
4567 static s32
wl_cfg80211_leave_mesh(
4568 struct wiphy
*wiphy
, struct net_device
*dev
)
4570 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4575 RETURN_EIO_IF_NOT_UP(cfg
);
4578 WL_ERR(("Leave MESH\n"));
4579 curbssid
= wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
4580 wl_set_drv_status(cfg
, DISCONNECTING
, dev
);
4582 memcpy(&scbval
.ea
, curbssid
, ETHER_ADDR_LEN
);
4583 err
= wldev_ioctl_set(dev
, WLC_DISASSOC
, &scbval
,
4585 if (unlikely(err
)) {
4586 wl_clr_drv_status(cfg
, DISCONNECTING
, dev
);
4587 WL_ERR(("error(%d)\n", err
));
4590 memset(cfg
->sae_password
, 0, SAE_MAX_PASSWD_LEN
);
4591 cfg
->sae_password_len
= 0;
4598 wl_cfg80211_join_ibss(struct wiphy
*wiphy
, struct net_device
*dev
,
4599 struct cfg80211_ibss_params
*params
)
4601 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4602 struct cfg80211_bss
*bss
;
4603 struct ieee80211_channel
*chan
;
4604 struct wl_join_params join_params
;
4606 struct cfg80211_ssid ssid
;
4609 size_t join_params_size
;
4610 chanspec_t chanspec
= 0;
4611 u32 param
[2] = {0, 0};
4615 RETURN_EIO_IF_NOT_UP(cfg
);
4616 WL_INFORM(("JOIN BSSID:" MACDBG
"\n", MAC2STRDBG(params
->bssid
)));
4617 if (!params
->ssid
|| params
->ssid_len
<= 0 ||
4618 params
->ssid_len
> DOT11_MAX_SSID_LEN
) {
4619 WL_ERR(("Invalid parameter\n"));
4622 #if defined(WL_CFG80211_P2P_DEV_IF)
4623 chan
= params
->chandef
.chan
;
4625 chan
= params
->channel
;
4626 #endif /* WL_CFG80211_P2P_DEV_IF */
4628 cfg
->channel
= ieee80211_frequency_to_channel(chan
->center_freq
);
4629 if (wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
4630 struct wlc_ssid
*lssid
= (struct wlc_ssid
*)wl_read_prof(cfg
, dev
, WL_PROF_SSID
);
4631 u8
*bssid
= (u8
*)wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
4632 u32
*channel
= (u32
*)wl_read_prof(cfg
, dev
, WL_PROF_CHAN
);
4633 if (!params
->bssid
|| ((memcmp(params
->bssid
, bssid
, ETHER_ADDR_LEN
) == 0) &&
4634 (memcmp(params
->ssid
, lssid
->SSID
, lssid
->SSID_len
) == 0) &&
4635 (*channel
== cfg
->channel
))) {
4636 WL_ERR(("Connection already existed to " MACDBG
"\n",
4637 MAC2STRDBG((u8
*)wl_read_prof(cfg
, dev
, WL_PROF_BSSID
))));
4640 WL_ERR(("Ignore Previous connecton to %s (" MACDBG
")\n",
4641 lssid
->SSID
, MAC2STRDBG(bssid
)));
4644 /* remove the VSIE */
4645 wl_cfg80211_ibss_vsie_delete(dev
);
4647 bss
= cfg80211_get_ibss(wiphy
, NULL
, params
->ssid
, params
->ssid_len
);
4649 if (IBSS_INITIAL_SCAN_ALLOWED
== TRUE
) {
4650 memcpy(ssid
.ssid
, params
->ssid
, params
->ssid_len
);
4651 ssid
.ssid_len
= params
->ssid_len
;
4654 (__wl_cfg80211_scan(wiphy
, dev
, NULL
, &ssid
) ==
4660 } while (++scan_retry
< WL_SCAN_RETRY_MAX
);
4662 /* rtnl lock code is removed here. don't see why rtnl lock
4663 * needs to be released.
4666 /* wait 4 secons till scan done.... */
4667 schedule_timeout_interruptible(msecs_to_jiffies(4000));
4669 bss
= cfg80211_get_ibss(wiphy
, NULL
,
4670 params
->ssid
, params
->ssid_len
);
4673 if (bss
&& ((IBSS_COALESCE_ALLOWED
== TRUE
) ||
4674 ((IBSS_COALESCE_ALLOWED
== FALSE
) && params
->bssid
&&
4675 !memcmp(bss
->bssid
, params
->bssid
, ETHER_ADDR_LEN
)))) {
4676 cfg
->ibss_starter
= false;
4677 WL_DBG(("Found IBSS\n"));
4679 cfg
->ibss_starter
= true;
4683 CFG80211_PUT_BSS(wiphy
, bss
);
4687 if (chan
->band
== IEEE80211_BAND_5GHZ
)
4688 param
[0] = WLC_BAND_5G
;
4689 else if (chan
->band
== IEEE80211_BAND_2GHZ
)
4690 param
[0] = WLC_BAND_2G
;
4691 err
= wldev_iovar_getint(dev
, "bw_cap", param
);
4692 if (unlikely(err
)) {
4693 WL_ERR(("Get bw_cap Failed (%d)\n", err
));
4697 chanspec
= channel_to_chanspec(wiphy
, dev
, cfg
->channel
, bw_cap
);
4700 * Join with specific BSSID and cached SSID
4701 * If SSID is zero join based on BSSID only
4703 memset(&join_params
, 0, sizeof(join_params
));
4704 memcpy((void *)join_params
.ssid
.SSID
, (void *)params
->ssid
,
4706 join_params
.ssid
.SSID_len
= htod32(params
->ssid_len
);
4707 if (params
->bssid
) {
4708 memcpy(&join_params
.params
.bssid
, params
->bssid
, ETHER_ADDR_LEN
);
4709 err
= wldev_ioctl_set(dev
, WLC_SET_DESIRED_BSSID
, &join_params
.params
.bssid
,
4711 if (unlikely(err
)) {
4712 WL_ERR(("Error (%d)\n", err
));
4716 memset(&join_params
.params
.bssid
, 0, ETHER_ADDR_LEN
);
4718 if (IBSS_INITIAL_SCAN_ALLOWED
== FALSE
) {
4719 scan_suppress
= TRUE
;
4720 /* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
4721 err
= wldev_ioctl_set(dev
, WLC_SET_SCANSUPPRESS
,
4722 &scan_suppress
, sizeof(int));
4723 if (unlikely(err
)) {
4724 WL_ERR(("Scan Suppress Setting Failed (%d)\n", err
));
4729 join_params
.params
.chanspec_list
[0] = chanspec
;
4730 join_params
.params
.chanspec_num
= 1;
4731 wldev_iovar_setint(dev
, "chanspec", chanspec
);
4732 join_params_size
= sizeof(join_params
);
4734 /* Disable Authentication, IBSS will add key if it required */
4735 wldev_iovar_setint(dev
, "wpa_auth", WPA_AUTH_DISABLED
);
4736 wldev_iovar_setint(dev
, "wsec", 0);
4738 err
= wldev_ioctl_set(dev
, WLC_SET_SSID
, &join_params
,
4740 if (unlikely(err
)) {
4741 WL_ERR(("Error (%d)\n", err
));
4745 if (IBSS_INITIAL_SCAN_ALLOWED
== FALSE
) {
4746 scan_suppress
= FALSE
;
4747 /* Reset the SCAN SUPPRESS Flag */
4748 err
= wldev_ioctl_set(dev
, WLC_SET_SCANSUPPRESS
,
4749 &scan_suppress
, sizeof(int));
4750 if (unlikely(err
)) {
4751 WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err
));
4755 wl_update_prof(cfg
, dev
, NULL
, &join_params
.ssid
, WL_PROF_SSID
);
4756 wl_update_prof(cfg
, dev
, NULL
, &cfg
->channel
, WL_PROF_CHAN
);
4758 cfg
->rmc_event_seq
= 0; /* initialize rmcfail sequence */
4759 #endif /* WL_RELMCAST */
4763 static s32
wl_cfg80211_leave_ibss(struct wiphy
*wiphy
, struct net_device
*dev
)
4765 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
4770 RETURN_EIO_IF_NOT_UP(cfg
);
4773 WL_ERR(("Leave IBSS\n"));
4774 curbssid
= wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
4775 wl_set_drv_status(cfg
, DISCONNECTING
, dev
);
4777 memcpy(&scbval
.ea
, curbssid
, ETHER_ADDR_LEN
);
4778 err
= wldev_ioctl_set(dev
, WLC_DISASSOC
, &scbval
,
4780 if (unlikely(err
)) {
4781 wl_clr_drv_status(cfg
, DISCONNECTING
, dev
);
4782 WL_ERR(("error(%d)\n", err
));
4786 /* remove the VSIE */
4787 wl_cfg80211_ibss_vsie_delete(dev
);
4793 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t
*wpa2ie
, u8
** rsn_cap
)
4796 wpa_suite_mcast_t
*mcast
;
4797 wpa_suite_ucast_t
*ucast
;
4799 wpa_suite_auth_key_mgmt_t
*mgmt
;
4805 mcast
= (wpa_suite_mcast_t
*)&wpa2ie
->data
[WPA2_VERSION_LEN
];
4806 if ((len
-= WPA_SUITE_LEN
) <= 0)
4808 ucast
= (wpa_suite_ucast_t
*)&mcast
[1];
4809 suite_count
= ltoh16_ua(&ucast
->count
);
4810 if ((suite_count
> NL80211_MAX_NR_CIPHER_SUITES
) ||
4811 (len
-= (WPA_IE_SUITE_COUNT_LEN
+
4812 (WPA_SUITE_LEN
* suite_count
))) <= 0)
4815 mgmt
= (wpa_suite_auth_key_mgmt_t
*)&ucast
->list
[suite_count
];
4816 suite_count
= ltoh16_ua(&mgmt
->count
);
4818 if ((suite_count
> NL80211_MAX_NR_CIPHER_SUITES
) ||
4819 (len
-= (WPA_IE_SUITE_COUNT_LEN
+
4820 (WPA_SUITE_LEN
* suite_count
))) >= RSN_CAP_LEN
) {
4821 rsn_cap
[0] = (u8
*)&mgmt
->list
[suite_count
];
4830 wl_set_wpa_version(struct net_device
*dev
, struct cfg80211_connect_params
*sme
)
4832 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
4833 struct wl_security
*sec
;
4838 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
4839 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
4843 if (sme
->crypto
.wpa_versions
& NL80211_WPA_VERSION_1
)
4844 val
= WPA_AUTH_PSK
|
4845 WPA_AUTH_UNSPECIFIED
;
4846 else if (sme
->crypto
.wpa_versions
& NL80211_WPA_VERSION_2
)
4847 val
= WPA2_AUTH_PSK
|
4848 WPA2_AUTH_UNSPECIFIED
;
4850 val
= WPA_AUTH_DISABLED
;
4852 if (is_wps_conn(sme
))
4853 val
= WPA_AUTH_DISABLED
;
4855 WL_DBG(("setting wpa_auth to 0x%0x\n", val
));
4856 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", val
, bssidx
);
4857 if (unlikely(err
)) {
4858 WL_ERR(("set wpa_auth failed (%d)\n", err
));
4861 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
4862 sec
->wpa_versions
= sme
->crypto
.wpa_versions
;
4868 wl_set_auth_type(struct net_device
*dev
, struct cfg80211_connect_params
*sme
)
4870 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
4871 struct wl_security
*sec
;
4876 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
4877 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
4881 switch (sme
->auth_type
) {
4882 case NL80211_AUTHTYPE_OPEN_SYSTEM
:
4883 val
= WL_AUTH_OPEN_SYSTEM
;
4884 WL_DBG(("open system\n"));
4886 case NL80211_AUTHTYPE_SHARED_KEY
:
4887 val
= WL_AUTH_SHARED_KEY
;
4888 WL_DBG(("shared key\n"));
4890 case NL80211_AUTHTYPE_AUTOMATIC
:
4891 val
= WL_AUTH_OPEN_SHARED
;
4892 WL_DBG(("automatic\n"));
4896 WL_ERR(("invalid auth type (%d)\n", sme
->auth_type
));
4900 err
= wldev_iovar_setint_bsscfg(dev
, "auth", val
, bssidx
);
4901 if (unlikely(err
)) {
4902 WL_ERR(("set auth failed (%d)\n", err
));
4905 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
4906 sec
->auth_type
= sme
->auth_type
;
4911 wl_set_set_cipher(struct net_device
*dev
, struct cfg80211_connect_params
*sme
)
4913 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
4914 struct wl_security
*sec
;
4921 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
4922 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
4926 if (sme
->crypto
.n_ciphers_pairwise
) {
4927 switch (sme
->crypto
.ciphers_pairwise
[0]) {
4928 case WLAN_CIPHER_SUITE_WEP40
:
4929 case WLAN_CIPHER_SUITE_WEP104
:
4932 case WLAN_CIPHER_SUITE_TKIP
:
4933 pval
= TKIP_ENABLED
;
4935 case WLAN_CIPHER_SUITE_CCMP
:
4936 case WLAN_CIPHER_SUITE_AES_CMAC
:
4940 WL_ERR(("invalid cipher pairwise (%d)\n",
4941 sme
->crypto
.ciphers_pairwise
[0]));
4945 if (sme
->crypto
.cipher_group
) {
4946 switch (sme
->crypto
.cipher_group
) {
4947 case WLAN_CIPHER_SUITE_WEP40
:
4948 case WLAN_CIPHER_SUITE_WEP104
:
4951 case WLAN_CIPHER_SUITE_TKIP
:
4952 gval
= TKIP_ENABLED
;
4954 case WLAN_CIPHER_SUITE_CCMP
:
4957 case WLAN_CIPHER_SUITE_AES_CMAC
:
4961 WL_ERR(("invalid cipher group (%d)\n",
4962 sme
->crypto
.cipher_group
));
4967 WL_DBG(("pval (%d) gval (%d)\n", pval
, gval
));
4969 if (is_wps_conn(sme
)) {
4971 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", 4, bssidx
);
4973 /* WPS-2.0 allows no security */
4974 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", 0, bssidx
);
4976 WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
4977 wsec_val
= pval
| gval
;
4979 WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val
));
4980 err
= wldev_iovar_setint_bsscfg(dev
, "wsec",
4983 if (unlikely(err
)) {
4984 WL_ERR(("error (%d)\n", err
));
4988 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
4989 sec
->cipher_pairwise
= sme
->crypto
.ciphers_pairwise
[0];
4990 sec
->cipher_group
= sme
->crypto
.cipher_group
;
4997 wl_cfg80211_set_mfp(struct bcm_cfg80211
*cfg
,
4998 struct net_device
*dev
,
4999 struct cfg80211_connect_params
*sme
)
5001 s32 mfp
= WL_MFP_NONE
;
5002 s32 current_mfp
= WL_MFP_NONE
;
5005 bool fw_support
= false;
5007 u8
*eptr
= NULL
, *ptr
= NULL
;
5008 u8
* group_mgmt_cs
= NULL
;
5009 wpa_pmkid_list_t
* pmkid
= NULL
;
5012 /* No connection params from userspace, Do nothing. */
5016 /* Check fw support and retreive current mfp val */
5017 err
= wldev_iovar_getint(dev
, "mfp", ¤t_mfp
);
5022 /* Parse the wpa2ie to decode the MFP capablity */
5023 if (((wpa2_ie
= bcm_parse_tlvs((u8
*)sme
->ie
, sme
->ie_len
,
5024 DOT11_MNG_RSN_ID
)) != NULL
) &&
5025 (wl_cfg80211_get_rsn_capa(wpa2_ie
, &rsn_cap
) == 0)) {
5026 /* Check for MFP cap in the RSN capability field */
5027 if (rsn_cap
[0] & RSN_CAP_MFPR
) {
5028 mfp
= WL_MFP_REQUIRED
;
5029 } else if (rsn_cap
[0] & RSN_CAP_MFPC
) {
5030 mfp
= WL_MFP_CAPABLE
;
5034 * eptr --> end/last byte addr of wpa2_ie
5035 * ptr --> to keep track of current/required byte addr
5037 eptr
= (u8
*)wpa2_ie
+ (wpa2_ie
->len
+ TLV_HDR_LEN
);
5038 /* pointing ptr to the next byte after rns_cap */
5039 ptr
= (u8
*)rsn_cap
+ RSN_CAP_LEN
;
5040 if (mfp
&& (eptr
- ptr
) >= WPA2_PMKID_COUNT_LEN
) {
5041 /* pmkid now to point to 1st byte addr of pmkid in wpa2_ie */
5042 pmkid
= (wpa_pmkid_list_t
*)ptr
;
5043 count
= pmkid
->count
.low
| (pmkid
->count
.high
<< 8);
5044 /* ptr now to point to last byte addr of pmkid */
5045 ptr
= (u8
*)pmkid
+ (count
* WPA2_PMKID_LEN
5046 + WPA2_PMKID_COUNT_LEN
);
5047 if ((eptr
- ptr
) >= WPA_SUITE_LEN
) {
5048 /* group_mgmt_cs now to point to first byte addr of bip */
5049 group_mgmt_cs
= ptr
;
5054 WL_DBG((" mfp:%d wpa2_ie ptr:%p rsn_cap 0x%x%x fw mfp support:%d\n",
5055 mfp
, wpa2_ie
, rsn_cap
[0], rsn_cap
[1], fw_support
));
5057 if (fw_support
== false) {
5058 if (mfp
== WL_MFP_REQUIRED
) {
5059 /* if mfp > 0, mfp capability set in wpa ie, but
5060 * FW indicated error for mfp. Propagate the error up.
5062 WL_ERR(("mfp capability found in wpaie. But fw doesn't "
5063 "seem to support MFP\n"));
5066 /* Firmware doesn't support mfp. But since connection request
5067 * is for non-mfp case, don't bother.
5071 } else if (mfp
!= current_mfp
) {
5072 err
= wldev_iovar_setint(dev
, "mfp", mfp
);
5073 if (unlikely(err
)) {
5074 WL_ERR(("mfp (%d) set failed ret:%d \n", mfp
, err
));
5077 WL_DBG(("mfp set to 0x%x \n", mfp
));
5080 if (group_mgmt_cs
&& bcmp((const uint8
*)WPA2_OUI
,
5081 group_mgmt_cs
, (WPA_SUITE_LEN
- 1)) == 0) {
5082 WL_DBG(("BIP is found\n"));
5083 err
= wldev_iovar_setbuf(dev
, "bip",
5084 group_mgmt_cs
, WPA_SUITE_LEN
, cfg
->ioctl_buf
,
5085 WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
);
5087 * Dont return failure for unsupported cases
5088 * of bip iovar for backward compatibility
5090 if (err
!= BCME_UNSUPPORTED
&& err
< 0) {
5091 WL_ERR(("bip set error (%d)\n", err
));
5101 wl_set_key_mgmt(struct net_device
*dev
, struct cfg80211_connect_params
*sme
)
5103 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
5104 struct wl_security
*sec
;
5109 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5110 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
5114 if (sme
->crypto
.n_akm_suites
) {
5115 err
= wldev_iovar_getint(dev
, "wpa_auth", &val
);
5116 if (unlikely(err
)) {
5117 WL_ERR(("could not get wpa_auth (%d)\n", err
));
5120 if (val
& (WPA_AUTH_PSK
|
5121 WPA_AUTH_UNSPECIFIED
)) {
5122 switch (sme
->crypto
.akm_suites
[0]) {
5123 case WLAN_AKM_SUITE_8021X
:
5124 val
= WPA_AUTH_UNSPECIFIED
;
5126 case WLAN_AKM_SUITE_PSK
:
5130 WL_ERR(("invalid akm suite (0x%x)\n",
5131 sme
->crypto
.akm_suites
[0]));
5134 } else if (val
& (WPA2_AUTH_PSK
|
5135 WPA2_AUTH_UNSPECIFIED
)) {
5136 switch (sme
->crypto
.akm_suites
[0]) {
5137 case WLAN_AKM_SUITE_8021X
:
5138 val
= WPA2_AUTH_UNSPECIFIED
;
5142 case WL_AKM_SUITE_SHA256_1X
:
5143 if (wl_customer6_legacy_chip_check(cfg
, dev
)) {
5144 val
= WPA2_AUTH_UNSPECIFIED
;
5146 val
= WPA2_AUTH_1X_SHA256
;
5149 case WL_AKM_SUITE_SHA256_PSK
:
5150 if (wl_customer6_legacy_chip_check(cfg
, dev
)) {
5151 val
= WPA2_AUTH_PSK
;
5153 val
= WPA2_AUTH_PSK_SHA256
;
5157 case WL_AKM_SUITE_SHA256_1X
:
5158 val
= WPA2_AUTH_1X_SHA256
;
5160 case WL_AKM_SUITE_SHA256_PSK
:
5161 val
= WPA2_AUTH_PSK_SHA256
;
5163 #endif /* CUSTOMER_HW6 */
5165 case WLAN_AKM_SUITE_PSK
:
5166 val
= WPA2_AUTH_PSK
;
5169 WL_ERR(("invalid akm suite (0x%x)\n",
5170 sme
->crypto
.akm_suites
[0]));
5176 if ((err
= wl_cfg80211_set_mfp(cfg
, dev
, sme
)) < 0) {
5177 WL_ERR(("MFP set failed err:%d\n", err
));
5182 WL_DBG(("setting wpa_auth to 0x%x\n", val
));
5183 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", val
, bssidx
);
5184 if (unlikely(err
)) {
5185 WL_ERR(("could not set wpa_auth (0x%x)\n", err
));
5189 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
5190 sec
->wpa_auth
= sme
->crypto
.akm_suites
[0];
5196 wl_set_set_sharedkey(struct net_device
*dev
,
5197 struct cfg80211_connect_params
*sme
)
5199 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
5200 struct wl_security
*sec
;
5201 struct wl_wsec_key key
;
5206 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5207 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
5211 WL_DBG(("key len (%d)\n", sme
->key_len
));
5213 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
5214 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
5215 sec
->wpa_versions
, sec
->cipher_pairwise
));
5216 if (!(sec
->wpa_versions
& (NL80211_WPA_VERSION_1
|
5217 NL80211_WPA_VERSION_2
)) &&
5218 (sec
->cipher_pairwise
& (WLAN_CIPHER_SUITE_WEP40
|
5219 WLAN_CIPHER_SUITE_WEP104
)))
5221 memset(&key
, 0, sizeof(key
));
5222 key
.len
= (u32
) sme
->key_len
;
5223 key
.index
= (u32
) sme
->key_idx
;
5224 if (unlikely(key
.len
> sizeof(key
.data
))) {
5225 WL_ERR(("Too long key length (%u)\n", key
.len
));
5228 memcpy(key
.data
, sme
->key
, key
.len
);
5229 key
.flags
= WL_PRIMARY_KEY
;
5230 switch (sec
->cipher_pairwise
) {
5231 case WLAN_CIPHER_SUITE_WEP40
:
5232 key
.algo
= CRYPTO_ALGO_WEP1
;
5234 case WLAN_CIPHER_SUITE_WEP104
:
5235 key
.algo
= CRYPTO_ALGO_WEP128
;
5238 WL_ERR(("Invalid algorithm (%d)\n",
5239 sme
->crypto
.ciphers_pairwise
[0]));
5242 /* Set the new key/index */
5243 WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
5244 key
.len
, key
.index
, key
.algo
));
5245 WL_DBG(("key \"%s\"\n", key
.data
));
5246 swap_key_from_BE(&key
);
5247 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &key
, sizeof(key
),
5248 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
5249 if (unlikely(err
)) {
5250 WL_ERR(("WLC_SET_KEY error (%d)\n", err
));
5253 if (sec
->auth_type
== NL80211_AUTHTYPE_SHARED_KEY
) {
5254 WL_DBG(("set auth_type to shared key\n"));
5255 val
= WL_AUTH_SHARED_KEY
; /* shared key */
5256 err
= wldev_iovar_setint_bsscfg(dev
, "auth", val
, bssidx
);
5257 if (unlikely(err
)) {
5258 WL_ERR(("set auth failed (%d)\n", err
));
5267 #if defined(ESCAN_RESULT_PATCH)
5268 static u8 connect_req_bssid
[6];
5269 static u8 broad_bssid
[6];
5270 #endif /* ESCAN_RESULT_PATCH */
5274 #if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
5275 static bool wl_get_chan_isvht80(struct net_device
*net
, dhd_pub_t
*dhd
)
5280 if (wldev_iovar_getint(net
, "chanspec", (s32
*)&chanspec
) == BCME_OK
)
5281 chanspec
= wl_chspec_driver_to_host(chanspec
);
5283 isvht80
= chanspec
& WL_CHANSPEC_BW_80
;
5284 WL_INFORM(("%s: chanspec(%x:%d)\n", __FUNCTION__
, chanspec
, isvht80
));
5288 #endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
5290 int wl_cfg80211_cleanup_mismatch_status(struct net_device
*dev
, struct bcm_cfg80211
*cfg
,
5298 WL_ERR(("Disassociate previous connection!\n"));
5299 wl_set_drv_status(cfg
, DISCONNECTING
, dev
);
5300 scbval
.val
= DOT11_RC_DISASSOC_LEAVING
;
5301 scbval
.val
= htod32(scbval
.val
);
5303 err
= wldev_ioctl_set(dev
, WLC_DISASSOC
, &scbval
,
5305 if (unlikely(err
)) {
5306 wl_clr_drv_status(cfg
, DISCONNECTING
, dev
);
5307 WL_ERR(("error (%d)\n", err
));
5313 WL_ERR(("Waiting for previous DISCONNECTING status!\n"));
5314 if (wl_get_drv_status(cfg
, DISCONNECTING
, dev
)) {
5315 wl_clr_drv_status(cfg
, DISCONNECTING
, dev
);
5319 while (wl_get_drv_status(cfg
, DISCONNECTING
, dev
) && wait_cnt
) {
5320 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
5326 if (wait_cnt
== 0) {
5327 WL_ERR(("DISCONNECING clean up failed!\n"));
5328 return BCME_NOTREADY
;
5333 #define MAX_SCAN_ABORT_WAIT_CNT 20
5334 #define WAIT_SCAN_ABORT_OSL_SLEEP_TIME 10
5337 wl_cfg80211_connect(struct wiphy
*wiphy
, struct net_device
*dev
,
5338 struct cfg80211_connect_params
*sme
)
5340 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5341 struct ieee80211_channel
*chan
= sme
->channel
;
5342 wl_extjoin_params_t
*ext_join_params
;
5343 struct wl_join_params join_params
;
5344 size_t join_params_size
;
5345 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
5347 wpa_ie_fixed_t
*wpa_ie
;
5352 struct ether_addr bssid
;
5354 #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
5359 BCM_REFERENCE(dhdp
);
5362 wl_config_ifmode(cfg
, dev
, dev
->ieee80211_ptr
->iftype
);
5364 #if defined(SUPPORT_RANDOM_MAC_SCAN)
5365 wl_cfg80211_set_random_mac(dev
, FALSE
);
5366 #endif /* SUPPORT_RANDOM_MAC_SCAN */
5368 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
5369 if (sme
->channel_hint
) {
5370 chan
= sme
->channel_hint
;
5371 WL_DBG(("channel_hint (%d), channel_hint center_freq (%d)\n",
5372 ieee80211_frequency_to_channel(sme
->channel_hint
->center_freq
),
5373 sme
->channel_hint
->center_freq
));
5375 if (sme
->bssid_hint
) {
5376 sme
->bssid
= sme
->bssid_hint
;
5377 WL_DBG(("bssid_hint "MACDBG
" \n", MAC2STRDBG(sme
->bssid_hint
)));
5379 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
5381 if (unlikely(!sme
->ssid
)) {
5382 WL_ERR(("Invalid ssid\n"));
5386 if (unlikely(sme
->ssid_len
> DOT11_MAX_SSID_LEN
)) {
5387 WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
5388 sme
->ssid
, sme
->ssid_len
));
5392 WL_DBG(("SME IE : len=%zu\n", sme
->ie_len
));
5393 if (sme
->ie
!= NULL
&& sme
->ie_len
> 0 && (wl_dbg_level
& WL_DBG_DBG
)) {
5394 prhex(NULL
, (uchar
*)sme
->ie
, sme
->ie_len
);
5397 RETURN_EIO_IF_NOT_UP(cfg
);
5400 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
5402 #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
5403 if (cfg
->scan_request
) {
5404 WL_TRACE_HW4(("Aborting the scan! \n"));
5405 wl_cfg80211_scan_abort(cfg
);
5406 wait_cnt
= MAX_SCAN_ABORT_WAIT_CNT
;
5407 while (wl_get_drv_status(cfg
, SCANNING
, dev
) && wait_cnt
) {
5408 WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt
));
5410 OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME
);
5412 if (wl_get_drv_status(cfg
, SCANNING
, dev
)) {
5413 wl_notify_escan_complete(cfg
, dev
, true, true);
5417 #ifdef WL_SCHED_SCAN
5418 /* Locks are taken in wl_cfg80211_sched_scan_stop()
5419 * A start scan occuring during connect is unlikely
5421 if (cfg
->sched_scan_req
) {
5422 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
5423 wl_cfg80211_sched_scan_stop(wiphy
, bcmcfg_to_prmry_ndev(cfg
), 0);
5425 wl_cfg80211_sched_scan_stop(wiphy
, bcmcfg_to_prmry_ndev(cfg
));
5426 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
5429 #if defined(ESCAN_RESULT_PATCH)
5431 memcpy(connect_req_bssid
, sme
->bssid
, ETHER_ADDR_LEN
);
5433 bzero(connect_req_bssid
, ETHER_ADDR_LEN
);
5434 bzero(broad_bssid
, ETHER_ADDR_LEN
);
5436 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5439 if (wl_get_drv_status(cfg
, CONNECTING
, dev
) || wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
5440 /* set nested connect bit to identify the context */
5441 wl_set_drv_status(cfg
, NESTED_CONNECT
, dev
);
5442 /* DHD prev status is CONNECTING/CONNECTED */
5443 err
= wl_cfg80211_cleanup_mismatch_status(dev
, cfg
, TRUE
);
5444 } else if (wl_get_drv_status(cfg
, DISCONNECTING
, dev
)) {
5445 /* DHD prev status is DISCONNECTING */
5446 err
= wl_cfg80211_cleanup_mismatch_status(dev
, cfg
, FALSE
);
5447 } else if (!wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
5448 /* DHD previous status is not connected and FW connected */
5449 if (wldev_ioctl_get(dev
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
) == 0) {
5450 /* set nested connect bit to identify the context */
5451 wl_set_drv_status(cfg
, NESTED_CONNECT
, dev
);
5452 err
= wl_cfg80211_cleanup_mismatch_status(dev
, cfg
, TRUE
);
5456 /* 'connect' request received */
5457 wl_set_drv_status(cfg
, CONNECTING
, dev
);
5458 /* clear nested connect bit on proceeding for connection */
5459 wl_clr_drv_status(cfg
, NESTED_CONNECT
, dev
);
5462 bzero(&bssid
, sizeof(bssid
));
5463 if (!wl_get_drv_status(cfg
, DISCONNECTING
, dev
))
5464 wl_update_prof(cfg
, dev
, NULL
, (void *)&bssid
, WL_PROF_BSSID
);
5466 if (p2p_is_on(cfg
) && (dev
!= bcmcfg_to_prmry_ndev(cfg
))) {
5467 /* we only allow to connect using virtual interface in case of P2P */
5468 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5469 WL_ERR(("Find p2p index from wdev(%p) failed\n",
5470 dev
->ieee80211_ptr
));
5474 wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
5475 VNDR_IE_ASSOCREQ_FLAG
, sme
->ie
, sme
->ie_len
);
5476 } else if (dev
== bcmcfg_to_prmry_ndev(cfg
)) {
5477 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5478 WL_ERR(("Find wlan index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
5483 /* find the RSN_IE */
5484 if ((wpa2_ie
= bcm_parse_tlvs((u8
*)sme
->ie
, sme
->ie_len
,
5485 DOT11_MNG_RSN_ID
)) != NULL
) {
5486 WL_DBG((" WPA2 IE is found\n"));
5488 /* find the WPA_IE */
5489 if ((wpa_ie
= wl_cfgp2p_find_wpaie((u8
*)sme
->ie
,
5490 sme
->ie_len
)) != NULL
) {
5491 WL_DBG((" WPA IE is found\n"));
5493 if (wpa_ie
!= NULL
|| wpa2_ie
!= NULL
) {
5494 wpaie
= (wpa_ie
!= NULL
) ? (u8
*)wpa_ie
: (u8
*)wpa2_ie
;
5495 wpaie_len
= (wpa_ie
!= NULL
) ? wpa_ie
->length
: wpa2_ie
->len
;
5496 wpaie_len
+= WPA_RSN_IE_TAG_FIXED_LEN
;
5497 err
= wldev_iovar_setbuf(dev
, "wpaie", wpaie
, wpaie_len
,
5498 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
5499 if (unlikely(err
)) {
5500 WL_ERR(("wpaie set error (%d)\n", err
));
5504 err
= wldev_iovar_setbuf(dev
, "wpaie", NULL
, 0,
5505 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
5506 if (unlikely(err
)) {
5507 WL_ERR(("wpaie set error (%d)\n", err
));
5511 err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
5512 VNDR_IE_ASSOCREQ_FLAG
, (const u8
*)sme
->ie
, sme
->ie_len
);
5513 if (unlikely(err
)) {
5519 cfg
->channel
= ieee80211_frequency_to_channel(chan
->center_freq
);
5521 WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg
->channel
,
5522 chan
->center_freq
, chan_cnt
));
5524 WL_DBG(("No channel info from user space\n"));
5529 WL_DBG(("3. set wpa version \n"));
5531 err
= wl_set_wpa_version(dev
, sme
);
5532 if (unlikely(err
)) {
5533 WL_ERR(("Invalid wpa_version\n"));
5536 err
= wl_set_auth_type(dev
, sme
);
5537 if (unlikely(err
)) {
5538 WL_ERR(("Invalid auth type\n"));
5542 err
= wl_set_set_cipher(dev
, sme
);
5543 if (unlikely(err
)) {
5544 WL_ERR(("Invalid ciper\n"));
5548 err
= wl_set_key_mgmt(dev
, sme
);
5549 if (unlikely(err
)) {
5550 WL_ERR(("Invalid key mgmt\n"));
5554 err
= wl_set_set_sharedkey(dev
, sme
);
5555 if (unlikely(err
)) {
5556 WL_ERR(("Invalid shared key\n"));
5561 * Join with specific BSSID and cached SSID
5562 * If SSID is zero join based on BSSID only
5564 join_params_size
= WL_EXTJOIN_PARAMS_FIXED_SIZE
+
5565 chan_cnt
* sizeof(chanspec_t
);
5566 ext_join_params
= (wl_extjoin_params_t
*)kzalloc(join_params_size
, GFP_KERNEL
);
5567 if (ext_join_params
== NULL
) {
5569 wl_clr_drv_status(cfg
, CONNECTING
, dev
);
5572 ext_join_params
->ssid
.SSID_len
= min(sizeof(ext_join_params
->ssid
.SSID
), sme
->ssid_len
);
5573 memcpy(&ext_join_params
->ssid
.SSID
, sme
->ssid
, ext_join_params
->ssid
.SSID_len
);
5574 wl_update_prof(cfg
, dev
, NULL
, &ext_join_params
->ssid
, WL_PROF_SSID
);
5575 ext_join_params
->ssid
.SSID_len
= htod32(ext_join_params
->ssid
.SSID_len
);
5576 /* increate dwell time to receive probe response or detect Beacon
5577 * from target AP at a noisy air only during connect command
5579 ext_join_params
->scan
.active_time
= chan_cnt
? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS
: -1;
5580 ext_join_params
->scan
.passive_time
= chan_cnt
? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS
: -1;
5581 /* Set up join scan parameters */
5582 ext_join_params
->scan
.scan_type
= -1;
5583 ext_join_params
->scan
.nprobes
= chan_cnt
?
5584 (ext_join_params
->scan
.active_time
/WL_SCAN_JOIN_PROBE_INTERVAL_MS
) : -1;
5585 ext_join_params
->scan
.home_time
= -1;
5588 memcpy(&ext_join_params
->assoc
.bssid
, sme
->bssid
, ETH_ALEN
);
5590 memcpy(&ext_join_params
->assoc
.bssid
, ðer_bcast
, ETH_ALEN
);
5591 ext_join_params
->assoc
.chanspec_num
= chan_cnt
;
5595 * Use the channel provided by userspace
5597 u16 channel
, band
, bw
, ctl_sb
;
5599 channel
= cfg
->channel
;
5600 band
= (channel
<= CH_MAX_2G_CHANNEL
) ? WL_CHANSPEC_BAND_2G
5601 : WL_CHANSPEC_BAND_5G
;
5603 /* Get min_bw set for the interface */
5604 bw
= wl_cfg80211_ulb_get_min_bw_chspec(cfg
, dev
->ieee80211_ptr
, bssidx
);
5605 if (bw
== INVCHANSPEC
) {
5606 WL_ERR(("Invalid chanspec \n"));
5607 kfree(ext_join_params
);
5612 ctl_sb
= WL_CHANSPEC_CTL_SB_NONE
;
5613 chspec
= (channel
| band
| bw
| ctl_sb
);
5614 ext_join_params
->assoc
.chanspec_list
[0] &= WL_CHANSPEC_CHAN_MASK
;
5615 ext_join_params
->assoc
.chanspec_list
[0] |= chspec
;
5616 ext_join_params
->assoc
.chanspec_list
[0] =
5617 wl_chspec_host_to_driver(ext_join_params
->assoc
.chanspec_list
[0]);
5620 ext_join_params
->assoc
.chanspec_num
= htod32(ext_join_params
->assoc
.chanspec_num
);
5621 if (ext_join_params
->ssid
.SSID_len
< IEEE80211_MAX_SSID_LEN
) {
5622 WL_INFORM(("ssid \"%s\", len (%d)\n", ext_join_params
->ssid
.SSID
,
5623 ext_join_params
->ssid
.SSID_len
));
5626 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5627 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
5628 kfree(ext_join_params
);
5632 #if defined(CUSTOMER_HW2)
5633 DHD_DISABLE_RUNTIME_PM((dhd_pub_t
*)cfg
->pub
);
5634 #endif /* BCMDONGLEHOST && CUSTOMER_HW2 */
5635 #ifdef WL_EXT_IAPSTA
5636 wl_ext_iapsta_disconnect_sta(dev
, cfg
->channel
);
5638 err
= wldev_iovar_setbuf_bsscfg(dev
, "join", ext_join_params
, join_params_size
,
5639 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
5641 if (cfg
->rcc_enabled
) {
5642 printf("Connecting with " MACDBG
" ssid \"%s\", len (%d) with rcc channels \n\n",
5643 MAC2STRDBG((u8
*)(&ext_join_params
->assoc
.bssid
)),
5644 ext_join_params
->ssid
.SSID
, ext_join_params
->ssid
.SSID_len
);
5646 printf("Connecting with " MACDBG
" ssid \"%s\", len (%d) channel=%d\n\n",
5647 MAC2STRDBG((u8
*)(&ext_join_params
->assoc
.bssid
)),
5648 ext_join_params
->ssid
.SSID
, ext_join_params
->ssid
.SSID_len
, cfg
->channel
);
5651 kfree(ext_join_params
);
5653 wl_clr_drv_status(cfg
, CONNECTING
, dev
);
5654 if (err
== BCME_UNSUPPORTED
) {
5655 WL_DBG(("join iovar is not supported\n"));
5658 WL_ERR(("error (%d)\n", err
));
5665 memset(&join_params
, 0, sizeof(join_params
));
5666 join_params_size
= sizeof(join_params
.ssid
);
5668 join_params
.ssid
.SSID_len
= min(sizeof(join_params
.ssid
.SSID
), sme
->ssid_len
);
5669 memcpy(&join_params
.ssid
.SSID
, sme
->ssid
, join_params
.ssid
.SSID_len
);
5670 join_params
.ssid
.SSID_len
= htod32(join_params
.ssid
.SSID_len
);
5671 wl_update_prof(cfg
, dev
, NULL
, &join_params
.ssid
, WL_PROF_SSID
);
5673 memcpy(&join_params
.params
.bssid
, sme
->bssid
, ETH_ALEN
);
5675 memcpy(&join_params
.params
.bssid
, ðer_bcast
, ETH_ALEN
);
5677 if (wl_ch_to_chanspec(dev
, cfg
->channel
, &join_params
, &join_params_size
) < 0) {
5678 WL_ERR(("Invalid chanspec\n"));
5682 WL_DBG(("join_param_size %zu\n", join_params_size
));
5684 if (join_params
.ssid
.SSID_len
< IEEE80211_MAX_SSID_LEN
) {
5685 WL_INFORM(("ssid \"%s\", len (%d)\n", join_params
.ssid
.SSID
,
5686 join_params
.ssid
.SSID_len
));
5688 err
= wldev_ioctl_set(dev
, WLC_SET_SSID
, &join_params
, join_params_size
);
5691 WL_ERR(("error (%d)\n", err
));
5692 wl_clr_drv_status(cfg
, CONNECTING
, dev
);
5696 /* disable TDLS if number of connected interfaces is >= 1 */
5697 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_CONNECT
, false);
5701 if ((dev
== bcmcfg_to_prmry_ndev(cfg
)) && !err
) {
5702 DHD_DBG_PKT_MON_START(dhdp
);
5704 #endif /* DBG_PKT_MON */
5708 #define WAIT_FOR_DISCONNECT_MAX 10
5709 static void wl_cfg80211_wait_for_disconnection(struct bcm_cfg80211
*cfg
, struct net_device
*dev
)
5713 wait_cnt
= WAIT_FOR_DISCONNECT_MAX
;
5714 while (wl_get_drv_status(cfg
, DISCONNECTING
, dev
) && wait_cnt
) {
5715 WL_DBG(("Waiting for disconnection, wait_cnt: %d\n", wait_cnt
));
5724 wl_cfg80211_disconnect(struct wiphy
*wiphy
, struct net_device
*dev
,
5727 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5732 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
5733 WL_ERR(("Reason %d\n", reason_code
));
5734 RETURN_EIO_IF_NOT_UP(cfg
);
5735 act
= *(bool *) wl_read_prof(cfg
, dev
, WL_PROF_ACT
);
5736 curbssid
= wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
5738 BCM_REFERENCE(dhdp
);
5740 #ifdef ESCAN_RESULT_PATCH
5741 if (wl_get_drv_status(cfg
, CONNECTING
, dev
) && curbssid
&&
5742 (memcmp(curbssid
, connect_req_bssid
, ETHER_ADDR_LEN
) == 0)) {
5743 WL_ERR(("Disconnecting from connecting device: " MACDBG
"\n",
5744 MAC2STRDBG(curbssid
)));
5747 #endif /* ESCAN_RESULT_PATCH */
5751 if (dev
== bcmcfg_to_prmry_ndev(cfg
)) {
5752 DHD_DBG_PKT_MON_STOP(dhdp
);
5754 #endif /* DBG_PKT_MON */
5756 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
5758 #if !defined(ESCAN_RESULT_PATCH)
5759 /* Let scan aborted by F/W */
5760 if (cfg
->scan_request
) {
5761 WL_TRACE_HW4(("Aborting the scan! \n"));
5762 wl_notify_escan_complete(cfg
, dev
, true, true);
5764 #endif /* ESCAN_RESULT_PATCH */
5765 if (wl_get_drv_status(cfg
, CONNECTING
, dev
) ||
5766 wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
5767 wl_set_drv_status(cfg
, DISCONNECTING
, dev
);
5768 scbval
.val
= reason_code
;
5769 memcpy(&scbval
.ea
, curbssid
, ETHER_ADDR_LEN
);
5770 scbval
.val
= htod32(scbval
.val
);
5771 err
= wldev_ioctl_set(dev
, WLC_DISASSOC
, &scbval
,
5773 if (unlikely(err
)) {
5774 wl_clr_drv_status(cfg
, DISCONNECTING
, dev
);
5775 WL_ERR(("error (%d)\n", err
));
5778 wl_cfg80211_wait_for_disconnection(cfg
, dev
);
5781 #ifdef CUSTOM_SET_CPUCORE
5782 /* set default cpucore */
5783 if (dev
== bcmcfg_to_prmry_ndev(cfg
)) {
5784 dhdp
->chan_isvht80
&= ~DHD_FLAG_STA_MODE
;
5785 if (!(dhdp
->chan_isvht80
))
5786 dhd_set_cpucore(dhdp
, FALSE
);
5788 #endif /* CUSTOM_SET_CPUCORE */
5794 #if defined(WL_CFG80211_P2P_DEV_IF)
5795 wl_cfg80211_set_tx_power(struct wiphy
*wiphy
, struct wireless_dev
*wdev
,
5796 enum nl80211_tx_power_setting type
, s32 mbm
)
5798 wl_cfg80211_set_tx_power(struct wiphy
*wiphy
,
5799 enum nl80211_tx_power_setting type
, s32 dbm
)
5800 #endif /* WL_CFG80211_P2P_DEV_IF */
5803 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5804 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
5806 #if defined(WL_CFG80211_P2P_DEV_IF)
5807 s32 dbm
= MBM_TO_DBM(mbm
);
5808 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
5809 defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
5810 dbm
= MBM_TO_DBM(dbm
);
5811 #endif /* WL_CFG80211_P2P_DEV_IF */
5813 RETURN_EIO_IF_NOT_UP(cfg
);
5815 case NL80211_TX_POWER_AUTOMATIC
:
5817 case NL80211_TX_POWER_LIMITED
:
5819 WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
5823 case NL80211_TX_POWER_FIXED
:
5825 WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
5831 err
= wl_set_tx_power(ndev
, type
, dbm
);
5832 if (unlikely(err
)) {
5833 WL_ERR(("error (%d)\n", err
));
5837 cfg
->conf
->tx_power
= dbm
;
5843 #if defined(WL_CFG80211_P2P_DEV_IF)
5844 wl_cfg80211_get_tx_power(struct wiphy
*wiphy
,
5845 struct wireless_dev
*wdev
, s32
*dbm
)
5847 wl_cfg80211_get_tx_power(struct wiphy
*wiphy
, s32
*dbm
)
5848 #endif /* WL_CFG80211_P2P_DEV_IF */
5850 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5851 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
5854 RETURN_EIO_IF_NOT_UP(cfg
);
5855 err
= wl_get_tx_power(ndev
, dbm
);
5857 WL_ERR(("error (%d)\n", err
));
5863 wl_cfg80211_config_default_key(struct wiphy
*wiphy
, struct net_device
*dev
,
5864 u8 key_idx
, bool unicast
, bool multicast
)
5866 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5872 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5873 WL_ERR(("Find p2p index from dev(%p) failed\n", dev
->ieee80211_ptr
));
5877 WL_DBG(("key index (%d)\n", key_idx
));
5878 RETURN_EIO_IF_NOT_UP(cfg
);
5879 err
= wldev_iovar_getint_bsscfg(dev
, "wsec", &wsec
, bssidx
);
5880 if (unlikely(err
)) {
5881 WL_ERR(("WLC_GET_WSEC error (%d)\n", err
));
5884 if (wsec
== WEP_ENABLED
) {
5885 /* Just select a new current key */
5886 index
= (u32
) key_idx
;
5887 index
= htod32(index
);
5888 err
= wldev_ioctl_set(dev
, WLC_SET_KEY_PRIMARY
, &index
,
5890 if (unlikely(err
)) {
5891 WL_ERR(("error (%d)\n", err
));
5898 wl_add_keyext(struct wiphy
*wiphy
, struct net_device
*dev
,
5899 u8 key_idx
, const u8
*mac_addr
, struct key_params
*params
)
5901 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
5902 struct wl_wsec_key key
;
5905 s32 mode
= wl_get_mode_by_netdev(cfg
, dev
);
5907 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
5908 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
5911 memset(&key
, 0, sizeof(key
));
5912 key
.index
= (u32
) key_idx
;
5914 if (!ETHER_ISMULTI(mac_addr
))
5915 memcpy((char *)&key
.ea
, (const void *)mac_addr
, ETHER_ADDR_LEN
);
5916 key
.len
= (u32
) params
->key_len
;
5918 /* check for key index change */
5921 swap_key_from_BE(&key
);
5922 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &key
, sizeof(key
),
5923 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
5924 if (unlikely(err
)) {
5925 WL_ERR(("key delete error (%d)\n", err
));
5929 if (key
.len
> sizeof(key
.data
)) {
5930 WL_ERR(("Invalid key length (%d)\n", key
.len
));
5933 WL_DBG(("Setting the key index %d\n", key
.index
));
5934 memcpy(key
.data
, params
->key
, key
.len
);
5936 if ((mode
== WL_MODE_BSS
) &&
5937 (params
->cipher
== WLAN_CIPHER_SUITE_TKIP
)) {
5939 memcpy(keybuf
, &key
.data
[24], sizeof(keybuf
));
5940 memcpy(&key
.data
[24], &key
.data
[16], sizeof(keybuf
));
5941 memcpy(&key
.data
[16], keybuf
, sizeof(keybuf
));
5944 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
5945 if (params
->seq
&& params
->seq_len
== 6) {
5948 ivptr
= (u8
*) params
->seq
;
5949 key
.rxiv
.hi
= (ivptr
[5] << 24) | (ivptr
[4] << 16) |
5950 (ivptr
[3] << 8) | ivptr
[2];
5951 key
.rxiv
.lo
= (ivptr
[1] << 8) | ivptr
[0];
5952 key
.iv_initialized
= true;
5955 switch (params
->cipher
) {
5956 case WLAN_CIPHER_SUITE_WEP40
:
5957 key
.algo
= CRYPTO_ALGO_WEP1
;
5958 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
5960 case WLAN_CIPHER_SUITE_WEP104
:
5961 key
.algo
= CRYPTO_ALGO_WEP128
;
5962 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
5964 case WLAN_CIPHER_SUITE_TKIP
:
5965 key
.algo
= CRYPTO_ALGO_TKIP
;
5966 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
5968 case WLAN_CIPHER_SUITE_AES_CMAC
:
5969 key
.algo
= CRYPTO_ALGO_AES_CCM
;
5970 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
5972 case WLAN_CIPHER_SUITE_CCMP
:
5973 key
.algo
= CRYPTO_ALGO_AES_CCM
;
5974 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
5977 WL_ERR(("Invalid cipher (0x%x)\n", params
->cipher
));
5980 swap_key_from_BE(&key
);
5981 /* need to guarantee EAPOL 4/4 send out before set key */
5982 dhd_wait_pend8021x(dev
);
5983 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &key
, sizeof(key
),
5984 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
5985 if (unlikely(err
)) {
5986 WL_ERR(("WLC_SET_KEY error (%d)\n", err
));
5994 wl_cfg80211_enable_roam_offload(struct net_device
*dev
, int enable
)
5997 wl_eventmsg_buf_t ev_buf
;
5998 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6000 if (dev
!= bcmcfg_to_prmry_ndev(cfg
)) {
6001 /* roam offload is only for the primary device */
6004 err
= wldev_iovar_setint(dev
, "roam_offload", enable
);
6008 bzero(&ev_buf
, sizeof(wl_eventmsg_buf_t
));
6009 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_PSK_SUP
, !enable
);
6010 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_ASSOC_REQ_IE
, !enable
);
6011 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_ASSOC_RESP_IE
, !enable
);
6012 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_REASSOC
, !enable
);
6013 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_JOIN
, !enable
);
6014 wl_cfg80211_add_to_eventbuffer(&ev_buf
, WLC_E_ROAM
, !enable
);
6015 err
= wl_cfg80211_apply_eventbuffer(dev
, cfg
, &ev_buf
);
6017 cfg
->roam_offload
= enable
;
6022 #if defined(WL_VIRTUAL_APSTA)
6024 wl_cfg80211_interface_create(struct net_device
*dev
, char *name
)
6026 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6027 bcm_struct_cfgdev
*new_cfgdev
;
6029 char ifname
[IFNAMSIZ
];
6030 char iftype
[IFNAMSIZ
];
6031 enum nl80211_iftype iface_type
= NL80211_IFTYPE_STATION
;
6033 sscanf(name
, "%s %s", ifname
, iftype
);
6035 if (strnicmp(iftype
, "AP", strlen("AP")) == 0) {
6036 iface_type
= NL80211_IFTYPE_AP
;
6040 new_cfgdev
= wl_cfg80211_create_iface(cfg
->wdev
->wiphy
,
6042 iface_type
, NULL
, ifname
);
6044 NL80211_IFTYPE_STATION
, NULL
, name
);
6050 WL_DBG(("Iface %s created successfuly\n", name
));
6056 wl_cfg80211_interface_delete(struct net_device
*dev
, char *name
)
6058 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6059 struct net_info
*iter
, *next
;
6060 int err
= BCME_ERROR
;
6066 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
6067 #pragma GCC diagnostic push
6068 #pragma GCC diagnostic ignored "-Wcast-qual"
6070 for_each_ndev(cfg
, iter
, next
) {
6072 if (strcmp(iter
->ndev
->name
, name
) == 0) {
6073 err
= wl_cfg80211_del_iface(cfg
->wdev
->wiphy
,
6074 ndev_to_cfgdev(iter
->ndev
));
6079 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
6080 #pragma GCC diagnostic pop
6083 WL_DBG(("Iface %s deleted successfuly", name
));
6088 #if defined(PKT_FILTER_SUPPORT) && defined(APSTA_BLOCK_ARP_DURING_DHCP)
6090 wl_cfg80211_block_arp(struct net_device
*dev
, int enable
)
6092 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6093 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
6095 if (!dhd_pkt_filter_enable
) {
6096 WL_INFORM(("Packet filter isn't enabled\n"));
6100 /* Block/Unblock ARP frames only if STA is connected to
6101 * the upstream AP in case of STA+SoftAP Concurrenct mode
6103 if (!wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
6104 WL_INFORM(("STA doesn't connected to upstream AP\n"));
6109 WL_DBG(("Enable ARP Filter\n"));
6110 /* Add ARP filter */
6111 dhd_packet_filter_add_remove(dhdp
, TRUE
, DHD_BROADCAST_ARP_FILTER_NUM
);
6113 /* Enable ARP packet filter - blacklist */
6114 dhd_master_mode
= FALSE
;
6115 dhd_pktfilter_offload_enable(dhdp
, dhdp
->pktfilter
[DHD_BROADCAST_ARP_FILTER_NUM
],
6116 TRUE
, dhd_master_mode
);
6118 WL_DBG(("Disable ARP Filter\n"));
6119 /* Disable ARP packet filter */
6120 dhd_master_mode
= TRUE
;
6121 dhd_pktfilter_offload_enable(dhdp
, dhdp
->pktfilter
[DHD_BROADCAST_ARP_FILTER_NUM
],
6122 FALSE
, dhd_master_mode
);
6124 /* Delete ARP filter */
6125 dhd_packet_filter_add_remove(dhdp
, FALSE
, DHD_BROADCAST_ARP_FILTER_NUM
);
6128 #endif /* PKT_FILTER_SUPPORT && APSTA_BLOCK_ARP_DURING_DHCP */
6129 #endif /* defined (WL_VIRTUAL_APSTA) */
6132 wl_cfg80211_add_key(struct wiphy
*wiphy
, struct net_device
*dev
,
6133 u8 key_idx
, bool pairwise
, const u8
*mac_addr
,
6134 struct key_params
*params
)
6136 struct wl_wsec_key key
;
6142 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6143 s32 mode
= wl_get_mode_by_netdev(cfg
, dev
);
6144 WL_DBG(("key index (%d)\n", key_idx
));
6145 RETURN_EIO_IF_NOT_UP(cfg
);
6147 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
6148 WL_ERR(("Find p2p index from dev(%p) failed\n", dev
->ieee80211_ptr
));
6153 ((params
->cipher
!= WLAN_CIPHER_SUITE_WEP40
) &&
6154 (params
->cipher
!= WLAN_CIPHER_SUITE_WEP104
))) {
6155 wl_add_keyext(wiphy
, dev
, key_idx
, mac_addr
, params
);
6158 memset(&key
, 0, sizeof(key
));
6159 /* Clear any buffered wep key */
6160 memset(&cfg
->wep_key
, 0, sizeof(struct wl_wsec_key
));
6162 key
.len
= (u32
) params
->key_len
;
6163 key
.index
= (u32
) key_idx
;
6165 if (unlikely(key
.len
> sizeof(key
.data
))) {
6166 WL_ERR(("Too long key length (%u)\n", key
.len
));
6169 memcpy(key
.data
, params
->key
, key
.len
);
6171 key
.flags
= WL_PRIMARY_KEY
;
6172 switch (params
->cipher
) {
6173 case WLAN_CIPHER_SUITE_WEP40
:
6174 key
.algo
= CRYPTO_ALGO_WEP1
;
6176 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
6178 case WLAN_CIPHER_SUITE_WEP104
:
6179 key
.algo
= CRYPTO_ALGO_WEP128
;
6181 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
6183 case WLAN_CIPHER_SUITE_TKIP
:
6184 key
.algo
= CRYPTO_ALGO_TKIP
;
6186 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
6187 if (mode
== WL_MODE_BSS
) {
6188 bcopy(&key
.data
[24], keybuf
, sizeof(keybuf
));
6189 bcopy(&key
.data
[16], &key
.data
[24], sizeof(keybuf
));
6190 bcopy(keybuf
, &key
.data
[16], sizeof(keybuf
));
6192 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6194 case WLAN_CIPHER_SUITE_AES_CMAC
:
6195 key
.algo
= CRYPTO_ALGO_AES_CCM
;
6197 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
6199 case WLAN_CIPHER_SUITE_CCMP
:
6200 key
.algo
= CRYPTO_ALGO_AES_CCM
;
6202 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
6205 WL_ERR(("Invalid cipher (0x%x)\n", params
->cipher
));
6209 /* Set the new key/index */
6210 if ((mode
== WL_MODE_IBSS
) && (val
& (TKIP_ENABLED
| AES_ENABLED
))) {
6211 WL_ERR(("IBSS KEY setted\n"));
6212 wldev_iovar_setint(dev
, "wpa_auth", WPA_AUTH_NONE
);
6214 swap_key_from_BE(&key
);
6215 if ((params
->cipher
== WLAN_CIPHER_SUITE_WEP40
) ||
6216 (params
->cipher
== WLAN_CIPHER_SUITE_WEP104
)) {
6218 * For AP role, since we are doing a wl down before bringing up AP,
6219 * the plumbed keys will be lost. So for AP once we bring up AP, we
6220 * need to plumb keys again. So buffer the keys for future use. This
6221 * is more like a WAR. If firmware later has the capability to do
6222 * interface upgrade without doing a "wl down" and "wl apsta 0", then
6223 * this will not be required.
6225 WL_DBG(("Buffering WEP Keys \n"));
6226 memcpy(&cfg
->wep_key
, &key
, sizeof(struct wl_wsec_key
));
6228 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &key
, sizeof(key
), cfg
->ioctl_buf
,
6229 WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
6230 if (unlikely(err
)) {
6231 WL_ERR(("WLC_SET_KEY error (%d)\n", err
));
6236 err
= wldev_iovar_getint_bsscfg(dev
, "wsec", &wsec
, bssidx
);
6237 if (unlikely(err
)) {
6238 WL_ERR(("get wsec error (%d)\n", err
));
6243 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", wsec
, bssidx
);
6244 if (unlikely(err
)) {
6245 WL_ERR(("set wsec error (%d)\n", err
));
6253 wl_cfg80211_del_key(struct wiphy
*wiphy
, struct net_device
*dev
,
6254 u8 key_idx
, bool pairwise
, const u8
*mac_addr
)
6256 struct wl_wsec_key key
;
6257 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6261 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
6262 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
6265 WL_DBG(("Enter\n"));
6268 if ((key_idx
>= DOT11_MAX_DEFAULT_KEYS
) && (key_idx
< DOT11_MAX_DEFAULT_KEYS
+2))
6272 RETURN_EIO_IF_NOT_UP(cfg
);
6273 memset(&key
, 0, sizeof(key
));
6275 key
.flags
= WL_PRIMARY_KEY
;
6276 key
.algo
= CRYPTO_ALGO_OFF
;
6277 key
.index
= (u32
) key_idx
;
6279 WL_DBG(("key index (%d)\n", key_idx
));
6280 /* Set the new key/index */
6281 swap_key_from_BE(&key
);
6282 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &key
, sizeof(key
), cfg
->ioctl_buf
,
6283 WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
6284 if (unlikely(err
)) {
6285 if (err
== -EINVAL
) {
6286 if (key
.index
>= DOT11_MAX_DEFAULT_KEYS
) {
6287 /* we ignore this key index in this case */
6288 WL_DBG(("invalid key index (%d)\n", key_idx
));
6291 WL_ERR(("WLC_SET_KEY error (%d)\n", err
));
6299 wl_cfg80211_get_key(struct wiphy
*wiphy
, struct net_device
*dev
,
6300 u8 key_idx
, bool pairwise
, const u8
*mac_addr
, void *cookie
,
6301 void (*callback
) (void *cookie
, struct key_params
* params
))
6303 struct key_params params
;
6304 struct wl_wsec_key key
;
6305 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6306 struct wl_security
*sec
;
6311 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
6312 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
6315 WL_DBG(("key index (%d)\n", key_idx
));
6316 RETURN_EIO_IF_NOT_UP(cfg
);
6317 memset(&key
, 0, sizeof(key
));
6318 key
.index
= key_idx
;
6319 swap_key_to_BE(&key
);
6320 memset(¶ms
, 0, sizeof(params
));
6321 params
.key_len
= (u8
) min_t(u8
, DOT11_MAX_KEY_SIZE
, key
.len
);
6322 memcpy((void *)params
.key
, key
.data
, params
.key_len
);
6324 err
= wldev_iovar_getint_bsscfg(dev
, "wsec", &wsec
, bssidx
);
6325 if (unlikely(err
)) {
6326 WL_ERR(("WLC_GET_WSEC error (%d)\n", err
));
6329 switch (WSEC_ENABLED(wsec
)) {
6331 sec
= wl_read_prof(cfg
, dev
, WL_PROF_SEC
);
6332 if (sec
->cipher_pairwise
& WLAN_CIPHER_SUITE_WEP40
) {
6333 params
.cipher
= WLAN_CIPHER_SUITE_WEP40
;
6334 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
6335 } else if (sec
->cipher_pairwise
& WLAN_CIPHER_SUITE_WEP104
) {
6336 params
.cipher
= WLAN_CIPHER_SUITE_WEP104
;
6337 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
6341 params
.cipher
= WLAN_CIPHER_SUITE_TKIP
;
6342 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6345 params
.cipher
= WLAN_CIPHER_SUITE_AES_CMAC
;
6346 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
6348 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
6349 /* to connect to mixed mode AP */
6350 case (AES_ENABLED
| TKIP_ENABLED
): /* TKIP CCMP */
6351 params
.cipher
= WLAN_CIPHER_SUITE_AES_CMAC
;
6352 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6356 WL_ERR(("Invalid algo (0x%x)\n", wsec
));
6360 callback(cookie
, ¶ms
);
6365 wl_cfg80211_config_default_mgmt_key(struct wiphy
*wiphy
,
6366 struct net_device
*dev
, u8 key_idx
)
6371 WL_INFORM(("Not supported\n"));
6376 #if defined(RSSIAVG)
6377 static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl
;
6378 static wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl
;
6380 #if defined(BSSCACHE)
6381 static wl_bss_cache_ctrl_t g_bss_cache_ctrl
;
6385 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
6386 wl_cfg80211_get_station(struct wiphy
*wiphy
, struct net_device
*dev
,
6387 const u8
*mac
, struct station_info
*sinfo
)
6389 wl_cfg80211_get_station(struct wiphy
*wiphy
, struct net_device
*dev
,
6390 u8
*mac
, struct station_info
*sinfo
)
6393 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6399 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
6400 s8 eabuf
[ETHER_ADDR_STR_LEN
];
6402 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
6403 bool fw_assoc_state
= FALSE
;
6404 u32 dhd_assoc_state
= 0;
6405 static int err_cnt
= 0;
6407 RETURN_EIO_IF_NOT_UP(cfg
);
6408 if (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
) {
6409 err
= wldev_iovar_getbuf(dev
, "sta_info", (struct ether_addr
*)mac
,
6410 ETHER_ADDR_LEN
, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
);
6412 WL_ERR(("GET STA INFO failed, %d\n", err
));
6415 sinfo
->filled
= STA_INFO_BIT(INFO_INACTIVE_TIME
);
6416 sta
= (sta_info_t
*)cfg
->ioctl_buf
;
6417 sta
->len
= dtoh16(sta
->len
);
6418 sta
->cap
= dtoh16(sta
->cap
);
6419 sta
->flags
= dtoh32(sta
->flags
);
6420 sta
->idle
= dtoh32(sta
->idle
);
6421 sta
->in
= dtoh32(sta
->in
);
6422 sinfo
->inactive_time
= sta
->idle
* 1000;
6423 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
6424 if (sta
->flags
& WL_STA_ASSOC
) {
6425 sinfo
->filled
|= STA_INFO_BIT(INFO_CONNECTED_TIME
);
6426 sinfo
->connected_time
= sta
->in
;
6428 WL_INFORM(("STA %s : idle time : %d sec, connected time :%d ms\n",
6429 bcm_ether_ntoa((const struct ether_addr
*)mac
, eabuf
), sinfo
->inactive_time
,
6432 } else if (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_BSS
||
6433 wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_IBSS
) {
6434 get_pktcnt_t pktcnt
;
6435 #ifdef DHD_SUPPORT_IF_CNTS
6436 wl_if_stats_t
*if_stats
= NULL
;
6437 #endif /* DHD_SUPPORT_IF_CNTS */
6440 if (cfg
->roam_offload
) {
6441 struct ether_addr bssid
;
6442 memset(&bssid
, 0, sizeof(bssid
));
6443 err
= wldev_ioctl_get(dev
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
);
6445 WL_ERR(("Failed to get current BSSID\n"));
6447 if (memcmp(mac
, &bssid
.octet
, ETHER_ADDR_LEN
) != 0) {
6448 /* roaming is detected */
6449 err
= wl_cfg80211_delayed_roam(cfg
, dev
, &bssid
);
6451 WL_ERR(("Failed to handle the delayed roam, "
6453 mac
= (u8
*)bssid
.octet
;
6457 dhd_assoc_state
= wl_get_drv_status(cfg
, CONNECTED
, dev
);
6458 DHD_OS_WAKE_LOCK(dhd
);
6459 fw_assoc_state
= dhd_is_associated(dhd
, 0, &err
);
6460 DHD_OS_WAKE_UNLOCK(dhd
);
6461 if (!dhd_assoc_state
|| !fw_assoc_state
) {
6462 WL_ERR(("NOT assoc\n"));
6463 if (err
== -ENODATA
)
6465 if (!dhd_assoc_state
) {
6466 WL_TRACE_HW4(("drv state is not connected \n"));
6468 if (!fw_assoc_state
) {
6469 WL_TRACE_HW4(("fw state is not associated \n"));
6471 /* Disconnect due to fw is not associated for FW_ASSOC_WATCHDOG_TIME ms.
6472 * 'err == 0' of dhd_is_associated() and '!fw_assoc_state'
6473 * means that BSSID is null.
6475 if (dhd_assoc_state
&& !fw_assoc_state
&& !err
) {
6476 if (!fw_assoc_watchdog_started
) {
6477 fw_assoc_watchdog_ms
= OSL_SYSUPTIME();
6478 fw_assoc_watchdog_started
= TRUE
;
6479 WL_TRACE_HW4(("fw_assoc_watchdog_started \n"));
6481 if (OSL_SYSUPTIME() - fw_assoc_watchdog_ms
>
6482 FW_ASSOC_WATCHDOG_TIME
) {
6483 fw_assoc_watchdog_started
= FALSE
;
6485 WL_TRACE_HW4(("fw is not associated for %d ms \n",
6486 (OSL_SYSUPTIME() - fw_assoc_watchdog_ms
)));
6487 goto get_station_err
;
6494 fw_assoc_watchdog_started
= FALSE
;
6495 curmacp
= wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
6496 if (memcmp(mac
, curmacp
, ETHER_ADDR_LEN
)) {
6497 WL_ERR(("Wrong Mac address: "MACDBG
" != "MACDBG
"\n",
6498 MAC2STRDBG(mac
), MAC2STRDBG(curmacp
)));
6501 /* Report the current tx rate */
6503 err
= wldev_ioctl_get(dev
, WLC_GET_RATE
, &rate
, sizeof(rate
));
6505 WL_ERR(("Could not get rate (%d)\n", err
));
6507 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
6510 rate
= dtoh32(rate
);
6511 sinfo
->filled
|= STA_INFO_BIT(INFO_TX_BITRATE
);
6512 sinfo
->txrate
.legacy
= rate
* 5;
6513 WL_DBG(("Rate %d Mbps\n", (rate
/ 2)));
6514 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
6515 rxpktglom
= ((rate
/2) > 150) ? 20 : 10;
6517 if (maxrxpktglom
!= rxpktglom
) {
6518 maxrxpktglom
= rxpktglom
;
6519 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate
/2),
6521 err
= wldev_iovar_setbuf(dev
, "bus:maxtxpktglom",
6522 (char*)&maxrxpktglom
, 4, cfg
->ioctl_buf
,
6523 WLC_IOCTL_MAXLEN
, NULL
);
6525 WL_ERR(("set bus:maxtxpktglom failed, %d\n", err
));
6531 memset(&scb_val
, 0, sizeof(scb_val
));
6533 err
= wldev_ioctl_get(dev
, WLC_GET_RSSI
, &scb_val
,
6536 WL_ERR(("Could not get rssi (%d)\n", err
));
6537 goto get_station_err
;
6539 rssi
= dtoh32(scb_val
.val
);
6540 #if defined(RSSIAVG)
6541 err
= wl_update_connected_rssi_cache(dev
, &g_connected_rssi_cache_ctrl
, &rssi
);
6543 WL_ERR(("Could not get rssi (%d)\n", err
));
6544 goto get_station_err
;
6546 wl_delete_dirty_rssi_cache(&g_connected_rssi_cache_ctrl
);
6547 wl_reset_rssi_cache(&g_connected_rssi_cache_ctrl
);
6549 #if defined(RSSIOFFSET)
6550 rssi
= wl_update_rssi_offset(dev
, rssi
);
6552 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
6553 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
6554 rssi
= MIN(rssi
, RSSI_MAXVAL
);
6556 sinfo
->filled
|= STA_INFO_BIT(INFO_SIGNAL
);
6557 sinfo
->signal
= rssi
;
6558 WL_DBG(("RSSI %d dBm\n", rssi
));
6560 #ifdef DHD_SUPPORT_IF_CNTS
6561 if ((if_stats
= kmalloc(sizeof(*if_stats
), GFP_KERNEL
)) == NULL
) {
6562 WL_ERR(("%s(%d): kmalloc failed\n", __FUNCTION__
, __LINE__
));
6565 memset(if_stats
, 0, sizeof(*if_stats
));
6567 err
= wldev_iovar_getbuf(dev
, "if_counters", NULL
, 0,
6568 (char *)if_stats
, sizeof(*if_stats
), NULL
);
6570 sinfo
->rx_packets
= (uint32
)dtoh64(if_stats
->rxframe
);
6571 sinfo
->rx_dropped_misc
= 0;
6572 sinfo
->tx_packets
= (uint32
)dtoh64(if_stats
->txfrmsnt
);
6573 sinfo
->tx_failed
= (uint32
)dtoh64(if_stats
->txnobuf
) +
6574 (uint32
)dtoh64(if_stats
->txrunt
) +
6575 (uint32
)dtoh64(if_stats
->txfail
);
6577 // WL_ERR(("%s: if_counters not supported ret=%d\n",
6578 // __FUNCTION__, err));
6579 #endif /* DHD_SUPPORT_IF_CNTS */
6581 err
= wldev_ioctl_get(dev
, WLC_GET_PKTCNTS
, &pktcnt
,
6584 WL_ERR(("Could not get WLC_GET_PKTCNTS (%d)\n", err
));
6585 goto get_station_err
;
6587 sinfo
->rx_packets
= pktcnt
.rx_good_pkt
;
6588 sinfo
->rx_dropped_misc
= pktcnt
.rx_bad_pkt
;
6589 sinfo
->tx_packets
= pktcnt
.tx_good_pkt
;
6590 sinfo
->tx_failed
= pktcnt
.tx_bad_pkt
;
6591 #ifdef DHD_SUPPORT_IF_CNTS
6593 #endif /* DHD_SUPPORT_IF_CNTS */
6595 sinfo
->filled
|= (STA_INFO_BIT(INFO_RX_PACKETS
) |
6596 STA_INFO_BIT(INFO_RX_DROP_MISC
) |
6597 STA_INFO_BIT(INFO_TX_PACKETS
) |
6598 STA_INFO_BIT(INFO_TX_FAILED
));
6605 if (err_cnt
>= 3 && (err
!= -ENODATA
)) {
6606 /* Disconnect due to zero BSSID or error to get RSSI */
6608 scbval
.val
= htod32(DOT11_RC_DISASSOC_LEAVING
);
6609 err
= wldev_ioctl_set(dev
, WLC_DISASSOC
, &scbval
, sizeof(scb_val_t
));
6610 if (unlikely(err
)) {
6611 WL_ERR(("disassoc error (%d)\n", err
));
6614 WL_ERR(("force cfg80211_disconnected: %d\n", err
));
6615 wl_clr_drv_status(cfg
, CONNECTED
, dev
);
6616 CFG80211_DISCONNECTED(dev
, 0, NULL
, 0, false, GFP_KERNEL
);
6619 #ifdef DHD_SUPPORT_IF_CNTS
6624 #endif /* DHD_SUPPORT_IF_CNTS */
6627 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg
, dev
)));
6634 wl_cfg80211_set_power_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
6635 bool enabled
, s32 timeout
)
6639 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6640 struct net_info
*_net_info
= wl_get_netinfo_by_netdev(cfg
, dev
);
6642 rtt_status_info_t
*rtt_status
;
6643 #endif /* RTT_SUPPORT */
6644 dhd_pub_t
*dhd
= cfg
->pub
;
6646 RETURN_EIO_IF_NOT_UP(cfg
);
6647 WL_DBG(("Enter\n"));
6648 if (cfg
->p2p_net
== dev
|| _net_info
== NULL
||
6649 !wl_get_drv_status(cfg
, CONNECTED
, dev
) ||
6650 (wl_get_mode_by_netdev(cfg
, dev
) != WL_MODE_BSS
&&
6651 wl_get_mode_by_netdev(cfg
, dev
) != WL_MODE_IBSS
)) {
6655 /* Enlarge pm_enable_work */
6656 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_LONG
);
6658 pm
= enabled
? PM_FAST
: PM_OFF
;
6659 if (_net_info
->pm_block
) {
6660 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
6661 dev
->name
, _net_info
->pm_block
));
6664 if (enabled
&& dhd_conf_get_pm(dhd
) >= 0)
6665 pm
= dhd_conf_get_pm(dhd
);
6667 WL_DBG(("%s:power save %s\n", dev
->name
, (pm
? "enabled" : "disabled")));
6669 rtt_status
= GET_RTTSTATE(dhd
);
6670 if (rtt_status
->status
!= RTT_ENABLED
) {
6671 #endif /* RTT_SUPPORT */
6672 err
= wldev_ioctl_set(dev
, WLC_SET_PM
, &pm
, sizeof(pm
));
6673 if (unlikely(err
)) {
6675 WL_DBG(("net_device is not ready yet\n"));
6677 WL_ERR(("error (%d)\n", err
));
6682 #endif /* RTT_SUPPORT */
6683 wl_cfg80211_update_power_mode(dev
);
6687 void wl_cfg80211_update_power_mode(struct net_device
*dev
)
6691 err
= wldev_ioctl_get(dev
, WLC_GET_PM
, &pm
, sizeof(pm
));
6693 WL_ERR(("%s:error (%d)\n", __FUNCTION__
, err
));
6694 else if (pm
!= -1 && dev
->ieee80211_ptr
)
6695 dev
->ieee80211_ptr
->ps
= (pm
== PM_OFF
) ? false : true;
6698 void wl_cfg80211_set_passive_scan(struct net_device
*dev
, char *command
)
6700 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6702 if (strcmp(command
, "SCAN-ACTIVE") == 0) {
6703 cfg
->active_scan
= 1;
6704 } else if (strcmp(command
, "SCAN-PASSIVE") == 0) {
6705 cfg
->active_scan
= 0;
6707 WL_ERR(("Unknown command \n"));
6710 static __used u32
wl_find_msb(u16 bit16
)
6714 if (bit16
& 0xff00) {
6737 static s32
wl_cfg80211_resume(struct wiphy
*wiphy
)
6739 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6740 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
6743 if (unlikely(!wl_get_drv_status(cfg
, READY
, ndev
))) {
6744 WL_INFORM(("device is not ready\n"));
6754 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
6755 wl_cfg80211_suspend(struct wiphy
*wiphy
, struct cfg80211_wowlan
*wow
)
6757 wl_cfg80211_suspend(struct wiphy
*wiphy
)
6758 #endif /* KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES */
6761 #ifdef DHD_CLEAR_ON_SUSPEND
6762 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6763 struct net_info
*iter
, *next
;
6764 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
6765 unsigned long flags
;
6766 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
6767 struct cfg80211_scan_info info
;
6770 if (unlikely(!wl_get_drv_status(cfg
, READY
, ndev
))) {
6771 WL_INFORM(("device is not ready : status (%d)\n",
6775 for_each_ndev(cfg
, iter
, next
) {
6776 /* p2p discovery iface doesn't have a ndev associated with it (for kernel > 3.8) */
6778 wl_set_drv_status(cfg
, SCAN_ABORTING
, iter
->ndev
);
6780 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
6781 if (cfg
->scan_request
) {
6782 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
6783 info
.aborted
= true;
6784 cfg80211_scan_done(cfg
->scan_request
, &info
);
6786 cfg80211_scan_done(cfg
->scan_request
, true);
6788 cfg
->scan_request
= NULL
;
6790 for_each_ndev(cfg
, iter
, next
) {
6792 wl_clr_drv_status(cfg
, SCANNING
, iter
->ndev
);
6793 wl_clr_drv_status(cfg
, SCAN_ABORTING
, iter
->ndev
);
6796 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
6797 for_each_ndev(cfg
, iter
, next
) {
6799 if (wl_get_drv_status(cfg
, CONNECTING
, iter
->ndev
)) {
6800 wl_bss_connect_done(cfg
, iter
->ndev
, NULL
, NULL
, false);
6804 #endif /* DHD_CLEAR_ON_SUSPEND */
6811 wl_update_pmklist(struct net_device
*dev
, struct wl_pmk_list
*pmk_list
,
6815 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
6816 struct net_device
*primary_dev
= bcmcfg_to_prmry_ndev(cfg
);
6819 printf("pmk_list is NULL\n");
6822 /* pmk list is supported only for STA interface i.e. primary interface
6823 * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
6825 if (primary_dev
!= dev
) {
6826 WL_INFORM(("Not supporting Flushing pmklist on virtual"
6827 " interfaces than primary interface\n"));
6831 WL_DBG(("No of elements %d\n", pmk_list
->pmkids
.npmkid
));
6832 for (i
= 0; i
< pmk_list
->pmkids
.npmkid
; i
++) {
6833 WL_DBG(("PMKID[%d]: %pM =\n", i
,
6834 &pmk_list
->pmkids
.pmkid
[i
].BSSID
));
6835 for (j
= 0; j
< WPA2_PMKID_LEN
; j
++) {
6836 WL_DBG(("%02x\n", pmk_list
->pmkids
.pmkid
[i
].PMKID
[j
]));
6840 err
= wldev_iovar_setbuf(dev
, "pmkid_info", (char *)pmk_list
,
6841 sizeof(*pmk_list
), cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
6848 wl_cfg80211_set_pmksa(struct wiphy
*wiphy
, struct net_device
*dev
,
6849 struct cfg80211_pmksa
*pmksa
)
6851 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6855 RETURN_EIO_IF_NOT_UP(cfg
);
6856 for (i
= 0; i
< cfg
->pmk_list
->pmkids
.npmkid
; i
++)
6857 if (!memcmp(pmksa
->bssid
, &cfg
->pmk_list
->pmkids
.pmkid
[i
].BSSID
,
6860 if (i
< WL_NUM_PMKIDS_MAX
) {
6861 memcpy(&cfg
->pmk_list
->pmkids
.pmkid
[i
].BSSID
, pmksa
->bssid
,
6863 memcpy(&cfg
->pmk_list
->pmkids
.pmkid
[i
].PMKID
, pmksa
->pmkid
,
6865 if (i
== cfg
->pmk_list
->pmkids
.npmkid
)
6866 cfg
->pmk_list
->pmkids
.npmkid
++;
6870 WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
6871 &cfg
->pmk_list
->pmkids
.pmkid
[cfg
->pmk_list
->pmkids
.npmkid
- 1].BSSID
));
6872 for (i
= 0; i
< WPA2_PMKID_LEN
; i
++) {
6874 cfg
->pmk_list
->pmkids
.pmkid
[cfg
->pmk_list
->pmkids
.npmkid
- 1].
6878 err
= wl_update_pmklist(dev
, cfg
->pmk_list
, err
);
6884 wl_cfg80211_del_pmksa(struct wiphy
*wiphy
, struct net_device
*dev
,
6885 struct cfg80211_pmksa
*pmksa
)
6887 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6889 struct _pmkid_list pmkid
= {.npmkid
= 0};
6893 RETURN_EIO_IF_NOT_UP(cfg
);
6894 memcpy(&pmkid
.pmkid
[0].BSSID
, pmksa
->bssid
, ETHER_ADDR_LEN
);
6895 memcpy(pmkid
.pmkid
[0].PMKID
, pmksa
->pmkid
, WPA2_PMKID_LEN
);
6897 WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
6898 &pmkid
.pmkid
[0].BSSID
));
6899 for (i
= 0; i
< WPA2_PMKID_LEN
; i
++) {
6900 WL_DBG(("%02x\n", pmkid
.pmkid
[0].PMKID
[i
]));
6903 for (i
= 0; i
< cfg
->pmk_list
->pmkids
.npmkid
; i
++)
6905 (pmksa
->bssid
, &cfg
->pmk_list
->pmkids
.pmkid
[i
].BSSID
,
6909 if ((cfg
->pmk_list
->pmkids
.npmkid
> 0) &&
6910 (i
< cfg
->pmk_list
->pmkids
.npmkid
)) {
6911 memset(&cfg
->pmk_list
->pmkids
.pmkid
[i
], 0, sizeof(pmkid_t
));
6912 for (; i
< (cfg
->pmk_list
->pmkids
.npmkid
- 1); i
++) {
6913 memcpy(&cfg
->pmk_list
->pmkids
.pmkid
[i
].BSSID
,
6914 &cfg
->pmk_list
->pmkids
.pmkid
[i
+ 1].BSSID
,
6916 memcpy(&cfg
->pmk_list
->pmkids
.pmkid
[i
].PMKID
,
6917 &cfg
->pmk_list
->pmkids
.pmkid
[i
+ 1].PMKID
,
6920 cfg
->pmk_list
->pmkids
.npmkid
--;
6925 err
= wl_update_pmklist(dev
, cfg
->pmk_list
, err
);
6932 wl_cfg80211_flush_pmksa(struct wiphy
*wiphy
, struct net_device
*dev
)
6934 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
6936 RETURN_EIO_IF_NOT_UP(cfg
);
6937 memset(cfg
->pmk_list
, 0, sizeof(*cfg
->pmk_list
));
6938 err
= wl_update_pmklist(dev
, cfg
->pmk_list
, err
);
6942 static wl_scan_params_t
*
6943 wl_cfg80211_scan_alloc_params(struct bcm_cfg80211
*cfg
, int channel
, int nprobes
,
6944 int *out_params_size
)
6946 wl_scan_params_t
*params
;
6951 *out_params_size
= 0;
6953 /* Our scan params only need space for 1 channel and 0 ssids */
6954 params_size
= WL_SCAN_PARAMS_FIXED_SIZE
+ 1 * sizeof(uint16
);
6955 params
= (wl_scan_params_t
*) kzalloc(params_size
, GFP_KERNEL
);
6956 if (params
== NULL
) {
6957 WL_ERR(("mem alloc failed (%d bytes)\n", params_size
));
6960 memset(params
, 0, params_size
);
6961 params
->nprobes
= nprobes
;
6963 num_chans
= (channel
== 0) ? 0 : 1;
6965 memcpy(¶ms
->bssid
, ðer_bcast
, ETHER_ADDR_LEN
);
6966 params
->bss_type
= DOT11_BSSTYPE_ANY
;
6967 params
->scan_type
= DOT11_SCANTYPE_ACTIVE
;
6968 params
->nprobes
= htod32(1);
6969 params
->active_time
= htod32(-1);
6970 params
->passive_time
= htod32(-1);
6971 params
->home_time
= htod32(10);
6973 params
->channel_list
[0] = htodchanspec(channel
);
6975 params
->channel_list
[0] = wl_ch_host_to_driver(cfg
, bssidx
, channel
);
6977 /* Our scan params have 1 channel and 0 ssids */
6978 params
->channel_num
= htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT
) |
6979 (num_chans
& WL_SCAN_PARAMS_COUNT_MASK
));
6981 *out_params_size
= params_size
; /* rtn size to the caller */
6986 #if defined(WL_CFG80211_P2P_DEV_IF)
6987 wl_cfg80211_remain_on_channel(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
,
6988 struct ieee80211_channel
*channel
, unsigned int duration
, u64
*cookie
)
6990 wl_cfg80211_remain_on_channel(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
,
6991 struct ieee80211_channel
* channel
,
6992 enum nl80211_channel_type channel_type
,
6993 unsigned int duration
, u64
*cookie
)
6994 #endif /* WL_CFG80211_P2P_DEV_IF */
6999 struct ether_addr primary_mac
;
7000 struct net_device
*ndev
= NULL
;
7001 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7004 PRINT_WDEV_INFO(cfgdev
);
7005 #endif /* DHD_IFDEBUG */
7007 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
7009 WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
7010 ieee80211_frequency_to_channel(channel
->center_freq
),
7011 duration
, (wl_get_drv_status(cfg
, SCANNING
, ndev
)) ? "YES":"NO"));
7014 WL_ERR(("cfg->p2p is not initialized\n"));
7019 #ifdef P2P_LISTEN_OFFLOADING
7020 if (wl_get_p2p_status(cfg
, DISC_IN_PROGRESS
)) {
7021 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
7024 #endif /* P2P_LISTEN_OFFLOADING */
7026 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7027 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
7028 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, true, true);
7030 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7032 target_channel
= ieee80211_frequency_to_channel(channel
->center_freq
);
7033 memcpy(&cfg
->remain_on_chan
, channel
, sizeof(struct ieee80211_channel
));
7034 #if defined(WL_ENABLE_P2P_IF)
7035 cfg
->remain_on_chan_type
= channel_type
;
7036 #endif /* WL_ENABLE_P2P_IF */
7037 id
= ++cfg
->last_roc_id
;
7039 id
= ++cfg
->last_roc_id
;
7042 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7043 if (wl_get_drv_status(cfg
, SCANNING
, ndev
)) {
7044 struct timer_list
*_timer
;
7045 WL_DBG(("scan is running. go to fake listen state\n"));
7047 if (duration
> LONG_LISTEN_TIME
) {
7048 wl_cfg80211_scan_abort(cfg
);
7050 wl_set_drv_status(cfg
, FAKE_REMAINING_ON_CHANNEL
, ndev
);
7052 if (timer_pending(&cfg
->p2p
->listen_timer
)) {
7053 WL_DBG(("cancel current listen timer \n"));
7054 del_timer_sync(&cfg
->p2p
->listen_timer
);
7057 _timer
= &cfg
->p2p
->listen_timer
;
7058 wl_clr_p2p_status(cfg
, LISTEN_EXPIRED
);
7060 INIT_TIMER(_timer
, wl_cfgp2p_listen_expired
, duration
, 0);
7066 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7068 #ifdef WL_CFG80211_SYNC_GON
7069 if (wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM_LISTEN
)) {
7070 /* do not enter listen mode again if we are in listen mode already for next af.
7071 * remain on channel completion will be returned by waiting next af completion.
7073 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7074 wl_set_drv_status(cfg
, FAKE_REMAINING_ON_CHANNEL
, ndev
);
7076 wl_set_drv_status(cfg
, REMAINING_ON_CHANNEL
, ndev
);
7077 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7080 #endif /* WL_CFG80211_SYNC_GON */
7081 if (cfg
->p2p
&& !cfg
->p2p
->on
) {
7082 /* In case of p2p_listen command, supplicant send remain_on_channel
7083 * without turning on P2P
7085 get_primary_mac(cfg
, &primary_mac
);
7086 wl_cfgp2p_generate_bss_mac(cfg
, &primary_mac
);
7090 if (p2p_is_on(cfg
)) {
7091 err
= wl_cfgp2p_enable_discovery(cfg
, ndev
, NULL
, 0);
7092 if (unlikely(err
)) {
7095 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7096 wl_set_drv_status(cfg
, REMAINING_ON_CHANNEL
, ndev
);
7097 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7098 err
= wl_cfgp2p_discover_listen(cfg
, target_channel
, duration
);
7100 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7101 if (err
== BCME_OK
) {
7102 wl_set_drv_status(cfg
, REMAINING_ON_CHANNEL
, ndev
);
7104 /* if failed, firmware may be internal scanning state.
7105 * so other scan request shall not abort it
7107 wl_set_drv_status(cfg
, FAKE_REMAINING_ON_CHANNEL
, ndev
);
7109 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7110 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
7111 * and expire timer will send a completion to the upper layer
7117 if (err
== BCME_OK
) {
7118 WL_INFORM(("Success\n"));
7119 #if defined(WL_CFG80211_P2P_DEV_IF)
7120 cfg80211_ready_on_channel(cfgdev
, *cookie
, channel
,
7121 duration
, GFP_KERNEL
);
7123 cfg80211_ready_on_channel(cfgdev
, *cookie
, channel
,
7124 channel_type
, duration
, GFP_KERNEL
);
7125 #endif /* WL_CFG80211_P2P_DEV_IF */
7127 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err
, *cookie
));
7133 wl_cfg80211_cancel_remain_on_channel(struct wiphy
*wiphy
,
7134 bcm_struct_cfgdev
*cfgdev
, u64 cookie
)
7138 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7140 #ifdef P2PLISTEN_AP_SAMECHN
7141 struct net_device
*dev
;
7142 #endif /* P2PLISTEN_AP_SAMECHN */
7144 RETURN_EIO_IF_NOT_UP(cfg
);
7147 PRINT_WDEV_INFO(cfgdev
);
7148 #endif /* DHD_IFDEBUG */
7150 #if defined(WL_CFG80211_P2P_DEV_IF)
7151 if (cfgdev
->iftype
== NL80211_IFTYPE_P2P_DEVICE
) {
7152 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
7155 WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev
->ifindex
));
7156 #endif /* WL_CFG80211_P2P_DEV_IF */
7158 #ifdef P2PLISTEN_AP_SAMECHN
7159 if (cfg
&& cfg
->p2p_resp_apchn_status
) {
7160 dev
= bcmcfg_to_prmry_ndev(cfg
);
7161 wl_cfg80211_set_p2p_resp_ap_chn(dev
, 0);
7162 cfg
->p2p_resp_apchn_status
= false;
7163 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
7165 #endif /* P2PLISTEN_AP_SAMECHN */
7167 if (cfg
->last_roc_id
== cookie
) {
7168 wl_cfgp2p_set_p2p_mode(cfg
, WL_P2P_DISC_ST_SCAN
, 0, 0,
7169 wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
));
7171 WL_ERR(("%s : ignore, request cookie(%llu) is not matched. (cur : %llu)\n",
7172 __FUNCTION__
, cookie
, cfg
->last_roc_id
));
7179 wl_cfg80211_afx_handler(struct work_struct
*work
)
7181 struct afx_hdl
*afx_instance
;
7182 struct bcm_cfg80211
*cfg
;
7185 BCM_SET_CONTAINER_OF(afx_instance
, work
, struct afx_hdl
, work
);
7186 if (!afx_instance
) {
7187 WL_ERR(("afx_instance is NULL\n"));
7190 cfg
= wl_get_cfg(afx_instance
->dev
);
7192 if (cfg
->afx_hdl
->is_active
) {
7193 if (cfg
->afx_hdl
->is_listen
&& cfg
->afx_hdl
->my_listen_chan
) {
7194 ret
= wl_cfgp2p_discover_listen(cfg
, cfg
->afx_hdl
->my_listen_chan
,
7195 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
7197 ret
= wl_cfgp2p_act_frm_search(cfg
, cfg
->afx_hdl
->dev
,
7198 cfg
->afx_hdl
->bssidx
, cfg
->afx_hdl
->peer_listen_chan
,
7201 if (unlikely(ret
!= BCME_OK
)) {
7202 WL_ERR(("ERROR occurred! returned value is (%d)\n", ret
));
7203 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
))
7204 complete(&cfg
->act_frm_scan
);
7211 wl_cfg80211_af_searching_channel(struct bcm_cfg80211
*cfg
, struct net_device
*dev
)
7213 u32 max_retry
= WL_CHANNEL_SYNC_RETRY
;
7214 bool is_p2p_gas
= false;
7219 WL_DBG((" enter ) \n"));
7221 wl_set_drv_status(cfg
, FINDING_COMMON_CHANNEL
, dev
);
7222 cfg
->afx_hdl
->is_active
= TRUE
;
7224 if (cfg
->afx_hdl
->pending_tx_act_frm
) {
7225 wl_action_frame_t
*action_frame
;
7226 action_frame
= &(cfg
->afx_hdl
->pending_tx_act_frm
->action_frame
);
7227 if (wl_cfgp2p_is_p2p_gas_action(action_frame
->data
, action_frame
->len
))
7231 /* Loop to wait until we find a peer's channel or the
7232 * pending action frame tx is cancelled.
7234 while ((cfg
->afx_hdl
->retry
< max_retry
) &&
7235 (cfg
->afx_hdl
->peer_chan
== WL_INVALID
)) {
7236 cfg
->afx_hdl
->is_listen
= FALSE
;
7237 wl_set_drv_status(cfg
, SCANNING
, dev
);
7238 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
7239 cfg
->afx_hdl
->retry
));
7240 /* search peer on peer's listen channel */
7241 schedule_work(&cfg
->afx_hdl
->work
);
7242 wait_for_completion_timeout(&cfg
->act_frm_scan
,
7243 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX
));
7245 if ((cfg
->afx_hdl
->peer_chan
!= WL_INVALID
) ||
7246 !(wl_get_drv_status(cfg
, FINDING_COMMON_CHANNEL
, dev
)))
7252 if (cfg
->afx_hdl
->my_listen_chan
) {
7253 WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
7254 cfg
->afx_hdl
->my_listen_chan
));
7255 /* listen on my listen channel */
7256 cfg
->afx_hdl
->is_listen
= TRUE
;
7257 schedule_work(&cfg
->afx_hdl
->work
);
7258 wait_for_completion_timeout(&cfg
->act_frm_scan
,
7259 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX
));
7261 if ((cfg
->afx_hdl
->peer_chan
!= WL_INVALID
) ||
7262 !(wl_get_drv_status(cfg
, FINDING_COMMON_CHANNEL
, dev
)))
7265 cfg
->afx_hdl
->retry
++;
7267 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg
);
7270 cfg
->afx_hdl
->is_active
= FALSE
;
7272 wl_clr_drv_status(cfg
, SCANNING
, dev
);
7273 wl_clr_drv_status(cfg
, FINDING_COMMON_CHANNEL
, dev
);
7275 return (cfg
->afx_hdl
->peer_chan
);
7278 struct p2p_config_af_params
{
7279 s32 max_tx_retry
; /* max tx retry count if tx no ack */
7280 #ifdef WL_CFG80211_SYNC_GON
7283 bool search_channel
; /* 1: search peer's channel to send af */
7287 wl_cfg80211_config_p2p_pub_af_tx(struct wiphy
*wiphy
,
7288 wl_action_frame_t
*action_frame
, wl_af_params_t
*af_params
,
7289 struct p2p_config_af_params
*config_af_params
)
7292 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7293 wifi_p2p_pub_act_frame_t
*act_frm
=
7294 (wifi_p2p_pub_act_frame_t
*) (action_frame
->data
);
7296 /* initialize default value */
7297 #ifdef WL_CFG80211_SYNC_GON
7298 config_af_params
->extra_listen
= true;
7300 config_af_params
->search_channel
= false;
7301 config_af_params
->max_tx_retry
= WL_AF_TX_MAX_RETRY
;
7302 cfg
->next_af_subtype
= P2P_PAF_SUBTYPE_INVALID
;
7304 switch (act_frm
->subtype
) {
7305 case P2P_PAF_GON_REQ
: {
7306 WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
7307 wl_set_p2p_status(cfg
, GO_NEG_PHASE
);
7309 config_af_params
->search_channel
= true;
7310 cfg
->next_af_subtype
= act_frm
->subtype
+ 1;
7312 /* increase dwell time to wait for RESP frame */
7313 af_params
->dwell_time
= WL_MED_DWELL_TIME
;
7317 case P2P_PAF_GON_RSP
: {
7318 cfg
->next_af_subtype
= act_frm
->subtype
+ 1;
7319 /* increase dwell time to wait for CONF frame */
7320 af_params
->dwell_time
= WL_MED_DWELL_TIME
+ 100;
7323 case P2P_PAF_GON_CONF
: {
7324 /* If we reached till GO Neg confirmation reset the filter */
7325 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
7326 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
7328 /* minimize dwell time */
7329 af_params
->dwell_time
= WL_MIN_DWELL_TIME
;
7331 #ifdef WL_CFG80211_SYNC_GON
7332 config_af_params
->extra_listen
= false;
7333 #endif /* WL_CFG80211_SYNC_GON */
7336 case P2P_PAF_INVITE_REQ
: {
7337 config_af_params
->search_channel
= true;
7338 cfg
->next_af_subtype
= act_frm
->subtype
+ 1;
7340 /* increase dwell time */
7341 af_params
->dwell_time
= WL_MED_DWELL_TIME
;
7344 case P2P_PAF_INVITE_RSP
:
7345 /* minimize dwell time */
7346 af_params
->dwell_time
= WL_MIN_DWELL_TIME
;
7347 #ifdef WL_CFG80211_SYNC_GON
7348 config_af_params
->extra_listen
= false;
7349 #endif /* WL_CFG80211_SYNC_GON */
7351 case P2P_PAF_DEVDIS_REQ
: {
7352 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm
->elts
[0],
7353 action_frame
->len
)) {
7354 config_af_params
->search_channel
= true;
7357 cfg
->next_af_subtype
= act_frm
->subtype
+ 1;
7358 /* maximize dwell time to wait for RESP frame */
7359 af_params
->dwell_time
= WL_LONG_DWELL_TIME
;
7362 case P2P_PAF_DEVDIS_RSP
:
7363 /* minimize dwell time */
7364 af_params
->dwell_time
= WL_MIN_DWELL_TIME
;
7365 #ifdef WL_CFG80211_SYNC_GON
7366 config_af_params
->extra_listen
= false;
7367 #endif /* WL_CFG80211_SYNC_GON */
7369 case P2P_PAF_PROVDIS_REQ
: {
7370 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm
->elts
[0],
7371 action_frame
->len
)) {
7372 config_af_params
->search_channel
= true;
7375 cfg
->next_af_subtype
= act_frm
->subtype
+ 1;
7376 /* increase dwell time to wait for RESP frame */
7377 af_params
->dwell_time
= WL_MED_DWELL_TIME
;
7380 case P2P_PAF_PROVDIS_RSP
: {
7381 cfg
->next_af_subtype
= P2P_PAF_GON_REQ
;
7382 af_params
->dwell_time
= WL_MED_DWELL_TIME
;
7383 #ifdef WL_CFG80211_SYNC_GON
7384 config_af_params
->extra_listen
= false;
7385 #endif /* WL_CFG80211_SYNC_GON */
7389 WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
7398 wl_cfg80211_check_DFS_channel(struct bcm_cfg80211
*cfg
, wl_af_params_t
*af_params
,
7399 void *frame
, u16 frame_len
)
7401 struct wl_scan_results
*bss_list
;
7402 struct wl_bss_info
*bi
= NULL
;
7403 bool result
= false;
7405 chanspec_t chanspec
;
7407 /* If DFS channel is 52~148, check to block it or not */
7409 (af_params
->channel
>= 52 && af_params
->channel
<= 148)) {
7410 if (!wl_cfgp2p_is_p2p_action(frame
, frame_len
)) {
7411 bss_list
= cfg
->bss_list
;
7412 bi
= next_bss(bss_list
, bi
);
7413 for_each_bss(bss_list
, bi
, i
) {
7414 chanspec
= wl_chspec_driver_to_host(bi
->chanspec
);
7415 if (CHSPEC_IS5G(chanspec
) &&
7416 ((bi
->ctl_ch
? bi
->ctl_ch
: CHSPEC_CHANNEL(chanspec
))
7417 == af_params
->channel
)) {
7418 result
= true; /* do not block the action frame */
7428 WL_DBG(("result=%s", result
?"true":"false"));
7433 wl_cfg80211_check_dwell_overflow(int32 requested_dwell
, ulong dwell_jiffies
)
7435 if ((requested_dwell
& CUSTOM_RETRY_MASK
) &&
7436 (jiffies_to_msecs(jiffies
- dwell_jiffies
) >
7437 (requested_dwell
& ~CUSTOM_RETRY_MASK
))) {
7438 WL_ERR(("Action frame TX retry time over dwell time!\n"));
7445 wl_cfg80211_send_action_frame(struct wiphy
*wiphy
, struct net_device
*dev
,
7446 bcm_struct_cfgdev
*cfgdev
, wl_af_params_t
*af_params
,
7447 wl_action_frame_t
*action_frame
, u16 action_frame_len
, s32 bssidx
)
7450 struct net_device
*ndev
= NULL
;
7452 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7454 u8 category
, action
;
7456 struct p2p_config_af_params config_af_params
;
7457 struct net_info
*netinfo
;
7459 ulong off_chan_started_jiffies
= 0;
7461 ulong dwell_jiffies
= 0;
7462 bool dwell_overflow
= false;
7463 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
7464 bool miss_gon_cfm
= false;
7466 int32 requested_dwell
= af_params
->dwell_time
;
7468 /* Add the default dwell time
7469 * Dwell time to stay off-channel to wait for a response action frame
7470 * after transmitting an GO Negotiation action frame
7472 af_params
->dwell_time
= WL_DWELL_TIME
;
7475 #if defined(WL_CFG80211_P2P_DEV_IF)
7478 ndev
= ndev_to_cfgdev(cfgdev
);
7479 #endif /* WL_CFG80211_P2P_DEV_IF */
7482 category
= action_frame
->data
[DOT11_ACTION_CAT_OFF
];
7483 action
= action_frame
->data
[DOT11_ACTION_ACT_OFF
];
7485 /* initialize variables */
7487 cfg
->next_af_subtype
= P2P_PAF_SUBTYPE_INVALID
;
7488 config_af_params
.max_tx_retry
= WL_AF_TX_MAX_RETRY
;
7489 config_af_params
.search_channel
= false;
7490 #ifdef WL_CFG80211_SYNC_GON
7491 config_af_params
.extra_listen
= false;
7494 /* config parameters */
7495 /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
7496 if (category
== DOT11_ACTION_CAT_PUBLIC
) {
7497 if ((action
== P2P_PUB_AF_ACTION
) &&
7498 (action_frame_len
>= sizeof(wifi_p2p_pub_act_frame_t
))) {
7499 /* p2p public action frame process */
7500 if (BCME_OK
!= wl_cfg80211_config_p2p_pub_af_tx(wiphy
,
7501 action_frame
, af_params
, &config_af_params
)) {
7502 WL_DBG(("Unknown subtype.\n"));
7505 } else if (action_frame_len
>= sizeof(wifi_p2psd_gas_pub_act_frame_t
)) {
7506 /* service discovery process */
7507 if (action
== P2PSD_ACTION_ID_GAS_IREQ
||
7508 action
== P2PSD_ACTION_ID_GAS_CREQ
) {
7509 /* configure service discovery query frame */
7511 config_af_params
.search_channel
= true;
7513 /* save next af suptype to cancel remained dwell time */
7514 cfg
->next_af_subtype
= action
+ 1;
7516 af_params
->dwell_time
= WL_MED_DWELL_TIME
;
7517 if (requested_dwell
& CUSTOM_RETRY_MASK
) {
7518 config_af_params
.max_tx_retry
=
7519 (requested_dwell
& CUSTOM_RETRY_MASK
) >> 24;
7520 af_params
->dwell_time
=
7521 (requested_dwell
& ~CUSTOM_RETRY_MASK
);
7522 WL_DBG(("Custom retry(%d) and dwell time(%d) is set.\n",
7523 config_af_params
.max_tx_retry
,
7524 af_params
->dwell_time
));
7526 } else if (action
== P2PSD_ACTION_ID_GAS_IRESP
||
7527 action
== P2PSD_ACTION_ID_GAS_CRESP
) {
7528 /* configure service discovery response frame */
7529 af_params
->dwell_time
= WL_MIN_DWELL_TIME
;
7531 WL_DBG(("Unknown action type: %d\n", action
));
7534 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
7535 category
, action
, action_frame_len
));
7537 } else if (category
== P2P_AF_CATEGORY
) {
7538 /* do not configure anything. it will be sent with a default configuration */
7540 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
7542 if (dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
) {
7543 wl_clr_drv_status(cfg
, SENDING_ACT_FRM
, dev
);
7547 netinfo
= wl_get_netinfo_by_bssidx(cfg
, bssidx
);
7548 /* validate channel and p2p ies */
7549 if (config_af_params
.search_channel
&& IS_P2P_SOCIAL(af_params
->channel
) &&
7550 netinfo
&& netinfo
->bss
.ies
.probe_req_ie_len
) {
7551 config_af_params
.search_channel
= true;
7553 config_af_params
.search_channel
= false;
7556 if (ndev
== bcmcfg_to_prmry_ndev(cfg
))
7557 config_af_params
.search_channel
= false;
7561 /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
7562 if (wl_get_drv_status(cfg
, CONNECTING
, bcmcfg_to_prmry_ndev(cfg
))) {
7567 /* if scan is ongoing, abort current scan. */
7568 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
7569 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, true, true);
7572 /* Abort P2P listen */
7573 if (discover_cfgdev(cfgdev
, cfg
)) {
7574 if (cfg
->p2p_supported
&& cfg
->p2p
) {
7575 wl_cfgp2p_set_p2p_mode(cfg
, WL_P2P_DISC_ST_SCAN
, 0, 0,
7576 wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
));
7581 /* handling DFS channel exceptions */
7582 if (!wl_cfg80211_check_DFS_channel(cfg
, af_params
, action_frame
->data
, action_frame
->len
)) {
7583 return false; /* the action frame was blocked */
7587 /* set status and destination address before sending af */
7588 if (cfg
->next_af_subtype
!= P2P_PAF_SUBTYPE_INVALID
) {
7589 /* set this status to cancel the remained dwell time in rx process */
7590 wl_set_drv_status(cfg
, WAITING_NEXT_ACT_FRM
, dev
);
7592 wl_set_drv_status(cfg
, SENDING_ACT_FRM
, dev
);
7593 memcpy(cfg
->afx_hdl
->tx_dst_addr
.octet
,
7594 af_params
->action_frame
.da
.octet
,
7595 sizeof(cfg
->afx_hdl
->tx_dst_addr
.octet
));
7597 /* save af_params for rx process */
7598 cfg
->afx_hdl
->pending_tx_act_frm
= af_params
;
7600 if (wl_cfgp2p_is_p2p_gas_action(action_frame
->data
, action_frame
->len
)) {
7601 WL_DBG(("Set GAS action frame config.\n"));
7602 config_af_params
.search_channel
= false;
7603 config_af_params
.max_tx_retry
= 1;
7606 /* search peer's channel */
7607 if (config_af_params
.search_channel
) {
7608 /* initialize afx_hdl */
7609 if ((cfg
->afx_hdl
->bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
7610 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
7613 cfg
->afx_hdl
->dev
= dev
;
7614 cfg
->afx_hdl
->retry
= 0;
7615 cfg
->afx_hdl
->peer_chan
= WL_INVALID
;
7617 if (wl_cfg80211_af_searching_channel(cfg
, dev
) == WL_INVALID
) {
7618 WL_ERR(("couldn't find peer's channel.\n"));
7619 wl_cfgp2p_print_actframe(true, action_frame
->data
, action_frame
->len
,
7620 af_params
->channel
);
7621 /* Even if we couldn't find peer channel, try to send the frame
7622 * out. P2P cert 5.1.14 testbed device (realtek) doesn't seem to
7623 * respond to probe request (Ideally it has to be in listen and
7624 * responsd to probe request). However if we send Go neg req, the
7625 * peer is sending GO-neg resp. So instead of giving up here, just
7626 * proceed and attempt sending out the action frame.
7630 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
7632 * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
7633 * but after the check of piggyback algorithm.
7634 * To take care of current piggback algo, lets abort the scan here itself.
7636 wl_notify_escan_complete(cfg
, dev
, true, true);
7637 /* Suspend P2P discovery's search-listen to prevent it from
7638 * starting a scan or changing the channel.
7640 if ((wl_cfgp2p_discover_enable_search(cfg
, false)) < 0) {
7641 WL_ERR(("Can not disable discovery mode\n"));
7645 /* update channel */
7646 if (cfg
->afx_hdl
->peer_chan
!= WL_INVALID
) {
7647 af_params
->channel
= cfg
->afx_hdl
->peer_chan
;
7648 WL_ERR(("Attempt tx on peer listen channel:%d ",
7649 cfg
->afx_hdl
->peer_chan
));
7651 WL_ERR(("Attempt tx with the channel provided by userspace."
7652 "Channel: %d\n", af_params
->channel
));
7657 off_chan_started_jiffies
= jiffies
;
7660 wl_cfgp2p_print_actframe(true, action_frame
->data
, action_frame
->len
, af_params
->channel
);
7662 wl_cfgp2p_need_wait_actfrmae(cfg
, action_frame
->data
, action_frame
->len
, true);
7664 dwell_jiffies
= jiffies
;
7665 /* Now send a tx action frame */
7666 ack
= wl_cfgp2p_tx_action_frame(cfg
, dev
, af_params
, bssidx
) ? false : true;
7667 dwell_overflow
= wl_cfg80211_check_dwell_overflow(requested_dwell
, dwell_jiffies
);
7669 if (ack
&& (wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM
))) {
7670 wifi_p2p_pub_act_frame_t
*pact_frm
;
7671 pact_frm
= (wifi_p2p_pub_act_frame_t
*)(action_frame
->data
);
7672 if (pact_frm
->subtype
== P2P_PAF_GON_RSP
) {
7673 WL_ERR(("Miss GO Nego cfm after P2P_PAF_GON_RSP\n"));
7674 miss_gon_cfm
= true;
7678 /* if failed, retry it. tx_retry_max value is configure by .... */
7679 while ((miss_gon_cfm
|| (ack
== false)) && (tx_retry
++ < config_af_params
.max_tx_retry
) &&
7682 if (af_params
->channel
) {
7683 if (jiffies_to_msecs(jiffies
- off_chan_started_jiffies
) >
7684 OFF_CHAN_TIME_THRESHOLD_MS
) {
7685 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg
);
7686 off_chan_started_jiffies
= jiffies
;
7688 OSL_SLEEP(AF_RETRY_DELAY_TIME
);
7691 ack
= wl_cfgp2p_tx_action_frame(cfg
, dev
, af_params
, bssidx
) ?
7693 if (miss_gon_cfm
&& !wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM
)) {
7694 WL_ERR(("Received GO Nego cfm after P2P_PAF_GON_RSP\n"));
7695 miss_gon_cfm
= false;
7697 dwell_overflow
= wl_cfg80211_check_dwell_overflow(requested_dwell
, dwell_jiffies
);
7701 WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry
));
7703 WL_DBG(("Complete to send action frame\n"));
7705 /* Clear SENDING_ACT_FRM after all sending af is done */
7706 wl_clr_drv_status(cfg
, SENDING_ACT_FRM
, dev
);
7708 #ifdef WL_CFG80211_SYNC_GON
7709 /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
7710 * if we coundn't get the next action response frame and dongle does not keep
7711 * the dwell time, go to listen state again to get next action response frame.
7713 if (ack
&& config_af_params
.extra_listen
&&
7714 wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM
) &&
7715 cfg
->af_sent_channel
== cfg
->afx_hdl
->my_listen_chan
) {
7716 s32 extar_listen_time
;
7718 extar_listen_time
= af_params
->dwell_time
-
7719 jiffies_to_msecs(jiffies
- cfg
->af_tx_sent_jiffies
);
7721 if (extar_listen_time
> 50) {
7722 wl_set_drv_status(cfg
, WAITING_NEXT_ACT_FRM_LISTEN
, dev
);
7723 WL_DBG(("Wait more time! actual af time:%d,"
7724 "calculated extar listen:%d\n",
7725 af_params
->dwell_time
, extar_listen_time
));
7726 if (wl_cfgp2p_discover_listen(cfg
, cfg
->af_sent_channel
,
7727 extar_listen_time
+ 100) == BCME_OK
) {
7728 wait_for_completion_timeout(&cfg
->wait_next_af
,
7729 msecs_to_jiffies(extar_listen_time
+ 100 + 300));
7731 wl_clr_drv_status(cfg
, WAITING_NEXT_ACT_FRM_LISTEN
, dev
);
7734 #endif /* WL_CFG80211_SYNC_GON */
7735 wl_clr_drv_status(cfg
, WAITING_NEXT_ACT_FRM
, dev
);
7736 cfg
->afx_hdl
->pending_tx_act_frm
= NULL
;
7738 WL_INFORM(("-- sending Action Frame is %s, listen chan: %d\n",
7739 (ack
) ? "Succeeded!!":"Failed!!", cfg
->afx_hdl
->my_listen_chan
));
7744 #define MAX_NUM_OF_ASSOCIATED_DEV 64
7746 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7747 wl_cfg80211_mgmt_tx(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
,
7748 struct cfg80211_mgmt_tx_params
*params
, u64
*cookie
)
7750 wl_cfg80211_mgmt_tx(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
,
7751 struct ieee80211_channel
*channel
, bool offchan
,
7752 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0))
7753 enum nl80211_channel_type channel_type
,
7754 bool channel_type_valid
,
7755 #endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0) */
7756 unsigned int wait
, const u8
* buf
, size_t len
,
7757 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
7760 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
7761 bool dont_wait_for_ack
,
7764 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
7766 wl_action_frame_t
*action_frame
;
7767 wl_af_params_t
*af_params
;
7769 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7770 struct ieee80211_channel
*channel
= params
->chan
;
7771 const u8
*buf
= params
->buf
;
7772 size_t len
= params
->len
;
7774 const struct ieee80211_mgmt
*mgmt
;
7775 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7776 struct net_device
*dev
= NULL
;
7781 s8 eabuf
[ETHER_ADDR_STR_LEN
];
7783 WL_DBG(("Enter \n"));
7785 if (len
> ACTION_FRAME_SIZE
) {
7786 WL_ERR(("bad length:%zu\n", len
));
7790 PRINT_WDEV_INFO(cfgdev
);
7791 #endif /* DHD_IFDEBUG */
7793 dev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
7796 WL_ERR(("dev is NULL\n"));
7800 /* set bsscfg idx for iovar (wlan0: P2PAPI_BSSCFG_PRIMARY, p2p: P2PAPI_BSSCFG_DEVICE) */
7801 if (discover_cfgdev(cfgdev
, cfg
)) {
7802 if (!cfg
->p2p_supported
|| !cfg
->p2p
) {
7803 WL_ERR(("P2P doesn't setup completed yet\n"));
7806 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
7809 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, cfgdev_to_wdev(cfgdev
))) < 0) {
7810 WL_ERR(("Find p2p index failed\n"));
7815 WL_DBG(("TX target bssidx=%d\n", bssidx
));
7817 if (p2p_is_on(cfg
)) {
7818 /* Suspend P2P discovery search-listen to prevent it from changing the
7821 if ((err
= wl_cfgp2p_discover_enable_search(cfg
, false)) < 0) {
7822 WL_ERR(("Can not disable discovery mode\n"));
7827 id
= cfg
->send_action_id
++;
7829 id
= cfg
->send_action_id
++;
7831 mgmt
= (const struct ieee80211_mgmt
*)buf
;
7832 if (ieee80211_is_mgmt(mgmt
->frame_control
)) {
7833 if (ieee80211_is_probe_resp(mgmt
->frame_control
)) {
7834 s32 ie_offset
= DOT11_MGMT_HDR_LEN
+ DOT11_BCN_PRB_FIXED_LEN
;
7835 s32 ie_len
= len
- ie_offset
;
7836 if ((dev
== bcmcfg_to_prmry_ndev(cfg
)) && cfg
->p2p
) {
7837 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
7839 wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
7840 VNDR_IE_PRBRSP_FLAG
, (const u8
*)(buf
+ ie_offset
), ie_len
);
7841 cfg80211_mgmt_tx_status(cfgdev
, *cookie
, buf
, len
, true, GFP_KERNEL
);
7842 #if defined(P2P_IE_MISSING_FIX)
7843 if (!cfg
->p2p_prb_noti
) {
7844 cfg
->p2p_prb_noti
= true;
7845 WL_DBG(("%s: TX 802_1X Probe Response first time.\n",
7850 } else if (ieee80211_is_disassoc(mgmt
->frame_control
) ||
7851 ieee80211_is_deauth(mgmt
->frame_control
)) {
7852 char mac_buf
[MAX_NUM_OF_ASSOCIATED_DEV
*
7853 sizeof(struct ether_addr
) + sizeof(uint
)] = {0};
7854 int num_associated
= 0;
7855 struct maclist
*assoc_maclist
= (struct maclist
*)mac_buf
;
7856 if (!bcmp((const uint8
*)BSSID_BROADCAST
,
7857 (const struct ether_addr
*)mgmt
->da
, ETHER_ADDR_LEN
)) {
7858 assoc_maclist
->count
= MAX_NUM_OF_ASSOCIATED_DEV
;
7859 err
= wldev_ioctl_get(dev
, WLC_GET_ASSOCLIST
,
7860 assoc_maclist
, sizeof(mac_buf
));
7862 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err
));
7864 num_associated
= assoc_maclist
->count
;
7866 memcpy(scb_val
.ea
.octet
, mgmt
->da
, ETH_ALEN
);
7867 scb_val
.val
= mgmt
->u
.disassoc
.reason_code
;
7868 err
= wldev_ioctl_set(dev
, WLC_SCB_DEAUTHENTICATE_FOR_REASON
, &scb_val
,
7871 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err
));
7872 WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
7873 bcm_ether_ntoa((const struct ether_addr
*)mgmt
->da
, eabuf
),
7876 if (num_associated
> 0 && ETHER_ISBCAST(mgmt
->da
))
7879 cfg80211_mgmt_tx_status(cfgdev
, *cookie
, buf
, len
, true, GFP_KERNEL
);
7882 } else if (ieee80211_is_action(mgmt
->frame_control
)) {
7883 /* Abort the dwell time of any previous off-channel
7884 * action frame that may be still in effect. Sending
7885 * off-channel action frames relies on the driver's
7886 * scan engine. If a previous off-channel action frame
7887 * tx is still in progress (including the dwell time),
7888 * then this new action frame will not be sent out.
7890 /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
7891 * And previous off-channel action frame must be ended before new af tx.
7893 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7894 wl_notify_escan_complete(cfg
, dev
, true, true);
7895 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7899 WL_ERR(("Driver only allows MGMT packet type\n"));
7903 af_params
= (wl_af_params_t
*) kzalloc(WL_WIFI_AF_PARAMS_SIZE
, GFP_KERNEL
);
7905 if (af_params
== NULL
)
7907 WL_ERR(("unable to allocate frame\n"));
7911 action_frame
= &af_params
->action_frame
;
7913 /* Add the packet Id */
7914 action_frame
->packetId
= *cookie
;
7915 WL_DBG(("action frame %d\n", action_frame
->packetId
));
7917 memcpy(&action_frame
->da
, &mgmt
->da
[0], ETHER_ADDR_LEN
);
7918 memcpy(&af_params
->BSSID
, &mgmt
->bssid
[0], ETHER_ADDR_LEN
);
7920 /* Add the length exepted for 802.11 header */
7921 action_frame
->len
= len
- DOT11_MGMT_HDR_LEN
;
7922 WL_DBG(("action_frame->len: %d\n", action_frame
->len
));
7924 /* Add the channel */
7925 af_params
->channel
=
7926 ieee80211_frequency_to_channel(channel
->center_freq
);
7927 /* Save listen_chan for searching common channel */
7928 cfg
->afx_hdl
->peer_listen_chan
= af_params
->channel
;
7929 WL_DBG(("channel from upper layer %d\n", cfg
->afx_hdl
->peer_listen_chan
));
7931 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7932 af_params
->dwell_time
= params
->wait
;
7934 af_params
->dwell_time
= wait
;
7937 memcpy(action_frame
->data
, &buf
[DOT11_MGMT_HDR_LEN
], action_frame
->len
);
7939 ack
= wl_cfg80211_send_action_frame(wiphy
, dev
, cfgdev
, af_params
,
7940 action_frame
, action_frame
->len
, bssidx
);
7941 cfg80211_mgmt_tx_status(cfgdev
, *cookie
, buf
, len
, ack
, GFP_KERNEL
);
7950 wl_cfg80211_mgmt_frame_register(struct wiphy
*wiphy
, bcm_struct_cfgdev
*cfgdev
,
7951 u16 frame
, bool reg
)
7954 WL_DBG(("frame_type: %x, reg: %d\n", frame
, reg
));
7956 if (frame
!= (IEEE80211_FTYPE_MGMT
| IEEE80211_STYPE_PROBE_REQ
))
7964 wl_cfg80211_change_bss(struct wiphy
*wiphy
,
7965 struct net_device
*dev
,
7966 struct bss_parameters
*params
)
7970 #ifdef PCIE_FULL_DONGLE
7971 s32 ifidx
= DHD_BAD_IF
;
7973 #if defined(PCIE_FULL_DONGLE)
7975 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
7976 dhd
= (dhd_pub_t
*)(cfg
->pub
);
7977 #if defined(WL_ENABLE_P2P_IF)
7978 if (cfg
->p2p_net
== dev
)
7979 dev
= bcmcfg_to_prmry_ndev(cfg
);
7983 if (params
->use_cts_prot
>= 0) {
7986 if (params
->use_short_preamble
>= 0) {
7989 if (params
->use_short_slot_time
>= 0) {
7992 if (params
->basic_rates
) {
7995 if (params
->ap_isolate
>= 0) {
7996 ap_isolate
= params
->ap_isolate
;
7997 #ifdef PCIE_FULL_DONGLE
7998 ifidx
= dhd_net2idx(dhd
->info
, dev
);
8000 if (ifidx
!= DHD_BAD_IF
) {
8001 err
= dhd_set_ap_isolate(dhd
, ifidx
, ap_isolate
);
8003 WL_ERR(("Failed to set ap_isolate\n"));
8006 err
= wldev_iovar_setint(dev
, "ap_isolate", ap_isolate
);
8009 WL_ERR(("set ap_isolate Error (%d)\n", err
));
8011 #endif /* PCIE_FULL_DONGLE */
8014 if (params
->ht_opmode
>= 0) {
8022 wl_cfg80211_set_channel(struct wiphy
*wiphy
, struct net_device
*dev
,
8023 struct ieee80211_channel
*chan
,
8024 enum nl80211_channel_type channel_type
)
8027 chanspec_t chspec
= 0;
8028 chanspec_t fw_chspec
= 0;
8029 u32 bw
= WL_CHANSPEC_BW_20
;
8031 u32 ulb_bw
= wl_cfg80211_get_ulb_bw(wl_get_cfg(dev
), dev
->ieee80211_ptr
);
8032 #endif /* WL11ULB */
8040 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
8041 #if defined(CUSTOM_SET_CPUCORE) || (defined(WL_VIRTUAL_APSTA) && \
8042 defined(APSTA_RESTRICTED_CHANNEL))
8043 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
8044 #endif /* CUSTOM_SET_CPUCORE || (WL_VIRTUAL_APSTA && APSTA_RESTRICTED_CHANNEL) */
8046 dev
= ndev_to_wlc_ndev(dev
, cfg
);
8047 _chan
= ieee80211_frequency_to_channel(chan
->center_freq
);
8048 printf("%s: netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
8049 __FUNCTION__
, dev
->ifindex
, channel_type
, _chan
);
8052 #if defined(WL_VIRTUAL_APSTA) && defined(APSTA_RESTRICTED_CHANNEL)
8053 #define DEFAULT_2G_SOFTAP_CHANNEL 1
8054 #define DEFAULT_5G_SOFTAP_CHANNEL 149
8055 if (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
&&
8056 (dhd
->op_mode
& DHD_FLAG_CONCURR_STA_HOSTAP_MODE
) ==
8057 DHD_FLAG_CONCURR_STA_HOSTAP_MODE
&&
8058 wl_get_drv_status(cfg
, CONNECTED
, bcmcfg_to_prmry_ndev(cfg
))) {
8059 u32
*sta_chan
= (u32
*)wl_read_prof(cfg
,
8060 bcmcfg_to_prmry_ndev(cfg
), WL_PROF_CHAN
);
8061 u32 sta_band
= (*sta_chan
> CH_MAX_2G_CHANNEL
) ?
8062 IEEE80211_BAND_5GHZ
: IEEE80211_BAND_2GHZ
;
8063 if (chan
->band
== sta_band
) {
8064 /* Do not try SCC in 5GHz if channel is not CH149 */
8065 _chan
= (sta_band
== IEEE80211_BAND_5GHZ
&&
8066 *sta_chan
!= DEFAULT_5G_SOFTAP_CHANNEL
) ?
8067 DEFAULT_2G_SOFTAP_CHANNEL
: *sta_chan
;
8068 WL_ERR(("target channel will be changed to %d\n", _chan
));
8069 if (_chan
<= CH_MAX_2G_CHANNEL
) {
8070 bw
= WL_CHANSPEC_BW_20
;
8075 #undef DEFAULT_2G_SOFTAP_CHANNEL
8076 #undef DEFAULT_5G_SOFTAP_CHANNEL
8077 #endif /* WL_VIRTUAL_APSTA && APSTA_RESTRICTED_CHANNEL */
8081 WL_DBG(("[ULB] setting AP/GO BW to ulb_bw 0x%x \n", ulb_bw
));
8082 bw
= wl_cfg80211_ulbbw_to_ulbchspec(ulb_bw
);
8085 #endif /* WL11ULB */
8086 if (chan
->band
== IEEE80211_BAND_5GHZ
) {
8087 param
.band
= WLC_BAND_5G
;
8088 err
= wldev_iovar_getbuf(dev
, "bw_cap", ¶m
, sizeof(param
),
8089 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
);
8091 if (err
!= BCME_UNSUPPORTED
) {
8092 WL_ERR(("bw_cap failed, %d\n", err
));
8095 err
= wldev_iovar_getint(dev
, "mimo_bw_cap", &bw_cap
);
8097 WL_ERR(("error get mimo_bw_cap (%d)\n", err
));
8099 if (bw_cap
!= WLC_N_BW_20ALL
)
8100 bw
= WL_CHANSPEC_BW_40
;
8103 if (WL_BW_CAP_80MHZ(cfg
->ioctl_buf
[0]))
8104 bw
= WL_CHANSPEC_BW_80
;
8105 else if (WL_BW_CAP_40MHZ(cfg
->ioctl_buf
[0]))
8106 bw
= WL_CHANSPEC_BW_40
;
8108 bw
= WL_CHANSPEC_BW_20
;
8112 } else if (chan
->band
== IEEE80211_BAND_2GHZ
)
8113 bw
= WL_CHANSPEC_BW_20
;
8115 chspec
= wf_channel2chspec(_chan
, bw
);
8116 if (wf_chspec_valid(chspec
)) {
8117 fw_chspec
= wl_chspec_host_to_driver(chspec
);
8118 if (fw_chspec
!= INVCHANSPEC
) {
8119 if ((err
= wldev_iovar_setint(dev
, "chanspec",
8120 fw_chspec
)) == BCME_BADCHAN
) {
8121 if (bw
== WL_CHANSPEC_BW_80
)
8123 err
= wldev_ioctl_set(dev
, WLC_SET_CHANNEL
,
8124 &_chan
, sizeof(_chan
));
8126 WL_ERR(("WLC_SET_CHANNEL error %d"
8127 "chip may not be supporting this channel\n", err
));
8130 WL_ERR(("failed to set chanspec error %d\n", err
));
8133 WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
8138 if (bw
== WL_CHANSPEC_BW_80
)
8139 bw
= WL_CHANSPEC_BW_40
;
8140 else if (bw
== WL_CHANSPEC_BW_40
)
8141 bw
= WL_CHANSPEC_BW_20
;
8146 WL_ERR(("Invalid chanspec 0x%x\n", chspec
));
8149 #ifdef CUSTOM_SET_CPUCORE
8150 if (dhd
->op_mode
== DHD_FLAG_HOSTAP_MODE
) {
8151 WL_DBG(("SoftAP mode do not need to set cpucore\n"));
8152 } else if (chspec
& WL_CHANSPEC_BW_80
) {
8153 /* SoftAp only mode do not need to set cpucore */
8154 if ((dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) &&
8155 dev
!= bcmcfg_to_prmry_ndev(cfg
)) {
8156 /* Soft AP on virtual Iface (AP+STA case) */
8157 dhd
->chan_isvht80
|= DHD_FLAG_HOSTAP_MODE
;
8158 dhd_set_cpucore(dhd
, TRUE
);
8159 } else if (is_p2p_group_iface(dev
->ieee80211_ptr
)) {
8160 /* If P2P IF is vht80 */
8161 dhd
->chan_isvht80
|= DHD_FLAG_P2P_MODE
;
8162 dhd_set_cpucore(dhd
, TRUE
);
8165 #endif /* CUSTOM_SET_CPUCORE */
8166 if (!err
&& (wl_get_mode_by_netdev(cfg
, dev
) == WL_MODE_AP
)) {
8167 /* Update AP/GO operating channel */
8168 cfg
->ap_oper_channel
= ieee80211_frequency_to_channel(chan
->center_freq
);
8173 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
8175 wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211
*cfg
)
8177 struct net_info
*_net_info
, *next
;
8178 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
8179 #pragma GCC diagnostic push
8180 #pragma GCC diagnostic ignored "-Wcast-qual"
8182 list_for_each_entry_safe(_net_info
, next
, &cfg
->net_list
, list
) {
8183 if (_net_info
->ndev
&&
8184 test_bit(WL_STATUS_REMAINING_ON_CHANNEL
, &_net_info
->sme_state
))
8185 return _net_info
->ndev
;
8187 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
8188 #pragma GCC diagnostic pop
8192 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
8195 wl_validate_opensecurity(struct net_device
*dev
, s32 bssidx
, bool privacy
)
8202 err
= wldev_iovar_setint_bsscfg(dev
, "auth", 0, bssidx
);
8204 WL_ERR(("auth error %d\n", err
));
8209 /* If privacy bit is set in open mode, then WEP would be enabled */
8211 WL_DBG(("Setting wsec to %d for WEP \n", wsec
));
8215 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", wsec
, bssidx
);
8217 WL_ERR(("wsec error %d\n", err
));
8221 /* set upper-layer auth */
8222 if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_ADHOC
)
8223 wpa_val
= WPA_AUTH_NONE
;
8225 wpa_val
= WPA_AUTH_DISABLED
;
8226 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", wpa_val
, bssidx
);
8228 WL_ERR(("wpa_auth error %d\n", err
));
8236 wl_validate_wpa2ie(struct net_device
*dev
, bcm_tlv_t
*wpa2ie
, s32 bssidx
)
8240 u16 auth
= 0; /* d11 open authentication */
8245 wpa_suite_mcast_t
*mcast
;
8246 wpa_suite_ucast_t
*ucast
;
8247 wpa_suite_auth_key_mgmt_t
*mgmt
;
8248 wpa_pmkid_list_t
*pmkid
;
8252 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
8257 u32 wme_bss_disable
;
8262 WL_DBG(("Enter \n"));
8263 len
= wpa2ie
->len
- WPA2_VERSION_LEN
;
8264 /* check the mcast cipher */
8265 mcast
= (wpa_suite_mcast_t
*)&wpa2ie
->data
[WPA2_VERSION_LEN
];
8266 switch (mcast
->type
) {
8267 case WPA_CIPHER_NONE
:
8270 case WPA_CIPHER_WEP_40
:
8271 case WPA_CIPHER_WEP_104
:
8274 case WPA_CIPHER_TKIP
:
8275 gval
= TKIP_ENABLED
;
8277 case WPA_CIPHER_AES_CCM
:
8281 WL_ERR(("No Security Info\n"));
8284 if ((len
-= WPA_SUITE_LEN
) <= 0)
8287 /* check the unicast cipher */
8288 ucast
= (wpa_suite_ucast_t
*)&mcast
[1];
8289 suite_count
= ltoh16_ua(&ucast
->count
);
8290 switch (ucast
->list
[0].type
) {
8291 case WPA_CIPHER_NONE
:
8294 case WPA_CIPHER_WEP_40
:
8295 case WPA_CIPHER_WEP_104
:
8298 case WPA_CIPHER_TKIP
:
8299 pval
= TKIP_ENABLED
;
8301 case WPA_CIPHER_AES_CCM
:
8305 WL_ERR(("No Security Info\n"));
8307 if ((len
-= (WPA_IE_SUITE_COUNT_LEN
+ (WPA_SUITE_LEN
* suite_count
))) <= 0)
8310 /* FOR WPS , set SEC_OW_ENABLED */
8311 wsec
= (pval
| gval
| SES_OW_ENABLED
);
8313 mgmt
= (wpa_suite_auth_key_mgmt_t
*)&ucast
->list
[suite_count
];
8314 suite_count
= cnt
= ltoh16_ua(&mgmt
->count
);
8316 switch (mgmt
->list
[cnt
].type
) {
8318 wpa_auth
|= WPA_AUTH_NONE
;
8320 case RSN_AKM_UNSPECIFIED
:
8321 wpa_auth
|= WPA2_AUTH_UNSPECIFIED
;
8324 wpa_auth
|= WPA2_AUTH_PSK
;
8327 case RSN_AKM_MFP_PSK
:
8328 wpa_auth
|= WPA2_AUTH_PSK_SHA256
;
8330 case RSN_AKM_MFP_1X
:
8331 wpa_auth
|= WPA2_AUTH_1X_SHA256
;
8335 WL_ERR(("No Key Mgmt Info\n"));
8339 if ((len
-= (WPA_IE_SUITE_COUNT_LEN
+ (WPA_SUITE_LEN
* suite_count
))) >= RSN_CAP_LEN
) {
8340 rsn_cap
[0] = *(u8
*)&mgmt
->list
[suite_count
];
8341 rsn_cap
[1] = *((u8
*)&mgmt
->list
[suite_count
] + 1);
8343 if (rsn_cap
[0] & (RSN_CAP_16_REPLAY_CNTRS
<< RSN_CAP_PTK_REPLAY_CNTR_SHIFT
)) {
8344 wme_bss_disable
= 0;
8346 wme_bss_disable
= 1;
8350 if (rsn_cap
[0] & RSN_CAP_MFPR
) {
8351 WL_DBG(("MFP Required \n"));
8352 mfp
= WL_MFP_REQUIRED
;
8353 /* Our firmware has requirement that WPA2_AUTH_PSK/WPA2_AUTH_UNSPECIFIED
8354 * be set, if SHA256 OUI is to be included in the rsn ie.
8356 if (wpa_auth
& WPA2_AUTH_PSK_SHA256
) {
8357 wpa_auth
|= WPA2_AUTH_PSK
;
8358 } else if (wpa_auth
& WPA2_AUTH_1X_SHA256
) {
8359 wpa_auth
|= WPA2_AUTH_UNSPECIFIED
;
8361 } else if (rsn_cap
[0] & RSN_CAP_MFPC
) {
8362 WL_DBG(("MFP Capable \n"));
8363 mfp
= WL_MFP_CAPABLE
;
8367 /* set wme_bss_disable to sync RSN Capabilities */
8368 err
= wldev_iovar_setint_bsscfg(dev
, "wme_bss_disable", wme_bss_disable
, bssidx
);
8370 WL_ERR(("wme_bss_disable error %d\n", err
));
8374 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len
));
8378 if (len
>= WPA2_PMKID_COUNT_LEN
) {
8379 pmkid
= (wpa_pmkid_list_t
*)((u8
*)&mgmt
->list
[suite_count
] + RSN_CAP_LEN
);
8380 cnt
= ltoh16_ua(&pmkid
->count
);
8382 WL_ERR(("AP has non-zero PMKID count. Wrong!\n"));
8385 /* since PMKID cnt is known to be 0 for AP, */
8386 /* so don't bother to send down this info to firmware */
8390 len
-= WPA2_PMKID_COUNT_LEN
;
8391 if (len
>= WPA_SUITE_LEN
) {
8392 cfg
->bip_pos
= (u8
*)&mgmt
->list
[suite_count
] + RSN_CAP_LEN
+ WPA2_PMKID_COUNT_LEN
;
8394 cfg
->bip_pos
= NULL
;
8399 err
= wldev_iovar_setint_bsscfg(dev
, "auth", auth
, bssidx
);
8401 WL_ERR(("auth error %d\n", err
));
8406 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", wsec
, bssidx
);
8408 WL_ERR(("wsec error %d\n", err
));
8413 cfg
->mfp_mode
= mfp
;
8416 /* set upper-layer auth */
8417 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", wpa_auth
, bssidx
);
8419 WL_ERR(("wpa_auth error %d\n", err
));
8427 wl_validate_wpaie(struct net_device
*dev
, wpa_ie_fixed_t
*wpaie
, s32 bssidx
)
8429 wpa_suite_mcast_t
*mcast
;
8430 wpa_suite_ucast_t
*ucast
;
8431 wpa_suite_auth_key_mgmt_t
*mgmt
;
8432 u16 auth
= 0; /* d11 open authentication */
8445 WL_DBG(("Enter \n"));
8446 len
= wpaie
->length
; /* value length */
8447 len
-= WPA_IE_TAG_FIXED_LEN
;
8448 /* check for multicast cipher suite */
8449 if (len
< WPA_SUITE_LEN
) {
8450 WL_INFORM(("no multicast cipher suite\n"));
8454 /* pick up multicast cipher */
8455 mcast
= (wpa_suite_mcast_t
*)&wpaie
[1];
8456 len
-= WPA_SUITE_LEN
;
8457 if (!bcmp(mcast
->oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8458 if (IS_WPA_CIPHER(mcast
->type
)) {
8460 switch (mcast
->type
) {
8461 case WPA_CIPHER_NONE
:
8464 case WPA_CIPHER_WEP_40
:
8465 case WPA_CIPHER_WEP_104
:
8468 case WPA_CIPHER_TKIP
:
8471 case WPA_CIPHER_AES_CCM
:
8475 WL_ERR(("No Security Info\n"));
8480 /* Check for unicast suite(s) */
8481 if (len
< WPA_IE_SUITE_COUNT_LEN
) {
8482 WL_INFORM(("no unicast suite\n"));
8485 /* walk thru unicast cipher list and pick up what we recognize */
8486 ucast
= (wpa_suite_ucast_t
*)&mcast
[1];
8487 count
= ltoh16_ua(&ucast
->count
);
8488 len
-= WPA_IE_SUITE_COUNT_LEN
;
8489 for (i
= 0; i
< count
&& len
>= WPA_SUITE_LEN
;
8490 i
++, len
-= WPA_SUITE_LEN
) {
8491 if (!bcmp(ucast
->list
[i
].oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8492 if (IS_WPA_CIPHER(ucast
->list
[i
].type
)) {
8494 switch (ucast
->list
[i
].type
) {
8495 case WPA_CIPHER_NONE
:
8498 case WPA_CIPHER_WEP_40
:
8499 case WPA_CIPHER_WEP_104
:
8502 case WPA_CIPHER_TKIP
:
8505 case WPA_CIPHER_AES_CCM
:
8509 WL_ERR(("No Security Info\n"));
8515 len
-= (count
- i
) * WPA_SUITE_LEN
;
8516 /* Check for auth key management suite(s) */
8517 if (len
< WPA_IE_SUITE_COUNT_LEN
) {
8518 WL_INFORM((" no auth key mgmt suite\n"));
8521 /* walk thru auth management suite list and pick up what we recognize */
8522 mgmt
= (wpa_suite_auth_key_mgmt_t
*)&ucast
->list
[count
];
8523 count
= ltoh16_ua(&mgmt
->count
);
8524 len
-= WPA_IE_SUITE_COUNT_LEN
;
8525 for (i
= 0; i
< count
&& len
>= WPA_SUITE_LEN
;
8526 i
++, len
-= WPA_SUITE_LEN
) {
8527 if (!bcmp(mgmt
->list
[i
].oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8528 if (IS_WPA_AKM(mgmt
->list
[i
].type
)) {
8530 switch (mgmt
->list
[i
].type
) {
8532 tmp
= WPA_AUTH_NONE
;
8534 case RSN_AKM_UNSPECIFIED
:
8535 tmp
= WPA_AUTH_UNSPECIFIED
;
8541 WL_ERR(("No Key Mgmt Info\n"));
8548 /* FOR WPS , set SEC_OW_ENABLED */
8549 wsec
= (pval
| gval
| SES_OW_ENABLED
);
8551 err
= wldev_iovar_setint_bsscfg(dev
, "auth", auth
, bssidx
);
8553 WL_ERR(("auth error %d\n", err
));
8557 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", wsec
, bssidx
);
8559 WL_ERR(("wsec error %d\n", err
));
8562 /* set upper-layer auth */
8563 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", wpa_auth
, bssidx
);
8565 WL_ERR(("wpa_auth error %d\n", err
));
8572 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8573 static u32
wl_get_cipher_type(uint8 type
)
8577 case WPA_CIPHER_NONE
:
8580 case WPA_CIPHER_WEP_40
:
8581 case WPA_CIPHER_WEP_104
:
8584 case WPA_CIPHER_TKIP
:
8587 case WPA_CIPHER_AES_CCM
:
8591 case WAPI_CIPHER_SMS4
:
8596 WL_ERR(("No Security Info\n"));
8601 static u32
wl_get_suite_auth_key_mgmt_type(uint8 type
)
8606 ret
= WPA_AUTH_NONE
;
8608 case RSN_AKM_UNSPECIFIED
:
8609 ret
= WPA_AUTH_UNSPECIFIED
;
8615 WL_ERR(("No Key Mgmt Info\n"));
8620 static u32
wl_get_suite_auth2_key_mgmt_type(uint8 type
)
8625 ret
= WPA_AUTH_NONE
;
8627 case RSN_AKM_UNSPECIFIED
:
8628 ret
= WPA2_AUTH_UNSPECIFIED
;
8631 ret
= WPA2_AUTH_PSK
;
8634 WL_ERR(("No Key Mgmt Info\n"));
8640 wl_validate_wpaie_wpa2ie(struct net_device
*dev
, wpa_ie_fixed_t
*wpaie
,
8641 bcm_tlv_t
*wpa2ie
, s32 bssidx
)
8643 wpa_suite_mcast_t
*mcast
;
8644 wpa_suite_ucast_t
*ucast
;
8645 wpa_suite_auth_key_mgmt_t
*mgmt
;
8646 u16 auth
= 0; /* d11 open authentication */
8649 u32 wme_bss_disable
;
8654 u32 wsec1
, wsec2
, wsec
;
8662 if (wpaie
== NULL
|| wpa2ie
== NULL
)
8665 WL_DBG(("Enter \n"));
8666 len
= wpaie
->length
; /* value length */
8667 len
-= WPA_IE_TAG_FIXED_LEN
;
8668 /* check for multicast cipher suite */
8669 if (len
< WPA_SUITE_LEN
) {
8670 WL_INFORM(("no multicast cipher suite\n"));
8674 /* pick up multicast cipher */
8675 mcast
= (wpa_suite_mcast_t
*)&wpaie
[1];
8676 len
-= WPA_SUITE_LEN
;
8677 if (!bcmp(mcast
->oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8678 if (IS_WPA_CIPHER(mcast
->type
)) {
8679 gval
|= wl_get_cipher_type(mcast
->type
);
8682 WL_ERR(("\nwpa ie validate\n"));
8683 WL_ERR(("wpa ie mcast cipher = 0x%X\n", gval
));
8685 /* Check for unicast suite(s) */
8686 if (len
< WPA_IE_SUITE_COUNT_LEN
) {
8687 WL_INFORM(("no unicast suite\n"));
8691 /* walk thru unicast cipher list and pick up what we recognize */
8692 ucast
= (wpa_suite_ucast_t
*)&mcast
[1];
8693 count
= ltoh16_ua(&ucast
->count
);
8694 len
-= WPA_IE_SUITE_COUNT_LEN
;
8695 for (i
= 0; i
< count
&& len
>= WPA_SUITE_LEN
;
8696 i
++, len
-= WPA_SUITE_LEN
) {
8697 if (!bcmp(ucast
->list
[i
].oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8698 if (IS_WPA_CIPHER(ucast
->list
[i
].type
)) {
8699 pval
|= wl_get_cipher_type(ucast
->list
[i
].type
);
8703 WL_ERR(("wpa ie ucast count =%d, cipher = 0x%X\n", count
, pval
));
8705 /* FOR WPS , set SEC_OW_ENABLED */
8706 wsec1
= (pval
| gval
| SES_OW_ENABLED
);
8707 WL_ERR(("wpa ie wsec = 0x%X\n", wsec1
));
8709 len
-= (count
- i
) * WPA_SUITE_LEN
;
8710 /* Check for auth key management suite(s) */
8711 if (len
< WPA_IE_SUITE_COUNT_LEN
) {
8712 WL_INFORM((" no auth key mgmt suite\n"));
8715 /* walk thru auth management suite list and pick up what we recognize */
8716 mgmt
= (wpa_suite_auth_key_mgmt_t
*)&ucast
->list
[count
];
8717 count
= ltoh16_ua(&mgmt
->count
);
8718 len
-= WPA_IE_SUITE_COUNT_LEN
;
8719 for (i
= 0; i
< count
&& len
>= WPA_SUITE_LEN
;
8720 i
++, len
-= WPA_SUITE_LEN
) {
8721 if (!bcmp(mgmt
->list
[i
].oui
, WPA_OUI
, WPA_OUI_LEN
)) {
8722 if (IS_WPA_AKM(mgmt
->list
[i
].type
)) {
8724 wpa_auth1
|= wl_get_suite_auth_key_mgmt_type(mgmt
->list
[i
].type
);
8729 WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count
, wpa_auth1
));
8730 WL_ERR(("\nwpa2 ie validate\n"));
8735 /* check the mcast cipher */
8736 mcast
= (wpa_suite_mcast_t
*)&wpa2ie
->data
[WPA2_VERSION_LEN
];
8738 gval
= wl_get_cipher_type(ptmp
[DOT11_OUI_LEN
]);
8740 WL_ERR(("wpa2 ie mcast cipher = 0x%X\n", gval
));
8741 if ((len
-= WPA_SUITE_LEN
) <= 0)
8743 WL_ERR(("P:wpa2 ie len[%d]", len
));
8747 /* check the unicast cipher */
8748 ucast
= (wpa_suite_ucast_t
*)&mcast
[1];
8749 suite_count
= ltoh16_ua(&ucast
->count
);
8750 WL_ERR((" WPA2 ucast cipher count=%d\n", suite_count
));
8751 pval
|= wl_get_cipher_type(ucast
->list
[0].type
);
8753 if ((len
-= (WPA_IE_SUITE_COUNT_LEN
+ (WPA_SUITE_LEN
* suite_count
))) <= 0)
8756 WL_ERR(("wpa2 ie ucast cipher = 0x%X\n", pval
));
8758 /* FOR WPS , set SEC_OW_ENABLED */
8759 wsec2
= (pval
| gval
| SES_OW_ENABLED
);
8760 WL_ERR(("wpa2 ie wsec = 0x%X\n", wsec2
));
8763 mgmt
= (wpa_suite_auth_key_mgmt_t
*)&ucast
->list
[suite_count
];
8764 suite_count
= ltoh16_ua(&mgmt
->count
);
8765 ptmp
= (u8
*)&mgmt
->list
[0];
8766 wpa_auth2
= wl_get_suite_auth2_key_mgmt_type(ptmp
[DOT11_OUI_LEN
]);
8767 WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count
, wpa_auth2
));
8769 if ((len
-= (WPA_IE_SUITE_COUNT_LEN
+ (WPA_SUITE_LEN
* suite_count
))) >= RSN_CAP_LEN
) {
8770 rsn_cap
[0] = *(u8
*)&mgmt
->list
[suite_count
];
8771 rsn_cap
[1] = *((u8
*)&mgmt
->list
[suite_count
] + 1);
8772 if (rsn_cap
[0] & (RSN_CAP_16_REPLAY_CNTRS
<< RSN_CAP_PTK_REPLAY_CNTR_SHIFT
)) {
8773 wme_bss_disable
= 0;
8775 wme_bss_disable
= 1;
8777 WL_DBG(("P:rsn_cap[0]=[0x%X]:wme_bss_disabled[%d]\n", rsn_cap
[0], wme_bss_disable
));
8779 /* set wme_bss_disable to sync RSN Capabilities */
8780 err
= wldev_iovar_setint_bsscfg(dev
, "wme_bss_disable", wme_bss_disable
, bssidx
);
8782 WL_ERR(("wme_bss_disable error %d\n", err
));
8786 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len
));
8789 wsec
= (wsec1
| wsec2
);
8790 wpa_auth
= (wpa_auth1
| wpa_auth2
);
8791 WL_ERR(("wpa_wpa2 wsec=0x%X wpa_auth=0x%X\n", wsec
, wpa_auth
));
8794 err
= wldev_iovar_setint_bsscfg(dev
, "auth", auth
, bssidx
);
8796 WL_ERR(("auth error %d\n", err
));
8800 err
= wldev_iovar_setint_bsscfg(dev
, "wsec", wsec
, bssidx
);
8802 WL_ERR(("wsec error %d\n", err
));
8805 /* set upper-layer auth */
8806 err
= wldev_iovar_setint_bsscfg(dev
, "wpa_auth", wpa_auth
, bssidx
);
8808 WL_ERR(("wpa_auth error %d\n", err
));
8814 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8817 wl_cfg80211_bcn_validate_sec(
8818 struct net_device
*dev
,
8819 struct parsed_ies
*ies
,
8824 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
8825 wl_cfgbss_t
*bss
= wl_get_cfgbss_by_wdev(cfg
, dev
->ieee80211_ptr
);
8828 WL_ERR(("cfgbss is NULL \n"));
8832 if (dev_role
== NL80211_IFTYPE_P2P_GO
&& (ies
->wpa2_ie
)) {
8833 /* For P2P GO, the sec type is WPA2-PSK */
8834 WL_DBG(("P2P GO: validating wpa2_ie"));
8835 if (wl_validate_wpa2ie(dev
, ies
->wpa2_ie
, bssidx
) < 0)
8838 } else if (dev_role
== NL80211_IFTYPE_AP
) {
8840 WL_DBG(("SoftAP: validating security"));
8841 /* If wpa2_ie or wpa_ie is present validate it */
8843 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8844 if ((ies
->wpa_ie
!= NULL
&& ies
->wpa2_ie
!= NULL
)) {
8845 if (wl_validate_wpaie_wpa2ie(dev
, ies
->wpa_ie
, ies
->wpa2_ie
, bssidx
) < 0) {
8846 bss
->security_mode
= false;
8851 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8852 if ((ies
->wpa2_ie
|| ies
->wpa_ie
) &&
8853 ((wl_validate_wpa2ie(dev
, ies
->wpa2_ie
, bssidx
) < 0 ||
8854 wl_validate_wpaie(dev
, ies
->wpa_ie
, bssidx
) < 0))) {
8855 bss
->security_mode
= false;
8859 bss
->security_mode
= true;
8872 if (ies
->wpa_ie
!= NULL
) {
8875 bss
->wpa_ie
= kmemdup(ies
->wpa_ie
,
8876 ies
->wpa_ie
->length
+ WPA_RSN_IE_TAG_FIXED_LEN
,
8878 } else if (ies
->wpa2_ie
!= NULL
) {
8881 bss
->rsn_ie
= kmemdup(ies
->wpa2_ie
,
8882 ies
->wpa2_ie
->len
+ WPA_RSN_IE_TAG_FIXED_LEN
,
8885 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8887 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8888 if (!ies
->wpa2_ie
&& !ies
->wpa_ie
) {
8889 wl_validate_opensecurity(dev
, bssidx
, privacy
);
8890 bss
->security_mode
= false;
8894 bss
->wps_ie
= kmemdup(ies
->wps_ie
, ies
->wps_ie_len
, GFP_KERNEL
);
8902 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
8903 static s32
wl_cfg80211_bcn_set_params(
8904 struct cfg80211_ap_settings
*info
,
8905 struct net_device
*dev
,
8906 u32 dev_role
, s32 bssidx
)
8908 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
8911 WL_DBG(("interval (%d) \ndtim_period (%d) \n",
8912 info
->beacon_interval
, info
->dtim_period
));
8914 if (info
->beacon_interval
) {
8915 if ((err
= wldev_ioctl_set(dev
, WLC_SET_BCNPRD
,
8916 &info
->beacon_interval
, sizeof(s32
))) < 0) {
8917 WL_ERR(("Beacon Interval Set Error, %d\n", err
));
8922 if (info
->dtim_period
) {
8923 if ((err
= wldev_ioctl_set(dev
, WLC_SET_DTIMPRD
,
8924 &info
->dtim_period
, sizeof(s32
))) < 0) {
8925 WL_ERR(("DTIM Interval Set Error, %d\n", err
));
8930 if ((info
->ssid
) && (info
->ssid_len
> 0) &&
8931 (info
->ssid_len
<= DOT11_MAX_SSID_LEN
)) {
8932 WL_DBG(("SSID (%s) len:%zd \n", info
->ssid
, info
->ssid_len
));
8933 if (dev_role
== NL80211_IFTYPE_AP
) {
8934 /* Store the hostapd SSID */
8935 memset(cfg
->hostapd_ssid
.SSID
, 0x00, DOT11_MAX_SSID_LEN
);
8936 memcpy(cfg
->hostapd_ssid
.SSID
, info
->ssid
, info
->ssid_len
);
8937 cfg
->hostapd_ssid
.SSID_len
= info
->ssid_len
;
8940 memset(cfg
->p2p
->ssid
.SSID
, 0x00, DOT11_MAX_SSID_LEN
);
8941 memcpy(cfg
->p2p
->ssid
.SSID
, info
->ssid
, info
->ssid_len
);
8942 cfg
->p2p
->ssid
.SSID_len
= info
->ssid_len
;
8946 if (info
->hidden_ssid
!= NL80211_HIDDEN_SSID_NOT_IN_USE
) {
8947 if ((err
= wldev_iovar_setint(dev
, "closednet", 1)) < 0)
8948 WL_ERR(("failed to set hidden : %d\n", err
));
8949 WL_DBG(("hidden_ssid_enum_val: %d \n", info
->hidden_ssid
));
8957 wl_cfg80211_parse_ies(u8
*ptr
, u32 len
, struct parsed_ies
*ies
)
8961 memset(ies
, 0, sizeof(struct parsed_ies
));
8963 /* find the WPSIE */
8964 if ((ies
->wps_ie
= wl_cfgp2p_find_wpsie(ptr
, len
)) != NULL
) {
8965 WL_DBG(("WPSIE in beacon \n"));
8966 ies
->wps_ie_len
= ies
->wps_ie
->length
+ WPA_RSN_IE_TAG_FIXED_LEN
;
8968 WL_DBG(("No WPSIE in beacon \n"));
8971 /* find the RSN_IE */
8972 if ((ies
->wpa2_ie
= bcm_parse_tlvs(ptr
, len
,
8973 DOT11_MNG_RSN_ID
)) != NULL
) {
8974 WL_DBG((" WPA2 IE found\n"));
8975 ies
->wpa2_ie_len
= ies
->wpa2_ie
->len
;
8978 /* find the WPA_IE */
8979 if ((ies
->wpa_ie
= wl_cfgp2p_find_wpaie(ptr
, len
)) != NULL
) {
8980 WL_DBG((" WPA found\n"));
8981 ies
->wpa_ie_len
= ies
->wpa_ie
->length
;
8988 wl_cfg80211_set_ap_role(
8989 struct bcm_cfg80211
*cfg
,
8990 struct net_device
*dev
)
8996 s32 is_rsdb_supported
= BCME_ERROR
;
9000 is_rsdb_supported
= DHD_OPMODE_SUPPORTED(cfg
->pub
, DHD_FLAG_RSDB_MODE
);
9001 if (is_rsdb_supported
< 0)
9004 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
9005 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
9009 /* AP on primary Interface */
9011 if (is_rsdb_supported
) {
9012 if ((err
= wl_cfg80211_add_del_bss(cfg
, dev
, bssidx
,
9013 NL80211_IFTYPE_AP
, 0, NULL
)) < 0) {
9014 WL_ERR(("wl add_del_bss returned error:%d\n", err
));
9017 } else if (is_rsdb_supported
== 0) {
9018 /* AP mode switch not supported. Try setting up AP explicitly */
9019 err
= wldev_iovar_getint(dev
, "apsta", (s32
*)&apsta
);
9020 if (unlikely(err
)) {
9021 WL_ERR(("Could not get apsta %d\n", err
));
9023 if (1) { // terence: fix me
9024 /* If apsta is not set, set it */
9025 err
= wldev_ioctl_set(dev
, WLC_DOWN
, &ap
, sizeof(s32
));
9027 WL_ERR(("WLC_DOWN error %d\n", err
));
9030 err
= wldev_iovar_setint(dev
, "apsta", 0);
9032 WL_ERR(("wl apsta 0 error %d\n", err
));
9035 if ((err
= wldev_ioctl_set(dev
,
9036 WLC_SET_AP
, &ap
, sizeof(s32
))) < 0) {
9037 WL_ERR(("setting AP mode failed %d \n", err
));
9044 if ((err
= wldev_ioctl_set(dev
, WLC_SET_PM
, &pm
, sizeof(pm
))) != 0) {
9045 WL_ERR(("wl PM 0 returned error:%d\n", err
));
9046 /* Ignore error, if any */
9049 err
= wldev_ioctl_set(dev
, WLC_SET_INFRA
, &infra
, sizeof(s32
));
9051 WL_ERR(("SET INFRA error %d\n", err
));
9055 WL_DBG(("Bringup SoftAP on virtual Interface bssidx:%d \n", bssidx
));
9056 if ((err
= wl_cfg80211_add_del_bss(cfg
, dev
,
9057 bssidx
, NL80211_IFTYPE_AP
, 0, NULL
)) < 0) {
9058 WL_ERR(("wl bss ap returned error:%d\n", err
));
9063 /* On success, mark AP creation in progress. */
9064 wl_set_drv_status(cfg
, AP_CREATING
, dev
);
9069 /* In RSDB downgrade cases, the link up event can get delayed upto 7-8 secs */
9070 #define MAX_AP_LINK_WAIT_TIME 10000
9072 wl_cfg80211_bcn_bringup_ap(
9073 struct net_device
*dev
,
9074 struct parsed_ies
*ies
,
9075 u32 dev_role
, s32 bssidx
)
9077 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
9078 struct wl_join_params join_params
;
9079 bool is_bssup
= false;
9081 s32 join_params_size
= 0;
9085 bool retried
= false;
9087 #ifdef SOFTAP_UAPSD_OFF
9088 uint32 wme_apsd
= 0;
9089 #endif /* SOFTAP_UAPSD_OFF */
9091 s32 is_rsdb_supported
= BCME_ERROR
;
9093 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
9094 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
9095 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
9097 is_rsdb_supported
= DHD_OPMODE_SUPPORTED(cfg
->pub
, DHD_FLAG_RSDB_MODE
);
9098 if (is_rsdb_supported
< 0)
9101 WL_DBG(("Enter dev_role:%d bssidx:%d ifname:%s\n", dev_role
, bssidx
, dev
->name
));
9103 /* Common code for SoftAP and P2P GO */
9104 wl_clr_drv_status(cfg
, AP_CREATED
, dev
);
9106 /* Make sure INFRA is set for AP/GO */
9107 err
= wldev_ioctl_set(dev
, WLC_SET_INFRA
, &infra
, sizeof(s32
));
9109 WL_ERR(("SET INFRA error %d\n", err
));
9113 /* Do abort scan before creating GO */
9114 wl_cfg80211_scan_abort(cfg
);
9116 if (dev_role
== NL80211_IFTYPE_P2P_GO
) {
9117 is_bssup
= wl_cfg80211_bss_isup(dev
, bssidx
);
9118 if (!is_bssup
&& (ies
->wpa2_ie
!= NULL
)) {
9120 err
= wldev_iovar_setbuf_bsscfg(dev
, "ssid", &cfg
->p2p
->ssid
,
9121 sizeof(cfg
->p2p
->ssid
), cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
,
9122 bssidx
, &cfg
->ioctl_buf_sync
);
9124 WL_ERR(("GO SSID setting error %d\n", err
));
9128 if ((err
= wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 1)) < 0) {
9129 WL_ERR(("GO Bring up error %d\n", err
));
9133 WL_DBG(("Bss is already up\n"));
9134 } else if (dev_role
== NL80211_IFTYPE_AP
) {
9136 // if (!wl_get_drv_status(cfg, AP_CREATING, dev)) {
9137 /* Make sure fw is in proper state */
9138 err
= wl_cfg80211_set_ap_role(cfg
, dev
);
9139 if (unlikely(err
)) {
9140 WL_ERR(("set ap role failed!\n"));
9145 /* Device role SoftAP */
9146 WL_DBG(("Creating AP bssidx:%d dev_role:%d\n", bssidx
, dev_role
));
9147 /* Clear the status bit after use */
9148 wl_clr_drv_status(cfg
, AP_CREATING
, dev
);
9151 #ifdef SOFTAP_UAPSD_OFF
9152 err
= wldev_iovar_setbuf_bsscfg(dev
, "wme_apsd", &wme_apsd
, sizeof(wme_apsd
),
9153 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
9155 WL_ERR(("failed to disable uapsd, error=%d\n", err
));
9157 #endif /* SOFTAP_UAPSD_OFF */
9158 dhd_conf_set_wme(cfg
->pub
, 1);
9160 err
= wldev_ioctl_set(dev
, WLC_UP
, &ap
, sizeof(s32
));
9161 if (unlikely(err
)) {
9162 WL_ERR(("WLC_UP error (%d)\n", err
));
9168 err
= wldev_iovar_setbuf_bsscfg(dev
, "bip",
9169 (void *)(cfg
->bip_pos
), WPA_SUITE_LEN
, cfg
->ioctl_buf
,
9170 WLC_IOCTL_SMLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
9172 WL_ERR(("bip set error %d\n", err
));
9173 if (wl_customer6_legacy_chip_check(cfg
,
9174 bcmcfg_to_prmry_ndev(cfg
))) {
9175 /* Ignore bip error: Some older firmwares doesn't
9176 * support bip iovar/ return BCME_NOTUP while trying
9177 * to set bip from AP bring up context. These firmares
9178 * include bip in RSNIE by default. So its okay to ignore
9189 err
= wldev_iovar_getint(dev
, "wsec", (s32
*)&wsec
);
9190 if (unlikely(err
)) {
9191 WL_ERR(("Could not get wsec %d\n", err
));
9194 if ((wsec
== WEP_ENABLED
) && cfg
->wep_key
.len
) {
9195 WL_DBG(("Applying buffered WEP KEY \n"));
9196 err
= wldev_iovar_setbuf_bsscfg(dev
, "wsec_key", &cfg
->wep_key
,
9197 sizeof(struct wl_wsec_key
), cfg
->ioctl_buf
,
9198 WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
9199 /* clear the key after use */
9200 memset(&cfg
->wep_key
, 0, sizeof(struct wl_wsec_key
));
9201 if (unlikely(err
)) {
9202 WL_ERR(("WLC_SET_KEY error (%d)\n", err
));
9208 if (cfg
->mfp_mode
) {
9209 /* This needs to go after wsec otherwise the wsec command will
9210 * overwrite the values set by MFP
9212 err
= wldev_iovar_setint_bsscfg(dev
, "mfp", cfg
->mfp_mode
, bssidx
);
9214 WL_ERR(("MFP Setting failed. ret = %d \n", err
));
9215 /* If fw doesn't support mfp, Ignore the error */
9216 if (err
!= BCME_UNSUPPORTED
) {
9226 memset(&join_params
, 0, sizeof(join_params
));
9227 /* join parameters starts with ssid */
9228 join_params_size
= sizeof(join_params
.ssid
);
9229 join_params
.ssid
.SSID_len
= MIN(cfg
->hostapd_ssid
.SSID_len
,
9230 (uint32
)DOT11_MAX_SSID_LEN
);
9231 memcpy(join_params
.ssid
.SSID
, cfg
->hostapd_ssid
.SSID
,
9232 join_params
.ssid
.SSID_len
);
9233 join_params
.ssid
.SSID_len
= htod32(join_params
.ssid
.SSID_len
);
9236 if ((err
= wldev_ioctl_set(dev
, WLC_SET_SSID
, &join_params
,
9237 join_params_size
)) != 0) {
9238 WL_ERR(("SoftAP/GO set ssid failed! \n"));
9241 WL_DBG((" SoftAP SSID \"%s\" \n", join_params
.ssid
.SSID
));
9245 /* AP on Virtual Interface */
9246 if ((err
= wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 1)) < 0) {
9247 WL_ERR(("AP Bring up error %d\n", err
));
9254 /* Wait for Linkup event to mark successful AP/GO bring up */
9255 timeout
= wait_event_interruptible_timeout(cfg
->netif_change_event
,
9256 wl_get_drv_status(cfg
, AP_CREATED
, dev
), msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME
));
9257 if (timeout
<= 0 || !wl_get_drv_status(cfg
, AP_CREATED
, dev
)) {
9261 WL_ERR(("Link up didn't come for AP interface. Try to set ssid again to recover it! \n"));
9265 WL_ERR(("Link up didn't come for AP interface. AP/GO creation failed! \n"));
9266 if (timeout
== -ERESTARTSYS
) {
9267 WL_ERR(("waitqueue was interrupted by a signal, returns -ERESTARTSYS\n"));
9271 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
9272 if (dhdp
->memdump_enabled
) {
9273 dhdp
->memdump_type
= DUMP_TYPE_AP_LINKUP_FAILURE
;
9274 dhd_bus_mem_dump(dhdp
);
9276 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
9282 if (cfg
->wep_key
.len
) {
9283 memset(&cfg
->wep_key
, 0, sizeof(struct wl_wsec_key
));
9287 if (cfg
->mfp_mode
) {
9292 cfg
->bip_pos
= NULL
;
9299 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9301 wl_cfg80211_parse_ap_ies(
9302 struct net_device
*dev
,
9303 struct cfg80211_beacon_data
*info
,
9304 struct parsed_ies
*ies
)
9306 struct parsed_ies prb_ies
;
9307 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
9308 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
9309 const u8
*vndr
= NULL
;
9310 u32 vndr_ie_len
= 0;
9313 /* Parse Beacon IEs */
9314 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9315 #pragma GCC diagnostic push
9316 #pragma GCC diagnostic ignored "-Wcast-qual"
9318 if (wl_cfg80211_parse_ies((u8
*)info
->tail
,
9319 info
->tail_len
, ies
) < 0) {
9320 WL_ERR(("Beacon get IEs failed \n"));
9324 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9325 #pragma GCC diagnostic pop
9327 vndr
= (const u8
*)info
->proberesp_ies
;
9328 vndr_ie_len
= info
->proberesp_ies_len
;
9330 if (dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
) {
9332 const struct ieee80211_mgmt
*mgmt
;
9333 mgmt
= (const struct ieee80211_mgmt
*)info
->probe_resp
;
9335 vndr
= (const u8
*)&mgmt
->u
.probe_resp
.variable
;
9336 vndr_ie_len
= info
->probe_resp_len
-
9337 offsetof(const struct ieee80211_mgmt
, u
.probe_resp
.variable
);
9340 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9341 #pragma GCC diagnostic push
9342 #pragma GCC diagnostic ignored "-Wcast-qual"
9344 /* Parse Probe Response IEs */
9345 if (wl_cfg80211_parse_ies((u8
*)vndr
, vndr_ie_len
, &prb_ies
) < 0) {
9346 WL_ERR(("PROBE RESP get IEs failed \n"));
9349 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9350 #pragma GCC diagnostic pop
9358 wl_cfg80211_set_ies(
9359 struct net_device
*dev
,
9360 struct cfg80211_beacon_data
*info
,
9363 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
9364 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
9365 const u8
*vndr
= NULL
;
9366 u32 vndr_ie_len
= 0;
9369 /* Set Beacon IEs to FW */
9370 if ((err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
9371 VNDR_IE_BEACON_FLAG
, (const u8
*)info
->tail
,
9372 info
->tail_len
)) < 0) {
9373 WL_ERR(("Set Beacon IE Failed \n"));
9375 WL_DBG(("Applied Vndr IEs for Beacon \n"));
9378 vndr
= (const u8
*)info
->proberesp_ies
;
9379 vndr_ie_len
= info
->proberesp_ies_len
;
9381 if (dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
) {
9383 const struct ieee80211_mgmt
*mgmt
;
9384 mgmt
= (const struct ieee80211_mgmt
*)info
->probe_resp
;
9386 vndr
= (const u8
*)&mgmt
->u
.probe_resp
.variable
;
9387 vndr_ie_len
= info
->probe_resp_len
-
9388 offsetof(struct ieee80211_mgmt
, u
.probe_resp
.variable
);
9392 /* Set Probe Response IEs to FW */
9393 if ((err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
9394 VNDR_IE_PRBRSP_FLAG
, vndr
, vndr_ie_len
)) < 0) {
9395 WL_ERR(("Set Probe Resp IE Failed \n"));
9397 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
9404 static s32
wl_cfg80211_hostapd_sec(
9405 struct net_device
*dev
,
9406 struct parsed_ies
*ies
,
9409 bool update_bss
= 0;
9410 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
9411 wl_cfgbss_t
*bss
= wl_get_cfgbss_by_wdev(cfg
, dev
->ieee80211_ptr
);
9414 WL_ERR(("cfgbss is NULL \n"));
9420 memcmp(bss
->wps_ie
, ies
->wps_ie
, ies
->wps_ie_len
)) {
9421 WL_DBG((" WPS IE is changed\n"));
9423 bss
->wps_ie
= kmemdup(ies
->wps_ie
, ies
->wps_ie_len
, GFP_KERNEL
);
9424 } else if (bss
->wps_ie
== NULL
) {
9425 WL_DBG((" WPS IE is added\n"));
9426 bss
->wps_ie
= kmemdup(ies
->wps_ie
, ies
->wps_ie_len
, GFP_KERNEL
);
9429 if ((ies
->wpa_ie
!= NULL
|| ies
->wpa2_ie
!= NULL
)) {
9430 if (!bss
->security_mode
) {
9431 /* change from open mode to security mode */
9433 if (ies
->wpa_ie
!= NULL
) {
9434 bss
->wpa_ie
= kmemdup(ies
->wpa_ie
,
9435 ies
->wpa_ie
->length
+ WPA_RSN_IE_TAG_FIXED_LEN
,
9438 bss
->rsn_ie
= kmemdup(ies
->wpa2_ie
,
9439 ies
->wpa2_ie
->len
+ WPA_RSN_IE_TAG_FIXED_LEN
,
9442 } else if (bss
->wpa_ie
) {
9443 /* change from WPA2 mode to WPA mode */
9444 if (ies
->wpa_ie
!= NULL
) {
9448 bss
->wpa_ie
= kmemdup(ies
->wpa_ie
,
9449 ies
->wpa_ie
->length
+ WPA_RSN_IE_TAG_FIXED_LEN
,
9451 } else if (memcmp(bss
->rsn_ie
,
9452 ies
->wpa2_ie
, ies
->wpa2_ie
->len
9453 + WPA_RSN_IE_TAG_FIXED_LEN
)) {
9456 bss
->rsn_ie
= kmemdup(ies
->wpa2_ie
,
9457 ies
->wpa2_ie
->len
+ WPA_RSN_IE_TAG_FIXED_LEN
,
9463 bss
->security_mode
= true;
9464 wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 0);
9465 if (wl_validate_wpa2ie(dev
, ies
->wpa2_ie
, bssidx
) < 0 ||
9466 wl_validate_wpaie(dev
, ies
->wpa_ie
, bssidx
) < 0) {
9469 wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 1);
9473 WL_ERR(("No WPSIE in beacon \n"));
9478 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
9481 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9482 wl_cfg80211_del_station(
9483 struct wiphy
*wiphy
, struct net_device
*ndev
,
9484 struct station_del_parameters
*params
)
9485 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9486 wl_cfg80211_del_station(
9487 struct wiphy
*wiphy
,
9488 struct net_device
*ndev
,
9491 wl_cfg80211_del_station(
9492 struct wiphy
*wiphy
,
9493 struct net_device
*ndev
,
9495 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9497 struct net_device
*dev
;
9498 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
9500 s8 eabuf
[ETHER_ADDR_STR_LEN
];
9502 char mac_buf
[MAX_NUM_OF_ASSOCIATED_DEV
*
9503 sizeof(struct ether_addr
) + sizeof(uint
)] = {0};
9504 struct maclist
*assoc_maclist
= (struct maclist
*)mac_buf
;
9505 int num_associated
= 0;
9507 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9508 const u8
*mac_addr
= params
->mac
;
9509 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9510 u16 rc
= params
->reason_code
;
9511 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9512 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9513 WL_DBG(("Entry\n"));
9514 if (mac_addr
== NULL
) {
9515 WL_DBG(("mac_addr is NULL ignore it\n"));
9519 dev
= ndev_to_wlc_ndev(ndev
, cfg
);
9521 if (p2p_is_on(cfg
)) {
9522 /* Suspend P2P discovery search-listen to prevent it from changing the
9525 if ((wl_cfgp2p_discover_enable_search(cfg
, false)) < 0) {
9526 WL_ERR(("Can not disable discovery mode\n"));
9531 assoc_maclist
->count
= MAX_NUM_OF_ASSOCIATED_DEV
;
9532 err
= wldev_ioctl_get(ndev
, WLC_GET_ASSOCLIST
,
9533 assoc_maclist
, sizeof(mac_buf
));
9535 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err
));
9537 num_associated
= assoc_maclist
->count
;
9539 memcpy(scb_val
.ea
.octet
, mac_addr
, ETHER_ADDR_LEN
);
9540 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9541 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9542 if (rc
== DOT11_RC_8021X_AUTH_FAIL
) {
9543 WL_ERR(("deauth will be sent at F/W\n"));
9544 scb_val
.val
= DOT11_RC_8021X_AUTH_FAIL
;
9546 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9547 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9548 dhd_wait_pend8021x(dev
);
9549 scb_val
.val
= DOT11_RC_DEAUTH_LEAVING
;
9550 err
= wldev_ioctl_set(dev
, WLC_SCB_DEAUTHENTICATE_FOR_REASON
, &scb_val
,
9553 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err
));
9554 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9555 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9557 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9558 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9559 printf("%s: Disconnect STA : %s scb_val.val %d\n", __FUNCTION__
,
9560 bcm_ether_ntoa((const struct ether_addr
*)mac_addr
, eabuf
),
9563 if (num_associated
> 0 && ETHER_ISBCAST(mac_addr
))
9570 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9571 wl_cfg80211_change_station(
9572 struct wiphy
*wiphy
,
9573 struct net_device
*dev
,
9575 struct station_parameters
*params
)
9577 wl_cfg80211_change_station(
9578 struct wiphy
*wiphy
,
9579 struct net_device
*dev
,
9581 struct station_parameters
*params
)
9585 #if defined(WL_ENABLE_P2P_IF)
9586 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
9588 struct net_device
*ndev
= ndev_to_wlc_ndev(dev
, cfg
);
9590 WL_DBG(("SCB_AUTHORIZE mac_addr:"MACDBG
" sta_flags_mask:0x%x "
9591 "sta_flags_set:0x%x iface:%s \n", MAC2STRDBG(mac
),
9592 params
->sta_flags_mask
, params
->sta_flags_set
, ndev
->name
));
9594 /* Processing only authorize/de-authorize flag for now */
9595 if (!(params
->sta_flags_mask
& BIT(NL80211_STA_FLAG_AUTHORIZED
))) {
9596 WL_ERR(("WLC_SCB_AUTHORIZE sta_flags_mask not set \n"));
9600 if (!(params
->sta_flags_set
& BIT(NL80211_STA_FLAG_AUTHORIZED
))) {
9601 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9602 err
= wldev_ioctl_set(ndev
, WLC_SCB_DEAUTHORIZE
, (u8
*)mac
, ETH_ALEN
);
9604 err
= wldev_ioctl_set(ndev
, WLC_SCB_DEAUTHORIZE
, mac
, ETH_ALEN
);
9607 WL_ERR(("WLC_SCB_DEAUTHORIZE error (%d)\n", err
));
9611 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9612 err
= wldev_ioctl_set(ndev
, WLC_SCB_AUTHORIZE
, (u8
*)mac
, ETH_ALEN
);
9614 err
= wldev_ioctl_set(ndev
, WLC_SCB_AUTHORIZE
, mac
, ETH_ALEN
);
9617 WL_ERR(("WLC_SCB_AUTHORIZE error (%d)\n", err
));
9618 #ifdef DHD_LOSSLESS_ROAMING
9619 wl_del_roam_timeout(cfg
);
9623 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
9626 wl_cfg80211_set_scb_timings(
9627 struct bcm_cfg80211
*cfg
,
9628 struct net_device
*dev
)
9632 wl_scb_probe_t scb_probe
;
9634 bzero(&scb_probe
, sizeof(wl_scb_probe_t
));
9635 scb_probe
.scb_timeout
= WL_SCB_TIMEOUT
;
9636 scb_probe
.scb_activity_time
= WL_SCB_ACTIVITY_TIME
;
9637 scb_probe
.scb_max_probe
= WL_SCB_MAX_PROBE
;
9638 err
= wldev_iovar_setbuf(dev
, "scb_probe", (void *)&scb_probe
,
9639 sizeof(wl_scb_probe_t
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
9640 &cfg
->ioctl_buf_sync
);
9641 if (unlikely(err
)) {
9642 WL_ERR(("set 'scb_probe' failed, error = %d\n", err
));
9646 ps_pretend
= MAX(WL_SCB_MAX_PROBE
/ 2, WL_MIN_PSPRETEND_THRESHOLD
);
9647 err
= wldev_iovar_setint(dev
, "pspretend_threshold", ps_pretend
);
9648 if (unlikely(err
)) {
9649 if (err
== BCME_UNSUPPORTED
) {
9650 /* Ignore error if fw doesn't support the iovar */
9651 WL_DBG(("wl pspretend_threshold %d set error %d\n",
9654 WL_ERR(("wl pspretend_threshold %d set error %d\n",
9663 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9665 wl_cfg80211_start_ap(
9666 struct wiphy
*wiphy
,
9667 struct net_device
*dev
,
9668 struct cfg80211_ap_settings
*info
)
9670 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
9672 struct parsed_ies ies
;
9675 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
9677 struct wl_join_params join_params
;
9678 s32 join_params_size
= 0;
9681 WL_DBG(("Enter \n"));
9683 #if defined(SUPPORT_RANDOM_MAC_SCAN)
9684 wl_cfg80211_set_random_mac(dev
, FALSE
);
9685 #endif /* SUPPORT_RANDOM_MAC_SCAN */
9687 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
9688 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
9692 if (p2p_is_on(cfg
) && (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
)) {
9693 dev_role
= NL80211_IFTYPE_P2P_GO
;
9694 } else if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
9695 dev_role
= NL80211_IFTYPE_AP
;
9696 dhd
->op_mode
|= DHD_FLAG_HOSTAP_MODE
;
9697 err
= dhd_ndo_enable(dhd
, FALSE
);
9698 WL_DBG(("%s: Disabling NDO on Hostapd mode %d\n", __FUNCTION__
, err
));
9700 WL_ERR(("%s: Disabling NDO Failed %d\n", __FUNCTION__
, err
));
9702 #ifdef PKT_FILTER_SUPPORT
9703 /* Disable packet filter */
9704 if (dhd
->early_suspended
) {
9705 WL_ERR(("Disable pkt_filter\n"));
9706 dhd_enable_packet_filter(0, dhd
);
9708 #endif /* PKT_FILTER_SUPPORT */
9709 #ifdef ARP_OFFLOAD_SUPPORT
9710 /* IF SoftAP is enabled, disable arpoe */
9711 if (dhd
->op_mode
& DHD_FLAG_STA_MODE
) {
9712 dhd_arp_offload_set(dhd
, 0);
9713 dhd_arp_offload_enable(dhd
, FALSE
);
9715 #endif /* ARP_OFFLOAD_SUPPORT */
9716 #ifdef SUPPORT_SET_CAC
9717 wl_cfg80211_set_cac(cfg
, 0);
9718 #endif /* SUPPORT_SET_CAC */
9720 /* only AP or GO role need to be handled here. */
9728 /* Disable TDLS for primary Iface. For virtual interface,
9729 * tdls disable will happen from interface create context
9731 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_AP_CREATE
, false);
9735 if (!check_dev_role_integrity(cfg
, dev_role
)) {
9740 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9741 if ((err
= wl_cfg80211_set_channel(wiphy
, dev
,
9742 dev
->ieee80211_ptr
->preset_chandef
.chan
,
9743 NL80211_CHAN_HT20
) < 0)) {
9744 WL_ERR(("Set channel failed \n"));
9749 if ((err
= wl_cfg80211_bcn_set_params(info
, dev
,
9750 dev_role
, bssidx
)) < 0) {
9751 WL_ERR(("Beacon params set failed \n"));
9756 if ((err
= wl_cfg80211_parse_ap_ies(dev
, &info
->beacon
, &ies
)) < 0) {
9757 WL_ERR(("Set IEs failed \n"));
9761 if ((err
= wl_cfg80211_bcn_validate_sec(dev
, &ies
,
9762 dev_role
, bssidx
, info
->privacy
)) < 0)
9764 WL_ERR(("Beacon set security failed \n"));
9768 if ((err
= wl_cfg80211_bcn_bringup_ap(dev
, &ies
,
9769 dev_role
, bssidx
)) < 0) {
9770 WL_ERR(("Beacon bring up AP/GO failed \n"));
9774 /* Set GC/STA SCB expiry timings. */
9775 if ((err
= wl_cfg80211_set_scb_timings(cfg
, dev
))) {
9776 WL_ERR(("scb setting failed \n"));
9782 if ((dev_role
== NL80211_IFTYPE_P2P_GO
) || (dev_role
== NL80211_IFTYPE_AP
)) {
9783 memset(&join_params
, 0, sizeof(join_params
));
9784 /* join parameters starts with ssid */
9785 join_params_size
= sizeof(join_params
.ssid
);
9786 if (dev_role
== NL80211_IFTYPE_P2P_GO
) {
9787 join_params
.ssid
.SSID_len
= min(cfg
->p2p
->ssid
.SSID_len
,
9788 (uint32
)DOT11_MAX_SSID_LEN
);
9789 memcpy(join_params
.ssid
.SSID
, cfg
->p2p
->ssid
.SSID
,
9790 join_params
.ssid
.SSID_len
);
9791 } else if (dev_role
== NL80211_IFTYPE_AP
) {
9792 join_params
.ssid
.SSID_len
= min(cfg
->hostapd_ssid
.SSID_len
,
9793 (uint32
)DOT11_MAX_SSID_LEN
);
9794 memcpy(join_params
.ssid
.SSID
, cfg
->hostapd_ssid
.SSID
,
9795 join_params
.ssid
.SSID_len
);
9797 join_params
.ssid
.SSID_len
= htod32(join_params
.ssid
.SSID_len
);
9799 if ((err
= wldev_ioctl_set(dev
, WLC_SET_SSID
, &join_params
,
9800 join_params_size
)) != 0) {
9801 WL_ERR(("SoftAP/GO set ssid failed! \n"));
9804 WL_DBG((" SoftAP SSID \"%s\" \n", join_params
.ssid
.SSID
));
9809 WL_DBG(("** AP/GO Created **\n"));
9811 #ifdef WL_CFG80211_ACL
9812 /* Enfoce Admission Control. */
9813 if ((err
= wl_cfg80211_set_mac_acl(wiphy
, dev
, info
->acl
)) < 0) {
9814 WL_ERR(("Set ACL failed\n"));
9816 #endif /* WL_CFG80211_ACL */
9819 if ((err
= wl_cfg80211_set_ies(dev
, &info
->beacon
, bssidx
)) < 0)
9820 WL_ERR(("Set IEs failed \n"));
9822 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
9823 if ((dev_role
== NL80211_IFTYPE_AP
) && (ies
.wps_ie
!= NULL
)) {
9825 wl_validate_wps_ie((char *) ies
.wps_ie
, ies
.wps_ie_len
, &pbc
);
9827 WL_DBG(("set WLC_E_PROBREQ_MSG\n"));
9828 wl_add_remove_eventmsg(dev
, WLC_E_PROBREQ_MSG
, true);
9832 #ifdef SUPPORT_AP_RADIO_PWRSAVE
9833 if ((dev_role
== NL80211_IFTYPE_AP
)) {
9834 wl_set_ap_rps(dev
, FALSE
, dev
->name
);
9835 wl_cfg80211_init_ap_rps(cfg
);
9837 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
9840 WL_ERR(("ADD/SET beacon failed\n"));
9841 wl_cfg80211_stop_ap(wiphy
, dev
);
9842 if (dev_role
== NL80211_IFTYPE_AP
) {
9843 dhd
->op_mode
&= ~DHD_FLAG_HOSTAP_MODE
;
9844 #ifdef PKT_FILTER_SUPPORT
9845 /* Enable packet filter */
9846 if (dhd
->early_suspended
) {
9847 WL_ERR(("Enable pkt_filter\n"));
9848 dhd_enable_packet_filter(1, dhd
);
9850 #endif /* PKT_FILTER_SUPPORT */
9851 #ifdef ARP_OFFLOAD_SUPPORT
9852 /* IF SoftAP is disabled, enable arpoe back for STA mode. */
9853 if (dhd
->op_mode
& DHD_FLAG_STA_MODE
) {
9854 dhd_arp_offload_set(dhd
, dhd_arp_mode
);
9855 dhd_arp_offload_enable(dhd
, TRUE
);
9857 #endif /* ARP_OFFLOAD_SUPPORT */
9861 /* Since AP creation failed, re-enable TDLS */
9862 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_AP_DELETE
, false);
9872 wl_cfg80211_stop_ap(
9873 struct wiphy
*wiphy
,
9874 struct net_device
*dev
)
9880 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
9881 s32 is_rsdb_supported
= BCME_ERROR
;
9882 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
9884 WL_DBG(("Enter \n"));
9886 is_rsdb_supported
= DHD_OPMODE_SUPPORTED(cfg
->pub
, DHD_FLAG_RSDB_MODE
);
9887 if (is_rsdb_supported
< 0)
9890 wl_clr_drv_status(cfg
, AP_CREATING
, dev
);
9891 wl_clr_drv_status(cfg
, AP_CREATED
, dev
);
9892 cfg
->ap_oper_channel
= 0;
9894 if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
9895 dev_role
= NL80211_IFTYPE_AP
;
9896 WL_DBG(("stopping AP operation\n"));
9897 } else if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
) {
9898 dev_role
= NL80211_IFTYPE_P2P_GO
;
9899 WL_DBG(("stopping P2P GO operation\n"));
9901 WL_ERR(("no AP/P2P GO interface is operational.\n"));
9905 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
9906 WL_ERR(("find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
9910 if (!check_dev_role_integrity(cfg
, dev_role
)) {
9911 WL_ERR(("role integrity check failed \n"));
9916 /* Clear AP/GO connected status */
9917 wl_clr_drv_status(cfg
, CONNECTED
, dev
);
9918 if ((err
= wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 0)) < 0) {
9919 WL_ERR(("bss down error %d\n", err
));
9922 if (dev_role
== NL80211_IFTYPE_AP
) {
9923 #ifdef PKT_FILTER_SUPPORT
9924 /* Enable packet filter */
9925 if (dhd
->early_suspended
) {
9926 WL_ERR(("Enable pkt_filter\n"));
9927 dhd_enable_packet_filter(1, dhd
);
9929 #endif /* PKT_FILTER_SUPPORT */
9930 #ifdef ARP_OFFLOAD_SUPPORT
9931 /* IF SoftAP is disabled, enable arpoe back for STA mode. */
9932 if (dhd
->op_mode
& DHD_FLAG_STA_MODE
) {
9933 dhd_arp_offload_set(dhd
, dhd_arp_mode
);
9934 dhd_arp_offload_enable(dhd
, TRUE
);
9936 #endif /* ARP_OFFLOAD_SUPPORT */
9938 if (is_rsdb_supported
== 0) {
9939 /* For non-rsdb chips, we use stand alone AP. Do wl down on stop AP */
9940 err
= wldev_ioctl_set(dev
, WLC_UP
, &ap
, sizeof(s32
));
9941 if (unlikely(err
)) {
9942 WL_ERR(("WLC_UP error (%d)\n", err
));
9948 wl_cfg80211_clear_per_bss_ies(cfg
, bssidx
);
9949 #ifdef SUPPORT_AP_RADIO_PWRSAVE
9950 wl_set_ap_rps(dev
, FALSE
, dev
->name
);
9951 wl_cfg80211_init_ap_rps(cfg
);
9952 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
9954 WL_DBG(("Stopping P2P GO \n"));
9955 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t
*)(cfg
->pub
),
9956 DHD_EVENT_TIMEOUT_MS
*3);
9957 DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t
*)(cfg
->pub
));
9962 /* re-enable TDLS if the number of connected interfaces is less than 2 */
9963 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_AP_DELETE
, false);
9967 if (dev_role
== NL80211_IFTYPE_AP
) {
9968 /* clear the AP mode */
9969 dhd
->op_mode
&= ~DHD_FLAG_HOSTAP_MODE
;
9971 #ifdef SUPPORT_SET_CAC
9972 wl_cfg80211_set_cac(cfg
, 1);
9973 #endif /* SUPPORT_SET_CAC */
9978 wl_cfg80211_change_beacon(
9979 struct wiphy
*wiphy
,
9980 struct net_device
*dev
,
9981 struct cfg80211_beacon_data
*info
)
9984 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
9985 struct parsed_ies ies
;
9990 WL_DBG(("Enter \n"));
9992 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
9993 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
9997 if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
) {
9998 dev_role
= NL80211_IFTYPE_P2P_GO
;
9999 } else if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
10000 dev_role
= NL80211_IFTYPE_AP
;
10006 if (!check_dev_role_integrity(cfg
, dev_role
)) {
10011 if ((dev_role
== NL80211_IFTYPE_P2P_GO
) && (cfg
->p2p_wdev
== NULL
)) {
10012 WL_ERR(("P2P already down status!\n"));
10018 if ((err
= wl_cfg80211_parse_ap_ies(dev
, info
, &ies
)) < 0) {
10019 WL_ERR(("Parse IEs failed \n"));
10023 /* Set IEs to FW */
10024 if ((err
= wl_cfg80211_set_ies(dev
, info
, bssidx
)) < 0) {
10025 WL_ERR(("Set IEs failed \n"));
10029 if (dev_role
== NL80211_IFTYPE_AP
) {
10030 if (wl_cfg80211_hostapd_sec(dev
, &ies
, bssidx
) < 0) {
10031 WL_ERR(("Hostapd update sec failed \n"));
10035 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
10036 if ((dev_role
== NL80211_IFTYPE_AP
) && (ies
.wps_ie
!= NULL
)) {
10037 wl_validate_wps_ie((char *) ies
.wps_ie
, ies
.wps_ie_len
, &pbc
);
10038 WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc
));
10040 wl_add_remove_eventmsg(dev
, WLC_E_PROBREQ_MSG
, true);
10042 wl_add_remove_eventmsg(dev
, WLC_E_PROBREQ_MSG
, false);
10051 wl_cfg80211_add_set_beacon(struct wiphy
*wiphy
, struct net_device
*dev
,
10052 struct beacon_parameters
*info
)
10055 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10058 u32 dev_role
= NL80211_IFTYPE_AP
;
10059 struct parsed_ies ies
;
10060 bcm_tlv_t
*ssid_ie
;
10063 bool is_bss_up
= 0;
10064 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
10066 WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
10067 info
->interval
, info
->dtim_period
, info
->head_len
, info
->tail_len
));
10069 if (dev
== bcmcfg_to_prmry_ndev(cfg
)) {
10070 dev_role
= NL80211_IFTYPE_AP
;
10072 #if defined(WL_ENABLE_P2P_IF)
10073 else if (dev
== cfg
->p2p_net
) {
10074 /* Group Add request on p2p0 */
10075 dev
= bcmcfg_to_prmry_ndev(cfg
);
10076 dev_role
= NL80211_IFTYPE_P2P_GO
;
10078 #endif /* WL_ENABLE_P2P_IF */
10080 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
10081 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
10085 if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_GO
) {
10086 dev_role
= NL80211_IFTYPE_P2P_GO
;
10087 } else if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
10088 dhd
->op_mode
|= DHD_FLAG_HOSTAP_MODE
;
10091 if (!check_dev_role_integrity(cfg
, dev_role
)) {
10096 if ((dev_role
== NL80211_IFTYPE_P2P_GO
) && (cfg
->p2p_wdev
== NULL
)) {
10097 WL_ERR(("P2P already down status!\n"));
10102 ie_offset
= DOT11_MGMT_HDR_LEN
+ DOT11_BCN_PRB_FIXED_LEN
;
10103 /* find the SSID */
10104 if ((ssid_ie
= bcm_parse_tlvs((u8
*)&info
->head
[ie_offset
],
10105 info
->head_len
- ie_offset
,
10106 DOT11_MNG_SSID_ID
)) != NULL
) {
10107 if (dev_role
== NL80211_IFTYPE_AP
) {
10108 /* Store the hostapd SSID */
10109 memset(&cfg
->hostapd_ssid
.SSID
[0], 0x00, DOT11_MAX_SSID_LEN
);
10110 cfg
->hostapd_ssid
.SSID_len
= MIN(ssid_ie
->len
, DOT11_MAX_SSID_LEN
);
10111 memcpy(&cfg
->hostapd_ssid
.SSID
[0], ssid_ie
->data
,
10112 cfg
->hostapd_ssid
.SSID_len
);
10115 memset(&cfg
->p2p
->ssid
.SSID
[0], 0x00, DOT11_MAX_SSID_LEN
);
10116 cfg
->p2p
->ssid
.SSID_len
= MIN(ssid_ie
->len
, DOT11_MAX_SSID_LEN
);
10117 memcpy(cfg
->p2p
->ssid
.SSID
, ssid_ie
->data
,
10118 cfg
->p2p
->ssid
.SSID_len
);
10122 if (wl_cfg80211_parse_ies((u8
*)info
->tail
,
10123 info
->tail_len
, &ies
) < 0) {
10124 WL_ERR(("Beacon get IEs failed \n"));
10129 if ((err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
10130 VNDR_IE_BEACON_FLAG
, (u8
*)info
->tail
,
10131 info
->tail_len
)) < 0) {
10132 WL_ERR(("Beacon set IEs failed \n"));
10135 WL_DBG(("Applied Vndr IEs for Beacon \n"));
10138 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10139 if ((err
= wl_cfg80211_set_mgmt_vndr_ies(cfg
, ndev_to_cfgdev(dev
), bssidx
,
10140 VNDR_IE_PRBRSP_FLAG
, (u8
*)info
->proberesp_ies
,
10141 info
->proberesp_ies_len
)) < 0) {
10142 WL_ERR(("ProbeRsp set IEs failed \n"));
10145 WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
10149 is_bss_up
= wl_cfg80211_bss_isup(dev
, bssidx
);
10151 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10152 privacy
= info
->privacy
;
10157 (wl_cfg80211_bcn_validate_sec(dev
, &ies
, dev_role
, bssidx
, privacy
) < 0))
10159 WL_ERR(("Beacon set security failed \n"));
10164 /* Set BI and DTIM period */
10165 if (info
->interval
) {
10166 if ((err
= wldev_ioctl_set(dev
, WLC_SET_BCNPRD
,
10167 &info
->interval
, sizeof(s32
))) < 0) {
10168 WL_ERR(("Beacon Interval Set Error, %d\n", err
));
10172 if (info
->dtim_period
) {
10173 if ((err
= wldev_ioctl_set(dev
, WLC_SET_DTIMPRD
,
10174 &info
->dtim_period
, sizeof(s32
))) < 0) {
10175 WL_ERR(("DTIM Interval Set Error, %d\n", err
));
10180 /* If bss is already up, skip bring up */
10182 (err
= wl_cfg80211_bcn_bringup_ap(dev
, &ies
, dev_role
, bssidx
)) < 0)
10184 WL_ERR(("Beacon bring up AP/GO failed \n"));
10188 /* Set GC/STA SCB expiry timings. */
10189 if ((err
= wl_cfg80211_set_scb_timings(cfg
, dev
))) {
10190 WL_ERR(("scb setting failed \n"));
10194 if (wl_get_drv_status(cfg
, AP_CREATED
, dev
)) {
10195 /* Soft AP already running. Update changed params */
10196 if (wl_cfg80211_hostapd_sec(dev
, &ies
, bssidx
) < 0) {
10197 WL_ERR(("Hostapd update sec failed \n"));
10203 /* Enable Probe Req filter */
10204 if (((dev_role
== NL80211_IFTYPE_P2P_GO
) ||
10205 (dev_role
== NL80211_IFTYPE_AP
)) && (ies
.wps_ie
!= NULL
)) {
10206 wl_validate_wps_ie((char *) ies
.wps_ie
, ies
.wps_ie_len
, &pbc
);
10208 wl_add_remove_eventmsg(dev
, WLC_E_PROBREQ_MSG
, true);
10211 WL_DBG(("** ADD/SET beacon done **\n"));
10215 WL_ERR(("ADD/SET beacon failed\n"));
10216 if (dev_role
== NL80211_IFTYPE_AP
) {
10217 /* clear the AP mode */
10218 dhd
->op_mode
&= ~DHD_FLAG_HOSTAP_MODE
;
10226 wl_cfg80211_del_beacon(struct wiphy
*wiphy
, struct net_device
*dev
)
10231 struct wireless_dev
*wdev
= dev
->ieee80211_ptr
;
10232 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10233 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
10235 WL_DBG(("Enter. \n"));
10238 WL_ERR(("wdev null \n"));
10242 if ((wdev
->iftype
!= NL80211_IFTYPE_P2P_GO
) && (wdev
->iftype
!= NL80211_IFTYPE_AP
)) {
10243 WL_ERR(("Unspported iface type iftype:%d \n", wdev
->iftype
));
10246 wl_clr_drv_status(cfg
, AP_CREATING
, dev
);
10247 wl_clr_drv_status(cfg
, AP_CREATED
, dev
);
10249 /* Clear AP/GO connected status */
10250 wl_clr_drv_status(cfg
, CONNECTED
, dev
);
10252 cfg
->ap_oper_channel
= 0;
10255 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) < 0) {
10256 WL_ERR(("find p2p index from wdev(%p) failed\n", dev
->ieee80211_ptr
));
10261 if ((err
= wl_cfg80211_bss_up(cfg
, dev
, bssidx
, 0)) < 0) {
10262 WL_ERR(("bss down error %d\n", err
));
10265 /* fall through is intentional */
10266 err
= wldev_ioctl_set(dev
, WLC_SET_INFRA
, &infra
, sizeof(s32
));
10268 WL_ERR(("SET INFRA error %d\n", err
));
10270 wl_cfg80211_clear_per_bss_ies(cfg
, bssidx
);
10272 if (wdev
->iftype
== NL80211_IFTYPE_AP
) {
10273 /* clear the AP mode */
10274 dhd
->op_mode
&= ~DHD_FLAG_HOSTAP_MODE
;
10281 #ifdef WL_SCHED_SCAN
10282 #define PNO_TIME 30
10283 #define PNO_REPEAT 4
10284 #define PNO_FREQ_EXPO_MAX 2
10286 is_ssid_in_list(struct cfg80211_ssid
*ssid
, struct cfg80211_ssid
*ssid_list
, int count
)
10290 if (!ssid
|| !ssid_list
)
10293 for (i
= 0; i
< count
; i
++) {
10294 if (ssid
->ssid_len
== ssid_list
[i
].ssid_len
) {
10295 if (strncmp(ssid
->ssid
, ssid_list
[i
].ssid
, ssid
->ssid_len
) == 0)
10303 wl_cfg80211_sched_scan_start(struct wiphy
*wiphy
,
10304 struct net_device
*dev
,
10305 struct cfg80211_sched_scan_request
*request
)
10307 ushort pno_time
= PNO_TIME
;
10308 int pno_repeat
= PNO_REPEAT
;
10309 int pno_freq_expo_max
= PNO_FREQ_EXPO_MAX
;
10310 wlc_ssid_ext_t ssids_local
[MAX_PFN_LIST_COUNT
];
10311 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10312 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
10313 struct cfg80211_ssid
*ssid
= NULL
;
10314 struct cfg80211_ssid
*hidden_ssid_list
= NULL
;
10315 log_conn_event_t
*event_data
= NULL
;
10316 tlv_log
*tlv_data
= NULL
;
10317 u32 alloc_len
, tlv_len
;
10322 unsigned long flags
;
10325 WL_ERR(("Sched scan request was NULL\n"));
10329 WL_DBG(("Enter \n"));
10330 WL_PNO((">>> SCHED SCAN START\n"));
10331 WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
10332 request
->n_match_sets
, request
->n_ssids
));
10333 WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
10334 request
->n_ssids
, pno_time
, pno_repeat
, pno_freq_expo_max
));
10337 if (!request
->n_ssids
|| !request
->n_match_sets
) {
10338 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request
->n_ssids
));
10342 memset(&ssids_local
, 0, sizeof(ssids_local
));
10344 if (request
->n_ssids
> 0) {
10345 hidden_ssid_list
= request
->ssids
;
10348 if (DBG_RING_ACTIVE(dhdp
, DHD_EVENT_RING_ID
)) {
10349 alloc_len
= sizeof(log_conn_event_t
) + DOT11_MAX_SSID_LEN
;
10350 event_data
= MALLOC(dhdp
->osh
, alloc_len
);
10352 WL_ERR(("%s: failed to allocate log_conn_event_t with "
10353 "length(%d)\n", __func__
, alloc_len
));
10356 memset(event_data
, 0, alloc_len
);
10357 event_data
->tlvs
= NULL
;
10358 tlv_len
= sizeof(tlv_log
);
10359 event_data
->tlvs
= (tlv_log
*)MALLOC(dhdp
->osh
, tlv_len
);
10360 if (!event_data
->tlvs
) {
10361 WL_ERR(("%s: failed to allocate log_tlv with "
10362 "length(%d)\n", __func__
, tlv_len
));
10363 MFREE(dhdp
->osh
, event_data
, alloc_len
);
10367 for (i
= 0; i
< request
->n_match_sets
&& ssid_cnt
< MAX_PFN_LIST_COUNT
; i
++) {
10368 ssid
= &request
->match_sets
[i
].ssid
;
10369 /* No need to include null ssid */
10370 if (ssid
->ssid_len
) {
10371 ssids_local
[ssid_cnt
].SSID_len
= MIN(ssid
->ssid_len
,
10372 (uint32
)DOT11_MAX_SSID_LEN
);
10373 memcpy(ssids_local
[ssid_cnt
].SSID
, ssid
->ssid
,
10374 ssids_local
[ssid_cnt
].SSID_len
);
10375 if (is_ssid_in_list(ssid
, hidden_ssid_list
, request
->n_ssids
)) {
10376 ssids_local
[ssid_cnt
].hidden
= TRUE
;
10377 WL_PNO((">>> PNO hidden SSID (%s) \n", ssid
->ssid
));
10379 ssids_local
[ssid_cnt
].hidden
= FALSE
;
10380 WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid
->ssid
));
10382 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0))
10383 if (request
->match_sets
[i
].rssi_thold
!= NL80211_SCAN_RSSI_THOLD_OFF
) {
10384 ssids_local
[ssid_cnt
].rssi_thresh
=
10385 (int8
)request
->match_sets
[i
].rssi_thold
;
10387 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0)) */
10393 if ((ret
= dhd_dev_pno_set_for_ssid(dev
, ssids_local
, ssid_cnt
,
10394 pno_time
, pno_repeat
, pno_freq_expo_max
, NULL
, 0)) < 0) {
10395 WL_ERR(("PNO setup failed!! ret=%d \n", ret
));
10400 if (DBG_RING_ACTIVE(dhdp
, DHD_EVENT_RING_ID
)) {
10401 for (i
= 0; i
< ssid_cnt
; i
++) {
10402 payload_len
= sizeof(log_conn_event_t
);
10403 event_data
->event
= WIFI_EVENT_DRIVER_PNO_ADD
;
10404 tlv_data
= event_data
->tlvs
;
10406 tlv_data
->tag
= WIFI_TAG_SSID
;
10407 tlv_data
->len
= ssids_local
[i
].SSID_len
;
10408 memcpy(tlv_data
->value
, ssids_local
[i
].SSID
,
10409 ssids_local
[i
].SSID_len
);
10410 payload_len
+= TLV_LOG_SIZE(tlv_data
);
10412 dhd_os_push_push_ring_data(dhdp
, DHD_EVENT_RING_ID
,
10413 event_data
, payload_len
);
10417 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
10418 cfg
->sched_scan_req
= request
;
10419 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
10425 MFREE(dhdp
->osh
, event_data
->tlvs
, tlv_len
);
10426 MFREE(dhdp
->osh
, event_data
, alloc_len
);
10432 wl_cfg80211_sched_scan_stop(struct wiphy
*wiphy
, struct net_device
*dev
10433 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
10435 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
10438 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10439 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
10440 unsigned long flags
;
10442 WL_DBG(("Enter \n"));
10443 WL_PNO((">>> SCHED SCAN STOP\n"));
10445 BCM_REFERENCE(dhdp
);
10446 if (dhd_dev_pno_stop_for_ssid(dev
) < 0) {
10447 WL_ERR(("PNO Stop for SSID failed"));
10449 DBG_EVENT_LOG(dhdp
, WIFI_EVENT_DRIVER_PNO_REMOVE
);
10452 if (cfg
->scan_request
&& cfg
->sched_scan_running
) {
10453 WL_PNO((">>> Sched scan running. Aborting it..\n"));
10454 wl_notify_escan_complete(cfg
, dev
, true, true);
10456 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
10457 cfg
->sched_scan_req
= NULL
;
10458 cfg
->sched_scan_running
= FALSE
;
10459 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
10462 #endif /* WL_SCHED_SCAN */
10464 #ifdef WL_SUPPORT_ACS
10466 * Currently the dump_obss IOVAR is returning string as output so we need to
10467 * parse the output buffer in an unoptimized way. Going forward if we get the
10468 * IOVAR output in binary format this method can be optimized
10470 static int wl_parse_dump_obss(char *buf
, struct wl_dump_survey
*survey
)
10474 char delim
[] = " \n";
10476 token
= strsep(&buf
, delim
);
10477 while (token
!= NULL
) {
10478 if (!strcmp(token
, "OBSS")) {
10479 for (i
= 0; i
< OBSS_TOKEN_IDX
; i
++)
10480 token
= strsep(&buf
, delim
);
10481 survey
->obss
= simple_strtoul(token
, NULL
, 10);
10484 if (!strcmp(token
, "IBSS")) {
10485 for (i
= 0; i
< IBSS_TOKEN_IDX
; i
++)
10486 token
= strsep(&buf
, delim
);
10487 survey
->ibss
= simple_strtoul(token
, NULL
, 10);
10490 if (!strcmp(token
, "TXDur")) {
10491 for (i
= 0; i
< TX_TOKEN_IDX
; i
++)
10492 token
= strsep(&buf
, delim
);
10493 survey
->tx
= simple_strtoul(token
, NULL
, 10);
10496 if (!strcmp(token
, "Category")) {
10497 for (i
= 0; i
< CTG_TOKEN_IDX
; i
++)
10498 token
= strsep(&buf
, delim
);
10499 survey
->no_ctg
= simple_strtoul(token
, NULL
, 10);
10502 if (!strcmp(token
, "Packet")) {
10503 for (i
= 0; i
< PKT_TOKEN_IDX
; i
++)
10504 token
= strsep(&buf
, delim
);
10505 survey
->no_pckt
= simple_strtoul(token
, NULL
, 10);
10508 if (!strcmp(token
, "Opp(time):")) {
10509 for (i
= 0; i
< IDLE_TOKEN_IDX
; i
++)
10510 token
= strsep(&buf
, delim
);
10511 survey
->idle
= simple_strtoul(token
, NULL
, 10);
10514 token
= strsep(&buf
, delim
);
10520 static int wl_dump_obss(struct net_device
*ndev
, cca_msrmnt_query req
,
10521 struct wl_dump_survey
*survey
)
10523 cca_stats_n_flags
*results
;
10527 buf
= kzalloc(sizeof(char) * WLC_IOCTL_MAXLEN
, GFP_KERNEL
);
10528 if (unlikely(!buf
)) {
10529 WL_ERR(("%s: buf alloc failed\n", __func__
));
10533 retry
= IOCTL_RETRY_COUNT
;
10535 err
= wldev_iovar_getbuf(ndev
, "dump_obss", &req
, sizeof(req
),
10536 buf
, WLC_IOCTL_MAXLEN
, NULL
);
10540 WL_DBG(("attempt = %d, err = %d, \n",
10541 (IOCTL_RETRY_COUNT
- retry
), err
));
10545 WL_ERR(("failure, dump_obss IOVAR failed\n"));
10550 results
= (cca_stats_n_flags
*)(buf
);
10551 wl_parse_dump_obss(results
->buf
, survey
);
10560 static int wl_cfg80211_dump_survey(struct wiphy
*wiphy
, struct net_device
*ndev
,
10561 int idx
, struct survey_info
*info
)
10563 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
10564 struct wl_dump_survey
*survey
;
10565 struct ieee80211_supported_band
*band
;
10566 struct ieee80211_channel
*chan
;
10567 cca_msrmnt_query req
;
10568 int val
, err
, noise
, retry
;
10570 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
10571 if (!(dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
10574 band
= wiphy
->bands
[IEEE80211_BAND_2GHZ
];
10575 if (band
&& idx
>= band
->n_channels
) {
10576 idx
-= band
->n_channels
;
10580 if (!band
|| idx
>= band
->n_channels
) {
10581 /* Move to 5G band */
10582 band
= wiphy
->bands
[IEEE80211_BAND_5GHZ
];
10583 if (idx
>= band
->n_channels
) {
10588 chan
= &band
->channels
[idx
];
10589 /* Setting current channel to the requested channel */
10590 if ((err
= wl_cfg80211_set_channel(wiphy
, ndev
, chan
,
10591 NL80211_CHAN_HT20
) < 0)) {
10592 WL_ERR(("Set channel failed \n"));
10596 /* Set interface up, explicitly. */
10598 err
= wldev_ioctl_set(ndev
, WLC_UP
, (void *)&val
, sizeof(val
));
10600 WL_ERR(("set interface up failed, error = %d\n", err
));
10604 /* Get noise value */
10605 retry
= IOCTL_RETRY_COUNT
;
10608 err
= wldev_ioctl_get(ndev
, WLC_GET_PHY_NOISE
, &noise
,
10613 WL_DBG(("attempt = %d, err = %d, \n",
10614 (IOCTL_RETRY_COUNT
- retry
), err
));
10618 WL_ERR(("Get Phy Noise failed, error = %d\n", err
));
10619 noise
= CHAN_NOISE_DUMMY
;
10622 survey
= (struct wl_dump_survey
*) kzalloc(sizeof(struct wl_dump_survey
),
10624 if (unlikely(!survey
)) {
10625 WL_ERR(("%s: alloc failed\n", __func__
));
10629 /* Start Measurement for obss stats on current channel */
10630 req
.msrmnt_query
= 0;
10631 req
.time_req
= ACS_MSRMNT_DELAY
;
10632 if ((err
= wl_dump_obss(ndev
, req
, survey
)) < 0) {
10637 * Wait for the meaurement to complete, adding a buffer value of 10 to take
10638 * into consideration any delay in IOVAR completion
10640 msleep(ACS_MSRMNT_DELAY
+ 10);
10642 /* Issue IOVAR to collect measurement results */
10643 req
.msrmnt_query
= 1;
10644 if ((err
= wl_dump_obss(ndev
, req
, survey
)) < 0) {
10648 info
->channel
= chan
;
10649 info
->noise
= noise
;
10650 info
->channel_time
= ACS_MSRMNT_DELAY
;
10651 info
->channel_time_busy
= ACS_MSRMNT_DELAY
- survey
->idle
;
10652 info
->channel_time_rx
= survey
->obss
+ survey
->ibss
+ survey
->no_ctg
+
10654 info
->channel_time_tx
= survey
->tx
;
10655 info
->filled
= SURVEY_INFO_NOISE_DBM
|SURVEY_INFO_CHANNEL_TIME
|
10656 SURVEY_INFO_CHANNEL_TIME_BUSY
| SURVEY_INFO_CHANNEL_TIME_RX
|
10657 SURVEY_INFO_CHANNEL_TIME_TX
;
10665 #endif /* WL_SUPPORT_ACS */
10667 static struct cfg80211_ops wl_cfg80211_ops
= {
10668 .add_virtual_intf
= wl_cfg80211_add_virtual_iface
,
10669 .del_virtual_intf
= wl_cfg80211_del_virtual_iface
,
10670 .change_virtual_intf
= wl_cfg80211_change_virtual_iface
,
10671 #if defined(WL_CFG80211_P2P_DEV_IF)
10672 .start_p2p_device
= wl_cfgp2p_start_p2p_device
,
10673 .stop_p2p_device
= wl_cfgp2p_stop_p2p_device
,
10674 #endif /* WL_CFG80211_P2P_DEV_IF */
10675 .scan
= wl_cfg80211_scan
,
10676 .set_wiphy_params
= wl_cfg80211_set_wiphy_params
,
10677 .join_ibss
= wl_cfg80211_join_ibss
,
10678 .leave_ibss
= wl_cfg80211_leave_ibss
,
10679 .get_station
= wl_cfg80211_get_station
,
10680 .set_tx_power
= wl_cfg80211_set_tx_power
,
10681 .get_tx_power
= wl_cfg80211_get_tx_power
,
10682 .add_key
= wl_cfg80211_add_key
,
10683 .del_key
= wl_cfg80211_del_key
,
10684 .get_key
= wl_cfg80211_get_key
,
10685 .set_default_key
= wl_cfg80211_config_default_key
,
10686 .set_default_mgmt_key
= wl_cfg80211_config_default_mgmt_key
,
10687 .set_power_mgmt
= wl_cfg80211_set_power_mgmt
,
10688 .connect
= wl_cfg80211_connect
,
10689 .disconnect
= wl_cfg80211_disconnect
,
10690 .suspend
= wl_cfg80211_suspend
,
10691 .resume
= wl_cfg80211_resume
,
10692 .set_pmksa
= wl_cfg80211_set_pmksa
,
10693 .del_pmksa
= wl_cfg80211_del_pmksa
,
10694 .flush_pmksa
= wl_cfg80211_flush_pmksa
,
10695 .remain_on_channel
= wl_cfg80211_remain_on_channel
,
10696 .cancel_remain_on_channel
= wl_cfg80211_cancel_remain_on_channel
,
10697 .mgmt_tx
= wl_cfg80211_mgmt_tx
,
10698 .mgmt_frame_register
= wl_cfg80211_mgmt_frame_register
,
10699 .change_bss
= wl_cfg80211_change_bss
,
10700 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
10701 .set_channel
= wl_cfg80211_set_channel
,
10703 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
10704 .set_beacon
= wl_cfg80211_add_set_beacon
,
10705 .add_beacon
= wl_cfg80211_add_set_beacon
,
10706 .del_beacon
= wl_cfg80211_del_beacon
,
10708 .change_beacon
= wl_cfg80211_change_beacon
,
10709 .start_ap
= wl_cfg80211_start_ap
,
10710 .stop_ap
= wl_cfg80211_stop_ap
,
10712 #ifdef WL_SCHED_SCAN
10713 .sched_scan_start
= wl_cfg80211_sched_scan_start
,
10714 .sched_scan_stop
= wl_cfg80211_sched_scan_stop
,
10715 #endif /* WL_SCHED_SCAN */
10716 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
10718 .del_station
= wl_cfg80211_del_station
,
10719 .change_station
= wl_cfg80211_change_station
,
10720 .mgmt_tx_cancel_wait
= wl_cfg80211_mgmt_tx_cancel_wait
,
10721 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
10723 .join_mesh
= wl_cfg80211_join_mesh
,
10724 .leave_mesh
= wl_cfg80211_leave_mesh
,
10725 #endif /* WLMESH */
10726 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
10727 .tdls_mgmt
= wl_cfg80211_tdls_mgmt
,
10728 .tdls_oper
= wl_cfg80211_tdls_oper
,
10730 #ifdef WL_SUPPORT_ACS
10731 .dump_survey
= wl_cfg80211_dump_survey
,
10732 #endif /* WL_SUPPORT_ACS */
10733 #ifdef WL_CFG80211_ACL
10734 .set_mac_acl
= wl_cfg80211_set_mac_acl
,
10735 #endif /* WL_CFG80211_ACL */
10736 #ifdef GTK_OFFLOAD_SUPPORT
10737 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
10738 .set_rekey_data
= wl_cfg80211_set_rekey_data
,
10739 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
10740 #endif /* GTK_OFFLOAD_SUPPORT */
10743 s32
wl_mode_to_nl80211_iftype(s32 mode
)
10749 return NL80211_IFTYPE_STATION
;
10751 return NL80211_IFTYPE_ADHOC
;
10753 return NL80211_IFTYPE_AP
;
10756 return NL80211_IFTYPE_MESH_POINT
;
10759 return NL80211_IFTYPE_UNSPECIFIED
;
10765 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
10766 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
10767 #define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
10769 #define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
10770 #endif /* kernel version < 3.9.0 */
10773 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
10774 WL_CFG80211_REG_NOTIFIER()
10776 struct bcm_cfg80211
*cfg
= (struct bcm_cfg80211
*)wiphy_priv(wiphy
);
10780 if (!request
|| !cfg
) {
10781 WL_ERR(("Invalid arg\n"));
10782 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
10786 #endif /* kernel version < 3.10.11 */
10789 WL_DBG(("ccode: %c%c Initiator: %d\n",
10790 request
->alpha2
[0], request
->alpha2
[1], request
->initiator
));
10792 /* We support only REGDOM_SET_BY_USER as of now */
10793 if ((request
->initiator
!= NL80211_REGDOM_SET_BY_USER
) &&
10794 (request
->initiator
!= NL80211_REGDOM_SET_BY_COUNTRY_IE
)) {
10795 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
10796 request
->initiator
));
10797 /* in case of no supported country by regdb
10798 lets driver setup platform default Locale
10802 WL_ERR(("Set country code %c%c from %s\n",
10803 request
->alpha2
[0], request
->alpha2
[1],
10804 ((request
->initiator
== NL80211_REGDOM_SET_BY_COUNTRY_IE
) ? " 11d AP" : "User")));
10806 if ((ret
= wldev_set_country(bcmcfg_to_prmry_ndev(cfg
), request
->alpha2
,
10807 false, (request
->initiator
== NL80211_REGDOM_SET_BY_USER
? true : false),
10809 WL_ERR(("set country Failed :%d\n", ret
));
10812 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
10816 #endif /* kernel version < 3.10.11 */
10818 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
10821 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
10822 static const struct wiphy_wowlan_support brcm_wowlan_support
= {
10823 .flags
= WIPHY_WOWLAN_ANY
,
10824 .n_patterns
= WL_WOWLAN_MAX_PATTERNS
,
10825 .pattern_min_len
= WL_WOWLAN_MIN_PATTERN_LEN
,
10826 .pattern_max_len
= WL_WOWLAN_MAX_PATTERN_LEN
,
10827 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
10828 .max_pkt_offset
= WL_WOWLAN_MAX_PATTERN_LEN
,
10829 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
10831 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
10832 #endif /* CONFIG_PM */
10834 static s32
wl_setup_wiphy(struct wireless_dev
*wdev
, struct device
*sdiofunc_dev
, dhd_pub_t
*context
)
10838 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10839 struct cfg80211_wowlan
*brcm_wowlan_config
= NULL
;
10840 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
10841 #endif /* CONFIG_PM */
10843 //#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
10844 dhd_pub_t
*dhd
= (dhd_pub_t
*)context
;
10845 BCM_REFERENCE(dhd
);
10848 WL_ERR(("DHD is NULL!!"));
10855 wiphy_new(&wl_cfg80211_ops
, sizeof(struct bcm_cfg80211
));
10856 if (unlikely(!wdev
->wiphy
)) {
10857 WL_ERR(("Couldn not allocate wiphy device\n"));
10861 set_wiphy_dev(wdev
->wiphy
, sdiofunc_dev
);
10862 wdev
->wiphy
->max_scan_ie_len
= WL_SCAN_IE_LEN_MAX
;
10863 /* Report how many SSIDs Driver can support per Scan request */
10864 wdev
->wiphy
->max_scan_ssids
= WL_SCAN_PARAMS_SSID_MAX
;
10865 wdev
->wiphy
->max_num_pmkids
= WL_NUM_PMKIDS_MAX
;
10866 #ifdef WL_SCHED_SCAN
10867 wdev
->wiphy
->max_sched_scan_ssids
= MAX_PFN_LIST_COUNT
;
10868 wdev
->wiphy
->max_match_sets
= MAX_PFN_LIST_COUNT
;
10869 wdev
->wiphy
->max_sched_scan_ie_len
= WL_SCAN_IE_LEN_MAX
;
10870 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
10871 wdev
->wiphy
->max_sched_scan_plan_interval
= PNO_SCAN_MAX_FW_SEC
;
10873 wdev
->wiphy
->flags
|= WIPHY_FLAG_SUPPORTS_SCHED_SCAN
;
10874 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
10875 #endif /* WL_SCHED_SCAN */
10877 wdev
->wiphy
->flags
|= WIPHY_FLAG_MESH_AUTH
;
10879 wdev
->wiphy
->interface_modes
=
10880 BIT(NL80211_IFTYPE_STATION
)
10881 | BIT(NL80211_IFTYPE_ADHOC
)
10882 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
10883 | BIT(NL80211_IFTYPE_MONITOR
)
10884 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
10885 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
10886 | BIT(NL80211_IFTYPE_P2P_CLIENT
)
10887 | BIT(NL80211_IFTYPE_P2P_GO
)
10888 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
10889 #if defined(WL_CFG80211_P2P_DEV_IF)
10890 | BIT(NL80211_IFTYPE_P2P_DEVICE
)
10891 #endif /* WL_CFG80211_P2P_DEV_IF */
10893 | BIT(NL80211_IFTYPE_MESH_POINT
)
10894 #endif /* WLMESH */
10895 | BIT(NL80211_IFTYPE_AP
);
10897 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
10898 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
10899 WL_DBG(("Setting interface combinations for common mode\n"));
10901 if (dhd
->conf
->num_different_channels
>= 0)
10902 common_iface_combinations
[0].num_different_channels
= dhd
->conf
->num_different_channels
;
10903 #endif /* !BCMDBUS */
10904 wdev
->wiphy
->iface_combinations
= common_iface_combinations
;
10905 wdev
->wiphy
->n_iface_combinations
=
10906 ARRAY_SIZE(common_iface_combinations
);
10907 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
10909 wdev
->wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &__wl_band_2ghz
;
10911 wdev
->wiphy
->signal_type
= CFG80211_SIGNAL_TYPE_MBM
;
10912 wdev
->wiphy
->cipher_suites
= __wl_cipher_suites
;
10913 wdev
->wiphy
->n_cipher_suites
= ARRAY_SIZE(__wl_cipher_suites
);
10914 wdev
->wiphy
->max_remain_on_channel_duration
= 5000;
10915 wdev
->wiphy
->mgmt_stypes
= wl_cfg80211_default_mgmt_stypes
;
10916 #ifndef WL_POWERSAVE_DISABLED
10917 wdev
->wiphy
->flags
|= WIPHY_FLAG_PS_ON_BY_DEFAULT
;
10919 wdev
->wiphy
->flags
&= ~WIPHY_FLAG_PS_ON_BY_DEFAULT
;
10920 #endif /* !WL_POWERSAVE_DISABLED */
10921 wdev
->wiphy
->flags
|= WIPHY_FLAG_NETNS_OK
|
10922 WIPHY_FLAG_4ADDR_AP
|
10923 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
10924 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS
|
10926 WIPHY_FLAG_4ADDR_STATION
;
10927 #if ((defined(ROAM_ENABLE) || defined(BCMFW_ROAM_ENABLE)) && (LINUX_VERSION_CODE >= \
10928 KERNEL_VERSION(3, 2, 0)))
10930 * If FW ROAM flag is advertised, upper layer wouldn't provide
10931 * the bssid & freq in the connect command. This will result a
10932 * delay in initial connection time due to firmware doing a full
10933 * channel scan to figure out the channel & bssid. However kernel
10934 * ver >= 3.15, provides bssid_hint & freq_hint and hence kernel
10935 * ver >= 3.15 won't have any issue. So if this flags need to be
10936 * advertised for kernel < 3.15, suggest to use RCC along with it
10937 * to avoid the initial connection delay.
10939 wdev
->wiphy
->flags
|= WIPHY_FLAG_SUPPORTS_FW_ROAM
;
10941 #ifdef UNSET_FW_ROAM_WIPHY_FLAG
10942 wdev
->wiphy
->flags
&= ~WIPHY_FLAG_SUPPORTS_FW_ROAM
;
10943 #endif /* UNSET_FW_ROAM_WIPHY_FLAG */
10944 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
10945 wdev
->wiphy
->flags
|= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL
|
10946 WIPHY_FLAG_OFFCHAN_TX
;
10948 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
10950 /* From 3.4 kernel ownards AP_SME flag can be advertised
10951 * to remove the patch from supplicant
10953 wdev
->wiphy
->flags
|= WIPHY_FLAG_HAVE_AP_SME
;
10955 #ifdef WL_CFG80211_ACL
10956 /* Configure ACL capabilities. */
10957 wdev
->wiphy
->max_acl_mac_addrs
= MAX_NUM_MAC_FILT
;
10960 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
10961 /* Supplicant distinguish between the SoftAP mode and other
10962 * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
10963 * response frame from Supplicant MR1 and Kernel 3.4.0 or
10964 * later version. To add Vendor specific IE into the
10965 * probe response frame in case of SoftAP mode,
10966 * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
10968 if (dhd_get_fw_mode(dhd
->info
) == DHD_FLAG_HOSTAP_MODE
) {
10969 wdev
->wiphy
->flags
|= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD
;
10970 wdev
->wiphy
->probe_resp_offload
= 0;
10973 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
10975 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
10976 wdev
->wiphy
->flags
|= WIPHY_FLAG_SUPPORTS_TDLS
;
10979 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
10981 * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
10982 * disconnection of connected network before suspend. So a dummy wowlan
10983 * filter is configured for kernels linux-3.8 and above.
10986 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10987 wdev
->wiphy
->wowlan
= &brcm_wowlan_support
;
10988 /* If this is not provided cfg stack will get disconnect
10991 brcm_wowlan_config
= kmalloc(sizeof(struct cfg80211_wowlan
), GFP_KERNEL
);
10992 if (brcm_wowlan_config
) {
10993 brcm_wowlan_config
->disconnect
= true;
10994 brcm_wowlan_config
->gtk_rekey_failure
= true;
10995 brcm_wowlan_config
->eap_identity_req
= true;
10996 brcm_wowlan_config
->four_way_handshake
= true;
10997 brcm_wowlan_config
->patterns
= NULL
;
10998 brcm_wowlan_config
->n_patterns
= 0;
10999 brcm_wowlan_config
->tcp
= NULL
;
11000 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
11001 brcm_wowlan_config
->nd_config
= NULL
;
11004 WL_ERR(("Can not allocate memory for brcm_wowlan_config,"
11005 " So wiphy->wowlan_config is set to NULL\n"));
11007 wdev
->wiphy
->wowlan_config
= brcm_wowlan_config
;
11009 wdev
->wiphy
->wowlan
.flags
= WIPHY_WOWLAN_ANY
;
11010 wdev
->wiphy
->wowlan
.n_patterns
= WL_WOWLAN_MAX_PATTERNS
;
11011 wdev
->wiphy
->wowlan
.pattern_min_len
= WL_WOWLAN_MIN_PATTERN_LEN
;
11012 wdev
->wiphy
->wowlan
.pattern_max_len
= WL_WOWLAN_MAX_PATTERN_LEN
;
11013 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
11014 wdev
->wiphy
->wowlan
.max_pkt_offset
= WL_WOWLAN_MAX_PATTERN_LEN
;
11015 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
11016 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
11017 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
11019 WL_DBG(("Registering custom regulatory)\n"));
11020 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
11021 wdev
->wiphy
->regulatory_flags
|= REGULATORY_CUSTOM_REG
;
11023 wdev
->wiphy
->flags
|= WIPHY_FLAG_CUSTOM_REGULATORY
;
11025 wiphy_apply_custom_regulatory(wdev
->wiphy
, &brcm_regdom
);
11027 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
11028 WL_ERR(("Registering Vendor80211\n"));
11029 err
= wl_cfgvendor_attach(wdev
->wiphy
, dhd
);
11030 if (unlikely(err
< 0)) {
11031 WL_ERR(("Couldn not attach vendor commands (%d)\n", err
));
11033 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
11035 /* Now we can register wiphy with cfg80211 module */
11036 err
= wiphy_register(wdev
->wiphy
);
11037 if (unlikely(err
< 0)) {
11038 WL_ERR(("Couldn not register wiphy device (%d)\n", err
));
11039 wiphy_free(wdev
->wiphy
);
11042 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
11043 KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
11044 wdev
->wiphy
->flags
&= ~WIPHY_FLAG_ENFORCE_COMBINATIONS
;
11050 static void wl_free_wdev(struct bcm_cfg80211
*cfg
)
11052 struct wireless_dev
*wdev
= cfg
->wdev
;
11053 struct wiphy
*wiphy
= NULL
;
11055 WL_ERR(("wdev is invalid\n"));
11059 wiphy
= wdev
->wiphy
;
11061 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
11062 wl_cfgvendor_detach(wdev
->wiphy
);
11063 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
11064 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
11065 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
11066 /* Reset wowlan & wowlan_config before Unregister to avoid Kernel Panic */
11067 WL_DBG(("wl_free_wdev Clearing wowlan Config \n"));
11068 wdev
->wiphy
->wowlan
= NULL
;
11069 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
11070 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
11071 wiphy_unregister(wdev
->wiphy
);
11072 wdev
->wiphy
->dev
.parent
= NULL
;
11073 wdev
->wiphy
= NULL
;
11076 wl_delete_all_netinfo(cfg
);
11080 /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
11081 * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
11085 static s32
wl_inform_bss(struct bcm_cfg80211
*cfg
)
11087 struct wl_scan_results
*bss_list
;
11088 struct wl_bss_info
*bi
= NULL
; /* must be initialized */
11091 #if defined(RSSIAVG)
11092 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
11095 #if defined(BSSCACHE)
11096 wl_bss_cache_t
*node
;
11099 bss_list
= cfg
->bss_list
;
11101 /* Free cache in p2p scanning*/
11102 if (p2p_is_on(cfg
) && p2p_scan(cfg
)) {
11103 #if defined(RSSIAVG)
11104 wl_free_rssi_cache(&g_rssi_cache_ctrl
);
11106 #if defined(BSSCACHE)
11107 wl_free_bss_cache(&g_bss_cache_ctrl
);
11111 /* Delete disconnected cache */
11112 #if defined(BSSCACHE)
11113 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl
, (u8
*)&cfg
->disconnected_bssid
);
11114 #if defined(RSSIAVG)
11115 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl
, (u8
*)&cfg
->disconnected_bssid
);
11117 if (cfg
->p2p_disconnected
== 0)
11118 memset(&cfg
->disconnected_bssid
, 0, ETHER_ADDR_LEN
);
11122 #if defined(RSSIAVG)
11123 wl_update_rssi_cache(&g_rssi_cache_ctrl
, bss_list
);
11125 wl_update_connected_rssi_cache(ndev
, &g_rssi_cache_ctrl
, &rssi
);
11127 #if defined(BSSCACHE)
11128 wl_update_bss_cache(&g_bss_cache_ctrl
,
11129 #if defined(RSSIAVG)
11130 &g_rssi_cache_ctrl
,
11135 /* delete dirty cache */
11136 #if defined(RSSIAVG)
11137 wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl
);
11138 wl_reset_rssi_cache(&g_rssi_cache_ctrl
);
11140 #if defined(BSSCACHE)
11141 wl_delete_dirty_bss_cache(&g_bss_cache_ctrl
);
11142 wl_reset_bss_cache(&g_bss_cache_ctrl
);
11145 #if defined(BSSCACHE)
11146 if (cfg
->p2p_disconnected
> 0) {
11147 // terence 20130703: Fix for wrong group_capab (timing issue)
11148 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl
, (u8
*)&cfg
->disconnected_bssid
);
11149 #if defined(RSSIAVG)
11150 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl
, (u8
*)&cfg
->disconnected_bssid
);
11153 WL_SCAN(("scanned AP count (%d)\n", bss_list
->count
));
11154 node
= g_bss_cache_ctrl
.m_cache_head
;
11155 for (i
=0; node
&& i
<WL_AP_MAX
; i
++) {
11156 bi
= node
->results
.bss_info
;
11157 err
= wl_inform_single_bss(cfg
, bi
, false);
11161 WL_SCAN(("scanned AP count (%d)\n", bss_list
->count
));
11163 bi
= next_bss(bss_list
, bi
);
11164 for_each_bss(bss_list
, bi
, i
) {
11165 if (cfg
->p2p_disconnected
> 0 && !memcmp(&bi
->BSSID
, &cfg
->disconnected_bssid
, ETHER_ADDR_LEN
))
11167 err
= wl_inform_single_bss(cfg
, bi
, false);
11172 if (cfg
->p2p_disconnected
> 0) {
11173 // terence 20130703: Fix for wrong group_capab (timing issue)
11174 cfg
->p2p_disconnected
++;
11175 if (cfg
->p2p_disconnected
>= REPEATED_SCAN_RESULT_CNT
+1) {
11176 cfg
->p2p_disconnected
= 0;
11177 memset(&cfg
->disconnected_bssid
, 0, ETHER_ADDR_LEN
);
11184 static s32
wl_inform_single_bss(struct bcm_cfg80211
*cfg
, struct wl_bss_info
*bi
, bool roam
)
11186 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
11187 struct ieee80211_mgmt
*mgmt
;
11188 struct ieee80211_channel
*channel
;
11189 struct ieee80211_supported_band
*band
;
11190 struct wl_cfg80211_bss_info
*notif_bss_info
;
11191 struct wl_scan_req
*sr
= wl_to_sr(cfg
);
11192 struct beacon_proberesp
*beacon_proberesp
;
11193 struct cfg80211_bss
*cbss
= NULL
;
11194 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
11195 log_conn_event_t
*event_data
= NULL
;
11196 tlv_log
*tlv_data
= NULL
;
11197 u32 alloc_len
, tlv_len
;
11205 if (unlikely(dtoh32(bi
->length
) > WL_BSS_INFO_MAX
)) {
11206 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
11209 aflags
= (in_atomic()) ? GFP_ATOMIC
: GFP_KERNEL
;
11210 notif_bss_info
= kzalloc(sizeof(*notif_bss_info
) + sizeof(*mgmt
)
11211 - sizeof(u8
) + WL_BSS_INFO_MAX
, aflags
);
11212 if (unlikely(!notif_bss_info
)) {
11213 WL_ERR(("notif_bss_info alloc failed\n"));
11216 mgmt
= (struct ieee80211_mgmt
*)notif_bss_info
->frame_buf
;
11217 notif_bss_info
->channel
=
11218 wf_chspec_ctlchan(wl_chspec_driver_to_host(bi
->chanspec
));
11220 if (notif_bss_info
->channel
<= CH_MAX_2G_CHANNEL
)
11221 band
= wiphy
->bands
[IEEE80211_BAND_2GHZ
];
11223 band
= wiphy
->bands
[IEEE80211_BAND_5GHZ
];
11225 WL_ERR(("No valid band\n"));
11226 kfree(notif_bss_info
);
11229 notif_bss_info
->rssi
= dtoh16(bi
->RSSI
);
11230 #if defined(RSSIAVG)
11231 notif_bss_info
->rssi
= wl_get_avg_rssi(&g_rssi_cache_ctrl
, &bi
->BSSID
);
11232 if (notif_bss_info
->rssi
== RSSI_MINVAL
)
11233 notif_bss_info
->rssi
= MIN(dtoh16(bi
->RSSI
), RSSI_MAXVAL
);
11235 #if defined(RSSIOFFSET)
11236 notif_bss_info
->rssi
= wl_update_rssi_offset(bcmcfg_to_prmry_ndev(cfg
), notif_bss_info
->rssi
);
11238 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
11239 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
11240 notif_bss_info
->rssi
= MIN(notif_bss_info
->rssi
, RSSI_MAXVAL
);
11242 memcpy(mgmt
->bssid
, &bi
->BSSID
, ETHER_ADDR_LEN
);
11243 mgmt_type
= cfg
->active_scan
?
11244 IEEE80211_STYPE_PROBE_RESP
: IEEE80211_STYPE_BEACON
;
11245 if (!memcmp(bi
->SSID
, sr
->ssid
.SSID
, bi
->SSID_len
)) {
11246 mgmt
->frame_control
= cpu_to_le16(IEEE80211_FTYPE_MGMT
| mgmt_type
);
11248 beacon_proberesp
= cfg
->active_scan
?
11249 (struct beacon_proberesp
*)&mgmt
->u
.probe_resp
:
11250 (struct beacon_proberesp
*)&mgmt
->u
.beacon
;
11251 beacon_proberesp
->timestamp
= 0;
11252 beacon_proberesp
->beacon_int
= cpu_to_le16(bi
->beacon_period
);
11253 beacon_proberesp
->capab_info
= cpu_to_le16(bi
->capability
);
11255 wl_update_hidden_ap_ie(bi
, ((u8
*) bi
) + bi
->ie_offset
, &bi
->ie_length
, roam
);
11256 wl_mrg_ie(cfg
, ((u8
*) bi
) + bi
->ie_offset
, bi
->ie_length
);
11257 wl_cp_ie(cfg
, beacon_proberesp
->variable
, WL_BSS_INFO_MAX
-
11258 offsetof(struct wl_cfg80211_bss_info
, frame_buf
));
11259 notif_bss_info
->frame_len
= offsetof(struct ieee80211_mgmt
,
11260 u
.beacon
.variable
) + wl_get_ielen(cfg
);
11261 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11262 freq
= ieee80211_channel_to_frequency(notif_bss_info
->channel
);
11265 freq
= ieee80211_channel_to_frequency(notif_bss_info
->channel
, band
->band
);
11268 WL_ERR(("Invalid channel, fail to change channel to freq\n"));
11269 kfree(notif_bss_info
);
11272 channel
= ieee80211_get_channel(wiphy
, freq
);
11273 WL_SCAN(("BSSID %pM, channel %2d, rssi %3d, capa 0x04%x, mgmt_type %d, "
11274 "frame_len %d, SSID \"%s\"\n", &bi
->BSSID
, notif_bss_info
->channel
,
11275 notif_bss_info
->rssi
, mgmt
->u
.beacon
.capab_info
, mgmt_type
,
11276 notif_bss_info
->frame_len
, bi
->SSID
));
11277 if (unlikely(!channel
)) {
11278 WL_ERR(("ieee80211_get_channel error, freq=%d, channel=%d\n",
11279 freq
, notif_bss_info
->channel
));
11280 kfree(notif_bss_info
);
11284 signal
= notif_bss_info
->rssi
* 100;
11285 if (!mgmt
->u
.probe_resp
.timestamp
) {
11286 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
11287 struct timespec ts
;
11288 get_monotonic_boottime(&ts
);
11289 mgmt
->u
.probe_resp
.timestamp
= ((u64
)ts
.tv_sec
*1000000)
11290 + ts
.tv_nsec
/ 1000;
11293 do_gettimeofday(&tv
);
11294 mgmt
->u
.probe_resp
.timestamp
= ((u64
)tv
.tv_sec
*1000000)
11300 cbss
= cfg80211_inform_bss_frame(wiphy
, channel
, mgmt
,
11301 le16_to_cpu(notif_bss_info
->frame_len
), signal
, aflags
);
11302 if (unlikely(!cbss
)) {
11303 WL_ERR(("cfg80211_inform_bss_frame error\n"));
11308 CFG80211_PUT_BSS(wiphy
, cbss
);
11310 if (DBG_RING_ACTIVE(dhdp
, DHD_EVENT_RING_ID
) &&
11311 (cfg
->sched_scan_req
&& !cfg
->scan_request
)) {
11312 alloc_len
= sizeof(log_conn_event_t
) + IEEE80211_MAX_SSID_LEN
+ sizeof(uint16
) +
11314 event_data
= MALLOCZ(dhdp
->osh
, alloc_len
);
11316 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
11317 "length(%d)\n", __func__
, alloc_len
));
11320 tlv_len
= 3 * sizeof(tlv_log
);
11321 event_data
->tlvs
= MALLOC(dhdp
->osh
, tlv_len
);
11322 if (!event_data
->tlvs
) {
11323 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
11324 "length(%d)\n", __func__
, tlv_len
));
11328 payload_len
= sizeof(log_conn_event_t
);
11329 event_data
->event
= WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND
;
11330 tlv_data
= event_data
->tlvs
;
11333 tlv_data
->tag
= WIFI_TAG_SSID
;
11334 tlv_data
->len
= bi
->SSID_len
;
11335 memcpy(tlv_data
->value
, bi
->SSID
, bi
->SSID_len
);
11336 payload_len
+= TLV_LOG_SIZE(tlv_data
);
11337 tlv_data
= TLV_LOG_NEXT(tlv_data
);
11340 tlv_data
->tag
= WIFI_TAG_CHANNEL
;
11341 tlv_data
->len
= sizeof(uint16
);
11342 memcpy(tlv_data
->value
, ¬if_bss_info
->channel
, sizeof(uint16
));
11343 payload_len
+= TLV_LOG_SIZE(tlv_data
);
11344 tlv_data
= TLV_LOG_NEXT(tlv_data
);
11347 tlv_data
->tag
= WIFI_TAG_RSSI
;
11348 tlv_data
->len
= sizeof(int16
);
11349 memcpy(tlv_data
->value
, ¬if_bss_info
->rssi
, sizeof(int16
));
11350 payload_len
+= TLV_LOG_SIZE(tlv_data
);
11351 tlv_data
= TLV_LOG_NEXT(tlv_data
);
11353 dhd_os_push_push_ring_data(dhdp
, DHD_EVENT_RING_ID
,
11354 event_data
, payload_len
);
11355 MFREE(dhdp
->osh
, event_data
->tlvs
, tlv_len
);
11356 MFREE(dhdp
->osh
, event_data
, alloc_len
);
11360 kfree(notif_bss_info
);
11364 static bool wl_is_linkup(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
, struct net_device
*ndev
)
11366 u32 event
= ntoh32(e
->event_type
);
11367 u32 status
= ntoh32(e
->status
);
11368 u16 flags
= ntoh16(e
->flags
);
11369 #if defined(CUSTOM_SET_ANTNPM) || defined(CUSTOM_SET_OCLOFF)
11371 dhd
= (dhd_pub_t
*)(cfg
->pub
);
11372 #endif /* CUSTOM_SET_ANTNPM */
11374 WL_DBG(("event %d, status %d flags %x\n", event
, status
, flags
));
11375 if (event
== WLC_E_SET_SSID
) {
11376 if (status
== WLC_E_STATUS_SUCCESS
) {
11377 #ifdef CUSTOM_SET_ANTNPM
11378 if (dhd
->mimo_ant_set
) {
11381 WL_ERR(("[WIFI_SEC] mimo_ant_set = %d\n", dhd
->mimo_ant_set
));
11382 err
= wldev_iovar_setint(ndev
, "txchain", dhd
->mimo_ant_set
);
11384 WL_ERR(("[WIFI_SEC] Fail set txchain\n"));
11386 err
= wldev_iovar_setint(ndev
, "rxchain", dhd
->mimo_ant_set
);
11388 WL_ERR(("[WIFI_SEC] Fail set rxchain\n"));
11391 #endif /* CUSTOM_SET_ANTNPM */
11392 #ifdef CUSTOM_SET_OCLOFF
11393 if (dhd
->ocl_off
) {
11395 int ocl_enable
= 0;
11396 err
= wldev_iovar_setint(ndev
, "ocl_enable", ocl_enable
);
11398 WL_ERR(("[WIFI_SEC] %s: Set ocl_enable %d failed %d\n",
11399 __FUNCTION__
, ocl_enable
, err
));
11401 WL_ERR(("[WIFI_SEC] %s: Set ocl_enable %d succeeded %d\n",
11402 __FUNCTION__
, ocl_enable
, err
));
11405 #endif /* CUSTOM_SET_OCLOFF */
11406 if (!wl_is_ibssmode(cfg
, ndev
))
11409 } else if (event
== WLC_E_LINK
) {
11410 if (flags
& WLC_EVENT_MSG_LINK
)
11414 WL_DBG(("wl_is_linkup false\n"));
11419 static bool wl_is_linkdown(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
, void *data
)
11421 u32 event
= ntoh32(e
->event_type
);
11422 u16 flags
= ntoh16(e
->flags
);
11423 wl_last_event_t
*last_event
= (wl_last_event_t
*)data
;
11424 u32 len
= ntoh32(e
->datalen
);
11426 if (event
== WLC_E_DEAUTH_IND
||
11427 event
== WLC_E_DISASSOC_IND
||
11428 event
== WLC_E_DISASSOC
||
11429 event
== WLC_E_DEAUTH
) {
11430 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event
)));
11432 } else if (event
== WLC_E_LINK
) {
11433 if (!(flags
& WLC_EVENT_MSG_LINK
)) {
11434 if (last_event
&& len
> 0) {
11435 u32 current_time
= last_event
->current_time
;
11436 u32 timestamp
= last_event
->timestamp
;
11437 u32 event_type
= last_event
->event
.event_type
;
11438 u32 status
= last_event
->event
.status
;
11439 u32 reason
= last_event
->event
.reason
;
11441 WL_ERR(("Last roam event before disconnection : current_time %d,"
11442 " time %d, type %d, status %d, reason %d\n",
11443 current_time
, timestamp
, event_type
, status
, reason
));
11445 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event
)));
11453 static bool wl_is_linkdown(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
)
11455 u32 event
= ntoh32(e
->event_type
);
11456 u16 flags
= ntoh16(e
->flags
);
11458 if (event
== WLC_E_DEAUTH_IND
||
11459 event
== WLC_E_DISASSOC_IND
||
11460 event
== WLC_E_DISASSOC
||
11461 event
== WLC_E_DEAUTH
) {
11462 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event
)));
11464 } else if (event
== WLC_E_LINK
) {
11465 if (!(flags
& WLC_EVENT_MSG_LINK
)) {
11466 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event
)));
11473 #endif /* WL_LASTEVT */
11475 static bool wl_is_nonetwork(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
)
11477 u32 event
= ntoh32(e
->event_type
);
11478 u32 status
= ntoh32(e
->status
);
11480 if (event
== WLC_E_LINK
&& status
== WLC_E_STATUS_NO_NETWORKS
)
11482 if (event
== WLC_E_SET_SSID
&& status
!= WLC_E_STATUS_SUCCESS
)
11488 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
11489 * to AP/P2P GO via events. If this change is backported to kernel for which
11490 * this driver is being built, then define WL_CFG80211_STA_EVENT. You
11491 * should use this new/del sta event mechanism for BRCM supplicant >= 22.
11494 wl_notify_connect_status_ap(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
11495 const wl_event_msg_t
*e
, void *data
)
11498 u32 event
= ntoh32(e
->event_type
);
11499 u32 reason
= ntoh32(e
->reason
);
11500 u32 len
= ntoh32(e
->datalen
);
11501 u32 status
= ntoh32(e
->status
);
11503 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
11504 bool isfree
= false;
11506 u8 bsscfgidx
= e
->bsscfgidx
;
11512 struct ieee80211_supported_band
*band
;
11513 struct ether_addr da
;
11514 struct ether_addr bssid
;
11515 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
11518 struct station_info sinfo
;
11521 WL_DBG(("event %d status %d reason %d\n", event
, ntoh32(e
->status
), reason
));
11522 /* if link down, bsscfg is disabled. */
11523 if (event
== WLC_E_LINK
&& reason
== WLC_E_LINK_BSSCFG_DIS
&&
11524 wl_get_p2p_status(cfg
, IF_DELETING
) && (ndev
!= bcmcfg_to_prmry_ndev(cfg
))) {
11525 wl_add_remove_eventmsg(ndev
, WLC_E_PROBREQ_MSG
, false);
11526 WL_INFORM(("AP mode link down !! \n"));
11527 complete(&cfg
->iface_disable
);
11531 if ((event
== WLC_E_LINK
) && (status
== WLC_E_STATUS_SUCCESS
) &&
11532 (reason
== WLC_E_REASON_INITIAL_ASSOC
) &&
11533 (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_AP
)) {
11534 if (!wl_get_drv_status(cfg
, AP_CREATED
, ndev
)) {
11535 /* AP/GO brought up successfull in firmware */
11536 printf("%s: ** AP/GO Link up event **\n", __FUNCTION__
);
11537 wl_set_drv_status(cfg
, AP_CREATED
, ndev
);
11538 wake_up_interruptible(&cfg
->netif_change_event
);
11539 if (!memcmp(ndev
->name
, WL_P2P_INTERFACE_PREFIX
, strlen(WL_P2P_INTERFACE_PREFIX
))) {
11540 dhd_conf_set_mchan_bw(cfg
->pub
, WL_P2P_IF_GO
, -1);
11546 if (event
== WLC_E_DISASSOC_IND
|| event
== WLC_E_DEAUTH_IND
|| event
== WLC_E_DEAUTH
) {
11547 printf("%s: event %s(%d) status %d reason %d\n", __FUNCTION__
,
11548 bcmevent_get_name(event
), event
, ntoh32(e
->status
), reason
);
11551 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
11552 WL_DBG(("Enter \n"));
11553 if (!len
&& (event
== WLC_E_DEAUTH
)) {
11554 len
= 2; /* reason code field */
11558 body
= kzalloc(len
, GFP_KERNEL
);
11560 if (body
== NULL
) {
11561 WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
11565 memset(&bssid
, 0, ETHER_ADDR_LEN
);
11566 WL_DBG(("Enter event %d ndev %p\n", event
, ndev
));
11567 if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_INVALID
) {
11572 memcpy(body
, data
, len
);
11574 wldev_iovar_getbuf_bsscfg(ndev
, "cur_etheraddr",
11575 NULL
, 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, bsscfgidx
, &cfg
->ioctl_buf_sync
);
11576 memcpy(da
.octet
, cfg
->ioctl_buf
, ETHER_ADDR_LEN
);
11577 memset(&bssid
, 0, sizeof(bssid
));
11578 err
= wldev_ioctl_get(ndev
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
);
11580 case WLC_E_ASSOC_IND
:
11583 case WLC_E_REASSOC_IND
:
11584 fc
= FC_REASSOC_REQ
;
11586 case WLC_E_DISASSOC_IND
:
11589 case WLC_E_DEAUTH_IND
:
11599 memset(&ci
, 0, sizeof(ci
));
11600 if ((err
= wldev_ioctl_get(ndev
, WLC_GET_CHANNEL
, &ci
, sizeof(ci
)))) {
11605 channel
= dtoh32(ci
.hw_channel
);
11606 if (channel
<= CH_MAX_2G_CHANNEL
)
11607 band
= wiphy
->bands
[IEEE80211_BAND_2GHZ
];
11609 band
= wiphy
->bands
[IEEE80211_BAND_5GHZ
];
11611 WL_ERR(("No valid band\n"));
11616 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11617 freq
= ieee80211_channel_to_frequency(channel
);
11620 freq
= ieee80211_channel_to_frequency(channel
, band
->band
);
11623 err
= wl_frame_get_mgmt(fc
, &da
, &e
->addr
, &bssid
,
11624 &mgmt_frame
, &len
, body
);
11629 if ((event
== WLC_E_ASSOC_IND
&& reason
== DOT11_SC_SUCCESS
) ||
11630 (event
== WLC_E_DISASSOC_IND
) ||
11631 ((event
== WLC_E_DEAUTH_IND
) || (event
== WLC_E_DEAUTH
))) {
11632 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
11633 cfg80211_rx_mgmt(ndev
, freq
, 0, mgmt_frame
, len
, 0);
11634 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
11635 cfg80211_rx_mgmt(ndev
, freq
, 0, mgmt_frame
, len
, 0, GFP_ATOMIC
);
11636 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
11637 defined(WL_COMPAT_WIRELESS)
11638 cfg80211_rx_mgmt(ndev
, freq
, 0, mgmt_frame
, len
, GFP_ATOMIC
);
11640 cfg80211_rx_mgmt(ndev
, freq
, mgmt_frame
, len
, GFP_ATOMIC
);
11649 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
11651 if (((event
== WLC_E_ASSOC_IND
) || (event
== WLC_E_REASSOC_IND
)) &&
11652 reason
== DOT11_SC_SUCCESS
) {
11653 /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
11654 * STATION_INFO_ASSOC_REQ_IES flag
11656 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
11657 sinfo
.filled
= STA_INFO_BIT(INFO_ASSOC_REQ_IES
);
11658 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
11660 WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
11663 sinfo
.assoc_req_ies
= data
;
11664 sinfo
.assoc_req_ies_len
= len
;
11665 printf("%s: connected device "MACDBG
"\n", __FUNCTION__
, MAC2STRDBG(e
->addr
.octet
));
11666 cfg80211_new_sta(ndev
, e
->addr
.octet
, &sinfo
, GFP_ATOMIC
);
11667 } else if (event
== WLC_E_DISASSOC_IND
) {
11668 printf("%s: disassociated device "MACDBG
"\n", __FUNCTION__
, MAC2STRDBG(e
->addr
.octet
));
11669 cfg80211_del_sta(ndev
, e
->addr
.octet
, GFP_ATOMIC
);
11670 } else if ((event
== WLC_E_DEAUTH_IND
) ||
11671 ((event
== WLC_E_DEAUTH
) && (reason
!= DOT11_RC_RESERVED
))) {
11672 printf("%s: deauthenticated device "MACDBG
"\n", __FUNCTION__
, MAC2STRDBG(e
->addr
.octet
));
11673 cfg80211_del_sta(ndev
, e
->addr
.octet
, GFP_ATOMIC
);
11679 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11680 #define MAX_ASSOC_REJECT_ERR_STATUS 5
11681 int wl_get_connect_failed_status(struct bcm_cfg80211
*cfg
, const wl_event_msg_t
*e
)
11683 u32 status
= ntoh32(e
->status
);
11685 cfg
->assoc_reject_status
= 0;
11687 if (status
== WLC_E_STATUS_FAIL
) {
11688 WL_ERR(("auth assoc status event=%d e->status %d e->reason %d \n",
11689 ntoh32(cfg
->event_auth_assoc
.event_type
),
11690 (int)ntoh32(cfg
->event_auth_assoc
.status
),
11691 (int)ntoh32(cfg
->event_auth_assoc
.reason
)));
11693 switch ((int)ntoh32(cfg
->event_auth_assoc
.status
)) {
11694 case WLC_E_STATUS_NO_ACK
:
11695 cfg
->assoc_reject_status
= 1;
11697 case WLC_E_STATUS_FAIL
:
11698 cfg
->assoc_reject_status
= 2;
11700 case WLC_E_STATUS_UNSOLICITED
:
11701 cfg
->assoc_reject_status
= 3;
11703 case WLC_E_STATUS_TIMEOUT
:
11704 cfg
->assoc_reject_status
= 4;
11706 case WLC_E_STATUS_ABORT
:
11707 cfg
->assoc_reject_status
= 5;
11712 if (cfg
->assoc_reject_status
) {
11713 if (ntoh32(cfg
->event_auth_assoc
.event_type
) == WLC_E_ASSOC
) {
11714 cfg
->assoc_reject_status
+= MAX_ASSOC_REJECT_ERR_STATUS
;
11719 WL_ERR(("assoc_reject_status %d \n", cfg
->assoc_reject_status
));
11724 s32
wl_cfg80211_get_connect_failed_status(struct net_device
*dev
, char* cmd
, int total_len
)
11726 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
11727 int bytes_written
= 0;
11733 memset(cmd
, 0, total_len
);
11734 bytes_written
= snprintf(cmd
, 30, "assoc_reject.status %d", cfg
->assoc_reject_status
);
11736 WL_ERR(("cmd: %s \n", cmd
));
11738 return bytes_written
;
11740 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
11743 wl_get_auth_assoc_status(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
11744 const wl_event_msg_t
*e
)
11746 u32 reason
= ntoh32(e
->reason
);
11747 u32 event
= ntoh32(e
->event_type
);
11748 struct wl_security
*sec
= wl_read_prof(cfg
, ndev
, WL_PROF_SEC
);
11749 WL_DBG(("event type : %d, reason : %d\n", event
, reason
));
11751 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11752 memcpy(&cfg
->event_auth_assoc
, e
, sizeof(wl_event_msg_t
));
11753 WL_ERR(("event=%d status %d reason %d \n",
11754 ntoh32(cfg
->event_auth_assoc
.event_type
),
11755 ntoh32(cfg
->event_auth_assoc
.status
),
11756 ntoh32(cfg
->event_auth_assoc
.reason
)));
11757 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
11762 sec
->auth_assoc_res_status
= reason
;
11767 WL_ERR(("sec is NULL\n"));
11772 wl_notify_connect_status_ibss(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
11773 const wl_event_msg_t
*e
, void *data
)
11776 u32 event
= ntoh32(e
->event_type
);
11777 u16 flags
= ntoh16(e
->flags
);
11778 u32 status
= ntoh32(e
->status
);
11780 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11781 struct ieee80211_channel
*channel
= NULL
;
11782 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
11783 u32 chanspec
, chan
;
11785 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
11787 if (event
== WLC_E_JOIN
) {
11788 WL_DBG(("joined in IBSS network\n"));
11790 if (event
== WLC_E_START
) {
11791 WL_DBG(("started IBSS network\n"));
11793 if (event
== WLC_E_JOIN
|| event
== WLC_E_START
||
11794 (event
== WLC_E_LINK
&& (flags
== WLC_EVENT_MSG_LINK
))) {
11795 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11796 err
= wldev_iovar_getint(ndev
, "chanspec", (s32
*)&chanspec
);
11797 if (unlikely(err
)) {
11798 WL_ERR(("Could not get chanspec %d\n", err
));
11801 chan
= wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec
));
11802 band
= (chan
<= CH_MAX_2G_CHANNEL
) ? IEEE80211_BAND_2GHZ
: IEEE80211_BAND_5GHZ
;
11803 freq
= ieee80211_channel_to_frequency(chan
, band
);
11804 channel
= ieee80211_get_channel(wiphy
, freq
);
11805 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
11806 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
11807 /* ROAM or Redundant */
11808 u8
*cur_bssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
11809 if (memcmp(cur_bssid
, &e
->addr
, ETHER_ADDR_LEN
) == 0) {
11810 WL_DBG(("IBSS connected event from same BSSID("
11811 MACDBG
"), ignore it\n", MAC2STRDBG(cur_bssid
)));
11814 WL_INFORM(("IBSS BSSID is changed from " MACDBG
" to " MACDBG
"\n",
11815 MAC2STRDBG(cur_bssid
), MAC2STRDBG((const u8
*)&e
->addr
)));
11816 wl_get_assoc_ies(cfg
, ndev
);
11817 wl_update_prof(cfg
, ndev
, NULL
, (const void *)&e
->addr
, WL_PROF_BSSID
);
11818 wl_update_bss_info(cfg
, ndev
, false);
11819 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11820 cfg80211_ibss_joined(ndev
, (const s8
*)&e
->addr
, channel
, GFP_KERNEL
);
11822 cfg80211_ibss_joined(ndev
, (const s8
*)&e
->addr
, GFP_KERNEL
);
11826 /* New connection */
11827 WL_INFORM(("IBSS connected to " MACDBG
"\n",
11828 MAC2STRDBG((const u8
*)&e
->addr
)));
11830 wl_get_assoc_ies(cfg
, ndev
);
11831 wl_update_prof(cfg
, ndev
, NULL
, (const void *)&e
->addr
, WL_PROF_BSSID
);
11832 wl_update_bss_info(cfg
, ndev
, false);
11833 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11834 cfg80211_ibss_joined(ndev
, (const s8
*)&e
->addr
, channel
, GFP_KERNEL
);
11836 cfg80211_ibss_joined(ndev
, (const s8
*)&e
->addr
, GFP_KERNEL
);
11838 wl_set_drv_status(cfg
, CONNECTED
, ndev
);
11840 wl_update_prof(cfg
, ndev
, NULL
, (const void *)&active
, WL_PROF_ACT
);
11842 } else if ((event
== WLC_E_LINK
&& !(flags
& WLC_EVENT_MSG_LINK
)) ||
11843 event
== WLC_E_DEAUTH_IND
|| event
== WLC_E_DISASSOC_IND
) {
11844 wl_clr_drv_status(cfg
, CONNECTED
, ndev
);
11846 wl_init_prof(cfg
, ndev
);
11848 else if (event
== WLC_E_SET_SSID
&& status
== WLC_E_STATUS_NO_NETWORKS
) {
11849 WL_DBG(("no action - join fail (IBSS mode)\n"));
11852 WL_DBG(("no action (IBSS mode)\n"));
11857 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11858 #define WiFiALL_OUI "\x50\x6F\x9A" /* Wi-FiAll OUI */
11859 #define WiFiALL_OUI_LEN 3
11860 #define WiFiALL_OUI_TYPE 16
11862 int wl_get_bss_info(struct bcm_cfg80211
*cfg
, struct net_device
*dev
, uint8
*mac
)
11865 struct wl_bss_info
*bi
;
11866 uint8 eabuf
[ETHER_ADDR_LEN
];
11867 u32 rate
, channel
, freq
, supported_rate
, nss
= 0, mcs_map
, mode_80211
= 0;
11871 struct wiphy
*wiphy
;
11872 struct cfg80211_bss
*bss
;
11873 bcm_tlv_t
*interworking_ie
= NULL
;
11874 bcm_tlv_t
*tlv_ie
= NULL
;
11875 bcm_tlv_t
*vht_ie
= NULL
;
11877 int16 ie_11u_rel_num
= -1, ie_mu_mimo_cap
= -1;
11878 u32 i
, remained_len
, count
= 0;
11879 char roam_count_str
[4], akm_str
[4];
11882 /* get BSS information */
11884 strncpy(cfg
->bss_info
, "x x x x x x x x x x x x x", GET_BSS_INFO_LEN
);
11886 memset(cfg
->extra_buf
, 0, WL_EXTRA_BUF_MAX
);
11887 *(u32
*) cfg
->extra_buf
= htod32(WL_EXTRA_BUF_MAX
);
11889 err
= wldev_ioctl_get(dev
, WLC_GET_BSS_INFO
, cfg
->extra_buf
, WL_EXTRA_BUF_MAX
);
11890 if (unlikely(err
)) {
11891 WL_ERR(("Could not get bss info %d\n", err
));
11892 cfg
->roam_count
= 0;
11897 WL_ERR(("mac is null \n"));
11898 cfg
->roam_count
= 0;
11902 memcpy(eabuf
, mac
, ETHER_ADDR_LEN
);
11904 bi
= (struct wl_bss_info
*)(cfg
->extra_buf
+ 4);
11905 channel
= wf_chspec_ctlchan(bi
->chanspec
);
11907 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11908 freq
= ieee80211_channel_to_frequency(channel
);
11910 if (channel
> 14) {
11911 freq
= ieee80211_channel_to_frequency(channel
, IEEE80211_BAND_5GHZ
);
11913 freq
= ieee80211_channel_to_frequency(channel
, IEEE80211_BAND_2GHZ
);
11917 err
= wldev_ioctl_get(dev
, WLC_GET_RATE
, &rate
, sizeof(rate
));
11919 WL_ERR(("Could not get rate (%d)\n", err
));
11920 snprintf(rate_str
, sizeof(rate_str
), "x"); // Unknown
11923 rate
= dtoh32(rate
);
11924 snprintf(rate_str
, sizeof(rate_str
), "%d", (rate
/2));
11927 //supported maximum rate
11928 supported_rate
= (bi
->rateset
.rates
[bi
->rateset
.count
- 1] & 0x7f) / 2;
11930 if (supported_rate
< 12) {
11931 mode_80211
= 0; //11b maximum rate is 11Mbps. 11b mode
11933 //It's not HT Capable case.
11934 if (channel
> 14) {
11935 mode_80211
= 3; // 11a mode
11937 mode_80211
= 1; // 11g mode
11942 /* check Rx MCS Map for HT */
11945 for (i
= 0; i
< MAX_STREAMS_SUPPORTED
; i
++) {
11946 int8 bitmap
= 0xFF;
11947 if (i
== MAX_STREAMS_SUPPORTED
-1) {
11950 if (bi
->basic_mcs
[i
] & bitmap
) {
11959 for (i
= 1; i
<= VHT_CAP_MCS_MAP_NSS_MAX
; i
++) {
11960 mcs_map
= VHT_MCS_MAP_GET_MCS_PER_SS(i
, dtoh16(bi
->vht_rxmcsmap
));
11961 if (mcs_map
!= VHT_CAP_MCS_MAP_NONE
) {
11971 wiphy
= bcmcfg_to_wiphy(cfg
);
11972 bss
= CFG80211_GET_BSS(wiphy
, NULL
, eabuf
, bi
->SSID
, bi
->SSID_len
);
11974 WL_ERR(("Could not find the AP\n"));
11976 #if defined(WL_CFG80211_P2P_DEV_IF)
11977 ie
= (u8
*)bss
->ies
->data
;
11978 ie_len
= bss
->ies
->len
;
11980 ie
= bss
->information_elements
;
11981 ie_len
= bss
->len_information_elements
;
11982 #endif /* WL_CFG80211_P2P_DEV_IF */
11986 ie_mu_mimo_cap
= 0;
11987 ie_11u_rel_num
= 0;
11990 if ((vht_ie
= bcm_parse_tlvs(ie
, (u32
)ie_len
,
11991 DOT11_MNG_VHT_CAP_ID
)) != NULL
) {
11992 ie_mu_mimo_cap
= (vht_ie
->data
[2] & 0x08) >> 3;
11996 if ((interworking_ie
= bcm_parse_tlvs(ie
, (u32
)ie_len
,
11997 DOT11_MNG_INTERWORKING_ID
)) != NULL
) {
11998 if ((tlv_ie
= bcm_parse_tlvs(ie
, (u32
)ie_len
, DOT11_MNG_VS_ID
)) != NULL
) {
11999 remained_len
= ie_len
;
12002 if (count
> MAX_VNDR_IE_NUMBER
)
12005 if (tlv_ie
->id
== DOT11_MNG_VS_ID
) {
12006 vndrie
= (vndr_ie_t
*) tlv_ie
;
12008 if (vndrie
->len
< (VNDR_IE_MIN_LEN
+ 1)) {
12009 WL_ERR(("%s: invalid vndr ie."
12010 "length is too small %d\n",
12011 __FUNCTION__
, vndrie
->len
));
12015 if (!bcmp(vndrie
->oui
,
12016 (u8
*)WiFiALL_OUI
, WiFiALL_OUI_LEN
) &&
12017 (vndrie
->data
[0] == WiFiALL_OUI_TYPE
))
12019 WL_ERR(("Found Wi-FiAll OUI oui.\n"));
12020 ie_11u_rel_num
= vndrie
->data
[1];
12021 ie_11u_rel_num
= (ie_11u_rel_num
& 0xf0)>>4;
12022 ie_11u_rel_num
+= 1;
12028 tlv_ie
= bcm_next_tlv(tlv_ie
, &remained_len
);
12034 for (i
= 0; i
< bi
->SSID_len
; i
++) {
12035 if (bi
->SSID
[i
] == ' ') {
12040 //0 : None, 1 : OKC, 2 : FT, 3 : CCKM
12041 err
= wldev_iovar_getint(dev
, "wpa_auth", &val
);
12042 if (unlikely(err
)) {
12043 WL_ERR(("could not get wpa_auth (%d)\n", err
));
12044 snprintf(akm_str
, sizeof(akm_str
), "x"); // Unknown
12046 WL_ERR(("wpa_auth val %d \n", val
));
12047 #if defined(BCMEXTCCX)
12048 if (val
& (WPA_AUTH_CCKM
| WPA2_AUTH_CCKM
)) {
12049 snprintf(akm_str
, sizeof(akm_str
), "3");
12052 if (val
& WPA2_AUTH_FT
) {
12053 snprintf(akm_str
, sizeof(akm_str
), "2");
12054 } else if (val
& (WPA_AUTH_UNSPECIFIED
| WPA2_AUTH_UNSPECIFIED
)) {
12055 snprintf(akm_str
, sizeof(akm_str
), "1");
12057 snprintf(akm_str
, sizeof(akm_str
), "0");
12061 if (cfg
->roam_offload
) {
12062 snprintf(roam_count_str
, sizeof(roam_count_str
), "x"); // Unknown
12064 snprintf(roam_count_str
, sizeof(roam_count_str
), "%d", cfg
->roam_count
);
12066 cfg
->roam_count
= 0;
12068 WL_ERR(("BSSID:" MACDBG
" SSID %s \n", MAC2STRDBG(eabuf
), bi
->SSID
));
12069 WL_ERR(("freq:%d, BW:%s, RSSI:%d dBm, Rate:%d Mbps, 11mode:%d, stream:%d,"
12070 "MU-MIMO:%d, Passpoint:%d, SNR:%d, Noise:%d, \n"
12071 "akm:%s roam:%s \n",
12072 freq
, wf_chspec_to_bw_str(bi
->chanspec
),
12073 dtoh32(bi
->RSSI
), (rate
/ 2), mode_80211
, nss
,
12074 ie_mu_mimo_cap
, ie_11u_rel_num
, bi
->SNR
, bi
->phy_noise
,
12075 akm_str
, roam_count_str
));
12078 snprintf(cfg
->bss_info
, GET_BSS_INFO_LEN
,
12079 "%02x:%02x:%02x %d %s %d %s %d %d %d %d %d %d %s %s",
12080 eabuf
[0], eabuf
[1], eabuf
[2],
12081 freq
, wf_chspec_to_bw_str(bi
->chanspec
),
12082 dtoh32(bi
->RSSI
), rate_str
, mode_80211
, nss
,
12083 ie_mu_mimo_cap
, ie_11u_rel_num
,
12084 bi
->SNR
, bi
->phy_noise
, akm_str
, roam_count_str
);
12086 //ie_mu_mimo_cap and ie_11u_rel_num is unknow.
12087 snprintf(cfg
->bss_info
, GET_BSS_INFO_LEN
,
12088 "%02x:%02x:%02x %d %s %d %s %d %d x x %d %d %s %s",
12089 eabuf
[0], eabuf
[1], eabuf
[2],
12090 freq
, wf_chspec_to_bw_str(bi
->chanspec
),
12091 dtoh32(bi
->RSSI
), rate_str
, mode_80211
, nss
,
12092 bi
->SNR
, bi
->phy_noise
, akm_str
, roam_count_str
);
12095 CFG80211_PUT_BSS(wiphy
, bss
);
12100 s32
wl_cfg80211_get_bss_info(struct net_device
*dev
, char* cmd
, int total_len
)
12102 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
12108 memset(cmd
, 0, total_len
);
12109 memcpy(cmd
, cfg
->bss_info
, GET_BSS_INFO_LEN
);
12111 WL_ERR(("cmd: %s \n", cmd
));
12113 return GET_BSS_INFO_LEN
;
12116 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12119 wl_notify_connect_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12120 const wl_event_msg_t
*e
, void *data
)
12123 struct net_device
*ndev
= NULL
;
12125 u32 event
= ntoh32(e
->event_type
);
12126 struct wiphy
*wiphy
= NULL
;
12127 struct cfg80211_bss
*bss
= NULL
;
12128 struct wlc_ssid
*ssid
= NULL
;
12131 int vndr_oui_num
= 0;
12132 char vndr_oui
[MAX_VNDR_OUI_STR_LEN
] = {0, };
12134 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12135 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
12136 BCM_REFERENCE(dhdp
);
12138 if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_AP
) {
12139 err
= wl_notify_connect_status_ap(cfg
, ndev
, e
, data
);
12140 } else if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_IBSS
) {
12141 err
= wl_notify_connect_status_ibss(cfg
, ndev
, e
, data
);
12142 } else if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_BSS
) {
12143 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
12144 ntoh32(e
->event_type
), ntoh32(e
->status
), ndev
));
12145 if (event
== WLC_E_ASSOC
|| event
== WLC_E_AUTH
) {
12146 wl_get_auth_assoc_status(cfg
, ndev
, e
);
12149 DHD_DISABLE_RUNTIME_PM((dhd_pub_t
*)cfg
->pub
);
12150 if (wl_is_linkup(cfg
, e
, ndev
)) {
12153 if (!wl_get_drv_status(cfg
, DISCONNECTING
, ndev
)) {
12154 if (event
== WLC_E_LINK
&&
12155 #ifdef DHD_LOSSLESS_ROAMING
12156 !cfg
->roam_offload
&&
12157 #endif /* DHD_LOSSLESS_ROAMING */
12158 wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
12159 wl_bss_roaming_done(cfg
, ndev
, e
, data
);
12162 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
12163 vndr_oui_num
= wl_vndr_ies_get_vendor_oui(cfg
,
12164 ndev
, vndr_oui
, ARRAYSIZE(vndr_oui
));
12165 #if defined(STAT_REPORT)
12166 /* notify STA connection only */
12167 wl_stat_report_notify_connected(cfg
);
12168 #endif /* STAT_REPORT */
12171 printf("wl_bss_connect_done succeeded with "
12172 MACDBG
" %s%s\n", MAC2STRDBG((const u8
*)(&e
->addr
)),
12173 vndr_oui_num
> 0 ? "vndr_oui: " : "",
12174 vndr_oui_num
> 0 ? vndr_oui
: "");
12176 wl_bss_connect_done(cfg
, ndev
, e
, data
, true);
12177 dhd_conf_set_intiovar(cfg
->pub
, WLC_SET_VAR
, "phy_oclscdenable", cfg
->pub
->conf
->phy_oclscdenable
, 0, FALSE
);
12178 WL_DBG(("joined in BSS network \"%s\"\n",
12179 ((struct wlc_ssid
*)
12180 wl_read_prof(cfg
, ndev
, WL_PROF_SSID
))->SSID
));
12183 if (ndev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_STATION
&&
12184 dhdp
->wbtext_support
&&
12185 event
== WLC_E_SET_SSID
) {
12186 /* set wnm_keepalives_max_idle after association */
12187 wl_cfg80211_wbtext_set_wnm_maxidle(cfg
, ndev
);
12188 /* send nbr request or BTM query to update RCC */
12189 wl_cfg80211_wbtext_update_rcc(cfg
, ndev
);
12191 #endif /* WBTEXT */
12193 wl_update_prof(cfg
, ndev
, e
, &act
, WL_PROF_ACT
);
12194 wl_update_prof(cfg
, ndev
, NULL
, (const void *)&e
->addr
, WL_PROF_BSSID
);
12195 dhd_conf_set_wme(cfg
->pub
, 0);
12196 if (!memcmp(ndev
->name
, WL_P2P_INTERFACE_PREFIX
, strlen(WL_P2P_INTERFACE_PREFIX
))) {
12197 dhd_conf_set_mchan_bw(cfg
->pub
, WL_P2P_IF_CLIENT
, -1);
12199 } else if (WL_IS_LINKDOWN(cfg
, e
, data
) ||
12200 ((event
== WLC_E_SET_SSID
) &&
12201 (ntoh32(e
->status
) != WLC_E_STATUS_SUCCESS
) &&
12202 (wl_get_drv_status(cfg
, CONNECTED
, ndev
)))) {
12204 WL_INFORM(("connection state bit status: [%d:%d:%d:%d]\n",
12205 wl_get_drv_status(cfg
, CONNECTING
, ndev
),
12206 wl_get_drv_status(cfg
, CONNECTED
, ndev
),
12207 wl_get_drv_status(cfg
, DISCONNECTING
, ndev
),
12208 wl_get_drv_status(cfg
, NESTED_CONNECT
, ndev
)));
12210 if (wl_get_drv_status(cfg
, DISCONNECTING
, ndev
) &&
12211 (wl_get_drv_status(cfg
, NESTED_CONNECT
, ndev
) ||
12212 wl_get_drv_status(cfg
, CONNECTING
, ndev
))) {
12213 /* wl_cfg80211_connect was called before 'DISCONNECTING' was
12214 * cleared. Deauth/Link down event is caused by WLC_DISASSOC
12215 * command issued from the wl_cfg80211_connect context. Ignore
12216 * the event to avoid pre-empting the current connection
12218 WL_INFORM(("Nested connection case. Drop event. \n"));
12219 wl_clr_drv_status(cfg
, NESTED_CONNECT
, ndev
);
12220 wl_clr_drv_status(cfg
, DISCONNECTING
, ndev
);
12221 /* Not in 'CONNECTED' state, clear it */
12222 wl_clr_drv_status(cfg
, CONNECTED
, ndev
);
12226 #ifdef DHD_LOSSLESS_ROAMING
12227 wl_del_roam_timeout(cfg
);
12229 #ifdef P2PLISTEN_AP_SAMECHN
12230 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
12231 wl_cfg80211_set_p2p_resp_ap_chn(ndev
, 0);
12232 cfg
->p2p_resp_apchn_status
= false;
12233 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
12235 #endif /* P2PLISTEN_AP_SAMECHN */
12236 wl_cfg80211_cancel_scan(cfg
);
12238 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
12239 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
12240 wl_get_bss_info(cfg
, ndev
, (u8
*)(&e
->addr
));
12242 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12243 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
12244 u8
*curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
12245 if (memcmp(curbssid
, &e
->addr
, ETHER_ADDR_LEN
) != 0) {
12246 bool fw_assoc_state
= TRUE
;
12247 dhd_pub_t
*dhd
= (dhd_pub_t
*)cfg
->pub
;
12248 fw_assoc_state
= dhd_is_associated(dhd
, e
->ifidx
, &err
);
12249 if (!fw_assoc_state
) {
12250 WL_ERR(("Event sends up even different BSSID"
12251 " cur: " MACDBG
" event: " MACDBG
"\n",
12252 MAC2STRDBG(curbssid
),
12253 MAC2STRDBG((const u8
*)(&e
->addr
))));
12255 WL_ERR(("BSSID of event is not the connected BSSID"
12256 "(ignore it) cur: " MACDBG
12257 " event: " MACDBG
"\n",
12258 MAC2STRDBG(curbssid
),
12259 MAC2STRDBG((const u8
*)(&e
->addr
))));
12264 /* Explicitly calling unlink to remove BSS in CFG */
12265 wiphy
= bcmcfg_to_wiphy(cfg
);
12266 ssid
= (struct wlc_ssid
*)wl_read_prof(cfg
, ndev
, WL_PROF_SSID
);
12267 bssid
= (u8
*)wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
12268 if (ssid
&& bssid
) {
12269 bss
= CFG80211_GET_BSS(wiphy
, NULL
, bssid
,
12270 ssid
->SSID
, ssid
->SSID_len
);
12272 cfg80211_unlink_bss(wiphy
, bss
);
12273 CFG80211_PUT_BSS(wiphy
, bss
);
12277 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
12279 u8
*curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
12281 struct ether_addr bssid_dongle
= {{0, 0, 0, 0, 0, 0}};
12282 struct ether_addr bssid_null
= {{0, 0, 0, 0, 0, 0}};
12284 if (event
== WLC_E_DEAUTH_IND
|| event
== WLC_E_DISASSOC_IND
)
12285 reason
= ntoh32(e
->reason
);
12286 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
12287 reason
= (reason
== WLAN_REASON_UNSPECIFIED
)? 0 : reason
;
12289 printf("link down if %s may call cfg80211_disconnected. "
12290 "event : %d, reason=%d from " MACDBG
"\n",
12291 ndev
->name
, event
, ntoh32(e
->reason
),
12292 MAC2STRDBG((const u8
*)(&e
->addr
)));
12294 /* roam offload does not sync BSSID always, get it from dongle */
12295 if (cfg
->roam_offload
) {
12296 memset(&bssid_dongle
, 0, sizeof(bssid_dongle
));
12297 if (wldev_ioctl_get(ndev
, WLC_GET_BSSID
, &bssid_dongle
,
12298 sizeof(bssid_dongle
)) == BCME_OK
) {
12299 /* if not roam case, it would return null bssid */
12300 if (memcmp(&bssid_dongle
, &bssid_null
,
12301 ETHER_ADDR_LEN
) != 0) {
12302 curbssid
= (u8
*)&bssid_dongle
;
12306 if (memcmp(curbssid
, &e
->addr
, ETHER_ADDR_LEN
) != 0) {
12307 bool fw_assoc_state
= TRUE
;
12308 dhd_pub_t
*dhd
= (dhd_pub_t
*)cfg
->pub
;
12309 fw_assoc_state
= dhd_is_associated(dhd
, e
->ifidx
, &err
);
12310 if (!fw_assoc_state
) {
12311 WL_ERR(("Event sends up even different BSSID"
12312 " cur: " MACDBG
" event: " MACDBG
"\n",
12313 MAC2STRDBG(curbssid
),
12314 MAC2STRDBG((const u8
*)(&e
->addr
))));
12316 WL_ERR(("BSSID of event is not the connected BSSID"
12317 "(ignore it) cur: " MACDBG
12318 " event: " MACDBG
"\n",
12319 MAC2STRDBG(curbssid
),
12320 MAC2STRDBG((const u8
*)(&e
->addr
))));
12326 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
12327 DHD_DBG_PKT_MON_STOP(dhdp
);
12329 #endif /* DBG_PKT_MON */
12331 /* clear RSSI monitor, framework will set new cfg */
12332 #ifdef RSSI_MONITOR_SUPPORT
12333 dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg
),
12335 #endif /* RSSI_MONITOR_SUPPORT */
12336 if (!memcmp(ndev
->name
, WL_P2P_INTERFACE_PREFIX
, strlen(WL_P2P_INTERFACE_PREFIX
))) {
12337 // terence 20130703: Fix for wrong group_capab (timing issue)
12338 cfg
->p2p_disconnected
= 1;
12340 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
12341 if (wl_get_drv_status(cfg
, DISCONNECTING
, ndev
)) {
12342 CFG80211_DISCONNECTED(ndev
, reason
, NULL
, 0, false, GFP_KERNEL
);
12345 memcpy(&cfg
->disconnected_bssid
, curbssid
, ETHER_ADDR_LEN
);
12346 wl_clr_drv_status(cfg
, CONNECTED
, ndev
);
12348 if (!wl_get_drv_status(cfg
, DISCONNECTING
, ndev
)) {
12349 /* To make sure disconnect, explictly send dissassoc
12350 * for BSSID 00:00:00:00:00:00 issue
12352 scbval
.val
= WLAN_REASON_DEAUTH_LEAVING
;
12354 memcpy(&scbval
.ea
, curbssid
, ETHER_ADDR_LEN
);
12355 scbval
.val
= htod32(scbval
.val
);
12356 err
= wldev_ioctl_set(ndev
, WLC_DISASSOC
, &scbval
,
12357 sizeof(scb_val_t
));
12359 WL_ERR(("WLC_DISASSOC error %d\n", err
));
12364 /* Send up deauth and clear states */
12365 CFG80211_DISCONNECTED(ndev
, reason
, NULL
, 0,
12366 false, GFP_KERNEL
);
12368 wl_init_prof(cfg
, ndev
);
12370 /* when STA was disconnected, clear join pref and set wbtext */
12371 if (ndev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_STATION
) {
12372 char smbuf
[WLC_IOCTL_SMLEN
];
12373 char clear
[] = { 0x01, 0x02, 0x00, 0x00, 0x03,
12374 0x02, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00 };
12375 if ((err
= wldev_iovar_setbuf(ndev
, "join_pref",
12376 clear
, sizeof(clear
), smbuf
,
12377 sizeof(smbuf
), NULL
))
12379 if ((err
= wldev_iovar_setint(ndev
,
12380 "wnm_bsstrans_resp",
12381 WL_BSSTRANS_POLICY_PRODUCT_WBTEXT
))
12383 wl_cfg80211_wbtext_set_default(ndev
);
12385 WL_ERR(("%s: Failed to set wbtext = %d\n",
12386 __FUNCTION__
, err
));
12389 WL_ERR(("%s: Failed to clear join pref = %d\n",
12390 __FUNCTION__
, err
));
12392 wl_cfg80211_wbtext_clear_bssid_list(cfg
);
12394 #endif /* WBTEXT */
12395 wl_vndr_ies_clear_vendor_oui_list(cfg
);
12397 else if (wl_get_drv_status(cfg
, CONNECTING
, ndev
)) {
12398 printf("link down, during connecting\n");
12399 /* Issue WLC_DISASSOC to prevent FW roam attempts */
12400 err
= wldev_ioctl_set(ndev
, WLC_DISASSOC
, NULL
, 0);
12402 WL_ERR(("CONNECTING state, WLC_DISASSOC error %d\n", err
));
12405 WL_INFORM(("Clear drv CONNECTING status\n"));
12406 wl_clr_drv_status(cfg
, CONNECTING
, ndev
);
12407 #ifdef ESCAN_RESULT_PATCH
12408 if ((memcmp(connect_req_bssid
, broad_bssid
, ETHER_ADDR_LEN
) == 0) ||
12409 (memcmp(&e
->addr
, broad_bssid
, ETHER_ADDR_LEN
) == 0) ||
12410 (memcmp(&e
->addr
, connect_req_bssid
, ETHER_ADDR_LEN
) == 0))
12411 /* In case this event comes while associating another AP */
12412 #endif /* ESCAN_RESULT_PATCH */
12413 wl_bss_connect_done(cfg
, ndev
, e
, data
, false);
12415 wl_clr_drv_status(cfg
, DISCONNECTING
, ndev
);
12417 /* if link down, bsscfg is diabled */
12418 if (ndev
!= bcmcfg_to_prmry_ndev(cfg
))
12419 complete(&cfg
->iface_disable
);
12421 /* re-enable TDLS if the number of connected interfaces
12424 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_DISCONNECT
, false);
12425 #endif /* WLTDLS */
12426 } else if (wl_is_nonetwork(cfg
, e
)) {
12427 printf("connect failed event=%d e->status %d e->reason %d \n",
12428 event
, (int)ntoh32(e
->status
), (int)ntoh32(e
->reason
));
12429 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
12430 if (event
== WLC_E_SET_SSID
) {
12431 wl_get_connect_failed_status(cfg
, e
);
12433 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12435 if (wl_get_drv_status(cfg
, DISCONNECTING
, ndev
) &&
12436 wl_get_drv_status(cfg
, CONNECTING
, ndev
)) {
12437 wl_clr_drv_status(cfg
, DISCONNECTING
, ndev
);
12438 wl_clr_drv_status(cfg
, CONNECTING
, ndev
);
12439 wl_cfg80211_scan_abort(cfg
);
12440 DHD_ENABLE_RUNTIME_PM((dhd_pub_t
*)cfg
->pub
);
12443 /* Clean up any pending scan request */
12444 wl_cfg80211_cancel_scan(cfg
);
12446 if (wl_get_drv_status(cfg
, CONNECTING
, ndev
))
12447 wl_bss_connect_done(cfg
, ndev
, e
, data
, false);
12449 WL_DBG(("%s nothing\n", __FUNCTION__
));
12451 DHD_ENABLE_RUNTIME_PM((dhd_pub_t
*)cfg
->pub
);
12454 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg
, ndev
)));
12460 void wl_cfg80211_set_rmc_pid(struct net_device
*dev
, int pid
)
12462 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
12464 cfg
->rmc_event_pid
= pid
;
12465 WL_DBG(("set pid for rmc event : pid=%d\n", pid
));
12467 #endif /* WL_RELMCAST */
12471 wl_notify_rmc_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12472 const wl_event_msg_t
*e
, void *data
)
12474 u32 evt
= ntoh32(e
->event_type
);
12475 u32 reason
= ntoh32(e
->reason
);
12479 case WLC_E_REASON_RMC_AR_LOST
:
12480 case WLC_E_REASON_RMC_AR_NO_ACK
:
12481 if (cfg
->rmc_event_pid
!= 0) {
12482 ret
= wl_netlink_send_msg(cfg
->rmc_event_pid
,
12483 RMC_EVENT_LEADER_CHECK_FAIL
,
12484 cfg
->rmc_event_seq
++, NULL
, 0);
12490 WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt
, cfg
->rmc_event_pid
, ret
));
12493 #endif /* WL_RELMCAST */
12495 #ifdef GSCAN_SUPPORT
12497 wl_handle_roam_exp_event(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12498 const wl_event_msg_t
*e
, void *data
)
12500 struct net_device
*ndev
= NULL
;
12501 u32 datalen
= be32_to_cpu(e
->datalen
);
12504 wl_roam_exp_event_t
*evt_data
= (wl_roam_exp_event_t
*)data
;
12505 if (evt_data
->version
== ROAM_EXP_EVENT_VERSION
) {
12506 wlc_ssid_t
*ssid
= &evt_data
->cur_ssid
;
12507 struct wireless_dev
*wdev
;
12508 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12510 wdev
= ndev
->ieee80211_ptr
;
12511 wdev
->ssid_len
= min(ssid
->SSID_len
, (uint32
)DOT11_MAX_SSID_LEN
);
12512 memcpy(wdev
->ssid
, ssid
->SSID
, wdev
->ssid_len
);
12513 WL_ERR(("SSID is %s\n", ssid
->SSID
));
12514 wl_update_prof(cfg
, ndev
, NULL
, ssid
, WL_PROF_SSID
);
12516 WL_ERR(("NULL ndev!\n"));
12519 WL_ERR(("Version mismatch %d, expected %d", evt_data
->version
,
12520 ROAM_EXP_EVENT_VERSION
));
12525 #endif /* GSCAN_SUPPORT */
12527 #ifdef RSSI_MONITOR_SUPPORT
12528 static s32
wl_handle_rssi_monitor_event(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12529 const wl_event_msg_t
*e
, void *data
)
12532 #if defined(WL_VENDOR_EXT_SUPPORT) || defined(CONFIG_BCMDHD_VENDOR_EXT)
12533 u32 datalen
= be32_to_cpu(e
->datalen
);
12534 struct net_device
*ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12535 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
12538 wl_rssi_monitor_evt_t
*evt_data
= (wl_rssi_monitor_evt_t
*)data
;
12539 if (evt_data
->version
== RSSI_MONITOR_VERSION
) {
12540 dhd_rssi_monitor_evt_t monitor_data
;
12541 monitor_data
.version
= DHD_RSSI_MONITOR_EVT_VERSION
;
12542 monitor_data
.cur_rssi
= evt_data
->cur_rssi
;
12543 memcpy(&monitor_data
.BSSID
, &e
->addr
, ETHER_ADDR_LEN
);
12544 wl_cfgvendor_send_async_event(wiphy
, ndev
,
12545 GOOGLE_RSSI_MONITOR_EVENT
,
12546 &monitor_data
, sizeof(monitor_data
));
12548 WL_ERR(("Version mismatch %d, expected %d", evt_data
->version
,
12549 RSSI_MONITOR_VERSION
));
12552 #endif /* WL_VENDOR_EXT_SUPPORT || CONFIG_BCMDHD_VENDOR_EXT */
12555 #endif /* RSSI_MONITOR_SUPPORT */
12558 wl_notify_roaming_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12559 const wl_event_msg_t
*e
, void *data
)
12562 struct net_device
*ndev
= NULL
;
12564 u32 event
= be32_to_cpu(e
->event_type
);
12565 u32 status
= be32_to_cpu(e
->status
);
12566 #ifdef DHD_LOSSLESS_ROAMING
12567 struct wl_security
*sec
;
12569 WL_DBG(("Enter \n"));
12571 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12573 if ((!cfg
->disable_roam_event
) && (event
== WLC_E_BSSID
)) {
12574 wl_add_remove_eventmsg(ndev
, WLC_E_ROAM
, false);
12575 cfg
->disable_roam_event
= TRUE
;
12578 if ((cfg
->disable_roam_event
) && (event
== WLC_E_ROAM
))
12581 if ((event
== WLC_E_ROAM
|| event
== WLC_E_BSSID
) && status
== WLC_E_STATUS_SUCCESS
) {
12582 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
12583 #ifdef DHD_LOSSLESS_ROAMING
12584 sec
= wl_read_prof(cfg
, ndev
, WL_PROF_SEC
);
12585 /* In order to reduce roaming delay, wl_bss_roaming_done is
12586 * early called with WLC_E_LINK event. It is called from
12587 * here only if WLC_E_LINK event is blocked for specific
12590 if (IS_AKM_SUITE_FT(sec
)) {
12591 wl_bss_roaming_done(cfg
, ndev
, e
, data
);
12593 /* Roam timer is deleted mostly from wl_cfg80211_change_station
12594 * after roaming is finished successfully. We need to delete
12595 * the timer from here only for some security types that aren't
12596 * using wl_cfg80211_change_station to authorize SCB
12598 if (IS_AKM_SUITE_FT(sec
) || IS_AKM_SUITE_CCKM(sec
)) {
12599 wl_del_roam_timeout(cfg
);
12602 wl_bss_roaming_done(cfg
, ndev
, e
, data
);
12603 #endif /* DHD_LOSSLESS_ROAMING */
12605 wl_bss_connect_done(cfg
, ndev
, e
, data
, true);
12608 wl_update_prof(cfg
, ndev
, e
, &act
, WL_PROF_ACT
);
12609 wl_update_prof(cfg
, ndev
, NULL
, (const void *)&e
->addr
, WL_PROF_BSSID
);
12611 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
12612 wl_vndr_ies_get_vendor_oui(cfg
, ndev
, NULL
, 0);
12615 #ifdef DHD_LOSSLESS_ROAMING
12616 else if ((event
== WLC_E_ROAM
|| event
== WLC_E_BSSID
) && status
!= WLC_E_STATUS_SUCCESS
) {
12617 wl_del_roam_timeout(cfg
);
12623 #ifdef CUSTOM_EVENT_PM_WAKE
12624 uint32 last_dpm_upd_time
= 0; /* ms */
12625 #define DPM_UPD_LMT_TIME 25000 /* ms */
12626 #define DPM_UPD_LMT_RSSI -85 /* dbm */
12629 wl_check_pmstatus(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12630 const wl_event_msg_t
*e
, void *data
)
12633 struct net_device
*ndev
= NULL
;
12635 uint32 cur_dpm_upd_time
= 0;
12636 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
12640 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12642 pbuf
= kzalloc(WLC_IOCTL_MEDLEN
, GFP_KERNEL
);
12643 if (pbuf
== NULL
) {
12644 WL_ERR(("failed to allocate local pbuf\n"));
12648 err
= wldev_iovar_getbuf_bsscfg(ndev
, "dump",
12649 "pm", strlen("pm"), pbuf
, WLC_IOCTL_MEDLEN
, 0, &cfg
->ioctl_buf_sync
);
12652 WL_ERR(("dump ioctl err = %d", err
));
12654 WL_ERR(("PM status : %s\n", pbuf
));
12661 if (dhd
->early_suspended
) {
12663 memset(&scb_val
, 0, sizeof(scb_val_t
));
12665 err
= wldev_ioctl_get(ndev
, WLC_GET_RSSI
, &scb_val
, sizeof(scb_val_t
));
12667 WL_ERR(("Could not get rssi (%d)\n", err
));
12669 rssi
= wl_rssi_offset(dtoh32(scb_val
.val
));
12670 WL_ERR(("[%s] RSSI %d dBm\n", ndev
->name
, rssi
));
12671 if (rssi
> DPM_UPD_LMT_RSSI
) {
12679 if (last_dpm_upd_time
== 0) {
12680 last_dpm_upd_time
= OSL_SYSUPTIME();
12682 cur_dpm_upd_time
= OSL_SYSUPTIME();
12683 if (cur_dpm_upd_time
- last_dpm_upd_time
< DPM_UPD_LMT_TIME
) {
12685 bzero(&scbval
, sizeof(scb_val_t
));
12687 err
= wldev_ioctl_set(ndev
, WLC_DISASSOC
, &scbval
, sizeof(scb_val_t
));
12689 WL_ERR(("%s: Disassoc error %d\n", __FUNCTION__
, err
));
12692 WL_ERR(("%s: Force Disassoc due to updated DPM event.\n", __FUNCTION__
));
12694 last_dpm_upd_time
= 0;
12696 last_dpm_upd_time
= cur_dpm_upd_time
;
12702 #endif /* CUSTOM_EVENT_PM_WAKE */
12705 /* get user priority table */
12707 wl_get_up_table(dhd_pub_t
* dhdp
, int idx
)
12709 struct net_device
*ndev
;
12710 struct bcm_cfg80211
*cfg
;
12712 ndev
= dhd_idx2net(dhdp
, idx
);
12714 cfg
= wl_get_cfg(ndev
);
12716 return (uint8
*)(cfg
->up_table
);
12721 #endif /* QOS_MAP_SET */
12723 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
12725 wl_notify_roam_prep_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12726 const wl_event_msg_t
*e
, void *data
)
12728 struct wl_security
*sec
;
12729 struct net_device
*ndev
;
12730 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
12731 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
12732 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
12733 u32 status
= ntoh32(e
->status
);
12734 u32 reason
= ntoh32(e
->reason
);
12736 BCM_REFERENCE(sec
);
12738 if (status
== WLC_E_STATUS_SUCCESS
&& reason
!= WLC_E_REASON_INITIAL_ASSOC
) {
12739 WL_ERR(("Attempting roam with reason code : %d\n", reason
));
12742 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
12745 if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
12746 DHD_DBG_PKT_MON_STOP(dhdp
);
12747 DHD_DBG_PKT_MON_START(dhdp
);
12749 #endif /* DBG_PKT_MON */
12751 #ifdef DHD_LOSSLESS_ROAMING
12752 sec
= wl_read_prof(cfg
, ndev
, WL_PROF_SEC
);
12753 /* Disable Lossless Roaming for specific AKM suite
12754 * Any other AKM suite can be added below if transition time
12755 * is delayed because of Lossless Roaming
12756 * and it causes any certication failure
12758 if (IS_AKM_SUITE_FT(sec
)) {
12761 dhdp
->dequeue_prec_map
= 1 << PRIO_8021D_NC
;
12762 /* Restore flow control */
12763 dhd_txflowcontrol(dhdp
, ALL_INTERFACES
, OFF
);
12765 mod_timer(&cfg
->roam_timeout
, jiffies
+ msecs_to_jiffies(WL_ROAM_TIMEOUT_MS
));
12766 #endif /* DHD_LOSSLESS_ROAMING */
12770 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
12771 #ifdef ENABLE_TEMP_THROTTLING
12773 wl_check_rx_throttle_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
12774 const wl_event_msg_t
*e
, void *data
)
12777 u32 status
= ntoh32(e
->status
);
12778 u32 reason
= ntoh32(e
->reason
);
12780 WL_ERR_EX(("RX THROTTLE : status=%d, reason=0x%x\n", status
, reason
));
12784 #endif /* ENABLE_TEMP_THROTTLING */
12786 static s32
wl_get_assoc_ies(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
)
12788 wl_assoc_info_t assoc_info
;
12789 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
12792 bcm_tlv_t
* qos_map_ie
= NULL
;
12793 #endif /* QOS_MAP_SET */
12795 WL_DBG(("Enter \n"));
12796 err
= wldev_iovar_getbuf(ndev
, "assoc_info", NULL
, 0, cfg
->extra_buf
,
12797 WL_ASSOC_INFO_MAX
, NULL
);
12798 if (unlikely(err
)) {
12799 WL_ERR(("could not get assoc info (%d)\n", err
));
12802 memcpy(&assoc_info
, cfg
->extra_buf
, sizeof(wl_assoc_info_t
));
12803 assoc_info
.req_len
= htod32(assoc_info
.req_len
);
12804 assoc_info
.resp_len
= htod32(assoc_info
.resp_len
);
12805 assoc_info
.flags
= htod32(assoc_info
.flags
);
12806 if (conn_info
->req_ie_len
) {
12807 conn_info
->req_ie_len
= 0;
12808 bzero(conn_info
->req_ie
, sizeof(conn_info
->req_ie
));
12810 if (conn_info
->resp_ie_len
) {
12811 conn_info
->resp_ie_len
= 0;
12812 bzero(conn_info
->resp_ie
, sizeof(conn_info
->resp_ie
));
12814 if (assoc_info
.req_len
) {
12815 err
= wldev_iovar_getbuf(ndev
, "assoc_req_ies", NULL
, 0, cfg
->extra_buf
,
12816 WL_ASSOC_INFO_MAX
, NULL
);
12817 if (unlikely(err
)) {
12818 WL_ERR(("could not get assoc req (%d)\n", err
));
12821 conn_info
->req_ie_len
= assoc_info
.req_len
- sizeof(struct dot11_assoc_req
);
12822 if (assoc_info
.flags
& WLC_ASSOC_REQ_IS_REASSOC
) {
12823 conn_info
->req_ie_len
-= ETHER_ADDR_LEN
;
12825 if (conn_info
->req_ie_len
<= MAX_REQ_LINE
)
12826 memcpy(conn_info
->req_ie
, cfg
->extra_buf
, conn_info
->req_ie_len
);
12828 WL_ERR(("IE size %d above max %d size \n",
12829 conn_info
->req_ie_len
, MAX_REQ_LINE
));
12833 conn_info
->req_ie_len
= 0;
12835 if (assoc_info
.resp_len
) {
12836 err
= wldev_iovar_getbuf(ndev
, "assoc_resp_ies", NULL
, 0, cfg
->extra_buf
,
12837 WL_ASSOC_INFO_MAX
, NULL
);
12838 if (unlikely(err
)) {
12839 WL_ERR(("could not get assoc resp (%d)\n", err
));
12842 conn_info
->resp_ie_len
= assoc_info
.resp_len
-sizeof(struct dot11_assoc_resp
);
12843 if (conn_info
->resp_ie_len
<= MAX_REQ_LINE
) {
12844 memcpy(conn_info
->resp_ie
, cfg
->extra_buf
, conn_info
->resp_ie_len
);
12846 WL_ERR(("IE size %d above max %d size \n",
12847 conn_info
->resp_ie_len
, MAX_REQ_LINE
));
12852 /* find qos map set ie */
12853 if ((qos_map_ie
= bcm_parse_tlvs(conn_info
->resp_ie
, conn_info
->resp_ie_len
,
12854 DOT11_MNG_QOS_MAP_ID
)) != NULL
) {
12855 WL_DBG((" QoS map set IE found in assoc response\n"));
12856 if (!cfg
->up_table
) {
12857 cfg
->up_table
= kmalloc(UP_TABLE_MAX
, GFP_KERNEL
);
12859 wl_set_up_table(cfg
->up_table
, qos_map_ie
);
12861 kfree(cfg
->up_table
);
12862 cfg
->up_table
= NULL
;
12864 #endif /* QOS_MAP_SET */
12866 conn_info
->resp_ie_len
= 0;
12868 WL_DBG(("req len (%d) resp len (%d)\n", conn_info
->req_ie_len
,
12869 conn_info
->resp_ie_len
));
12874 static s32
wl_ch_to_chanspec(struct net_device
*dev
, int ch
, struct wl_join_params
*join_params
,
12875 size_t *join_params_size
)
12878 chanspec_t chanspec
= 0, chspec
;
12881 struct bcm_cfg80211
*cfg
=
12882 (struct bcm_cfg80211
*)wiphy_priv(dev
->ieee80211_ptr
->wiphy
);
12883 join_params
->params
.chanspec_num
= 1;
12884 join_params
->params
.chanspec_list
[0] = ch
;
12886 if (join_params
->params
.chanspec_list
[0] <= CH_MAX_2G_CHANNEL
)
12887 chanspec
|= WL_CHANSPEC_BAND_2G
;
12889 chanspec
|= WL_CHANSPEC_BAND_5G
;
12891 /* Get the min_bw set for the interface */
12892 chspec
= wl_cfg80211_ulb_get_min_bw_chspec(cfg
, dev
->ieee80211_ptr
, bssidx
);
12893 if (chspec
== INVCHANSPEC
) {
12894 WL_ERR(("Invalid chanspec \n"));
12897 chanspec
|= chspec
;
12898 chanspec
|= WL_CHANSPEC_CTL_SB_NONE
;
12900 *join_params_size
+= WL_ASSOC_PARAMS_FIXED_SIZE
+
12901 join_params
->params
.chanspec_num
* sizeof(chanspec_t
);
12903 join_params
->params
.chanspec_list
[0] &= WL_CHANSPEC_CHAN_MASK
;
12904 join_params
->params
.chanspec_list
[0] |= chanspec
;
12905 join_params
->params
.chanspec_list
[0] =
12906 wl_chspec_host_to_driver(join_params
->params
.chanspec_list
[0]);
12908 join_params
->params
.chanspec_num
=
12909 htod32(join_params
->params
.chanspec_num
);
12911 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
12912 join_params
->params
.chanspec_list
[0],
12913 join_params
->params
.chanspec_num
));
12918 static s32
wl_update_bss_info(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, bool roam
)
12920 struct cfg80211_bss
*bss
;
12921 struct wl_bss_info
*bi
;
12922 struct wlc_ssid
*ssid
;
12923 struct bcm_tlv
*tim
;
12924 s32 beacon_interval
;
12930 struct wiphy
*wiphy
;
12935 wiphy
= bcmcfg_to_wiphy(cfg
);
12937 ssid
= (struct wlc_ssid
*)wl_read_prof(cfg
, ndev
, WL_PROF_SSID
);
12938 curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
12939 bss
= CFG80211_GET_BSS(wiphy
, NULL
, curbssid
,
12940 ssid
->SSID
, ssid
->SSID_len
);
12941 buf
= kzalloc(WL_EXTRA_BUF_MAX
, GFP_ATOMIC
);
12943 WL_ERR(("buffer alloc failed.\n"));
12946 mutex_lock(&cfg
->usr_sync
);
12947 *(u32
*)buf
= htod32(WL_EXTRA_BUF_MAX
);
12948 err
= wldev_ioctl_get(ndev
, WLC_GET_BSS_INFO
, buf
, WL_EXTRA_BUF_MAX
);
12949 if (unlikely(err
)) {
12950 WL_ERR(("Could not get bss info %d\n", err
));
12951 goto update_bss_info_out
;
12953 bi
= (struct wl_bss_info
*)(buf
+ 4);
12954 channel
= wf_chspec_ctlchan(wl_chspec_driver_to_host(bi
->chanspec
));
12955 wl_update_prof(cfg
, ndev
, NULL
, &channel
, WL_PROF_CHAN
);
12958 WL_DBG(("Could not find the AP\n"));
12959 if (memcmp(bi
->BSSID
.octet
, curbssid
, ETHER_ADDR_LEN
)) {
12960 WL_ERR(("Bssid doesn't match\n"));
12962 goto update_bss_info_out
;
12964 err
= wl_inform_single_bss(cfg
, bi
, roam
);
12966 goto update_bss_info_out
;
12968 ie
= ((u8
*)bi
) + bi
->ie_offset
;
12969 ie_len
= bi
->ie_length
;
12970 beacon_interval
= cpu_to_le16(bi
->beacon_period
);
12972 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss
->bssid
));
12973 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
12974 freq
= ieee80211_channel_to_frequency(channel
);
12976 band
= (channel
<= CH_MAX_2G_CHANNEL
) ? IEEE80211_BAND_2GHZ
: IEEE80211_BAND_5GHZ
;
12977 freq
= ieee80211_channel_to_frequency(channel
, band
);
12979 bss
->channel
= ieee80211_get_channel(wiphy
, freq
);
12980 #if defined(WL_CFG80211_P2P_DEV_IF)
12981 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
12982 #pragma GCC diagnostic push
12983 #pragma GCC diagnostic ignored "-Wcast-qual"
12985 ie
= (u8
*)bss
->ies
->data
;
12986 ie_len
= bss
->ies
->len
;
12987 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
12988 #pragma GCC diagnostic pop
12991 ie
= bss
->information_elements
;
12992 ie_len
= bss
->len_information_elements
;
12993 #endif /* WL_CFG80211_P2P_DEV_IF */
12994 beacon_interval
= bss
->beacon_interval
;
12996 CFG80211_PUT_BSS(wiphy
, bss
);
12999 tim
= bcm_parse_tlvs(ie
, ie_len
, WLAN_EID_TIM
);
13001 dtim_period
= tim
->data
[1];
13004 * active scan was done so we could not get dtim
13005 * information out of probe response.
13006 * so we speficially query dtim information.
13009 err
= wldev_ioctl_get(ndev
, WLC_GET_DTIMPRD
,
13010 &dtim_period
, sizeof(dtim_period
));
13011 if (unlikely(err
)) {
13012 WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err
));
13013 goto update_bss_info_out
;
13017 wl_update_prof(cfg
, ndev
, NULL
, &beacon_interval
, WL_PROF_BEACONINT
);
13018 wl_update_prof(cfg
, ndev
, NULL
, &dtim_period
, WL_PROF_DTIMPERIOD
);
13020 update_bss_info_out
:
13021 if (unlikely(err
)) {
13022 WL_ERR(("Failed with error %d\n", err
));
13026 mutex_unlock(&cfg
->usr_sync
);
13031 wl_bss_roaming_done(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
13032 const wl_event_msg_t
*e
, void *data
)
13034 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
13038 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13039 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
13040 struct ieee80211_supported_band
*band
;
13041 struct ieee80211_channel
*notify_channel
= NULL
;
13043 #ifdef BCM4359_CHIP
13044 struct channel_info ci
;
13046 #endif /* BCM4359_CHIP */
13048 #if defined(WLADPS_SEAK_AP_WAR) || defined(WBTEXT)
13049 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
13050 #endif /* WLADPS_SEAK_AP_WAR || WBTEXT */
13051 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13052 struct cfg80211_roam_info roam_info
= {};
13053 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13055 #ifdef WLADPS_SEAK_AP_WAR
13056 BCM_REFERENCE(dhdp
);
13057 #endif /* WLADPS_SEAK_AP_WAR */
13059 curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
13060 channel
= (u32
*)wl_read_prof(cfg
, ndev
, WL_PROF_CHAN
);
13061 #ifdef BCM4359_CHIP
13062 /* Skip calling cfg80211_roamed If the channels are same and
13063 * the current bssid/last_roamed_bssid & the new bssid are same
13064 * Also clear timer roam_timeout.
13065 * Only used on BCM4359 devices.
13067 memset(&ci
, 0, sizeof(ci
));
13068 if ((wldev_ioctl_get(ndev
, WLC_GET_CHANNEL
, &ci
,
13069 sizeof(ci
))) < 0) {
13070 WL_ERR(("Failed to get current channel !"));
13073 cur_channel
= dtoh32(ci
.hw_channel
);
13074 if ((*channel
== cur_channel
) && ((memcmp(curbssid
, &e
->addr
,
13075 ETHER_ADDR_LEN
) == 0) || (memcmp(&cfg
->last_roamed_addr
,
13076 &e
->addr
, ETHER_ADDR_LEN
) == 0))) {
13077 WL_ERR(("BSS already present, Skipping roamed event to"
13078 " upper layer\n"));
13079 #ifdef DHD_LOSSLESS_ROAMING
13080 wl_del_roam_timeout(cfg
);
13081 #endif /* DHD_LOSSLESS_ROAMING */
13084 #endif /* BCM4359_CHIP */
13086 wl_get_assoc_ies(cfg
, ndev
);
13087 wl_update_prof(cfg
, ndev
, NULL
, (const void *)(e
->addr
.octet
), WL_PROF_BSSID
);
13088 curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
13089 wl_update_bss_info(cfg
, ndev
, true);
13090 wl_update_pmklist(ndev
, cfg
->pmk_list
, err
);
13092 channel
= (u32
*)wl_read_prof(cfg
, ndev
, WL_PROF_CHAN
);
13093 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13094 /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
13095 if (*channel
<= CH_MAX_2G_CHANNEL
)
13096 band
= wiphy
->bands
[IEEE80211_BAND_2GHZ
];
13098 band
= wiphy
->bands
[IEEE80211_BAND_5GHZ
];
13099 freq
= ieee80211_channel_to_frequency(*channel
, band
->band
);
13100 notify_channel
= ieee80211_get_channel(wiphy
, freq
);
13102 #ifdef WLADPS_SEAK_AP_WAR
13103 if ((dhdp
->op_mode
& DHD_FLAG_STA_MODE
) &&
13104 (!dhdp
->disabled_adps
)) {
13107 if (!memcmp(curbssid
, (u8
*)CAMEO_MAC_PREFIX
, MAC_PREFIX_LEN
)) {
13108 find
= wl_find_vndr_ies_specific_vender(cfg
, ndev
, ATHEROS_OUI
);
13110 enable_mode
= (find
== TRUE
) ? OFF
: ON
;
13111 wl_set_adps_mode(cfg
, ndev
, enable_mode
);
13113 #endif /* WLADPS_SEAK_AP_WAR */
13114 printf("%s succeeded to " MACDBG
" (ch:%d)\n", __FUNCTION__
,
13115 MAC2STRDBG((const u8
*)(&e
->addr
)), *channel
);
13116 dhd_conf_set_wme(cfg
->pub
, 0);
13118 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13119 roam_info
.channel
= notify_channel
;
13120 roam_info
.bssid
= curbssid
;
13121 roam_info
.req_ie
= conn_info
->req_ie
;
13122 roam_info
.req_ie_len
= conn_info
->req_ie_len
;
13123 roam_info
.resp_ie
= conn_info
->resp_ie
;
13124 roam_info
.resp_ie_len
= conn_info
->resp_ie_len
;
13125 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13127 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13128 cfg80211_roamed(ndev
, &roam_info
, GFP_KERNEL
);
13130 cfg80211_roamed(ndev
,
13131 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13135 conn_info
->req_ie
, conn_info
->req_ie_len
,
13136 conn_info
->resp_ie
, conn_info
->resp_ie_len
, GFP_KERNEL
);
13137 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13138 WL_DBG(("Report roaming result\n"));
13140 memcpy(&cfg
->last_roamed_addr
, &e
->addr
, ETHER_ADDR_LEN
);
13141 wl_set_drv_status(cfg
, CONNECTED
, ndev
);
13143 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
13145 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
13148 if (dhdp
->wbtext_support
) {
13149 /* set wnm_keepalives_max_idle after association */
13150 wl_cfg80211_wbtext_set_wnm_maxidle(cfg
, ndev
);
13151 /* send nbr request or BTM query to update RCC */
13152 wl_cfg80211_wbtext_update_rcc(cfg
, ndev
);
13154 #endif /* WBTEXT */
13160 wl_cfg80211_verify_bss(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
)
13162 struct cfg80211_bss
*bss
;
13163 struct wiphy
*wiphy
;
13164 struct wlc_ssid
*ssid
;
13169 wiphy
= bcmcfg_to_wiphy(cfg
);
13170 ssid
= (struct wlc_ssid
*)wl_read_prof(cfg
, ndev
, WL_PROF_SSID
);
13171 curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
13173 WL_ERR(("No SSID found in the saved profile \n"));
13178 bss
= CFG80211_GET_BSS(wiphy
, NULL
, curbssid
,
13179 ssid
->SSID
, ssid
->SSID_len
);
13180 if (bss
|| (count
> 5)) {
13186 } while (bss
== NULL
);
13188 WL_DBG(("cfg80211 bss_ptr:%p loop_cnt:%d\n", bss
, count
));
13190 /* Update the reference count after use */
13191 CFG80211_PUT_BSS(wiphy
, bss
);
13199 wl_bss_connect_done(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
13200 const wl_event_msg_t
*e
, void *data
, bool completed
)
13202 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
13203 struct wl_security
*sec
= wl_read_prof(cfg
, ndev
, WL_PROF_SEC
);
13205 u8
*curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
13208 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
13209 BCM_REFERENCE(dhdp
);
13212 WL_ERR(("sec is NULL\n"));
13215 WL_DBG((" enter\n"));
13216 #ifdef ESCAN_RESULT_PATCH
13217 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) {
13218 if (memcmp(curbssid
, connect_req_bssid
, ETHER_ADDR_LEN
) == 0) {
13219 WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
13220 ntoh32(e
->event_type
), ntoh32(e
->status
)));
13224 if (memcmp(curbssid
, broad_bssid
, ETHER_ADDR_LEN
) == 0 &&
13225 memcmp(broad_bssid
, connect_req_bssid
, ETHER_ADDR_LEN
) != 0) {
13226 WL_DBG(("copy bssid\n"));
13227 memcpy(curbssid
, connect_req_bssid
, ETHER_ADDR_LEN
);
13231 if (cfg
->scan_request
) {
13232 wl_notify_escan_complete(cfg
, ndev
, true, true);
13234 #endif /* ESCAN_RESULT_PATCH */
13235 if (wl_get_drv_status(cfg
, CONNECTING
, ndev
)) {
13236 wl_cfg80211_scan_abort(cfg
);
13237 wl_clr_drv_status(cfg
, CONNECTING
, ndev
);
13239 wl_get_assoc_ies(cfg
, ndev
);
13240 wl_update_prof(cfg
, ndev
, NULL
, (const void *)(e
->addr
.octet
),
13242 curbssid
= wl_read_prof(cfg
, ndev
, WL_PROF_BSSID
);
13243 wl_update_bss_info(cfg
, ndev
, false);
13244 wl_update_pmklist(ndev
, cfg
->pmk_list
, err
);
13245 wl_set_drv_status(cfg
, CONNECTED
, ndev
);
13246 #ifdef WLADPS_SEAK_AP_WAR
13247 if ((dhdp
->op_mode
& DHD_FLAG_STA_MODE
) &&
13248 (!dhdp
->disabled_adps
)) {
13251 if (!memcmp(curbssid
, (u8
*)CAMEO_MAC_PREFIX
, MAC_PREFIX_LEN
)) {
13252 find
= wl_find_vndr_ies_specific_vender(cfg
,
13253 ndev
, ATHEROS_OUI
);
13255 enable_mode
= (find
== TRUE
) ? OFF
: ON
;
13256 wl_set_adps_mode(cfg
, ndev
, enable_mode
);
13258 #endif /* WLADPS_SEAK_AP_WAR */
13259 if (ndev
!= bcmcfg_to_prmry_ndev(cfg
)) {
13260 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
13261 init_completion(&cfg
->iface_disable
);
13263 /* reinitialize completion to clear previous count */
13264 INIT_COMPLETION(cfg
->iface_disable
);
13267 #ifdef CUSTOM_SET_CPUCORE
13268 if (wl_get_chan_isvht80(ndev
, dhdp
)) {
13269 if (ndev
== bcmcfg_to_prmry_ndev(cfg
))
13270 dhdp
->chan_isvht80
|= DHD_FLAG_STA_MODE
; /* STA mode */
13271 else if (is_p2p_group_iface(ndev
->ieee80211_ptr
))
13272 dhdp
->chan_isvht80
|= DHD_FLAG_P2P_MODE
; /* p2p mode */
13273 dhd_set_cpucore(dhdp
, TRUE
);
13275 #endif /* CUSTOM_SET_CPUCORE */
13276 memset(&cfg
->last_roamed_addr
, 0, ETHER_ADDR_LEN
);
13279 if (completed
&& (wl_cfg80211_verify_bss(cfg
, ndev
) != true)) {
13280 /* If bss entry is not available in the cfg80211 bss cache
13281 * the wireless stack will complain and won't populate
13282 * wdev->current_bss ptr
13284 WL_ERR(("BSS entry not found. Indicate assoc event failure\n"));
13286 sec
->auth_assoc_res_status
= WLAN_STATUS_UNSPECIFIED_FAILURE
;
13288 cfg80211_connect_result(ndev
,
13291 conn_info
->req_ie_len
,
13292 conn_info
->resp_ie
,
13293 conn_info
->resp_ie_len
,
13294 completed
? WLAN_STATUS_SUCCESS
:
13295 (sec
->auth_assoc_res_status
) ?
13296 sec
->auth_assoc_res_status
:
13297 WLAN_STATUS_UNSPECIFIED_FAILURE
,
13300 WL_INFORM(("Report connect result - connection succeeded\n"));
13301 dhd_conf_set_wme(cfg
->pub
, 0);
13303 WL_ERR(("Report connect result - connection failed\n"));
13305 #ifdef CONFIG_TCPACK_FASTTX
13306 if (wl_get_chan_isvht80(ndev
, dhdp
))
13307 wldev_iovar_setint(ndev
, "tcpack_fast_tx", 0);
13309 wldev_iovar_setint(ndev
, "tcpack_fast_tx", 1);
13310 #endif /* CONFIG_TCPACK_FASTTX */
13316 wl_notify_mic_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13317 const wl_event_msg_t
*e
, void *data
)
13319 struct net_device
*ndev
= NULL
;
13320 u16 flags
= ntoh16(e
->flags
);
13321 enum nl80211_key_type key_type
;
13323 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13325 mutex_lock(&cfg
->usr_sync
);
13326 if (flags
& WLC_EVENT_MSG_GROUP
)
13327 key_type
= NL80211_KEYTYPE_GROUP
;
13329 key_type
= NL80211_KEYTYPE_PAIRWISE
;
13331 cfg80211_michael_mic_failure(ndev
, (const u8
*)&e
->addr
, key_type
, -1,
13333 mutex_unlock(&cfg
->usr_sync
);
13338 #ifdef BT_WIFI_HANDOVER
13340 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13341 const wl_event_msg_t
*e
, void *data
)
13343 struct net_device
*ndev
= NULL
;
13344 u32 event
= ntoh32(e
->event_type
);
13345 u32 datalen
= ntoh32(e
->datalen
);
13348 WL_ERR(("wl_notify_bt_wifi_handover_req: event_type : %d, datalen : %d\n", event
, datalen
));
13349 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13350 err
= wl_genl_send_msg(ndev
, event
, data
, (u16
)datalen
, 0, 0);
13354 #endif /* BT_WIFI_HANDOVER */
13358 wl_notify_pfn_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13359 const wl_event_msg_t
*e
, void *data
)
13361 struct net_device
*ndev
= NULL
;
13362 #ifdef GSCAN_SUPPORT
13364 int send_evt_bytes
= 0;
13365 u32 event
= be32_to_cpu(e
->event_type
);
13366 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
13367 #endif /* GSCAN_SUPPORT */
13369 WL_ERR((">>> PNO Event\n"));
13371 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13372 #ifdef GSCAN_SUPPORT
13373 ptr
= dhd_dev_process_epno_result(ndev
, data
, event
, &send_evt_bytes
);
13375 wl_cfgvendor_send_async_event(wiphy
, ndev
,
13376 GOOGLE_SCAN_EPNO_EVENT
, ptr
, send_evt_bytes
);
13379 if (!dhd_dev_is_legacy_pno_enabled(ndev
))
13381 #endif /* GSCAN_SUPPORT */
13384 #ifndef WL_SCHED_SCAN
13385 mutex_lock(&cfg
->usr_sync
);
13386 /* TODO: Use cfg80211_sched_scan_results(wiphy); */
13387 CFG80211_DISCONNECTED(ndev
, 0, NULL
, 0, false, GFP_KERNEL
);
13388 mutex_unlock(&cfg
->usr_sync
);
13390 /* If cfg80211 scheduled scan is supported, report the pno results via sched
13393 wl_notify_sched_scan_results(cfg
, ndev
, e
, data
);
13394 #endif /* WL_SCHED_SCAN */
13397 #endif /* PNO_SUPPORT */
13399 #ifdef GSCAN_SUPPORT
13401 wl_notify_gscan_event(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13402 const wl_event_msg_t
*e
, void *data
)
13405 u32 event
= be32_to_cpu(e
->event_type
);
13407 int send_evt_bytes
= 0;
13409 struct net_device
*ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13410 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
13411 u32 len
= ntoh32(e
->datalen
);
13414 case WLC_E_PFN_BEST_BATCHING
:
13415 err
= dhd_dev_retrieve_batch_scan(ndev
);
13417 WL_ERR(("Batch retrieval already in progress %d\n", err
));
13419 event_type
= WIFI_SCAN_THRESHOLD_NUM_SCANS
;
13421 event_type
= *((int *)data
);
13423 wl_cfgvendor_send_async_event(wiphy
, ndev
,
13424 GOOGLE_GSCAN_BATCH_SCAN_EVENT
,
13425 &event_type
, sizeof(int));
13428 case WLC_E_PFN_SCAN_COMPLETE
:
13429 event_type
= WIFI_SCAN_COMPLETE
;
13430 wl_cfgvendor_send_async_event(wiphy
, ndev
,
13431 GOOGLE_SCAN_COMPLETE_EVENT
,
13432 &event_type
, sizeof(int));
13434 case WLC_E_PFN_BSSID_NET_FOUND
:
13435 ptr
= dhd_dev_hotlist_scan_event(ndev
, data
, &send_evt_bytes
,
13438 wl_cfgvendor_send_hotlist_event(wiphy
, ndev
,
13439 ptr
, send_evt_bytes
, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT
);
13440 dhd_dev_gscan_hotlist_cache_cleanup(ndev
, HOTLIST_FOUND
);
13445 case WLC_E_PFN_BSSID_NET_LOST
:
13446 /* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
13447 * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
13450 ptr
= dhd_dev_hotlist_scan_event(ndev
, data
, &send_evt_bytes
,
13453 wl_cfgvendor_send_hotlist_event(wiphy
, ndev
,
13454 ptr
, send_evt_bytes
, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT
);
13455 dhd_dev_gscan_hotlist_cache_cleanup(ndev
, HOTLIST_LOST
);
13463 case WLC_E_PFN_GSCAN_FULL_RESULT
:
13464 ptr
= dhd_dev_process_full_gscan_result(ndev
, data
, len
, &send_evt_bytes
);
13466 wl_cfgvendor_send_async_event(wiphy
, ndev
,
13467 GOOGLE_SCAN_FULL_RESULTS_EVENT
, ptr
, send_evt_bytes
);
13473 case WLC_E_PFN_SSID_EXT
:
13474 ptr
= dhd_dev_process_epno_result(ndev
, data
, event
, &send_evt_bytes
);
13476 wl_cfgvendor_send_async_event(wiphy
, ndev
,
13477 GOOGLE_SCAN_EPNO_EVENT
, ptr
, send_evt_bytes
);
13484 WL_ERR(("Unknown event %d\n", event
));
13489 #endif /* GSCAN_SUPPORT */
13492 wl_notify_scan_status(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13493 const wl_event_msg_t
*e
, void *data
)
13495 struct channel_info channel_inform
;
13496 struct wl_scan_results
*bss_list
;
13497 struct net_device
*ndev
= NULL
;
13498 u32 len
= WL_SCAN_BUF_MAX
;
13500 unsigned long flags
;
13501 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
13502 struct cfg80211_scan_info info
;
13505 WL_DBG(("Enter \n"));
13506 if (!wl_get_drv_status(cfg
, SCANNING
, ndev
)) {
13507 WL_ERR(("scan is not ready \n"));
13510 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13512 mutex_lock(&cfg
->usr_sync
);
13513 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
13514 memset(&channel_inform
, 0, sizeof(channel_inform
));
13515 err
= wldev_ioctl_get(ndev
, WLC_GET_CHANNEL
, &channel_inform
,
13516 sizeof(channel_inform
));
13517 if (unlikely(err
)) {
13518 WL_ERR(("scan busy (%d)\n", err
));
13519 goto scan_done_out
;
13521 channel_inform
.scan_channel
= dtoh32(channel_inform
.scan_channel
);
13522 if (unlikely(channel_inform
.scan_channel
)) {
13524 WL_DBG(("channel_inform.scan_channel (%d)\n",
13525 channel_inform
.scan_channel
));
13527 cfg
->bss_list
= cfg
->scan_results
;
13528 bss_list
= cfg
->bss_list
;
13529 memset(bss_list
, 0, len
);
13530 bss_list
->buflen
= htod32(len
);
13531 err
= wldev_ioctl_get(ndev
, WLC_SCAN_RESULTS
, bss_list
, len
);
13532 if (unlikely(err
) && unlikely(!cfg
->scan_suppressed
)) {
13533 WL_ERR(("%s Scan_results error (%d)\n", ndev
->name
, err
));
13535 goto scan_done_out
;
13537 bss_list
->buflen
= dtoh32(bss_list
->buflen
);
13538 bss_list
->version
= dtoh32(bss_list
->version
);
13539 bss_list
->count
= dtoh32(bss_list
->count
);
13541 err
= wl_inform_bss(cfg
);
13544 del_timer_sync(&cfg
->scan_timeout
);
13545 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
13546 if (cfg
->scan_request
) {
13547 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
13548 info
.aborted
= false;
13549 cfg80211_scan_done(cfg
->scan_request
, &info
);
13551 cfg80211_scan_done(cfg
->scan_request
, false);
13553 cfg
->scan_request
= NULL
;
13555 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
13556 WL_DBG(("cfg80211_scan_done\n"));
13557 mutex_unlock(&cfg
->usr_sync
);
13562 wl_frame_get_mgmt(u16 fc
, const struct ether_addr
*da
,
13563 const struct ether_addr
*sa
, const struct ether_addr
*bssid
,
13564 u8
**pheader
, u32
*body_len
, u8
*pbody
)
13566 struct dot11_management_header
*hdr
;
13570 u32 prebody_len
= *body_len
;
13573 /* capability , listen interval */
13574 totlen
= DOT11_ASSOC_REQ_FIXED_LEN
;
13575 *body_len
+= DOT11_ASSOC_REQ_FIXED_LEN
;
13578 case FC_REASSOC_REQ
:
13579 /* capability, listen inteval, ap address */
13580 totlen
= DOT11_REASSOC_REQ_FIXED_LEN
;
13581 *body_len
+= DOT11_REASSOC_REQ_FIXED_LEN
;
13584 totlen
+= DOT11_MGMT_HDR_LEN
+ prebody_len
;
13585 *pheader
= kzalloc(totlen
, GFP_KERNEL
);
13586 if (*pheader
== NULL
) {
13587 WL_ERR(("memory alloc failed \n"));
13590 hdr
= (struct dot11_management_header
*) (*pheader
);
13591 hdr
->fc
= htol16(fc
);
13594 offset
= (u8
*)(hdr
+ 1) + (totlen
- DOT11_MGMT_HDR_LEN
- prebody_len
);
13595 bcopy((const char*)da
, (u8
*)&hdr
->da
, ETHER_ADDR_LEN
);
13596 bcopy((const char*)sa
, (u8
*)&hdr
->sa
, ETHER_ADDR_LEN
);
13597 bcopy((const char*)bssid
, (u8
*)&hdr
->bssid
, ETHER_ADDR_LEN
);
13598 if ((pbody
!= NULL
) && prebody_len
)
13599 bcopy((const char*)pbody
, offset
, prebody_len
);
13600 *body_len
= totlen
;
13606 wl_stop_wait_next_action_frame(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, u8 bsscfgidx
)
13610 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
)) {
13611 if (timer_pending(&cfg
->p2p
->listen_timer
)) {
13612 del_timer_sync(&cfg
->p2p
->listen_timer
);
13614 if (cfg
->afx_hdl
!= NULL
) {
13615 if (cfg
->afx_hdl
->dev
!= NULL
) {
13616 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
13617 wl_clr_drv_status(cfg
, FINDING_COMMON_CHANNEL
, cfg
->afx_hdl
->dev
);
13619 cfg
->afx_hdl
->peer_chan
= WL_INVALID
;
13621 complete(&cfg
->act_frm_scan
);
13622 WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
13623 } else if (wl_get_drv_status_all(cfg
, SENDING_ACT_FRM
)) {
13624 if (!(wl_get_p2p_status(cfg
, ACTION_TX_COMPLETED
) ||
13625 wl_get_p2p_status(cfg
, ACTION_TX_NOACK
)))
13626 wl_set_p2p_status(cfg
, ACTION_TX_COMPLETED
);
13628 WL_DBG(("*** Wake UP ** abort actframe iovar on bsscfxidx %d\n", bsscfgidx
));
13629 /* if channel is not zero, "actfame" uses off channel scan.
13630 * So abort scan for off channel completion.
13632 if (cfg
->af_sent_channel
) {
13633 /* Scan engine is not used for sending action frames in the latest driver
13634 * branches. So, actframe_abort is used in the latest driver branches
13635 * instead of scan abort.
13636 * New driver branches:
13637 * Issue actframe_abort and it succeeded. So, don't execute scan abort.
13638 * Old driver branches:
13639 * Issue actframe_abort and it fails. So, execute scan abort.
13641 err
= wldev_iovar_setint_bsscfg(ndev
, "actframe_abort", 1, bsscfgidx
);
13643 wl_cfg80211_scan_abort(cfg
);
13647 #ifdef WL_CFG80211_SYNC_GON
13648 else if (wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM_LISTEN
)) {
13649 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
13650 /* So abort scan to cancel listen */
13651 wl_cfg80211_scan_abort(cfg
);
13653 #endif /* WL_CFG80211_SYNC_GON */
13656 #if defined(WLTDLS)
13657 bool wl_cfg80211_is_tdls_tunneled_frame(void *frame
, u32 frame_len
)
13659 unsigned char *data
;
13661 if (frame
== NULL
) {
13662 WL_ERR(("Invalid frame \n"));
13666 if (frame_len
< 5) {
13667 WL_ERR(("Invalid frame length [%d] \n", frame_len
));
13673 if (!memcmp(data
, TDLS_TUNNELED_PRB_REQ
, 5) ||
13674 !memcmp(data
, TDLS_TUNNELED_PRB_RESP
, 5)) {
13675 WL_DBG(("TDLS Vendor Specific Received type\n"));
13681 #endif /* WLTDLS */
13684 int wl_cfg80211_get_ioctl_version(void)
13686 return ioctl_version
;
13690 wl_notify_rx_mgmt_frame(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
13691 const wl_event_msg_t
*e
, void *data
)
13693 struct ieee80211_supported_band
*band
;
13694 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
13695 struct ether_addr da
;
13696 struct ether_addr bssid
;
13697 bool isfree
= false;
13700 #if defined(TDLS_MSG_ONLY_WFD)
13701 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
13702 #endif /* TDLS_MSG_ONLY_WFD && BCMDONGLEHOST */
13703 struct net_device
*ndev
= NULL
;
13704 wifi_p2p_pub_act_frame_t
*act_frm
= NULL
;
13705 wifi_p2p_action_frame_t
*p2p_act_frm
= NULL
;
13706 wifi_p2psd_gas_pub_act_frame_t
*sd_act_frm
= NULL
;
13707 wl_event_rx_frame_data_t
*rxframe
;
13711 u32 mgmt_frame_len
;
13713 if (ntoh32(e
->datalen
) < sizeof(wl_event_rx_frame_data_t
)) {
13714 WL_ERR(("wrong datalen:%d\n", ntoh32(e
->datalen
)));
13717 mgmt_frame_len
= ntoh32(e
->datalen
) - sizeof(wl_event_rx_frame_data_t
);
13718 event
= ntoh32(e
->event_type
);
13719 bsscfgidx
= e
->bsscfgidx
;
13720 rxframe
= (wl_event_rx_frame_data_t
*)data
;
13722 WL_ERR(("rxframe: NULL\n"));
13725 channel
= (ntoh16(rxframe
->channel
) & WL_CHANSPEC_CHAN_MASK
);
13726 memset(&bssid
, 0, ETHER_ADDR_LEN
);
13727 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
13728 if ((ndev
->ieee80211_ptr
->iftype
!= NL80211_IFTYPE_AP
) &&
13729 (event
== WLC_E_PROBREQ_MSG
)) {
13730 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
13731 4 && __GNUC_MINOR__ >= 6))
13732 _Pragma("GCC diagnostic push")
13733 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
13735 struct net_info
*iter
, *next
;
13736 for_each_ndev(cfg
, iter
, next
) {
13737 if (iter
->ndev
&& iter
->wdev
&&
13738 iter
->wdev
->iftype
== NL80211_IFTYPE_AP
) {
13740 cfgdev
= ndev_to_cfgdev(ndev
);
13744 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
13745 4 && __GNUC_MINOR__ >= 6))
13746 _Pragma("GCC diagnostic pop")
13750 if (channel
<= CH_MAX_2G_CHANNEL
)
13751 band
= wiphy
->bands
[IEEE80211_BAND_2GHZ
];
13753 band
= wiphy
->bands
[IEEE80211_BAND_5GHZ
];
13755 WL_ERR(("No valid band\n"));
13758 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
13759 freq
= ieee80211_channel_to_frequency(channel
);
13762 freq
= ieee80211_channel_to_frequency(channel
, band
->band
);
13764 if (event
== WLC_E_ACTION_FRAME_RX
) {
13765 if ((err
= wldev_iovar_getbuf_bsscfg(ndev
, "cur_etheraddr",
13766 NULL
, 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, bsscfgidx
,
13767 &cfg
->ioctl_buf_sync
)) != BCME_OK
) {
13768 WL_ERR(("WLC_GET_CUR_ETHERADDR failed, error %d\n", err
));
13772 err
= wldev_ioctl_get(ndev
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
);
13774 WL_ERR(("WLC_GET_BSSID error %d\n", err
));
13775 memcpy(da
.octet
, cfg
->ioctl_buf
, ETHER_ADDR_LEN
);
13776 err
= wl_frame_get_mgmt(FC_ACTION
, &da
, &e
->addr
, &bssid
,
13777 &mgmt_frame
, &mgmt_frame_len
,
13778 (u8
*)((wl_event_rx_frame_data_t
*)rxframe
+ 1));
13780 WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
13781 mgmt_frame_len
, channel
, freq
));
13785 if (wl_cfgp2p_is_pub_action(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13786 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
)) {
13787 act_frm
= (wifi_p2p_pub_act_frame_t
*)
13788 (&mgmt_frame
[DOT11_MGMT_HDR_LEN
]);
13789 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13790 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
)) {
13791 p2p_act_frm
= (wifi_p2p_action_frame_t
*)
13792 (&mgmt_frame
[DOT11_MGMT_HDR_LEN
]);
13793 (void) p2p_act_frm
;
13794 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13795 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
)) {
13797 sd_act_frm
= (wifi_p2psd_gas_pub_act_frame_t
*)
13798 (&mgmt_frame
[DOT11_MGMT_HDR_LEN
]);
13799 if (sd_act_frm
&& wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM
)) {
13800 if (cfg
->next_af_subtype
== sd_act_frm
->action
) {
13801 WL_DBG(("We got a right next frame of SD!(%d)\n",
13802 sd_act_frm
->action
));
13803 wl_clr_drv_status(cfg
, WAITING_NEXT_ACT_FRM
, ndev
);
13805 /* Stop waiting for next AF. */
13806 wl_stop_wait_next_action_frame(cfg
, ndev
, bsscfgidx
);
13811 } else if ((mgmt_frame
[DOT11_MGMT_HDR_LEN
] == TDLS_AF_CATEGORY
) ||
13812 (wl_cfg80211_is_tdls_tunneled_frame(
13813 &mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13814 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
))) {
13815 if (mgmt_frame
[DOT11_MGMT_HDR_LEN
] == TDLS_AF_CATEGORY
) {
13816 WL_ERR((" TDLS Action Frame Received type = %d \n",
13817 mgmt_frame
[DOT11_MGMT_HDR_LEN
+ 1]));
13819 #ifdef TDLS_MSG_ONLY_WFD
13820 if (!dhdp
->tdls_mode
) {
13821 WL_DBG((" TDLS Frame filtered \n"));
13825 if (mgmt_frame
[DOT11_MGMT_HDR_LEN
+ 1] == TDLS_ACTION_SETUP_RESP
) {
13826 cfg
->tdls_mgmt_frame
= mgmt_frame
;
13827 cfg
->tdls_mgmt_frame_len
= mgmt_frame_len
;
13828 cfg
->tdls_mgmt_freq
= freq
;
13831 #endif /* TDLS_MSG_ONLY_WFD */
13832 #endif /* WLTDLS */
13834 } else if (mgmt_frame
[DOT11_MGMT_HDR_LEN
] == DOT11_ACTION_CAT_QOS
) {
13835 /* update QoS map set table */
13836 bcm_tlv_t
* qos_map_ie
= NULL
;
13837 if ((qos_map_ie
= bcm_parse_tlvs(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13838 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
,
13839 DOT11_MNG_QOS_MAP_ID
)) != NULL
) {
13840 WL_DBG((" QoS map set IE found in QoS action frame\n"));
13841 if (!cfg
->up_table
) {
13842 cfg
->up_table
= kmalloc(UP_TABLE_MAX
, GFP_KERNEL
);
13844 wl_set_up_table(cfg
->up_table
, qos_map_ie
);
13846 kfree(cfg
->up_table
);
13847 cfg
->up_table
= NULL
;
13849 #endif /* QOS_MAP_SET */
13851 } else if (mgmt_frame
[DOT11_MGMT_HDR_LEN
] == DOT11_ACTION_CAT_RRM
) {
13852 /* radio measurement category */
13853 switch (mgmt_frame
[DOT11_MGMT_HDR_LEN
+1]) {
13854 case DOT11_RM_ACTION_NR_REP
:
13855 if (wl_cfg80211_recv_nbr_resp(ndev
,
13856 &mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13857 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
)
13859 WL_DBG(("RCC updated by nbr response\n"));
13865 #endif /* WBTEXT */
13868 * if we got normal action frame and ndev is p2p0,
13869 * we have to change ndev from p2p0 to wlan0
13873 if (cfg
->next_af_subtype
!= P2P_PAF_SUBTYPE_INVALID
) {
13875 if (wl_get_public_action(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13876 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
, &action
) != BCME_OK
) {
13877 WL_DBG(("Recived action is not public action frame\n"));
13878 } else if (cfg
->next_af_subtype
== action
) {
13879 WL_DBG(("Recived action is the waiting action(%d)\n",
13881 wl_clr_drv_status(cfg
, WAITING_NEXT_ACT_FRM
, ndev
);
13883 /* Stop waiting for next AF. */
13884 wl_stop_wait_next_action_frame(cfg
, ndev
, bsscfgidx
);
13891 if (wl_get_drv_status_all(cfg
, WAITING_NEXT_ACT_FRM
)) {
13892 if (cfg
->next_af_subtype
== act_frm
->subtype
) {
13893 WL_DBG(("We got a right next frame!(%d)\n",
13894 act_frm
->subtype
));
13895 wl_clr_drv_status(cfg
, WAITING_NEXT_ACT_FRM
, ndev
);
13897 if (cfg
->next_af_subtype
== P2P_PAF_GON_CONF
) {
13901 /* Stop waiting for next AF. */
13902 wl_stop_wait_next_action_frame(cfg
, ndev
, bsscfgidx
);
13907 wl_cfgp2p_print_actframe(false, &mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13908 mgmt_frame_len
- DOT11_MGMT_HDR_LEN
, channel
);
13909 if (act_frm
&& (act_frm
->subtype
== P2P_PAF_GON_CONF
)) {
13910 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
13911 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
13913 } else if (event
== WLC_E_PROBREQ_MSG
) {
13915 /* Handle probe reqs frame
13916 * WPS-AP certification 4.2.13
13918 struct parsed_ies prbreq_ies
;
13919 u32 prbreq_ie_len
= 0;
13922 WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
13923 mgmt_frame
= (u8
*)(data
);
13924 mgmt_frame_len
= ntoh32(e
->datalen
);
13925 if (mgmt_frame_len
< DOT11_MGMT_HDR_LEN
) {
13926 WL_ERR(("wrong datalen:%d\n", mgmt_frame_len
));
13929 prbreq_ie_len
= mgmt_frame_len
- DOT11_MGMT_HDR_LEN
;
13931 /* Parse prob_req IEs */
13932 if (wl_cfg80211_parse_ies(&mgmt_frame
[DOT11_MGMT_HDR_LEN
],
13933 prbreq_ie_len
, &prbreq_ies
) < 0) {
13934 WL_ERR(("Prob req get IEs failed\n"));
13937 if (prbreq_ies
.wps_ie
!= NULL
) {
13938 wl_validate_wps_ie((char *)prbreq_ies
.wps_ie
, prbreq_ies
.wps_ie_len
, &pbc
);
13939 WL_DBG((" wps_ie exist pbc = %d\n", pbc
));
13940 /* if pbc method, send prob_req mgmt frame to upper layer */
13946 mgmt_frame
= (u8
*)((wl_event_rx_frame_data_t
*)rxframe
+ 1);
13948 /* wpa supplicant use probe request event for restarting another GON Req.
13949 * but it makes GON Req repetition.
13950 * so if src addr of prb req is same as my target device,
13951 * do not send probe request event during sending action frame.
13953 if (event
== WLC_E_P2P_PROBREQ_MSG
) {
13954 WL_DBG((" Event %s\n", (event
== WLC_E_P2P_PROBREQ_MSG
) ?
13955 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
13958 /* Filter any P2P probe reqs arriving during the
13962 #if defined(P2P_IE_MISSING_FIX)
13963 cfg
->p2p_prb_noti
&&
13965 wl_get_p2p_status(cfg
, GO_NEG_PHASE
)) {
13966 WL_DBG(("Filtering P2P probe_req while "
13967 "being in GO-Neg state\n"));
13973 if (discover_cfgdev(cfgdev
, cfg
))
13974 WL_DBG(("Rx Managment frame For P2P Discovery Interface \n"));
13976 WL_DBG(("Rx Managment frame For Iface (%s) \n", ndev
->name
));
13977 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
13978 cfg80211_rx_mgmt(cfgdev
, freq
, 0, mgmt_frame
, mgmt_frame_len
, 0);
13979 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
13980 cfg80211_rx_mgmt(cfgdev
, freq
, 0, mgmt_frame
, mgmt_frame_len
, 0, GFP_ATOMIC
);
13981 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
13982 defined(WL_COMPAT_WIRELESS)
13983 cfg80211_rx_mgmt(cfgdev
, freq
, 0, mgmt_frame
, mgmt_frame_len
, GFP_ATOMIC
);
13985 cfg80211_rx_mgmt(cfgdev
, freq
, mgmt_frame
, mgmt_frame_len
, GFP_ATOMIC
);
13986 #endif /* LINUX_VERSION >= VERSION(3, 18, 0) */
13988 WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
13989 mgmt_frame_len
, ntoh32(e
->datalen
), channel
, freq
));
13996 #ifdef WL_SCHED_SCAN
13997 /* If target scan is not reliable, set the below define to "1" to do a
14000 #define FULL_ESCAN_ON_PFN_NET_FOUND 0
14002 wl_notify_sched_scan_results(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
14003 const wl_event_msg_t
*e
, void *data
)
14005 wl_pfn_net_info_v2_t
*netinfo
, *pnetinfo
;
14006 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
14007 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
14009 struct cfg80211_scan_request
*request
= NULL
;
14010 struct cfg80211_ssid ssid
[MAX_PFN_LIST_COUNT
];
14011 struct ieee80211_channel
*channel
= NULL
;
14012 int channel_req
= 0;
14014 wl_pfn_scanresults_t
*pfn_result
= (wl_pfn_scanresults_t
*)data
;
14015 int n_pfn_results
= pfn_result
->count
;
14016 log_conn_event_t
*event_data
= NULL
;
14017 tlv_log
*tlv_data
= NULL
;
14018 u32 alloc_len
, tlv_len
;
14021 WL_DBG(("Enter\n"));
14023 if (pfn_result
->version
!= PFN_SCANRESULT_VERSION
) {
14024 WL_ERR(("Incorrect version %d, expected %d\n", pfn_result
->version
,
14025 PFN_SCANRESULT_VERSION
));
14026 return BCME_VERSION
;
14029 if (e
->event_type
== WLC_E_PFN_NET_LOST
) {
14030 WL_PNO(("PFN NET LOST event. Do Nothing\n"));
14034 WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results
));
14035 if (n_pfn_results
> 0) {
14038 if (n_pfn_results
> MAX_PFN_LIST_COUNT
)
14039 n_pfn_results
= MAX_PFN_LIST_COUNT
;
14040 pnetinfo
= (wl_pfn_net_info_v2_t
*)((char *)data
+ sizeof(wl_pfn_scanresults_v2_t
)
14041 - sizeof(wl_pfn_net_info_v2_t
));
14043 memset(&ssid
, 0x00, sizeof(ssid
));
14045 request
= kzalloc(sizeof(*request
)
14046 + sizeof(*request
->channels
) * n_pfn_results
,
14048 channel
= (struct ieee80211_channel
*)kzalloc(
14049 (sizeof(struct ieee80211_channel
) * n_pfn_results
),
14051 if (!request
|| !channel
) {
14052 WL_ERR(("No memory"));
14057 request
->wiphy
= wiphy
;
14059 if (DBG_RING_ACTIVE(dhdp
, DHD_EVENT_RING_ID
)) {
14060 alloc_len
= sizeof(log_conn_event_t
) + DOT11_MAX_SSID_LEN
+ sizeof(uint16
) +
14062 event_data
= MALLOC(dhdp
->osh
, alloc_len
);
14064 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
14065 "length(%d)\n", __func__
, alloc_len
));
14068 tlv_len
= 3 * sizeof(tlv_log
);
14069 event_data
->tlvs
= MALLOC(dhdp
->osh
, tlv_len
);
14070 if (!event_data
->tlvs
) {
14071 WL_ERR(("%s: failed to allocate the tlv_log with "
14072 "length(%d)\n", __func__
, tlv_len
));
14077 for (i
= 0; i
< n_pfn_results
; i
++) {
14078 netinfo
= &pnetinfo
[i
];
14080 WL_ERR(("Invalid netinfo ptr. index:%d", i
));
14084 WL_PNO((">>> SSID:%s Channel:%d \n",
14085 netinfo
->pfnsubnet
.u
.SSID
, netinfo
->pfnsubnet
.channel
));
14086 /* PFN result doesn't have all the info which are required by the supplicant
14087 * (For e.g IEs) Do a target Escan so that sched scan results are reported
14088 * via wl_inform_single_bss in the required format. Escan does require the
14089 * scan request in the form of cfg80211_scan_request. For timebeing, create
14090 * cfg80211_scan_request one out of the received PNO event.
14092 ssid
[i
].ssid_len
= MIN(DOT11_MAX_SSID_LEN
, netinfo
->pfnsubnet
.SSID_len
);
14093 memcpy(ssid
[i
].ssid
, netinfo
->pfnsubnet
.u
.SSID
,
14095 request
->n_ssids
++;
14097 channel_req
= netinfo
->pfnsubnet
.channel
;
14098 band
= (channel_req
<= CH_MAX_2G_CHANNEL
) ? NL80211_BAND_2GHZ
14099 : NL80211_BAND_5GHZ
;
14100 channel
[i
].center_freq
= ieee80211_channel_to_frequency(channel_req
, band
);
14101 channel
[i
].band
= band
;
14102 channel
[i
].flags
|= IEEE80211_CHAN_NO_HT40
;
14103 request
->channels
[i
] = &channel
[i
];
14104 request
->n_channels
++;
14106 if (DBG_RING_ACTIVE(dhdp
, DHD_EVENT_RING_ID
)) {
14107 payload_len
= sizeof(log_conn_event_t
);
14108 event_data
->event
= WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND
;
14109 tlv_data
= event_data
->tlvs
;
14112 tlv_data
->tag
= WIFI_TAG_SSID
;
14113 tlv_data
->len
= netinfo
->pfnsubnet
.SSID_len
;
14114 memcpy(tlv_data
->value
, ssid
[i
].ssid
, ssid
[i
].ssid_len
);
14115 payload_len
+= TLV_LOG_SIZE(tlv_data
);
14116 tlv_data
= TLV_LOG_NEXT(tlv_data
);
14119 tlv_data
->tag
= WIFI_TAG_CHANNEL
;
14120 tlv_data
->len
= sizeof(uint16
);
14121 memcpy(tlv_data
->value
, &channel_req
, sizeof(uint16
));
14122 payload_len
+= TLV_LOG_SIZE(tlv_data
);
14123 tlv_data
= TLV_LOG_NEXT(tlv_data
);
14126 tlv_data
->tag
= WIFI_TAG_RSSI
;
14127 tlv_data
->len
= sizeof(int16
);
14128 memcpy(tlv_data
->value
, &netinfo
->RSSI
, sizeof(int16
));
14129 payload_len
+= TLV_LOG_SIZE(tlv_data
);
14130 tlv_data
= TLV_LOG_NEXT(tlv_data
);
14132 dhd_os_push_push_ring_data(dhdp
, DHD_EVENT_RING_ID
,
14133 &event_data
->event
, payload_len
);
14137 /* assign parsed ssid array */
14138 if (request
->n_ssids
)
14139 request
->ssids
= &ssid
[0];
14141 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
14142 /* Abort any on-going scan */
14143 wl_notify_escan_complete(cfg
, ndev
, true, true);
14146 if (wl_get_p2p_status(cfg
, DISCOVERY_ON
)) {
14147 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
14148 err
= wl_cfgp2p_discover_enable_search(cfg
, false);
14149 if (unlikely(err
)) {
14150 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
14153 p2p_scan(cfg
) = false;
14156 wl_set_drv_status(cfg
, SCANNING
, ndev
);
14157 #if FULL_ESCAN_ON_PFN_NET_FOUND
14158 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
14159 err
= wl_do_escan(cfg
, wiphy
, ndev
, NULL
);
14161 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
14162 err
= wl_do_escan(cfg
, wiphy
, ndev
, request
);
14165 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
14168 DBG_EVENT_LOG(dhdp
, WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED
);
14169 cfg
->sched_scan_running
= TRUE
;
14172 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
14181 MFREE(dhdp
->osh
, event_data
->tlvs
, tlv_len
);
14182 MFREE(dhdp
->osh
, event_data
, alloc_len
);
14186 #endif /* WL_SCHED_SCAN */
14188 static void wl_init_conf(struct wl_conf
*conf
)
14190 WL_DBG(("Enter \n"));
14191 conf
->frag_threshold
= (u32
)-1;
14192 conf
->rts_threshold
= (u32
)-1;
14193 conf
->retry_short
= (u32
)-1;
14194 conf
->retry_long
= (u32
)-1;
14195 conf
->tx_power
= -1;
14198 static void wl_init_prof(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
)
14200 unsigned long flags
;
14201 struct wl_profile
*profile
= wl_get_profile_by_netdev(cfg
, ndev
);
14204 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
14205 memset(profile
, 0, sizeof(struct wl_profile
));
14206 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
14208 WL_ERR(("%s: No profile\n", __FUNCTION__
));
14213 static void wl_init_event_handler(struct bcm_cfg80211
*cfg
)
14215 memset(cfg
->evt_handler
, 0, sizeof(cfg
->evt_handler
));
14217 cfg
->evt_handler
[WLC_E_SCAN_COMPLETE
] = wl_notify_scan_status
;
14218 cfg
->evt_handler
[WLC_E_AUTH
] = wl_notify_connect_status
;
14219 cfg
->evt_handler
[WLC_E_ASSOC
] = wl_notify_connect_status
;
14220 cfg
->evt_handler
[WLC_E_LINK
] = wl_notify_connect_status
;
14221 cfg
->evt_handler
[WLC_E_DEAUTH_IND
] = wl_notify_connect_status
;
14222 cfg
->evt_handler
[WLC_E_DEAUTH
] = wl_notify_connect_status
;
14223 cfg
->evt_handler
[WLC_E_DISASSOC_IND
] = wl_notify_connect_status
;
14224 cfg
->evt_handler
[WLC_E_ASSOC_IND
] = wl_notify_connect_status
;
14225 cfg
->evt_handler
[WLC_E_REASSOC_IND
] = wl_notify_connect_status
;
14226 cfg
->evt_handler
[WLC_E_ROAM
] = wl_notify_roaming_status
;
14227 cfg
->evt_handler
[WLC_E_MIC_ERROR
] = wl_notify_mic_status
;
14228 cfg
->evt_handler
[WLC_E_SET_SSID
] = wl_notify_connect_status
;
14229 cfg
->evt_handler
[WLC_E_ACTION_FRAME_RX
] = wl_notify_rx_mgmt_frame
;
14230 cfg
->evt_handler
[WLC_E_PROBREQ_MSG
] = wl_notify_rx_mgmt_frame
;
14231 cfg
->evt_handler
[WLC_E_P2P_PROBREQ_MSG
] = wl_notify_rx_mgmt_frame
;
14232 cfg
->evt_handler
[WLC_E_P2P_DISC_LISTEN_COMPLETE
] = wl_cfgp2p_listen_complete
;
14233 cfg
->evt_handler
[WLC_E_ACTION_FRAME_COMPLETE
] = wl_cfgp2p_action_tx_complete
;
14234 cfg
->evt_handler
[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE
] = wl_cfgp2p_action_tx_complete
;
14235 cfg
->evt_handler
[WLC_E_JOIN
] = wl_notify_connect_status
;
14236 cfg
->evt_handler
[WLC_E_START
] = wl_notify_connect_status
;
14238 cfg
->evt_handler
[WLC_E_PFN_NET_FOUND
] = wl_notify_pfn_status
;
14239 #endif /* PNO_SUPPORT */
14240 #ifdef GSCAN_SUPPORT
14241 cfg
->evt_handler
[WLC_E_PFN_BEST_BATCHING
] = wl_notify_gscan_event
;
14242 cfg
->evt_handler
[WLC_E_PFN_SCAN_COMPLETE
] = wl_notify_gscan_event
;
14243 cfg
->evt_handler
[WLC_E_PFN_GSCAN_FULL_RESULT
] = wl_notify_gscan_event
;
14244 cfg
->evt_handler
[WLC_E_PFN_BSSID_NET_FOUND
] = wl_notify_gscan_event
;
14245 cfg
->evt_handler
[WLC_E_PFN_BSSID_NET_LOST
] = wl_notify_gscan_event
;
14246 cfg
->evt_handler
[WLC_E_PFN_SSID_EXT
] = wl_notify_gscan_event
;
14247 cfg
->evt_handler
[WLC_E_GAS_FRAGMENT_RX
] = wl_notify_gscan_event
;
14248 cfg
->evt_handler
[WLC_E_ROAM_EXP_EVENT
] = wl_handle_roam_exp_event
;
14249 #endif /* GSCAN_SUPPORT */
14250 #ifdef RSSI_MONITOR_SUPPORT
14251 cfg
->evt_handler
[WLC_E_RSSI_LQM
] = wl_handle_rssi_monitor_event
;
14252 #endif /* RSSI_MONITOR_SUPPORT */
14254 cfg
->evt_handler
[WLC_E_TDLS_PEER_EVENT
] = wl_tdls_event_handler
;
14255 #endif /* WLTDLS */
14256 cfg
->evt_handler
[WLC_E_BSSID
] = wl_notify_roaming_status
;
14258 cfg
->evt_handler
[WLC_E_RMC_EVENT
] = wl_notify_rmc_status
;
14259 #endif /* WL_RELMCAST */
14260 #ifdef BT_WIFI_HANDOVER
14261 cfg
->evt_handler
[WLC_E_BT_WIFI_HANDOVER_REQ
] = wl_notify_bt_wifi_handover_req
;
14263 cfg
->evt_handler
[WLC_E_CSA_COMPLETE_IND
] = wl_csa_complete_ind
;
14264 cfg
->evt_handler
[WLC_E_AP_STARTED
] = wl_ap_start_ind
;
14265 #ifdef CUSTOM_EVENT_PM_WAKE
14266 cfg
->evt_handler
[WLC_E_EXCESS_PM_WAKE_EVENT
] = wl_check_pmstatus
;
14267 #endif /* CUSTOM_EVENT_PM_WAKE */
14268 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
14269 cfg
->evt_handler
[WLC_E_ROAM_PREP
] = wl_notify_roam_prep_status
;
14270 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
14271 #ifdef ENABLE_TEMP_THROTTLING
14272 cfg
->evt_handler
[WLC_E_TEMP_THROTTLE
] = wl_check_rx_throttle_status
;
14273 #endif /* ENABLE_TEMP_THROTTLING */
14277 #if defined(STATIC_WL_PRIV_STRUCT)
14279 wl_init_escan_result_buf(struct bcm_cfg80211
*cfg
)
14281 cfg
->escan_info
.escan_buf
= DHD_OS_PREALLOC(cfg
->pub
,
14282 DHD_PREALLOC_WIPHY_ESCAN0
, ESCAN_BUF_SIZE
);
14283 if (cfg
->escan_info
.escan_buf
== NULL
) {
14284 WL_ERR(("Failed to alloc ESCAN_BUF\n"));
14287 bzero(cfg
->escan_info
.escan_buf
, ESCAN_BUF_SIZE
);
14293 wl_deinit_escan_result_buf(struct bcm_cfg80211
*cfg
)
14295 if (cfg
->escan_info
.escan_buf
!= NULL
) {
14296 cfg
->escan_info
.escan_buf
= NULL
;
14299 #endif /* STATIC_WL_PRIV_STRUCT */
14301 static s32
wl_init_priv_mem(struct bcm_cfg80211
*cfg
)
14303 WL_DBG(("Enter \n"));
14305 cfg
->scan_results
= (void *)kzalloc(WL_SCAN_BUF_MAX
, GFP_KERNEL
);
14306 if (unlikely(!cfg
->scan_results
)) {
14307 WL_ERR(("Scan results alloc failed\n"));
14308 goto init_priv_mem_out
;
14310 cfg
->conf
= (void *)kzalloc(sizeof(*cfg
->conf
), GFP_KERNEL
);
14311 if (unlikely(!cfg
->conf
)) {
14312 WL_ERR(("wl_conf alloc failed\n"));
14313 goto init_priv_mem_out
;
14315 cfg
->scan_req_int
=
14316 (void *)kzalloc(sizeof(*cfg
->scan_req_int
), GFP_KERNEL
);
14317 if (unlikely(!cfg
->scan_req_int
)) {
14318 WL_ERR(("Scan req alloc failed\n"));
14319 goto init_priv_mem_out
;
14321 cfg
->ioctl_buf
= (void *)kzalloc(WLC_IOCTL_MAXLEN
, GFP_KERNEL
);
14322 if (unlikely(!cfg
->ioctl_buf
)) {
14323 WL_ERR(("Ioctl buf alloc failed\n"));
14324 goto init_priv_mem_out
;
14326 cfg
->escan_ioctl_buf
= (void *)kzalloc(WLC_IOCTL_MAXLEN
, GFP_KERNEL
);
14327 if (unlikely(!cfg
->escan_ioctl_buf
)) {
14328 WL_ERR(("Ioctl buf alloc failed\n"));
14329 goto init_priv_mem_out
;
14331 cfg
->extra_buf
= (void *)kzalloc(WL_EXTRA_BUF_MAX
, GFP_KERNEL
);
14332 if (unlikely(!cfg
->extra_buf
)) {
14333 WL_ERR(("Extra buf alloc failed\n"));
14334 goto init_priv_mem_out
;
14336 cfg
->pmk_list
= (void *)kzalloc(sizeof(*cfg
->pmk_list
), GFP_KERNEL
);
14337 if (unlikely(!cfg
->pmk_list
)) {
14338 WL_ERR(("pmk list alloc failed\n"));
14339 goto init_priv_mem_out
;
14341 #if defined(STATIC_WL_PRIV_STRUCT)
14342 cfg
->conn_info
= (void *)kzalloc(sizeof(*cfg
->conn_info
), GFP_KERNEL
);
14343 if (unlikely(!cfg
->conn_info
)) {
14344 WL_ERR(("cfg->conn_info alloc failed\n"));
14345 goto init_priv_mem_out
;
14347 cfg
->ie
= (void *)kzalloc(sizeof(*cfg
->ie
), GFP_KERNEL
);
14348 if (unlikely(!cfg
->ie
)) {
14349 WL_ERR(("cfg->ie alloc failed\n"));
14350 goto init_priv_mem_out
;
14352 if (unlikely(wl_init_escan_result_buf(cfg
))) {
14353 WL_ERR(("Failed to init escan resul buf\n"));
14354 goto init_priv_mem_out
;
14356 #endif /* STATIC_WL_PRIV_STRUCT */
14357 cfg
->afx_hdl
= (void *)kzalloc(sizeof(*cfg
->afx_hdl
), GFP_KERNEL
);
14358 if (unlikely(!cfg
->afx_hdl
)) {
14359 WL_ERR(("afx hdl alloc failed\n"));
14360 goto init_priv_mem_out
;
14362 init_completion(&cfg
->act_frm_scan
);
14363 init_completion(&cfg
->wait_next_af
);
14365 INIT_WORK(&cfg
->afx_hdl
->work
, wl_cfg80211_afx_handler
);
14368 if (cfg
->tdls_mgmt_frame
) {
14369 kfree(cfg
->tdls_mgmt_frame
);
14370 cfg
->tdls_mgmt_frame
= NULL
;
14372 #endif /* WLTDLS */
14376 wl_deinit_priv_mem(cfg
);
14381 static void wl_deinit_priv_mem(struct bcm_cfg80211
*cfg
)
14383 kfree(cfg
->scan_results
);
14384 cfg
->scan_results
= NULL
;
14387 kfree(cfg
->scan_req_int
);
14388 cfg
->scan_req_int
= NULL
;
14389 kfree(cfg
->ioctl_buf
);
14390 cfg
->ioctl_buf
= NULL
;
14391 kfree(cfg
->escan_ioctl_buf
);
14392 cfg
->escan_ioctl_buf
= NULL
;
14393 kfree(cfg
->extra_buf
);
14394 cfg
->extra_buf
= NULL
;
14395 kfree(cfg
->pmk_list
);
14396 cfg
->pmk_list
= NULL
;
14397 #if defined(STATIC_WL_PRIV_STRUCT)
14398 kfree(cfg
->conn_info
);
14399 cfg
->conn_info
= NULL
;
14402 wl_deinit_escan_result_buf(cfg
);
14403 #endif /* STATIC_WL_PRIV_STRUCT */
14404 if (cfg
->afx_hdl
) {
14405 cancel_work_sync(&cfg
->afx_hdl
->work
);
14406 kfree(cfg
->afx_hdl
);
14407 cfg
->afx_hdl
= NULL
;
14412 static s32
wl_create_event_handler(struct bcm_cfg80211
*cfg
)
14415 WL_DBG(("Enter \n"));
14417 /* Allocate workqueue for event */
14418 if (!cfg
->event_workq
) {
14419 cfg
->event_workq
= alloc_workqueue("dhd_eventd", WQ_MEM_RECLAIM
| WQ_HIGHPRI
, 0);
14422 if (!cfg
->event_workq
) {
14425 INIT_WORK(&cfg
->event_work
, wl_event_handler
);
14430 static void wl_destroy_event_handler(struct bcm_cfg80211
*cfg
)
14432 if (cfg
&& cfg
->event_workq
) {
14433 cancel_work_sync(&cfg
->event_work
);
14434 destroy_workqueue(cfg
->event_workq
);
14435 cfg
->event_workq
= NULL
;
14439 void wl_terminate_event_handler(struct net_device
*dev
)
14441 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
14444 wl_destroy_event_handler(cfg
);
14449 static void wl_scan_timeout(unsigned long data
)
14451 wl_event_msg_t msg
;
14452 struct bcm_cfg80211
*cfg
= (struct bcm_cfg80211
*)data
;
14453 struct wireless_dev
*wdev
= NULL
;
14454 struct net_device
*ndev
= NULL
;
14455 struct wl_scan_results
*bss_list
;
14456 struct wl_bss_info
*bi
= NULL
;
14460 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
14461 uint32 prev_memdump_mode
= dhdp
->memdump_enabled
;
14462 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
14464 if (!(cfg
->scan_request
)) {
14465 WL_ERR(("timer expired but no scan request\n"));
14469 bss_list
= wl_escan_get_buf(cfg
, FALSE
);
14471 WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
14473 WL_ERR(("scanned AP count (%d)\n", bss_list
->count
));
14475 bi
= next_bss(bss_list
, bi
);
14476 for_each_bss(bss_list
, bi
, i
) {
14477 if (bi
!= NULL
&& &(bi
->chanspec
) != NULL
&& (bi
->SSID
)) {
14478 channel
= wf_chspec_ctlchan(wl_chspec_driver_to_host(bi
->chanspec
));
14479 WL_ERR(("SSID :%s SSID_LEN :%d Channel :%d\n", bi
->SSID
, bi
->SSID_len
, channel
));
14480 if (bi
->SSID
[0] == '\0') {
14481 WL_ERR(("SSID :%s is null ssid_len:%d ,need return\n", bi
->SSID
, bi
->SSID_len
));
14485 WL_ERR(("SSID or Channel is null\n"));
14491 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
14492 if (cfg
->scan_request
->dev
)
14493 wdev
= cfg
->scan_request
->dev
->ieee80211_ptr
;
14495 if (cfg
->scan_request
)
14496 wdev
= cfg
->scan_request
->wdev
;
14497 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
14499 WL_ERR(("No wireless_dev present\n"));
14502 ndev
= wdev_to_wlc_ndev(wdev
, cfg
);
14504 bzero(&msg
, sizeof(wl_event_msg_t
));
14505 WL_ERR(("timer expired\n"));
14507 if (dhdp
->memdump_enabled
) {
14508 dhdp
->memdump_enabled
= DUMP_MEMFILE
;
14509 dhdp
->memdump_type
= DUMP_TYPE_SCAN_TIMEOUT
;
14510 dhd_bus_mem_dump(dhdp
);
14511 dhdp
->memdump_enabled
= prev_memdump_mode
;
14513 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
14514 msg
.event_type
= hton32(WLC_E_ESCAN_RESULT
);
14515 msg
.status
= hton32(WLC_E_STATUS_TIMEOUT
);
14516 msg
.reason
= 0xFFFFFFFF;
14517 wl_cfg80211_event(ndev
, &msg
, NULL
);
14518 #ifdef CUSTOMER_HW4_DEBUG
14519 if (!wl_scan_timeout_dbg_enabled
)
14520 wl_scan_timeout_dbg_set();
14521 #endif /* CUSTOMER_HW4_DEBUG */
14523 // terence 20130729: workaround to fix out of memory in firmware
14524 // if (dhd_conf_get_chip(dhd_get_pub(ndev)) == BCM43362_CHIP_ID) {
14525 // WL_ERR(("Send hang event\n"));
14526 // net_os_send_hang_message(ndev);
14530 #ifdef DHD_LOSSLESS_ROAMING
14531 static void wl_del_roam_timeout(struct bcm_cfg80211
*cfg
)
14533 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
14535 /* restore prec_map to ALLPRIO */
14536 dhdp
->dequeue_prec_map
= ALLPRIO
;
14537 if (timer_pending(&cfg
->roam_timeout
)) {
14538 del_timer_sync(&cfg
->roam_timeout
);
14543 static void wl_roam_timeout(unsigned long data
)
14545 struct bcm_cfg80211
*cfg
= (struct bcm_cfg80211
*)data
;
14546 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
14548 WL_ERR(("roam timer expired\n"));
14550 /* restore prec_map to ALLPRIO */
14551 dhdp
->dequeue_prec_map
= ALLPRIO
;
14554 #endif /* DHD_LOSSLESS_ROAMING */
14557 wl_cfg80211_netdev_notifier_call(struct notifier_block
* nb
,
14558 unsigned long state
, void *ptr
)
14560 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
14561 struct net_device
*dev
= ptr
;
14563 struct net_device
*dev
= netdev_notifier_info_to_dev(ptr
);
14564 #endif /* LINUX_VERSION < VERSION(3, 11, 0) */
14565 struct wireless_dev
*wdev
= ndev_to_wdev(dev
);
14566 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
14568 WL_DBG(("Enter \n"));
14570 if (!wdev
|| !cfg
|| dev
== bcmcfg_to_prmry_ndev(cfg
))
14571 return NOTIFY_DONE
;
14576 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
14577 int max_wait_timeout
= 2;
14578 int max_wait_count
= 100;
14580 unsigned long limit
= jiffies
+ max_wait_timeout
* HZ
;
14581 while (work_pending(&wdev
->cleanup_work
)) {
14582 if (refcnt
%5 == 0) {
14583 WL_ERR(("[NETDEV_DOWN] wait for "
14584 "complete of cleanup_work"
14585 " (%d th)\n", refcnt
));
14587 if (!time_before(jiffies
, limit
)) {
14588 WL_ERR(("[NETDEV_DOWN] cleanup_work"
14589 " of CFG80211 is not"
14590 " completed in %d sec\n",
14591 max_wait_timeout
));
14594 if (refcnt
>= max_wait_count
) {
14595 WL_ERR(("[NETDEV_DOWN] cleanup_work"
14596 " of CFG80211 is not"
14597 " completed in %d loop\n",
14601 set_current_state(TASK_INTERRUPTIBLE
);
14602 (void)schedule_timeout(100);
14603 set_current_state(TASK_RUNNING
);
14606 #endif /* LINUX_VERSION < VERSION(3, 14, 0) */
14609 case NETDEV_UNREGISTER
:
14610 /* after calling list_del_rcu(&wdev->list) */
14611 wl_cfg80211_clear_per_bss_ies(cfg
,
14612 wl_get_bssidx_by_wdev(cfg
, wdev
));
14613 wl_dealloc_netinfo_by_wdev(cfg
, wdev
);
14615 case NETDEV_GOING_DOWN
:
14617 * At NETDEV_DOWN state, wdev_cleanup_work work will be called.
14618 * In front of door, the function checks whether current scan
14619 * is working or not. If the scanning is still working,
14620 * wdev_cleanup_work call WARN_ON and make the scan done forcibly.
14622 if (wl_get_drv_status(cfg
, SCANNING
, dev
))
14623 wl_notify_escan_complete(cfg
, dev
, true, true);
14626 return NOTIFY_DONE
;
14629 static struct notifier_block wl_cfg80211_netdev_notifier
= {
14630 .notifier_call
= wl_cfg80211_netdev_notifier_call
,
14634 * to make sure we won't register the same notifier twice, otherwise a loop is likely to be
14635 * created in kernel notifier link list (with 'next' pointing to itself)
14637 static bool wl_cfg80211_netdev_notifier_registered
= FALSE
;
14639 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211
*cfg
)
14641 struct wireless_dev
*wdev
= NULL
;
14642 struct net_device
*ndev
= NULL
;
14644 if (!cfg
->scan_request
)
14647 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
14648 if (cfg
->scan_request
->dev
)
14649 wdev
= cfg
->scan_request
->dev
->ieee80211_ptr
;
14651 wdev
= cfg
->scan_request
->wdev
;
14652 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
14655 WL_ERR(("No wireless_dev present\n"));
14659 ndev
= wdev_to_wlc_ndev(wdev
, cfg
);
14660 wl_notify_escan_complete(cfg
, ndev
, true, true);
14661 WL_ERR(("Scan aborted! \n"));
14664 void wl_cfg80211_scan_abort(struct bcm_cfg80211
*cfg
)
14666 wl_scan_params_t
*params
= NULL
;
14667 s32 params_size
= 0;
14669 struct net_device
*dev
= bcmcfg_to_prmry_ndev(cfg
);
14670 if (!in_atomic()) {
14671 /* Our scan params only need space for 1 channel and 0 ssids */
14672 params
= wl_cfg80211_scan_alloc_params(cfg
, -1, 0, ¶ms_size
);
14673 if (params
== NULL
) {
14674 WL_ERR(("scan params allocation failed \n"));
14677 /* Do a scan abort to stop the driver's scan engine */
14678 err
= wldev_ioctl_set(dev
, WLC_SCAN
, params
, params_size
);
14680 WL_ERR(("scan abort failed \n"));
14686 if (cfg
->tdls_mgmt_frame
) {
14687 kfree(cfg
->tdls_mgmt_frame
);
14688 cfg
->tdls_mgmt_frame
= NULL
;
14690 #endif /* WLTDLS */
14693 static s32
wl_notify_escan_complete(struct bcm_cfg80211
*cfg
,
14694 struct net_device
*ndev
,
14695 bool aborted
, bool fw_abort
)
14698 unsigned long flags
;
14699 struct net_device
*dev
;
14700 dhd_pub_t
*dhdp
= (dhd_pub_t
*)(cfg
->pub
);
14701 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
14702 struct cfg80211_scan_info info
;
14703 info
.aborted
= aborted
;
14706 WL_DBG(("Enter \n"));
14707 BCM_REFERENCE(dhdp
);
14709 mutex_lock(&cfg
->scan_complete
);
14712 WL_ERR(("ndev is null\n"));
14717 if (cfg
->escan_info
.ndev
!= ndev
) {
14718 WL_ERR(("ndev is different %p %p\n", cfg
->escan_info
.ndev
, ndev
));
14723 if (cfg
->scan_request
) {
14724 dev
= bcmcfg_to_prmry_ndev(cfg
);
14725 #if defined(WL_ENABLE_P2P_IF)
14726 if (cfg
->scan_request
->dev
!= cfg
->p2p_net
)
14727 dev
= cfg
->scan_request
->dev
;
14728 #elif defined(WL_CFG80211_P2P_DEV_IF)
14729 if (cfg
->scan_request
->wdev
->iftype
!= NL80211_IFTYPE_P2P_DEVICE
)
14730 dev
= cfg
->scan_request
->wdev
->netdev
;
14731 #endif /* WL_ENABLE_P2P_IF */
14734 WL_DBG(("cfg->scan_request is NULL may be internal scan."
14735 "doing scan_abort for ndev %p primary %p",
14736 ndev
, bcmcfg_to_prmry_ndev(cfg
)));
14739 if (fw_abort
&& !in_atomic())
14740 wl_cfg80211_scan_abort(cfg
);
14741 if (timer_pending(&cfg
->scan_timeout
))
14742 del_timer_sync(&cfg
->scan_timeout
);
14743 #if defined(ESCAN_RESULT_PATCH)
14744 if (likely(cfg
->scan_request
)) {
14745 cfg
->bss_list
= wl_escan_get_buf(cfg
, aborted
);
14746 wl_inform_bss(cfg
);
14748 #endif /* ESCAN_RESULT_PATCH */
14749 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
14750 #ifdef WL_SCHED_SCAN
14751 if (cfg
->sched_scan_req
&& !cfg
->scan_request
) {
14752 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
14754 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
14755 cfg80211_sched_scan_results(cfg
->sched_scan_req
->wiphy
, 0);
14757 cfg80211_sched_scan_results(cfg
->sched_scan_req
->wiphy
);
14758 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
14761 DBG_EVENT_LOG(dhdp
, WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE
);
14762 cfg
->sched_scan_running
= FALSE
;
14764 #endif /* WL_SCHED_SCAN */
14765 if (likely(cfg
->scan_request
)) {
14766 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
14767 cfg80211_scan_done(cfg
->scan_request
, &info
);
14769 cfg80211_scan_done(cfg
->scan_request
, aborted
);
14771 cfg
->scan_request
= NULL
;
14772 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t
*)(cfg
->pub
));
14773 DHD_ENABLE_RUNTIME_PM((dhd_pub_t
*)(cfg
->pub
));
14775 if (p2p_is_on(cfg
))
14776 wl_clr_p2p_status(cfg
, SCANNING
);
14777 wl_clr_drv_status(cfg
, SCANNING
, dev
);
14778 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
14781 mutex_unlock(&cfg
->scan_complete
);
14785 #ifdef ESCAN_BUF_OVERFLOW_MGMT
14786 #ifndef WL_DRV_AVOID_SCANCACHE
14788 wl_cfg80211_find_removal_candidate(wl_bss_info_t
*bss
, removal_element_t
*candidate
)
14791 for (idx
= 0; idx
< BUF_OVERFLOW_MGMT_COUNT
; idx
++) {
14792 int len
= BUF_OVERFLOW_MGMT_COUNT
- idx
- 1;
14793 if (bss
->RSSI
< candidate
[idx
].RSSI
) {
14795 memcpy(&candidate
[idx
+ 1], &candidate
[idx
],
14796 sizeof(removal_element_t
) * len
);
14797 candidate
[idx
].RSSI
= bss
->RSSI
;
14798 candidate
[idx
].length
= bss
->length
;
14799 memcpy(&candidate
[idx
].BSSID
, &bss
->BSSID
, ETHER_ADDR_LEN
);
14806 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t
*list
, removal_element_t
*candidate
,
14810 int total_delete_len
= 0;
14811 for (idx1
= 0; idx1
< BUF_OVERFLOW_MGMT_COUNT
; idx1
++) {
14812 int cur_len
= WL_SCAN_RESULTS_FIXED_SIZE
;
14813 wl_bss_info_t
*bss
= NULL
;
14814 if (candidate
[idx1
].RSSI
>= bi
->RSSI
)
14816 for (idx2
= 0; idx2
< list
->count
; idx2
++) {
14817 bss
= bss
? (wl_bss_info_t
*)((uintptr
)bss
+ dtoh32(bss
->length
)) :
14819 if (!bcmp(&candidate
[idx1
].BSSID
, &bss
->BSSID
, ETHER_ADDR_LEN
) &&
14820 candidate
[idx1
].RSSI
== bss
->RSSI
&&
14821 candidate
[idx1
].length
== dtoh32(bss
->length
)) {
14822 u32 delete_len
= dtoh32(bss
->length
);
14823 WL_DBG(("delete scan info of " MACDBG
" to add new AP\n",
14824 MAC2STRDBG(bss
->BSSID
.octet
)));
14825 if (idx2
< list
->count
-1) {
14826 memmove((u8
*)bss
, (u8
*)bss
+ delete_len
,
14827 list
->buflen
- cur_len
- delete_len
);
14829 list
->buflen
-= delete_len
;
14831 total_delete_len
+= delete_len
;
14832 /* if delete_len is greater than or equal to result length */
14833 if (total_delete_len
>= bi
->length
) {
14838 cur_len
+= dtoh32(bss
->length
);
14842 #endif /* WL_DRV_AVOID_SCANCACHE */
14843 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
14845 #ifdef WL_DRV_AVOID_SCANCACHE
14846 static u32
wl_p2p_find_peer_channel(struct bcm_cfg80211
*cfg
, s32 status
, wl_bss_info_t
*bi
,
14850 u8
*p2p_dev_addr
= NULL
;
14852 ret
= wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
);
14856 if (status
== WLC_E_STATUS_PARTIAL
) {
14857 p2p_dev_addr
= wl_cfgp2p_retreive_p2p_dev_addr(bi
, bi_length
);
14858 if (p2p_dev_addr
&& !memcmp(p2p_dev_addr
,
14859 cfg
->afx_hdl
->tx_dst_addr
.octet
, ETHER_ADDR_LEN
)) {
14860 s32 channel
= wf_chspec_ctlchan(
14861 wl_chspec_driver_to_host(bi
->chanspec
));
14863 if ((channel
> MAXCHANNEL
) || (channel
<= 0))
14864 channel
= WL_INVALID
;
14866 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG
" found,"
14868 MAC2STRDBG(cfg
->afx_hdl
->tx_dst_addr
.octet
),
14871 wl_clr_p2p_status(cfg
, SCANNING
);
14872 cfg
->afx_hdl
->peer_chan
= channel
;
14873 complete(&cfg
->act_frm_scan
);
14876 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
14877 wl_clr_p2p_status(cfg
, SCANNING
);
14878 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
14879 if (cfg
->afx_hdl
->peer_chan
== WL_INVALID
)
14880 complete(&cfg
->act_frm_scan
);
14886 static s32
wl_escan_without_scan_cache(struct bcm_cfg80211
*cfg
, wl_escan_result_t
*escan_result
,
14887 struct net_device
*ndev
, const wl_event_msg_t
*e
, s32 status
)
14892 bool aborted
= false;
14893 bool fw_abort
= false;
14894 bool notify_escan_complete
= false;
14896 if (wl_escan_check_sync_id(status
, escan_result
->sync_id
,
14897 cfg
->escan_info
.cur_sync_id
) < 0) {
14901 wl_escan_print_sync_id(status
, escan_result
->sync_id
,
14902 cfg
->escan_info
.cur_sync_id
);
14904 if (!(status
== WLC_E_STATUS_TIMEOUT
) || !(status
== WLC_E_STATUS_PARTIAL
)) {
14905 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
14908 if ((likely(cfg
->scan_request
)) || (cfg
->sched_scan_running
)) {
14909 notify_escan_complete
= true;
14912 if (status
== WLC_E_STATUS_PARTIAL
) {
14913 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
14914 DBG_EVENT_LOG((dhd_pub_t
*)cfg
->pub
, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND
);
14915 if ((!escan_result
) || (dtoh16(escan_result
->bss_count
) != 1)) {
14916 WL_ERR(("Invalid escan result (NULL pointer) or invalid bss_count\n"));
14920 bi
= escan_result
->bss_info
;
14921 bi_length
= dtoh32(bi
->length
);
14923 (bi_length
!= (dtoh32(escan_result
->buflen
) - WL_ESCAN_RESULTS_FIXED_SIZE
))) {
14924 WL_ERR(("Invalid escan bss info (NULL pointer)"
14925 "or invalid bss_info length\n"));
14929 if (!(bcmcfg_to_wiphy(cfg
)->interface_modes
& BIT(NL80211_IFTYPE_ADHOC
))) {
14930 if (dtoh16(bi
->capability
) & DOT11_CAP_IBSS
) {
14931 WL_DBG(("Ignoring IBSS result\n"));
14936 if (wl_p2p_find_peer_channel(cfg
, status
, bi
, bi_length
)) {
14939 if (scan_req_match(cfg
)) {
14940 /* p2p scan && allow only probe response */
14941 if ((cfg
->p2p
->search_state
!= WL_P2P_DISC_ST_SCAN
) &&
14942 (bi
->flags
& WL_BSS_FLAGS_FROM_BEACON
))
14945 err
= wl_inform_single_bss(cfg
, bi
, false);
14948 * !Broadcast && number of ssid = 1 && number of channels =1
14949 * means specific scan to association
14951 if (wl_cfgp2p_is_p2p_specific_scan(cfg
->scan_request
)) {
14952 WL_ERR(("P2P assoc scan fast aborted.\n"));
14956 /* Directly exit from function here and
14957 * avoid sending notify completion to cfg80211
14961 } else if (status
== WLC_E_STATUS_SUCCESS
) {
14962 if (wl_p2p_find_peer_channel(cfg
, status
, NULL
, 0)) {
14965 WL_INFORM(("ESCAN COMPLETED\n"));
14966 DBG_EVENT_LOG((dhd_pub_t
*)cfg
->pub
, WIFI_EVENT_DRIVER_SCAN_COMPLETE
);
14968 /* Update escan complete status */
14972 #ifdef CUSTOMER_HW4_DEBUG
14973 if (wl_scan_timeout_dbg_enabled
)
14974 wl_scan_timeout_dbg_clear();
14975 #endif /* CUSTOMER_HW4_DEBUG */
14976 } else if ((status
== WLC_E_STATUS_ABORT
) || (status
== WLC_E_STATUS_NEWSCAN
) ||
14977 (status
== WLC_E_STATUS_11HQUIET
) || (status
== WLC_E_STATUS_CS_ABORT
) ||
14978 (status
== WLC_E_STATUS_NEWASSOC
)) {
14979 /* Handle all cases of scan abort */
14981 WL_DBG(("ESCAN ABORT reason: %d\n", status
));
14982 if (wl_p2p_find_peer_channel(cfg
, status
, NULL
, 0)) {
14985 WL_INFORM(("ESCAN ABORTED\n"));
14987 /* Update escan complete status */
14991 } else if (status
== WLC_E_STATUS_TIMEOUT
) {
14992 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg
->scan_request
));
14993 WL_ERR(("reason[0x%x]\n", e
->reason
));
14994 if (e
->reason
== 0xFFFFFFFF) {
14995 /* Update escan complete status */
15000 WL_ERR(("unexpected Escan Event %d : abort\n", status
));
15002 if (wl_p2p_find_peer_channel(cfg
, status
, NULL
, 0)) {
15005 /* Update escan complete status */
15010 /* Notify escan complete status */
15011 if (notify_escan_complete
) {
15012 wl_notify_escan_complete(cfg
, ndev
, aborted
, fw_abort
);
15019 #endif /* WL_DRV_AVOID_SCANCACHE */
15020 static s32
wl_escan_handler(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
15021 const wl_event_msg_t
*e
, void *data
)
15024 s32 status
= ntoh32(e
->status
);
15025 wl_escan_result_t
*escan_result
;
15026 struct net_device
*ndev
= NULL
;
15027 #ifndef WL_DRV_AVOID_SCANCACHE
15030 wifi_p2p_ie_t
* p2p_ie
;
15031 u8
*p2p_dev_addr
= NULL
;
15032 wl_scan_results_t
*list
;
15033 wl_bss_info_t
*bss
= NULL
;
15035 #endif /* WL_DRV_AVOID_SCANCACHE */
15037 struct ieee80211_supported_band
*band
;
15039 WL_DBG((" enter event type : %d, status : %d \n",
15040 ntoh32(e
->event_type
), ntoh32(e
->status
)));
15042 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
15044 mutex_lock(&cfg
->usr_sync
);
15045 /* P2P SCAN is coming from primary interface */
15046 if (wl_get_p2p_status(cfg
, SCANNING
)) {
15047 if (wl_get_drv_status_all(cfg
, SENDING_ACT_FRM
))
15048 ndev
= cfg
->afx_hdl
->dev
;
15050 ndev
= cfg
->escan_info
.ndev
;
15053 if (!ndev
|| (!wl_get_drv_status(cfg
, SCANNING
, ndev
) && !cfg
->sched_scan_running
)) {
15054 WL_ERR(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n",
15055 ndev
, wl_get_drv_status(cfg
, SCANNING
, ndev
),
15056 ntoh32(e
->event_type
), ntoh32(e
->status
)));
15059 escan_result
= (wl_escan_result_t
*)data
;
15061 #ifndef WL_DRV_AVOID_SCANCACHE
15062 if (status
== WLC_E_STATUS_PARTIAL
) {
15063 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
15064 DBG_EVENT_LOG((dhd_pub_t
*)cfg
->pub
, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND
);
15065 if (!escan_result
) {
15066 WL_ERR(("Invalid escan result (NULL pointer)\n"));
15069 if ((dtoh32(escan_result
->buflen
) > (int)ESCAN_BUF_SIZE
) ||
15070 (dtoh32(escan_result
->buflen
) < sizeof(wl_escan_result_t
))) {
15071 WL_ERR(("Invalid escan buffer len:%d\n", dtoh32(escan_result
->buflen
)));
15074 if (dtoh16(escan_result
->bss_count
) != 1) {
15075 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result
->bss_count
));
15078 bi
= escan_result
->bss_info
;
15080 WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
15083 bi_length
= dtoh32(bi
->length
);
15084 if (bi_length
!= (dtoh32(escan_result
->buflen
) - WL_ESCAN_RESULTS_FIXED_SIZE
)) {
15085 WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length
));
15089 /* +++++ terence 20130524: skip invalid bss */
15091 bi
->ctl_ch
? bi
->ctl_ch
: CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi
->chanspec
));
15092 if (channel
<= CH_MAX_2G_CHANNEL
)
15093 band
= bcmcfg_to_wiphy(cfg
)->bands
[IEEE80211_BAND_2GHZ
];
15095 band
= bcmcfg_to_wiphy(cfg
)->bands
[IEEE80211_BAND_5GHZ
];
15097 WL_ERR(("No valid band\n"));
15100 if (!dhd_conf_match_channel(cfg
->pub
, channel
))
15102 /* ----- terence 20130524: skip invalid bss */
15104 if (wl_escan_check_sync_id(status
, escan_result
->sync_id
,
15105 cfg
->escan_info
.cur_sync_id
) < 0)
15108 if (!(bcmcfg_to_wiphy(cfg
)->interface_modes
& BIT(NL80211_IFTYPE_ADHOC
))) {
15109 if (dtoh16(bi
->capability
) & DOT11_CAP_IBSS
) {
15110 WL_DBG(("Ignoring IBSS result\n"));
15115 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
)) {
15116 p2p_dev_addr
= wl_cfgp2p_retreive_p2p_dev_addr(bi
, bi_length
);
15117 if (p2p_dev_addr
&& !memcmp(p2p_dev_addr
,
15118 cfg
->afx_hdl
->tx_dst_addr
.octet
, ETHER_ADDR_LEN
)) {
15119 s32 channel
= wf_chspec_ctlchan(
15120 wl_chspec_driver_to_host(bi
->chanspec
));
15122 if ((channel
> MAXCHANNEL
) || (channel
<= 0))
15123 channel
= WL_INVALID
;
15125 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG
" found,"
15127 MAC2STRDBG(cfg
->afx_hdl
->tx_dst_addr
.octet
),
15130 wl_clr_p2p_status(cfg
, SCANNING
);
15131 cfg
->afx_hdl
->peer_chan
= channel
;
15132 complete(&cfg
->act_frm_scan
);
15137 int cur_len
= WL_SCAN_RESULTS_FIXED_SIZE
;
15138 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15139 removal_element_t candidate
[BUF_OVERFLOW_MGMT_COUNT
];
15140 int remove_lower_rssi
= FALSE
;
15142 bzero(candidate
, sizeof(removal_element_t
)*BUF_OVERFLOW_MGMT_COUNT
);
15143 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15145 list
= wl_escan_get_buf(cfg
, FALSE
);
15146 if (scan_req_match(cfg
)) {
15147 /* p2p scan && allow only probe response */
15148 if ((cfg
->p2p
->search_state
!= WL_P2P_DISC_ST_SCAN
) &&
15149 (bi
->flags
& WL_BSS_FLAGS_FROM_BEACON
))
15151 if ((p2p_ie
= wl_cfgp2p_find_p2pie(((u8
*) bi
) + bi
->ie_offset
,
15152 bi
->ie_length
)) == NULL
) {
15153 WL_ERR(("Couldn't find P2PIE in probe"
15154 " response/beacon\n"));
15158 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15159 if (bi_length
> ESCAN_BUF_SIZE
- list
->buflen
)
15160 remove_lower_rssi
= TRUE
;
15161 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15163 WL_SCAN(("%s("MACDBG
") RSSI %d flags 0x%x length %d\n", bi
->SSID
,
15164 MAC2STRDBG(bi
->BSSID
.octet
), bi
->RSSI
, bi
->flags
, bi
->length
));
15165 for (i
= 0; i
< list
->count
; i
++) {
15166 bss
= bss
? (wl_bss_info_t
*)((uintptr
)bss
+ dtoh32(bss
->length
))
15169 WL_ERR(("bss is NULL\n"));
15172 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15173 WL_TRACE(("%s("MACDBG
"), i=%d bss: RSSI %d list->count %d\n",
15174 bss
->SSID
, MAC2STRDBG(bss
->BSSID
.octet
),
15175 i
, bss
->RSSI
, list
->count
));
15177 if (remove_lower_rssi
)
15178 wl_cfg80211_find_removal_candidate(bss
, candidate
);
15179 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15181 if (!bcmp(&bi
->BSSID
, &bss
->BSSID
, ETHER_ADDR_LEN
) &&
15182 (CHSPEC_BAND(wl_chspec_driver_to_host(bi
->chanspec
))
15183 == CHSPEC_BAND(wl_chspec_driver_to_host(bss
->chanspec
))) &&
15184 bi
->SSID_len
== bss
->SSID_len
&&
15185 !bcmp(bi
->SSID
, bss
->SSID
, bi
->SSID_len
)) {
15187 /* do not allow beacon data to update
15188 *the data recd from a probe response
15190 if (!(bss
->flags
& WL_BSS_FLAGS_FROM_BEACON
) &&
15191 (bi
->flags
& WL_BSS_FLAGS_FROM_BEACON
))
15194 WL_SCAN(("%s("MACDBG
"), i=%d prev: RSSI %d"
15195 " flags 0x%x, new: RSSI %d flags 0x%x\n",
15196 bss
->SSID
, MAC2STRDBG(bi
->BSSID
.octet
), i
,
15197 bss
->RSSI
, bss
->flags
, bi
->RSSI
, bi
->flags
));
15199 if ((bss
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
) ==
15200 (bi
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
)) {
15201 /* preserve max RSSI if the measurements are
15202 * both on-channel or both off-channel
15204 WL_SCAN(("%s("MACDBG
"), same onchan"
15205 ", RSSI: prev %d new %d\n",
15206 bss
->SSID
, MAC2STRDBG(bi
->BSSID
.octet
),
15207 bss
->RSSI
, bi
->RSSI
));
15208 bi
->RSSI
= MAX(bss
->RSSI
, bi
->RSSI
);
15209 } else if ((bss
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
) &&
15210 (bi
->flags
& WL_BSS_FLAGS_RSSI_ONCHANNEL
) == 0) {
15211 /* preserve the on-channel rssi measurement
15212 * if the new measurement is off channel
15214 WL_SCAN(("%s("MACDBG
"), prev onchan"
15215 ", RSSI: prev %d new %d\n",
15216 bss
->SSID
, MAC2STRDBG(bi
->BSSID
.octet
),
15217 bss
->RSSI
, bi
->RSSI
));
15218 bi
->RSSI
= bss
->RSSI
;
15219 bi
->flags
|= WL_BSS_FLAGS_RSSI_ONCHANNEL
;
15221 if (dtoh32(bss
->length
) != bi_length
) {
15222 u32 prev_len
= dtoh32(bss
->length
);
15224 WL_SCAN(("bss info replacement"
15225 " is occured(bcast:%d->probresp%d)\n",
15226 bss
->ie_length
, bi
->ie_length
));
15227 WL_SCAN(("%s("MACDBG
"), replacement!(%d -> %d)\n",
15228 bss
->SSID
, MAC2STRDBG(bi
->BSSID
.octet
),
15229 prev_len
, bi_length
));
15231 if (list
->buflen
- prev_len
+ bi_length
15232 > ESCAN_BUF_SIZE
) {
15233 WL_ERR(("Buffer is too small: keep the"
15234 " previous result of this AP\n"));
15235 /* Only update RSSI */
15236 bss
->RSSI
= bi
->RSSI
;
15237 bss
->flags
|= (bi
->flags
15238 & WL_BSS_FLAGS_RSSI_ONCHANNEL
);
15242 if (i
< list
->count
- 1) {
15243 /* memory copy required by this case only */
15244 memmove((u8
*)bss
+ bi_length
,
15245 (u8
*)bss
+ prev_len
,
15246 list
->buflen
- cur_len
- prev_len
);
15248 list
->buflen
-= prev_len
;
15249 list
->buflen
+= bi_length
;
15251 list
->version
= dtoh32(bi
->version
);
15252 memcpy((u8
*)bss
, (u8
*)bi
, bi_length
);
15255 cur_len
+= dtoh32(bss
->length
);
15257 if (bi_length
> ESCAN_BUF_SIZE
- list
->buflen
) {
15258 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15259 wl_cfg80211_remove_lowRSSI_info(list
, candidate
, bi
);
15260 if (bi_length
> ESCAN_BUF_SIZE
- list
->buflen
) {
15261 WL_DBG(("RSSI(" MACDBG
") is too low(%d) to add Buffer\n",
15262 MAC2STRDBG(bi
->BSSID
.octet
), bi
->RSSI
));
15266 WL_ERR(("Buffer is too small: ignoring\n"));
15268 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15271 memcpy(&(((char *)list
)[list
->buflen
]), bi
, bi_length
);
15272 list
->version
= dtoh32(bi
->version
);
15273 list
->buflen
+= bi_length
;
15277 * !Broadcast && number of ssid = 1 && number of channels =1
15278 * means specific scan to association
15280 if (wl_cfgp2p_is_p2p_specific_scan(cfg
->scan_request
)) {
15281 WL_ERR(("P2P assoc scan fast aborted.\n"));
15282 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, false, true);
15287 else if (status
== WLC_E_STATUS_SUCCESS
) {
15288 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
15289 wl_escan_print_sync_id(status
, cfg
->escan_info
.cur_sync_id
,
15290 escan_result
->sync_id
);
15292 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
)) {
15293 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15294 wl_clr_p2p_status(cfg
, SCANNING
);
15295 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
15296 if (cfg
->afx_hdl
->peer_chan
== WL_INVALID
)
15297 complete(&cfg
->act_frm_scan
);
15298 } else if ((likely(cfg
->scan_request
)) || (cfg
->sched_scan_running
)) {
15299 WL_INFORM(("ESCAN COMPLETED\n"));
15300 DBG_EVENT_LOG((dhd_pub_t
*)cfg
->pub
, WIFI_EVENT_DRIVER_SCAN_COMPLETE
);
15301 cfg
->bss_list
= wl_escan_get_buf(cfg
, FALSE
);
15302 if (!scan_req_match(cfg
)) {
15303 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
15304 cfg
->bss_list
->count
));
15306 wl_inform_bss(cfg
);
15307 wl_notify_escan_complete(cfg
, ndev
, false, false);
15309 wl_escan_increment_sync_id(cfg
, SCAN_BUF_NEXT
);
15310 #ifdef CUSTOMER_HW4_DEBUG
15311 if (wl_scan_timeout_dbg_enabled
)
15312 wl_scan_timeout_dbg_clear();
15313 #endif /* CUSTOMER_HW4_DEBUG */
15314 } else if ((status
== WLC_E_STATUS_ABORT
) || (status
== WLC_E_STATUS_NEWSCAN
) ||
15315 (status
== WLC_E_STATUS_11HQUIET
) || (status
== WLC_E_STATUS_CS_ABORT
) ||
15316 (status
== WLC_E_STATUS_NEWASSOC
)) {
15317 /* Handle all cases of scan abort */
15318 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
15319 wl_escan_print_sync_id(status
, escan_result
->sync_id
,
15320 cfg
->escan_info
.cur_sync_id
);
15321 WL_DBG(("ESCAN ABORT reason: %d\n", status
));
15322 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
)) {
15323 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15324 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
15325 wl_clr_p2p_status(cfg
, SCANNING
);
15326 if (cfg
->afx_hdl
->peer_chan
== WL_INVALID
)
15327 complete(&cfg
->act_frm_scan
);
15328 } else if ((likely(cfg
->scan_request
)) || (cfg
->sched_scan_running
)) {
15329 WL_INFORM(("ESCAN ABORTED\n"));
15330 cfg
->bss_list
= wl_escan_get_buf(cfg
, TRUE
);
15331 if (!scan_req_match(cfg
)) {
15332 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
15333 cfg
->bss_list
->count
));
15335 wl_inform_bss(cfg
);
15336 wl_notify_escan_complete(cfg
, ndev
, true, false);
15338 /* If there is no pending host initiated scan, do nothing */
15339 WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
15341 wl_escan_increment_sync_id(cfg
, SCAN_BUF_CNT
);
15342 } else if (status
== WLC_E_STATUS_TIMEOUT
) {
15343 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg
->scan_request
));
15344 WL_ERR(("reason[0x%x]\n", e
->reason
));
15345 if (e
->reason
== 0xFFFFFFFF) {
15346 wl_notify_escan_complete(cfg
, cfg
->escan_info
.ndev
, true, true);
15349 WL_ERR(("unexpected Escan Event %d : abort\n", status
));
15350 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
15351 wl_escan_print_sync_id(status
, escan_result
->sync_id
,
15352 cfg
->escan_info
.cur_sync_id
);
15353 if (wl_get_drv_status_all(cfg
, FINDING_COMMON_CHANNEL
)) {
15354 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15355 wl_clr_p2p_status(cfg
, SCANNING
);
15356 wl_clr_drv_status(cfg
, SCANNING
, cfg
->afx_hdl
->dev
);
15357 if (cfg
->afx_hdl
->peer_chan
== WL_INVALID
)
15358 complete(&cfg
->act_frm_scan
);
15359 } else if ((likely(cfg
->scan_request
)) || (cfg
->sched_scan_running
)) {
15360 cfg
->bss_list
= wl_escan_get_buf(cfg
, TRUE
);
15361 if (!scan_req_match(cfg
)) {
15362 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
15363 "scanned AP count=%d\n",
15364 cfg
->bss_list
->count
));
15366 wl_inform_bss(cfg
);
15367 wl_notify_escan_complete(cfg
, ndev
, true, false);
15369 wl_escan_increment_sync_id(cfg
, 2);
15371 #else /* WL_DRV_AVOID_SCANCACHE */
15372 err
= wl_escan_without_scan_cache(cfg
, escan_result
, ndev
, e
, status
);
15373 #endif /* WL_DRV_AVOID_SCANCACHE */
15375 mutex_unlock(&cfg
->usr_sync
);
15379 static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211
*cfg
, int enable
)
15381 u32 connected_cnt
= wl_get_drv_status_all(cfg
, CONNECTED
);
15382 bool p2p_connected
= wl_cfgp2p_vif_created(cfg
);
15383 struct net_info
*iter
, *next
;
15385 if (!(cfg
->roam_flags
& WL_ROAM_OFF_ON_CONCURRENT
))
15388 WL_DBG(("roam off:%d p2p_connected:%d connected_cnt:%d \n",
15389 enable
, p2p_connected
, connected_cnt
));
15390 /* Disable FW roam when we have a concurrent P2P connection */
15391 if (enable
&& p2p_connected
&& connected_cnt
> 1) {
15393 /* Mark it as to be reverted */
15394 cfg
->roam_flags
|= WL_ROAM_REVERT_STATUS
;
15395 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15396 4 && __GNUC_MINOR__ >= 6))
15397 _Pragma("GCC diagnostic push")
15398 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15400 for_each_ndev(cfg
, iter
, next
) {
15401 if (iter
->ndev
&& iter
->wdev
&&
15402 iter
->wdev
->iftype
== NL80211_IFTYPE_STATION
) {
15403 if (wldev_iovar_setint(iter
->ndev
, "roam_off", TRUE
)
15405 iter
->roam_off
= TRUE
;
15408 WL_ERR(("error to enable roam_off\n"));
15412 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15413 4 && __GNUC_MINOR__ >= 6))
15414 _Pragma("GCC diagnostic pop")
15417 else if (!enable
&& (cfg
->roam_flags
& WL_ROAM_REVERT_STATUS
)) {
15418 cfg
->roam_flags
&= ~WL_ROAM_REVERT_STATUS
;
15419 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15420 4 && __GNUC_MINOR__ >= 6))
15421 _Pragma("GCC diagnostic push")
15422 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15424 for_each_ndev(cfg
, iter
, next
) {
15425 if (iter
->ndev
&& iter
->wdev
&&
15426 iter
->wdev
->iftype
== NL80211_IFTYPE_STATION
) {
15427 if (iter
->roam_off
!= WL_INVALID
) {
15428 if (wldev_iovar_setint(iter
->ndev
, "roam_off", FALSE
)
15430 iter
->roam_off
= FALSE
;
15433 WL_ERR(("error to disable roam_off\n"));
15438 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15439 4 && __GNUC_MINOR__ >= 6))
15440 _Pragma("GCC diagnostic pop")
15447 static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211
*cfg
)
15449 struct net_info
*iter
, *next
;
15452 u32 pre_ctl_chan
= 0;
15453 u32 connected_cnt
= wl_get_drv_status_all(cfg
, CONNECTED
);
15454 cfg
->vsdb_mode
= false;
15456 if (connected_cnt
<= 1) {
15459 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15460 4 && __GNUC_MINOR__ >= 6))
15461 _Pragma("GCC diagnostic push")
15462 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15464 for_each_ndev(cfg
, iter
, next
) {
15465 /* p2p discovery iface ndev could be null */
15469 if (wl_get_drv_status(cfg
, CONNECTED
, iter
->ndev
)) {
15470 if (wldev_iovar_getint(iter
->ndev
, "chanspec",
15471 (s32
*)&chanspec
) == BCME_OK
) {
15472 chanspec
= wl_chspec_driver_to_host(chanspec
);
15473 ctl_chan
= wf_chspec_ctlchan(chanspec
);
15474 wl_update_prof(cfg
, iter
->ndev
, NULL
,
15475 &ctl_chan
, WL_PROF_CHAN
);
15477 if (!cfg
->vsdb_mode
) {
15478 if (!pre_ctl_chan
&& ctl_chan
)
15479 pre_ctl_chan
= ctl_chan
;
15480 else if (pre_ctl_chan
&& (pre_ctl_chan
!= ctl_chan
)) {
15481 cfg
->vsdb_mode
= true;
15487 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15488 4 && __GNUC_MINOR__ >= 6))
15489 _Pragma("GCC diagnostic pop")
15491 printf("%s concurrency is enabled\n", cfg
->vsdb_mode
? "Multi Channel" : "Same Channel");
15495 #if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF)
15496 extern int g_frameburst
;
15497 #endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */
15499 static s32
wl_notifier_change_state(struct bcm_cfg80211
*cfg
, struct net_info
*_net_info
,
15500 enum wl_status state
, bool set
)
15506 struct net_device
*primary_dev
= bcmcfg_to_prmry_ndev(cfg
);
15507 dhd_pub_t
*dhd
= cfg
->pub
;
15509 rtt_status_info_t
*rtt_status
;
15510 #endif /* RTT_SUPPORT */
15511 if (dhd
->busstate
== DHD_BUS_DOWN
) {
15512 WL_ERR(("%s : busstate is DHD_BUS_DOWN!\n", __FUNCTION__
));
15515 WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
15516 state
, set
, _net_info
->pm_restore
, _net_info
->ndev
->name
));
15518 if (state
!= WL_STATUS_CONNECTED
)
15520 mode
= wl_get_mode_by_netdev(cfg
, _net_info
->ndev
);
15522 wl_cfg80211_concurrent_roam(cfg
, 1);
15523 wl_cfg80211_determine_vsdb_mode(cfg
);
15524 if (mode
== WL_MODE_AP
) {
15525 if (wl_add_remove_eventmsg(primary_dev
, WLC_E_P2P_PROBREQ_MSG
, false))
15526 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
15529 if ((err
= wldev_ioctl_set(_net_info
->ndev
, WLC_SET_PM
, &pm
,
15530 sizeof(pm
))) != 0) {
15531 if (err
== -ENODEV
)
15532 WL_DBG(("%s:netdev not ready\n",
15533 _net_info
->ndev
->name
));
15535 WL_ERR(("%s:error (%d)\n",
15536 _net_info
->ndev
->name
, err
));
15538 wl_cfg80211_update_power_mode(_net_info
->ndev
);
15540 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_SHORT
);
15542 } else { /* clear */
15544 /* clear chan information when the net device is disconnected */
15545 wl_update_prof(cfg
, _net_info
->ndev
, NULL
, &chan
, WL_PROF_CHAN
);
15546 wl_cfg80211_determine_vsdb_mode(cfg
);
15547 if (primary_dev
== _net_info
->ndev
) {
15550 rtt_status
= GET_RTTSTATE(dhd
);
15551 if (rtt_status
->status
!= RTT_ENABLED
) {
15552 #endif /* RTT_SUPPORT */
15553 if (dhd_conf_get_pm(dhd
) >= 0)
15554 pm
= dhd_conf_get_pm(dhd
);
15555 if ((err
= wldev_ioctl_set(_net_info
->ndev
, WLC_SET_PM
, &pm
,
15556 sizeof(pm
))) != 0) {
15557 if (err
== -ENODEV
)
15558 WL_DBG(("%s:netdev not ready\n",
15559 _net_info
->ndev
->name
));
15561 WL_ERR(("%s:error (%d)\n",
15562 _net_info
->ndev
->name
, err
));
15564 wl_cfg80211_update_power_mode(_net_info
->ndev
);
15568 #endif /* RTT_SUPPORT */
15570 wl_cfg80211_concurrent_roam(cfg
, 0);
15575 static s32
wl_init_scan(struct bcm_cfg80211
*cfg
)
15579 cfg
->evt_handler
[WLC_E_ESCAN_RESULT
] = wl_escan_handler
;
15580 cfg
->escan_info
.escan_state
= WL_ESCAN_STATE_IDLE
;
15581 wl_escan_init_sync_id(cfg
);
15583 /* Init scan_timeout timer */
15584 init_timer(&cfg
->scan_timeout
);
15585 cfg
->scan_timeout
.data
= (unsigned long) cfg
;
15586 cfg
->scan_timeout
.function
= wl_scan_timeout
;
15591 #ifdef DHD_LOSSLESS_ROAMING
15592 static s32
wl_init_roam_timeout(struct bcm_cfg80211
*cfg
)
15596 /* Init roam timer */
15597 init_timer(&cfg
->roam_timeout
);
15598 cfg
->roam_timeout
.data
= (unsigned long) cfg
;
15599 cfg
->roam_timeout
.function
= wl_roam_timeout
;
15603 #endif /* DHD_LOSSLESS_ROAMING */
15605 static s32
wl_init_priv(struct bcm_cfg80211
*cfg
)
15607 struct wiphy
*wiphy
= bcmcfg_to_wiphy(cfg
);
15608 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
15611 cfg
->scan_request
= NULL
;
15612 cfg
->pwr_save
= !!(wiphy
->flags
& WIPHY_FLAG_PS_ON_BY_DEFAULT
);
15613 #ifdef DISABLE_BUILTIN_ROAM
15614 cfg
->roam_on
= false;
15616 cfg
->roam_on
= true;
15617 #endif /* DISABLE_BUILTIN_ROAM */
15618 cfg
->active_scan
= true;
15619 cfg
->rf_blocked
= false;
15620 cfg
->vsdb_mode
= false;
15621 #if defined(BCMSDIO) || defined(BCMDBUS)
15622 cfg
->wlfc_on
= false;
15623 #endif /* BCMSDIO || BCMDBUS */
15624 cfg
->roam_flags
|= WL_ROAM_OFF_ON_CONCURRENT
;
15625 cfg
->disable_roam_event
= false;
15626 /* register interested state */
15627 set_bit(WL_STATUS_CONNECTED
, &cfg
->interrested_state
);
15628 spin_lock_init(&cfg
->cfgdrv_lock
);
15629 mutex_init(&cfg
->ioctl_buf_sync
);
15630 init_waitqueue_head(&cfg
->netif_change_event
);
15631 init_completion(&cfg
->send_af_done
);
15632 init_completion(&cfg
->iface_disable
);
15634 err
= wl_init_priv_mem(cfg
);
15637 if (wl_create_event_handler(cfg
))
15639 wl_init_event_handler(cfg
);
15640 mutex_init(&cfg
->usr_sync
);
15641 mutex_init(&cfg
->event_sync
);
15642 mutex_init(&cfg
->scan_complete
);
15643 mutex_init(&cfg
->if_sync
);
15645 mutex_init(&cfg
->tdls_sync
);
15646 #endif /* WLTDLS */
15647 err
= wl_init_scan(cfg
);
15650 #ifdef DHD_LOSSLESS_ROAMING
15651 err
= wl_init_roam_timeout(cfg
);
15655 #endif /* DHD_LOSSLESS_ROAMING */
15656 wl_init_conf(cfg
->conf
);
15657 wl_init_prof(cfg
, ndev
);
15659 DNGL_FUNC(dhd_cfg80211_init
, (cfg
));
15661 cfg
->nan_dp_state
= NAN_DP_STATE_DISABLED
;
15662 init_waitqueue_head(&cfg
->ndp_if_change_event
);
15663 #endif /* NAN_DP */
15667 static void wl_deinit_priv(struct bcm_cfg80211
*cfg
)
15669 DNGL_FUNC(dhd_cfg80211_deinit
, (cfg
));
15670 wl_destroy_event_handler(cfg
);
15673 del_timer_sync(&cfg
->scan_timeout
);
15674 #ifdef DHD_LOSSLESS_ROAMING
15675 del_timer_sync(&cfg
->roam_timeout
);
15677 wl_deinit_priv_mem(cfg
);
15678 if (wl_cfg80211_netdev_notifier_registered
) {
15679 wl_cfg80211_netdev_notifier_registered
= FALSE
;
15680 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier
);
15684 #if defined(WL_ENABLE_P2P_IF)
15685 static s32
wl_cfg80211_attach_p2p(struct bcm_cfg80211
*cfg
)
15687 WL_TRACE(("Enter \n"));
15689 if (wl_cfgp2p_register_ndev(cfg
) < 0) {
15690 WL_ERR(("P2P attach failed. \n"));
15697 static s32
wl_cfg80211_detach_p2p(struct bcm_cfg80211
*cfg
)
15699 struct wireless_dev
*wdev
;
15701 WL_DBG(("Enter \n"));
15703 WL_ERR(("Invalid Ptr\n"));
15707 wdev
= cfg
->p2p_wdev
;
15709 WL_ERR(("Invalid Ptr\n"));
15714 wl_cfgp2p_unregister_ndev(cfg
);
15716 cfg
->p2p_wdev
= NULL
;
15717 cfg
->p2p_net
= NULL
;
15718 WL_DBG(("Freeing 0x%p \n", wdev
));
15725 static s32
wl_cfg80211_attach_post(struct net_device
*ndev
)
15727 struct bcm_cfg80211
* cfg
;
15730 WL_TRACE(("In\n"));
15731 if (unlikely(!ndev
)) {
15732 WL_ERR(("ndev is invaild\n"));
15735 cfg
= wl_get_cfg(ndev
);
15736 if (unlikely(!cfg
)) {
15737 WL_ERR(("cfg is invaild\n"));
15740 if (!wl_get_drv_status(cfg
, READY
, ndev
)) {
15742 ret
= wl_cfgp2p_supported(cfg
, ndev
);
15744 #if !defined(WL_ENABLE_P2P_IF)
15745 cfg
->wdev
->wiphy
->interface_modes
|=
15746 (BIT(NL80211_IFTYPE_P2P_CLIENT
)|
15747 BIT(NL80211_IFTYPE_P2P_GO
));
15748 #endif /* !WL_ENABLE_P2P_IF */
15749 if ((err
= wl_cfgp2p_init_priv(cfg
)) != 0)
15752 #if defined(WL_ENABLE_P2P_IF)
15753 if (cfg
->p2p_net
) {
15754 /* Update MAC addr for p2p0 interface here. */
15755 memcpy(cfg
->p2p_net
->dev_addr
, ndev
->dev_addr
, ETH_ALEN
);
15756 cfg
->p2p_net
->dev_addr
[0] |= 0x02;
15757 printf("%s: p2p_dev_addr="MACDBG
"\n",
15758 cfg
->p2p_net
->name
,
15759 MAC2STRDBG(cfg
->p2p_net
->dev_addr
));
15761 WL_ERR(("p2p_net not yet populated."
15762 " Couldn't update the MAC Address for p2p0 \n"));
15765 #endif /* WL_ENABLE_P2P_IF */
15766 cfg
->p2p_supported
= true;
15767 } else if (ret
== 0) {
15768 if ((err
= wl_cfgp2p_init_priv(cfg
)) != 0)
15771 /* SDIO bus timeout */
15777 wl_set_drv_status(cfg
, READY
, ndev
);
15782 struct bcm_cfg80211
*wl_get_cfg(struct net_device
*ndev
)
15784 struct wireless_dev
*wdev
= ndev
->ieee80211_ptr
;
15789 return wiphy_priv(wdev
->wiphy
);
15792 s32
wl_cfg80211_attach(struct net_device
*ndev
, void *context
)
15794 struct wireless_dev
*wdev
;
15795 struct bcm_cfg80211
*cfg
;
15797 struct device
*dev
;
15799 WL_TRACE(("In\n"));
15801 WL_ERR(("ndev is invaild\n"));
15804 WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
15805 dev
= wl_cfg80211_get_parent_dev();
15807 wdev
= kzalloc(sizeof(*wdev
), GFP_KERNEL
);
15808 if (unlikely(!wdev
)) {
15809 WL_ERR(("Could not allocate wireless device\n"));
15812 err
= wl_setup_wiphy(wdev
, dev
, context
);
15813 if (unlikely(err
)) {
15818 wdev
->iftype
= wl_mode_to_nl80211_iftype(WL_MODE_MESH
);
15820 wdev
->iftype
= wl_mode_to_nl80211_iftype(WL_MODE_BSS
);
15822 cfg
= wiphy_priv(wdev
->wiphy
);
15824 cfg
->pub
= context
;
15825 INIT_LIST_HEAD(&cfg
->net_list
);
15827 INIT_LIST_HEAD(&cfg
->wbtext_bssid_list
);
15828 #endif /* WBTEXT */
15829 INIT_LIST_HEAD(&cfg
->vndr_oui_list
);
15830 spin_lock_init(&cfg
->net_list_sync
);
15831 ndev
->ieee80211_ptr
= wdev
;
15832 SET_NETDEV_DEV(ndev
, wiphy_dev(wdev
->wiphy
));
15833 wdev
->netdev
= ndev
;
15834 cfg
->state_notifier
= wl_notifier_change_state
;
15835 err
= wl_alloc_netinfo(cfg
, ndev
, wdev
, wdev
->iftype
, PM_ENABLE
, 0);
15837 WL_ERR(("Failed to alloc net_info (%d)\n", err
));
15838 goto cfg80211_attach_out
;
15840 err
= wl_init_priv(cfg
);
15842 WL_ERR(("Failed to init iwm_priv (%d)\n", err
));
15843 goto cfg80211_attach_out
;
15846 err
= wl_setup_rfkill(cfg
, TRUE
);
15848 WL_ERR(("Failed to setup rfkill %d\n", err
));
15849 goto cfg80211_attach_out
;
15851 #ifdef DEBUGFS_CFG80211
15852 err
= wl_setup_debugfs(cfg
);
15854 WL_ERR(("Failed to setup debugfs %d\n", err
));
15855 goto cfg80211_attach_out
;
15858 if (!wl_cfg80211_netdev_notifier_registered
) {
15859 wl_cfg80211_netdev_notifier_registered
= TRUE
;
15860 err
= register_netdevice_notifier(&wl_cfg80211_netdev_notifier
);
15862 wl_cfg80211_netdev_notifier_registered
= FALSE
;
15863 WL_ERR(("Failed to register notifierl %d\n", err
));
15864 goto cfg80211_attach_out
;
15867 #if defined(COEX_DHCP)
15868 cfg
->btcoex_info
= wl_cfg80211_btcoex_init(cfg
->wdev
->netdev
);
15869 if (!cfg
->btcoex_info
)
15870 goto cfg80211_attach_out
;
15872 #if defined(SUPPORT_RANDOM_MAC_SCAN)
15873 cfg
->random_mac_enabled
= FALSE
;
15874 #endif /* SUPPORT_RANDOM_MAC_SCAN */
15876 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
15877 wdev
->wiphy
->reg_notifier
= wl_cfg80211_reg_notifier
;
15878 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
15880 #if defined(WL_ENABLE_P2P_IF)
15881 err
= wl_cfg80211_attach_p2p(cfg
);
15883 goto cfg80211_attach_out
;
15886 INIT_DELAYED_WORK(&cfg
->pm_enable_work
, wl_cfg80211_work_handler
);
15887 mutex_init(&cfg
->pm_sync
);
15889 #if defined(STAT_REPORT)
15890 err
= wl_attach_stat_report(cfg
);
15892 goto cfg80211_attach_out
;
15894 #endif /* STAT_REPORT */
15897 cfg80211_attach_out
:
15898 wl_setup_rfkill(cfg
, FALSE
);
15903 void wl_cfg80211_detach(struct bcm_cfg80211
*cfg
)
15906 WL_TRACE(("In\n"));
15910 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_DEL
);
15912 #if defined(COEX_DHCP)
15913 wl_cfg80211_btcoex_deinit();
15914 cfg
->btcoex_info
= NULL
;
15917 wl_setup_rfkill(cfg
, FALSE
);
15918 #ifdef DEBUGFS_CFG80211
15919 wl_free_debugfs(cfg
);
15921 if (cfg
->p2p_supported
) {
15922 if (timer_pending(&cfg
->p2p
->listen_timer
))
15923 del_timer_sync(&cfg
->p2p
->listen_timer
);
15924 wl_cfgp2p_deinit_priv(cfg
);
15927 if (timer_pending(&cfg
->scan_timeout
))
15928 del_timer_sync(&cfg
->scan_timeout
);
15929 #ifdef DHD_LOSSLESS_ROAMING
15930 if (timer_pending(&cfg
->roam_timeout
)) {
15931 del_timer_sync(&cfg
->roam_timeout
);
15933 #endif /* DHD_LOSSLESS_ROAMING */
15935 #if defined(WL_CFG80211_P2P_DEV_IF)
15937 wl_cfgp2p_del_p2p_disc_if(cfg
->p2p_wdev
, cfg
);
15938 #endif /* WL_CFG80211_P2P_DEV_IF */
15939 #if defined(WL_ENABLE_P2P_IF)
15940 wl_cfg80211_detach_p2p(cfg
);
15942 #if defined(STAT_REPORT)
15943 wl_detach_stat_report(cfg
);
15944 #endif /* STAT_REPORT */
15946 wl_cfg80211_ibss_vsie_free(cfg
);
15947 wl_cfg80211_clear_mgmt_vndr_ies(cfg
);
15948 wl_deinit_priv(cfg
);
15949 wl_cfg80211_clear_parent_dev();
15951 #if defined(RSSIAVG)
15952 wl_free_rssi_cache(&g_rssi_cache_ctrl
);
15953 wl_free_rssi_cache(&g_connected_rssi_cache_ctrl
);
15955 #if defined(BSSCACHE)
15956 wl_release_bss_cache_ctrl(&g_bss_cache_ctrl
);
15958 /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
15959 * structure "cfg", which is the private part of wiphy, has been freed in
15960 * wl_free_wdev !!!!!!!!!!!
15964 static void wl_event_handler(struct work_struct
*work_data
)
15966 struct bcm_cfg80211
*cfg
= NULL
;
15967 struct wl_event_q
*e
;
15968 struct wireless_dev
*wdev
= NULL
;
15970 BCM_SET_CONTAINER_OF(cfg
, work_data
, struct bcm_cfg80211
, event_work
);
15971 DHD_EVENT_WAKE_LOCK(cfg
->pub
);
15972 while ((e
= wl_deq_event(cfg
))) {
15973 WL_DBG(("event type (%d), ifidx: %d bssidx: %d \n",
15974 e
->etype
, e
->emsg
.ifidx
, e
->emsg
.bsscfgidx
));
15976 if (e
->emsg
.ifidx
> WL_MAX_IFS
) {
15977 WL_ERR((" Event ifidx not in range. val:%d \n", e
->emsg
.ifidx
));
15981 /* Make sure iface operations, don't creat race conditions */
15982 mutex_lock(&cfg
->if_sync
);
15983 if (!(wdev
= wl_get_wdev_by_bssidx(cfg
, e
->emsg
.bsscfgidx
))) {
15984 /* For WLC_E_IF would be handled by wl_host_event */
15985 if (e
->etype
!= WLC_E_IF
)
15986 WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"
15987 " Ignoring event.\n", e
->emsg
.bsscfgidx
));
15988 } else if (e
->etype
< WLC_E_LAST
&& cfg
->evt_handler
[e
->etype
]) {
15989 dhd_pub_t
*dhd
= (struct dhd_pub
*)(cfg
->pub
);
15990 if (dhd
->busstate
== DHD_BUS_DOWN
) {
15991 WL_ERR((": BUS is DOWN.\n"));
15993 cfg
->evt_handler
[e
->etype
](cfg
, wdev_to_cfgdev(wdev
),
15994 &e
->emsg
, e
->edata
);
15996 WL_DBG(("Unknown Event (%d): ignoring\n", e
->etype
));
15998 mutex_unlock(&cfg
->if_sync
);
16002 DHD_EVENT_WAKE_UNLOCK(cfg
->pub
);
16006 wl_cfg80211_event(struct net_device
*ndev
, const wl_event_msg_t
* e
, void *data
)
16008 u32 event_type
= ntoh32(e
->event_type
);
16009 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
16010 struct net_info
*netinfo
;
16012 WL_DBG(("event_type (%d): %s\n", event_type
, bcmevent_get_name(event_type
)));
16014 if ((cfg
== NULL
) || (cfg
->p2p_supported
&& cfg
->p2p
== NULL
)) {
16015 WL_ERR(("Stale event ignored\n"));
16019 if (cfg
->event_workq
== NULL
) {
16020 WL_ERR(("Event handler is not created\n"));
16024 if (wl_get_p2p_status(cfg
, IF_CHANGING
) || wl_get_p2p_status(cfg
, IF_ADDING
)) {
16025 WL_ERR(("during IF change, ignore event %d\n", event_type
));
16029 netinfo
= wl_get_netinfo_by_bssidx(cfg
, e
->bsscfgidx
);
16031 /* Since the netinfo entry is not there, the netdev entry is not
16032 * created via cfg80211 interface. so the event is not of interest
16033 * to the cfg80211 layer.
16035 WL_ERR(("ignore event %d, not interested\n", event_type
));
16039 if (event_type
== WLC_E_PFN_NET_FOUND
) {
16040 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
16042 else if (event_type
== WLC_E_PFN_NET_LOST
) {
16043 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
16046 if (likely(!wl_enq_event(cfg
, ndev
, event_type
, e
, data
))) {
16047 queue_work(cfg
->event_workq
, &cfg
->event_work
);
16051 static void wl_init_eq(struct bcm_cfg80211
*cfg
)
16053 wl_init_eq_lock(cfg
);
16054 INIT_LIST_HEAD(&cfg
->eq_list
);
16057 static void wl_flush_eq(struct bcm_cfg80211
*cfg
)
16059 struct wl_event_q
*e
;
16060 unsigned long flags
;
16062 flags
= wl_lock_eq(cfg
);
16063 while (!list_empty_careful(&cfg
->eq_list
)) {
16064 BCM_SET_LIST_FIRST_ENTRY(e
, &cfg
->eq_list
, struct wl_event_q
, eq_list
);
16065 list_del(&e
->eq_list
);
16068 wl_unlock_eq(cfg
, flags
);
16072 * retrieve first queued event from head
16075 static struct wl_event_q
*wl_deq_event(struct bcm_cfg80211
*cfg
)
16077 struct wl_event_q
*e
= NULL
;
16078 unsigned long flags
;
16080 flags
= wl_lock_eq(cfg
);
16081 if (likely(!list_empty(&cfg
->eq_list
))) {
16082 BCM_SET_LIST_FIRST_ENTRY(e
, &cfg
->eq_list
, struct wl_event_q
, eq_list
);
16083 list_del(&e
->eq_list
);
16085 wl_unlock_eq(cfg
, flags
);
16091 * push event to tail of the queue
16095 wl_enq_event(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, u32 event
,
16096 const wl_event_msg_t
*msg
, void *data
)
16098 struct wl_event_q
*e
;
16102 unsigned long flags
;
16107 data_len
= ntoh32(msg
->datalen
);
16108 evtq_size
= sizeof(struct wl_event_q
) + data_len
;
16109 aflags
= (in_atomic()) ? GFP_ATOMIC
: GFP_KERNEL
;
16110 e
= kzalloc(evtq_size
, aflags
);
16111 if (unlikely(!e
)) {
16112 WL_ERR(("event alloc failed\n"));
16116 memcpy(&e
->emsg
, msg
, sizeof(wl_event_msg_t
));
16118 memcpy(e
->edata
, data
, data_len
);
16119 flags
= wl_lock_eq(cfg
);
16120 list_add_tail(&e
->eq_list
, &cfg
->eq_list
);
16121 wl_unlock_eq(cfg
, flags
);
16126 static void wl_put_event(struct wl_event_q
*e
)
16131 static s32
wl_config_ifmode(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 iftype
)
16137 case NL80211_IFTYPE_MONITOR
:
16138 case NL80211_IFTYPE_WDS
:
16139 WL_ERR(("type (%d) : currently we do not support this mode\n",
16143 case NL80211_IFTYPE_ADHOC
:
16144 mode
= WL_MODE_IBSS
;
16146 case NL80211_IFTYPE_STATION
:
16147 case NL80211_IFTYPE_P2P_CLIENT
:
16148 mode
= WL_MODE_BSS
;
16152 case NL80211_IFTYPE_MESH_POINT
:
16153 mode
= WL_MODE_MESH
;
16154 infra
= WL_BSSTYPE_MESH
;
16156 #endif /* WLMESH */
16157 case NL80211_IFTYPE_AP
:
16158 case NL80211_IFTYPE_P2P_GO
:
16164 WL_ERR(("invalid type (%d)\n", iftype
));
16167 infra
= htod32(infra
);
16168 err
= wldev_ioctl_set(ndev
, WLC_SET_INFRA
, &infra
, sizeof(infra
));
16169 if (unlikely(err
)) {
16170 WL_ERR(("WLC_SET_INFRA error (%d)\n", err
));
16174 wl_set_mode_by_netdev(cfg
, ndev
, mode
);
16179 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf
*ev
, u16 event
, bool set
)
16181 if (!ev
|| (event
> WLC_E_LAST
))
16184 if (ev
->num
< MAX_EVENT_BUF_NUM
) {
16185 ev
->event
[ev
->num
].type
= event
;
16186 ev
->event
[ev
->num
].set
= set
;
16189 WL_ERR(("evenbuffer doesn't support > %u events. Update"
16190 " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM
));
16195 s32
wl_cfg80211_apply_eventbuffer(
16196 struct net_device
*ndev
,
16197 struct bcm_cfg80211
*cfg
,
16198 wl_eventmsg_buf_t
*ev
)
16200 char eventmask
[WL_EVENTING_MASK_LEN
];
16202 s8 iovbuf
[WL_EVENTING_MASK_LEN
+ 12];
16204 if (!ev
|| (!ev
->num
))
16207 mutex_lock(&cfg
->event_sync
);
16209 /* Read event_msgs mask */
16210 ret
= wldev_iovar_getbuf(ndev
, "event_msgs", NULL
, 0, iovbuf
, sizeof(iovbuf
), NULL
);
16211 if (unlikely(ret
)) {
16212 WL_ERR(("Get event_msgs error (%d)\n", ret
));
16215 memcpy(eventmask
, iovbuf
, WL_EVENTING_MASK_LEN
);
16217 /* apply the set bits */
16218 for (i
= 0; i
< ev
->num
; i
++) {
16219 if (ev
->event
[i
].set
)
16220 setbit(eventmask
, ev
->event
[i
].type
);
16222 clrbit(eventmask
, ev
->event
[i
].type
);
16225 /* Write updated Event mask */
16226 ret
= wldev_iovar_setbuf(ndev
, "event_msgs", eventmask
, sizeof(eventmask
), iovbuf
,
16227 sizeof(iovbuf
), NULL
);
16228 if (unlikely(ret
)) {
16229 WL_ERR(("Set event_msgs error (%d)\n", ret
));
16233 mutex_unlock(&cfg
->event_sync
);
16237 s32
wl_add_remove_eventmsg(struct net_device
*ndev
, u16 event
, bool add
)
16239 s8 iovbuf
[WL_EVENTING_MASK_LEN
+ 12];
16240 s8 eventmask
[WL_EVENTING_MASK_LEN
];
16242 struct bcm_cfg80211
*cfg
;
16247 cfg
= wl_get_cfg(ndev
);
16251 mutex_lock(&cfg
->event_sync
);
16253 /* Setup event_msgs */
16254 err
= wldev_iovar_getbuf(ndev
, "event_msgs", NULL
, 0, iovbuf
, sizeof(iovbuf
), NULL
);
16255 if (unlikely(err
)) {
16256 WL_ERR(("Get event_msgs error (%d)\n", err
));
16259 memcpy(eventmask
, iovbuf
, WL_EVENTING_MASK_LEN
);
16261 setbit(eventmask
, event
);
16263 clrbit(eventmask
, event
);
16265 err
= wldev_iovar_setbuf(ndev
, "event_msgs", eventmask
, WL_EVENTING_MASK_LEN
, iovbuf
,
16266 sizeof(iovbuf
), NULL
);
16267 if (unlikely(err
)) {
16268 WL_ERR(("Set event_msgs error (%d)\n", err
));
16273 mutex_unlock(&cfg
->event_sync
);
16277 static int wl_construct_reginfo(struct bcm_cfg80211
*cfg
, s32 bw_cap
)
16279 struct net_device
*dev
= bcmcfg_to_prmry_ndev(cfg
);
16280 struct ieee80211_channel
*band_chan_arr
= NULL
;
16281 wl_uint32_list_t
*list
;
16282 u32 i
, j
, index
, n_2g
, n_5g
, band
, channel
, array_size
;
16289 bool dfs_radar_disabled
= FALSE
;
16291 #define LOCAL_BUF_LEN 1024
16292 pbuf
= kzalloc(LOCAL_BUF_LEN
, GFP_KERNEL
);
16294 if (pbuf
== NULL
) {
16295 WL_ERR(("failed to allocate local buf\n"));
16299 err
= wldev_iovar_getbuf_bsscfg(dev
, "chanspecs", NULL
,
16300 0, pbuf
, LOCAL_BUF_LEN
, 0, &cfg
->ioctl_buf_sync
);
16302 WL_ERR(("get chanspecs failed with %d\n", err
));
16306 #undef LOCAL_BUF_LEN
16308 list
= (wl_uint32_list_t
*)(void *)pbuf
;
16309 band
= array_size
= n_2g
= n_5g
= 0;
16310 for (i
= 0; i
< dtoh32(list
->count
); i
++) {
16313 ht40_allowed
= false;
16314 c
= (chanspec_t
)dtoh32(list
->element
[i
]);
16315 c
= wl_chspec_driver_to_host(c
);
16316 channel
= wf_chspec_ctlchan(c
);
16318 if (!CHSPEC_IS40(c
) && ! CHSPEC_IS20(c
)) {
16319 WL_DBG(("HT80/160/80p80 center channel : %d\n", channel
));
16322 if (CHSPEC_IS2G(c
) && (channel
>= CH_MIN_2G_CHANNEL
) &&
16323 (channel
<= CH_MAX_2G_CHANNEL
)) {
16324 band_chan_arr
= __wl_2ghz_channels
;
16325 array_size
= ARRAYSIZE(__wl_2ghz_channels
);
16327 band
= IEEE80211_BAND_2GHZ
;
16328 ht40_allowed
= (bw_cap
== WLC_N_BW_40ALL
)? true : false;
16329 } else if (CHSPEC_IS5G(c
) && channel
>= CH_MIN_5G_CHANNEL
) {
16330 band_chan_arr
= __wl_5ghz_a_channels
;
16331 array_size
= ARRAYSIZE(__wl_5ghz_a_channels
);
16333 band
= IEEE80211_BAND_5GHZ
;
16334 ht40_allowed
= (bw_cap
== WLC_N_BW_20ALL
)? false : true;
16336 WL_ERR(("Invalid channel Sepc. 0x%x.\n", c
));
16339 if (!ht40_allowed
&& CHSPEC_IS40(c
))
16341 for (j
= 0; (j
< *n_cnt
&& (*n_cnt
< array_size
)); j
++) {
16342 if (band_chan_arr
[j
].hw_value
== channel
) {
16351 if (!dhd_conf_match_channel(cfg
->pub
, channel
))
16353 if (index
< array_size
) {
16354 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
16355 band_chan_arr
[index
].center_freq
=
16356 ieee80211_channel_to_frequency(channel
);
16358 band_chan_arr
[index
].center_freq
=
16359 ieee80211_channel_to_frequency(channel
, band
);
16361 band_chan_arr
[index
].hw_value
= channel
;
16362 band_chan_arr
[index
].beacon_found
= false;
16364 if (CHSPEC_IS40(c
) && ht40_allowed
) {
16365 /* assuming the order is HT20, HT40 Upper,
16366 * HT40 lower from chanspecs
16368 u32 ht40_flag
= band_chan_arr
[index
].flags
& IEEE80211_CHAN_NO_HT40
;
16369 if (CHSPEC_SB_UPPER(c
)) {
16370 if (ht40_flag
== IEEE80211_CHAN_NO_HT40
)
16371 band_chan_arr
[index
].flags
&=
16372 ~IEEE80211_CHAN_NO_HT40
;
16373 band_chan_arr
[index
].flags
|= IEEE80211_CHAN_NO_HT40PLUS
;
16375 /* It should be one of
16376 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
16378 band_chan_arr
[index
].flags
&= ~IEEE80211_CHAN_NO_HT40
;
16379 if (ht40_flag
== IEEE80211_CHAN_NO_HT40
)
16380 band_chan_arr
[index
].flags
|=
16381 IEEE80211_CHAN_NO_HT40MINUS
;
16384 band_chan_arr
[index
].flags
= IEEE80211_CHAN_NO_HT40
;
16385 if (!dfs_radar_disabled
) {
16386 if (band
== IEEE80211_BAND_2GHZ
)
16387 channel
|= WL_CHANSPEC_BAND_2G
;
16389 channel
|= WL_CHANSPEC_BAND_5G
;
16390 channel
|= WL_CHANSPEC_BW_20
;
16391 channel
= wl_chspec_host_to_driver(channel
);
16392 err
= wldev_iovar_getint(dev
, "per_chan_info", &channel
);
16394 if (channel
& WL_CHAN_RADAR
) {
16395 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
16396 band_chan_arr
[index
].flags
|=
16397 (IEEE80211_CHAN_RADAR
16398 | IEEE80211_CHAN_NO_IBSS
);
16400 band_chan_arr
[index
].flags
|=
16401 IEEE80211_CHAN_RADAR
;
16405 if (channel
& WL_CHAN_PASSIVE
)
16406 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
16407 band_chan_arr
[index
].flags
|=
16408 IEEE80211_CHAN_PASSIVE_SCAN
;
16410 band_chan_arr
[index
].flags
|=
16411 IEEE80211_CHAN_NO_IR
;
16413 } else if (err
== BCME_UNSUPPORTED
) {
16414 dfs_radar_disabled
= TRUE
;
16415 WL_ERR(("does not support per_chan_info\n"));
16424 __wl_band_2ghz
.n_channels
= n_2g
;
16425 __wl_band_5ghz_a
.n_channels
= n_5g
;
16430 static s32
__wl_update_wiphybands(struct bcm_cfg80211
*cfg
, bool notify
)
16432 struct wiphy
*wiphy
;
16433 struct net_device
*dev
= bcmcfg_to_prmry_ndev(cfg
);
16440 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16448 s32 txbf_bfe_cap
= 0;
16449 s32 txbf_bfr_cap
= 0;
16453 struct ieee80211_supported_band
*bands
[IEEE80211_NUM_BANDS
] = {NULL
, };
16455 memset(bandlist
, 0, sizeof(bandlist
));
16456 err
= wldev_ioctl_get(dev
, WLC_GET_BANDLIST
, bandlist
,
16458 if (unlikely(err
)) {
16459 WL_ERR(("error read bandlist (%d)\n", err
));
16462 err
= wldev_ioctl_get(dev
, WLC_GET_BAND
, &cur_band
,
16464 if (unlikely(err
)) {
16465 WL_ERR(("error (%d)\n", err
));
16469 err
= wldev_iovar_getint(dev
, "nmode", &nmode
);
16470 if (unlikely(err
)) {
16471 WL_ERR(("error reading nmode (%d)\n", err
));
16474 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16475 err
= wldev_iovar_getint(dev
, "vhtmode", &vhtmode
);
16476 if (unlikely(err
)) {
16477 WL_ERR(("error reading vhtmode (%d)\n", err
));
16481 err
= wldev_iovar_getint(dev
, "txstreams", &txstreams
);
16482 if (unlikely(err
)) {
16483 WL_ERR(("error reading txstreams (%d)\n", err
));
16486 err
= wldev_iovar_getint(dev
, "rxstreams", &rxstreams
);
16487 if (unlikely(err
)) {
16488 WL_ERR(("error reading rxstreams (%d)\n", err
));
16491 err
= wldev_iovar_getint(dev
, "ldpc_cap", &ldpc_cap
);
16492 if (unlikely(err
)) {
16493 WL_ERR(("error reading ldpc_cap (%d)\n", err
));
16496 err
= wldev_iovar_getint(dev
, "stbc_rx", &stbc_rx
);
16497 if (unlikely(err
)) {
16498 WL_ERR(("error reading stbc_rx (%d)\n", err
));
16501 err
= wldev_iovar_getint(dev
, "stbc_tx", &stbc_tx
);
16502 if (unlikely(err
)) {
16503 WL_ERR(("error reading stbc_tx (%d)\n", err
));
16506 err
= wldev_iovar_getint(dev
, "txbf_bfe_cap", &txbf_bfe_cap
);
16507 if (unlikely(err
)) {
16508 WL_ERR(("error reading txbf_bfe_cap (%d)\n", err
));
16511 err
= wldev_iovar_getint(dev
, "txbf_bfr_cap", &txbf_bfr_cap
);
16512 if (unlikely(err
)) {
16513 WL_ERR(("error reading txbf_bfr_cap (%d)\n", err
));
16518 /* For nmode and vhtmode check bw cap */
16520 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16524 err
= wldev_iovar_getint(dev
, "mimo_bw_cap", &bw_cap
);
16525 if (unlikely(err
)) {
16526 WL_ERR(("error get mimo_bw_cap (%d)\n", err
));
16530 err
= wl_construct_reginfo(cfg
, bw_cap
);
16532 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err
));
16533 if (err
!= BCME_UNSUPPORTED
)
16537 wiphy
= bcmcfg_to_wiphy(cfg
);
16538 nband
= bandlist
[0];
16540 for (i
= 1; i
<= nband
&& i
< ARRAYSIZE(bandlist
); i
++) {
16542 if (bandlist
[i
] == WLC_BAND_5G
&& __wl_band_5ghz_a
.n_channels
> 0) {
16543 bands
[IEEE80211_BAND_5GHZ
] =
16545 index
= IEEE80211_BAND_5GHZ
;
16546 if (nmode
&& (bw_cap
== WLC_N_BW_40ALL
|| bw_cap
== WLC_N_BW_20IN2G_40IN5G
))
16547 bands
[index
]->ht_cap
.cap
|= IEEE80211_HT_CAP_SGI_40
;
16549 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16550 /* VHT capabilities. */
16553 bands
[index
]->vht_cap
.vht_supported
= TRUE
;
16555 for (j
= 1; j
<= VHT_CAP_MCS_MAP_NSS_MAX
; j
++) {
16556 /* TX stream rates. */
16557 if (j
<= txstreams
) {
16558 VHT_MCS_MAP_SET_MCS_PER_SS(j
, VHT_CAP_MCS_MAP_0_9
,
16559 bands
[index
]->vht_cap
.vht_mcs
.tx_mcs_map
);
16561 VHT_MCS_MAP_SET_MCS_PER_SS(j
, VHT_CAP_MCS_MAP_NONE
,
16562 bands
[index
]->vht_cap
.vht_mcs
.tx_mcs_map
);
16565 /* RX stream rates. */
16566 if (j
<= rxstreams
) {
16567 VHT_MCS_MAP_SET_MCS_PER_SS(j
, VHT_CAP_MCS_MAP_0_9
,
16568 bands
[index
]->vht_cap
.vht_mcs
.rx_mcs_map
);
16570 VHT_MCS_MAP_SET_MCS_PER_SS(j
, VHT_CAP_MCS_MAP_NONE
,
16571 bands
[index
]->vht_cap
.vht_mcs
.rx_mcs_map
);
16577 /* 80 MHz is mandatory */
16578 bands
[index
]->vht_cap
.cap
|=
16579 IEEE80211_VHT_CAP_SHORT_GI_80
;
16581 if (WL_BW_CAP_160MHZ(bw_cap
)) {
16582 bands
[index
]->vht_cap
.cap
|=
16583 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ
;
16584 bands
[index
]->vht_cap
.cap
|=
16585 IEEE80211_VHT_CAP_SHORT_GI_160
;
16588 bands
[index
]->vht_cap
.cap
|=
16589 IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454
;
16592 bands
[index
]->vht_cap
.cap
|=
16593 IEEE80211_VHT_CAP_RXLDPC
;
16596 bands
[index
]->vht_cap
.cap
|=
16597 IEEE80211_VHT_CAP_TXSTBC
;
16600 bands
[index
]->vht_cap
.cap
|=
16601 (stbc_rx
<< VHT_CAP_INFO_RX_STBC_SHIFT
);
16604 bands
[index
]->vht_cap
.cap
|=
16605 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE
;
16607 if (txbf_bfr_cap
) {
16608 bands
[index
]->vht_cap
.cap
|=
16609 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE
;
16612 if (txbf_bfe_cap
|| txbf_bfr_cap
) {
16613 bands
[index
]->vht_cap
.cap
|=
16614 (2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT
);
16615 bands
[index
]->vht_cap
.cap
|=
16616 ((txstreams
- 1) <<
16617 VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT
);
16618 bands
[index
]->vht_cap
.cap
|=
16619 IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB
;
16622 /* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
16623 bands
[index
]->vht_cap
.cap
|=
16624 (7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT
);
16625 WL_INFORM(("%s band[%d] vht_enab=%d vht_cap=%08x "
16626 "vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
16627 __FUNCTION__
, index
,
16628 bands
[index
]->vht_cap
.vht_supported
,
16629 bands
[index
]->vht_cap
.cap
,
16630 bands
[index
]->vht_cap
.vht_mcs
.rx_mcs_map
,
16631 bands
[index
]->vht_cap
.vht_mcs
.tx_mcs_map
));
16635 else if (bandlist
[i
] == WLC_BAND_2G
&& __wl_band_2ghz
.n_channels
> 0) {
16636 bands
[IEEE80211_BAND_2GHZ
] =
16638 index
= IEEE80211_BAND_2GHZ
;
16639 if (bw_cap
== WLC_N_BW_40ALL
)
16640 bands
[index
]->ht_cap
.cap
|= IEEE80211_HT_CAP_SGI_40
;
16643 if ((index
>= 0) && nmode
) {
16644 bands
[index
]->ht_cap
.cap
|=
16645 (IEEE80211_HT_CAP_SGI_20
| IEEE80211_HT_CAP_DSSSCCK40
);
16646 bands
[index
]->ht_cap
.ht_supported
= TRUE
;
16647 bands
[index
]->ht_cap
.ampdu_factor
= IEEE80211_HT_MAX_AMPDU_64K
;
16648 bands
[index
]->ht_cap
.ampdu_density
= IEEE80211_HT_MPDU_DENSITY_16
;
16649 /* An HT shall support all EQM rates for one spatial stream */
16650 bands
[index
]->ht_cap
.mcs
.rx_mask
[0] = 0xff;
16655 wiphy
->bands
[IEEE80211_BAND_2GHZ
] = bands
[IEEE80211_BAND_2GHZ
];
16656 wiphy
->bands
[IEEE80211_BAND_5GHZ
] = bands
[IEEE80211_BAND_5GHZ
];
16658 /* check if any bands populated otherwise makes 2Ghz as default */
16659 if (wiphy
->bands
[IEEE80211_BAND_2GHZ
] == NULL
&&
16660 wiphy
->bands
[IEEE80211_BAND_5GHZ
] == NULL
) {
16661 /* Setup 2Ghz band as default */
16662 wiphy
->bands
[IEEE80211_BAND_2GHZ
] = &__wl_band_2ghz
;
16666 wiphy_apply_custom_regulatory(wiphy
, &brcm_regdom
);
16671 s32
wl_update_wiphybands(struct bcm_cfg80211
*cfg
, bool notify
)
16675 mutex_lock(&cfg
->usr_sync
);
16676 err
= __wl_update_wiphybands(cfg
, notify
);
16677 mutex_unlock(&cfg
->usr_sync
);
16682 static s32
__wl_cfg80211_up(struct bcm_cfg80211
*cfg
)
16685 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
16686 struct wireless_dev
*wdev
= ndev
->ieee80211_ptr
;
16688 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
16689 #endif /* WBTEXT */
16692 #endif /* WLTDLS */
16696 err
= wl_create_event_handler(cfg
);
16698 WL_ERR(("wl_create_event_handler failed\n"));
16701 wl_init_event_handler(cfg
);
16703 err
= dhd_config_dongle(cfg
);
16707 err
= wl_config_ifmode(cfg
, ndev
, wdev
->iftype
);
16708 if (unlikely(err
&& err
!= -EINPROGRESS
)) {
16709 WL_ERR(("wl_config_ifmode failed\n"));
16711 WL_ERR(("return error %d\n", err
));
16716 err
= wl_init_scan(cfg
);
16718 WL_ERR(("wl_init_scan failed\n"));
16721 err
= __wl_update_wiphybands(cfg
, true);
16722 if (unlikely(err
)) {
16723 WL_ERR(("wl_update_wiphybands failed\n"));
16725 WL_ERR(("return error %d\n", err
));
16729 if (!dhd_download_fw_on_driverload
) {
16730 err
= wl_create_event_handler(cfg
);
16732 WL_ERR(("wl_create_event_handler failed\n"));
16735 wl_init_event_handler(cfg
);
16737 err
= wl_init_scan(cfg
);
16739 WL_ERR(("wl_init_scan failed\n"));
16742 #ifdef DHD_LOSSLESS_ROAMING
16743 if (timer_pending(&cfg
->roam_timeout
)) {
16744 del_timer_sync(&cfg
->roam_timeout
);
16746 #endif /* DHD_LOSSLESS_ROAMING */
16748 err
= dhd_monitor_init(cfg
->pub
);
16751 /* when wifi up, set roam_prof to default value */
16752 if (dhd
->wbtext_support
) {
16753 if (dhd
->op_mode
& DHD_FLAG_STA_MODE
) {
16754 wl_cfg80211_wbtext_set_default(ndev
);
16755 wl_cfg80211_wbtext_clear_bssid_list(cfg
);
16758 #endif /* WBTEXT */
16760 if (wldev_iovar_getint(ndev
, "tdls_enable", &tdls
) == 0) {
16761 WL_DBG(("TDLS supported in fw\n"));
16762 cfg
->tdls_supported
= true;
16764 #endif /* WLTDLS */
16765 INIT_DELAYED_WORK(&cfg
->pm_enable_work
, wl_cfg80211_work_handler
);
16766 wl_set_drv_status(cfg
, READY
, ndev
);
16770 static s32
__wl_cfg80211_down(struct bcm_cfg80211
*cfg
)
16773 unsigned long flags
;
16774 struct net_info
*iter
, *next
;
16775 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
16776 #if defined(WL_CFG80211) && (defined(WL_ENABLE_P2P_IF) || \
16777 defined(WL_NEW_CFG_PRIVCMD_SUPPORT)) && !defined(PLATFORM_SLP)
16778 struct net_device
*p2p_net
= cfg
->p2p_net
;
16780 #ifdef PROP_TXSTATUS_VSDB
16781 #if defined(BCMSDIO) || defined(BCMDBUS)
16782 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
16783 #endif /* BCMSDIO || BCMDBUS */
16784 #endif /* PROP_TXSTATUS_VSDB */
16785 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
16786 struct cfg80211_scan_info info
;
16791 /* Check if cfg80211 interface is already down */
16792 if (!wl_get_drv_status(cfg
, READY
, ndev
)) {
16793 WL_DBG(("cfg80211 interface is already down\n"));
16794 return err
; /* it is even not ready */
16798 cfg
->tdls_supported
= false;
16799 #endif /* WLTDLS */
16801 /* Delete pm_enable_work */
16802 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_DEL
);
16804 /* clear all the security setting on primary Interface */
16805 wl_cfg80211_clear_security(cfg
);
16808 if (cfg
->p2p_supported
) {
16809 wl_clr_p2p_status(cfg
, GO_NEG_PHASE
);
16810 #ifdef PROP_TXSTATUS_VSDB
16811 #if defined(BCMSDIO) || defined(BCMDBUS)
16812 if (wl_cfgp2p_vif_created(cfg
)) {
16813 bool enabled
= false;
16814 dhd_wlfc_get_enable(dhd
, &enabled
);
16815 if (enabled
&& cfg
->wlfc_on
&& dhd
->op_mode
!= DHD_FLAG_HOSTAP_MODE
&&
16816 dhd
->op_mode
!= DHD_FLAG_IBSS_MODE
) {
16817 dhd_wlfc_deinit(dhd
);
16818 cfg
->wlfc_on
= false;
16821 #endif /* BCMSDIO || BCMDBUS */
16822 #endif /* PROP_TXSTATUS_VSDB */
16826 /* clean up any left over interfaces */
16827 wl_cfg80211_cleanup_virtual_ifaces(ndev
, false);
16829 /* If primary BSS is operational (for e.g SoftAP), bring it down */
16830 if (wl_cfg80211_bss_isup(ndev
, 0)) {
16831 if (wl_cfg80211_bss_up(cfg
, ndev
, 0, 0) < 0)
16832 WL_ERR(("BSS down failed \n"));
16835 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16836 4 && __GNUC_MINOR__ >= 6))
16837 _Pragma("GCC diagnostic push")
16838 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16840 for_each_ndev(cfg
, iter
, next
) {
16841 if (iter
->ndev
) /* p2p discovery iface is null */
16842 wl_set_drv_status(cfg
, SCAN_ABORTING
, iter
->ndev
);
16844 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16845 4 && __GNUC_MINOR__ >= 6))
16846 _Pragma("GCC diagnostic pop")
16849 #ifdef P2P_LISTEN_OFFLOADING
16850 wl_cfg80211_p2plo_deinit(cfg
);
16851 #endif /* P2P_LISTEN_OFFLOADING */
16853 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
16854 if (cfg
->scan_request
) {
16855 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
16856 info
.aborted
= true;
16857 cfg80211_scan_done(cfg
->scan_request
, &info
);
16859 cfg80211_scan_done(cfg
->scan_request
, true);
16861 cfg
->scan_request
= NULL
;
16863 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
16864 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16865 4 && __GNUC_MINOR__ >= 6))
16866 _Pragma("GCC diagnostic push")
16867 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16869 for_each_ndev(cfg
, iter
, next
) {
16870 /* p2p discovery iface ndev ptr could be null */
16871 if (iter
->ndev
== NULL
)
16873 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
16874 if (wl_get_drv_status(cfg
, CONNECTED
, iter
->ndev
)) {
16875 CFG80211_DISCONNECTED(iter
->ndev
, 0, NULL
, 0, false, GFP_KERNEL
);
16877 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) */
16878 wl_clr_drv_status(cfg
, READY
, iter
->ndev
);
16879 wl_clr_drv_status(cfg
, SCANNING
, iter
->ndev
);
16880 wl_clr_drv_status(cfg
, SCAN_ABORTING
, iter
->ndev
);
16881 wl_clr_drv_status(cfg
, CONNECTING
, iter
->ndev
);
16882 wl_clr_drv_status(cfg
, CONNECTED
, iter
->ndev
);
16883 wl_clr_drv_status(cfg
, DISCONNECTING
, iter
->ndev
);
16884 wl_clr_drv_status(cfg
, AP_CREATED
, iter
->ndev
);
16885 wl_clr_drv_status(cfg
, AP_CREATING
, iter
->ndev
);
16887 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16888 4 && __GNUC_MINOR__ >= 6))
16889 _Pragma("GCC diagnostic pop")
16891 bcmcfg_to_prmry_ndev(cfg
)->ieee80211_ptr
->iftype
=
16892 NL80211_IFTYPE_STATION
;
16893 #if defined(WL_CFG80211) && (defined(WL_ENABLE_P2P_IF) || \
16894 defined(WL_NEW_CFG_PRIVCMD_SUPPORT)) && !defined(PLATFORM_SLP)
16896 dev_close(p2p_net
);
16899 /* Avoid deadlock from wl_cfg80211_down */
16900 if (!dhd_download_fw_on_driverload
) {
16901 mutex_unlock(&cfg
->usr_sync
);
16902 wl_destroy_event_handler(cfg
);
16903 mutex_lock(&cfg
->usr_sync
);
16908 if (cfg
->link_up
) { //army fix wifi stop call trace issue
16909 CFG80211_DISCONNECTED(ndev
, 0, NULL
, 0, false, GFP_KERNEL
);
16912 if (cfg
->p2p_supported
) {
16913 if (timer_pending(&cfg
->p2p
->listen_timer
))
16914 del_timer_sync(&cfg
->p2p
->listen_timer
);
16915 wl_cfgp2p_down(cfg
);
16918 if (timer_pending(&cfg
->scan_timeout
)) {
16919 del_timer_sync(&cfg
->scan_timeout
);
16922 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t
*)(cfg
->pub
));
16924 dhd_monitor_uninit();
16925 #ifdef WLAIBSS_MCHAN
16926 bcm_cfg80211_del_ibss_if(cfg
->wdev
->wiphy
, cfg
->ibss_cfgdev
);
16927 #endif /* WLAIBSS_MCHAN */
16931 /* Clear interworking element. */
16933 cfg
->wl11u
= FALSE
;
16937 #ifdef CUSTOMER_HW4_DEBUG
16938 if (wl_scan_timeout_dbg_enabled
) {
16939 wl_scan_timeout_dbg_clear();
16941 #endif /* CUSTOMER_HW4_DEBUG */
16943 cfg
->disable_roam_event
= false;
16945 DNGL_FUNC(dhd_cfg80211_down
, (cfg
));
16948 /* Printout all netinfo entries */
16949 wl_probe_wdev_all(cfg
);
16950 #endif /* DHD_IFDEBUG */
16955 s32
wl_cfg80211_up(struct net_device
*net
)
16957 struct bcm_cfg80211
*cfg
;
16961 #ifdef DISABLE_PM_BCNRX
16964 s8 iovbuf
[WLC_IOCTL_SMLEN
];
16965 #endif /* DISABLE_PM_BCNRX */
16968 cfg
= wl_get_cfg(net
);
16970 if ((err
= wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg
), WLC_GET_VERSION
, &val
,
16971 sizeof(int)) < 0)) {
16972 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err
));
16976 if (val
!= WLC_IOCTL_VERSION
&& val
!= 1) {
16977 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
16978 val
, WLC_IOCTL_VERSION
));
16979 return BCME_VERSION
;
16981 ioctl_version
= val
;
16982 WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version
));
16984 mutex_lock(&cfg
->usr_sync
);
16985 dhd
= (dhd_pub_t
*)(cfg
->pub
);
16986 if (!(dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
16987 err
= wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg
));
16988 if (unlikely(err
)) {
16989 mutex_unlock(&cfg
->usr_sync
);
16994 cfg
->wdev
->wiphy
->features
|= NL80211_FEATURE_USERSPACE_MPM
;
16995 #endif /* WLMESH */
16997 err
= __wl_cfg80211_up(cfg
);
16999 WL_ERR(("__wl_cfg80211_up failed\n"));
17003 /* IOVAR configurations with 'up' condition */
17004 #ifdef DISABLE_PM_BCNRX
17005 interr
= wldev_iovar_setbuf(bcmcfg_to_prmry_ndev(cfg
), "pm_bcnrx", (char *)¶m
,
17006 sizeof(param
), iovbuf
, sizeof(iovbuf
), NULL
);
17007 if (unlikely(interr
)) {
17008 WL_ERR(("Set pm_bcnrx returned (%d)\n", interr
));
17010 #endif /* DISABLE_PM_BCNRX */
17012 mutex_unlock(&cfg
->usr_sync
);
17014 #ifdef WLAIBSS_MCHAN
17015 bcm_cfg80211_add_ibss_if(cfg
->wdev
->wiphy
, IBSS_IF_NAME
);
17016 #endif /* WLAIBSS_MCHAN */
17018 #ifdef DUAL_STA_STATIC_IF
17019 #ifdef WL_VIRTUAL_APSTA
17020 #error "Both DUAL STA and DUAL_STA_STATIC_IF can't be enabled together"
17022 /* Static Interface support is currently supported only for STA only builds (without P2P) */
17023 wl_cfg80211_create_iface(cfg
->wdev
->wiphy
, NL80211_IFTYPE_STATION
, NULL
, "wlan%d");
17024 #endif /* DUAL_STA_STATIC_IF */
17029 /* Private Event to Supplicant with indication that chip hangs */
17030 int wl_cfg80211_hang(struct net_device
*dev
, u16 reason
)
17032 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
17034 #if defined(SOFTAP_SEND_HANGEVT)
17035 /* specifc mac address used for hang event */
17036 uint8 hang_mac
[ETHER_ADDR_LEN
] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
17037 #endif /* SOFTAP_SEND_HANGEVT */
17042 dhd
= (dhd_pub_t
*)(cfg
->pub
);
17043 #if defined(DHD_HANG_SEND_UP_TEST)
17044 if (dhd
->req_hang_type
) {
17045 WL_ERR(("%s, Clear HANG test request 0x%x\n",
17046 __FUNCTION__
, dhd
->req_hang_type
));
17047 dhd
->req_hang_type
= 0;
17049 #endif /* DHD_HANG_SEND_UP_TEST */
17050 if ((dhd
->hang_reason
<= HANG_REASON_MASK
) || (dhd
->hang_reason
>= HANG_REASON_MAX
)) {
17051 WL_ERR(("%s, Invalid hang reason 0x%x\n",
17052 __FUNCTION__
, dhd
->hang_reason
));
17053 dhd
->hang_reason
= HANG_REASON_UNKNOWN
;
17055 #ifdef DHD_USE_EXTENDED_HANG_REASON
17056 if (dhd
->hang_reason
!= 0) {
17057 reason
= dhd
->hang_reason
;
17059 #endif /* DHD_USE_EXTENDED_HANG_REASON */
17060 WL_ERR(("In : chip crash eventing, reason=0x%x\n", (uint32
)(dhd
->hang_reason
)));
17062 wl_add_remove_pm_enable_work(cfg
, WL_PM_WORKQ_DEL
);
17063 #ifdef SOFTAP_SEND_HANGEVT
17064 if (dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
) {
17065 cfg80211_del_sta(dev
, hang_mac
, GFP_ATOMIC
);
17067 #endif /* SOFTAP_SEND_HANGEVT */
17069 CFG80211_DISCONNECTED(dev
, reason
, NULL
, 0, false, GFP_KERNEL
);
17071 #if defined(RSSIAVG)
17072 wl_free_rssi_cache(&g_rssi_cache_ctrl
);
17074 #if defined(BSSCACHE)
17075 wl_free_bss_cache(&g_bss_cache_ctrl
);
17083 s32
wl_cfg80211_down(struct net_device
*dev
)
17086 struct bcm_cfg80211
*cfg
= NULL
;
17090 cfg
= wl_get_cfg(dev
);
17096 mutex_lock(&cfg
->usr_sync
);
17097 #if defined(RSSIAVG)
17098 wl_free_rssi_cache(&g_rssi_cache_ctrl
);
17100 #if defined(BSSCACHE)
17101 wl_free_bss_cache(&g_bss_cache_ctrl
);
17103 err
= __wl_cfg80211_down(cfg
);
17104 mutex_unlock(&cfg
->usr_sync
);
17109 static void *wl_read_prof(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 item
)
17111 unsigned long flags
;
17113 struct wl_profile
*profile
= wl_get_profile_by_netdev(cfg
, ndev
);
17117 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
17120 rptr
= &profile
->sec
;
17123 rptr
= &profile
->active
;
17125 case WL_PROF_BSSID
:
17126 rptr
= profile
->bssid
;
17129 rptr
= &profile
->ssid
;
17132 rptr
= &profile
->channel
;
17135 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
17137 WL_ERR(("invalid item (%d)\n", item
));
17142 wl_update_prof(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
17143 const wl_event_msg_t
*e
, const void *data
, s32 item
)
17146 const struct wlc_ssid
*ssid
;
17147 unsigned long flags
;
17148 struct wl_profile
*profile
= wl_get_profile_by_netdev(cfg
, ndev
);
17152 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
17155 ssid
= (const wlc_ssid_t
*) data
;
17156 memset(profile
->ssid
.SSID
, 0,
17157 sizeof(profile
->ssid
.SSID
));
17158 profile
->ssid
.SSID_len
= MIN(ssid
->SSID_len
, DOT11_MAX_SSID_LEN
);
17159 memcpy(profile
->ssid
.SSID
, ssid
->SSID
, profile
->ssid
.SSID_len
);
17161 case WL_PROF_BSSID
:
17163 memcpy(profile
->bssid
, data
, ETHER_ADDR_LEN
);
17165 memset(profile
->bssid
, 0, ETHER_ADDR_LEN
);
17168 memcpy(&profile
->sec
, data
, sizeof(profile
->sec
));
17171 profile
->active
= *(const bool *)data
;
17173 case WL_PROF_BEACONINT
:
17174 profile
->beacon_interval
= *(const u16
*)data
;
17176 case WL_PROF_DTIMPERIOD
:
17177 profile
->dtim_period
= *(const u8
*)data
;
17180 profile
->channel
= *(const u32
*)data
;
17186 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
17188 if (err
== -EOPNOTSUPP
)
17189 WL_ERR(("unsupported item (%d)\n", item
));
17194 void wl_cfg80211_dbg_level(u32 level
)
17197 * prohibit to change debug level
17198 * by insmod parameter.
17199 * eventually debug level will be configured
17200 * in compile time by using CONFIG_XXX
17202 /* wl_dbg_level = level; */
17205 static bool wl_is_ibssmode(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
)
17207 return wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_IBSS
;
17210 static __used
bool wl_is_ibssstarter(struct bcm_cfg80211
*cfg
)
17212 return cfg
->ibss_starter
;
17215 static void wl_rst_ie(struct bcm_cfg80211
*cfg
)
17217 struct wl_ie
*ie
= wl_to_ie(cfg
);
17222 static __used s32
wl_add_ie(struct bcm_cfg80211
*cfg
, u8 t
, u8 l
, u8
*v
)
17224 struct wl_ie
*ie
= wl_to_ie(cfg
);
17227 if (unlikely(ie
->offset
+ l
+ 2 > WL_TLV_INFO_MAX
)) {
17228 WL_ERR(("ei crosses buffer boundary\n"));
17231 ie
->buf
[ie
->offset
] = t
;
17232 ie
->buf
[ie
->offset
+ 1] = l
;
17233 memcpy(&ie
->buf
[ie
->offset
+ 2], v
, l
);
17234 ie
->offset
+= l
+ 2;
17239 static void wl_update_hidden_ap_ie(struct wl_bss_info
*bi
, const u8
*ie_stream
, u32
*ie_size
,
17243 int32 ssid_len
= MIN(bi
->SSID_len
, DOT11_MAX_SSID_LEN
);
17244 int32 remaining_ie_buf_len
, available_buffer_len
;
17245 /* cfg80211_find_ie defined in kernel returning const u8 */
17246 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
17247 4 && __GNUC_MINOR__ >= 6))
17248 _Pragma("GCC diagnostic push")
17249 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
17251 ssidie
= (u8
*)cfg80211_find_ie(WLAN_EID_SSID
, ie_stream
, *ie_size
);
17252 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
17253 4 && __GNUC_MINOR__ >= 6))
17254 _Pragma("GCC diagnostic pop")
17257 * 1. No ssid IE is FOUND or
17258 * 2. New ssid length is > what was allocated for existing ssid (as
17259 * we do not want to overwrite the rest of the IEs) or
17260 * 3. If in case of erroneous buffer input where ssid length doesnt match the space
17266 available_buffer_len
= ((int)(*ie_size
)) - (ssidie
+ 2 - ie_stream
);
17267 remaining_ie_buf_len
= available_buffer_len
- (int)ssidie
[1];
17268 if ((ssid_len
> ssidie
[1]) ||
17269 (ssidie
[1] > available_buffer_len
)) {
17274 if (ssidie
[1] != ssid_len
) {
17276 WL_ERR(("%s: Wrong SSID len: %d != %d\n",
17277 __FUNCTION__
, ssidie
[1], bi
->SSID_len
));
17280 WL_ERR(("Changing the SSID Info.\n"));
17281 memmove(ssidie
+ ssid_len
+ 2,
17282 (ssidie
+ 2) + ssidie
[1],
17283 remaining_ie_buf_len
);
17284 memcpy(ssidie
+ 2, bi
->SSID
, ssid_len
);
17285 *ie_size
= *ie_size
+ ssid_len
- ssidie
[1];
17286 ssidie
[1] = ssid_len
;
17290 if (*(ssidie
+ 2) == '\0')
17291 memcpy(ssidie
+ 2, bi
->SSID
, ssid_len
);
17295 static s32
wl_mrg_ie(struct bcm_cfg80211
*cfg
, u8
*ie_stream
, u16 ie_size
)
17297 struct wl_ie
*ie
= wl_to_ie(cfg
);
17300 if (unlikely(ie
->offset
+ ie_size
> WL_TLV_INFO_MAX
)) {
17301 WL_ERR(("ei_stream crosses buffer boundary\n"));
17304 memcpy(&ie
->buf
[ie
->offset
], ie_stream
, ie_size
);
17305 ie
->offset
+= ie_size
;
17310 static s32
wl_cp_ie(struct bcm_cfg80211
*cfg
, u8
*dst
, u16 dst_size
)
17312 struct wl_ie
*ie
= wl_to_ie(cfg
);
17315 if (unlikely(ie
->offset
> dst_size
)) {
17316 WL_ERR(("dst_size is not enough\n"));
17319 memcpy(dst
, &ie
->buf
[0], ie
->offset
);
17324 static u32
wl_get_ielen(struct bcm_cfg80211
*cfg
)
17326 struct wl_ie
*ie
= wl_to_ie(cfg
);
17331 static void wl_link_up(struct bcm_cfg80211
*cfg
)
17333 cfg
->link_up
= true;
17336 static void wl_link_down(struct bcm_cfg80211
*cfg
)
17338 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
17341 cfg
->link_up
= false;
17343 conn_info
->req_ie_len
= 0;
17344 conn_info
->resp_ie_len
= 0;
17348 static unsigned long wl_lock_eq(struct bcm_cfg80211
*cfg
)
17350 unsigned long flags
;
17352 spin_lock_irqsave(&cfg
->eq_lock
, flags
);
17356 static void wl_unlock_eq(struct bcm_cfg80211
*cfg
, unsigned long flags
)
17358 spin_unlock_irqrestore(&cfg
->eq_lock
, flags
);
17361 static void wl_init_eq_lock(struct bcm_cfg80211
*cfg
)
17363 spin_lock_init(&cfg
->eq_lock
);
17366 static void wl_delay(u32 ms
)
17368 if (in_atomic() || (ms
< jiffies_to_msecs(1))) {
17369 OSL_DELAY(ms
*1000);
17375 s32
wl_cfg80211_get_p2p_dev_addr(struct net_device
*net
, struct ether_addr
*p2pdev_addr
)
17377 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17378 struct ether_addr primary_mac
;
17381 if (!p2p_is_on(cfg
)) {
17382 get_primary_mac(cfg
, &primary_mac
);
17383 wl_cfgp2p_generate_bss_mac(cfg
, &primary_mac
);
17385 memcpy(p2pdev_addr
->octet
, wl_to_p2p_bss_macaddr(cfg
, P2PAPI_BSSCFG_DEVICE
).octet
,
17391 s32
wl_cfg80211_set_p2p_noa(struct net_device
*net
, char* buf
, int len
)
17393 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17395 return wl_cfgp2p_set_p2p_noa(cfg
, net
, buf
, len
);
17398 s32
wl_cfg80211_get_p2p_noa(struct net_device
*net
, char* buf
, int len
)
17400 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17402 return wl_cfgp2p_get_p2p_noa(cfg
, net
, buf
, len
);
17405 s32
wl_cfg80211_set_p2p_ps(struct net_device
*net
, char* buf
, int len
)
17407 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17409 return wl_cfgp2p_set_p2p_ps(cfg
, net
, buf
, len
);
17412 s32
wl_cfg80211_set_p2p_ecsa(struct net_device
*net
, char* buf
, int len
)
17414 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17416 return wl_cfgp2p_set_p2p_ecsa(cfg
, net
, buf
, len
);
17419 s32
wl_cfg80211_increase_p2p_bw(struct net_device
*net
, char* buf
, int len
)
17421 struct bcm_cfg80211
*cfg
= wl_get_cfg(net
);
17423 return wl_cfgp2p_increase_p2p_bw(cfg
, net
, buf
, len
);
17426 #ifdef P2PLISTEN_AP_SAMECHN
17427 s32
wl_cfg80211_set_p2p_resp_ap_chn(struct net_device
*net
, s32 enable
)
17429 s32 ret
= wldev_iovar_setint(net
, "p2p_resp_ap_chn", enable
);
17431 if ((ret
== 0) && enable
) {
17432 /* disable PM for p2p responding on infra AP channel */
17435 ret
= wldev_ioctl_set(net
, WLC_SET_PM
, &pm
, sizeof(pm
));
17440 #endif /* P2PLISTEN_AP_SAMECHN */
17442 s32
wl_cfg80211_channel_to_freq(u32 channel
)
17446 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
17447 freq
= ieee80211_channel_to_frequency(channel
);
17451 if (channel
<= CH_MAX_2G_CHANNEL
)
17452 band
= IEEE80211_BAND_2GHZ
;
17454 band
= IEEE80211_BAND_5GHZ
;
17455 freq
= ieee80211_channel_to_frequency(channel
, band
);
17464 wl_tdls_event_handler(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
17465 const wl_event_msg_t
*e
, void *data
) {
17467 struct net_device
*ndev
= NULL
;
17468 u32 reason
= ntoh32(e
->reason
);
17471 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
17474 case WLC_E_TDLS_PEER_DISCOVERED
:
17475 msg
= " TDLS PEER DISCOVERD ";
17477 case WLC_E_TDLS_PEER_CONNECTED
:
17478 if (cfg
->tdls_mgmt_frame
) {
17479 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
17480 cfg80211_rx_mgmt(cfgdev
, cfg
->tdls_mgmt_freq
, 0,
17481 cfg
->tdls_mgmt_frame
, cfg
->tdls_mgmt_frame_len
, 0);
17482 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
17483 cfg80211_rx_mgmt(cfgdev
, cfg
->tdls_mgmt_freq
, 0,
17484 cfg
->tdls_mgmt_frame
, cfg
->tdls_mgmt_frame_len
, 0,
17486 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
17487 defined(WL_COMPAT_WIRELESS)
17488 cfg80211_rx_mgmt(cfgdev
, cfg
->tdls_mgmt_freq
, 0,
17489 cfg
->tdls_mgmt_frame
, cfg
->tdls_mgmt_frame_len
,
17492 cfg80211_rx_mgmt(cfgdev
, cfg
->tdls_mgmt_freq
,
17493 cfg
->tdls_mgmt_frame
, cfg
->tdls_mgmt_frame_len
, GFP_ATOMIC
);
17496 msg
= " TDLS PEER CONNECTED ";
17497 #ifdef SUPPORT_SET_CAC
17498 /* TDLS connect reset CAC */
17499 wl_cfg80211_set_cac(cfg
, 0);
17500 #endif /* SUPPORT_SET_CAC */
17502 case WLC_E_TDLS_PEER_DISCONNECTED
:
17503 if (cfg
->tdls_mgmt_frame
) {
17504 kfree(cfg
->tdls_mgmt_frame
);
17505 cfg
->tdls_mgmt_frame
= NULL
;
17506 cfg
->tdls_mgmt_freq
= 0;
17508 msg
= "TDLS PEER DISCONNECTED ";
17509 #ifdef SUPPORT_SET_CAC
17510 /* TDLS disconnec, set CAC */
17511 wl_cfg80211_set_cac(cfg
, 1);
17512 #endif /* SUPPORT_SET_CAC */
17516 WL_ERR(("%s: " MACDBG
" on %s ndev\n", msg
, MAC2STRDBG((const u8
*)(&e
->addr
)),
17517 (bcmcfg_to_prmry_ndev(cfg
) == ndev
) ? "primary" : "secondary"));
17522 #endif /* WLTDLS */
17524 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
17526 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
17527 KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
17528 wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
17529 u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
17530 u32 peer_capability
, const u8
*buf
, size_t len
)
17531 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
17532 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
17533 wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
17534 const u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
17535 u32 peer_capability
, const u8
*buf
, size_t len
)
17536 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
17537 wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
17538 const u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
17539 u32 peer_capability
, bool initiator
, const u8
*buf
, size_t len
)
17540 #else /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17541 wl_cfg80211_tdls_mgmt(struct wiphy
*wiphy
, struct net_device
*dev
,
17542 u8
*peer
, u8 action_code
, u8 dialog_token
, u16 status_code
,
17543 const u8
*buf
, size_t len
)
17544 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17548 struct bcm_cfg80211
*cfg
;
17549 tdls_wfd_ie_iovar_t info
;
17550 memset(&info
, 0, sizeof(tdls_wfd_ie_iovar_t
));
17551 cfg
= wl_get_cfg(dev
);
17553 #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
17554 /* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
17555 * and that cuases build error
17557 BCM_REFERENCE(peer_capability
);
17558 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17560 switch (action_code
) {
17561 /* We need to set TDLS Wifi Display IE to firmware
17562 * using tdls_wfd_ie iovar
17564 case WLAN_TDLS_SET_PROBE_WFD_IE
:
17565 WL_ERR(("%s WLAN_TDLS_SET_PROBE_WFD_IE\n", __FUNCTION__
));
17566 info
.mode
= TDLS_WFD_PROBE_IE_TX
;
17567 memcpy(&info
.data
, buf
, len
);
17570 case WLAN_TDLS_SET_SETUP_WFD_IE
:
17571 WL_ERR(("%s WLAN_TDLS_SET_SETUP_WFD_IE\n", __FUNCTION__
));
17572 info
.mode
= TDLS_WFD_IE_TX
;
17573 memcpy(&info
.data
, buf
, len
);
17576 case WLAN_TDLS_SET_WFD_ENABLED
:
17577 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_ENABLED\n", __FUNCTION__
));
17578 dhd_tdls_set_mode((dhd_pub_t
*)(cfg
->pub
), true);
17580 case WLAN_TDLS_SET_WFD_DISABLED
:
17581 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_DISABLED\n", __FUNCTION__
));
17582 dhd_tdls_set_mode((dhd_pub_t
*)(cfg
->pub
), false);
17585 WL_ERR(("Unsupported action code : %d\n", action_code
));
17588 ret
= wldev_iovar_setbuf(dev
, "tdls_wfd_ie", &info
, sizeof(info
),
17589 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
17592 WL_ERR(("tdls_wfd_ie error %d\n", ret
));
17596 #endif /* WLTDLS */
17601 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
17602 wl_cfg80211_tdls_oper(struct wiphy
*wiphy
, struct net_device
*dev
,
17603 const u8
*peer
, enum nl80211_tdls_operation oper
)
17605 wl_cfg80211_tdls_oper(struct wiphy
*wiphy
, struct net_device
*dev
,
17606 u8
*peer
, enum nl80211_tdls_operation oper
)
17611 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
17614 bool tdls_auto_mode
= false;
17615 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
17616 memset(&info
, 0, sizeof(tdls_iovar_t
));
17618 memcpy(&info
.ea
, peer
, ETHER_ADDR_LEN
);
17623 case NL80211_TDLS_DISCOVERY_REQ
:
17624 /* If the discovery request is broadcast then we need to set
17625 * info.mode to Tunneled Probe Request
17627 if (memcmp(peer
, (const uint8
*)BSSID_BROADCAST
, ETHER_ADDR_LEN
) == 0) {
17628 info
.mode
= TDLS_MANUAL_EP_WFD_TPQ
;
17629 WL_ERR(("%s TDLS TUNNELED PRBOBE REQUEST\n", __FUNCTION__
));
17631 info
.mode
= TDLS_MANUAL_EP_DISCOVERY
;
17634 case NL80211_TDLS_SETUP
:
17635 if (dhdp
->tdls_mode
== true) {
17636 info
.mode
= TDLS_MANUAL_EP_CREATE
;
17637 tdls_auto_mode
= false;
17638 /* Do tear down and create a fresh one */
17639 ret
= wl_cfg80211_tdls_config(cfg
, TDLS_STATE_TEARDOWN
, tdls_auto_mode
);
17644 tdls_auto_mode
= true;
17647 case NL80211_TDLS_TEARDOWN
:
17648 info
.mode
= TDLS_MANUAL_EP_DELETE
;
17651 WL_ERR(("Unsupported operation : %d\n", oper
));
17655 wl_cfg80211_tdls_config(cfg
, TDLS_STATE_SETUP
, tdls_auto_mode
);
17660 ret
= wldev_iovar_setbuf(dev
, "tdls_endpoint", &info
, sizeof(info
),
17661 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
);
17663 WL_ERR(("tdls_endpoint error %d\n", ret
));
17670 #endif /* WLTDLS */
17676 * This function returns no of bytes written
17677 * In case of failure return zero, not bcme_error
17679 s32
wl_cfg80211_set_wps_p2p_ie(struct net_device
*ndev
, char *buf
, int len
,
17680 enum wl_management_type type
)
17682 struct bcm_cfg80211
*cfg
;
17684 struct ether_addr primary_mac
;
17687 cfg
= wl_get_cfg(ndev
);
17689 if (wl_get_drv_status(cfg
, AP_CREATING
, ndev
)) {
17690 /* Vendor IEs should be set to FW
17691 * after SoftAP interface is brought up
17693 WL_DBG(("Skipping set IE since AP is not up \n"));
17695 } else if (ndev
== bcmcfg_to_prmry_ndev(cfg
)) {
17696 /* Either stand alone AP case or P2P discovery */
17697 if (wl_get_drv_status(cfg
, AP_CREATED
, ndev
)) {
17698 /* Stand alone AP case on primary interface */
17699 WL_DBG(("Apply IEs for Primary AP Interface \n"));
17703 /* If p2p not initialized, return failure */
17704 WL_ERR(("P2P not initialized \n"));
17707 /* P2P Discovery case (p2p listen) */
17708 if (!cfg
->p2p
->on
) {
17709 /* Turn on Discovery interface */
17710 get_primary_mac(cfg
, &primary_mac
);
17711 wl_cfgp2p_generate_bss_mac(cfg
, &primary_mac
);
17712 p2p_on(cfg
) = true;
17713 ret
= wl_cfgp2p_enable_discovery(cfg
, ndev
, NULL
, 0);
17714 if (unlikely(ret
)) {
17715 WL_ERR(("Enable discovery failed \n"));
17719 WL_DBG(("Apply IEs for P2P Discovery Iface \n"));
17720 ndev
= wl_to_p2p_bss_ndev(cfg
, P2PAPI_BSSCFG_PRIMARY
);
17721 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
17724 /* Virtual AP/ P2P Group Interface */
17725 WL_DBG(("Apply IEs for iface:%s\n", ndev
->name
));
17726 bssidx
= wl_get_bssidx_by_wdev(cfg
, ndev
->ieee80211_ptr
);
17729 if (ndev
!= NULL
) {
17732 pktflag
= VNDR_IE_BEACON_FLAG
;
17734 case WL_PROBE_RESP
:
17735 pktflag
= VNDR_IE_PRBRSP_FLAG
;
17737 case WL_ASSOC_RESP
:
17738 pktflag
= VNDR_IE_ASSOCRSP_FLAG
;
17742 ret
= wl_cfg80211_set_mgmt_vndr_ies(cfg
,
17743 ndev_to_cfgdev(ndev
), bssidx
, pktflag
, buf
, len
);
17750 #ifdef WL_SUPPORT_AUTO_CHANNEL
17752 wl_cfg80211_set_auto_channel_scan_state(struct net_device
*ndev
)
17755 s32 ret
= BCME_ERROR
;
17756 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
17757 /* Set interface up, explicitly. */
17760 ret
= wldev_ioctl_set(ndev
, WLC_UP
, (void *)&val
, sizeof(val
));
17762 WL_ERR(("set interface up failed, error = %d\n", ret
));
17766 /* Stop all scan explicitly, till auto channel selection complete. */
17767 wl_set_drv_status(cfg
, SCANNING
, ndev
);
17768 if (cfg
->escan_info
.ndev
== NULL
) {
17772 ret
= wl_notify_escan_complete(cfg
, ndev
, true, true);
17774 WL_ERR(("set scan abort failed, error = %d\n", ret
));
17775 ret
= BCME_OK
; // terence 20140115: fix escan_complete error
17784 wl_cfg80211_valid_channel_p2p(int channel
)
17786 bool valid
= false;
17788 /* channel 1 to 14 */
17789 if ((channel
>= 1) && (channel
<= 14)) {
17792 /* channel 36 to 48 */
17793 else if ((channel
>= 36) && (channel
<= 48)) {
17796 /* channel 149 to 161 */
17797 else if ((channel
>= 149) && (channel
<= 161)) {
17802 WL_INFORM(("invalid P2P chanspec, channel = %d\n", channel
));
17809 wl_cfg80211_get_chanspecs_2g(struct net_device
*ndev
, void *buf
, s32 buflen
)
17811 s32 ret
= BCME_ERROR
;
17812 struct bcm_cfg80211
*cfg
= NULL
;
17813 chanspec_t chanspec
= 0;
17815 cfg
= wl_get_cfg(ndev
);
17817 /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
17818 chanspec
|= (WL_CHANSPEC_BAND_2G
| WL_CHANSPEC_BW_20
|
17819 WL_CHANSPEC_CTL_SB_NONE
);
17820 chanspec
= wl_chspec_host_to_driver(chanspec
);
17822 ret
= wldev_iovar_getbuf_bsscfg(ndev
, "chanspecs", (void *)&chanspec
,
17823 sizeof(chanspec
), buf
, buflen
, 0, &cfg
->ioctl_buf_sync
);
17825 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret
));
17832 wl_cfg80211_get_chanspecs_5g(struct net_device
*ndev
, void *buf
, s32 buflen
)
17835 s32 ret
= BCME_ERROR
;
17838 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
17839 wl_uint32_list_t
*list
= NULL
;
17840 chanspec_t chanspec
= 0;
17842 /* Restrict channels to 5GHz, 20MHz BW, no SB. */
17843 chanspec
|= (WL_CHANSPEC_BAND_5G
| WL_CHANSPEC_BW_20
|
17844 WL_CHANSPEC_CTL_SB_NONE
);
17845 chanspec
= wl_chspec_host_to_driver(chanspec
);
17847 ret
= wldev_iovar_getbuf_bsscfg(ndev
, "chanspecs", (void *)&chanspec
,
17848 sizeof(chanspec
), buf
, buflen
, 0, &cfg
->ioctl_buf_sync
);
17850 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret
));
17854 list
= (wl_uint32_list_t
*)buf
;
17855 /* Skip DFS and inavlid P2P channel. */
17856 for (i
= 0, j
= 0; i
< dtoh32(list
->count
); i
++) {
17857 chanspec
= (chanspec_t
) dtoh32(list
->element
[i
]);
17858 channel
= CHSPEC_CHANNEL(chanspec
);
17860 ret
= wldev_iovar_getint(ndev
, "per_chan_info", &channel
);
17862 WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret
));
17866 if (CHANNEL_IS_RADAR(channel
) ||
17867 !(wl_cfg80211_valid_channel_p2p(CHSPEC_CHANNEL(chanspec
)))) {
17870 list
->element
[j
] = list
->element
[i
];
17883 wl_cfg80211_get_best_channel(struct net_device
*ndev
, void *buf
, int buflen
,
17886 s32 ret
= BCME_ERROR
;
17891 /* Start auto channel selection scan. */
17892 ret
= wldev_ioctl_set(ndev
, WLC_START_CHANNEL_SEL
, buf
, buflen
);
17894 WL_ERR(("can't start auto channel scan, error = %d\n", ret
));
17899 /* Wait for auto channel selection, worst case possible delay is 5250ms. */
17900 retry
= CHAN_SEL_RETRY_COUNT
;
17903 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY
);
17905 ret
= wldev_ioctl_get(ndev
, WLC_GET_CHANNEL_SEL
, &chosen
, sizeof(chosen
));
17906 if ((ret
== 0) && (dtoh32(chosen
) != 0)) {
17907 chip
= dhd_conf_get_chip(dhd_get_pub(ndev
));
17908 if (chip
!= BCM43362_CHIP_ID
&& chip
!= BCM4330_CHIP_ID
&&
17909 chip
!= BCM43143_CHIP_ID
) {
17912 chanspec
= wl_chspec_driver_to_host(chosen
);
17913 WL_INFORM(("selected chanspec = 0x%x\n", chanspec
));
17914 ctl_chan
= wf_chspec_ctlchan(chanspec
);
17915 WL_INFORM(("selected ctl_chan = %d\n", ctl_chan
));
17916 *channel
= (u16
)(ctl_chan
& 0x00FF);
17918 *channel
= (u16
)(chosen
& 0x00FF);
17919 WL_INFORM(("selected channel = %d\n", *channel
));
17922 WL_INFORM(("attempt = %d, ret = %d, chosen = %d\n",
17923 (CHAN_SEL_RETRY_COUNT
- retry
), ret
, dtoh32(chosen
)));
17927 WL_ERR(("failure, auto channel selection timed out\n"));
17931 WL_INFORM(("selected channel = %d\n", *channel
));
17938 wl_cfg80211_restore_auto_channel_scan_state(struct net_device
*ndev
)
17940 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
17941 /* Clear scan stop driver status. */
17942 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
17948 wl_cfg80211_get_best_channels(struct net_device
*dev
, char* cmd
, int total_len
)
17950 int channel
= 0, band
, band_cur
;
17951 s32 ret
= BCME_ERROR
;
17954 struct bcm_cfg80211
*cfg
= NULL
;
17955 struct net_device
*ndev
= NULL
;
17957 memset(cmd
, 0, total_len
);
17959 buf
= kmalloc(CHANSPEC_BUF_SIZE
, GFP_KERNEL
);
17961 WL_ERR(("failed to allocate chanspec buffer\n"));
17966 * Always use primary interface, irrespective of interface on which
17969 cfg
= wl_get_cfg(dev
);
17970 ndev
= bcmcfg_to_prmry_ndev(cfg
);
17973 * Make sure that FW and driver are in right state to do auto channel
17976 ret
= wl_cfg80211_set_auto_channel_scan_state(ndev
);
17978 WL_ERR(("can't set auto channel scan state, error = %d\n", ret
));
17982 ret
= wldev_ioctl(dev
, WLC_GET_BAND
, &band_cur
, sizeof(band_cur
), false);
17983 if (band_cur
!= WLC_BAND_5G
) {
17984 /* Best channel selection in 2.4GHz band. */
17985 ret
= wl_cfg80211_get_chanspecs_2g(ndev
, (void *)buf
, CHANSPEC_BUF_SIZE
);
17987 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret
));
17991 ret
= wl_cfg80211_get_best_channel(ndev
, (void *)buf
, CHANSPEC_BUF_SIZE
,
17994 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret
));
17998 if (CHANNEL_IS_2G(channel
)) {
18000 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
18001 channel
= ieee80211_channel_to_frequency(channel
);
18003 channel
= ieee80211_channel_to_frequency(channel
, IEEE80211_BAND_2GHZ
);
18007 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel
));
18010 pos
+= snprintf(pos
, total_len
, "2g=%d ", channel
);
18013 if (band_cur
!= WLC_BAND_2G
) {
18014 // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
18015 band
= band_cur
==WLC_BAND_2G
? band_cur
: WLC_BAND_5G
;
18016 ret
= wldev_ioctl(dev
, WLC_SET_BAND
, &band
, sizeof(band
), true);
18018 WL_ERR(("WLC_SET_BAND error %d\n", ret
));
18020 /* Best channel selection in 5GHz band. */
18021 ret
= wl_cfg80211_get_chanspecs_5g(ndev
, (void *)buf
, CHANSPEC_BUF_SIZE
);
18023 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret
));
18027 ret
= wl_cfg80211_get_best_channel(ndev
, (void *)buf
, CHANSPEC_BUF_SIZE
,
18030 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret
));
18034 if (CHANNEL_IS_5G(channel
)) {
18036 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
18037 channel
= ieee80211_channel_to_frequency(channel
);
18039 channel
= ieee80211_channel_to_frequency(channel
, IEEE80211_BAND_5GHZ
);
18043 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel
));
18047 ret
= wldev_ioctl(dev
, WLC_SET_BAND
, &band_cur
, sizeof(band_cur
), true);
18049 WL_ERR(("WLC_SET_BAND error %d\n", ret
));
18050 pos
+= snprintf(pos
, total_len
, "5g=%d ", channel
);
18058 /* Restore FW and driver back to normal state. */
18059 ret
= wl_cfg80211_restore_auto_channel_scan_state(ndev
);
18061 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret
));
18064 printf("%s: %s\n", __FUNCTION__
, cmd
);
18066 return (pos
- cmd
);
18068 #endif /* WL_SUPPORT_AUTO_CHANNEL */
18070 static const struct rfkill_ops wl_rfkill_ops
= {
18071 .set_block
= wl_rfkill_set
18074 static int wl_rfkill_set(void *data
, bool blocked
)
18076 struct bcm_cfg80211
*cfg
= (struct bcm_cfg80211
*)data
;
18078 WL_DBG(("Enter \n"));
18079 WL_DBG(("RF %s\n", blocked
? "blocked" : "unblocked"));
18084 cfg
->rf_blocked
= blocked
;
18089 static int wl_setup_rfkill(struct bcm_cfg80211
*cfg
, bool setup
)
18093 WL_DBG(("Enter \n"));
18097 cfg
->rfkill
= rfkill_alloc("brcmfmac-wifi",
18098 wl_cfg80211_get_parent_dev(),
18099 RFKILL_TYPE_WLAN
, &wl_rfkill_ops
, (void *)cfg
);
18101 if (!cfg
->rfkill
) {
18106 err
= rfkill_register(cfg
->rfkill
);
18109 rfkill_destroy(cfg
->rfkill
);
18111 if (!cfg
->rfkill
) {
18116 rfkill_unregister(cfg
->rfkill
);
18117 rfkill_destroy(cfg
->rfkill
);
18124 #ifdef DEBUGFS_CFG80211
18126 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
18127 * to turn on SCAN and DBG log.
18128 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
18129 * To see current setting of debug level,
18130 * cat /sys/kernel/debug/dhd/debug_level
18133 wl_debuglevel_write(struct file
*file
, const char __user
*userbuf
,
18134 size_t count
, loff_t
*ppos
)
18136 char tbuf
[S_SUBLOGLEVEL
* ARRAYSIZE(sublogname_map
)], sublog
[S_SUBLOGLEVEL
];
18137 char *params
, *token
, *colon
;
18138 uint i
, tokens
, log_on
= 0;
18139 size_t minsize
= min_t(size_t, (sizeof(tbuf
) - 1), count
);
18141 memset(tbuf
, 0, sizeof(tbuf
));
18142 memset(sublog
, 0, sizeof(sublog
));
18143 if (copy_from_user(&tbuf
, userbuf
, minsize
)) {
18147 tbuf
[minsize
+ 1] = '\0';
18149 colon
= strchr(params
, '\n');
18152 while ((token
= strsep(¶ms
, " ")) != NULL
) {
18153 memset(sublog
, 0, sizeof(sublog
));
18154 if (token
== NULL
|| !*token
)
18156 if (*token
== '\0')
18158 colon
= strchr(token
, ':');
18159 if (colon
!= NULL
) {
18162 tokens
= sscanf(token
, "%s %u", sublog
, &log_on
);
18167 for (i
= 0; i
< ARRAYSIZE(sublogname_map
); i
++) {
18168 if (!strncmp(sublog
, sublogname_map
[i
].sublogname
,
18169 strlen(sublogname_map
[i
].sublogname
))) {
18172 (sublogname_map
[i
].log_level
);
18175 ~(sublogname_map
[i
].log_level
);
18179 WL_ERR(("%s: can't parse '%s' as a "
18180 "SUBMODULE:LEVEL (%d tokens)\n",
18181 tbuf
, token
, tokens
));
18189 wl_debuglevel_read(struct file
*file
, char __user
*user_buf
,
18190 size_t count
, loff_t
*ppos
)
18193 char tbuf
[S_SUBLOGLEVEL
* ARRAYSIZE(sublogname_map
)];
18195 memset(tbuf
, 0, sizeof(tbuf
));
18197 for (i
= 0; i
< ARRAYSIZE(sublogname_map
); i
++) {
18198 param
+= snprintf(param
, sizeof(tbuf
) - 1, "%s:%d ",
18199 sublogname_map
[i
].sublogname
,
18200 (wl_dbg_level
& sublogname_map
[i
].log_level
) ? 1 : 0);
18203 return simple_read_from_buffer(user_buf
, count
, ppos
, tbuf
, strlen(&tbuf
[0]));
18206 static const struct file_operations fops_debuglevel
= {
18208 .write
= wl_debuglevel_write
,
18209 .read
= wl_debuglevel_read
,
18210 .owner
= THIS_MODULE
,
18214 static s32
wl_setup_debugfs(struct bcm_cfg80211
*cfg
)
18217 struct dentry
*_dentry
;
18220 cfg
->debugfs
= debugfs_create_dir(KBUILD_MODNAME
, NULL
);
18221 if (!cfg
->debugfs
|| IS_ERR(cfg
->debugfs
)) {
18222 if (cfg
->debugfs
== ERR_PTR(-ENODEV
))
18223 WL_ERR(("Debugfs is not enabled on this kernel\n"));
18225 WL_ERR(("Can not create debugfs directory\n"));
18226 cfg
->debugfs
= NULL
;
18230 _dentry
= debugfs_create_file("debug_level", S_IRUSR
| S_IWUSR
,
18231 cfg
->debugfs
, cfg
, &fops_debuglevel
);
18232 if (!_dentry
|| IS_ERR(_dentry
)) {
18233 WL_ERR(("failed to create debug_level debug file\n"));
18234 wl_free_debugfs(cfg
);
18239 static s32
wl_free_debugfs(struct bcm_cfg80211
*cfg
)
18244 debugfs_remove_recursive(cfg
->debugfs
);
18245 cfg
->debugfs
= NULL
;
18248 #endif /* DEBUGFS_CFG80211 */
18250 struct device
*wl_cfg80211_get_parent_dev(void)
18252 return cfg80211_parent_dev
;
18255 void wl_cfg80211_set_parent_dev(void *dev
)
18257 cfg80211_parent_dev
= dev
;
18260 static void wl_cfg80211_clear_parent_dev(void)
18262 cfg80211_parent_dev
= NULL
;
18265 void get_primary_mac(struct bcm_cfg80211
*cfg
, struct ether_addr
*mac
)
18267 if (wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg
), "cur_etheraddr", NULL
,
18268 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, 0, &cfg
->ioctl_buf_sync
) == BCME_OK
) {
18269 memcpy(mac
->octet
, cfg
->ioctl_buf
, ETHER_ADDR_LEN
);
18271 memset(mac
->octet
, 0, ETHER_ADDR_LEN
);
18274 static bool check_dev_role_integrity(struct bcm_cfg80211
*cfg
, u32 dev_role
)
18276 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
18277 if (((dev_role
== NL80211_IFTYPE_AP
) &&
18278 !(dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) ||
18279 ((dev_role
== NL80211_IFTYPE_P2P_GO
) &&
18280 !(dhd
->op_mode
& DHD_FLAG_P2P_GO_MODE
)))
18282 WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role
, dhd
->op_mode
));
18288 int wl_cfg80211_do_driver_init(struct net_device
*net
)
18290 struct bcm_cfg80211
*cfg
= *(struct bcm_cfg80211
**)netdev_priv(net
);
18292 if (!cfg
|| !cfg
->wdev
)
18295 if (dhd_do_driver_init(cfg
->wdev
->netdev
) < 0)
18301 void wl_cfg80211_enable_trace(u32 level
)
18303 wl_dbg_level
= level
;
18304 printf("%s: wl_dbg_level = 0x%x\n", __FUNCTION__
, wl_dbg_level
);
18307 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
18310 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy
*wiphy
,
18311 bcm_struct_cfgdev
*cfgdev
, u64 cookie
)
18313 /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
18314 * is passed with CMD_FRAME. This callback is supposed to cancel
18315 * the OFFCHANNEL Wait. Since we are already taking care of that
18316 * with the tx_mgmt logic, do nothing here.
18321 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
18325 wl_cfg80211_find_interworking_ie(const u8
*parse
, u32 len
)
18329 /* unfortunately it's too much work to dispose the const cast - bcm_parse_tlvs
18330 * is used everywhere and changing its prototype to take const qualifier needs
18331 * a massive change to all its callers...
18333 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
18334 4 && __GNUC_MINOR__ >= 6))
18335 _Pragma("GCC diagnostic push")
18336 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
18338 if ((ie
= bcm_parse_tlvs((void *)parse
, (int)len
, DOT11_MNG_INTERWORKING_ID
))) {
18341 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
18342 4 && __GNUC_MINOR__ >= 6))
18343 _Pragma("GCC diagnostic pop")
18349 wl_cfg80211_clear_iw_ie(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 bssidx
)
18351 ie_setbuf_t ie_setbuf
;
18353 WL_DBG(("clear interworking IE\n"));
18355 memset(&ie_setbuf
, 0, sizeof(ie_setbuf_t
));
18357 ie_setbuf
.ie_buffer
.iecount
= htod32(1);
18358 ie_setbuf
.ie_buffer
.ie_list
[0].ie_data
.id
= DOT11_MNG_INTERWORKING_ID
;
18359 ie_setbuf
.ie_buffer
.ie_list
[0].ie_data
.len
= 0;
18361 return wldev_iovar_setbuf_bsscfg(ndev
, "ie", &ie_setbuf
, sizeof(ie_setbuf
),
18362 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
18366 wl_cfg80211_add_iw_ie(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, s32 bssidx
, s32 pktflag
,
18367 uint8 ie_id
, uint8
*data
, uint8 data_len
)
18371 ie_setbuf_t
*ie_setbuf
;
18372 ie_getbuf_t ie_getbufp
;
18373 char getbuf
[WLC_IOCTL_SMLEN
];
18375 if (ie_id
!= DOT11_MNG_INTERWORKING_ID
) {
18376 WL_ERR(("unsupported (id=%d)\n", ie_id
));
18377 return BCME_UNSUPPORTED
;
18380 /* access network options (1 octet) is the mandatory field */
18381 if (!data
|| data_len
== 0 || data_len
> IW_IES_MAX_BUF_LEN
) {
18382 WL_ERR(("wrong interworking IE (len=%d)\n", data_len
));
18383 return BCME_BADARG
;
18386 /* Validate the pktflag parameter */
18387 if ((pktflag
& ~(VNDR_IE_BEACON_FLAG
| VNDR_IE_PRBRSP_FLAG
|
18388 VNDR_IE_ASSOCRSP_FLAG
| VNDR_IE_AUTHRSP_FLAG
|
18389 VNDR_IE_PRBREQ_FLAG
| VNDR_IE_ASSOCREQ_FLAG
|
18390 VNDR_IE_CUSTOM_FLAG
))) {
18391 WL_ERR(("invalid packet flag 0x%x\n", pktflag
));
18392 return BCME_BADARG
;
18395 buf_len
= sizeof(ie_setbuf_t
) + data_len
- 1;
18397 ie_getbufp
.id
= DOT11_MNG_INTERWORKING_ID
;
18398 if (wldev_iovar_getbuf_bsscfg(ndev
, "ie", (void *)&ie_getbufp
,
18399 sizeof(ie_getbufp
), getbuf
, WLC_IOCTL_SMLEN
, bssidx
, &cfg
->ioctl_buf_sync
)
18401 if (!memcmp(&getbuf
[TLV_HDR_LEN
], data
, data_len
)) {
18402 WL_DBG(("skip to set interworking IE\n"));
18407 /* if already set with previous values, delete it first */
18409 if ((err
= wl_cfg80211_clear_iw_ie(cfg
, ndev
, bssidx
)) != BCME_OK
) {
18414 ie_setbuf
= (ie_setbuf_t
*) kzalloc(buf_len
, GFP_KERNEL
);
18416 WL_ERR(("Error allocating buffer for IE\n"));
18419 strncpy(ie_setbuf
->cmd
, "add", sizeof(ie_setbuf
->cmd
));
18420 ie_setbuf
->cmd
[sizeof(ie_setbuf
->cmd
) - 1] = '\0';
18422 /* Buffer contains only 1 IE */
18423 ie_setbuf
->ie_buffer
.iecount
= htod32(1);
18424 /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
18425 ie_setbuf
->ie_buffer
.ie_list
[0].pktflag
= htod32(pktflag
);
18427 /* Now, add the IE to the buffer */
18428 ie_setbuf
->ie_buffer
.ie_list
[0].ie_data
.id
= DOT11_MNG_INTERWORKING_ID
;
18429 ie_setbuf
->ie_buffer
.ie_list
[0].ie_data
.len
= data_len
;
18430 memcpy((uchar
*)&ie_setbuf
->ie_buffer
.ie_list
[0].ie_data
.data
[0], data
, data_len
);
18432 if ((err
= wldev_iovar_setbuf_bsscfg(ndev
, "ie", ie_setbuf
, buf_len
,
18433 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, bssidx
, &cfg
->ioctl_buf_sync
))
18435 WL_DBG(("set interworking IE\n"));
18437 err
= wldev_iovar_setint_bsscfg(ndev
, "grat_arp", 1, bssidx
);
18447 wl_cfg80211_set_if_band(struct net_device
*ndev
, int band
)
18449 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
18450 int ret
= 0, wait_cnt
;
18451 char ioctl_buf
[32];
18453 if ((band
< WLC_BAND_AUTO
) || (band
> WLC_BAND_2G
)) {
18454 WL_ERR(("Invalid band\n"));
18457 if (wl_get_drv_status(cfg
, CONNECTED
, ndev
) ||
18458 wl_get_drv_status(cfg
, CONNECTING
, ndev
)) {
18459 /* if driver is connected or connecting status, try to disconnect first.
18460 * if dongle is associated, iovar 'if_band' would be rejected.
18462 wl_set_drv_status(cfg
, DISCONNECTING
, ndev
);
18463 ret
= wldev_ioctl_set(ndev
, WLC_DISASSOC
, NULL
, 0);
18465 WL_ERR(("WLC_DISASSOC error %d\n", ret
));
18466 /* continue to set 'if_band' */
18469 /* This is to ensure that 'if_band' iovar is issued only after
18470 * disconnection is completed
18472 wait_cnt
= WAIT_FOR_DISCONNECT_MAX
;
18473 while (wl_get_drv_status(cfg
, DISCONNECTING
, ndev
) && wait_cnt
) {
18474 WL_DBG(("Wait until disconnected. wait_cnt: %d\n", wait_cnt
));
18480 if ((ret
= wldev_iovar_setbuf(ndev
, "if_band", &band
,
18481 sizeof(int), ioctl_buf
, sizeof(ioctl_buf
), NULL
)) < 0) {
18482 WL_ERR(("seting if_band failed ret=%d\n", ret
));
18483 /* issue 'WLC_SET_BAND' if if_band is not supported */
18484 if (ret
== BCME_UNSUPPORTED
) {
18485 ret
= wldev_set_band(ndev
, band
);
18487 WL_ERR(("seting band failed ret=%d\n", ret
));
18495 wl_cfg80211_dfs_ap_move(struct net_device
*ndev
, char *data
, char *command
, int total_len
)
18497 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
18498 char ioctl_buf
[50];
18501 chanspec_t chanspec
= 0;
18503 int bytes_written
= 0;
18504 wl_dfs_ap_move_status_t
*status
;
18505 char chanbuf
[CHANSPEC_STR_LEN
];
18506 const char *dfs_state_str
[DFS_SCAN_S_MAX
] = {
18507 "Radar Free On Channel",
18508 "Radar Found On Channel",
18509 "Radar Scan In Progress",
18510 "Radar Scan Aborted",
18511 "RSDB Mode switch in Progress For Scan"
18513 if (ndev
->ieee80211_ptr
->iftype
!= NL80211_IFTYPE_AP
) {
18514 bytes_written
= snprintf(command
, total_len
, "AP is not up\n");
18515 return bytes_written
;
18518 if ((err
= wldev_iovar_getbuf(ndev
, "dfs_ap_move", NULL
, 0,
18519 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
18520 WL_ERR(("setting dfs_ap_move failed with err=%d \n", err
));
18523 status
= (wl_dfs_ap_move_status_t
*)cfg
->ioctl_buf
;
18525 if (status
->version
!= WL_DFS_AP_MOVE_VERSION
) {
18526 err
= BCME_UNSUPPORTED
;
18527 WL_ERR(("err=%d version=%d\n", err
, status
->version
));
18531 if (status
->move_status
!= (int8
) DFS_SCAN_S_IDLE
) {
18532 chanspec
= wl_chspec_driver_to_host(status
->chanspec
);
18533 if (chanspec
!= 0 && chanspec
!= INVCHANSPEC
) {
18534 wf_chspec_ntoa(chanspec
, chanbuf
);
18535 bytes_written
= snprintf(command
, total_len
,
18536 "AP Target Chanspec %s (0x%x)\n", chanbuf
, chanspec
);
18539 bytes_written
+= snprintf(command
+ bytes_written
, total_len
,
18540 "%s\n", dfs_state_str
[status
->move_status
]);
18541 return bytes_written
;
18543 bytes_written
= snprintf(command
, total_len
, "dfs AP move in IDLE state\n");
18544 return bytes_written
;
18549 abort
= bcm_atoi(data
);
18551 if ((err
= wldev_iovar_setbuf(ndev
, "dfs_ap_move", &abort
,
18552 sizeof(int), ioctl_buf
, sizeof(ioctl_buf
), NULL
)) < 0) {
18553 WL_ERR(("seting dfs_ap_move failed with err %d\n", err
));
18557 chanspec
= wf_chspec_aton(data
);
18558 if (chanspec
!= 0) {
18559 val
= wl_chspec_host_to_driver(chanspec
);
18560 if (val
!= INVCHANSPEC
) {
18561 if ((err
= wldev_iovar_setbuf(ndev
, "dfs_ap_move", &val
,
18562 sizeof(int), ioctl_buf
, sizeof(ioctl_buf
), NULL
)) < 0) {
18563 WL_ERR(("seting dfs_ap_move failed with err %d\n", err
));
18566 WL_DBG((" set dfs_ap_move successfull"));
18568 err
= BCME_USAGE_ERROR
;
18577 wl_cfg80211_wbtext_set_default(struct net_device
*ndev
)
18579 char commandp
[WLC_IOCTL_SMLEN
];
18583 WL_DBG(("set wbtext to default\n"));
18585 /* set roam profile */
18586 memset(commandp
, 0, sizeof(commandp
));
18587 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18588 CMD_WBTEXT_PROFILE_CONFIG
, DEFAULT_WBTEXT_PROFILE_A
);
18589 data
= (commandp
+ strlen(CMD_WBTEXT_PROFILE_CONFIG
) + 1);
18590 ret
= wl_cfg80211_wbtext_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18591 if (ret
!= BCME_OK
) {
18592 WL_ERR(("%s: Failed to set roam_prof %s error = %d\n",
18593 __FUNCTION__
, data
, ret
));
18597 memset(commandp
, 0, sizeof(commandp
));
18598 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18599 CMD_WBTEXT_PROFILE_CONFIG
, DEFAULT_WBTEXT_PROFILE_B
);
18600 data
= (commandp
+ strlen(CMD_WBTEXT_PROFILE_CONFIG
) + 1);
18601 ret
= wl_cfg80211_wbtext_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18602 if (ret
!= BCME_OK
) {
18603 WL_ERR(("%s: Failed to set roam_prof %s error = %d\n",
18604 __FUNCTION__
, data
, ret
));
18608 /* set RSSI weight */
18609 memset(commandp
, 0, sizeof(commandp
));
18610 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18611 CMD_WBTEXT_WEIGHT_CONFIG
, DEFAULT_WBTEXT_WEIGHT_RSSI_A
);
18612 data
= (commandp
+ strlen(CMD_WBTEXT_WEIGHT_CONFIG
) + 1);
18613 ret
= wl_cfg80211_wbtext_weight_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18614 if (ret
!= BCME_OK
) {
18615 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18616 __FUNCTION__
, data
, ret
));
18620 memset(commandp
, 0, sizeof(commandp
));
18621 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18622 CMD_WBTEXT_WEIGHT_CONFIG
, DEFAULT_WBTEXT_WEIGHT_RSSI_B
);
18623 data
= (commandp
+ strlen(CMD_WBTEXT_WEIGHT_CONFIG
) + 1);
18624 ret
= wl_cfg80211_wbtext_weight_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18625 if (ret
!= BCME_OK
) {
18626 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18627 __FUNCTION__
, data
, ret
));
18631 /* set CU weight */
18632 memset(commandp
, 0, sizeof(commandp
));
18633 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18634 CMD_WBTEXT_WEIGHT_CONFIG
, DEFAULT_WBTEXT_WEIGHT_CU_A
);
18635 data
= (commandp
+ strlen(CMD_WBTEXT_WEIGHT_CONFIG
) + 1);
18636 ret
= wl_cfg80211_wbtext_weight_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18637 if (ret
!= BCME_OK
) {
18638 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18639 __FUNCTION__
, data
, ret
));
18643 memset(commandp
, 0, sizeof(commandp
));
18644 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18645 CMD_WBTEXT_WEIGHT_CONFIG
, DEFAULT_WBTEXT_WEIGHT_CU_B
);
18646 data
= (commandp
+ strlen(CMD_WBTEXT_WEIGHT_CONFIG
) + 1);
18647 ret
= wl_cfg80211_wbtext_weight_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18648 if (ret
!= BCME_OK
) {
18649 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18650 __FUNCTION__
, data
, ret
));
18654 /* set RSSI table */
18655 memset(commandp
, 0, sizeof(commandp
));
18656 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18657 CMD_WBTEXT_TABLE_CONFIG
, DEFAULT_WBTEXT_TABLE_RSSI_A
);
18658 data
= (commandp
+ strlen(CMD_WBTEXT_TABLE_CONFIG
) + 1);
18659 ret
= wl_cfg80211_wbtext_table_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18660 if (ret
!= BCME_OK
) {
18661 WL_ERR(("%s: Failed to set RSSI table %s error = %d\n",
18662 __FUNCTION__
, data
, ret
));
18666 memset(commandp
, 0, sizeof(commandp
));
18667 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18668 CMD_WBTEXT_TABLE_CONFIG
, DEFAULT_WBTEXT_TABLE_RSSI_B
);
18669 data
= (commandp
+ strlen(CMD_WBTEXT_TABLE_CONFIG
) + 1);
18670 ret
= wl_cfg80211_wbtext_table_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18671 if (ret
!= BCME_OK
) {
18672 WL_ERR(("%s: Failed to set RSSI table %s error = %d\n",
18673 __FUNCTION__
, data
, ret
));
18678 memset(commandp
, 0, sizeof(commandp
));
18679 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18680 CMD_WBTEXT_TABLE_CONFIG
, DEFAULT_WBTEXT_TABLE_CU_A
);
18681 data
= (commandp
+ strlen(CMD_WBTEXT_TABLE_CONFIG
) + 1);
18682 ret
= wl_cfg80211_wbtext_table_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18683 if (ret
!= BCME_OK
) {
18684 WL_ERR(("%s: Failed to set CU table %s error = %d\n",
18685 __FUNCTION__
, data
, ret
));
18689 memset(commandp
, 0, sizeof(commandp
));
18690 snprintf(commandp
, WLC_IOCTL_SMLEN
, "%s %s",
18691 CMD_WBTEXT_TABLE_CONFIG
, DEFAULT_WBTEXT_TABLE_CU_B
);
18692 data
= (commandp
+ strlen(CMD_WBTEXT_TABLE_CONFIG
) + 1);
18693 ret
= wl_cfg80211_wbtext_table_config(ndev
, data
, commandp
, WLC_IOCTL_SMLEN
);
18694 if (ret
!= BCME_OK
) {
18695 WL_ERR(("%s: Failed to set CU table %s error = %d\n",
18696 __FUNCTION__
, data
, ret
));
18704 wl_cfg80211_wbtext_config(struct net_device
*ndev
, char *data
, char *command
, int total_len
)
18707 long int rssi_lower
, roam_trigger
;
18708 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
18709 wl_roam_prof_band_t
*rp
;
18710 int err
= -EINVAL
, bytes_written
= 0;
18711 size_t len
= strlen(data
);
18714 rp
= (wl_roam_prof_band_t
*) kzalloc(sizeof(*rp
)
18715 * WL_MAX_ROAM_PROF_BRACKETS
, GFP_KERNEL
);
18716 if (unlikely(!rp
)) {
18717 WL_ERR(("%s: failed to allocate memory\n", __func__
));
18721 rp
->ver
= WL_MAX_ROAM_PROF_VER
;
18722 if (*data
&& (!strncmp(data
, "b", 1))) {
18723 rp
->band
= WLC_BAND_2G
;
18724 } else if (*data
&& (!strncmp(data
, "a", 1))) {
18725 rp
->band
= WLC_BAND_5G
;
18727 err
= snprintf(command
, total_len
, "Missing band\n");
18732 /* Getting roam profile from fw */
18733 if ((err
= wldev_iovar_getbuf(ndev
, "roam_prof", rp
, sizeof(*rp
),
18734 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
18735 WL_ERR(("Getting roam_profile failed with err=%d \n", err
));
18738 memcpy(rp
, cfg
->ioctl_buf
, sizeof(*rp
) * WL_MAX_ROAM_PROF_BRACKETS
);
18739 /* roam_prof version get */
18740 if (rp
->ver
!= WL_MAX_ROAM_PROF_VER
) {
18741 WL_ERR(("bad version (=%d) in return data\n", rp
->ver
));
18745 if ((rp
->len
% sizeof(wl_roam_prof_t
)) != 0) {
18746 WL_ERR(("bad length (=%d) in return data\n", rp
->len
));
18752 for (i
= 0; i
< WL_MAX_ROAM_PROF_BRACKETS
; i
++) {
18753 /* printing contents of roam profile data from fw and exits
18754 * if code hits any of one of the below condtion. If remaining
18755 * length of buffer is less than roam profile size or
18756 * if there is no valid entry.
18758 if (((i
* sizeof(wl_roam_prof_t
)) > rp
->len
) ||
18759 (rp
->roam_prof
[i
].fullscan_period
== 0)) {
18762 bytes_written
+= snprintf(command
+bytes_written
,
18763 total_len
, "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)\n",
18764 rp
->roam_prof
[i
].roam_trigger
, rp
->roam_prof
[i
].rssi_lower
,
18765 rp
->roam_prof
[i
].channel_usage
,
18766 rp
->roam_prof
[i
].cu_avg_calc_dur
);
18768 err
= bytes_written
;
18771 for (i
= 0; i
< WL_MAX_ROAM_PROF_BRACKETS
; i
++) {
18772 /* reading contents of roam profile data from fw and exits
18773 * if code hits any of one of the below condtion, If remaining
18774 * length of buffer is less than roam profile size or if there
18775 * is no valid entry.
18777 if (((i
* sizeof(wl_roam_prof_t
)) > rp
->len
) ||
18778 (rp
->roam_prof
[i
].fullscan_period
== 0)) {
18782 /* Do not set roam_prof from upper layer if fw doesn't have 2 rows */
18784 WL_ERR(("FW must have 2 rows to fill roam_prof\n"));
18788 /* setting roam profile to fw */
18790 for (i
= 0; i
< WL_MAX_ROAM_PROF_BRACKETS
; i
++) {
18791 roam_trigger
= simple_strtol(data
, &data
, 10);
18792 if (roam_trigger
>= 0) {
18793 WL_ERR(("roam trigger[%d] value must be negative\n", i
));
18797 rp
->roam_prof
[i
].roam_trigger
= roam_trigger
;
18799 rssi_lower
= simple_strtol(data
, &data
, 10);
18800 if (rssi_lower
>= 0) {
18801 WL_ERR(("rssi lower[%d] value must be negative\n", i
));
18805 rp
->roam_prof
[i
].rssi_lower
= rssi_lower
;
18807 rp
->roam_prof
[i
].channel_usage
= simple_strtol(data
, &data
, 10);
18809 rp
->roam_prof
[i
].cu_avg_calc_dur
= simple_strtol(data
, &data
, 10);
18811 rp_len
+= sizeof(wl_roam_prof_t
);
18813 if (*data
== '\0') {
18819 WL_ERR(("Only two roam_prof rows supported.\n"));
18824 if ((err
= wldev_iovar_setbuf(ndev
, "roam_prof", rp
,
18825 sizeof(*rp
), cfg
->ioctl_buf
, WLC_IOCTL_MEDLEN
,
18826 &cfg
->ioctl_buf_sync
)) < 0) {
18827 WL_ERR(("seting roam_profile failed with err %d\n", err
));
18842 int wl_cfg80211_wbtext_weight_config(struct net_device
*ndev
, char *data
,
18843 char *command
, int total_len
)
18845 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
18846 int bytes_written
= 0, err
= -EINVAL
, argc
= 0;
18847 char rssi
[BUFSZ
], band
[BUFSZ
], weight
[BUFSZ
];
18848 char *endptr
= NULL
;
18849 wnm_bss_select_weight_cfg_t
*bwcfg
;
18851 bwcfg
= kzalloc(sizeof(*bwcfg
), GFP_KERNEL
);
18852 if (unlikely(!bwcfg
)) {
18853 WL_ERR(("%s: failed to allocate memory\n", __func__
));
18857 bwcfg
->version
= WNM_BSSLOAD_MONITOR_VERSION
;
18861 argc
= sscanf(data
, "%"S(BUFSZ
)"s %"S(BUFSZ
)"s %"S(BUFSZ
)"s", rssi
, band
, weight
);
18863 if (!strcasecmp(rssi
, "rssi"))
18864 bwcfg
->type
= WNM_BSS_SELECT_TYPE_RSSI
;
18865 else if (!strcasecmp(rssi
, "cu"))
18866 bwcfg
->type
= WNM_BSS_SELECT_TYPE_CU
;
18868 /* Usage DRIVER WBTEXT_WEIGHT_CONFIG <rssi/cu> <band> <weight> */
18869 WL_ERR(("%s: Command usage error\n", __func__
));
18873 if (!strcasecmp(band
, "a"))
18874 bwcfg
->band
= WLC_BAND_5G
;
18875 else if (!strcasecmp(band
, "b"))
18876 bwcfg
->band
= WLC_BAND_2G
;
18877 else if (!strcasecmp(band
, "all"))
18878 bwcfg
->band
= WLC_BAND_ALL
;
18880 WL_ERR(("%s: Command usage error\n", __func__
));
18885 /* If there is no data after band, getting wnm_bss_select_weight from fw */
18886 if (bwcfg
->band
== WLC_BAND_ALL
) {
18887 WL_ERR(("band option \"all\" is for set only, not get\n"));
18890 if ((err
= wldev_iovar_getbuf(ndev
, "wnm_bss_select_weight", bwcfg
,
18892 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
18893 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d \n", err
));
18896 memcpy(bwcfg
, cfg
->ioctl_buf
, sizeof(*bwcfg
));
18897 bytes_written
= snprintf(command
, total_len
, "%s %s weight = %d\n",
18898 (bwcfg
->type
== WNM_BSS_SELECT_TYPE_RSSI
) ? "RSSI" : "CU",
18899 (bwcfg
->band
== WLC_BAND_2G
) ? "2G" : "5G", bwcfg
->weight
);
18900 err
= bytes_written
;
18903 /* if weight is non integer returns command usage error */
18904 bwcfg
->weight
= simple_strtol(weight
, &endptr
, 0);
18905 if (*endptr
!= '\0') {
18906 WL_ERR(("%s: Command usage error", __func__
));
18909 /* setting weight for iovar wnm_bss_select_weight to fw */
18910 if ((err
= wldev_iovar_setbuf(ndev
, "wnm_bss_select_weight", bwcfg
,
18912 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
18913 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d\n", err
));
18923 /* WBTEXT_TUPLE_MIN_LEN_CHECK :strlen(low)+" "+strlen(high)+" "+strlen(factor) */
18924 #define WBTEXT_TUPLE_MIN_LEN_CHECK 5
18926 int wl_cfg80211_wbtext_table_config(struct net_device
*ndev
, char *data
,
18927 char *command
, int total_len
)
18929 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
18930 int bytes_written
= 0, err
= -EINVAL
;
18931 char rssi
[BUFSZ
], band
[BUFSZ
];
18932 int btcfg_len
= 0, i
= 0, parsed_len
= 0;
18933 wnm_bss_select_factor_cfg_t
*btcfg
;
18934 size_t slen
= strlen(data
);
18935 char *start_addr
= NULL
;
18938 btcfg
= kzalloc((sizeof(*btcfg
) + sizeof(*btcfg
) *
18939 WL_FACTOR_TABLE_MAX_LIMIT
), GFP_KERNEL
);
18940 if (unlikely(!btcfg
)) {
18941 WL_ERR(("%s: failed to allocate memory\n", __func__
));
18946 btcfg
->version
= WNM_BSS_SELECT_FACTOR_VERSION
;
18947 btcfg
->band
= WLC_BAND_AUTO
;
18951 sscanf(data
, "%"S(BUFSZ
)"s %"S(BUFSZ
)"s", rssi
, band
);
18953 if (!strcasecmp(rssi
, "rssi")) {
18954 btcfg
->type
= WNM_BSS_SELECT_TYPE_RSSI
;
18956 else if (!strcasecmp(rssi
, "cu")) {
18957 btcfg
->type
= WNM_BSS_SELECT_TYPE_CU
;
18960 WL_ERR(("%s: Command usage error\n", __func__
));
18964 if (!strcasecmp(band
, "a")) {
18965 btcfg
->band
= WLC_BAND_5G
;
18967 else if (!strcasecmp(band
, "b")) {
18968 btcfg
->band
= WLC_BAND_2G
;
18970 else if (!strcasecmp(band
, "all")) {
18971 btcfg
->band
= WLC_BAND_ALL
;
18974 WL_ERR(("%s: Command usage, Wrong band\n", __func__
));
18978 if ((slen
- 1) == (strlen(rssi
) + strlen(band
))) {
18979 /* Getting factor table using iovar 'wnm_bss_select_table' from fw */
18980 if ((err
= wldev_iovar_getbuf(ndev
, "wnm_bss_select_table", btcfg
,
18982 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
18983 WL_ERR(("Getting wnm_bss_select_table failed with err=%d \n", err
));
18986 memcpy(btcfg
, cfg
->ioctl_buf
, sizeof(*btcfg
));
18987 memcpy(btcfg
, cfg
->ioctl_buf
, (btcfg
->count
+1) * sizeof(*btcfg
));
18989 bytes_written
+= snprintf(command
+ bytes_written
, total_len
,
18990 "No of entries in table: %d\n", btcfg
->count
);
18991 bytes_written
+= snprintf(command
+ bytes_written
, total_len
, "%s factor table\n",
18992 (btcfg
->type
== WNM_BSS_SELECT_TYPE_RSSI
) ? "RSSI" : "CU");
18993 bytes_written
+= snprintf(command
+ bytes_written
, total_len
,
18994 "low\thigh\tfactor\n");
18995 for (i
= 0; i
<= btcfg
->count
-1; i
++) {
18996 bytes_written
+= snprintf(command
+ bytes_written
, total_len
,
18997 "%d\t%d\t%d\n", btcfg
->params
[i
].low
, btcfg
->params
[i
].high
,
18998 btcfg
->params
[i
].factor
);
19000 err
= bytes_written
;
19003 memset(btcfg
->params
, 0, sizeof(wnm_bss_select_factor_params_t
)
19004 * WL_FACTOR_TABLE_MAX_LIMIT
);
19005 data
+= (strlen(rssi
) + strlen(band
) + 2);
19007 slen
= slen
- (strlen(rssi
) + strlen(band
) + 2);
19008 for (i
= 0; i
< WL_FACTOR_TABLE_MAX_LIMIT
; i
++) {
19009 if (parsed_len
+ WBTEXT_TUPLE_MIN_LEN_CHECK
<= slen
) {
19010 btcfg
->params
[i
].low
= simple_strtol(data
, &data
, 10);
19012 btcfg
->params
[i
].high
= simple_strtol(data
, &data
, 10);
19014 btcfg
->params
[i
].factor
= simple_strtol(data
, &data
, 10);
19016 if (*data
== '\0') {
19020 parsed_len
= data
- start_addr
;
19022 WL_ERR(("%s:Command usage:less no of args\n", __func__
));
19026 btcfg_len
= sizeof(*btcfg
) + ((btcfg
->count
) * sizeof(*btcfg
));
19027 if ((err
= wldev_iovar_setbuf(ndev
, "wnm_bss_select_table", btcfg
, btcfg_len
,
19028 cfg
->ioctl_buf
, WLC_IOCTL_MEDLEN
, &cfg
->ioctl_buf_sync
)) < 0) {
19029 WL_ERR(("seting wnm_bss_select_table failed with err %d\n", err
));
19041 wl_cfg80211_wbtext_delta_config(struct net_device
*ndev
, char *data
, char *command
, int total_len
)
19044 struct bcm_cfg80211
*cfg
= wl_get_cfg(ndev
);
19045 int err
= -EINVAL
, bytes_written
= 0, argc
= 0, val
, len
= 0;
19046 char delta
[BUFSZ
], band
[BUFSZ
], *endptr
= NULL
;
19047 wl_roam_prof_band_t
*rp
;
19049 rp
= (wl_roam_prof_band_t
*) kzalloc(sizeof(*rp
)
19050 * WL_MAX_ROAM_PROF_BRACKETS
, GFP_KERNEL
);
19051 if (unlikely(!rp
)) {
19052 WL_ERR(("%s: failed to allocate memory\n", __func__
));
19057 argc
= sscanf(data
, "%"S(BUFSZ
)"s %"S(BUFSZ
)"s", band
, delta
);
19058 if (!strcasecmp(band
, "a"))
19059 rp
->band
= WLC_BAND_5G
;
19060 else if (!strcasecmp(band
, "b"))
19061 rp
->band
= WLC_BAND_2G
;
19063 WL_ERR(("%s: Missing band\n", __func__
));
19066 /* Getting roam profile from fw */
19067 if ((err
= wldev_iovar_getbuf(ndev
, "roam_prof", rp
, sizeof(*rp
),
19068 cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
, &cfg
->ioctl_buf_sync
))) {
19069 WL_ERR(("Getting roam_profile failed with err=%d \n", err
));
19072 memcpy(rp
, cfg
->ioctl_buf
, sizeof(wl_roam_prof_band_t
));
19073 if (rp
->ver
!= WL_MAX_ROAM_PROF_VER
) {
19074 WL_ERR(("bad version (=%d) in return data\n", rp
->ver
));
19078 if ((rp
->len
% sizeof(wl_roam_prof_t
)) != 0) {
19079 WL_ERR(("bad length (=%d) in return data\n", rp
->len
));
19085 /* if delta is non integer returns command usage error */
19086 val
= simple_strtol(delta
, &endptr
, 0);
19087 if (*endptr
!= '\0') {
19088 WL_ERR(("%s: Command usage error", __func__
));
19091 for (i
= 0; i
< WL_MAX_ROAM_PROF_BRACKETS
; i
++) {
19093 * Checking contents of roam profile data from fw and exits
19094 * if code hits below condtion. If remaining length of buffer is
19095 * less than roam profile size or if there is no valid entry.
19097 if (((i
* sizeof(wl_roam_prof_t
)) > rp
->len
) ||
19098 (rp
->roam_prof
[i
].fullscan_period
== 0)) {
19101 if (rp
->roam_prof
[i
].channel_usage
!= 0) {
19102 rp
->roam_prof
[i
].roam_delta
= val
;
19104 len
+= sizeof(wl_roam_prof_t
);
19108 if (rp
->roam_prof
[i
].channel_usage
!= 0) {
19109 bytes_written
= snprintf(command
, total_len
,
19110 "%s Delta %d\n", (rp
->band
== WLC_BAND_2G
) ? "2G" : "5G",
19111 rp
->roam_prof
[0].roam_delta
);
19113 err
= bytes_written
;
19117 if ((err
= wldev_iovar_setbuf(ndev
, "roam_prof", rp
,
19118 sizeof(*rp
), cfg
->ioctl_buf
, WLC_IOCTL_MEDLEN
, &cfg
->ioctl_buf_sync
)) < 0) {
19119 WL_ERR(("seting roam_profile failed with err %d\n", err
));
19127 #endif /* WBTEXT */
19130 int wl_cfg80211_scan_stop(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
)
19132 struct net_device
*ndev
= NULL
;
19133 unsigned long flags
;
19134 int clear_flag
= 0;
19136 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
19137 struct cfg80211_scan_info info
;
19140 WL_TRACE(("Enter\n"));
19145 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
19147 spin_lock_irqsave(&cfg
->cfgdrv_lock
, flags
);
19148 #ifdef WL_CFG80211_P2P_DEV_IF
19149 if (cfg
->scan_request
&& cfg
->scan_request
->wdev
== cfgdev
)
19151 if (cfg
->scan_request
&& cfg
->scan_request
->dev
== cfgdev
)
19154 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
19155 info
.aborted
= true;
19156 cfg80211_scan_done(cfg
->scan_request
, &info
);
19158 cfg80211_scan_done(cfg
->scan_request
, true);
19160 cfg
->scan_request
= NULL
;
19163 spin_unlock_irqrestore(&cfg
->cfgdrv_lock
, flags
);
19166 wl_clr_drv_status(cfg
, SCANNING
, ndev
);
19171 bool wl_cfg80211_is_concurrent_mode(struct net_device
*dev
)
19173 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
19174 if ((cfg
) && (wl_get_drv_status_all(cfg
, CONNECTED
) > 1)) {
19181 void* wl_cfg80211_get_dhdp(struct net_device
*dev
)
19183 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
19188 bool wl_cfg80211_is_p2p_active(struct net_device
*dev
)
19190 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
19191 return (cfg
&& cfg
->p2p
);
19194 bool wl_cfg80211_is_roam_offload(struct net_device
* dev
)
19196 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
19197 return (cfg
&& cfg
->roam_offload
);
19200 bool wl_cfg80211_is_event_from_connected_bssid(struct net_device
* dev
, const wl_event_msg_t
*e
,
19203 u8
*curbssid
= NULL
;
19204 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
19207 /* When interface is created using wl
19208 * ndev->ieee80211_ptr will be NULL.
19212 curbssid
= wl_read_prof(cfg
, dev
, WL_PROF_BSSID
);
19218 if (memcmp(curbssid
, &e
->addr
, ETHER_ADDR_LEN
) == 0) {
19224 static void wl_cfg80211_work_handler(struct work_struct
* work
)
19226 struct bcm_cfg80211
*cfg
= NULL
;
19227 struct net_info
*iter
, *next
;
19231 BCM_SET_CONTAINER_OF(cfg
, work
, struct bcm_cfg80211
, pm_enable_work
.work
);
19232 WL_DBG(("Enter \n"));
19233 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19234 4 && __GNUC_MINOR__ >= 6))
19235 _Pragma("GCC diagnostic push")
19236 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19238 for_each_ndev(cfg
, iter
, next
) {
19239 /* p2p discovery iface ndev could be null */
19241 if (!wl_get_drv_status(cfg
, CONNECTED
, iter
->ndev
) ||
19242 (wl_get_mode_by_netdev(cfg
, iter
->ndev
) != WL_MODE_BSS
&&
19243 wl_get_mode_by_netdev(cfg
, iter
->ndev
) != WL_MODE_IBSS
))
19246 dhd
= (dhd_pub_t
*)(cfg
->pub
);
19247 if (dhd_conf_get_pm(dhd
) >= 0)
19248 pm
= dhd_conf_get_pm(dhd
);
19249 if ((err
= wldev_ioctl_set(iter
->ndev
, WLC_SET_PM
,
19250 &pm
, sizeof(pm
))) != 0) {
19251 if (err
== -ENODEV
)
19252 WL_DBG(("%s:netdev not ready\n",
19253 iter
->ndev
->name
));
19255 WL_ERR(("%s:error (%d)\n",
19256 iter
->ndev
->name
, err
));
19258 wl_cfg80211_update_power_mode(iter
->ndev
);
19262 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19263 4 && __GNUC_MINOR__ >= 6))
19264 _Pragma("GCC diagnostic pop")
19266 DHD_PM_WAKE_UNLOCK(cfg
->pub
);
19270 wl_get_action_category(void *frame
, u32 frame_len
)
19273 u8
*ptr
= (u8
*)frame
;
19275 return DOT11_ACTION_CAT_ERR_MASK
;
19276 if (frame_len
< DOT11_ACTION_HDR_LEN
)
19277 return DOT11_ACTION_CAT_ERR_MASK
;
19278 category
= ptr
[DOT11_ACTION_CAT_OFF
];
19279 WL_INFORM(("Action Category: %d\n", category
));
19284 wl_get_public_action(void *frame
, u32 frame_len
, u8
*ret_action
)
19286 u8
*ptr
= (u8
*)frame
;
19287 if (frame
== NULL
|| ret_action
== NULL
)
19289 if (frame_len
< DOT11_ACTION_HDR_LEN
)
19291 if (DOT11_ACTION_CAT_PUBLIC
!= wl_get_action_category(frame
, frame_len
))
19293 *ret_action
= ptr
[DOT11_ACTION_ACT_OFF
];
19294 WL_INFORM(("Public Action : %d\n", *ret_action
));
19300 wl_cfg80211_delayed_roam(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
19301 const struct ether_addr
*bssid
)
19306 bzero(&e
, sizeof(e
));
19307 e
.event_type
= cpu_to_be32(WLC_E_ROAM
);
19308 memcpy(&e
.addr
, bssid
, ETHER_ADDR_LEN
);
19309 /* trigger the roam event handler */
19310 err
= wl_notify_roaming_status(cfg
, ndev_to_cfgdev(ndev
), &e
, NULL
);
19316 wl_cfg80211_parse_vndr_ies(u8
*parse
, u32 len
,
19317 struct parsed_vndr_ies
*vndr_ies
)
19322 struct parsed_vndr_ie_info
*parsed_info
;
19326 remained_len
= (s32
)len
;
19327 memset(vndr_ies
, 0, sizeof(*vndr_ies
));
19329 WL_DBG(("---> len %d\n", len
));
19330 ie
= (bcm_tlv_t
*) parse
;
19331 if (!bcm_valid_tlv(ie
, remained_len
))
19334 if (count
>= MAX_VNDR_IE_NUMBER
)
19336 if (ie
->id
== DOT11_MNG_VS_ID
) {
19337 vndrie
= (vndr_ie_t
*) ie
;
19338 /* len should be bigger than OUI length + one data length at least */
19339 if (vndrie
->len
< (VNDR_IE_MIN_LEN
+ 1)) {
19340 WL_ERR(("%s: invalid vndr ie. length is too small %d\n",
19341 __FUNCTION__
, vndrie
->len
));
19344 /* if wpa or wme ie, do not add ie */
19345 if (!bcmp(vndrie
->oui
, (u8
*)WPA_OUI
, WPA_OUI_LEN
) &&
19346 ((vndrie
->data
[0] == WPA_OUI_TYPE
) ||
19347 (vndrie
->data
[0] == WME_OUI_TYPE
))) {
19348 WL_DBG(("Found WPA/WME oui. Do not add it\n"));
19352 parsed_info
= &vndr_ies
->ie_info
[count
++];
19354 /* save vndr ie information */
19355 parsed_info
->ie_ptr
= (char *)vndrie
;
19356 parsed_info
->ie_len
= (vndrie
->len
+ TLV_HDR_LEN
);
19357 memcpy(&parsed_info
->vndrie
, vndrie
, sizeof(vndr_ie_t
));
19358 vndr_ies
->count
= count
;
19360 WL_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x len:%d\n",
19361 parsed_info
->vndrie
.oui
[0], parsed_info
->vndrie
.oui
[1],
19362 parsed_info
->vndrie
.oui
[2], parsed_info
->vndrie
.data
[0],
19363 parsed_info
->ie_len
));
19366 ie
= bcm_next_tlv(ie
, &remained_len
);
19371 #ifdef WLADPS_SEAK_AP_WAR
19373 wl_find_vndr_ies_specific_vender(struct bcm_cfg80211
*cfg
,
19374 struct net_device
*ndev
, const u8
*vndr_oui
)
19376 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
19377 struct parsed_vndr_ie_info
*vndr_info_list
;
19378 struct parsed_vndr_ies vndr_ies
;
19382 if (conn_info
->resp_ie_len
) {
19383 if ((wl_cfg80211_parse_vndr_ies((u8
*)conn_info
->resp_ie
,
19384 conn_info
->resp_ie_len
, &vndr_ies
)) == BCME_OK
) {
19385 for (i
= 0; i
< vndr_ies
.count
; i
++) {
19386 vndr_info_list
= &vndr_ies
.ie_info
[i
];
19387 if (!bcmp(vndr_info_list
->vndrie
.oui
,
19388 (u8
*)vndr_oui
, DOT11_OUI_LEN
)) {
19389 WL_ERR(("Find OUI %02x %02x %02x\n",
19390 vndr_info_list
->vndrie
.oui
[0],
19391 vndr_info_list
->vndrie
.oui
[1],
19392 vndr_info_list
->vndrie
.oui
[2]));
19403 wl_set_adps_mode(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
, uint8 enable_mode
)
19409 bcm_iov_buf_t
*iov_buf
= NULL
;
19410 wl_adps_params_v1_t
*data
= NULL
;
19412 len
= OFFSETOF(bcm_iov_buf_t
, data
) + sizeof(*data
);
19413 iov_buf
= kmalloc(len
, GFP_KERNEL
);
19414 if (iov_buf
== NULL
) {
19415 WL_ERR(("%s - failed to allocate %d bytes for iov_buf\n", __FUNCTION__
, len
));
19420 iov_buf
->version
= WL_ADPS_IOV_VER
;
19421 iov_buf
->len
= sizeof(*data
);
19422 iov_buf
->id
= WL_ADPS_IOV_MODE
;
19424 data
= (wl_adps_params_v1_t
*)iov_buf
->data
;
19425 data
->version
= ADPS_SUB_IOV_VERSION_1
;
19426 data
->length
= sizeof(*data
);
19427 data
->mode
= enable_mode
;
19429 for (i
= 1; i
<= MAX_BANDS
; i
++) {
19431 ret
= wldev_iovar_setbuf(ndev
, "adps", iov_buf
, len
,
19432 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, NULL
);
19442 #endif /* WLADPS_SEAK_AP_WAR */
19445 wl_vndr_ies_exclude_vndr_oui(struct parsed_vndr_ie_info
*vndr_info
)
19449 while (exclude_vndr_oui_list
[i
]) {
19450 if (!memcmp(vndr_info
->vndrie
.oui
,
19451 exclude_vndr_oui_list
[i
],
19462 wl_vndr_ies_check_duplicate_vndr_oui(struct bcm_cfg80211
*cfg
,
19463 struct parsed_vndr_ie_info
*vndr_info
)
19465 wl_vndr_oui_entry_t
*oui_entry
= NULL
;
19467 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19468 #pragma GCC diagnostic push
19469 #pragma GCC diagnostic ignored "-Wcast-qual"
19471 list_for_each_entry(oui_entry
, &cfg
->vndr_oui_list
, list
) {
19472 if (!memcmp(oui_entry
->oui
, vndr_info
->vndrie
.oui
, DOT11_OUI_LEN
)) {
19476 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19477 #pragma GCC diagnostic pop
19484 wl_vndr_ies_add_vendor_oui_list(struct bcm_cfg80211
*cfg
,
19485 struct parsed_vndr_ie_info
*vndr_info
)
19487 wl_vndr_oui_entry_t
*oui_entry
= NULL
;
19489 oui_entry
= kmalloc(sizeof(*oui_entry
), GFP_KERNEL
);
19490 if (oui_entry
== NULL
) {
19491 WL_ERR(("alloc failed\n"));
19495 memcpy(oui_entry
->oui
, vndr_info
->vndrie
.oui
, DOT11_OUI_LEN
);
19497 INIT_LIST_HEAD(&oui_entry
->list
);
19498 list_add_tail(&oui_entry
->list
, &cfg
->vndr_oui_list
);
19504 wl_vndr_ies_clear_vendor_oui_list(struct bcm_cfg80211
*cfg
)
19506 wl_vndr_oui_entry_t
*oui_entry
= NULL
;
19508 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19509 #pragma GCC diagnostic push
19510 #pragma GCC diagnostic ignored "-Wcast-qual"
19512 while (!list_empty(&cfg
->vndr_oui_list
)) {
19513 oui_entry
= list_entry(cfg
->vndr_oui_list
.next
, wl_vndr_oui_entry_t
, list
);
19515 list_del(&oui_entry
->list
);
19519 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19520 #pragma GCC diagnostic pop
19525 wl_vndr_ies_get_vendor_oui(struct bcm_cfg80211
*cfg
, struct net_device
*ndev
,
19526 char *vndr_oui
, u32 vndr_oui_len
)
19529 int vndr_oui_num
= 0;
19531 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
19532 wl_vndr_oui_entry_t
*oui_entry
= NULL
;
19533 struct parsed_vndr_ie_info
*vndr_info
;
19534 struct parsed_vndr_ies vndr_ies
;
19536 char *pos
= vndr_oui
;
19537 u32 remained_buf_len
= vndr_oui_len
;
19539 if (!conn_info
->resp_ie_len
) {
19543 wl_vndr_ies_clear_vendor_oui_list(cfg
);
19545 if ((wl_cfg80211_parse_vndr_ies((u8
*)conn_info
->resp_ie
,
19546 conn_info
->resp_ie_len
, &vndr_ies
)) == BCME_OK
) {
19547 for (i
= 0; i
< vndr_ies
.count
; i
++) {
19548 vndr_info
= &vndr_ies
.ie_info
[i
];
19549 if (wl_vndr_ies_exclude_vndr_oui(vndr_info
)) {
19553 if (wl_vndr_ies_check_duplicate_vndr_oui(cfg
, vndr_info
)) {
19557 wl_vndr_ies_add_vendor_oui_list(cfg
, vndr_info
);
19563 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19564 #pragma GCC diagnostic push
19565 #pragma GCC diagnostic ignored "-Wcast-qual"
19567 list_for_each_entry(oui_entry
, &cfg
->vndr_oui_list
, list
) {
19568 if (remained_buf_len
< VNDR_OUI_STR_LEN
) {
19571 pos
+= snprintf(pos
, VNDR_OUI_STR_LEN
, "%02X-%02X-%02X ",
19572 oui_entry
->oui
[0], oui_entry
->oui
[1], oui_entry
->oui
[2]);
19573 remained_buf_len
-= VNDR_OUI_STR_LEN
;
19575 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19576 #pragma GCC diagnostic pop
19580 return vndr_oui_num
;
19584 wl_cfg80211_get_vndr_ouilist(struct bcm_cfg80211
*cfg
, uint8
*buf
, int max_cnt
)
19586 wl_vndr_oui_entry_t
*oui_entry
= NULL
;
19589 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19590 #pragma GCC diagnostic push
19591 #pragma GCC diagnostic ignored "-Wcast-qual"
19593 list_for_each_entry(oui_entry
, &cfg
->vndr_oui_list
, list
) {
19594 memcpy(buf
, oui_entry
->oui
, DOT11_OUI_LEN
);
19596 if (cnt
>= max_cnt
) {
19599 buf
+= DOT11_OUI_LEN
;
19601 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19602 #pragma GCC diagnostic pop
19608 wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211
*cfg
, s32 bssidx
)
19611 struct net_info
*netinfo
;
19612 s32 vndrie_flag
[] = {VNDR_IE_BEACON_FLAG
, VNDR_IE_PRBRSP_FLAG
,
19613 VNDR_IE_ASSOCRSP_FLAG
, VNDR_IE_PRBREQ_FLAG
, VNDR_IE_ASSOCREQ_FLAG
};
19615 netinfo
= wl_get_netinfo_by_bssidx(cfg
, bssidx
);
19616 if (!netinfo
|| !netinfo
->wdev
) {
19617 WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
19621 WL_DBG(("clear management vendor IEs for bssidx:%d \n", bssidx
));
19622 /* Clear the IEs set in the firmware so that host is in sync with firmware */
19623 for (index
= 0; index
< ARRAYSIZE(vndrie_flag
); index
++) {
19624 if (wl_cfg80211_set_mgmt_vndr_ies(cfg
, wdev_to_cfgdev(netinfo
->wdev
),
19625 bssidx
, vndrie_flag
[index
], NULL
, 0) < 0)
19626 WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
19633 wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211
*cfg
)
19635 struct net_info
*iter
, *next
;
19637 WL_DBG(("clear management vendor IEs \n"));
19638 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19639 4 && __GNUC_MINOR__ >= 6))
19640 _Pragma("GCC diagnostic push")
19641 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19643 for_each_ndev(cfg
, iter
, next
) {
19644 wl_cfg80211_clear_per_bss_ies(cfg
, iter
->bssidx
);
19646 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19647 4 && __GNUC_MINOR__ >= 6))
19648 _Pragma("GCC diagnostic pop")
19653 #define WL_VNDR_IE_MAXLEN 2048
19654 static s8 g_mgmt_ie_buf
[WL_VNDR_IE_MAXLEN
];
19656 wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
19657 s32 bssidx
, s32 pktflag
, const u8
*vndr_ie
, u32 vndr_ie_len
)
19659 struct net_device
*ndev
= NULL
;
19661 u8
*curr_ie_buf
= NULL
;
19662 u8
*mgmt_ie_buf
= NULL
;
19663 u32 mgmt_ie_buf_len
= 0;
19664 u32
*mgmt_ie_len
= 0;
19665 u32 del_add_ie_buf_len
= 0;
19666 u32 total_ie_buf_len
= 0;
19667 u32 parsed_ie_buf_len
= 0;
19668 struct parsed_vndr_ies old_vndr_ies
;
19669 struct parsed_vndr_ies new_vndr_ies
;
19672 s32 remained_buf_len
;
19673 wl_bss_vndr_ies_t
*ies
= NULL
;
19674 struct net_info
*netinfo
;
19676 WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d \n",
19677 pktflag
, bssidx
, vndr_ie_len
));
19679 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
19681 if (bssidx
> WL_MAX_IFS
) {
19682 WL_ERR(("bssidx > supported concurrent Ifaces \n"));
19686 netinfo
= wl_get_netinfo_by_bssidx(cfg
, bssidx
);
19688 WL_ERR(("net_info ptr is NULL \n"));
19692 /* Clear the global buffer */
19693 memset(g_mgmt_ie_buf
, 0, sizeof(g_mgmt_ie_buf
));
19694 curr_ie_buf
= g_mgmt_ie_buf
;
19695 ies
= &netinfo
->bss
.ies
;
19698 case VNDR_IE_PRBRSP_FLAG
:
19699 mgmt_ie_buf
= ies
->probe_res_ie
;
19700 mgmt_ie_len
= &ies
->probe_res_ie_len
;
19701 mgmt_ie_buf_len
= sizeof(ies
->probe_res_ie
);
19703 case VNDR_IE_ASSOCRSP_FLAG
:
19704 mgmt_ie_buf
= ies
->assoc_res_ie
;
19705 mgmt_ie_len
= &ies
->assoc_res_ie_len
;
19706 mgmt_ie_buf_len
= sizeof(ies
->assoc_res_ie
);
19708 case VNDR_IE_BEACON_FLAG
:
19709 mgmt_ie_buf
= ies
->beacon_ie
;
19710 mgmt_ie_len
= &ies
->beacon_ie_len
;
19711 mgmt_ie_buf_len
= sizeof(ies
->beacon_ie
);
19713 case VNDR_IE_PRBREQ_FLAG
:
19714 mgmt_ie_buf
= ies
->probe_req_ie
;
19715 mgmt_ie_len
= &ies
->probe_req_ie_len
;
19716 mgmt_ie_buf_len
= sizeof(ies
->probe_req_ie
);
19718 case VNDR_IE_ASSOCREQ_FLAG
:
19719 mgmt_ie_buf
= ies
->assoc_req_ie
;
19720 mgmt_ie_len
= &ies
->assoc_req_ie_len
;
19721 mgmt_ie_buf_len
= sizeof(ies
->assoc_req_ie
);
19724 mgmt_ie_buf
= NULL
;
19725 mgmt_ie_len
= NULL
;
19726 WL_ERR(("not suitable packet type (%d)\n", pktflag
));
19730 if (vndr_ie_len
> mgmt_ie_buf_len
) {
19731 WL_ERR(("extra IE size too big\n"));
19734 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
19735 if (vndr_ie
&& vndr_ie_len
&& curr_ie_buf
) {
19737 /* must discard vndr_ie constness, attempt to change vndr_ie arg to non-const
19738 * causes cascade of errors in other places, fix involves const casts there
19740 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19741 4 && __GNUC_MINOR__ >= 6))
19742 _Pragma("GCC diagnostic push")
19743 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19745 if ((ret
= wl_cfg80211_parse_vndr_ies((u8
*)vndr_ie
,
19746 vndr_ie_len
, &new_vndr_ies
)) < 0) {
19747 WL_ERR(("parse vndr ie failed \n"));
19750 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19751 4 && __GNUC_MINOR__ >= 6))
19752 _Pragma("GCC diagnostic pop")
19754 for (i
= 0; i
< new_vndr_ies
.count
; i
++) {
19755 struct parsed_vndr_ie_info
*vndrie_info
=
19756 &new_vndr_ies
.ie_info
[i
];
19758 if ((parsed_ie_buf_len
+ vndrie_info
->ie_len
) > WL_VNDR_IE_MAXLEN
) {
19759 WL_ERR(("IE size is too big (%d > %d)\n",
19760 parsed_ie_buf_len
, WL_VNDR_IE_MAXLEN
));
19765 memcpy(ptr
+ parsed_ie_buf_len
, vndrie_info
->ie_ptr
,
19766 vndrie_info
->ie_len
);
19767 parsed_ie_buf_len
+= vndrie_info
->ie_len
;
19771 if (mgmt_ie_buf
!= NULL
) {
19772 if (parsed_ie_buf_len
&& (parsed_ie_buf_len
== *mgmt_ie_len
) &&
19773 (memcmp(mgmt_ie_buf
, curr_ie_buf
, parsed_ie_buf_len
) == 0)) {
19774 WL_INFORM(("Previous mgmt IE is equals to current IE"));
19778 /* parse old vndr_ie */
19779 if ((ret
= wl_cfg80211_parse_vndr_ies(mgmt_ie_buf
, *mgmt_ie_len
,
19780 &old_vndr_ies
)) < 0) {
19781 WL_ERR(("parse vndr ie failed \n"));
19784 /* make a command to delete old ie */
19785 for (i
= 0; i
< old_vndr_ies
.count
; i
++) {
19786 struct parsed_vndr_ie_info
*vndrie_info
=
19787 &old_vndr_ies
.ie_info
[i
];
19789 WL_INFORM(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
19790 vndrie_info
->vndrie
.id
, vndrie_info
->vndrie
.len
,
19791 vndrie_info
->vndrie
.oui
[0], vndrie_info
->vndrie
.oui
[1],
19792 vndrie_info
->vndrie
.oui
[2]));
19794 del_add_ie_buf_len
= wl_cfgp2p_vndr_ie(cfg
, curr_ie_buf
,
19795 pktflag
, vndrie_info
->vndrie
.oui
,
19796 vndrie_info
->vndrie
.id
,
19797 vndrie_info
->ie_ptr
+ VNDR_IE_FIXED_LEN
,
19798 vndrie_info
->ie_len
- VNDR_IE_FIXED_LEN
,
19801 curr_ie_buf
+= del_add_ie_buf_len
;
19802 total_ie_buf_len
+= del_add_ie_buf_len
;
19807 /* Add if there is any extra IE */
19808 if (mgmt_ie_buf
&& parsed_ie_buf_len
) {
19811 remained_buf_len
= mgmt_ie_buf_len
;
19813 /* make a command to add new ie */
19814 for (i
= 0; i
< new_vndr_ies
.count
; i
++) {
19815 struct parsed_vndr_ie_info
*vndrie_info
=
19816 &new_vndr_ies
.ie_info
[i
];
19818 WL_INFORM(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
19819 vndrie_info
->vndrie
.id
, vndrie_info
->vndrie
.len
,
19820 vndrie_info
->ie_len
- 2,
19821 vndrie_info
->vndrie
.oui
[0], vndrie_info
->vndrie
.oui
[1],
19822 vndrie_info
->vndrie
.oui
[2]));
19824 del_add_ie_buf_len
= wl_cfgp2p_vndr_ie(cfg
, curr_ie_buf
,
19825 pktflag
, vndrie_info
->vndrie
.oui
,
19826 vndrie_info
->vndrie
.id
,
19827 vndrie_info
->ie_ptr
+ VNDR_IE_FIXED_LEN
,
19828 vndrie_info
->ie_len
- VNDR_IE_FIXED_LEN
,
19831 /* verify remained buf size before copy data */
19832 if (remained_buf_len
>= vndrie_info
->ie_len
) {
19833 remained_buf_len
-= vndrie_info
->ie_len
;
19835 WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
19836 "found vndr ies # = %d(cur %d), remained len %d, "
19837 "cur mgmt_ie_len %d, new ie len = %d\n",
19838 pktflag
, new_vndr_ies
.count
, i
, remained_buf_len
,
19839 *mgmt_ie_len
, vndrie_info
->ie_len
));
19843 /* save the parsed IE in cfg struct */
19844 memcpy(ptr
+ (*mgmt_ie_len
), vndrie_info
->ie_ptr
,
19845 vndrie_info
->ie_len
);
19846 *mgmt_ie_len
+= vndrie_info
->ie_len
;
19847 curr_ie_buf
+= del_add_ie_buf_len
;
19848 total_ie_buf_len
+= del_add_ie_buf_len
;
19852 if (total_ie_buf_len
&& cfg
->ioctl_buf
!= NULL
) {
19853 ret
= wldev_iovar_setbuf_bsscfg(ndev
, "vndr_ie", g_mgmt_ie_buf
,
19854 total_ie_buf_len
, cfg
->ioctl_buf
, WLC_IOCTL_MAXLEN
,
19855 bssidx
, &cfg
->ioctl_buf_sync
);
19857 WL_ERR(("vndr ie set error : %d\n", ret
));
19865 #ifdef WL_CFG80211_ACL
19867 wl_cfg80211_set_mac_acl(struct wiphy
*wiphy
, struct net_device
*cfgdev
,
19868 const struct cfg80211_acl_data
*acl
)
19873 int macmode
= MACLIST_MODE_DISABLED
;
19874 struct maclist
*list
;
19876 /* get the MAC filter mode */
19877 if (acl
&& acl
->acl_policy
== NL80211_ACL_POLICY_DENY_UNLESS_LISTED
) {
19878 macmode
= MACLIST_MODE_ALLOW
;
19879 } else if (acl
&& acl
->acl_policy
== NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED
&&
19880 acl
->n_acl_entries
) {
19881 macmode
= MACLIST_MODE_DENY
;
19884 /* if acl == NULL, macmode is still disabled.. */
19885 if (macmode
== MACLIST_MODE_DISABLED
) {
19886 if ((ret
= wl_android_set_ap_mac_list(cfgdev
, macmode
, NULL
)) != 0)
19887 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__
, ret
));
19892 macnum
= acl
->n_acl_entries
;
19893 if (macnum
< 0 || macnum
> MAX_NUM_MAC_FILT
) {
19894 WL_ERR(("%s : invalid number of MAC address entries %d\n",
19895 __FUNCTION__
, macnum
));
19899 /* allocate memory for the MAC list */
19900 list
= (struct maclist
*)kmalloc(sizeof(int) +
19901 sizeof(struct ether_addr
) * macnum
, GFP_KERNEL
);
19903 WL_ERR(("%s : failed to allocate memory\n", __FUNCTION__
));
19907 /* prepare the MAC list */
19908 list
->count
= htod32(macnum
);
19909 for (i
= 0; i
< macnum
; i
++) {
19910 memcpy(&list
->ea
[i
], &acl
->mac_addrs
[i
], ETHER_ADDR_LEN
);
19913 if ((ret
= wl_android_set_ap_mac_list(cfgdev
, macmode
, list
)) != 0)
19914 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__
, ret
));
19920 #endif /* WL_CFG80211_ACL */
19922 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
19923 int wl_chspec_chandef(chanspec_t chanspec
,
19924 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
19925 struct cfg80211_chan_def
*chandef
,
19926 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
19927 struct chan_info
*chaninfo
,
19928 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
19929 struct wiphy
*wiphy
)
19935 struct ieee80211_channel
*chan
;
19940 channel
= CHSPEC_CHANNEL(chanspec
);
19942 switch (CHSPEC_BW(chanspec
)) {
19943 case WL_CHANSPEC_BW_20
:
19944 chan_type
= NL80211_CHAN_HT20
;
19946 case WL_CHANSPEC_BW_40
:
19948 if (CHSPEC_SB_UPPER(chanspec
)) {
19949 channel
+= CH_10MHZ_APART
;
19951 channel
-= CH_10MHZ_APART
;
19954 chan_type
= NL80211_CHAN_HT40PLUS
;
19957 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
19958 case WL_CHANSPEC_BW_80
:
19959 case WL_CHANSPEC_BW_8080
:
19961 uint16 sb
= CHSPEC_CTL_SB(chanspec
);
19963 if (sb
== WL_CHANSPEC_CTL_SB_LL
) {
19964 channel
-= (CH_10MHZ_APART
+ CH_20MHZ_APART
);
19965 } else if (sb
== WL_CHANSPEC_CTL_SB_LU
) {
19966 channel
-= CH_10MHZ_APART
;
19967 } else if (sb
== WL_CHANSPEC_CTL_SB_UL
) {
19968 channel
+= CH_10MHZ_APART
;
19970 /* WL_CHANSPEC_CTL_SB_UU */
19971 channel
+= (CH_10MHZ_APART
+ CH_20MHZ_APART
);
19974 if (sb
== WL_CHANSPEC_CTL_SB_LL
|| sb
== WL_CHANSPEC_CTL_SB_LU
)
19975 chan_type
= NL80211_CHAN_HT40MINUS
;
19976 else if (sb
== WL_CHANSPEC_CTL_SB_UL
|| sb
== WL_CHANSPEC_CTL_SB_UU
)
19977 chan_type
= NL80211_CHAN_HT40PLUS
;
19980 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
19982 chan_type
= NL80211_CHAN_HT20
;
19987 if (CHSPEC_IS5G(chanspec
))
19988 freq
= ieee80211_channel_to_frequency(channel
, NL80211_BAND_5GHZ
);
19990 freq
= ieee80211_channel_to_frequency(channel
, NL80211_BAND_2GHZ
);
19992 chan
= ieee80211_get_channel(wiphy
, freq
);
19993 WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
19994 channel
, freq
, chan_type
, chan
));
19996 if (unlikely(!chan
)) {
19997 /* fw and cfg80211 channel lists are not in sync */
19998 WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
20003 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20004 cfg80211_chandef_create(chandef
, chan
, chan_type
);
20005 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
20010 chaninfo
->freq
= freq
;
20011 chaninfo
->chan_type
= chan_type
;
20012 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20017 wl_cfg80211_ch_switch_notify(struct net_device
*dev
, uint16 chanspec
, struct wiphy
*wiphy
)
20020 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20021 struct cfg80211_chan_def chandef
;
20022 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
20027 struct chan_info chaninfo
;
20028 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20031 printf("wiphy is null\n");
20034 #ifndef ALLOW_CHSW_EVT
20035 /* Channel switch support is only for AP/GO/ADHOC/MESH */
20036 if (dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_STATION
||
20037 dev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_P2P_CLIENT
) {
20038 WL_ERR(("No channel switch notify support for STA/GC\n"));
20041 #endif /* !ALLOW_CHSW_EVT */
20042 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20043 if (wl_chspec_chandef(chanspec
, &chandef
, wiphy
))
20044 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
20045 if (wl_chspec_chandef(chanspec
, &chaninfo
, wiphy
))
20046 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20048 WL_ERR(("chspec_chandef failed\n"));
20051 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20052 freq
= chandef
.chan
? chandef
.chan
->center_freq
: chandef
.center_freq1
;
20053 cfg80211_ch_switch_notify(dev
, &chandef
);
20054 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
20055 freq
= chan_info
.freq
;
20056 cfg80211_ch_switch_notify(dev
, freq
, chan_info
.chan_type
);
20057 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20059 WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq
, chanspec
));
20062 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20066 wl_cfg80211_set_ulb_mode(struct net_device
*dev
, int mode
)
20071 ret
= wldev_iovar_getint(dev
, "ulb_mode", &cur_mode
);
20072 if (unlikely(ret
)) {
20073 WL_ERR(("[ULB] ulb_mode get failed. ret:%d \n", ret
));
20077 if (cur_mode
== mode
) {
20078 /* If request mode is same as that of the current mode, then
20079 * do nothing (Avoid unnecessary wl down and up).
20081 WL_INFORM(("[ULB] No change in ulb_mode. Do nothing.\n"));
20085 /* setting of ulb_mode requires wl to be down */
20086 ret
= wldev_ioctl_set(dev
, WLC_DOWN
, NULL
, 0);
20087 if (unlikely(ret
)) {
20088 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret
));
20092 if (mode
>= MAX_SUPP_ULB_MODES
) {
20093 WL_ERR(("[ULB] unsupported ulb_mode :[%d]\n", mode
));
20097 ret
= wldev_iovar_setint(dev
, "ulb_mode", mode
);
20098 if (unlikely(ret
)) {
20099 WL_ERR(("[ULB] ulb_mode set failed. ret:%d \n", ret
));
20103 ret
= wldev_ioctl_set(dev
, WLC_UP
, NULL
, 0);
20104 if (unlikely(ret
)) {
20105 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret
));
20109 WL_DBG(("[ULB] ulb_mode set to %d successfully \n", mode
));
20115 wl_cfg80211_ulbbw_to_ulbchspec(u32 bw
)
20117 if (bw
== ULB_BW_DISABLED
) {
20118 return WL_CHANSPEC_BW_20
;
20119 } else if (bw
== ULB_BW_10MHZ
) {
20120 return WL_CHANSPEC_BW_10
;
20121 } else if (bw
== ULB_BW_5MHZ
) {
20122 return WL_CHANSPEC_BW_5
;
20123 } else if (bw
== ULB_BW_2P5MHZ
) {
20124 return WL_CHANSPEC_BW_2P5
;
20126 WL_ERR(("[ULB] unsupported value for ulb_bw \n"));
20132 wl_cfg80211_ulb_get_min_bw_chspec(struct bcm_cfg80211
*cfg
, struct wireless_dev
*wdev
, s32 bssidx
)
20134 struct net_info
*_netinfo
;
20137 * Return the chspec value corresponding to the
20138 * BW setting for a particular interface
20141 /* if wdev is provided, use it */
20142 _netinfo
= wl_get_netinfo_by_wdev(cfg
, wdev
);
20143 } else if (bssidx
>= 0) {
20144 /* if wdev is not provided, use it */
20145 _netinfo
= wl_get_netinfo_by_bssidx(cfg
, bssidx
);
20147 WL_ERR(("[ULB] wdev/bssidx not provided\n"));
20148 return INVCHANSPEC
;
20151 if (unlikely(!_netinfo
)) {
20152 WL_ERR(("[ULB] net_info is null \n"));
20153 return INVCHANSPEC
;
20156 if (_netinfo
->ulb_bw
) {
20157 WL_DBG(("[ULB] wdev_ptr:%p ulb_bw:0x%x \n", _netinfo
->wdev
, _netinfo
->ulb_bw
));
20158 return wl_cfg80211_ulbbw_to_ulbchspec(_netinfo
->ulb_bw
);
20160 return WL_CHANSPEC_BW_20
;
20165 wl_cfg80211_get_ulb_bw(struct bcm_cfg80211
*cfg
, struct wireless_dev
*wdev
)
20167 struct net_info
*_netinfo
= wl_get_netinfo_by_wdev(cfg
, wdev
);
20170 * Return the ulb_bw setting for a
20171 * particular interface
20173 if (unlikely(!_netinfo
)) {
20174 WL_ERR(("[ULB] net_info is null \n"));
20178 return _netinfo
->ulb_bw
;
20182 wl_cfg80211_set_ulb_bw(struct net_device
*dev
,
20183 u32 ulb_bw
, char *ifname
)
20185 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20188 struct net_info
*_netinfo
= NULL
, *iter
, *next
;
20194 WL_DBG(("[ULB] Enter. bw_type:%d \n", ulb_bw
));
20196 ret
= wldev_iovar_getint(dev
, "ulb_mode", &mode
);
20197 if (unlikely(ret
)) {
20198 WL_ERR(("[ULB] ulb_mode not supported \n"));
20202 if (mode
!= ULB_MODE_STD_ALONE_MODE
) {
20203 WL_ERR(("[ULB] ulb bw modification allowed only in stand-alone mode\n"));
20207 if (ulb_bw
>= MAX_SUPP_ULB_BW
) {
20208 WL_ERR(("[ULB] unsupported value (%d) for ulb_bw \n", ulb_bw
));
20212 #ifdef WL_CFG80211_P2P_DEV_IF
20213 if (strcmp(ifname
, "p2p-dev-wlan0") == 0) {
20214 /* Use wdev corresponding to the dedicated p2p discovery interface */
20215 if (likely(cfg
->p2p_wdev
)) {
20216 _netinfo
= wl_get_netinfo_by_wdev(cfg
, cfg
->p2p_wdev
);
20221 #endif /* WL_CFG80211_P2P_DEV_IF */
20223 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20224 #pragma GCC diagnostic push
20225 #pragma GCC diagnostic ignored "-Wcast-qual"
20227 for_each_ndev(cfg
, iter
, next
) {
20229 if (strncmp(iter
->ndev
->name
, ifname
, strlen(ifname
)) == 0) {
20230 _netinfo
= wl_get_netinfo_by_netdev(cfg
, iter
->ndev
);
20234 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20235 #pragma GCC diagnostic pop
20241 bssidx
= _netinfo
->bssidx
;
20242 _netinfo
->ulb_bw
= ulb_bw
;
20245 WL_DBG(("[ULB] Applying ulb_bw:%d for bssidx:%d \n", ulb_bw
, bssidx
));
20246 ret
= wldev_iovar_setbuf_bsscfg(dev
, "ulb_bw", (void *)&ulb_bw
, 4,
20247 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, bssidx
,
20248 &cfg
->ioctl_buf_sync
);
20249 if (unlikely(ret
)) {
20250 WL_ERR(("[ULB] ulb_bw set failed. ret:%d \n", ret
));
20256 #endif /* WL11ULB */
20259 wl_ap_channel_ind(struct bcm_cfg80211
*cfg
,
20260 struct net_device
*ndev
,
20261 chanspec_t chanspec
)
20263 u32 channel
= LCHSPEC_CHANNEL(chanspec
);
20265 WL_DBG(("(%s) AP channel:%d chspec:0x%x \n",
20266 ndev
->name
, channel
, chanspec
));
20267 if (cfg
->ap_oper_channel
&& (cfg
->ap_oper_channel
!= channel
)) {
20269 * If cached channel is different from the channel indicated
20270 * by the event, notify user space about the channel switch.
20272 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
20273 wl_cfg80211_ch_switch_notify(ndev
, chanspec
, bcmcfg_to_wiphy(cfg
));
20274 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20275 cfg
->ap_oper_channel
= channel
;
20280 wl_ap_start_ind(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
20281 const wl_event_msg_t
*e
, void *data
)
20283 struct net_device
*ndev
= NULL
;
20284 chanspec_t chanspec
;
20286 WL_DBG(("Enter\n"));
20287 if (unlikely(e
->status
)) {
20288 WL_ERR(("status:0x%x \n", e
->status
));
20296 if (likely(cfgdev
)) {
20297 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
20298 chanspec
= *((chanspec_t
*)data
);
20300 if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_AP
) {
20301 /* For AP/GO role */
20302 wl_ap_channel_ind(cfg
, ndev
, chanspec
);
20310 wl_csa_complete_ind(struct bcm_cfg80211
*cfg
, bcm_struct_cfgdev
*cfgdev
,
20311 const wl_event_msg_t
*e
, void *data
)
20315 struct net_device
*ndev
= NULL
;
20317 WL_DBG(("Enter\n"));
20318 if (unlikely(e
->status
)) {
20319 WL_ERR(("status:0x%x \n", e
->status
));
20323 if (likely(cfgdev
)) {
20324 ndev
= cfgdev_to_wlc_ndev(cfgdev
, cfg
);
20325 error
= wldev_iovar_getint(ndev
, "chanspec", &chanspec
);
20326 if (unlikely(error
)) {
20327 WL_ERR(("Get chanspec error: %d \n", error
));
20331 if (wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_AP
) {
20332 /* For AP/GO role */
20333 wl_ap_channel_ind(cfg
, ndev
, chanspec
);
20335 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
20336 wl_cfg80211_ch_switch_notify(ndev
, chanspec
, bcmcfg_to_wiphy(cfg
));
20337 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20346 void wl_cfg80211_clear_security(struct bcm_cfg80211
*cfg
)
20348 struct net_device
*dev
= bcmcfg_to_prmry_ndev(cfg
);
20351 /* Clear the security settings on the primary Interface */
20352 err
= wldev_iovar_setint(dev
, "wsec", 0);
20353 if (unlikely(err
)) {
20354 WL_ERR(("wsec clear failed \n"));
20356 err
= wldev_iovar_setint(dev
, "auth", 0);
20357 if (unlikely(err
)) {
20358 WL_ERR(("auth clear failed \n"));
20360 err
= wldev_iovar_setint(dev
, "wpa_auth", WPA_AUTH_DISABLED
);
20361 if (unlikely(err
)) {
20362 WL_ERR(("wpa_auth clear failed \n"));
20366 #ifdef WL_CFG80211_P2P_DEV_IF
20367 void wl_cfg80211_del_p2p_wdev(struct net_device
*dev
)
20369 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20370 struct wireless_dev
*wdev
= NULL
;
20372 WL_DBG(("Enter \n"));
20374 WL_ERR(("Invalid Ptr\n"));
20377 wdev
= cfg
->p2p_wdev
;
20380 if (wdev
&& cfg
->down_disc_if
) {
20381 wl_cfgp2p_del_p2p_disc_if(wdev
, cfg
);
20382 cfg
->down_disc_if
= FALSE
;
20385 #endif /* WL_CFG80211_P2P_DEV_IF */
20387 #ifdef GTK_OFFLOAD_SUPPORT
20388 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
20390 wl_cfg80211_set_rekey_data(struct wiphy
*wiphy
, struct net_device
*dev
,
20391 struct cfg80211_gtk_rekey_data
*data
)
20393 struct bcm_cfg80211
*cfg
= wiphy_priv(wiphy
);
20395 gtk_keyinfo_t keyinfo
;
20397 WL_DBG(("Enter\n"));
20398 if (data
== NULL
|| cfg
->p2p_net
== dev
) {
20399 WL_ERR(("data is NULL or wrong net device\n"));
20402 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
20403 prhex("kck", (uchar
*) (data
->kck
), RSN_KCK_LENGTH
);
20404 prhex("kek", (uchar
*) (data
->kek
), RSN_KEK_LENGTH
);
20405 prhex("replay_ctr", (uchar
*) (data
->replay_ctr
), RSN_REPLAY_LEN
);
20407 prhex("kck", (uchar
*)data
->kck
, RSN_KCK_LENGTH
);
20408 prhex("kek", (uchar
*)data
->kek
, RSN_KEK_LENGTH
);
20409 prhex("replay_ctr", (uchar
*)data
->replay_ctr
, RSN_REPLAY_LEN
);
20410 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) */
20411 bcopy(data
->kck
, keyinfo
.KCK
, RSN_KCK_LENGTH
);
20412 bcopy(data
->kek
, keyinfo
.KEK
, RSN_KEK_LENGTH
);
20413 bcopy(data
->replay_ctr
, keyinfo
.ReplayCounter
, RSN_REPLAY_LEN
);
20415 if ((err
= wldev_iovar_setbuf(dev
, "gtk_key_info", &keyinfo
, sizeof(keyinfo
),
20416 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
)) < 0) {
20417 WL_ERR(("seting gtk_key_info failed code=%d\n", err
));
20420 WL_DBG(("Exit\n"));
20423 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
20424 #endif /* GTK_OFFLOAD_SUPPORT */
20426 #if defined(WL_SUPPORT_AUTO_CHANNEL)
20428 wl_cfg80211_set_spect(struct net_device
*dev
, int spect
)
20430 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20435 if (!wl_get_drv_status_all(cfg
, CONNECTED
)) {
20436 err
= wldev_ioctl_set(dev
, WLC_DOWN
, &wlc_down
, sizeof(wlc_down
));
20438 WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__
, err
));
20442 err
= wldev_ioctl_set(dev
, WLC_SET_SPECT_MANAGMENT
, &spect
, sizeof(spect
));
20444 WL_ERR(("%s: error setting spect: code: %d\n", __func__
, err
));
20448 err
= wldev_ioctl_set(dev
, WLC_UP
, &wlc_up
, sizeof(wlc_up
));
20450 WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__
, err
));
20458 wl_cfg80211_get_sta_channel(struct net_device
*dev
)
20460 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20463 if (wl_get_drv_status(cfg
, CONNECTED
, dev
)) {
20464 channel
= cfg
->channel
;
20468 #endif /* WL_SUPPORT_AUTO_CHANNEL */
20469 #ifdef P2P_LISTEN_OFFLOADING
20471 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211
*cfg
)
20475 int p2plo_pause
= 0;
20476 if (!cfg
|| !cfg
->p2p
) {
20477 WL_ERR(("Wl %p or cfg->p2p %p is null\n",
20478 cfg
, cfg
? cfg
->p2p
: 0));
20482 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
20483 ret
= wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg
),
20484 "p2po_stop", (void*)&p2plo_pause
, sizeof(p2plo_pause
),
20485 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, bssidx
, &cfg
->ioctl_buf_sync
);
20487 WL_ERR(("p2po_stop Failed :%d\n", ret
));
20493 wl_cfg80211_p2plo_listen_start(struct net_device
*dev
, u8
*buf
, int len
)
20495 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20496 s32 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
20497 wl_p2plo_listen_t p2plo_listen
;
20503 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg
)) {
20504 WL_ERR(("Sending Action Frames. Try it again.\n"));
20508 if (wl_get_drv_status_all(cfg
, SCANNING
)) {
20509 WL_ERR(("Scanning already\n"));
20513 if (wl_get_drv_status(cfg
, SCAN_ABORTING
, dev
)) {
20514 WL_ERR(("Scanning being aborted\n"));
20518 if (wl_get_p2p_status(cfg
, DISC_IN_PROGRESS
)) {
20519 WL_ERR(("p2p listen offloading already running\n"));
20523 /* Just in case if it is not enabled */
20524 if ((ret
= wl_cfgp2p_enable_discovery(cfg
, dev
, NULL
, 0)) < 0) {
20525 WL_ERR(("cfgp2p_enable discovery failed"));
20529 bzero(&p2plo_listen
, sizeof(wl_p2plo_listen_t
));
20532 sscanf(buf
, " %10d %10d %10d %10d", &channel
, &period
, &interval
, &count
);
20533 if ((channel
== 0) || (period
== 0) ||
20534 (interval
== 0) || (count
== 0)) {
20535 WL_ERR(("Wrong argument %d/%d/%d/%d \n",
20536 channel
, period
, interval
, count
));
20540 p2plo_listen
.period
= period
;
20541 p2plo_listen
.interval
= interval
;
20542 p2plo_listen
.count
= count
;
20544 WL_ERR(("channel:%d period:%d, interval:%d count:%d\n",
20545 channel
, period
, interval
, count
));
20547 WL_ERR(("Argument len is wrong.\n"));
20552 if ((ret
= wldev_iovar_setbuf_bsscfg(dev
, "p2po_listen_channel", (void*)&channel
,
20553 sizeof(channel
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
20554 bssidx
, &cfg
->ioctl_buf_sync
)) < 0) {
20555 WL_ERR(("p2po_listen_channel Failed :%d\n", ret
));
20559 if ((ret
= wldev_iovar_setbuf_bsscfg(dev
, "p2po_listen", (void*)&p2plo_listen
,
20560 sizeof(wl_p2plo_listen_t
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
20561 bssidx
, &cfg
->ioctl_buf_sync
)) < 0) {
20562 WL_ERR(("p2po_listen Failed :%d\n", ret
));
20566 wl_set_p2p_status(cfg
, DISC_IN_PROGRESS
);
20571 wl_cfg80211_p2plo_listen_stop(struct net_device
*dev
)
20573 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20574 s32 bssidx
= wl_to_p2p_bss_bssidx(cfg
, P2PAPI_BSSCFG_DEVICE
);
20577 if ((ret
= wldev_iovar_setbuf_bsscfg(dev
, "p2po_stop", NULL
,
20578 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
20579 bssidx
, &cfg
->ioctl_buf_sync
)) < 0) {
20580 WL_ERR(("p2po_stop Failed :%d\n", ret
));
20587 #endif /* P2P_LISTEN_OFFLOADING */
20590 wl_cfg80211_get_new_roc_id(struct bcm_cfg80211
*cfg
)
20593 id
= ++cfg
->last_roc_id
;
20594 #ifdef P2P_LISTEN_OFFLOADING
20595 if (id
== P2PO_COOKIE
) {
20596 id
= ++cfg
->last_roc_id
;
20598 #endif /* P2P_LISTEN_OFFLOADING */
20600 id
= ++cfg
->last_roc_id
;
20604 #if defined(SUPPORT_RANDOM_MAC_SCAN)
20606 wl_cfg80211_set_random_mac(struct net_device
*dev
, bool enable
)
20608 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20611 if (cfg
->random_mac_enabled
== enable
) {
20612 WL_ERR(("Random MAC already %s\n", enable
? "Enabled" : "Disabled"));
20617 ret
= wl_cfg80211_random_mac_enable(dev
);
20619 ret
= wl_cfg80211_random_mac_disable(dev
);
20623 cfg
->random_mac_enabled
= enable
;
20630 wl_cfg80211_random_mac_enable(struct net_device
*dev
)
20632 u8 random_mac
[ETH_ALEN
] = {0, };
20633 u8 rand_bytes
[3] = {0, };
20634 s32 err
= BCME_ERROR
;
20635 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20637 if (wl_get_drv_status_all(cfg
, CONNECTED
) || wl_get_drv_status_all(cfg
, CONNECTING
) ||
20638 wl_get_drv_status_all(cfg
, AP_CREATED
) || wl_get_drv_status_all(cfg
, AP_CREATING
)) {
20639 WL_ERR(("fail to Set random mac, current state is wrong\n"));
20643 memcpy(random_mac
, bcmcfg_to_prmry_ndev(cfg
)->dev_addr
, ETH_ALEN
);
20644 get_random_bytes(&rand_bytes
, sizeof(rand_bytes
));
20646 if (rand_bytes
[2] == 0x0 || rand_bytes
[2] == 0xff) {
20647 rand_bytes
[2] = 0xf0;
20650 memcpy(&random_mac
[3], rand_bytes
, sizeof(rand_bytes
));
20652 err
= wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg
), "cur_etheraddr",
20653 random_mac
, ETH_ALEN
, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, 0, &cfg
->ioctl_buf_sync
);
20655 if (err
!= BCME_OK
) {
20656 WL_ERR(("failed to set random generate MAC address\n"));
20658 WL_ERR(("set mac " MACDBG
" to " MACDBG
"\n",
20659 MAC2STRDBG((const u8
*)bcmcfg_to_prmry_ndev(cfg
)->dev_addr
),
20660 MAC2STRDBG((const u8
*)&random_mac
)));
20661 WL_ERR(("random MAC enable done"));
20668 wl_cfg80211_random_mac_disable(struct net_device
*dev
)
20670 s32 err
= BCME_ERROR
;
20671 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20673 WL_ERR(("set original mac " MACDBG
"\n",
20674 MAC2STRDBG((const u8
*)bcmcfg_to_prmry_ndev(cfg
)->dev_addr
)));
20676 err
= wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg
), "cur_etheraddr",
20677 bcmcfg_to_prmry_ndev(cfg
)->dev_addr
, ETH_ALEN
,
20678 cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, 0, &cfg
->ioctl_buf_sync
);
20680 if (err
!= BCME_OK
) {
20681 WL_ERR(("failed to set original MAC address\n"));
20683 WL_ERR(("random MAC disable done\n"));
20688 #endif /* SUPPORT_RANDOM_MAC_SCAN */
20692 wl_cfg80211_tdls_config(struct bcm_cfg80211
*cfg
, enum wl_tdls_config state
, bool auto_mode
)
20694 struct net_device
*ndev
= bcmcfg_to_prmry_ndev(cfg
);
20696 struct net_info
*iter
, *next
;
20697 int update_reqd
= 0;
20700 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
20703 * TDLS need to be enabled only if we have a single STA/GC
20707 WL_DBG(("Enter state:%d\n", state
));
20709 if (!cfg
->tdls_supported
) {
20710 /* FW doesn't support tdls. Do nothing */
20714 /* Protect tdls config session */
20715 mutex_lock(&cfg
->tdls_sync
);
20717 if ((state
== TDLS_STATE_TEARDOWN
)) {
20718 /* Host initiated TDLS tear down */
20719 err
= dhd_tdls_enable(ndev
, false, auto_mode
, NULL
);
20721 } else if (state
== TDLS_STATE_AP_CREATE
) {
20722 /* We don't support tdls while AP/GO is operational */
20723 update_reqd
= true;
20725 } else if ((state
== TDLS_STATE_CONNECT
) || (state
== TDLS_STATE_IF_CREATE
)) {
20726 if (wl_get_drv_status_all(cfg
,
20727 CONNECTED
) >= TDLS_MAX_IFACE_FOR_ENABLE
) {
20728 /* For STA/GC connect command request, disable
20729 * tdls if we have any concurrent interfaces
20732 WL_DBG(("Interface limit restriction. disable tdls.\n"));
20733 update_reqd
= true;
20736 } else if ((state
== TDLS_STATE_DISCONNECT
) ||
20737 (state
== TDLS_STATE_AP_DELETE
) ||
20738 (state
== TDLS_STATE_SETUP
) ||
20739 (state
== TDLS_STATE_IF_DELETE
)) {
20740 /* Enable back the tdls connection only if we have less than
20741 * or equal to a single STA/GC connection.
20743 if (wl_get_drv_status_all(cfg
,
20745 /* If there are no interfaces connected, enable tdls */
20746 update_reqd
= true;
20748 } else if (wl_get_drv_status_all(cfg
,
20749 CONNECTED
) == TDLS_MAX_IFACE_FOR_ENABLE
) {
20750 /* We have one interface in CONNECTED state.
20751 * Verify whether its a non-AP interface before
20752 * we enable back tdls.
20754 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20755 #pragma GCC diagnostic push
20756 #pragma GCC diagnostic ignored "-Wcast-qual"
20758 for_each_ndev(cfg
, iter
, next
) {
20759 if ((iter
->ndev
) && (wl_get_drv_status(cfg
, CONNECTED
, ndev
)) &&
20760 wl_get_mode_by_netdev(cfg
, ndev
) == WL_MODE_AP
) {
20761 WL_DBG(("AP/GO operational. Can't enable tdls. \n"));
20766 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20767 #pragma GCC diagnostic pop
20769 /* No AP/GO found. Enable back tdls */
20770 update_reqd
= true;
20773 WL_DBG(("Concurrent connection mode. Can't enable tdls. \n"));
20778 WL_ERR(("Unknown tdls state:%d \n", state
));
20783 if (update_reqd
== true) {
20784 if (dhdp
->tdls_enable
== enable
) {
20785 WL_ERR(("No change in tdls state. Do nothing."
20786 " tdls_enable:%d\n", enable
));
20789 err
= wldev_iovar_setint(ndev
, "tdls_enable", enable
);
20790 if (unlikely(err
)) {
20791 WL_ERR(("tdls_enable setting failed. err:%d\n", err
));
20794 WL_DBG(("set tdls_enable: %d done\n", enable
));
20795 /* Update the dhd state variable to be in sync */
20796 dhdp
->tdls_enable
= enable
;
20797 if (state
== TDLS_STATE_SETUP
) {
20798 /* For host initiated setup, apply TDLS params
20799 * Don't propagate errors up for param config
20802 dhd_tdls_enable(ndev
, true, auto_mode
, NULL
);
20807 WL_DBG(("Skip tdls config. state:%d update_reqd:%d "
20808 "current_status:%d \n",
20809 state
, update_reqd
, dhdp
->tdls_enable
));
20813 mutex_unlock(&cfg
->tdls_sync
);
20817 #endif /* WLTDLS */
20819 struct net_device
* wl_get_ap_netdev(struct bcm_cfg80211
*cfg
, char *ifname
)
20821 struct net_info
*iter
, *next
;
20822 struct net_device
*ndev
= NULL
;
20824 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20825 #pragma GCC diagnostic push
20826 #pragma GCC diagnostic ignored "-Wcast-qual"
20828 for_each_ndev(cfg
, iter
, next
) {
20830 if (strncmp(iter
->ndev
->name
, ifname
, strlen(iter
->ndev
->name
)) == 0) {
20831 if (iter
->ndev
->ieee80211_ptr
->iftype
== NL80211_IFTYPE_AP
) {
20838 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20839 #pragma GCC diagnostic pop
20846 wl_get_netdev_by_name(struct bcm_cfg80211
*cfg
, char *ifname
)
20848 struct net_info
*iter
, *next
;
20849 struct net_device
*ndev
= NULL
;
20851 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20852 #pragma GCC diagnostic push
20853 #pragma GCC diagnostic ignored "-Wcast-qual"
20855 for_each_ndev(cfg
, iter
, next
) {
20857 if (strncmp(iter
->ndev
->name
, ifname
, IFNAMSIZ
) == 0) {
20863 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20864 #pragma GCC diagnostic pop
20870 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
20871 #define WLC_RATE_FLAG 0x80
20872 #define RATE_MASK 0x7f
20874 int wl_set_ap_beacon_rate(struct net_device
*dev
, int val
, char *ifname
)
20876 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20878 wl_rateset_args_t rs
;
20879 int error
= BCME_ERROR
, i
;
20880 struct net_device
*ndev
= NULL
;
20882 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
20884 if (dhdp
&& !(dhdp
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
20885 WL_ERR(("Not Hostapd mode\n"));
20889 ndev
= wl_get_ap_netdev(cfg
, ifname
);
20891 if (ndev
== NULL
) {
20892 WL_ERR(("No softAP interface named %s\n", ifname
));
20896 bzero(&rs
, sizeof(wl_rateset_args_t
));
20897 error
= wldev_iovar_getbuf(ndev
, "rateset", NULL
, 0,
20898 &rs
, sizeof(wl_rateset_args_t
), NULL
);
20900 WL_ERR(("get rateset failed = %d\n", error
));
20904 if (rs
.count
< 1) {
20905 WL_ERR(("Failed to get rate count\n"));
20909 /* Host delivers target rate in the unit of 500kbps */
20910 /* To make it to 1mbps unit, atof should be implemented for 5.5mbps basic rate */
20911 for (i
= 0; i
< rs
.count
&& i
< WL_NUMRATES
; i
++)
20912 if (rs
.rates
[i
] & WLC_RATE_FLAG
)
20913 if ((rs
.rates
[i
] & RATE_MASK
) == val
)
20916 /* Valid rate has been delivered as an argument */
20917 if (i
< rs
.count
&& i
< WL_NUMRATES
) {
20918 error
= wldev_iovar_setint(ndev
, "force_bcn_rspec", val
);
20920 WL_ERR(("set beacon rate failed = %d\n", error
));
20924 WL_ERR(("Rate is invalid"));
20925 return BCME_BADARG
;
20932 wl_get_ap_basic_rate(struct net_device
*dev
, char* command
, char *ifname
, int total_len
)
20934 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20936 wl_rateset_args_t rs
;
20937 int error
= BCME_ERROR
;
20938 int i
, bytes_written
= 0;
20939 struct net_device
*ndev
= NULL
;
20941 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
20943 if (!(dhdp
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
20944 WL_ERR(("Not Hostapd mode\n"));
20948 ndev
= wl_get_ap_netdev(cfg
, ifname
);
20950 if (ndev
== NULL
) {
20951 WL_ERR(("No softAP interface named %s\n", ifname
));
20955 bzero(&rs
, sizeof(wl_rateset_args_t
));
20956 error
= wldev_iovar_getbuf(ndev
, "rateset", NULL
, 0,
20957 &rs
, sizeof(wl_rateset_args_t
), NULL
);
20959 WL_ERR(("get rateset failed = %d\n", error
));
20963 if (rs
.count
< 1) {
20964 WL_ERR(("Failed to get rate count\n"));
20968 /* Delivers basic rate in the unit of 500kbps to host */
20969 for (i
= 0; i
< rs
.count
&& i
< WL_NUMRATES
; i
++)
20970 if (rs
.rates
[i
] & WLC_RATE_FLAG
)
20971 bytes_written
+= snprintf(command
+ bytes_written
, total_len
,
20972 "%d ", rs
.rates
[i
] & RATE_MASK
);
20974 /* Remove last space in the command buffer */
20975 if (bytes_written
) {
20976 command
[bytes_written
- 1] = '\0';
20980 return bytes_written
;
20983 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
20985 #ifdef SUPPORT_AP_RADIO_PWRSAVE
20987 _wl_update_ap_rps_params(struct net_device
*dev
)
20989 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
20990 rpsnoa_iovar_params_t iovar
;
20991 u8 smbuf
[WLC_IOCTL_SMLEN
];
20994 return BCME_BADARG
;
20996 memset(&iovar
, 0, sizeof(iovar
));
20997 memset(smbuf
, 0, sizeof(smbuf
));
20999 iovar
.hdr
.ver
= RADIO_PWRSAVE_VERSION
;
21000 iovar
.hdr
.subcmd
= WL_RPSNOA_CMD_PARAMS
;
21001 iovar
.hdr
.len
= sizeof(iovar
);
21002 iovar
.param
->band
= WLC_BAND_ALL
;
21003 iovar
.param
->level
= cfg
->ap_rps_info
.level
;
21004 iovar
.param
->stas_assoc_check
= cfg
->ap_rps_info
.sta_assoc_check
;
21005 iovar
.param
->pps
= cfg
->ap_rps_info
.pps
;
21006 iovar
.param
->quiet_time
= cfg
->ap_rps_info
.quiet_time
;
21008 if (wldev_iovar_setbuf(dev
, "rpsnoa", &iovar
, sizeof(iovar
),
21009 smbuf
, sizeof(smbuf
), NULL
)) {
21010 WL_ERR(("Failed to set rpsnoa params"));
21018 wl_get_ap_rps(struct net_device
*dev
, char* command
, char *ifname
, int total_len
)
21020 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21022 int error
= BCME_ERROR
;
21023 int bytes_written
= 0;
21024 struct net_device
*ndev
= NULL
;
21025 rpsnoa_iovar_t iovar
;
21026 u8 smbuf
[WLC_IOCTL_SMLEN
];
21031 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
21034 error
= BCME_NOTUP
;
21038 if (!(dhdp
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
21039 WL_ERR(("Not Hostapd mode\n"));
21040 error
= BCME_NOTAP
;
21044 ndev
= wl_get_ap_netdev(cfg
, ifname
);
21046 if (ndev
== NULL
) {
21047 WL_ERR(("No softAP interface named %s\n", ifname
));
21048 error
= BCME_NOTAP
;
21052 memset(&iovar
, 0, sizeof(iovar
));
21053 memset(smbuf
, 0, sizeof(smbuf
));
21055 iovar
.hdr
.ver
= RADIO_PWRSAVE_VERSION
;
21056 iovar
.hdr
.subcmd
= WL_RPSNOA_CMD_STATUS
;
21057 iovar
.hdr
.len
= sizeof(iovar
);
21058 iovar
.data
->band
= WLC_BAND_ALL
;
21060 error
= wldev_iovar_getbuf(ndev
, "rpsnoa", &iovar
, sizeof(iovar
),
21061 smbuf
, sizeof(smbuf
), NULL
);
21063 WL_ERR(("get ap radio pwrsave failed = %d\n", error
));
21067 /* RSDB event doesn't seem to be handled correctly.
21068 * So check chanspec of AP directly from the firmware
21070 error
= wldev_iovar_getint(ndev
, "chanspec", (s32
*)&chanspec
);
21072 WL_ERR(("get chanspec from AP failed = %d\n", error
));
21076 chanspec
= wl_chspec_driver_to_host(chanspec
);
21077 if (CHSPEC_IS2G(chanspec
))
21079 else if (CHSPEC_IS5G(chanspec
))
21082 error
= BCME_BADCHAN
;
21086 val
= ((rpsnoa_iovar_t
*)smbuf
)->data
[idx
].value
;
21087 bytes_written
+= snprintf(command
+ bytes_written
, total_len
, "%d", val
);
21088 error
= bytes_written
;
21095 wl_set_ap_rps(struct net_device
*dev
, bool enable
, char *ifname
)
21097 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21099 struct net_device
*ndev
= NULL
;
21100 rpsnoa_iovar_t iovar
;
21101 u8 smbuf
[WLC_IOCTL_SMLEN
];
21104 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
21111 if (!(dhdp
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
21112 WL_ERR(("Not Hostapd mode\n"));
21117 ndev
= wl_get_ap_netdev(cfg
, ifname
);
21119 if (ndev
== NULL
) {
21120 WL_ERR(("No softAP interface named %s\n", ifname
));
21125 if (cfg
->ap_rps_info
.enable
!= enable
) {
21126 cfg
->ap_rps_info
.enable
= enable
;
21128 ret
= _wl_update_ap_rps_params(ndev
);
21130 WL_ERR(("Filed to update rpsnoa params\n"));
21134 memset(&iovar
, 0, sizeof(iovar
));
21135 memset(smbuf
, 0, sizeof(smbuf
));
21137 iovar
.hdr
.ver
= RADIO_PWRSAVE_VERSION
;
21138 iovar
.hdr
.subcmd
= WL_RPSNOA_CMD_ENABLE
;
21139 iovar
.hdr
.len
= sizeof(iovar
);
21140 iovar
.data
->band
= WLC_BAND_ALL
;
21141 iovar
.data
->value
= (int16
)enable
;
21143 ret
= wldev_iovar_setbuf(ndev
, "rpsnoa", &iovar
, sizeof(iovar
),
21144 smbuf
, sizeof(smbuf
), NULL
);
21146 WL_ERR(("Failed to enable AP radio power save"));
21149 cfg
->ap_rps_info
.enable
= enable
;
21156 wl_update_ap_rps_params(struct net_device
*dev
, ap_rps_info_t
* rps
, char *ifname
)
21158 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21160 struct net_device
*ndev
= NULL
;
21162 dhdp
= (dhd_pub_t
*)(cfg
->pub
);
21167 if (!(dhdp
->op_mode
& DHD_FLAG_HOSTAP_MODE
)) {
21168 WL_ERR(("Not Hostapd mode\n"));
21172 ndev
= wl_get_ap_netdev(cfg
, ifname
);
21174 if (ndev
== NULL
) {
21175 WL_ERR(("No softAP interface named %s\n", ifname
));
21180 return BCME_BADARG
;
21182 if (rps
->pps
< RADIO_PWRSAVE_PPS_MIN
)
21183 return BCME_BADARG
;
21185 if (rps
->level
< RADIO_PWRSAVE_LEVEL_MIN
||
21186 rps
->level
> RADIO_PWRSAVE_LEVEL_MAX
)
21187 return BCME_BADARG
;
21189 if (rps
->quiet_time
< RADIO_PWRSAVE_QUIETTIME_MIN
)
21190 return BCME_BADARG
;
21192 if (rps
->sta_assoc_check
> RADIO_PWRSAVE_ASSOCCHECK_MAX
||
21193 rps
->sta_assoc_check
< RADIO_PWRSAVE_ASSOCCHECK_MIN
)
21194 return BCME_BADARG
;
21196 cfg
->ap_rps_info
.pps
= rps
->pps
;
21197 cfg
->ap_rps_info
.level
= rps
->level
;
21198 cfg
->ap_rps_info
.quiet_time
= rps
->quiet_time
;
21199 cfg
->ap_rps_info
.sta_assoc_check
= rps
->sta_assoc_check
;
21201 if (cfg
->ap_rps_info
.enable
) {
21202 if (_wl_update_ap_rps_params(ndev
)) {
21203 WL_ERR(("Failed to update rpsnoa params"));
21212 wl_cfg80211_init_ap_rps(struct bcm_cfg80211
*cfg
)
21214 cfg
->ap_rps_info
.enable
= FALSE
;
21215 cfg
->ap_rps_info
.sta_assoc_check
= RADIO_PWRSAVE_STAS_ASSOC_CHECK
;
21216 cfg
->ap_rps_info
.pps
= RADIO_PWRSAVE_PPS
;
21217 cfg
->ap_rps_info
.quiet_time
= RADIO_PWRSAVE_QUIET_TIME
;
21218 cfg
->ap_rps_info
.level
= RADIO_PWRSAVE_LEVEL
;
21220 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
21223 wl_cfg80211_iface_count(struct net_device
*dev
)
21225 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21226 struct net_info
*iter
, *next
;
21227 int iface_count
= 0;
21229 /* Return the count of network interfaces (skip netless p2p discovery
21232 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21233 #pragma GCC diagnostic push
21234 #pragma GCC diagnostic ignored "-Wcast-qual"
21236 for_each_ndev(cfg
, iter
, next
) {
21241 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21242 #pragma GCC diagnostic pop
21244 return iface_count
;
21248 static bool wl_cfg80211_wbtext_check_bssid_list(struct bcm_cfg80211
*cfg
, struct ether_addr
*ea
)
21250 wl_wbtext_bssid_t
*bssid
= NULL
;
21251 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21252 #pragma GCC diagnostic push
21253 #pragma GCC diagnostic ignored "-Wcast-qual"
21256 /* check duplicate */
21257 list_for_each_entry(bssid
, &cfg
->wbtext_bssid_list
, list
) {
21258 if (!memcmp(bssid
->ea
.octet
, ea
, ETHER_ADDR_LEN
)) {
21266 static bool wl_cfg80211_wbtext_add_bssid_list(struct bcm_cfg80211
*cfg
, struct ether_addr
*ea
)
21268 wl_wbtext_bssid_t
*bssid
= NULL
;
21269 char eabuf
[ETHER_ADDR_STR_LEN
];
21271 bssid
= kmalloc(sizeof(wl_wbtext_bssid_t
), GFP_KERNEL
);
21272 if (bssid
== NULL
) {
21273 WL_ERR(("alloc failed\n"));
21277 memcpy(bssid
->ea
.octet
, ea
, ETHER_ADDR_LEN
);
21279 INIT_LIST_HEAD(&bssid
->list
);
21280 list_add_tail(&bssid
->list
, &cfg
->wbtext_bssid_list
);
21282 WL_DBG(("add wbtext bssid : %s\n", bcm_ether_ntoa(ea
, eabuf
)));
21287 static void wl_cfg80211_wbtext_clear_bssid_list(struct bcm_cfg80211
*cfg
)
21289 wl_wbtext_bssid_t
*bssid
= NULL
;
21290 char eabuf
[ETHER_ADDR_STR_LEN
];
21292 while (!list_empty(&cfg
->wbtext_bssid_list
)) {
21293 bssid
= list_entry(cfg
->wbtext_bssid_list
.next
, wl_wbtext_bssid_t
, list
);
21295 WL_DBG(("clear wbtext bssid : %s\n", bcm_ether_ntoa(&bssid
->ea
, eabuf
)));
21296 list_del(&bssid
->list
);
21302 static void wl_cfg80211_wbtext_update_rcc(struct bcm_cfg80211
*cfg
, struct net_device
*dev
)
21304 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
21305 bcm_tlv_t
* cap_ie
= NULL
;
21306 bool req_sent
= FALSE
;
21307 struct wl_profile
*profile
;
21309 WL_DBG(("Enter\n"));
21311 profile
= wl_get_profile_by_netdev(cfg
, dev
);
21313 WL_ERR(("no profile exists\n"));
21317 if (wl_cfg80211_wbtext_check_bssid_list(cfg
,
21318 (struct ether_addr
*)&profile
->bssid
) == FALSE
) {
21319 WL_DBG(("already updated\n"));
21323 /* first, check NBR bit in RRM IE */
21324 if ((cap_ie
= bcm_parse_tlvs(conn_info
->resp_ie
, conn_info
->resp_ie_len
,
21325 DOT11_MNG_RRM_CAP_ID
)) != NULL
) {
21326 if (isset(cap_ie
->data
, DOT11_RRM_CAP_NEIGHBOR_REPORT
)) {
21327 req_sent
= wl_cfg80211_wbtext_send_nbr_req(cfg
, dev
, profile
);
21331 /* if RRM nbr was not supported, check BTM bit in extend cap. IE */
21333 if ((cap_ie
= bcm_parse_tlvs(conn_info
->resp_ie
, conn_info
->resp_ie_len
,
21334 DOT11_MNG_EXT_CAP_ID
)) != NULL
) {
21335 if (cap_ie
->len
>= DOT11_EXTCAP_LEN_BSSTRANS
&&
21336 isset(cap_ie
->data
, DOT11_EXT_CAP_BSSTRANS_MGMT
)) {
21337 wl_cfg80211_wbtext_send_btm_query(cfg
, dev
, profile
);
21343 static bool wl_cfg80211_wbtext_send_nbr_req(struct bcm_cfg80211
*cfg
, struct net_device
*dev
,
21344 struct wl_profile
*profile
)
21347 char *smbuf
= NULL
;
21348 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
21349 bcm_tlv_t
* rrm_cap_ie
= NULL
;
21350 wlc_ssid_t
*ssid
= NULL
;
21353 WL_DBG(("Enter\n"));
21355 /* check RRM nbr bit in extend cap. IE of assoc response */
21356 if ((rrm_cap_ie
= bcm_parse_tlvs(conn_info
->resp_ie
, conn_info
->resp_ie_len
,
21357 DOT11_MNG_RRM_CAP_ID
)) != NULL
) {
21358 if (!isset(rrm_cap_ie
->data
, DOT11_RRM_CAP_NEIGHBOR_REPORT
)) {
21359 WL_DBG(("AP doesn't support neighbor report\n"));
21364 smbuf
= (char *) kmalloc(WLC_IOCTL_MAXLEN
, GFP_KERNEL
);
21365 if (smbuf
== NULL
) {
21366 WL_ERR(("failed to allocated memory\n"));
21370 ssid
= (wlc_ssid_t
*) kzalloc(sizeof(wlc_ssid_t
), GFP_KERNEL
);
21371 if (ssid
== NULL
) {
21372 WL_ERR(("failed to allocated memory\n"));
21376 ssid
->SSID_len
= MIN(profile
->ssid
.SSID_len
, DOT11_MAX_SSID_LEN
);
21377 memcpy(ssid
->SSID
, profile
->ssid
.SSID
, ssid
->SSID_len
);
21379 error
= wldev_iovar_setbuf(dev
, "rrm_nbr_req", ssid
,
21380 sizeof(wlc_ssid_t
), smbuf
, WLC_IOCTL_MAXLEN
, NULL
);
21381 if (error
== BCME_OK
) {
21382 ret
= wl_cfg80211_wbtext_add_bssid_list(cfg
,
21383 (struct ether_addr
*)&profile
->bssid
);
21385 WL_ERR(("failed to send neighbor report request, error=%d\n", error
));
21399 static bool wl_cfg80211_wbtext_send_btm_query(struct bcm_cfg80211
*cfg
, struct net_device
*dev
,
21400 struct wl_profile
*profile
)
21406 WL_DBG(("Enter\n"));
21408 error
= wldev_iovar_setbuf(dev
, "wnm_bsstrans_query", NULL
,
21409 0, cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
, &cfg
->ioctl_buf_sync
);
21410 if (error
== BCME_OK
) {
21411 ret
= wl_cfg80211_wbtext_add_bssid_list(cfg
,
21412 (struct ether_addr
*)&profile
->bssid
);
21414 WL_ERR(("%s: failed to set BTM query, error=%d\n", __FUNCTION__
, error
));
21419 static void wl_cfg80211_wbtext_set_wnm_maxidle(struct bcm_cfg80211
*cfg
, struct net_device
*dev
)
21421 keepalives_max_idle_t keepalive
= {0, 0, 0, 0};
21423 int wnm_maxidle
= 0;
21424 struct wl_connect_info
*conn_info
= wl_to_conn(cfg
);
21426 /* AP supports wnm max idle ? */
21427 if (bcm_parse_tlvs(conn_info
->resp_ie
, conn_info
->resp_ie_len
,
21428 DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID
) != NULL
) {
21429 error
= wldev_iovar_getint(dev
, "wnm_maxidle", &wnm_maxidle
);
21431 WL_ERR(("failed to get wnm max idle period : %d\n", error
));
21435 WL_DBG(("wnm max idle period : %d\n", wnm_maxidle
));
21437 /* if wnm maxidle has valid period, set it as keep alive */
21438 if (wnm_maxidle
> 0) {
21439 keepalive
.keepalive_count
= 1;
21442 if ((bssidx
= wl_get_bssidx_by_wdev(cfg
, dev
->ieee80211_ptr
)) >= 0) {
21443 error
= wldev_iovar_setbuf_bsscfg(dev
, "wnm_keepalives_max_idle", &keepalive
,
21444 sizeof(keepalives_max_idle_t
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
21445 bssidx
, &cfg
->ioctl_buf_sync
);
21447 WL_ERR(("set wnm_keepalives_max_idle failed : %d\n", error
));
21453 wl_cfg80211_recv_nbr_resp(struct net_device
*dev
, uint8
*body
, int body_len
)
21455 dot11_rm_action_t
*rm_rep
;
21457 int tlv_len
, i
, error
;
21458 dot11_neighbor_rep_ie_t
*nbr_rep_ie
;
21460 wl_roam_channel_list_t channel_list
;
21461 char iobuf
[WLC_IOCTL_SMLEN
];
21463 if (body_len
< DOT11_RM_ACTION_LEN
) {
21464 WL_ERR(("Received Neighbor Report frame with incorrect length %d\n",
21469 rm_rep
= (dot11_rm_action_t
*)body
;
21470 WL_DBG(("received neighbor report (token = %d)\n", rm_rep
->token
));
21472 tlvs
= (bcm_tlv_t
*)&rm_rep
->data
[0];
21474 tlv_len
= body_len
- DOT11_RM_ACTION_LEN
;
21476 while (tlvs
&& tlvs
->id
== DOT11_MNG_NEIGHBOR_REP_ID
) {
21477 nbr_rep_ie
= (dot11_neighbor_rep_ie_t
*)tlvs
;
21479 if (nbr_rep_ie
->len
< DOT11_NEIGHBOR_REP_IE_FIXED_LEN
) {
21480 WL_ERR(("malformed Neighbor Report element with length %d\n",
21482 tlvs
= bcm_next_tlv(tlvs
, &tlv_len
);
21486 ch
= CH20MHZ_CHSPEC(nbr_rep_ie
->channel
);
21487 WL_DBG(("ch:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x\n",
21488 ch
, nbr_rep_ie
->bssid
.octet
[0], nbr_rep_ie
->bssid
.octet
[1],
21489 nbr_rep_ie
->bssid
.octet
[2], nbr_rep_ie
->bssid
.octet
[3],
21490 nbr_rep_ie
->bssid
.octet
[4], nbr_rep_ie
->bssid
.octet
[5]));
21493 error
= wldev_iovar_getbuf(dev
, "roamscan_channels", 0, 0,
21494 (void *)&channel_list
, sizeof(channel_list
), NULL
);
21496 WL_ERR(("Failed to get roamscan channels, error = %d\n", error
));
21501 if (channel_list
.n
< MAX_ROAM_CHANNEL
) {
21502 for (i
= 0; i
< channel_list
.n
; i
++) {
21503 if (channel_list
.channels
[i
] == ch
) {
21507 if (i
== channel_list
.n
) {
21508 channel_list
.channels
[channel_list
.n
] = ch
;
21514 error
= wldev_iovar_setbuf(dev
, "roamscan_channels", &channel_list
,
21515 sizeof(channel_list
), iobuf
, sizeof(iobuf
), NULL
);
21517 WL_DBG(("Failed to set roamscan channels, error = %d\n", error
));
21520 tlvs
= bcm_next_tlv(tlvs
, &tlv_len
);
21525 #endif /* WBTEXT */
21527 #ifdef SUPPORT_SET_CAC
21529 wl_cfg80211_set_cac(struct bcm_cfg80211
*cfg
, int enable
)
21532 dhd_pub_t
*dhd
= (dhd_pub_t
*)(cfg
->pub
);
21534 WL_DBG(("cac enable %d, op_mode 0x%04x\n", enable
, dhd
->op_mode
));
21536 WL_ERR(("dhd is NULL\n"));
21539 if (enable
&& ((dhd
->op_mode
& DHD_FLAG_HOSTAP_MODE
) ||
21540 (dhd
->op_mode
& DHD_FLAG_P2P_GC_MODE
) ||
21541 (dhd
->op_mode
& DHD_FLAG_P2P_GO_MODE
))) {
21542 WL_ERR(("op_mode 0x%04x\n", dhd
->op_mode
));
21545 if ((ret
= dhd_wl_ioctl_set_intiovar(dhd
, "cac", enable
,
21546 WLC_SET_VAR
, TRUE
, 0)) < 0) {
21547 WL_ERR(("Failed set CAC, ret=%d\n", ret
));
21549 WL_DBG(("CAC set successfully\n"));
21553 #endif /* SUPPORT_SET_CAC */
21555 #ifdef SUPPORT_RSSI_LOGGING
21557 wl_get_rssi_per_ant(struct net_device
*dev
, char *ifname
, char *peer_mac
, void *param
)
21559 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21560 wl_rssi_ant_mimo_t
*get_param
= (wl_rssi_ant_mimo_t
*)param
;
21561 rssi_ant_param_t
*set_param
= NULL
;
21562 struct net_device
*ifdev
= NULL
;
21563 char iobuf
[WLC_IOCTL_SMLEN
];
21567 memset(iobuf
, 0, WLC_IOCTL_SMLEN
);
21569 /* Check the interface type */
21570 ifdev
= wl_get_netdev_by_name(cfg
, ifname
);
21571 if (ifdev
== NULL
) {
21572 WL_ERR(("Could not find net_device for ifname:%s\n", ifname
));
21577 iftype
= ifdev
->ieee80211_ptr
->iftype
;
21578 if (iftype
== NL80211_IFTYPE_AP
|| iftype
== NL80211_IFTYPE_P2P_GO
) {
21580 set_param
= (rssi_ant_param_t
*)kzalloc(sizeof(rssi_ant_param_t
),
21582 err
= wl_cfg80211_ether_atoe(peer_mac
, &set_param
->ea
);
21584 WL_ERR(("Invalid Peer MAC format\n"));
21589 WL_ERR(("Peer MAC is not provided for iftype %d\n", iftype
));
21595 err
= wldev_iovar_getbuf(ifdev
, "phy_rssi_ant", peer_mac
?
21596 (void *)&(set_param
->ea
) : NULL
, peer_mac
? ETHER_ADDR_LEN
: 0,
21597 (void *)iobuf
, sizeof(iobuf
), NULL
);
21598 if (unlikely(err
)) {
21599 WL_ERR(("Failed to get rssi info, err=%d\n", err
));
21601 memcpy(get_param
, iobuf
, sizeof(wl_rssi_ant_mimo_t
));
21602 if (get_param
->count
== 0) {
21603 WL_ERR(("Not supported on this chip\n"));
21604 err
= BCME_UNSUPPORTED
;
21617 wl_get_rssi_logging(struct net_device
*dev
, void *param
)
21619 rssilog_get_param_t
*get_param
= (rssilog_get_param_t
*)param
;
21620 char iobuf
[WLC_IOCTL_SMLEN
];
21623 memset(iobuf
, 0, WLC_IOCTL_SMLEN
);
21624 memset(get_param
, 0, sizeof(*get_param
));
21625 err
= wldev_iovar_getbuf(dev
, "rssilog", NULL
, 0, (void *)iobuf
,
21626 sizeof(iobuf
), NULL
);
21628 WL_ERR(("Failed to get rssi logging info, err=%d\n", err
));
21630 memcpy(get_param
, iobuf
, sizeof(*get_param
));
21637 wl_set_rssi_logging(struct net_device
*dev
, void *param
)
21639 struct bcm_cfg80211
*cfg
= wl_get_cfg(dev
);
21640 rssilog_set_param_t
*set_param
= (rssilog_set_param_t
*)param
;
21643 err
= wldev_iovar_setbuf(dev
, "rssilog", set_param
,
21644 sizeof(*set_param
), cfg
->ioctl_buf
, WLC_IOCTL_SMLEN
,
21645 &cfg
->ioctl_buf_sync
);
21647 WL_ERR(("Failed to set rssi logging param, err=%d\n", err
));
21652 #endif /* SUPPORT_RSSI_LOGGING */