2 * Linux cfg80211 driver
4 * Copyright (C) 1999-2016, 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 610196 2016-01-06 11:20:45Z $
33 #include <linux/kernel.h>
36 #include <bcmwifi_channels.h>
37 #include <bcmendian.h>
38 #include <proto/ethernet.h>
39 #include <proto/802.11.h>
40 #include <linux/if_arp.h>
41 #include <asm/uaccess.h>
43 #include <proto/ethernet.h>
44 #include <linux/kernel.h>
45 #include <linux/kthread.h>
46 #include <linux/netdevice.h>
47 #include <linux/sched.h>
48 #include <linux/etherdevice.h>
49 #include <linux/wireless.h>
50 #include <linux/ieee80211.h>
51 #include <linux/wait.h>
52 #include <net/cfg80211.h>
53 #include <net/rtnetlink.h>
56 #include <wldev_common.h>
57 #include <wl_cfg80211.h>
58 #include <wl_cfgp2p.h>
59 #include <wl_android.h>
60 #include <dngl_stats.h>
62 #include <dhd_linux.h>
65 #include <dhd_cfg80211.h>
69 #endif /* PNO_SUPPORT */
71 #if defined(WL_VENDOR_EXT_SUPPORT)
72 #include <wl_cfgvendor.h>
73 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
76 #include <wl_cfgnan.h>
78 #include <dhd_config.h>
85 #include <dhd_flowring.h>
89 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
90 #error You should enable 'WL_ENABLE_P2P_IF' or 'WL_CFG80211_P2P_DEV_IF' \
91 according to Kernel version and is supported only in Android-JB
92 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
96 #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
98 static struct device *cfg80211_parent_dev = NULL;
99 /* g_bcm_cfg should be static. Do not change */
100 static struct bcm_cfg80211 *g_bcm_cfg = NULL;
101 #ifdef CUSTOMER_HW4_DEBUG
102 u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_P2P_ACTION;
104 u32 wl_dbg_level = WL_DBG_ERR;
105 #endif /* CUSTOMER_HW4_DEBUG */
107 #define MAX_WAIT_TIME 1500
109 #define IBSS_IF_NAME "ibss%d"
110 #endif /* WLAIBSS_MCHAN */
113 /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
114 #define DEFAULT_SLEEP_TIME_VSDB 120
115 #define OFF_CHAN_TIME_THRESHOLD_MS 200
116 #define AF_RETRY_DELAY_TIME 40
118 /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
119 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg) \
121 if (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg)) || \
122 wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) { \
123 OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB); \
127 /* if not VSDB, do nothing */
128 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)
131 #ifdef WL_CFG80211_SYNC_GON
132 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) \
133 (wl_get_drv_status_all(cfg, SENDING_ACT_FRM) || \
134 wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN))
136 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) wl_get_drv_status_all(cfg, SENDING_ACT_FRM)
137 #endif /* WL_CFG80211_SYNC_GON */
139 #define DNGL_FUNC(func, parameters) func parameters
142 #define WLAN_EID_SSID 0
143 #define CH_MIN_5G_CHANNEL 34
144 #define CH_MIN_2G_CHANNEL 1
145 #define ACTIVE_SCAN 1
146 #define PASSIVE_SCAN 0
148 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
149 4 && __GNUC_MINOR__ >= 6))
150 #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
151 _Pragma("GCC diagnostic push") \
152 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
153 (entry) = list_first_entry((ptr), type, member); \
154 _Pragma("GCC diagnostic pop") \
156 #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
157 _Pragma("GCC diagnostic push") \
158 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
159 entry = container_of((ptr), type, member); \
160 _Pragma("GCC diagnostic pop") \
163 #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
164 (entry) = list_first_entry((ptr), type, member); \
166 #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
167 entry = container_of((ptr), type, member); \
169 #endif /* STRICT_GCC_WARNINGS */
171 enum rmc_event_type {
173 RMC_EVENT_LEADER_CHECK_FAIL
176 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
177 * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
178 * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
179 * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
180 * All the chnages in world regulatory domain are to be done here.
182 * this definition reuires disabling missing-field-initializer warning
183 * as the ieee80211_regdomain definition differs in plain linux and in Android
185 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
186 4 && __GNUC_MINOR__ >= 6))
187 _Pragma("GCC diagnostic push")
188 _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
190 static const struct ieee80211_regdomain brcm_regdom = {
194 /* IEEE 802.11b/g, channels 1..11 */
195 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
197 /* IEEE 802.11 channel 14 - Only JP enables
198 * this and for 802.11b only
200 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
201 /* IEEE 802.11a, channel 36..64 */
202 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
203 /* IEEE 802.11a, channel 100..165 */
204 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
206 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
207 4 && __GNUC_MINOR__ >= 6))
208 _Pragma("GCC diagnostic pop")
212 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
213 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
214 static const struct ieee80211_iface_limit common_if_limits[] = {
217 * Driver can support up to 2 AP's
220 .types = BIT(NL80211_IFTYPE_AP),
224 * During P2P-GO removal, P2P-GO is first changed to STA and later only
225 * removed. So setting maximum possible number of STA interfaces according
228 * less than linux-3.8 - max:3 (wlan0 + p2p0 + group removal of p2p-p2p0-x)
229 * linux-3.8 and above - max:2 (wlan0 + group removal of p2p-wlan0-x)
231 #ifdef WL_ENABLE_P2P_IF
235 #endif /* WL_ENABLE_P2P_IF */
236 .types = BIT(NL80211_IFTYPE_STATION),
240 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
242 #if defined(WL_CFG80211_P2P_DEV_IF)
245 .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
247 #endif /* WL_CFG80211_P2P_DEV_IF */
250 .types = BIT(NL80211_IFTYPE_ADHOC),
254 #define NUM_DIFF_CHANNELS 1
256 #define NUM_DIFF_CHANNELS 2
258 static const struct ieee80211_iface_combination
259 common_iface_combinations[] = {
261 .num_different_channels = NUM_DIFF_CHANNELS,
264 * The max no of interfaces will be used in dual p2p case.
265 * {STA, P2P Device, P2P Group 1, P2P Group 2}. Though we
266 * will not be using the STA functionality in this case, it
267 * will remain registered as it is the primary interface.
270 .limits = common_if_limits,
271 .n_limits = ARRAY_SIZE(common_if_limits),
274 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
276 /* Data Element Definitions */
277 #define WPS_ID_CONFIG_METHODS 0x1008
278 #define WPS_ID_REQ_TYPE 0x103A
279 #define WPS_ID_DEVICE_NAME 0x1011
280 #define WPS_ID_VERSION 0x104A
281 #define WPS_ID_DEVICE_PWD_ID 0x1012
282 #define WPS_ID_REQ_DEV_TYPE 0x106A
283 #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
284 #define WPS_ID_PRIM_DEV_TYPE 0x1054
286 /* Device Password ID */
287 #define DEV_PW_DEFAULT 0x0000
288 #define DEV_PW_USER_SPECIFIED 0x0001,
289 #define DEV_PW_MACHINE_SPECIFIED 0x0002
290 #define DEV_PW_REKEY 0x0003
291 #define DEV_PW_PUSHBUTTON 0x0004
292 #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
295 #define WPS_CONFIG_USBA 0x0001
296 #define WPS_CONFIG_ETHERNET 0x0002
297 #define WPS_CONFIG_LABEL 0x0004
298 #define WPS_CONFIG_DISPLAY 0x0008
299 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
300 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
301 #define WPS_CONFIG_NFC_INTERFACE 0x0040
302 #define WPS_CONFIG_PUSHBUTTON 0x0080
303 #define WPS_CONFIG_KEYPAD 0x0100
304 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
305 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
306 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
307 #define WPS_CONFIG_PHY_DISPLAY 0x4008
313 #define WL_AKM_SUITE_SHA256_1X 0x000FAC05
314 #define WL_AKM_SUITE_SHA256_PSK 0x000FAC06
316 #ifndef IBSS_COALESCE_ALLOWED
317 #define IBSS_COALESCE_ALLOWED 0
320 #ifndef IBSS_INITIAL_SCAN_ALLOWED
321 #define IBSS_INITIAL_SCAN_ALLOWED 0
324 #define CUSTOM_RETRY_MASK 0xff000000 /* Mask for retry counter of custom dwell time */
325 #define LONG_LISTEN_TIME 2000
327 #define MAX_SCAN_ABORT_WAIT_CNT 20
328 #define WAIT_SCAN_ABORT_OSL_SLEEP_TIME 10
330 #define IDSUP_4WAY_HANDSHAKE_TIMEOUT 10000
331 enum idsup_event_type {
332 IDSUP_EVENT_SUCCESS = 0,
333 IDSUP_EVENT_4WAY_HANDSHAKE_TIMEOUT
336 * cfg80211_ops api/callback list
338 static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
339 const struct ether_addr *sa, const struct ether_addr *bssid,
340 u8 **pheader, u32 *body_len, u8 *pbody);
341 static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
342 struct cfg80211_scan_request *request,
343 struct cfg80211_ssid *this_ssid);
344 #if defined(WL_CFG80211_P2P_DEV_IF)
346 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
349 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
350 struct cfg80211_scan_request *request);
351 #endif /* WL_CFG80211_P2P_DEV_IF */
352 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
354 static bcm_struct_cfgdev* bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name);
355 static s32 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
356 #endif /* WLAIBSS_MCHAN */
357 static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
358 struct cfg80211_ibss_params *params);
359 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
360 struct net_device *dev);
361 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
362 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
363 struct net_device *dev, const u8 *mac,
364 struct station_info *sinfo);
366 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
367 struct net_device *dev, u8 *mac,
368 struct station_info *sinfo);
370 static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
371 struct net_device *dev, bool enabled,
373 static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
374 struct cfg80211_connect_params *sme);
375 static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
377 #if defined(WL_CFG80211_P2P_DEV_IF)
379 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
380 enum nl80211_tx_power_setting type, s32 mbm);
383 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
384 enum nl80211_tx_power_setting type, s32 dbm);
385 #endif /* WL_CFG80211_P2P_DEV_IF */
386 #if defined(WL_CFG80211_P2P_DEV_IF)
387 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
388 struct wireless_dev *wdev, s32 *dbm);
390 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
391 #endif /* WL_CFG80211_P2P_DEV_IF */
392 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
393 struct net_device *dev,
394 u8 key_idx, bool unicast, bool multicast);
395 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
396 u8 key_idx, bool pairwise, const u8 *mac_addr,
397 struct key_params *params);
398 static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
399 u8 key_idx, bool pairwise, const u8 *mac_addr);
400 static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
401 u8 key_idx, bool pairwise, const u8 *mac_addr,
402 void *cookie, void (*callback) (void *cookie,
403 struct key_params *params));
404 static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
405 struct net_device *dev, u8 key_idx);
406 static s32 wl_cfg80211_resume(struct wiphy *wiphy);
407 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
409 static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
410 bcm_struct_cfgdev *cfgdev, u64 cookie);
411 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
412 static s32 wl_cfg80211_del_station(
413 struct wiphy *wiphy, struct net_device *ndev,
414 struct station_del_parameters *params);
415 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
416 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
417 struct net_device *ndev, const u8* mac_addr);
419 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
420 struct net_device *ndev, u8* mac_addr);
422 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
423 static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
424 struct net_device *dev, const u8 *mac, struct station_parameters *params);
426 static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
427 struct net_device *dev, u8 *mac, struct station_parameters *params);
429 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
430 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
431 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
433 static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
434 #endif /* KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES */
435 static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
436 struct cfg80211_pmksa *pmksa);
437 static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
438 struct cfg80211_pmksa *pmksa);
439 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
440 struct net_device *dev);
441 static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg);
442 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg);
443 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
444 struct net_device *ndev, bool aborted, bool fw_abort);
445 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
446 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
447 KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
448 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
449 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
450 u32 peer_capability, const u8 *data, size_t len);
451 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
452 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
453 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
454 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
455 u32 peer_capability, const u8 *data, size_t len);
456 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
457 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
458 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
459 u32 peer_capability, bool initiator, const u8 *data, size_t len);
461 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
462 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
464 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
465 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
466 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
467 const u8 *peer, enum nl80211_tdls_operation oper);
469 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
470 u8 *peer, enum nl80211_tdls_operation oper);
474 static int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev);
476 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
478 wl_cfg80211_create_iface(struct wiphy *wiphy, enum nl80211_iftype
479 iface_type, u8 *mac_addr, const char *name);
481 wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
482 #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
484 s32 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
485 struct net_device *ndev, s32 bsscfg_idx,
486 enum nl80211_iftype iface_type, s32 del, u8 *addr);
487 s32 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
488 struct net_device *ndev, s32 bsscfg_idx,
489 enum nl80211_iftype iface_type, s32 del, u8 *addr);
490 chanspec_t wl_chspec_driver_to_host(chanspec_t chanspec);
491 chanspec_t wl_chspec_host_to_driver(chanspec_t chanspec);
493 static s32 wl_cfg80211_get_ulb_bw(struct wireless_dev *wdev);
494 static chanspec_t wl_cfg80211_ulb_get_min_bw_chspec(struct wireless_dev *wdev, s32 bssidx);
495 static s32 wl_cfg80211_ulbbw_to_ulbchspec(u32 ulb_bw);
497 static inline chanspec_t wl_cfg80211_ulb_get_min_bw_chspec(
498 struct wireless_dev *wdev, s32 bssidx)
500 return WL_CHANSPEC_BW_20;
505 * event & event Q handlers for cfg80211 interfaces
507 static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg);
508 static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg);
509 static s32 wl_event_handler(void *data);
510 static void wl_init_eq(struct bcm_cfg80211 *cfg);
511 static void wl_flush_eq(struct bcm_cfg80211 *cfg);
512 static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg);
513 static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags);
514 static void wl_init_eq_lock(struct bcm_cfg80211 *cfg);
515 static void wl_init_event_handler(struct bcm_cfg80211 *cfg);
516 static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg);
517 static s32 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 type,
518 const wl_event_msg_t *msg, void *data);
519 static void wl_put_event(struct wl_event_q *e);
520 static void wl_wakeup_event(struct bcm_cfg80211 *cfg);
521 static s32 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
522 const wl_event_msg_t *e, void *data);
523 static s32 wl_notify_connect_status(struct bcm_cfg80211 *cfg,
524 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
525 static s32 wl_notify_roaming_status(struct bcm_cfg80211 *cfg,
526 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
527 static s32 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
528 const wl_event_msg_t *e, void *data);
529 static s32 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
530 const wl_event_msg_t *e, void *data, bool completed);
531 static s32 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
532 const wl_event_msg_t *e, void *data);
533 static s32 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
534 const wl_event_msg_t *e, void *data);
535 #ifdef BT_WIFI_HANDOVER
536 static s32 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg,
537 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
538 #endif /* BT_WIFI_HANDOVER */
541 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
542 const wl_event_msg_t *e, void *data);
543 #endif /* WL_SCHED_SCAN */
545 static s32 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
546 const wl_event_msg_t *e, void *data);
547 #endif /* PNO_SUPPORT */
549 static s32 wl_notify_gscan_event(struct bcm_cfg80211 *wl, bcm_struct_cfgdev *cfgdev,
550 const wl_event_msg_t *e, void *data);
551 #endif /* GSCAN_SUPPORT */
552 static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
553 enum wl_status state, bool set);
554 #ifdef DHD_LOSSLESS_ROAMING
555 static s32 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg,
556 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
557 static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg);
558 #endif /* DHD_LOSSLESS_ROAMING */
559 #ifdef CUSTOM_EVENT_PM_WAKE
560 static s32 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
561 const wl_event_msg_t *e, void *data);
562 #endif /* CUSTOM_EVENT_PM_WAKE */
565 static s32 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
566 const wl_event_msg_t *e, void *data);
569 * register/deregister parent device
571 static void wl_cfg80211_clear_parent_dev(void);
577 * cfg80211 set_wiphy_params utilities
579 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
580 static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
581 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
584 * cfg profile utilities
586 static s32 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
587 const wl_event_msg_t *e, const void *data, s32 item);
588 static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item);
589 static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev);
592 * cfg80211 connect utilites
594 static s32 wl_set_wpa_version(struct net_device *dev,
595 struct cfg80211_connect_params *sme);
596 static s32 wl_set_auth_type(struct net_device *dev,
597 struct cfg80211_connect_params *sme);
598 static s32 wl_set_set_cipher(struct net_device *dev,
599 struct cfg80211_connect_params *sme);
600 static s32 wl_set_key_mgmt(struct net_device *dev,
601 struct cfg80211_connect_params *sme);
602 static s32 wl_set_set_sharedkey(struct net_device *dev,
603 struct cfg80211_connect_params *sme);
604 static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev);
605 static s32 wl_ch_to_chanspec(struct net_device *dev, int ch,
606 struct wl_join_params *join_params, size_t *join_params_size);
607 void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg);
610 * information element utilities
612 static void wl_rst_ie(struct bcm_cfg80211 *cfg);
613 static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v);
614 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
616 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size);
617 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size);
618 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg);
622 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len);
624 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
625 uint8 ie_id, uint8 *data, uint8 data_len);
628 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, void *data);
629 static void wl_free_wdev(struct bcm_cfg80211 *cfg);
630 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
631 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
635 #endif /* kernel version < 3.10.11 */
636 wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
637 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
639 static s32 wl_inform_bss(struct bcm_cfg80211 *cfg);
640 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam);
641 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam);
642 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
643 s32 wl_cfg80211_channel_to_freq(u32 channel);
646 static void wl_cfg80211_work_handler(struct work_struct *work);
647 static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
648 u8 key_idx, const u8 *mac_addr,
649 struct key_params *params);
651 * key indianess swap utilities
653 static void swap_key_from_BE(struct wl_wsec_key *key);
654 static void swap_key_to_BE(struct wl_wsec_key *key);
657 * bcm_cfg80211 memory init/deinit utilities
659 static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg);
660 static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg);
662 static void wl_delay(u32 ms);
665 * ibss mode utilities
667 static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev);
668 static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg);
671 * link up/down , default configuration utilities
673 static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg);
674 static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg);
675 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
676 static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e,
677 struct net_device *ndev);
678 static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
679 static void wl_link_up(struct bcm_cfg80211 *cfg);
680 static void wl_link_down(struct bcm_cfg80211 *cfg);
681 static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype);
682 static void wl_init_conf(struct wl_conf *conf);
683 static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
684 struct net_device* ndev);
686 int wl_cfg80211_get_ioctl_version(void);
689 * find most significant bit set
691 static __used u32 wl_find_msb(u16 bit16);
696 static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup);
697 static int wl_rfkill_set(void *data, bool blocked);
698 #ifdef DEBUGFS_CFG80211
699 static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg);
700 static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg);
703 static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel,
704 int nprobes, int *out_params_size);
705 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role);
707 #ifdef WL_CFG80211_ACL
709 static int wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
710 const struct cfg80211_acl_data *acl);
711 #endif /* WL_CFG80211_ACL */
714 * Some external functions, TODO: move them to dhd_linux.h
716 int dhd_add_monitor(char *name, struct net_device **new_ndev);
717 int dhd_del_monitor(struct net_device *ndev);
718 int dhd_monitor_init(void *dhd_pub);
719 int dhd_monitor_uninit(void);
720 int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
724 void wl_dump_ifinfo(struct bcm_cfg80211 *cfg);
727 #ifdef P2P_LISTEN_OFFLOADING
728 s32 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg);
729 #endif /* P2P_LISTEN_OFFLOADING */
731 static int wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
732 const struct ether_addr *bssid);
734 static int bw2cap[] = { 0, 0, WLC_BW_CAP_20MHZ, WLC_BW_CAP_40MHZ, WLC_BW_CAP_80MHZ,
735 WLC_BW_CAP_160MHZ, WLC_BW_CAP_160MHZ };
737 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
738 #define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
739 cfg80211_disconnected(dev, reason, ie, len, gfp);
740 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0))
741 #define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
742 cfg80211_disconnected(dev, reason, ie, len, loc_gen, gfp);
745 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \
746 (akm) == RSN_AKM_UNSPECIFIED || \
747 (akm) == RSN_AKM_PSK)
750 extern int dhd_wait_pend8021x(struct net_device *dev);
751 #ifdef PROP_TXSTATUS_VSDB
752 extern int disable_proptx;
753 #endif /* PROP_TXSTATUS_VSDB */
756 extern int passive_channel_skip;
759 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
760 const wl_event_msg_t *e, void *data);
762 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
763 const wl_event_msg_t *e, void *data);
764 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, \
773 #if (WL_DBG_LEVEL > 0)
774 #define WL_DBG_ESTR_MAX 50
775 static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = {
776 "SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND",
777 "DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC",
778 "REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END",
779 "BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM",
780 "TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH",
781 "EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND",
782 "BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND",
784 "RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START",
786 "RADIO", "PSM_WATCHDOG",
787 "WLC_E_XXX_ASSOC_START", "WLC_E_XXX_ASSOC_ABORT",
789 "SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED",
790 "EXCEEDED_MEDIUM_TIME", "ICV_ERROR",
791 "UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE",
792 "WLC_E_BTA_HCI_EVENT", "IF", "WLC_E_P2P_DISC_LISTEN_COMPLETE",
793 "RSSI", "PFN_SCAN_COMPLETE", "WLC_E_EXTLOG_MSG",
794 "ACTION_FRAME", "ACTION_FRAME_COMPLETE", "WLC_E_PRE_ASSOC_IND",
795 "WLC_E_PRE_REASSOC_IND", "WLC_E_CHANNEL_ADOPTED", "WLC_E_AP_STARTED",
796 "WLC_E_DFS_AP_STOP", "WLC_E_DFS_AP_RESUME", "WLC_E_WAI_STA_EVENT",
797 "WLC_E_WAI_MSG", "WLC_E_ESCAN_RESULT", "WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE",
798 "WLC_E_PROBRESP_MSG", "WLC_E_P2P_PROBREQ_MSG", "WLC_E_DCS_REQUEST", "WLC_E_FIFO_CREDIT_MAP",
799 "WLC_E_ACTION_FRAME_RX", "WLC_E_WAKE_EVENT", "WLC_E_RM_COMPLETE"
801 #endif /* WL_DBG_LEVEL */
803 #define CHAN2G(_channel, _freq, _flags) { \
804 .band = IEEE80211_BAND_2GHZ, \
805 .center_freq = (_freq), \
806 .hw_value = (_channel), \
808 .max_antenna_gain = 0, \
812 #define CHAN5G(_channel, _flags) { \
813 .band = IEEE80211_BAND_5GHZ, \
814 .center_freq = 5000 + (5 * (_channel)), \
815 .hw_value = (_channel), \
817 .max_antenna_gain = 0, \
821 #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
822 #define RATETAB_ENT(_rateid, _flags) \
824 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
825 .hw_value = (_rateid), \
829 static struct ieee80211_rate __wl_rates[] = {
830 RATETAB_ENT(DOT11_RATE_1M, 0),
831 RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
832 RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
833 RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
834 RATETAB_ENT(DOT11_RATE_6M, 0),
835 RATETAB_ENT(DOT11_RATE_9M, 0),
836 RATETAB_ENT(DOT11_RATE_12M, 0),
837 RATETAB_ENT(DOT11_RATE_18M, 0),
838 RATETAB_ENT(DOT11_RATE_24M, 0),
839 RATETAB_ENT(DOT11_RATE_36M, 0),
840 RATETAB_ENT(DOT11_RATE_48M, 0),
841 RATETAB_ENT(DOT11_RATE_54M, 0)
844 #define wl_a_rates (__wl_rates + 4)
845 #define wl_a_rates_size 8
846 #define wl_g_rates (__wl_rates + 0)
847 #define wl_g_rates_size 12
849 static struct ieee80211_channel __wl_2ghz_channels[] = {
866 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
867 CHAN5G(34, 0), CHAN5G(36, 0),
868 CHAN5G(38, 0), CHAN5G(40, 0),
869 CHAN5G(42, 0), CHAN5G(44, 0),
870 CHAN5G(46, 0), CHAN5G(48, 0),
871 CHAN5G(52, 0), CHAN5G(56, 0),
872 CHAN5G(60, 0), CHAN5G(64, 0),
873 CHAN5G(100, 0), CHAN5G(104, 0),
874 CHAN5G(108, 0), CHAN5G(112, 0),
875 CHAN5G(116, 0), CHAN5G(120, 0),
876 CHAN5G(124, 0), CHAN5G(128, 0),
877 CHAN5G(132, 0), CHAN5G(136, 0),
878 CHAN5G(140, 0), CHAN5G(144, 0),
879 CHAN5G(149, 0), CHAN5G(153, 0),
880 CHAN5G(157, 0), CHAN5G(161, 0),
884 static struct ieee80211_supported_band __wl_band_2ghz = {
885 .band = IEEE80211_BAND_2GHZ,
886 .channels = __wl_2ghz_channels,
887 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
888 .bitrates = wl_g_rates,
889 .n_bitrates = wl_g_rates_size
892 static struct ieee80211_supported_band __wl_band_5ghz_a = {
893 .band = IEEE80211_BAND_5GHZ,
894 .channels = __wl_5ghz_a_channels,
895 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
896 .bitrates = wl_a_rates,
897 .n_bitrates = wl_a_rates_size
900 static const u32 __wl_cipher_suites[] = {
901 WLAN_CIPHER_SUITE_WEP40,
902 WLAN_CIPHER_SUITE_WEP104,
903 WLAN_CIPHER_SUITE_TKIP,
904 WLAN_CIPHER_SUITE_CCMP,
905 WLAN_CIPHER_SUITE_AES_CMAC,
908 #ifdef WL_SUPPORT_ACS
910 * The firmware code required for this feature to work is currently under
911 * BCMINTERNAL flag. In future if this is to enabled we need to bring the
912 * required firmware code out of the BCMINTERNAL flag.
914 struct wl_dump_survey {
922 #endif /* WL_SUPPORT_ACS */
925 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
926 static int maxrxpktglom = 0;
929 /* IOCtl version read from targeted driver */
930 static int ioctl_version;
931 #ifdef DEBUGFS_CFG80211
932 #define S_SUBLOGLEVEL 20
933 static const struct {
936 } sublogname_map[] = {
938 {WL_DBG_INFO, "INFO"},
940 {WL_DBG_SCAN, "SCAN"},
941 {WL_DBG_TRACE, "TRACE"},
942 {WL_DBG_P2P_ACTION, "P2PACTION"}
946 #ifdef CUSTOMER_HW4_DEBUG
947 uint prev_dhd_console_ms = 0;
948 u32 prev_wl_dbg_level = 0;
949 bool wl_scan_timeout_dbg_enabled = 0;
950 static void wl_scan_timeout_dbg_set(void);
951 static void wl_scan_timeout_dbg_clear(void);
953 static void wl_scan_timeout_dbg_set(void)
955 WL_ERR(("Enter \n"));
956 prev_dhd_console_ms = dhd_console_ms;
957 prev_wl_dbg_level = wl_dbg_level;
960 wl_dbg_level |= (WL_DBG_ERR | WL_DBG_P2P_ACTION | WL_DBG_SCAN);
962 wl_scan_timeout_dbg_enabled = 1;
964 static void wl_scan_timeout_dbg_clear(void)
966 WL_ERR(("Enter \n"));
967 dhd_console_ms = prev_dhd_console_ms;
968 wl_dbg_level = prev_wl_dbg_level;
970 wl_scan_timeout_dbg_enabled = 0;
972 #endif /* CUSTOMER_HW4_DEBUG */
974 /* watchdog timer for disconnecting when fw is not associated for FW_ASSOC_WATCHDOG_TIME ms */
975 uint32 fw_assoc_watchdog_ms = 0;
976 bool fw_assoc_watchdog_started = 0;
977 #define FW_ASSOC_WATCHDOG_TIME 10 * 1000 /* msec */
981 void wl_dump_ifinfo(struct bcm_cfg80211 *cfg)
983 WL_ERR(("cfg=%p\n", cfg));
985 WL_ERR(("cfg->wdev=%p\n", bcmcfg_to_prmry_wdev(cfg)));
986 if (bcmcfg_to_prmry_wdev(cfg)) {
987 WL_ERR(("cfg->wdev->wiphy=%p\n", bcmcfg_to_wiphy(cfg)));
988 WL_ERR(("cfg->wdev->netdev=%p\n", bcmcfg_to_prmry_ndev(cfg)));
994 static void wl_add_remove_pm_enable_work(struct bcm_cfg80211 *cfg,
995 enum wl_pm_workq_act_type type)
1002 mutex_lock(&cfg->pm_sync);
1004 * Make cancel and schedule work part mutually exclusive
1005 * so that while cancelling, we are sure that there is no
1006 * work getting scheduled.
1008 if (delayed_work_pending(&cfg->pm_enable_work)) {
1009 cancel_delayed_work_sync(&cfg->pm_enable_work);
1010 DHD_OS_WAKE_UNLOCK(cfg->pub);
1013 if (type == WL_PM_WORKQ_SHORT) {
1014 wq_duration = WL_PM_ENABLE_TIMEOUT;
1015 } else if (type == WL_PM_WORKQ_LONG) {
1016 wq_duration = (WL_PM_ENABLE_TIMEOUT*2);
1019 DHD_OS_WAKE_LOCK(cfg->pub);
1020 schedule_delayed_work(&cfg->pm_enable_work,
1021 msecs_to_jiffies((const unsigned int)wq_duration));
1023 mutex_unlock(&cfg->pm_sync);
1026 /* Return a new chanspec given a legacy chanspec
1027 * Returns INVCHANSPEC on error
1030 wl_chspec_from_legacy(chanspec_t legacy_chspec)
1034 /* get the channel number */
1035 chspec = LCHSPEC_CHANNEL(legacy_chspec);
1037 /* convert the band */
1038 if (LCHSPEC_IS2G(legacy_chspec)) {
1039 chspec |= WL_CHANSPEC_BAND_2G;
1041 chspec |= WL_CHANSPEC_BAND_5G;
1044 /* convert the bw and sideband */
1045 if (LCHSPEC_IS20(legacy_chspec)) {
1046 chspec |= WL_CHANSPEC_BW_20;
1048 chspec |= WL_CHANSPEC_BW_40;
1049 if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
1050 chspec |= WL_CHANSPEC_CTL_SB_L;
1052 chspec |= WL_CHANSPEC_CTL_SB_U;
1056 if (wf_chspec_malformed(chspec)) {
1057 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
1065 /* Return a legacy chanspec given a new chanspec
1066 * Returns INVCHANSPEC on error
1069 wl_chspec_to_legacy(chanspec_t chspec)
1073 if (wf_chspec_malformed(chspec)) {
1074 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
1079 /* get the channel number */
1080 lchspec = CHSPEC_CHANNEL(chspec);
1082 /* convert the band */
1083 if (CHSPEC_IS2G(chspec)) {
1084 lchspec |= WL_LCHANSPEC_BAND_2G;
1086 lchspec |= WL_LCHANSPEC_BAND_5G;
1089 /* convert the bw and sideband */
1090 if (CHSPEC_IS20(chspec)) {
1091 lchspec |= WL_LCHANSPEC_BW_20;
1092 lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
1093 } else if (CHSPEC_IS40(chspec)) {
1094 lchspec |= WL_LCHANSPEC_BW_40;
1095 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
1096 lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
1098 lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
1101 /* cannot express the bandwidth */
1102 char chanbuf[CHANSPEC_STR_LEN];
1104 "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
1105 "to pre-11ac format\n",
1106 wf_chspec_ntoa(chspec, chanbuf), chspec));
1113 /* given a chanspec value, do the endian and chanspec version conversion to
1114 * a chanspec_t value
1115 * Returns INVCHANSPEC on error
1118 wl_chspec_host_to_driver(chanspec_t chanspec)
1120 if (ioctl_version == 1) {
1121 chanspec = wl_chspec_to_legacy(chanspec);
1122 if (chanspec == INVCHANSPEC) {
1126 chanspec = htodchanspec(chanspec);
1131 /* given a channel value, do the endian and chanspec version conversion to
1132 * a chanspec_t value
1133 * Returns INVCHANSPEC on error
1136 wl_ch_host_to_driver(s32 bssidx, u16 channel)
1138 chanspec_t chanspec;
1140 chanspec = channel & WL_CHANSPEC_CHAN_MASK;
1142 if (channel <= CH_MAX_2G_CHANNEL)
1143 chanspec |= WL_CHANSPEC_BAND_2G;
1145 chanspec |= WL_CHANSPEC_BAND_5G;
1147 chanspec |= wl_cfg80211_ulb_get_min_bw_chspec(NULL, bssidx);
1149 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1151 return wl_chspec_host_to_driver(chanspec);
1154 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
1155 * a chanspec_t value
1156 * Returns INVCHANSPEC on error
1159 wl_chspec_driver_to_host(chanspec_t chanspec)
1161 chanspec = dtohchanspec(chanspec);
1162 if (ioctl_version == 1) {
1163 chanspec = wl_chspec_from_legacy(chanspec);
1170 * convert ASCII string to MAC address (colon-delimited format)
1171 * eg: 00:11:22:33:44:55
1174 wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n)
1179 memset(n, 0, ETHER_ADDR_LEN);
1181 n->octet[count++] = (uint8)simple_strtoul(a, &c, 16);
1182 if (!*c++ || count == ETHER_ADDR_LEN)
1186 return (count == ETHER_ADDR_LEN);
1189 /* There isn't a lot of sense in it, but you can transmit anything you like */
1190 static const struct ieee80211_txrx_stypes
1191 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
1192 [NL80211_IFTYPE_ADHOC] = {
1194 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
1196 [NL80211_IFTYPE_STATION] = {
1198 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1199 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1201 [NL80211_IFTYPE_AP] = {
1203 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1204 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1205 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1206 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1207 BIT(IEEE80211_STYPE_AUTH >> 4) |
1208 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1209 BIT(IEEE80211_STYPE_ACTION >> 4)
1211 [NL80211_IFTYPE_AP_VLAN] = {
1214 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1215 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1216 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1217 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1218 BIT(IEEE80211_STYPE_AUTH >> 4) |
1219 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1220 BIT(IEEE80211_STYPE_ACTION >> 4)
1222 [NL80211_IFTYPE_P2P_CLIENT] = {
1224 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1225 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1227 [NL80211_IFTYPE_P2P_GO] = {
1229 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1230 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1231 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1232 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1233 BIT(IEEE80211_STYPE_AUTH >> 4) |
1234 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1235 BIT(IEEE80211_STYPE_ACTION >> 4)
1237 #if defined(WL_CFG80211_P2P_DEV_IF)
1238 [NL80211_IFTYPE_P2P_DEVICE] = {
1240 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1241 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1243 #endif /* WL_CFG80211_P2P_DEV_IF */
1246 static void swap_key_from_BE(struct wl_wsec_key *key)
1248 key->index = htod32(key->index);
1249 key->len = htod32(key->len);
1250 key->algo = htod32(key->algo);
1251 key->flags = htod32(key->flags);
1252 key->rxiv.hi = htod32(key->rxiv.hi);
1253 key->rxiv.lo = htod16(key->rxiv.lo);
1254 key->iv_initialized = htod32(key->iv_initialized);
1257 static void swap_key_to_BE(struct wl_wsec_key *key)
1259 key->index = dtoh32(key->index);
1260 key->len = dtoh32(key->len);
1261 key->algo = dtoh32(key->algo);
1262 key->flags = dtoh32(key->flags);
1263 key->rxiv.hi = dtoh32(key->rxiv.hi);
1264 key->rxiv.lo = dtoh16(key->rxiv.lo);
1265 key->iv_initialized = dtoh32(key->iv_initialized);
1268 /* Dump the contents of the encoded wps ie buffer and get pbc value */
1270 wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
1272 #define WPS_IE_FIXED_LEN 6
1278 u8 *valptr = (uint8*) &val;
1279 if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
1280 WL_ERR(("invalid argument : NULL\n"));
1283 len = (u16)wps_ie[TLV_LEN_OFF];
1285 if (len > wps_ie_len) {
1286 WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
1289 WL_DBG(("wps_ie len=%d\n", len));
1290 len -= 4; /* for the WPS IE's OUI, oui_type fields */
1291 subel = wps_ie + WPS_IE_FIXED_LEN;
1292 while (len >= 4) { /* must have attr id, attr len fields */
1293 valptr[0] = *subel++;
1294 valptr[1] = *subel++;
1295 subelt_id = HTON16(val);
1297 valptr[0] = *subel++;
1298 valptr[1] = *subel++;
1299 subelt_len = HTON16(val);
1301 len -= 4; /* for the attr id, attr len fields */
1302 len -= subelt_len; /* for the remaining fields in this attribute */
1303 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1304 subel, subelt_id, subelt_len));
1306 if (subelt_id == WPS_ID_VERSION) {
1307 WL_DBG((" attr WPS_ID_VERSION: %u\n", *subel));
1308 } else if (subelt_id == WPS_ID_REQ_TYPE) {
1309 WL_DBG((" attr WPS_ID_REQ_TYPE: %u\n", *subel));
1310 } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
1312 valptr[1] = *(subel + 1);
1313 WL_DBG((" attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
1314 } else if (subelt_id == WPS_ID_DEVICE_NAME) {
1316 memcpy(devname, subel, subelt_len);
1317 devname[subelt_len] = '\0';
1318 WL_DBG((" attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1319 devname, subelt_len));
1320 } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
1322 valptr[1] = *(subel + 1);
1323 WL_DBG((" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
1324 *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
1325 } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
1327 valptr[1] = *(subel + 1);
1328 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
1329 valptr[0] = *(subel + 6);
1330 valptr[1] = *(subel + 7);
1331 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
1332 } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
1334 valptr[1] = *(subel + 1);
1335 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
1336 valptr[0] = *(subel + 6);
1337 valptr[1] = *(subel + 7);
1338 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
1339 } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
1341 valptr[1] = *(subel + 1);
1342 WL_DBG((" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1343 ": cat=%u\n", HTON16(val)));
1345 WL_DBG((" unknown attr 0x%x\n", subelt_id));
1348 subel += subelt_len;
1352 s32 wl_set_tx_power(struct net_device *dev,
1353 enum nl80211_tx_power_setting type, s32 dbm)
1358 struct bcm_cfg80211 *cfg = g_bcm_cfg;
1360 /* Make sure radio is off or on as far as software is concerned */
1361 disable = WL_RADIO_SW_DISABLE << 16;
1362 disable = htod32(disable);
1363 err = wldev_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable), true);
1364 if (unlikely(err)) {
1365 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
1371 txpwrqdbm = dbm * 4;
1372 err = wldev_iovar_setbuf_bsscfg(dev, "qtxpower", (void *)&txpwrqdbm,
1373 sizeof(txpwrqdbm), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
1374 &cfg->ioctl_buf_sync);
1376 WL_ERR(("qtxpower error (%d)\n", err));
1378 WL_ERR(("dBm=%d, txpwrqdbm=0x%x\n", dbm, txpwrqdbm));
1383 s32 wl_get_tx_power(struct net_device *dev, s32 *dbm)
1387 struct bcm_cfg80211 *cfg = g_bcm_cfg;
1389 err = wldev_iovar_getbuf_bsscfg(dev, "qtxpower",
1390 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
1391 if (unlikely(err)) {
1392 WL_ERR(("error (%d)\n", err));
1396 memcpy(&txpwrdbm, cfg->ioctl_buf, sizeof(txpwrdbm));
1397 txpwrdbm = dtoh32(txpwrdbm);
1398 *dbm = (txpwrdbm & ~WL_TXPWR_OVERRIDE) / 4;
1400 WL_INFORM(("dBm=%d, txpwrdbm=0x%x\n", *dbm, txpwrdbm));
1405 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
1409 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1410 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
1411 struct ether_addr bssid;
1412 struct wl_bss_info *bss = NULL;
1413 s32 bssidx = 0; /* Explicitly set to primary bssidx */
1415 if ((err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), false))) {
1416 /* STA interface is not associated. So start the new interface on a temp
1417 * channel . Later proper channel will be applied by the above framework
1418 * via set_channel (cfg80211 API).
1420 WL_DBG(("Not associated. Return a temp channel. \n"));
1421 return wl_ch_host_to_driver(bssidx, WL_P2P_TEMP_CHAN);
1425 *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
1426 if ((err = wldev_ioctl(dev, WLC_GET_BSS_INFO, cfg->extra_buf,
1427 WL_EXTRA_BUF_MAX, false))) {
1428 WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1429 chspec = wl_ch_host_to_driver(bssidx, WL_P2P_TEMP_CHAN);
1432 bss = (struct wl_bss_info *) (cfg->extra_buf + 4);
1433 chspec = bss->chanspec;
1435 WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
1440 static bcm_struct_cfgdev *
1441 wl_cfg80211_add_monitor_if(char *name)
1443 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1444 WL_INFORM(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1445 return ERR_PTR(-EOPNOTSUPP);
1447 struct net_device* ndev = NULL;
1449 dhd_add_monitor(name, &ndev);
1450 WL_INFORM(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
1451 return ndev_to_cfgdev(ndev);
1452 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1455 static bcm_struct_cfgdev *
1456 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
1457 #if defined(WL_CFG80211_P2P_DEV_IF)
1461 #endif /* WL_CFG80211_P2P_DEV_IF */
1462 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
1463 unsigned char name_assign_type,
1464 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
1465 enum nl80211_iftype type, u32 *flags,
1466 struct vif_params *params)
1476 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1477 struct net_device *primary_ndev;
1478 struct net_device *new_ndev;
1479 struct ether_addr primary_mac;
1480 #ifdef WL_VIRTUAL_APSTA
1481 bcm_struct_cfgdev *new_cfgdev;
1482 #endif /* WL_VIRTUAL_APSTA */
1483 #ifdef PROP_TXSTATUS_VSDB
1484 #if defined(BCMSDIO)
1489 #endif /* PROP_TXSTATUS_VSDB */
1490 #if defined(SUPPORT_AP_POWERSAVE)
1492 #endif /* SUPPORT_AP_POWERSAVE */
1493 bool hang_required = false;
1496 return ERR_PTR(-EINVAL);
1498 #ifdef PROP_TXSTATUS_VSDB
1499 #if defined(BCMSDIO)
1500 dhd = (dhd_pub_t *)(cfg->pub);
1502 #endif /* PROP_TXSTATUS_VSDB */
1503 #if defined(SUPPORT_AP_POWERSAVE)
1504 dhd = (dhd_pub_t *)(cfg->pub);
1505 #endif /* SUPPORT_AP_POWERSAVE */
1507 /* Use primary I/F for sending cmds down to firmware */
1508 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1510 if (unlikely(!wl_get_drv_status(cfg, READY, primary_ndev))) {
1511 WL_ERR(("device is not ready\n"));
1512 return ERR_PTR(-ENODEV);
1515 WL_DBG(("if name: %s, type: %d\n", name, type));
1517 case NL80211_IFTYPE_ADHOC:
1518 #ifdef WLAIBSS_MCHAN
1519 return bcm_cfg80211_add_ibss_if(wiphy, (char *)name);
1520 #endif /* WLAIBSS_MCHAN */
1521 case NL80211_IFTYPE_AP_VLAN:
1522 case NL80211_IFTYPE_WDS:
1523 case NL80211_IFTYPE_MESH_POINT:
1524 WL_ERR(("Unsupported interface type\n"));
1525 mode = WL_MODE_IBSS;
1527 case NL80211_IFTYPE_MONITOR:
1528 return wl_cfg80211_add_monitor_if((char *)name);
1529 #if defined(WL_CFG80211_P2P_DEV_IF)
1530 case NL80211_IFTYPE_P2P_DEVICE:
1531 cfg->down_disc_if = FALSE;
1532 return wl_cfgp2p_add_p2p_disc_if(cfg);
1533 #endif /* WL_CFG80211_P2P_DEV_IF */
1534 case NL80211_IFTYPE_STATION:
1535 #ifdef WL_VIRTUAL_APSTA
1536 #ifdef WLAIBSS_MCHAN
1537 if (cfg->ibss_cfgdev) {
1538 WL_ERR(("AIBSS is already operational. "
1539 " AIBSS & DUALSTA can't be used together \n"));
1540 return ERR_PTR(-ENOMEM);
1542 #endif /* WLAIBSS_MCHAN */
1544 WL_ERR(("Interface name not provided \n"));
1545 return ERR_PTR(-ENODEV);
1548 if (wl_cfgp2p_vif_created(cfg)) {
1549 WL_ERR(("Could not create new iface."
1550 "Already one p2p interface is running"));
1551 return ERR_PTR(-ENODEV);
1553 new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
1554 NL80211_IFTYPE_STATION, NULL, name);
1556 return ERR_PTR(-ENOMEM);
1559 #endif /* WL_VIRTUAL_APSTA */
1560 case NL80211_IFTYPE_P2P_CLIENT:
1561 wlif_type = WL_P2P_IF_CLIENT;
1564 case NL80211_IFTYPE_P2P_GO:
1565 case NL80211_IFTYPE_AP:
1566 wlif_type = WL_P2P_IF_GO;
1570 WL_ERR(("Unsupported interface type\n"));
1571 return ERR_PTR(-ENODEV);
1576 WL_ERR(("name is NULL\n"));
1577 return ERR_PTR(-ENODEV);
1579 if (cfg->p2p_supported && (wlif_type != -1)) {
1580 ASSERT(cfg->p2p); /* ensure expectation of p2p initialization */
1582 #ifdef PROP_TXSTATUS_VSDB
1583 #if defined(BCMSDIO)
1585 return ERR_PTR(-ENODEV);
1587 #endif /* PROP_TXSTATUS_VSDB */
1589 return ERR_PTR(-ENODEV);
1591 if (cfg->cfgdev_bssidx != -1) {
1592 WL_ERR(("Failed to start p2p, Maximum no of interface reached"));
1593 return ERR_PTR(-ENODEV);
1596 if (cfg->p2p && !cfg->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
1598 wl_cfgp2p_set_firm_p2p(cfg);
1599 wl_cfgp2p_init_discovery(cfg);
1600 get_primary_mac(cfg, &primary_mac);
1601 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
1604 strncpy(cfg->p2p->vir_ifname, name, IFNAMSIZ - 1);
1605 cfg->p2p->vir_ifname[IFNAMSIZ - 1] = '\0';
1607 wl_cfg80211_scan_abort(cfg);
1608 #ifdef PROP_TXSTATUS_VSDB
1609 #if defined(BCMSDIO)
1610 if (!cfg->wlfc_on && !disable_proptx) {
1611 dhd_wlfc_get_enable(dhd, &enabled);
1612 if (!enabled && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
1613 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
1615 err = wldev_ioctl(primary_ndev, WLC_UP, &up, sizeof(s32), true);
1617 WL_ERR(("WLC_UP return err:%d\n", err));
1619 cfg->wlfc_on = true;
1622 #endif /* PROP_TXSTATUS_VSDB */
1624 /* Dual p2p doesn't support multiple P2PGO interfaces,
1625 * p2p_go_count is the counter for GO creation
1628 if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
1629 WL_ERR(("Fw doesnot support multiple Go"));
1630 return ERR_PTR(-ENOMEM);
1632 /* In concurrency case, STA may be already associated in a particular channel.
1633 * so retrieve the current channel of primary interface and then start the virtual
1634 * interface on that.
1636 chspec = wl_cfg80211_get_shared_freq(wiphy);
1638 /* For P2P mode, use P2P-specific driver features to create the
1639 * bss: "cfg p2p_ifadd"
1641 if (wl_check_dongle_idle(wiphy) != TRUE) {
1642 WL_ERR(("FW is busy to add interface"));
1643 return ERR_PTR(-ENOMEM);
1645 wl_set_p2p_status(cfg, IF_ADDING);
1646 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
1647 if (wlif_type == WL_P2P_IF_GO)
1648 wldev_iovar_setint(primary_ndev, "mpc", 0);
1649 cfg_type = wl_cfgp2p_get_conn_idx(cfg);
1650 if (cfg_type == BCME_ERROR) {
1651 wl_clr_p2p_status(cfg, IF_ADDING);
1652 WL_ERR(("Failed to get connection idx for p2p interface"));
1655 err = wl_cfgp2p_ifadd(cfg, wl_to_p2p_bss_macaddr(cfg, cfg_type),
1656 htod32(wlif_type), chspec);
1657 if (unlikely(err)) {
1658 wl_clr_p2p_status(cfg, IF_ADDING);
1659 WL_ERR((" virtual iface add failed (%d) \n", err));
1660 return ERR_PTR(-ENOMEM);
1663 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1664 ((wl_get_p2p_status(cfg, IF_ADDING) == false) &&
1665 (cfg->if_event_info.valid)),
1666 msecs_to_jiffies(MAX_WAIT_TIME));
1668 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_ADDING) && cfg->if_event_info.valid) {
1669 struct wireless_dev *vwdev;
1670 int pm_mode = PM_ENABLE;
1671 wl_if_event_info *event = &cfg->if_event_info;
1672 /* IF_ADD event has come back, we can proceed to to register
1673 * the new interface now, use the interface name provided by caller (thus
1674 * ignore the one from wlc)
1676 new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, cfg->p2p->vir_ifname,
1677 event->mac, event->bssidx, event->name);
1678 if (new_ndev == NULL)
1681 wl_to_p2p_bss_ndev(cfg, cfg_type) = new_ndev;
1682 wl_to_p2p_bss_bssidx(cfg, cfg_type) = event->bssidx;
1683 vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
1684 if (unlikely(!vwdev)) {
1685 WL_ERR(("Could not allocate wireless device\n"));
1689 vwdev->wiphy = cfg->wdev->wiphy;
1690 WL_INFORM(("virtual interface(%s) is created\n", cfg->p2p->vir_ifname));
1691 if (type == NL80211_IFTYPE_P2P_GO) {
1692 cfg->p2p->p2p_go_count++;
1694 vwdev->iftype = type;
1696 WL_ERR(("new_ndev: %p\n", new_ndev));
1698 vwdev->netdev = new_ndev;
1699 new_ndev->ieee80211_ptr = vwdev;
1700 SET_NETDEV_DEV(new_ndev, wiphy_dev(vwdev->wiphy));
1701 wl_set_drv_status(cfg, READY, new_ndev);
1702 wl_set_mode_by_netdev(cfg, new_ndev, mode);
1704 if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
1705 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
1709 err = wl_alloc_netinfo(cfg, new_ndev, vwdev, mode, pm_mode, event->bssidx);
1710 if (unlikely(err != 0)) {
1711 WL_ERR(("Allocation of netinfo failed (%d) \n", err));
1715 /* Disable firmware roaming for P2P interface */
1716 wldev_iovar_setint(new_ndev, "roam_off", val);
1718 if (cfg->p2p_wdev && is_p2p_group_iface(new_ndev->ieee80211_ptr)) {
1719 u32 ulb_bw = wl_cfg80211_get_ulb_bw(cfg->p2p_wdev);
1721 /* Apply ULB BW settings on the newly spawned interface */
1722 WL_DBG(("[ULB] Applying ULB BW for the newly"
1723 "created P2P interface \n"));
1724 if (wl_cfg80211_set_ulb_bw(new_ndev,
1725 ulb_bw, new_ndev->name) < 0) {
1727 * If ulb_bw set failed, fail the iface creation.
1728 * wl_dealloc_netinfo_by_wdev will be called by the
1729 * unregister notifier.
1731 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
1737 #endif /* WL11ULB */
1739 if (mode != WL_MODE_AP)
1740 wldev_iovar_setint(new_ndev, "buf_key_b4_m4", 1);
1742 WL_ERR((" virtual interface(%s) is "
1743 "created net attach done\n", cfg->p2p->vir_ifname));
1744 if (mode == WL_MODE_AP)
1745 wl_set_drv_status(cfg, CONNECTED, new_ndev);
1746 #ifdef SUPPORT_AP_POWERSAVE
1747 if (mode == WL_MODE_AP) {
1748 dhd_set_ap_powersave(dhd, 0, TRUE);
1750 #endif /* SUPPORT_AP_POWERSAVE */
1751 if (type == NL80211_IFTYPE_P2P_CLIENT)
1752 dhd_mode = DHD_FLAG_P2P_GC_MODE;
1753 else if (type == NL80211_IFTYPE_P2P_GO)
1754 dhd_mode = DHD_FLAG_P2P_GO_MODE;
1755 DNGL_FUNC(dhd_cfg80211_set_p2p_info, (cfg, dhd_mode));
1756 /* reinitialize completion to clear previous count */
1757 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
1758 INIT_COMPLETION(cfg->iface_disable);
1760 init_completion(&cfg->iface_disable);
1762 return ndev_to_cfgdev(new_ndev);
1764 wl_clr_p2p_status(cfg, IF_ADDING);
1765 WL_ERR((" virtual interface(%s) is not created \n", cfg->p2p->vir_ifname));
1767 WL_ERR(("left timeout : %d\n", timeout));
1768 WL_ERR(("IF_ADDING status : %d\n", wl_get_p2p_status(cfg, IF_ADDING)));
1769 WL_ERR(("event valid : %d\n", cfg->if_event_info.valid));
1771 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
1772 wl_set_p2p_status(cfg, IF_DELETING);
1774 err = wl_cfgp2p_ifdel(cfg, wl_to_p2p_bss_macaddr(cfg, cfg_type));
1775 if (err == BCME_OK) {
1776 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1777 ((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
1778 (cfg->if_event_info.valid)),
1779 msecs_to_jiffies(MAX_WAIT_TIME));
1780 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
1781 cfg->if_event_info.valid) {
1783 * Should indicate upper layer this failure case of p2p
1784 * interface creation
1786 WL_ERR(("IFDEL operation done\n"));
1788 WL_ERR(("IFDEL didn't complete properly\n"));
1789 hang_required = true;
1792 hang_required = true;
1795 if (hang_required) {
1796 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
1797 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1799 WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
1801 dhd->hang_reason = HANG_REASON_P2P_IFACE_DEL_FAILURE;
1802 net_os_send_hang_message(ndev);
1805 memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
1806 wl_to_p2p_bss_bssidx(cfg, cfg_type) = -1;
1807 #ifdef PROP_TXSTATUS_VSDB
1808 #if defined(BCMSDIO)
1809 dhd_wlfc_get_enable(dhd, &enabled);
1810 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
1811 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
1812 dhd_wlfc_deinit(dhd);
1813 cfg->wlfc_on = false;
1816 #endif /* PROP_TXSTATUS_VSDB */
1818 * Returns -ENODEV to upperlayer to indicate that DHD
1819 * failed to create p2p interface
1825 if (wlif_type == WL_P2P_IF_GO)
1826 wldev_iovar_setint(primary_ndev, "mpc", 1);
1827 return ERR_PTR(err);
1831 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
1833 struct net_device *dev = NULL;
1834 struct ether_addr p2p_mac;
1835 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1840 #ifdef CUSTOM_SET_CPUCORE
1841 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1842 #endif /* CUSTOM_SET_CPUCORE */
1843 WL_DBG(("Enter\n"));
1845 #ifdef CUSTOM_SET_CPUCORE
1846 dhd->chan_isvht80 &= ~DHD_FLAG_P2P_MODE;
1847 if (!(dhd->chan_isvht80))
1848 dhd_set_cpucore(dhd, FALSE);
1849 #endif /* CUSTOM_SET_CPUCORE */
1850 #ifdef WL_CFG80211_P2P_DEV_IF
1851 if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
1852 if (dhd_download_fw_on_driverload) {
1853 return wl_cfgp2p_del_p2p_disc_if(cfgdev, cfg);
1855 cfg->down_disc_if = TRUE;
1859 #endif /* WL_CFG80211_P2P_DEV_IF */
1860 dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
1862 #ifdef WLAIBSS_MCHAN
1863 if (cfgdev == cfg->ibss_cfgdev)
1864 return bcm_cfg80211_del_ibss_if(wiphy, cfgdev);
1865 #endif /* WLAIBSS_MCHAN */
1867 #ifdef WL_VIRTUAL_APSTA
1868 if (cfgdev == cfg->bss_cfgdev)
1869 return wl_cfg80211_del_iface(wiphy, cfgdev);
1870 #endif /* WL_VIRTUAL_APSTA */
1871 if ((index = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
1872 WL_ERR(("Find p2p index from wdev failed\n"));
1875 if (wl_check_dongle_idle(wiphy) != TRUE) {
1876 WL_ERR(("FW is busy to add interface"));
1879 if (cfg->p2p_supported) {
1880 if (wl_cfgp2p_find_type(cfg, index, &type) != BCME_OK)
1882 memcpy(p2p_mac.octet, wl_to_p2p_bss_macaddr(cfg, type).octet, ETHER_ADDR_LEN);
1884 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
1886 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
1887 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
1888 if (wl_cfgp2p_vif_created(cfg)) {
1889 if (wl_get_drv_status(cfg, SCANNING, dev)) {
1890 wl_notify_escan_complete(cfg, dev, true, true);
1892 wldev_iovar_setint(dev, "mpc", 1);
1893 /* Delete pm_enable_work */
1894 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
1897 if (wl_get_drv_status(cfg, DISCONNECTING, dev) &&
1898 (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)) {
1899 WL_ERR(("Wait for Link Down event for GC !\n"));
1900 wait_for_completion_timeout
1901 (&cfg->iface_disable, msecs_to_jiffies(500));
1904 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
1905 wl_set_p2p_status(cfg, IF_DELETING);
1906 DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (cfg));
1909 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
1910 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
1911 cfg->p2p->p2p_go_count--;
1912 /* disable interface before bsscfg free */
1913 ret = wl_cfgp2p_ifdisable(cfg, &p2p_mac);
1914 /* if fw doesn't support "ifdis",
1915 do not wait for link down of ap mode
1918 WL_ERR(("Wait for Link Down event for GO !!!\n"));
1919 wait_for_completion_timeout(&cfg->iface_disable,
1920 msecs_to_jiffies(500));
1921 } else if (ret != BCME_UNSUPPORTED) {
1925 wl_cfg80211_clear_per_bss_ies(cfg, index);
1927 if (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)
1928 wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
1929 memcpy(p2p_mac.octet, wl_to_p2p_bss_macaddr(cfg, type).octet,
1931 CFGP2P_INFO(("primary idx %d : cfg p2p_ifdis "MACDBG"\n",
1932 dev->ifindex, MAC2STRDBG(p2p_mac.octet)));
1934 /* delete interface after link down */
1935 ret = wl_cfgp2p_ifdel(cfg, &p2p_mac);
1936 if (ret != BCME_OK) {
1937 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
1938 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1940 WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
1942 dhd->hang_reason = HANG_REASON_P2P_IFACE_DEL_FAILURE;
1943 net_os_send_hang_message(ndev);
1945 /* Wait for IF_DEL operation to be finished */
1946 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1947 ((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
1948 (cfg->if_event_info.valid)),
1949 msecs_to_jiffies(MAX_WAIT_TIME));
1950 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
1951 cfg->if_event_info.valid) {
1953 WL_DBG(("IFDEL operation done\n"));
1954 wl_cfg80211_handle_ifdel(cfg, &cfg->if_event_info, dev);
1956 WL_ERR(("IFDEL didn't complete properly\n"));
1960 ret = dhd_del_monitor(dev);
1961 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
1962 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL((dhd_pub_t *)(cfg->pub));
1970 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
1971 enum nl80211_iftype type, u32 *flags,
1972 struct vif_params *params)
1983 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1984 struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1985 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1987 WL_DBG(("Enter type %d\n", type));
1989 case NL80211_IFTYPE_MONITOR:
1990 case NL80211_IFTYPE_WDS:
1991 case NL80211_IFTYPE_MESH_POINT:
1993 WL_ERR(("type (%d) : currently we do not support this type\n",
1996 case NL80211_IFTYPE_ADHOC:
1997 mode = WL_MODE_IBSS;
2000 case NL80211_IFTYPE_STATION:
2001 case NL80211_IFTYPE_P2P_CLIENT:
2005 case NL80211_IFTYPE_AP:
2006 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
2007 /* intentional fall through */
2008 case NL80211_IFTYPE_AP_VLAN:
2009 case NL80211_IFTYPE_P2P_GO:
2019 /* If any scan is going on, abort it */
2020 if (wl_get_drv_status_all(cfg, SCANNING)) {
2021 int wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
2022 WL_ERR(("Scan in progress. Aborting the scan!\n"));
2023 wl_cfg80211_scan_abort(cfg);
2024 while (wl_get_drv_status_all(cfg, SCANNING) && wait_cnt) {
2025 WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
2027 OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
2029 if (wl_get_drv_status_all(cfg, SCANNING)) {
2030 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
2034 if (wl_check_dongle_idle(wiphy) != TRUE) {
2035 WL_ERR(("FW is busy to add interface"));
2039 wl_set_mode_by_netdev(cfg, ndev, mode);
2040 if (is_p2p_group_iface(ndev->ieee80211_ptr) &&
2041 cfg->p2p && wl_cfgp2p_vif_created(cfg)) {
2042 WL_DBG(("p2p_vif_created p2p_on (%d)\n", p2p_on(cfg)));
2043 wldev_iovar_setint(ndev, "mpc", 0);
2044 wl_notify_escan_complete(cfg, ndev, true, true);
2046 /* Dual p2p doesn't support multiple P2PGO interfaces,
2047 * p2p_go_count is the counter for GO creation
2050 if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
2051 wl_set_mode_by_netdev(cfg, ndev, WL_MODE_BSS);
2052 WL_ERR(("Fw doesnot support multiple GO "));
2055 /* In concurrency case, STA may be already associated in a particular
2056 * channel. so retrieve the current channel of primary interface and
2057 * then start the virtual interface on that.
2059 chspec = wl_cfg80211_get_shared_freq(wiphy);
2060 index = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2062 WL_ERR(("Find p2p index from ndev(%p) failed\n", ndev));
2065 if (wl_cfgp2p_find_type(cfg, index, &conn_idx) != BCME_OK)
2068 wlif_type = WL_P2P_IF_GO;
2069 printf("%s : ap (%d), infra (%d), iftype (%d) conn_idx (%d)\n",
2070 ndev->name, ap, infra, type, conn_idx);
2071 wl_set_p2p_status(cfg, IF_CHANGING);
2072 wl_clr_p2p_status(cfg, IF_CHANGED);
2073 wl_cfgp2p_ifchange(cfg, wl_to_p2p_bss_macaddr(cfg, conn_idx),
2074 htod32(wlif_type), chspec, conn_idx);
2075 wait_event_interruptible_timeout(cfg->netif_change_event,
2076 (wl_get_p2p_status(cfg, IF_CHANGED) == true),
2077 msecs_to_jiffies(MAX_WAIT_TIME));
2078 wl_set_mode_by_netdev(cfg, ndev, mode);
2079 dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
2080 dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
2081 wl_clr_p2p_status(cfg, IF_CHANGING);
2082 wl_clr_p2p_status(cfg, IF_CHANGED);
2083 if (mode == WL_MODE_AP)
2084 wl_set_drv_status(cfg, CONNECTED, ndev);
2085 #ifdef SUPPORT_AP_POWERSAVE
2086 dhd_set_ap_powersave(dhd, 0, TRUE);
2087 #endif /* SUPPORT_AP_POWERSAVE */
2088 } else if (((ndev == primary_ndev) ||
2089 (ndev == ((struct net_device *)cfgdev_to_ndev(cfg->bss_cfgdev)))) &&
2090 !wl_get_drv_status(cfg, AP_CREATED, ndev)) {
2091 wl_set_drv_status(cfg, AP_CREATING, ndev);
2093 WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
2097 /* P2P GO interface deletion is handled on the basis of role type (AP).
2098 * So avoid changing role for p2p type.
2100 if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2101 wl_set_mode_by_netdev(cfg, ndev, mode);
2102 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA"));
2103 #ifdef SUPPORT_AP_POWERSAVE
2104 dhd_set_ap_powersave(dhd, 0, FALSE);
2105 #endif /* SUPPORT_AP_POWERSAVE */
2110 wl_set_mode_by_netdev(cfg, ndev, mode);
2111 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(s32), true);
2113 WL_ERR(("SET Adhoc error %d\n", err));
2118 ndev->ieee80211_ptr->iftype = type;
2123 wl_cfg80211_notify_ifadd(int ifidx, char *name, uint8 *mac, uint8 bssidx)
2125 bool ifadd_expected = FALSE;
2126 struct bcm_cfg80211 *cfg = g_bcm_cfg;
2128 /* P2P may send WLC_E_IF_ADD and/or WLC_E_IF_CHANGE during IF updating ("p2p_ifupd")
2129 * redirect the IF_ADD event to ifchange as it is not a real "new" interface
2131 if (wl_get_p2p_status(cfg, IF_CHANGING))
2132 return wl_cfg80211_notify_ifchange(ifidx, name, mac, bssidx);
2134 /* Okay, we are expecting IF_ADD (as IF_ADDING is true) */
2135 if (wl_get_p2p_status(cfg, IF_ADDING)) {
2136 ifadd_expected = TRUE;
2137 wl_clr_p2p_status(cfg, IF_ADDING);
2138 } else if (cfg->bss_pending_op) {
2139 ifadd_expected = TRUE;
2140 cfg->bss_pending_op = FALSE;
2143 if (ifadd_expected) {
2144 wl_if_event_info *if_event_info = &cfg->if_event_info;
2146 if_event_info->valid = TRUE;
2147 if_event_info->ifidx = ifidx;
2148 if_event_info->bssidx = bssidx;
2149 strncpy(if_event_info->name, name, IFNAMSIZ);
2150 if_event_info->name[IFNAMSIZ] = '\0';
2152 memcpy(if_event_info->mac, mac, ETHER_ADDR_LEN);
2153 wake_up_interruptible(&cfg->netif_change_event);
2161 wl_cfg80211_notify_ifdel(int ifidx, char *name, uint8 *mac, uint8 bssidx)
2163 bool ifdel_expected = FALSE;
2164 struct bcm_cfg80211 *cfg = g_bcm_cfg;
2165 wl_if_event_info *if_event_info = &cfg->if_event_info;
2167 if (wl_get_p2p_status(cfg, IF_DELETING)) {
2168 ifdel_expected = TRUE;
2169 wl_clr_p2p_status(cfg, IF_DELETING);
2170 } else if (cfg->bss_pending_op) {
2171 ifdel_expected = TRUE;
2172 cfg->bss_pending_op = FALSE;
2175 if (ifdel_expected) {
2176 if_event_info->valid = TRUE;
2177 if_event_info->ifidx = ifidx;
2178 if_event_info->bssidx = bssidx;
2179 wake_up_interruptible(&cfg->netif_change_event);
2187 wl_cfg80211_notify_ifchange(int ifidx, char *name, uint8 *mac, uint8 bssidx)
2189 struct bcm_cfg80211 *cfg = g_bcm_cfg;
2191 if (wl_get_p2p_status(cfg, IF_CHANGING)) {
2192 wl_set_p2p_status(cfg, IF_CHANGED);
2193 wake_up_interruptible(&cfg->netif_change_event);
2200 static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
2201 struct net_device* ndev)
2205 #ifdef PROP_TXSTATUS_VSDB
2206 #if defined(BCMSDIO)
2207 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2210 #endif /* PROP_TXSTATUS_VSDB */
2212 bssidx = if_event_info->bssidx;
2213 if (bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) &&
2214 bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2)) {
2215 WL_ERR(("got IF_DEL for if %d, not owned by cfg driver\n", bssidx));
2219 if (p2p_is_on(cfg) && wl_cfgp2p_vif_created(cfg)) {
2220 if (cfg->scan_request && (cfg->escan_info.ndev == ndev)) {
2221 /* Abort any pending scan requests */
2222 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2223 WL_DBG(("ESCAN COMPLETED\n"));
2224 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, false);
2227 memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
2228 if (wl_cfgp2p_find_type(cfg, bssidx, &type) == BCME_OK) {
2229 /* Update P2P data */
2230 wl_clr_drv_status(cfg, CONNECTED, wl_to_p2p_bss_ndev(cfg, type));
2231 wl_to_p2p_bss_ndev(cfg, type) = NULL;
2232 wl_to_p2p_bss_bssidx(cfg, type) = -1;
2233 } else if (wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr) < 0) {
2234 WL_ERR(("bssidx not known for the given ndev as per net_info data \n"));
2238 #ifdef PROP_TXSTATUS_VSDB
2239 #if defined(BCMSDIO)
2240 dhd_wlfc_get_enable(dhd, &enabled);
2241 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
2242 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
2243 dhd_wlfc_deinit(dhd);
2244 cfg->wlfc_on = false;
2247 #endif /* PROP_TXSTATUS_VSDB */
2250 dhd_net_if_lock(ndev);
2251 wl_cfg80211_remove_if(cfg, if_event_info->ifidx, ndev);
2252 dhd_net_if_unlock(ndev);
2257 /* Find listen channel */
2258 static s32 wl_find_listen_channel(struct bcm_cfg80211 *cfg,
2259 const u8 *ie, u32 ie_len)
2261 wifi_p2p_ie_t *p2p_ie;
2265 /* unfortunately const cast required here - function is
2266 * a callback so its signature must not be changed
2267 * and cascade of changing wl_cfgp2p_find_p2pie
2268 * causes need for const cast in other places
2270 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2271 4 && __GNUC_MINOR__ >= 6))
2272 _Pragma("GCC diagnostic push")
2273 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
2276 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2277 4 && __GNUC_MINOR__ >= 6))
2278 _Pragma("GCC diagnostic pop")
2280 p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
2285 pos = p2p_ie->subelts;
2286 end = p2p_ie->subelts + (p2p_ie->len - 4);
2288 CFGP2P_DBG((" found p2p ie ! lenth %d \n",
2293 if (pos + 2 >= end) {
2294 CFGP2P_DBG((" -- Invalid P2P attribute"));
2297 attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
2299 if (pos + 3 + attr_len > end) {
2300 CFGP2P_DBG(("P2P: Attribute underflow "
2302 attr_len, (int) (end - pos - 3)));
2306 /* if Listen Channel att id is 6 and the vailue is valid,
2307 * return the listen channel
2310 /* listen channel subel length format
2311 * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
2313 listen_channel = pos[1 + 2 + 3 + 1];
2315 if (listen_channel == SOCIAL_CHAN_1 ||
2316 listen_channel == SOCIAL_CHAN_2 ||
2317 listen_channel == SOCIAL_CHAN_3) {
2318 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
2319 return listen_channel;
2322 pos += 3 + attr_len;
2327 static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_request *request)
2332 chanspec_t chanspec;
2333 s32 i = 0, j = 0, offset;
2336 struct bcm_cfg80211 *cfg = g_bcm_cfg;
2337 struct wireless_dev *wdev;
2339 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
2340 params->bss_type = DOT11_BSSTYPE_ANY;
2341 params->scan_type = 0;
2342 params->nprobes = -1;
2343 params->active_time = -1;
2344 params->passive_time = -1;
2345 params->home_time = -1;
2346 params->channel_num = 0;
2347 memset(¶ms->ssid, 0, sizeof(wlc_ssid_t));
2349 WL_SCAN(("Preparing Scan request\n"));
2350 WL_SCAN(("nprobes=%d\n", params->nprobes));
2351 WL_SCAN(("active_time=%d\n", params->active_time));
2352 WL_SCAN(("passive_time=%d\n", params->passive_time));
2353 WL_SCAN(("home_time=%d\n", params->home_time));
2354 WL_SCAN(("scan_type=%d\n", params->scan_type));
2356 params->nprobes = htod32(params->nprobes);
2357 params->active_time = htod32(params->active_time);
2358 params->passive_time = htod32(params->passive_time);
2359 params->home_time = htod32(params->home_time);
2361 /* if request is null just exit so it will be all channel broadcast scan */
2365 n_ssids = request->n_ssids;
2366 n_channels = request->n_channels;
2368 /* Copy channel array if applicable */
2369 WL_SCAN(("### List of channelspecs to scan ###\n"));
2370 if (n_channels > 0) {
2371 for (i = 0; i < n_channels; i++) {
2373 channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
2374 /* SKIP DFS channels for Secondary interface */
2375 if ((cfg->escan_info.ndev != bcmcfg_to_prmry_ndev(cfg)) &&
2376 (request->channels[i]->flags &
2377 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
2378 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
2380 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR)))
2381 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
2383 if (!dhd_conf_match_channel(cfg->pub, channel))
2386 #if defined(WL_CFG80211_P2P_DEV_IF)
2387 wdev = request->wdev;
2389 wdev = request->dev->ieee80211_ptr;
2390 #endif /* WL_CFG80211_P2P_DEV_IF */
2391 chanspec = wl_cfg80211_ulb_get_min_bw_chspec(wdev, -1);
2392 if (chanspec == INVCHANSPEC) {
2393 WL_ERR(("Invalid chanspec! Skipping channel\n"));
2397 if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
2398 chanspec |= WL_CHANSPEC_BAND_2G;
2400 chanspec |= WL_CHANSPEC_BAND_5G;
2402 params->channel_list[j] = channel;
2403 params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
2404 params->channel_list[j] |= chanspec;
2405 WL_SCAN(("Chan : %d, Channel spec: %x \n",
2406 channel, params->channel_list[j]));
2407 params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
2411 WL_SCAN(("Scanning all channels\n"));
2414 /* Copy ssid array if applicable */
2415 WL_SCAN(("### List of SSIDs to scan ###\n"));
2417 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
2418 offset = roundup(offset, sizeof(u32));
2419 ptr = (char*)params + offset;
2420 for (i = 0; i < n_ssids; i++) {
2421 memset(&ssid, 0, sizeof(wlc_ssid_t));
2422 ssid.SSID_len = request->ssids[i].ssid_len;
2423 memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
2425 WL_SCAN(("%d: Broadcast scan\n", i));
2427 WL_SCAN(("%d: scan for %s size =%d\n", i,
2428 ssid.SSID, ssid.SSID_len));
2429 memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
2430 ptr += sizeof(wlc_ssid_t);
2433 WL_SCAN(("Broadcast scan\n"));
2435 /* Adding mask to channel numbers */
2436 params->channel_num =
2437 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
2438 (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
2440 if (n_channels == 1) {
2441 params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
2442 params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
2447 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
2449 wl_uint32_list_t *list;
2451 if (valid_chan_list == NULL || size <= 0)
2454 memset(valid_chan_list, 0, size);
2455 list = (wl_uint32_list_t *)(void *) valid_chan_list;
2456 list->count = htod32(WL_NUMCHANNELS);
2457 err = wldev_ioctl(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size, false);
2459 WL_ERR(("get channels failed with %d\n", err));
2465 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2466 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
2467 bool g_first_broadcast_scan = TRUE;
2471 wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev,
2472 struct cfg80211_scan_request *request, uint16 action)
2477 s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
2478 wl_escan_params_t *params = NULL;
2479 u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
2483 s32 search_state = WL_P2P_DISC_ST_SCAN;
2484 u32 i, j, n_nodfs = 0;
2485 u16 *default_chan_list = NULL;
2486 wl_uint32_list_t *list;
2488 struct net_device *dev = NULL;
2489 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2490 bool is_first_init_2g_scan = false;
2492 p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
2496 WL_DBG(("Enter \n"));
2498 /* scan request can come with empty request : perform all default scan */
2503 if (!cfg->p2p_supported || !p2p_scan(cfg)) {
2504 /* LEGACY SCAN TRIGGER */
2505 WL_SCAN((" LEGACY E-SCAN START\n"));
2507 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2512 if (ndev == bcmcfg_to_prmry_ndev(cfg) && g_first_broadcast_scan == true) {
2513 is_first_init_2g_scan = true;
2514 g_first_broadcast_scan = false;
2518 /* if scan request is not empty parse scan request paramters */
2519 if (request != NULL) {
2520 n_channels = request->n_channels;
2521 n_ssids = request->n_ssids;
2523 /* If n_channels is odd, add a padd of u16 */
2524 params_size += sizeof(u16) * (n_channels + 1);
2526 params_size += sizeof(u16) * n_channels;
2528 /* Allocate space for populating ssids in wl_escan_params_t struct */
2529 params_size += sizeof(struct wlc_ssid) * n_ssids;
2531 params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
2532 if (params == NULL) {
2536 wl_scan_prep(¶ms->params, request);
2538 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2539 /* Override active_time to reduce scan time if it's first bradcast scan. */
2540 if (is_first_init_2g_scan)
2541 params->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
2544 params->version = htod32(ESCAN_REQ_VERSION);
2545 params->action = htod16(action);
2546 wl_escan_set_sync_id(params->sync_id, cfg);
2547 wl_escan_set_type(cfg, WL_SCANTYPE_LEGACY);
2548 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
2549 WL_ERR(("ioctl buffer length not sufficient\n"));
2554 if (cfg->active_scan == PASSIVE_SCAN) {
2555 params->params.scan_type = DOT11_SCANTYPE_PASSIVE;
2556 WL_DBG(("Passive scan_type %d \n", params->params.scan_type));
2559 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2561 err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
2562 cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2563 WL_SCAN(("%s: LEGACY_SCAN sync ID: %d, bssidx: %d\n", __FUNCTION__, params->sync_id, bssidx));
2564 if (unlikely(err)) {
2565 if (err == BCME_EPERM)
2566 /* Scan Not permitted at this point of time */
2567 WL_DBG((" Escan not permitted at this time (%d)\n", err));
2569 WL_ERR((" Escan set error (%d)\n", err));
2573 else if (p2p_is_on(cfg) && p2p_scan(cfg)) {
2574 /* P2P SCAN TRIGGER */
2577 if (request && request->n_channels) {
2578 num_chans = request->n_channels;
2579 WL_SCAN((" chann number : %d\n", num_chans));
2580 default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
2582 if (default_chan_list == NULL) {
2583 WL_ERR(("channel list allocation failed \n"));
2587 if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
2589 int is_printed = false;
2590 #endif /* P2P_SKIP_DFS */
2591 list = (wl_uint32_list_t *) chan_buf;
2592 n_valid_chan = dtoh32(list->count);
2593 for (i = 0; i < num_chans; i++)
2595 _freq = request->channels[i]->center_freq;
2596 channel = ieee80211_frequency_to_channel(_freq);
2598 /* ignore DFS channels */
2599 if (request->channels[i]->flags &
2600 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2601 (IEEE80211_CHAN_NO_IR
2602 | IEEE80211_CHAN_RADAR))
2604 (IEEE80211_CHAN_RADAR
2605 | IEEE80211_CHAN_PASSIVE_SCAN))
2609 if (channel >= 52 && channel <= 144) {
2610 if (is_printed == false) {
2611 WL_ERR(("SKIP DFS CHANs(52~144)\n"));
2616 #endif /* P2P_SKIP_DFS */
2618 for (j = 0; j < n_valid_chan; j++) {
2619 /* allows only supported channel on
2622 if (channel == (dtoh32(list->element[j])))
2623 default_chan_list[n_nodfs++] =
2629 if (num_chans == SOCIAL_CHAN_CNT && (
2630 (default_chan_list[0] == SOCIAL_CHAN_1) &&
2631 (default_chan_list[1] == SOCIAL_CHAN_2) &&
2632 (default_chan_list[2] == SOCIAL_CHAN_3))) {
2633 /* SOCIAL CHANNELS 1, 6, 11 */
2634 search_state = WL_P2P_DISC_ST_SEARCH;
2635 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2636 WL_INFORM(("P2P SEARCH PHASE START \n"));
2637 } else if (((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1)) &&
2638 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) ||
2639 ((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2)) &&
2640 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP))) {
2641 /* If you are already a GO, then do SEARCH only */
2642 WL_INFORM(("Already a GO. Do SEARCH Only"));
2643 search_state = WL_P2P_DISC_ST_SEARCH;
2644 num_chans = n_nodfs;
2645 p2p_scan_purpose = P2P_SCAN_NORMAL;
2647 } else if (num_chans == 1) {
2648 p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
2649 } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
2650 /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2653 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2655 WL_INFORM(("P2P SCAN STATE START \n"));
2656 num_chans = n_nodfs;
2657 p2p_scan_purpose = P2P_SCAN_NORMAL;
2663 err = wl_cfgp2p_escan(cfg, ndev, ACTIVE_SCAN, num_chans, default_chan_list,
2664 search_state, action,
2665 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE), NULL,
2669 cfg->p2p->search_state = search_state;
2671 kfree(default_chan_list);
2674 if (unlikely(err)) {
2675 /* Don't print Error incase of Scan suppress */
2676 if ((err == BCME_EPERM) && cfg->scan_suppressed)
2677 WL_DBG(("Escan failed: Scan Suppressed \n"));
2680 WL_ERR(("error (%d), cnt=%d\n", err, cnt));
2681 // terence 20140111: send disassoc to firmware
2683 dev = bcmcfg_to_prmry_ndev(cfg);
2684 memset(&scbval, 0, sizeof(scb_val_t));
2685 wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true);
2686 WL_ERR(("Send disassoc to break the busy dev=%p\n", dev));
2698 wl_do_escan(struct bcm_cfg80211 *cfg, struct wiphy *wiphy, struct net_device *ndev,
2699 struct cfg80211_scan_request *request)
2703 s32 passive_scan_time;
2704 s32 passive_scan_time_org;
2705 wl_scan_results_t *results;
2706 WL_SCAN(("Enter \n"));
2708 results = wl_escan_get_buf(cfg, FALSE);
2709 results->version = 0;
2711 results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
2713 cfg->escan_info.ndev = ndev;
2714 cfg->escan_info.wiphy = wiphy;
2715 cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
2716 passive_scan = cfg->active_scan ? 0 : 1;
2717 err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
2718 &passive_scan, sizeof(passive_scan), true);
2719 if (unlikely(err)) {
2720 WL_ERR(("error (%d)\n", err));
2724 if (passive_channel_skip) {
2726 err = wldev_ioctl(ndev, WLC_GET_SCAN_PASSIVE_TIME,
2727 &passive_scan_time_org, sizeof(passive_scan_time_org), false);
2728 if (unlikely(err)) {
2729 WL_ERR(("== error (%d)\n", err));
2733 WL_SCAN(("PASSIVE SCAN time : %d \n", passive_scan_time_org));
2735 passive_scan_time = 0;
2736 err = wldev_ioctl(ndev, WLC_SET_SCAN_PASSIVE_TIME,
2737 &passive_scan_time, sizeof(passive_scan_time), true);
2738 if (unlikely(err)) {
2739 WL_ERR(("== error (%d)\n", err));
2743 WL_SCAN(("PASSIVE SCAN SKIPED!! (passive_channel_skip:%d) \n",
2744 passive_channel_skip));
2747 err = wl_run_escan(cfg, ndev, request, WL_SCAN_ACTION_START);
2749 if (passive_channel_skip) {
2750 err = wldev_ioctl(ndev, WLC_SET_SCAN_PASSIVE_TIME,
2751 &passive_scan_time_org, sizeof(passive_scan_time_org), true);
2752 if (unlikely(err)) {
2753 WL_ERR(("== error (%d)\n", err));
2757 WL_SCAN(("PASSIVE SCAN RECOVERED!! (passive_scan_time_org:%d) \n",
2758 passive_scan_time_org));
2766 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
2767 struct cfg80211_scan_request *request,
2768 struct cfg80211_ssid *this_ssid)
2770 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2771 struct cfg80211_ssid *ssids;
2772 struct ether_addr primary_mac;
2775 bcm_tlv_t *interworking_ie;
2781 unsigned long flags;
2782 static s32 busy_count = 0;
2783 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2784 struct net_device *remain_on_channel_ndev = NULL;
2788 * Hostapd triggers scan before starting automatic channel selection
2789 * to collect channel characteristics. However firmware scan engine
2790 * doesn't support any channel characteristics collection along with
2791 * scan. Hence return scan success.
2793 if (request && (scan_req_iftype(request) == NL80211_IFTYPE_AP)) {
2794 WL_INFORM(("Scan Command on SoftAP Interface. Ignoring...\n"));
2798 ndev = ndev_to_wlc_ndev(ndev, cfg);
2800 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
2801 WL_ERR(("Sending Action Frames. Try it again.\n"));
2805 WL_DBG(("Enter wiphy (%p)\n", wiphy));
2806 if (wl_get_drv_status_all(cfg, SCANNING)) {
2807 if (cfg->scan_request == NULL) {
2808 wl_clr_drv_status_all(cfg, SCANNING);
2809 WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
2811 WL_ERR(("Scanning already\n"));
2815 if (wl_get_drv_status(cfg, SCAN_ABORTING, ndev)) {
2816 WL_ERR(("Scanning being aborted\n"));
2819 if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
2820 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
2824 #ifdef P2P_LISTEN_OFFLOADING
2825 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
2826 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
2829 #endif /* P2P_LISTEN_OFFLOADING */
2831 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
2832 remain_on_channel_ndev = wl_cfg80211_get_remain_on_channel_ndev(cfg);
2833 if (remain_on_channel_ndev) {
2834 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
2835 wl_notify_escan_complete(cfg, remain_on_channel_ndev, true, true);
2837 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
2840 /* Arm scan timeout timer */
2841 mod_timer(&cfg->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS));
2842 if (request) { /* scan bss */
2843 ssids = request->ssids;
2845 for (i = 0; i < request->n_ssids; i++) {
2846 if (ssids[i].ssid_len &&
2847 IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
2853 if (cfg->p2p_supported) {
2854 /* p2p scan trigger */
2855 if (p2p_on(cfg) == false) {
2856 /* p2p on at the first time */
2858 wl_cfgp2p_set_firm_p2p(cfg);
2859 get_primary_mac(cfg, &primary_mac);
2860 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
2861 #if defined(P2P_IE_MISSING_FIX)
2862 cfg->p2p_prb_noti = false;
2865 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
2866 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
2867 p2p_scan(cfg) = true;
2870 /* legacy scan trigger
2871 * So, we have to disable p2p discovery if p2p discovery is on
2873 if (cfg->p2p_supported) {
2874 p2p_scan(cfg) = false;
2875 /* If Netdevice is not equals to primary and p2p is on
2876 * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
2879 if (p2p_scan(cfg) == false) {
2880 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
2881 err = wl_cfgp2p_discover_enable_search(cfg,
2883 if (unlikely(err)) {
2890 if (!cfg->p2p_supported || !p2p_scan(cfg)) {
2891 if ((bssidx = wl_get_bssidx_by_wdev(cfg,
2892 ndev->ieee80211_ptr)) < 0) {
2893 WL_ERR(("Find p2p index from ndev(%p) failed\n",
2899 if ((interworking_ie = wl_cfg80211_find_interworking_ie(
2900 (u8 *)request->ie, request->ie_len)) != NULL) {
2901 err = wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
2902 VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
2903 interworking_ie->data, interworking_ie->len);
2905 if (unlikely(err)) {
2906 WL_ERR(("Failed to add interworking IE"));
2908 } else if (cfg->iw_ie_len != 0) {
2909 /* we have to clear IW IE and disable gratuitous APR */
2910 wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
2911 VNDR_IE_CUSTOM_FLAG,
2912 DOT11_MNG_INTERWORKING_ID,
2915 (void)wldev_iovar_setint_bsscfg(ndev, "grat_arp", 0,
2919 memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
2920 /* we don't care about error */
2923 err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(ndev),
2924 bssidx, VNDR_IE_PRBREQ_FLAG, request->ie,
2927 if (unlikely(err)) {
2933 } else { /* scan in ibss */
2937 if (request && cfg->p2p_supported && !p2p_scan(cfg)) {
2938 WL_TRACE_HW4(("START SCAN\n"));
2939 DHD_OS_SCAN_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub),
2940 SCAN_WAKE_LOCK_TIMEOUT);
2941 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
2944 if (cfg->p2p_supported) {
2945 if (p2p_on(cfg) && p2p_scan(cfg)) {
2947 /* find my listen channel */
2948 cfg->afx_hdl->my_listen_chan =
2949 wl_find_listen_channel(cfg, request->ie,
2951 err = wl_cfgp2p_enable_discovery(cfg, ndev,
2952 request->ie, request->ie_len);
2954 if (unlikely(err)) {
2959 err = wl_do_escan(cfg, wiphy, ndev, request);
2967 cfg->scan_request = request;
2968 wl_set_drv_status(cfg, SCANNING, ndev);
2973 if (err == BCME_BUSY || err == BCME_NOTREADY) {
2974 WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
2976 } else if ((err == BCME_EPERM) && cfg->scan_suppressed) {
2977 WL_ERR(("Scan not permitted due to scan suppress\n"));
2980 /* For all other fw errors, use a generic error code as return
2981 * value to cfg80211 stack
2986 #define SCAN_EBUSY_RETRY_LIMIT 20
2987 if (err == -EBUSY) {
2988 if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
2989 struct ether_addr bssid;
2991 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2992 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
2993 #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
2995 WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
2996 wl_get_drv_status(cfg, SCANNING, ndev),
2997 wl_get_drv_status(cfg, SCAN_ABORTING, ndev),
2998 wl_get_drv_status(cfg, CONNECTING, ndev),
2999 wl_get_drv_status(cfg, CONNECTED, ndev),
3000 wl_get_drv_status(cfg, DISCONNECTING, ndev),
3001 wl_get_drv_status(cfg, AP_CREATING, ndev),
3002 wl_get_drv_status(cfg, AP_CREATED, ndev),
3003 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev),
3004 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev)));
3006 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
3007 if (dhdp->memdump_enabled) {
3008 dhdp->memdump_type = DUMP_TYPE_SCAN_BUSY;
3009 dhd_bus_mem_dump(dhdp);
3011 #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
3013 bzero(&bssid, sizeof(bssid));
3014 if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID,
3015 &bssid, ETHER_ADDR_LEN, false)) == 0)
3016 WL_ERR(("FW is connected with " MACDBG "/n",
3017 MAC2STRDBG(bssid.octet)));
3019 WL_ERR(("GET BSSID failed with %d\n", ret));
3021 wl_cfg80211_scan_abort(cfg);
3024 /* Hold the context for 400msec, so that 10 subsequent scans
3025 * can give a buffer of 4sec which is enough to
3026 * cover any on-going scan in the firmware
3028 WL_DBG(("Enforcing delay for EBUSY case \n"));
3035 wl_clr_drv_status(cfg, SCANNING, ndev);
3036 if (timer_pending(&cfg->scan_timeout))
3037 del_timer_sync(&cfg->scan_timeout);
3038 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
3039 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
3040 cfg->scan_request = NULL;
3041 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
3047 #if defined(WL_CFG80211_P2P_DEV_IF)
3048 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
3050 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
3051 struct cfg80211_scan_request *request)
3052 #endif /* WL_CFG80211_P2P_DEV_IF */
3055 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3056 #if defined(WL_CFG80211_P2P_DEV_IF)
3057 struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, cfg);
3058 #endif /* WL_CFG80211_P2P_DEV_IF */
3060 WL_DBG(("Enter\n"));
3061 RETURN_EIO_IF_NOT_UP(cfg);
3063 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
3064 if (wl_cfg_multip2p_operational(cfg)) {
3065 WL_ERR(("wlan0 scan failed, p2p devices are operational"));
3070 mutex_lock(&cfg->usr_sync);
3071 err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
3072 if (unlikely(err)) {
3073 WL_ERR(("scan error (%d)\n", err));
3075 mutex_unlock(&cfg->usr_sync);
3080 static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
3084 err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
3085 if (unlikely(err)) {
3086 WL_ERR(("Error (%d)\n", err));
3092 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
3096 err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
3097 if (unlikely(err)) {
3098 WL_ERR(("Error (%d)\n", err));
3104 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
3107 u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
3109 retry = htod32(retry);
3110 err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), true);
3111 if (unlikely(err)) {
3112 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
3118 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
3120 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
3121 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
3124 RETURN_EIO_IF_NOT_UP(cfg);
3125 WL_DBG(("Enter\n"));
3126 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
3127 (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
3128 cfg->conf->rts_threshold = wiphy->rts_threshold;
3129 err = wl_set_rts(ndev, cfg->conf->rts_threshold);
3133 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
3134 (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
3135 cfg->conf->frag_threshold = wiphy->frag_threshold;
3136 err = wl_set_frag(ndev, cfg->conf->frag_threshold);
3140 if (changed & WIPHY_PARAM_RETRY_LONG &&
3141 (cfg->conf->retry_long != wiphy->retry_long)) {
3142 cfg->conf->retry_long = wiphy->retry_long;
3143 err = wl_set_retry(ndev, cfg->conf->retry_long, true);
3147 if (changed & WIPHY_PARAM_RETRY_SHORT &&
3148 (cfg->conf->retry_short != wiphy->retry_short)) {
3149 cfg->conf->retry_short = wiphy->retry_short;
3150 err = wl_set_retry(ndev, cfg->conf->retry_short, false);
3159 channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
3161 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3163 wl_uint32_list_t *list;
3165 chanspec_t c = 0, ret_c = 0;
3166 int bw = 0, tmp_bw = 0;
3169 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
3170 #define LOCAL_BUF_SIZE 1024
3171 buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
3173 WL_ERR(("buf memory alloc failed\n"));
3176 list = (wl_uint32_list_t *)(void *)buf;
3177 list->count = htod32(WL_NUMCHANSPECS);
3178 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
3179 0, buf, LOCAL_BUF_SIZE, 0, &cfg->ioctl_buf_sync);
3180 if (err != BCME_OK) {
3181 WL_ERR(("get chanspecs failed with %d\n", err));
3184 for (i = 0; i < dtoh32(list->count); i++) {
3185 c = dtoh32(list->element[i]);
3186 if (channel <= CH_MAX_2G_CHANNEL) {
3187 if (!CHSPEC_IS20(c))
3189 if (channel == CHSPEC_CHANNEL(c)) {
3195 tmp_c = wf_chspec_ctlchan(c);
3196 tmp_bw = bw2cap[CHSPEC_BW(c) >> WL_CHANSPEC_BW_SHIFT];
3197 if (tmp_c != channel)
3200 if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
3210 #undef LOCAL_BUF_SIZE
3211 WL_INFORM(("return chanspec %x %d\n", ret_c, bw));
3216 wl_cfg80211_ibss_vsie_set_buffer(vndr_ie_setbuf_t *ibss_vsie, int ibss_vsie_len)
3218 struct bcm_cfg80211 *cfg = g_bcm_cfg;
3220 if (cfg != NULL && ibss_vsie != NULL) {
3221 if (cfg->ibss_vsie != NULL) {
3222 kfree(cfg->ibss_vsie);
3224 cfg->ibss_vsie = ibss_vsie;
3225 cfg->ibss_vsie_len = ibss_vsie_len;
3230 wl_cfg80211_ibss_vsie_free(struct bcm_cfg80211 *cfg)
3232 /* free & initiralize VSIE (Vendor Specific IE) */
3233 if (cfg->ibss_vsie != NULL) {
3234 kfree(cfg->ibss_vsie);
3235 cfg->ibss_vsie = NULL;
3236 cfg->ibss_vsie_len = 0;
3241 wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
3243 struct bcm_cfg80211 *cfg = g_bcm_cfg;
3244 char *ioctl_buf = NULL;
3247 if (cfg != NULL && cfg->ibss_vsie != NULL) {
3248 ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
3250 WL_ERR(("ioctl memory alloc failed\n"));
3254 /* change the command from "add" to "del" */
3255 strncpy(cfg->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
3256 cfg->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
3258 ret = wldev_iovar_setbuf(dev, "ie",
3259 cfg->ibss_vsie, cfg->ibss_vsie_len,
3260 ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
3261 WL_ERR(("ret=%d\n", ret));
3263 if (ret == BCME_OK) {
3264 /* free & initiralize VSIE */
3265 kfree(cfg->ibss_vsie);
3266 cfg->ibss_vsie = NULL;
3267 cfg->ibss_vsie_len = 0;
3278 #ifdef WLAIBSS_MCHAN
3279 static bcm_struct_cfgdev*
3280 bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name)
3283 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3284 struct wireless_dev* wdev = NULL;
3285 struct net_device *new_ndev = NULL;
3286 struct net_device *primary_ndev = NULL;
3288 wl_aibss_if_t aibss_if;
3289 wl_if_event_info *event = NULL;
3291 if (cfg->ibss_cfgdev != NULL) {
3292 WL_ERR(("IBSS interface %s already exists\n", name));
3296 WL_ERR(("Try to create IBSS interface %s\n", name));
3297 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3298 /* generate a new MAC address for the IBSS interface */
3299 get_primary_mac(cfg, &cfg->ibss_if_addr);
3300 cfg->ibss_if_addr.octet[4] ^= 0x40;
3301 memset(&aibss_if, sizeof(aibss_if), 0);
3302 memcpy(&aibss_if.addr, &cfg->ibss_if_addr, sizeof(aibss_if.addr));
3303 aibss_if.chspec = 0;
3304 aibss_if.len = sizeof(aibss_if);
3306 cfg->bss_pending_op = TRUE;
3307 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3308 err = wldev_iovar_setbuf(primary_ndev, "aibss_ifadd", &aibss_if,
3309 sizeof(aibss_if), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
3311 WL_ERR(("IOVAR aibss_ifadd failed with error %d\n", err));
3314 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3315 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3316 if (timeout <= 0 || cfg->bss_pending_op)
3319 event = &cfg->if_event_info;
3320 /* By calling wl_cfg80211_allocate_if (dhd_allocate_if eventually) we give the control
3321 * over this net_device interface to dhd_linux, hence the interface is managed by dhd_liux
3322 * and will be freed by dhd_detach unless it gets unregistered before that. The
3323 * wireless_dev instance new_ndev->ieee80211_ptr associated with this net_device will
3324 * be freed by wl_dealloc_netinfo
3326 new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, event->name,
3327 event->mac, event->bssidx, event->name);
3328 if (new_ndev == NULL)
3330 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
3333 wdev->wiphy = wiphy;
3334 wdev->iftype = NL80211_IFTYPE_ADHOC;
3335 wdev->netdev = new_ndev;
3336 new_ndev->ieee80211_ptr = wdev;
3337 SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
3339 /* rtnl lock must have been acquired, if this is not the case, wl_cfg80211_register_if
3340 * needs to be modified to take one parameter (bool need_rtnl_lock)
3343 if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK)
3346 wl_alloc_netinfo(cfg, new_ndev, wdev, WL_MODE_IBSS, PM_ENABLE, event->bssidx);
3347 cfg->ibss_cfgdev = ndev_to_cfgdev(new_ndev);
3348 WL_ERR(("IBSS interface %s created\n", new_ndev->name));
3349 return cfg->ibss_cfgdev;
3352 WL_ERR(("failed to create IBSS interface %s \n", name));
3353 cfg->bss_pending_op = FALSE;
3355 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
3362 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
3365 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3366 struct net_device *ndev = NULL;
3367 struct net_device *primary_ndev = NULL;
3370 if (!cfgdev || cfg->ibss_cfgdev != cfgdev || ETHER_ISNULLADDR(&cfg->ibss_if_addr.octet))
3372 ndev = (struct net_device *)cfgdev_to_ndev(cfg->ibss_cfgdev);
3373 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3375 cfg->bss_pending_op = TRUE;
3376 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3377 err = wldev_iovar_setbuf(primary_ndev, "aibss_ifdel", &cfg->ibss_if_addr,
3378 sizeof(cfg->ibss_if_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
3380 WL_ERR(("IOVAR aibss_ifdel failed with error %d\n", err));
3383 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3384 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3385 if (timeout <= 0 || cfg->bss_pending_op) {
3386 WL_ERR(("timeout in waiting IF_DEL event\n"));
3390 wl_cfg80211_remove_if(cfg, cfg->if_event_info.ifidx, ndev);
3391 cfg->ibss_cfgdev = NULL;
3395 cfg->bss_pending_op = FALSE;
3398 #endif /* WLAIBSS_MCHAN */
3401 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
3402 struct net_device *ndev, s32 bsscfg_idx,
3403 enum nl80211_iftype iface_type, s32 del, u8 *addr)
3405 wl_interface_create_t iface;
3407 wl_interface_info_t *info;
3409 bzero(&iface, sizeof(wl_interface_create_t));
3411 iface.ver = WL_INTERFACE_CREATE_VER;
3413 if (iface_type == NL80211_IFTYPE_AP)
3414 iface.flags = WL_INTERFACE_CREATE_AP;
3416 iface.flags = WL_INTERFACE_CREATE_STA;
3419 ret = wldev_iovar_setbuf(ndev, "interface_remove",
3420 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
3423 memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
3424 iface.flags |= WL_INTERFACE_MAC_USE;
3426 ret = wldev_iovar_getbuf(ndev, "interface_create",
3427 &iface, sizeof(wl_interface_create_t),
3428 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3431 info = (wl_interface_info_t *)cfg->ioctl_buf;
3432 WL_DBG(("wl interface create success!! bssidx:%d \n",
3434 ret = info->bsscfgidx;
3439 WL_ERR(("Interface %s failed!! ret %d\n",
3440 del ? "remove" : "create", ret));
3447 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
3448 struct net_device *ndev, s32 bsscfg_idx,
3449 enum nl80211_iftype iface_type, s32 del, u8 *addr)
3457 struct ether_addr ea;
3460 WL_INFORM(("iface_type:%d del:%d \n", iface_type, del));
3462 bzero(&bss_setbuf, sizeof(bss_setbuf));
3464 /* AP=3, STA=2, up=1, down=0, val=-1 */
3467 } else if (iface_type == NL80211_IFTYPE_AP) {
3469 WL_DBG(("Adding AP Interface \n"));
3471 } else if (iface_type == NL80211_IFTYPE_STATION) {
3472 WL_DBG(("Adding STA Interface \n"));
3475 WL_ERR((" add_del_bss NOT supported for IFACE type:0x%x", iface_type));
3479 bss_setbuf.cfg = htod32(bsscfg_idx);
3480 bss_setbuf.val = htod32(val);
3483 memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
3486 ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
3487 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3489 WL_ERR(("'bss %d' failed with %d\n", val, ret));
3494 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
3495 /* Create a Generic Network Interface and initialize it depending up on
3496 * the interface type
3499 wl_cfg80211_create_iface(struct wiphy *wiphy,
3500 enum nl80211_iftype iface_type,
3501 u8 *mac_addr, const char *name)
3503 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3504 struct net_device *new_ndev = NULL;
3505 struct net_device *primary_ndev = NULL;
3509 wl_if_event_info *event = NULL;
3510 struct wireless_dev *wdev = NULL;
3513 WL_DBG(("Enter\n"));
3516 WL_ERR(("Interface name not provided\n"));
3520 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3523 WL_ERR(("cfg=%p, primary_ndev=%p, ifname=%s\n", cfg, primary_ndev, name));
3526 /* If any scan is going on, abort it */
3527 if (wl_get_drv_status_all(cfg, SCANNING)) {
3528 int wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
3529 WL_ERR(("Scan in progress. Aborting the scan!\n"));
3530 wl_cfg80211_scan_abort(cfg);
3531 while (wl_get_drv_status_all(cfg, SCANNING) && wait_cnt) {
3532 WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
3534 OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
3536 if (!wait_cnt && wl_get_drv_status_all(cfg, SCANNING)) {
3537 WL_ERR(("Failed to abort scan\n"));
3542 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3543 if (likely(!mac_addr)) {
3544 /* Use primary MAC with the locally administered bit for the
3547 memcpy(addr, primary_ndev->dev_addr, ETH_ALEN);
3550 /* Use the application provided mac address (if any) */
3551 memcpy(addr, mac_addr, ETH_ALEN);
3554 if ((iface_type != NL80211_IFTYPE_STATION) && (iface_type != NL80211_IFTYPE_AP)) {
3555 WL_ERR(("IFACE type:%d not supported. STA "
3556 "or AP IFACE is only supported\n", iface_type));
3560 cfg->bss_pending_op = TRUE;
3561 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3563 /* De-initialize the p2p discovery interface, if operational */
3564 if (p2p_is_on(cfg)) {
3565 WL_DBG(("Disabling P2P Discovery Interface \n"));
3566 #ifdef WL_CFG80211_P2P_DEV_IF
3567 ret = wl_cfg80211_scan_stop(bcmcfg_to_p2p_wdev(cfg));
3569 ret = wl_cfg80211_scan_stop(cfg->p2p_net);
3571 if (unlikely(ret < 0)) {
3572 CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
3576 WL_ERR(("call wl_cfgp2p_disable_discovery()\n"));
3578 wl_cfgp2p_disable_discovery(cfg);
3579 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
3580 p2p_on(cfg) = false;
3584 * Intialize the firmware I/F.
3586 ret = wl_cfg80211_interface_ops(cfg, primary_ndev, bsscfg_idx,
3587 NL80211_IFTYPE_STATION, 0, addr);
3588 if (ret == BCME_UNSUPPORTED) {
3589 /* Use bssidx 1 by default */
3591 if ((ret = wl_cfg80211_add_del_bss(cfg, primary_ndev,
3592 bsscfg_idx, iface_type, 0, addr)) < 0) {
3595 } else if (ret < 0) {
3596 WL_ERR(("Interface create failed!! ret:%d \n", ret));
3603 WL_DBG(("Interface created!! bssidx:%d \n", bsscfg_idx));
3606 * Wait till the firmware send a confirmation event back.
3608 WL_DBG(("Wait for the FW I/F Event\n"));
3609 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3610 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3611 if (timeout <= 0 || cfg->bss_pending_op) {
3612 WL_ERR(("ADD_IF event, didn't come. Return \n"));
3617 * Since FW operation is successful,we can go ahead with the
3618 * the host interface creation.
3620 event = &cfg->if_event_info;
3621 new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx,
3622 (char*)name, addr, event->bssidx, event->name);
3624 WL_ERR(("I/F allocation failed! \n"));
3627 WL_DBG(("I/F allocation succeeded! ifidx:0x%x bssidx:0x%x \n",
3628 event->ifidx, event->bssidx));
3630 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
3632 WL_ERR(("wireless_dev alloc failed! \n"));
3636 wdev->wiphy = wiphy;
3637 wdev->iftype = iface_type;
3638 new_ndev->ieee80211_ptr = wdev;
3639 SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
3642 WL_ERR(("wdev=%p, new_ndev=%p\n", wdev, new_ndev));
3645 /* RTNL lock must have been acquired. */
3648 /* Set the locally administed mac addr, if not applied already */
3649 if (memcmp(addr, event->mac, ETH_ALEN) != 0) {
3650 ret = wldev_iovar_setbuf_bsscfg(primary_ndev, "cur_etheraddr",
3651 addr, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
3652 event->bssidx, &cfg->ioctl_buf_sync);
3653 if (unlikely(ret)) {
3654 WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
3657 memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
3660 if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev) != BCME_OK) {
3661 WL_ERR(("IFACE register failed \n"));
3665 /* Initialize with the station mode params */
3666 wl_alloc_netinfo(cfg, new_ndev, wdev,
3667 (iface_type == NL80211_IFTYPE_STATION) ?
3668 WL_MODE_BSS : WL_MODE_AP, PM_ENABLE, event->bssidx);
3669 cfg->bss_cfgdev = ndev_to_cfgdev(new_ndev);
3670 cfg->cfgdev_bssidx = event->bssidx;
3672 WL_DBG(("Host Network Interface for Secondary I/F created"));
3675 WL_ERR(("cfg->bss_cfgdev=%p\n", cfg->bss_cfgdev));
3678 return cfg->bss_cfgdev;
3681 cfg->bss_pending_op = FALSE;
3682 cfg->cfgdev_bssidx = -1;
3686 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev);
3689 WL_ERR(("failed!!!\n"));
3696 wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
3698 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3699 struct net_device *ndev = NULL;
3700 struct net_device *primary_ndev = NULL;
3705 enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
3707 WL_ERR(("Enter\n"));
3709 if (!cfg->bss_cfgdev)
3712 /* If any scan is going on, abort it */
3713 if (wl_get_drv_status_all(cfg, SCANNING)) {
3714 WL_ERR(("Scan in progress. Aborting the scan!\n"));
3715 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
3718 ndev = (struct net_device *)cfgdev_to_ndev(cfg->bss_cfgdev);
3719 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3722 WL_ERR(("cfg->bss_cfgdev=%p, ndev=%p, primary_ndev=%p\n",
3723 cfg->bss_cfgdev, ndev, primary_ndev));
3726 cfg->bss_pending_op = TRUE;
3727 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3729 /* Delete the firmware interface. "interface_remove" command
3730 * should go on the interface to be deleted
3732 ret = wl_cfg80211_interface_ops(cfg, ndev, cfg->cfgdev_bssidx,
3733 NL80211_IFTYPE_STATION, 1, NULL);
3734 if (ret == BCME_UNSUPPORTED) {
3735 if ((ret = wl_cfg80211_add_del_bss(cfg, ndev,
3736 bsscfg_idx, iface_type, true, NULL)) < 0) {
3737 WL_ERR(("DEL bss failed ret:%d \n", ret));
3740 } else if (ret < 0) {
3741 WL_ERR(("Interface DEL failed ret:%d \n", ret));
3745 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3746 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3747 if (timeout <= 0 || cfg->bss_pending_op) {
3748 WL_ERR(("timeout in waiting IF_DEL event\n"));
3752 ifidx = dhd_net2idx(((struct dhd_pub *)(cfg->pub))->info, ndev);
3753 wl_cfg80211_remove_if(cfg, ifidx, ndev);
3754 cfg->bss_cfgdev = NULL;
3755 cfg->cfgdev_bssidx = -1;
3756 cfg->bss_pending_op = FALSE;
3758 WL_ERR(("IF_DEL Done.\n"));
3762 #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
3765 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
3766 struct cfg80211_ibss_params *params)
3768 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3769 struct cfg80211_bss *bss;
3770 struct ieee80211_channel *chan;
3771 struct wl_join_params join_params;
3773 struct cfg80211_ssid ssid;
3776 size_t join_params_size;
3777 chanspec_t chanspec = 0;
3778 u32 param[2] = {0, 0};
3782 RETURN_EIO_IF_NOT_UP(cfg);
3783 WL_INFORM(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
3784 if (!params->ssid || params->ssid_len <= 0) {
3785 WL_ERR(("Invalid parameter\n"));
3788 #if defined(WL_CFG80211_P2P_DEV_IF)
3789 chan = params->chandef.chan;
3791 chan = params->channel;
3792 #endif /* WL_CFG80211_P2P_DEV_IF */
3794 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
3795 if (wl_get_drv_status(cfg, CONNECTED, dev)) {
3796 struct wlc_ssid *lssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
3797 u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
3798 u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
3799 if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
3800 (memcmp(params->ssid, lssid->SSID, lssid->SSID_len) == 0) &&
3801 (*channel == cfg->channel))) {
3802 WL_ERR(("Connection already existed to " MACDBG "\n",
3803 MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
3806 WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
3807 lssid->SSID, MAC2STRDBG(bssid)));
3810 /* remove the VSIE */
3811 wl_cfg80211_ibss_vsie_delete(dev);
3813 bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
3815 if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
3816 memcpy(ssid.ssid, params->ssid, params->ssid_len);
3817 ssid.ssid_len = params->ssid_len;
3820 (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
3826 } while (++scan_retry < WL_SCAN_RETRY_MAX);
3828 /* rtnl lock code is removed here. don't see why rtnl lock
3829 * needs to be released.
3832 /* wait 4 secons till scan done.... */
3833 schedule_timeout_interruptible(msecs_to_jiffies(4000));
3835 bss = cfg80211_get_ibss(wiphy, NULL,
3836 params->ssid, params->ssid_len);
3839 if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
3840 ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
3841 !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
3842 cfg->ibss_starter = false;
3843 WL_DBG(("Found IBSS\n"));
3845 cfg->ibss_starter = true;
3848 if (chan->band == IEEE80211_BAND_5GHZ)
3849 param[0] = WLC_BAND_5G;
3850 else if (chan->band == IEEE80211_BAND_2GHZ)
3851 param[0] = WLC_BAND_2G;
3852 err = wldev_iovar_getint(dev, "bw_cap", param);
3853 if (unlikely(err)) {
3854 WL_ERR(("Get bw_cap Failed (%d)\n", err));
3858 chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
3861 * Join with specific BSSID and cached SSID
3862 * If SSID is zero join based on BSSID only
3864 memset(&join_params, 0, sizeof(join_params));
3865 memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
3867 join_params.ssid.SSID_len = htod32(params->ssid_len);
3868 if (params->bssid) {
3869 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
3870 err = wldev_ioctl(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
3871 ETHER_ADDR_LEN, true);
3872 if (unlikely(err)) {
3873 WL_ERR(("Error (%d)\n", err));
3877 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
3878 wldev_iovar_setint(dev, "ibss_coalesce_allowed", IBSS_COALESCE_ALLOWED);
3880 if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
3881 scan_suppress = TRUE;
3882 /* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
3883 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
3884 &scan_suppress, sizeof(int), true);
3885 if (unlikely(err)) {
3886 WL_ERR(("Scan Suppress Setting Failed (%d)\n", err));
3891 join_params.params.chanspec_list[0] = chanspec;
3892 join_params.params.chanspec_num = 1;
3893 wldev_iovar_setint(dev, "chanspec", chanspec);
3894 join_params_size = sizeof(join_params);
3896 /* Disable Authentication, IBSS will add key if it required */
3897 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
3898 wldev_iovar_setint(dev, "wsec", 0);
3901 err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
3902 join_params_size, true);
3903 if (unlikely(err)) {
3904 WL_ERR(("Error (%d)\n", err));
3908 if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
3909 scan_suppress = FALSE;
3910 /* Reset the SCAN SUPPRESS Flag */
3911 err = wldev_ioctl(dev, WLC_SET_SCANSUPPRESS,
3912 &scan_suppress, sizeof(int), true);
3913 if (unlikely(err)) {
3914 WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err));
3918 wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
3919 wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
3920 cfg->rmc_event_seq = 0; /* initialize rmcfail sequence */
3924 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
3926 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3931 RETURN_EIO_IF_NOT_UP(cfg);
3934 WL_ERR(("Leave IBSS\n"));
3935 curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
3936 wl_set_drv_status(cfg, DISCONNECTING, dev);
3938 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
3939 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
3940 sizeof(scb_val_t), true);
3941 if (unlikely(err)) {
3942 wl_clr_drv_status(cfg, DISCONNECTING, dev);
3943 WL_ERR(("error(%d)\n", err));
3947 /* remove the VSIE */
3948 wl_cfg80211_ibss_vsie_delete(dev);
3955 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
3957 struct bcm_cfg80211 *cfg = g_bcm_cfg;
3958 struct wl_security *sec;
3963 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
3964 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
3968 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
3969 val = WPA_AUTH_PSK |
3970 WPA_AUTH_UNSPECIFIED;
3971 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
3972 val = WPA2_AUTH_PSK|
3973 WPA2_AUTH_UNSPECIFIED;
3975 val = WPA_AUTH_DISABLED;
3977 if (is_wps_conn(sme))
3978 val = WPA_AUTH_DISABLED;
3980 WL_DBG(("setting wpa_auth to 0x%0x\n", val));
3981 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
3982 if (unlikely(err)) {
3983 WL_ERR(("set wpa_auth failed (%d)\n", err));
3986 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
3987 sec->wpa_versions = sme->crypto.wpa_versions;
3993 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
3995 struct bcm_cfg80211 *cfg = g_bcm_cfg;
3996 struct wl_security *sec;
4001 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4002 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4006 switch (sme->auth_type) {
4007 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4008 val = WL_AUTH_OPEN_SYSTEM;
4009 WL_DBG(("open system\n"));
4011 case NL80211_AUTHTYPE_SHARED_KEY:
4012 val = WL_AUTH_SHARED_KEY;
4013 WL_DBG(("shared key\n"));
4015 case NL80211_AUTHTYPE_AUTOMATIC:
4016 val = WL_AUTH_OPEN_SHARED;
4017 WL_DBG(("automatic\n"));
4021 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
4025 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
4026 if (unlikely(err)) {
4027 WL_ERR(("set auth failed (%d)\n", err));
4030 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4031 sec->auth_type = sme->auth_type;
4036 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
4038 struct bcm_cfg80211 *cfg = g_bcm_cfg;
4039 struct wl_security *sec;
4047 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4048 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4052 if (sme->crypto.n_ciphers_pairwise) {
4053 switch (sme->crypto.ciphers_pairwise[0]) {
4054 case WLAN_CIPHER_SUITE_WEP40:
4055 case WLAN_CIPHER_SUITE_WEP104:
4058 case WLAN_CIPHER_SUITE_TKIP:
4059 pval = TKIP_ENABLED;
4061 case WLAN_CIPHER_SUITE_CCMP:
4062 case WLAN_CIPHER_SUITE_AES_CMAC:
4066 WL_ERR(("invalid cipher pairwise (%d)\n",
4067 sme->crypto.ciphers_pairwise[0]));
4071 if (sme->crypto.cipher_group) {
4072 switch (sme->crypto.cipher_group) {
4073 case WLAN_CIPHER_SUITE_WEP40:
4074 case WLAN_CIPHER_SUITE_WEP104:
4077 case WLAN_CIPHER_SUITE_TKIP:
4078 gval = TKIP_ENABLED;
4080 case WLAN_CIPHER_SUITE_CCMP:
4083 case WLAN_CIPHER_SUITE_AES_CMAC:
4087 WL_ERR(("invalid cipher group (%d)\n",
4088 sme->crypto.cipher_group));
4093 WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
4095 if (is_wps_conn(sme)) {
4097 err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
4099 /* WPS-2.0 allows no security */
4100 err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
4102 WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
4103 wsec_val = pval | gval;
4105 WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
4106 err = wldev_iovar_setint_bsscfg(dev, "wsec",
4109 if (unlikely(err)) {
4110 WL_ERR(("error (%d)\n", err));
4114 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4115 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
4116 sec->cipher_group = sme->crypto.cipher_group;
4122 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
4124 struct bcm_cfg80211 *cfg = g_bcm_cfg;
4125 struct wl_security *sec;
4130 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4131 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4135 if (sme->crypto.n_akm_suites) {
4136 err = wldev_iovar_getint(dev, "wpa_auth", &val);
4137 if (unlikely(err)) {
4138 WL_ERR(("could not get wpa_auth (%d)\n", err));
4141 if (val & (WPA_AUTH_PSK |
4142 WPA_AUTH_UNSPECIFIED)) {
4143 switch (sme->crypto.akm_suites[0]) {
4144 case WLAN_AKM_SUITE_8021X:
4145 val = WPA_AUTH_UNSPECIFIED;
4147 case WLAN_AKM_SUITE_PSK:
4151 WL_ERR(("invalid akm suite (0x%x)\n",
4152 sme->crypto.akm_suites[0]));
4155 } else if (val & (WPA2_AUTH_PSK |
4156 WPA2_AUTH_UNSPECIFIED)) {
4157 switch (sme->crypto.akm_suites[0]) {
4158 case WLAN_AKM_SUITE_8021X:
4159 val = WPA2_AUTH_UNSPECIFIED;
4161 case WLAN_AKM_SUITE_PSK:
4162 val = WPA2_AUTH_PSK;
4165 WL_ERR(("invalid akm suite (0x%x)\n",
4166 sme->crypto.akm_suites[0]));
4172 WL_DBG(("setting wpa_auth to 0x%x\n", val));
4174 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
4175 if (unlikely(err)) {
4176 WL_ERR(("could not set wpa_auth (%d)\n", err));
4180 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4181 sec->wpa_auth = sme->crypto.akm_suites[0];
4187 wl_set_set_sharedkey(struct net_device *dev,
4188 struct cfg80211_connect_params *sme)
4190 struct bcm_cfg80211 *cfg = g_bcm_cfg;
4191 struct wl_security *sec;
4192 struct wl_wsec_key key;
4197 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4198 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4202 WL_DBG(("key len (%d)\n", sme->key_len));
4204 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4205 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
4206 sec->wpa_versions, sec->cipher_pairwise));
4207 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
4208 NL80211_WPA_VERSION_2)) &&
4209 (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
4210 WLAN_CIPHER_SUITE_WEP104)))
4212 memset(&key, 0, sizeof(key));
4213 key.len = (u32) sme->key_len;
4214 key.index = (u32) sme->key_idx;
4215 if (unlikely(key.len > sizeof(key.data))) {
4216 WL_ERR(("Too long key length (%u)\n", key.len));
4219 memcpy(key.data, sme->key, key.len);
4220 key.flags = WL_PRIMARY_KEY;
4221 switch (sec->cipher_pairwise) {
4222 case WLAN_CIPHER_SUITE_WEP40:
4223 key.algo = CRYPTO_ALGO_WEP1;
4225 case WLAN_CIPHER_SUITE_WEP104:
4226 key.algo = CRYPTO_ALGO_WEP128;
4229 WL_ERR(("Invalid algorithm (%d)\n",
4230 sme->crypto.ciphers_pairwise[0]));
4233 /* Set the new key/index */
4234 WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
4235 key.len, key.index, key.algo));
4236 WL_DBG(("key \"%s\"\n", key.data));
4237 swap_key_from_BE(&key);
4238 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4239 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4240 if (unlikely(err)) {
4241 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4244 if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
4245 WL_DBG(("set auth_type to shared key\n"));
4246 val = WL_AUTH_SHARED_KEY; /* shared key */
4247 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
4248 if (unlikely(err)) {
4249 WL_ERR(("set auth failed (%d)\n", err));
4258 #if defined(ESCAN_RESULT_PATCH)
4259 static u8 connect_req_bssid[6];
4260 static u8 broad_bssid[6];
4261 #endif /* ESCAN_RESULT_PATCH */
4265 #if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
4266 static bool wl_get_chan_isvht80(struct net_device *net, dhd_pub_t *dhd)
4271 if (wldev_iovar_getint(net, "chanspec", (s32 *)&chanspec) == BCME_OK)
4272 chanspec = wl_chspec_driver_to_host(chanspec);
4274 isvht80 = chanspec & WL_CHANSPEC_BW_80;
4275 WL_INFO(("%s: chanspec(%x:%d)\n", __FUNCTION__, chanspec, isvht80));
4279 #endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
4282 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
4283 struct cfg80211_connect_params *sme)
4285 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4286 struct ieee80211_channel *chan = sme->channel;
4287 wl_extjoin_params_t *ext_join_params;
4288 struct wl_join_params join_params;
4289 size_t join_params_size;
4291 wpa_ie_fixed_t *wpa_ie;
4296 struct ether_addr bssid;
4303 #if defined(SUPPORT_RANDOM_MAC_SCAN)
4304 wl_cfg80211_set_random_mac(dev, FALSE);
4305 #endif /* SUPPORT_RANDOM_MAC_SCAN */
4307 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
4308 if (sme->channel_hint) {
4309 chan = sme->channel_hint;
4310 WL_DBG(("channel_hint (%d), channel_hint center_freq (%d)\n",
4311 ieee80211_frequency_to_channel(sme->channel_hint->center_freq),
4312 sme->channel_hint->center_freq));
4314 if (sme->bssid_hint) {
4315 sme->bssid = sme->bssid_hint;
4316 WL_DBG(("bssid_hint "MACDBG" \n", MAC2STRDBG(sme->bssid_hint)));
4318 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
4320 if (unlikely(!sme->ssid)) {
4321 WL_ERR(("Invalid ssid\n"));
4325 if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
4326 WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
4327 sme->ssid, sme->ssid_len));
4331 RETURN_EIO_IF_NOT_UP(cfg);
4334 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
4336 #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
4337 if (cfg->scan_request) {
4338 WL_TRACE_HW4(("Aborting the scan! \n"));
4339 wl_cfg80211_scan_abort(cfg);
4340 wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
4341 while (wl_get_drv_status(cfg, SCANNING, dev) && wait_cnt) {
4342 WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
4344 OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
4346 if (wl_get_drv_status(cfg, SCANNING, dev)) {
4347 wl_notify_escan_complete(cfg, dev, true, true);
4351 #ifdef WL_SCHED_SCAN
4352 if (cfg->sched_scan_req) {
4353 wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg));
4356 #if defined(ESCAN_RESULT_PATCH)
4358 memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
4360 bzero(connect_req_bssid, ETHER_ADDR_LEN);
4361 bzero(broad_bssid, ETHER_ADDR_LEN);
4363 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
4366 bzero(&bssid, sizeof(bssid));
4367 if (!wl_get_drv_status(cfg, CONNECTED, dev)&&
4368 (ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) {
4369 if (!ETHER_ISNULLADDR(&bssid)) {
4371 wl_set_drv_status(cfg, DISCONNECTING, dev);
4372 scbval.val = DOT11_RC_DISASSOC_LEAVING;
4373 memcpy(&scbval.ea, &bssid, ETHER_ADDR_LEN);
4374 scbval.val = htod32(scbval.val);
4376 WL_DBG(("drv status CONNECTED is not set, but connected in FW!" MACDBG "/n",
4377 MAC2STRDBG(bssid.octet)));
4378 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
4379 sizeof(scb_val_t), true);
4380 if (unlikely(err)) {
4381 wl_clr_drv_status(cfg, DISCONNECTING, dev);
4382 WL_ERR(("error (%d)\n", err));
4386 while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
4387 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
4393 WL_DBG(("Currently not associated!\n"));
4395 /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */
4397 while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
4398 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt));
4402 if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
4403 WL_ERR(("Force clear DISCONNECTING status!\n"));
4404 wl_clr_drv_status(cfg, DISCONNECTING, dev);
4409 bzero(&bssid, sizeof(bssid));
4410 if (!wl_get_drv_status(cfg, DISCONNECTING, dev))
4411 wl_update_prof(cfg, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
4413 if (p2p_is_on(cfg) && (dev != bcmcfg_to_prmry_ndev(cfg))) {
4414 /* we only allow to connect using virtual interface in case of P2P */
4415 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4416 WL_ERR(("Find p2p index from wdev(%p) failed\n",
4417 dev->ieee80211_ptr));
4420 wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
4421 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
4422 } else if (dev == bcmcfg_to_prmry_ndev(cfg)) {
4423 /* find the RSN_IE */
4424 if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
4425 DOT11_MNG_RSN_ID)) != NULL) {
4426 WL_DBG((" WPA2 IE is found\n"));
4428 /* find the WPA_IE */
4429 if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
4430 sme->ie_len)) != NULL) {
4431 WL_DBG((" WPA IE is found\n"));
4433 if (wpa_ie != NULL || wpa2_ie != NULL) {
4434 wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
4435 wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
4436 wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
4437 err = wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
4438 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
4439 if (unlikely(err)) {
4440 WL_ERR(("wpaie set error (%d)\n", err));
4444 err = wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
4445 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
4446 if (unlikely(err)) {
4447 WL_ERR(("wpaie set error (%d)\n", err));
4452 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4453 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4456 err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
4457 VNDR_IE_ASSOCREQ_FLAG, (const u8 *)sme->ie, sme->ie_len);
4458 if (unlikely(err)) {
4463 /* If RCC is not enabled, use the channel provided by userspace */
4464 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
4466 WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg->channel,
4467 chan->center_freq, chan_cnt));
4470 * No channel information from user space. if RCC is enabled, the RCC
4471 * would prepare the channel list, else no channel would be provided
4472 * and firmware would need to do a full channel scan.
4474 WL_DBG(("No channel info from user space\n"));
4477 WL_DBG(("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len));
4478 WL_DBG(("3. set wpa version \n"));
4479 err = wl_set_wpa_version(dev, sme);
4480 if (unlikely(err)) {
4481 WL_ERR(("Invalid wpa_version\n"));
4484 err = wl_set_auth_type(dev, sme);
4485 if (unlikely(err)) {
4486 WL_ERR(("Invalid auth type\n"));
4490 err = wl_set_set_cipher(dev, sme);
4491 if (unlikely(err)) {
4492 WL_ERR(("Invalid ciper\n"));
4496 err = wl_set_key_mgmt(dev, sme);
4497 if (unlikely(err)) {
4498 WL_ERR(("Invalid key mgmt\n"));
4502 err = wl_set_set_sharedkey(dev, sme);
4503 if (unlikely(err)) {
4504 WL_ERR(("Invalid shared key\n"));
4509 * Join with specific BSSID and cached SSID
4510 * If SSID is zero join based on BSSID only
4512 join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
4513 chan_cnt * sizeof(chanspec_t);
4514 ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
4515 if (ext_join_params == NULL) {
4517 wl_clr_drv_status(cfg, CONNECTING, dev);
4520 ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
4521 memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
4522 wl_update_prof(cfg, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
4523 ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
4524 /* increate dwell time to receive probe response or detect Beacon
4525 * from target AP at a noisy air only during connect command
4527 ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
4528 ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
4529 /* Set up join scan parameters */
4530 ext_join_params->scan.scan_type = -1;
4531 ext_join_params->scan.nprobes = chan_cnt ?
4532 (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
4533 ext_join_params->scan.home_time = -1;
4536 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
4538 memcpy(&ext_join_params->assoc.bssid, ðer_bcast, ETH_ALEN);
4539 ext_join_params->assoc.chanspec_num = chan_cnt;
4543 * Use the channel provided by userspace
4545 u16 channel, band, bw, ctl_sb;
4547 channel = cfg->channel;
4548 band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
4549 : WL_CHANSPEC_BAND_5G;
4551 /* Get min_bw set for the interface */
4552 bw = wl_cfg80211_ulb_get_min_bw_chspec(dev->ieee80211_ptr, bssidx);
4553 if (bw == INVCHANSPEC) {
4554 WL_ERR(("Invalid chanspec \n"));
4555 kfree(ext_join_params);
4559 ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
4560 chspec = (channel | band | bw | ctl_sb);
4561 ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
4562 ext_join_params->assoc.chanspec_list[0] |= chspec;
4563 ext_join_params->assoc.chanspec_list[0] =
4564 wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
4567 ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
4568 if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
4569 WL_INFORM(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
4570 ext_join_params->ssid.SSID_len));
4572 wl_set_drv_status(cfg, CONNECTING, dev);
4574 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4575 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4576 kfree(ext_join_params);
4579 err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
4580 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4582 if (cfg->rcc_enabled) {
4583 printf("Connecting with " MACDBG " ssid \"%s\", len (%d) with rcc channels \n\n",
4584 MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
4585 ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len);
4587 printf("Connecting with " MACDBG " ssid \"%s\", len (%d) channel=%d\n\n",
4588 MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
4589 ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, cfg->channel);
4592 kfree(ext_join_params);
4594 wl_clr_drv_status(cfg, CONNECTING, dev);
4595 if (err == BCME_UNSUPPORTED) {
4596 WL_DBG(("join iovar is not supported\n"));
4599 WL_ERR(("error (%d)\n", err));
4606 memset(&join_params, 0, sizeof(join_params));
4607 join_params_size = sizeof(join_params.ssid);
4609 join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
4610 memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
4611 join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
4612 wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
4614 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
4616 memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN);
4618 if (wl_ch_to_chanspec(dev, cfg->channel, &join_params, &join_params_size) < 0) {
4619 WL_ERR(("Invalid chanspec\n"));
4623 WL_DBG(("join_param_size %zu\n", join_params_size));
4625 if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
4626 WL_INFORM(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
4627 join_params.ssid.SSID_len));
4629 wl_set_drv_status(cfg, CONNECTING, dev);
4630 err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, true);
4632 WL_ERR(("error (%d)\n", err));
4633 wl_clr_drv_status(cfg, CONNECTING, dev);
4640 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
4643 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4648 #ifdef CUSTOM_SET_CPUCORE
4649 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
4650 #endif /* CUSTOM_SET_CPUCORE */
4651 WL_ERR(("Reason %d\n", reason_code));
4652 RETURN_EIO_IF_NOT_UP(cfg);
4653 act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
4654 curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
4655 #ifdef ESCAN_RESULT_PATCH
4656 if (wl_get_drv_status(cfg, CONNECTING, dev) && curbssid &&
4657 (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0)) {
4658 WL_ERR(("Disconnecting from connecting device: " MACDBG "\n",
4659 MAC2STRDBG(curbssid)));
4662 #endif /* ESCAN_RESULT_PATCH */
4666 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
4668 #if !defined(ESCAN_RESULT_PATCH)
4669 /* Let scan aborted by F/W */
4670 if (cfg->scan_request) {
4671 WL_TRACE_HW4(("Aborting the scan! \n"));
4672 wl_notify_escan_complete(cfg, dev, true, true);
4674 #endif /* ESCAN_RESULT_PATCH */
4675 if (wl_get_drv_status(cfg, CONNECTING, dev) ||
4676 wl_get_drv_status(cfg, CONNECTED, dev)) {
4677 wl_set_drv_status(cfg, DISCONNECTING, dev);
4678 scbval.val = reason_code;
4679 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
4680 scbval.val = htod32(scbval.val);
4681 err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
4682 sizeof(scb_val_t), true);
4683 if (unlikely(err)) {
4684 wl_clr_drv_status(cfg, DISCONNECTING, dev);
4685 WL_ERR(("error (%d)\n", err));
4688 #if defined(BCM4358_CHIP)
4689 WL_ERR(("Wait for complete of disconnecting \n"));
4691 #endif /* BCM4358_CHIP */
4694 #ifdef CUSTOM_SET_CPUCORE
4695 /* set default cpucore */
4696 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
4697 dhd->chan_isvht80 &= ~DHD_FLAG_STA_MODE;
4698 if (!(dhd->chan_isvht80))
4699 dhd_set_cpucore(dhd, FALSE);
4701 #endif /* CUSTOM_SET_CPUCORE */
4707 #if defined(WL_CFG80211_P2P_DEV_IF)
4708 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
4709 enum nl80211_tx_power_setting type, s32 mbm)
4711 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
4712 enum nl80211_tx_power_setting type, s32 dbm)
4713 #endif /* WL_CFG80211_P2P_DEV_IF */
4716 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4717 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
4719 #if defined(WL_CFG80211_P2P_DEV_IF)
4720 s32 dbm = MBM_TO_DBM(mbm);
4721 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
4722 defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
4723 dbm = MBM_TO_DBM(dbm);
4724 #endif /* WL_CFG80211_P2P_DEV_IF */
4726 RETURN_EIO_IF_NOT_UP(cfg);
4728 case NL80211_TX_POWER_AUTOMATIC:
4730 case NL80211_TX_POWER_LIMITED:
4732 WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
4736 case NL80211_TX_POWER_FIXED:
4738 WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
4744 err = wl_set_tx_power(ndev, type, dbm);
4745 if (unlikely(err)) {
4746 WL_ERR(("error (%d)\n", err));
4750 cfg->conf->tx_power = dbm;
4756 #if defined(WL_CFG80211_P2P_DEV_IF)
4757 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
4758 struct wireless_dev *wdev, s32 *dbm)
4760 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
4761 #endif /* WL_CFG80211_P2P_DEV_IF */
4763 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4764 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
4767 RETURN_EIO_IF_NOT_UP(cfg);
4768 err = wl_get_tx_power(ndev, dbm);
4770 WL_ERR(("error (%d)\n", err));
4776 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
4777 u8 key_idx, bool unicast, bool multicast)
4779 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4785 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4786 WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
4790 WL_DBG(("key index (%d)\n", key_idx));
4791 RETURN_EIO_IF_NOT_UP(cfg);
4792 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
4793 if (unlikely(err)) {
4794 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
4797 if (wsec == WEP_ENABLED) {
4798 /* Just select a new current key */
4799 index = (u32) key_idx;
4800 index = htod32(index);
4801 err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
4802 sizeof(index), true);
4803 if (unlikely(err)) {
4804 WL_ERR(("error (%d)\n", err));
4811 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
4812 u8 key_idx, const u8 *mac_addr, struct key_params *params)
4814 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4815 struct wl_wsec_key key;
4818 s32 mode = wl_get_mode_by_netdev(cfg, dev);
4820 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4821 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4824 memset(&key, 0, sizeof(key));
4825 key.index = (u32) key_idx;
4827 if (!ETHER_ISMULTI(mac_addr))
4828 memcpy((char *)&key.ea, (const void *)mac_addr, ETHER_ADDR_LEN);
4829 key.len = (u32) params->key_len;
4831 /* check for key index change */
4834 swap_key_from_BE(&key);
4835 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4836 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4837 if (unlikely(err)) {
4838 WL_ERR(("key delete error (%d)\n", err));
4842 if (key.len > sizeof(key.data)) {
4843 WL_ERR(("Invalid key length (%d)\n", key.len));
4846 WL_DBG(("Setting the key index %d\n", key.index));
4847 memcpy(key.data, params->key, key.len);
4849 if ((mode == WL_MODE_BSS) &&
4850 (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
4852 memcpy(keybuf, &key.data[24], sizeof(keybuf));
4853 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
4854 memcpy(&key.data[16], keybuf, sizeof(keybuf));
4857 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
4858 if (params->seq && params->seq_len == 6) {
4861 ivptr = (u8 *) params->seq;
4862 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
4863 (ivptr[3] << 8) | ivptr[2];
4864 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
4865 key.iv_initialized = true;
4868 switch (params->cipher) {
4869 case WLAN_CIPHER_SUITE_WEP40:
4870 key.algo = CRYPTO_ALGO_WEP1;
4871 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
4873 case WLAN_CIPHER_SUITE_WEP104:
4874 key.algo = CRYPTO_ALGO_WEP128;
4875 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
4877 case WLAN_CIPHER_SUITE_TKIP:
4878 key.algo = CRYPTO_ALGO_TKIP;
4879 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
4881 case WLAN_CIPHER_SUITE_AES_CMAC:
4882 key.algo = CRYPTO_ALGO_AES_CCM;
4883 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
4885 case WLAN_CIPHER_SUITE_CCMP:
4886 key.algo = CRYPTO_ALGO_AES_CCM;
4887 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
4890 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
4893 swap_key_from_BE(&key);
4894 /* need to guarantee EAPOL 4/4 send out before set key */
4895 dhd_wait_pend8021x(dev);
4896 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
4897 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
4898 if (unlikely(err)) {
4899 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
4907 wl_cfg80211_enable_roam_offload(struct net_device *dev, int enable)
4910 wl_eventmsg_buf_t ev_buf;
4912 if (dev != bcmcfg_to_prmry_ndev(g_bcm_cfg)) {
4913 /* roam offload is only for the primary device */
4916 err = wldev_iovar_setint(dev, "roam_offload", enable);
4921 err = wldev_iovar_setint(dev, "sup_wpa_tmo", IDSUP_4WAY_HANDSHAKE_TIMEOUT);
4923 WL_INFORM(("Setting 'sup_wpa_tmo' failed, err=%d\n", err));
4927 bzero(&ev_buf, sizeof(wl_eventmsg_buf_t));
4928 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
4929 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
4930 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
4931 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
4932 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
4933 err = wl_cfg80211_apply_eventbuffer(dev, g_bcm_cfg, &ev_buf);
4935 g_bcm_cfg->roam_offload = enable;
4940 #if defined(WL_VIRTUAL_APSTA)
4942 wl_cfg80211_interface_create(struct net_device *dev, char *name)
4944 struct bcm_cfg80211 *cfg = g_bcm_cfg;
4945 bcm_struct_cfgdev *new_cfgdev;
4947 new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
4948 NL80211_IFTYPE_STATION, NULL, name);
4953 WL_DBG(("Iface %s created successfuly\n", name));
4959 wl_cfg80211_interface_delete(struct net_device *dev, char *name)
4961 struct bcm_cfg80211 *cfg = g_bcm_cfg;
4962 struct net_info *iter, *next;
4963 int err = BCME_ERROR;
4969 for_each_ndev(cfg, iter, next) {
4971 if (strcmp(iter->ndev->name, name) == 0) {
4972 err = wl_cfg80211_del_iface(cfg->wdev->wiphy, cfg->bss_cfgdev);
4978 WL_DBG(("Iface %s deleted successfuly", name));
4982 #endif /* defined (WL_VIRTUAL_APSTA) */
4985 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
4986 u8 key_idx, bool pairwise, const u8 *mac_addr,
4987 struct key_params *params)
4989 struct wl_wsec_key key;
4995 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4996 s32 mode = wl_get_mode_by_netdev(cfg, dev);
4997 WL_DBG(("key index (%d)\n", key_idx));
4998 RETURN_EIO_IF_NOT_UP(cfg);
5000 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5001 WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
5006 ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
5007 (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
5008 wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
5011 memset(&key, 0, sizeof(key));
5012 /* Clear any buffered wep key */
5013 memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
5015 key.len = (u32) params->key_len;
5016 key.index = (u32) key_idx;
5018 if (unlikely(key.len > sizeof(key.data))) {
5019 WL_ERR(("Too long key length (%u)\n", key.len));
5022 memcpy(key.data, params->key, key.len);
5024 key.flags = WL_PRIMARY_KEY;
5025 switch (params->cipher) {
5026 case WLAN_CIPHER_SUITE_WEP40:
5027 key.algo = CRYPTO_ALGO_WEP1;
5029 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
5031 case WLAN_CIPHER_SUITE_WEP104:
5032 key.algo = CRYPTO_ALGO_WEP128;
5034 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
5036 case WLAN_CIPHER_SUITE_TKIP:
5037 key.algo = CRYPTO_ALGO_TKIP;
5039 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
5040 if (mode == WL_MODE_BSS) {
5041 bcopy(&key.data[24], keybuf, sizeof(keybuf));
5042 bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
5043 bcopy(keybuf, &key.data[16], sizeof(keybuf));
5045 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
5047 case WLAN_CIPHER_SUITE_AES_CMAC:
5048 key.algo = CRYPTO_ALGO_AES_CCM;
5050 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
5052 case WLAN_CIPHER_SUITE_CCMP:
5053 key.algo = CRYPTO_ALGO_AES_CCM;
5055 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
5058 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
5062 /* Set the new key/index */
5063 if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
5064 WL_ERR(("IBSS KEY setted\n"));
5065 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
5067 swap_key_from_BE(&key);
5068 if ((params->cipher == WLAN_CIPHER_SUITE_WEP40) ||
5069 (params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
5071 * For AP role, since we are doing a wl down before bringing up AP,
5072 * the plumbed keys will be lost. So for AP once we bring up AP, we
5073 * need to plumb keys again. So buffer the keys for future use. This
5074 * is more like a WAR. If firmware later has the capability to do
5075 * interface upgrade without doing a "wl down" and "wl apsta 0", then
5076 * this will not be required.
5078 WL_DBG(("Buffering WEP Keys \n"));
5079 memcpy(&cfg->wep_key, &key, sizeof(struct wl_wsec_key));
5081 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
5082 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5083 if (unlikely(err)) {
5084 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
5089 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
5090 if (unlikely(err)) {
5091 WL_ERR(("get wsec error (%d)\n", err));
5096 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
5097 if (unlikely(err)) {
5098 WL_ERR(("set wsec error (%d)\n", err));
5106 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
5107 u8 key_idx, bool pairwise, const u8 *mac_addr)
5109 struct wl_wsec_key key;
5110 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5114 WL_DBG(("Enter. key_idx: %d\n", key_idx));
5115 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5116 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5120 if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
5123 RETURN_EIO_IF_NOT_UP(cfg);
5124 memset(&key, 0, sizeof(key));
5126 key.flags = WL_PRIMARY_KEY;
5127 key.algo = CRYPTO_ALGO_OFF;
5128 key.index = (u32) key_idx;
5130 /* Set the new key/index */
5131 swap_key_from_BE(&key);
5132 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
5133 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5134 if (unlikely(err)) {
5135 if (err == -EINVAL) {
5136 if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
5137 /* we ignore this key index in this case */
5138 WL_DBG(("invalid key index (%d)\n", key_idx));
5141 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
5149 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
5150 u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
5151 void (*callback) (void *cookie, struct key_params * params))
5153 struct key_params params;
5154 struct wl_wsec_key key;
5155 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5156 struct wl_security *sec;
5161 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5162 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5165 WL_DBG(("key index (%d)\n", key_idx));
5166 RETURN_EIO_IF_NOT_UP(cfg);
5167 memset(&key, 0, sizeof(key));
5168 key.index = key_idx;
5169 swap_key_to_BE(&key);
5170 memset(¶ms, 0, sizeof(params));
5171 params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
5172 memcpy((void *)params.key, key.data, params.key_len);
5174 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
5175 if (unlikely(err)) {
5176 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
5179 switch (WSEC_ENABLED(wsec)) {
5181 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
5182 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
5183 params.cipher = WLAN_CIPHER_SUITE_WEP40;
5184 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
5185 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
5186 params.cipher = WLAN_CIPHER_SUITE_WEP104;
5187 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
5191 params.cipher = WLAN_CIPHER_SUITE_TKIP;
5192 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
5195 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
5196 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
5199 WL_ERR(("Invalid algo (0x%x)\n", wsec));
5203 callback(cookie, ¶ms);
5208 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
5209 struct net_device *dev, u8 key_idx)
5211 WL_INFORM(("Not supported\n"));
5215 #if defined(RSSIAVG)
5216 static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
5217 static wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
5219 #if defined(BSSCACHE)
5220 static wl_bss_cache_ctrl_t g_bss_cache_ctrl;
5224 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
5225 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5226 const u8 *mac, struct station_info *sinfo)
5228 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
5229 u8 *mac, struct station_info *sinfo)
5232 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5238 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
5239 s8 eabuf[ETHER_ADDR_STR_LEN];
5241 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
5242 bool fw_assoc_state = FALSE;
5243 u32 dhd_assoc_state = 0;
5244 static int err_cnt = 0;
5246 RETURN_EIO_IF_NOT_UP(cfg);
5247 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
5248 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
5249 ETHER_ADDR_LEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
5251 WL_ERR(("GET STA INFO failed, %d\n", err));
5254 sinfo->filled = STA_INFO_BIT(INFO_INACTIVE_TIME);
5255 sta = (sta_info_t *)cfg->ioctl_buf;
5256 sta->len = dtoh16(sta->len);
5257 sta->cap = dtoh16(sta->cap);
5258 sta->flags = dtoh32(sta->flags);
5259 sta->idle = dtoh32(sta->idle);
5260 sta->in = dtoh32(sta->in);
5261 sinfo->inactive_time = sta->idle * 1000;
5262 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
5263 if (sta->flags & WL_STA_ASSOC) {
5264 sinfo->filled |= STA_INFO_BIT(INFO_CONNECTED_TIME);
5265 sinfo->connected_time = sta->in;
5267 WL_INFORM(("STA %s : idle time : %d sec, connected time :%d ms\n",
5268 bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
5271 } else if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_BSS ||
5272 wl_get_mode_by_netdev(cfg, dev) == WL_MODE_IBSS) {
5273 get_pktcnt_t pktcnt;
5276 if (cfg->roam_offload) {
5277 struct ether_addr bssid;
5278 err = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
5280 WL_ERR(("Failed to get current BSSID\n"));
5282 if (!ETHER_ISNULLADDR(&bssid.octet) &&
5283 memcmp(mac, &bssid.octet, ETHER_ADDR_LEN) != 0) {
5284 /* roaming is detected */
5285 err = wl_cfg80211_delayed_roam(cfg, dev, &bssid);
5287 WL_ERR(("Failed to handle the delayed roam, "
5289 mac = (u8 *)bssid.octet;
5293 dhd_assoc_state = wl_get_drv_status(cfg, CONNECTED, dev);
5294 fw_assoc_state = dhd_is_associated(dhd, 0, &err);
5295 if (!dhd_assoc_state || !fw_assoc_state) {
5296 WL_ERR(("NOT assoc\n"));
5297 if (err == -ERESTARTSYS)
5299 if (!dhd_assoc_state) {
5300 WL_TRACE_HW4(("drv state is not connected \n"));
5302 if (!fw_assoc_state) {
5303 WL_TRACE_HW4(("fw state is not associated \n"));
5305 /* Disconnect due to fw is not associated for FW_ASSOC_WATCHDOG_TIME ms.
5306 * 'err == 0' of dhd_is_associated() and '!fw_assoc_state'
5307 * means that BSSID is null.
5309 if (dhd_assoc_state && !fw_assoc_state && !err) {
5310 if (!fw_assoc_watchdog_started) {
5311 fw_assoc_watchdog_ms = OSL_SYSUPTIME();
5312 fw_assoc_watchdog_started = TRUE;
5313 WL_TRACE_HW4(("fw_assoc_watchdog_started \n"));
5315 if (OSL_SYSUPTIME() - fw_assoc_watchdog_ms >
5316 FW_ASSOC_WATCHDOG_TIME) {
5317 fw_assoc_watchdog_started = FALSE;
5319 WL_TRACE_HW4(("fw is not associated for %d ms \n",
5320 (OSL_SYSUPTIME() - fw_assoc_watchdog_ms)));
5321 goto get_station_err;
5328 fw_assoc_watchdog_started = FALSE;
5329 curmacp = wl_read_prof(cfg, dev, WL_PROF_BSSID);
5330 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
5331 WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
5332 MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
5335 /* Report the current tx rate */
5336 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
5338 WL_ERR(("Could not get rate (%d)\n", err));
5340 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5343 rate = dtoh32(rate);
5344 sinfo->filled |= STA_INFO_BIT(INFO_TX_BITRATE);
5345 sinfo->txrate.legacy = rate * 5;
5346 WL_DBG(("Rate %d Mbps\n", (rate / 2)));
5347 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5348 rxpktglom = ((rate/2) > 150) ? 20 : 10;
5350 if (maxrxpktglom != rxpktglom) {
5351 maxrxpktglom = rxpktglom;
5352 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
5354 err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
5355 (char*)&maxrxpktglom, 4, cfg->ioctl_buf,
5356 WLC_IOCTL_MAXLEN, NULL);
5358 WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
5364 memset(&scb_val, 0, sizeof(scb_val));
5366 err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
5367 sizeof(scb_val_t), false);
5369 WL_ERR(("Could not get rssi (%d)\n", err));
5370 goto get_station_err;
5372 rssi = dtoh32(scb_val.val);
5373 #if defined(RSSIAVG)
5374 err = wl_update_connected_rssi_cache(dev, &g_connected_rssi_cache_ctrl, &rssi);
5376 WL_ERR(("Could not get rssi (%d)\n", err));
5377 goto get_station_err;
5379 wl_delete_dirty_rssi_cache(&g_connected_rssi_cache_ctrl);
5380 wl_reset_rssi_cache(&g_connected_rssi_cache_ctrl);
5382 #if defined(RSSIOFFSET)
5383 rssi = wl_update_rssi_offset(dev, rssi);
5385 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
5386 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
5387 rssi = MIN(rssi, RSSI_MAXVAL);
5389 sinfo->filled |= STA_INFO_BIT(INFO_SIGNAL);
5390 sinfo->signal = rssi;
5391 WL_DBG(("RSSI %d dBm\n", rssi));
5392 err = wldev_ioctl(dev, WLC_GET_PKTCNTS, &pktcnt,
5393 sizeof(pktcnt), false);
5395 sinfo->filled |= (STA_INFO_BIT(INFO_RX_PACKETS) |
5396 STA_INFO_BIT(INFO_RX_DROP_MISC) |
5397 STA_INFO_BIT(INFO_TX_PACKETS) |
5398 STA_INFO_BIT(INFO_TX_FAILED));
5399 sinfo->rx_packets = pktcnt.rx_good_pkt;
5400 sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
5401 sinfo->tx_packets = pktcnt.tx_good_pkt;
5402 sinfo->tx_failed = pktcnt.tx_bad_pkt;
5409 if (err_cnt >= 3 && (err != -ERESTARTSYS)) {
5410 /* Disconnect due to zero BSSID or error to get RSSI */
5411 WL_ERR(("force cfg80211_disconnected: %d\n", err));
5412 wl_clr_drv_status(cfg, CONNECTED, dev);
5413 CFG80211_DISCONNECTED(dev, 0, NULL, 0, false, GFP_KERNEL);
5418 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg, dev)));
5425 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
5426 bool enabled, s32 timeout)
5430 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5431 struct net_info *_net_info = wl_get_netinfo_by_netdev(cfg, dev);
5432 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
5434 RETURN_EIO_IF_NOT_UP(cfg);
5435 WL_DBG(("Enter\n"));
5436 if (cfg->p2p_net == dev || _net_info == NULL ||
5437 !wl_get_drv_status(cfg, CONNECTED, dev) ||
5438 (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_BSS &&
5439 wl_get_mode_by_netdev(cfg, dev) != WL_MODE_IBSS)) {
5442 /* Enlarge pm_enable_work */
5443 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_LONG);
5445 pm = enabled ? PM_FAST : PM_OFF;
5446 if (_net_info->pm_block) {
5447 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
5448 dev->name, _net_info->pm_block));
5451 if (enabled && dhd_conf_get_pm(dhd) >= 0)
5452 pm = dhd_conf_get_pm(dhd);
5454 WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
5455 err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true);
5456 if (unlikely(err)) {
5458 WL_DBG(("net_device is not ready yet\n"));
5460 WL_ERR(("error (%d)\n", err));
5463 wl_cfg80211_update_power_mode(dev);
5467 void wl_cfg80211_update_power_mode(struct net_device *dev)
5471 err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), true);
5473 WL_ERR(("%s:error (%d)\n", __FUNCTION__, err));
5474 else if (pm != -1 && dev->ieee80211_ptr)
5475 dev->ieee80211_ptr->ps = (pm == PM_OFF) ? false : true;
5478 void wl_cfg80211_set_passive_scan(struct net_device *dev, char *command)
5480 struct bcm_cfg80211 *cfg = g_bcm_cfg;
5482 if (strcmp(command, "SCAN-ACTIVE") == 0) {
5483 cfg->active_scan = 1;
5484 } else if (strcmp(command, "SCAN-PASSIVE") == 0) {
5485 cfg->active_scan = 0;
5487 WL_ERR(("Unknown command \n"));
5490 static __used u32 wl_find_msb(u16 bit16)
5494 if (bit16 & 0xff00) {
5517 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
5519 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5520 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5523 if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
5524 WL_INFORM(("device is not ready\n"));
5532 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
5533 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
5535 wl_cfg80211_suspend(struct wiphy *wiphy)
5536 #endif /* KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES */
5539 #ifdef DHD_CLEAR_ON_SUSPEND
5540 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5541 struct net_info *iter, *next;
5542 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5543 unsigned long flags;
5544 if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
5545 WL_INFORM(("device is not ready : status (%d)\n",
5549 for_each_ndev(cfg, iter, next) {
5550 /* p2p discovery iface doesn't have a ndev associated with it (for kernel > 3.8) */
5552 wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
5554 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
5555 if (cfg->scan_request) {
5556 cfg80211_scan_done(cfg->scan_request, true);
5557 cfg->scan_request = NULL;
5559 for_each_ndev(cfg, iter, next) {
5561 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
5562 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
5565 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
5566 for_each_ndev(cfg, iter, next) {
5568 if (wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
5569 wl_bss_connect_done(cfg, iter->ndev, NULL, NULL, false);
5573 #endif /* DHD_CLEAR_ON_SUSPEND */
5580 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
5584 struct bcm_cfg80211 *cfg = g_bcm_cfg;
5585 struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
5588 printf("pmk_list is NULL\n");
5591 /* pmk list is supported only for STA interface i.e. primary interface
5592 * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
5594 if (primary_dev != dev) {
5595 WL_INFORM(("Not supporting Flushing pmklist on virtual"
5596 " interfaces than primary interface\n"));
5600 WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
5601 for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
5602 WL_DBG(("PMKID[%d]: %pM =\n", i,
5603 &pmk_list->pmkids.pmkid[i].BSSID));
5604 for (j = 0; j < WPA2_PMKID_LEN; j++) {
5605 WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
5609 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
5610 sizeof(*pmk_list), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
5617 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
5618 struct cfg80211_pmksa *pmksa)
5620 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5624 RETURN_EIO_IF_NOT_UP(cfg);
5625 for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
5626 if (!memcmp(pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
5629 if (i < WL_NUM_PMKIDS_MAX) {
5630 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
5632 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
5634 if (i == cfg->pmk_list->pmkids.npmkid)
5635 cfg->pmk_list->pmkids.npmkid++;
5639 WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
5640 &cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].BSSID));
5641 for (i = 0; i < WPA2_PMKID_LEN; i++) {
5643 cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].
5647 err = wl_update_pmklist(dev, cfg->pmk_list, err);
5653 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
5654 struct cfg80211_pmksa *pmksa)
5656 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5658 struct _pmkid_list pmkid = {.npmkid = 0};
5662 RETURN_EIO_IF_NOT_UP(cfg);
5663 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
5664 memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
5666 WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
5667 &pmkid.pmkid[0].BSSID));
5668 for (i = 0; i < WPA2_PMKID_LEN; i++) {
5669 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
5672 for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
5674 (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
5678 if ((cfg->pmk_list->pmkids.npmkid > 0) &&
5679 (i < cfg->pmk_list->pmkids.npmkid)) {
5680 memset(&cfg->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
5681 for (; i < (cfg->pmk_list->pmkids.npmkid - 1); i++) {
5682 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
5683 &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
5685 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
5686 &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
5689 cfg->pmk_list->pmkids.npmkid--;
5694 err = wl_update_pmklist(dev, cfg->pmk_list, err);
5701 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
5703 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5705 RETURN_EIO_IF_NOT_UP(cfg);
5706 memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
5707 err = wl_update_pmklist(dev, cfg->pmk_list, err);
5712 static wl_scan_params_t *
5713 wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size)
5715 wl_scan_params_t *params;
5720 *out_params_size = 0;
5722 /* Our scan params only need space for 1 channel and 0 ssids */
5723 params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
5724 params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
5725 if (params == NULL) {
5726 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
5729 memset(params, 0, params_size);
5730 params->nprobes = nprobes;
5732 num_chans = (channel == 0) ? 0 : 1;
5734 memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN);
5735 params->bss_type = DOT11_BSSTYPE_ANY;
5736 params->scan_type = DOT11_SCANTYPE_ACTIVE;
5737 params->nprobes = htod32(1);
5738 params->active_time = htod32(-1);
5739 params->passive_time = htod32(-1);
5740 params->home_time = htod32(10);
5742 params->channel_list[0] = htodchanspec(channel);
5744 params->channel_list[0] = wl_ch_host_to_driver(bssidx, channel);
5746 /* Our scan params have 1 channel and 0 ssids */
5747 params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
5748 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
5750 *out_params_size = params_size; /* rtn size to the caller */
5755 #if defined(WL_CFG80211_P2P_DEV_IF)
5756 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5757 struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
5759 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
5760 struct ieee80211_channel * channel,
5761 enum nl80211_channel_type channel_type,
5762 unsigned int duration, u64 *cookie)
5763 #endif /* WL_CFG80211_P2P_DEV_IF */
5767 struct ether_addr primary_mac;
5768 struct net_device *ndev = NULL;
5769 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5771 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
5773 WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
5774 ieee80211_frequency_to_channel(channel->center_freq),
5775 duration, (wl_get_drv_status(cfg, SCANNING, ndev)) ? "YES":"NO"));
5778 WL_ERR(("cfg->p2p is not initialized\n"));
5783 #ifdef P2P_LISTEN_OFFLOADING
5784 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
5785 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
5788 #endif /* P2P_LISTEN_OFFLOADING */
5790 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5791 if (wl_get_drv_status_all(cfg, SCANNING)) {
5792 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
5794 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5796 target_channel = ieee80211_frequency_to_channel(channel->center_freq);
5797 memcpy(&cfg->remain_on_chan, channel, sizeof(struct ieee80211_channel));
5798 #if defined(WL_ENABLE_P2P_IF)
5799 cfg->remain_on_chan_type = channel_type;
5800 #endif /* WL_ENABLE_P2P_IF */
5801 *cookie = wl_cfg80211_get_new_roc_id(cfg);
5802 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5803 if (wl_get_drv_status(cfg, SCANNING, ndev)) {
5804 struct timer_list *_timer;
5805 WL_DBG(("scan is running. go to fake listen state\n"));
5807 if (duration > LONG_LISTEN_TIME) {
5808 wl_cfg80211_scan_abort(cfg);
5810 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5812 if (timer_pending(&cfg->p2p->listen_timer)) {
5813 WL_DBG(("cancel current listen timer \n"));
5814 del_timer_sync(&cfg->p2p->listen_timer);
5817 _timer = &cfg->p2p->listen_timer;
5818 wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
5820 INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
5826 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5828 #ifdef WL_CFG80211_SYNC_GON
5829 if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
5830 /* do not enter listen mode again if we are in listen mode already for next af.
5831 * remain on channel completion will be returned by waiting next af completion.
5833 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5834 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5836 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5837 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5840 #endif /* WL_CFG80211_SYNC_GON */
5841 if (cfg->p2p && !cfg->p2p->on) {
5842 /* In case of p2p_listen command, supplicant send remain_on_channel
5843 * without turning on P2P
5845 get_primary_mac(cfg, &primary_mac);
5846 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
5850 if (p2p_is_on(cfg)) {
5851 err = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
5852 if (unlikely(err)) {
5855 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5856 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5857 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5858 err = wl_cfgp2p_discover_listen(cfg, target_channel, duration);
5860 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
5861 if (err == BCME_OK) {
5862 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
5864 /* if failed, firmware may be internal scanning state.
5865 * so other scan request shall not abort it
5867 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
5869 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
5870 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
5871 * and expire timer will send a completion to the upper layer
5877 if (err == BCME_OK) {
5878 WL_INFORM(("Success\n"));
5879 #if defined(WL_CFG80211_P2P_DEV_IF)
5880 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
5881 duration, GFP_KERNEL);
5883 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
5884 channel_type, duration, GFP_KERNEL);
5885 #endif /* WL_CFG80211_P2P_DEV_IF */
5887 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
5893 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
5894 bcm_struct_cfgdev *cfgdev, u64 cookie)
5897 struct bcm_cfg80211 *cfg = g_bcm_cfg;
5899 #ifdef P2PLISTEN_AP_SAMECHN
5900 struct net_device *dev;
5901 #endif /* P2PLISTEN_AP_SAMECHN */
5903 RETURN_EIO_IF_NOT_UP(cfg);
5904 #if defined(WL_CFG80211_P2P_DEV_IF)
5905 if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
5906 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
5909 WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
5910 #endif /* WL_CFG80211_P2P_DEV_IF */
5912 #ifdef P2PLISTEN_AP_SAMECHN
5913 if (cfg && cfg->p2p_resp_apchn_status) {
5914 dev = bcmcfg_to_prmry_ndev(cfg);
5915 wl_cfg80211_set_p2p_resp_ap_chn(dev, 0);
5916 cfg->p2p_resp_apchn_status = false;
5917 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
5919 #endif /* P2PLISTEN_AP_SAMECHN */
5921 if (cfg->last_roc_id == cookie) {
5922 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
5923 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
5925 WL_ERR(("%s : ignore, request cookie(%llu) is not matched. (cur : %llu)\n",
5926 __FUNCTION__, cookie, cfg->last_roc_id));
5933 wl_cfg80211_afx_handler(struct work_struct *work)
5935 struct afx_hdl *afx_instance;
5936 struct bcm_cfg80211 *cfg = g_bcm_cfg;
5939 BCM_SET_CONTAINER_OF(afx_instance, work, struct afx_hdl, work);
5940 if (afx_instance != NULL && cfg->afx_hdl->is_active) {
5941 if (cfg->afx_hdl->is_listen && cfg->afx_hdl->my_listen_chan) {
5942 ret = wl_cfgp2p_discover_listen(cfg, cfg->afx_hdl->my_listen_chan,
5943 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
5945 ret = wl_cfgp2p_act_frm_search(cfg, cfg->afx_hdl->dev,
5946 cfg->afx_hdl->bssidx, cfg->afx_hdl->peer_listen_chan,
5949 if (unlikely(ret != BCME_OK)) {
5950 WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
5951 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL))
5952 complete(&cfg->act_frm_scan);
5958 wl_cfg80211_af_searching_channel(struct bcm_cfg80211 *cfg, struct net_device *dev)
5960 u32 max_retry = WL_CHANNEL_SYNC_RETRY;
5961 bool is_p2p_gas = false;
5966 WL_DBG((" enter ) \n"));
5968 wl_set_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
5969 cfg->afx_hdl->is_active = TRUE;
5971 if (cfg->afx_hdl->pending_tx_act_frm) {
5972 wl_action_frame_t *action_frame;
5973 action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
5974 if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len))
5978 /* Loop to wait until we find a peer's channel or the
5979 * pending action frame tx is cancelled.
5981 while ((cfg->afx_hdl->retry < max_retry) &&
5982 (cfg->afx_hdl->peer_chan == WL_INVALID)) {
5983 cfg->afx_hdl->is_listen = FALSE;
5984 wl_set_drv_status(cfg, SCANNING, dev);
5985 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
5986 cfg->afx_hdl->retry));
5987 /* search peer on peer's listen channel */
5988 schedule_work(&cfg->afx_hdl->work);
5989 wait_for_completion_timeout(&cfg->act_frm_scan,
5990 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
5992 if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
5993 !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
5999 if (cfg->afx_hdl->my_listen_chan) {
6000 WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
6001 cfg->afx_hdl->my_listen_chan));
6002 /* listen on my listen channel */
6003 cfg->afx_hdl->is_listen = TRUE;
6004 schedule_work(&cfg->afx_hdl->work);
6005 wait_for_completion_timeout(&cfg->act_frm_scan,
6006 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
6008 if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
6009 !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
6012 cfg->afx_hdl->retry++;
6014 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
6017 cfg->afx_hdl->is_active = FALSE;
6019 wl_clr_drv_status(cfg, SCANNING, dev);
6020 wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
6022 return (cfg->afx_hdl->peer_chan);
6025 struct p2p_config_af_params {
6026 s32 max_tx_retry; /* max tx retry count if tx no ack */
6027 /* To make sure to send successfully action frame, we have to turn off mpc
6028 * 0: off, 1: on, (-1): do nothing
6031 #ifdef WL_CFG80211_SYNC_GON
6034 bool search_channel; /* 1: search peer's channel to send af */
6038 wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
6039 wl_action_frame_t *action_frame, wl_af_params_t *af_params,
6040 struct p2p_config_af_params *config_af_params)
6043 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6044 wifi_p2p_pub_act_frame_t *act_frm =
6045 (wifi_p2p_pub_act_frame_t *) (action_frame->data);
6047 /* initialize default value */
6048 #ifdef WL_CFG80211_SYNC_GON
6049 config_af_params->extra_listen = true;
6051 config_af_params->search_channel = false;
6052 config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
6053 config_af_params->mpc_onoff = -1;
6054 cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
6056 switch (act_frm->subtype) {
6057 case P2P_PAF_GON_REQ: {
6058 WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
6059 wl_set_p2p_status(cfg, GO_NEG_PHASE);
6061 config_af_params->mpc_onoff = 0;
6062 config_af_params->search_channel = true;
6063 cfg->next_af_subtype = act_frm->subtype + 1;
6065 /* increase dwell time to wait for RESP frame */
6066 af_params->dwell_time = WL_MED_DWELL_TIME;
6070 case P2P_PAF_GON_RSP: {
6071 cfg->next_af_subtype = act_frm->subtype + 1;
6072 /* increase dwell time to wait for CONF frame */
6073 af_params->dwell_time = WL_MED_DWELL_TIME + 100;
6076 case P2P_PAF_GON_CONF: {
6077 /* If we reached till GO Neg confirmation reset the filter */
6078 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
6079 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
6081 /* turn on mpc again if go nego is done */
6082 config_af_params->mpc_onoff = 1;
6084 /* minimize dwell time */
6085 af_params->dwell_time = WL_MIN_DWELL_TIME;
6087 #ifdef WL_CFG80211_SYNC_GON
6088 config_af_params->extra_listen = false;
6089 #endif /* WL_CFG80211_SYNC_GON */
6092 case P2P_PAF_INVITE_REQ: {
6093 config_af_params->search_channel = true;
6094 cfg->next_af_subtype = act_frm->subtype + 1;
6096 /* increase dwell time */
6097 af_params->dwell_time = WL_MED_DWELL_TIME;
6100 case P2P_PAF_INVITE_RSP:
6101 /* minimize dwell time */
6102 af_params->dwell_time = WL_MIN_DWELL_TIME;
6103 #ifdef WL_CFG80211_SYNC_GON
6104 config_af_params->extra_listen = false;
6105 #endif /* WL_CFG80211_SYNC_GON */
6107 case P2P_PAF_DEVDIS_REQ: {
6108 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
6109 action_frame->len)) {
6110 config_af_params->search_channel = true;
6113 cfg->next_af_subtype = act_frm->subtype + 1;
6114 /* maximize dwell time to wait for RESP frame */
6115 af_params->dwell_time = WL_LONG_DWELL_TIME;
6118 case P2P_PAF_DEVDIS_RSP:
6119 /* minimize dwell time */
6120 af_params->dwell_time = WL_MIN_DWELL_TIME;
6121 #ifdef WL_CFG80211_SYNC_GON
6122 config_af_params->extra_listen = false;
6123 #endif /* WL_CFG80211_SYNC_GON */
6125 case P2P_PAF_PROVDIS_REQ: {
6126 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
6127 action_frame->len)) {
6128 config_af_params->search_channel = true;
6131 config_af_params->mpc_onoff = 0;
6132 cfg->next_af_subtype = act_frm->subtype + 1;
6133 /* increase dwell time to wait for RESP frame */
6134 af_params->dwell_time = WL_MED_DWELL_TIME;
6137 case P2P_PAF_PROVDIS_RSP: {
6138 cfg->next_af_subtype = P2P_PAF_GON_REQ;
6139 af_params->dwell_time = WL_MIN_DWELL_TIME;
6140 #ifdef WL_CFG80211_SYNC_GON
6141 config_af_params->extra_listen = false;
6142 #endif /* WL_CFG80211_SYNC_GON */
6146 WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
6155 wl_cfg80211_check_DFS_channel(struct bcm_cfg80211 *cfg, wl_af_params_t *af_params,
6156 void *frame, u16 frame_len)
6158 struct wl_scan_results *bss_list;
6159 struct wl_bss_info *bi = NULL;
6160 bool result = false;
6162 chanspec_t chanspec;
6164 /* If DFS channel is 52~148, check to block it or not */
6166 (af_params->channel >= 52 && af_params->channel <= 148)) {
6167 if (!wl_cfgp2p_is_p2p_action(frame, frame_len)) {
6168 bss_list = cfg->bss_list;
6169 bi = next_bss(bss_list, bi);
6170 for_each_bss(bss_list, bi, i) {
6171 chanspec = wl_chspec_driver_to_host(bi->chanspec);
6172 if (CHSPEC_IS5G(chanspec) &&
6173 ((bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(chanspec))
6174 == af_params->channel)) {
6175 result = true; /* do not block the action frame */
6185 WL_DBG(("result=%s", result?"true":"false"));
6190 wl_cfg80211_check_dwell_overflow(int32 requested_dwell, ulong dwell_jiffies)
6192 if ((requested_dwell & CUSTOM_RETRY_MASK) &&
6193 (jiffies_to_msecs(jiffies - dwell_jiffies) >
6194 (requested_dwell & ~CUSTOM_RETRY_MASK))) {
6195 WL_ERR(("Action frame TX retry time over dwell time!\n"));
6202 wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
6203 bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
6204 wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
6207 struct net_device *ndev = NULL;
6209 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6211 u8 category, action;
6213 struct p2p_config_af_params config_af_params;
6214 struct net_info *netinfo;
6216 ulong off_chan_started_jiffies = 0;
6218 ulong dwell_jiffies = 0;
6219 bool dwell_overflow = false;
6220 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
6222 int32 requested_dwell = af_params->dwell_time;
6224 /* Add the default dwell time
6225 * Dwell time to stay off-channel to wait for a response action frame
6226 * after transmitting an GO Negotiation action frame
6228 af_params->dwell_time = WL_DWELL_TIME;
6231 #if defined(WL_CFG80211_P2P_DEV_IF)
6234 ndev = ndev_to_cfgdev(cfgdev);
6235 #endif /* WL_CFG80211_P2P_DEV_IF */
6238 category = action_frame->data[DOT11_ACTION_CAT_OFF];
6239 action = action_frame->data[DOT11_ACTION_ACT_OFF];
6241 /* initialize variables */
6243 cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
6244 config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
6245 config_af_params.mpc_onoff = -1;
6246 config_af_params.search_channel = false;
6247 #ifdef WL_CFG80211_SYNC_GON
6248 config_af_params.extra_listen = false;
6251 /* config parameters */
6252 /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
6253 if (category == DOT11_ACTION_CAT_PUBLIC) {
6254 if ((action == P2P_PUB_AF_ACTION) &&
6255 (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
6256 /* p2p public action frame process */
6257 if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
6258 action_frame, af_params, &config_af_params)) {
6259 WL_DBG(("Unknown subtype.\n"));
6262 } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
6263 /* service discovery process */
6264 if (action == P2PSD_ACTION_ID_GAS_IREQ ||
6265 action == P2PSD_ACTION_ID_GAS_CREQ) {
6266 /* configure service discovery query frame */
6268 config_af_params.search_channel = true;
6270 /* save next af suptype to cancel remained dwell time */
6271 cfg->next_af_subtype = action + 1;
6273 af_params->dwell_time = WL_MED_DWELL_TIME;
6274 if (requested_dwell & CUSTOM_RETRY_MASK) {
6275 config_af_params.max_tx_retry =
6276 (requested_dwell & CUSTOM_RETRY_MASK) >> 24;
6277 af_params->dwell_time =
6278 (requested_dwell & ~CUSTOM_RETRY_MASK);
6279 WL_DBG(("Custom retry(%d) and dwell time(%d) is set.\n",
6280 config_af_params.max_tx_retry,
6281 af_params->dwell_time));
6283 } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
6284 action == P2PSD_ACTION_ID_GAS_CRESP) {
6285 /* configure service discovery response frame */
6286 af_params->dwell_time = WL_MIN_DWELL_TIME;
6288 WL_DBG(("Unknown action type: %d\n", action));
6291 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
6292 category, action, action_frame_len));
6294 } else if (category == P2P_AF_CATEGORY) {
6295 /* do not configure anything. it will be sent with a default configuration */
6297 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
6299 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
6300 wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
6305 /* To make sure to send successfully action frame, we have to turn off mpc */
6306 if (config_af_params.mpc_onoff == 0) {
6307 wldev_iovar_setint(dev, "mpc", 0);
6310 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
6311 /* validate channel and p2p ies */
6312 if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
6313 netinfo && netinfo->bss.ies.probe_req_ie_len) {
6314 config_af_params.search_channel = true;
6316 config_af_params.search_channel = false;
6319 if (ndev == bcmcfg_to_prmry_ndev(cfg))
6320 config_af_params.search_channel = false;
6324 /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
6325 if (wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {
6330 /* if scan is ongoing, abort current scan. */
6331 if (wl_get_drv_status_all(cfg, SCANNING)) {
6332 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
6335 /* Abort P2P listen */
6336 if (discover_cfgdev(cfgdev, cfg)) {
6337 if (cfg->p2p_supported && cfg->p2p) {
6338 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
6339 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
6344 /* handling DFS channel exceptions */
6345 if (!wl_cfg80211_check_DFS_channel(cfg, af_params, action_frame->data, action_frame->len)) {
6346 return false; /* the action frame was blocked */
6350 /* set status and destination address before sending af */
6351 if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
6352 /* set this status to cancel the remained dwell time in rx process */
6353 wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
6355 wl_set_drv_status(cfg, SENDING_ACT_FRM, dev);
6356 memcpy(cfg->afx_hdl->tx_dst_addr.octet,
6357 af_params->action_frame.da.octet,
6358 sizeof(cfg->afx_hdl->tx_dst_addr.octet));
6360 /* save af_params for rx process */
6361 cfg->afx_hdl->pending_tx_act_frm = af_params;
6363 if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) {
6364 WL_DBG(("Set GAS action frame config.\n"));
6365 config_af_params.search_channel = false;
6366 config_af_params.max_tx_retry = 1;
6369 /* search peer's channel */
6370 if (config_af_params.search_channel) {
6371 /* initialize afx_hdl */
6372 if ((cfg->afx_hdl->bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
6373 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
6376 cfg->afx_hdl->dev = dev;
6377 cfg->afx_hdl->retry = 0;
6378 cfg->afx_hdl->peer_chan = WL_INVALID;
6380 if (wl_cfg80211_af_searching_channel(cfg, dev) == WL_INVALID) {
6381 WL_ERR(("couldn't find peer's channel.\n"));
6382 wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
6383 af_params->channel);
6387 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
6389 * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
6390 * but after the check of piggyback algorithm.
6391 * To take care of current piggback algo, lets abort the scan here itself.
6393 wl_notify_escan_complete(cfg, dev, true, true);
6394 /* Suspend P2P discovery's search-listen to prevent it from
6395 * starting a scan or changing the channel.
6397 if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
6398 WL_ERR(("Can not disable discovery mode\n"));
6402 /* update channel */
6403 af_params->channel = cfg->afx_hdl->peer_chan;
6407 off_chan_started_jiffies = jiffies;
6410 wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
6412 wl_cfgp2p_need_wait_actfrmae(cfg, action_frame->data, action_frame->len, true);
6414 dwell_jiffies = jiffies;
6415 /* Now send a tx action frame */
6416 ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ? false : true;
6417 dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
6419 /* if failed, retry it. tx_retry_max value is configure by .... */
6420 while ((ack == false) && (tx_retry++ < config_af_params.max_tx_retry) &&
6423 if (af_params->channel) {
6424 if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
6425 OFF_CHAN_TIME_THRESHOLD_MS) {
6426 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
6427 off_chan_started_jiffies = jiffies;
6429 OSL_SLEEP(AF_RETRY_DELAY_TIME);
6432 ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ?
6434 dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
6438 WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
6440 WL_DBG(("Complete to send action frame\n"));
6442 /* Clear SENDING_ACT_FRM after all sending af is done */
6443 wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
6445 #ifdef WL_CFG80211_SYNC_GON
6446 /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
6447 * if we coundn't get the next action response frame and dongle does not keep
6448 * the dwell time, go to listen state again to get next action response frame.
6450 if (ack && config_af_params.extra_listen &&
6451 wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM) &&
6452 cfg->af_sent_channel == cfg->afx_hdl->my_listen_chan) {
6453 s32 extar_listen_time;
6455 extar_listen_time = af_params->dwell_time -
6456 jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies);
6458 if (extar_listen_time > 50) {
6459 wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
6460 WL_DBG(("Wait more time! actual af time:%d,"
6461 "calculated extar listen:%d\n",
6462 af_params->dwell_time, extar_listen_time));
6463 if (wl_cfgp2p_discover_listen(cfg, cfg->af_sent_channel,
6464 extar_listen_time + 100) == BCME_OK) {
6465 wait_for_completion_timeout(&cfg->wait_next_af,
6466 msecs_to_jiffies(extar_listen_time + 100 + 300));
6468 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
6471 #endif /* WL_CFG80211_SYNC_GON */
6472 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
6474 if (cfg->afx_hdl->pending_tx_act_frm)
6475 cfg->afx_hdl->pending_tx_act_frm = NULL;
6477 WL_INFORM(("-- sending Action Frame is %s, listen chan: %d\n",
6478 (ack) ? "Succeeded!!":"Failed!!", cfg->afx_hdl->my_listen_chan));
6481 /* if all done, turn mpc on again */
6482 if (config_af_params.mpc_onoff == 1) {
6483 wldev_iovar_setint(dev, "mpc", 1);
6489 #define MAX_NUM_OF_ASSOCIATED_DEV 64
6491 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
6492 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
6493 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
6495 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
6496 struct ieee80211_channel *channel, bool offchan,
6497 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0))
6498 enum nl80211_channel_type channel_type,
6499 bool channel_type_valid,
6500 #endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0) */
6501 unsigned int wait, const u8* buf, size_t len,
6502 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
6505 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
6506 bool dont_wait_for_ack,
6509 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
6511 wl_action_frame_t *action_frame;
6512 wl_af_params_t *af_params;
6514 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
6515 struct ieee80211_channel *channel = params->chan;
6516 const u8 *buf = params->buf;
6517 size_t len = params->len;
6519 const struct ieee80211_mgmt *mgmt;
6520 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6521 struct net_device *dev = NULL;
6526 s8 eabuf[ETHER_ADDR_STR_LEN];
6528 WL_DBG(("Enter \n"));
6530 dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
6533 WL_ERR(("dev is NULL\n"));
6537 /* set bsscfg idx for iovar (wlan0: P2PAPI_BSSCFG_PRIMARY, p2p: P2PAPI_BSSCFG_DEVICE) */
6538 if (discover_cfgdev(cfgdev, cfg)) {
6539 if (!cfg->p2p_supported || !cfg->p2p) {
6540 WL_ERR(("P2P doesn't setup completed yet\n"));
6543 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
6546 if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
6547 WL_ERR(("Find p2p index failed\n"));
6552 WL_DBG(("TX target bssidx=%d\n", bssidx));
6554 if (p2p_is_on(cfg)) {
6555 /* Suspend P2P discovery search-listen to prevent it from changing the
6558 if ((err = wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
6559 WL_ERR(("Can not disable discovery mode\n"));
6564 id = cfg->send_action_id++;
6566 id = cfg->send_action_id++;
6568 mgmt = (const struct ieee80211_mgmt *)buf;
6569 if (ieee80211_is_mgmt(mgmt->frame_control)) {
6570 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
6571 s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
6572 s32 ie_len = len - ie_offset;
6573 if ((dev == bcmcfg_to_prmry_ndev(cfg)) && cfg->p2p) {
6574 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
6576 wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
6577 VNDR_IE_PRBRSP_FLAG, (const u8 *)(buf + ie_offset), ie_len);
6578 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
6579 #if defined(P2P_IE_MISSING_FIX)
6580 if (!cfg->p2p_prb_noti) {
6581 cfg->p2p_prb_noti = true;
6582 WL_DBG(("%s: TX 802_1X Probe Response first time.\n",
6587 } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
6588 ieee80211_is_deauth(mgmt->frame_control)) {
6589 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
6590 sizeof(struct ether_addr) + sizeof(uint)] = {0};
6591 int num_associated = 0;
6592 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
6593 if (!bcmp((const uint8 *)BSSID_BROADCAST,
6594 (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
6595 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
6596 err = wldev_ioctl(dev, WLC_GET_ASSOCLIST,
6597 assoc_maclist, sizeof(mac_buf), false);
6599 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
6601 num_associated = assoc_maclist->count;
6603 memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
6604 scb_val.val = mgmt->u.disassoc.reason_code;
6605 err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
6606 sizeof(scb_val_t), true);
6608 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
6609 WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
6610 bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
6613 if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
6616 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
6619 } else if (ieee80211_is_action(mgmt->frame_control)) {
6620 /* Abort the dwell time of any previous off-channel
6621 * action frame that may be still in effect. Sending
6622 * off-channel action frames relies on the driver's
6623 * scan engine. If a previous off-channel action frame
6624 * tx is still in progress (including the dwell time),
6625 * then this new action frame will not be sent out.
6627 /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
6628 * And previous off-channel action frame must be ended before new af tx.
6630 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
6631 wl_notify_escan_complete(cfg, dev, true, true);
6632 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
6636 WL_ERR(("Driver only allows MGMT packet type\n"));
6640 af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
6642 if (af_params == NULL)
6644 WL_ERR(("unable to allocate frame\n"));
6648 action_frame = &af_params->action_frame;
6650 /* Add the packet Id */
6651 action_frame->packetId = *cookie;
6652 WL_DBG(("action frame %d\n", action_frame->packetId));
6654 memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
6655 memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
6657 /* Add the length exepted for 802.11 header */
6658 action_frame->len = len - DOT11_MGMT_HDR_LEN;
6659 WL_DBG(("action_frame->len: %d\n", action_frame->len));
6661 /* Add the channel */
6662 af_params->channel =
6663 ieee80211_frequency_to_channel(channel->center_freq);
6664 /* Save listen_chan for searching common channel */
6665 cfg->afx_hdl->peer_listen_chan = af_params->channel;
6666 WL_DBG(("channel from upper layer %d\n", cfg->afx_hdl->peer_listen_chan));
6668 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
6669 af_params->dwell_time = params->wait;
6671 af_params->dwell_time = wait;
6674 memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
6676 ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
6677 action_frame, action_frame->len, bssidx);
6678 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
6687 wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
6688 u16 frame_type, bool reg)
6691 WL_DBG(("frame_type: %x, reg: %d\n", frame_type, reg));
6693 if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
6701 wl_cfg80211_change_bss(struct wiphy *wiphy,
6702 struct net_device *dev,
6703 struct bss_parameters *params)
6708 if (params->use_cts_prot >= 0) {
6711 if (params->use_short_preamble >= 0) {
6714 if (params->use_short_slot_time >= 0) {
6717 if (params->basic_rates) {
6720 if (params->ap_isolate >= 0) {
6721 ap_isolate = params->ap_isolate;
6722 err = wldev_iovar_setint(dev, "ap_isolate", ap_isolate);
6725 WL_ERR(("set ap_isolate Error (%d)\n", err));
6729 if (params->ht_opmode >= 0) {
6737 wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
6738 struct ieee80211_channel *chan,
6739 enum nl80211_channel_type channel_type)
6742 chanspec_t chspec = 0;
6743 chanspec_t fw_chspec = 0;
6744 u32 bw = WL_CHANSPEC_BW_20;
6746 u32 ulb_bw = wl_cfg80211_get_ulb_bw(dev->ieee80211_ptr);
6747 #endif /* WL11ULB */
6755 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6756 #ifdef CUSTOM_SET_CPUCORE
6757 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
6758 #endif /* CUSTOM_SET_CPUCORE */
6760 dev = ndev_to_wlc_ndev(dev, cfg);
6761 _chan = ieee80211_frequency_to_channel(chan->center_freq);
6762 printf("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
6763 dev->ifindex, channel_type, _chan);
6768 WL_DBG(("[ULB] setting AP/GO BW to ulb_bw 0x%x \n", ulb_bw));
6769 bw = wl_cfg80211_ulbbw_to_ulbchspec(ulb_bw);
6772 #endif /* WL11ULB */
6773 if (chan->band == IEEE80211_BAND_5GHZ) {
6774 param.band = WLC_BAND_5G;
6775 err = wldev_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param),
6776 cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
6778 if (err != BCME_UNSUPPORTED) {
6779 WL_ERR(("bw_cap failed, %d\n", err));
6782 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
6784 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
6786 if (bw_cap != WLC_N_BW_20ALL)
6787 bw = WL_CHANSPEC_BW_40;
6790 if (WL_BW_CAP_80MHZ(cfg->ioctl_buf[0]))
6791 bw = WL_CHANSPEC_BW_80;
6792 else if (WL_BW_CAP_40MHZ(cfg->ioctl_buf[0]))
6793 bw = WL_CHANSPEC_BW_40;
6795 bw = WL_CHANSPEC_BW_20;
6799 } else if (chan->band == IEEE80211_BAND_2GHZ)
6800 bw = WL_CHANSPEC_BW_20;
6802 chspec = wf_channel2chspec(_chan, bw);
6803 if (wf_chspec_valid(chspec)) {
6804 fw_chspec = wl_chspec_host_to_driver(chspec);
6805 if (fw_chspec != INVCHANSPEC) {
6806 if ((err = wldev_iovar_setint(dev, "chanspec",
6807 fw_chspec)) == BCME_BADCHAN) {
6808 if (bw == WL_CHANSPEC_BW_80)
6810 err = wldev_ioctl(dev, WLC_SET_CHANNEL,
6811 &_chan, sizeof(_chan), true);
6813 WL_ERR(("WLC_SET_CHANNEL error %d"
6814 "chip may not be supporting this channel\n", err));
6817 WL_ERR(("failed to set chanspec error %d\n", err));
6820 WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
6825 if (bw == WL_CHANSPEC_BW_80)
6826 bw = WL_CHANSPEC_BW_40;
6827 else if (bw == WL_CHANSPEC_BW_40)
6828 bw = WL_CHANSPEC_BW_20;
6833 WL_ERR(("Invalid chanspec 0x%x\n", chspec));
6836 #ifdef CUSTOM_SET_CPUCORE
6837 if (dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
6838 WL_DBG(("SoftAP mode do not need to set cpucore\n"));
6839 } else if (chspec & WL_CHANSPEC_BW_80) {
6840 /* SoftAp only mode do not need to set cpucore */
6841 if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) &&
6842 dev != bcmcfg_to_prmry_ndev(cfg)) {
6843 /* Soft AP on virtual Iface (AP+STA case) */
6844 dhd->chan_isvht80 |= DHD_FLAG_HOSTAP_MODE;
6845 dhd_set_cpucore(dhd, TRUE);
6846 } else if (is_p2p_group_iface(dev->ieee80211_ptr)) {
6847 /* If P2P IF is vht80 */
6848 dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE;
6849 dhd_set_cpucore(dhd, TRUE);
6852 #endif /* CUSTOM_SET_CPUCORE */
6853 if (!err && (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) {
6854 /* Update AP/GO operating channel */
6855 cfg->ap_oper_channel = _chan;
6860 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
6862 wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg)
6864 struct net_info *_net_info, *next;
6865 list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
6866 if (_net_info->ndev &&
6867 test_bit(WL_STATUS_REMAINING_ON_CHANNEL, &_net_info->sme_state))
6868 return _net_info->ndev;
6872 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
6875 wl_validate_opensecurity(struct net_device *dev, s32 bssidx, bool privacy)
6882 err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
6884 WL_ERR(("auth error %d\n", err));
6889 /* If privacy bit is set in open mode, then WEP would be enabled */
6891 WL_DBG(("Setting wsec to %d for WEP \n", wsec));
6895 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
6897 WL_ERR(("wsec error %d\n", err));
6901 /* set upper-layer auth */
6902 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC)
6903 wpa_val = WPA_AUTH_NONE;
6905 wpa_val = WPA_AUTH_DISABLED;
6906 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_val, bssidx);
6908 WL_ERR(("wpa_auth error %d\n", err));
6916 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
6920 u16 auth = 0; /* d11 open authentication */
6925 wpa_suite_mcast_t *mcast;
6926 wpa_suite_ucast_t *ucast;
6927 wpa_suite_auth_key_mgmt_t *mgmt;
6928 wpa_pmkid_list_t *pmkid;
6933 u32 wme_bss_disable;
6938 WL_DBG(("Enter \n"));
6939 len = wpa2ie->len - WPA2_VERSION_LEN;
6940 /* check the mcast cipher */
6941 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
6942 switch (mcast->type) {
6943 case WPA_CIPHER_NONE:
6946 case WPA_CIPHER_WEP_40:
6947 case WPA_CIPHER_WEP_104:
6950 case WPA_CIPHER_TKIP:
6951 gval = TKIP_ENABLED;
6953 case WPA_CIPHER_AES_CCM:
6957 WL_ERR(("No Security Info\n"));
6960 if ((len -= WPA_SUITE_LEN) <= 0)
6963 /* check the unicast cipher */
6964 ucast = (wpa_suite_ucast_t *)&mcast[1];
6965 suite_count = ltoh16_ua(&ucast->count);
6966 switch (ucast->list[0].type) {
6967 case WPA_CIPHER_NONE:
6970 case WPA_CIPHER_WEP_40:
6971 case WPA_CIPHER_WEP_104:
6974 case WPA_CIPHER_TKIP:
6975 pval = TKIP_ENABLED;
6977 case WPA_CIPHER_AES_CCM:
6981 WL_ERR(("No Security Info\n"));
6983 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
6986 /* FOR WPS , set SEC_OW_ENABLED */
6987 wsec = (pval | gval | SES_OW_ENABLED);
6989 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
6990 suite_count = cnt = ltoh16_ua(&mgmt->count);
6992 switch (mgmt->list[cnt].type) {
6994 wpa_auth |= WPA_AUTH_NONE;
6996 case RSN_AKM_UNSPECIFIED:
6997 wpa_auth |= WPA2_AUTH_UNSPECIFIED;
7000 wpa_auth |= WPA2_AUTH_PSK;
7003 WL_ERR(("No Key Mgmt Info\n"));
7007 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
7008 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
7009 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
7011 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
7012 wme_bss_disable = 0;
7014 wme_bss_disable = 1;
7018 /* set wme_bss_disable to sync RSN Capabilities */
7019 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
7021 WL_ERR(("wme_bss_disable error %d\n", err));
7025 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
7029 if (len >= WPA2_PMKID_COUNT_LEN) {
7030 pmkid = (wpa_pmkid_list_t *)((u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN);
7031 cnt = ltoh16_ua(&pmkid->count);
7033 WL_ERR(("AP has non-zero PMKID count. Wrong!\n"));
7036 /* since PMKID cnt is known to be 0 for AP, */
7037 /* so don't bother to send down this info to firmware */
7042 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
7044 WL_ERR(("auth error %d\n", err));
7049 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
7051 WL_ERR(("wsec error %d\n", err));
7056 /* set upper-layer auth */
7057 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
7059 WL_ERR(("wpa_auth error %d\n", err));
7067 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
7069 wpa_suite_mcast_t *mcast;
7070 wpa_suite_ucast_t *ucast;
7071 wpa_suite_auth_key_mgmt_t *mgmt;
7072 u16 auth = 0; /* d11 open authentication */
7085 WL_DBG(("Enter \n"));
7086 len = wpaie->length; /* value length */
7087 len -= WPA_IE_TAG_FIXED_LEN;
7088 /* check for multicast cipher suite */
7089 if (len < WPA_SUITE_LEN) {
7090 WL_INFORM(("no multicast cipher suite\n"));
7094 /* pick up multicast cipher */
7095 mcast = (wpa_suite_mcast_t *)&wpaie[1];
7096 len -= WPA_SUITE_LEN;
7097 if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
7098 if (IS_WPA_CIPHER(mcast->type)) {
7100 switch (mcast->type) {
7101 case WPA_CIPHER_NONE:
7104 case WPA_CIPHER_WEP_40:
7105 case WPA_CIPHER_WEP_104:
7108 case WPA_CIPHER_TKIP:
7111 case WPA_CIPHER_AES_CCM:
7115 WL_ERR(("No Security Info\n"));
7120 /* Check for unicast suite(s) */
7121 if (len < WPA_IE_SUITE_COUNT_LEN) {
7122 WL_INFORM(("no unicast suite\n"));
7125 /* walk thru unicast cipher list and pick up what we recognize */
7126 ucast = (wpa_suite_ucast_t *)&mcast[1];
7127 count = ltoh16_ua(&ucast->count);
7128 len -= WPA_IE_SUITE_COUNT_LEN;
7129 for (i = 0; i < count && len >= WPA_SUITE_LEN;
7130 i++, len -= WPA_SUITE_LEN) {
7131 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
7132 if (IS_WPA_CIPHER(ucast->list[i].type)) {
7134 switch (ucast->list[i].type) {
7135 case WPA_CIPHER_NONE:
7138 case WPA_CIPHER_WEP_40:
7139 case WPA_CIPHER_WEP_104:
7142 case WPA_CIPHER_TKIP:
7145 case WPA_CIPHER_AES_CCM:
7149 WL_ERR(("No Security Info\n"));
7155 len -= (count - i) * WPA_SUITE_LEN;
7156 /* Check for auth key management suite(s) */
7157 if (len < WPA_IE_SUITE_COUNT_LEN) {
7158 WL_INFORM((" no auth key mgmt suite\n"));
7161 /* walk thru auth management suite list and pick up what we recognize */
7162 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
7163 count = ltoh16_ua(&mgmt->count);
7164 len -= WPA_IE_SUITE_COUNT_LEN;
7165 for (i = 0; i < count && len >= WPA_SUITE_LEN;
7166 i++, len -= WPA_SUITE_LEN) {
7167 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
7168 if (IS_WPA_AKM(mgmt->list[i].type)) {
7170 switch (mgmt->list[i].type) {
7172 tmp = WPA_AUTH_NONE;
7174 case RSN_AKM_UNSPECIFIED:
7175 tmp = WPA_AUTH_UNSPECIFIED;
7181 WL_ERR(("No Key Mgmt Info\n"));
7188 /* FOR WPS , set SEC_OW_ENABLED */
7189 wsec = (pval | gval | SES_OW_ENABLED);
7191 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
7193 WL_ERR(("auth error %d\n", err));
7197 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
7199 WL_ERR(("wsec error %d\n", err));
7202 /* set upper-layer auth */
7203 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
7205 WL_ERR(("wpa_auth error %d\n", err));
7214 wl_cfg80211_bcn_validate_sec(
7215 struct net_device *dev,
7216 struct parsed_ies *ies,
7221 struct bcm_cfg80211 *cfg = g_bcm_cfg;
7222 wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
7225 WL_ERR(("cfgbss is NULL \n"));
7229 if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
7230 /* For P2P GO, the sec type is WPA2-PSK */
7231 WL_DBG(("P2P GO: validating wpa2_ie"));
7232 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0)
7235 } else if (dev_role == NL80211_IFTYPE_AP) {
7237 WL_DBG(("SoftAP: validating security"));
7238 /* If wpa2_ie or wpa_ie is present validate it */
7240 if ((ies->wpa2_ie || ies->wpa_ie) &&
7241 ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
7242 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
7243 bss->security_mode = false;
7247 bss->security_mode = true;
7260 if (ies->wpa_ie != NULL) {
7263 bss->wpa_ie = kmemdup(ies->wpa_ie,
7264 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
7266 } else if (ies->wpa2_ie != NULL) {
7269 bss->rsn_ie = kmemdup(ies->wpa2_ie,
7270 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
7273 if (!ies->wpa2_ie && !ies->wpa_ie) {
7274 wl_validate_opensecurity(dev, bssidx, privacy);
7275 bss->security_mode = false;
7279 bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
7287 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
7288 static s32 wl_cfg80211_bcn_set_params(
7289 struct cfg80211_ap_settings *info,
7290 struct net_device *dev,
7291 u32 dev_role, s32 bssidx)
7293 struct bcm_cfg80211 *cfg = g_bcm_cfg;
7296 WL_DBG(("interval (%d) \ndtim_period (%d) \n",
7297 info->beacon_interval, info->dtim_period));
7299 if (info->beacon_interval) {
7300 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
7301 &info->beacon_interval, sizeof(s32), true)) < 0) {
7302 WL_ERR(("Beacon Interval Set Error, %d\n", err));
7307 if (info->dtim_period) {
7308 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
7309 &info->dtim_period, sizeof(s32), true)) < 0) {
7310 WL_ERR(("DTIM Interval Set Error, %d\n", err));
7315 if ((info->ssid) && (info->ssid_len > 0) &&
7316 (info->ssid_len <= 32)) {
7317 WL_DBG(("SSID (%s) len:%zd \n", info->ssid, info->ssid_len));
7318 if (dev_role == NL80211_IFTYPE_AP) {
7319 /* Store the hostapd SSID */
7320 memset(cfg->hostapd_ssid.SSID, 0x00, 32);
7321 memcpy(cfg->hostapd_ssid.SSID, info->ssid, info->ssid_len);
7322 cfg->hostapd_ssid.SSID_len = info->ssid_len;
7325 memset(cfg->p2p->ssid.SSID, 0x00, 32);
7326 memcpy(cfg->p2p->ssid.SSID, info->ssid, info->ssid_len);
7327 cfg->p2p->ssid.SSID_len = info->ssid_len;
7331 if (info->hidden_ssid) {
7332 if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
7333 WL_ERR(("failed to set hidden : %d\n", err));
7334 WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
7342 wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
7346 memset(ies, 0, sizeof(struct parsed_ies));
7348 /* find the WPSIE */
7349 if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
7350 WL_DBG(("WPSIE in beacon \n"));
7351 ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
7353 WL_DBG(("No WPSIE in beacon \n"));
7356 /* find the RSN_IE */
7357 if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
7358 DOT11_MNG_RSN_ID)) != NULL) {
7359 WL_DBG((" WPA2 IE found\n"));
7360 ies->wpa2_ie_len = ies->wpa2_ie->len;
7363 /* find the WPA_IE */
7364 if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
7365 WL_DBG((" WPA found\n"));
7366 ies->wpa_ie_len = ies->wpa_ie->length;
7373 #define MAX_AP_LINK_WAIT_TIME 10000
7375 wl_cfg80211_bcn_bringup_ap(
7376 struct net_device *dev,
7377 struct parsed_ies *ies,
7378 u32 dev_role, s32 bssidx)
7380 struct bcm_cfg80211 *cfg = g_bcm_cfg;
7381 struct wl_join_params join_params;
7382 struct wiphy *wiphy;
7383 bool is_bssup = false;
7385 s32 join_params_size = 0;
7389 #ifdef SOFTAP_UAPSD_OFF
7390 uint32 wme_apsd = 0;
7391 #endif /* SOFTAP_UAPSD_OFF */
7393 s32 is_rsdb_supported = BCME_ERROR;
7395 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
7396 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
7397 #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
7399 is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
7400 if (is_rsdb_supported < 0)
7403 WL_DBG(("Enter dev_role:%d bssidx:%d\n", dev_role, bssidx));
7405 /* Common code for SoftAP and P2P GO */
7406 wiphy = bcmcfg_to_wiphy(cfg);
7407 if (wl_check_dongle_idle(wiphy) != TRUE) {
7408 WL_ERR(("FW is busy to add interface"));
7411 wldev_iovar_setint(dev, "mpc", 0);
7413 wl_clr_drv_status(cfg, AP_CREATED, dev);
7415 if (dev_role == NL80211_IFTYPE_P2P_GO) {
7416 is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
7417 if (!is_bssup && (ies->wpa2_ie != NULL)) {
7419 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
7421 WL_ERR(("SET INFRA error %d\n", err));
7425 err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &cfg->p2p->ssid,
7426 sizeof(cfg->p2p->ssid), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
7427 bssidx, &cfg->ioctl_buf_sync);
7429 WL_ERR(("GO SSID setting error %d\n", err));
7433 /* Do abort scan before creating GO */
7434 wl_cfg80211_scan_abort(cfg);
7436 if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 1)) < 0) {
7437 WL_ERR(("GO Bring up error %d\n", err));
7441 WL_DBG(("Bss is already up\n"));
7442 } else if ((dev_role == NL80211_IFTYPE_AP) &&
7443 (wl_get_drv_status(cfg, AP_CREATING, dev))) {
7445 /* Device role SoftAP */
7446 WL_DBG(("Creating AP bssidx:%d dev_role:%d\n", bssidx, dev_role));
7448 /* Clear the status bit after use */
7449 wl_clr_drv_status(cfg, AP_CREATING, dev);
7451 /* AP on primary Interface */
7453 if (is_rsdb_supported) {
7454 if ((err = wl_cfg80211_add_del_bss(cfg, dev, bssidx,
7455 NL80211_IFTYPE_AP, 0, NULL)) < 0) {
7456 WL_ERR(("wl add_del_bss returned error:%d\n", err));
7459 } else if (is_rsdb_supported == 0) {
7460 /* AP mode switch not supported. Try setting up AP explicitly */
7461 err = wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), true);
7463 WL_ERR(("WLC_DOWN error %d\n", err));
7466 err = wldev_iovar_setint(dev, "apsta", 0);
7468 WL_ERR(("wl apsta 0 error %d\n", err));
7472 if ((err = wldev_ioctl(dev,
7473 WLC_SET_AP, &ap, sizeof(s32), true)) < 0) {
7474 WL_ERR(("setting AP mode failed %d \n", err));
7481 if ((err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true)) != 0) {
7482 WL_ERR(("wl PM 0 returned error:%d\n", err));
7486 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
7488 WL_ERR(("SET INFRA error %d\n", err));
7491 } else if (cfg->cfgdev_bssidx && (bssidx == cfg->cfgdev_bssidx)) {
7493 WL_DBG(("Bringup SoftAP on virtual Interface bssidx:%d \n", bssidx));
7495 if ((err = wl_cfg80211_add_del_bss(cfg, dev,
7496 bssidx, NL80211_IFTYPE_AP, 0, NULL)) < 0) {
7497 WL_ERR(("wl bss ap returned error:%d\n", err));
7503 #ifdef SOFTAP_UAPSD_OFF
7504 err = wldev_iovar_setbuf_bsscfg(dev, "wme_apsd", &wme_apsd, sizeof(wme_apsd),
7505 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
7507 WL_ERR(("failed to disable uapsd, error=%d\n", err));
7509 #endif /* SOFTAP_UAPSD_OFF */
7511 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
7512 if (unlikely(err)) {
7513 WL_ERR(("WLC_UP error (%d)\n", err));
7517 err = wldev_iovar_getint(dev, "wsec", (s32 *)&wsec);
7518 if (unlikely(err)) {
7519 WL_ERR(("Could not get wsec %d\n", err));
7522 if ((wsec == WEP_ENABLED) && cfg->wep_key.len) {
7523 WL_DBG(("Applying buffered WEP KEY \n"));
7524 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &cfg->wep_key,
7525 sizeof(struct wl_wsec_key), cfg->ioctl_buf,
7526 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
7527 /* clear the key after use */
7528 memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
7529 if (unlikely(err)) {
7530 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
7535 memset(&join_params, 0, sizeof(join_params));
7536 /* join parameters starts with ssid */
7537 join_params_size = sizeof(join_params.ssid);
7538 memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
7539 cfg->hostapd_ssid.SSID_len);
7540 join_params.ssid.SSID_len = htod32(cfg->hostapd_ssid.SSID_len);
7543 if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
7544 join_params_size, true)) != 0) {
7545 WL_ERR(("SoftAP/GO set ssid failed! \n"));
7548 WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
7552 /* AP on Virtual Interface */
7553 if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 1)) < 0) {
7554 WL_ERR(("GO Bring up error %d\n", err));
7560 /* Wait for Linkup event to mark successful AP/GO bring up */
7561 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
7562 wl_get_drv_status(cfg, AP_CREATED, dev), msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
7563 if (timeout <= 0 || !wl_get_drv_status(cfg, AP_CREATED, dev)) {
7564 WL_ERR(("Link up didn't come for AP interface. AP/GO creation failed! \n"));
7565 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
7566 if (dhdp->memdump_enabled) {
7567 dhdp->memdump_type = DUMP_TYPE_AP_LINKUP_FAILURE;
7568 dhd_bus_mem_dump(dhdp);
7570 #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
7576 if (cfg->wep_key.len)
7577 memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
7581 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
7583 wl_cfg80211_parse_ap_ies(
7584 struct net_device *dev,
7585 struct cfg80211_beacon_data *info,
7586 struct parsed_ies *ies)
7588 struct parsed_ies prb_ies;
7589 struct bcm_cfg80211 *cfg = g_bcm_cfg;
7590 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
7592 u32 vndr_ie_len = 0;
7595 /* Parse Beacon IEs */
7596 if (wl_cfg80211_parse_ies((u8 *)info->tail,
7597 info->tail_len, ies) < 0) {
7598 WL_ERR(("Beacon get IEs failed \n"));
7603 vndr = (u8 *)info->proberesp_ies;
7604 vndr_ie_len = info->proberesp_ies_len;
7606 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
7608 struct ieee80211_mgmt *mgmt;
7609 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
7611 vndr = (u8 *)&mgmt->u.probe_resp.variable;
7612 vndr_ie_len = info->probe_resp_len -
7613 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
7617 /* Parse Probe Response IEs */
7618 if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) {
7619 WL_ERR(("PROBE RESP get IEs failed \n"));
7629 wl_cfg80211_set_ies(
7630 struct net_device *dev,
7631 struct cfg80211_beacon_data *info,
7634 struct bcm_cfg80211 *cfg = g_bcm_cfg;
7635 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
7637 u32 vndr_ie_len = 0;
7640 /* Set Beacon IEs to FW */
7641 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
7642 VNDR_IE_BEACON_FLAG, (const u8 *)info->tail,
7643 info->tail_len)) < 0) {
7644 WL_ERR(("Set Beacon IE Failed \n"));
7646 WL_DBG(("Applied Vndr IEs for Beacon \n"));
7649 vndr = (u8 *)info->proberesp_ies;
7650 vndr_ie_len = info->proberesp_ies_len;
7652 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
7654 struct ieee80211_mgmt *mgmt;
7655 mgmt = (struct ieee80211_mgmt *)info->probe_resp;
7657 vndr = (u8 *)&mgmt->u.probe_resp.variable;
7658 vndr_ie_len = info->probe_resp_len -
7659 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
7663 /* Set Probe Response IEs to FW */
7664 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
7665 VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
7666 WL_ERR(("Set Probe Resp IE Failed \n"));
7668 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
7675 static s32 wl_cfg80211_hostapd_sec(
7676 struct net_device *dev,
7677 struct parsed_ies *ies,
7680 bool update_bss = 0;
7681 struct bcm_cfg80211 *cfg = g_bcm_cfg;
7682 wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
7685 WL_ERR(("cfgbss is NULL \n"));
7691 memcmp(bss->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
7692 WL_DBG((" WPS IE is changed\n"));
7694 bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
7695 } else if (bss->wps_ie == NULL) {
7696 WL_DBG((" WPS IE is added\n"));
7697 bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
7700 if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
7701 if (!bss->security_mode) {
7702 /* change from open mode to security mode */
7704 if (ies->wpa_ie != NULL) {
7705 bss->wpa_ie = kmemdup(ies->wpa_ie,
7706 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
7709 bss->rsn_ie = kmemdup(ies->wpa2_ie,
7710 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
7713 } else if (bss->wpa_ie) {
7714 /* change from WPA2 mode to WPA mode */
7715 if (ies->wpa_ie != NULL) {
7719 bss->wpa_ie = kmemdup(ies->wpa_ie,
7720 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
7722 } else if (memcmp(bss->rsn_ie,
7723 ies->wpa2_ie, ies->wpa2_ie->len
7724 + WPA_RSN_IE_TAG_FIXED_LEN)) {
7727 bss->rsn_ie = kmemdup(ies->wpa2_ie,
7728 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
7734 bss->security_mode = true;
7735 wl_cfgp2p_bss(cfg, dev, bssidx, 0);
7736 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
7737 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
7740 wl_cfgp2p_bss(cfg, dev, bssidx, 1);
7744 WL_ERR(("No WPSIE in beacon \n"));
7749 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
7752 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
7753 wl_cfg80211_del_station(
7754 struct wiphy *wiphy, struct net_device *ndev,
7755 struct station_del_parameters *params)
7756 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
7757 wl_cfg80211_del_station(
7758 struct wiphy *wiphy,
7759 struct net_device *ndev,
7762 wl_cfg80211_del_station(
7763 struct wiphy *wiphy,
7764 struct net_device *ndev,
7766 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
7768 struct net_device *dev;
7769 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7771 s8 eabuf[ETHER_ADDR_STR_LEN];
7773 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
7774 sizeof(struct ether_addr) + sizeof(uint)] = {0};
7775 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
7776 int num_associated = 0;
7778 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
7779 const u8 *mac_addr = params->mac;
7780 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
7782 WL_DBG(("Entry\n"));
7783 if (mac_addr == NULL) {
7784 WL_DBG(("mac_addr is NULL ignore it\n"));
7788 dev = ndev_to_wlc_ndev(ndev, cfg);
7790 if (p2p_is_on(cfg)) {
7791 /* Suspend P2P discovery search-listen to prevent it from changing the
7794 if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
7795 WL_ERR(("Can not disable discovery mode\n"));
7800 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
7801 err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST,
7802 assoc_maclist, sizeof(mac_buf), false);
7804 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
7806 num_associated = assoc_maclist->count;
7808 memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
7809 scb_val.val = DOT11_RC_DEAUTH_LEAVING;
7810 err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
7811 sizeof(scb_val_t), true);
7813 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
7814 WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
7815 bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
7818 if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
7825 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
7826 wl_cfg80211_change_station(
7827 struct wiphy *wiphy,
7828 struct net_device *dev,
7830 struct station_parameters *params)
7832 wl_cfg80211_change_station(
7833 struct wiphy *wiphy,
7834 struct net_device *dev,
7836 struct station_parameters *params)
7840 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7841 struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
7843 WL_DBG(("SCB_AUTHORIZE mac_addr:"MACDBG" sta_flags_mask:0x%x "
7844 "sta_flags_set:0x%x iface:%s \n", MAC2STRDBG(mac),
7845 params->sta_flags_mask, params->sta_flags_set, dev->name));
7847 /* Processing only authorize/de-authorize flag for now */
7848 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
7849 WL_ERR(("WLC_SCB_AUTHORIZE sta_flags_mask not set \n"));
7853 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
7854 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
7855 err = wldev_ioctl(primary_ndev, WLC_SCB_DEAUTHORIZE, (u8 *)mac, ETH_ALEN, true);
7857 err = wldev_ioctl(primary_ndev, WLC_SCB_DEAUTHORIZE, mac, ETH_ALEN, true);
7860 WL_ERR(("WLC_SCB_DEAUTHORIZE error (%d)\n", err));
7864 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
7865 err = wldev_ioctl(primary_ndev, WLC_SCB_AUTHORIZE, (u8 *)mac, ETH_ALEN, true);
7867 err = wldev_ioctl(primary_ndev, WLC_SCB_AUTHORIZE, mac, ETH_ALEN, true);
7870 WL_ERR(("WLC_SCB_AUTHORIZE error (%d)\n", err));
7871 #ifdef DHD_LOSSLESS_ROAMING
7872 wl_del_roam_timeout(cfg);
7876 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
7879 wl_cfg80211_set_scb_timings(
7880 struct bcm_cfg80211 *cfg,
7881 struct net_device *dev)
7885 wl_scb_probe_t scb_probe;
7887 bzero(&scb_probe, sizeof(wl_scb_probe_t));
7888 scb_probe.scb_timeout = WL_SCB_TIMEOUT;
7889 scb_probe.scb_activity_time = WL_SCB_ACTIVITY_TIME;
7890 scb_probe.scb_max_probe = WL_SCB_MAX_PROBE;
7891 err = wldev_iovar_setbuf(dev, "scb_probe", (void *)&scb_probe,
7892 sizeof(wl_scb_probe_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
7893 &cfg->ioctl_buf_sync);
7894 if (unlikely(err)) {
7895 WL_ERR(("set 'scb_probe' failed, error = %d\n", err));
7899 ps_pretend = MAX(WL_SCB_MAX_PROBE / 2, WL_MIN_PSPRETEND_THRESHOLD);
7900 err = wldev_iovar_setint(dev, "pspretend_threshold", ps_pretend);
7901 if (unlikely(err)) {
7902 if (err == BCME_UNSUPPORTED) {
7903 /* Ignore error if fw doesn't support the iovar */
7904 WL_DBG(("wl pspretend_threshold %d set error %d\n",
7907 WL_ERR(("wl pspretend_threshold %d set error %d\n",
7916 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
7918 wl_cfg80211_start_ap(
7919 struct wiphy *wiphy,
7920 struct net_device *dev,
7921 struct cfg80211_ap_settings *info)
7923 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7925 struct parsed_ies ies;
7928 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
7930 WL_DBG(("Enter \n"));
7932 #if defined(SUPPORT_RANDOM_MAC_SCAN)
7933 wl_cfg80211_set_random_mac(dev, FALSE);
7934 #endif /* SUPPORT_RANDOM_MAC_SCAN */
7936 if ((dev == bcmcfg_to_prmry_ndev(cfg)) ||
7937 (dev == ((struct net_device *)cfgdev_to_ndev(cfg->bss_cfgdev)))) {
7938 WL_DBG(("Start AP req on iface: %s \n", dev->name));
7939 dev_role = NL80211_IFTYPE_AP;
7941 #if defined(WL_ENABLE_P2P_IF)
7942 else if (dev == cfg->p2p_net) {
7943 /* Group Add request on p2p0 */
7944 WL_DBG(("Start AP req on P2P iface: GO\n"));
7945 dev = bcmcfg_to_prmry_ndev(cfg);
7946 dev_role = NL80211_IFTYPE_P2P_GO;
7948 #endif /* WL_ENABLE_P2P_IF */
7950 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
7951 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
7955 if (p2p_is_on(cfg) && (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) {
7956 dev_role = NL80211_IFTYPE_P2P_GO;
7957 } else if (dev_role == NL80211_IFTYPE_AP) {
7958 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
7960 * Enabling Softap is causing issues with STA NDO operations
7961 * as NDO is not interface specific. So disable NDO while
7964 err = dhd_ndo_enable(dhd, FALSE);
7965 WL_DBG(("%s: Disabling NDO on Hostapd mode %d\n", __FUNCTION__, err));
7967 /* Non fatal error. */
7968 WL_ERR(("%s: Disabling NDO Failed %d\n", __FUNCTION__, err));
7970 cfg->revert_ndo_disable = true;
7973 #ifdef PKT_FILTER_SUPPORT
7974 /* Disable packet filter */
7975 if (dhd->early_suspended) {
7976 WL_ERR(("Disable pkt_filter\n"));
7977 dhd_enable_packet_filter(0, dhd);
7979 #endif /* PKT_FILTER_SUPPORT */
7980 #ifdef ARP_OFFLOAD_SUPPORT
7981 /* IF SoftAP is enabled, disable arpoe */
7982 dhd_arp_offload_set(dhd, 0);
7983 dhd_arp_offload_enable(dhd, FALSE);
7984 #endif /* ARP_OFFLOAD_SUPPORT */
7985 if ((dhd->op_mode & DHD_FLAG_STA_MODE) && wl_cfg80211_is_roam_offload()) {
7986 WL_ERR(("Cleare roam_offload_bssid_list at STA-SoftAP MODE.\n"));
7987 wl_android_set_roam_offload_bssid_list(dev, "0");
7990 /* only AP or GO role need to be handled here. */
7995 if (!check_dev_role_integrity(cfg, dev_role)) {
8000 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8001 if ((err = wl_cfg80211_set_channel(wiphy, dev,
8002 dev->ieee80211_ptr->preset_chandef.chan,
8003 NL80211_CHAN_HT20) < 0)) {
8004 WL_ERR(("Set channel failed \n"));
8009 if ((err = wl_cfg80211_bcn_set_params(info, dev,
8010 dev_role, bssidx)) < 0) {
8011 WL_ERR(("Beacon params set failed \n"));
8016 if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
8017 WL_ERR(("Set IEs failed \n"));
8021 if ((err = wl_cfg80211_bcn_validate_sec(dev, &ies,
8022 dev_role, bssidx, info->privacy)) < 0)
8024 WL_ERR(("Beacon set security failed \n"));
8028 if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
8029 dev_role, bssidx)) < 0) {
8030 WL_ERR(("Beacon bring up AP/GO failed \n"));
8034 /* Set GC/STA SCB expiry timings. */
8035 if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
8036 WL_ERR(("scb setting failed \n"));
8040 WL_DBG(("** AP/GO Created **\n"));
8042 #ifdef WL_CFG80211_ACL
8043 /* Enfoce Admission Control. */
8044 if ((err = wl_cfg80211_set_mac_acl(wiphy, dev, info->acl)) < 0) {
8045 WL_ERR(("Set ACL failed\n"));
8047 #endif /* WL_CFG80211_ACL */
8050 if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
8051 WL_ERR(("Set IEs failed \n"));
8053 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
8054 if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
8056 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
8058 WL_DBG(("set WLC_E_PROBREQ_MSG\n"));
8059 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
8065 WL_ERR(("ADD/SET beacon failed\n"));
8066 wldev_iovar_setint(dev, "mpc", 1);
8067 if (dev_role == NL80211_IFTYPE_AP) {
8068 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
8070 #ifdef PKT_FILTER_SUPPORT
8071 /* Enable packet filter */
8072 if (dhd->early_suspended) {
8073 WL_ERR(("Enable pkt_filter\n"));
8074 dhd_enable_packet_filter(1, dhd);
8076 #endif /* PKT_FILTER_SUPPORT */
8084 wl_cfg80211_stop_ap(
8085 struct wiphy *wiphy,
8086 struct net_device *dev)
8093 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8094 s32 is_rsdb_supported = BCME_ERROR;
8095 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8097 WL_DBG(("Enter \n"));
8099 is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
8100 if (is_rsdb_supported < 0)
8103 wl_clr_drv_status(cfg, AP_CREATING, dev);
8104 wl_clr_drv_status(cfg, AP_CREATED, dev);
8105 cfg->ap_oper_channel = 0;
8107 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
8108 dev_role = NL80211_IFTYPE_AP;
8109 WL_DBG(("stopping AP operation\n"));
8110 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
8111 dev_role = NL80211_IFTYPE_P2P_GO;
8112 WL_DBG(("stopping P2P GO operation\n"));
8114 WL_ERR(("no AP/P2P GO interface is operational.\n"));
8118 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
8119 WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
8123 if (!check_dev_role_integrity(cfg, dev_role)) {
8124 WL_ERR(("role integrity check failed \n"));
8129 if ((err = wl_cfgp2p_bss(cfg, dev, bssidx, 0)) < 0) {
8130 WL_ERR(("bss down error %d\n", err));
8133 if (dev_role == NL80211_IFTYPE_AP) {
8134 if (cfg->revert_ndo_disable == true) {
8135 err = dhd_ndo_enable(dhd, TRUE);
8136 WL_DBG(("%s: Enabling back NDO on Softap turn off %d\n",
8137 __FUNCTION__, err));
8139 WL_ERR(("%s: Enabling NDO Failed %d\n", __FUNCTION__, err));
8141 cfg->revert_ndo_disable = false;
8144 #ifdef PKT_FILTER_SUPPORT
8145 /* Enable packet filter */
8146 if (dhd->early_suspended) {
8147 WL_ERR(("Enable pkt_filter\n"));
8148 dhd_enable_packet_filter(1, dhd);
8150 #endif /* PKT_FILTER_SUPPORT */
8151 #ifdef ARP_OFFLOAD_SUPPORT
8152 /* IF SoftAP is disabled, enable arpoe back for STA mode. */
8153 dhd_arp_offload_set(dhd, dhd_arp_mode);
8154 dhd_arp_offload_enable(dhd, TRUE);
8155 #endif /* ARP_OFFLOAD_SUPPORT */
8157 * Bring down the AP interface by changing role to STA.
8158 * Don't do a down or "WLC_SET_AP 0" since the shared
8159 * interface may be still running
8161 if (is_rsdb_supported) {
8162 if ((err = wl_cfg80211_add_del_bss(cfg, dev,
8163 bssidx, NL80211_IFTYPE_STATION, 0, NULL)) < 0) {
8164 if ((err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32),
8166 WL_ERR(("setting AP mode failed %d \n", err));
8171 } else if (is_rsdb_supported == 0) {
8172 /* terence 20160426: fix softap issue */
8173 err = wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), true);
8175 WL_ERR(("setting AP mode failed %d \n", err));
8179 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
8181 WL_ERR(("SET INFRA error %d\n", err));
8185 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
8186 if (unlikely(err)) {
8187 WL_ERR(("WLC_UP error (%d)\n", err));
8193 /* Turn on the MPC */
8194 wldev_iovar_setint(dev, "mpc", 1);
8196 wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
8198 WL_DBG(("Stopping P2P GO \n"));
8199 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(cfg->pub),
8200 DHD_EVENT_TIMEOUT_MS*3);
8201 DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub));
8206 if (dev_role == NL80211_IFTYPE_AP) {
8207 /* clear the AP mode */
8208 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
8214 wl_cfg80211_change_beacon(
8215 struct wiphy *wiphy,
8216 struct net_device *dev,
8217 struct cfg80211_beacon_data *info)
8220 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8221 struct parsed_ies ies;
8226 WL_DBG(("Enter \n"));
8228 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
8229 dev_role = NL80211_IFTYPE_AP;
8231 #if defined(WL_ENABLE_P2P_IF)
8232 else if (dev == cfg->p2p_net) {
8233 /* Group Add request on p2p0 */
8234 dev = bcmcfg_to_prmry_ndev(cfg);
8235 dev_role = NL80211_IFTYPE_P2P_GO;
8237 #endif /* WL_ENABLE_P2P_IF */
8239 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
8240 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
8244 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
8245 dev_role = NL80211_IFTYPE_P2P_GO;
8248 if (!check_dev_role_integrity(cfg, dev_role)) {
8253 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
8254 WL_ERR(("P2P already down status!\n"));
8260 if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
8261 WL_ERR(("Parse IEs failed \n"));
8266 if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
8267 WL_ERR(("Set IEs failed \n"));
8271 if (dev_role == NL80211_IFTYPE_AP) {
8272 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
8273 WL_ERR(("Hostapd update sec failed \n"));
8277 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
8278 if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
8279 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
8280 WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc));
8282 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
8284 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
8293 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
8294 struct beacon_parameters *info)
8297 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8300 u32 dev_role = NL80211_IFTYPE_AP;
8301 struct parsed_ies ies;
8306 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8308 WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
8309 info->interval, info->dtim_period, info->head_len, info->tail_len));
8311 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
8312 dev_role = NL80211_IFTYPE_AP;
8314 #if defined(WL_ENABLE_P2P_IF)
8315 else if (dev == cfg->p2p_net) {
8316 /* Group Add request on p2p0 */
8317 dev = bcmcfg_to_prmry_ndev(cfg);
8318 dev_role = NL80211_IFTYPE_P2P_GO;
8320 #endif /* WL_ENABLE_P2P_IF */
8322 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
8323 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
8327 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
8328 dev_role = NL80211_IFTYPE_P2P_GO;
8329 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
8330 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
8333 if (!check_dev_role_integrity(cfg, dev_role)) {
8338 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
8339 WL_ERR(("P2P already down status!\n"));
8344 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
8346 if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
8347 info->head_len - ie_offset,
8348 DOT11_MNG_SSID_ID)) != NULL) {
8349 if (dev_role == NL80211_IFTYPE_AP) {
8350 /* Store the hostapd SSID */
8351 memset(&cfg->hostapd_ssid.SSID[0], 0x00, 32);
8352 memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
8353 cfg->hostapd_ssid.SSID_len = ssid_ie->len;
8356 memset(&cfg->p2p->ssid.SSID[0], 0x00, 32);
8357 memcpy(cfg->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
8358 cfg->p2p->ssid.SSID_len = ssid_ie->len;
8362 if (wl_cfg80211_parse_ies((u8 *)info->tail,
8363 info->tail_len, &ies) < 0) {
8364 WL_ERR(("Beacon get IEs failed \n"));
8369 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
8370 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
8371 info->tail_len)) < 0) {
8372 WL_ERR(("Beacon set IEs failed \n"));
8375 WL_DBG(("Applied Vndr IEs for Beacon \n"));
8378 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
8379 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
8380 VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies,
8381 info->proberesp_ies_len)) < 0) {
8382 WL_ERR(("ProbeRsp set IEs failed \n"));
8385 WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
8389 is_bss_up = wl_cfgp2p_bss_isup(dev, bssidx);
8391 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
8392 privacy = info->privacy;
8397 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx, privacy) < 0))
8399 WL_ERR(("Beacon set security failed \n"));
8404 /* Set BI and DTIM period */
8405 if (info->interval) {
8406 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
8407 &info->interval, sizeof(s32), true)) < 0) {
8408 WL_ERR(("Beacon Interval Set Error, %d\n", err));
8412 if (info->dtim_period) {
8413 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
8414 &info->dtim_period, sizeof(s32), true)) < 0) {
8415 WL_ERR(("DTIM Interval Set Error, %d\n", err));
8420 /* If bss is already up, skip bring up */
8422 (err = wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx)) < 0)
8424 WL_ERR(("Beacon bring up AP/GO failed \n"));
8428 /* Set GC/STA SCB expiry timings. */
8429 if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
8430 WL_ERR(("scb setting failed \n"));
8434 if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
8435 /* Soft AP already running. Update changed params */
8436 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
8437 WL_ERR(("Hostapd update sec failed \n"));
8443 /* Enable Probe Req filter */
8444 if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
8445 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
8446 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
8448 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
8451 WL_DBG(("** ADD/SET beacon done **\n"));
8455 WL_ERR(("ADD/SET beacon failed\n"));
8456 wldev_iovar_setint(dev, "mpc", 1);
8457 if (dev_role == NL80211_IFTYPE_AP) {
8458 /* clear the AP mode */
8459 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
8467 #ifdef WL_SCHED_SCAN
8469 #define PNO_REPEAT 4
8470 #define PNO_FREQ_EXPO_MAX 2
8472 is_ssid_in_list(struct cfg80211_ssid *ssid, struct cfg80211_ssid *ssid_list, int count)
8476 if (!ssid || !ssid_list)
8479 for (i = 0; i < count; i++) {
8480 if (ssid->ssid_len == ssid_list[i].ssid_len) {
8481 if (strncmp(ssid->ssid, ssid_list[i].ssid, ssid->ssid_len) == 0)
8489 wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
8490 struct net_device *dev,
8491 struct cfg80211_sched_scan_request *request)
8493 ushort pno_time = PNO_TIME;
8494 int pno_repeat = PNO_REPEAT;
8495 int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
8496 wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
8497 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8498 struct cfg80211_ssid *ssid = NULL;
8499 struct cfg80211_ssid *hidden_ssid_list = NULL;
8505 WL_ERR(("Sched scan request was NULL\n"));
8509 WL_DBG(("Enter \n"));
8510 WL_PNO((">>> SCHED SCAN START\n"));
8511 WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
8512 request->n_match_sets, request->n_ssids));
8513 WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
8514 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
8517 if (!request->n_ssids || !request->n_match_sets) {
8518 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
8522 memset(&ssids_local, 0, sizeof(ssids_local));
8524 if (request->n_ssids > 0) {
8525 hidden_ssid_list = request->ssids;
8528 for (i = 0; i < request->n_match_sets && ssid_cnt < MAX_PFN_LIST_COUNT; i++) {
8529 ssid = &request->match_sets[i].ssid;
8530 /* No need to include null ssid */
8531 if (ssid->ssid_len) {
8532 memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid, ssid->ssid_len);
8533 ssids_local[ssid_cnt].SSID_len = ssid->ssid_len;
8534 if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
8535 ssids_local[ssid_cnt].hidden = TRUE;
8536 WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
8538 ssids_local[ssid_cnt].hidden = FALSE;
8539 WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid->ssid));
8546 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, ssid_cnt,
8547 pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
8548 WL_ERR(("PNO setup failed!! ret=%d \n", ret));
8551 cfg->sched_scan_req = request;
8560 wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
8562 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8564 WL_DBG(("Enter \n"));
8565 WL_PNO((">>> SCHED SCAN STOP\n"));
8567 if (dhd_dev_pno_stop_for_ssid(dev) < 0)
8568 WL_ERR(("PNO Stop for SSID failed"));
8570 if (cfg->scan_request && cfg->sched_scan_running) {
8571 WL_PNO((">>> Sched scan running. Aborting it..\n"));
8572 wl_notify_escan_complete(cfg, dev, true, true);
8575 cfg->sched_scan_req = NULL;
8576 cfg->sched_scan_running = FALSE;
8580 #endif /* WL_SCHED_SCAN */
8582 #ifdef WL_SUPPORT_ACS
8584 * Currently the dump_obss IOVAR is returning string as output so we need to
8585 * parse the output buffer in an unoptimized way. Going forward if we get the
8586 * IOVAR output in binary format this method can be optimized
8588 static int wl_parse_dump_obss(char *buf, struct wl_dump_survey *survey)
8592 char delim[] = " \n";
8594 token = strsep(&buf, delim);
8595 while (token != NULL) {
8596 if (!strcmp(token, "OBSS")) {
8597 for (i = 0; i < OBSS_TOKEN_IDX; i++)
8598 token = strsep(&buf, delim);
8599 survey->obss = simple_strtoul(token, NULL, 10);
8602 if (!strcmp(token, "IBSS")) {
8603 for (i = 0; i < IBSS_TOKEN_IDX; i++)
8604 token = strsep(&buf, delim);
8605 survey->ibss = simple_strtoul(token, NULL, 10);
8608 if (!strcmp(token, "TXDur")) {
8609 for (i = 0; i < TX_TOKEN_IDX; i++)
8610 token = strsep(&buf, delim);
8611 survey->tx = simple_strtoul(token, NULL, 10);
8614 if (!strcmp(token, "Category")) {
8615 for (i = 0; i < CTG_TOKEN_IDX; i++)
8616 token = strsep(&buf, delim);
8617 survey->no_ctg = simple_strtoul(token, NULL, 10);
8620 if (!strcmp(token, "Packet")) {
8621 for (i = 0; i < PKT_TOKEN_IDX; i++)
8622 token = strsep(&buf, delim);
8623 survey->no_pckt = simple_strtoul(token, NULL, 10);
8626 if (!strcmp(token, "Opp(time):")) {
8627 for (i = 0; i < IDLE_TOKEN_IDX; i++)
8628 token = strsep(&buf, delim);
8629 survey->idle = simple_strtoul(token, NULL, 10);
8632 token = strsep(&buf, delim);
8638 static int wl_dump_obss(struct net_device *ndev, cca_msrmnt_query req,
8639 struct wl_dump_survey *survey)
8641 cca_stats_n_flags *results;
8645 buf = kzalloc(sizeof(char) * WLC_IOCTL_MAXLEN, GFP_KERNEL);
8646 if (unlikely(!buf)) {
8647 WL_ERR(("%s: buf alloc failed\n", __func__));
8651 retry = IOCTL_RETRY_COUNT;
8653 err = wldev_iovar_getbuf(ndev, "dump_obss", &req, sizeof(req),
8654 buf, WLC_IOCTL_MAXLEN, NULL);
8658 WL_DBG(("attempt = %d, err = %d, \n",
8659 (IOCTL_RETRY_COUNT - retry), err));
8663 WL_ERR(("failure, dump_obss IOVAR failed\n"));
8668 results = (cca_stats_n_flags *)(buf);
8669 wl_parse_dump_obss(results->buf, survey);
8678 static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
8679 int idx, struct survey_info *info)
8681 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8682 struct wl_dump_survey *survey;
8683 struct ieee80211_supported_band *band;
8684 struct ieee80211_channel*chan;
8685 cca_msrmnt_query req;
8686 int val, err, noise, retry;
8688 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8689 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
8692 band = wiphy->bands[IEEE80211_BAND_2GHZ];
8693 if (band && idx >= band->n_channels) {
8694 idx -= band->n_channels;
8698 if (!band || idx >= band->n_channels) {
8699 /* Move to 5G band */
8700 band = wiphy->bands[IEEE80211_BAND_5GHZ];
8701 if (idx >= band->n_channels) {
8706 chan = &band->channels[idx];
8707 /* Setting current channel to the requested channel */
8708 if ((err = wl_cfg80211_set_channel(wiphy, ndev, chan,
8709 NL80211_CHAN_HT20) < 0)) {
8710 WL_ERR(("Set channel failed \n"));
8716 err = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
8717 sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
8718 &cfg->ioctl_buf_sync);
8720 WL_ERR(("set 'mpc' failed, error = %d\n", err));
8723 /* Set interface up, explicitly. */
8725 err = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
8727 WL_ERR(("set interface up failed, error = %d\n", err));
8731 /* Get noise value */
8732 retry = IOCTL_RETRY_COUNT;
8734 err = wldev_ioctl(ndev, WLC_GET_PHY_NOISE, &noise,
8735 sizeof(noise), false);
8739 WL_DBG(("attempt = %d, err = %d, \n",
8740 (IOCTL_RETRY_COUNT - retry), err));
8744 WL_ERR(("Get Phy Noise failed, error = %d\n", err));
8745 noise = CHAN_NOISE_DUMMY;
8748 survey = (struct wl_dump_survey *) kzalloc(sizeof(struct wl_dump_survey),
8750 if (unlikely(!survey)) {
8751 WL_ERR(("%s: alloc failed\n", __func__));
8755 /* Start Measurement for obss stats on current channel */
8756 req.msrmnt_query = 0;
8757 req.time_req = ACS_MSRMNT_DELAY;
8758 if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
8763 * Wait for the meaurement to complete, adding a buffer value of 10 to take
8764 * into consideration any delay in IOVAR completion
8766 msleep(ACS_MSRMNT_DELAY + 10);
8768 /* Issue IOVAR to collect measurement results */
8769 req.msrmnt_query = 1;
8770 if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
8774 info->channel = chan;
8775 info->noise = noise;
8776 info->channel_time = ACS_MSRMNT_DELAY;
8777 info->channel_time_busy = ACS_MSRMNT_DELAY - survey->idle;
8778 info->channel_time_rx = survey->obss + survey->ibss + survey->no_ctg +
8780 info->channel_time_tx = survey->tx;
8781 info->filled = SURVEY_INFO_NOISE_DBM |SURVEY_INFO_CHANNEL_TIME |
8782 SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_RX |
8783 SURVEY_INFO_CHANNEL_TIME_TX;
8791 #endif /* WL_SUPPORT_ACS */
8793 static struct cfg80211_ops wl_cfg80211_ops = {
8794 .add_virtual_intf = wl_cfg80211_add_virtual_iface,
8795 .del_virtual_intf = wl_cfg80211_del_virtual_iface,
8796 .change_virtual_intf = wl_cfg80211_change_virtual_iface,
8797 #if defined(WL_CFG80211_P2P_DEV_IF)
8798 .start_p2p_device = wl_cfgp2p_start_p2p_device,
8799 .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
8800 #endif /* WL_CFG80211_P2P_DEV_IF */
8801 .scan = wl_cfg80211_scan,
8802 .set_wiphy_params = wl_cfg80211_set_wiphy_params,
8803 .join_ibss = wl_cfg80211_join_ibss,
8804 .leave_ibss = wl_cfg80211_leave_ibss,
8805 .get_station = wl_cfg80211_get_station,
8806 .set_tx_power = wl_cfg80211_set_tx_power,
8807 .get_tx_power = wl_cfg80211_get_tx_power,
8808 .add_key = wl_cfg80211_add_key,
8809 .del_key = wl_cfg80211_del_key,
8810 .get_key = wl_cfg80211_get_key,
8811 .set_default_key = wl_cfg80211_config_default_key,
8812 .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
8813 .set_power_mgmt = wl_cfg80211_set_power_mgmt,
8814 .connect = wl_cfg80211_connect,
8815 .disconnect = wl_cfg80211_disconnect,
8816 .suspend = wl_cfg80211_suspend,
8817 .resume = wl_cfg80211_resume,
8818 .set_pmksa = wl_cfg80211_set_pmksa,
8819 .del_pmksa = wl_cfg80211_del_pmksa,
8820 .flush_pmksa = wl_cfg80211_flush_pmksa,
8821 .remain_on_channel = wl_cfg80211_remain_on_channel,
8822 .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
8823 .mgmt_tx = wl_cfg80211_mgmt_tx,
8824 .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
8825 .change_bss = wl_cfg80211_change_bss,
8826 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
8827 .set_channel = wl_cfg80211_set_channel,
8829 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
8830 .set_beacon = wl_cfg80211_add_set_beacon,
8831 .add_beacon = wl_cfg80211_add_set_beacon,
8833 .change_beacon = wl_cfg80211_change_beacon,
8834 .start_ap = wl_cfg80211_start_ap,
8835 .stop_ap = wl_cfg80211_stop_ap,
8837 #ifdef WL_SCHED_SCAN
8838 .sched_scan_start = wl_cfg80211_sched_scan_start,
8839 .sched_scan_stop = wl_cfg80211_sched_scan_stop,
8840 #endif /* WL_SCHED_SCAN */
8841 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
8843 .del_station = wl_cfg80211_del_station,
8844 .change_station = wl_cfg80211_change_station,
8845 .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
8846 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
8847 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
8848 .tdls_mgmt = wl_cfg80211_tdls_mgmt,
8849 .tdls_oper = wl_cfg80211_tdls_oper,
8851 #ifdef WL_SUPPORT_ACS
8852 .dump_survey = wl_cfg80211_dump_survey,
8853 #endif /* WL_SUPPORT_ACS */
8854 #ifdef WL_CFG80211_ACL
8855 .set_mac_acl = wl_cfg80211_set_mac_acl,
8856 #endif /* WL_CFG80211_ACL */
8859 s32 wl_mode_to_nl80211_iftype(s32 mode)
8865 return NL80211_IFTYPE_STATION;
8867 return NL80211_IFTYPE_ADHOC;
8869 return NL80211_IFTYPE_AP;
8871 return NL80211_IFTYPE_UNSPECIFIED;
8877 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
8878 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8879 #define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
8881 #define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
8882 #endif /* kernel version < 3.9.0 */
8885 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
8886 WL_CFG80211_REG_NOTIFIER()
8888 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
8892 if (!request || !cfg) {
8893 WL_ERR(("Invalid arg\n"));
8894 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8898 #endif /* kernel version < 3.9.0 */
8901 WL_DBG(("ccode: %c%c Initiator: %d\n",
8902 request->alpha2[0], request->alpha2[1], request->initiator));
8904 /* We support only REGDOM_SET_BY_USER as of now */
8905 if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
8906 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
8907 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
8908 request->initiator));
8909 /* in case of no supported country by regdb
8910 lets driver setup platform default Locale
8914 WL_ERR(("Set country code %c%c from %s\n",
8915 request->alpha2[0], request->alpha2[1],
8916 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
8918 if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2,
8919 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false),
8921 WL_ERR(("set country Failed :%d\n", ret));
8924 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8928 #endif /* kernel version < 3.9.0 */
8930 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
8933 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8934 static const struct wiphy_wowlan_support brcm_wowlan_support = {
8935 .flags = WIPHY_WOWLAN_ANY,
8936 .n_patterns = WL_WOWLAN_MAX_PATTERNS,
8937 .pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN,
8938 .pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN,
8939 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
8940 .max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN,
8941 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
8943 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
8945 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8946 static struct cfg80211_wowlan brcm_wowlan_config = {
8948 .gtk_rekey_failure = true,
8949 .eap_identity_req = true,
8950 .four_way_handshake = true,
8952 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
8954 #endif /* CONFIG_PM */
8956 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *context)
8959 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
8960 dhd_pub_t *dhd = (dhd_pub_t *)context;
8964 WL_ERR(("DHD is NULL!!"));
8971 wiphy_new(&wl_cfg80211_ops, sizeof(struct bcm_cfg80211));
8972 if (unlikely(!wdev->wiphy)) {
8973 WL_ERR(("Couldn not allocate wiphy device\n"));
8977 set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
8978 wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
8979 /* Report how many SSIDs Driver can support per Scan request */
8980 wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
8981 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
8982 #ifdef WL_SCHED_SCAN
8983 wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
8984 wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
8985 wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
8986 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8987 #endif /* WL_SCHED_SCAN */
8988 wdev->wiphy->interface_modes =
8989 BIT(NL80211_IFTYPE_STATION)
8990 | BIT(NL80211_IFTYPE_ADHOC)
8991 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
8992 | BIT(NL80211_IFTYPE_MONITOR)
8993 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
8994 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
8995 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8996 | BIT(NL80211_IFTYPE_P2P_GO)
8997 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
8998 #if defined(WL_CFG80211_P2P_DEV_IF)
8999 | BIT(NL80211_IFTYPE_P2P_DEVICE)
9000 #endif /* WL_CFG80211_P2P_DEV_IF */
9001 | BIT(NL80211_IFTYPE_AP);
9003 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
9004 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
9005 WL_DBG(("Setting interface combinations for common mode\n"));
9006 wdev->wiphy->iface_combinations = common_iface_combinations;
9007 wdev->wiphy->n_iface_combinations =
9008 ARRAY_SIZE(common_iface_combinations);
9009 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
9011 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
9013 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9014 wdev->wiphy->cipher_suites = __wl_cipher_suites;
9015 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
9016 wdev->wiphy->max_remain_on_channel_duration = 5000;
9017 wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
9018 #ifndef WL_POWERSAVE_DISABLED
9019 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
9021 wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
9022 #endif /* !WL_POWERSAVE_DISABLED */
9023 wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
9024 WIPHY_FLAG_4ADDR_AP |
9025 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
9026 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
9028 WIPHY_FLAG_4ADDR_STATION;
9029 #if ((defined(ROAM_ENABLE) || defined(BCMFW_ROAM_ENABLE)) && (LINUX_VERSION_CODE >= \
9030 KERNEL_VERSION(3, 2, 0)))
9032 * If FW ROAM flag is advertised, upper layer wouldn't provide
9033 * the bssid & freq in the connect command. This will result a
9034 * delay in initial connection time due to firmware doing a full
9035 * channel scan to figure out the channel & bssid. However kernel
9036 * ver >= 3.15, provides bssid_hint & freq_hint and hence kernel
9037 * ver >= 3.15 won't have any issue. So if this flags need to be
9038 * advertised for kernel < 3.15, suggest to use RCC along with it
9039 * to avoid the initial connection delay.
9041 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
9043 #ifdef UNSET_FW_ROAM_WIPHY_FLAG
9044 wdev->wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_FW_ROAM;
9045 #endif /* UNSET_FW_ROAM_WIPHY_FLAG */
9046 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
9047 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
9048 WIPHY_FLAG_OFFCHAN_TX;
9050 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
9052 /* From 3.4 kernel ownards AP_SME flag can be advertised
9053 * to remove the patch from supplicant
9055 wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
9057 #ifdef WL_CFG80211_ACL
9058 /* Configure ACL capabilities. */
9059 wdev->wiphy->max_acl_mac_addrs = MAX_NUM_MAC_FILT;
9062 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9063 /* Supplicant distinguish between the SoftAP mode and other
9064 * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
9065 * response frame from Supplicant MR1 and Kernel 3.4.0 or
9066 * later version. To add Vendor specific IE into the
9067 * probe response frame in case of SoftAP mode,
9068 * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
9070 if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) {
9071 wdev->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
9072 wdev->wiphy->probe_resp_offload = 0;
9075 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
9077 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
9078 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
9081 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
9083 * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
9084 * disconnection of connected network before suspend. So a dummy wowlan
9085 * filter is configured for kernels linux-3.8 and above.
9088 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9089 wdev->wiphy->wowlan = &brcm_wowlan_support;
9090 /* If this is not provided cfg stack will get disconnect
9093 //wdev->wiphy->wowlan_config = &brcm_wowlan_config;
9095 wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
9096 wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
9097 wdev->wiphy->wowlan.pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN;
9098 wdev->wiphy->wowlan.pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN;
9099 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9100 wdev->wiphy->wowlan.max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN;
9101 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
9102 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
9103 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
9105 WL_DBG(("Registering custom regulatory)\n"));
9106 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
9107 wdev->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
9109 wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
9111 wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
9112 #if defined(WL_VENDOR_EXT_SUPPORT)
9113 WL_ERR(("Registering Vendor80211\n"));
9114 err = wl_cfgvendor_attach(wdev->wiphy);
9115 if (unlikely(err < 0)) {
9116 WL_ERR(("Couldn not attach vendor commands (%d)\n", err));
9118 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
9119 /* Now we can register wiphy with cfg80211 module */
9120 err = wiphy_register(wdev->wiphy);
9121 if (unlikely(err < 0)) {
9122 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
9123 wiphy_free(wdev->wiphy);
9126 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
9127 KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
9128 wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
9134 static void wl_free_wdev(struct bcm_cfg80211 *cfg)
9136 struct wireless_dev *wdev = cfg->wdev;
9137 struct wiphy *wiphy = NULL;
9139 WL_ERR(("wdev is invalid\n"));
9143 wiphy = wdev->wiphy;
9145 #if defined(WL_VENDOR_EXT_SUPPORT)
9146 wl_cfgvendor_detach(wdev->wiphy);
9147 #endif /* if defined(WL_VENDOR_EXT_SUPPORT) */
9148 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9149 /* Reset wowlan & wowlan_config before Unregister to avoid Kernel Panic */
9150 WL_DBG(("wl_free_wdev Clearing wowlan Config \n"));
9151 wdev->wiphy->wowlan = NULL;
9152 wdev->wiphy->wowlan_config = NULL;
9153 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
9154 wiphy_unregister(wdev->wiphy);
9155 wdev->wiphy->dev.parent = NULL;
9159 wl_delete_all_netinfo(cfg);
9163 /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
9164 * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
9168 static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
9170 struct wl_scan_results *bss_list;
9171 struct wl_bss_info *bi = NULL; /* must be initialized */
9174 #if defined(RSSIAVG)
9175 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
9178 #if defined(BSSCACHE)
9179 wl_bss_cache_t *node;
9182 bss_list = cfg->bss_list;
9184 /* Free cache in p2p scanning*/
9185 if (p2p_is_on(cfg) && p2p_scan(cfg)) {
9186 #if defined(RSSIAVG)
9187 wl_free_rssi_cache(&g_rssi_cache_ctrl);
9189 #if defined(BSSCACHE)
9190 wl_free_bss_cache(&g_bss_cache_ctrl);
9194 /* Delete disconnected cache */
9195 #if defined(BSSCACHE)
9196 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9197 #if defined(RSSIAVG)
9198 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9200 if (cfg->p2p_disconnected == 0)
9201 memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
9205 #if defined(RSSIAVG)
9206 wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
9208 wl_update_connected_rssi_cache(ndev, &g_rssi_cache_ctrl, &rssi);
9210 #if defined(BSSCACHE)
9211 wl_update_bss_cache(&g_bss_cache_ctrl,
9212 #if defined(RSSIAVG)
9218 /* delete dirty cache */
9219 #if defined(RSSIAVG)
9220 wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
9221 wl_reset_rssi_cache(&g_rssi_cache_ctrl);
9223 #if defined(BSSCACHE)
9224 wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
9225 wl_reset_bss_cache(&g_bss_cache_ctrl);
9228 #if defined(BSSCACHE)
9229 if (cfg->p2p_disconnected > 0) {
9230 // terence 20130703: Fix for wrong group_capab (timing issue)
9231 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9232 #if defined(RSSIAVG)
9233 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9236 WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
9237 node = g_bss_cache_ctrl.m_cache_head;
9238 for (i=0; node && i<WL_AP_MAX; i++) {
9239 bi = node->results.bss_info;
9240 err = wl_inform_single_bss(cfg, bi, false);
9244 WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
9245 bi = next_bss(bss_list, bi);
9246 for_each_bss(bss_list, bi, i) {
9247 if (cfg->p2p_disconnected > 0 && !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN))
9249 err = wl_inform_single_bss(cfg, bi, false);
9253 if (cfg->p2p_disconnected > 0) {
9254 // terence 20130703: Fix for wrong group_capab (timing issue)
9255 cfg->p2p_disconnected++;
9256 if (cfg->p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1) {
9257 cfg->p2p_disconnected = 0;
9258 memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
9265 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam)
9267 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9268 struct ieee80211_mgmt *mgmt;
9269 struct ieee80211_channel *channel;
9270 struct ieee80211_supported_band *band;
9271 struct wl_cfg80211_bss_info *notif_bss_info;
9272 struct wl_scan_req *sr = wl_to_sr(cfg);
9273 struct beacon_proberesp *beacon_proberesp;
9274 struct cfg80211_bss *cbss = NULL;
9281 if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
9282 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
9285 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
9286 notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
9287 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
9288 if (unlikely(!notif_bss_info)) {
9289 WL_ERR(("notif_bss_info alloc failed\n"));
9292 mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
9293 notif_bss_info->channel =
9294 wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
9296 if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
9297 band = wiphy->bands[IEEE80211_BAND_2GHZ];
9299 band = wiphy->bands[IEEE80211_BAND_5GHZ];
9301 WL_ERR(("No valid band\n"));
9302 kfree(notif_bss_info);
9305 notif_bss_info->rssi = dtoh16(bi->RSSI);
9306 #if defined(RSSIAVG)
9307 notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
9308 if (notif_bss_info->rssi == RSSI_MINVAL)
9309 notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
9311 #if defined(RSSIOFFSET)
9312 notif_bss_info->rssi = wl_update_rssi_offset(bcmcfg_to_prmry_ndev(cfg), notif_bss_info->rssi);
9314 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
9315 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
9316 notif_bss_info->rssi = MIN(notif_bss_info->rssi, RSSI_MAXVAL);
9318 memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
9319 mgmt_type = cfg->active_scan ?
9320 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
9321 if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
9322 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
9324 beacon_proberesp = cfg->active_scan ?
9325 (struct beacon_proberesp *)&mgmt->u.probe_resp :
9326 (struct beacon_proberesp *)&mgmt->u.beacon;
9327 beacon_proberesp->timestamp = 0;
9328 beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
9329 beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
9331 wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length, roam);
9332 wl_mrg_ie(cfg, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
9333 wl_cp_ie(cfg, beacon_proberesp->variable, WL_BSS_INFO_MAX -
9334 offsetof(struct wl_cfg80211_bss_info, frame_buf));
9335 notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
9336 u.beacon.variable) + wl_get_ielen(cfg);
9337 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9338 freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
9341 freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
9344 WL_ERR(("Invalid channel, fail to change channel to freq\n"));
9345 kfree(notif_bss_info);
9348 channel = ieee80211_get_channel(wiphy, freq);
9349 WL_SCAN(("BSSID %pM, channel %2d, rssi %3d, capa 0x04%x, mgmt_type %d, "
9350 "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel,
9351 notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
9352 notif_bss_info->frame_len, bi->SSID));
9353 if (unlikely(!channel)) {
9354 WL_ERR(("ieee80211_get_channel error, freq=%d, channel=%d\n",
9355 freq, notif_bss_info->channel));
9356 kfree(notif_bss_info);
9360 signal = notif_bss_info->rssi * 100;
9361 if (!mgmt->u.probe_resp.timestamp) {
9362 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
9364 get_monotonic_boottime(&ts);
9365 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
9366 + ts.tv_nsec / 1000;
9369 do_gettimeofday(&tv);
9370 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
9376 cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
9377 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
9378 if (unlikely(!cbss)) {
9379 WL_ERR(("cfg80211_inform_bss_frame error\n"));
9380 kfree(notif_bss_info);
9385 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9386 cfg80211_put_bss(wiphy, cbss);
9388 cfg80211_put_bss(cbss);
9389 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
9390 kfree(notif_bss_info);
9394 static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, struct net_device *ndev)
9396 u32 event = ntoh32(e->event_type);
9397 u32 status = ntoh32(e->status);
9398 u16 flags = ntoh16(e->flags);
9400 WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
9401 if (event == WLC_E_SET_SSID) {
9402 if (status == WLC_E_STATUS_SUCCESS) {
9403 if (!wl_is_ibssmode(cfg, ndev))
9406 } else if (event == WLC_E_LINK) {
9407 if (flags & WLC_EVENT_MSG_LINK)
9411 WL_DBG(("wl_is_linkup false\n"));
9415 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9417 u32 event = ntoh32(e->event_type);
9418 u16 flags = ntoh16(e->flags);
9420 if (event == WLC_E_DEAUTH_IND ||
9421 event == WLC_E_DISASSOC_IND ||
9422 event == WLC_E_DISASSOC ||
9423 event == WLC_E_DEAUTH) {
9424 #if (WL_DBG_LEVEL > 0)
9425 WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
9426 #endif /* (WL_DBG_LEVEL > 0) */
9428 } else if (event == WLC_E_LINK) {
9429 if (!(flags & WLC_EVENT_MSG_LINK)) {
9430 #if (WL_DBG_LEVEL > 0)
9431 WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
9432 #endif /* (WL_DBG_LEVEL > 0) */
9440 static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9442 u32 event = ntoh32(e->event_type);
9443 u32 status = ntoh32(e->status);
9445 if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
9447 if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
9453 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
9454 * to AP/P2P GO via events. If this change is backported to kernel for which
9455 * this driver is being built, then define WL_CFG80211_STA_EVENT. You
9456 * should use this new/del sta event mechanism for BRCM supplicant >= 22.
9459 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9460 const wl_event_msg_t *e, void *data)
9463 u32 event = ntoh32(e->event_type);
9464 u32 reason = ntoh32(e->reason);
9465 u32 len = ntoh32(e->datalen);
9466 u32 status = ntoh32(e->status);
9468 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
9469 bool isfree = false;
9471 u8 bsscfgidx = e->bsscfgidx;
9477 struct ieee80211_supported_band *band;
9478 struct ether_addr da;
9479 struct ether_addr bssid;
9480 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9483 struct station_info sinfo;
9486 WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
9487 /* if link down, bsscfg is disabled. */
9488 if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
9489 wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) {
9490 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
9491 WL_INFORM(("AP mode link down !! \n"));
9492 complete(&cfg->iface_disable);
9496 if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
9497 (reason == WLC_E_REASON_INITIAL_ASSOC) &&
9498 (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) {
9499 if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
9500 /* AP/GO brought up successfull in firmware */
9501 WL_ERR(("** AP/GO Link up event **\n"));
9502 wl_set_drv_status(cfg, AP_CREATED, ndev);
9503 wake_up_interruptible(&cfg->netif_change_event);
9508 if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
9509 WL_ERR(("event %s(%d) status %d reason %d\n",
9510 bcmevent_get_name(event), event, ntoh32(e->status), reason));
9513 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
9514 WL_DBG(("Enter \n"));
9515 if (!len && (event == WLC_E_DEAUTH)) {
9516 len = 2; /* reason code field */
9520 body = kzalloc(len, GFP_KERNEL);
9523 WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
9527 memset(&bssid, 0, ETHER_ADDR_LEN);
9528 WL_DBG(("Enter event %d ndev %p\n", event, ndev));
9529 if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
9534 memcpy(body, data, len);
9536 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
9537 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
9538 memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
9539 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
9541 case WLC_E_ASSOC_IND:
9544 case WLC_E_REASSOC_IND:
9545 fc = FC_REASSOC_REQ;
9547 case WLC_E_DISASSOC_IND:
9550 case WLC_E_DEAUTH_IND:
9560 if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
9565 channel = dtoh32(ci.hw_channel);
9566 if (channel <= CH_MAX_2G_CHANNEL)
9567 band = wiphy->bands[IEEE80211_BAND_2GHZ];
9569 band = wiphy->bands[IEEE80211_BAND_5GHZ];
9571 WL_ERR(("No valid band\n"));
9576 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9577 freq = ieee80211_channel_to_frequency(channel);
9580 freq = ieee80211_channel_to_frequency(channel, band->band);
9583 err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
9584 &mgmt_frame, &len, body);
9589 if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
9590 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) && (LINUX_VERSION_CODE < \
9591 KERNEL_VERSION(3, 18, 0)))
9592 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9594 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
9595 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len);
9597 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9599 } else if (event == WLC_E_DISASSOC_IND) {
9600 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9601 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9603 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9605 } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
9606 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9607 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9609 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9618 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
9620 if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
9621 reason == DOT11_SC_SUCCESS) {
9622 /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
9623 * STATION_INFO_ASSOC_REQ_IES flag
9625 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
9626 sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
9627 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
9629 WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
9632 sinfo.assoc_req_ies = data;
9633 sinfo.assoc_req_ies_len = len;
9634 printf("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9635 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
9636 } else if (event == WLC_E_DISASSOC_IND) {
9637 printf("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9638 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
9639 } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
9640 printf("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9641 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
9647 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9648 #define MAX_ASSOC_REJECT_ERR_STATUS 5
9649 int wl_get_connect_failed_status(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9651 u32 status = ntoh32(e->status);
9653 cfg->assoc_reject_status = 0;
9655 if (status == WLC_E_STATUS_FAIL) {
9656 WL_ERR(("auth assoc status event=%d e->status %d e->reason %d \n",
9657 ntoh32(cfg->event_auth_assoc.event_type),
9658 (int)ntoh32(cfg->event_auth_assoc.status),
9659 (int)ntoh32(cfg->event_auth_assoc.reason)));
9661 switch ((int)ntoh32(cfg->event_auth_assoc.status)) {
9662 case WLC_E_STATUS_NO_ACK:
9663 cfg->assoc_reject_status = 1;
9665 case WLC_E_STATUS_FAIL:
9666 cfg->assoc_reject_status = 2;
9668 case WLC_E_STATUS_UNSOLICITED:
9669 cfg->assoc_reject_status = 3;
9671 case WLC_E_STATUS_TIMEOUT:
9672 cfg->assoc_reject_status = 4;
9674 case WLC_E_STATUS_ABORT:
9675 cfg->assoc_reject_status = 5;
9680 if (cfg->assoc_reject_status) {
9681 if (ntoh32(cfg->event_auth_assoc.event_type) == WLC_E_ASSOC) {
9682 cfg->assoc_reject_status += MAX_ASSOC_REJECT_ERR_STATUS;
9687 WL_ERR(("assoc_reject_status %d \n", cfg->assoc_reject_status));
9692 s32 wl_cfg80211_get_connect_failed_status(struct net_device *dev, char* cmd, int total_len)
9694 struct bcm_cfg80211 *cfg = NULL;
9695 int bytes_written = 0;
9703 memset(cmd, 0, total_len);
9704 bytes_written = snprintf(cmd, 30, "assoc_reject.status %d", cfg->assoc_reject_status);
9706 WL_ERR(("cmd: %s \n", cmd));
9708 return bytes_written;
9710 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
9713 wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9714 const wl_event_msg_t *e)
9716 u32 reason = ntoh32(e->reason);
9717 u32 event = ntoh32(e->event_type);
9718 struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
9719 WL_DBG(("event type : %d, reason : %d\n", event, reason));
9721 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9722 memcpy(&cfg->event_auth_assoc, e, sizeof(wl_event_msg_t));
9723 WL_ERR(("event=%d status %d reason %d \n",
9724 ntoh32(cfg->event_auth_assoc.event_type),
9725 ntoh32(cfg->event_auth_assoc.status),
9726 ntoh32(cfg->event_auth_assoc.reason)));
9727 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
9732 sec->auth_assoc_res_status = reason;
9737 WL_ERR(("sec is NULL\n"));
9742 wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9743 const wl_event_msg_t *e, void *data)
9746 u32 event = ntoh32(e->event_type);
9747 u16 flags = ntoh16(e->flags);
9748 u32 status = ntoh32(e->status);
9750 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9751 struct ieee80211_channel *channel = NULL;
9752 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9755 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
9757 if (event == WLC_E_JOIN) {
9758 WL_DBG(("joined in IBSS network\n"));
9760 if (event == WLC_E_START) {
9761 WL_DBG(("started IBSS network\n"));
9763 if (event == WLC_E_JOIN || event == WLC_E_START ||
9764 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
9765 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9766 err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
9767 if (unlikely(err)) {
9768 WL_ERR(("Could not get chanspec %d\n", err));
9771 chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
9772 band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
9773 freq = ieee80211_channel_to_frequency(chan, band);
9774 channel = ieee80211_get_channel(wiphy, freq);
9775 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
9776 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
9777 /* ROAM or Redundant */
9778 u8 *cur_bssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
9779 if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
9780 WL_DBG(("IBSS connected event from same BSSID("
9781 MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
9784 WL_INFORM(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
9785 MAC2STRDBG(cur_bssid), MAC2STRDBG((const u8 *)&e->addr)));
9786 wl_get_assoc_ies(cfg, ndev);
9787 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
9788 wl_update_bss_info(cfg, ndev, false);
9789 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9790 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
9792 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
9796 /* New connection */
9797 WL_INFORM(("IBSS connected to " MACDBG "\n",
9798 MAC2STRDBG((const u8 *)&e->addr)));
9800 wl_get_assoc_ies(cfg, ndev);
9801 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
9802 wl_update_bss_info(cfg, ndev, false);
9803 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9804 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
9806 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
9808 wl_set_drv_status(cfg, CONNECTED, ndev);
9810 wl_update_prof(cfg, ndev, NULL, (const void *)&active, WL_PROF_ACT);
9812 } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
9813 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
9814 wl_clr_drv_status(cfg, CONNECTED, ndev);
9816 wl_init_prof(cfg, ndev);
9818 else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
9819 WL_DBG(("no action - join fail (IBSS mode)\n"));
9822 WL_DBG(("no action (IBSS mode)\n"));
9827 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9828 #define WiFiALL_OUI "\x50\x6F\x9A" /* Wi-FiAll OUI */
9829 #define WiFiALL_OUI_LEN 3
9830 #define WiFiALL_OUI_TYPE 16
9832 int wl_get_bss_info(struct bcm_cfg80211 *cfg, struct net_device *dev, uint8 *mac)
9835 struct wl_bss_info *bi;
9836 uint8 eabuf[ETHER_ADDR_LEN];
9837 u32 rate, channel, freq, supported_rate, nss = 0, mcs_map, mode_80211 = 0;
9841 struct wiphy *wiphy;
9842 struct cfg80211_bss *bss;
9843 bcm_tlv_t *interworking_ie = NULL;
9844 bcm_tlv_t *tlv_ie = NULL;
9845 bcm_tlv_t *vht_ie = NULL;
9847 int16 ie_11u_rel_num = -1, ie_mu_mimo_cap = -1;
9848 u32 i, remained_len, count = 0;
9849 char roam_count_str[4], akm_str[4];
9852 /* get BSS information */
9854 strncpy(cfg->bss_info, "x x x x x x x x x x x x x", GET_BSS_INFO_LEN);
9856 *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
9858 err = wldev_ioctl(dev, WLC_GET_BSS_INFO, cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
9859 if (unlikely(err)) {
9860 WL_ERR(("Could not get bss info %d\n", err));
9861 cfg->roam_count = 0;
9866 WL_ERR(("mac is null \n"));
9867 cfg->roam_count = 0;
9871 memcpy(eabuf, mac, ETHER_ADDR_LEN);
9873 bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
9874 channel = wf_chspec_ctlchan(bi->chanspec);
9876 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9877 freq = ieee80211_channel_to_frequency(channel);
9880 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
9882 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
9886 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
9888 WL_ERR(("Could not get rate (%d)\n", err));
9889 snprintf(rate_str, sizeof(rate_str), "x"); // Unknown
9892 rate = dtoh32(rate);
9893 snprintf(rate_str, sizeof(rate_str), "%d", (rate/2));
9896 //supported maximum rate
9897 supported_rate = (bi->rateset.rates[bi->rateset.count - 1] & 0x7f) / 2;
9899 if (supported_rate < 12) {
9900 mode_80211 = 0; //11b maximum rate is 11Mbps. 11b mode
9902 //It's not HT Capable case.
9904 mode_80211 = 3; // 11a mode
9906 mode_80211 = 1; // 11g mode
9911 /* check Rx MCS Map for HT */
9914 for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
9916 if (i == MAX_STREAMS_SUPPORTED-1) {
9919 if (bi->basic_mcs[i] & bitmap) {
9928 for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
9929 mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
9930 if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
9940 wiphy = bcmcfg_to_wiphy(cfg);
9941 bss = cfg80211_get_bss(wiphy, NULL, eabuf,
9942 bi->SSID, strlen(bi->SSID), WLAN_CAPABILITY_ESS,
9943 WLAN_CAPABILITY_ESS);
9946 WL_ERR(("Could not find the AP\n"));
9948 #if defined(WL_CFG80211_P2P_DEV_IF)
9949 ie = (u8 *)bss->ies->data;
9950 ie_len = bss->ies->len;
9952 ie = bss->information_elements;
9953 ie_len = bss->len_information_elements;
9954 #endif /* WL_CFG80211_P2P_DEV_IF */
9962 if ((vht_ie = bcm_parse_tlvs(ie, (u32)ie_len,
9963 DOT11_MNG_VHT_CAP_ID)) != NULL) {
9964 ie_mu_mimo_cap = (vht_ie->data[2] & 0x08) >> 3;
9968 if ((interworking_ie = bcm_parse_tlvs(ie, (u32)ie_len,
9969 DOT11_MNG_INTERWORKING_ID)) != NULL) {
9970 if ((tlv_ie = bcm_parse_tlvs(ie, (u32)ie_len, DOT11_MNG_VS_ID)) != NULL) {
9971 remained_len = ie_len;
9974 if (count > MAX_VNDR_IE_NUMBER)
9977 if (tlv_ie->id == DOT11_MNG_VS_ID) {
9978 vndrie = (vndr_ie_t *) tlv_ie;
9980 if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
9981 WL_ERR(("%s: invalid vndr ie."
9982 "length is too small %d\n",
9983 __FUNCTION__, vndrie->len));
9987 if (!bcmp(vndrie->oui,
9988 (u8*)WiFiALL_OUI, WiFiALL_OUI_LEN) &&
9989 (vndrie->data[0] == WiFiALL_OUI_TYPE))
9991 WL_ERR(("Found Wi-FiAll OUI oui.\n"));
9992 ie_11u_rel_num = vndrie->data[1];
9993 ie_11u_rel_num = (ie_11u_rel_num & 0xf0)>>4;
9994 ie_11u_rel_num += 1;
10000 tlv_ie = bcm_next_tlv(tlv_ie, &remained_len);
10006 for (i = 0; i < bi->SSID_len; i++) {
10007 if (bi->SSID[i] == ' ') {
10012 //0 : None, 1 : OKC, 2 : FT, 3 : CCKM
10013 err = wldev_iovar_getint(dev, "wpa_auth", &val);
10014 if (unlikely(err)) {
10015 WL_ERR(("could not get wpa_auth (%d)\n", err));
10016 snprintf(akm_str, sizeof(akm_str), "x"); // Unknown
10018 WL_ERR(("wpa_auth val %d \n", val));
10019 #if defined(BCMEXTCCX)
10020 if (val & (WPA_AUTH_CCKM | WPA2_AUTH_CCKM)) {
10021 snprintf(akm_str, sizeof(akm_str), "3");
10024 if (val & WPA2_AUTH_FT) {
10025 snprintf(akm_str, sizeof(akm_str), "2");
10026 } else if (val & (WPA_AUTH_UNSPECIFIED | WPA2_AUTH_UNSPECIFIED)) {
10027 snprintf(akm_str, sizeof(akm_str), "1");
10029 snprintf(akm_str, sizeof(akm_str), "0");
10033 if (cfg->roam_offload) {
10034 snprintf(roam_count_str, sizeof(roam_count_str), "x"); // Unknown
10036 snprintf(roam_count_str, sizeof(roam_count_str), "%d", cfg->roam_count);
10038 cfg->roam_count = 0;
10040 WL_ERR(("BSSID:" MACDBG " SSID %s \n", MAC2STRDBG(eabuf), bi->SSID));
10041 WL_ERR(("freq:%d, BW:%s, RSSI:%d dBm, Rate:%d Mbps, 11mode:%d, stream:%d,"
10042 "MU-MIMO:%d, Passpoint:%d, SNR:%d, Noise:%d, \n"
10043 "akm:%s roam:%s \n",
10044 freq, wf_chspec_to_bw_str(bi->chanspec),
10045 dtoh32(bi->RSSI), (rate / 2), mode_80211, nss,
10046 ie_mu_mimo_cap, ie_11u_rel_num, bi->SNR, bi->phy_noise,
10047 akm_str, roam_count_str));
10050 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
10051 "%02x:%02x:%02x %d %s %d %s %d %d %d %d %d %d %s %s",
10052 eabuf[0], eabuf[1], eabuf[2],
10053 freq, wf_chspec_to_bw_str(bi->chanspec),
10054 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
10055 ie_mu_mimo_cap, ie_11u_rel_num,
10056 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
10058 //ie_mu_mimo_cap and ie_11u_rel_num is unknow.
10059 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
10060 "%02x:%02x:%02x %d %s %d %s %d %d x x %d %d %s %s",
10061 eabuf[0], eabuf[1], eabuf[2],
10062 freq, wf_chspec_to_bw_str(bi->chanspec),
10063 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
10064 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
10071 s32 wl_cfg80211_get_bss_info(struct net_device *dev, char* cmd, int total_len)
10073 struct bcm_cfg80211 *cfg = NULL;
10081 memset(cmd, 0, total_len);
10082 memcpy(cmd, cfg->bss_info, GET_BSS_INFO_LEN);
10084 WL_ERR(("cmd: %s \n", cmd));
10086 return GET_BSS_INFO_LEN;
10089 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10092 wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10093 const wl_event_msg_t *e, void *data)
10096 struct net_device *ndev = NULL;
10098 u32 event = ntoh32(e->event_type);
10099 struct wiphy *wiphy = NULL;
10100 struct cfg80211_bss *bss = NULL;
10101 struct wlc_ssid *ssid = NULL;
10104 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10106 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
10107 err = wl_notify_connect_status_ap(cfg, ndev, e, data);
10108 } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS) {
10109 err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
10110 } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) {
10111 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
10112 ntoh32(e->event_type), ntoh32(e->status), ndev));
10113 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
10114 wl_get_auth_assoc_status(cfg, ndev, e);
10117 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
10118 if (wl_is_linkup(cfg, e, ndev)) {
10121 if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
10122 #ifdef DHD_LOSSLESS_ROAMING
10123 bool is_connected = wl_get_drv_status(cfg, CONNECTED, ndev);
10126 printf("wl_bss_connect_done succeeded with " MACDBG "\n",
10127 MAC2STRDBG((const u8*)(&e->addr)));
10128 wl_bss_connect_done(cfg, ndev, e, data, true);
10129 dhd_conf_set_fw_string_cmd(cfg->pub, "phy_oclscdenable", cfg->pub->conf->phy_oclscdenable, 0, FALSE);
10130 WL_DBG(("joined in BSS network \"%s\"\n",
10131 ((struct wlc_ssid *)
10132 wl_read_prof(cfg, ndev, WL_PROF_SSID))->SSID));
10133 #ifdef DHD_LOSSLESS_ROAMING
10134 if (event == WLC_E_LINK && is_connected &&
10135 !cfg->roam_offload) {
10136 wl_bss_roaming_done(cfg, ndev, e, data);
10138 #endif /* DHD_LOSSLESS_ROAMING */
10141 wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
10142 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
10143 dhd_conf_set_wme(cfg->pub);
10145 } else if (wl_is_linkdown(cfg, e)) {
10146 #ifdef DHD_LOSSLESS_ROAMING
10147 wl_del_roam_timeout(cfg);
10149 #ifdef P2PLISTEN_AP_SAMECHN
10150 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
10151 wl_cfg80211_set_p2p_resp_ap_chn(ndev, 0);
10152 cfg->p2p_resp_apchn_status = false;
10153 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
10155 #endif /* P2PLISTEN_AP_SAMECHN */
10156 wl_cfg80211_cancel_scan(cfg);
10158 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10159 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10160 wl_get_bss_info(cfg, ndev, (u8*)(&e->addr));
10162 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10163 /* Explicitly calling unlink to remove BSS in CFG */
10164 wiphy = bcmcfg_to_wiphy(cfg);
10165 ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
10166 bssid = (u8 *)wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10167 if (ssid && bssid) {
10168 bss = cfg80211_get_bss(wiphy, NULL, bssid,
10169 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
10170 WLAN_CAPABILITY_ESS);
10172 cfg80211_unlink_bss(wiphy, bss);
10176 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10178 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10180 struct ether_addr bssid_dongle;
10181 struct ether_addr bssid_null = {{0, 0, 0, 0, 0, 0}};
10183 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
10184 reason = ntoh32(e->reason);
10185 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
10186 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
10188 printf("link down if %s may call cfg80211_disconnected. "
10189 "event : %d, reason=%d from " MACDBG "\n",
10190 ndev->name, event, ntoh32(e->reason),
10191 MAC2STRDBG((const u8*)(&e->addr)));
10193 /* roam offload does not sync BSSID always, get it from dongle */
10194 if (cfg->roam_offload) {
10195 if (wldev_ioctl(ndev, WLC_GET_BSSID, &bssid_dongle,
10196 sizeof(bssid_dongle), false) == BCME_OK) {
10197 /* if not roam case, it would return null bssid */
10198 if (memcmp(&bssid_dongle, &bssid_null,
10199 ETHER_ADDR_LEN) != 0) {
10200 curbssid = (u8 *)&bssid_dongle;
10204 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
10205 bool fw_assoc_state = TRUE;
10206 dhd_pub_t *dhd = (dhd_pub_t *)cfg->pub;
10207 fw_assoc_state = dhd_is_associated(dhd, e->ifidx, &err);
10208 if (!fw_assoc_state) {
10209 WL_ERR(("Even sends up even different BSSID"
10210 " cur: " MACDBG " event: " MACDBG"\n",
10211 MAC2STRDBG(curbssid),
10212 MAC2STRDBG((const u8*)(&e->addr))));
10214 WL_ERR(("BSSID of event is not the connected BSSID"
10215 "(ignore it) cur: " MACDBG
10216 " event: " MACDBG"\n",
10217 MAC2STRDBG(curbssid),
10218 MAC2STRDBG((const u8*)(&e->addr))));
10222 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
10223 // terence 20130703: Fix for wrong group_capab (timing issue)
10224 cfg->p2p_disconnected = 1;
10226 memcpy(&cfg->disconnected_bssid, curbssid, ETHER_ADDR_LEN);
10227 wl_clr_drv_status(cfg, CONNECTED, ndev);
10228 if (! wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
10229 /* To make sure disconnect, explictly send dissassoc
10230 * for BSSID 00:00:00:00:00:00 issue
10232 scbval.val = WLAN_REASON_DEAUTH_LEAVING;
10234 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
10235 scbval.val = htod32(scbval.val);
10236 err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
10237 sizeof(scb_val_t), true);
10239 WL_ERR(("WLC_DISASSOC error %d\n", err));
10242 CFG80211_DISCONNECTED(ndev, reason, NULL, 0,
10243 false, GFP_KERNEL);
10245 wl_init_prof(cfg, ndev);
10246 memset(&cfg->last_roamed_addr, 0, ETHER_ADDR_LEN);
10249 else if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
10250 printf("link down, during connecting\n");
10251 #ifdef ESCAN_RESULT_PATCH
10252 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
10253 (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
10254 (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
10255 /* In case this event comes while associating another AP */
10256 #endif /* ESCAN_RESULT_PATCH */
10257 wl_bss_connect_done(cfg, ndev, e, data, false);
10259 wl_clr_drv_status(cfg, DISCONNECTING, ndev);
10261 /* if link down, bsscfg is diabled */
10262 if (ndev != bcmcfg_to_prmry_ndev(cfg))
10263 complete(&cfg->iface_disable);
10265 } else if (wl_is_nonetwork(cfg, e)) {
10266 printf("connect failed event=%d e->status %d e->reason %d \n",
10267 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
10268 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10269 if (event == WLC_E_SET_SSID) {
10270 wl_get_connect_failed_status(cfg, e);
10272 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10273 /* Clean up any pending scan request */
10274 wl_cfg80211_cancel_scan(cfg);
10275 if (wl_get_drv_status(cfg, CONNECTING, ndev))
10276 wl_bss_connect_done(cfg, ndev, e, data, false);
10278 WL_DBG(("%s nothing\n", __FUNCTION__));
10280 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
10283 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg, ndev)));
10288 void wl_cfg80211_set_rmc_pid(int pid)
10290 struct bcm_cfg80211 *cfg = g_bcm_cfg;
10292 cfg->rmc_event_pid = pid;
10293 WL_DBG(("set pid for rmc event : pid=%d\n", pid));
10298 wl_notify_rmc_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10299 const wl_event_msg_t *e, void *data)
10301 u32 evt = ntoh32(e->event_type);
10302 u32 reason = ntoh32(e->reason);
10306 case WLC_E_REASON_RMC_AR_LOST:
10307 case WLC_E_REASON_RMC_AR_NO_ACK:
10308 if (cfg->rmc_event_pid != 0) {
10309 ret = wl_netlink_send_msg(cfg->rmc_event_pid,
10310 RMC_EVENT_LEADER_CHECK_FAIL,
10311 cfg->rmc_event_seq++, NULL, 0);
10317 WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt, cfg->rmc_event_pid, ret));
10320 #endif /* WL_RELMCAST */
10322 wl_notify_roaming_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10323 const wl_event_msg_t *e, void *data)
10326 struct net_device *ndev = NULL;
10328 u32 event = be32_to_cpu(e->event_type);
10329 u32 status = be32_to_cpu(e->status);
10330 #ifdef DHD_LOSSLESS_ROAMING
10331 struct wl_security *sec;
10333 WL_DBG(("Enter \n"));
10335 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10337 if ((!cfg->disable_roam_event) && (event == WLC_E_BSSID)) {
10338 wl_add_remove_eventmsg(ndev, WLC_E_ROAM, false);
10339 cfg->disable_roam_event = TRUE;
10342 if ((cfg->disable_roam_event) && (event == WLC_E_ROAM))
10345 if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status == WLC_E_STATUS_SUCCESS) {
10346 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10347 #ifdef DHD_LOSSLESS_ROAMING
10348 if (cfg->roam_offload) {
10349 wl_bss_roaming_done(cfg, ndev, e, data);
10350 wl_del_roam_timeout(cfg);
10353 sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10354 /* In order to reduce roaming delay, wl_bss_roaming_done is
10355 * early called with WLC_E_LINK event. It is called from
10356 * here only if WLC_E_LINK event is blocked for specific
10359 if (IS_AKM_SUITE_FT(sec)) {
10360 wl_bss_roaming_done(cfg, ndev, e, data);
10362 /* Roam timer is deleted mostly from wl_cfg80211_change_station
10363 * after roaming is finished successfully. We need to delete
10364 * the timer from here only for some security types that aren't
10365 * using wl_cfg80211_change_station to authorize SCB
10367 if (IS_AKM_SUITE_FT(sec) || IS_AKM_SUITE_CCKM(sec)) {
10368 wl_del_roam_timeout(cfg);
10372 wl_bss_roaming_done(cfg, ndev, e, data);
10373 #endif /* DHD_LOSSLESS_ROAMING */
10375 wl_bss_connect_done(cfg, ndev, e, data, true);
10378 wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
10379 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
10381 #ifdef DHD_LOSSLESS_ROAMING
10382 else if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status != WLC_E_STATUS_SUCCESS) {
10383 wl_del_roam_timeout(cfg);
10390 /* up range from low to high with up value */
10392 up_table_set(uint8 *up_table, uint8 up, uint8 low, uint8 high)
10396 if (up > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) {
10400 for (i = low; i <= high; i++) {
10407 /* set user priority table */
10409 wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie)
10413 if (up_table == NULL || qos_map_ie == NULL) {
10417 /* clear table to check table was set or not */
10418 memset(up_table, 0xff, UP_TABLE_MAX);
10420 /* length of QoS Map IE must be 16+n*2, n is number of exceptions */
10421 if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID &&
10422 (len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH &&
10424 uint8 *except_ptr = (uint8 *)qos_map_ie->data;
10425 uint8 except_len = len - QOS_MAP_FIXED_LENGTH;
10426 uint8 *range_ptr = except_ptr + except_len;
10429 /* fill in ranges */
10430 for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) {
10431 uint8 low = range_ptr[i];
10432 uint8 high = range_ptr[i + 1];
10433 if (low == 255 && high == 255) {
10437 if (!up_table_set(up_table, i / 2, low, high)) {
10438 /* clear the table on failure */
10439 memset(up_table, 0xff, UP_TABLE_MAX);
10444 /* update exceptions */
10445 for (i = 0; i < except_len; i += 2) {
10446 uint8 dscp = except_ptr[i];
10447 uint8 up = except_ptr[i+1];
10449 /* exceptions with invalid dscp/up are ignored */
10450 up_table_set(up_table, up, dscp, dscp);
10454 if (wl_dbg_level & WL_DBG_DBG) {
10455 prhex("UP table", up_table, UP_TABLE_MAX);
10459 /* get user priority table */
10461 wl_get_up_table(void)
10463 return (uint8 *)(g_bcm_cfg->up_table);
10465 #endif /* QOS_MAP_SET */
10467 #ifdef DHD_LOSSLESS_ROAMING
10469 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10470 const wl_event_msg_t *e, void *data)
10473 struct wl_security *sec;
10474 struct net_device *ndev;
10475 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
10477 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10479 sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10480 /* Disable Lossless Roaming for specific AKM suite
10481 * Any other AKM suite can be added below if transition time
10482 * is delayed because of Lossless Roaming
10483 * and it causes any certication failure
10485 if (IS_AKM_SUITE_FT(sec)) {
10489 dhdp->dequeue_prec_map = 1 << PRIO_8021D_NC;
10490 /* Restore flow control */
10491 dhd_txflowcontrol(dhdp, ALL_INTERFACES, OFF);
10493 mod_timer(&cfg->roam_timeout, jiffies + msecs_to_jiffies(WL_ROAM_TIMEOUT_MS));
10497 #endif /* DHD_LOSSLESS_ROAMING */
10500 wl_notify_idsup_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10501 const wl_event_msg_t *e, void *data)
10504 #if defined(WL_VENDOR_EXT_SUPPORT)
10506 u32 reason = ntoh32(e->reason);
10507 struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10508 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
10509 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
10511 if (cfg->roam_offload) {
10512 #if defined(WL_VENDOR_EXT_SUPPORT)
10514 case WLC_E_SUP_WPA_PSK_TMO:
10515 idsup_status = IDSUP_EVENT_4WAY_HANDSHAKE_TIMEOUT;
10517 case WLC_E_SUP_OTHER:
10518 idsup_status = IDSUP_EVENT_SUCCESS;
10521 WL_ERR(("Other type at IDSUP. "
10522 "event=%d e->status %d e->reason %d \n",
10523 (int)ntoh32(e->event_type), (int)ntoh32(e->status),
10524 (int)ntoh32(e->reason)));
10528 err = wl_cfgvendor_send_async_event(wiphy, ndev,
10529 BRCM_VENDOR_EVENT_IDSUP_STATUS, &idsup_status, sizeof(u32));
10530 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
10535 #ifdef CUSTOM_EVENT_PM_WAKE
10537 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10538 const wl_event_msg_t *e, void *data)
10541 struct net_device *ndev = NULL;
10543 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10545 pbuf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
10546 if (pbuf == NULL) {
10547 WL_ERR(("failed to allocate local pbuf\n"));
10551 err = wldev_iovar_getbuf_bsscfg(ndev, "dump",
10552 "pm", strlen("pm"), pbuf, WLC_IOCTL_MEDLEN, 0, &cfg->ioctl_buf_sync);
10555 WL_ERR(("dump ioctl err = %d", err));
10557 WL_ERR(("PM status : %s\n", pbuf));
10565 #endif /* CUSTOM_EVENT_PM_WAKE */
10567 static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev)
10569 wl_assoc_info_t assoc_info;
10570 struct wl_connect_info *conn_info = wl_to_conn(cfg);
10573 bcm_tlv_t * qos_map_ie = NULL;
10574 #endif /* QOS_MAP_SET */
10576 WL_DBG(("Enter \n"));
10577 err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, cfg->extra_buf,
10578 WL_ASSOC_INFO_MAX, NULL);
10579 if (unlikely(err)) {
10580 WL_ERR(("could not get assoc info (%d)\n", err));
10583 memcpy(&assoc_info, cfg->extra_buf, sizeof(wl_assoc_info_t));
10584 assoc_info.req_len = htod32(assoc_info.req_len);
10585 assoc_info.resp_len = htod32(assoc_info.resp_len);
10586 assoc_info.flags = htod32(assoc_info.flags);
10587 if (conn_info->req_ie_len) {
10588 conn_info->req_ie_len = 0;
10589 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
10591 if (conn_info->resp_ie_len) {
10592 conn_info->resp_ie_len = 0;
10593 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
10595 if (assoc_info.req_len) {
10596 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, cfg->extra_buf,
10597 WL_ASSOC_INFO_MAX, NULL);
10598 if (unlikely(err)) {
10599 WL_ERR(("could not get assoc req (%d)\n", err));
10602 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
10603 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
10604 conn_info->req_ie_len -= ETHER_ADDR_LEN;
10606 if (conn_info->req_ie_len <= MAX_REQ_LINE)
10607 memcpy(conn_info->req_ie, cfg->extra_buf, conn_info->req_ie_len);
10609 WL_ERR(("IE size %d above max %d size \n",
10610 conn_info->req_ie_len, MAX_REQ_LINE));
10614 conn_info->req_ie_len = 0;
10616 if (assoc_info.resp_len) {
10617 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, cfg->extra_buf,
10618 WL_ASSOC_INFO_MAX, NULL);
10619 if (unlikely(err)) {
10620 WL_ERR(("could not get assoc resp (%d)\n", err));
10623 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
10624 if (conn_info->resp_ie_len <= MAX_REQ_LINE) {
10625 memcpy(conn_info->resp_ie, cfg->extra_buf, conn_info->resp_ie_len);
10627 WL_ERR(("IE size %d above max %d size \n",
10628 conn_info->resp_ie_len, MAX_REQ_LINE));
10633 /* find qos map set ie */
10634 if ((qos_map_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
10635 DOT11_MNG_QOS_MAP_ID)) != NULL) {
10636 WL_DBG((" QoS map set IE found in assoc response\n"));
10637 if (!cfg->up_table) {
10638 cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
10640 wl_set_up_table(cfg->up_table, qos_map_ie);
10642 kfree(cfg->up_table);
10643 cfg->up_table = NULL;
10645 #endif /* QOS_MAP_SET */
10647 conn_info->resp_ie_len = 0;
10649 WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
10650 conn_info->resp_ie_len));
10655 static s32 wl_ch_to_chanspec(struct net_device *dev, int ch, struct wl_join_params *join_params,
10656 size_t *join_params_size)
10658 struct bcm_cfg80211 *cfg;
10660 chanspec_t chanspec = 0, chspec;
10663 cfg = (struct bcm_cfg80211 *)wiphy_priv(dev->ieee80211_ptr->wiphy);
10664 if (cfg && cfg->rcc_enabled) {
10666 join_params->params.chanspec_num = 1;
10667 join_params->params.chanspec_list[0] = ch;
10669 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
10670 chanspec |= WL_CHANSPEC_BAND_2G;
10672 chanspec |= WL_CHANSPEC_BAND_5G;
10674 /* Get the min_bw set for the interface */
10675 chspec = wl_cfg80211_ulb_get_min_bw_chspec(dev->ieee80211_ptr, bssidx);
10676 if (chspec == INVCHANSPEC) {
10677 WL_ERR(("Invalid chanspec \n"));
10680 chanspec |= chspec;
10681 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
10683 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
10684 join_params->params.chanspec_num * sizeof(chanspec_t);
10686 join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
10687 join_params->params.chanspec_list[0] |= chanspec;
10688 join_params->params.chanspec_list[0] =
10689 wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
10691 join_params->params.chanspec_num =
10692 htod32(join_params->params.chanspec_num);
10695 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
10696 join_params->params.chanspec_list[0],
10697 join_params->params.chanspec_num));
10702 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam)
10704 struct wl_bss_info *bi;
10705 struct wlc_ssid *ssid;
10706 struct bcm_tlv *tim;
10707 s32 beacon_interval;
10713 struct wiphy *wiphy;
10716 wiphy = bcmcfg_to_wiphy(cfg);
10718 ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
10719 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10721 mutex_lock(&cfg->usr_sync);
10723 *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
10724 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
10725 cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
10726 if (unlikely(err)) {
10727 WL_ERR(("Could not get bss info %d\n", err));
10728 goto update_bss_info_out;
10730 bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
10731 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
10732 wl_update_prof(cfg, ndev, NULL, &channel, WL_PROF_CHAN);
10734 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
10735 WL_ERR(("Bssid doesn't match\n"));
10737 goto update_bss_info_out;
10739 err = wl_inform_single_bss(cfg, bi, roam);
10741 goto update_bss_info_out;
10743 ie = ((u8 *)bi) + bi->ie_offset;
10744 ie_len = bi->ie_length;
10745 beacon_interval = cpu_to_le16(bi->beacon_period);
10746 tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
10748 dtim_period = tim->data[1];
10751 * active scan was done so we could not get dtim
10752 * information out of probe response.
10753 * so we speficially query dtim information.
10755 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
10756 &dtim_period, sizeof(dtim_period), false);
10757 if (unlikely(err)) {
10758 WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
10759 goto update_bss_info_out;
10763 wl_update_prof(cfg, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
10764 wl_update_prof(cfg, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
10766 update_bss_info_out:
10767 if (unlikely(err)) {
10768 WL_ERR(("Failed with error %d\n", err));
10770 mutex_unlock(&cfg->usr_sync);
10775 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
10776 const wl_event_msg_t *e, void *data)
10778 struct wl_connect_info *conn_info = wl_to_conn(cfg);
10781 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10782 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
10783 struct ieee80211_supported_band *band;
10784 struct ieee80211_channel *notify_channel = NULL;
10790 if (memcmp(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN) == 0) {
10791 WL_INFORM(("BSSID already updated\n"));
10795 /* Skip calling cfg80211_roamed If current bssid and
10796 * roamed bssid are same. Also clear timer roam_timeout.
10798 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10799 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0) {
10800 WL_ERR(("BSS already present, Skipping roamed event to upper layer\n"));
10801 #ifdef DHD_LOSSLESS_ROAMING
10802 wl_del_roam_timeout(cfg);
10803 #endif /* DHD_LOSSLESS_ROAMING */
10807 wl_get_assoc_ies(cfg, ndev);
10808 wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet), WL_PROF_BSSID);
10809 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10810 wl_update_bss_info(cfg, ndev, true);
10811 wl_update_pmklist(ndev, cfg->pmk_list, err);
10813 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10814 /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
10815 channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
10816 if (*channel <= CH_MAX_2G_CHANNEL)
10817 band = wiphy->bands[IEEE80211_BAND_2GHZ];
10819 band = wiphy->bands[IEEE80211_BAND_5GHZ];
10820 freq = ieee80211_channel_to_frequency(*channel, band->band);
10821 notify_channel = ieee80211_get_channel(wiphy, freq);
10823 printf("wl_bss_roaming_done succeeded to " MACDBG "\n",
10824 MAC2STRDBG((const u8*)(&e->addr)));
10825 dhd_conf_set_wme(cfg->pub);
10827 cfg80211_roamed(ndev,
10828 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10832 conn_info->req_ie, conn_info->req_ie_len,
10833 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
10834 WL_DBG(("Report roaming result\n"));
10836 memcpy(&cfg->last_roamed_addr, (void *)&e->addr, ETHER_ADDR_LEN);
10837 wl_set_drv_status(cfg, CONNECTED, ndev);
10839 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10841 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10847 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
10848 const wl_event_msg_t *e, void *data, bool completed)
10850 struct wl_connect_info *conn_info = wl_to_conn(cfg);
10851 struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10852 #if defined(CUSTOM_SET_CPUCORE)
10853 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
10856 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10858 WL_ERR(("sec is NULL\n"));
10861 WL_DBG((" enter\n"));
10862 #ifdef ESCAN_RESULT_PATCH
10863 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10864 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
10865 WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
10866 ntoh32(e->event_type), ntoh32(e->status)));
10870 if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
10871 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
10872 WL_DBG(("copy bssid\n"));
10873 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
10877 if (cfg->scan_request) {
10878 wl_notify_escan_complete(cfg, ndev, true, true);
10880 #endif /* ESCAN_RESULT_PATCH */
10881 if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
10882 wl_cfg80211_scan_abort(cfg);
10883 wl_clr_drv_status(cfg, CONNECTING, ndev);
10885 wl_get_assoc_ies(cfg, ndev);
10886 wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet),
10888 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10889 wl_update_bss_info(cfg, ndev, false);
10890 wl_update_pmklist(ndev, cfg->pmk_list, err);
10891 wl_set_drv_status(cfg, CONNECTED, ndev);
10892 if (ndev != bcmcfg_to_prmry_ndev(cfg)) {
10893 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
10894 init_completion(&cfg->iface_disable);
10896 /* reinitialize completion to clear previous count */
10897 INIT_COMPLETION(cfg->iface_disable);
10900 #ifdef CUSTOM_SET_CPUCORE
10901 if (wl_get_chan_isvht80(ndev, dhd)) {
10902 if (ndev == bcmcfg_to_prmry_ndev(cfg))
10903 dhd->chan_isvht80 |= DHD_FLAG_STA_MODE; /* STA mode */
10904 else if (is_p2p_group_iface(ndev->ieee80211_ptr))
10905 dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE; /* p2p mode */
10906 dhd_set_cpucore(dhd, TRUE);
10908 #endif /* CUSTOM_SET_CPUCORE */
10911 cfg80211_connect_result(ndev,
10914 conn_info->req_ie_len,
10915 conn_info->resp_ie,
10916 conn_info->resp_ie_len,
10917 completed ? WLAN_STATUS_SUCCESS :
10918 (sec->auth_assoc_res_status) ?
10919 sec->auth_assoc_res_status :
10920 WLAN_STATUS_UNSPECIFIED_FAILURE,
10923 WL_INFORM(("Report connect result - connection succeeded\n"));
10924 dhd_conf_set_wme(cfg->pub);
10926 WL_ERR(("Report connect result - connection failed\n"));
10928 #ifdef CONFIG_TCPACK_FASTTX
10929 if (wl_get_chan_isvht80(ndev, dhd))
10930 wldev_iovar_setint(ndev, "tcpack_fast_tx", 0);
10932 wldev_iovar_setint(ndev, "tcpack_fast_tx", 1);
10933 #endif /* CONFIG_TCPACK_FASTTX */
10939 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10940 const wl_event_msg_t *e, void *data)
10942 struct net_device *ndev = NULL;
10943 u16 flags = ntoh16(e->flags);
10944 enum nl80211_key_type key_type;
10946 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10948 mutex_lock(&cfg->usr_sync);
10949 if (flags & WLC_EVENT_MSG_GROUP)
10950 key_type = NL80211_KEYTYPE_GROUP;
10952 key_type = NL80211_KEYTYPE_PAIRWISE;
10954 cfg80211_michael_mic_failure(ndev, (const u8 *)&e->addr, key_type, -1,
10956 mutex_unlock(&cfg->usr_sync);
10961 #ifdef BT_WIFI_HANDOVER
10963 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10964 const wl_event_msg_t *e, void *data)
10966 struct net_device *ndev = NULL;
10967 u32 event = ntoh32(e->event_type);
10968 u32 datalen = ntoh32(e->datalen);
10971 WL_ERR(("wl_notify_bt_wifi_handover_req: event_type : %d, datalen : %d\n", event, datalen));
10972 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10973 err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
10977 #endif /* BT_WIFI_HANDOVER */
10981 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10982 const wl_event_msg_t *e, void *data)
10984 struct net_device *ndev = NULL;
10986 WL_ERR((">>> PNO Event\n"));
10988 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10990 #ifndef WL_SCHED_SCAN
10991 mutex_lock(&cfg->usr_sync);
10992 /* TODO: Use cfg80211_sched_scan_results(wiphy); */
10993 CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
10994 mutex_unlock(&cfg->usr_sync);
10996 /* If cfg80211 scheduled scan is supported, report the pno results via sched
10999 wl_notify_sched_scan_results(cfg, ndev, e, data);
11000 #endif /* WL_SCHED_SCAN */
11003 #endif /* PNO_SUPPORT */
11005 #ifdef GSCAN_SUPPORT
11007 wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11008 const wl_event_msg_t *e, void *data)
11011 u32 event = be32_to_cpu(e->event_type);
11013 int send_evt_bytes = 0;
11014 int batch_event_result_dummy = 0;
11015 struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11016 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11017 u32 len = ntoh32(e->datalen);
11020 case WLC_E_PFN_SWC:
11021 ptr = dhd_dev_swc_scan_event(ndev, data, &send_evt_bytes);
11022 if (send_evt_bytes) {
11023 wl_cfgvendor_send_async_event(wiphy, ndev,
11024 GOOGLE_GSCAN_SIGNIFICANT_EVENT, ptr, send_evt_bytes);
11028 case WLC_E_PFN_BEST_BATCHING:
11029 err = dhd_dev_retrieve_batch_scan(ndev);
11031 WL_ERR(("Batch retrieval already in progress %d\n", err));
11033 wl_cfgvendor_send_async_event(wiphy, ndev,
11034 GOOGLE_GSCAN_BATCH_SCAN_EVENT,
11035 &batch_event_result_dummy, sizeof(int));
11038 case WLC_E_PFN_SCAN_COMPLETE:
11039 batch_event_result_dummy = WIFI_SCAN_COMPLETE;
11040 wl_cfgvendor_send_async_event(wiphy, ndev,
11041 GOOGLE_SCAN_COMPLETE_EVENT,
11042 &batch_event_result_dummy, sizeof(int));
11044 case WLC_E_PFN_BSSID_NET_FOUND:
11045 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
11048 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
11049 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT);
11050 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_FOUND);
11053 case WLC_E_PFN_BSSID_NET_LOST:
11054 /* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
11055 * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
11058 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
11061 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
11062 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT);
11063 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_LOST);
11067 case WLC_E_PFN_GSCAN_FULL_RESULT:
11068 ptr = dhd_dev_process_full_gscan_result(ndev, data, &send_evt_bytes);
11070 wl_cfgvendor_send_async_event(wiphy, ndev,
11071 GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, send_evt_bytes);
11076 WL_ERR(("%s: Unexpected event! - %d\n", __FUNCTION__, event));
11081 #endif /* GSCAN_SUPPORT */
11084 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11085 const wl_event_msg_t *e, void *data)
11087 struct channel_info channel_inform;
11088 struct wl_scan_results *bss_list;
11089 struct net_device *ndev = NULL;
11090 u32 len = WL_SCAN_BUF_MAX;
11092 unsigned long flags;
11094 WL_DBG(("Enter \n"));
11095 if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
11096 WL_ERR(("scan is not ready \n"));
11099 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11101 mutex_lock(&cfg->usr_sync);
11102 wl_clr_drv_status(cfg, SCANNING, ndev);
11103 err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
11104 sizeof(channel_inform), false);
11105 if (unlikely(err)) {
11106 WL_ERR(("scan busy (%d)\n", err));
11107 goto scan_done_out;
11109 channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
11110 if (unlikely(channel_inform.scan_channel)) {
11112 WL_DBG(("channel_inform.scan_channel (%d)\n",
11113 channel_inform.scan_channel));
11115 cfg->bss_list = cfg->scan_results;
11116 bss_list = cfg->bss_list;
11117 memset(bss_list, 0, len);
11118 bss_list->buflen = htod32(len);
11119 err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
11120 if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {
11121 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
11123 goto scan_done_out;
11125 bss_list->buflen = dtoh32(bss_list->buflen);
11126 bss_list->version = dtoh32(bss_list->version);
11127 bss_list->count = dtoh32(bss_list->count);
11129 err = wl_inform_bss(cfg);
11132 del_timer_sync(&cfg->scan_timeout);
11133 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
11134 if (cfg->scan_request) {
11135 cfg80211_scan_done(cfg->scan_request, false);
11136 cfg->scan_request = NULL;
11138 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
11139 WL_DBG(("cfg80211_scan_done\n"));
11140 mutex_unlock(&cfg->usr_sync);
11145 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
11146 const struct ether_addr *sa, const struct ether_addr *bssid,
11147 u8 **pheader, u32 *body_len, u8 *pbody)
11149 struct dot11_management_header *hdr;
11153 u32 prebody_len = *body_len;
11156 /* capability , listen interval */
11157 totlen = DOT11_ASSOC_REQ_FIXED_LEN;
11158 *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
11161 case FC_REASSOC_REQ:
11162 /* capability, listen inteval, ap address */
11163 totlen = DOT11_REASSOC_REQ_FIXED_LEN;
11164 *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
11167 totlen += DOT11_MGMT_HDR_LEN + prebody_len;
11168 *pheader = kzalloc(totlen, GFP_KERNEL);
11169 if (*pheader == NULL) {
11170 WL_ERR(("memory alloc failed \n"));
11173 hdr = (struct dot11_management_header *) (*pheader);
11174 hdr->fc = htol16(fc);
11177 offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
11178 bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
11179 bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
11180 bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
11181 if ((pbody != NULL) && prebody_len)
11182 bcopy((const char*)pbody, offset, prebody_len);
11183 *body_len = totlen;
11189 wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev)
11191 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
11192 if (timer_pending(&cfg->p2p->listen_timer)) {
11193 del_timer_sync(&cfg->p2p->listen_timer);
11195 if (cfg->afx_hdl != NULL) {
11196 if (cfg->afx_hdl->dev != NULL) {
11197 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
11198 wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, cfg->afx_hdl->dev);
11200 cfg->afx_hdl->peer_chan = WL_INVALID;
11202 complete(&cfg->act_frm_scan);
11203 WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
11204 } else if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
11205 if (!(wl_get_p2p_status(cfg, ACTION_TX_COMPLETED) ||
11206 wl_get_p2p_status(cfg, ACTION_TX_NOACK)))
11207 wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
11209 WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
11210 /* if channel is not zero, "actfame" uses off channel scan.
11211 * So abort scan for off channel completion.
11213 if (cfg->af_sent_channel)
11214 wl_cfg80211_scan_abort(cfg);
11216 #ifdef WL_CFG80211_SYNC_GON
11217 else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
11218 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
11219 /* So abort scan to cancel listen */
11220 wl_cfg80211_scan_abort(cfg);
11222 #endif /* WL_CFG80211_SYNC_GON */
11225 #if defined(WLTDLS)
11226 bool wl_cfg80211_is_tdls_tunneled_frame(void *frame, u32 frame_len)
11228 unsigned char *data;
11230 if (frame == NULL) {
11231 WL_ERR(("Invalid frame \n"));
11235 if (frame_len < 5) {
11236 WL_ERR(("Invalid frame length [%d] \n", frame_len));
11242 if (!memcmp(data, TDLS_TUNNELED_PRB_REQ, 5) ||
11243 !memcmp(data, TDLS_TUNNELED_PRB_RESP, 5)) {
11244 WL_DBG(("TDLS Vendor Specific Received type\n"));
11250 #endif /* WLTDLS */
11253 int wl_cfg80211_get_ioctl_version(void)
11255 return ioctl_version;
11259 wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11260 const wl_event_msg_t *e, void *data)
11262 struct ieee80211_supported_band *band;
11263 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11264 struct ether_addr da;
11265 struct ether_addr bssid;
11266 bool isfree = false;
11269 struct net_device *ndev = NULL;
11270 wifi_p2p_pub_act_frame_t *act_frm = NULL;
11271 wifi_p2p_action_frame_t *p2p_act_frm = NULL;
11272 wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
11273 #if defined(WLTDLS) && defined(TDLS_MSG_ONLY_WFD)
11275 #endif /* WLTDLS && TDLS_MSG_ONLY_WFD */
11276 wl_event_rx_frame_data_t *rxframe =
11277 (wl_event_rx_frame_data_t*)data;
11278 u32 event = ntoh32(e->event_type);
11280 u8 bsscfgidx = e->bsscfgidx;
11281 u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
11282 u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
11284 memset(&bssid, 0, ETHER_ADDR_LEN);
11286 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11288 if (channel <= CH_MAX_2G_CHANNEL)
11289 band = wiphy->bands[IEEE80211_BAND_2GHZ];
11291 band = wiphy->bands[IEEE80211_BAND_5GHZ];
11293 WL_ERR(("No valid band\n"));
11296 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
11297 freq = ieee80211_channel_to_frequency(channel);
11300 freq = ieee80211_channel_to_frequency(channel, band->band);
11302 if (event == WLC_E_ACTION_FRAME_RX) {
11303 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
11304 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
11306 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
11308 WL_ERR(("WLC_GET_BSSID error %d\n", err));
11309 memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
11310 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
11311 &mgmt_frame, &mgmt_frame_len,
11312 (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
11314 WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
11315 mgmt_frame_len, channel, freq));
11319 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11320 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11321 act_frm = (wifi_p2p_pub_act_frame_t *)
11322 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11323 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11324 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11325 p2p_act_frm = (wifi_p2p_action_frame_t *)
11326 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11327 (void) p2p_act_frm;
11328 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11329 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11331 sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
11332 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11333 if (sd_act_frm && wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
11334 if (cfg->next_af_subtype == sd_act_frm->action) {
11335 WL_DBG(("We got a right next frame of SD!(%d)\n",
11336 sd_act_frm->action));
11337 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11339 /* Stop waiting for next AF. */
11340 wl_stop_wait_next_action_frame(cfg, ndev);
11345 } else if ((mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) ||
11346 (wl_cfg80211_is_tdls_tunneled_frame(
11347 &mgmt_frame[DOT11_MGMT_HDR_LEN],
11348 mgmt_frame_len - DOT11_MGMT_HDR_LEN))) {
11349 if (mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) {
11350 WL_ERR((" TDLS Action Frame Received type = %d \n",
11351 mgmt_frame[DOT11_MGMT_HDR_LEN + 1]));
11353 #ifdef TDLS_MSG_ONLY_WFD
11354 dhdp = (dhd_pub_t *)(cfg->pub);
11355 if (!dhdp->tdls_mode) {
11356 WL_DBG((" TDLS Frame filtered \n"));
11360 if (mgmt_frame[DOT11_MGMT_HDR_LEN + 1] == TDLS_ACTION_SETUP_RESP) {
11361 cfg->tdls_mgmt_frame = mgmt_frame;
11362 cfg->tdls_mgmt_frame_len = mgmt_frame_len;
11363 cfg->tdls_mgmt_freq = freq;
11366 #endif /* TDLS_MSG_ONLY_WFD */
11367 #endif /* WLTDLS */
11369 } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_QOS) {
11370 /* update QoS map set table */
11371 bcm_tlv_t * qos_map_ie = NULL;
11372 if ((qos_map_ie = bcm_parse_tlvs(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11373 mgmt_frame_len - DOT11_MGMT_HDR_LEN,
11374 DOT11_MNG_QOS_MAP_ID)) != NULL) {
11375 WL_DBG((" QoS map set IE found in QoS action frame\n"));
11376 if (!cfg->up_table) {
11377 cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
11379 wl_set_up_table(cfg->up_table, qos_map_ie);
11381 kfree(cfg->up_table);
11382 cfg->up_table = NULL;
11384 #endif /* QOS_MAP_SET */
11387 * if we got normal action frame and ndev is p2p0,
11388 * we have to change ndev from p2p0 to wlan0
11392 if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
11394 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11395 mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
11396 WL_DBG(("Recived action is not public action frame\n"));
11397 } else if (cfg->next_af_subtype == action) {
11398 WL_DBG(("Recived action is the waiting action(%d)\n",
11400 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11402 /* Stop waiting for next AF. */
11403 wl_stop_wait_next_action_frame(cfg, ndev);
11410 if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
11411 if (cfg->next_af_subtype == act_frm->subtype) {
11412 WL_DBG(("We got a right next frame!(%d)\n",
11413 act_frm->subtype));
11414 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11416 if (cfg->next_af_subtype == P2P_PAF_GON_CONF) {
11420 /* Stop waiting for next AF. */
11421 wl_stop_wait_next_action_frame(cfg, ndev);
11426 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
11427 mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
11429 * After complete GO Negotiation, roll back to mpc mode
11431 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
11432 (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
11433 wldev_iovar_setint(ndev, "mpc", 1);
11435 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
11436 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
11437 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
11439 } else if (event == WLC_E_PROBREQ_MSG) {
11441 /* Handle probe reqs frame
11442 * WPS-AP certification 4.2.13
11444 struct parsed_ies prbreq_ies;
11445 u32 prbreq_ie_len = 0;
11448 WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
11449 mgmt_frame = (u8 *)(data);
11450 mgmt_frame_len = ntoh32(e->datalen);
11452 prbreq_ie_len = mgmt_frame_len - DOT11_MGMT_HDR_LEN;
11454 /* Parse prob_req IEs */
11455 if (wl_cfg80211_parse_ies(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11456 prbreq_ie_len, &prbreq_ies) < 0) {
11457 WL_ERR(("Prob req get IEs failed\n"));
11460 if (prbreq_ies.wps_ie != NULL) {
11461 wl_validate_wps_ie((char *)prbreq_ies.wps_ie, prbreq_ies.wps_ie_len, &pbc);
11462 WL_DBG((" wps_ie exist pbc = %d\n", pbc));
11463 /* if pbc method, send prob_req mgmt frame to upper layer */
11469 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
11471 /* wpa supplicant use probe request event for restarting another GON Req.
11472 * but it makes GON Req repetition.
11473 * so if src addr of prb req is same as my target device,
11474 * do not send probe request event during sending action frame.
11476 if (event == WLC_E_P2P_PROBREQ_MSG) {
11477 WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
11478 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
11481 /* Filter any P2P probe reqs arriving during the
11485 #if defined(P2P_IE_MISSING_FIX)
11486 cfg->p2p_prb_noti &&
11488 wl_get_p2p_status(cfg, GO_NEG_PHASE)) {
11489 WL_DBG(("Filtering P2P probe_req while "
11490 "being in GO-Neg state\n"));
11496 if (discover_cfgdev(cfgdev, cfg))
11497 WL_DBG(("Rx Managment frame For P2P Discovery Interface \n"));
11499 WL_DBG(("Rx Managment frame For Iface (%s) \n", ndev->name));
11501 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
11502 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0);
11503 #elif(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
11504 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0, GFP_ATOMIC);
11505 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
11506 defined(WL_COMPAT_WIRELESS)
11507 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
11509 cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
11510 #endif /* LINUX_VERSION >= VERSION(3, 14, 0) */
11512 WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
11513 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
11520 #ifdef WL_SCHED_SCAN
11521 /* If target scan is not reliable, set the below define to "1" to do a
11524 #define FULL_ESCAN_ON_PFN_NET_FOUND 0
11526 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
11527 const wl_event_msg_t *e, void *data)
11529 wl_pfn_net_info_t *netinfo, *pnetinfo;
11530 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11532 struct cfg80211_scan_request *request = NULL;
11533 struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
11534 struct ieee80211_channel *channel = NULL;
11535 int channel_req = 0;
11537 struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
11538 int n_pfn_results = pfn_result->count;
11540 WL_DBG(("Enter\n"));
11542 if (e->event_type == WLC_E_PFN_NET_LOST) {
11543 WL_PNO(("PFN NET LOST event. Do Nothing \n"));
11546 WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
11547 if (n_pfn_results > 0) {
11550 if (n_pfn_results > MAX_PFN_LIST_COUNT)
11551 n_pfn_results = MAX_PFN_LIST_COUNT;
11552 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
11553 - sizeof(wl_pfn_net_info_t));
11555 memset(&ssid, 0x00, sizeof(ssid));
11557 request = kzalloc(sizeof(*request)
11558 + sizeof(*request->channels) * n_pfn_results,
11560 channel = (struct ieee80211_channel *)kzalloc(
11561 (sizeof(struct ieee80211_channel) * n_pfn_results),
11563 if (!request || !channel) {
11564 WL_ERR(("No memory"));
11569 request->wiphy = wiphy;
11571 for (i = 0; i < n_pfn_results; i++) {
11572 netinfo = &pnetinfo[i];
11574 WL_ERR(("Invalid netinfo ptr. index:%d", i));
11578 WL_PNO((">>> SSID:%s Channel:%d \n",
11579 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
11580 /* PFN result doesn't have all the info which are required by the supplicant
11581 * (For e.g IEs) Do a target Escan so that sched scan results are reported
11582 * via wl_inform_single_bss in the required format. Escan does require the
11583 * scan request in the form of cfg80211_scan_request. For timebeing, create
11584 * cfg80211_scan_request one out of the received PNO event.
11586 memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
11587 netinfo->pfnsubnet.SSID_len);
11588 ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
11589 request->n_ssids++;
11591 channel_req = netinfo->pfnsubnet.channel;
11592 band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
11593 : NL80211_BAND_5GHZ;
11594 channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
11595 channel[i].band = band;
11596 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
11597 request->channels[i] = &channel[i];
11598 request->n_channels++;
11601 /* assign parsed ssid array */
11602 if (request->n_ssids)
11603 request->ssids = &ssid[0];
11605 if (wl_get_drv_status_all(cfg, SCANNING)) {
11606 /* Abort any on-going scan */
11607 wl_notify_escan_complete(cfg, ndev, true, true);
11610 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
11611 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
11612 err = wl_cfgp2p_discover_enable_search(cfg, false);
11613 if (unlikely(err)) {
11614 wl_clr_drv_status(cfg, SCANNING, ndev);
11617 p2p_scan(cfg) = false;
11620 wl_set_drv_status(cfg, SCANNING, ndev);
11621 #if FULL_ESCAN_ON_PFN_NET_FOUND
11622 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
11623 err = wl_do_escan(cfg, wiphy, ndev, NULL);
11625 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
11626 err = wl_do_escan(cfg, wiphy, ndev, request);
11629 wl_clr_drv_status(cfg, SCANNING, ndev);
11632 cfg->sched_scan_running = TRUE;
11635 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
11644 #endif /* WL_SCHED_SCAN */
11646 static void wl_init_conf(struct wl_conf *conf)
11648 WL_DBG(("Enter \n"));
11649 conf->frag_threshold = (u32)-1;
11650 conf->rts_threshold = (u32)-1;
11651 conf->retry_short = (u32)-1;
11652 conf->retry_long = (u32)-1;
11653 conf->tx_power = -1;
11656 static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev)
11658 unsigned long flags;
11659 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
11661 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
11662 memset(profile, 0, sizeof(struct wl_profile));
11663 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
11666 static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
11668 memset(cfg->evt_handler, 0, sizeof(cfg->evt_handler));
11670 cfg->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
11671 cfg->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
11672 cfg->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
11673 cfg->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
11674 cfg->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
11675 cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
11676 cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
11677 cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
11678 cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
11679 cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
11680 cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
11681 cfg->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
11682 cfg->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
11683 cfg->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
11684 cfg->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
11685 cfg->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
11686 cfg->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
11687 cfg->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
11688 cfg->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
11689 cfg->evt_handler[WLC_E_START] = wl_notify_connect_status;
11691 cfg->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
11692 #endif /* PNO_SUPPORT */
11693 #ifdef GSCAN_SUPPORT
11694 cfg->evt_handler[WLC_E_PFN_BEST_BATCHING] = wl_notify_gscan_event;
11695 cfg->evt_handler[WLC_E_PFN_SCAN_COMPLETE] = wl_notify_gscan_event;
11696 cfg->evt_handler[WLC_E_PFN_GSCAN_FULL_RESULT] = wl_notify_gscan_event;
11697 cfg->evt_handler[WLC_E_PFN_SWC] = wl_notify_gscan_event;
11698 cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event;
11699 cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event;
11700 #endif /* GSCAN_SUPPORT */
11702 cfg->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
11703 #endif /* WLTDLS */
11704 cfg->evt_handler[WLC_E_BSSID] = wl_notify_roaming_status;
11706 cfg->evt_handler[WLC_E_RMC_EVENT] = wl_notify_rmc_status;
11708 #ifdef BT_WIFI_HANDOVER
11709 cfg->evt_handler[WLC_E_BT_WIFI_HANDOVER_REQ] = wl_notify_bt_wifi_handover_req;
11712 cfg->evt_handler[WLC_E_NAN] = wl_cfgnan_notify_nan_status;
11713 cfg->evt_handler[WLC_E_PROXD] = wl_cfgnan_notify_proxd_status;
11714 #endif /* WL_NAN */
11715 cfg->evt_handler[WLC_E_CSA_COMPLETE_IND] = wl_csa_complete_ind;
11716 #ifdef DHD_LOSSLESS_ROAMING
11717 cfg->evt_handler[WLC_E_ROAM_PREP] = wl_notify_roam_prep_status;
11719 cfg->evt_handler[WLC_E_AP_STARTED] = wl_ap_start_ind;
11720 #ifdef CUSTOM_EVENT_PM_WAKE
11721 cfg->evt_handler[WLC_E_EXCESS_PM_WAKE_EVENT] = wl_check_pmstatus;
11722 #endif /* CUSTOM_EVENT_PM_WAKE */
11723 cfg->evt_handler[WLC_E_PSK_SUP] = wl_notify_idsup_status;
11726 #if defined(STATIC_WL_PRIV_STRUCT)
11728 wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
11730 cfg->escan_info.escan_buf = DHD_OS_PREALLOC(cfg->pub,
11731 DHD_PREALLOC_WIPHY_ESCAN0, ESCAN_BUF_SIZE);
11732 bzero(cfg->escan_info.escan_buf, ESCAN_BUF_SIZE);
11736 wl_deinit_escan_result_buf(struct bcm_cfg80211 *cfg)
11738 cfg->escan_info.escan_buf = NULL;
11741 #endif /* STATIC_WL_PRIV_STRUCT */
11743 static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg)
11745 WL_DBG(("Enter \n"));
11747 cfg->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
11748 if (unlikely(!cfg->scan_results)) {
11749 WL_ERR(("Scan results alloc failed\n"));
11750 goto init_priv_mem_out;
11752 cfg->conf = (void *)kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
11753 if (unlikely(!cfg->conf)) {
11754 WL_ERR(("wl_conf alloc failed\n"));
11755 goto init_priv_mem_out;
11757 cfg->scan_req_int =
11758 (void *)kzalloc(sizeof(*cfg->scan_req_int), GFP_KERNEL);
11759 if (unlikely(!cfg->scan_req_int)) {
11760 WL_ERR(("Scan req alloc failed\n"));
11761 goto init_priv_mem_out;
11763 cfg->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
11764 if (unlikely(!cfg->ioctl_buf)) {
11765 WL_ERR(("Ioctl buf alloc failed\n"));
11766 goto init_priv_mem_out;
11768 cfg->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
11769 if (unlikely(!cfg->escan_ioctl_buf)) {
11770 WL_ERR(("Ioctl buf alloc failed\n"));
11771 goto init_priv_mem_out;
11773 cfg->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
11774 if (unlikely(!cfg->extra_buf)) {
11775 WL_ERR(("Extra buf alloc failed\n"));
11776 goto init_priv_mem_out;
11778 cfg->pmk_list = (void *)kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
11779 if (unlikely(!cfg->pmk_list)) {
11780 WL_ERR(("pmk list alloc failed\n"));
11781 goto init_priv_mem_out;
11783 #if defined(STATIC_WL_PRIV_STRUCT)
11784 cfg->conn_info = (void *)kzalloc(sizeof(*cfg->conn_info), GFP_KERNEL);
11785 if (unlikely(!cfg->conn_info)) {
11786 WL_ERR(("cfg->conn_info alloc failed\n"));
11787 goto init_priv_mem_out;
11789 cfg->ie = (void *)kzalloc(sizeof(*cfg->ie), GFP_KERNEL);
11790 if (unlikely(!cfg->ie)) {
11791 WL_ERR(("cfg->ie alloc failed\n"));
11792 goto init_priv_mem_out;
11794 wl_init_escan_result_buf(cfg);
11795 #endif /* STATIC_WL_PRIV_STRUCT */
11796 cfg->afx_hdl = (void *)kzalloc(sizeof(*cfg->afx_hdl), GFP_KERNEL);
11797 if (unlikely(!cfg->afx_hdl)) {
11798 WL_ERR(("afx hdl alloc failed\n"));
11799 goto init_priv_mem_out;
11801 init_completion(&cfg->act_frm_scan);
11802 init_completion(&cfg->wait_next_af);
11804 INIT_WORK(&cfg->afx_hdl->work, wl_cfg80211_afx_handler);
11807 if (cfg->tdls_mgmt_frame) {
11808 kfree(cfg->tdls_mgmt_frame);
11809 cfg->tdls_mgmt_frame = NULL;
11811 #endif /* WLTDLS */
11815 wl_deinit_priv_mem(cfg);
11820 static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg)
11822 kfree(cfg->scan_results);
11823 cfg->scan_results = NULL;
11826 kfree(cfg->scan_req_int);
11827 cfg->scan_req_int = NULL;
11828 kfree(cfg->ioctl_buf);
11829 cfg->ioctl_buf = NULL;
11830 kfree(cfg->escan_ioctl_buf);
11831 cfg->escan_ioctl_buf = NULL;
11832 kfree(cfg->extra_buf);
11833 cfg->extra_buf = NULL;
11834 kfree(cfg->pmk_list);
11835 cfg->pmk_list = NULL;
11836 #if defined(STATIC_WL_PRIV_STRUCT)
11837 kfree(cfg->conn_info);
11838 cfg->conn_info = NULL;
11841 wl_deinit_escan_result_buf(cfg);
11842 #endif /* STATIC_WL_PRIV_STRUCT */
11843 if (cfg->afx_hdl) {
11844 cancel_work_sync(&cfg->afx_hdl->work);
11845 kfree(cfg->afx_hdl);
11846 cfg->afx_hdl = NULL;
11851 static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg)
11854 WL_DBG(("Enter \n"));
11856 /* Do not use DHD in cfg driver */
11857 cfg->event_tsk.thr_pid = -1;
11859 PROC_START(wl_event_handler, cfg, &cfg->event_tsk, 0, "wl_event_handler");
11860 if (cfg->event_tsk.thr_pid < 0)
11865 static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg)
11867 if (cfg->event_tsk.thr_pid >= 0)
11868 PROC_STOP(&cfg->event_tsk);
11871 void wl_terminate_event_handler(void)
11873 struct bcm_cfg80211 *cfg = g_bcm_cfg;
11876 wl_destroy_event_handler(cfg);
11881 static void wl_scan_timeout(unsigned long data)
11883 wl_event_msg_t msg;
11884 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
11885 struct wireless_dev *wdev = NULL;
11886 struct net_device *ndev = NULL;
11887 struct wl_scan_results *bss_list;
11888 struct wl_bss_info *bi = NULL;
11891 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
11892 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11893 uint32 prev_memdump_mode = dhdp->memdump_enabled;
11894 #endif /* DHD_DEBUG && BCMPCIE */
11896 if (!(cfg->scan_request)) {
11897 WL_ERR(("timer expired but no scan request\n"));
11901 bss_list = wl_escan_get_buf(cfg, FALSE);
11903 WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
11905 WL_ERR(("scanned AP count (%d)\n", bss_list->count));
11907 bi = next_bss(bss_list, bi);
11908 for_each_bss(bss_list, bi, i) {
11909 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
11910 WL_ERR(("SSID :%s Channel :%d\n", bi->SSID, channel));
11914 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
11915 if (cfg->scan_request->dev)
11916 wdev = cfg->scan_request->dev->ieee80211_ptr;
11918 wdev = cfg->scan_request->wdev;
11919 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
11921 WL_ERR(("No wireless_dev present\n"));
11924 ndev = wdev_to_wlc_ndev(wdev, cfg);
11926 bzero(&msg, sizeof(wl_event_msg_t));
11927 WL_ERR(("timer expired\n"));
11928 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
11929 if (dhdp->memdump_enabled) {
11930 dhdp->memdump_enabled = DUMP_MEMFILE;
11931 dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
11932 dhd_bus_mem_dump(dhdp);
11933 dhdp->memdump_enabled = prev_memdump_mode;
11935 #endif /* DHD_DEBUG && BCMPCIE */
11936 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
11937 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
11938 msg.reason = 0xFFFFFFFF;
11939 wl_cfg80211_event(ndev, &msg, NULL);
11940 #ifdef CUSTOMER_HW4_DEBUG
11941 if (!wl_scan_timeout_dbg_enabled)
11942 wl_scan_timeout_dbg_set();
11943 #endif /* CUSTOMER_HW4_DEBUG */
11945 // terence 20130729: workaround to fix out of memory in firmware
11946 // if (dhd_conf_get_chip(dhd_get_pub(dev)) == BCM43362_CHIP_ID) {
11947 // WL_ERR(("Send hang event\n"));
11948 // net_os_send_hang_message(dev);
11952 #ifdef DHD_LOSSLESS_ROAMING
11953 static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg)
11955 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11957 /* restore prec_map to ALLPRIO */
11958 dhdp->dequeue_prec_map = ALLPRIO;
11959 if (timer_pending(&cfg->roam_timeout)) {
11960 del_timer_sync(&cfg->roam_timeout);
11965 static void wl_roam_timeout(unsigned long data)
11967 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
11968 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11970 WL_ERR(("roam timer expired\n"));
11972 /* restore prec_map to ALLPRIO */
11973 dhdp->dequeue_prec_map = ALLPRIO;
11976 #endif /* DHD_LOSSLESS_ROAMING */
11979 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
11980 unsigned long state, void *ptr)
11982 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
11983 struct net_device *dev = ptr;
11985 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
11986 #endif /* LINUX_VERSION < VERSION(3, 11, 0) */
11987 struct wireless_dev *wdev = ndev_to_wdev(dev);
11988 struct bcm_cfg80211 *cfg = g_bcm_cfg;
11991 WL_ERR(("Enter \n"));
11994 if (!wdev || !cfg || dev == bcmcfg_to_prmry_ndev(cfg))
11995 return NOTIFY_DONE;
12000 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
12001 int max_wait_timeout = 2;
12002 int max_wait_count = 100;
12004 unsigned long limit = jiffies + max_wait_timeout * HZ;
12006 WL_ERR(("NETDEV_DOWN(+) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12008 while (work_pending(&wdev->cleanup_work)) {
12009 if (refcnt%5 == 0) {
12010 WL_ERR(("[NETDEV_DOWN] wait for "
12011 "complete of cleanup_work"
12012 " (%d th)\n", refcnt));
12014 if (!time_before(jiffies, limit)) {
12015 WL_ERR(("[NETDEV_DOWN] cleanup_work"
12016 " of CFG80211 is not"
12017 " completed in %d sec\n",
12018 max_wait_timeout));
12021 if (refcnt >= max_wait_count) {
12022 WL_ERR(("[NETDEV_DOWN] cleanup_work"
12023 " of CFG80211 is not"
12024 " completed in %d loop\n",
12028 set_current_state(TASK_INTERRUPTIBLE);
12029 (void)schedule_timeout(100);
12030 set_current_state(TASK_RUNNING);
12034 WL_ERR(("NETDEV_DOWN(-) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12036 #endif /* LINUX_VERSION < VERSION(3, 14, 0) */
12039 case NETDEV_UNREGISTER:
12041 WL_ERR(("NETDEV_UNREGISTER(+) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12043 /* after calling list_del_rcu(&wdev->list) */
12044 wl_cfg80211_clear_per_bss_ies(cfg,
12045 wl_get_bssidx_by_wdev(cfg, wdev));
12046 wl_dealloc_netinfo_by_wdev(cfg, wdev);
12048 WL_ERR(("NETDEV_UNREGISTER(-) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12051 case NETDEV_GOING_DOWN:
12053 * At NETDEV_DOWN state, wdev_cleanup_work work will be called.
12054 * In front of door, the function checks whether current scan
12055 * is working or not. If the scanning is still working,
12056 * wdev_cleanup_work call WARN_ON and make the scan done forcibly.
12059 WL_ERR(("NETDEV_GOING_DOWN wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12061 if (wl_get_drv_status(cfg, SCANNING, dev))
12062 wl_notify_escan_complete(cfg, dev, true, true);
12065 return NOTIFY_DONE;
12068 static struct notifier_block wl_cfg80211_netdev_notifier = {
12069 .notifier_call = wl_cfg80211_netdev_notifier_call,
12073 * to make sure we won't register the same notifier twice, otherwise a loop is likely to be
12074 * created in kernel notifier link list (with 'next' pointing to itself)
12076 static bool wl_cfg80211_netdev_notifier_registered = FALSE;
12078 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg)
12080 struct wireless_dev *wdev = NULL;
12081 struct net_device *ndev = NULL;
12083 if (!cfg->scan_request)
12086 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
12087 if (cfg->scan_request->dev)
12088 wdev = cfg->scan_request->dev->ieee80211_ptr;
12090 wdev = cfg->scan_request->wdev;
12091 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
12094 WL_ERR(("No wireless_dev present\n"));
12098 ndev = wdev_to_wlc_ndev(wdev, cfg);
12099 wl_notify_escan_complete(cfg, ndev, true, true);
12100 WL_ERR(("Scan aborted! \n"));
12103 static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
12105 wl_scan_params_t *params = NULL;
12106 s32 params_size = 0;
12108 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
12109 if (!in_atomic()) {
12110 /* Our scan params only need space for 1 channel and 0 ssids */
12111 params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size);
12112 if (params == NULL) {
12113 WL_ERR(("scan params allocation failed \n"));
12116 /* Do a scan abort to stop the driver's scan engine */
12117 err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
12119 WL_ERR(("scan abort failed \n"));
12125 if (cfg->tdls_mgmt_frame) {
12126 kfree(cfg->tdls_mgmt_frame);
12127 cfg->tdls_mgmt_frame = NULL;
12129 #endif /* WLTDLS */
12132 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
12133 struct net_device *ndev,
12134 bool aborted, bool fw_abort)
12137 unsigned long flags;
12138 struct net_device *dev;
12140 WL_DBG(("Enter \n"));
12142 mutex_lock(&cfg->scan_complete);
12145 WL_ERR(("ndev is null\n"));
12150 if (cfg->escan_info.ndev != ndev) {
12151 WL_ERR(("ndev is different %p %p\n", cfg->escan_info.ndev, ndev));
12156 if (cfg->scan_request) {
12157 dev = bcmcfg_to_prmry_ndev(cfg);
12158 #if defined(WL_ENABLE_P2P_IF)
12159 if (cfg->scan_request->dev != cfg->p2p_net)
12160 dev = cfg->scan_request->dev;
12161 #elif defined(WL_CFG80211_P2P_DEV_IF)
12162 if (cfg->scan_request->wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) {
12164 WL_ERR(("%s: dev: %p\n", __FUNCTION__, cfg->scan_request->wdev->netdev));
12166 dev = cfg->scan_request->wdev->netdev;
12168 #endif /* WL_ENABLE_P2P_IF */
12171 WL_DBG(("cfg->scan_request is NULL may be internal scan."
12172 "doing scan_abort for ndev %p primary %p",
12173 ndev, bcmcfg_to_prmry_ndev(cfg)));
12176 if (fw_abort && !in_atomic())
12177 wl_cfg80211_scan_abort(cfg);
12178 if (timer_pending(&cfg->scan_timeout))
12179 del_timer_sync(&cfg->scan_timeout);
12180 #if defined(ESCAN_RESULT_PATCH)
12181 if (likely(cfg->scan_request)) {
12182 cfg->bss_list = wl_escan_get_buf(cfg, aborted);
12183 wl_inform_bss(cfg);
12185 #endif /* ESCAN_RESULT_PATCH */
12186 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
12187 #ifdef WL_SCHED_SCAN
12188 if (cfg->sched_scan_req && !cfg->scan_request) {
12189 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
12191 cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy);
12192 cfg->sched_scan_running = FALSE;
12193 cfg->sched_scan_req = NULL;
12195 #endif /* WL_SCHED_SCAN */
12196 if (likely(cfg->scan_request)) {
12197 cfg80211_scan_done(cfg->scan_request, aborted);
12198 cfg->scan_request = NULL;
12199 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
12200 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
12202 if (p2p_is_on(cfg))
12203 wl_clr_p2p_status(cfg, SCANNING);
12204 wl_clr_drv_status(cfg, SCANNING, dev);
12205 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
12208 mutex_unlock(&cfg->scan_complete);
12212 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12214 wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
12217 for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
12218 int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
12219 if (bss->RSSI < candidate[idx].RSSI) {
12221 memcpy(&candidate[idx + 1], &candidate[idx],
12222 sizeof(removal_element_t) * len);
12223 candidate[idx].RSSI = bss->RSSI;
12224 candidate[idx].length = bss->length;
12225 memcpy(&candidate[idx].BSSID, &bss->BSSID, ETHER_ADDR_LEN);
12232 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
12236 int total_delete_len = 0;
12237 for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
12238 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
12239 wl_bss_info_t *bss = NULL;
12240 if (candidate[idx1].RSSI >= bi->RSSI)
12242 for (idx2 = 0; idx2 < list->count; idx2++) {
12243 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
12245 if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
12246 candidate[idx1].RSSI == bss->RSSI &&
12247 candidate[idx1].length == dtoh32(bss->length)) {
12248 u32 delete_len = dtoh32(bss->length);
12249 WL_DBG(("delete scan info of " MACDBG " to add new AP\n",
12250 MAC2STRDBG(bss->BSSID.octet)));
12251 if (idx2 < list->count -1) {
12252 memmove((u8 *)bss, (u8 *)bss + delete_len,
12253 list->buflen - cur_len - delete_len);
12255 list->buflen -= delete_len;
12257 total_delete_len += delete_len;
12258 /* if delete_len is greater than or equal to result length */
12259 if (total_delete_len >= bi->length) {
12264 cur_len += dtoh32(bss->length);
12268 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12270 static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12271 const wl_event_msg_t *e, void *data)
12274 s32 status = ntoh32(e->status);
12276 wl_escan_result_t *escan_result;
12277 wl_bss_info_t *bss = NULL;
12278 wl_scan_results_t *list;
12279 wifi_p2p_ie_t * p2p_ie;
12280 struct net_device *ndev = NULL;
12283 u8 *p2p_dev_addr = NULL;
12285 struct ieee80211_supported_band *band;
12287 WL_DBG((" enter event type : %d, status : %d \n",
12288 ntoh32(e->event_type), ntoh32(e->status)));
12290 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12292 mutex_lock(&cfg->usr_sync);
12293 /* P2P SCAN is coming from primary interface */
12294 if (wl_get_p2p_status(cfg, SCANNING)) {
12295 if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
12296 ndev = cfg->afx_hdl->dev;
12298 ndev = cfg->escan_info.ndev;
12301 if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
12302 WL_DBG(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n",
12303 ndev, wl_get_drv_status(cfg, SCANNING, ndev),
12304 ntoh32(e->event_type), ntoh32(e->status)));
12307 escan_result = (wl_escan_result_t *)data;
12309 if (status == WLC_E_STATUS_PARTIAL) {
12310 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
12311 if (!escan_result) {
12312 WL_ERR(("Invalid escan result (NULL pointer)\n"));
12315 if (dtoh16(escan_result->bss_count) != 1) {
12316 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
12319 bi = escan_result->bss_info;
12321 WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
12324 bi_length = dtoh32(bi->length);
12325 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
12326 WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
12330 /* +++++ terence 20130524: skip invalid bss */
12332 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
12333 if (channel <= CH_MAX_2G_CHANNEL)
12334 band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
12336 band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_5GHZ];
12338 WL_ERR(("No valid band\n"));
12341 if (!dhd_conf_match_channel(cfg->pub, channel))
12343 /* ----- terence 20130524: skip invalid bss */
12345 if (wl_escan_check_sync_id(status, escan_result->sync_id,
12346 cfg->escan_info.cur_sync_id) < 0)
12349 if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
12350 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
12351 WL_DBG(("Ignoring IBSS result\n"));
12356 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12357 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
12358 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
12359 cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
12360 s32 channel = wf_chspec_ctlchan(
12361 wl_chspec_driver_to_host(bi->chanspec));
12363 if ((channel > MAXCHANNEL) || (channel <= 0))
12364 channel = WL_INVALID;
12366 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
12368 MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
12371 wl_clr_p2p_status(cfg, SCANNING);
12372 cfg->afx_hdl->peer_chan = channel;
12373 complete(&cfg->act_frm_scan);
12378 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
12379 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12380 removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
12381 int remove_lower_rssi = FALSE;
12383 bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
12384 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12386 list = wl_escan_get_buf(cfg, FALSE);
12387 if (scan_req_match(cfg)) {
12388 /* p2p scan && allow only probe response */
12389 if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
12390 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
12392 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
12393 bi->ie_length)) == NULL) {
12394 WL_ERR(("Couldn't find P2PIE in probe"
12395 " response/beacon\n"));
12399 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12400 if (bi_length > ESCAN_BUF_SIZE - list->buflen)
12401 remove_lower_rssi = TRUE;
12402 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12404 WL_SCAN(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID,
12405 MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length));
12406 for (i = 0; i < list->count; i++) {
12407 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
12409 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12410 WL_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
12411 bss->SSID, MAC2STRDBG(bss->BSSID.octet),
12412 i, bss->RSSI, list->count));
12414 if (remove_lower_rssi)
12415 wl_cfg80211_find_removal_candidate(bss, candidate);
12416 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12418 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
12419 (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
12420 == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
12421 bi->SSID_len == bss->SSID_len &&
12422 !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
12424 /* do not allow beacon data to update
12425 *the data recd from a probe response
12427 if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
12428 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
12431 WL_SCAN(("%s("MACDBG"), i=%d prev: RSSI %d"
12432 " flags 0x%x, new: RSSI %d flags 0x%x\n",
12433 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
12434 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
12436 if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
12437 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
12438 /* preserve max RSSI if the measurements are
12439 * both on-channel or both off-channel
12441 WL_SCAN(("%s("MACDBG"), same onchan"
12442 ", RSSI: prev %d new %d\n",
12443 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12444 bss->RSSI, bi->RSSI));
12445 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
12446 } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
12447 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
12448 /* preserve the on-channel rssi measurement
12449 * if the new measurement is off channel
12451 WL_SCAN(("%s("MACDBG"), prev onchan"
12452 ", RSSI: prev %d new %d\n",
12453 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12454 bss->RSSI, bi->RSSI));
12455 bi->RSSI = bss->RSSI;
12456 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
12458 if (dtoh32(bss->length) != bi_length) {
12459 u32 prev_len = dtoh32(bss->length);
12461 WL_SCAN(("bss info replacement"
12462 " is occured(bcast:%d->probresp%d)\n",
12463 bss->ie_length, bi->ie_length));
12464 WL_SCAN(("%s("MACDBG"), replacement!(%d -> %d)\n",
12465 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12466 prev_len, bi_length));
12468 if (list->buflen - prev_len + bi_length
12469 > ESCAN_BUF_SIZE) {
12470 WL_ERR(("Buffer is too small: keep the"
12471 " previous result of this AP\n"));
12472 /* Only update RSSI */
12473 bss->RSSI = bi->RSSI;
12474 bss->flags |= (bi->flags
12475 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
12479 if (i < list->count - 1) {
12480 /* memory copy required by this case only */
12481 memmove((u8 *)bss + bi_length,
12482 (u8 *)bss + prev_len,
12483 list->buflen - cur_len - prev_len);
12485 list->buflen -= prev_len;
12486 list->buflen += bi_length;
12488 list->version = dtoh32(bi->version);
12489 memcpy((u8 *)bss, (u8 *)bi, bi_length);
12492 cur_len += dtoh32(bss->length);
12494 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
12495 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12496 wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
12497 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
12498 WL_DBG(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
12499 MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
12503 WL_ERR(("Buffer is too small: ignoring\n"));
12505 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12508 memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
12509 list->version = dtoh32(bi->version);
12510 list->buflen += bi_length;
12514 * !Broadcast && number of ssid = 1 && number of channels =1
12515 * means specific scan to association
12517 if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
12518 WL_ERR(("P2P assoc scan fast aborted.\n"));
12519 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, false, true);
12524 else if (status == WLC_E_STATUS_SUCCESS) {
12525 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12526 wl_escan_print_sync_id(status, cfg->escan_info.cur_sync_id,
12527 escan_result->sync_id);
12529 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12530 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12531 wl_clr_p2p_status(cfg, SCANNING);
12532 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12533 if (cfg->afx_hdl->peer_chan == WL_INVALID)
12534 complete(&cfg->act_frm_scan);
12535 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12536 WL_INFORM(("ESCAN COMPLETED\n"));
12537 cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
12538 if (!scan_req_match(cfg)) {
12539 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
12540 cfg->bss_list->count));
12542 wl_inform_bss(cfg);
12543 wl_notify_escan_complete(cfg, ndev, false, false);
12545 wl_escan_increment_sync_id(cfg, SCAN_BUF_NEXT);
12546 #ifdef CUSTOMER_HW4_DEBUG
12547 if (wl_scan_timeout_dbg_enabled)
12548 wl_scan_timeout_dbg_clear();
12549 #endif /* CUSTOMER_HW4_DEBUG */
12550 } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
12551 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
12552 (status == WLC_E_STATUS_NEWASSOC)) {
12553 /* Handle all cases of scan abort */
12554 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12555 wl_escan_print_sync_id(status, escan_result->sync_id,
12556 cfg->escan_info.cur_sync_id);
12557 WL_DBG(("ESCAN ABORT reason: %d\n", status));
12558 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12559 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12560 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12561 wl_clr_p2p_status(cfg, SCANNING);
12562 if (cfg->afx_hdl->peer_chan == WL_INVALID)
12563 complete(&cfg->act_frm_scan);
12564 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12565 WL_INFORM(("ESCAN ABORTED\n"));
12566 cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
12567 if (!scan_req_match(cfg)) {
12568 WL_TRACE_HW4(("scan_req_match=0: scanned AP count=%d\n",
12569 cfg->bss_list->count));
12571 wl_inform_bss(cfg);
12572 wl_notify_escan_complete(cfg, ndev, true, false);
12574 /* If there is no pending host initiated scan, do nothing */
12575 WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
12577 wl_escan_increment_sync_id(cfg, SCAN_BUF_CNT);
12578 } else if (status == WLC_E_STATUS_TIMEOUT) {
12579 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
12580 WL_ERR(("reason[0x%x]\n", e->reason));
12581 if (e->reason == 0xFFFFFFFF) {
12582 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
12585 WL_ERR(("unexpected Escan Event %d : abort\n", status));
12586 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12587 wl_escan_print_sync_id(status, escan_result->sync_id,
12588 cfg->escan_info.cur_sync_id);
12589 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12590 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12591 wl_clr_p2p_status(cfg, SCANNING);
12592 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12593 if (cfg->afx_hdl->peer_chan == WL_INVALID)
12594 complete(&cfg->act_frm_scan);
12595 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12596 cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
12597 if (!scan_req_match(cfg)) {
12598 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
12599 "scanned AP count=%d\n",
12600 cfg->bss_list->count));
12602 wl_inform_bss(cfg);
12603 wl_notify_escan_complete(cfg, ndev, true, false);
12605 wl_escan_increment_sync_id(cfg, 2);
12608 mutex_unlock(&cfg->usr_sync);
12612 static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211 *cfg, int enable)
12614 u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
12615 bool p2p_connected = wl_cfgp2p_vif_created(cfg);
12616 struct net_info *iter, *next;
12618 if (!cfg->roamoff_on_concurrent)
12620 if (enable && (p2p_connected||(connected_cnt > 1))) {
12621 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12622 4 && __GNUC_MINOR__ >= 6))
12623 _Pragma("GCC diagnostic push")
12624 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12626 for_each_ndev(cfg, iter, next) {
12627 if (iter->ndev && iter->wdev &&
12628 iter->wdev->iftype == NL80211_IFTYPE_STATION) {
12629 if (wldev_iovar_setint(iter->ndev, "roam_off", TRUE)
12631 iter->roam_off = TRUE;
12634 WL_ERR(("error to enable roam_off\n"));
12638 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12639 4 && __GNUC_MINOR__ >= 6))
12640 _Pragma("GCC diagnostic pop")
12643 else if (!enable) {
12644 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12645 4 && __GNUC_MINOR__ >= 6))
12646 _Pragma("GCC diagnostic push")
12647 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12649 for_each_ndev(cfg, iter, next) {
12650 if (iter->ndev && iter->wdev &&
12651 iter->wdev->iftype == NL80211_IFTYPE_STATION) {
12652 if (iter->roam_off != WL_INVALID) {
12653 if (wldev_iovar_setint(iter->ndev, "roam_off", FALSE)
12655 iter->roam_off = FALSE;
12658 WL_ERR(("error to disable roam_off\n"));
12663 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12664 4 && __GNUC_MINOR__ >= 6))
12665 _Pragma("GCC diagnostic pop")
12671 static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211 *cfg)
12673 struct net_info *iter, *next;
12676 u32 pre_ctl_chan = 0;
12677 u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
12678 cfg->vsdb_mode = false;
12680 if (connected_cnt <= 1) {
12683 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12684 4 && __GNUC_MINOR__ >= 6))
12685 _Pragma("GCC diagnostic push")
12686 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12688 for_each_ndev(cfg, iter, next) {
12689 /* p2p discovery iface ndev could be null */
12693 if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
12694 if (wldev_iovar_getint(iter->ndev, "chanspec",
12695 (s32 *)&chanspec) == BCME_OK) {
12696 chanspec = wl_chspec_driver_to_host(chanspec);
12697 ctl_chan = wf_chspec_ctlchan(chanspec);
12698 wl_update_prof(cfg, iter->ndev, NULL,
12699 &ctl_chan, WL_PROF_CHAN);
12701 if (!cfg->vsdb_mode) {
12702 if (!pre_ctl_chan && ctl_chan)
12703 pre_ctl_chan = ctl_chan;
12704 else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
12705 cfg->vsdb_mode = true;
12711 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12712 4 && __GNUC_MINOR__ >= 6))
12713 _Pragma("GCC diagnostic pop")
12715 printf("%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel");
12719 #if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF)
12720 extern int g_frameburst;
12721 #endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */
12723 static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
12724 enum wl_status state, bool set)
12730 struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
12731 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
12732 if (dhd->busstate == DHD_BUS_DOWN) {
12733 WL_ERR(("%s : busstate is DHD_BUS_DOWN!\n", __FUNCTION__));
12736 WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
12737 state, set, _net_info->pm_restore, _net_info->ndev->name));
12739 if (state != WL_STATUS_CONNECTED)
12741 mode = wl_get_mode_by_netdev(cfg, _net_info->ndev);
12743 wl_cfg80211_concurrent_roam(cfg, 1);
12744 wl_cfg80211_determine_vsdb_mode(cfg);
12745 if (mode == WL_MODE_AP) {
12746 if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
12747 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
12751 if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, &pm,
12752 sizeof(pm), true)) != 0) {
12753 if (err == -ENODEV)
12754 WL_DBG(("%s:netdev not ready\n",
12755 _net_info->ndev->name));
12757 WL_ERR(("%s:error (%d)\n",
12758 _net_info->ndev->name, err));
12760 wl_cfg80211_update_power_mode(_net_info->ndev);
12762 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_SHORT);
12763 #if defined(WLTDLS)
12764 if (wl_cfg80211_is_concurrent_mode()) {
12765 err = wldev_iovar_setint(primary_dev, "tdls_enable", 0);
12767 #endif /* defined(WLTDLS) */
12769 #ifdef DISABLE_FRAMEBURST_VSDB
12770 #ifdef USE_WFA_CERT_CONF
12772 #endif /* USE_WFA_CERT_CONF */
12774 if (wl_cfg80211_is_concurrent_mode()) {
12775 int frameburst = 0;
12776 if (wldev_ioctl(primary_dev, WLC_SET_FAKEFRAG, &frameburst,
12777 sizeof(frameburst), true) != 0) {
12778 WL_DBG(("frameburst set error\n"));
12780 WL_DBG(("Frameburst Disabled\n"));
12783 #endif /* DISABLE_FRAMEBURST_VSDB */
12784 } else { /* clear */
12786 /* clear chan information when the net device is disconnected */
12787 wl_update_prof(cfg, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
12788 wl_cfg80211_determine_vsdb_mode(cfg);
12789 if (primary_dev == _net_info->ndev) {
12791 if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, &pm,
12792 sizeof(pm), true)) != 0) {
12793 if (err == -ENODEV)
12794 WL_DBG(("%s:netdev not ready\n",
12795 _net_info->ndev->name));
12797 WL_ERR(("%s:error (%d)\n",
12798 _net_info->ndev->name, err));
12800 wl_cfg80211_update_power_mode(_net_info->ndev);
12804 wl_cfg80211_concurrent_roam(cfg, 0);
12805 #if defined(WLTDLS)
12806 if (!wl_cfg80211_is_concurrent_mode()) {
12807 err = wldev_iovar_setint(primary_dev, "tdls_enable", 1);
12809 #endif /* defined(WLTDLS) */
12811 #ifdef DISABLE_FRAMEBURST_VSDB
12812 #ifdef USE_WFA_CERT_CONF
12814 #endif /* USE_WFA_CERT_CONF */
12816 int frameburst = 1;
12817 if (wldev_ioctl(primary_dev, WLC_SET_FAKEFRAG, &frameburst,
12818 sizeof(frameburst), true) != 0) {
12819 WL_DBG(("frameburst set error\n"));
12821 WL_DBG(("Frameburst Enabled\n"));
12823 #endif /* DISABLE_FRAMEBURST_VSDB */
12827 static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
12831 cfg->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
12832 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12833 wl_escan_init_sync_id(cfg);
12835 /* Init scan_timeout timer */
12836 init_timer(&cfg->scan_timeout);
12837 cfg->scan_timeout.data = (unsigned long) cfg;
12838 cfg->scan_timeout.function = wl_scan_timeout;
12843 #ifdef DHD_LOSSLESS_ROAMING
12844 static s32 wl_init_roam_timeout(struct bcm_cfg80211 *cfg)
12848 /* Init roam timer */
12849 init_timer(&cfg->roam_timeout);
12850 cfg->roam_timeout.data = (unsigned long) cfg;
12851 cfg->roam_timeout.function = wl_roam_timeout;
12855 #endif /* DHD_LOSSLESS_ROAMING */
12857 static s32 wl_init_priv(struct bcm_cfg80211 *cfg)
12859 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
12860 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
12863 cfg->scan_request = NULL;
12864 cfg->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
12865 cfg->roam_on = false;
12866 cfg->active_scan = true;
12867 cfg->rf_blocked = false;
12868 cfg->vsdb_mode = false;
12869 #if defined(BCMSDIO)
12870 cfg->wlfc_on = false;
12872 cfg->roamoff_on_concurrent = true;
12873 cfg->disable_roam_event = false;
12874 cfg->cfgdev_bssidx = -1;
12875 /* register interested state */
12876 set_bit(WL_STATUS_CONNECTED, &cfg->interrested_state);
12877 spin_lock_init(&cfg->cfgdrv_lock);
12878 mutex_init(&cfg->ioctl_buf_sync);
12879 init_waitqueue_head(&cfg->netif_change_event);
12880 init_completion(&cfg->send_af_done);
12881 init_completion(&cfg->iface_disable);
12883 err = wl_init_priv_mem(cfg);
12886 if (wl_create_event_handler(cfg))
12888 wl_init_event_handler(cfg);
12889 mutex_init(&cfg->usr_sync);
12890 mutex_init(&cfg->event_sync);
12891 mutex_init(&cfg->scan_complete);
12892 err = wl_init_scan(cfg);
12895 #ifdef DHD_LOSSLESS_ROAMING
12896 err = wl_init_roam_timeout(cfg);
12900 #endif /* DHD_LOSSLESS_ROAMING */
12901 wl_init_conf(cfg->conf);
12902 wl_init_prof(cfg, ndev);
12904 DNGL_FUNC(dhd_cfg80211_init, (cfg));
12909 static void wl_deinit_priv(struct bcm_cfg80211 *cfg)
12911 DNGL_FUNC(dhd_cfg80211_deinit, (cfg));
12912 wl_destroy_event_handler(cfg);
12915 del_timer_sync(&cfg->scan_timeout);
12916 #ifdef DHD_LOSSLESS_ROAMING
12917 del_timer_sync(&cfg->roam_timeout);
12919 wl_deinit_priv_mem(cfg);
12920 if (wl_cfg80211_netdev_notifier_registered) {
12921 wl_cfg80211_netdev_notifier_registered = FALSE;
12922 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
12926 #if defined(WL_ENABLE_P2P_IF)
12927 static s32 wl_cfg80211_attach_p2p(void)
12929 struct bcm_cfg80211 *cfg = g_bcm_cfg;
12931 WL_TRACE(("Enter \n"));
12933 if (wl_cfgp2p_register_ndev(cfg) < 0) {
12934 WL_ERR(("P2P attach failed. \n"));
12941 static s32 wl_cfg80211_detach_p2p(void)
12943 struct bcm_cfg80211 *cfg = g_bcm_cfg;
12944 struct wireless_dev *wdev;
12946 WL_DBG(("Enter \n"));
12948 WL_ERR(("Invalid Ptr\n"));
12951 wdev = cfg->p2p_wdev;
12954 WL_ERR(("Invalid Ptr\n"));
12958 wl_cfgp2p_unregister_ndev(cfg);
12960 cfg->p2p_wdev = NULL;
12961 cfg->p2p_net = NULL;
12962 WL_DBG(("Freeing 0x%p \n", wdev));
12969 s32 wl_cfg80211_attach_post(struct net_device *ndev)
12971 struct bcm_cfg80211 * cfg = NULL;
12974 WL_TRACE(("In\n"));
12975 if (unlikely(!ndev)) {
12976 WL_ERR(("ndev is invaild\n"));
12980 if (unlikely(!cfg)) {
12981 WL_ERR(("cfg is invaild\n"));
12984 if (!wl_get_drv_status(cfg, READY, ndev)) {
12986 ret = wl_cfgp2p_supported(cfg, ndev);
12988 #if !defined(WL_ENABLE_P2P_IF)
12989 cfg->wdev->wiphy->interface_modes |=
12990 (BIT(NL80211_IFTYPE_P2P_CLIENT)|
12991 BIT(NL80211_IFTYPE_P2P_GO));
12992 #endif /* !WL_ENABLE_P2P_IF */
12993 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
12996 #if defined(WL_ENABLE_P2P_IF)
12997 if (cfg->p2p_net) {
12998 /* Update MAC addr for p2p0 interface here. */
12999 memcpy(cfg->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
13000 cfg->p2p_net->dev_addr[0] |= 0x02;
13001 printf("%s: p2p_dev_addr="MACDBG "\n",
13002 cfg->p2p_net->name,
13003 MAC2STRDBG(cfg->p2p_net->dev_addr));
13005 WL_ERR(("p2p_net not yet populated."
13006 " Couldn't update the MAC Address for p2p0 \n"));
13009 #endif /* WL_ENABLE_P2P_IF */
13010 cfg->p2p_supported = true;
13011 } else if (ret == 0) {
13012 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
13015 /* SDIO bus timeout */
13021 wl_set_drv_status(cfg, READY, ndev);
13026 s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
13028 struct wireless_dev *wdev;
13029 struct bcm_cfg80211 *cfg;
13031 struct device *dev;
13033 WL_TRACE(("In\n"));
13035 WL_ERR(("ndev is invaild\n"));
13038 WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
13039 dev = wl_cfg80211_get_parent_dev();
13041 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
13042 if (unlikely(!wdev)) {
13043 WL_ERR(("Could not allocate wireless device\n"));
13046 err = wl_setup_wiphy(wdev, dev, context);
13047 if (unlikely(err)) {
13051 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
13052 cfg = (struct bcm_cfg80211 *)wiphy_priv(wdev->wiphy);
13054 cfg->pub = context;
13055 INIT_LIST_HEAD(&cfg->net_list);
13056 spin_lock_init(&cfg->net_list_sync);
13057 ndev->ieee80211_ptr = wdev;
13058 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
13059 wdev->netdev = ndev;
13060 cfg->state_notifier = wl_notifier_change_state;
13061 err = wl_alloc_netinfo(cfg, ndev, wdev, WL_MODE_BSS, PM_ENABLE, 0);
13063 WL_ERR(("Failed to alloc net_info (%d)\n", err));
13064 goto cfg80211_attach_out;
13066 err = wl_init_priv(cfg);
13068 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
13069 goto cfg80211_attach_out;
13072 err = wl_setup_rfkill(cfg, TRUE);
13074 WL_ERR(("Failed to setup rfkill %d\n", err));
13075 goto cfg80211_attach_out;
13077 #ifdef DEBUGFS_CFG80211
13078 err = wl_setup_debugfs(cfg);
13080 WL_ERR(("Failed to setup debugfs %d\n", err));
13081 goto cfg80211_attach_out;
13084 if (!wl_cfg80211_netdev_notifier_registered) {
13085 wl_cfg80211_netdev_notifier_registered = TRUE;
13086 err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
13088 wl_cfg80211_netdev_notifier_registered = FALSE;
13089 WL_ERR(("Failed to register notifierl %d\n", err));
13090 goto cfg80211_attach_out;
13093 #if defined(COEX_DHCP)
13094 cfg->btcoex_info = wl_cfg80211_btcoex_init(cfg->wdev->netdev);
13095 if (!cfg->btcoex_info)
13096 goto cfg80211_attach_out;
13098 #if defined(SUPPORT_RANDOM_MAC_SCAN)
13099 cfg->random_mac_enabled = FALSE;
13100 #endif /* SUPPORT_RANDOM_MAC_SCAN */
13103 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
13104 wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
13105 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
13107 #if defined(WL_ENABLE_P2P_IF)
13108 err = wl_cfg80211_attach_p2p();
13110 goto cfg80211_attach_out;
13113 INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
13114 mutex_init(&cfg->pm_sync);
13118 cfg80211_attach_out:
13119 wl_setup_rfkill(cfg, FALSE);
13124 void wl_cfg80211_detach(void *para)
13126 struct bcm_cfg80211 *cfg;
13131 WL_TRACE(("In\n"));
13133 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
13135 #if defined(COEX_DHCP)
13136 wl_cfg80211_btcoex_deinit();
13137 cfg->btcoex_info = NULL;
13140 wl_setup_rfkill(cfg, FALSE);
13141 #ifdef DEBUGFS_CFG80211
13142 wl_free_debugfs(cfg);
13144 if (cfg->p2p_supported) {
13145 if (timer_pending(&cfg->p2p->listen_timer))
13146 del_timer_sync(&cfg->p2p->listen_timer);
13147 wl_cfgp2p_deinit_priv(cfg);
13150 if (timer_pending(&cfg->scan_timeout))
13151 del_timer_sync(&cfg->scan_timeout);
13152 #ifdef DHD_LOSSLESS_ROAMING
13153 if (timer_pending(&cfg->roam_timeout)) {
13154 del_timer_sync(&cfg->roam_timeout);
13156 #endif /* DHD_LOSSLESS_ROAMING */
13158 #if defined(WL_CFG80211_P2P_DEV_IF)
13160 wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
13161 #endif /* WL_CFG80211_P2P_DEV_IF */
13162 #if defined(WL_ENABLE_P2P_IF)
13163 wl_cfg80211_detach_p2p();
13166 wl_cfg80211_ibss_vsie_free(cfg);
13167 wl_cfg80211_clear_mgmt_vndr_ies(cfg);
13168 wl_deinit_priv(cfg);
13170 wl_cfg80211_clear_parent_dev();
13172 #if defined(RSSIAVG)
13173 wl_free_rssi_cache(&g_rssi_cache_ctrl);
13174 wl_free_rssi_cache(&g_connected_rssi_cache_ctrl);
13176 #if defined(BSSCACHE)
13177 wl_release_bss_cache_ctrl(&g_bss_cache_ctrl);
13179 /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
13180 * structure "cfg", which is the private part of wiphy, has been freed in
13181 * wl_free_wdev !!!!!!!!!!!
13185 static void wl_wakeup_event(struct bcm_cfg80211 *cfg)
13187 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
13189 if (dhd->up && (cfg->event_tsk.thr_pid >= 0)) {
13190 up(&cfg->event_tsk.sema);
13194 static s32 wl_event_handler(void *data)
13196 struct bcm_cfg80211 *cfg = NULL;
13197 struct wl_event_q *e;
13198 tsk_ctl_t *tsk = (tsk_ctl_t *)data;
13199 struct wireless_dev *wdev = NULL;
13201 cfg = (struct bcm_cfg80211 *)tsk->parent;
13203 printf("tsk Enter, tsk = 0x%p\n", tsk);
13205 while (down_interruptible (&tsk->sema) == 0) {
13206 SMP_RD_BARRIER_DEPENDS();
13207 if (tsk->terminated) {
13210 while ((e = wl_deq_event(cfg))) {
13211 WL_DBG(("event type (%d), ifidx: %d bssidx: %d \n",
13212 e->etype, e->emsg.ifidx, e->emsg.bsscfgidx));
13214 if (e->emsg.ifidx > WL_MAX_IFS) {
13215 WL_ERR((" Event ifidx not in range. val:%d \n", e->emsg.ifidx));
13219 if (!(wdev = wl_get_wdev_by_bssidx(cfg, e->emsg.bsscfgidx))) {
13220 /* For WLC_E_IF would be handled by wl_host_event */
13221 if (e->etype != WLC_E_IF)
13222 WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"
13223 " Ignoring event.\n", e->emsg.bsscfgidx));
13224 } else if (e->etype < WLC_E_LAST && cfg->evt_handler[e->etype]) {
13225 dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
13226 if (dhd->busstate == DHD_BUS_DOWN) {
13227 WL_ERR((": BUS is DOWN.\n"));
13230 if (cfg->iface_cnt == 0) {
13231 wl_dump_ifinfo(cfg);
13234 cfg->evt_handler[e->etype](cfg, wdev_to_cfgdev(wdev),
13235 &e->emsg, e->edata);
13238 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
13242 DHD_EVENT_WAKE_UNLOCK(cfg->pub);
13245 printf("%s: was terminated\n", __FUNCTION__);
13246 complete_and_exit(&tsk->completed, 0);
13251 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
13253 u32 event_type = ntoh32(e->event_type);
13254 struct bcm_cfg80211 *cfg = g_bcm_cfg;
13255 struct net_info *netinfo;
13257 #if (WL_DBG_LEVEL > 0)
13258 s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
13259 wl_dbg_estr[event_type] : (s8 *) "Unknown";
13260 WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
13261 #endif /* (WL_DBG_LEVEL > 0) */
13263 if (cfg->event_tsk.thr_pid == -1) {
13264 WL_ERR(("Event handler is not created\n"));
13268 if ((cfg == NULL) || (cfg->p2p_supported && cfg->p2p == NULL)) {
13269 WL_ERR(("Stale event ignored\n"));
13273 if (wl_get_p2p_status(cfg, IF_CHANGING) || wl_get_p2p_status(cfg, IF_ADDING)) {
13274 WL_ERR(("during IF change, ignore event %d\n", event_type));
13279 if (event_type != WLC_E_ESCAN_RESULT) {
13280 WL_ERR(("Event_type %d , status : %d, reason : %d, bssidx:%d \n",
13281 event_type, ntoh32(e->status), ntoh32(e->reason), e->bsscfgidx));
13284 netinfo = wl_get_netinfo_by_bssidx(cfg, e->bsscfgidx);
13286 /* Since the netinfo entry is not there, the netdev entry is not
13287 * created via cfg80211 interface. so the event is not of interest
13288 * to the cfg80211 layer.
13290 WL_ERR(("ignore event %d, not interested\n", event_type));
13294 if (event_type == WLC_E_PFN_NET_FOUND) {
13295 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
13297 else if (event_type == WLC_E_PFN_NET_LOST) {
13298 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
13301 DHD_EVENT_WAKE_LOCK(cfg->pub);
13302 if (likely(!wl_enq_event(cfg, ndev, event_type, e, data))) {
13303 wl_wakeup_event(cfg);
13305 DHD_EVENT_WAKE_UNLOCK(cfg->pub);
13309 static void wl_init_eq(struct bcm_cfg80211 *cfg)
13311 wl_init_eq_lock(cfg);
13312 INIT_LIST_HEAD(&cfg->eq_list);
13315 static void wl_flush_eq(struct bcm_cfg80211 *cfg)
13317 struct wl_event_q *e;
13318 unsigned long flags;
13320 flags = wl_lock_eq(cfg);
13321 while (!list_empty_careful(&cfg->eq_list)) {
13322 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
13323 list_del(&e->eq_list);
13326 wl_unlock_eq(cfg, flags);
13330 * retrieve first queued event from head
13333 static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg)
13335 struct wl_event_q *e = NULL;
13336 unsigned long flags;
13338 flags = wl_lock_eq(cfg);
13339 if (likely(!list_empty(&cfg->eq_list))) {
13340 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
13341 list_del(&e->eq_list);
13343 wl_unlock_eq(cfg, flags);
13349 * push event to tail of the queue
13353 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 event,
13354 const wl_event_msg_t *msg, void *data)
13356 struct wl_event_q *e;
13360 unsigned long flags;
13365 data_len = ntoh32(msg->datalen);
13366 evtq_size = sizeof(struct wl_event_q) + data_len;
13367 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
13368 e = kzalloc(evtq_size, aflags);
13369 if (unlikely(!e)) {
13370 WL_ERR(("event alloc failed\n"));
13374 memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
13376 memcpy(e->edata, data, data_len);
13377 flags = wl_lock_eq(cfg);
13378 list_add_tail(&e->eq_list, &cfg->eq_list);
13379 wl_unlock_eq(cfg, flags);
13384 static void wl_put_event(struct wl_event_q *e)
13389 static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype)
13395 case NL80211_IFTYPE_MONITOR:
13396 case NL80211_IFTYPE_WDS:
13397 WL_ERR(("type (%d) : currently we do not support this mode\n",
13401 case NL80211_IFTYPE_ADHOC:
13402 mode = WL_MODE_IBSS;
13404 case NL80211_IFTYPE_STATION:
13405 case NL80211_IFTYPE_P2P_CLIENT:
13406 mode = WL_MODE_BSS;
13409 case NL80211_IFTYPE_AP:
13410 case NL80211_IFTYPE_P2P_GO:
13416 WL_ERR(("invalid type (%d)\n", iftype));
13419 infra = htod32(infra);
13420 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
13421 if (unlikely(err)) {
13422 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
13426 wl_set_mode_by_netdev(cfg, ndev, mode);
13431 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
13433 if (!ev || (event > WLC_E_LAST))
13436 if (ev->num < MAX_EVENT_BUF_NUM) {
13437 ev->event[ev->num].type = event;
13438 ev->event[ev->num].set = set;
13441 WL_ERR(("evenbuffer doesn't support > %u events. Update"
13442 " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
13447 s32 wl_cfg80211_apply_eventbuffer(
13448 struct net_device *ndev,
13449 struct bcm_cfg80211 *cfg,
13450 wl_eventmsg_buf_t *ev)
13452 char eventmask[WL_EVENTING_MASK_LEN];
13454 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
13456 if (!ev || (!ev->num))
13459 mutex_lock(&cfg->event_sync);
13461 /* Read event_msgs mask */
13462 bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
13464 ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
13465 if (unlikely(ret)) {
13466 WL_ERR(("Get event_msgs error (%d)\n", ret));
13469 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
13471 /* apply the set bits */
13472 for (i = 0; i < ev->num; i++) {
13473 if (ev->event[i].set)
13474 setbit(eventmask, ev->event[i].type);
13476 clrbit(eventmask, ev->event[i].type);
13479 /* Write updated Event mask */
13480 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
13482 ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
13483 if (unlikely(ret)) {
13484 WL_ERR(("Set event_msgs error (%d)\n", ret));
13488 mutex_unlock(&cfg->event_sync);
13492 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
13494 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
13495 s8 eventmask[WL_EVENTING_MASK_LEN];
13497 struct bcm_cfg80211 *cfg = g_bcm_cfg;
13502 mutex_lock(&cfg->event_sync);
13504 /* Setup event_msgs */
13505 bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
13507 err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
13508 if (unlikely(err)) {
13509 WL_ERR(("Get event_msgs error (%d)\n", err));
13512 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
13514 setbit(eventmask, event);
13516 clrbit(eventmask, event);
13518 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
13520 err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
13521 if (unlikely(err)) {
13522 WL_ERR(("Set event_msgs error (%d)\n", err));
13527 mutex_unlock(&cfg->event_sync);
13531 static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap)
13533 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
13534 struct ieee80211_channel *band_chan_arr = NULL;
13535 wl_uint32_list_t *list;
13536 u32 i, j, index, n_2g, n_5g, band, channel, array_size;
13543 bool dfs_radar_disabled = FALSE;
13545 #define LOCAL_BUF_LEN 1024
13546 pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
13548 if (pbuf == NULL) {
13549 WL_ERR(("failed to allocate local buf\n"));
13552 list = (wl_uint32_list_t *)(void *)pbuf;
13553 list->count = htod32(WL_NUMCHANSPECS);
13556 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
13557 0, pbuf, LOCAL_BUF_LEN, 0, &cfg->ioctl_buf_sync);
13559 WL_ERR(("get chanspecs failed with %d\n", err));
13563 #undef LOCAL_BUF_LEN
13565 list = (wl_uint32_list_t *)(void *)pbuf;
13566 band = array_size = n_2g = n_5g = 0;
13567 for (i = 0; i < dtoh32(list->count); i++) {
13570 ht40_allowed = false;
13571 c = (chanspec_t)dtoh32(list->element[i]);
13572 c = wl_chspec_driver_to_host(c);
13573 channel = wf_chspec_ctlchan(c);
13575 if (!CHSPEC_IS40(c) && ! CHSPEC_IS20(c)) {
13576 WL_DBG(("HT80/160/80p80 center channel : %d\n", channel));
13579 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
13580 (channel <= CH_MAX_2G_CHANNEL)) {
13581 band_chan_arr = __wl_2ghz_channels;
13582 array_size = ARRAYSIZE(__wl_2ghz_channels);
13584 band = IEEE80211_BAND_2GHZ;
13585 ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false;
13586 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
13587 band_chan_arr = __wl_5ghz_a_channels;
13588 array_size = ARRAYSIZE(__wl_5ghz_a_channels);
13590 band = IEEE80211_BAND_5GHZ;
13591 ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
13593 WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
13596 if (!ht40_allowed && CHSPEC_IS40(c))
13598 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
13599 if (band_chan_arr[j].hw_value == channel) {
13608 if (!dhd_conf_match_channel(cfg->pub, channel))
13610 if (index < array_size) {
13611 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
13612 band_chan_arr[index].center_freq =
13613 ieee80211_channel_to_frequency(channel);
13615 band_chan_arr[index].center_freq =
13616 ieee80211_channel_to_frequency(channel, band);
13618 band_chan_arr[index].hw_value = channel;
13619 WL_DBG(("channel = %d\n", channel));
13621 if (CHSPEC_IS40(c) && ht40_allowed) {
13622 /* assuming the order is HT20, HT40 Upper,
13623 * HT40 lower from chanspecs
13625 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
13626 if (CHSPEC_SB_UPPER(c)) {
13627 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
13628 band_chan_arr[index].flags &=
13629 ~IEEE80211_CHAN_NO_HT40;
13630 band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
13632 /* It should be one of
13633 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
13635 band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
13636 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
13637 band_chan_arr[index].flags |=
13638 IEEE80211_CHAN_NO_HT40MINUS;
13641 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
13642 if (!dfs_radar_disabled) {
13643 if (band == IEEE80211_BAND_2GHZ)
13644 channel |= WL_CHANSPEC_BAND_2G;
13646 channel |= WL_CHANSPEC_BAND_5G;
13647 channel |= WL_CHANSPEC_BW_20;
13648 channel = wl_chspec_host_to_driver(channel);
13649 err = wldev_iovar_getint(dev, "per_chan_info", &channel);
13651 if (channel & WL_CHAN_RADAR) {
13652 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
13653 band_chan_arr[index].flags |=
13654 (IEEE80211_CHAN_RADAR
13655 | IEEE80211_CHAN_NO_IBSS);
13657 band_chan_arr[index].flags |=
13658 IEEE80211_CHAN_RADAR;
13662 if (channel & WL_CHAN_PASSIVE)
13663 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
13664 band_chan_arr[index].flags |=
13665 IEEE80211_CHAN_PASSIVE_SCAN;
13667 band_chan_arr[index].flags |=
13668 IEEE80211_CHAN_NO_IR;
13670 } else if (err == BCME_UNSUPPORTED) {
13671 dfs_radar_disabled = TRUE;
13672 WL_ERR(("does not support per_chan_info\n"));
13681 __wl_band_2ghz.n_channels = n_2g;
13682 __wl_band_5ghz_a.n_channels = n_5g;
13687 s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
13689 struct wiphy *wiphy;
13690 struct net_device *dev;
13697 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13705 s32 txbf_bfe_cap = 0;
13706 s32 txbf_bfr_cap = 0;
13708 bool rollback_lock = false;
13711 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
13715 mutex_lock(&cfg->usr_sync);
13716 rollback_lock = true;
13718 dev = bcmcfg_to_prmry_ndev(cfg);
13720 memset(bandlist, 0, sizeof(bandlist));
13721 err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
13722 sizeof(bandlist), false);
13723 if (unlikely(err)) {
13724 WL_ERR(("error read bandlist (%d)\n", err));
13727 err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
13728 sizeof(s32), false);
13729 if (unlikely(err)) {
13730 WL_ERR(("error (%d)\n", err));
13734 err = wldev_iovar_getint(dev, "nmode", &nmode);
13735 if (unlikely(err)) {
13736 WL_ERR(("error reading nmode (%d)\n", err));
13739 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13740 err = wldev_iovar_getint(dev, "vhtmode", &vhtmode);
13741 if (unlikely(err)) {
13742 WL_ERR(("error reading vhtmode (%d)\n", err));
13746 err = wldev_iovar_getint(dev, "txstreams", &txstreams);
13747 if (unlikely(err)) {
13748 WL_ERR(("error reading txstreams (%d)\n", err));
13751 err = wldev_iovar_getint(dev, "rxstreams", &rxstreams);
13752 if (unlikely(err)) {
13753 WL_ERR(("error reading rxstreams (%d)\n", err));
13756 err = wldev_iovar_getint(dev, "ldpc_cap", &ldpc_cap);
13757 if (unlikely(err)) {
13758 WL_ERR(("error reading ldpc_cap (%d)\n", err));
13761 err = wldev_iovar_getint(dev, "stbc_rx", &stbc_rx);
13762 if (unlikely(err)) {
13763 WL_ERR(("error reading stbc_rx (%d)\n", err));
13766 err = wldev_iovar_getint(dev, "stbc_tx", &stbc_tx);
13767 if (unlikely(err)) {
13768 WL_ERR(("error reading stbc_tx (%d)\n", err));
13771 err = wldev_iovar_getint(dev, "txbf_bfe_cap", &txbf_bfe_cap);
13772 if (unlikely(err)) {
13773 WL_ERR(("error reading txbf_bfe_cap (%d)\n", err));
13776 err = wldev_iovar_getint(dev, "txbf_bfr_cap", &txbf_bfr_cap);
13777 if (unlikely(err)) {
13778 WL_ERR(("error reading txbf_bfr_cap (%d)\n", err));
13783 /* For nmode and vhtmode check bw cap */
13785 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13789 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
13790 if (unlikely(err)) {
13791 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
13795 err = wl_construct_reginfo(cfg, bw_cap);
13797 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
13798 if (err != BCME_UNSUPPORTED)
13802 wiphy = bcmcfg_to_wiphy(cfg);
13803 nband = bandlist[0];
13805 for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
13807 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
13808 bands[IEEE80211_BAND_5GHZ] =
13810 index = IEEE80211_BAND_5GHZ;
13811 if (nmode && (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G))
13812 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
13814 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13815 /* VHT capabilities. */
13818 bands[index]->vht_cap.vht_supported = TRUE;
13820 for (j = 1; j <= VHT_CAP_MCS_MAP_NSS_MAX; j++) {
13821 /* TX stream rates. */
13822 if (j <= txstreams) {
13823 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
13824 bands[index]->vht_cap.vht_mcs.tx_mcs_map);
13826 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
13827 bands[index]->vht_cap.vht_mcs.tx_mcs_map);
13830 /* RX stream rates. */
13831 if (j <= rxstreams) {
13832 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
13833 bands[index]->vht_cap.vht_mcs.rx_mcs_map);
13835 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
13836 bands[index]->vht_cap.vht_mcs.rx_mcs_map);
13842 /* 80 MHz is mandatory */
13843 bands[index]->vht_cap.cap |=
13844 IEEE80211_VHT_CAP_SHORT_GI_80;
13846 if (WL_BW_CAP_160MHZ(bw_cap)) {
13847 bands[index]->vht_cap.cap |=
13848 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
13849 bands[index]->vht_cap.cap |=
13850 IEEE80211_VHT_CAP_SHORT_GI_160;
13853 bands[index]->vht_cap.cap |=
13854 IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
13857 bands[index]->vht_cap.cap |=
13858 IEEE80211_VHT_CAP_RXLDPC;
13861 bands[index]->vht_cap.cap |=
13862 IEEE80211_VHT_CAP_TXSTBC;
13865 bands[index]->vht_cap.cap |=
13866 (stbc_rx << VHT_CAP_INFO_RX_STBC_SHIFT);
13869 bands[index]->vht_cap.cap |=
13870 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
13872 if (txbf_bfr_cap) {
13873 bands[index]->vht_cap.cap |=
13874 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
13877 if (txbf_bfe_cap || txbf_bfr_cap) {
13878 bands[index]->vht_cap.cap |=
13879 (2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT);
13880 bands[index]->vht_cap.cap |=
13881 ((txstreams - 1) <<
13882 VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT);
13883 bands[index]->vht_cap.cap |=
13884 IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
13887 /* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
13888 bands[index]->vht_cap.cap |=
13889 (7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT);
13890 WL_INFORM(("%s band[%d] vht_enab=%d vht_cap=%08x "
13891 "vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
13892 __FUNCTION__, index,
13893 bands[index]->vht_cap.vht_supported,
13894 bands[index]->vht_cap.cap,
13895 bands[index]->vht_cap.vht_mcs.rx_mcs_map,
13896 bands[index]->vht_cap.vht_mcs.tx_mcs_map));
13900 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
13901 bands[IEEE80211_BAND_2GHZ] =
13903 index = IEEE80211_BAND_2GHZ;
13904 if (bw_cap == WLC_N_BW_40ALL)
13905 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
13908 if ((index >= 0) && nmode) {
13909 bands[index]->ht_cap.cap |=
13910 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
13911 bands[index]->ht_cap.ht_supported = TRUE;
13912 bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
13913 bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
13914 /* An HT shall support all EQM rates for one spatial stream */
13915 bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
13920 wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
13921 wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
13923 /* check if any bands populated otherwise makes 2Ghz as default */
13924 if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
13925 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
13926 /* Setup 2Ghz band as default */
13927 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
13931 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
13935 mutex_unlock(&cfg->usr_sync);
13939 static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg)
13942 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
13943 struct wireless_dev *wdev = ndev->ieee80211_ptr;
13947 err = wl_create_event_handler(cfg);
13949 WL_ERR(("wl_create_event_handler failed\n"));
13952 wl_init_event_handler(cfg);
13954 err = dhd_config_dongle(cfg);
13958 err = wl_config_ifmode(cfg, ndev, wdev->iftype);
13959 if (unlikely(err && err != -EINPROGRESS)) {
13960 WL_ERR(("wl_config_ifmode failed\n"));
13962 WL_ERR(("return error %d\n", err));
13967 err = wl_init_scan(cfg);
13969 WL_ERR(("wl_init_scan failed\n"));
13972 err = wl_update_wiphybands(cfg, true);
13973 if (unlikely(err)) {
13974 WL_ERR(("wl_update_wiphybands failed\n"));
13976 WL_ERR(("return error %d\n", err));
13980 #ifdef DHD_LOSSLESS_ROAMING
13981 if (timer_pending(&cfg->roam_timeout)) {
13982 del_timer_sync(&cfg->roam_timeout);
13984 #endif /* DHD_LOSSLESS_ROAMING */
13986 err = dhd_monitor_init(cfg->pub);
13988 wl_set_drv_status(cfg, READY, ndev);
13992 static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
13995 unsigned long flags;
13996 struct net_info *iter, *next;
13997 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
13998 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
13999 struct net_device *p2p_net = cfg->p2p_net;
14001 #ifdef PROP_TXSTATUS_VSDB
14002 #if defined(BCMSDIO)
14003 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
14005 #endif /* PROP_TXSTATUS_VSDB */
14007 /* Delete pm_enable_work */
14008 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
14011 wl_cfgnan_stop_handler(ndev, g_bcm_cfg, NULL, 0, NULL);
14012 #endif /* WL_NAN */
14014 if (cfg->p2p_supported) {
14015 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
14016 #ifdef PROP_TXSTATUS_VSDB
14017 #if defined(BCMSDIO)
14018 if (wl_cfgp2p_vif_created(cfg)) {
14019 bool enabled = false;
14020 dhd_wlfc_get_enable(dhd, &enabled);
14021 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
14022 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
14023 dhd_wlfc_deinit(dhd);
14024 cfg->wlfc_on = false;
14028 #endif /* PROP_TXSTATUS_VSDB */
14032 /* If primary BSS is operational (for e.g SoftAP), bring it down */
14033 if (wl_cfgp2p_bss_isup(ndev, 0)) {
14034 if (wl_cfgp2p_bss(cfg, ndev, 0, 0) < 0)
14035 WL_ERR(("BSS down failed \n"));
14038 /* Check if cfg80211 interface is already down */
14039 if (!wl_get_drv_status(cfg, READY, ndev))
14040 return err; /* it is even not ready */
14042 /* clear all the security setting on primary Interface */
14043 wl_cfg80211_clear_security(cfg);
14045 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14046 4 && __GNUC_MINOR__ >= 6))
14047 _Pragma("GCC diagnostic push")
14048 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14050 for_each_ndev(cfg, iter, next) {
14051 if (iter->ndev) /* p2p discovery iface is null */
14052 wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
14054 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14055 4 && __GNUC_MINOR__ >= 6))
14056 _Pragma("GCC diagnostic pop")
14059 #ifdef P2P_LISTEN_OFFLOADING
14060 wl_cfg80211_p2plo_deinit(cfg);
14061 #endif /* P2P_LISTEN_OFFLOADING */
14063 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14064 if (cfg->scan_request) {
14065 cfg80211_scan_done(cfg->scan_request, true);
14066 cfg->scan_request = NULL;
14068 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14069 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14070 4 && __GNUC_MINOR__ >= 6))
14071 _Pragma("GCC diagnostic push")
14072 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14074 for_each_ndev(cfg, iter, next) {
14075 /* p2p discovery iface ndev ptr could be null */
14076 if (iter->ndev == NULL)
14078 wl_clr_drv_status(cfg, READY, iter->ndev);
14079 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
14080 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
14081 wl_clr_drv_status(cfg, CONNECTING, iter->ndev);
14082 wl_clr_drv_status(cfg, CONNECTED, iter->ndev);
14083 wl_clr_drv_status(cfg, DISCONNECTING, iter->ndev);
14084 wl_clr_drv_status(cfg, AP_CREATED, iter->ndev);
14085 wl_clr_drv_status(cfg, AP_CREATING, iter->ndev);
14087 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14088 4 && __GNUC_MINOR__ >= 6))
14089 _Pragma("GCC diagnostic pop")
14091 bcmcfg_to_prmry_ndev(cfg)->ieee80211_ptr->iftype =
14092 NL80211_IFTYPE_STATION;
14093 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
14095 dev_close(p2p_net);
14098 /* Avoid deadlock from wl_cfg80211_down */
14099 mutex_unlock(&cfg->usr_sync);
14100 wl_destroy_event_handler(cfg);
14101 mutex_lock(&cfg->usr_sync);
14104 if (cfg->p2p_supported) {
14105 if (timer_pending(&cfg->p2p->listen_timer))
14106 del_timer_sync(&cfg->p2p->listen_timer);
14107 wl_cfgp2p_down(cfg);
14110 if (timer_pending(&cfg->scan_timeout)) {
14111 del_timer_sync(&cfg->scan_timeout);
14114 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
14116 dhd_monitor_uninit();
14117 #ifdef WLAIBSS_MCHAN
14118 bcm_cfg80211_del_ibss_if(cfg->wdev->wiphy, cfg->ibss_cfgdev);
14119 #endif /* WLAIBSS_MCHAN */
14121 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
14122 /* Clean up if not removed already */
14123 if (cfg->bss_cfgdev)
14124 wl_cfg80211_del_iface(cfg->wdev->wiphy, cfg->bss_cfgdev);
14125 #endif /* defined (WL_VIRTUAL_APSTA) || defined (DUAL_STA_STATIC_IF) */
14128 /* Clear interworking element. */
14130 cfg->wl11u = FALSE;
14131 cfg->iw_ie_len = 0;
14132 memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
14136 #ifdef CUSTOMER_HW4_DEBUG
14137 if (wl_scan_timeout_dbg_enabled)
14138 wl_scan_timeout_dbg_clear();
14139 #endif /* CUSTOMER_HW4_DEBUG */
14141 cfg->disable_roam_event = false;
14143 DNGL_FUNC(dhd_cfg80211_down, (cfg));
14146 /* Printout all netinfo entries */
14147 wl_probe_wdev_all(cfg);
14148 #endif /* DHD_IFDEBUG */
14153 s32 wl_cfg80211_up(void *para)
14155 struct bcm_cfg80211 *cfg;
14159 #ifdef DISABLE_PM_BCNRX
14162 s8 iovbuf[WLC_IOCTL_SMLEN];
14163 #endif /* DISABLE_PM_BCNRX */
14169 if ((err = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_GET_VERSION, &val,
14170 sizeof(int), false) < 0)) {
14171 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
14175 if (val != WLC_IOCTL_VERSION && val != 1) {
14176 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
14177 val, WLC_IOCTL_VERSION));
14178 return BCME_VERSION;
14180 ioctl_version = val;
14181 WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
14183 mutex_lock(&cfg->usr_sync);
14184 dhd = (dhd_pub_t *)(cfg->pub);
14185 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
14186 err = wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg));
14187 if (unlikely(err)) {
14188 mutex_unlock(&cfg->usr_sync);
14192 err = __wl_cfg80211_up(cfg);
14194 WL_ERR(("__wl_cfg80211_up failed\n"));
14198 /* IOVAR configurations with 'up' condition */
14199 #ifdef DISABLE_PM_BCNRX
14200 bcm_mkiovar("pm_bcnrx", (char *)¶m, 4, iovbuf, sizeof(iovbuf));
14201 interr = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
14202 if (unlikely(interr))
14203 WL_ERR(("Set pm_bcnrx returned (%d)\n", interr));
14204 #endif /* DISABLE_PM_BCNRX */
14206 mutex_unlock(&cfg->usr_sync);
14208 #ifdef WLAIBSS_MCHAN
14209 bcm_cfg80211_add_ibss_if(cfg->wdev->wiphy, IBSS_IF_NAME);
14210 #endif /* WLAIBSS_MCHAN */
14212 #ifdef DUAL_STA_STATIC_IF
14213 #ifdef WL_VIRTUAL_APSTA
14214 #error "Both DUAL STA and DUAL_STA_STATIC_IF can't be enabled together"
14216 /* Static Interface support is currently supported only for STA only builds (without P2P) */
14217 wl_cfg80211_create_iface(cfg->wdev->wiphy, NL80211_IFTYPE_STATION, NULL, "wlan%d");
14218 #endif /* DUAL_STA_STATIC_IF */
14223 /* Private Event to Supplicant with indication that chip hangs */
14224 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
14226 struct bcm_cfg80211 *cfg;
14228 #if defined(SOFTAP_SEND_HANGEVT)
14229 /* specifc mac address used for hang event */
14230 uint8 hang_mac[ETHER_ADDR_LEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
14231 #endif /* SOFTAP_SEND_HANGEVT */
14237 dhd = (dhd_pub_t *)(cfg->pub);
14239 #ifdef DHD_USE_EXTENDED_HANG_REASON
14240 if (dhd->hang_reason != 0) {
14241 reason = dhd->hang_reason;
14243 #endif /* DHD_USE_EXTENDED_HANG_REASON */
14245 WL_ERR(("In : chip crash eventing, reason=0x%x\n", (uint32)(dhd->hang_reason)));
14246 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
14247 #if defined(SOFTAP_SEND_HANGEVT)
14248 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
14249 cfg80211_del_sta(dev, hang_mac, GFP_ATOMIC);
14251 #endif /* SOFTAP_SEND_HANGEVT */
14253 CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
14255 #if defined(RSSIAVG)
14256 wl_free_rssi_cache(&g_rssi_cache_ctrl);
14258 #if defined(BSSCACHE)
14259 wl_free_bss_cache(&g_bss_cache_ctrl);
14267 s32 wl_cfg80211_down(void *para)
14269 struct bcm_cfg80211 *cfg;
14275 mutex_lock(&cfg->usr_sync);
14276 #if defined(RSSIAVG)
14277 wl_free_rssi_cache(&g_rssi_cache_ctrl);
14279 #if defined(BSSCACHE)
14280 wl_free_bss_cache(&g_bss_cache_ctrl);
14282 err = __wl_cfg80211_down(cfg);
14283 mutex_unlock(&cfg->usr_sync);
14288 static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item)
14290 unsigned long flags;
14292 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
14296 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14299 rptr = &profile->sec;
14302 rptr = &profile->active;
14304 case WL_PROF_BSSID:
14305 rptr = profile->bssid;
14308 rptr = &profile->ssid;
14311 rptr = &profile->channel;
14314 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14316 WL_ERR(("invalid item (%d)\n", item));
14321 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
14322 const wl_event_msg_t *e, const void *data, s32 item)
14325 const struct wlc_ssid *ssid;
14326 unsigned long flags;
14327 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
14331 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14334 ssid = (const wlc_ssid_t *) data;
14335 memset(profile->ssid.SSID, 0,
14336 sizeof(profile->ssid.SSID));
14337 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
14338 profile->ssid.SSID_len = ssid->SSID_len;
14340 case WL_PROF_BSSID:
14342 memcpy(profile->bssid, data, ETHER_ADDR_LEN);
14344 memset(profile->bssid, 0, ETHER_ADDR_LEN);
14347 memcpy(&profile->sec, data, sizeof(profile->sec));
14350 profile->active = *(const bool *)data;
14352 case WL_PROF_BEACONINT:
14353 profile->beacon_interval = *(const u16 *)data;
14355 case WL_PROF_DTIMPERIOD:
14356 profile->dtim_period = *(const u8 *)data;
14359 profile->channel = *(const u32*)data;
14365 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14367 if (err == -EOPNOTSUPP)
14368 WL_ERR(("unsupported item (%d)\n", item));
14373 void wl_cfg80211_dbg_level(u32 level)
14376 * prohibit to change debug level
14377 * by insmod parameter.
14378 * eventually debug level will be configured
14379 * in compile time by using CONFIG_XXX
14381 /* wl_dbg_level = level; */
14384 static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev)
14386 return wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS;
14389 static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg)
14391 return cfg->ibss_starter;
14394 static void wl_rst_ie(struct bcm_cfg80211 *cfg)
14396 struct wl_ie *ie = wl_to_ie(cfg);
14401 static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v)
14403 struct wl_ie *ie = wl_to_ie(cfg);
14406 if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
14407 WL_ERR(("ei crosses buffer boundary\n"));
14410 ie->buf[ie->offset] = t;
14411 ie->buf[ie->offset + 1] = l;
14412 memcpy(&ie->buf[ie->offset + 2], v, l);
14413 ie->offset += l + 2;
14418 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
14422 /* cfg80211_find_ie defined in kernel returning const u8 */
14423 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14424 4 && __GNUC_MINOR__ >= 6))
14425 _Pragma("GCC diagnostic push")
14426 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14428 ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
14429 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14430 4 && __GNUC_MINOR__ >= 6))
14431 _Pragma("GCC diagnostic pop")
14435 if (ssidie[1] != bi->SSID_len) {
14437 WL_ERR(("%s: Wrong SSID len: %d != %d\n",
14438 __FUNCTION__, ssidie[1], bi->SSID_len));
14441 WL_ERR(("Changing the SSID Info.\n"));
14442 memmove(ssidie + bi->SSID_len + 2,
14443 (ssidie + 2) + ssidie[1],
14444 *ie_size - (ssidie + 2 + ssidie[1] - ie_stream));
14445 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
14446 *ie_size = *ie_size + bi->SSID_len - ssidie[1];
14447 ssidie[1] = bi->SSID_len;
14451 if (*(ssidie + 2) == '\0')
14452 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
14456 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size)
14458 struct wl_ie *ie = wl_to_ie(cfg);
14461 if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
14462 WL_ERR(("ei_stream crosses buffer boundary\n"));
14465 memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
14466 ie->offset += ie_size;
14471 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size)
14473 struct wl_ie *ie = wl_to_ie(cfg);
14476 if (unlikely(ie->offset > dst_size)) {
14477 WL_ERR(("dst_size is not enough\n"));
14480 memcpy(dst, &ie->buf[0], ie->offset);
14485 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg)
14487 struct wl_ie *ie = wl_to_ie(cfg);
14492 static void wl_link_up(struct bcm_cfg80211 *cfg)
14494 cfg->link_up = true;
14497 static void wl_link_down(struct bcm_cfg80211 *cfg)
14499 struct wl_connect_info *conn_info = wl_to_conn(cfg);
14502 cfg->link_up = false;
14503 conn_info->req_ie_len = 0;
14504 conn_info->resp_ie_len = 0;
14507 static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg)
14509 unsigned long flags;
14511 spin_lock_irqsave(&cfg->eq_lock, flags);
14515 static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags)
14517 spin_unlock_irqrestore(&cfg->eq_lock, flags);
14520 static void wl_init_eq_lock(struct bcm_cfg80211 *cfg)
14522 spin_lock_init(&cfg->eq_lock);
14525 static void wl_delay(u32 ms)
14527 if (in_atomic() || (ms < jiffies_to_msecs(1))) {
14528 OSL_DELAY(ms*1000);
14534 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
14536 struct bcm_cfg80211 *cfg = g_bcm_cfg;
14537 struct ether_addr primary_mac;
14540 if (!p2p_is_on(cfg)) {
14541 get_primary_mac(cfg, &primary_mac);
14542 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
14544 memcpy(p2pdev_addr->octet, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE).octet,
14550 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
14552 struct bcm_cfg80211 *cfg;
14556 return wl_cfgp2p_set_p2p_noa(cfg, net, buf, len);
14559 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
14561 struct bcm_cfg80211 *cfg;
14564 return wl_cfgp2p_get_p2p_noa(cfg, net, buf, len);
14567 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
14569 struct bcm_cfg80211 *cfg;
14572 return wl_cfgp2p_set_p2p_ps(cfg, net, buf, len);
14575 s32 wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
14577 struct bcm_cfg80211 *cfg;
14580 return wl_cfgp2p_set_p2p_ecsa(cfg, net, buf, len);
14583 #ifdef P2PLISTEN_AP_SAMECHN
14584 s32 wl_cfg80211_set_p2p_resp_ap_chn(struct net_device *net, s32 enable)
14586 s32 ret = wldev_iovar_setint(net, "p2p_resp_ap_chn", enable);
14588 if ((ret == 0) && enable) {
14589 /* disable PM for p2p responding on infra AP channel */
14592 ret = wldev_ioctl(net, WLC_SET_PM, &pm, sizeof(pm), true);
14597 #endif /* P2PLISTEN_AP_SAMECHN */
14599 s32 wl_cfg80211_channel_to_freq(u32 channel)
14603 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
14604 freq = ieee80211_channel_to_frequency(channel);
14608 if (channel <= CH_MAX_2G_CHANNEL)
14609 band = IEEE80211_BAND_2GHZ;
14611 band = IEEE80211_BAND_5GHZ;
14612 freq = ieee80211_channel_to_frequency(channel, band);
14621 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
14622 const wl_event_msg_t *e, void *data) {
14624 struct net_device *ndev = NULL;
14625 u32 reason = ntoh32(e->reason);
14628 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
14631 case WLC_E_TDLS_PEER_DISCOVERED :
14632 msg = " TDLS PEER DISCOVERD ";
14634 case WLC_E_TDLS_PEER_CONNECTED :
14635 #ifdef PCIE_FULL_DONGLE
14636 dhd_tdls_update_peer_info(ndev, TRUE, (uint8 *)&e->addr.octet[0]);
14637 #endif /* PCIE_FULL_DONGLE */
14638 if (cfg->tdls_mgmt_frame) {
14639 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
14640 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14641 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0);
14642 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14643 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14644 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14646 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
14647 defined(WL_COMPAT_WIRELESS)
14648 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14649 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14652 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq,
14653 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14655 #endif /* LINUX_VERSION >= VERSION(3, 12, 0) */
14657 msg = " TDLS PEER CONNECTED ";
14659 case WLC_E_TDLS_PEER_DISCONNECTED :
14660 #ifdef PCIE_FULL_DONGLE
14661 dhd_tdls_update_peer_info(ndev, FALSE, (uint8 *)&e->addr.octet[0]);
14662 #endif /* PCIE_FULL_DONGLE */
14663 if (cfg->tdls_mgmt_frame) {
14664 kfree(cfg->tdls_mgmt_frame);
14665 cfg->tdls_mgmt_frame = NULL;
14666 cfg->tdls_mgmt_freq = 0;
14668 msg = "TDLS PEER DISCONNECTED ";
14672 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
14673 (bcmcfg_to_prmry_ndev(cfg) == ndev) ? "primary" : "secondary"));
14678 #endif /* WLTDLS */
14680 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
14682 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
14683 KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14684 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14685 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14686 u32 peer_capability, const u8 *data, size_t len)
14687 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
14688 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
14689 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14690 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14691 u32 peer_capability, const u8 *data, size_t len)
14692 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
14693 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14694 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14695 u32 peer_capability, bool initiator, const u8 *data, size_t len)
14697 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14698 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
14700 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
14704 struct bcm_cfg80211 *cfg;
14705 tdls_wfd_ie_iovar_t info;
14706 memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
14709 #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
14710 /* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
14711 * and that cuases build error
14713 BCM_REFERENCE(peer_capability);
14714 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
14716 switch (action_code) {
14717 /* We need to set TDLS Wifi Display IE to firmware
14718 * using tdls_wfd_ie iovar
14720 case WLAN_TDLS_SET_PROBE_WFD_IE:
14721 WL_ERR(("%s WLAN_TDLS_SET_PROBE_WFD_IE\n", __FUNCTION__));
14722 info.mode = TDLS_WFD_PROBE_IE_TX;
14723 memcpy(&info.data, data, len);
14726 case WLAN_TDLS_SET_SETUP_WFD_IE:
14727 WL_ERR(("%s WLAN_TDLS_SET_SETUP_WFD_IE\n", __FUNCTION__));
14728 info.mode = TDLS_WFD_IE_TX;
14729 memcpy(&info.data, data, len);
14732 case WLAN_TDLS_SET_WFD_ENABLED:
14733 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_ENABLED\n", __FUNCTION__));
14734 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), true);
14736 case WLAN_TDLS_SET_WFD_DISABLED:
14737 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_DISABLED\n", __FUNCTION__));
14738 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), false);
14741 WL_ERR(("Unsupported action code : %d\n", action_code));
14745 ret = wldev_iovar_setbuf(dev, "tdls_wfd_ie", &info, sizeof(info),
14746 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
14749 WL_ERR(("tdls_wfd_ie error %d\n", ret));
14752 #endif /* WLTDLS */
14757 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14758 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
14759 const u8 *peer, enum nl80211_tdls_operation oper)
14761 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
14762 u8 *peer, enum nl80211_tdls_operation oper)
14767 struct bcm_cfg80211 *cfg;
14770 bool tdls_auto_mode = false;
14772 dhdp = (dhd_pub_t *)(cfg->pub);
14773 memset(&info, 0, sizeof(tdls_iovar_t));
14775 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
14780 case NL80211_TDLS_DISCOVERY_REQ:
14781 /* If the discovery request is broadcast then we need to set
14782 * info.mode to Tunneled Probe Request
14784 if (memcmp(peer, (const uint8 *)BSSID_BROADCAST, ETHER_ADDR_LEN) == 0) {
14785 info.mode = TDLS_MANUAL_EP_WFD_TPQ;
14786 WL_ERR(("%s TDLS TUNNELED PRBOBE REQUEST\n", __FUNCTION__));
14788 info.mode = TDLS_MANUAL_EP_DISCOVERY;
14791 case NL80211_TDLS_SETUP:
14792 if (dhdp->tdls_mode == true) {
14793 info.mode = TDLS_MANUAL_EP_CREATE;
14794 tdls_auto_mode = false;
14795 ret = dhd_tdls_enable(dev, false, tdls_auto_mode, NULL);
14800 tdls_auto_mode = true;
14803 case NL80211_TDLS_TEARDOWN:
14804 info.mode = TDLS_MANUAL_EP_DELETE;
14807 WL_ERR(("Unsupported operation : %d\n", oper));
14811 ret = dhd_tdls_enable(dev, true, tdls_auto_mode, NULL);
14816 ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
14817 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
14819 WL_ERR(("tdls_endpoint error %d\n", ret));
14823 #endif /* WLTDLS */
14828 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *ndev, char *buf, int len,
14829 enum wl_management_type type)
14831 struct bcm_cfg80211 *cfg;
14833 struct ether_addr primary_mac;
14838 if (wl_get_drv_status(cfg, AP_CREATING, ndev)) {
14839 /* Vendor IEs should be set to FW
14840 * after SoftAP interface is brought up
14842 WL_DBG(("Skipping set IE since AP is not up \n"));
14844 } else if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
14845 /* Either stand alone AP case or P2P discovery */
14846 if (wl_get_drv_status(cfg, AP_CREATED, ndev)) {
14847 /* Stand alone AP case on primary interface */
14848 WL_DBG(("Apply IEs for Primary AP Interface \n"));
14851 /* P2P Discovery case (p2p listen) */
14852 if (!cfg->p2p->on) {
14853 /* Turn on Discovery interface */
14854 get_primary_mac(cfg, &primary_mac);
14855 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
14856 p2p_on(cfg) = true;
14857 ret = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
14858 if (unlikely(ret)) {
14859 WL_ERR(("Enable discovery failed \n"));
14863 WL_DBG(("Apply IEs for P2P Discovery Iface \n"));
14864 ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
14865 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
14868 /* Virtual AP/ P2P Group Interface */
14869 WL_DBG(("Apply IEs for iface:%s\n", ndev->name));
14870 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
14873 if (ndev != NULL) {
14876 pktflag = VNDR_IE_BEACON_FLAG;
14878 case WL_PROBE_RESP:
14879 pktflag = VNDR_IE_PRBRSP_FLAG;
14881 case WL_ASSOC_RESP:
14882 pktflag = VNDR_IE_ASSOCRSP_FLAG;
14886 ret = wl_cfg80211_set_mgmt_vndr_ies(cfg,
14887 ndev_to_cfgdev(ndev), bssidx, pktflag, buf, len);
14894 #ifdef WL_SUPPORT_AUTO_CHANNEL
14896 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
14899 s32 ret = BCME_ERROR;
14900 struct bcm_cfg80211 *cfg = g_bcm_cfg;
14901 struct wiphy *wiphy;
14902 /* Disable mpc, to avoid automatic interface down. */
14905 wiphy = bcmcfg_to_wiphy(cfg);
14906 if (wl_check_dongle_idle(wiphy) != TRUE) {
14907 WL_ERR(("FW is busy to add interface"));
14910 ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
14911 sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
14912 &cfg->ioctl_buf_sync);
14914 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
14918 /* Set interface up, explicitly. */
14921 ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
14923 WL_ERR(("set interface up failed, error = %d\n", ret));
14927 /* Stop all scan explicitly, till auto channel selection complete. */
14928 wl_set_drv_status(cfg, SCANNING, ndev);
14929 if (cfg->escan_info.ndev == NULL) {
14933 ret = wl_notify_escan_complete(cfg, ndev, true, true);
14935 WL_ERR(("set scan abort failed, error = %d\n", ret));
14944 wl_cfg80211_valid_channel_p2p(int channel)
14946 bool valid = false;
14948 /* channel 1 to 14 */
14949 if ((channel >= 1) && (channel <= 14)) {
14952 /* channel 36 to 48 */
14953 else if ((channel >= 36) && (channel <= 48)) {
14956 /* channel 149 to 161 */
14957 else if ((channel >= 149) && (channel <= 161)) {
14962 WL_INFORM(("invalid P2P chanspec, channel = %d\n", channel));
14969 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
14971 s32 ret = BCME_ERROR;
14972 struct bcm_cfg80211 *cfg = NULL;
14973 wl_uint32_list_t *list = NULL;
14974 chanspec_t chanspec = 0;
14976 memset(buf, 0, buflen);
14979 list = (wl_uint32_list_t *)buf;
14980 list->count = htod32(WL_NUMCHANSPECS);
14982 /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
14983 chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
14984 WL_CHANSPEC_CTL_SB_NONE);
14985 chanspec = wl_chspec_host_to_driver(chanspec);
14987 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
14988 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
14990 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
14997 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
15000 s32 ret = BCME_ERROR;
15003 struct bcm_cfg80211 *cfg = NULL;
15004 wl_uint32_list_t *list = NULL;
15005 chanspec_t chanspec = 0;
15007 memset(buf, 0, buflen);
15010 list = (wl_uint32_list_t *)buf;
15011 list->count = htod32(WL_NUMCHANSPECS);
15013 /* Restrict channels to 5GHz, 20MHz BW, no SB. */
15014 chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
15015 WL_CHANSPEC_CTL_SB_NONE);
15016 chanspec = wl_chspec_host_to_driver(chanspec);
15018 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
15019 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
15021 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
15025 /* Skip DFS and inavlid P2P channel. */
15026 for (i = 0, j = 0; i < dtoh32(list->count); i++) {
15027 chanspec = (chanspec_t) dtoh32(list->element[i]);
15028 channel = CHSPEC_CHANNEL(chanspec);
15030 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
15032 WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
15036 if (CHANNEL_IS_RADAR(channel) ||
15037 !(wl_cfg80211_valid_channel_p2p(CHSPEC_CHANNEL(chanspec)))) {
15040 list->element[j] = list->element[i];
15053 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
15056 s32 ret = BCME_ERROR;
15061 /* Start auto channel selection scan. */
15062 ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
15064 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
15069 /* Wait for auto channel selection, worst case possible delay is 5250ms. */
15070 retry = CHAN_SEL_RETRY_COUNT;
15073 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
15075 ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
15077 if ((ret == 0) && (dtoh32(chosen) != 0)) {
15078 chip = dhd_conf_get_chip(dhd_get_pub(ndev));
15079 if (chip != BCM43362_CHIP_ID && chip != BCM4330_CHIP_ID) {
15082 chanspec = wl_chspec_driver_to_host(chosen);
15083 printf("selected chanspec = 0x%x\n", chanspec);
15084 ctl_chan = wf_chspec_ctlchan(chanspec);
15085 printf("selected ctl_chan = 0x%x\n", ctl_chan);
15086 *channel = (u16)(ctl_chan & 0x00FF);
15088 *channel = (u16)(chosen & 0x00FF);
15089 WL_INFORM(("selected channel = %d\n", *channel));
15092 WL_INFORM(("attempt = %d, ret = %d, chosen = %d\n",
15093 (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
15097 WL_ERR(("failure, auto channel selection timed out\n"));
15107 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
15110 s32 ret = BCME_ERROR;
15111 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15113 /* Clear scan stop driver status. */
15114 wl_clr_drv_status(cfg, SCANNING, ndev);
15116 /* Enable mpc back to 1, irrespective of initial state. */
15119 ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
15120 sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
15121 &cfg->ioctl_buf_sync);
15123 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
15130 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
15132 int channel = 0, band, band_cur;
15133 s32 ret = BCME_ERROR;
15136 struct bcm_cfg80211 *cfg = NULL;
15137 struct net_device *ndev = NULL;
15139 memset(cmd, 0, total_len);
15141 buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
15143 WL_ERR(("failed to allocate chanspec buffer\n"));
15148 * Always use primary interface, irrespective of interface on which
15152 ndev = bcmcfg_to_prmry_ndev(cfg);
15155 * Make sure that FW and driver are in right state to do auto channel
15158 ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
15160 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
15164 /* Best channel selection in 2.4GHz band. */
15165 ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
15167 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
15171 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
15174 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
15178 if (CHANNEL_IS_2G(channel)) {
15179 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
15181 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
15185 pos += snprintf(pos, total_len, "%04d ", channel);
15187 // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
15188 ret = wldev_ioctl(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur), false);
15189 band = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
15190 ret = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
15192 WL_ERR(("WLC_SET_BAND error %d\n", ret));
15194 /* Best channel selection in 5GHz band. */
15195 ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
15197 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
15201 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
15204 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
15208 if (CHANNEL_IS_5G(channel)) {
15209 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
15211 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
15215 ret = wldev_ioctl(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur), true);
15217 WL_ERR(("WLC_SET_BAND error %d\n", ret));
15219 pos += snprintf(pos, total_len, "%04d ", channel);
15221 /* Set overall best channel same as 5GHz best channel. */
15222 pos += snprintf(pos, total_len, "%04d ", channel);
15229 /* Restore FW and driver back to normal state. */
15230 ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
15232 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
15235 printf("%s: channel %s\n", __FUNCTION__, cmd);
15237 return (pos - cmd);
15239 #endif /* WL_SUPPORT_AUTO_CHANNEL */
15241 static const struct rfkill_ops wl_rfkill_ops = {
15242 .set_block = wl_rfkill_set
15245 static int wl_rfkill_set(void *data, bool blocked)
15247 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
15249 WL_DBG(("Enter \n"));
15250 WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
15255 cfg->rf_blocked = blocked;
15260 static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup)
15264 WL_DBG(("Enter \n"));
15268 cfg->rfkill = rfkill_alloc("brcmfmac-wifi",
15269 wl_cfg80211_get_parent_dev(),
15270 RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)cfg);
15272 if (!cfg->rfkill) {
15277 err = rfkill_register(cfg->rfkill);
15280 rfkill_destroy(cfg->rfkill);
15282 if (!cfg->rfkill) {
15287 rfkill_unregister(cfg->rfkill);
15288 rfkill_destroy(cfg->rfkill);
15295 #ifdef DEBUGFS_CFG80211
15297 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
15298 * to turn on SCAN and DBG log.
15299 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
15300 * To see current setting of debug level,
15301 * cat /sys/kernel/debug/dhd/debug_level
15304 wl_debuglevel_write(struct file *file, const char __user *userbuf,
15305 size_t count, loff_t *ppos)
15307 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
15308 char *params, *token, *colon;
15309 uint i, tokens, log_on = 0;
15310 memset(tbuf, 0, sizeof(tbuf));
15311 memset(sublog, 0, sizeof(sublog));
15312 if (copy_from_user(&tbuf, userbuf, min_t(size_t, (sizeof(tbuf) - 1), count)))
15316 colon = strchr(params, '\n');
15319 while ((token = strsep(¶ms, " ")) != NULL) {
15320 memset(sublog, 0, sizeof(sublog));
15321 if (token == NULL || !*token)
15323 if (*token == '\0')
15325 colon = strchr(token, ':');
15326 if (colon != NULL) {
15329 tokens = sscanf(token, "%s %u", sublog, &log_on);
15334 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
15335 if (!strncmp(sublog, sublogname_map[i].sublogname,
15336 strlen(sublogname_map[i].sublogname))) {
15339 (sublogname_map[i].log_level);
15342 ~(sublogname_map[i].log_level);
15346 WL_ERR(("%s: can't parse '%s' as a "
15347 "SUBMODULE:LEVEL (%d tokens)\n",
15348 tbuf, token, tokens));
15356 wl_debuglevel_read(struct file *file, char __user *user_buf,
15357 size_t count, loff_t *ppos)
15360 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
15362 memset(tbuf, 0, sizeof(tbuf));
15364 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
15365 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
15366 sublogname_map[i].sublogname,
15367 (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
15370 return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
15373 static const struct file_operations fops_debuglevel = {
15375 .write = wl_debuglevel_write,
15376 .read = wl_debuglevel_read,
15377 .owner = THIS_MODULE,
15381 static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg)
15384 struct dentry *_dentry;
15387 cfg->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
15388 if (!cfg->debugfs || IS_ERR(cfg->debugfs)) {
15389 if (cfg->debugfs == ERR_PTR(-ENODEV))
15390 WL_ERR(("Debugfs is not enabled on this kernel\n"));
15392 WL_ERR(("Can not create debugfs directory\n"));
15393 cfg->debugfs = NULL;
15397 _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
15398 cfg->debugfs, cfg, &fops_debuglevel);
15399 if (!_dentry || IS_ERR(_dentry)) {
15400 WL_ERR(("failed to create debug_level debug file\n"));
15401 wl_free_debugfs(cfg);
15406 static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg)
15411 debugfs_remove_recursive(cfg->debugfs);
15412 cfg->debugfs = NULL;
15415 #endif /* DEBUGFS_CFG80211 */
15417 struct device *wl_cfg80211_get_parent_dev(void)
15419 return cfg80211_parent_dev;
15422 void wl_cfg80211_set_parent_dev(void *dev)
15424 cfg80211_parent_dev = dev;
15427 static void wl_cfg80211_clear_parent_dev(void)
15429 cfg80211_parent_dev = NULL;
15432 void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
15434 wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr", NULL,
15435 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
15436 memcpy(mac->octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
15438 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role)
15440 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
15441 if (((dev_role == NL80211_IFTYPE_AP) &&
15442 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
15443 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
15444 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
15446 WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role, dhd->op_mode));
15452 int wl_cfg80211_do_driver_init(struct net_device *net)
15454 struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
15456 if (!cfg || !cfg->wdev)
15459 if (dhd_do_driver_init(cfg->wdev->netdev) < 0)
15465 void wl_cfg80211_enable_trace(u32 level)
15467 wl_dbg_level = level;
15468 printf("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level);
15471 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
15474 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
15475 bcm_struct_cfgdev *cfgdev, u64 cookie)
15477 /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
15478 * is passed with CMD_FRAME. This callback is supposed to cancel
15479 * the OFFCHANNEL Wait. Since we are already taking care of that
15480 * with the tx_mgmt logic, do nothing here.
15485 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
15489 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len)
15493 while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_INTERWORKING_ID))) {
15494 return (bcm_tlv_t *)ie;
15501 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
15502 uint8 ie_id, uint8 *data, uint8 data_len)
15507 ie_setbuf_t *ie_setbuf;
15509 if (ie_id != DOT11_MNG_INTERWORKING_ID)
15510 return BCME_UNSUPPORTED;
15512 /* Validate the pktflag parameter */
15513 if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
15514 VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
15515 VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
15516 VNDR_IE_CUSTOM_FLAG))) {
15517 WL_ERR(("cfg80211 Add IE: Invalid packet flag 0x%x\n", pktflag));
15521 /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
15522 pktflag = htod32(pktflag);
15524 buf_len = sizeof(ie_setbuf_t) + data_len - 1;
15525 ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL);
15528 WL_ERR(("Error allocating buffer for IE\n"));
15532 if (cfg->iw_ie_len == data_len && !memcmp(cfg->iw_ie, data, data_len)) {
15533 WL_ERR(("Previous IW IE is equals to current IE\n"));
15538 strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
15539 ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
15541 /* Buffer contains only 1 IE */
15542 iecount = htod32(1);
15543 memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int));
15544 memcpy((void *)&ie_setbuf->ie_buffer.ie_list[0].pktflag, &pktflag, sizeof(uint32));
15546 /* Now, add the IE to the buffer */
15547 ie_setbuf->ie_buffer.ie_list[0].ie_data.id = ie_id;
15549 /* if already set with previous values, delete it first */
15550 if (cfg->iw_ie_len != 0) {
15551 WL_DBG(("Different IW_IE was already set. clear first\n"));
15553 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = 0;
15555 err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
15556 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
15558 if (err != BCME_OK)
15562 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
15563 memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len);
15565 err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
15566 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
15568 if (err == BCME_OK) {
15569 memcpy(cfg->iw_ie, data, data_len);
15570 cfg->iw_ie_len = data_len;
15573 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
15584 wl_cfg80211_dfs_ap_move(struct net_device *ndev, char *data, char *command, int total_len)
15586 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15587 char ioctl_buf[50];
15590 chanspec_t chanspec = 0;
15592 int bytes_written = 0;
15593 wl_dfs_ap_move_status_t *status;
15594 char chanbuf[CHANSPEC_STR_LEN];
15595 const char *dfs_state_str[DFS_SCAN_S_MAX] = {
15596 "Radar Free On Channel",
15597 "Radar Found On Channel",
15598 "Radar Scan In Progress",
15599 "Radar Scan Aborted",
15600 "RSDB Mode switch in Progress For Scan"
15602 if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
15603 bytes_written = snprintf(command, total_len, "AP is not UP\n");
15604 return bytes_written;
15607 if ((err = wldev_iovar_getbuf(ndev, "dfs_ap_move", NULL, 0,
15608 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
15609 WL_ERR(("setting dfs_ap_move failed with err=%d \n", err));
15612 status = (wl_dfs_ap_move_status_t *)cfg->ioctl_buf;
15614 if (status->version != WL_DFS_AP_MOVE_VERSION) {
15615 err = BCME_UNSUPPORTED;
15616 WL_ERR(("err=%d version=%d\n", err, status->version));
15620 if (status->move_status != (int8) DFS_SCAN_S_IDLE) {
15621 chanspec = wl_chspec_driver_to_host(status->chanspec);
15622 if (chanspec != 0 && chanspec != INVCHANSPEC) {
15623 wf_chspec_ntoa(chanspec, chanbuf);
15624 bytes_written = snprintf(command, total_len,
15625 "AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
15627 bytes_written += snprintf(command + bytes_written, total_len,
15628 "%s\n", dfs_state_str[status->move_status]);
15629 return bytes_written;
15631 bytes_written = snprintf(command, total_len, "dfs AP move in IDLE state\n");
15632 return bytes_written;
15637 abort = bcm_atoi(data);
15639 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &abort,
15640 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
15641 WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
15645 chanspec = wf_chspec_aton(data);
15646 if (chanspec != 0) {
15647 val = wl_chspec_host_to_driver(chanspec);
15648 if (val != INVCHANSPEC) {
15649 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &val,
15650 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
15651 WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
15654 WL_DBG((" set dfs_ap_move successfull"));
15656 err = BCME_USAGE_ERROR;
15664 wl_cfg80211_wbtext_config(struct net_device *ndev, char *data, char *command, int total_len)
15667 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15668 wl_roam_prof_band_t *rp;
15669 int err = -EINVAL, bytes_written = 0;
15670 size_t len = strlen(data);
15673 rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
15674 * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
15675 if (unlikely(!rp)) {
15676 WL_ERR(("%s: failed to allocate memory\n", __func__));
15681 rp->ver = WL_MAX_ROAM_PROF_VER;
15682 if (*data && (!strncmp(data, "b", 1))) {
15683 rp->band = WLC_BAND_2G;
15684 } else if (*data && (!strncmp(data, "a", 1))) {
15685 rp->band = WLC_BAND_5G;
15687 err = snprintf(command, total_len, "Missing band\n");
15692 /* Getting roam profile from fw */
15693 if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
15694 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
15695 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
15698 memcpy(rp, cfg->ioctl_buf, sizeof(*rp) * WL_MAX_ROAM_PROF_BRACKETS);
15699 /* roam_prof version get */
15700 if (rp->ver != WL_MAX_ROAM_PROF_VER) {
15701 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
15705 if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
15706 WL_ERR(("bad length (=%d) in return data\n", rp->len));
15712 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15713 /* printing contents of roam profile data from fw and exits
15714 * if code hits any of one of the below condtion. If remaining
15715 * length of buffer is less than roam profile size or
15716 * if there is no valid entry.
15718 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
15719 (rp->roam_prof[i].fullscan_period == 0)) {
15722 bytes_written += snprintf(command+bytes_written,
15723 total_len, "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)\n",
15724 rp->roam_prof[i].roam_trigger, rp->roam_prof[i].rssi_lower,
15725 rp->roam_prof[i].channel_usage,
15726 rp->roam_prof[i].cu_avg_calc_dur);
15728 err = bytes_written;
15731 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15732 /* reading contents of roam profile data from fw and exits
15733 * if code hits any of one of the below condtion, If remaining
15734 * length of buffer is less than roam profile size or if there
15735 * is no valid entry.
15737 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
15738 (rp->roam_prof[i].fullscan_period == 0)) {
15742 /* Do not set roam_prof from upper layer if fw doesn't have 2 rows */
15744 WL_ERR(("FW must have 2 rows to fill roam_prof\n"));
15748 /* setting roam profile to fw */
15750 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15751 rp->roam_prof[i].roam_trigger = simple_strtol(data, &data, 10);
15753 rp->roam_prof[i].rssi_lower = simple_strtol(data, &data, 10);
15755 rp->roam_prof[i].channel_usage = simple_strtol(data, &data, 10);
15757 rp->roam_prof[i].cu_avg_calc_dur = simple_strtol(data, &data, 10);
15759 rp_len += sizeof(wl_roam_prof_t);
15760 if (*data == '\0') {
15766 WL_ERR(("Only two roam_prof rows supported.\n"));
15771 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
15772 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
15773 WL_ERR(("seting roam_profile failed with err %d\n", err));
15783 int wl_cfg80211_wbtext_weight_config(struct net_device *ndev, char *data,
15784 char *command, int total_len)
15786 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15787 int bytes_written = 0, err = -EINVAL, argc = 0;
15788 char rssi[5], band[5], weight[5];
15789 char *endptr = NULL;
15790 wnm_bss_select_weight_cfg_t *bwcfg;
15792 bwcfg = kzalloc(sizeof(*bwcfg), GFP_KERNEL);
15793 if (unlikely(!bwcfg)) {
15794 WL_ERR(("%s: failed to allocate memory\n", __func__));
15798 bwcfg->version = WNM_BSSLOAD_MONITOR_VERSION;
15802 argc = sscanf(data, "%s %s %s", rssi, band, weight);
15804 if (!strcasecmp(rssi, "rssi"))
15805 bwcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
15806 else if (!strcasecmp(rssi, "cu"))
15807 bwcfg->type = WNM_BSS_SELECT_TYPE_CU;
15809 /* Usage DRIVER WBTEXT_WEIGHT_CONFIG <rssi/cu> <band> <weight> */
15810 WL_ERR(("%s: Command usage error\n", __func__));
15814 if (!strcasecmp(band, "a"))
15815 bwcfg->band = WLC_BAND_5G;
15816 else if (!strcasecmp(band, "b"))
15817 bwcfg->band = WLC_BAND_2G;
15818 else if (!strcasecmp(band, "all"))
15819 bwcfg->band = WLC_BAND_ALL;
15821 WL_ERR(("%s: Command usage error\n", __func__));
15826 /* If there is no data after band, getting wnm_bss_select_weight from fw */
15827 if (bwcfg->band == WLC_BAND_ALL) {
15828 WL_ERR(("band option \"all\" is for set only, not get\n"));
15831 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_weight", bwcfg,
15833 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
15834 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d \n", err));
15837 memcpy(bwcfg, cfg->ioctl_buf, sizeof(*bwcfg));
15838 bytes_written = snprintf(command, total_len, "%s %s weight = %d\n",
15839 (bwcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU",
15840 (bwcfg->band == WLC_BAND_2G) ? "2G" : "5G", bwcfg->weight);
15841 err = bytes_written;
15844 /* if weight is non integer returns command usage error */
15845 bwcfg->weight = simple_strtol(weight, &endptr, 0);
15846 if (*endptr != '\0') {
15847 WL_ERR(("%s: Command usage error", __func__));
15850 /* setting weight for iovar wnm_bss_select_weight to fw */
15851 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_weight", bwcfg,
15853 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
15854 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d\n", err));
15864 /* WBTEXT_TUPLE_MIN_LEN_CHECK :strlen(low)+" "+strlen(high)+" "+strlen(factor) */
15865 #define WBTEXT_TUPLE_MIN_LEN_CHECK 5
15867 int wl_cfg80211_wbtext_table_config(struct net_device *ndev, char *data,
15868 char *command, int total_len)
15870 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15871 int bytes_written = 0, err = -EINVAL;
15872 char rssi[5], band[5];
15873 int btcfg_len = 0, i = 0, parsed_len = 0;
15874 wnm_bss_select_factor_cfg_t *btcfg;
15875 size_t slen = strlen(data);
15876 char *start_addr = NULL;
15879 btcfg = kzalloc((sizeof(*btcfg) + sizeof(*btcfg) *
15880 WL_FACTOR_TABLE_MAX_LIMIT), GFP_KERNEL);
15881 if (unlikely(!btcfg)) {
15882 WL_ERR(("%s: failed to allocate memory\n", __func__));
15887 btcfg->version = WNM_BSS_SELECT_FACTOR_VERSION;
15888 btcfg->band = WLC_BAND_AUTO;
15892 sscanf(data, "%s %s", rssi, band);
15894 if (!strcasecmp(rssi, "rssi")) {
15895 btcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
15897 else if (!strcasecmp(rssi, "cu")) {
15898 btcfg->type = WNM_BSS_SELECT_TYPE_CU;
15901 WL_ERR(("%s: Command usage error\n", __func__));
15905 if (!strcasecmp(band, "a")) {
15906 btcfg->band = WLC_BAND_5G;
15908 else if (!strcasecmp(band, "b")) {
15909 btcfg->band = WLC_BAND_2G;
15911 else if (!strcasecmp(band, "all")) {
15912 btcfg->band = WLC_BAND_ALL;
15915 WL_ERR(("%s: Command usage, Wrong band\n", __func__));
15919 if ((slen - 1) == (strlen(rssi) + strlen(band))) {
15920 /* Getting factor table using iovar 'wnm_bss_select_table' from fw */
15921 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_table", btcfg,
15923 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
15924 WL_ERR(("Getting wnm_bss_select_table failed with err=%d \n", err));
15927 memcpy(btcfg, cfg->ioctl_buf, sizeof(*btcfg));
15928 memcpy(btcfg, cfg->ioctl_buf, (btcfg->count+1) * sizeof(*btcfg));
15930 bytes_written += snprintf(command + bytes_written, total_len,
15931 "No of entries in table: %d\n", btcfg->count);
15932 bytes_written += snprintf(command + bytes_written, total_len, "%s factor table\n",
15933 (btcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU");
15934 bytes_written += snprintf(command + bytes_written, total_len,
15935 "low\thigh\tfactor\n");
15936 for (i = 0; i <= btcfg->count-1; i++) {
15937 bytes_written += snprintf(command + bytes_written, total_len,
15938 "%d\t%d\t%d\n", btcfg->params[i].low, btcfg->params[i].high,
15939 btcfg->params[i].factor);
15941 err = bytes_written;
15944 memset(btcfg->params, 0, sizeof(*btcfg) * WL_FACTOR_TABLE_MAX_LIMIT);
15945 data += (strlen(rssi) + strlen(band) + 2);
15947 slen = slen - (strlen(rssi) + strlen(band) + 2);
15948 for (i = 0; i < WL_FACTOR_TABLE_MAX_LIMIT; i++) {
15949 if (parsed_len + WBTEXT_TUPLE_MIN_LEN_CHECK <= slen) {
15950 btcfg->params[i].low = simple_strtol(data, &data, 10);
15952 btcfg->params[i].high = simple_strtol(data, &data, 10);
15954 btcfg->params[i].factor = simple_strtol(data, &data, 10);
15956 if (*data == '\0') {
15960 parsed_len = data - start_addr;
15962 WL_ERR(("%s:Command usage:less no of args\n", __func__));
15966 btcfg_len = sizeof(*btcfg) + ((btcfg->count) * sizeof(*btcfg));
15967 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_table", btcfg, btcfg_len,
15968 cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
15969 WL_ERR(("seting wnm_bss_select_table failed with err %d\n", err));
15981 wl_cfg80211_wbtext_delta_config(struct net_device *ndev, char *data, char *command, int total_len)
15984 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15985 int err = -EINVAL, bytes_written = 0, argc = 0, val, len = 0;
15986 char delta[5], band[5], *endptr = NULL;
15987 wl_roam_prof_band_t *rp;
15989 rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
15990 * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
15991 if (unlikely(!rp)) {
15992 WL_ERR(("%s: failed to allocate memory\n", __func__));
15997 argc = sscanf(data, "%s %s", band, delta);
15998 if (!strcasecmp(band, "a"))
15999 rp->band = WLC_BAND_5G;
16000 else if (!strcasecmp(band, "b"))
16001 rp->band = WLC_BAND_2G;
16003 WL_ERR(("%s: Missing band\n", __func__));
16006 /* Getting roam profile from fw */
16007 if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
16008 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
16009 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
16012 memcpy(rp, cfg->ioctl_buf, sizeof(wl_roam_prof_band_t));
16013 if (rp->ver != WL_MAX_ROAM_PROF_VER) {
16014 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
16018 if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
16019 WL_ERR(("bad length (=%d) in return data\n", rp->len));
16025 /* if delta is non integer returns command usage error */
16026 val = simple_strtol(delta, &endptr, 0);
16027 if (*endptr != '\0') {
16028 WL_ERR(("%s: Command usage error", __func__));
16031 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
16033 * Checking contents of roam profile data from fw and exits
16034 * if code hits below condtion. If remaining length of buffer is
16035 * less than roam profile size or if there is no valid entry.
16037 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
16038 (rp->roam_prof[i].fullscan_period == 0)) {
16041 if (rp->roam_prof[i].channel_usage != 0) {
16042 rp->roam_prof[i].roam_delta = val;
16044 len += sizeof(wl_roam_prof_t);
16048 if (rp->roam_prof[i].channel_usage != 0) {
16049 bytes_written = snprintf(command, total_len,
16050 "%s Delta %d\n", (rp->band == WLC_BAND_2G) ? "2G" : "5G",
16051 rp->roam_prof[0].roam_delta);
16053 err = bytes_written;
16057 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
16058 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
16059 WL_ERR(("seting roam_profile failed with err %d\n", err));
16069 int wl_cfg80211_scan_stop(bcm_struct_cfgdev *cfgdev)
16071 struct bcm_cfg80211 *cfg = NULL;
16072 struct net_device *ndev = NULL;
16073 unsigned long flags;
16074 int clear_flag = 0;
16077 WL_TRACE(("Enter\n"));
16083 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16085 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
16086 #ifdef WL_CFG80211_P2P_DEV_IF
16087 if (cfg->scan_request && cfg->scan_request->wdev == cfgdev)
16089 if (cfg->scan_request && cfg->scan_request->dev == cfgdev)
16092 cfg80211_scan_done(cfg->scan_request, true);
16093 cfg->scan_request = NULL;
16096 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
16099 wl_clr_drv_status(cfg, SCANNING, ndev);
16104 bool wl_cfg80211_is_concurrent_mode(void)
16106 if ((g_bcm_cfg) && (wl_get_drv_status_all(g_bcm_cfg, CONNECTED) > 1)) {
16113 void* wl_cfg80211_get_dhdp()
16115 struct bcm_cfg80211 *cfg = g_bcm_cfg;
16120 bool wl_cfg80211_is_p2p_active(void)
16122 return (g_bcm_cfg && g_bcm_cfg->p2p);
16125 bool wl_cfg80211_is_roam_offload(void)
16127 return (g_bcm_cfg && g_bcm_cfg->roam_offload);
16130 bool wl_cfg80211_is_event_from_connected_bssid(const wl_event_msg_t *e, int ifidx)
16132 dhd_pub_t *dhd = NULL;
16133 struct net_device *ndev = NULL;
16134 u8 *curbssid = NULL;
16136 dhd = (dhd_pub_t *)(g_bcm_cfg->pub);
16139 ndev = dhd_idx2net(dhd, ifidx);
16142 if (!dhd || !ndev) {
16146 curbssid = wl_read_prof(g_bcm_cfg, ndev, WL_PROF_BSSID);
16148 return memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0;
16151 static void wl_cfg80211_work_handler(struct work_struct * work)
16153 struct bcm_cfg80211 *cfg = NULL;
16154 struct net_info *iter, *next;
16157 BCM_SET_CONTAINER_OF(cfg, work, struct bcm_cfg80211, pm_enable_work.work);
16158 WL_DBG(("Enter \n"));
16159 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16160 4 && __GNUC_MINOR__ >= 6))
16161 _Pragma("GCC diagnostic push")
16162 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16164 for_each_ndev(cfg, iter, next) {
16165 /* p2p discovery iface ndev could be null */
16167 if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev) ||
16168 (wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_BSS &&
16169 wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_IBSS))
16172 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
16173 &pm, sizeof(pm), true)) != 0) {
16174 if (err == -ENODEV)
16175 WL_DBG(("%s:netdev not ready\n",
16176 iter->ndev->name));
16178 WL_ERR(("%s:error (%d)\n",
16179 iter->ndev->name, err));
16181 wl_cfg80211_update_power_mode(iter->ndev);
16185 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16186 4 && __GNUC_MINOR__ >= 6))
16187 _Pragma("GCC diagnostic pop")
16189 DHD_OS_WAKE_UNLOCK(cfg->pub);
16193 wl_get_action_category(void *frame, u32 frame_len)
16196 u8 *ptr = (u8 *)frame;
16198 return DOT11_ACTION_CAT_ERR_MASK;
16199 if (frame_len < DOT11_ACTION_HDR_LEN)
16200 return DOT11_ACTION_CAT_ERR_MASK;
16201 category = ptr[DOT11_ACTION_CAT_OFF];
16202 WL_INFORM(("Action Category: %d\n", category));
16207 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
16209 u8 *ptr = (u8 *)frame;
16210 if (frame == NULL || ret_action == NULL)
16212 if (frame_len < DOT11_ACTION_HDR_LEN)
16214 if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
16216 *ret_action = ptr[DOT11_ACTION_ACT_OFF];
16217 WL_INFORM(("Public Action : %d\n", *ret_action));
16223 wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
16224 const struct ether_addr *bssid)
16229 bzero(&e, sizeof(e));
16230 e.event_type = cpu_to_be32(WLC_E_BSSID);
16231 memcpy(&e.addr, bssid, ETHER_ADDR_LEN);
16232 /* trigger the roam event handler */
16233 WL_INFORM(("Delayed roam to " MACDBG "\n", MAC2STRDBG((u8*)(bssid))));
16234 err = wl_notify_roaming_status(cfg, ndev_to_cfgdev(ndev), &e, NULL);
16240 wl_cfg80211_parse_vndr_ies(u8 *parse, u32 len,
16241 struct parsed_vndr_ies *vndr_ies)
16246 struct parsed_vndr_ie_info *parsed_info;
16250 remained_len = (s32)len;
16251 memset(vndr_ies, 0, sizeof(*vndr_ies));
16253 WL_INFORM(("---> len %d\n", len));
16254 ie = (bcm_tlv_t *) parse;
16255 if (!bcm_valid_tlv(ie, remained_len))
16258 if (count >= MAX_VNDR_IE_NUMBER)
16260 if (ie->id == DOT11_MNG_VS_ID) {
16261 vndrie = (vndr_ie_t *) ie;
16262 /* len should be bigger than OUI length + one data length at least */
16263 if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
16264 WL_ERR(("%s: invalid vndr ie. length is too small %d\n",
16265 __FUNCTION__, vndrie->len));
16268 /* if wpa or wme ie, do not add ie */
16269 if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) &&
16270 ((vndrie->data[0] == WPA_OUI_TYPE) ||
16271 (vndrie->data[0] == WME_OUI_TYPE))) {
16272 CFGP2P_DBG(("Found WPA/WME oui. Do not add it\n"));
16276 parsed_info = &vndr_ies->ie_info[count++];
16278 /* save vndr ie information */
16279 parsed_info->ie_ptr = (char *)vndrie;
16280 parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN);
16281 memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t));
16282 vndr_ies->count = count;
16284 WL_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x len:%d\n",
16285 parsed_info->vndrie.oui[0], parsed_info->vndrie.oui[1],
16286 parsed_info->vndrie.oui[2], parsed_info->vndrie.data[0],
16287 parsed_info->ie_len));
16290 ie = bcm_next_tlv(ie, &remained_len);
16296 wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, s32 bssidx)
16299 struct net_info *netinfo;
16300 s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG,
16301 VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
16303 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16304 if (!netinfo || !netinfo->wdev) {
16305 WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
16309 WL_DBG(("clear management vendor IEs for bssidx:%d \n", bssidx));
16310 /* Clear the IEs set in the firmware so that host is in sync with firmware */
16311 for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
16312 if (wl_cfg80211_set_mgmt_vndr_ies(cfg, wdev_to_cfgdev(netinfo->wdev),
16313 bssidx, vndrie_flag[index], NULL, 0) < 0)
16314 WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
16321 wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg)
16323 struct net_info *iter, *next;
16325 WL_DBG(("clear management vendor IEs \n"));
16326 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16327 4 && __GNUC_MINOR__ >= 6))
16328 _Pragma("GCC diagnostic push")
16329 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16331 for_each_ndev(cfg, iter, next) {
16332 wl_cfg80211_clear_per_bss_ies(cfg, iter->bssidx);
16334 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16335 4 && __GNUC_MINOR__ >= 6))
16336 _Pragma("GCC diagnostic pop")
16341 #define WL_VNDR_IE_MAXLEN 2048
16342 static s8 g_mgmt_ie_buf[WL_VNDR_IE_MAXLEN];
16344 wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16345 s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
16347 struct net_device *ndev = NULL;
16349 u8 *curr_ie_buf = NULL;
16350 u8 *mgmt_ie_buf = NULL;
16351 u32 mgmt_ie_buf_len = 0;
16352 u32 *mgmt_ie_len = 0;
16353 u32 del_add_ie_buf_len = 0;
16354 u32 total_ie_buf_len = 0;
16355 u32 parsed_ie_buf_len = 0;
16356 struct parsed_vndr_ies old_vndr_ies;
16357 struct parsed_vndr_ies new_vndr_ies;
16360 s32 remained_buf_len;
16361 wl_bss_vndr_ies_t *ies = NULL;
16362 struct net_info *netinfo;
16364 WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d \n",
16365 pktflag, bssidx, vndr_ie_len));
16367 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16369 if (bssidx > WL_MAX_IFS) {
16370 WL_ERR(("bssidx > supported concurrent Ifaces \n"));
16374 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16376 WL_ERR(("net_info ptr is NULL \n"));
16380 /* Clear the global buffer */
16381 memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf));
16382 curr_ie_buf = g_mgmt_ie_buf;
16383 ies = &netinfo->bss.ies;
16386 case VNDR_IE_PRBRSP_FLAG :
16387 mgmt_ie_buf = ies->probe_res_ie;
16388 mgmt_ie_len = &ies->probe_res_ie_len;
16389 mgmt_ie_buf_len = sizeof(ies->probe_res_ie);
16391 case VNDR_IE_ASSOCRSP_FLAG :
16392 mgmt_ie_buf = ies->assoc_res_ie;
16393 mgmt_ie_len = &ies->assoc_res_ie_len;
16394 mgmt_ie_buf_len = sizeof(ies->assoc_res_ie);
16396 case VNDR_IE_BEACON_FLAG :
16397 mgmt_ie_buf = ies->beacon_ie;
16398 mgmt_ie_len = &ies->beacon_ie_len;
16399 mgmt_ie_buf_len = sizeof(ies->beacon_ie);
16401 case VNDR_IE_PRBREQ_FLAG :
16402 mgmt_ie_buf = ies->probe_req_ie;
16403 mgmt_ie_len = &ies->probe_req_ie_len;
16404 mgmt_ie_buf_len = sizeof(ies->probe_req_ie);
16406 case VNDR_IE_ASSOCREQ_FLAG :
16407 mgmt_ie_buf = ies->assoc_req_ie;
16408 mgmt_ie_len = &ies->assoc_req_ie_len;
16409 mgmt_ie_buf_len = sizeof(ies->assoc_req_ie);
16412 mgmt_ie_buf = NULL;
16413 mgmt_ie_len = NULL;
16414 WL_ERR(("not suitable packet type (%d)\n", pktflag));
16418 if (vndr_ie_len > mgmt_ie_buf_len) {
16419 WL_ERR(("extra IE size too big\n"));
16422 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
16423 if (vndr_ie && vndr_ie_len && curr_ie_buf) {
16425 /* must discard vndr_ie constness, attempt to change vndr_ie arg to non-const
16426 * causes cascade of errors in other places, fix involves const casts there
16428 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16429 4 && __GNUC_MINOR__ >= 6))
16430 _Pragma("GCC diagnostic push")
16431 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16433 if ((ret = wl_cfg80211_parse_vndr_ies((u8 *)vndr_ie,
16434 vndr_ie_len, &new_vndr_ies)) < 0) {
16435 WL_ERR(("parse vndr ie failed \n"));
16438 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16439 4 && __GNUC_MINOR__ >= 6))
16440 _Pragma("GCC diagnostic pop")
16442 for (i = 0; i < new_vndr_ies.count; i++) {
16443 struct parsed_vndr_ie_info *vndrie_info =
16444 &new_vndr_ies.ie_info[i];
16446 if ((parsed_ie_buf_len + vndrie_info->ie_len) > WL_VNDR_IE_MAXLEN) {
16447 WL_ERR(("IE size is too big (%d > %d)\n",
16448 parsed_ie_buf_len, WL_VNDR_IE_MAXLEN));
16453 memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
16454 vndrie_info->ie_len);
16455 parsed_ie_buf_len += vndrie_info->ie_len;
16459 if (mgmt_ie_buf != NULL) {
16460 if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
16461 (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) {
16462 WL_INFORM(("Previous mgmt IE is equals to current IE"));
16466 /* parse old vndr_ie */
16467 if ((ret = wl_cfg80211_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len,
16468 &old_vndr_ies)) < 0) {
16469 WL_ERR(("parse vndr ie failed \n"));
16472 /* make a command to delete old ie */
16473 for (i = 0; i < old_vndr_ies.count; i++) {
16474 struct parsed_vndr_ie_info *vndrie_info =
16475 &old_vndr_ies.ie_info[i];
16477 WL_INFORM(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
16478 vndrie_info->vndrie.id, vndrie_info->vndrie.len,
16479 vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
16480 vndrie_info->vndrie.oui[2]));
16482 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
16483 pktflag, vndrie_info->vndrie.oui,
16484 vndrie_info->vndrie.id,
16485 vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
16486 vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
16489 curr_ie_buf += del_add_ie_buf_len;
16490 total_ie_buf_len += del_add_ie_buf_len;
16495 /* Add if there is any extra IE */
16496 if (mgmt_ie_buf && parsed_ie_buf_len) {
16499 remained_buf_len = mgmt_ie_buf_len;
16501 /* make a command to add new ie */
16502 for (i = 0; i < new_vndr_ies.count; i++) {
16503 struct parsed_vndr_ie_info *vndrie_info =
16504 &new_vndr_ies.ie_info[i];
16506 WL_INFORM(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
16507 vndrie_info->vndrie.id, vndrie_info->vndrie.len,
16508 vndrie_info->ie_len - 2,
16509 vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
16510 vndrie_info->vndrie.oui[2]));
16512 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
16513 pktflag, vndrie_info->vndrie.oui,
16514 vndrie_info->vndrie.id,
16515 vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
16516 vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
16519 /* verify remained buf size before copy data */
16520 if (remained_buf_len >= vndrie_info->ie_len) {
16521 remained_buf_len -= vndrie_info->ie_len;
16523 WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
16524 "found vndr ies # = %d(cur %d), remained len %d, "
16525 "cur mgmt_ie_len %d, new ie len = %d\n",
16526 pktflag, new_vndr_ies.count, i, remained_buf_len,
16527 *mgmt_ie_len, vndrie_info->ie_len));
16531 /* save the parsed IE in cfg struct */
16532 memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
16533 vndrie_info->ie_len);
16534 *mgmt_ie_len += vndrie_info->ie_len;
16535 curr_ie_buf += del_add_ie_buf_len;
16536 total_ie_buf_len += del_add_ie_buf_len;
16540 if (total_ie_buf_len && cfg->ioctl_buf != NULL) {
16541 ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
16542 total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
16543 bssidx, &cfg->ioctl_buf_sync);
16545 WL_ERR(("vndr ie set error : %d\n", ret));
16553 #ifdef WL_CFG80211_ACL
16555 wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
16556 const struct cfg80211_acl_data *acl)
16561 int macmode = MACLIST_MODE_DISABLED;
16562 struct maclist *list;
16564 /* get the MAC filter mode */
16565 if (acl && acl->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED) {
16566 macmode = MACLIST_MODE_ALLOW;
16567 } else if (acl && acl->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
16568 acl->n_acl_entries) {
16569 macmode = MACLIST_MODE_DENY;
16572 /* if acl == NULL, macmode is still disabled.. */
16573 if (macmode == MACLIST_MODE_DISABLED) {
16574 if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, NULL)) != 0)
16575 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
16580 macnum = acl->n_acl_entries;
16581 if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
16582 WL_ERR(("%s : invalid number of MAC address entries %d\n",
16583 __FUNCTION__, macnum));
16587 /* allocate memory for the MAC list */
16588 list = (struct maclist*)kmalloc(sizeof(int) +
16589 sizeof(struct ether_addr) * macnum, GFP_KERNEL);
16591 WL_ERR(("%s : failed to allocate memory\n", __FUNCTION__));
16595 /* prepare the MAC list */
16596 list->count = htod32(macnum);
16597 for (i = 0; i < macnum; i++) {
16598 memcpy(&list->ea[i], &acl->mac_addrs[i], ETHER_ADDR_LEN);
16601 if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, list)) != 0)
16602 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
16608 #endif /* WL_CFG80211_ACL */
16610 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
16611 int wl_chspec_chandef(chanspec_t chanspec,
16612 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
16613 struct cfg80211_chan_def *chandef,
16614 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16615 struct chan_info *chaninfo,
16616 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
16617 struct wiphy *wiphy)
16623 struct ieee80211_channel *chan;
16628 channel = CHSPEC_CHANNEL(chanspec);
16630 switch (CHSPEC_BW(chanspec)) {
16631 case WL_CHANSPEC_BW_20:
16632 chan_type = NL80211_CHAN_HT20;
16634 case WL_CHANSPEC_BW_40:
16636 if (CHSPEC_SB_UPPER(chanspec)) {
16637 channel += CH_10MHZ_APART;
16639 channel -= CH_10MHZ_APART;
16642 chan_type = NL80211_CHAN_HT40PLUS;
16645 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16646 case WL_CHANSPEC_BW_80:
16647 case WL_CHANSPEC_BW_8080:
16649 uint16 sb = CHSPEC_CTL_SB(chanspec);
16651 if (sb == WL_CHANSPEC_CTL_SB_LL) {
16652 channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
16653 } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
16654 channel -= CH_10MHZ_APART;
16655 } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
16656 channel += CH_10MHZ_APART;
16658 /* WL_CHANSPEC_CTL_SB_UU */
16659 channel += (CH_10MHZ_APART + CH_20MHZ_APART);
16662 if (sb == WL_CHANSPEC_CTL_SB_LL || sb == WL_CHANSPEC_CTL_SB_LU)
16663 chan_type = NL80211_CHAN_HT40MINUS;
16664 else if (sb == WL_CHANSPEC_CTL_SB_UL || sb == WL_CHANSPEC_CTL_SB_UU)
16665 chan_type = NL80211_CHAN_HT40PLUS;
16668 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16670 chan_type = NL80211_CHAN_HT20;
16675 if (CHSPEC_IS5G(chanspec))
16676 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_5GHZ);
16678 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
16680 chan = ieee80211_get_channel(wiphy, freq);
16681 WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
16682 channel, freq, chan_type, chan));
16684 if (unlikely(!chan)) {
16685 /* fw and cfg80211 channel lists are not in sync */
16686 WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
16691 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16692 cfg80211_chandef_create(chandef, chan, chan_type);
16693 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
16698 chaninfo->freq = freq;
16699 chaninfo->chan_type = chan_type;
16700 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16705 wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
16708 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16709 struct cfg80211_chan_def chandef;
16710 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
16715 struct chan_info chaninfo;
16716 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16719 printf("wiphy is null\n");
16722 #ifndef ALLOW_CHSW_EVT
16723 /* Channel switch support is only for AP/GO/ADHOC/MESH */
16724 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
16725 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
16726 WL_ERR(("No channel switch notify support for STA/GC\n"));
16729 #endif /* !ALLOW_CHSW_EVT */
16730 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16731 if (wl_chspec_chandef(chanspec, &chandef, wiphy))
16732 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16733 if (wl_chspec_chandef(chanspec, &chaninfo, wiphy))
16734 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16736 WL_ERR(("%s:chspec_chandef failed\n", __FUNCTION__));
16739 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16740 freq = chandef.chan ? chandef.chan->center_freq : chandef.center_freq1;
16741 cfg80211_ch_switch_notify(dev, &chandef);
16742 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16743 freq = chan_info.freq;
16744 cfg80211_ch_switch_notify(dev, chan_info.freq, chan_info.chan_type);
16745 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16747 WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq, chanspec));
16750 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
16754 wl_cfg80211_set_ulb_mode(struct net_device *dev, int mode)
16759 ret = wldev_iovar_getint(dev, "ulb_mode", &cur_mode);
16760 if (unlikely(ret)) {
16761 WL_ERR(("[ULB] ulb_mode get failed. ret:%d \n", ret));
16765 if (cur_mode == mode) {
16766 /* If request mode is same as that of the current mode, then
16767 * do nothing (Avoid unnecessary wl down and up).
16769 WL_INFORM(("[ULB] No change in ulb_mode. Do nothing.\n"));
16773 /* setting of ulb_mode requires wl to be down */
16774 ret = wldev_ioctl(dev, WLC_DOWN, NULL, 0, true);
16775 if (unlikely(ret)) {
16776 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
16780 if (mode >= MAX_SUPP_ULB_MODES) {
16781 WL_ERR(("[ULB] unsupported ulb_mode :[%d]\n", mode));
16785 ret = wldev_iovar_setint(dev, "ulb_mode", mode);
16786 if (unlikely(ret)) {
16787 WL_ERR(("[ULB] ulb_mode set failed. ret:%d \n", ret));
16791 ret = wldev_ioctl(dev, WLC_UP, NULL, 0, true);
16792 if (unlikely(ret)) {
16793 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
16797 WL_DBG(("[ULB] ulb_mode set to %d successfully \n", mode));
16803 wl_cfg80211_ulbbw_to_ulbchspec(u32 bw)
16805 if (bw == ULB_BW_DISABLED) {
16806 return WL_CHANSPEC_BW_20;
16807 } else if (bw == ULB_BW_10MHZ) {
16808 return WL_CHANSPEC_BW_10;
16809 } else if (bw == ULB_BW_5MHZ) {
16810 return WL_CHANSPEC_BW_5;
16811 } else if (bw == ULB_BW_2P5MHZ) {
16812 return WL_CHANSPEC_BW_2P5;
16814 WL_ERR(("[ULB] unsupported value for ulb_bw \n"));
16820 wl_cfg80211_ulb_get_min_bw_chspec(struct wireless_dev *wdev, s32 bssidx)
16822 struct bcm_cfg80211 *cfg = g_bcm_cfg;
16823 struct net_info *_netinfo;
16826 * Return the chspec value corresponding to the
16827 * BW setting for a particular interface
16830 /* if wdev is provided, use it */
16831 _netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
16832 } else if (bssidx >= 0) {
16833 /* if wdev is not provided, use it */
16834 _netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16836 WL_ERR(("[ULB] wdev/bssidx not provided\n"));
16837 return INVCHANSPEC;
16840 if (unlikely(!_netinfo)) {
16841 WL_ERR(("[ULB] net_info is null \n"));
16842 return INVCHANSPEC;
16845 if (_netinfo->ulb_bw) {
16846 WL_DBG(("[ULB] wdev_ptr:%p ulb_bw:0x%x \n", _netinfo->wdev, _netinfo->ulb_bw));
16847 return wl_cfg80211_ulbbw_to_ulbchspec(_netinfo->ulb_bw);
16849 return WL_CHANSPEC_BW_20;
16854 wl_cfg80211_get_ulb_bw(struct wireless_dev *wdev)
16856 struct bcm_cfg80211 *cfg = g_bcm_cfg;
16857 struct net_info *_netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
16860 * Return the ulb_bw setting for a
16861 * particular interface
16863 if (unlikely(!_netinfo)) {
16864 WL_ERR(("[ULB] net_info is null \n"));
16868 return _netinfo->ulb_bw;
16872 wl_cfg80211_set_ulb_bw(struct net_device *dev,
16873 u32 ulb_bw, char *ifname)
16875 struct bcm_cfg80211 *cfg = g_bcm_cfg;
16878 struct net_info *_netinfo = NULL, *iter, *next;
16880 enum nl80211_iftype iftype;
16885 WL_DBG(("[ULB] Enter. bw_type:%d \n", ulb_bw));
16887 ret = wldev_iovar_getint(dev, "ulb_mode", &mode);
16888 if (unlikely(ret)) {
16889 WL_ERR(("[ULB] ulb_mode not supported \n"));
16893 if (mode != ULB_MODE_STD_ALONE_MODE) {
16894 WL_ERR(("[ULB] ulb bw modification allowed only in stand-alone mode\n"));
16898 if (ulb_bw >= MAX_SUPP_ULB_BW) {
16899 WL_ERR(("[ULB] unsupported value (%d) for ulb_bw \n", ulb_bw));
16903 #ifdef WL_CFG80211_P2P_DEV_IF
16904 if (strcmp(ifname, "p2p-dev-wlan0") == 0) {
16905 iftype = NL80211_IFTYPE_P2P_DEVICE;
16906 /* Use wdev corresponding to the dedicated p2p discovery interface */
16907 if (likely(cfg->p2p_wdev)) {
16908 _netinfo = wl_get_netinfo_by_wdev(cfg, cfg->p2p_wdev);
16913 #endif /* WL_CFG80211_P2P_DEV_IF */
16915 for_each_ndev(cfg, iter, next) {
16917 if (strncmp(iter->ndev->name, ifname, strlen(ifname)) == 0) {
16918 _netinfo = wl_get_netinfo_by_netdev(cfg, iter->ndev);
16919 iftype = NL80211_IFTYPE_STATION;
16927 bssidx = _netinfo->bssidx;
16928 _netinfo->ulb_bw = ulb_bw;
16931 WL_DBG(("[ULB] Applying ulb_bw:%d for bssidx:%d \n", ulb_bw, bssidx));
16932 ret = wldev_iovar_setbuf_bsscfg(dev, "ulb_bw", (void *)&ulb_bw, 4,
16933 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx,
16934 &cfg->ioctl_buf_sync);
16935 if (unlikely(ret)) {
16936 WL_ERR(("[ULB] ulb_bw set failed. ret:%d \n", ret));
16942 #endif /* WL11ULB */
16945 wl_ap_channel_ind(struct bcm_cfg80211 *cfg,
16946 struct net_device *ndev,
16947 chanspec_t chanspec)
16949 u32 channel = LCHSPEC_CHANNEL(chanspec);
16951 WL_DBG(("(%s) AP channel:%d chspec:0x%x \n",
16952 ndev->name, channel, chanspec));
16953 if (cfg->ap_oper_channel && (cfg->ap_oper_channel != channel)) {
16955 * If cached channel is different from the channel indicated
16956 * by the event, notify user space about the channel switch.
16958 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
16959 wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
16960 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
16961 cfg->ap_oper_channel = channel;
16966 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16967 const wl_event_msg_t *e, void *data)
16969 struct net_device *ndev = NULL;
16970 chanspec_t chanspec;
16973 WL_DBG(("Enter\n"));
16974 if (unlikely(e->status)) {
16975 WL_ERR(("status:0x%x \n", e->status));
16983 if (likely(cfgdev)) {
16984 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16985 chanspec = *((chanspec_t *)data);
16986 channel = LCHSPEC_CHANNEL(chanspec);
16988 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
16989 /* For AP/GO role */
16990 wl_ap_channel_ind(cfg, ndev, chanspec);
16998 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16999 const wl_event_msg_t *e, void *data)
17003 struct net_device *ndev = NULL;
17004 struct wiphy *wiphy = NULL;
17006 WL_DBG(("Enter\n"));
17007 if (unlikely(e->status)) {
17008 WL_ERR(("status:0x%x \n", e->status));
17012 if (likely(cfgdev)) {
17013 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
17014 wiphy = bcmcfg_to_wiphy(cfg);
17015 error = wldev_iovar_getint(ndev, "chanspec", &chanspec);
17016 if (unlikely(error)) {
17017 WL_ERR(("Get chanspec error: %d \n", error));
17021 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
17022 /* For AP/GO role */
17023 wl_ap_channel_ind(cfg, ndev, chanspec);
17025 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
17026 wl_cfg80211_ch_switch_notify(ndev, chanspec, wiphy);
17027 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
17037 wl_cfg80211_nan_cmd_handler(struct net_device *ndev, char *cmd, int cmd_len)
17039 return wl_cfgnan_cmd_handler(ndev, g_bcm_cfg, cmd, cmd_len);
17041 #endif /* WL_NAN */
17043 void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg)
17045 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
17048 /* Clear the security settings on the primary Interface */
17049 err = wldev_iovar_setint(dev, "wsec", 0);
17050 if (unlikely(err)) {
17051 WL_ERR(("wsec clear failed \n"));
17053 err = wldev_iovar_setint(dev, "auth", 0);
17054 if (unlikely(err)) {
17055 WL_ERR(("auth clear failed \n"));
17057 err = wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
17058 if (unlikely(err)) {
17059 WL_ERR(("wpa_auth clear failed \n"));
17063 #ifdef WL_CFG80211_P2P_DEV_IF
17064 void wl_cfg80211_del_p2p_wdev(void)
17066 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17067 struct wireless_dev *wdev = NULL;
17069 WL_DBG(("Enter \n"));
17071 WL_ERR(("Invalid Ptr\n"));
17074 wdev = cfg->p2p_wdev;
17077 if (wdev && cfg->down_disc_if) {
17078 wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
17079 cfg->down_disc_if = FALSE;
17082 #endif /* WL_CFG80211_P2P_DEV_IF */
17084 #if defined(WL_SUPPORT_AUTO_CHANNEL)
17086 wl_cfg80211_set_spect(struct net_device *dev, int spect)
17088 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17093 if (!wl_get_drv_status_all(cfg, CONNECTED)) {
17094 err = wldev_ioctl(dev, WLC_DOWN, &down, sizeof(down), true);
17096 WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__, err));
17100 err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT, &spect, sizeof(spect), true);
17102 WL_ERR(("%s: error setting spect: code: %d\n", __func__, err));
17106 err = wldev_ioctl(dev, WLC_UP, &up, sizeof(up), true);
17108 WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__, err));
17116 wl_cfg80211_get_sta_channel(void)
17118 struct net_device *ndev = bcmcfg_to_prmry_ndev(g_bcm_cfg);
17121 if (wl_get_drv_status(g_bcm_cfg, CONNECTED, ndev)) {
17122 channel = g_bcm_cfg->channel;
17126 #endif /* WL_SUPPORT_AUTO_CHANNEL */
17127 #ifdef P2P_LISTEN_OFFLOADING
17129 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg)
17133 int p2plo_pause = 0;
17134 if (!cfg || !cfg->p2p) {
17135 WL_ERR(("Wl %p or cfg->p2p %p is null\n",
17136 cfg, cfg ? cfg->p2p : 0));
17140 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17141 ret = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg),
17142 "p2po_stop", (void*)&p2plo_pause, sizeof(p2plo_pause),
17143 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL);
17145 WL_ERR(("p2po_stop Failed :%d\n", ret));
17151 wl_cfg80211_p2plo_listen_start(struct net_device *dev, u8 *buf, int len)
17153 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17154 s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17155 wl_p2plo_listen_t p2plo_listen;
17162 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
17163 WL_ERR(("Sending Action Frames. Try it again.\n"));
17167 if (wl_get_drv_status_all(cfg, SCANNING)) {
17168 WL_ERR(("Scanning already\n"));
17172 if (wl_get_drv_status(cfg, SCAN_ABORTING, dev)) {
17173 WL_ERR(("Scanning being aborted\n"));
17177 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
17178 WL_ERR(("p2p listen offloading already running\n"));
17182 /* Just in case if it is not enabled */
17183 if ((ret = wl_cfgp2p_enable_discovery(cfg, dev, NULL, 0)) < 0) {
17184 WL_ERR(("cfgp2p_enable discovery failed"));
17188 bzero(&p2plo_listen, sizeof(wl_p2plo_listen_t));
17191 sscanf(buf, " %10d %10d %10d %10d", &channel, &period, &interval, &count);
17192 if ((channel == 0) || (period == 0) ||
17193 (interval == 0) || (count == 0)) {
17194 WL_ERR(("Wrong argument %d/%d/%d/%d \n",
17195 channel, period, interval, count));
17199 p2plo_listen.period = period;
17200 p2plo_listen.interval = interval;
17201 p2plo_listen.count = count;
17203 WL_ERR(("channel:%d period:%d, interval:%d count:%d\n",
17204 channel, period, interval, count));
17206 WL_ERR(("Argument len is wrong.\n"));
17211 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
17212 sizeof(channel), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17213 bssidx, &cfg->ioctl_buf_sync)) < 0) {
17214 WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
17218 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&p2plo_listen,
17219 sizeof(wl_p2plo_listen_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17220 bssidx, &cfg->ioctl_buf_sync)) < 0) {
17221 WL_ERR(("p2po_listen Failed :%d\n", ret));
17225 wl_set_p2p_status(cfg, DISC_IN_PROGRESS);
17226 cfg->last_roc_id = P2PO_COOKIE;
17231 wl_cfg80211_p2plo_listen_stop(struct net_device *dev)
17233 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17234 s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17237 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop", NULL,
17238 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17239 bssidx, &cfg->ioctl_buf_sync)) < 0) {
17240 WL_ERR(("p2po_stop Failed :%d\n", ret));
17247 #endif /* P2P_LISTEN_OFFLOADING */
17249 wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg)
17252 id = ++cfg->last_roc_id;
17253 #ifdef P2P_LISTEN_OFFLOADING
17254 if (id == P2PO_COOKIE) {
17255 id = ++cfg->last_roc_id;
17257 #endif /* P2P_LISTEN_OFFLOADING */
17259 id = ++cfg->last_roc_id;
17263 #if defined(SUPPORT_RANDOM_MAC_SCAN)
17265 wl_cfg80211_set_random_mac(struct net_device *dev, bool enable)
17267 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17270 if (cfg->random_mac_enabled == enable) {
17271 WL_ERR(("Random MAC already %s\n", enable ? "Enabled" : "Disabled"));
17276 ret = wl_cfg80211_random_mac_enable(dev);
17278 ret = wl_cfg80211_random_mac_disable(dev);
17282 cfg->random_mac_enabled = enable;
17289 wl_cfg80211_random_mac_enable(struct net_device *dev)
17291 u8 current_mac[ETH_ALEN] = {0, };
17292 s32 err = BCME_ERROR;
17293 uint8 buffer[20] = {0, };
17294 wl_scanmac_t *sm = NULL;
17296 wl_scanmac_enable_t *sm_enable = NULL;
17297 wl_scanmac_config_t *sm_config = NULL;
17298 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17300 if (wl_get_drv_status_all(cfg, CONNECTED) || wl_get_drv_status_all(cfg, CONNECTING) ||
17301 wl_get_drv_status_all(cfg, AP_CREATED) || wl_get_drv_status_all(cfg, AP_CREATING)) {
17302 WL_ERR(("Fail to Set random mac, current state is wrong\n"));
17306 /* Read current mac address */
17307 err = wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr",
17308 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17310 if (err != BCME_OK) {
17311 WL_ERR(("failed to get current dongle mac address\n"));
17315 memcpy(current_mac, cfg->ioctl_buf, ETH_ALEN);
17317 /* Enable scan mac */
17318 sm = (wl_scanmac_t *)buffer;
17319 sm_enable = (wl_scanmac_enable_t *)sm->data;
17320 sm->len = sizeof(*sm_enable);
17321 sm_enable->enable = 1;
17322 len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17323 sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
17325 err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17326 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17328 if (err != BCME_OK) {
17329 WL_ERR(("failed to enable scanmac, err=%d\n", err));
17333 /* Configure scanmac */
17334 memset(buffer, 0x0, sizeof(buffer));
17335 sm_config = (wl_scanmac_config_t *)sm->data;
17336 sm->len = sizeof(*sm_config);
17337 sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
17338 sm_config->scan_bitmap = WL_SCANMAC_SCAN_UNASSOC;
17340 /* Set current mac address */
17341 memcpy(&sm_config->mac.octet, current_mac, ETH_ALEN);
17342 sm_config->mac.octet[3] = 0x0;
17343 sm_config->mac.octet[4] = 0x0;
17344 sm_config->mac.octet[5] = 0x0;
17346 /* Set randomize mac address(last 3bytes) */
17347 memset(&sm_config->random_mask.octet, 0x0, ETH_ALEN);
17348 sm_config->random_mask.octet[3] = 0xff;
17349 sm_config->random_mask.octet[4] = 0xff;
17350 sm_config->random_mask.octet[5] = 0xff;
17352 len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17354 err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17355 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17357 if (err != BCME_OK) {
17358 WL_ERR(("failed scanmac configuration\n"));
17360 /* Disable scan mac for clean-up */
17361 wl_cfg80211_random_mac_disable(dev);
17365 WL_ERR(("random MAC enable done"));
17370 wl_cfg80211_random_mac_disable(struct net_device *dev)
17372 s32 err = BCME_ERROR;
17373 uint8 buffer[20] = {0, };
17374 wl_scanmac_t *sm = NULL;
17376 wl_scanmac_enable_t *sm_enable = NULL;
17377 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17379 sm = (wl_scanmac_t *)buffer;
17380 sm_enable = (wl_scanmac_enable_t *)sm->data;
17381 sm->len = sizeof(*sm_enable);
17382 sm_enable->enable = 0;
17383 len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17385 sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
17387 err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17388 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17390 if (err != BCME_OK) {
17391 WL_ERR(("failed to disable scanmac, err=%d\n", err));
17395 WL_ERR(("random MAC disable done\n"));
17398 #endif /* SUPPORT_RANDOM_MAC_SCAN */
17401 wl_cfg80211_iface_count(void)
17403 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17404 struct net_info *iter, *next;
17405 int iface_count = 0;
17407 for_each_ndev(cfg, iter, next) {
17412 return iface_count;
17415 #ifdef DHD_LOG_DUMP
17416 struct bcm_cfg80211*
17417 wl_get_bcm_cfg80211_ptr(void)
17421 #endif /* DHD_LOG_DUMP */
17423 #define CHECK_DONGLE_IDLE_TIME 50
17424 #define CHECK_DONGLE_IDLE_CNT 100
17426 wl_check_dongle_idle(struct wiphy *wiphy)
17429 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
17430 struct net_device *primary_ndev;
17432 struct channel_info ci;
17435 /* Use primary I/F for sending cmds down to firmware */
17436 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
17438 while (retry++ < CHECK_DONGLE_IDLE_CNT) {
17439 error = wldev_ioctl(primary_ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false);
17440 if (error != BCME_OK || ci.scan_channel != 0) {
17441 WL_ERR(("Firmware is busy(err:%d scan channel:%d). wait %dms\n",
17442 error, ci.scan_channel, CHECK_DONGLE_IDLE_TIME));
17446 wl_delay(CHECK_DONGLE_IDLE_TIME);
17448 if (retry >= CHECK_DONGLE_IDLE_CNT) {
17449 WL_ERR(("DONGLE is BUSY too long\n"));
17452 WL_DBG(("DONGLE is idle\n"));