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 err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), true);
8174 WL_ERR(("SET INFRA error %d\n", err));
8178 err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
8179 if (unlikely(err)) {
8180 WL_ERR(("WLC_UP error (%d)\n", err));
8186 /* Turn on the MPC */
8187 wldev_iovar_setint(dev, "mpc", 1);
8189 wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
8191 WL_DBG(("Stopping P2P GO \n"));
8192 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(cfg->pub),
8193 DHD_EVENT_TIMEOUT_MS*3);
8194 DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub));
8199 if (dev_role == NL80211_IFTYPE_AP) {
8200 /* clear the AP mode */
8201 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
8207 wl_cfg80211_change_beacon(
8208 struct wiphy *wiphy,
8209 struct net_device *dev,
8210 struct cfg80211_beacon_data *info)
8213 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8214 struct parsed_ies ies;
8219 WL_DBG(("Enter \n"));
8221 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
8222 dev_role = NL80211_IFTYPE_AP;
8224 #if defined(WL_ENABLE_P2P_IF)
8225 else if (dev == cfg->p2p_net) {
8226 /* Group Add request on p2p0 */
8227 dev = bcmcfg_to_prmry_ndev(cfg);
8228 dev_role = NL80211_IFTYPE_P2P_GO;
8230 #endif /* WL_ENABLE_P2P_IF */
8232 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
8233 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
8237 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
8238 dev_role = NL80211_IFTYPE_P2P_GO;
8241 if (!check_dev_role_integrity(cfg, dev_role)) {
8246 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
8247 WL_ERR(("P2P already down status!\n"));
8253 if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
8254 WL_ERR(("Parse IEs failed \n"));
8259 if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
8260 WL_ERR(("Set IEs failed \n"));
8264 if (dev_role == NL80211_IFTYPE_AP) {
8265 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
8266 WL_ERR(("Hostapd update sec failed \n"));
8270 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
8271 if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
8272 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
8273 WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc));
8275 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
8277 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
8286 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
8287 struct beacon_parameters *info)
8290 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8293 u32 dev_role = NL80211_IFTYPE_AP;
8294 struct parsed_ies ies;
8299 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8301 WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
8302 info->interval, info->dtim_period, info->head_len, info->tail_len));
8304 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
8305 dev_role = NL80211_IFTYPE_AP;
8307 #if defined(WL_ENABLE_P2P_IF)
8308 else if (dev == cfg->p2p_net) {
8309 /* Group Add request on p2p0 */
8310 dev = bcmcfg_to_prmry_ndev(cfg);
8311 dev_role = NL80211_IFTYPE_P2P_GO;
8313 #endif /* WL_ENABLE_P2P_IF */
8315 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
8316 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
8320 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
8321 dev_role = NL80211_IFTYPE_P2P_GO;
8322 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
8323 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
8326 if (!check_dev_role_integrity(cfg, dev_role)) {
8331 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
8332 WL_ERR(("P2P already down status!\n"));
8337 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
8339 if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
8340 info->head_len - ie_offset,
8341 DOT11_MNG_SSID_ID)) != NULL) {
8342 if (dev_role == NL80211_IFTYPE_AP) {
8343 /* Store the hostapd SSID */
8344 memset(&cfg->hostapd_ssid.SSID[0], 0x00, 32);
8345 memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data, ssid_ie->len);
8346 cfg->hostapd_ssid.SSID_len = ssid_ie->len;
8349 memset(&cfg->p2p->ssid.SSID[0], 0x00, 32);
8350 memcpy(cfg->p2p->ssid.SSID, ssid_ie->data, ssid_ie->len);
8351 cfg->p2p->ssid.SSID_len = ssid_ie->len;
8355 if (wl_cfg80211_parse_ies((u8 *)info->tail,
8356 info->tail_len, &ies) < 0) {
8357 WL_ERR(("Beacon get IEs failed \n"));
8362 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
8363 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
8364 info->tail_len)) < 0) {
8365 WL_ERR(("Beacon set IEs failed \n"));
8368 WL_DBG(("Applied Vndr IEs for Beacon \n"));
8371 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
8372 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
8373 VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies,
8374 info->proberesp_ies_len)) < 0) {
8375 WL_ERR(("ProbeRsp set IEs failed \n"));
8378 WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
8382 is_bss_up = wl_cfgp2p_bss_isup(dev, bssidx);
8384 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
8385 privacy = info->privacy;
8390 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx, privacy) < 0))
8392 WL_ERR(("Beacon set security failed \n"));
8397 /* Set BI and DTIM period */
8398 if (info->interval) {
8399 if ((err = wldev_ioctl(dev, WLC_SET_BCNPRD,
8400 &info->interval, sizeof(s32), true)) < 0) {
8401 WL_ERR(("Beacon Interval Set Error, %d\n", err));
8405 if (info->dtim_period) {
8406 if ((err = wldev_ioctl(dev, WLC_SET_DTIMPRD,
8407 &info->dtim_period, sizeof(s32), true)) < 0) {
8408 WL_ERR(("DTIM Interval Set Error, %d\n", err));
8413 /* If bss is already up, skip bring up */
8415 (err = wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx)) < 0)
8417 WL_ERR(("Beacon bring up AP/GO failed \n"));
8421 /* Set GC/STA SCB expiry timings. */
8422 if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
8423 WL_ERR(("scb setting failed \n"));
8427 if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
8428 /* Soft AP already running. Update changed params */
8429 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
8430 WL_ERR(("Hostapd update sec failed \n"));
8436 /* Enable Probe Req filter */
8437 if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
8438 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
8439 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
8441 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
8444 WL_DBG(("** ADD/SET beacon done **\n"));
8448 WL_ERR(("ADD/SET beacon failed\n"));
8449 wldev_iovar_setint(dev, "mpc", 1);
8450 if (dev_role == NL80211_IFTYPE_AP) {
8451 /* clear the AP mode */
8452 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
8460 #ifdef WL_SCHED_SCAN
8462 #define PNO_REPEAT 4
8463 #define PNO_FREQ_EXPO_MAX 2
8465 is_ssid_in_list(struct cfg80211_ssid *ssid, struct cfg80211_ssid *ssid_list, int count)
8469 if (!ssid || !ssid_list)
8472 for (i = 0; i < count; i++) {
8473 if (ssid->ssid_len == ssid_list[i].ssid_len) {
8474 if (strncmp(ssid->ssid, ssid_list[i].ssid, ssid->ssid_len) == 0)
8482 wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
8483 struct net_device *dev,
8484 struct cfg80211_sched_scan_request *request)
8486 ushort pno_time = PNO_TIME;
8487 int pno_repeat = PNO_REPEAT;
8488 int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
8489 wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
8490 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8491 struct cfg80211_ssid *ssid = NULL;
8492 struct cfg80211_ssid *hidden_ssid_list = NULL;
8498 WL_ERR(("Sched scan request was NULL\n"));
8502 WL_DBG(("Enter \n"));
8503 WL_PNO((">>> SCHED SCAN START\n"));
8504 WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
8505 request->n_match_sets, request->n_ssids));
8506 WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
8507 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
8510 if (!request->n_ssids || !request->n_match_sets) {
8511 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
8515 memset(&ssids_local, 0, sizeof(ssids_local));
8517 if (request->n_ssids > 0) {
8518 hidden_ssid_list = request->ssids;
8521 for (i = 0; i < request->n_match_sets && ssid_cnt < MAX_PFN_LIST_COUNT; i++) {
8522 ssid = &request->match_sets[i].ssid;
8523 /* No need to include null ssid */
8524 if (ssid->ssid_len) {
8525 memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid, ssid->ssid_len);
8526 ssids_local[ssid_cnt].SSID_len = ssid->ssid_len;
8527 if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
8528 ssids_local[ssid_cnt].hidden = TRUE;
8529 WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
8531 ssids_local[ssid_cnt].hidden = FALSE;
8532 WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid->ssid));
8539 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, ssid_cnt,
8540 pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
8541 WL_ERR(("PNO setup failed!! ret=%d \n", ret));
8544 cfg->sched_scan_req = request;
8553 wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev)
8555 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8557 WL_DBG(("Enter \n"));
8558 WL_PNO((">>> SCHED SCAN STOP\n"));
8560 if (dhd_dev_pno_stop_for_ssid(dev) < 0)
8561 WL_ERR(("PNO Stop for SSID failed"));
8563 if (cfg->scan_request && cfg->sched_scan_running) {
8564 WL_PNO((">>> Sched scan running. Aborting it..\n"));
8565 wl_notify_escan_complete(cfg, dev, true, true);
8568 cfg->sched_scan_req = NULL;
8569 cfg->sched_scan_running = FALSE;
8573 #endif /* WL_SCHED_SCAN */
8575 #ifdef WL_SUPPORT_ACS
8577 * Currently the dump_obss IOVAR is returning string as output so we need to
8578 * parse the output buffer in an unoptimized way. Going forward if we get the
8579 * IOVAR output in binary format this method can be optimized
8581 static int wl_parse_dump_obss(char *buf, struct wl_dump_survey *survey)
8585 char delim[] = " \n";
8587 token = strsep(&buf, delim);
8588 while (token != NULL) {
8589 if (!strcmp(token, "OBSS")) {
8590 for (i = 0; i < OBSS_TOKEN_IDX; i++)
8591 token = strsep(&buf, delim);
8592 survey->obss = simple_strtoul(token, NULL, 10);
8595 if (!strcmp(token, "IBSS")) {
8596 for (i = 0; i < IBSS_TOKEN_IDX; i++)
8597 token = strsep(&buf, delim);
8598 survey->ibss = simple_strtoul(token, NULL, 10);
8601 if (!strcmp(token, "TXDur")) {
8602 for (i = 0; i < TX_TOKEN_IDX; i++)
8603 token = strsep(&buf, delim);
8604 survey->tx = simple_strtoul(token, NULL, 10);
8607 if (!strcmp(token, "Category")) {
8608 for (i = 0; i < CTG_TOKEN_IDX; i++)
8609 token = strsep(&buf, delim);
8610 survey->no_ctg = simple_strtoul(token, NULL, 10);
8613 if (!strcmp(token, "Packet")) {
8614 for (i = 0; i < PKT_TOKEN_IDX; i++)
8615 token = strsep(&buf, delim);
8616 survey->no_pckt = simple_strtoul(token, NULL, 10);
8619 if (!strcmp(token, "Opp(time):")) {
8620 for (i = 0; i < IDLE_TOKEN_IDX; i++)
8621 token = strsep(&buf, delim);
8622 survey->idle = simple_strtoul(token, NULL, 10);
8625 token = strsep(&buf, delim);
8631 static int wl_dump_obss(struct net_device *ndev, cca_msrmnt_query req,
8632 struct wl_dump_survey *survey)
8634 cca_stats_n_flags *results;
8638 buf = kzalloc(sizeof(char) * WLC_IOCTL_MAXLEN, GFP_KERNEL);
8639 if (unlikely(!buf)) {
8640 WL_ERR(("%s: buf alloc failed\n", __func__));
8644 retry = IOCTL_RETRY_COUNT;
8646 err = wldev_iovar_getbuf(ndev, "dump_obss", &req, sizeof(req),
8647 buf, WLC_IOCTL_MAXLEN, NULL);
8651 WL_DBG(("attempt = %d, err = %d, \n",
8652 (IOCTL_RETRY_COUNT - retry), err));
8656 WL_ERR(("failure, dump_obss IOVAR failed\n"));
8661 results = (cca_stats_n_flags *)(buf);
8662 wl_parse_dump_obss(results->buf, survey);
8671 static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
8672 int idx, struct survey_info *info)
8674 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8675 struct wl_dump_survey *survey;
8676 struct ieee80211_supported_band *band;
8677 struct ieee80211_channel*chan;
8678 cca_msrmnt_query req;
8679 int val, err, noise, retry;
8681 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8682 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
8685 band = wiphy->bands[IEEE80211_BAND_2GHZ];
8686 if (band && idx >= band->n_channels) {
8687 idx -= band->n_channels;
8691 if (!band || idx >= band->n_channels) {
8692 /* Move to 5G band */
8693 band = wiphy->bands[IEEE80211_BAND_5GHZ];
8694 if (idx >= band->n_channels) {
8699 chan = &band->channels[idx];
8700 /* Setting current channel to the requested channel */
8701 if ((err = wl_cfg80211_set_channel(wiphy, ndev, chan,
8702 NL80211_CHAN_HT20) < 0)) {
8703 WL_ERR(("Set channel failed \n"));
8709 err = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
8710 sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
8711 &cfg->ioctl_buf_sync);
8713 WL_ERR(("set 'mpc' failed, error = %d\n", err));
8716 /* Set interface up, explicitly. */
8718 err = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
8720 WL_ERR(("set interface up failed, error = %d\n", err));
8724 /* Get noise value */
8725 retry = IOCTL_RETRY_COUNT;
8727 err = wldev_ioctl(ndev, WLC_GET_PHY_NOISE, &noise,
8728 sizeof(noise), false);
8732 WL_DBG(("attempt = %d, err = %d, \n",
8733 (IOCTL_RETRY_COUNT - retry), err));
8737 WL_ERR(("Get Phy Noise failed, error = %d\n", err));
8738 noise = CHAN_NOISE_DUMMY;
8741 survey = (struct wl_dump_survey *) kzalloc(sizeof(struct wl_dump_survey),
8743 if (unlikely(!survey)) {
8744 WL_ERR(("%s: alloc failed\n", __func__));
8748 /* Start Measurement for obss stats on current channel */
8749 req.msrmnt_query = 0;
8750 req.time_req = ACS_MSRMNT_DELAY;
8751 if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
8756 * Wait for the meaurement to complete, adding a buffer value of 10 to take
8757 * into consideration any delay in IOVAR completion
8759 msleep(ACS_MSRMNT_DELAY + 10);
8761 /* Issue IOVAR to collect measurement results */
8762 req.msrmnt_query = 1;
8763 if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
8767 info->channel = chan;
8768 info->noise = noise;
8769 info->channel_time = ACS_MSRMNT_DELAY;
8770 info->channel_time_busy = ACS_MSRMNT_DELAY - survey->idle;
8771 info->channel_time_rx = survey->obss + survey->ibss + survey->no_ctg +
8773 info->channel_time_tx = survey->tx;
8774 info->filled = SURVEY_INFO_NOISE_DBM |SURVEY_INFO_CHANNEL_TIME |
8775 SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_RX |
8776 SURVEY_INFO_CHANNEL_TIME_TX;
8784 #endif /* WL_SUPPORT_ACS */
8786 static struct cfg80211_ops wl_cfg80211_ops = {
8787 .add_virtual_intf = wl_cfg80211_add_virtual_iface,
8788 .del_virtual_intf = wl_cfg80211_del_virtual_iface,
8789 .change_virtual_intf = wl_cfg80211_change_virtual_iface,
8790 #if defined(WL_CFG80211_P2P_DEV_IF)
8791 .start_p2p_device = wl_cfgp2p_start_p2p_device,
8792 .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
8793 #endif /* WL_CFG80211_P2P_DEV_IF */
8794 .scan = wl_cfg80211_scan,
8795 .set_wiphy_params = wl_cfg80211_set_wiphy_params,
8796 .join_ibss = wl_cfg80211_join_ibss,
8797 .leave_ibss = wl_cfg80211_leave_ibss,
8798 .get_station = wl_cfg80211_get_station,
8799 .set_tx_power = wl_cfg80211_set_tx_power,
8800 .get_tx_power = wl_cfg80211_get_tx_power,
8801 .add_key = wl_cfg80211_add_key,
8802 .del_key = wl_cfg80211_del_key,
8803 .get_key = wl_cfg80211_get_key,
8804 .set_default_key = wl_cfg80211_config_default_key,
8805 .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
8806 .set_power_mgmt = wl_cfg80211_set_power_mgmt,
8807 .connect = wl_cfg80211_connect,
8808 .disconnect = wl_cfg80211_disconnect,
8809 .suspend = wl_cfg80211_suspend,
8810 .resume = wl_cfg80211_resume,
8811 .set_pmksa = wl_cfg80211_set_pmksa,
8812 .del_pmksa = wl_cfg80211_del_pmksa,
8813 .flush_pmksa = wl_cfg80211_flush_pmksa,
8814 .remain_on_channel = wl_cfg80211_remain_on_channel,
8815 .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
8816 .mgmt_tx = wl_cfg80211_mgmt_tx,
8817 .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
8818 .change_bss = wl_cfg80211_change_bss,
8819 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
8820 .set_channel = wl_cfg80211_set_channel,
8822 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
8823 .set_beacon = wl_cfg80211_add_set_beacon,
8824 .add_beacon = wl_cfg80211_add_set_beacon,
8826 .change_beacon = wl_cfg80211_change_beacon,
8827 .start_ap = wl_cfg80211_start_ap,
8828 .stop_ap = wl_cfg80211_stop_ap,
8830 #ifdef WL_SCHED_SCAN
8831 .sched_scan_start = wl_cfg80211_sched_scan_start,
8832 .sched_scan_stop = wl_cfg80211_sched_scan_stop,
8833 #endif /* WL_SCHED_SCAN */
8834 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
8836 .del_station = wl_cfg80211_del_station,
8837 .change_station = wl_cfg80211_change_station,
8838 .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
8839 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
8840 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
8841 .tdls_mgmt = wl_cfg80211_tdls_mgmt,
8842 .tdls_oper = wl_cfg80211_tdls_oper,
8844 #ifdef WL_SUPPORT_ACS
8845 .dump_survey = wl_cfg80211_dump_survey,
8846 #endif /* WL_SUPPORT_ACS */
8847 #ifdef WL_CFG80211_ACL
8848 .set_mac_acl = wl_cfg80211_set_mac_acl,
8849 #endif /* WL_CFG80211_ACL */
8852 s32 wl_mode_to_nl80211_iftype(s32 mode)
8858 return NL80211_IFTYPE_STATION;
8860 return NL80211_IFTYPE_ADHOC;
8862 return NL80211_IFTYPE_AP;
8864 return NL80211_IFTYPE_UNSPECIFIED;
8870 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
8871 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8872 #define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
8874 #define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
8875 #endif /* kernel version < 3.9.0 */
8878 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
8879 WL_CFG80211_REG_NOTIFIER()
8881 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
8885 if (!request || !cfg) {
8886 WL_ERR(("Invalid arg\n"));
8887 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8891 #endif /* kernel version < 3.9.0 */
8894 WL_DBG(("ccode: %c%c Initiator: %d\n",
8895 request->alpha2[0], request->alpha2[1], request->initiator));
8897 /* We support only REGDOM_SET_BY_USER as of now */
8898 if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
8899 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
8900 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
8901 request->initiator));
8902 /* in case of no supported country by regdb
8903 lets driver setup platform default Locale
8907 WL_ERR(("Set country code %c%c from %s\n",
8908 request->alpha2[0], request->alpha2[1],
8909 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
8911 if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2,
8912 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false),
8914 WL_ERR(("set country Failed :%d\n", ret));
8917 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
8921 #endif /* kernel version < 3.9.0 */
8923 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
8926 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
8927 static const struct wiphy_wowlan_support brcm_wowlan_support = {
8928 .flags = WIPHY_WOWLAN_ANY,
8929 .n_patterns = WL_WOWLAN_MAX_PATTERNS,
8930 .pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN,
8931 .pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN,
8932 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
8933 .max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN,
8934 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
8936 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
8938 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
8939 static struct cfg80211_wowlan brcm_wowlan_config = {
8941 .gtk_rekey_failure = true,
8942 .eap_identity_req = true,
8943 .four_way_handshake = true,
8945 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
8947 #endif /* CONFIG_PM */
8949 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, void *context)
8952 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
8953 dhd_pub_t *dhd = (dhd_pub_t *)context;
8957 WL_ERR(("DHD is NULL!!"));
8964 wiphy_new(&wl_cfg80211_ops, sizeof(struct bcm_cfg80211));
8965 if (unlikely(!wdev->wiphy)) {
8966 WL_ERR(("Couldn not allocate wiphy device\n"));
8970 set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
8971 wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
8972 /* Report how many SSIDs Driver can support per Scan request */
8973 wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
8974 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
8975 #ifdef WL_SCHED_SCAN
8976 wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
8977 wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
8978 wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
8979 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
8980 #endif /* WL_SCHED_SCAN */
8981 wdev->wiphy->interface_modes =
8982 BIT(NL80211_IFTYPE_STATION)
8983 | BIT(NL80211_IFTYPE_ADHOC)
8984 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
8985 | BIT(NL80211_IFTYPE_MONITOR)
8986 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
8987 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
8988 | BIT(NL80211_IFTYPE_P2P_CLIENT)
8989 | BIT(NL80211_IFTYPE_P2P_GO)
8990 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
8991 #if defined(WL_CFG80211_P2P_DEV_IF)
8992 | BIT(NL80211_IFTYPE_P2P_DEVICE)
8993 #endif /* WL_CFG80211_P2P_DEV_IF */
8994 | BIT(NL80211_IFTYPE_AP);
8996 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
8997 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
8998 WL_DBG(("Setting interface combinations for common mode\n"));
8999 wdev->wiphy->iface_combinations = common_iface_combinations;
9000 wdev->wiphy->n_iface_combinations =
9001 ARRAY_SIZE(common_iface_combinations);
9002 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
9004 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
9006 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
9007 wdev->wiphy->cipher_suites = __wl_cipher_suites;
9008 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
9009 wdev->wiphy->max_remain_on_channel_duration = 5000;
9010 wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
9011 #ifndef WL_POWERSAVE_DISABLED
9012 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
9014 wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
9015 #endif /* !WL_POWERSAVE_DISABLED */
9016 wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
9017 WIPHY_FLAG_4ADDR_AP |
9018 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
9019 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
9021 WIPHY_FLAG_4ADDR_STATION;
9022 #if ((defined(ROAM_ENABLE) || defined(BCMFW_ROAM_ENABLE)) && (LINUX_VERSION_CODE >= \
9023 KERNEL_VERSION(3, 2, 0)))
9025 * If FW ROAM flag is advertised, upper layer wouldn't provide
9026 * the bssid & freq in the connect command. This will result a
9027 * delay in initial connection time due to firmware doing a full
9028 * channel scan to figure out the channel & bssid. However kernel
9029 * ver >= 3.15, provides bssid_hint & freq_hint and hence kernel
9030 * ver >= 3.15 won't have any issue. So if this flags need to be
9031 * advertised for kernel < 3.15, suggest to use RCC along with it
9032 * to avoid the initial connection delay.
9034 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
9036 #ifdef UNSET_FW_ROAM_WIPHY_FLAG
9037 wdev->wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_FW_ROAM;
9038 #endif /* UNSET_FW_ROAM_WIPHY_FLAG */
9039 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
9040 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
9041 WIPHY_FLAG_OFFCHAN_TX;
9043 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
9045 /* From 3.4 kernel ownards AP_SME flag can be advertised
9046 * to remove the patch from supplicant
9048 wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
9050 #ifdef WL_CFG80211_ACL
9051 /* Configure ACL capabilities. */
9052 wdev->wiphy->max_acl_mac_addrs = MAX_NUM_MAC_FILT;
9055 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9056 /* Supplicant distinguish between the SoftAP mode and other
9057 * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
9058 * response frame from Supplicant MR1 and Kernel 3.4.0 or
9059 * later version. To add Vendor specific IE into the
9060 * probe response frame in case of SoftAP mode,
9061 * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
9063 if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) {
9064 wdev->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
9065 wdev->wiphy->probe_resp_offload = 0;
9068 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
9070 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
9071 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
9074 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
9076 * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
9077 * disconnection of connected network before suspend. So a dummy wowlan
9078 * filter is configured for kernels linux-3.8 and above.
9081 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9082 wdev->wiphy->wowlan = &brcm_wowlan_support;
9083 /* If this is not provided cfg stack will get disconnect
9086 //wdev->wiphy->wowlan_config = &brcm_wowlan_config;
9088 wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
9089 wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
9090 wdev->wiphy->wowlan.pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN;
9091 wdev->wiphy->wowlan.pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN;
9092 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9093 wdev->wiphy->wowlan.max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN;
9094 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
9095 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
9096 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
9098 WL_DBG(("Registering custom regulatory)\n"));
9099 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
9100 wdev->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
9102 wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
9104 wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
9105 #if defined(WL_VENDOR_EXT_SUPPORT)
9106 WL_ERR(("Registering Vendor80211\n"));
9107 err = wl_cfgvendor_attach(wdev->wiphy);
9108 if (unlikely(err < 0)) {
9109 WL_ERR(("Couldn not attach vendor commands (%d)\n", err));
9111 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
9112 /* Now we can register wiphy with cfg80211 module */
9113 err = wiphy_register(wdev->wiphy);
9114 if (unlikely(err < 0)) {
9115 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
9116 wiphy_free(wdev->wiphy);
9119 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
9120 KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
9121 wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
9127 static void wl_free_wdev(struct bcm_cfg80211 *cfg)
9129 struct wireless_dev *wdev = cfg->wdev;
9130 struct wiphy *wiphy = NULL;
9132 WL_ERR(("wdev is invalid\n"));
9136 wiphy = wdev->wiphy;
9138 #if defined(WL_VENDOR_EXT_SUPPORT)
9139 wl_cfgvendor_detach(wdev->wiphy);
9140 #endif /* if defined(WL_VENDOR_EXT_SUPPORT) */
9141 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
9142 /* Reset wowlan & wowlan_config before Unregister to avoid Kernel Panic */
9143 WL_DBG(("wl_free_wdev Clearing wowlan Config \n"));
9144 wdev->wiphy->wowlan = NULL;
9145 wdev->wiphy->wowlan_config = NULL;
9146 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
9147 wiphy_unregister(wdev->wiphy);
9148 wdev->wiphy->dev.parent = NULL;
9152 wl_delete_all_netinfo(cfg);
9156 /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
9157 * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
9161 static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
9163 struct wl_scan_results *bss_list;
9164 struct wl_bss_info *bi = NULL; /* must be initialized */
9167 #if defined(RSSIAVG)
9168 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
9171 #if defined(BSSCACHE)
9172 wl_bss_cache_t *node;
9175 bss_list = cfg->bss_list;
9177 /* Free cache in p2p scanning*/
9178 if (p2p_is_on(cfg) && p2p_scan(cfg)) {
9179 #if defined(RSSIAVG)
9180 wl_free_rssi_cache(&g_rssi_cache_ctrl);
9182 #if defined(BSSCACHE)
9183 wl_free_bss_cache(&g_bss_cache_ctrl);
9187 /* Delete disconnected cache */
9188 #if defined(BSSCACHE)
9189 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9190 #if defined(RSSIAVG)
9191 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9193 if (cfg->p2p_disconnected == 0)
9194 memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
9198 #if defined(RSSIAVG)
9199 wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
9201 wl_update_connected_rssi_cache(ndev, &g_rssi_cache_ctrl, &rssi);
9203 #if defined(BSSCACHE)
9204 wl_update_bss_cache(&g_bss_cache_ctrl,
9205 #if defined(RSSIAVG)
9211 /* delete dirty cache */
9212 #if defined(RSSIAVG)
9213 wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
9214 wl_reset_rssi_cache(&g_rssi_cache_ctrl);
9216 #if defined(BSSCACHE)
9217 wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
9218 wl_reset_bss_cache(&g_bss_cache_ctrl);
9221 #if defined(BSSCACHE)
9222 if (cfg->p2p_disconnected > 0) {
9223 // terence 20130703: Fix for wrong group_capab (timing issue)
9224 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9225 #if defined(RSSIAVG)
9226 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
9229 WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
9230 node = g_bss_cache_ctrl.m_cache_head;
9231 for (i=0; node && i<WL_AP_MAX; i++) {
9232 bi = node->results.bss_info;
9233 err = wl_inform_single_bss(cfg, bi, false);
9237 WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
9238 bi = next_bss(bss_list, bi);
9239 for_each_bss(bss_list, bi, i) {
9240 if (cfg->p2p_disconnected > 0 && !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN))
9242 err = wl_inform_single_bss(cfg, bi, false);
9246 if (cfg->p2p_disconnected > 0) {
9247 // terence 20130703: Fix for wrong group_capab (timing issue)
9248 cfg->p2p_disconnected++;
9249 if (cfg->p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1) {
9250 cfg->p2p_disconnected = 0;
9251 memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
9258 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam)
9260 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9261 struct ieee80211_mgmt *mgmt;
9262 struct ieee80211_channel *channel;
9263 struct ieee80211_supported_band *band;
9264 struct wl_cfg80211_bss_info *notif_bss_info;
9265 struct wl_scan_req *sr = wl_to_sr(cfg);
9266 struct beacon_proberesp *beacon_proberesp;
9267 struct cfg80211_bss *cbss = NULL;
9274 if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
9275 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
9278 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
9279 notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
9280 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
9281 if (unlikely(!notif_bss_info)) {
9282 WL_ERR(("notif_bss_info alloc failed\n"));
9285 mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
9286 notif_bss_info->channel =
9287 wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
9289 if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
9290 band = wiphy->bands[IEEE80211_BAND_2GHZ];
9292 band = wiphy->bands[IEEE80211_BAND_5GHZ];
9294 WL_ERR(("No valid band\n"));
9295 kfree(notif_bss_info);
9298 notif_bss_info->rssi = dtoh16(bi->RSSI);
9299 #if defined(RSSIAVG)
9300 notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
9301 if (notif_bss_info->rssi == RSSI_MINVAL)
9302 notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
9304 #if defined(RSSIOFFSET)
9305 notif_bss_info->rssi = wl_update_rssi_offset(bcmcfg_to_prmry_ndev(cfg), notif_bss_info->rssi);
9307 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
9308 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
9309 notif_bss_info->rssi = MIN(notif_bss_info->rssi, RSSI_MAXVAL);
9311 memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
9312 mgmt_type = cfg->active_scan ?
9313 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
9314 if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
9315 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
9317 beacon_proberesp = cfg->active_scan ?
9318 (struct beacon_proberesp *)&mgmt->u.probe_resp :
9319 (struct beacon_proberesp *)&mgmt->u.beacon;
9320 beacon_proberesp->timestamp = 0;
9321 beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
9322 beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
9324 wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length, roam);
9325 wl_mrg_ie(cfg, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
9326 wl_cp_ie(cfg, beacon_proberesp->variable, WL_BSS_INFO_MAX -
9327 offsetof(struct wl_cfg80211_bss_info, frame_buf));
9328 notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
9329 u.beacon.variable) + wl_get_ielen(cfg);
9330 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9331 freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
9334 freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
9337 WL_ERR(("Invalid channel, fail to change channel to freq\n"));
9338 kfree(notif_bss_info);
9341 channel = ieee80211_get_channel(wiphy, freq);
9342 WL_SCAN(("BSSID %pM, channel %2d, rssi %3d, capa 0x04%x, mgmt_type %d, "
9343 "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel,
9344 notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
9345 notif_bss_info->frame_len, bi->SSID));
9346 if (unlikely(!channel)) {
9347 WL_ERR(("ieee80211_get_channel error, freq=%d, channel=%d\n",
9348 freq, notif_bss_info->channel));
9349 kfree(notif_bss_info);
9353 signal = notif_bss_info->rssi * 100;
9354 if (!mgmt->u.probe_resp.timestamp) {
9355 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
9357 get_monotonic_boottime(&ts);
9358 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
9359 + ts.tv_nsec / 1000;
9362 do_gettimeofday(&tv);
9363 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
9369 cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
9370 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
9371 if (unlikely(!cbss)) {
9372 WL_ERR(("cfg80211_inform_bss_frame error\n"));
9373 kfree(notif_bss_info);
9378 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
9379 cfg80211_put_bss(wiphy, cbss);
9381 cfg80211_put_bss(cbss);
9382 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
9383 kfree(notif_bss_info);
9387 static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, struct net_device *ndev)
9389 u32 event = ntoh32(e->event_type);
9390 u32 status = ntoh32(e->status);
9391 u16 flags = ntoh16(e->flags);
9393 WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
9394 if (event == WLC_E_SET_SSID) {
9395 if (status == WLC_E_STATUS_SUCCESS) {
9396 if (!wl_is_ibssmode(cfg, ndev))
9399 } else if (event == WLC_E_LINK) {
9400 if (flags & WLC_EVENT_MSG_LINK)
9404 WL_DBG(("wl_is_linkup false\n"));
9408 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9410 u32 event = ntoh32(e->event_type);
9411 u16 flags = ntoh16(e->flags);
9413 if (event == WLC_E_DEAUTH_IND ||
9414 event == WLC_E_DISASSOC_IND ||
9415 event == WLC_E_DISASSOC ||
9416 event == WLC_E_DEAUTH) {
9417 #if (WL_DBG_LEVEL > 0)
9418 WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
9419 #endif /* (WL_DBG_LEVEL > 0) */
9421 } else if (event == WLC_E_LINK) {
9422 if (!(flags & WLC_EVENT_MSG_LINK)) {
9423 #if (WL_DBG_LEVEL > 0)
9424 WL_ERR(("Link down Reason : WLC_E_%s\n", wl_dbg_estr[event]));
9425 #endif /* (WL_DBG_LEVEL > 0) */
9433 static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9435 u32 event = ntoh32(e->event_type);
9436 u32 status = ntoh32(e->status);
9438 if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
9440 if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
9446 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
9447 * to AP/P2P GO via events. If this change is backported to kernel for which
9448 * this driver is being built, then define WL_CFG80211_STA_EVENT. You
9449 * should use this new/del sta event mechanism for BRCM supplicant >= 22.
9452 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9453 const wl_event_msg_t *e, void *data)
9456 u32 event = ntoh32(e->event_type);
9457 u32 reason = ntoh32(e->reason);
9458 u32 len = ntoh32(e->datalen);
9459 u32 status = ntoh32(e->status);
9461 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
9462 bool isfree = false;
9464 u8 bsscfgidx = e->bsscfgidx;
9470 struct ieee80211_supported_band *band;
9471 struct ether_addr da;
9472 struct ether_addr bssid;
9473 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9476 struct station_info sinfo;
9479 WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
9480 /* if link down, bsscfg is disabled. */
9481 if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
9482 wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) {
9483 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
9484 WL_INFORM(("AP mode link down !! \n"));
9485 complete(&cfg->iface_disable);
9489 if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
9490 (reason == WLC_E_REASON_INITIAL_ASSOC) &&
9491 (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) {
9492 if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
9493 /* AP/GO brought up successfull in firmware */
9494 WL_ERR(("** AP/GO Link up event **\n"));
9495 wl_set_drv_status(cfg, AP_CREATED, ndev);
9496 wake_up_interruptible(&cfg->netif_change_event);
9501 if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
9502 WL_ERR(("event %s(%d) status %d reason %d\n",
9503 bcmevent_get_name(event), event, ntoh32(e->status), reason));
9506 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
9507 WL_DBG(("Enter \n"));
9508 if (!len && (event == WLC_E_DEAUTH)) {
9509 len = 2; /* reason code field */
9513 body = kzalloc(len, GFP_KERNEL);
9516 WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
9520 memset(&bssid, 0, ETHER_ADDR_LEN);
9521 WL_DBG(("Enter event %d ndev %p\n", event, ndev));
9522 if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
9527 memcpy(body, data, len);
9529 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
9530 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
9531 memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
9532 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
9534 case WLC_E_ASSOC_IND:
9537 case WLC_E_REASSOC_IND:
9538 fc = FC_REASSOC_REQ;
9540 case WLC_E_DISASSOC_IND:
9543 case WLC_E_DEAUTH_IND:
9553 if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false))) {
9558 channel = dtoh32(ci.hw_channel);
9559 if (channel <= CH_MAX_2G_CHANNEL)
9560 band = wiphy->bands[IEEE80211_BAND_2GHZ];
9562 band = wiphy->bands[IEEE80211_BAND_5GHZ];
9564 WL_ERR(("No valid band\n"));
9569 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9570 freq = ieee80211_channel_to_frequency(channel);
9573 freq = ieee80211_channel_to_frequency(channel, band->band);
9576 err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
9577 &mgmt_frame, &len, body);
9582 if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
9583 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) && (LINUX_VERSION_CODE < \
9584 KERNEL_VERSION(3, 18, 0)))
9585 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9587 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
9588 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len);
9590 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9592 } else if (event == WLC_E_DISASSOC_IND) {
9593 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9594 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9596 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9598 } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
9599 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9600 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
9602 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
9611 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
9613 if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
9614 reason == DOT11_SC_SUCCESS) {
9615 /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
9616 * STATION_INFO_ASSOC_REQ_IES flag
9618 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
9619 sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
9620 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
9622 WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
9625 sinfo.assoc_req_ies = data;
9626 sinfo.assoc_req_ies_len = len;
9627 printf("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9628 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
9629 } else if (event == WLC_E_DISASSOC_IND) {
9630 printf("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9631 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
9632 } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
9633 printf("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
9634 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
9640 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9641 #define MAX_ASSOC_REJECT_ERR_STATUS 5
9642 int wl_get_connect_failed_status(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
9644 u32 status = ntoh32(e->status);
9646 cfg->assoc_reject_status = 0;
9648 if (status == WLC_E_STATUS_FAIL) {
9649 WL_ERR(("auth assoc status event=%d e->status %d e->reason %d \n",
9650 ntoh32(cfg->event_auth_assoc.event_type),
9651 (int)ntoh32(cfg->event_auth_assoc.status),
9652 (int)ntoh32(cfg->event_auth_assoc.reason)));
9654 switch ((int)ntoh32(cfg->event_auth_assoc.status)) {
9655 case WLC_E_STATUS_NO_ACK:
9656 cfg->assoc_reject_status = 1;
9658 case WLC_E_STATUS_FAIL:
9659 cfg->assoc_reject_status = 2;
9661 case WLC_E_STATUS_UNSOLICITED:
9662 cfg->assoc_reject_status = 3;
9664 case WLC_E_STATUS_TIMEOUT:
9665 cfg->assoc_reject_status = 4;
9667 case WLC_E_STATUS_ABORT:
9668 cfg->assoc_reject_status = 5;
9673 if (cfg->assoc_reject_status) {
9674 if (ntoh32(cfg->event_auth_assoc.event_type) == WLC_E_ASSOC) {
9675 cfg->assoc_reject_status += MAX_ASSOC_REJECT_ERR_STATUS;
9680 WL_ERR(("assoc_reject_status %d \n", cfg->assoc_reject_status));
9685 s32 wl_cfg80211_get_connect_failed_status(struct net_device *dev, char* cmd, int total_len)
9687 struct bcm_cfg80211 *cfg = NULL;
9688 int bytes_written = 0;
9696 memset(cmd, 0, total_len);
9697 bytes_written = snprintf(cmd, 30, "assoc_reject.status %d", cfg->assoc_reject_status);
9699 WL_ERR(("cmd: %s \n", cmd));
9701 return bytes_written;
9703 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
9706 wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9707 const wl_event_msg_t *e)
9709 u32 reason = ntoh32(e->reason);
9710 u32 event = ntoh32(e->event_type);
9711 struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
9712 WL_DBG(("event type : %d, reason : %d\n", event, reason));
9714 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9715 memcpy(&cfg->event_auth_assoc, e, sizeof(wl_event_msg_t));
9716 WL_ERR(("event=%d status %d reason %d \n",
9717 ntoh32(cfg->event_auth_assoc.event_type),
9718 ntoh32(cfg->event_auth_assoc.status),
9719 ntoh32(cfg->event_auth_assoc.reason)));
9720 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
9725 sec->auth_assoc_res_status = reason;
9730 WL_ERR(("sec is NULL\n"));
9735 wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
9736 const wl_event_msg_t *e, void *data)
9739 u32 event = ntoh32(e->event_type);
9740 u16 flags = ntoh16(e->flags);
9741 u32 status = ntoh32(e->status);
9743 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9744 struct ieee80211_channel *channel = NULL;
9745 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
9748 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
9750 if (event == WLC_E_JOIN) {
9751 WL_DBG(("joined in IBSS network\n"));
9753 if (event == WLC_E_START) {
9754 WL_DBG(("started IBSS network\n"));
9756 if (event == WLC_E_JOIN || event == WLC_E_START ||
9757 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
9758 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9759 err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
9760 if (unlikely(err)) {
9761 WL_ERR(("Could not get chanspec %d\n", err));
9764 chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
9765 band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
9766 freq = ieee80211_channel_to_frequency(chan, band);
9767 channel = ieee80211_get_channel(wiphy, freq);
9768 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
9769 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
9770 /* ROAM or Redundant */
9771 u8 *cur_bssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
9772 if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
9773 WL_DBG(("IBSS connected event from same BSSID("
9774 MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
9777 WL_INFORM(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
9778 MAC2STRDBG(cur_bssid), MAC2STRDBG((const u8 *)&e->addr)));
9779 wl_get_assoc_ies(cfg, ndev);
9780 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
9781 wl_update_bss_info(cfg, ndev, false);
9782 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9783 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
9785 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
9789 /* New connection */
9790 WL_INFORM(("IBSS connected to " MACDBG "\n",
9791 MAC2STRDBG((const u8 *)&e->addr)));
9793 wl_get_assoc_ies(cfg, ndev);
9794 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
9795 wl_update_bss_info(cfg, ndev, false);
9796 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
9797 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
9799 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
9801 wl_set_drv_status(cfg, CONNECTED, ndev);
9803 wl_update_prof(cfg, ndev, NULL, (const void *)&active, WL_PROF_ACT);
9805 } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
9806 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
9807 wl_clr_drv_status(cfg, CONNECTED, ndev);
9809 wl_init_prof(cfg, ndev);
9811 else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
9812 WL_DBG(("no action - join fail (IBSS mode)\n"));
9815 WL_DBG(("no action (IBSS mode)\n"));
9820 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
9821 #define WiFiALL_OUI "\x50\x6F\x9A" /* Wi-FiAll OUI */
9822 #define WiFiALL_OUI_LEN 3
9823 #define WiFiALL_OUI_TYPE 16
9825 int wl_get_bss_info(struct bcm_cfg80211 *cfg, struct net_device *dev, uint8 *mac)
9828 struct wl_bss_info *bi;
9829 uint8 eabuf[ETHER_ADDR_LEN];
9830 u32 rate, channel, freq, supported_rate, nss = 0, mcs_map, mode_80211 = 0;
9834 struct wiphy *wiphy;
9835 struct cfg80211_bss *bss;
9836 bcm_tlv_t *interworking_ie = NULL;
9837 bcm_tlv_t *tlv_ie = NULL;
9838 bcm_tlv_t *vht_ie = NULL;
9840 int16 ie_11u_rel_num = -1, ie_mu_mimo_cap = -1;
9841 u32 i, remained_len, count = 0;
9842 char roam_count_str[4], akm_str[4];
9845 /* get BSS information */
9847 strncpy(cfg->bss_info, "x x x x x x x x x x x x x", GET_BSS_INFO_LEN);
9849 *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
9851 err = wldev_ioctl(dev, WLC_GET_BSS_INFO, cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
9852 if (unlikely(err)) {
9853 WL_ERR(("Could not get bss info %d\n", err));
9854 cfg->roam_count = 0;
9859 WL_ERR(("mac is null \n"));
9860 cfg->roam_count = 0;
9864 memcpy(eabuf, mac, ETHER_ADDR_LEN);
9866 bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
9867 channel = wf_chspec_ctlchan(bi->chanspec);
9869 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
9870 freq = ieee80211_channel_to_frequency(channel);
9873 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
9875 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
9879 err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
9881 WL_ERR(("Could not get rate (%d)\n", err));
9882 snprintf(rate_str, sizeof(rate_str), "x"); // Unknown
9885 rate = dtoh32(rate);
9886 snprintf(rate_str, sizeof(rate_str), "%d", (rate/2));
9889 //supported maximum rate
9890 supported_rate = (bi->rateset.rates[bi->rateset.count - 1] & 0x7f) / 2;
9892 if (supported_rate < 12) {
9893 mode_80211 = 0; //11b maximum rate is 11Mbps. 11b mode
9895 //It's not HT Capable case.
9897 mode_80211 = 3; // 11a mode
9899 mode_80211 = 1; // 11g mode
9904 /* check Rx MCS Map for HT */
9907 for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
9909 if (i == MAX_STREAMS_SUPPORTED-1) {
9912 if (bi->basic_mcs[i] & bitmap) {
9921 for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
9922 mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
9923 if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
9933 wiphy = bcmcfg_to_wiphy(cfg);
9934 bss = cfg80211_get_bss(wiphy, NULL, eabuf,
9935 bi->SSID, strlen(bi->SSID), WLAN_CAPABILITY_ESS,
9936 WLAN_CAPABILITY_ESS);
9939 WL_ERR(("Could not find the AP\n"));
9941 #if defined(WL_CFG80211_P2P_DEV_IF)
9942 ie = (u8 *)bss->ies->data;
9943 ie_len = bss->ies->len;
9945 ie = bss->information_elements;
9946 ie_len = bss->len_information_elements;
9947 #endif /* WL_CFG80211_P2P_DEV_IF */
9955 if ((vht_ie = bcm_parse_tlvs(ie, (u32)ie_len,
9956 DOT11_MNG_VHT_CAP_ID)) != NULL) {
9957 ie_mu_mimo_cap = (vht_ie->data[2] & 0x08) >> 3;
9961 if ((interworking_ie = bcm_parse_tlvs(ie, (u32)ie_len,
9962 DOT11_MNG_INTERWORKING_ID)) != NULL) {
9963 if ((tlv_ie = bcm_parse_tlvs(ie, (u32)ie_len, DOT11_MNG_VS_ID)) != NULL) {
9964 remained_len = ie_len;
9967 if (count > MAX_VNDR_IE_NUMBER)
9970 if (tlv_ie->id == DOT11_MNG_VS_ID) {
9971 vndrie = (vndr_ie_t *) tlv_ie;
9973 if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
9974 WL_ERR(("%s: invalid vndr ie."
9975 "length is too small %d\n",
9976 __FUNCTION__, vndrie->len));
9980 if (!bcmp(vndrie->oui,
9981 (u8*)WiFiALL_OUI, WiFiALL_OUI_LEN) &&
9982 (vndrie->data[0] == WiFiALL_OUI_TYPE))
9984 WL_ERR(("Found Wi-FiAll OUI oui.\n"));
9985 ie_11u_rel_num = vndrie->data[1];
9986 ie_11u_rel_num = (ie_11u_rel_num & 0xf0)>>4;
9987 ie_11u_rel_num += 1;
9993 tlv_ie = bcm_next_tlv(tlv_ie, &remained_len);
9999 for (i = 0; i < bi->SSID_len; i++) {
10000 if (bi->SSID[i] == ' ') {
10005 //0 : None, 1 : OKC, 2 : FT, 3 : CCKM
10006 err = wldev_iovar_getint(dev, "wpa_auth", &val);
10007 if (unlikely(err)) {
10008 WL_ERR(("could not get wpa_auth (%d)\n", err));
10009 snprintf(akm_str, sizeof(akm_str), "x"); // Unknown
10011 WL_ERR(("wpa_auth val %d \n", val));
10012 #if defined(BCMEXTCCX)
10013 if (val & (WPA_AUTH_CCKM | WPA2_AUTH_CCKM)) {
10014 snprintf(akm_str, sizeof(akm_str), "3");
10017 if (val & WPA2_AUTH_FT) {
10018 snprintf(akm_str, sizeof(akm_str), "2");
10019 } else if (val & (WPA_AUTH_UNSPECIFIED | WPA2_AUTH_UNSPECIFIED)) {
10020 snprintf(akm_str, sizeof(akm_str), "1");
10022 snprintf(akm_str, sizeof(akm_str), "0");
10026 if (cfg->roam_offload) {
10027 snprintf(roam_count_str, sizeof(roam_count_str), "x"); // Unknown
10029 snprintf(roam_count_str, sizeof(roam_count_str), "%d", cfg->roam_count);
10031 cfg->roam_count = 0;
10033 WL_ERR(("BSSID:" MACDBG " SSID %s \n", MAC2STRDBG(eabuf), bi->SSID));
10034 WL_ERR(("freq:%d, BW:%s, RSSI:%d dBm, Rate:%d Mbps, 11mode:%d, stream:%d,"
10035 "MU-MIMO:%d, Passpoint:%d, SNR:%d, Noise:%d, \n"
10036 "akm:%s roam:%s \n",
10037 freq, wf_chspec_to_bw_str(bi->chanspec),
10038 dtoh32(bi->RSSI), (rate / 2), mode_80211, nss,
10039 ie_mu_mimo_cap, ie_11u_rel_num, bi->SNR, bi->phy_noise,
10040 akm_str, roam_count_str));
10043 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
10044 "%02x:%02x:%02x %d %s %d %s %d %d %d %d %d %d %s %s",
10045 eabuf[0], eabuf[1], eabuf[2],
10046 freq, wf_chspec_to_bw_str(bi->chanspec),
10047 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
10048 ie_mu_mimo_cap, ie_11u_rel_num,
10049 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
10051 //ie_mu_mimo_cap and ie_11u_rel_num is unknow.
10052 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
10053 "%02x:%02x:%02x %d %s %d %s %d %d x x %d %d %s %s",
10054 eabuf[0], eabuf[1], eabuf[2],
10055 freq, wf_chspec_to_bw_str(bi->chanspec),
10056 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
10057 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
10064 s32 wl_cfg80211_get_bss_info(struct net_device *dev, char* cmd, int total_len)
10066 struct bcm_cfg80211 *cfg = NULL;
10074 memset(cmd, 0, total_len);
10075 memcpy(cmd, cfg->bss_info, GET_BSS_INFO_LEN);
10077 WL_ERR(("cmd: %s \n", cmd));
10079 return GET_BSS_INFO_LEN;
10082 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10085 wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10086 const wl_event_msg_t *e, void *data)
10089 struct net_device *ndev = NULL;
10091 u32 event = ntoh32(e->event_type);
10092 struct wiphy *wiphy = NULL;
10093 struct cfg80211_bss *bss = NULL;
10094 struct wlc_ssid *ssid = NULL;
10097 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10099 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
10100 err = wl_notify_connect_status_ap(cfg, ndev, e, data);
10101 } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS) {
10102 err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
10103 } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) {
10104 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
10105 ntoh32(e->event_type), ntoh32(e->status), ndev));
10106 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
10107 wl_get_auth_assoc_status(cfg, ndev, e);
10110 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
10111 if (wl_is_linkup(cfg, e, ndev)) {
10114 if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
10115 #ifdef DHD_LOSSLESS_ROAMING
10116 bool is_connected = wl_get_drv_status(cfg, CONNECTED, ndev);
10119 printf("wl_bss_connect_done succeeded with " MACDBG "\n",
10120 MAC2STRDBG((const u8*)(&e->addr)));
10121 wl_bss_connect_done(cfg, ndev, e, data, true);
10122 dhd_conf_set_fw_string_cmd(cfg->pub, "phy_oclscdenable", cfg->pub->conf->phy_oclscdenable, 0, FALSE);
10123 WL_DBG(("joined in BSS network \"%s\"\n",
10124 ((struct wlc_ssid *)
10125 wl_read_prof(cfg, ndev, WL_PROF_SSID))->SSID));
10126 #ifdef DHD_LOSSLESS_ROAMING
10127 if (event == WLC_E_LINK && is_connected &&
10128 !cfg->roam_offload) {
10129 wl_bss_roaming_done(cfg, ndev, e, data);
10131 #endif /* DHD_LOSSLESS_ROAMING */
10134 wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
10135 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
10136 dhd_conf_set_wme(cfg->pub);
10138 } else if (wl_is_linkdown(cfg, e)) {
10139 #ifdef DHD_LOSSLESS_ROAMING
10140 wl_del_roam_timeout(cfg);
10142 #ifdef P2PLISTEN_AP_SAMECHN
10143 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
10144 wl_cfg80211_set_p2p_resp_ap_chn(ndev, 0);
10145 cfg->p2p_resp_apchn_status = false;
10146 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
10148 #endif /* P2PLISTEN_AP_SAMECHN */
10149 wl_cfg80211_cancel_scan(cfg);
10151 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10152 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10153 wl_get_bss_info(cfg, ndev, (u8*)(&e->addr));
10155 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10156 /* Explicitly calling unlink to remove BSS in CFG */
10157 wiphy = bcmcfg_to_wiphy(cfg);
10158 ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
10159 bssid = (u8 *)wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10160 if (ssid && bssid) {
10161 bss = cfg80211_get_bss(wiphy, NULL, bssid,
10162 ssid->SSID, ssid->SSID_len, WLAN_CAPABILITY_ESS,
10163 WLAN_CAPABILITY_ESS);
10165 cfg80211_unlink_bss(wiphy, bss);
10169 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10171 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10173 struct ether_addr bssid_dongle;
10174 struct ether_addr bssid_null = {{0, 0, 0, 0, 0, 0}};
10176 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
10177 reason = ntoh32(e->reason);
10178 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
10179 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
10181 printf("link down if %s may call cfg80211_disconnected. "
10182 "event : %d, reason=%d from " MACDBG "\n",
10183 ndev->name, event, ntoh32(e->reason),
10184 MAC2STRDBG((const u8*)(&e->addr)));
10186 /* roam offload does not sync BSSID always, get it from dongle */
10187 if (cfg->roam_offload) {
10188 if (wldev_ioctl(ndev, WLC_GET_BSSID, &bssid_dongle,
10189 sizeof(bssid_dongle), false) == BCME_OK) {
10190 /* if not roam case, it would return null bssid */
10191 if (memcmp(&bssid_dongle, &bssid_null,
10192 ETHER_ADDR_LEN) != 0) {
10193 curbssid = (u8 *)&bssid_dongle;
10197 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
10198 bool fw_assoc_state = TRUE;
10199 dhd_pub_t *dhd = (dhd_pub_t *)cfg->pub;
10200 fw_assoc_state = dhd_is_associated(dhd, e->ifidx, &err);
10201 if (!fw_assoc_state) {
10202 WL_ERR(("Even sends up even different BSSID"
10203 " cur: " MACDBG " event: " MACDBG"\n",
10204 MAC2STRDBG(curbssid),
10205 MAC2STRDBG((const u8*)(&e->addr))));
10207 WL_ERR(("BSSID of event is not the connected BSSID"
10208 "(ignore it) cur: " MACDBG
10209 " event: " MACDBG"\n",
10210 MAC2STRDBG(curbssid),
10211 MAC2STRDBG((const u8*)(&e->addr))));
10215 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
10216 // terence 20130703: Fix for wrong group_capab (timing issue)
10217 cfg->p2p_disconnected = 1;
10219 memcpy(&cfg->disconnected_bssid, curbssid, ETHER_ADDR_LEN);
10220 wl_clr_drv_status(cfg, CONNECTED, ndev);
10221 if (! wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
10222 /* To make sure disconnect, explictly send dissassoc
10223 * for BSSID 00:00:00:00:00:00 issue
10225 scbval.val = WLAN_REASON_DEAUTH_LEAVING;
10227 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
10228 scbval.val = htod32(scbval.val);
10229 err = wldev_ioctl(ndev, WLC_DISASSOC, &scbval,
10230 sizeof(scb_val_t), true);
10232 WL_ERR(("WLC_DISASSOC error %d\n", err));
10235 CFG80211_DISCONNECTED(ndev, reason, NULL, 0,
10236 false, GFP_KERNEL);
10238 wl_init_prof(cfg, ndev);
10239 memset(&cfg->last_roamed_addr, 0, ETHER_ADDR_LEN);
10242 else if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
10243 printf("link down, during connecting\n");
10244 #ifdef ESCAN_RESULT_PATCH
10245 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
10246 (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
10247 (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
10248 /* In case this event comes while associating another AP */
10249 #endif /* ESCAN_RESULT_PATCH */
10250 wl_bss_connect_done(cfg, ndev, e, data, false);
10252 wl_clr_drv_status(cfg, DISCONNECTING, ndev);
10254 /* if link down, bsscfg is diabled */
10255 if (ndev != bcmcfg_to_prmry_ndev(cfg))
10256 complete(&cfg->iface_disable);
10258 } else if (wl_is_nonetwork(cfg, e)) {
10259 printf("connect failed event=%d e->status %d e->reason %d \n",
10260 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
10261 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10262 if (event == WLC_E_SET_SSID) {
10263 wl_get_connect_failed_status(cfg, e);
10265 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10266 /* Clean up any pending scan request */
10267 wl_cfg80211_cancel_scan(cfg);
10268 if (wl_get_drv_status(cfg, CONNECTING, ndev))
10269 wl_bss_connect_done(cfg, ndev, e, data, false);
10271 WL_DBG(("%s nothing\n", __FUNCTION__));
10273 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
10276 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg, ndev)));
10281 void wl_cfg80211_set_rmc_pid(int pid)
10283 struct bcm_cfg80211 *cfg = g_bcm_cfg;
10285 cfg->rmc_event_pid = pid;
10286 WL_DBG(("set pid for rmc event : pid=%d\n", pid));
10291 wl_notify_rmc_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10292 const wl_event_msg_t *e, void *data)
10294 u32 evt = ntoh32(e->event_type);
10295 u32 reason = ntoh32(e->reason);
10299 case WLC_E_REASON_RMC_AR_LOST:
10300 case WLC_E_REASON_RMC_AR_NO_ACK:
10301 if (cfg->rmc_event_pid != 0) {
10302 ret = wl_netlink_send_msg(cfg->rmc_event_pid,
10303 RMC_EVENT_LEADER_CHECK_FAIL,
10304 cfg->rmc_event_seq++, NULL, 0);
10310 WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt, cfg->rmc_event_pid, ret));
10313 #endif /* WL_RELMCAST */
10315 wl_notify_roaming_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10316 const wl_event_msg_t *e, void *data)
10319 struct net_device *ndev = NULL;
10321 u32 event = be32_to_cpu(e->event_type);
10322 u32 status = be32_to_cpu(e->status);
10323 #ifdef DHD_LOSSLESS_ROAMING
10324 struct wl_security *sec;
10326 WL_DBG(("Enter \n"));
10328 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10330 if ((!cfg->disable_roam_event) && (event == WLC_E_BSSID)) {
10331 wl_add_remove_eventmsg(ndev, WLC_E_ROAM, false);
10332 cfg->disable_roam_event = TRUE;
10335 if ((cfg->disable_roam_event) && (event == WLC_E_ROAM))
10338 if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status == WLC_E_STATUS_SUCCESS) {
10339 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10340 #ifdef DHD_LOSSLESS_ROAMING
10341 if (cfg->roam_offload) {
10342 wl_bss_roaming_done(cfg, ndev, e, data);
10343 wl_del_roam_timeout(cfg);
10346 sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10347 /* In order to reduce roaming delay, wl_bss_roaming_done is
10348 * early called with WLC_E_LINK event. It is called from
10349 * here only if WLC_E_LINK event is blocked for specific
10352 if (IS_AKM_SUITE_FT(sec)) {
10353 wl_bss_roaming_done(cfg, ndev, e, data);
10355 /* Roam timer is deleted mostly from wl_cfg80211_change_station
10356 * after roaming is finished successfully. We need to delete
10357 * the timer from here only for some security types that aren't
10358 * using wl_cfg80211_change_station to authorize SCB
10360 if (IS_AKM_SUITE_FT(sec) || IS_AKM_SUITE_CCKM(sec)) {
10361 wl_del_roam_timeout(cfg);
10365 wl_bss_roaming_done(cfg, ndev, e, data);
10366 #endif /* DHD_LOSSLESS_ROAMING */
10368 wl_bss_connect_done(cfg, ndev, e, data, true);
10371 wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
10372 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
10374 #ifdef DHD_LOSSLESS_ROAMING
10375 else if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status != WLC_E_STATUS_SUCCESS) {
10376 wl_del_roam_timeout(cfg);
10383 /* up range from low to high with up value */
10385 up_table_set(uint8 *up_table, uint8 up, uint8 low, uint8 high)
10389 if (up > 7 || low > high || low >= UP_TABLE_MAX || high >= UP_TABLE_MAX) {
10393 for (i = low; i <= high; i++) {
10400 /* set user priority table */
10402 wl_set_up_table(uint8 *up_table, bcm_tlv_t *qos_map_ie)
10406 if (up_table == NULL || qos_map_ie == NULL) {
10410 /* clear table to check table was set or not */
10411 memset(up_table, 0xff, UP_TABLE_MAX);
10413 /* length of QoS Map IE must be 16+n*2, n is number of exceptions */
10414 if (qos_map_ie != NULL && qos_map_ie->id == DOT11_MNG_QOS_MAP_ID &&
10415 (len = qos_map_ie->len) >= QOS_MAP_FIXED_LENGTH &&
10417 uint8 *except_ptr = (uint8 *)qos_map_ie->data;
10418 uint8 except_len = len - QOS_MAP_FIXED_LENGTH;
10419 uint8 *range_ptr = except_ptr + except_len;
10422 /* fill in ranges */
10423 for (i = 0; i < QOS_MAP_FIXED_LENGTH; i += 2) {
10424 uint8 low = range_ptr[i];
10425 uint8 high = range_ptr[i + 1];
10426 if (low == 255 && high == 255) {
10430 if (!up_table_set(up_table, i / 2, low, high)) {
10431 /* clear the table on failure */
10432 memset(up_table, 0xff, UP_TABLE_MAX);
10437 /* update exceptions */
10438 for (i = 0; i < except_len; i += 2) {
10439 uint8 dscp = except_ptr[i];
10440 uint8 up = except_ptr[i+1];
10442 /* exceptions with invalid dscp/up are ignored */
10443 up_table_set(up_table, up, dscp, dscp);
10447 if (wl_dbg_level & WL_DBG_DBG) {
10448 prhex("UP table", up_table, UP_TABLE_MAX);
10452 /* get user priority table */
10454 wl_get_up_table(void)
10456 return (uint8 *)(g_bcm_cfg->up_table);
10458 #endif /* QOS_MAP_SET */
10460 #ifdef DHD_LOSSLESS_ROAMING
10462 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10463 const wl_event_msg_t *e, void *data)
10466 struct wl_security *sec;
10467 struct net_device *ndev;
10468 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
10470 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10472 sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10473 /* Disable Lossless Roaming for specific AKM suite
10474 * Any other AKM suite can be added below if transition time
10475 * is delayed because of Lossless Roaming
10476 * and it causes any certication failure
10478 if (IS_AKM_SUITE_FT(sec)) {
10482 dhdp->dequeue_prec_map = 1 << PRIO_8021D_NC;
10483 /* Restore flow control */
10484 dhd_txflowcontrol(dhdp, ALL_INTERFACES, OFF);
10486 mod_timer(&cfg->roam_timeout, jiffies + msecs_to_jiffies(WL_ROAM_TIMEOUT_MS));
10490 #endif /* DHD_LOSSLESS_ROAMING */
10493 wl_notify_idsup_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10494 const wl_event_msg_t *e, void *data)
10497 #if defined(WL_VENDOR_EXT_SUPPORT)
10499 u32 reason = ntoh32(e->reason);
10500 struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10501 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
10502 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
10504 if (cfg->roam_offload) {
10505 #if defined(WL_VENDOR_EXT_SUPPORT)
10507 case WLC_E_SUP_WPA_PSK_TMO:
10508 idsup_status = IDSUP_EVENT_4WAY_HANDSHAKE_TIMEOUT;
10510 case WLC_E_SUP_OTHER:
10511 idsup_status = IDSUP_EVENT_SUCCESS;
10514 WL_ERR(("Other type at IDSUP. "
10515 "event=%d e->status %d e->reason %d \n",
10516 (int)ntoh32(e->event_type), (int)ntoh32(e->status),
10517 (int)ntoh32(e->reason)));
10521 err = wl_cfgvendor_send_async_event(wiphy, ndev,
10522 BRCM_VENDOR_EVENT_IDSUP_STATUS, &idsup_status, sizeof(u32));
10523 #endif /* defined(WL_VENDOR_EXT_SUPPORT) */
10528 #ifdef CUSTOM_EVENT_PM_WAKE
10530 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10531 const wl_event_msg_t *e, void *data)
10534 struct net_device *ndev = NULL;
10536 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10538 pbuf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
10539 if (pbuf == NULL) {
10540 WL_ERR(("failed to allocate local pbuf\n"));
10544 err = wldev_iovar_getbuf_bsscfg(ndev, "dump",
10545 "pm", strlen("pm"), pbuf, WLC_IOCTL_MEDLEN, 0, &cfg->ioctl_buf_sync);
10548 WL_ERR(("dump ioctl err = %d", err));
10550 WL_ERR(("PM status : %s\n", pbuf));
10558 #endif /* CUSTOM_EVENT_PM_WAKE */
10560 static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev)
10562 wl_assoc_info_t assoc_info;
10563 struct wl_connect_info *conn_info = wl_to_conn(cfg);
10566 bcm_tlv_t * qos_map_ie = NULL;
10567 #endif /* QOS_MAP_SET */
10569 WL_DBG(("Enter \n"));
10570 err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, cfg->extra_buf,
10571 WL_ASSOC_INFO_MAX, NULL);
10572 if (unlikely(err)) {
10573 WL_ERR(("could not get assoc info (%d)\n", err));
10576 memcpy(&assoc_info, cfg->extra_buf, sizeof(wl_assoc_info_t));
10577 assoc_info.req_len = htod32(assoc_info.req_len);
10578 assoc_info.resp_len = htod32(assoc_info.resp_len);
10579 assoc_info.flags = htod32(assoc_info.flags);
10580 if (conn_info->req_ie_len) {
10581 conn_info->req_ie_len = 0;
10582 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
10584 if (conn_info->resp_ie_len) {
10585 conn_info->resp_ie_len = 0;
10586 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
10588 if (assoc_info.req_len) {
10589 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, cfg->extra_buf,
10590 WL_ASSOC_INFO_MAX, NULL);
10591 if (unlikely(err)) {
10592 WL_ERR(("could not get assoc req (%d)\n", err));
10595 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
10596 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
10597 conn_info->req_ie_len -= ETHER_ADDR_LEN;
10599 if (conn_info->req_ie_len <= MAX_REQ_LINE)
10600 memcpy(conn_info->req_ie, cfg->extra_buf, conn_info->req_ie_len);
10602 WL_ERR(("IE size %d above max %d size \n",
10603 conn_info->req_ie_len, MAX_REQ_LINE));
10607 conn_info->req_ie_len = 0;
10609 if (assoc_info.resp_len) {
10610 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, cfg->extra_buf,
10611 WL_ASSOC_INFO_MAX, NULL);
10612 if (unlikely(err)) {
10613 WL_ERR(("could not get assoc resp (%d)\n", err));
10616 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
10617 if (conn_info->resp_ie_len <= MAX_REQ_LINE) {
10618 memcpy(conn_info->resp_ie, cfg->extra_buf, conn_info->resp_ie_len);
10620 WL_ERR(("IE size %d above max %d size \n",
10621 conn_info->resp_ie_len, MAX_REQ_LINE));
10626 /* find qos map set ie */
10627 if ((qos_map_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
10628 DOT11_MNG_QOS_MAP_ID)) != NULL) {
10629 WL_DBG((" QoS map set IE found in assoc response\n"));
10630 if (!cfg->up_table) {
10631 cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
10633 wl_set_up_table(cfg->up_table, qos_map_ie);
10635 kfree(cfg->up_table);
10636 cfg->up_table = NULL;
10638 #endif /* QOS_MAP_SET */
10640 conn_info->resp_ie_len = 0;
10642 WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
10643 conn_info->resp_ie_len));
10648 static s32 wl_ch_to_chanspec(struct net_device *dev, int ch, struct wl_join_params *join_params,
10649 size_t *join_params_size)
10651 struct bcm_cfg80211 *cfg;
10653 chanspec_t chanspec = 0, chspec;
10656 cfg = (struct bcm_cfg80211 *)wiphy_priv(dev->ieee80211_ptr->wiphy);
10657 if (cfg && cfg->rcc_enabled) {
10659 join_params->params.chanspec_num = 1;
10660 join_params->params.chanspec_list[0] = ch;
10662 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
10663 chanspec |= WL_CHANSPEC_BAND_2G;
10665 chanspec |= WL_CHANSPEC_BAND_5G;
10667 /* Get the min_bw set for the interface */
10668 chspec = wl_cfg80211_ulb_get_min_bw_chspec(dev->ieee80211_ptr, bssidx);
10669 if (chspec == INVCHANSPEC) {
10670 WL_ERR(("Invalid chanspec \n"));
10673 chanspec |= chspec;
10674 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
10676 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
10677 join_params->params.chanspec_num * sizeof(chanspec_t);
10679 join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
10680 join_params->params.chanspec_list[0] |= chanspec;
10681 join_params->params.chanspec_list[0] =
10682 wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
10684 join_params->params.chanspec_num =
10685 htod32(join_params->params.chanspec_num);
10688 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
10689 join_params->params.chanspec_list[0],
10690 join_params->params.chanspec_num));
10695 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam)
10697 struct wl_bss_info *bi;
10698 struct wlc_ssid *ssid;
10699 struct bcm_tlv *tim;
10700 s32 beacon_interval;
10706 struct wiphy *wiphy;
10709 wiphy = bcmcfg_to_wiphy(cfg);
10711 ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
10712 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10714 mutex_lock(&cfg->usr_sync);
10716 *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
10717 err = wldev_ioctl(ndev, WLC_GET_BSS_INFO,
10718 cfg->extra_buf, WL_EXTRA_BUF_MAX, false);
10719 if (unlikely(err)) {
10720 WL_ERR(("Could not get bss info %d\n", err));
10721 goto update_bss_info_out;
10723 bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
10724 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
10725 wl_update_prof(cfg, ndev, NULL, &channel, WL_PROF_CHAN);
10727 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
10728 WL_ERR(("Bssid doesn't match\n"));
10730 goto update_bss_info_out;
10732 err = wl_inform_single_bss(cfg, bi, roam);
10734 goto update_bss_info_out;
10736 ie = ((u8 *)bi) + bi->ie_offset;
10737 ie_len = bi->ie_length;
10738 beacon_interval = cpu_to_le16(bi->beacon_period);
10739 tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
10741 dtim_period = tim->data[1];
10744 * active scan was done so we could not get dtim
10745 * information out of probe response.
10746 * so we speficially query dtim information.
10748 err = wldev_ioctl(ndev, WLC_GET_DTIMPRD,
10749 &dtim_period, sizeof(dtim_period), false);
10750 if (unlikely(err)) {
10751 WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
10752 goto update_bss_info_out;
10756 wl_update_prof(cfg, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
10757 wl_update_prof(cfg, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
10759 update_bss_info_out:
10760 if (unlikely(err)) {
10761 WL_ERR(("Failed with error %d\n", err));
10763 mutex_unlock(&cfg->usr_sync);
10768 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
10769 const wl_event_msg_t *e, void *data)
10771 struct wl_connect_info *conn_info = wl_to_conn(cfg);
10774 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10775 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
10776 struct ieee80211_supported_band *band;
10777 struct ieee80211_channel *notify_channel = NULL;
10783 if (memcmp(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN) == 0) {
10784 WL_INFORM(("BSSID already updated\n"));
10788 /* Skip calling cfg80211_roamed If current bssid and
10789 * roamed bssid are same. Also clear timer roam_timeout.
10791 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10792 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0) {
10793 WL_ERR(("BSS already present, Skipping roamed event to upper layer\n"));
10794 #ifdef DHD_LOSSLESS_ROAMING
10795 wl_del_roam_timeout(cfg);
10796 #endif /* DHD_LOSSLESS_ROAMING */
10800 wl_get_assoc_ies(cfg, ndev);
10801 wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet), WL_PROF_BSSID);
10802 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10803 wl_update_bss_info(cfg, ndev, true);
10804 wl_update_pmklist(ndev, cfg->pmk_list, err);
10806 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10807 /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
10808 channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
10809 if (*channel <= CH_MAX_2G_CHANNEL)
10810 band = wiphy->bands[IEEE80211_BAND_2GHZ];
10812 band = wiphy->bands[IEEE80211_BAND_5GHZ];
10813 freq = ieee80211_channel_to_frequency(*channel, band->band);
10814 notify_channel = ieee80211_get_channel(wiphy, freq);
10816 printf("wl_bss_roaming_done succeeded to " MACDBG "\n",
10817 MAC2STRDBG((const u8*)(&e->addr)));
10818 dhd_conf_set_wme(cfg->pub);
10820 cfg80211_roamed(ndev,
10821 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
10825 conn_info->req_ie, conn_info->req_ie_len,
10826 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
10827 WL_DBG(("Report roaming result\n"));
10829 memcpy(&cfg->last_roamed_addr, (void *)&e->addr, ETHER_ADDR_LEN);
10830 wl_set_drv_status(cfg, CONNECTED, ndev);
10832 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
10834 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
10840 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
10841 const wl_event_msg_t *e, void *data, bool completed)
10843 struct wl_connect_info *conn_info = wl_to_conn(cfg);
10844 struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
10845 #if defined(CUSTOM_SET_CPUCORE)
10846 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
10849 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10851 WL_ERR(("sec is NULL\n"));
10854 WL_DBG((" enter\n"));
10855 #ifdef ESCAN_RESULT_PATCH
10856 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
10857 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
10858 WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
10859 ntoh32(e->event_type), ntoh32(e->status)));
10863 if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
10864 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
10865 WL_DBG(("copy bssid\n"));
10866 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
10870 if (cfg->scan_request) {
10871 wl_notify_escan_complete(cfg, ndev, true, true);
10873 #endif /* ESCAN_RESULT_PATCH */
10874 if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
10875 wl_cfg80211_scan_abort(cfg);
10876 wl_clr_drv_status(cfg, CONNECTING, ndev);
10878 wl_get_assoc_ies(cfg, ndev);
10879 wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet),
10881 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
10882 wl_update_bss_info(cfg, ndev, false);
10883 wl_update_pmklist(ndev, cfg->pmk_list, err);
10884 wl_set_drv_status(cfg, CONNECTED, ndev);
10885 if (ndev != bcmcfg_to_prmry_ndev(cfg)) {
10886 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
10887 init_completion(&cfg->iface_disable);
10889 /* reinitialize completion to clear previous count */
10890 INIT_COMPLETION(cfg->iface_disable);
10893 #ifdef CUSTOM_SET_CPUCORE
10894 if (wl_get_chan_isvht80(ndev, dhd)) {
10895 if (ndev == bcmcfg_to_prmry_ndev(cfg))
10896 dhd->chan_isvht80 |= DHD_FLAG_STA_MODE; /* STA mode */
10897 else if (is_p2p_group_iface(ndev->ieee80211_ptr))
10898 dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE; /* p2p mode */
10899 dhd_set_cpucore(dhd, TRUE);
10901 #endif /* CUSTOM_SET_CPUCORE */
10904 cfg80211_connect_result(ndev,
10907 conn_info->req_ie_len,
10908 conn_info->resp_ie,
10909 conn_info->resp_ie_len,
10910 completed ? WLAN_STATUS_SUCCESS :
10911 (sec->auth_assoc_res_status) ?
10912 sec->auth_assoc_res_status :
10913 WLAN_STATUS_UNSPECIFIED_FAILURE,
10916 WL_INFORM(("Report connect result - connection succeeded\n"));
10917 dhd_conf_set_wme(cfg->pub);
10919 WL_ERR(("Report connect result - connection failed\n"));
10921 #ifdef CONFIG_TCPACK_FASTTX
10922 if (wl_get_chan_isvht80(ndev, dhd))
10923 wldev_iovar_setint(ndev, "tcpack_fast_tx", 0);
10925 wldev_iovar_setint(ndev, "tcpack_fast_tx", 1);
10926 #endif /* CONFIG_TCPACK_FASTTX */
10932 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10933 const wl_event_msg_t *e, void *data)
10935 struct net_device *ndev = NULL;
10936 u16 flags = ntoh16(e->flags);
10937 enum nl80211_key_type key_type;
10939 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10941 mutex_lock(&cfg->usr_sync);
10942 if (flags & WLC_EVENT_MSG_GROUP)
10943 key_type = NL80211_KEYTYPE_GROUP;
10945 key_type = NL80211_KEYTYPE_PAIRWISE;
10947 cfg80211_michael_mic_failure(ndev, (const u8 *)&e->addr, key_type, -1,
10949 mutex_unlock(&cfg->usr_sync);
10954 #ifdef BT_WIFI_HANDOVER
10956 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10957 const wl_event_msg_t *e, void *data)
10959 struct net_device *ndev = NULL;
10960 u32 event = ntoh32(e->event_type);
10961 u32 datalen = ntoh32(e->datalen);
10964 WL_ERR(("wl_notify_bt_wifi_handover_req: event_type : %d, datalen : %d\n", event, datalen));
10965 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10966 err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
10970 #endif /* BT_WIFI_HANDOVER */
10974 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
10975 const wl_event_msg_t *e, void *data)
10977 struct net_device *ndev = NULL;
10979 WL_ERR((">>> PNO Event\n"));
10981 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
10983 #ifndef WL_SCHED_SCAN
10984 mutex_lock(&cfg->usr_sync);
10985 /* TODO: Use cfg80211_sched_scan_results(wiphy); */
10986 CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
10987 mutex_unlock(&cfg->usr_sync);
10989 /* If cfg80211 scheduled scan is supported, report the pno results via sched
10992 wl_notify_sched_scan_results(cfg, ndev, e, data);
10993 #endif /* WL_SCHED_SCAN */
10996 #endif /* PNO_SUPPORT */
10998 #ifdef GSCAN_SUPPORT
11000 wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11001 const wl_event_msg_t *e, void *data)
11004 u32 event = be32_to_cpu(e->event_type);
11006 int send_evt_bytes = 0;
11007 int batch_event_result_dummy = 0;
11008 struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11009 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11010 u32 len = ntoh32(e->datalen);
11013 case WLC_E_PFN_SWC:
11014 ptr = dhd_dev_swc_scan_event(ndev, data, &send_evt_bytes);
11015 if (send_evt_bytes) {
11016 wl_cfgvendor_send_async_event(wiphy, ndev,
11017 GOOGLE_GSCAN_SIGNIFICANT_EVENT, ptr, send_evt_bytes);
11021 case WLC_E_PFN_BEST_BATCHING:
11022 err = dhd_dev_retrieve_batch_scan(ndev);
11024 WL_ERR(("Batch retrieval already in progress %d\n", err));
11026 wl_cfgvendor_send_async_event(wiphy, ndev,
11027 GOOGLE_GSCAN_BATCH_SCAN_EVENT,
11028 &batch_event_result_dummy, sizeof(int));
11031 case WLC_E_PFN_SCAN_COMPLETE:
11032 batch_event_result_dummy = WIFI_SCAN_COMPLETE;
11033 wl_cfgvendor_send_async_event(wiphy, ndev,
11034 GOOGLE_SCAN_COMPLETE_EVENT,
11035 &batch_event_result_dummy, sizeof(int));
11037 case WLC_E_PFN_BSSID_NET_FOUND:
11038 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
11041 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
11042 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT);
11043 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_FOUND);
11046 case WLC_E_PFN_BSSID_NET_LOST:
11047 /* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
11048 * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
11051 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
11054 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
11055 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT);
11056 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_LOST);
11060 case WLC_E_PFN_GSCAN_FULL_RESULT:
11061 ptr = dhd_dev_process_full_gscan_result(ndev, data, &send_evt_bytes);
11063 wl_cfgvendor_send_async_event(wiphy, ndev,
11064 GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, send_evt_bytes);
11069 WL_ERR(("%s: Unexpected event! - %d\n", __FUNCTION__, event));
11074 #endif /* GSCAN_SUPPORT */
11077 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11078 const wl_event_msg_t *e, void *data)
11080 struct channel_info channel_inform;
11081 struct wl_scan_results *bss_list;
11082 struct net_device *ndev = NULL;
11083 u32 len = WL_SCAN_BUF_MAX;
11085 unsigned long flags;
11087 WL_DBG(("Enter \n"));
11088 if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
11089 WL_ERR(("scan is not ready \n"));
11092 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11094 mutex_lock(&cfg->usr_sync);
11095 wl_clr_drv_status(cfg, SCANNING, ndev);
11096 err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
11097 sizeof(channel_inform), false);
11098 if (unlikely(err)) {
11099 WL_ERR(("scan busy (%d)\n", err));
11100 goto scan_done_out;
11102 channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
11103 if (unlikely(channel_inform.scan_channel)) {
11105 WL_DBG(("channel_inform.scan_channel (%d)\n",
11106 channel_inform.scan_channel));
11108 cfg->bss_list = cfg->scan_results;
11109 bss_list = cfg->bss_list;
11110 memset(bss_list, 0, len);
11111 bss_list->buflen = htod32(len);
11112 err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, false);
11113 if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {
11114 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
11116 goto scan_done_out;
11118 bss_list->buflen = dtoh32(bss_list->buflen);
11119 bss_list->version = dtoh32(bss_list->version);
11120 bss_list->count = dtoh32(bss_list->count);
11122 err = wl_inform_bss(cfg);
11125 del_timer_sync(&cfg->scan_timeout);
11126 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
11127 if (cfg->scan_request) {
11128 cfg80211_scan_done(cfg->scan_request, false);
11129 cfg->scan_request = NULL;
11131 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
11132 WL_DBG(("cfg80211_scan_done\n"));
11133 mutex_unlock(&cfg->usr_sync);
11138 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
11139 const struct ether_addr *sa, const struct ether_addr *bssid,
11140 u8 **pheader, u32 *body_len, u8 *pbody)
11142 struct dot11_management_header *hdr;
11146 u32 prebody_len = *body_len;
11149 /* capability , listen interval */
11150 totlen = DOT11_ASSOC_REQ_FIXED_LEN;
11151 *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
11154 case FC_REASSOC_REQ:
11155 /* capability, listen inteval, ap address */
11156 totlen = DOT11_REASSOC_REQ_FIXED_LEN;
11157 *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
11160 totlen += DOT11_MGMT_HDR_LEN + prebody_len;
11161 *pheader = kzalloc(totlen, GFP_KERNEL);
11162 if (*pheader == NULL) {
11163 WL_ERR(("memory alloc failed \n"));
11166 hdr = (struct dot11_management_header *) (*pheader);
11167 hdr->fc = htol16(fc);
11170 offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
11171 bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
11172 bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
11173 bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
11174 if ((pbody != NULL) && prebody_len)
11175 bcopy((const char*)pbody, offset, prebody_len);
11176 *body_len = totlen;
11182 wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev)
11184 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
11185 if (timer_pending(&cfg->p2p->listen_timer)) {
11186 del_timer_sync(&cfg->p2p->listen_timer);
11188 if (cfg->afx_hdl != NULL) {
11189 if (cfg->afx_hdl->dev != NULL) {
11190 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
11191 wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, cfg->afx_hdl->dev);
11193 cfg->afx_hdl->peer_chan = WL_INVALID;
11195 complete(&cfg->act_frm_scan);
11196 WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
11197 } else if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
11198 if (!(wl_get_p2p_status(cfg, ACTION_TX_COMPLETED) ||
11199 wl_get_p2p_status(cfg, ACTION_TX_NOACK)))
11200 wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
11202 WL_DBG(("*** Wake UP ** abort actframe iovar\n"));
11203 /* if channel is not zero, "actfame" uses off channel scan.
11204 * So abort scan for off channel completion.
11206 if (cfg->af_sent_channel)
11207 wl_cfg80211_scan_abort(cfg);
11209 #ifdef WL_CFG80211_SYNC_GON
11210 else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
11211 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
11212 /* So abort scan to cancel listen */
11213 wl_cfg80211_scan_abort(cfg);
11215 #endif /* WL_CFG80211_SYNC_GON */
11218 #if defined(WLTDLS)
11219 bool wl_cfg80211_is_tdls_tunneled_frame(void *frame, u32 frame_len)
11221 unsigned char *data;
11223 if (frame == NULL) {
11224 WL_ERR(("Invalid frame \n"));
11228 if (frame_len < 5) {
11229 WL_ERR(("Invalid frame length [%d] \n", frame_len));
11235 if (!memcmp(data, TDLS_TUNNELED_PRB_REQ, 5) ||
11236 !memcmp(data, TDLS_TUNNELED_PRB_RESP, 5)) {
11237 WL_DBG(("TDLS Vendor Specific Received type\n"));
11243 #endif /* WLTDLS */
11246 int wl_cfg80211_get_ioctl_version(void)
11248 return ioctl_version;
11252 wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
11253 const wl_event_msg_t *e, void *data)
11255 struct ieee80211_supported_band *band;
11256 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11257 struct ether_addr da;
11258 struct ether_addr bssid;
11259 bool isfree = false;
11262 struct net_device *ndev = NULL;
11263 wifi_p2p_pub_act_frame_t *act_frm = NULL;
11264 wifi_p2p_action_frame_t *p2p_act_frm = NULL;
11265 wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
11266 #if defined(WLTDLS) && defined(TDLS_MSG_ONLY_WFD)
11268 #endif /* WLTDLS && TDLS_MSG_ONLY_WFD */
11269 wl_event_rx_frame_data_t *rxframe =
11270 (wl_event_rx_frame_data_t*)data;
11271 u32 event = ntoh32(e->event_type);
11273 u8 bsscfgidx = e->bsscfgidx;
11274 u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
11275 u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK));
11277 memset(&bssid, 0, ETHER_ADDR_LEN);
11279 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
11281 if (channel <= CH_MAX_2G_CHANNEL)
11282 band = wiphy->bands[IEEE80211_BAND_2GHZ];
11284 band = wiphy->bands[IEEE80211_BAND_5GHZ];
11286 WL_ERR(("No valid band\n"));
11289 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
11290 freq = ieee80211_channel_to_frequency(channel);
11293 freq = ieee80211_channel_to_frequency(channel, band->band);
11295 if (event == WLC_E_ACTION_FRAME_RX) {
11296 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
11297 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
11299 err = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
11301 WL_ERR(("WLC_GET_BSSID error %d\n", err));
11302 memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
11303 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
11304 &mgmt_frame, &mgmt_frame_len,
11305 (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
11307 WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
11308 mgmt_frame_len, channel, freq));
11312 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11313 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11314 act_frm = (wifi_p2p_pub_act_frame_t *)
11315 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11316 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11317 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11318 p2p_act_frm = (wifi_p2p_action_frame_t *)
11319 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11320 (void) p2p_act_frm;
11321 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11322 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
11324 sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
11325 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
11326 if (sd_act_frm && wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
11327 if (cfg->next_af_subtype == sd_act_frm->action) {
11328 WL_DBG(("We got a right next frame of SD!(%d)\n",
11329 sd_act_frm->action));
11330 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11332 /* Stop waiting for next AF. */
11333 wl_stop_wait_next_action_frame(cfg, ndev);
11338 } else if ((mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) ||
11339 (wl_cfg80211_is_tdls_tunneled_frame(
11340 &mgmt_frame[DOT11_MGMT_HDR_LEN],
11341 mgmt_frame_len - DOT11_MGMT_HDR_LEN))) {
11342 if (mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) {
11343 WL_ERR((" TDLS Action Frame Received type = %d \n",
11344 mgmt_frame[DOT11_MGMT_HDR_LEN + 1]));
11346 #ifdef TDLS_MSG_ONLY_WFD
11347 dhdp = (dhd_pub_t *)(cfg->pub);
11348 if (!dhdp->tdls_mode) {
11349 WL_DBG((" TDLS Frame filtered \n"));
11353 if (mgmt_frame[DOT11_MGMT_HDR_LEN + 1] == TDLS_ACTION_SETUP_RESP) {
11354 cfg->tdls_mgmt_frame = mgmt_frame;
11355 cfg->tdls_mgmt_frame_len = mgmt_frame_len;
11356 cfg->tdls_mgmt_freq = freq;
11359 #endif /* TDLS_MSG_ONLY_WFD */
11360 #endif /* WLTDLS */
11362 } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_QOS) {
11363 /* update QoS map set table */
11364 bcm_tlv_t * qos_map_ie = NULL;
11365 if ((qos_map_ie = bcm_parse_tlvs(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11366 mgmt_frame_len - DOT11_MGMT_HDR_LEN,
11367 DOT11_MNG_QOS_MAP_ID)) != NULL) {
11368 WL_DBG((" QoS map set IE found in QoS action frame\n"));
11369 if (!cfg->up_table) {
11370 cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
11372 wl_set_up_table(cfg->up_table, qos_map_ie);
11374 kfree(cfg->up_table);
11375 cfg->up_table = NULL;
11377 #endif /* QOS_MAP_SET */
11380 * if we got normal action frame and ndev is p2p0,
11381 * we have to change ndev from p2p0 to wlan0
11385 if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
11387 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11388 mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
11389 WL_DBG(("Recived action is not public action frame\n"));
11390 } else if (cfg->next_af_subtype == action) {
11391 WL_DBG(("Recived action is the waiting action(%d)\n",
11393 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11395 /* Stop waiting for next AF. */
11396 wl_stop_wait_next_action_frame(cfg, ndev);
11403 if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
11404 if (cfg->next_af_subtype == act_frm->subtype) {
11405 WL_DBG(("We got a right next frame!(%d)\n",
11406 act_frm->subtype));
11407 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
11409 if (cfg->next_af_subtype == P2P_PAF_GON_CONF) {
11413 /* Stop waiting for next AF. */
11414 wl_stop_wait_next_action_frame(cfg, ndev);
11419 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
11420 mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
11422 * After complete GO Negotiation, roll back to mpc mode
11424 if (act_frm && ((act_frm->subtype == P2P_PAF_GON_CONF) ||
11425 (act_frm->subtype == P2P_PAF_PROVDIS_RSP))) {
11426 wldev_iovar_setint(ndev, "mpc", 1);
11428 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
11429 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
11430 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
11432 } else if (event == WLC_E_PROBREQ_MSG) {
11434 /* Handle probe reqs frame
11435 * WPS-AP certification 4.2.13
11437 struct parsed_ies prbreq_ies;
11438 u32 prbreq_ie_len = 0;
11441 WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
11442 mgmt_frame = (u8 *)(data);
11443 mgmt_frame_len = ntoh32(e->datalen);
11445 prbreq_ie_len = mgmt_frame_len - DOT11_MGMT_HDR_LEN;
11447 /* Parse prob_req IEs */
11448 if (wl_cfg80211_parse_ies(&mgmt_frame[DOT11_MGMT_HDR_LEN],
11449 prbreq_ie_len, &prbreq_ies) < 0) {
11450 WL_ERR(("Prob req get IEs failed\n"));
11453 if (prbreq_ies.wps_ie != NULL) {
11454 wl_validate_wps_ie((char *)prbreq_ies.wps_ie, prbreq_ies.wps_ie_len, &pbc);
11455 WL_DBG((" wps_ie exist pbc = %d\n", pbc));
11456 /* if pbc method, send prob_req mgmt frame to upper layer */
11462 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
11464 /* wpa supplicant use probe request event for restarting another GON Req.
11465 * but it makes GON Req repetition.
11466 * so if src addr of prb req is same as my target device,
11467 * do not send probe request event during sending action frame.
11469 if (event == WLC_E_P2P_PROBREQ_MSG) {
11470 WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
11471 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
11474 /* Filter any P2P probe reqs arriving during the
11478 #if defined(P2P_IE_MISSING_FIX)
11479 cfg->p2p_prb_noti &&
11481 wl_get_p2p_status(cfg, GO_NEG_PHASE)) {
11482 WL_DBG(("Filtering P2P probe_req while "
11483 "being in GO-Neg state\n"));
11489 if (discover_cfgdev(cfgdev, cfg))
11490 WL_DBG(("Rx Managment frame For P2P Discovery Interface \n"));
11492 WL_DBG(("Rx Managment frame For Iface (%s) \n", ndev->name));
11494 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
11495 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0);
11496 #elif(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0))
11497 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0, GFP_ATOMIC);
11498 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
11499 defined(WL_COMPAT_WIRELESS)
11500 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
11502 cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
11503 #endif /* LINUX_VERSION >= VERSION(3, 14, 0) */
11505 WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
11506 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
11513 #ifdef WL_SCHED_SCAN
11514 /* If target scan is not reliable, set the below define to "1" to do a
11517 #define FULL_ESCAN_ON_PFN_NET_FOUND 0
11519 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
11520 const wl_event_msg_t *e, void *data)
11522 wl_pfn_net_info_t *netinfo, *pnetinfo;
11523 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11525 struct cfg80211_scan_request *request = NULL;
11526 struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
11527 struct ieee80211_channel *channel = NULL;
11528 int channel_req = 0;
11530 struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data;
11531 int n_pfn_results = pfn_result->count;
11533 WL_DBG(("Enter\n"));
11535 if (e->event_type == WLC_E_PFN_NET_LOST) {
11536 WL_PNO(("PFN NET LOST event. Do Nothing \n"));
11539 WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
11540 if (n_pfn_results > 0) {
11543 if (n_pfn_results > MAX_PFN_LIST_COUNT)
11544 n_pfn_results = MAX_PFN_LIST_COUNT;
11545 pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t)
11546 - sizeof(wl_pfn_net_info_t));
11548 memset(&ssid, 0x00, sizeof(ssid));
11550 request = kzalloc(sizeof(*request)
11551 + sizeof(*request->channels) * n_pfn_results,
11553 channel = (struct ieee80211_channel *)kzalloc(
11554 (sizeof(struct ieee80211_channel) * n_pfn_results),
11556 if (!request || !channel) {
11557 WL_ERR(("No memory"));
11562 request->wiphy = wiphy;
11564 for (i = 0; i < n_pfn_results; i++) {
11565 netinfo = &pnetinfo[i];
11567 WL_ERR(("Invalid netinfo ptr. index:%d", i));
11571 WL_PNO((">>> SSID:%s Channel:%d \n",
11572 netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel));
11573 /* PFN result doesn't have all the info which are required by the supplicant
11574 * (For e.g IEs) Do a target Escan so that sched scan results are reported
11575 * via wl_inform_single_bss in the required format. Escan does require the
11576 * scan request in the form of cfg80211_scan_request. For timebeing, create
11577 * cfg80211_scan_request one out of the received PNO event.
11579 memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID,
11580 netinfo->pfnsubnet.SSID_len);
11581 ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len;
11582 request->n_ssids++;
11584 channel_req = netinfo->pfnsubnet.channel;
11585 band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
11586 : NL80211_BAND_5GHZ;
11587 channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
11588 channel[i].band = band;
11589 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
11590 request->channels[i] = &channel[i];
11591 request->n_channels++;
11594 /* assign parsed ssid array */
11595 if (request->n_ssids)
11596 request->ssids = &ssid[0];
11598 if (wl_get_drv_status_all(cfg, SCANNING)) {
11599 /* Abort any on-going scan */
11600 wl_notify_escan_complete(cfg, ndev, true, true);
11603 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
11604 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
11605 err = wl_cfgp2p_discover_enable_search(cfg, false);
11606 if (unlikely(err)) {
11607 wl_clr_drv_status(cfg, SCANNING, ndev);
11610 p2p_scan(cfg) = false;
11613 wl_set_drv_status(cfg, SCANNING, ndev);
11614 #if FULL_ESCAN_ON_PFN_NET_FOUND
11615 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
11616 err = wl_do_escan(cfg, wiphy, ndev, NULL);
11618 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
11619 err = wl_do_escan(cfg, wiphy, ndev, request);
11622 wl_clr_drv_status(cfg, SCANNING, ndev);
11625 cfg->sched_scan_running = TRUE;
11628 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
11637 #endif /* WL_SCHED_SCAN */
11639 static void wl_init_conf(struct wl_conf *conf)
11641 WL_DBG(("Enter \n"));
11642 conf->frag_threshold = (u32)-1;
11643 conf->rts_threshold = (u32)-1;
11644 conf->retry_short = (u32)-1;
11645 conf->retry_long = (u32)-1;
11646 conf->tx_power = -1;
11649 static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev)
11651 unsigned long flags;
11652 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
11654 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
11655 memset(profile, 0, sizeof(struct wl_profile));
11656 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
11659 static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
11661 memset(cfg->evt_handler, 0, sizeof(cfg->evt_handler));
11663 cfg->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
11664 cfg->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
11665 cfg->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
11666 cfg->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
11667 cfg->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
11668 cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
11669 cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
11670 cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
11671 cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
11672 cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
11673 cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
11674 cfg->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
11675 cfg->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
11676 cfg->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
11677 cfg->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
11678 cfg->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
11679 cfg->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
11680 cfg->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
11681 cfg->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
11682 cfg->evt_handler[WLC_E_START] = wl_notify_connect_status;
11684 cfg->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
11685 #endif /* PNO_SUPPORT */
11686 #ifdef GSCAN_SUPPORT
11687 cfg->evt_handler[WLC_E_PFN_BEST_BATCHING] = wl_notify_gscan_event;
11688 cfg->evt_handler[WLC_E_PFN_SCAN_COMPLETE] = wl_notify_gscan_event;
11689 cfg->evt_handler[WLC_E_PFN_GSCAN_FULL_RESULT] = wl_notify_gscan_event;
11690 cfg->evt_handler[WLC_E_PFN_SWC] = wl_notify_gscan_event;
11691 cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event;
11692 cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event;
11693 #endif /* GSCAN_SUPPORT */
11695 cfg->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
11696 #endif /* WLTDLS */
11697 cfg->evt_handler[WLC_E_BSSID] = wl_notify_roaming_status;
11699 cfg->evt_handler[WLC_E_RMC_EVENT] = wl_notify_rmc_status;
11701 #ifdef BT_WIFI_HANDOVER
11702 cfg->evt_handler[WLC_E_BT_WIFI_HANDOVER_REQ] = wl_notify_bt_wifi_handover_req;
11705 cfg->evt_handler[WLC_E_NAN] = wl_cfgnan_notify_nan_status;
11706 cfg->evt_handler[WLC_E_PROXD] = wl_cfgnan_notify_proxd_status;
11707 #endif /* WL_NAN */
11708 cfg->evt_handler[WLC_E_CSA_COMPLETE_IND] = wl_csa_complete_ind;
11709 #ifdef DHD_LOSSLESS_ROAMING
11710 cfg->evt_handler[WLC_E_ROAM_PREP] = wl_notify_roam_prep_status;
11712 cfg->evt_handler[WLC_E_AP_STARTED] = wl_ap_start_ind;
11713 #ifdef CUSTOM_EVENT_PM_WAKE
11714 cfg->evt_handler[WLC_E_EXCESS_PM_WAKE_EVENT] = wl_check_pmstatus;
11715 #endif /* CUSTOM_EVENT_PM_WAKE */
11716 cfg->evt_handler[WLC_E_PSK_SUP] = wl_notify_idsup_status;
11719 #if defined(STATIC_WL_PRIV_STRUCT)
11721 wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
11723 cfg->escan_info.escan_buf = DHD_OS_PREALLOC(cfg->pub,
11724 DHD_PREALLOC_WIPHY_ESCAN0, ESCAN_BUF_SIZE);
11725 bzero(cfg->escan_info.escan_buf, ESCAN_BUF_SIZE);
11729 wl_deinit_escan_result_buf(struct bcm_cfg80211 *cfg)
11731 cfg->escan_info.escan_buf = NULL;
11734 #endif /* STATIC_WL_PRIV_STRUCT */
11736 static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg)
11738 WL_DBG(("Enter \n"));
11740 cfg->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
11741 if (unlikely(!cfg->scan_results)) {
11742 WL_ERR(("Scan results alloc failed\n"));
11743 goto init_priv_mem_out;
11745 cfg->conf = (void *)kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
11746 if (unlikely(!cfg->conf)) {
11747 WL_ERR(("wl_conf alloc failed\n"));
11748 goto init_priv_mem_out;
11750 cfg->scan_req_int =
11751 (void *)kzalloc(sizeof(*cfg->scan_req_int), GFP_KERNEL);
11752 if (unlikely(!cfg->scan_req_int)) {
11753 WL_ERR(("Scan req alloc failed\n"));
11754 goto init_priv_mem_out;
11756 cfg->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
11757 if (unlikely(!cfg->ioctl_buf)) {
11758 WL_ERR(("Ioctl buf alloc failed\n"));
11759 goto init_priv_mem_out;
11761 cfg->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
11762 if (unlikely(!cfg->escan_ioctl_buf)) {
11763 WL_ERR(("Ioctl buf alloc failed\n"));
11764 goto init_priv_mem_out;
11766 cfg->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
11767 if (unlikely(!cfg->extra_buf)) {
11768 WL_ERR(("Extra buf alloc failed\n"));
11769 goto init_priv_mem_out;
11771 cfg->pmk_list = (void *)kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
11772 if (unlikely(!cfg->pmk_list)) {
11773 WL_ERR(("pmk list alloc failed\n"));
11774 goto init_priv_mem_out;
11776 #if defined(STATIC_WL_PRIV_STRUCT)
11777 cfg->conn_info = (void *)kzalloc(sizeof(*cfg->conn_info), GFP_KERNEL);
11778 if (unlikely(!cfg->conn_info)) {
11779 WL_ERR(("cfg->conn_info alloc failed\n"));
11780 goto init_priv_mem_out;
11782 cfg->ie = (void *)kzalloc(sizeof(*cfg->ie), GFP_KERNEL);
11783 if (unlikely(!cfg->ie)) {
11784 WL_ERR(("cfg->ie alloc failed\n"));
11785 goto init_priv_mem_out;
11787 wl_init_escan_result_buf(cfg);
11788 #endif /* STATIC_WL_PRIV_STRUCT */
11789 cfg->afx_hdl = (void *)kzalloc(sizeof(*cfg->afx_hdl), GFP_KERNEL);
11790 if (unlikely(!cfg->afx_hdl)) {
11791 WL_ERR(("afx hdl alloc failed\n"));
11792 goto init_priv_mem_out;
11794 init_completion(&cfg->act_frm_scan);
11795 init_completion(&cfg->wait_next_af);
11797 INIT_WORK(&cfg->afx_hdl->work, wl_cfg80211_afx_handler);
11800 if (cfg->tdls_mgmt_frame) {
11801 kfree(cfg->tdls_mgmt_frame);
11802 cfg->tdls_mgmt_frame = NULL;
11804 #endif /* WLTDLS */
11808 wl_deinit_priv_mem(cfg);
11813 static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg)
11815 kfree(cfg->scan_results);
11816 cfg->scan_results = NULL;
11819 kfree(cfg->scan_req_int);
11820 cfg->scan_req_int = NULL;
11821 kfree(cfg->ioctl_buf);
11822 cfg->ioctl_buf = NULL;
11823 kfree(cfg->escan_ioctl_buf);
11824 cfg->escan_ioctl_buf = NULL;
11825 kfree(cfg->extra_buf);
11826 cfg->extra_buf = NULL;
11827 kfree(cfg->pmk_list);
11828 cfg->pmk_list = NULL;
11829 #if defined(STATIC_WL_PRIV_STRUCT)
11830 kfree(cfg->conn_info);
11831 cfg->conn_info = NULL;
11834 wl_deinit_escan_result_buf(cfg);
11835 #endif /* STATIC_WL_PRIV_STRUCT */
11836 if (cfg->afx_hdl) {
11837 cancel_work_sync(&cfg->afx_hdl->work);
11838 kfree(cfg->afx_hdl);
11839 cfg->afx_hdl = NULL;
11844 static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg)
11847 WL_DBG(("Enter \n"));
11849 /* Do not use DHD in cfg driver */
11850 cfg->event_tsk.thr_pid = -1;
11852 PROC_START(wl_event_handler, cfg, &cfg->event_tsk, 0, "wl_event_handler");
11853 if (cfg->event_tsk.thr_pid < 0)
11858 static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg)
11860 if (cfg->event_tsk.thr_pid >= 0)
11861 PROC_STOP(&cfg->event_tsk);
11864 void wl_terminate_event_handler(void)
11866 struct bcm_cfg80211 *cfg = g_bcm_cfg;
11869 wl_destroy_event_handler(cfg);
11874 static void wl_scan_timeout(unsigned long data)
11876 wl_event_msg_t msg;
11877 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
11878 struct wireless_dev *wdev = NULL;
11879 struct net_device *ndev = NULL;
11880 struct wl_scan_results *bss_list;
11881 struct wl_bss_info *bi = NULL;
11884 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
11885 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11886 uint32 prev_memdump_mode = dhdp->memdump_enabled;
11887 #endif /* DHD_DEBUG && BCMPCIE */
11889 if (!(cfg->scan_request)) {
11890 WL_ERR(("timer expired but no scan request\n"));
11894 bss_list = wl_escan_get_buf(cfg, FALSE);
11896 WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
11898 WL_ERR(("scanned AP count (%d)\n", bss_list->count));
11900 bi = next_bss(bss_list, bi);
11901 for_each_bss(bss_list, bi, i) {
11902 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
11903 WL_ERR(("SSID :%s Channel :%d\n", bi->SSID, channel));
11907 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
11908 if (cfg->scan_request->dev)
11909 wdev = cfg->scan_request->dev->ieee80211_ptr;
11911 wdev = cfg->scan_request->wdev;
11912 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
11914 WL_ERR(("No wireless_dev present\n"));
11917 ndev = wdev_to_wlc_ndev(wdev, cfg);
11919 bzero(&msg, sizeof(wl_event_msg_t));
11920 WL_ERR(("timer expired\n"));
11921 #if defined(DHD_DEBUG) && defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
11922 if (dhdp->memdump_enabled) {
11923 dhdp->memdump_enabled = DUMP_MEMFILE;
11924 dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
11925 dhd_bus_mem_dump(dhdp);
11926 dhdp->memdump_enabled = prev_memdump_mode;
11928 #endif /* DHD_DEBUG && BCMPCIE */
11929 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
11930 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
11931 msg.reason = 0xFFFFFFFF;
11932 wl_cfg80211_event(ndev, &msg, NULL);
11933 #ifdef CUSTOMER_HW4_DEBUG
11934 if (!wl_scan_timeout_dbg_enabled)
11935 wl_scan_timeout_dbg_set();
11936 #endif /* CUSTOMER_HW4_DEBUG */
11938 // terence 20130729: workaround to fix out of memory in firmware
11939 // if (dhd_conf_get_chip(dhd_get_pub(dev)) == BCM43362_CHIP_ID) {
11940 // WL_ERR(("Send hang event\n"));
11941 // net_os_send_hang_message(dev);
11945 #ifdef DHD_LOSSLESS_ROAMING
11946 static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg)
11948 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11950 /* restore prec_map to ALLPRIO */
11951 dhdp->dequeue_prec_map = ALLPRIO;
11952 if (timer_pending(&cfg->roam_timeout)) {
11953 del_timer_sync(&cfg->roam_timeout);
11958 static void wl_roam_timeout(unsigned long data)
11960 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
11961 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11963 WL_ERR(("roam timer expired\n"));
11965 /* restore prec_map to ALLPRIO */
11966 dhdp->dequeue_prec_map = ALLPRIO;
11969 #endif /* DHD_LOSSLESS_ROAMING */
11972 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
11973 unsigned long state, void *ptr)
11975 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
11976 struct net_device *dev = ptr;
11978 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
11979 #endif /* LINUX_VERSION < VERSION(3, 11, 0) */
11980 struct wireless_dev *wdev = ndev_to_wdev(dev);
11981 struct bcm_cfg80211 *cfg = g_bcm_cfg;
11984 WL_ERR(("Enter \n"));
11987 if (!wdev || !cfg || dev == bcmcfg_to_prmry_ndev(cfg))
11988 return NOTIFY_DONE;
11993 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
11994 int max_wait_timeout = 2;
11995 int max_wait_count = 100;
11997 unsigned long limit = jiffies + max_wait_timeout * HZ;
11999 WL_ERR(("NETDEV_DOWN(+) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12001 while (work_pending(&wdev->cleanup_work)) {
12002 if (refcnt%5 == 0) {
12003 WL_ERR(("[NETDEV_DOWN] wait for "
12004 "complete of cleanup_work"
12005 " (%d th)\n", refcnt));
12007 if (!time_before(jiffies, limit)) {
12008 WL_ERR(("[NETDEV_DOWN] cleanup_work"
12009 " of CFG80211 is not"
12010 " completed in %d sec\n",
12011 max_wait_timeout));
12014 if (refcnt >= max_wait_count) {
12015 WL_ERR(("[NETDEV_DOWN] cleanup_work"
12016 " of CFG80211 is not"
12017 " completed in %d loop\n",
12021 set_current_state(TASK_INTERRUPTIBLE);
12022 (void)schedule_timeout(100);
12023 set_current_state(TASK_RUNNING);
12027 WL_ERR(("NETDEV_DOWN(-) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12029 #endif /* LINUX_VERSION < VERSION(3, 14, 0) */
12032 case NETDEV_UNREGISTER:
12034 WL_ERR(("NETDEV_UNREGISTER(+) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12036 /* after calling list_del_rcu(&wdev->list) */
12037 wl_cfg80211_clear_per_bss_ies(cfg,
12038 wl_get_bssidx_by_wdev(cfg, wdev));
12039 wl_dealloc_netinfo_by_wdev(cfg, wdev);
12041 WL_ERR(("NETDEV_UNREGISTER(-) wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12044 case NETDEV_GOING_DOWN:
12046 * At NETDEV_DOWN state, wdev_cleanup_work work will be called.
12047 * In front of door, the function checks whether current scan
12048 * is working or not. If the scanning is still working,
12049 * wdev_cleanup_work call WARN_ON and make the scan done forcibly.
12052 WL_ERR(("NETDEV_GOING_DOWN wdev=%p, cfg=%p, dev=%p\n", wdev, cfg, dev));
12054 if (wl_get_drv_status(cfg, SCANNING, dev))
12055 wl_notify_escan_complete(cfg, dev, true, true);
12058 return NOTIFY_DONE;
12061 static struct notifier_block wl_cfg80211_netdev_notifier = {
12062 .notifier_call = wl_cfg80211_netdev_notifier_call,
12066 * to make sure we won't register the same notifier twice, otherwise a loop is likely to be
12067 * created in kernel notifier link list (with 'next' pointing to itself)
12069 static bool wl_cfg80211_netdev_notifier_registered = FALSE;
12071 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg)
12073 struct wireless_dev *wdev = NULL;
12074 struct net_device *ndev = NULL;
12076 if (!cfg->scan_request)
12079 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
12080 if (cfg->scan_request->dev)
12081 wdev = cfg->scan_request->dev->ieee80211_ptr;
12083 wdev = cfg->scan_request->wdev;
12084 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
12087 WL_ERR(("No wireless_dev present\n"));
12091 ndev = wdev_to_wlc_ndev(wdev, cfg);
12092 wl_notify_escan_complete(cfg, ndev, true, true);
12093 WL_ERR(("Scan aborted! \n"));
12096 static void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
12098 wl_scan_params_t *params = NULL;
12099 s32 params_size = 0;
12101 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
12102 if (!in_atomic()) {
12103 /* Our scan params only need space for 1 channel and 0 ssids */
12104 params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size);
12105 if (params == NULL) {
12106 WL_ERR(("scan params allocation failed \n"));
12109 /* Do a scan abort to stop the driver's scan engine */
12110 err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true);
12112 WL_ERR(("scan abort failed \n"));
12118 if (cfg->tdls_mgmt_frame) {
12119 kfree(cfg->tdls_mgmt_frame);
12120 cfg->tdls_mgmt_frame = NULL;
12122 #endif /* WLTDLS */
12125 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
12126 struct net_device *ndev,
12127 bool aborted, bool fw_abort)
12130 unsigned long flags;
12131 struct net_device *dev;
12133 WL_DBG(("Enter \n"));
12135 mutex_lock(&cfg->scan_complete);
12138 WL_ERR(("ndev is null\n"));
12143 if (cfg->escan_info.ndev != ndev) {
12144 WL_ERR(("ndev is different %p %p\n", cfg->escan_info.ndev, ndev));
12149 if (cfg->scan_request) {
12150 dev = bcmcfg_to_prmry_ndev(cfg);
12151 #if defined(WL_ENABLE_P2P_IF)
12152 if (cfg->scan_request->dev != cfg->p2p_net)
12153 dev = cfg->scan_request->dev;
12154 #elif defined(WL_CFG80211_P2P_DEV_IF)
12155 if (cfg->scan_request->wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) {
12157 WL_ERR(("%s: dev: %p\n", __FUNCTION__, cfg->scan_request->wdev->netdev));
12159 dev = cfg->scan_request->wdev->netdev;
12161 #endif /* WL_ENABLE_P2P_IF */
12164 WL_DBG(("cfg->scan_request is NULL may be internal scan."
12165 "doing scan_abort for ndev %p primary %p",
12166 ndev, bcmcfg_to_prmry_ndev(cfg)));
12169 if (fw_abort && !in_atomic())
12170 wl_cfg80211_scan_abort(cfg);
12171 if (timer_pending(&cfg->scan_timeout))
12172 del_timer_sync(&cfg->scan_timeout);
12173 #if defined(ESCAN_RESULT_PATCH)
12174 if (likely(cfg->scan_request)) {
12175 cfg->bss_list = wl_escan_get_buf(cfg, aborted);
12176 wl_inform_bss(cfg);
12178 #endif /* ESCAN_RESULT_PATCH */
12179 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
12180 #ifdef WL_SCHED_SCAN
12181 if (cfg->sched_scan_req && !cfg->scan_request) {
12182 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
12184 cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy);
12185 cfg->sched_scan_running = FALSE;
12186 cfg->sched_scan_req = NULL;
12188 #endif /* WL_SCHED_SCAN */
12189 if (likely(cfg->scan_request)) {
12190 cfg80211_scan_done(cfg->scan_request, aborted);
12191 cfg->scan_request = NULL;
12192 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
12193 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
12195 if (p2p_is_on(cfg))
12196 wl_clr_p2p_status(cfg, SCANNING);
12197 wl_clr_drv_status(cfg, SCANNING, dev);
12198 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
12201 mutex_unlock(&cfg->scan_complete);
12205 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12207 wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
12210 for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
12211 int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
12212 if (bss->RSSI < candidate[idx].RSSI) {
12214 memcpy(&candidate[idx + 1], &candidate[idx],
12215 sizeof(removal_element_t) * len);
12216 candidate[idx].RSSI = bss->RSSI;
12217 candidate[idx].length = bss->length;
12218 memcpy(&candidate[idx].BSSID, &bss->BSSID, ETHER_ADDR_LEN);
12225 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
12229 int total_delete_len = 0;
12230 for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
12231 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
12232 wl_bss_info_t *bss = NULL;
12233 if (candidate[idx1].RSSI >= bi->RSSI)
12235 for (idx2 = 0; idx2 < list->count; idx2++) {
12236 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
12238 if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
12239 candidate[idx1].RSSI == bss->RSSI &&
12240 candidate[idx1].length == dtoh32(bss->length)) {
12241 u32 delete_len = dtoh32(bss->length);
12242 WL_DBG(("delete scan info of " MACDBG " to add new AP\n",
12243 MAC2STRDBG(bss->BSSID.octet)));
12244 if (idx2 < list->count -1) {
12245 memmove((u8 *)bss, (u8 *)bss + delete_len,
12246 list->buflen - cur_len - delete_len);
12248 list->buflen -= delete_len;
12250 total_delete_len += delete_len;
12251 /* if delete_len is greater than or equal to result length */
12252 if (total_delete_len >= bi->length) {
12257 cur_len += dtoh32(bss->length);
12261 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12263 static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12264 const wl_event_msg_t *e, void *data)
12267 s32 status = ntoh32(e->status);
12269 wl_escan_result_t *escan_result;
12270 wl_bss_info_t *bss = NULL;
12271 wl_scan_results_t *list;
12272 wifi_p2p_ie_t * p2p_ie;
12273 struct net_device *ndev = NULL;
12276 u8 *p2p_dev_addr = NULL;
12278 struct ieee80211_supported_band *band;
12280 WL_DBG((" enter event type : %d, status : %d \n",
12281 ntoh32(e->event_type), ntoh32(e->status)));
12283 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12285 mutex_lock(&cfg->usr_sync);
12286 /* P2P SCAN is coming from primary interface */
12287 if (wl_get_p2p_status(cfg, SCANNING)) {
12288 if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
12289 ndev = cfg->afx_hdl->dev;
12291 ndev = cfg->escan_info.ndev;
12294 if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
12295 WL_ERR(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n",
12296 ndev, wl_get_drv_status(cfg, SCANNING, ndev),
12297 ntoh32(e->event_type), ntoh32(e->status)));
12300 escan_result = (wl_escan_result_t *)data;
12302 if (status == WLC_E_STATUS_PARTIAL) {
12303 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
12304 if (!escan_result) {
12305 WL_ERR(("Invalid escan result (NULL pointer)\n"));
12308 if (dtoh16(escan_result->bss_count) != 1) {
12309 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
12312 bi = escan_result->bss_info;
12314 WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
12317 bi_length = dtoh32(bi->length);
12318 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
12319 WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
12323 /* +++++ terence 20130524: skip invalid bss */
12325 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
12326 if (channel <= CH_MAX_2G_CHANNEL)
12327 band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
12329 band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_5GHZ];
12331 WL_ERR(("No valid band\n"));
12334 if (!dhd_conf_match_channel(cfg->pub, channel))
12336 /* ----- terence 20130524: skip invalid bss */
12338 if (wl_escan_check_sync_id(status, escan_result->sync_id,
12339 cfg->escan_info.cur_sync_id) < 0)
12342 if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
12343 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
12344 WL_DBG(("Ignoring IBSS result\n"));
12349 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12350 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
12351 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
12352 cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
12353 s32 channel = wf_chspec_ctlchan(
12354 wl_chspec_driver_to_host(bi->chanspec));
12356 if ((channel > MAXCHANNEL) || (channel <= 0))
12357 channel = WL_INVALID;
12359 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
12361 MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
12364 wl_clr_p2p_status(cfg, SCANNING);
12365 cfg->afx_hdl->peer_chan = channel;
12366 complete(&cfg->act_frm_scan);
12371 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
12372 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12373 removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
12374 int remove_lower_rssi = FALSE;
12376 bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
12377 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12379 list = wl_escan_get_buf(cfg, FALSE);
12380 if (scan_req_match(cfg)) {
12381 /* p2p scan && allow only probe response */
12382 if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
12383 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
12385 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
12386 bi->ie_length)) == NULL) {
12387 WL_ERR(("Couldn't find P2PIE in probe"
12388 " response/beacon\n"));
12392 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12393 if (bi_length > ESCAN_BUF_SIZE - list->buflen)
12394 remove_lower_rssi = TRUE;
12395 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12397 WL_SCAN(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID,
12398 MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length));
12399 for (i = 0; i < list->count; i++) {
12400 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
12402 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12403 WL_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
12404 bss->SSID, MAC2STRDBG(bss->BSSID.octet),
12405 i, bss->RSSI, list->count));
12407 if (remove_lower_rssi)
12408 wl_cfg80211_find_removal_candidate(bss, candidate);
12409 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12411 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
12412 (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
12413 == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
12414 bi->SSID_len == bss->SSID_len &&
12415 !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
12417 /* do not allow beacon data to update
12418 *the data recd from a probe response
12420 if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
12421 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
12424 WL_SCAN(("%s("MACDBG"), i=%d prev: RSSI %d"
12425 " flags 0x%x, new: RSSI %d flags 0x%x\n",
12426 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
12427 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
12429 if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
12430 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
12431 /* preserve max RSSI if the measurements are
12432 * both on-channel or both off-channel
12434 WL_SCAN(("%s("MACDBG"), same onchan"
12435 ", RSSI: prev %d new %d\n",
12436 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12437 bss->RSSI, bi->RSSI));
12438 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
12439 } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
12440 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
12441 /* preserve the on-channel rssi measurement
12442 * if the new measurement is off channel
12444 WL_SCAN(("%s("MACDBG"), prev onchan"
12445 ", RSSI: prev %d new %d\n",
12446 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12447 bss->RSSI, bi->RSSI));
12448 bi->RSSI = bss->RSSI;
12449 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
12451 if (dtoh32(bss->length) != bi_length) {
12452 u32 prev_len = dtoh32(bss->length);
12454 WL_SCAN(("bss info replacement"
12455 " is occured(bcast:%d->probresp%d)\n",
12456 bss->ie_length, bi->ie_length));
12457 WL_SCAN(("%s("MACDBG"), replacement!(%d -> %d)\n",
12458 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
12459 prev_len, bi_length));
12461 if (list->buflen - prev_len + bi_length
12462 > ESCAN_BUF_SIZE) {
12463 WL_ERR(("Buffer is too small: keep the"
12464 " previous result of this AP\n"));
12465 /* Only update RSSI */
12466 bss->RSSI = bi->RSSI;
12467 bss->flags |= (bi->flags
12468 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
12472 if (i < list->count - 1) {
12473 /* memory copy required by this case only */
12474 memmove((u8 *)bss + bi_length,
12475 (u8 *)bss + prev_len,
12476 list->buflen - cur_len - prev_len);
12478 list->buflen -= prev_len;
12479 list->buflen += bi_length;
12481 list->version = dtoh32(bi->version);
12482 memcpy((u8 *)bss, (u8 *)bi, bi_length);
12485 cur_len += dtoh32(bss->length);
12487 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
12488 #ifdef ESCAN_BUF_OVERFLOW_MGMT
12489 wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
12490 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
12491 WL_DBG(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
12492 MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
12496 WL_ERR(("Buffer is too small: ignoring\n"));
12498 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
12501 memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
12502 list->version = dtoh32(bi->version);
12503 list->buflen += bi_length;
12507 * !Broadcast && number of ssid = 1 && number of channels =1
12508 * means specific scan to association
12510 if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
12511 WL_ERR(("P2P assoc scan fast aborted.\n"));
12512 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, false, true);
12517 else if (status == WLC_E_STATUS_SUCCESS) {
12518 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12519 wl_escan_print_sync_id(status, cfg->escan_info.cur_sync_id,
12520 escan_result->sync_id);
12522 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12523 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12524 wl_clr_p2p_status(cfg, SCANNING);
12525 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12526 if (cfg->afx_hdl->peer_chan == WL_INVALID)
12527 complete(&cfg->act_frm_scan);
12528 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12529 WL_INFORM(("ESCAN COMPLETED\n"));
12530 cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
12531 if (!scan_req_match(cfg)) {
12532 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
12533 cfg->bss_list->count));
12535 wl_inform_bss(cfg);
12536 wl_notify_escan_complete(cfg, ndev, false, false);
12538 wl_escan_increment_sync_id(cfg, SCAN_BUF_NEXT);
12539 #ifdef CUSTOMER_HW4_DEBUG
12540 if (wl_scan_timeout_dbg_enabled)
12541 wl_scan_timeout_dbg_clear();
12542 #endif /* CUSTOMER_HW4_DEBUG */
12543 } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
12544 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
12545 (status == WLC_E_STATUS_NEWASSOC)) {
12546 /* Handle all cases of scan abort */
12547 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12548 wl_escan_print_sync_id(status, escan_result->sync_id,
12549 cfg->escan_info.cur_sync_id);
12550 WL_DBG(("ESCAN ABORT reason: %d\n", status));
12551 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12552 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12553 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12554 wl_clr_p2p_status(cfg, SCANNING);
12555 if (cfg->afx_hdl->peer_chan == WL_INVALID)
12556 complete(&cfg->act_frm_scan);
12557 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12558 WL_INFORM(("ESCAN ABORTED\n"));
12559 cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
12560 if (!scan_req_match(cfg)) {
12561 WL_TRACE_HW4(("scan_req_match=0: scanned AP count=%d\n",
12562 cfg->bss_list->count));
12564 wl_inform_bss(cfg);
12565 wl_notify_escan_complete(cfg, ndev, true, false);
12567 /* If there is no pending host initiated scan, do nothing */
12568 WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
12570 wl_escan_increment_sync_id(cfg, SCAN_BUF_CNT);
12571 } else if (status == WLC_E_STATUS_TIMEOUT) {
12572 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
12573 WL_ERR(("reason[0x%x]\n", e->reason));
12574 if (e->reason == 0xFFFFFFFF) {
12575 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
12578 WL_ERR(("unexpected Escan Event %d : abort\n", status));
12579 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12580 wl_escan_print_sync_id(status, escan_result->sync_id,
12581 cfg->escan_info.cur_sync_id);
12582 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
12583 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
12584 wl_clr_p2p_status(cfg, SCANNING);
12585 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
12586 if (cfg->afx_hdl->peer_chan == WL_INVALID)
12587 complete(&cfg->act_frm_scan);
12588 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
12589 cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
12590 if (!scan_req_match(cfg)) {
12591 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
12592 "scanned AP count=%d\n",
12593 cfg->bss_list->count));
12595 wl_inform_bss(cfg);
12596 wl_notify_escan_complete(cfg, ndev, true, false);
12598 wl_escan_increment_sync_id(cfg, 2);
12601 mutex_unlock(&cfg->usr_sync);
12605 static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211 *cfg, int enable)
12607 u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
12608 bool p2p_connected = wl_cfgp2p_vif_created(cfg);
12609 struct net_info *iter, *next;
12611 if (!cfg->roamoff_on_concurrent)
12613 if (enable && (p2p_connected||(connected_cnt > 1))) {
12614 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12615 4 && __GNUC_MINOR__ >= 6))
12616 _Pragma("GCC diagnostic push")
12617 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12619 for_each_ndev(cfg, iter, next) {
12620 if (iter->ndev && iter->wdev &&
12621 iter->wdev->iftype == NL80211_IFTYPE_STATION) {
12622 if (wldev_iovar_setint(iter->ndev, "roam_off", TRUE)
12624 iter->roam_off = TRUE;
12627 WL_ERR(("error to enable roam_off\n"));
12631 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12632 4 && __GNUC_MINOR__ >= 6))
12633 _Pragma("GCC diagnostic pop")
12636 else if (!enable) {
12637 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12638 4 && __GNUC_MINOR__ >= 6))
12639 _Pragma("GCC diagnostic push")
12640 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12642 for_each_ndev(cfg, iter, next) {
12643 if (iter->ndev && iter->wdev &&
12644 iter->wdev->iftype == NL80211_IFTYPE_STATION) {
12645 if (iter->roam_off != WL_INVALID) {
12646 if (wldev_iovar_setint(iter->ndev, "roam_off", FALSE)
12648 iter->roam_off = FALSE;
12651 WL_ERR(("error to disable roam_off\n"));
12656 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12657 4 && __GNUC_MINOR__ >= 6))
12658 _Pragma("GCC diagnostic pop")
12664 static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211 *cfg)
12666 struct net_info *iter, *next;
12669 u32 pre_ctl_chan = 0;
12670 u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
12671 cfg->vsdb_mode = false;
12673 if (connected_cnt <= 1) {
12676 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12677 4 && __GNUC_MINOR__ >= 6))
12678 _Pragma("GCC diagnostic push")
12679 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
12681 for_each_ndev(cfg, iter, next) {
12682 /* p2p discovery iface ndev could be null */
12686 if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
12687 if (wldev_iovar_getint(iter->ndev, "chanspec",
12688 (s32 *)&chanspec) == BCME_OK) {
12689 chanspec = wl_chspec_driver_to_host(chanspec);
12690 ctl_chan = wf_chspec_ctlchan(chanspec);
12691 wl_update_prof(cfg, iter->ndev, NULL,
12692 &ctl_chan, WL_PROF_CHAN);
12694 if (!cfg->vsdb_mode) {
12695 if (!pre_ctl_chan && ctl_chan)
12696 pre_ctl_chan = ctl_chan;
12697 else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
12698 cfg->vsdb_mode = true;
12704 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
12705 4 && __GNUC_MINOR__ >= 6))
12706 _Pragma("GCC diagnostic pop")
12708 printf("%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel");
12712 #if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF)
12713 extern int g_frameburst;
12714 #endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */
12716 static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
12717 enum wl_status state, bool set)
12723 struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
12724 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
12725 if (dhd->busstate == DHD_BUS_DOWN) {
12726 WL_ERR(("%s : busstate is DHD_BUS_DOWN!\n", __FUNCTION__));
12729 WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
12730 state, set, _net_info->pm_restore, _net_info->ndev->name));
12732 if (state != WL_STATUS_CONNECTED)
12734 mode = wl_get_mode_by_netdev(cfg, _net_info->ndev);
12736 wl_cfg80211_concurrent_roam(cfg, 1);
12737 wl_cfg80211_determine_vsdb_mode(cfg);
12738 if (mode == WL_MODE_AP) {
12739 if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
12740 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
12744 if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, &pm,
12745 sizeof(pm), true)) != 0) {
12746 if (err == -ENODEV)
12747 WL_DBG(("%s:netdev not ready\n",
12748 _net_info->ndev->name));
12750 WL_ERR(("%s:error (%d)\n",
12751 _net_info->ndev->name, err));
12753 wl_cfg80211_update_power_mode(_net_info->ndev);
12755 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_SHORT);
12756 #if defined(WLTDLS)
12757 if (wl_cfg80211_is_concurrent_mode()) {
12758 err = wldev_iovar_setint(primary_dev, "tdls_enable", 0);
12760 #endif /* defined(WLTDLS) */
12762 #ifdef DISABLE_FRAMEBURST_VSDB
12763 #ifdef USE_WFA_CERT_CONF
12765 #endif /* USE_WFA_CERT_CONF */
12767 if (wl_cfg80211_is_concurrent_mode()) {
12768 int frameburst = 0;
12769 if (wldev_ioctl(primary_dev, WLC_SET_FAKEFRAG, &frameburst,
12770 sizeof(frameburst), true) != 0) {
12771 WL_DBG(("frameburst set error\n"));
12773 WL_DBG(("Frameburst Disabled\n"));
12776 #endif /* DISABLE_FRAMEBURST_VSDB */
12777 } else { /* clear */
12779 /* clear chan information when the net device is disconnected */
12780 wl_update_prof(cfg, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
12781 wl_cfg80211_determine_vsdb_mode(cfg);
12782 if (primary_dev == _net_info->ndev) {
12784 if ((err = wldev_ioctl(_net_info->ndev, WLC_SET_PM, &pm,
12785 sizeof(pm), true)) != 0) {
12786 if (err == -ENODEV)
12787 WL_DBG(("%s:netdev not ready\n",
12788 _net_info->ndev->name));
12790 WL_ERR(("%s:error (%d)\n",
12791 _net_info->ndev->name, err));
12793 wl_cfg80211_update_power_mode(_net_info->ndev);
12797 wl_cfg80211_concurrent_roam(cfg, 0);
12798 #if defined(WLTDLS)
12799 if (!wl_cfg80211_is_concurrent_mode()) {
12800 err = wldev_iovar_setint(primary_dev, "tdls_enable", 1);
12802 #endif /* defined(WLTDLS) */
12804 #ifdef DISABLE_FRAMEBURST_VSDB
12805 #ifdef USE_WFA_CERT_CONF
12807 #endif /* USE_WFA_CERT_CONF */
12809 int frameburst = 1;
12810 if (wldev_ioctl(primary_dev, WLC_SET_FAKEFRAG, &frameburst,
12811 sizeof(frameburst), true) != 0) {
12812 WL_DBG(("frameburst set error\n"));
12814 WL_DBG(("Frameburst Enabled\n"));
12816 #endif /* DISABLE_FRAMEBURST_VSDB */
12820 static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
12824 cfg->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
12825 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
12826 wl_escan_init_sync_id(cfg);
12828 /* Init scan_timeout timer */
12829 init_timer(&cfg->scan_timeout);
12830 cfg->scan_timeout.data = (unsigned long) cfg;
12831 cfg->scan_timeout.function = wl_scan_timeout;
12836 #ifdef DHD_LOSSLESS_ROAMING
12837 static s32 wl_init_roam_timeout(struct bcm_cfg80211 *cfg)
12841 /* Init roam timer */
12842 init_timer(&cfg->roam_timeout);
12843 cfg->roam_timeout.data = (unsigned long) cfg;
12844 cfg->roam_timeout.function = wl_roam_timeout;
12848 #endif /* DHD_LOSSLESS_ROAMING */
12850 static s32 wl_init_priv(struct bcm_cfg80211 *cfg)
12852 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
12853 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
12856 cfg->scan_request = NULL;
12857 cfg->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
12858 cfg->roam_on = false;
12859 cfg->active_scan = true;
12860 cfg->rf_blocked = false;
12861 cfg->vsdb_mode = false;
12862 #if defined(BCMSDIO)
12863 cfg->wlfc_on = false;
12865 cfg->roamoff_on_concurrent = true;
12866 cfg->disable_roam_event = false;
12867 cfg->cfgdev_bssidx = -1;
12868 /* register interested state */
12869 set_bit(WL_STATUS_CONNECTED, &cfg->interrested_state);
12870 spin_lock_init(&cfg->cfgdrv_lock);
12871 mutex_init(&cfg->ioctl_buf_sync);
12872 init_waitqueue_head(&cfg->netif_change_event);
12873 init_completion(&cfg->send_af_done);
12874 init_completion(&cfg->iface_disable);
12876 err = wl_init_priv_mem(cfg);
12879 if (wl_create_event_handler(cfg))
12881 wl_init_event_handler(cfg);
12882 mutex_init(&cfg->usr_sync);
12883 mutex_init(&cfg->event_sync);
12884 mutex_init(&cfg->scan_complete);
12885 err = wl_init_scan(cfg);
12888 #ifdef DHD_LOSSLESS_ROAMING
12889 err = wl_init_roam_timeout(cfg);
12893 #endif /* DHD_LOSSLESS_ROAMING */
12894 wl_init_conf(cfg->conf);
12895 wl_init_prof(cfg, ndev);
12897 DNGL_FUNC(dhd_cfg80211_init, (cfg));
12902 static void wl_deinit_priv(struct bcm_cfg80211 *cfg)
12904 DNGL_FUNC(dhd_cfg80211_deinit, (cfg));
12905 wl_destroy_event_handler(cfg);
12908 del_timer_sync(&cfg->scan_timeout);
12909 #ifdef DHD_LOSSLESS_ROAMING
12910 del_timer_sync(&cfg->roam_timeout);
12912 wl_deinit_priv_mem(cfg);
12913 if (wl_cfg80211_netdev_notifier_registered) {
12914 wl_cfg80211_netdev_notifier_registered = FALSE;
12915 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
12919 #if defined(WL_ENABLE_P2P_IF)
12920 static s32 wl_cfg80211_attach_p2p(void)
12922 struct bcm_cfg80211 *cfg = g_bcm_cfg;
12924 WL_TRACE(("Enter \n"));
12926 if (wl_cfgp2p_register_ndev(cfg) < 0) {
12927 WL_ERR(("P2P attach failed. \n"));
12934 static s32 wl_cfg80211_detach_p2p(void)
12936 struct bcm_cfg80211 *cfg = g_bcm_cfg;
12937 struct wireless_dev *wdev;
12939 WL_DBG(("Enter \n"));
12941 WL_ERR(("Invalid Ptr\n"));
12944 wdev = cfg->p2p_wdev;
12947 WL_ERR(("Invalid Ptr\n"));
12951 wl_cfgp2p_unregister_ndev(cfg);
12953 cfg->p2p_wdev = NULL;
12954 cfg->p2p_net = NULL;
12955 WL_DBG(("Freeing 0x%p \n", wdev));
12962 s32 wl_cfg80211_attach_post(struct net_device *ndev)
12964 struct bcm_cfg80211 * cfg = NULL;
12967 WL_TRACE(("In\n"));
12968 if (unlikely(!ndev)) {
12969 WL_ERR(("ndev is invaild\n"));
12973 if (unlikely(!cfg)) {
12974 WL_ERR(("cfg is invaild\n"));
12977 if (!wl_get_drv_status(cfg, READY, ndev)) {
12979 ret = wl_cfgp2p_supported(cfg, ndev);
12981 #if !defined(WL_ENABLE_P2P_IF)
12982 cfg->wdev->wiphy->interface_modes |=
12983 (BIT(NL80211_IFTYPE_P2P_CLIENT)|
12984 BIT(NL80211_IFTYPE_P2P_GO));
12985 #endif /* !WL_ENABLE_P2P_IF */
12986 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
12989 #if defined(WL_ENABLE_P2P_IF)
12990 if (cfg->p2p_net) {
12991 /* Update MAC addr for p2p0 interface here. */
12992 memcpy(cfg->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
12993 cfg->p2p_net->dev_addr[0] |= 0x02;
12994 printf("%s: p2p_dev_addr="MACDBG "\n",
12995 cfg->p2p_net->name,
12996 MAC2STRDBG(cfg->p2p_net->dev_addr));
12998 WL_ERR(("p2p_net not yet populated."
12999 " Couldn't update the MAC Address for p2p0 \n"));
13002 #endif /* WL_ENABLE_P2P_IF */
13003 cfg->p2p_supported = true;
13004 } else if (ret == 0) {
13005 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
13008 /* SDIO bus timeout */
13014 wl_set_drv_status(cfg, READY, ndev);
13019 s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
13021 struct wireless_dev *wdev;
13022 struct bcm_cfg80211 *cfg;
13024 struct device *dev;
13026 WL_TRACE(("In\n"));
13028 WL_ERR(("ndev is invaild\n"));
13031 WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
13032 dev = wl_cfg80211_get_parent_dev();
13034 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
13035 if (unlikely(!wdev)) {
13036 WL_ERR(("Could not allocate wireless device\n"));
13039 err = wl_setup_wiphy(wdev, dev, context);
13040 if (unlikely(err)) {
13044 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
13045 cfg = (struct bcm_cfg80211 *)wiphy_priv(wdev->wiphy);
13047 cfg->pub = context;
13048 INIT_LIST_HEAD(&cfg->net_list);
13049 spin_lock_init(&cfg->net_list_sync);
13050 ndev->ieee80211_ptr = wdev;
13051 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
13052 wdev->netdev = ndev;
13053 cfg->state_notifier = wl_notifier_change_state;
13054 err = wl_alloc_netinfo(cfg, ndev, wdev, WL_MODE_BSS, PM_ENABLE, 0);
13056 WL_ERR(("Failed to alloc net_info (%d)\n", err));
13057 goto cfg80211_attach_out;
13059 err = wl_init_priv(cfg);
13061 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
13062 goto cfg80211_attach_out;
13065 err = wl_setup_rfkill(cfg, TRUE);
13067 WL_ERR(("Failed to setup rfkill %d\n", err));
13068 goto cfg80211_attach_out;
13070 #ifdef DEBUGFS_CFG80211
13071 err = wl_setup_debugfs(cfg);
13073 WL_ERR(("Failed to setup debugfs %d\n", err));
13074 goto cfg80211_attach_out;
13077 if (!wl_cfg80211_netdev_notifier_registered) {
13078 wl_cfg80211_netdev_notifier_registered = TRUE;
13079 err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
13081 wl_cfg80211_netdev_notifier_registered = FALSE;
13082 WL_ERR(("Failed to register notifierl %d\n", err));
13083 goto cfg80211_attach_out;
13086 #if defined(COEX_DHCP)
13087 cfg->btcoex_info = wl_cfg80211_btcoex_init(cfg->wdev->netdev);
13088 if (!cfg->btcoex_info)
13089 goto cfg80211_attach_out;
13091 #if defined(SUPPORT_RANDOM_MAC_SCAN)
13092 cfg->random_mac_enabled = FALSE;
13093 #endif /* SUPPORT_RANDOM_MAC_SCAN */
13096 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
13097 wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
13098 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
13100 #if defined(WL_ENABLE_P2P_IF)
13101 err = wl_cfg80211_attach_p2p();
13103 goto cfg80211_attach_out;
13106 INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
13107 mutex_init(&cfg->pm_sync);
13111 cfg80211_attach_out:
13112 wl_setup_rfkill(cfg, FALSE);
13117 void wl_cfg80211_detach(void *para)
13119 struct bcm_cfg80211 *cfg;
13124 WL_TRACE(("In\n"));
13126 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
13128 #if defined(COEX_DHCP)
13129 wl_cfg80211_btcoex_deinit();
13130 cfg->btcoex_info = NULL;
13133 wl_setup_rfkill(cfg, FALSE);
13134 #ifdef DEBUGFS_CFG80211
13135 wl_free_debugfs(cfg);
13137 if (cfg->p2p_supported) {
13138 if (timer_pending(&cfg->p2p->listen_timer))
13139 del_timer_sync(&cfg->p2p->listen_timer);
13140 wl_cfgp2p_deinit_priv(cfg);
13143 if (timer_pending(&cfg->scan_timeout))
13144 del_timer_sync(&cfg->scan_timeout);
13145 #ifdef DHD_LOSSLESS_ROAMING
13146 if (timer_pending(&cfg->roam_timeout)) {
13147 del_timer_sync(&cfg->roam_timeout);
13149 #endif /* DHD_LOSSLESS_ROAMING */
13151 #if defined(WL_CFG80211_P2P_DEV_IF)
13153 wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
13154 #endif /* WL_CFG80211_P2P_DEV_IF */
13155 #if defined(WL_ENABLE_P2P_IF)
13156 wl_cfg80211_detach_p2p();
13159 wl_cfg80211_ibss_vsie_free(cfg);
13160 wl_cfg80211_clear_mgmt_vndr_ies(cfg);
13161 wl_deinit_priv(cfg);
13163 wl_cfg80211_clear_parent_dev();
13165 #if defined(RSSIAVG)
13166 wl_free_rssi_cache(&g_rssi_cache_ctrl);
13167 wl_free_rssi_cache(&g_connected_rssi_cache_ctrl);
13169 #if defined(BSSCACHE)
13170 wl_release_bss_cache_ctrl(&g_bss_cache_ctrl);
13172 /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
13173 * structure "cfg", which is the private part of wiphy, has been freed in
13174 * wl_free_wdev !!!!!!!!!!!
13178 static void wl_wakeup_event(struct bcm_cfg80211 *cfg)
13180 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
13182 if (dhd->up && (cfg->event_tsk.thr_pid >= 0)) {
13183 up(&cfg->event_tsk.sema);
13187 static s32 wl_event_handler(void *data)
13189 struct bcm_cfg80211 *cfg = NULL;
13190 struct wl_event_q *e;
13191 tsk_ctl_t *tsk = (tsk_ctl_t *)data;
13192 struct wireless_dev *wdev = NULL;
13194 cfg = (struct bcm_cfg80211 *)tsk->parent;
13196 printf("tsk Enter, tsk = 0x%p\n", tsk);
13198 while (down_interruptible (&tsk->sema) == 0) {
13199 SMP_RD_BARRIER_DEPENDS();
13200 if (tsk->terminated) {
13203 while ((e = wl_deq_event(cfg))) {
13204 WL_DBG(("event type (%d), ifidx: %d bssidx: %d \n",
13205 e->etype, e->emsg.ifidx, e->emsg.bsscfgidx));
13207 if (e->emsg.ifidx > WL_MAX_IFS) {
13208 WL_ERR((" Event ifidx not in range. val:%d \n", e->emsg.ifidx));
13212 if (!(wdev = wl_get_wdev_by_bssidx(cfg, e->emsg.bsscfgidx))) {
13213 /* For WLC_E_IF would be handled by wl_host_event */
13214 if (e->etype != WLC_E_IF)
13215 WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"
13216 " Ignoring event.\n", e->emsg.bsscfgidx));
13217 } else if (e->etype < WLC_E_LAST && cfg->evt_handler[e->etype]) {
13218 dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
13219 if (dhd->busstate == DHD_BUS_DOWN) {
13220 WL_ERR((": BUS is DOWN.\n"));
13223 if (cfg->iface_cnt == 0) {
13224 wl_dump_ifinfo(cfg);
13227 cfg->evt_handler[e->etype](cfg, wdev_to_cfgdev(wdev),
13228 &e->emsg, e->edata);
13231 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
13235 DHD_EVENT_WAKE_UNLOCK(cfg->pub);
13238 printf("%s: was terminated\n", __FUNCTION__);
13239 complete_and_exit(&tsk->completed, 0);
13244 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
13246 u32 event_type = ntoh32(e->event_type);
13247 struct bcm_cfg80211 *cfg = g_bcm_cfg;
13248 struct net_info *netinfo;
13250 #if (WL_DBG_LEVEL > 0)
13251 s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
13252 wl_dbg_estr[event_type] : (s8 *) "Unknown";
13253 WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
13254 #endif /* (WL_DBG_LEVEL > 0) */
13256 if (cfg->event_tsk.thr_pid == -1) {
13257 WL_ERR(("Event handler is not created\n"));
13261 if ((cfg == NULL) || (cfg->p2p_supported && cfg->p2p == NULL)) {
13262 WL_ERR(("Stale event ignored\n"));
13266 if (wl_get_p2p_status(cfg, IF_CHANGING) || wl_get_p2p_status(cfg, IF_ADDING)) {
13267 WL_ERR(("during IF change, ignore event %d\n", event_type));
13272 if (event_type != WLC_E_ESCAN_RESULT) {
13273 WL_ERR(("Event_type %d , status : %d, reason : %d, bssidx:%d \n",
13274 event_type, ntoh32(e->status), ntoh32(e->reason), e->bsscfgidx));
13277 netinfo = wl_get_netinfo_by_bssidx(cfg, e->bsscfgidx);
13279 /* Since the netinfo entry is not there, the netdev entry is not
13280 * created via cfg80211 interface. so the event is not of interest
13281 * to the cfg80211 layer.
13283 WL_ERR(("ignore event %d, not interested\n", event_type));
13287 if (event_type == WLC_E_PFN_NET_FOUND) {
13288 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
13290 else if (event_type == WLC_E_PFN_NET_LOST) {
13291 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
13294 DHD_EVENT_WAKE_LOCK(cfg->pub);
13295 if (likely(!wl_enq_event(cfg, ndev, event_type, e, data))) {
13296 wl_wakeup_event(cfg);
13298 DHD_EVENT_WAKE_UNLOCK(cfg->pub);
13302 static void wl_init_eq(struct bcm_cfg80211 *cfg)
13304 wl_init_eq_lock(cfg);
13305 INIT_LIST_HEAD(&cfg->eq_list);
13308 static void wl_flush_eq(struct bcm_cfg80211 *cfg)
13310 struct wl_event_q *e;
13311 unsigned long flags;
13313 flags = wl_lock_eq(cfg);
13314 while (!list_empty_careful(&cfg->eq_list)) {
13315 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
13316 list_del(&e->eq_list);
13319 wl_unlock_eq(cfg, flags);
13323 * retrieve first queued event from head
13326 static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg)
13328 struct wl_event_q *e = NULL;
13329 unsigned long flags;
13331 flags = wl_lock_eq(cfg);
13332 if (likely(!list_empty(&cfg->eq_list))) {
13333 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
13334 list_del(&e->eq_list);
13336 wl_unlock_eq(cfg, flags);
13342 * push event to tail of the queue
13346 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 event,
13347 const wl_event_msg_t *msg, void *data)
13349 struct wl_event_q *e;
13353 unsigned long flags;
13358 data_len = ntoh32(msg->datalen);
13359 evtq_size = sizeof(struct wl_event_q) + data_len;
13360 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
13361 e = kzalloc(evtq_size, aflags);
13362 if (unlikely(!e)) {
13363 WL_ERR(("event alloc failed\n"));
13367 memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
13369 memcpy(e->edata, data, data_len);
13370 flags = wl_lock_eq(cfg);
13371 list_add_tail(&e->eq_list, &cfg->eq_list);
13372 wl_unlock_eq(cfg, flags);
13377 static void wl_put_event(struct wl_event_q *e)
13382 static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype)
13388 case NL80211_IFTYPE_MONITOR:
13389 case NL80211_IFTYPE_WDS:
13390 WL_ERR(("type (%d) : currently we do not support this mode\n",
13394 case NL80211_IFTYPE_ADHOC:
13395 mode = WL_MODE_IBSS;
13397 case NL80211_IFTYPE_STATION:
13398 case NL80211_IFTYPE_P2P_CLIENT:
13399 mode = WL_MODE_BSS;
13402 case NL80211_IFTYPE_AP:
13403 case NL80211_IFTYPE_P2P_GO:
13409 WL_ERR(("invalid type (%d)\n", iftype));
13412 infra = htod32(infra);
13413 err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), true);
13414 if (unlikely(err)) {
13415 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
13419 wl_set_mode_by_netdev(cfg, ndev, mode);
13424 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
13426 if (!ev || (event > WLC_E_LAST))
13429 if (ev->num < MAX_EVENT_BUF_NUM) {
13430 ev->event[ev->num].type = event;
13431 ev->event[ev->num].set = set;
13434 WL_ERR(("evenbuffer doesn't support > %u events. Update"
13435 " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
13440 s32 wl_cfg80211_apply_eventbuffer(
13441 struct net_device *ndev,
13442 struct bcm_cfg80211 *cfg,
13443 wl_eventmsg_buf_t *ev)
13445 char eventmask[WL_EVENTING_MASK_LEN];
13447 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
13449 if (!ev || (!ev->num))
13452 mutex_lock(&cfg->event_sync);
13454 /* Read event_msgs mask */
13455 bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
13457 ret = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
13458 if (unlikely(ret)) {
13459 WL_ERR(("Get event_msgs error (%d)\n", ret));
13462 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
13464 /* apply the set bits */
13465 for (i = 0; i < ev->num; i++) {
13466 if (ev->event[i].set)
13467 setbit(eventmask, ev->event[i].type);
13469 clrbit(eventmask, ev->event[i].type);
13472 /* Write updated Event mask */
13473 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
13475 ret = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
13476 if (unlikely(ret)) {
13477 WL_ERR(("Set event_msgs error (%d)\n", ret));
13481 mutex_unlock(&cfg->event_sync);
13485 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
13487 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
13488 s8 eventmask[WL_EVENTING_MASK_LEN];
13490 struct bcm_cfg80211 *cfg = g_bcm_cfg;
13495 mutex_lock(&cfg->event_sync);
13497 /* Setup event_msgs */
13498 bcm_mkiovar("event_msgs", NULL, 0, iovbuf,
13500 err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), false);
13501 if (unlikely(err)) {
13502 WL_ERR(("Get event_msgs error (%d)\n", err));
13505 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
13507 setbit(eventmask, event);
13509 clrbit(eventmask, event);
13511 bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
13513 err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
13514 if (unlikely(err)) {
13515 WL_ERR(("Set event_msgs error (%d)\n", err));
13520 mutex_unlock(&cfg->event_sync);
13524 static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap)
13526 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
13527 struct ieee80211_channel *band_chan_arr = NULL;
13528 wl_uint32_list_t *list;
13529 u32 i, j, index, n_2g, n_5g, band, channel, array_size;
13536 bool dfs_radar_disabled = FALSE;
13538 #define LOCAL_BUF_LEN 1024
13539 pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
13541 if (pbuf == NULL) {
13542 WL_ERR(("failed to allocate local buf\n"));
13545 list = (wl_uint32_list_t *)(void *)pbuf;
13546 list->count = htod32(WL_NUMCHANSPECS);
13549 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
13550 0, pbuf, LOCAL_BUF_LEN, 0, &cfg->ioctl_buf_sync);
13552 WL_ERR(("get chanspecs failed with %d\n", err));
13556 #undef LOCAL_BUF_LEN
13558 list = (wl_uint32_list_t *)(void *)pbuf;
13559 band = array_size = n_2g = n_5g = 0;
13560 for (i = 0; i < dtoh32(list->count); i++) {
13563 ht40_allowed = false;
13564 c = (chanspec_t)dtoh32(list->element[i]);
13565 c = wl_chspec_driver_to_host(c);
13566 channel = wf_chspec_ctlchan(c);
13568 if (!CHSPEC_IS40(c) && ! CHSPEC_IS20(c)) {
13569 WL_DBG(("HT80/160/80p80 center channel : %d\n", channel));
13572 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
13573 (channel <= CH_MAX_2G_CHANNEL)) {
13574 band_chan_arr = __wl_2ghz_channels;
13575 array_size = ARRAYSIZE(__wl_2ghz_channels);
13577 band = IEEE80211_BAND_2GHZ;
13578 ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false;
13579 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
13580 band_chan_arr = __wl_5ghz_a_channels;
13581 array_size = ARRAYSIZE(__wl_5ghz_a_channels);
13583 band = IEEE80211_BAND_5GHZ;
13584 ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
13586 WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
13589 if (!ht40_allowed && CHSPEC_IS40(c))
13591 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
13592 if (band_chan_arr[j].hw_value == channel) {
13601 if (!dhd_conf_match_channel(cfg->pub, channel))
13603 if (index < array_size) {
13604 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
13605 band_chan_arr[index].center_freq =
13606 ieee80211_channel_to_frequency(channel);
13608 band_chan_arr[index].center_freq =
13609 ieee80211_channel_to_frequency(channel, band);
13611 band_chan_arr[index].hw_value = channel;
13612 WL_DBG(("channel = %d\n", channel));
13614 if (CHSPEC_IS40(c) && ht40_allowed) {
13615 /* assuming the order is HT20, HT40 Upper,
13616 * HT40 lower from chanspecs
13618 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
13619 if (CHSPEC_SB_UPPER(c)) {
13620 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
13621 band_chan_arr[index].flags &=
13622 ~IEEE80211_CHAN_NO_HT40;
13623 band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
13625 /* It should be one of
13626 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
13628 band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
13629 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
13630 band_chan_arr[index].flags |=
13631 IEEE80211_CHAN_NO_HT40MINUS;
13634 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
13635 if (!dfs_radar_disabled) {
13636 if (band == IEEE80211_BAND_2GHZ)
13637 channel |= WL_CHANSPEC_BAND_2G;
13639 channel |= WL_CHANSPEC_BAND_5G;
13640 channel |= WL_CHANSPEC_BW_20;
13641 channel = wl_chspec_host_to_driver(channel);
13642 err = wldev_iovar_getint(dev, "per_chan_info", &channel);
13644 if (channel & WL_CHAN_RADAR) {
13645 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
13646 band_chan_arr[index].flags |=
13647 (IEEE80211_CHAN_RADAR
13648 | IEEE80211_CHAN_NO_IBSS);
13650 band_chan_arr[index].flags |=
13651 IEEE80211_CHAN_RADAR;
13655 if (channel & WL_CHAN_PASSIVE)
13656 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
13657 band_chan_arr[index].flags |=
13658 IEEE80211_CHAN_PASSIVE_SCAN;
13660 band_chan_arr[index].flags |=
13661 IEEE80211_CHAN_NO_IR;
13663 } else if (err == BCME_UNSUPPORTED) {
13664 dfs_radar_disabled = TRUE;
13665 WL_ERR(("does not support per_chan_info\n"));
13674 __wl_band_2ghz.n_channels = n_2g;
13675 __wl_band_5ghz_a.n_channels = n_5g;
13680 s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
13682 struct wiphy *wiphy;
13683 struct net_device *dev;
13690 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13698 s32 txbf_bfe_cap = 0;
13699 s32 txbf_bfr_cap = 0;
13701 bool rollback_lock = false;
13704 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
13708 mutex_lock(&cfg->usr_sync);
13709 rollback_lock = true;
13711 dev = bcmcfg_to_prmry_ndev(cfg);
13713 memset(bandlist, 0, sizeof(bandlist));
13714 err = wldev_ioctl(dev, WLC_GET_BANDLIST, bandlist,
13715 sizeof(bandlist), false);
13716 if (unlikely(err)) {
13717 WL_ERR(("error read bandlist (%d)\n", err));
13720 err = wldev_ioctl(dev, WLC_GET_BAND, &cur_band,
13721 sizeof(s32), false);
13722 if (unlikely(err)) {
13723 WL_ERR(("error (%d)\n", err));
13727 err = wldev_iovar_getint(dev, "nmode", &nmode);
13728 if (unlikely(err)) {
13729 WL_ERR(("error reading nmode (%d)\n", err));
13732 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13733 err = wldev_iovar_getint(dev, "vhtmode", &vhtmode);
13734 if (unlikely(err)) {
13735 WL_ERR(("error reading vhtmode (%d)\n", err));
13739 err = wldev_iovar_getint(dev, "txstreams", &txstreams);
13740 if (unlikely(err)) {
13741 WL_ERR(("error reading txstreams (%d)\n", err));
13744 err = wldev_iovar_getint(dev, "rxstreams", &rxstreams);
13745 if (unlikely(err)) {
13746 WL_ERR(("error reading rxstreams (%d)\n", err));
13749 err = wldev_iovar_getint(dev, "ldpc_cap", &ldpc_cap);
13750 if (unlikely(err)) {
13751 WL_ERR(("error reading ldpc_cap (%d)\n", err));
13754 err = wldev_iovar_getint(dev, "stbc_rx", &stbc_rx);
13755 if (unlikely(err)) {
13756 WL_ERR(("error reading stbc_rx (%d)\n", err));
13759 err = wldev_iovar_getint(dev, "stbc_tx", &stbc_tx);
13760 if (unlikely(err)) {
13761 WL_ERR(("error reading stbc_tx (%d)\n", err));
13764 err = wldev_iovar_getint(dev, "txbf_bfe_cap", &txbf_bfe_cap);
13765 if (unlikely(err)) {
13766 WL_ERR(("error reading txbf_bfe_cap (%d)\n", err));
13769 err = wldev_iovar_getint(dev, "txbf_bfr_cap", &txbf_bfr_cap);
13770 if (unlikely(err)) {
13771 WL_ERR(("error reading txbf_bfr_cap (%d)\n", err));
13776 /* For nmode and vhtmode check bw cap */
13778 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13782 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
13783 if (unlikely(err)) {
13784 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
13788 err = wl_construct_reginfo(cfg, bw_cap);
13790 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
13791 if (err != BCME_UNSUPPORTED)
13795 wiphy = bcmcfg_to_wiphy(cfg);
13796 nband = bandlist[0];
13798 for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
13800 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
13801 bands[IEEE80211_BAND_5GHZ] =
13803 index = IEEE80211_BAND_5GHZ;
13804 if (nmode && (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G))
13805 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
13807 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
13808 /* VHT capabilities. */
13811 bands[index]->vht_cap.vht_supported = TRUE;
13813 for (j = 1; j <= VHT_CAP_MCS_MAP_NSS_MAX; j++) {
13814 /* TX stream rates. */
13815 if (j <= txstreams) {
13816 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
13817 bands[index]->vht_cap.vht_mcs.tx_mcs_map);
13819 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
13820 bands[index]->vht_cap.vht_mcs.tx_mcs_map);
13823 /* RX stream rates. */
13824 if (j <= rxstreams) {
13825 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
13826 bands[index]->vht_cap.vht_mcs.rx_mcs_map);
13828 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
13829 bands[index]->vht_cap.vht_mcs.rx_mcs_map);
13835 /* 80 MHz is mandatory */
13836 bands[index]->vht_cap.cap |=
13837 IEEE80211_VHT_CAP_SHORT_GI_80;
13839 if (WL_BW_CAP_160MHZ(bw_cap)) {
13840 bands[index]->vht_cap.cap |=
13841 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
13842 bands[index]->vht_cap.cap |=
13843 IEEE80211_VHT_CAP_SHORT_GI_160;
13846 bands[index]->vht_cap.cap |=
13847 IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
13850 bands[index]->vht_cap.cap |=
13851 IEEE80211_VHT_CAP_RXLDPC;
13854 bands[index]->vht_cap.cap |=
13855 IEEE80211_VHT_CAP_TXSTBC;
13858 bands[index]->vht_cap.cap |=
13859 (stbc_rx << VHT_CAP_INFO_RX_STBC_SHIFT);
13862 bands[index]->vht_cap.cap |=
13863 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
13865 if (txbf_bfr_cap) {
13866 bands[index]->vht_cap.cap |=
13867 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
13870 if (txbf_bfe_cap || txbf_bfr_cap) {
13871 bands[index]->vht_cap.cap |=
13872 (2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT);
13873 bands[index]->vht_cap.cap |=
13874 ((txstreams - 1) <<
13875 VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT);
13876 bands[index]->vht_cap.cap |=
13877 IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
13880 /* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
13881 bands[index]->vht_cap.cap |=
13882 (7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT);
13883 WL_INFORM(("%s band[%d] vht_enab=%d vht_cap=%08x "
13884 "vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
13885 __FUNCTION__, index,
13886 bands[index]->vht_cap.vht_supported,
13887 bands[index]->vht_cap.cap,
13888 bands[index]->vht_cap.vht_mcs.rx_mcs_map,
13889 bands[index]->vht_cap.vht_mcs.tx_mcs_map));
13893 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
13894 bands[IEEE80211_BAND_2GHZ] =
13896 index = IEEE80211_BAND_2GHZ;
13897 if (bw_cap == WLC_N_BW_40ALL)
13898 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
13901 if ((index >= 0) && nmode) {
13902 bands[index]->ht_cap.cap |=
13903 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
13904 bands[index]->ht_cap.ht_supported = TRUE;
13905 bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
13906 bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
13907 /* An HT shall support all EQM rates for one spatial stream */
13908 bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
13913 wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
13914 wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
13916 /* check if any bands populated otherwise makes 2Ghz as default */
13917 if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
13918 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
13919 /* Setup 2Ghz band as default */
13920 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
13924 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
13928 mutex_unlock(&cfg->usr_sync);
13932 static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg)
13935 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
13936 struct wireless_dev *wdev = ndev->ieee80211_ptr;
13940 err = wl_create_event_handler(cfg);
13942 WL_ERR(("wl_create_event_handler failed\n"));
13945 wl_init_event_handler(cfg);
13947 err = dhd_config_dongle(cfg);
13951 err = wl_config_ifmode(cfg, ndev, wdev->iftype);
13952 if (unlikely(err && err != -EINPROGRESS)) {
13953 WL_ERR(("wl_config_ifmode failed\n"));
13955 WL_ERR(("return error %d\n", err));
13960 err = wl_init_scan(cfg);
13962 WL_ERR(("wl_init_scan failed\n"));
13965 err = wl_update_wiphybands(cfg, true);
13966 if (unlikely(err)) {
13967 WL_ERR(("wl_update_wiphybands failed\n"));
13969 WL_ERR(("return error %d\n", err));
13973 #ifdef DHD_LOSSLESS_ROAMING
13974 if (timer_pending(&cfg->roam_timeout)) {
13975 del_timer_sync(&cfg->roam_timeout);
13977 #endif /* DHD_LOSSLESS_ROAMING */
13979 err = dhd_monitor_init(cfg->pub);
13981 wl_set_drv_status(cfg, READY, ndev);
13985 static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
13988 unsigned long flags;
13989 struct net_info *iter, *next;
13990 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
13991 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
13992 struct net_device *p2p_net = cfg->p2p_net;
13994 #ifdef PROP_TXSTATUS_VSDB
13995 #if defined(BCMSDIO)
13996 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
13998 #endif /* PROP_TXSTATUS_VSDB */
14000 /* Delete pm_enable_work */
14001 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
14004 wl_cfgnan_stop_handler(ndev, g_bcm_cfg, NULL, 0, NULL);
14005 #endif /* WL_NAN */
14007 if (cfg->p2p_supported) {
14008 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
14009 #ifdef PROP_TXSTATUS_VSDB
14010 #if defined(BCMSDIO)
14011 if (wl_cfgp2p_vif_created(cfg)) {
14012 bool enabled = false;
14013 dhd_wlfc_get_enable(dhd, &enabled);
14014 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
14015 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
14016 dhd_wlfc_deinit(dhd);
14017 cfg->wlfc_on = false;
14021 #endif /* PROP_TXSTATUS_VSDB */
14025 /* If primary BSS is operational (for e.g SoftAP), bring it down */
14026 if (wl_cfgp2p_bss_isup(ndev, 0)) {
14027 if (wl_cfgp2p_bss(cfg, ndev, 0, 0) < 0)
14028 WL_ERR(("BSS down failed \n"));
14031 /* Check if cfg80211 interface is already down */
14032 if (!wl_get_drv_status(cfg, READY, ndev))
14033 return err; /* it is even not ready */
14035 /* clear all the security setting on primary Interface */
14036 wl_cfg80211_clear_security(cfg);
14038 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14039 4 && __GNUC_MINOR__ >= 6))
14040 _Pragma("GCC diagnostic push")
14041 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14043 for_each_ndev(cfg, iter, next) {
14044 if (iter->ndev) /* p2p discovery iface is null */
14045 wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
14047 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14048 4 && __GNUC_MINOR__ >= 6))
14049 _Pragma("GCC diagnostic pop")
14052 #ifdef P2P_LISTEN_OFFLOADING
14053 wl_cfg80211_p2plo_deinit(cfg);
14054 #endif /* P2P_LISTEN_OFFLOADING */
14056 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14057 if (cfg->scan_request) {
14058 cfg80211_scan_done(cfg->scan_request, true);
14059 cfg->scan_request = NULL;
14061 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14062 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14063 4 && __GNUC_MINOR__ >= 6))
14064 _Pragma("GCC diagnostic push")
14065 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14067 for_each_ndev(cfg, iter, next) {
14068 /* p2p discovery iface ndev ptr could be null */
14069 if (iter->ndev == NULL)
14071 wl_clr_drv_status(cfg, READY, iter->ndev);
14072 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
14073 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
14074 wl_clr_drv_status(cfg, CONNECTING, iter->ndev);
14075 wl_clr_drv_status(cfg, CONNECTED, iter->ndev);
14076 wl_clr_drv_status(cfg, DISCONNECTING, iter->ndev);
14077 wl_clr_drv_status(cfg, AP_CREATED, iter->ndev);
14078 wl_clr_drv_status(cfg, AP_CREATING, iter->ndev);
14080 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14081 4 && __GNUC_MINOR__ >= 6))
14082 _Pragma("GCC diagnostic pop")
14084 bcmcfg_to_prmry_ndev(cfg)->ieee80211_ptr->iftype =
14085 NL80211_IFTYPE_STATION;
14086 #if defined(WL_CFG80211) && defined(WL_ENABLE_P2P_IF)
14088 dev_close(p2p_net);
14091 /* Avoid deadlock from wl_cfg80211_down */
14092 mutex_unlock(&cfg->usr_sync);
14093 wl_destroy_event_handler(cfg);
14094 mutex_lock(&cfg->usr_sync);
14097 if (cfg->p2p_supported) {
14098 if (timer_pending(&cfg->p2p->listen_timer))
14099 del_timer_sync(&cfg->p2p->listen_timer);
14100 wl_cfgp2p_down(cfg);
14103 if (timer_pending(&cfg->scan_timeout)) {
14104 del_timer_sync(&cfg->scan_timeout);
14107 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
14109 dhd_monitor_uninit();
14110 #ifdef WLAIBSS_MCHAN
14111 bcm_cfg80211_del_ibss_if(cfg->wdev->wiphy, cfg->ibss_cfgdev);
14112 #endif /* WLAIBSS_MCHAN */
14114 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
14115 /* Clean up if not removed already */
14116 if (cfg->bss_cfgdev)
14117 wl_cfg80211_del_iface(cfg->wdev->wiphy, cfg->bss_cfgdev);
14118 #endif /* defined (WL_VIRTUAL_APSTA) || defined (DUAL_STA_STATIC_IF) */
14121 /* Clear interworking element. */
14123 cfg->wl11u = FALSE;
14124 cfg->iw_ie_len = 0;
14125 memset(cfg->iw_ie, 0, IW_IES_MAX_BUF_LEN);
14129 #ifdef CUSTOMER_HW4_DEBUG
14130 if (wl_scan_timeout_dbg_enabled)
14131 wl_scan_timeout_dbg_clear();
14132 #endif /* CUSTOMER_HW4_DEBUG */
14134 cfg->disable_roam_event = false;
14136 DNGL_FUNC(dhd_cfg80211_down, (cfg));
14139 /* Printout all netinfo entries */
14140 wl_probe_wdev_all(cfg);
14141 #endif /* DHD_IFDEBUG */
14146 s32 wl_cfg80211_up(void *para)
14148 struct bcm_cfg80211 *cfg;
14152 #ifdef DISABLE_PM_BCNRX
14155 s8 iovbuf[WLC_IOCTL_SMLEN];
14156 #endif /* DISABLE_PM_BCNRX */
14162 if ((err = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_GET_VERSION, &val,
14163 sizeof(int), false) < 0)) {
14164 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
14168 if (val != WLC_IOCTL_VERSION && val != 1) {
14169 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
14170 val, WLC_IOCTL_VERSION));
14171 return BCME_VERSION;
14173 ioctl_version = val;
14174 WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
14176 mutex_lock(&cfg->usr_sync);
14177 dhd = (dhd_pub_t *)(cfg->pub);
14178 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
14179 err = wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg));
14180 if (unlikely(err)) {
14181 mutex_unlock(&cfg->usr_sync);
14185 err = __wl_cfg80211_up(cfg);
14187 WL_ERR(("__wl_cfg80211_up failed\n"));
14191 /* IOVAR configurations with 'up' condition */
14192 #ifdef DISABLE_PM_BCNRX
14193 bcm_mkiovar("pm_bcnrx", (char *)¶m, 4, iovbuf, sizeof(iovbuf));
14194 interr = wldev_ioctl(bcmcfg_to_prmry_ndev(cfg), WLC_SET_VAR, iovbuf, sizeof(iovbuf), true);
14195 if (unlikely(interr))
14196 WL_ERR(("Set pm_bcnrx returned (%d)\n", interr));
14197 #endif /* DISABLE_PM_BCNRX */
14199 mutex_unlock(&cfg->usr_sync);
14201 #ifdef WLAIBSS_MCHAN
14202 bcm_cfg80211_add_ibss_if(cfg->wdev->wiphy, IBSS_IF_NAME);
14203 #endif /* WLAIBSS_MCHAN */
14205 #ifdef DUAL_STA_STATIC_IF
14206 #ifdef WL_VIRTUAL_APSTA
14207 #error "Both DUAL STA and DUAL_STA_STATIC_IF can't be enabled together"
14209 /* Static Interface support is currently supported only for STA only builds (without P2P) */
14210 wl_cfg80211_create_iface(cfg->wdev->wiphy, NL80211_IFTYPE_STATION, NULL, "wlan%d");
14211 #endif /* DUAL_STA_STATIC_IF */
14216 /* Private Event to Supplicant with indication that chip hangs */
14217 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
14219 struct bcm_cfg80211 *cfg;
14221 #if defined(SOFTAP_SEND_HANGEVT)
14222 /* specifc mac address used for hang event */
14223 uint8 hang_mac[ETHER_ADDR_LEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
14224 #endif /* SOFTAP_SEND_HANGEVT */
14230 dhd = (dhd_pub_t *)(cfg->pub);
14232 #ifdef DHD_USE_EXTENDED_HANG_REASON
14233 if (dhd->hang_reason != 0) {
14234 reason = dhd->hang_reason;
14236 #endif /* DHD_USE_EXTENDED_HANG_REASON */
14238 WL_ERR(("In : chip crash eventing, reason=0x%x\n", (uint32)(dhd->hang_reason)));
14239 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
14240 #if defined(SOFTAP_SEND_HANGEVT)
14241 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
14242 cfg80211_del_sta(dev, hang_mac, GFP_ATOMIC);
14244 #endif /* SOFTAP_SEND_HANGEVT */
14246 CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
14248 #if defined(RSSIAVG)
14249 wl_free_rssi_cache(&g_rssi_cache_ctrl);
14251 #if defined(BSSCACHE)
14252 wl_free_bss_cache(&g_bss_cache_ctrl);
14260 s32 wl_cfg80211_down(void *para)
14262 struct bcm_cfg80211 *cfg;
14268 mutex_lock(&cfg->usr_sync);
14269 #if defined(RSSIAVG)
14270 wl_free_rssi_cache(&g_rssi_cache_ctrl);
14272 #if defined(BSSCACHE)
14273 wl_free_bss_cache(&g_bss_cache_ctrl);
14275 err = __wl_cfg80211_down(cfg);
14276 mutex_unlock(&cfg->usr_sync);
14281 static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item)
14283 unsigned long flags;
14285 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
14289 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14292 rptr = &profile->sec;
14295 rptr = &profile->active;
14297 case WL_PROF_BSSID:
14298 rptr = profile->bssid;
14301 rptr = &profile->ssid;
14304 rptr = &profile->channel;
14307 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14309 WL_ERR(("invalid item (%d)\n", item));
14314 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
14315 const wl_event_msg_t *e, const void *data, s32 item)
14318 const struct wlc_ssid *ssid;
14319 unsigned long flags;
14320 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
14324 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14327 ssid = (const wlc_ssid_t *) data;
14328 memset(profile->ssid.SSID, 0,
14329 sizeof(profile->ssid.SSID));
14330 memcpy(profile->ssid.SSID, ssid->SSID, ssid->SSID_len);
14331 profile->ssid.SSID_len = ssid->SSID_len;
14333 case WL_PROF_BSSID:
14335 memcpy(profile->bssid, data, ETHER_ADDR_LEN);
14337 memset(profile->bssid, 0, ETHER_ADDR_LEN);
14340 memcpy(&profile->sec, data, sizeof(profile->sec));
14343 profile->active = *(const bool *)data;
14345 case WL_PROF_BEACONINT:
14346 profile->beacon_interval = *(const u16 *)data;
14348 case WL_PROF_DTIMPERIOD:
14349 profile->dtim_period = *(const u8 *)data;
14352 profile->channel = *(const u32*)data;
14358 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14360 if (err == -EOPNOTSUPP)
14361 WL_ERR(("unsupported item (%d)\n", item));
14366 void wl_cfg80211_dbg_level(u32 level)
14369 * prohibit to change debug level
14370 * by insmod parameter.
14371 * eventually debug level will be configured
14372 * in compile time by using CONFIG_XXX
14374 /* wl_dbg_level = level; */
14377 static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev)
14379 return wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS;
14382 static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg)
14384 return cfg->ibss_starter;
14387 static void wl_rst_ie(struct bcm_cfg80211 *cfg)
14389 struct wl_ie *ie = wl_to_ie(cfg);
14394 static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v)
14396 struct wl_ie *ie = wl_to_ie(cfg);
14399 if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
14400 WL_ERR(("ei crosses buffer boundary\n"));
14403 ie->buf[ie->offset] = t;
14404 ie->buf[ie->offset + 1] = l;
14405 memcpy(&ie->buf[ie->offset + 2], v, l);
14406 ie->offset += l + 2;
14411 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
14415 /* cfg80211_find_ie defined in kernel returning const u8 */
14416 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14417 4 && __GNUC_MINOR__ >= 6))
14418 _Pragma("GCC diagnostic push")
14419 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
14421 ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
14422 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
14423 4 && __GNUC_MINOR__ >= 6))
14424 _Pragma("GCC diagnostic pop")
14428 if (ssidie[1] != bi->SSID_len) {
14430 WL_ERR(("%s: Wrong SSID len: %d != %d\n",
14431 __FUNCTION__, ssidie[1], bi->SSID_len));
14434 WL_ERR(("Changing the SSID Info.\n"));
14435 memmove(ssidie + bi->SSID_len + 2,
14436 (ssidie + 2) + ssidie[1],
14437 *ie_size - (ssidie + 2 + ssidie[1] - ie_stream));
14438 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
14439 *ie_size = *ie_size + bi->SSID_len - ssidie[1];
14440 ssidie[1] = bi->SSID_len;
14444 if (*(ssidie + 2) == '\0')
14445 memcpy(ssidie + 2, bi->SSID, bi->SSID_len);
14449 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size)
14451 struct wl_ie *ie = wl_to_ie(cfg);
14454 if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
14455 WL_ERR(("ei_stream crosses buffer boundary\n"));
14458 memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
14459 ie->offset += ie_size;
14464 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size)
14466 struct wl_ie *ie = wl_to_ie(cfg);
14469 if (unlikely(ie->offset > dst_size)) {
14470 WL_ERR(("dst_size is not enough\n"));
14473 memcpy(dst, &ie->buf[0], ie->offset);
14478 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg)
14480 struct wl_ie *ie = wl_to_ie(cfg);
14485 static void wl_link_up(struct bcm_cfg80211 *cfg)
14487 cfg->link_up = true;
14490 static void wl_link_down(struct bcm_cfg80211 *cfg)
14492 struct wl_connect_info *conn_info = wl_to_conn(cfg);
14495 cfg->link_up = false;
14496 conn_info->req_ie_len = 0;
14497 conn_info->resp_ie_len = 0;
14500 static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg)
14502 unsigned long flags;
14504 spin_lock_irqsave(&cfg->eq_lock, flags);
14508 static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags)
14510 spin_unlock_irqrestore(&cfg->eq_lock, flags);
14513 static void wl_init_eq_lock(struct bcm_cfg80211 *cfg)
14515 spin_lock_init(&cfg->eq_lock);
14518 static void wl_delay(u32 ms)
14520 if (in_atomic() || (ms < jiffies_to_msecs(1))) {
14521 OSL_DELAY(ms*1000);
14527 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
14529 struct bcm_cfg80211 *cfg = g_bcm_cfg;
14530 struct ether_addr primary_mac;
14533 if (!p2p_is_on(cfg)) {
14534 get_primary_mac(cfg, &primary_mac);
14535 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
14537 memcpy(p2pdev_addr->octet, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE).octet,
14543 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
14545 struct bcm_cfg80211 *cfg;
14549 return wl_cfgp2p_set_p2p_noa(cfg, net, buf, len);
14552 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
14554 struct bcm_cfg80211 *cfg;
14557 return wl_cfgp2p_get_p2p_noa(cfg, net, buf, len);
14560 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
14562 struct bcm_cfg80211 *cfg;
14565 return wl_cfgp2p_set_p2p_ps(cfg, net, buf, len);
14568 s32 wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
14570 struct bcm_cfg80211 *cfg;
14573 return wl_cfgp2p_set_p2p_ecsa(cfg, net, buf, len);
14576 #ifdef P2PLISTEN_AP_SAMECHN
14577 s32 wl_cfg80211_set_p2p_resp_ap_chn(struct net_device *net, s32 enable)
14579 s32 ret = wldev_iovar_setint(net, "p2p_resp_ap_chn", enable);
14581 if ((ret == 0) && enable) {
14582 /* disable PM for p2p responding on infra AP channel */
14585 ret = wldev_ioctl(net, WLC_SET_PM, &pm, sizeof(pm), true);
14590 #endif /* P2PLISTEN_AP_SAMECHN */
14592 s32 wl_cfg80211_channel_to_freq(u32 channel)
14596 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
14597 freq = ieee80211_channel_to_frequency(channel);
14601 if (channel <= CH_MAX_2G_CHANNEL)
14602 band = IEEE80211_BAND_2GHZ;
14604 band = IEEE80211_BAND_5GHZ;
14605 freq = ieee80211_channel_to_frequency(channel, band);
14614 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
14615 const wl_event_msg_t *e, void *data) {
14617 struct net_device *ndev = NULL;
14618 u32 reason = ntoh32(e->reason);
14621 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
14624 case WLC_E_TDLS_PEER_DISCOVERED :
14625 msg = " TDLS PEER DISCOVERD ";
14627 case WLC_E_TDLS_PEER_CONNECTED :
14628 #ifdef PCIE_FULL_DONGLE
14629 dhd_tdls_update_peer_info(ndev, TRUE, (uint8 *)&e->addr.octet[0]);
14630 #endif /* PCIE_FULL_DONGLE */
14631 if (cfg->tdls_mgmt_frame) {
14632 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
14633 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14634 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0);
14635 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14636 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14637 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14639 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
14640 defined(WL_COMPAT_WIRELESS)
14641 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
14642 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14645 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq,
14646 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
14648 #endif /* LINUX_VERSION >= VERSION(3, 12, 0) */
14650 msg = " TDLS PEER CONNECTED ";
14652 case WLC_E_TDLS_PEER_DISCONNECTED :
14653 #ifdef PCIE_FULL_DONGLE
14654 dhd_tdls_update_peer_info(ndev, FALSE, (uint8 *)&e->addr.octet[0]);
14655 #endif /* PCIE_FULL_DONGLE */
14656 if (cfg->tdls_mgmt_frame) {
14657 kfree(cfg->tdls_mgmt_frame);
14658 cfg->tdls_mgmt_frame = NULL;
14659 cfg->tdls_mgmt_freq = 0;
14661 msg = "TDLS PEER DISCONNECTED ";
14665 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)),
14666 (bcmcfg_to_prmry_ndev(cfg) == ndev) ? "primary" : "secondary"));
14671 #endif /* WLTDLS */
14673 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
14675 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
14676 KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
14677 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14678 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14679 u32 peer_capability, const u8 *data, size_t len)
14680 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
14681 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
14682 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14683 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14684 u32 peer_capability, const u8 *data, size_t len)
14685 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
14686 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14687 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
14688 u32 peer_capability, bool initiator, const u8 *data, size_t len)
14690 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
14691 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code, const u8 *data,
14693 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
14697 struct bcm_cfg80211 *cfg;
14698 tdls_wfd_ie_iovar_t info;
14699 memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
14702 #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
14703 /* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
14704 * and that cuases build error
14706 BCM_REFERENCE(peer_capability);
14707 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
14709 switch (action_code) {
14710 /* We need to set TDLS Wifi Display IE to firmware
14711 * using tdls_wfd_ie iovar
14713 case WLAN_TDLS_SET_PROBE_WFD_IE:
14714 WL_ERR(("%s WLAN_TDLS_SET_PROBE_WFD_IE\n", __FUNCTION__));
14715 info.mode = TDLS_WFD_PROBE_IE_TX;
14716 memcpy(&info.data, data, len);
14719 case WLAN_TDLS_SET_SETUP_WFD_IE:
14720 WL_ERR(("%s WLAN_TDLS_SET_SETUP_WFD_IE\n", __FUNCTION__));
14721 info.mode = TDLS_WFD_IE_TX;
14722 memcpy(&info.data, data, len);
14725 case WLAN_TDLS_SET_WFD_ENABLED:
14726 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_ENABLED\n", __FUNCTION__));
14727 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), true);
14729 case WLAN_TDLS_SET_WFD_DISABLED:
14730 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_DISABLED\n", __FUNCTION__));
14731 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), false);
14734 WL_ERR(("Unsupported action code : %d\n", action_code));
14738 ret = wldev_iovar_setbuf(dev, "tdls_wfd_ie", &info, sizeof(info),
14739 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
14742 WL_ERR(("tdls_wfd_ie error %d\n", ret));
14745 #endif /* WLTDLS */
14750 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
14751 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
14752 const u8 *peer, enum nl80211_tdls_operation oper)
14754 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
14755 u8 *peer, enum nl80211_tdls_operation oper)
14760 struct bcm_cfg80211 *cfg;
14763 bool tdls_auto_mode = false;
14765 dhdp = (dhd_pub_t *)(cfg->pub);
14766 memset(&info, 0, sizeof(tdls_iovar_t));
14768 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
14773 case NL80211_TDLS_DISCOVERY_REQ:
14774 /* If the discovery request is broadcast then we need to set
14775 * info.mode to Tunneled Probe Request
14777 if (memcmp(peer, (const uint8 *)BSSID_BROADCAST, ETHER_ADDR_LEN) == 0) {
14778 info.mode = TDLS_MANUAL_EP_WFD_TPQ;
14779 WL_ERR(("%s TDLS TUNNELED PRBOBE REQUEST\n", __FUNCTION__));
14781 info.mode = TDLS_MANUAL_EP_DISCOVERY;
14784 case NL80211_TDLS_SETUP:
14785 if (dhdp->tdls_mode == true) {
14786 info.mode = TDLS_MANUAL_EP_CREATE;
14787 tdls_auto_mode = false;
14788 ret = dhd_tdls_enable(dev, false, tdls_auto_mode, NULL);
14793 tdls_auto_mode = true;
14796 case NL80211_TDLS_TEARDOWN:
14797 info.mode = TDLS_MANUAL_EP_DELETE;
14800 WL_ERR(("Unsupported operation : %d\n", oper));
14804 ret = dhd_tdls_enable(dev, true, tdls_auto_mode, NULL);
14809 ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
14810 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
14812 WL_ERR(("tdls_endpoint error %d\n", ret));
14816 #endif /* WLTDLS */
14821 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *ndev, char *buf, int len,
14822 enum wl_management_type type)
14824 struct bcm_cfg80211 *cfg;
14826 struct ether_addr primary_mac;
14831 if (wl_get_drv_status(cfg, AP_CREATING, ndev)) {
14832 /* Vendor IEs should be set to FW
14833 * after SoftAP interface is brought up
14835 WL_DBG(("Skipping set IE since AP is not up \n"));
14837 } else if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
14838 /* Either stand alone AP case or P2P discovery */
14839 if (wl_get_drv_status(cfg, AP_CREATED, ndev)) {
14840 /* Stand alone AP case on primary interface */
14841 WL_DBG(("Apply IEs for Primary AP Interface \n"));
14844 /* P2P Discovery case (p2p listen) */
14845 if (!cfg->p2p->on) {
14846 /* Turn on Discovery interface */
14847 get_primary_mac(cfg, &primary_mac);
14848 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
14849 p2p_on(cfg) = true;
14850 ret = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
14851 if (unlikely(ret)) {
14852 WL_ERR(("Enable discovery failed \n"));
14856 WL_DBG(("Apply IEs for P2P Discovery Iface \n"));
14857 ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
14858 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
14861 /* Virtual AP/ P2P Group Interface */
14862 WL_DBG(("Apply IEs for iface:%s\n", ndev->name));
14863 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
14866 if (ndev != NULL) {
14869 pktflag = VNDR_IE_BEACON_FLAG;
14871 case WL_PROBE_RESP:
14872 pktflag = VNDR_IE_PRBRSP_FLAG;
14874 case WL_ASSOC_RESP:
14875 pktflag = VNDR_IE_ASSOCRSP_FLAG;
14879 ret = wl_cfg80211_set_mgmt_vndr_ies(cfg,
14880 ndev_to_cfgdev(ndev), bssidx, pktflag, buf, len);
14887 #ifdef WL_SUPPORT_AUTO_CHANNEL
14889 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
14892 s32 ret = BCME_ERROR;
14893 struct bcm_cfg80211 *cfg = g_bcm_cfg;
14894 struct wiphy *wiphy;
14895 /* Disable mpc, to avoid automatic interface down. */
14898 wiphy = bcmcfg_to_wiphy(cfg);
14899 if (wl_check_dongle_idle(wiphy) != TRUE) {
14900 WL_ERR(("FW is busy to add interface"));
14903 ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
14904 sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
14905 &cfg->ioctl_buf_sync);
14907 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
14911 /* Set interface up, explicitly. */
14914 ret = wldev_ioctl(ndev, WLC_UP, (void *)&val, sizeof(val), true);
14916 WL_ERR(("set interface up failed, error = %d\n", ret));
14920 /* Stop all scan explicitly, till auto channel selection complete. */
14921 wl_set_drv_status(cfg, SCANNING, ndev);
14922 if (cfg->escan_info.ndev == NULL) {
14926 ret = wl_notify_escan_complete(cfg, ndev, true, true);
14928 WL_ERR(("set scan abort failed, error = %d\n", ret));
14937 wl_cfg80211_valid_channel_p2p(int channel)
14939 bool valid = false;
14941 /* channel 1 to 14 */
14942 if ((channel >= 1) && (channel <= 14)) {
14945 /* channel 36 to 48 */
14946 else if ((channel >= 36) && (channel <= 48)) {
14949 /* channel 149 to 161 */
14950 else if ((channel >= 149) && (channel <= 161)) {
14955 WL_INFORM(("invalid P2P chanspec, channel = %d\n", channel));
14962 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
14964 s32 ret = BCME_ERROR;
14965 struct bcm_cfg80211 *cfg = NULL;
14966 wl_uint32_list_t *list = NULL;
14967 chanspec_t chanspec = 0;
14969 memset(buf, 0, buflen);
14972 list = (wl_uint32_list_t *)buf;
14973 list->count = htod32(WL_NUMCHANSPECS);
14975 /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
14976 chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
14977 WL_CHANSPEC_CTL_SB_NONE);
14978 chanspec = wl_chspec_host_to_driver(chanspec);
14980 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
14981 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
14983 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
14990 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
14993 s32 ret = BCME_ERROR;
14996 struct bcm_cfg80211 *cfg = NULL;
14997 wl_uint32_list_t *list = NULL;
14998 chanspec_t chanspec = 0;
15000 memset(buf, 0, buflen);
15003 list = (wl_uint32_list_t *)buf;
15004 list->count = htod32(WL_NUMCHANSPECS);
15006 /* Restrict channels to 5GHz, 20MHz BW, no SB. */
15007 chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
15008 WL_CHANSPEC_CTL_SB_NONE);
15009 chanspec = wl_chspec_host_to_driver(chanspec);
15011 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
15012 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
15014 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
15018 /* Skip DFS and inavlid P2P channel. */
15019 for (i = 0, j = 0; i < dtoh32(list->count); i++) {
15020 chanspec = (chanspec_t) dtoh32(list->element[i]);
15021 channel = CHSPEC_CHANNEL(chanspec);
15023 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
15025 WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
15029 if (CHANNEL_IS_RADAR(channel) ||
15030 !(wl_cfg80211_valid_channel_p2p(CHSPEC_CHANNEL(chanspec)))) {
15033 list->element[j] = list->element[i];
15046 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
15049 s32 ret = BCME_ERROR;
15054 /* Start auto channel selection scan. */
15055 ret = wldev_ioctl(ndev, WLC_START_CHANNEL_SEL, buf, buflen, true);
15057 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
15062 /* Wait for auto channel selection, worst case possible delay is 5250ms. */
15063 retry = CHAN_SEL_RETRY_COUNT;
15066 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
15068 ret = wldev_ioctl(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen),
15070 if ((ret == 0) && (dtoh32(chosen) != 0)) {
15071 chip = dhd_conf_get_chip(dhd_get_pub(ndev));
15072 if (chip != BCM43362_CHIP_ID && chip != BCM4330_CHIP_ID) {
15075 chanspec = wl_chspec_driver_to_host(chosen);
15076 printf("selected chanspec = 0x%x\n", chanspec);
15077 ctl_chan = wf_chspec_ctlchan(chanspec);
15078 printf("selected ctl_chan = 0x%x\n", ctl_chan);
15079 *channel = (u16)(ctl_chan & 0x00FF);
15081 *channel = (u16)(chosen & 0x00FF);
15082 WL_INFORM(("selected channel = %d\n", *channel));
15085 WL_INFORM(("attempt = %d, ret = %d, chosen = %d\n",
15086 (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
15090 WL_ERR(("failure, auto channel selection timed out\n"));
15100 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
15103 s32 ret = BCME_ERROR;
15104 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15106 /* Clear scan stop driver status. */
15107 wl_clr_drv_status(cfg, SCANNING, ndev);
15109 /* Enable mpc back to 1, irrespective of initial state. */
15112 ret = wldev_iovar_setbuf_bsscfg(ndev, "mpc", (void *)&val,
15113 sizeof(val), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
15114 &cfg->ioctl_buf_sync);
15116 WL_ERR(("set 'mpc' failed, error = %d\n", ret));
15123 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
15125 int channel = 0, band, band_cur;
15126 s32 ret = BCME_ERROR;
15129 struct bcm_cfg80211 *cfg = NULL;
15130 struct net_device *ndev = NULL;
15132 memset(cmd, 0, total_len);
15134 buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
15136 WL_ERR(("failed to allocate chanspec buffer\n"));
15141 * Always use primary interface, irrespective of interface on which
15145 ndev = bcmcfg_to_prmry_ndev(cfg);
15148 * Make sure that FW and driver are in right state to do auto channel
15151 ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
15153 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
15157 /* Best channel selection in 2.4GHz band. */
15158 ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
15160 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
15164 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
15167 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
15171 if (CHANNEL_IS_2G(channel)) {
15172 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
15174 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
15178 pos += snprintf(pos, total_len, "%04d ", channel);
15180 // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
15181 ret = wldev_ioctl(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur), false);
15182 band = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
15183 ret = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
15185 WL_ERR(("WLC_SET_BAND error %d\n", ret));
15187 /* Best channel selection in 5GHz band. */
15188 ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
15190 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
15194 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
15197 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
15201 if (CHANNEL_IS_5G(channel)) {
15202 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
15204 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
15208 ret = wldev_ioctl(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur), true);
15210 WL_ERR(("WLC_SET_BAND error %d\n", ret));
15212 pos += snprintf(pos, total_len, "%04d ", channel);
15214 /* Set overall best channel same as 5GHz best channel. */
15215 pos += snprintf(pos, total_len, "%04d ", channel);
15222 /* Restore FW and driver back to normal state. */
15223 ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
15225 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
15228 printf("%s: channel %s\n", __FUNCTION__, cmd);
15230 return (pos - cmd);
15232 #endif /* WL_SUPPORT_AUTO_CHANNEL */
15234 static const struct rfkill_ops wl_rfkill_ops = {
15235 .set_block = wl_rfkill_set
15238 static int wl_rfkill_set(void *data, bool blocked)
15240 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
15242 WL_DBG(("Enter \n"));
15243 WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
15248 cfg->rf_blocked = blocked;
15253 static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup)
15257 WL_DBG(("Enter \n"));
15261 cfg->rfkill = rfkill_alloc("brcmfmac-wifi",
15262 wl_cfg80211_get_parent_dev(),
15263 RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)cfg);
15265 if (!cfg->rfkill) {
15270 err = rfkill_register(cfg->rfkill);
15273 rfkill_destroy(cfg->rfkill);
15275 if (!cfg->rfkill) {
15280 rfkill_unregister(cfg->rfkill);
15281 rfkill_destroy(cfg->rfkill);
15288 #ifdef DEBUGFS_CFG80211
15290 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
15291 * to turn on SCAN and DBG log.
15292 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
15293 * To see current setting of debug level,
15294 * cat /sys/kernel/debug/dhd/debug_level
15297 wl_debuglevel_write(struct file *file, const char __user *userbuf,
15298 size_t count, loff_t *ppos)
15300 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
15301 char *params, *token, *colon;
15302 uint i, tokens, log_on = 0;
15303 memset(tbuf, 0, sizeof(tbuf));
15304 memset(sublog, 0, sizeof(sublog));
15305 if (copy_from_user(&tbuf, userbuf, min_t(size_t, (sizeof(tbuf) - 1), count)))
15309 colon = strchr(params, '\n');
15312 while ((token = strsep(¶ms, " ")) != NULL) {
15313 memset(sublog, 0, sizeof(sublog));
15314 if (token == NULL || !*token)
15316 if (*token == '\0')
15318 colon = strchr(token, ':');
15319 if (colon != NULL) {
15322 tokens = sscanf(token, "%s %u", sublog, &log_on);
15327 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
15328 if (!strncmp(sublog, sublogname_map[i].sublogname,
15329 strlen(sublogname_map[i].sublogname))) {
15332 (sublogname_map[i].log_level);
15335 ~(sublogname_map[i].log_level);
15339 WL_ERR(("%s: can't parse '%s' as a "
15340 "SUBMODULE:LEVEL (%d tokens)\n",
15341 tbuf, token, tokens));
15349 wl_debuglevel_read(struct file *file, char __user *user_buf,
15350 size_t count, loff_t *ppos)
15353 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
15355 memset(tbuf, 0, sizeof(tbuf));
15357 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
15358 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
15359 sublogname_map[i].sublogname,
15360 (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
15363 return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
15366 static const struct file_operations fops_debuglevel = {
15368 .write = wl_debuglevel_write,
15369 .read = wl_debuglevel_read,
15370 .owner = THIS_MODULE,
15374 static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg)
15377 struct dentry *_dentry;
15380 cfg->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
15381 if (!cfg->debugfs || IS_ERR(cfg->debugfs)) {
15382 if (cfg->debugfs == ERR_PTR(-ENODEV))
15383 WL_ERR(("Debugfs is not enabled on this kernel\n"));
15385 WL_ERR(("Can not create debugfs directory\n"));
15386 cfg->debugfs = NULL;
15390 _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
15391 cfg->debugfs, cfg, &fops_debuglevel);
15392 if (!_dentry || IS_ERR(_dentry)) {
15393 WL_ERR(("failed to create debug_level debug file\n"));
15394 wl_free_debugfs(cfg);
15399 static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg)
15404 debugfs_remove_recursive(cfg->debugfs);
15405 cfg->debugfs = NULL;
15408 #endif /* DEBUGFS_CFG80211 */
15410 struct device *wl_cfg80211_get_parent_dev(void)
15412 return cfg80211_parent_dev;
15415 void wl_cfg80211_set_parent_dev(void *dev)
15417 cfg80211_parent_dev = dev;
15420 static void wl_cfg80211_clear_parent_dev(void)
15422 cfg80211_parent_dev = NULL;
15425 void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
15427 wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr", NULL,
15428 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
15429 memcpy(mac->octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
15431 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role)
15433 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
15434 if (((dev_role == NL80211_IFTYPE_AP) &&
15435 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
15436 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
15437 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
15439 WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role, dhd->op_mode));
15445 int wl_cfg80211_do_driver_init(struct net_device *net)
15447 struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
15449 if (!cfg || !cfg->wdev)
15452 if (dhd_do_driver_init(cfg->wdev->netdev) < 0)
15458 void wl_cfg80211_enable_trace(u32 level)
15460 wl_dbg_level = level;
15461 printf("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level);
15464 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
15467 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
15468 bcm_struct_cfgdev *cfgdev, u64 cookie)
15470 /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
15471 * is passed with CMD_FRAME. This callback is supposed to cancel
15472 * the OFFCHANNEL Wait. Since we are already taking care of that
15473 * with the tx_mgmt logic, do nothing here.
15478 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
15482 wl_cfg80211_find_interworking_ie(u8 *parse, u32 len)
15486 while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_INTERWORKING_ID))) {
15487 return (bcm_tlv_t *)ie;
15494 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
15495 uint8 ie_id, uint8 *data, uint8 data_len)
15500 ie_setbuf_t *ie_setbuf;
15502 if (ie_id != DOT11_MNG_INTERWORKING_ID)
15503 return BCME_UNSUPPORTED;
15505 /* Validate the pktflag parameter */
15506 if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
15507 VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
15508 VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
15509 VNDR_IE_CUSTOM_FLAG))) {
15510 WL_ERR(("cfg80211 Add IE: Invalid packet flag 0x%x\n", pktflag));
15514 /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
15515 pktflag = htod32(pktflag);
15517 buf_len = sizeof(ie_setbuf_t) + data_len - 1;
15518 ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL);
15521 WL_ERR(("Error allocating buffer for IE\n"));
15525 if (cfg->iw_ie_len == data_len && !memcmp(cfg->iw_ie, data, data_len)) {
15526 WL_ERR(("Previous IW IE is equals to current IE\n"));
15531 strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1);
15532 ie_setbuf->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
15534 /* Buffer contains only 1 IE */
15535 iecount = htod32(1);
15536 memcpy((void *)&ie_setbuf->ie_buffer.iecount, &iecount, sizeof(int));
15537 memcpy((void *)&ie_setbuf->ie_buffer.ie_list[0].pktflag, &pktflag, sizeof(uint32));
15539 /* Now, add the IE to the buffer */
15540 ie_setbuf->ie_buffer.ie_list[0].ie_data.id = ie_id;
15542 /* if already set with previous values, delete it first */
15543 if (cfg->iw_ie_len != 0) {
15544 WL_DBG(("Different IW_IE was already set. clear first\n"));
15546 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = 0;
15548 err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
15549 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
15551 if (err != BCME_OK)
15555 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
15556 memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len);
15558 err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
15559 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
15561 if (err == BCME_OK) {
15562 memcpy(cfg->iw_ie, data, data_len);
15563 cfg->iw_ie_len = data_len;
15566 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
15577 wl_cfg80211_dfs_ap_move(struct net_device *ndev, char *data, char *command, int total_len)
15579 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15580 char ioctl_buf[50];
15583 chanspec_t chanspec = 0;
15585 int bytes_written = 0;
15586 wl_dfs_ap_move_status_t *status;
15587 char chanbuf[CHANSPEC_STR_LEN];
15588 const char *dfs_state_str[DFS_SCAN_S_MAX] = {
15589 "Radar Free On Channel",
15590 "Radar Found On Channel",
15591 "Radar Scan In Progress",
15592 "Radar Scan Aborted",
15593 "RSDB Mode switch in Progress For Scan"
15595 if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
15596 bytes_written = snprintf(command, total_len, "AP is not UP\n");
15597 return bytes_written;
15600 if ((err = wldev_iovar_getbuf(ndev, "dfs_ap_move", NULL, 0,
15601 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
15602 WL_ERR(("setting dfs_ap_move failed with err=%d \n", err));
15605 status = (wl_dfs_ap_move_status_t *)cfg->ioctl_buf;
15607 if (status->version != WL_DFS_AP_MOVE_VERSION) {
15608 err = BCME_UNSUPPORTED;
15609 WL_ERR(("err=%d version=%d\n", err, status->version));
15613 if (status->move_status != (int8) DFS_SCAN_S_IDLE) {
15614 chanspec = wl_chspec_driver_to_host(status->chanspec);
15615 if (chanspec != 0 && chanspec != INVCHANSPEC) {
15616 wf_chspec_ntoa(chanspec, chanbuf);
15617 bytes_written = snprintf(command, total_len,
15618 "AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
15620 bytes_written += snprintf(command + bytes_written, total_len,
15621 "%s\n", dfs_state_str[status->move_status]);
15622 return bytes_written;
15624 bytes_written = snprintf(command, total_len, "dfs AP move in IDLE state\n");
15625 return bytes_written;
15630 abort = bcm_atoi(data);
15632 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &abort,
15633 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
15634 WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
15638 chanspec = wf_chspec_aton(data);
15639 if (chanspec != 0) {
15640 val = wl_chspec_host_to_driver(chanspec);
15641 if (val != INVCHANSPEC) {
15642 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &val,
15643 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
15644 WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
15647 WL_DBG((" set dfs_ap_move successfull"));
15649 err = BCME_USAGE_ERROR;
15657 wl_cfg80211_wbtext_config(struct net_device *ndev, char *data, char *command, int total_len)
15660 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15661 wl_roam_prof_band_t *rp;
15662 int err = -EINVAL, bytes_written = 0;
15663 size_t len = strlen(data);
15666 rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
15667 * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
15668 if (unlikely(!rp)) {
15669 WL_ERR(("%s: failed to allocate memory\n", __func__));
15674 rp->ver = WL_MAX_ROAM_PROF_VER;
15675 if (*data && (!strncmp(data, "b", 1))) {
15676 rp->band = WLC_BAND_2G;
15677 } else if (*data && (!strncmp(data, "a", 1))) {
15678 rp->band = WLC_BAND_5G;
15680 err = snprintf(command, total_len, "Missing band\n");
15685 /* Getting roam profile from fw */
15686 if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
15687 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
15688 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
15691 memcpy(rp, cfg->ioctl_buf, sizeof(*rp) * WL_MAX_ROAM_PROF_BRACKETS);
15692 /* roam_prof version get */
15693 if (rp->ver != WL_MAX_ROAM_PROF_VER) {
15694 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
15698 if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
15699 WL_ERR(("bad length (=%d) in return data\n", rp->len));
15705 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15706 /* printing contents of roam profile data from fw and exits
15707 * if code hits any of one of the below condtion. If remaining
15708 * length of buffer is less than roam profile size or
15709 * if there is no valid entry.
15711 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
15712 (rp->roam_prof[i].fullscan_period == 0)) {
15715 bytes_written += snprintf(command+bytes_written,
15716 total_len, "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)\n",
15717 rp->roam_prof[i].roam_trigger, rp->roam_prof[i].rssi_lower,
15718 rp->roam_prof[i].channel_usage,
15719 rp->roam_prof[i].cu_avg_calc_dur);
15721 err = bytes_written;
15724 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15725 /* reading contents of roam profile data from fw and exits
15726 * if code hits any of one of the below condtion, If remaining
15727 * length of buffer is less than roam profile size or if there
15728 * is no valid entry.
15730 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
15731 (rp->roam_prof[i].fullscan_period == 0)) {
15735 /* Do not set roam_prof from upper layer if fw doesn't have 2 rows */
15737 WL_ERR(("FW must have 2 rows to fill roam_prof\n"));
15741 /* setting roam profile to fw */
15743 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
15744 rp->roam_prof[i].roam_trigger = simple_strtol(data, &data, 10);
15746 rp->roam_prof[i].rssi_lower = simple_strtol(data, &data, 10);
15748 rp->roam_prof[i].channel_usage = simple_strtol(data, &data, 10);
15750 rp->roam_prof[i].cu_avg_calc_dur = simple_strtol(data, &data, 10);
15752 rp_len += sizeof(wl_roam_prof_t);
15753 if (*data == '\0') {
15759 WL_ERR(("Only two roam_prof rows supported.\n"));
15764 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
15765 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
15766 WL_ERR(("seting roam_profile failed with err %d\n", err));
15776 int wl_cfg80211_wbtext_weight_config(struct net_device *ndev, char *data,
15777 char *command, int total_len)
15779 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15780 int bytes_written = 0, err = -EINVAL, argc = 0;
15781 char rssi[5], band[5], weight[5];
15782 char *endptr = NULL;
15783 wnm_bss_select_weight_cfg_t *bwcfg;
15785 bwcfg = kzalloc(sizeof(*bwcfg), GFP_KERNEL);
15786 if (unlikely(!bwcfg)) {
15787 WL_ERR(("%s: failed to allocate memory\n", __func__));
15791 bwcfg->version = WNM_BSSLOAD_MONITOR_VERSION;
15795 argc = sscanf(data, "%s %s %s", rssi, band, weight);
15797 if (!strcasecmp(rssi, "rssi"))
15798 bwcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
15799 else if (!strcasecmp(rssi, "cu"))
15800 bwcfg->type = WNM_BSS_SELECT_TYPE_CU;
15802 /* Usage DRIVER WBTEXT_WEIGHT_CONFIG <rssi/cu> <band> <weight> */
15803 WL_ERR(("%s: Command usage error\n", __func__));
15807 if (!strcasecmp(band, "a"))
15808 bwcfg->band = WLC_BAND_5G;
15809 else if (!strcasecmp(band, "b"))
15810 bwcfg->band = WLC_BAND_2G;
15811 else if (!strcasecmp(band, "all"))
15812 bwcfg->band = WLC_BAND_ALL;
15814 WL_ERR(("%s: Command usage error\n", __func__));
15819 /* If there is no data after band, getting wnm_bss_select_weight from fw */
15820 if (bwcfg->band == WLC_BAND_ALL) {
15821 WL_ERR(("band option \"all\" is for set only, not get\n"));
15824 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_weight", bwcfg,
15826 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
15827 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d \n", err));
15830 memcpy(bwcfg, cfg->ioctl_buf, sizeof(*bwcfg));
15831 bytes_written = snprintf(command, total_len, "%s %s weight = %d\n",
15832 (bwcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU",
15833 (bwcfg->band == WLC_BAND_2G) ? "2G" : "5G", bwcfg->weight);
15834 err = bytes_written;
15837 /* if weight is non integer returns command usage error */
15838 bwcfg->weight = simple_strtol(weight, &endptr, 0);
15839 if (*endptr != '\0') {
15840 WL_ERR(("%s: Command usage error", __func__));
15843 /* setting weight for iovar wnm_bss_select_weight to fw */
15844 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_weight", bwcfg,
15846 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
15847 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d\n", err));
15857 /* WBTEXT_TUPLE_MIN_LEN_CHECK :strlen(low)+" "+strlen(high)+" "+strlen(factor) */
15858 #define WBTEXT_TUPLE_MIN_LEN_CHECK 5
15860 int wl_cfg80211_wbtext_table_config(struct net_device *ndev, char *data,
15861 char *command, int total_len)
15863 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15864 int bytes_written = 0, err = -EINVAL;
15865 char rssi[5], band[5];
15866 int btcfg_len = 0, i = 0, parsed_len = 0;
15867 wnm_bss_select_factor_cfg_t *btcfg;
15868 size_t slen = strlen(data);
15869 char *start_addr = NULL;
15872 btcfg = kzalloc((sizeof(*btcfg) + sizeof(*btcfg) *
15873 WL_FACTOR_TABLE_MAX_LIMIT), GFP_KERNEL);
15874 if (unlikely(!btcfg)) {
15875 WL_ERR(("%s: failed to allocate memory\n", __func__));
15880 btcfg->version = WNM_BSS_SELECT_FACTOR_VERSION;
15881 btcfg->band = WLC_BAND_AUTO;
15885 sscanf(data, "%s %s", rssi, band);
15887 if (!strcasecmp(rssi, "rssi")) {
15888 btcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
15890 else if (!strcasecmp(rssi, "cu")) {
15891 btcfg->type = WNM_BSS_SELECT_TYPE_CU;
15894 WL_ERR(("%s: Command usage error\n", __func__));
15898 if (!strcasecmp(band, "a")) {
15899 btcfg->band = WLC_BAND_5G;
15901 else if (!strcasecmp(band, "b")) {
15902 btcfg->band = WLC_BAND_2G;
15904 else if (!strcasecmp(band, "all")) {
15905 btcfg->band = WLC_BAND_ALL;
15908 WL_ERR(("%s: Command usage, Wrong band\n", __func__));
15912 if ((slen - 1) == (strlen(rssi) + strlen(band))) {
15913 /* Getting factor table using iovar 'wnm_bss_select_table' from fw */
15914 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_table", btcfg,
15916 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
15917 WL_ERR(("Getting wnm_bss_select_table failed with err=%d \n", err));
15920 memcpy(btcfg, cfg->ioctl_buf, sizeof(*btcfg));
15921 memcpy(btcfg, cfg->ioctl_buf, (btcfg->count+1) * sizeof(*btcfg));
15923 bytes_written += snprintf(command + bytes_written, total_len,
15924 "No of entries in table: %d\n", btcfg->count);
15925 bytes_written += snprintf(command + bytes_written, total_len, "%s factor table\n",
15926 (btcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU");
15927 bytes_written += snprintf(command + bytes_written, total_len,
15928 "low\thigh\tfactor\n");
15929 for (i = 0; i <= btcfg->count-1; i++) {
15930 bytes_written += snprintf(command + bytes_written, total_len,
15931 "%d\t%d\t%d\n", btcfg->params[i].low, btcfg->params[i].high,
15932 btcfg->params[i].factor);
15934 err = bytes_written;
15937 memset(btcfg->params, 0, sizeof(*btcfg) * WL_FACTOR_TABLE_MAX_LIMIT);
15938 data += (strlen(rssi) + strlen(band) + 2);
15940 slen = slen - (strlen(rssi) + strlen(band) + 2);
15941 for (i = 0; i < WL_FACTOR_TABLE_MAX_LIMIT; i++) {
15942 if (parsed_len + WBTEXT_TUPLE_MIN_LEN_CHECK <= slen) {
15943 btcfg->params[i].low = simple_strtol(data, &data, 10);
15945 btcfg->params[i].high = simple_strtol(data, &data, 10);
15947 btcfg->params[i].factor = simple_strtol(data, &data, 10);
15949 if (*data == '\0') {
15953 parsed_len = data - start_addr;
15955 WL_ERR(("%s:Command usage:less no of args\n", __func__));
15959 btcfg_len = sizeof(*btcfg) + ((btcfg->count) * sizeof(*btcfg));
15960 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_table", btcfg, btcfg_len,
15961 cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
15962 WL_ERR(("seting wnm_bss_select_table failed with err %d\n", err));
15974 wl_cfg80211_wbtext_delta_config(struct net_device *ndev, char *data, char *command, int total_len)
15977 struct bcm_cfg80211 *cfg = g_bcm_cfg;
15978 int err = -EINVAL, bytes_written = 0, argc = 0, val, len = 0;
15979 char delta[5], band[5], *endptr = NULL;
15980 wl_roam_prof_band_t *rp;
15982 rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
15983 * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
15984 if (unlikely(!rp)) {
15985 WL_ERR(("%s: failed to allocate memory\n", __func__));
15990 argc = sscanf(data, "%s %s", band, delta);
15991 if (!strcasecmp(band, "a"))
15992 rp->band = WLC_BAND_5G;
15993 else if (!strcasecmp(band, "b"))
15994 rp->band = WLC_BAND_2G;
15996 WL_ERR(("%s: Missing band\n", __func__));
15999 /* Getting roam profile from fw */
16000 if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
16001 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
16002 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
16005 memcpy(rp, cfg->ioctl_buf, sizeof(wl_roam_prof_band_t));
16006 if (rp->ver != WL_MAX_ROAM_PROF_VER) {
16007 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
16011 if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
16012 WL_ERR(("bad length (=%d) in return data\n", rp->len));
16018 /* if delta is non integer returns command usage error */
16019 val = simple_strtol(delta, &endptr, 0);
16020 if (*endptr != '\0') {
16021 WL_ERR(("%s: Command usage error", __func__));
16024 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
16026 * Checking contents of roam profile data from fw and exits
16027 * if code hits below condtion. If remaining length of buffer is
16028 * less than roam profile size or if there is no valid entry.
16030 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
16031 (rp->roam_prof[i].fullscan_period == 0)) {
16034 if (rp->roam_prof[i].channel_usage != 0) {
16035 rp->roam_prof[i].roam_delta = val;
16037 len += sizeof(wl_roam_prof_t);
16041 if (rp->roam_prof[i].channel_usage != 0) {
16042 bytes_written = snprintf(command, total_len,
16043 "%s Delta %d\n", (rp->band == WLC_BAND_2G) ? "2G" : "5G",
16044 rp->roam_prof[0].roam_delta);
16046 err = bytes_written;
16050 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
16051 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL)) < 0) {
16052 WL_ERR(("seting roam_profile failed with err %d\n", err));
16062 int wl_cfg80211_scan_stop(bcm_struct_cfgdev *cfgdev)
16064 struct bcm_cfg80211 *cfg = NULL;
16065 struct net_device *ndev = NULL;
16066 unsigned long flags;
16067 int clear_flag = 0;
16070 WL_TRACE(("Enter\n"));
16076 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16078 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
16079 #ifdef WL_CFG80211_P2P_DEV_IF
16080 if (cfg->scan_request && cfg->scan_request->wdev == cfgdev)
16082 if (cfg->scan_request && cfg->scan_request->dev == cfgdev)
16085 cfg80211_scan_done(cfg->scan_request, true);
16086 cfg->scan_request = NULL;
16089 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
16092 wl_clr_drv_status(cfg, SCANNING, ndev);
16097 bool wl_cfg80211_is_concurrent_mode(void)
16099 if ((g_bcm_cfg) && (wl_get_drv_status_all(g_bcm_cfg, CONNECTED) > 1)) {
16106 void* wl_cfg80211_get_dhdp()
16108 struct bcm_cfg80211 *cfg = g_bcm_cfg;
16113 bool wl_cfg80211_is_p2p_active(void)
16115 return (g_bcm_cfg && g_bcm_cfg->p2p);
16118 bool wl_cfg80211_is_roam_offload(void)
16120 return (g_bcm_cfg && g_bcm_cfg->roam_offload);
16123 bool wl_cfg80211_is_event_from_connected_bssid(const wl_event_msg_t *e, int ifidx)
16125 dhd_pub_t *dhd = NULL;
16126 struct net_device *ndev = NULL;
16127 u8 *curbssid = NULL;
16129 dhd = (dhd_pub_t *)(g_bcm_cfg->pub);
16132 ndev = dhd_idx2net(dhd, ifidx);
16135 if (!dhd || !ndev) {
16139 curbssid = wl_read_prof(g_bcm_cfg, ndev, WL_PROF_BSSID);
16141 return memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0;
16144 static void wl_cfg80211_work_handler(struct work_struct * work)
16146 struct bcm_cfg80211 *cfg = NULL;
16147 struct net_info *iter, *next;
16150 BCM_SET_CONTAINER_OF(cfg, work, struct bcm_cfg80211, pm_enable_work.work);
16151 WL_DBG(("Enter \n"));
16152 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16153 4 && __GNUC_MINOR__ >= 6))
16154 _Pragma("GCC diagnostic push")
16155 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16157 for_each_ndev(cfg, iter, next) {
16158 /* p2p discovery iface ndev could be null */
16160 if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev) ||
16161 (wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_BSS &&
16162 wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_IBSS))
16165 if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM,
16166 &pm, sizeof(pm), true)) != 0) {
16167 if (err == -ENODEV)
16168 WL_DBG(("%s:netdev not ready\n",
16169 iter->ndev->name));
16171 WL_ERR(("%s:error (%d)\n",
16172 iter->ndev->name, err));
16174 wl_cfg80211_update_power_mode(iter->ndev);
16178 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16179 4 && __GNUC_MINOR__ >= 6))
16180 _Pragma("GCC diagnostic pop")
16182 DHD_OS_WAKE_UNLOCK(cfg->pub);
16186 wl_get_action_category(void *frame, u32 frame_len)
16189 u8 *ptr = (u8 *)frame;
16191 return DOT11_ACTION_CAT_ERR_MASK;
16192 if (frame_len < DOT11_ACTION_HDR_LEN)
16193 return DOT11_ACTION_CAT_ERR_MASK;
16194 category = ptr[DOT11_ACTION_CAT_OFF];
16195 WL_INFORM(("Action Category: %d\n", category));
16200 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
16202 u8 *ptr = (u8 *)frame;
16203 if (frame == NULL || ret_action == NULL)
16205 if (frame_len < DOT11_ACTION_HDR_LEN)
16207 if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
16209 *ret_action = ptr[DOT11_ACTION_ACT_OFF];
16210 WL_INFORM(("Public Action : %d\n", *ret_action));
16216 wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
16217 const struct ether_addr *bssid)
16222 bzero(&e, sizeof(e));
16223 e.event_type = cpu_to_be32(WLC_E_BSSID);
16224 memcpy(&e.addr, bssid, ETHER_ADDR_LEN);
16225 /* trigger the roam event handler */
16226 WL_INFORM(("Delayed roam to " MACDBG "\n", MAC2STRDBG((u8*)(bssid))));
16227 err = wl_notify_roaming_status(cfg, ndev_to_cfgdev(ndev), &e, NULL);
16233 wl_cfg80211_parse_vndr_ies(u8 *parse, u32 len,
16234 struct parsed_vndr_ies *vndr_ies)
16239 struct parsed_vndr_ie_info *parsed_info;
16243 remained_len = (s32)len;
16244 memset(vndr_ies, 0, sizeof(*vndr_ies));
16246 WL_INFORM(("---> len %d\n", len));
16247 ie = (bcm_tlv_t *) parse;
16248 if (!bcm_valid_tlv(ie, remained_len))
16251 if (count >= MAX_VNDR_IE_NUMBER)
16253 if (ie->id == DOT11_MNG_VS_ID) {
16254 vndrie = (vndr_ie_t *) ie;
16255 /* len should be bigger than OUI length + one data length at least */
16256 if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
16257 WL_ERR(("%s: invalid vndr ie. length is too small %d\n",
16258 __FUNCTION__, vndrie->len));
16261 /* if wpa or wme ie, do not add ie */
16262 if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) &&
16263 ((vndrie->data[0] == WPA_OUI_TYPE) ||
16264 (vndrie->data[0] == WME_OUI_TYPE))) {
16265 CFGP2P_DBG(("Found WPA/WME oui. Do not add it\n"));
16269 parsed_info = &vndr_ies->ie_info[count++];
16271 /* save vndr ie information */
16272 parsed_info->ie_ptr = (char *)vndrie;
16273 parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN);
16274 memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t));
16275 vndr_ies->count = count;
16277 WL_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x len:%d\n",
16278 parsed_info->vndrie.oui[0], parsed_info->vndrie.oui[1],
16279 parsed_info->vndrie.oui[2], parsed_info->vndrie.data[0],
16280 parsed_info->ie_len));
16283 ie = bcm_next_tlv(ie, &remained_len);
16289 wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, s32 bssidx)
16292 struct net_info *netinfo;
16293 s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG,
16294 VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
16296 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16297 if (!netinfo || !netinfo->wdev) {
16298 WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
16302 WL_DBG(("clear management vendor IEs for bssidx:%d \n", bssidx));
16303 /* Clear the IEs set in the firmware so that host is in sync with firmware */
16304 for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
16305 if (wl_cfg80211_set_mgmt_vndr_ies(cfg, wdev_to_cfgdev(netinfo->wdev),
16306 bssidx, vndrie_flag[index], NULL, 0) < 0)
16307 WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
16314 wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg)
16316 struct net_info *iter, *next;
16318 WL_DBG(("clear management vendor IEs \n"));
16319 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16320 4 && __GNUC_MINOR__ >= 6))
16321 _Pragma("GCC diagnostic push")
16322 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16324 for_each_ndev(cfg, iter, next) {
16325 wl_cfg80211_clear_per_bss_ies(cfg, iter->bssidx);
16327 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16328 4 && __GNUC_MINOR__ >= 6))
16329 _Pragma("GCC diagnostic pop")
16334 #define WL_VNDR_IE_MAXLEN 2048
16335 static s8 g_mgmt_ie_buf[WL_VNDR_IE_MAXLEN];
16337 wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16338 s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
16340 struct net_device *ndev = NULL;
16342 u8 *curr_ie_buf = NULL;
16343 u8 *mgmt_ie_buf = NULL;
16344 u32 mgmt_ie_buf_len = 0;
16345 u32 *mgmt_ie_len = 0;
16346 u32 del_add_ie_buf_len = 0;
16347 u32 total_ie_buf_len = 0;
16348 u32 parsed_ie_buf_len = 0;
16349 struct parsed_vndr_ies old_vndr_ies;
16350 struct parsed_vndr_ies new_vndr_ies;
16353 s32 remained_buf_len;
16354 wl_bss_vndr_ies_t *ies = NULL;
16355 struct net_info *netinfo;
16357 WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d \n",
16358 pktflag, bssidx, vndr_ie_len));
16360 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16362 if (bssidx > WL_MAX_IFS) {
16363 WL_ERR(("bssidx > supported concurrent Ifaces \n"));
16367 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16369 WL_ERR(("net_info ptr is NULL \n"));
16373 /* Clear the global buffer */
16374 memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf));
16375 curr_ie_buf = g_mgmt_ie_buf;
16376 ies = &netinfo->bss.ies;
16379 case VNDR_IE_PRBRSP_FLAG :
16380 mgmt_ie_buf = ies->probe_res_ie;
16381 mgmt_ie_len = &ies->probe_res_ie_len;
16382 mgmt_ie_buf_len = sizeof(ies->probe_res_ie);
16384 case VNDR_IE_ASSOCRSP_FLAG :
16385 mgmt_ie_buf = ies->assoc_res_ie;
16386 mgmt_ie_len = &ies->assoc_res_ie_len;
16387 mgmt_ie_buf_len = sizeof(ies->assoc_res_ie);
16389 case VNDR_IE_BEACON_FLAG :
16390 mgmt_ie_buf = ies->beacon_ie;
16391 mgmt_ie_len = &ies->beacon_ie_len;
16392 mgmt_ie_buf_len = sizeof(ies->beacon_ie);
16394 case VNDR_IE_PRBREQ_FLAG :
16395 mgmt_ie_buf = ies->probe_req_ie;
16396 mgmt_ie_len = &ies->probe_req_ie_len;
16397 mgmt_ie_buf_len = sizeof(ies->probe_req_ie);
16399 case VNDR_IE_ASSOCREQ_FLAG :
16400 mgmt_ie_buf = ies->assoc_req_ie;
16401 mgmt_ie_len = &ies->assoc_req_ie_len;
16402 mgmt_ie_buf_len = sizeof(ies->assoc_req_ie);
16405 mgmt_ie_buf = NULL;
16406 mgmt_ie_len = NULL;
16407 WL_ERR(("not suitable packet type (%d)\n", pktflag));
16411 if (vndr_ie_len > mgmt_ie_buf_len) {
16412 WL_ERR(("extra IE size too big\n"));
16415 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
16416 if (vndr_ie && vndr_ie_len && curr_ie_buf) {
16418 /* must discard vndr_ie constness, attempt to change vndr_ie arg to non-const
16419 * causes cascade of errors in other places, fix involves const casts there
16421 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16422 4 && __GNUC_MINOR__ >= 6))
16423 _Pragma("GCC diagnostic push")
16424 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16426 if ((ret = wl_cfg80211_parse_vndr_ies((u8 *)vndr_ie,
16427 vndr_ie_len, &new_vndr_ies)) < 0) {
16428 WL_ERR(("parse vndr ie failed \n"));
16431 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16432 4 && __GNUC_MINOR__ >= 6))
16433 _Pragma("GCC diagnostic pop")
16435 for (i = 0; i < new_vndr_ies.count; i++) {
16436 struct parsed_vndr_ie_info *vndrie_info =
16437 &new_vndr_ies.ie_info[i];
16439 if ((parsed_ie_buf_len + vndrie_info->ie_len) > WL_VNDR_IE_MAXLEN) {
16440 WL_ERR(("IE size is too big (%d > %d)\n",
16441 parsed_ie_buf_len, WL_VNDR_IE_MAXLEN));
16446 memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
16447 vndrie_info->ie_len);
16448 parsed_ie_buf_len += vndrie_info->ie_len;
16452 if (mgmt_ie_buf != NULL) {
16453 if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
16454 (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) {
16455 WL_INFORM(("Previous mgmt IE is equals to current IE"));
16459 /* parse old vndr_ie */
16460 if ((ret = wl_cfg80211_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len,
16461 &old_vndr_ies)) < 0) {
16462 WL_ERR(("parse vndr ie failed \n"));
16465 /* make a command to delete old ie */
16466 for (i = 0; i < old_vndr_ies.count; i++) {
16467 struct parsed_vndr_ie_info *vndrie_info =
16468 &old_vndr_ies.ie_info[i];
16470 WL_INFORM(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
16471 vndrie_info->vndrie.id, vndrie_info->vndrie.len,
16472 vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
16473 vndrie_info->vndrie.oui[2]));
16475 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
16476 pktflag, vndrie_info->vndrie.oui,
16477 vndrie_info->vndrie.id,
16478 vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
16479 vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
16482 curr_ie_buf += del_add_ie_buf_len;
16483 total_ie_buf_len += del_add_ie_buf_len;
16488 /* Add if there is any extra IE */
16489 if (mgmt_ie_buf && parsed_ie_buf_len) {
16492 remained_buf_len = mgmt_ie_buf_len;
16494 /* make a command to add new ie */
16495 for (i = 0; i < new_vndr_ies.count; i++) {
16496 struct parsed_vndr_ie_info *vndrie_info =
16497 &new_vndr_ies.ie_info[i];
16499 WL_INFORM(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
16500 vndrie_info->vndrie.id, vndrie_info->vndrie.len,
16501 vndrie_info->ie_len - 2,
16502 vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
16503 vndrie_info->vndrie.oui[2]));
16505 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
16506 pktflag, vndrie_info->vndrie.oui,
16507 vndrie_info->vndrie.id,
16508 vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
16509 vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
16512 /* verify remained buf size before copy data */
16513 if (remained_buf_len >= vndrie_info->ie_len) {
16514 remained_buf_len -= vndrie_info->ie_len;
16516 WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
16517 "found vndr ies # = %d(cur %d), remained len %d, "
16518 "cur mgmt_ie_len %d, new ie len = %d\n",
16519 pktflag, new_vndr_ies.count, i, remained_buf_len,
16520 *mgmt_ie_len, vndrie_info->ie_len));
16524 /* save the parsed IE in cfg struct */
16525 memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
16526 vndrie_info->ie_len);
16527 *mgmt_ie_len += vndrie_info->ie_len;
16528 curr_ie_buf += del_add_ie_buf_len;
16529 total_ie_buf_len += del_add_ie_buf_len;
16533 if (total_ie_buf_len && cfg->ioctl_buf != NULL) {
16534 ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
16535 total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
16536 bssidx, &cfg->ioctl_buf_sync);
16538 WL_ERR(("vndr ie set error : %d\n", ret));
16546 #ifdef WL_CFG80211_ACL
16548 wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
16549 const struct cfg80211_acl_data *acl)
16554 int macmode = MACLIST_MODE_DISABLED;
16555 struct maclist *list;
16557 /* get the MAC filter mode */
16558 if (acl && acl->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED) {
16559 macmode = MACLIST_MODE_ALLOW;
16560 } else if (acl && acl->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
16561 acl->n_acl_entries) {
16562 macmode = MACLIST_MODE_DENY;
16565 /* if acl == NULL, macmode is still disabled.. */
16566 if (macmode == MACLIST_MODE_DISABLED) {
16567 if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, NULL)) != 0)
16568 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
16573 macnum = acl->n_acl_entries;
16574 if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
16575 WL_ERR(("%s : invalid number of MAC address entries %d\n",
16576 __FUNCTION__, macnum));
16580 /* allocate memory for the MAC list */
16581 list = (struct maclist*)kmalloc(sizeof(int) +
16582 sizeof(struct ether_addr) * macnum, GFP_KERNEL);
16584 WL_ERR(("%s : failed to allocate memory\n", __FUNCTION__));
16588 /* prepare the MAC list */
16589 list->count = htod32(macnum);
16590 for (i = 0; i < macnum; i++) {
16591 memcpy(&list->ea[i], &acl->mac_addrs[i], ETHER_ADDR_LEN);
16594 if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, list)) != 0)
16595 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
16601 #endif /* WL_CFG80211_ACL */
16603 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
16604 int wl_chspec_chandef(chanspec_t chanspec,
16605 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
16606 struct cfg80211_chan_def *chandef,
16607 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16608 struct chan_info *chaninfo,
16609 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
16610 struct wiphy *wiphy)
16616 struct ieee80211_channel *chan;
16621 channel = CHSPEC_CHANNEL(chanspec);
16623 switch (CHSPEC_BW(chanspec)) {
16624 case WL_CHANSPEC_BW_20:
16625 chan_type = NL80211_CHAN_HT20;
16627 case WL_CHANSPEC_BW_40:
16629 if (CHSPEC_SB_UPPER(chanspec)) {
16630 channel += CH_10MHZ_APART;
16632 channel -= CH_10MHZ_APART;
16635 chan_type = NL80211_CHAN_HT40PLUS;
16638 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16639 case WL_CHANSPEC_BW_80:
16640 case WL_CHANSPEC_BW_8080:
16642 uint16 sb = CHSPEC_CTL_SB(chanspec);
16644 if (sb == WL_CHANSPEC_CTL_SB_LL) {
16645 channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
16646 } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
16647 channel -= CH_10MHZ_APART;
16648 } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
16649 channel += CH_10MHZ_APART;
16651 /* WL_CHANSPEC_CTL_SB_UU */
16652 channel += (CH_10MHZ_APART + CH_20MHZ_APART);
16655 if (sb == WL_CHANSPEC_CTL_SB_LL || sb == WL_CHANSPEC_CTL_SB_LU)
16656 chan_type = NL80211_CHAN_HT40MINUS;
16657 else if (sb == WL_CHANSPEC_CTL_SB_UL || sb == WL_CHANSPEC_CTL_SB_UU)
16658 chan_type = NL80211_CHAN_HT40PLUS;
16661 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16663 chan_type = NL80211_CHAN_HT20;
16668 if (CHSPEC_IS5G(chanspec))
16669 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_5GHZ);
16671 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
16673 chan = ieee80211_get_channel(wiphy, freq);
16674 WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
16675 channel, freq, chan_type, chan));
16677 if (unlikely(!chan)) {
16678 /* fw and cfg80211 channel lists are not in sync */
16679 WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
16684 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16685 cfg80211_chandef_create(chandef, chan, chan_type);
16686 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
16691 chaninfo->freq = freq;
16692 chaninfo->chan_type = chan_type;
16693 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16698 wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
16701 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16702 struct cfg80211_chan_def chandef;
16703 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
16708 struct chan_info chaninfo;
16709 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16712 printf("wiphy is null\n");
16715 #ifndef ALLOW_CHSW_EVT
16716 /* Channel switch support is only for AP/GO/ADHOC/MESH */
16717 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
16718 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
16719 WL_ERR(("No channel switch notify support for STA/GC\n"));
16722 #endif /* !ALLOW_CHSW_EVT */
16723 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16724 if (wl_chspec_chandef(chanspec, &chandef, wiphy))
16725 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16726 if (wl_chspec_chandef(chanspec, &chaninfo, wiphy))
16727 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16729 WL_ERR(("%s:chspec_chandef failed\n", __FUNCTION__));
16732 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
16733 freq = chandef.chan ? chandef.chan->center_freq : chandef.center_freq1;
16734 cfg80211_ch_switch_notify(dev, &chandef);
16735 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
16736 freq = chan_info.freq;
16737 cfg80211_ch_switch_notify(dev, chan_info.freq, chan_info.chan_type);
16738 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
16740 WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq, chanspec));
16743 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
16747 wl_cfg80211_set_ulb_mode(struct net_device *dev, int mode)
16752 ret = wldev_iovar_getint(dev, "ulb_mode", &cur_mode);
16753 if (unlikely(ret)) {
16754 WL_ERR(("[ULB] ulb_mode get failed. ret:%d \n", ret));
16758 if (cur_mode == mode) {
16759 /* If request mode is same as that of the current mode, then
16760 * do nothing (Avoid unnecessary wl down and up).
16762 WL_INFORM(("[ULB] No change in ulb_mode. Do nothing.\n"));
16766 /* setting of ulb_mode requires wl to be down */
16767 ret = wldev_ioctl(dev, WLC_DOWN, NULL, 0, true);
16768 if (unlikely(ret)) {
16769 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
16773 if (mode >= MAX_SUPP_ULB_MODES) {
16774 WL_ERR(("[ULB] unsupported ulb_mode :[%d]\n", mode));
16778 ret = wldev_iovar_setint(dev, "ulb_mode", mode);
16779 if (unlikely(ret)) {
16780 WL_ERR(("[ULB] ulb_mode set failed. ret:%d \n", ret));
16784 ret = wldev_ioctl(dev, WLC_UP, NULL, 0, true);
16785 if (unlikely(ret)) {
16786 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
16790 WL_DBG(("[ULB] ulb_mode set to %d successfully \n", mode));
16796 wl_cfg80211_ulbbw_to_ulbchspec(u32 bw)
16798 if (bw == ULB_BW_DISABLED) {
16799 return WL_CHANSPEC_BW_20;
16800 } else if (bw == ULB_BW_10MHZ) {
16801 return WL_CHANSPEC_BW_10;
16802 } else if (bw == ULB_BW_5MHZ) {
16803 return WL_CHANSPEC_BW_5;
16804 } else if (bw == ULB_BW_2P5MHZ) {
16805 return WL_CHANSPEC_BW_2P5;
16807 WL_ERR(("[ULB] unsupported value for ulb_bw \n"));
16813 wl_cfg80211_ulb_get_min_bw_chspec(struct wireless_dev *wdev, s32 bssidx)
16815 struct bcm_cfg80211 *cfg = g_bcm_cfg;
16816 struct net_info *_netinfo;
16819 * Return the chspec value corresponding to the
16820 * BW setting for a particular interface
16823 /* if wdev is provided, use it */
16824 _netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
16825 } else if (bssidx >= 0) {
16826 /* if wdev is not provided, use it */
16827 _netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
16829 WL_ERR(("[ULB] wdev/bssidx not provided\n"));
16830 return INVCHANSPEC;
16833 if (unlikely(!_netinfo)) {
16834 WL_ERR(("[ULB] net_info is null \n"));
16835 return INVCHANSPEC;
16838 if (_netinfo->ulb_bw) {
16839 WL_DBG(("[ULB] wdev_ptr:%p ulb_bw:0x%x \n", _netinfo->wdev, _netinfo->ulb_bw));
16840 return wl_cfg80211_ulbbw_to_ulbchspec(_netinfo->ulb_bw);
16842 return WL_CHANSPEC_BW_20;
16847 wl_cfg80211_get_ulb_bw(struct wireless_dev *wdev)
16849 struct bcm_cfg80211 *cfg = g_bcm_cfg;
16850 struct net_info *_netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
16853 * Return the ulb_bw setting for a
16854 * particular interface
16856 if (unlikely(!_netinfo)) {
16857 WL_ERR(("[ULB] net_info is null \n"));
16861 return _netinfo->ulb_bw;
16865 wl_cfg80211_set_ulb_bw(struct net_device *dev,
16866 u32 ulb_bw, char *ifname)
16868 struct bcm_cfg80211 *cfg = g_bcm_cfg;
16871 struct net_info *_netinfo = NULL, *iter, *next;
16873 enum nl80211_iftype iftype;
16878 WL_DBG(("[ULB] Enter. bw_type:%d \n", ulb_bw));
16880 ret = wldev_iovar_getint(dev, "ulb_mode", &mode);
16881 if (unlikely(ret)) {
16882 WL_ERR(("[ULB] ulb_mode not supported \n"));
16886 if (mode != ULB_MODE_STD_ALONE_MODE) {
16887 WL_ERR(("[ULB] ulb bw modification allowed only in stand-alone mode\n"));
16891 if (ulb_bw >= MAX_SUPP_ULB_BW) {
16892 WL_ERR(("[ULB] unsupported value (%d) for ulb_bw \n", ulb_bw));
16896 #ifdef WL_CFG80211_P2P_DEV_IF
16897 if (strcmp(ifname, "p2p-dev-wlan0") == 0) {
16898 iftype = NL80211_IFTYPE_P2P_DEVICE;
16899 /* Use wdev corresponding to the dedicated p2p discovery interface */
16900 if (likely(cfg->p2p_wdev)) {
16901 _netinfo = wl_get_netinfo_by_wdev(cfg, cfg->p2p_wdev);
16906 #endif /* WL_CFG80211_P2P_DEV_IF */
16908 for_each_ndev(cfg, iter, next) {
16910 if (strncmp(iter->ndev->name, ifname, strlen(ifname)) == 0) {
16911 _netinfo = wl_get_netinfo_by_netdev(cfg, iter->ndev);
16912 iftype = NL80211_IFTYPE_STATION;
16920 bssidx = _netinfo->bssidx;
16921 _netinfo->ulb_bw = ulb_bw;
16924 WL_DBG(("[ULB] Applying ulb_bw:%d for bssidx:%d \n", ulb_bw, bssidx));
16925 ret = wldev_iovar_setbuf_bsscfg(dev, "ulb_bw", (void *)&ulb_bw, 4,
16926 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx,
16927 &cfg->ioctl_buf_sync);
16928 if (unlikely(ret)) {
16929 WL_ERR(("[ULB] ulb_bw set failed. ret:%d \n", ret));
16935 #endif /* WL11ULB */
16938 wl_ap_channel_ind(struct bcm_cfg80211 *cfg,
16939 struct net_device *ndev,
16940 chanspec_t chanspec)
16942 u32 channel = LCHSPEC_CHANNEL(chanspec);
16944 WL_DBG(("(%s) AP channel:%d chspec:0x%x \n",
16945 ndev->name, channel, chanspec));
16946 if (cfg->ap_oper_channel && (cfg->ap_oper_channel != channel)) {
16948 * If cached channel is different from the channel indicated
16949 * by the event, notify user space about the channel switch.
16951 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
16952 wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
16953 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
16954 cfg->ap_oper_channel = channel;
16959 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16960 const wl_event_msg_t *e, void *data)
16962 struct net_device *ndev = NULL;
16963 chanspec_t chanspec;
16966 WL_DBG(("Enter\n"));
16967 if (unlikely(e->status)) {
16968 WL_ERR(("status:0x%x \n", e->status));
16976 if (likely(cfgdev)) {
16977 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
16978 chanspec = *((chanspec_t *)data);
16979 channel = LCHSPEC_CHANNEL(chanspec);
16981 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
16982 /* For AP/GO role */
16983 wl_ap_channel_ind(cfg, ndev, chanspec);
16991 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
16992 const wl_event_msg_t *e, void *data)
16996 struct net_device *ndev = NULL;
16997 struct wiphy *wiphy = NULL;
16999 WL_DBG(("Enter\n"));
17000 if (unlikely(e->status)) {
17001 WL_ERR(("status:0x%x \n", e->status));
17005 if (likely(cfgdev)) {
17006 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
17007 wiphy = bcmcfg_to_wiphy(cfg);
17008 error = wldev_iovar_getint(ndev, "chanspec", &chanspec);
17009 if (unlikely(error)) {
17010 WL_ERR(("Get chanspec error: %d \n", error));
17014 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
17015 /* For AP/GO role */
17016 wl_ap_channel_ind(cfg, ndev, chanspec);
17018 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
17019 wl_cfg80211_ch_switch_notify(ndev, chanspec, wiphy);
17020 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
17030 wl_cfg80211_nan_cmd_handler(struct net_device *ndev, char *cmd, int cmd_len)
17032 return wl_cfgnan_cmd_handler(ndev, g_bcm_cfg, cmd, cmd_len);
17034 #endif /* WL_NAN */
17036 void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg)
17038 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
17041 /* Clear the security settings on the primary Interface */
17042 err = wldev_iovar_setint(dev, "wsec", 0);
17043 if (unlikely(err)) {
17044 WL_ERR(("wsec clear failed \n"));
17046 err = wldev_iovar_setint(dev, "auth", 0);
17047 if (unlikely(err)) {
17048 WL_ERR(("auth clear failed \n"));
17050 err = wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
17051 if (unlikely(err)) {
17052 WL_ERR(("wpa_auth clear failed \n"));
17056 #ifdef WL_CFG80211_P2P_DEV_IF
17057 void wl_cfg80211_del_p2p_wdev(void)
17059 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17060 struct wireless_dev *wdev = NULL;
17062 WL_DBG(("Enter \n"));
17064 WL_ERR(("Invalid Ptr\n"));
17067 wdev = cfg->p2p_wdev;
17070 if (wdev && cfg->down_disc_if) {
17071 wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
17072 cfg->down_disc_if = FALSE;
17075 #endif /* WL_CFG80211_P2P_DEV_IF */
17077 #if defined(WL_SUPPORT_AUTO_CHANNEL)
17079 wl_cfg80211_set_spect(struct net_device *dev, int spect)
17081 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17086 if (!wl_get_drv_status_all(cfg, CONNECTED)) {
17087 err = wldev_ioctl(dev, WLC_DOWN, &down, sizeof(down), true);
17089 WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__, err));
17093 err = wldev_ioctl(dev, WLC_SET_SPECT_MANAGMENT, &spect, sizeof(spect), true);
17095 WL_ERR(("%s: error setting spect: code: %d\n", __func__, err));
17099 err = wldev_ioctl(dev, WLC_UP, &up, sizeof(up), true);
17101 WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__, err));
17109 wl_cfg80211_get_sta_channel(void)
17111 struct net_device *ndev = bcmcfg_to_prmry_ndev(g_bcm_cfg);
17114 if (wl_get_drv_status(g_bcm_cfg, CONNECTED, ndev)) {
17115 channel = g_bcm_cfg->channel;
17119 #endif /* WL_SUPPORT_AUTO_CHANNEL */
17120 #ifdef P2P_LISTEN_OFFLOADING
17122 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg)
17126 int p2plo_pause = 0;
17127 if (!cfg || !cfg->p2p) {
17128 WL_ERR(("Wl %p or cfg->p2p %p is null\n",
17129 cfg, cfg ? cfg->p2p : 0));
17133 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17134 ret = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg),
17135 "p2po_stop", (void*)&p2plo_pause, sizeof(p2plo_pause),
17136 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL);
17138 WL_ERR(("p2po_stop Failed :%d\n", ret));
17144 wl_cfg80211_p2plo_listen_start(struct net_device *dev, u8 *buf, int len)
17146 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17147 s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17148 wl_p2plo_listen_t p2plo_listen;
17155 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
17156 WL_ERR(("Sending Action Frames. Try it again.\n"));
17160 if (wl_get_drv_status_all(cfg, SCANNING)) {
17161 WL_ERR(("Scanning already\n"));
17165 if (wl_get_drv_status(cfg, SCAN_ABORTING, dev)) {
17166 WL_ERR(("Scanning being aborted\n"));
17170 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
17171 WL_ERR(("p2p listen offloading already running\n"));
17175 /* Just in case if it is not enabled */
17176 if ((ret = wl_cfgp2p_enable_discovery(cfg, dev, NULL, 0)) < 0) {
17177 WL_ERR(("cfgp2p_enable discovery failed"));
17181 bzero(&p2plo_listen, sizeof(wl_p2plo_listen_t));
17184 sscanf(buf, " %10d %10d %10d %10d", &channel, &period, &interval, &count);
17185 if ((channel == 0) || (period == 0) ||
17186 (interval == 0) || (count == 0)) {
17187 WL_ERR(("Wrong argument %d/%d/%d/%d \n",
17188 channel, period, interval, count));
17192 p2plo_listen.period = period;
17193 p2plo_listen.interval = interval;
17194 p2plo_listen.count = count;
17196 WL_ERR(("channel:%d period:%d, interval:%d count:%d\n",
17197 channel, period, interval, count));
17199 WL_ERR(("Argument len is wrong.\n"));
17204 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
17205 sizeof(channel), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17206 bssidx, &cfg->ioctl_buf_sync)) < 0) {
17207 WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
17211 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&p2plo_listen,
17212 sizeof(wl_p2plo_listen_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17213 bssidx, &cfg->ioctl_buf_sync)) < 0) {
17214 WL_ERR(("p2po_listen Failed :%d\n", ret));
17218 wl_set_p2p_status(cfg, DISC_IN_PROGRESS);
17219 cfg->last_roc_id = P2PO_COOKIE;
17224 wl_cfg80211_p2plo_listen_stop(struct net_device *dev)
17226 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17227 s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17230 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop", NULL,
17231 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN,
17232 bssidx, &cfg->ioctl_buf_sync)) < 0) {
17233 WL_ERR(("p2po_stop Failed :%d\n", ret));
17240 #endif /* P2P_LISTEN_OFFLOADING */
17242 wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg)
17245 id = ++cfg->last_roc_id;
17246 #ifdef P2P_LISTEN_OFFLOADING
17247 if (id == P2PO_COOKIE) {
17248 id = ++cfg->last_roc_id;
17250 #endif /* P2P_LISTEN_OFFLOADING */
17252 id = ++cfg->last_roc_id;
17256 #if defined(SUPPORT_RANDOM_MAC_SCAN)
17258 wl_cfg80211_set_random_mac(struct net_device *dev, bool enable)
17260 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17263 if (cfg->random_mac_enabled == enable) {
17264 WL_ERR(("Random MAC already %s\n", enable ? "Enabled" : "Disabled"));
17269 ret = wl_cfg80211_random_mac_enable(dev);
17271 ret = wl_cfg80211_random_mac_disable(dev);
17275 cfg->random_mac_enabled = enable;
17282 wl_cfg80211_random_mac_enable(struct net_device *dev)
17284 u8 current_mac[ETH_ALEN] = {0, };
17285 s32 err = BCME_ERROR;
17286 uint8 buffer[20] = {0, };
17287 wl_scanmac_t *sm = NULL;
17289 wl_scanmac_enable_t *sm_enable = NULL;
17290 wl_scanmac_config_t *sm_config = NULL;
17291 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17293 if (wl_get_drv_status_all(cfg, CONNECTED) || wl_get_drv_status_all(cfg, CONNECTING) ||
17294 wl_get_drv_status_all(cfg, AP_CREATED) || wl_get_drv_status_all(cfg, AP_CREATING)) {
17295 WL_ERR(("Fail to Set random mac, current state is wrong\n"));
17299 /* Read current mac address */
17300 err = wldev_iovar_getbuf_bsscfg(dev, "cur_etheraddr",
17301 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17303 if (err != BCME_OK) {
17304 WL_ERR(("failed to get current dongle mac address\n"));
17308 memcpy(current_mac, cfg->ioctl_buf, ETH_ALEN);
17310 /* Enable scan mac */
17311 sm = (wl_scanmac_t *)buffer;
17312 sm_enable = (wl_scanmac_enable_t *)sm->data;
17313 sm->len = sizeof(*sm_enable);
17314 sm_enable->enable = 1;
17315 len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17316 sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
17318 err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17319 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17321 if (err != BCME_OK) {
17322 WL_ERR(("failed to enable scanmac, err=%d\n", err));
17326 /* Configure scanmac */
17327 memset(buffer, 0x0, sizeof(buffer));
17328 sm_config = (wl_scanmac_config_t *)sm->data;
17329 sm->len = sizeof(*sm_config);
17330 sm->subcmd_id = WL_SCANMAC_SUBCMD_CONFIG;
17331 sm_config->scan_bitmap = WL_SCANMAC_SCAN_UNASSOC;
17333 /* Set current mac address */
17334 memcpy(&sm_config->mac.octet, current_mac, ETH_ALEN);
17335 sm_config->mac.octet[3] = 0x0;
17336 sm_config->mac.octet[4] = 0x0;
17337 sm_config->mac.octet[5] = 0x0;
17339 /* Set randomize mac address(last 3bytes) */
17340 memset(&sm_config->random_mask.octet, 0x0, ETH_ALEN);
17341 sm_config->random_mask.octet[3] = 0xff;
17342 sm_config->random_mask.octet[4] = 0xff;
17343 sm_config->random_mask.octet[5] = 0xff;
17345 len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17347 err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17348 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17350 if (err != BCME_OK) {
17351 WL_ERR(("failed scanmac configuration\n"));
17353 /* Disable scan mac for clean-up */
17354 wl_cfg80211_random_mac_disable(dev);
17358 WL_ERR(("random MAC enable done"));
17363 wl_cfg80211_random_mac_disable(struct net_device *dev)
17365 s32 err = BCME_ERROR;
17366 uint8 buffer[20] = {0, };
17367 wl_scanmac_t *sm = NULL;
17369 wl_scanmac_enable_t *sm_enable = NULL;
17370 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17372 sm = (wl_scanmac_t *)buffer;
17373 sm_enable = (wl_scanmac_enable_t *)sm->data;
17374 sm->len = sizeof(*sm_enable);
17375 sm_enable->enable = 0;
17376 len = OFFSETOF(wl_scanmac_t, data) + sm->len;
17378 sm->subcmd_id = WL_SCANMAC_SUBCMD_ENABLE;
17380 err = wldev_iovar_setbuf_bsscfg(dev, "scanmac",
17381 sm, len, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
17383 if (err != BCME_OK) {
17384 WL_ERR(("failed to disable scanmac, err=%d\n", err));
17388 WL_ERR(("random MAC disable done\n"));
17391 #endif /* SUPPORT_RANDOM_MAC_SCAN */
17394 wl_cfg80211_iface_count(void)
17396 struct bcm_cfg80211 *cfg = g_bcm_cfg;
17397 struct net_info *iter, *next;
17398 int iface_count = 0;
17400 for_each_ndev(cfg, iter, next) {
17405 return iface_count;
17408 #ifdef DHD_LOG_DUMP
17409 struct bcm_cfg80211*
17410 wl_get_bcm_cfg80211_ptr(void)
17414 #endif /* DHD_LOG_DUMP */
17416 #define CHECK_DONGLE_IDLE_TIME 50
17417 #define CHECK_DONGLE_IDLE_CNT 100
17419 wl_check_dongle_idle(struct wiphy *wiphy)
17422 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
17423 struct net_device *primary_ndev;
17425 struct channel_info ci;
17428 /* Use primary I/F for sending cmds down to firmware */
17429 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
17431 while (retry++ < CHECK_DONGLE_IDLE_CNT) {
17432 error = wldev_ioctl(primary_ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false);
17433 if (error != BCME_OK || ci.scan_channel != 0) {
17434 WL_ERR(("Firmware is busy(err:%d scan channel:%d). wait %dms\n",
17435 error, ci.scan_channel, CHECK_DONGLE_IDLE_TIME));
17439 wl_delay(CHECK_DONGLE_IDLE_TIME);
17441 if (retry >= CHECK_DONGLE_IDLE_CNT) {
17442 WL_ERR(("DONGLE is BUSY too long\n"));
17445 WL_DBG(("DONGLE is idle\n"));