wifi: fix some make fail issue
[GitHub/LineageOS/G12/android_hardware_amlogic_kernel-modules_dhd-driver.git] / bcmdhd.1.579.77.41.1.cn / wl_cfg80211.c
1 /*
2 * Linux cfg80211 driver
3 *
4 * Copyright (C) 1999-2017, Broadcom Corporation
5 *
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:
11 *
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.
19 *
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.
23 *
24 *
25 * <<Broadcom-WL-IPTag/Open:>>
26 *
27 * $Id: wl_cfg80211.c 711110 2017-07-17 04:38:25Z $
28 */
29 /* */
30 #include <typedefs.h>
31 #include <linuxver.h>
32 #include <osl.h>
33 #include <linux/kernel.h>
34
35 #include <wlc_types.h>
36 #include <bcmutils.h>
37 #include <bcmwifi_channels.h>
38 #include <bcmendian.h>
39 #include <ethernet.h>
40 #include <802.11.h>
41 #include <linux/if_arp.h>
42 #include <asm/uaccess.h>
43
44 #include <ethernet.h>
45 #include <linux/kernel.h>
46 #include <linux/kthread.h>
47 #include <linux/netdevice.h>
48 #include <linux/sched.h>
49 #include <linux/etherdevice.h>
50 #include <linux/wireless.h>
51 #include <linux/ieee80211.h>
52 #include <linux/wait.h>
53 #include <net/cfg80211.h>
54 #include <net/rtnetlink.h>
55
56 #include <wlioctl.h>
57 #include <wldev_common.h>
58 #include <wl_cfg80211.h>
59 #include <wl_cfgp2p.h>
60 #include <bcmdevs.h>
61 #include <wl_android.h>
62 #include <dngl_stats.h>
63 #include <dhd.h>
64 #include <dhd_linux.h>
65 #include <dhd_debug.h>
66 #include <dhdioctl.h>
67 #include <wlioctl.h>
68 #include <dhd_cfg80211.h>
69 #include <dhd_bus.h>
70 #ifdef PNO_SUPPORT
71 #include <dhd_pno.h>
72 #endif /* PNO_SUPPORT */
73 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
74 #include <wl_cfgvendor.h>
75 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
76
77 #if !defined(WL_VENDOR_EXT_SUPPORT)
78 #undef GSCAN_SUPPORT
79 #endif
80
81 #if defined(STAT_REPORT)
82 #include <wl_statreport.h>
83 #endif /* STAT_REPORT */
84 #include <dhd_config.h>
85
86
87 #ifdef PROP_TXSTATUS
88 #include <dhd_wlfc.h>
89 #endif
90
91 #ifdef BCMPCIE
92 #include <dhd_flowring.h>
93 #endif
94 #ifdef RTT_SUPPORT
95 #include <dhd_rtt.h>
96 #endif /* RTT_SUPPORT */
97 #ifdef WL11U
98 #endif /* WL11U */
99
100 #ifndef DHD_UNSUPPORT_IF_CNTS
101 #define DHD_SUPPORT_IF_CNTS
102 #endif /* !DHD_UN_SUPPORT_IF_CNTS */
103
104
105 #define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))
106
107 static struct device *cfg80211_parent_dev = NULL;
108 #ifdef CUSTOMER_HW4_DEBUG
109 u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_P2P_ACTION;
110 #else
111 u32 wl_dbg_level = WL_DBG_ERR;
112 #endif /* CUSTOMER_HW4_DEBUG */
113
114 #define MAX_WAIT_TIME 1500
115 #ifdef WLAIBSS_MCHAN
116 #define IBSS_IF_NAME "ibss%d"
117 #endif /* WLAIBSS_MCHAN */
118
119 #ifdef VSDB
120 /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */
121 #define DEFAULT_SLEEP_TIME_VSDB 120
122 #define OFF_CHAN_TIME_THRESHOLD_MS 200
123 #define AF_RETRY_DELAY_TIME 40
124
125 /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */
126 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg) \
127 do { \
128 if (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg)) || \
129 wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) { \
130 OSL_SLEEP(DEFAULT_SLEEP_TIME_VSDB); \
131 } \
132 } while (0)
133 #else /* VSDB */
134 /* if not VSDB, do nothing */
135 #define WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg)
136 #endif /* VSDB */
137
138 #ifdef WL_CFG80211_SYNC_GON
139 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) \
140 (wl_get_drv_status_all(cfg, SENDING_ACT_FRM) || \
141 wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN))
142 #else
143 #define WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg) wl_get_drv_status_all(cfg, SENDING_ACT_FRM)
144 #endif /* WL_CFG80211_SYNC_GON */
145
146 #define DNGL_FUNC(func, parameters) func parameters
147 #define COEX_DHCP
148
149 #define WLAN_EID_SSID 0
150 #define CH_MIN_5G_CHANNEL 34
151 #define CH_MIN_2G_CHANNEL 1
152 #define ACTIVE_SCAN 1
153 #define PASSIVE_SCAN 0
154
155 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
156 4 && __GNUC_MINOR__ >= 6))
157 #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
158 _Pragma("GCC diagnostic push") \
159 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
160 (entry) = list_first_entry((ptr), type, member); \
161 _Pragma("GCC diagnostic pop") \
162
163 #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
164 _Pragma("GCC diagnostic push") \
165 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
166 entry = container_of((ptr), type, member); \
167 _Pragma("GCC diagnostic pop") \
168
169 #else
170 #define BCM_SET_LIST_FIRST_ENTRY(entry, ptr, type, member) \
171 (entry) = list_first_entry((ptr), type, member); \
172
173 #define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
174 entry = container_of((ptr), type, member); \
175
176 #endif /* STRICT_GCC_WARNINGS */
177
178 #ifdef WL_RELMCAST
179 enum rmc_event_type {
180 RMC_EVENT_NONE,
181 RMC_EVENT_LEADER_CHECK_FAIL
182 };
183 #endif /* WL_RELMCAST */
184
185 #ifdef WL_LASTEVT
186 typedef struct wl_last_event {
187 uint32 current_time; /* current tyime */
188 uint32 timestamp; /* event timestamp */
189 wl_event_msg_t event; /* Encapsulated event */
190 } wl_last_event_t;
191 #endif /* WL_LASTEVT */
192
193 /* This is to override regulatory domains defined in cfg80211 module (reg.c)
194 * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN
195 * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165).
196 * With respect to these flags, wpa_supplicant doesn't start p2p operations on 5GHz channels.
197 * All the chnages in world regulatory domain are to be done here.
198 *
199 * this definition reuires disabling missing-field-initializer warning
200 * as the ieee80211_regdomain definition differs in plain linux and in Android
201 */
202 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
203 4 && __GNUC_MINOR__ >= 6))
204 _Pragma("GCC diagnostic push")
205 _Pragma("GCC diagnostic ignored \"-Wmissing-field-initializers\"")
206 #endif
207 static const struct ieee80211_regdomain brcm_regdom = {
208 .n_reg_rules = 4,
209 .alpha2 = "99",
210 .reg_rules = {
211 /* IEEE 802.11b/g, channels 1..11 */
212 REG_RULE(2412-10, 2472+10, 40, 6, 20, 0),
213 /* If any */
214 /* IEEE 802.11 channel 14 - Only JP enables
215 * this and for 802.11b only
216 */
217 REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
218 /* IEEE 802.11a, channel 36..64 */
219 REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
220 /* IEEE 802.11a, channel 100..165 */
221 REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
222 };
223 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
224 4 && __GNUC_MINOR__ >= 6))
225 _Pragma("GCC diagnostic pop")
226 #endif
227
228
229 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
230 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
231 static const struct ieee80211_iface_limit common_if_limits[] = {
232 {
233 /*
234 * Driver can support up to 2 AP's
235 */
236 .max = 2,
237 .types = BIT(NL80211_IFTYPE_AP),
238 },
239 {
240 /*
241 * During P2P-GO removal, P2P-GO is first changed to STA and later only
242 * removed. So setting maximum possible number of STA interfaces according
243 * to kernel version.
244 *
245 * less than linux-3.8 - max:3 (wlan0 + p2p0 + group removal of p2p-p2p0-x)
246 * linux-3.8 and above - max:2 (wlan0 + group removal of p2p-wlan0-x)
247 */
248 #ifdef WL_ENABLE_P2P_IF
249 .max = 3,
250 #else
251 .max = 2,
252 #endif /* WL_ENABLE_P2P_IF */
253 .types = BIT(NL80211_IFTYPE_STATION),
254 },
255 {
256 .max = 2,
257 .types = BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_P2P_CLIENT),
258 },
259 #if defined(WL_CFG80211_P2P_DEV_IF)
260 {
261 .max = 1,
262 .types = BIT(NL80211_IFTYPE_P2P_DEVICE),
263 },
264 #endif /* WL_CFG80211_P2P_DEV_IF */
265 {
266 .max = 1,
267 .types = BIT(NL80211_IFTYPE_ADHOC),
268 },
269 };
270 #ifdef BCM4330_CHIP
271 #define NUM_DIFF_CHANNELS 1
272 #else
273 #define NUM_DIFF_CHANNELS 2
274 #endif
275 static struct ieee80211_iface_combination
276 common_iface_combinations[] = {
277 {
278 .num_different_channels = NUM_DIFF_CHANNELS,
279 /*
280 * max_interfaces = 4
281 * The max no of interfaces will be used in dual p2p case.
282 * {STA, P2P Device, P2P Group 1, P2P Group 2}. Though we
283 * will not be using the STA functionality in this case, it
284 * will remain registered as it is the primary interface.
285 */
286 .max_interfaces = 4,
287 .limits = common_if_limits,
288 .n_limits = ARRAY_SIZE(common_if_limits),
289 },
290 };
291 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
292
293 /* Data Element Definitions */
294 #define WPS_ID_CONFIG_METHODS 0x1008
295 #define WPS_ID_REQ_TYPE 0x103A
296 #define WPS_ID_DEVICE_NAME 0x1011
297 #define WPS_ID_VERSION 0x104A
298 #define WPS_ID_DEVICE_PWD_ID 0x1012
299 #define WPS_ID_REQ_DEV_TYPE 0x106A
300 #define WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS 0x1053
301 #define WPS_ID_PRIM_DEV_TYPE 0x1054
302
303 /* Device Password ID */
304 #define DEV_PW_DEFAULT 0x0000
305 #define DEV_PW_USER_SPECIFIED 0x0001,
306 #define DEV_PW_MACHINE_SPECIFIED 0x0002
307 #define DEV_PW_REKEY 0x0003
308 #define DEV_PW_PUSHBUTTON 0x0004
309 #define DEV_PW_REGISTRAR_SPECIFIED 0x0005
310
311 /* Config Methods */
312 #define WPS_CONFIG_USBA 0x0001
313 #define WPS_CONFIG_ETHERNET 0x0002
314 #define WPS_CONFIG_LABEL 0x0004
315 #define WPS_CONFIG_DISPLAY 0x0008
316 #define WPS_CONFIG_EXT_NFC_TOKEN 0x0010
317 #define WPS_CONFIG_INT_NFC_TOKEN 0x0020
318 #define WPS_CONFIG_NFC_INTERFACE 0x0040
319 #define WPS_CONFIG_PUSHBUTTON 0x0080
320 #define WPS_CONFIG_KEYPAD 0x0100
321 #define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280
322 #define WPS_CONFIG_PHY_PUSHBUTTON 0x0480
323 #define WPS_CONFIG_VIRT_DISPLAY 0x2008
324 #define WPS_CONFIG_PHY_DISPLAY 0x4008
325
326 #define PM_BLOCK 1
327 #define PM_ENABLE 0
328
329
330 #define WL_AKM_SUITE_SHA256_1X 0x000FAC05
331 #define WL_AKM_SUITE_SHA256_PSK 0x000FAC06
332
333 #ifndef IBSS_COALESCE_ALLOWED
334 #define IBSS_COALESCE_ALLOWED IBSS_COALESCE_DEFAULT
335 #endif
336
337 #ifndef IBSS_INITIAL_SCAN_ALLOWED
338 #define IBSS_INITIAL_SCAN_ALLOWED IBSS_INITIAL_SCAN_ALLOWED_DEFAULT
339 #endif
340
341 #define CUSTOM_RETRY_MASK 0xff000000 /* Mask for retry counter of custom dwell time */
342 #define LONG_LISTEN_TIME 2000
343
344 #ifdef WBTEXT
345 #define CMD_WBTEXT_PROFILE_CONFIG "WBTEXT_PROFILE_CONFIG"
346 #define CMD_WBTEXT_WEIGHT_CONFIG "WBTEXT_WEIGHT_CONFIG"
347 #define CMD_WBTEXT_TABLE_CONFIG "WBTEXT_TABLE_CONFIG"
348 #define CMD_WBTEXT_DELTA_CONFIG "WBTEXT_DELTA_CONFIG"
349 #define DEFAULT_WBTEXT_PROFILE_A "a -70 -75 70 10 -75 -128 0 10"
350 #define DEFAULT_WBTEXT_PROFILE_B "b -60 -75 70 10 -75 -128 0 10"
351 #define DEFAULT_WBTEXT_WEIGHT_RSSI_A "RSSI a 65"
352 #define DEFAULT_WBTEXT_WEIGHT_RSSI_B "RSSI b 65"
353 #define DEFAULT_WBTEXT_WEIGHT_CU_A "CU a 35"
354 #define DEFAULT_WBTEXT_WEIGHT_CU_B "CU b 35"
355 #define DEFAULT_WBTEXT_TABLE_RSSI_A "RSSI a 0 55 100 55 60 90 \
356 60 65 70 65 70 50 70 128 20"
357 #define DEFAULT_WBTEXT_TABLE_RSSI_B "RSSI b 0 55 100 55 60 90 \
358 60 65 70 65 70 50 70 128 20"
359 #define DEFAULT_WBTEXT_TABLE_CU_A "CU a 0 30 100 30 50 90 \
360 50 60 70 60 80 50 80 100 20"
361 #define DEFAULT_WBTEXT_TABLE_CU_B "CU b 0 10 100 10 25 90 \
362 25 40 70 40 70 50 70 100 20"
363
364 typedef struct wl_wbtext_bssid {
365 struct ether_addr ea;
366 struct list_head list;
367 } wl_wbtext_bssid_t;
368
369 static void wl_cfg80211_wbtext_update_rcc(struct bcm_cfg80211 *cfg, struct net_device *dev);
370 static bool wl_cfg80211_wbtext_check_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea);
371 static bool wl_cfg80211_wbtext_add_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea);
372 static void wl_cfg80211_wbtext_clear_bssid_list(struct bcm_cfg80211 *cfg);
373 static bool wl_cfg80211_wbtext_send_nbr_req(struct bcm_cfg80211 *cfg, struct net_device *dev,
374 struct wl_profile *profile);
375 static bool wl_cfg80211_wbtext_send_btm_query(struct bcm_cfg80211 *cfg, struct net_device *dev,
376 struct wl_profile *profile);
377 static void wl_cfg80211_wbtext_set_wnm_maxidle(struct bcm_cfg80211 *cfg, struct net_device *dev);
378 static int wl_cfg80211_recv_nbr_resp(struct net_device *dev, uint8 *body, int body_len);
379 #endif /* WBTEXT */
380
381 #ifdef SUPPORT_AP_RADIO_PWRSAVE
382 #define RADIO_PWRSAVE_PPS 10
383 #define RADIO_PWRSAVE_QUIET_TIME 10
384 #define RADIO_PWRSAVE_LEVEL 3
385 #define RADIO_PWRSAVE_STAS_ASSOC_CHECK 0
386
387 #define RADIO_PWRSAVE_LEVEL_MIN 1
388 #define RADIO_PWRSAVE_LEVEL_MAX 5
389 #define RADIO_PWRSAVE_PPS_MIN 1
390 #define RADIO_PWRSAVE_QUIETTIME_MIN 1
391 #define RADIO_PWRSAVE_ASSOCCHECK_MIN 0
392 #define RADIO_PWRSAVE_ASSOCCHECK_MAX 1
393
394 #define RADIO_PWRSAVE_MAJOR_VER 1
395 #define RADIO_PWRSAVE_MINOR_VER 0
396 #define RADIO_PWRSAVE_MAJOR_VER_SHIFT 8
397 #define RADIO_PWRSAVE_VERSION \
398 ((RADIO_PWRSAVE_MAJOR_VER << RADIO_PWRSAVE_MAJOR_VER_SHIFT)| RADIO_PWRSAVE_MINOR_VER)
399 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
400
401 #ifdef WLADPS_SEAK_AP_WAR
402 #define ATHEROS_OUI "\x00\x03\x7F"
403 #define CAMEO_MAC_PREFIX "\x00\x18\xE7"
404 #define MAC_PREFIX_LEN 3
405 static bool
406 wl_find_vndr_ies_specific_vender(struct bcm_cfg80211 *cfg,
407 struct net_device *ndev, const u8 *vndr_oui);
408 static s32 wl_set_adps_mode(struct bcm_cfg80211 *cfg, struct net_device *ndev, uint8 enable_mode);
409 #endif /* WLADPS_SEAK_AP_WAR */
410
411 #define MAX_VNDR_OUI_STR_LEN 256
412 #define VNDR_OUI_STR_LEN 10
413 static const uchar *exclude_vndr_oui_list[] = {
414 "\x00\x50\xf2", /* Microsoft */
415 "\x00\x00\xf0", /* Samsung Elec */
416 WFA_OUI, /* WFA */
417 NULL
418 };
419
420 typedef struct wl_vndr_oui_entry {
421 uchar oui[DOT11_OUI_LEN];
422 struct list_head list;
423 } wl_vndr_oui_entry_t;
424
425 static int wl_vndr_ies_get_vendor_oui(struct bcm_cfg80211 *cfg,
426 struct net_device *ndev, char *vndr_oui, u32 vndr_oui_len);
427 static void wl_vndr_ies_clear_vendor_oui_list(struct bcm_cfg80211 *cfg);
428
429 /*
430 * cfg80211_ops api/callback list
431 */
432 static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
433 const struct ether_addr *sa, const struct ether_addr *bssid,
434 u8 **pheader, u32 *body_len, u8 *pbody);
435 static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
436 struct cfg80211_scan_request *request,
437 struct cfg80211_ssid *this_ssid);
438 #if defined(WL_CFG80211_P2P_DEV_IF)
439 static s32
440 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request);
441 #else
442 static s32
443 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
444 struct cfg80211_scan_request *request);
445 #endif /* WL_CFG80211_P2P_DEV_IF */
446 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed);
447 #ifdef WLAIBSS_MCHAN
448 static bcm_struct_cfgdev* bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name);
449 static s32 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
450 #endif /* WLAIBSS_MCHAN */
451 static s32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
452 struct cfg80211_ibss_params *params);
453 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy,
454 struct net_device *dev);
455 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
456 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
457 struct net_device *dev, const u8 *mac,
458 struct station_info *sinfo);
459 #else
460 static s32 wl_cfg80211_get_station(struct wiphy *wiphy,
461 struct net_device *dev, u8 *mac,
462 struct station_info *sinfo);
463 #endif
464 static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
465 struct net_device *dev, bool enabled,
466 s32 timeout);
467 static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
468 struct cfg80211_connect_params *sme);
469 static s32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
470 u16 reason_code);
471 #if defined(WL_CFG80211_P2P_DEV_IF)
472 static s32
473 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
474 enum nl80211_tx_power_setting type, s32 mbm);
475 #else
476 static s32
477 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
478 enum nl80211_tx_power_setting type, s32 dbm);
479 #endif /* WL_CFG80211_P2P_DEV_IF */
480 #if defined(WL_CFG80211_P2P_DEV_IF)
481 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
482 struct wireless_dev *wdev, s32 *dbm);
483 #else
484 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
485 #endif /* WL_CFG80211_P2P_DEV_IF */
486 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
487 struct net_device *dev,
488 u8 key_idx, bool unicast, bool multicast);
489 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
490 u8 key_idx, bool pairwise, const u8 *mac_addr,
491 struct key_params *params);
492 static s32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
493 u8 key_idx, bool pairwise, const u8 *mac_addr);
494 static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
495 u8 key_idx, bool pairwise, const u8 *mac_addr,
496 void *cookie, void (*callback) (void *cookie,
497 struct key_params *params));
498 static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
499 struct net_device *dev, u8 key_idx);
500 static s32 wl_cfg80211_resume(struct wiphy *wiphy);
501 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
502 2, 0))
503 static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
504 bcm_struct_cfgdev *cfgdev, u64 cookie);
505 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
506 static s32 wl_cfg80211_del_station(
507 struct wiphy *wiphy, struct net_device *ndev,
508 struct station_del_parameters *params);
509 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
510 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
511 struct net_device *ndev, const u8* mac_addr);
512 #else
513 static s32 wl_cfg80211_del_station(struct wiphy *wiphy,
514 struct net_device *ndev, u8* mac_addr);
515 #endif
516 #ifdef WLMESH
517 static s32 wl_cfg80211_join_mesh(
518 struct wiphy *wiphy, struct net_device *dev,
519 const struct mesh_config *conf,
520 const struct mesh_setup *setup);
521 static s32 wl_cfg80211_leave_mesh(struct wiphy *wiphy,
522 struct net_device *dev);
523 #endif /* WLMESH */
524 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
525 static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
526 struct net_device *dev, const u8 *mac, struct station_parameters *params);
527 #else
528 static s32 wl_cfg80211_change_station(struct wiphy *wiphy,
529 struct net_device *dev, u8 *mac, struct station_parameters *params);
530 #endif
531 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
532 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
533 static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
534 #else
535 static s32 wl_cfg80211_suspend(struct wiphy *wiphy);
536 #endif
537 static s32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
538 struct cfg80211_pmksa *pmksa);
539 static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
540 struct cfg80211_pmksa *pmksa);
541 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
542 struct net_device *dev);
543 void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg);
544 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg);
545 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
546 struct net_device *ndev, bool aborted, bool fw_abort);
547 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
548 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
549 KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
550 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
551 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
552 u32 peer_capability, const u8 *buf, size_t len);
553 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
554 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
555 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
556 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
557 u32 peer_capability, const u8 *buf, size_t len);
558 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
559 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
560 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
561 u32 peer_capability, bool initiator, const u8 *buf, size_t len);
562 #else /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
563 static s32 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
564 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
565 const u8 *buf, size_t len);
566 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
567 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
568 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
569 const u8 *peer, enum nl80211_tdls_operation oper);
570 #else
571 static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
572 u8 *peer, enum nl80211_tdls_operation oper);
573 #endif
574 #endif
575 #ifdef WL_SCHED_SCAN
576 static int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev
577 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
578 , u64 reqid
579 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
580 );
581 #endif
582 static s32 wl_cfg80211_set_ap_role(struct bcm_cfg80211 *cfg, struct net_device *dev);
583 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
584 bcm_struct_cfgdev*
585 wl_cfg80211_create_iface(struct wiphy *wiphy, enum nl80211_iftype
586 iface_type, u8 *mac_addr, const char *name);
587 s32
588 wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev);
589 #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
590
591 s32 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
592 struct net_device *ndev, s32 bsscfg_idx,
593 enum nl80211_iftype iface_type, s32 del, u8 *addr);
594 s32 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
595 struct net_device *ndev, s32 bsscfg_idx,
596 enum nl80211_iftype iface_type, s32 del, u8 *addr);
597 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
598 static s32 wl_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev);
599 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */
600 #ifdef GTK_OFFLOAD_SUPPORT
601 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
602 static s32 wl_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
603 struct cfg80211_gtk_rekey_data *data);
604 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
605 #endif /* GTK_OFFLOAD_SUPPORT */
606 chanspec_t wl_chspec_driver_to_host(chanspec_t chanspec);
607 chanspec_t wl_chspec_host_to_driver(chanspec_t chanspec);
608 #ifdef WL11ULB
609 static s32 wl_cfg80211_get_ulb_bw(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev);
610 static chanspec_t wl_cfg80211_ulb_get_min_bw_chspec(struct bcm_cfg80211 *cfg,
611 struct wireless_dev *wdev, s32 bssidx);
612 static s32 wl_cfg80211_ulbbw_to_ulbchspec(u32 ulb_bw);
613 #else
614 static inline chanspec_t wl_cfg80211_ulb_get_min_bw_chspec(
615 struct bcm_cfg80211 *cfg, struct wireless_dev *wdev, s32 bssidx)
616 {
617 return WL_CHANSPEC_BW_20;
618 }
619 #endif /* WL11ULB */
620 static void wl_cfg80211_wait_for_disconnection(struct bcm_cfg80211 *cfg, struct net_device *dev);
621
622 /*
623 * event & event Q handlers for cfg80211 interfaces
624 */
625 static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg);
626 static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg);
627 static void wl_event_handler(struct work_struct *work_data);
628 static void wl_init_eq(struct bcm_cfg80211 *cfg);
629 static void wl_flush_eq(struct bcm_cfg80211 *cfg);
630 static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg);
631 static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags);
632 static void wl_init_eq_lock(struct bcm_cfg80211 *cfg);
633 static void wl_init_event_handler(struct bcm_cfg80211 *cfg);
634 static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg);
635 static s32 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 type,
636 const wl_event_msg_t *msg, void *data);
637 static void wl_put_event(struct wl_event_q *e);
638 static s32 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
639 const wl_event_msg_t *e, void *data);
640 static s32 wl_notify_connect_status(struct bcm_cfg80211 *cfg,
641 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
642 static s32 wl_notify_roaming_status(struct bcm_cfg80211 *cfg,
643 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
644 static s32 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
645 const wl_event_msg_t *e, void *data);
646 static s32 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
647 const wl_event_msg_t *e, void *data, bool completed);
648 static s32 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
649 const wl_event_msg_t *e, void *data);
650 static s32 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
651 const wl_event_msg_t *e, void *data);
652 #ifdef BT_WIFI_HANDOVER
653 static s32 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg,
654 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
655 #endif /* BT_WIFI_HANDOVER */
656 #ifdef WL_SCHED_SCAN
657 static s32
658 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
659 const wl_event_msg_t *e, void *data);
660 #endif /* WL_SCHED_SCAN */
661 #ifdef PNO_SUPPORT
662 static s32 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
663 const wl_event_msg_t *e, void *data);
664 #endif /* PNO_SUPPORT */
665 #ifdef GSCAN_SUPPORT
666 static s32 wl_notify_gscan_event(struct bcm_cfg80211 *wl, bcm_struct_cfgdev *cfgdev,
667 const wl_event_msg_t *e, void *data);
668 static s32 wl_handle_roam_exp_event(struct bcm_cfg80211 *wl, bcm_struct_cfgdev *cfgdev,
669 const wl_event_msg_t *e, void *data);
670 #endif /* GSCAN_SUPPORT */
671 #ifdef RSSI_MONITOR_SUPPORT
672 static s32 wl_handle_rssi_monitor_event(struct bcm_cfg80211 *wl, bcm_struct_cfgdev *cfgdev,
673 const wl_event_msg_t *e, void *data);
674 #endif /* RSSI_MONITOR_SUPPORT */
675 static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
676 enum wl_status state, bool set);
677 #ifdef CUSTOM_EVENT_PM_WAKE
678 static s32 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
679 const wl_event_msg_t *e, void *data);
680 #endif /* CUSTOM_EVENT_PM_WAKE */
681 #ifdef ENABLE_TEMP_THROTTLING
682 static s32 wl_check_rx_throttle_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
683 const wl_event_msg_t *e, void *data);
684 #endif /* ENABLE_TEMP_THROTTLING */
685 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
686 static s32 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg,
687 bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
688 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
689 #ifdef DHD_LOSSLESS_ROAMING
690 static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg);
691 #endif /* DHD_LOSSLESS_ROAMING */
692
693 #ifdef WLTDLS
694 static s32 wl_cfg80211_tdls_config(struct bcm_cfg80211 *cfg,
695 enum wl_tdls_config state, bool tdls_mode);
696 static s32 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
697 const wl_event_msg_t *e, void *data);
698 #endif /* WLTDLS */
699 /*
700 * register/deregister parent device
701 */
702 static void wl_cfg80211_clear_parent_dev(void);
703 /*
704 * ioctl utilites
705 */
706
707 /*
708 * cfg80211 set_wiphy_params utilities
709 */
710 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold);
711 static s32 wl_set_rts(struct net_device *dev, u32 frag_threshold);
712 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l);
713
714 /*
715 * cfg profile utilities
716 */
717 static s32 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
718 const wl_event_msg_t *e, const void *data, s32 item);
719 static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item);
720 static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev);
721
722 /*
723 * cfg80211 connect utilites
724 */
725 static s32 wl_set_wpa_version(struct net_device *dev,
726 struct cfg80211_connect_params *sme);
727 static s32 wl_set_auth_type(struct net_device *dev,
728 struct cfg80211_connect_params *sme);
729 static s32 wl_set_set_cipher(struct net_device *dev,
730 struct cfg80211_connect_params *sme);
731 static s32 wl_set_key_mgmt(struct net_device *dev,
732 struct cfg80211_connect_params *sme);
733 static s32 wl_set_set_sharedkey(struct net_device *dev,
734 struct cfg80211_connect_params *sme);
735 static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev);
736 static s32 wl_ch_to_chanspec(struct net_device *dev, int ch,
737 struct wl_join_params *join_params, size_t *join_params_size);
738 void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg);
739
740 /*
741 * information element utilities
742 */
743 static void wl_rst_ie(struct bcm_cfg80211 *cfg);
744 static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v);
745 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
746 bool roam);
747 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size);
748 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size);
749 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg);
750 #ifdef MFP
751 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8** rsn_cap);
752 #endif
753
754 #ifdef WL11U
755 static bcm_tlv_t *
756 wl_cfg80211_find_interworking_ie(const u8 *parse, u32 len);
757 static s32
758 wl_cfg80211_clear_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx);
759 static s32
760 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
761 uint8 ie_id, uint8 *data, uint8 data_len);
762 #endif /* WL11U */
763
764 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, dhd_pub_t *data);
765 static void wl_free_wdev(struct bcm_cfg80211 *cfg);
766 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
767 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
768 static int
769 #else
770 static void
771 #endif /* kernel version < 3.10.11 */
772 wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
773 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
774
775 static s32 wl_inform_bss(struct bcm_cfg80211 *cfg);
776 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam);
777 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam);
778 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy);
779 s32 wl_cfg80211_channel_to_freq(u32 channel);
780
781
782 static void wl_cfg80211_work_handler(struct work_struct *work);
783 static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
784 u8 key_idx, const u8 *mac_addr,
785 struct key_params *params);
786 /*
787 * key indianess swap utilities
788 */
789 static void swap_key_from_BE(struct wl_wsec_key *key);
790 static void swap_key_to_BE(struct wl_wsec_key *key);
791
792 /*
793 * bcm_cfg80211 memory init/deinit utilities
794 */
795 static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg);
796 static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg);
797
798 static void wl_delay(u32 ms);
799
800 /*
801 * ibss mode utilities
802 */
803 static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev);
804 static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg);
805
806 /*
807 * link up/down , default configuration utilities
808 */
809 static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg);
810 static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg);
811
812 #ifdef WL_LASTEVT
813 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, void *data);
814 #define WL_IS_LINKDOWN(cfg, e, data) wl_is_linkdown(cfg, e, data)
815 #else
816 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
817 #define WL_IS_LINKDOWN(cfg, e, data) wl_is_linkdown(cfg, e)
818 #endif /* WL_LASTEVT */
819
820 static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e,
821 struct net_device *ndev);
822 static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e);
823 static void wl_link_up(struct bcm_cfg80211 *cfg);
824 static void wl_link_down(struct bcm_cfg80211 *cfg);
825 static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype);
826 static void wl_init_conf(struct wl_conf *conf);
827 static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
828 struct net_device* ndev);
829 int wl_cfg80211_get_ioctl_version(void);
830
831 /*
832 * find most significant bit set
833 */
834 static __used u32 wl_find_msb(u16 bit16);
835
836 /*
837 * rfkill support
838 */
839 static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup);
840 static int wl_rfkill_set(void *data, bool blocked);
841 #ifdef DEBUGFS_CFG80211
842 static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg);
843 static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg);
844 #endif
845 static wl_scan_params_t *wl_cfg80211_scan_alloc_params(struct bcm_cfg80211 *cfg,
846 int channel, int nprobes, int *out_params_size);
847 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role);
848
849 #ifdef WL_CFG80211_ACL
850 /* ACL */
851 static int wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
852 const struct cfg80211_acl_data *acl);
853 #endif /* WL_CFG80211_ACL */
854
855 /*
856 * Some external functions, TODO: move them to dhd_linux.h
857 */
858 int dhd_add_monitor(const char *name, struct net_device **new_ndev);
859 int dhd_del_monitor(struct net_device *ndev);
860 int dhd_monitor_init(void *dhd_pub);
861 int dhd_monitor_uninit(void);
862 int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
863
864
865 #ifdef P2P_LISTEN_OFFLOADING
866 s32 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg);
867 #endif /* P2P_LISTEN_OFFLOADING */
868
869 #ifdef PKT_FILTER_SUPPORT
870 extern uint dhd_pkt_filter_enable;
871 extern uint dhd_master_mode;
872 extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode);
873 #endif /* PKT_FILTER_SUPPORT */
874
875 #ifdef SUPPORT_SET_CAC
876 static void wl_cfg80211_set_cac(struct bcm_cfg80211 *cfg, int enable);
877 #endif /* SUPPORT_SET_CAC */
878
879 static int wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
880 const struct ether_addr *bssid);
881 static s32 __wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify);
882
883 static int bw2cap[] = { 0, 0, WLC_BW_CAP_20MHZ, WLC_BW_CAP_40MHZ, WLC_BW_CAP_80MHZ,
884 WLC_BW_CAP_160MHZ, WLC_BW_CAP_160MHZ };
885
886 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) || (defined(CONFIG_ARCH_MSM) && \
887 defined(CFG80211_DISCONNECTED_V2))
888 #define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
889 cfg80211_disconnected(dev, reason, ie, len, loc_gen, gfp);
890 #elif (LINUX_VERSION_CODE < KERNEL_VERSION(4, 2, 0))
891 #define CFG80211_DISCONNECTED(dev, reason, ie, len, loc_gen, gfp) \
892 cfg80211_disconnected(dev, reason, ie, len, gfp);
893 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)) */
894
895 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) || (defined(CONFIG_ARCH_MSM) && \
896 defined(CFG80211_DISCONNECTED_V2))
897 #define CFG80211_GET_BSS(wiphy, channel, bssid, ssid, ssid_len) \
898 cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, \
899 IEEE80211_BSS_TYPE_ESS, IEEE80211_PRIVACY_ANY);
900 #else
901 #define CFG80211_GET_BSS(wiphy, channel, bssid, ssid, ssid_len) \
902 cfg80211_get_bss(wiphy, channel, bssid, ssid, ssid_len, \
903 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
904 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
905
906 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \
907 (akm) == RSN_AKM_UNSPECIFIED || \
908 (akm) == RSN_AKM_PSK)
909
910
911 extern int dhd_wait_pend8021x(struct net_device *dev);
912 #ifdef PROP_TXSTATUS_VSDB
913 extern int disable_proptx;
914 #endif /* PROP_TXSTATUS_VSDB */
915
916
917 extern int passive_channel_skip;
918
919 static s32
920 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
921 const wl_event_msg_t *e, void *data);
922 static s32
923 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
924 const wl_event_msg_t *e, void *data);
925 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, \
926 0)))
927 struct chan_info {
928 int freq;
929 int chan_type;
930 };
931 #endif
932
933 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
934 #define CFG80211_PUT_BSS(wiphy, bss) cfg80211_put_bss(wiphy, bss);
935 #else
936 #define CFG80211_PUT_BSS(wiphy, bss) cfg80211_put_bss(bss);
937 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
938
939 #define CHAN2G(_channel, _freq, _flags) { \
940 .band = IEEE80211_BAND_2GHZ, \
941 .center_freq = (_freq), \
942 .hw_value = (_channel), \
943 .flags = (_flags), \
944 .max_antenna_gain = 0, \
945 .max_power = 30, \
946 }
947
948 #define CHAN5G(_channel, _flags) { \
949 .band = IEEE80211_BAND_5GHZ, \
950 .center_freq = 5000 + (5 * (_channel)), \
951 .hw_value = (_channel), \
952 .flags = (_flags), \
953 .max_antenna_gain = 0, \
954 .max_power = 30, \
955 }
956
957 #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
958 #define RATETAB_ENT(_rateid, _flags) \
959 { \
960 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
961 .hw_value = (_rateid), \
962 .flags = (_flags), \
963 }
964
965 static struct ieee80211_rate __wl_rates[] = {
966 RATETAB_ENT(DOT11_RATE_1M, 0),
967 RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
968 RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
969 RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
970 RATETAB_ENT(DOT11_RATE_6M, 0),
971 RATETAB_ENT(DOT11_RATE_9M, 0),
972 RATETAB_ENT(DOT11_RATE_12M, 0),
973 RATETAB_ENT(DOT11_RATE_18M, 0),
974 RATETAB_ENT(DOT11_RATE_24M, 0),
975 RATETAB_ENT(DOT11_RATE_36M, 0),
976 RATETAB_ENT(DOT11_RATE_48M, 0),
977 RATETAB_ENT(DOT11_RATE_54M, 0)
978 };
979
980 #define wl_a_rates (__wl_rates + 4)
981 #define wl_a_rates_size 8
982 #define wl_g_rates (__wl_rates + 0)
983 #define wl_g_rates_size 12
984
985 static struct ieee80211_channel __wl_2ghz_channels[] = {
986 CHAN2G(1, 2412, 0),
987 CHAN2G(2, 2417, 0),
988 CHAN2G(3, 2422, 0),
989 CHAN2G(4, 2427, 0),
990 CHAN2G(5, 2432, 0),
991 CHAN2G(6, 2437, 0),
992 CHAN2G(7, 2442, 0),
993 CHAN2G(8, 2447, 0),
994 CHAN2G(9, 2452, 0),
995 CHAN2G(10, 2457, 0),
996 CHAN2G(11, 2462, 0),
997 CHAN2G(12, 2467, 0),
998 CHAN2G(13, 2472, 0),
999 CHAN2G(14, 2484, 0)
1000 };
1001
1002 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
1003 CHAN5G(34, 0), CHAN5G(36, 0),
1004 CHAN5G(38, 0), CHAN5G(40, 0),
1005 CHAN5G(42, 0), CHAN5G(44, 0),
1006 CHAN5G(46, 0), CHAN5G(48, 0),
1007 CHAN5G(52, 0), CHAN5G(56, 0),
1008 CHAN5G(60, 0), CHAN5G(64, 0),
1009 CHAN5G(100, 0), CHAN5G(104, 0),
1010 CHAN5G(108, 0), CHAN5G(112, 0),
1011 CHAN5G(116, 0), CHAN5G(120, 0),
1012 CHAN5G(124, 0), CHAN5G(128, 0),
1013 CHAN5G(132, 0), CHAN5G(136, 0),
1014 CHAN5G(140, 0), CHAN5G(144, 0),
1015 CHAN5G(149, 0), CHAN5G(153, 0),
1016 CHAN5G(157, 0), CHAN5G(161, 0),
1017 CHAN5G(165, 0)
1018 };
1019
1020 static struct ieee80211_supported_band __wl_band_2ghz = {
1021 .band = IEEE80211_BAND_2GHZ,
1022 .channels = __wl_2ghz_channels,
1023 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
1024 .bitrates = wl_g_rates,
1025 .n_bitrates = wl_g_rates_size
1026 };
1027
1028 static struct ieee80211_supported_band __wl_band_5ghz_a = {
1029 .band = IEEE80211_BAND_5GHZ,
1030 .channels = __wl_5ghz_a_channels,
1031 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
1032 .bitrates = wl_a_rates,
1033 .n_bitrates = wl_a_rates_size
1034 };
1035
1036 static const u32 __wl_cipher_suites[] = {
1037 WLAN_CIPHER_SUITE_WEP40,
1038 WLAN_CIPHER_SUITE_WEP104,
1039 WLAN_CIPHER_SUITE_TKIP,
1040 WLAN_CIPHER_SUITE_CCMP,
1041 #ifdef MFP
1042 /*
1043 * Advertising AES_CMAC cipher suite to userspace would imply that we
1044 * are supporting MFP. So advertise only when MFP support is enabled.
1045 */
1046 WLAN_CIPHER_SUITE_AES_CMAC,
1047 #endif /* MFP */
1048 };
1049
1050 #ifdef WL_SUPPORT_ACS
1051 /*
1052 * The firmware code required for this feature to work is currently under
1053 * BCMINTERNAL flag. In future if this is to enabled we need to bring the
1054 * required firmware code out of the BCMINTERNAL flag.
1055 */
1056 struct wl_dump_survey {
1057 u32 obss;
1058 u32 ibss;
1059 u32 no_ctg;
1060 u32 no_pckt;
1061 u32 tx;
1062 u32 idle;
1063 };
1064 #endif /* WL_SUPPORT_ACS */
1065
1066
1067 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
1068 static int maxrxpktglom = 0;
1069 #endif
1070
1071 /* IOCtl version read from targeted driver */
1072 int ioctl_version;
1073 #ifdef DEBUGFS_CFG80211
1074 #define S_SUBLOGLEVEL 20
1075 static const struct {
1076 u32 log_level;
1077 char *sublogname;
1078 } sublogname_map[] = {
1079 {WL_DBG_ERR, "ERR"},
1080 {WL_DBG_INFO, "INFO"},
1081 {WL_DBG_DBG, "DBG"},
1082 {WL_DBG_SCAN, "SCAN"},
1083 {WL_DBG_TRACE, "TRACE"},
1084 {WL_DBG_P2P_ACTION, "P2PACTION"}
1085 };
1086 #endif
1087
1088 #ifdef CUSTOMER_HW4_DEBUG
1089 uint prev_dhd_console_ms = 0;
1090 u32 prev_wl_dbg_level = 0;
1091 bool wl_scan_timeout_dbg_enabled = 0;
1092 static void wl_scan_timeout_dbg_set(void);
1093 static void wl_scan_timeout_dbg_clear(void);
1094
1095 static void wl_scan_timeout_dbg_set(void)
1096 {
1097 WL_ERR(("Enter \n"));
1098 prev_dhd_console_ms = dhd_console_ms;
1099 prev_wl_dbg_level = wl_dbg_level;
1100
1101 dhd_console_ms = 1;
1102 wl_dbg_level |= (WL_DBG_ERR | WL_DBG_P2P_ACTION | WL_DBG_SCAN);
1103
1104 wl_scan_timeout_dbg_enabled = 1;
1105 }
1106 static void wl_scan_timeout_dbg_clear(void)
1107 {
1108 WL_ERR(("Enter \n"));
1109 dhd_console_ms = prev_dhd_console_ms;
1110 wl_dbg_level = prev_wl_dbg_level;
1111
1112 wl_scan_timeout_dbg_enabled = 0;
1113 }
1114 #endif /* CUSTOMER_HW4_DEBUG */
1115
1116 /* watchdog timer for disconnecting when fw is not associated for FW_ASSOC_WATCHDOG_TIME ms */
1117 uint32 fw_assoc_watchdog_ms = 0;
1118 bool fw_assoc_watchdog_started = 0;
1119 #define FW_ASSOC_WATCHDOG_TIME 10 * 1000 /* msec */
1120
1121 static void wl_add_remove_pm_enable_work(struct bcm_cfg80211 *cfg,
1122 enum wl_pm_workq_act_type type)
1123 {
1124 u16 wq_duration = 0;
1125 dhd_pub_t *dhd = NULL;
1126
1127 if (cfg == NULL)
1128 return;
1129
1130 dhd = (dhd_pub_t *)(cfg->pub);
1131
1132 mutex_lock(&cfg->pm_sync);
1133 /*
1134 * Make cancel and schedule work part mutually exclusive
1135 * so that while cancelling, we are sure that there is no
1136 * work getting scheduled.
1137 */
1138 if (delayed_work_pending(&cfg->pm_enable_work)) {
1139 cancel_delayed_work_sync(&cfg->pm_enable_work);
1140 DHD_PM_WAKE_UNLOCK(cfg->pub);
1141 }
1142
1143 if (type == WL_PM_WORKQ_SHORT) {
1144 wq_duration = WL_PM_ENABLE_TIMEOUT;
1145 } else if (type == WL_PM_WORKQ_LONG) {
1146 wq_duration = (WL_PM_ENABLE_TIMEOUT*2);
1147 }
1148
1149 /* It should schedule work item only if driver is up */
1150 if (wq_duration && dhd->up) {
1151 if (schedule_delayed_work(&cfg->pm_enable_work,
1152 msecs_to_jiffies((const unsigned int)wq_duration))) {
1153 DHD_PM_WAKE_LOCK_TIMEOUT(cfg->pub, wq_duration);
1154 } else {
1155 WL_ERR(("Can't schedule pm work handler\n"));
1156 }
1157 }
1158 mutex_unlock(&cfg->pm_sync);
1159 }
1160
1161 /* Return a new chanspec given a legacy chanspec
1162 * Returns INVCHANSPEC on error
1163 */
1164 chanspec_t
1165 wl_chspec_from_legacy(chanspec_t legacy_chspec)
1166 {
1167 chanspec_t chspec;
1168
1169 /* get the channel number */
1170 chspec = LCHSPEC_CHANNEL(legacy_chspec);
1171
1172 /* convert the band */
1173 if (LCHSPEC_IS2G(legacy_chspec)) {
1174 chspec |= WL_CHANSPEC_BAND_2G;
1175 } else {
1176 chspec |= WL_CHANSPEC_BAND_5G;
1177 }
1178
1179 /* convert the bw and sideband */
1180 if (LCHSPEC_IS20(legacy_chspec)) {
1181 chspec |= WL_CHANSPEC_BW_20;
1182 } else {
1183 chspec |= WL_CHANSPEC_BW_40;
1184 if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
1185 chspec |= WL_CHANSPEC_CTL_SB_L;
1186 } else {
1187 chspec |= WL_CHANSPEC_CTL_SB_U;
1188 }
1189 }
1190
1191 if (wf_chspec_malformed(chspec)) {
1192 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
1193 chspec));
1194 return INVCHANSPEC;
1195 }
1196
1197 return chspec;
1198 }
1199
1200 /* Return a legacy chanspec given a new chanspec
1201 * Returns INVCHANSPEC on error
1202 */
1203 static chanspec_t
1204 wl_chspec_to_legacy(chanspec_t chspec)
1205 {
1206 chanspec_t lchspec;
1207
1208 if (wf_chspec_malformed(chspec)) {
1209 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
1210 chspec));
1211 return INVCHANSPEC;
1212 }
1213
1214 /* get the channel number */
1215 lchspec = CHSPEC_CHANNEL(chspec);
1216
1217 /* convert the band */
1218 if (CHSPEC_IS2G(chspec)) {
1219 lchspec |= WL_LCHANSPEC_BAND_2G;
1220 } else {
1221 lchspec |= WL_LCHANSPEC_BAND_5G;
1222 }
1223
1224 /* convert the bw and sideband */
1225 if (CHSPEC_IS20(chspec)) {
1226 lchspec |= WL_LCHANSPEC_BW_20;
1227 lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
1228 } else if (CHSPEC_IS40(chspec)) {
1229 lchspec |= WL_LCHANSPEC_BW_40;
1230 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
1231 lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
1232 } else {
1233 lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
1234 }
1235 } else {
1236 /* cannot express the bandwidth */
1237 char chanbuf[CHANSPEC_STR_LEN];
1238 WL_ERR((
1239 "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
1240 "to pre-11ac format\n",
1241 wf_chspec_ntoa(chspec, chanbuf), chspec));
1242 return INVCHANSPEC;
1243 }
1244
1245 return lchspec;
1246 }
1247
1248 /* given a chanspec value, do the endian and chanspec version conversion to
1249 * a chanspec_t value
1250 * Returns INVCHANSPEC on error
1251 */
1252 chanspec_t
1253 wl_chspec_host_to_driver(chanspec_t chanspec)
1254 {
1255 if (ioctl_version == 1) {
1256 chanspec = wl_chspec_to_legacy(chanspec);
1257 if (chanspec == INVCHANSPEC) {
1258 return chanspec;
1259 }
1260 }
1261 chanspec = htodchanspec(chanspec);
1262
1263 return chanspec;
1264 }
1265
1266 /* given a channel value, do the endian and chanspec version conversion to
1267 * a chanspec_t value
1268 * Returns INVCHANSPEC on error
1269 */
1270 chanspec_t
1271 wl_ch_host_to_driver(struct bcm_cfg80211 *cfg, s32 bssidx, u16 channel)
1272 {
1273 chanspec_t chanspec;
1274
1275 chanspec = channel & WL_CHANSPEC_CHAN_MASK;
1276
1277 if (channel <= CH_MAX_2G_CHANNEL)
1278 chanspec |= WL_CHANSPEC_BAND_2G;
1279 else
1280 chanspec |= WL_CHANSPEC_BAND_5G;
1281
1282 chanspec |= wl_cfg80211_ulb_get_min_bw_chspec(cfg, NULL, bssidx);
1283
1284 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1285
1286 return wl_chspec_host_to_driver(chanspec);
1287 }
1288
1289 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
1290 * a chanspec_t value
1291 * Returns INVCHANSPEC on error
1292 */
1293 chanspec_t
1294 wl_chspec_driver_to_host(chanspec_t chanspec)
1295 {
1296 chanspec = dtohchanspec(chanspec);
1297 if (ioctl_version == 1) {
1298 chanspec = wl_chspec_from_legacy(chanspec);
1299 }
1300
1301 return chanspec;
1302 }
1303
1304 /*
1305 * convert ASCII string to MAC address (colon-delimited format)
1306 * eg: 00:11:22:33:44:55
1307 */
1308 int
1309 wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n)
1310 {
1311 char *c = NULL;
1312 int count = 0;
1313
1314 memset(n, 0, ETHER_ADDR_LEN);
1315 for (;;) {
1316 n->octet[count++] = (uint8)simple_strtoul(a, &c, 16);
1317 if (!*c++ || count == ETHER_ADDR_LEN)
1318 break;
1319 a = c;
1320 }
1321 return (count == ETHER_ADDR_LEN);
1322 }
1323
1324 /* There isn't a lot of sense in it, but you can transmit anything you like */
1325 static const struct ieee80211_txrx_stypes
1326 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
1327 #ifdef WLMESH
1328 [NL80211_IFTYPE_MESH_POINT] = {
1329 .tx = 0xffff,
1330 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1331 BIT(IEEE80211_STYPE_AUTH >> 4)
1332 },
1333 #endif /* WLMESH */
1334 [NL80211_IFTYPE_ADHOC] = {
1335 .tx = 0xffff,
1336 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
1337 },
1338 [NL80211_IFTYPE_STATION] = {
1339 .tx = 0xffff,
1340 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1341 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1342 },
1343 [NL80211_IFTYPE_AP] = {
1344 .tx = 0xffff,
1345 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1346 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1347 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1348 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1349 BIT(IEEE80211_STYPE_AUTH >> 4) |
1350 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1351 BIT(IEEE80211_STYPE_ACTION >> 4)
1352 },
1353 [NL80211_IFTYPE_AP_VLAN] = {
1354 /* copy AP */
1355 .tx = 0xffff,
1356 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1357 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1358 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1359 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1360 BIT(IEEE80211_STYPE_AUTH >> 4) |
1361 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1362 BIT(IEEE80211_STYPE_ACTION >> 4)
1363 },
1364 [NL80211_IFTYPE_P2P_CLIENT] = {
1365 .tx = 0xffff,
1366 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1367 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1368 },
1369 [NL80211_IFTYPE_P2P_GO] = {
1370 .tx = 0xffff,
1371 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1372 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1373 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1374 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1375 BIT(IEEE80211_STYPE_AUTH >> 4) |
1376 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1377 BIT(IEEE80211_STYPE_ACTION >> 4)
1378 },
1379 #if defined(WL_CFG80211_P2P_DEV_IF)
1380 [NL80211_IFTYPE_P2P_DEVICE] = {
1381 .tx = 0xffff,
1382 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1383 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1384 },
1385 #endif /* WL_CFG80211_P2P_DEV_IF */
1386 };
1387
1388 static void swap_key_from_BE(struct wl_wsec_key *key)
1389 {
1390 key->index = htod32(key->index);
1391 key->len = htod32(key->len);
1392 key->algo = htod32(key->algo);
1393 key->flags = htod32(key->flags);
1394 key->rxiv.hi = htod32(key->rxiv.hi);
1395 key->rxiv.lo = htod16(key->rxiv.lo);
1396 key->iv_initialized = htod32(key->iv_initialized);
1397 }
1398
1399 static void swap_key_to_BE(struct wl_wsec_key *key)
1400 {
1401 key->index = dtoh32(key->index);
1402 key->len = dtoh32(key->len);
1403 key->algo = dtoh32(key->algo);
1404 key->flags = dtoh32(key->flags);
1405 key->rxiv.hi = dtoh32(key->rxiv.hi);
1406 key->rxiv.lo = dtoh16(key->rxiv.lo);
1407 key->iv_initialized = dtoh32(key->iv_initialized);
1408 }
1409
1410 /* Dump the contents of the encoded wps ie buffer and get pbc value */
1411 static void
1412 wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
1413 {
1414 #define WPS_IE_FIXED_LEN 6
1415 s16 len;
1416 u8 *subel = NULL;
1417 u16 subelt_id;
1418 u16 subelt_len;
1419 u16 val;
1420 u8 *valptr = (uint8*) &val;
1421 if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
1422 WL_ERR(("invalid argument : NULL\n"));
1423 return;
1424 }
1425 len = (s16)wps_ie[TLV_LEN_OFF];
1426
1427 if (len > wps_ie_len) {
1428 WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
1429 return;
1430 }
1431 WL_DBG(("wps_ie len=%d\n", len));
1432 len -= 4; /* for the WPS IE's OUI, oui_type fields */
1433 subel = wps_ie + WPS_IE_FIXED_LEN;
1434 while (len >= 4) { /* must have attr id, attr len fields */
1435 valptr[0] = *subel++;
1436 valptr[1] = *subel++;
1437 subelt_id = HTON16(val);
1438
1439 valptr[0] = *subel++;
1440 valptr[1] = *subel++;
1441 subelt_len = HTON16(val);
1442
1443 len -= 4; /* for the attr id, attr len fields */
1444 len -= (s16)subelt_len; /* for the remaining fields in this attribute */
1445 if (len < 0) {
1446 break;
1447 }
1448 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1449 subel, subelt_id, subelt_len));
1450
1451 if (subelt_id == WPS_ID_VERSION) {
1452 WL_DBG((" attr WPS_ID_VERSION: %u\n", *subel));
1453 } else if (subelt_id == WPS_ID_REQ_TYPE) {
1454 WL_DBG((" attr WPS_ID_REQ_TYPE: %u\n", *subel));
1455 } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
1456 valptr[0] = *subel;
1457 valptr[1] = *(subel + 1);
1458 WL_DBG((" attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
1459 } else if (subelt_id == WPS_ID_DEVICE_NAME) {
1460 char devname[100];
1461 int namelen = MIN(subelt_len, (sizeof(devname) - 1));
1462
1463 if (namelen) {
1464 memcpy(devname, subel, namelen);
1465 devname[namelen] = '\0';
1466 /* Printing len as rx'ed in the IE */
1467 WL_DBG((" attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1468 devname, subelt_len));
1469 }
1470 } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
1471 valptr[0] = *subel;
1472 valptr[1] = *(subel + 1);
1473 WL_DBG((" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
1474 *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
1475 } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
1476 valptr[0] = *subel;
1477 valptr[1] = *(subel + 1);
1478 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
1479 valptr[0] = *(subel + 6);
1480 valptr[1] = *(subel + 7);
1481 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
1482 } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
1483 valptr[0] = *subel;
1484 valptr[1] = *(subel + 1);
1485 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
1486 valptr[0] = *(subel + 6);
1487 valptr[1] = *(subel + 7);
1488 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
1489 } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
1490 valptr[0] = *subel;
1491 valptr[1] = *(subel + 1);
1492 WL_DBG((" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1493 ": cat=%u\n", HTON16(val)));
1494 } else {
1495 WL_DBG((" unknown attr 0x%x\n", subelt_id));
1496 }
1497
1498 subel += subelt_len;
1499 }
1500 }
1501
1502 s32 wl_set_tx_power(struct net_device *dev,
1503 enum nl80211_tx_power_setting type, s32 dbm)
1504 {
1505 s32 err = 0;
1506 s32 disable = 0;
1507 s32 txpwrqdbm;
1508 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
1509
1510 /* Make sure radio is off or on as far as software is concerned */
1511 disable = WL_RADIO_SW_DISABLE << 16;
1512 disable = htod32(disable);
1513 err = wldev_ioctl_set(dev, WLC_SET_RADIO, &disable, sizeof(disable));
1514 if (unlikely(err)) {
1515 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
1516 return err;
1517 }
1518
1519 if (dbm > 0xffff)
1520 dbm = 0xffff;
1521 txpwrqdbm = dbm * 4;
1522 err = wldev_iovar_setbuf_bsscfg(dev, "qtxpower", (void *)&txpwrqdbm,
1523 sizeof(txpwrqdbm), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
1524 &cfg->ioctl_buf_sync);
1525 if (unlikely(err))
1526 WL_ERR(("qtxpower error (%d)\n", err));
1527 else
1528 WL_ERR(("dBm=%d, txpwrqdbm=0x%x\n", dbm, txpwrqdbm));
1529
1530 return err;
1531 }
1532
1533 s32 wl_get_tx_power(struct net_device *dev, s32 *dbm)
1534 {
1535 s32 err = 0;
1536 s32 txpwrdbm;
1537 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
1538
1539 err = wldev_iovar_getbuf_bsscfg(dev, "qtxpower",
1540 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
1541 if (unlikely(err)) {
1542 WL_ERR(("error (%d)\n", err));
1543 return err;
1544 }
1545
1546 memcpy(&txpwrdbm, cfg->ioctl_buf, sizeof(txpwrdbm));
1547 txpwrdbm = dtoh32(txpwrdbm);
1548 *dbm = (txpwrdbm & ~WL_TXPWR_OVERRIDE) / 4;
1549
1550 WL_INFORM(("dBm=%d, txpwrdbm=0x%x\n", *dbm, txpwrdbm));
1551
1552 return err;
1553 }
1554
1555 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
1556 {
1557 chanspec_t chspec;
1558 int cur_band, err = 0;
1559 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1560 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
1561 struct ether_addr bssid;
1562 struct wl_bss_info *bss = NULL;
1563 s32 bssidx = 0; /* Explicitly set to primary bssidx */
1564 char *buf;
1565
1566 memset(&bssid, 0, sizeof(bssid));
1567 if ((err = wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, sizeof(bssid)))) {
1568 /* STA interface is not associated. So start the new interface on a temp
1569 * channel . Later proper channel will be applied by the above framework
1570 * via set_channel (cfg80211 API).
1571 */
1572 WL_DBG(("Not associated. Return a temp channel. \n"));
1573 cur_band = 0;
1574 err = wldev_ioctl_get(dev, WLC_GET_BAND, &cur_band, sizeof(int));
1575 if (unlikely(err)) {
1576 WL_ERR(("Get band failed\n"));
1577 return wl_ch_host_to_driver(cfg, bssidx, WL_P2P_TEMP_CHAN);
1578 }
1579 if (cur_band == WLC_BAND_5G)
1580 return wl_ch_host_to_driver(cfg, bssidx, WL_P2P_TEMP_CHAN_5G);
1581 else
1582 return wl_ch_host_to_driver(cfg, bssidx, WL_P2P_TEMP_CHAN);
1583 }
1584
1585 buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
1586 if (!buf) {
1587 WL_ERR(("buf alloc failed. use temp channel\n"));
1588 return wl_ch_host_to_driver(cfg, bssidx, WL_P2P_TEMP_CHAN);
1589 }
1590
1591 *(u32 *)buf = htod32(WL_EXTRA_BUF_MAX);
1592 if ((err = wldev_ioctl_get(dev, WLC_GET_BSS_INFO, buf,
1593 WL_EXTRA_BUF_MAX))) {
1594 WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1595 chspec = wl_ch_host_to_driver(cfg, bssidx, WL_P2P_TEMP_CHAN);
1596 }
1597 else {
1598 bss = (struct wl_bss_info *) (buf + 4);
1599 chspec = bss->chanspec;
1600
1601 WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
1602 }
1603
1604 kfree(buf);
1605 return chspec;
1606 }
1607
1608 static bcm_struct_cfgdev *
1609 wl_cfg80211_add_monitor_if(const char *name)
1610 {
1611 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1612 WL_INFORM(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1613 return ERR_PTR(-EOPNOTSUPP);
1614 #else
1615 struct net_device* ndev = NULL;
1616
1617 dhd_add_monitor(name, &ndev);
1618 WL_INFORM(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
1619 return ndev_to_cfgdev(ndev);
1620 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1621 }
1622
1623 static bcm_struct_cfgdev *
1624 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
1625 #if defined(WL_CFG80211_P2P_DEV_IF)
1626 const char *name,
1627 #else
1628 char *name,
1629 #endif /* WL_CFG80211_P2P_DEV_IF */
1630 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
1631 unsigned char name_assign_type,
1632 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
1633 enum nl80211_iftype type,
1634 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
1635 u32 *flags,
1636 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) */
1637 struct vif_params *params)
1638 {
1639 s32 err = -ENODEV;
1640 s32 timeout = -1;
1641 s32 wlif_type = -1;
1642 s32 mode = 0;
1643 s32 val = 0;
1644 s32 cfg_type;
1645 s32 dhd_mode = 0;
1646 chanspec_t chspec;
1647 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1648 struct net_device *primary_ndev;
1649 struct net_device *new_ndev;
1650 struct ether_addr primary_mac;
1651 bcm_struct_cfgdev *new_cfgdev;
1652 #ifdef PROP_TXSTATUS_VSDB
1653 #if defined(BCMSDIO) || defined(BCMDBUS)
1654 s32 up = 1;
1655 bool enabled;
1656 #endif /* BCMSDIO || BCMDBUS */
1657 #endif /* PROP_TXSTATUS_VSDB */
1658 dhd_pub_t *dhd;
1659 bool hang_required = false;
1660
1661 if (!cfg)
1662 return ERR_PTR(-EINVAL);
1663
1664 dhd = (dhd_pub_t *)(cfg->pub);
1665
1666 /* Use primary I/F for sending cmds down to firmware */
1667 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1668
1669 if (unlikely(!wl_get_drv_status(cfg, READY, primary_ndev))) {
1670 WL_ERR(("device is not ready\n"));
1671 return ERR_PTR(-ENODEV);
1672 }
1673
1674 if (!name) {
1675 WL_ERR(("Interface name not provided \n"));
1676 return ERR_PTR(-EINVAL);
1677 }
1678
1679 #ifdef WLTDLS
1680 /* disable TDLS if number of connected interfaces is >= 1 */
1681 wl_cfg80211_tdls_config(cfg, TDLS_STATE_IF_CREATE, false);
1682 #endif /* WLTDLS */
1683
1684 mutex_lock(&cfg->if_sync);
1685 WL_DBG(("if name: %s, type: %d\n", name, type));
1686 switch (type) {
1687 case NL80211_IFTYPE_ADHOC:
1688 #ifdef WLAIBSS_MCHAN
1689 new_cfgdev = bcm_cfg80211_add_ibss_if(wiphy, (char *)name);
1690 mutex_unlock(&cfg->if_sync);
1691 return new_cfgdev;
1692 #endif /* WLAIBSS_MCHAN */
1693 case NL80211_IFTYPE_AP_VLAN:
1694 case NL80211_IFTYPE_WDS:
1695 case NL80211_IFTYPE_MESH_POINT:
1696 WL_ERR(("Unsupported interface type\n"));
1697 mode = WL_MODE_IBSS;
1698 err = -EINVAL;
1699 goto fail;
1700 case NL80211_IFTYPE_MONITOR:
1701 new_cfgdev = wl_cfg80211_add_monitor_if(name);
1702 mutex_unlock(&cfg->if_sync);
1703 return new_cfgdev;
1704 #if defined(WL_CFG80211_P2P_DEV_IF)
1705 case NL80211_IFTYPE_P2P_DEVICE:
1706 cfg->down_disc_if = FALSE;
1707 new_cfgdev = wl_cfgp2p_add_p2p_disc_if(cfg);
1708 mutex_unlock(&cfg->if_sync);
1709 return new_cfgdev;
1710 #endif /* WL_CFG80211_P2P_DEV_IF */
1711 case NL80211_IFTYPE_STATION:
1712 #ifdef WL_VIRTUAL_APSTA
1713 #ifdef WLAIBSS_MCHAN
1714 if (cfg->ibss_cfgdev) {
1715 WL_ERR(("AIBSS is already operational. "
1716 " AIBSS & DUALSTA can't be used together \n"));
1717 err = -ENOMEM;
1718 goto fail;
1719 }
1720 #endif /* WLAIBSS_MCHAN */
1721
1722 if (wl_cfgp2p_vif_created(cfg)) {
1723 WL_ERR(("Could not create new iface."
1724 "Already one p2p interface is running"));
1725 err = -ENOMEM;
1726 goto fail;
1727 }
1728 new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
1729 NL80211_IFTYPE_STATION, NULL, name);
1730 if (!new_cfgdev) {
1731 err = -ENOMEM;
1732 goto fail;
1733 } else {
1734 mutex_unlock(&cfg->if_sync);
1735 return new_cfgdev;
1736 }
1737 #endif /* WL_VIRTUAL_APSTA */
1738 case NL80211_IFTYPE_P2P_CLIENT:
1739 wlif_type = WL_P2P_IF_CLIENT;
1740 mode = WL_MODE_BSS;
1741 break;
1742 case NL80211_IFTYPE_P2P_GO:
1743 wlif_type = WL_P2P_IF_GO;
1744 mode = WL_MODE_AP;
1745 break;
1746 #ifdef WL_VIRTUAL_APSTA
1747 case NL80211_IFTYPE_AP:
1748 dhd->op_mode = DHD_FLAG_HOSTAP_MODE;
1749 new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
1750 NL80211_IFTYPE_AP, NULL, name);
1751 if (!new_cfgdev) {
1752 err = -ENOMEM;
1753 goto fail;
1754 } else {
1755 mutex_unlock(&cfg->if_sync);
1756 return new_cfgdev;
1757 }
1758 #endif /* WL_VIRTUAL_APSTA */
1759 default:
1760 WL_ERR(("Unsupported interface type\n"));
1761 err = -EINVAL;
1762 goto fail;
1763 }
1764
1765 if (cfg->p2p_supported && (wlif_type != -1)) {
1766 ASSERT(cfg->p2p); /* ensure expectation of p2p initialization */
1767
1768 #ifdef PROP_TXSTATUS_VSDB
1769 #if defined(BCMSDIO)
1770 if (!dhd) {
1771 err = -EINVAL;
1772 goto fail;
1773 }
1774 #endif
1775 #endif /* PROP_TXSTATUS_VSDB */
1776
1777 if (!cfg->p2p) {
1778 WL_ERR(("Failed to start p2p"));
1779 err = -ENODEV;
1780 goto fail;
1781 }
1782
1783 if (cfg->p2p && !cfg->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
1784 p2p_on(cfg) = true;
1785 wl_cfgp2p_set_firm_p2p(cfg);
1786 wl_cfgp2p_init_discovery(cfg);
1787 get_primary_mac(cfg, &primary_mac);
1788 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
1789 }
1790
1791 strncpy(cfg->p2p->vir_ifname, name, IFNAMSIZ - 1);
1792 cfg->p2p->vir_ifname[IFNAMSIZ - 1] = '\0';
1793
1794 wl_cfg80211_scan_abort(cfg);
1795 #ifdef PROP_TXSTATUS_VSDB
1796 #if defined(BCMSDIO) || defined(BCMDBUS)
1797 if (!cfg->wlfc_on && !disable_proptx) {
1798 dhd_wlfc_get_enable(dhd, &enabled);
1799 if (!enabled && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
1800 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
1801 dhd_wlfc_init(dhd);
1802 err = wldev_ioctl_set(primary_ndev, WLC_UP, &up, sizeof(s32));
1803 if (err < 0)
1804 WL_ERR(("WLC_UP return err:%d\n", err));
1805 }
1806 cfg->wlfc_on = true;
1807 }
1808 #endif /* BCMSDIO || BCMDBUS */
1809 #endif /* PROP_TXSTATUS_VSDB */
1810
1811 /* Dual p2p doesn't support multiple P2PGO interfaces,
1812 * p2p_go_count is the counter for GO creation
1813 * requests.
1814 */
1815 if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
1816 WL_ERR(("Fw doesnot support multiple Go"));
1817 err = -ENOTSUPP;
1818 goto fail;
1819 }
1820 /* In concurrency case, STA may be already associated in a particular channel.
1821 * so retrieve the current channel of primary interface and then start the virtual
1822 * interface on that.
1823 */
1824 chspec = wl_cfg80211_get_shared_freq(wiphy);
1825
1826 /* For P2P mode, use P2P-specific driver features to create the
1827 * bss: "cfg p2p_ifadd"
1828 */
1829 wl_set_p2p_status(cfg, IF_ADDING);
1830 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
1831 cfg_type = wl_cfgp2p_get_conn_idx(cfg);
1832 if (cfg_type == BCME_ERROR) {
1833 wl_clr_p2p_status(cfg, IF_ADDING);
1834 WL_ERR(("Failed to get connection idx for p2p interface"));
1835 err = -ENOTSUPP;
1836 goto fail;
1837 }
1838 err = wl_cfgp2p_ifadd(cfg, wl_to_p2p_bss_macaddr(cfg, cfg_type),
1839 htod32(wlif_type), chspec);
1840 if (unlikely(err)) {
1841 wl_clr_p2p_status(cfg, IF_ADDING);
1842 WL_ERR((" virtual iface add failed (%d) \n", err));
1843 err = -ENOMEM;
1844 goto fail;
1845 }
1846
1847 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1848 ((wl_get_p2p_status(cfg, IF_ADDING) == false) &&
1849 (cfg->if_event_info.valid)),
1850 msecs_to_jiffies(MAX_WAIT_TIME));
1851
1852 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_ADDING) && cfg->if_event_info.valid) {
1853 struct wireless_dev *vwdev;
1854 int pm_mode = PM_ENABLE;
1855 wl_if_event_info *event = &cfg->if_event_info;
1856 /* IF_ADD event has come back, we can proceed to to register
1857 * the new interface now, use the interface name provided by caller (thus
1858 * ignore the one from wlc)
1859 */
1860 new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, cfg->p2p->vir_ifname,
1861 event->mac, event->bssidx, event->name);
1862 if (new_ndev == NULL) {
1863 err = -ENODEV;
1864 goto fail;
1865 }
1866
1867 wl_to_p2p_bss_ndev(cfg, cfg_type) = new_ndev;
1868 wl_to_p2p_bss_bssidx(cfg, cfg_type) = event->bssidx;
1869 vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
1870 if (unlikely(!vwdev)) {
1871 WL_ERR(("Could not allocate wireless device\n"));
1872 err = -ENOMEM;
1873 goto fail;
1874 }
1875 vwdev->wiphy = cfg->wdev->wiphy;
1876 WL_INFORM(("virtual interface(%s) is created\n", cfg->p2p->vir_ifname));
1877 if (type == NL80211_IFTYPE_P2P_GO) {
1878 cfg->p2p->p2p_go_count++;
1879 }
1880 vwdev->iftype = type;
1881 vwdev->netdev = new_ndev;
1882 new_ndev->ieee80211_ptr = vwdev;
1883 SET_NETDEV_DEV(new_ndev, wiphy_dev(vwdev->wiphy));
1884 wl_set_drv_status(cfg, READY, new_ndev);
1885 if (wl_config_ifmode(cfg, new_ndev, type) < 0) {
1886 WL_ERR(("conf ifmode failed\n"));
1887 kfree(vwdev);
1888 err = -ENOTSUPP;
1889 goto fail;
1890 }
1891
1892 if (wl_cfg80211_register_if(cfg,
1893 event->ifidx, new_ndev, FALSE) != BCME_OK) {
1894 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, FALSE);
1895 err = -ENODEV;
1896 goto fail;
1897 }
1898 err = wl_alloc_netinfo(cfg, new_ndev, vwdev, mode, pm_mode, event->bssidx);
1899 if (unlikely(err != 0)) {
1900 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, FALSE);
1901 WL_ERR(("Allocation of netinfo failed (%d) \n", err));
1902 goto fail;
1903 }
1904 val = 1;
1905 /* Disable firmware roaming for P2P interface */
1906 wldev_iovar_setint(new_ndev, "roam_off", val);
1907 wldev_iovar_setint(new_ndev, "bcn_timeout", dhd->conf->bcn_timeout);
1908 #ifdef WL11ULB
1909 if (cfg->p2p_wdev && is_p2p_group_iface(new_ndev->ieee80211_ptr)) {
1910 u32 ulb_bw = wl_cfg80211_get_ulb_bw(cfg, cfg->p2p_wdev);
1911 if (ulb_bw) {
1912 /* Apply ULB BW settings on the newly spawned interface */
1913 WL_DBG(("[ULB] Applying ULB BW for the newly"
1914 "created P2P interface \n"));
1915 if (wl_cfg80211_set_ulb_bw(new_ndev,
1916 ulb_bw, new_ndev->name) < 0) {
1917 /*
1918 * If ulb_bw set failed, fail the iface creation.
1919 * wl_dealloc_netinfo_by_wdev will be called by the
1920 * unregister notifier.
1921 */
1922 wl_cfg80211_remove_if(cfg,
1923 event->ifidx, new_ndev, FALSE);
1924 err = -EINVAL;
1925 goto fail;
1926 }
1927 }
1928 }
1929 #endif /* WL11ULB */
1930
1931 if (mode != WL_MODE_AP)
1932 wldev_iovar_setint(new_ndev, "buf_key_b4_m4", 1);
1933
1934 WL_ERR((" virtual interface(%s) is "
1935 "created net attach done\n", cfg->p2p->vir_ifname));
1936 if (mode == WL_MODE_AP)
1937 wl_set_drv_status(cfg, CONNECTED, new_ndev);
1938 #ifdef SUPPORT_AP_POWERSAVE
1939 if (mode == WL_MODE_AP) {
1940 dhd_set_ap_powersave(dhd, 0, TRUE);
1941 }
1942 #endif /* SUPPORT_AP_POWERSAVE */
1943 if (type == NL80211_IFTYPE_P2P_CLIENT)
1944 dhd_mode = DHD_FLAG_P2P_GC_MODE;
1945 else if (type == NL80211_IFTYPE_P2P_GO)
1946 dhd_mode = DHD_FLAG_P2P_GO_MODE;
1947 DNGL_FUNC(dhd_cfg80211_set_p2p_info, (cfg, dhd_mode));
1948 /* reinitialize completion to clear previous count */
1949 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
1950 INIT_COMPLETION(cfg->iface_disable);
1951 #else
1952 init_completion(&cfg->iface_disable);
1953 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */
1954 #ifdef SUPPORT_SET_CAC
1955 wl_cfg80211_set_cac(cfg, 0);
1956 #endif /* SUPPORT_SET_CAC */
1957 mutex_unlock(&cfg->if_sync);
1958 return ndev_to_cfgdev(new_ndev);
1959 } else {
1960 wl_clr_p2p_status(cfg, IF_ADDING);
1961 WL_ERR((" virtual interface(%s) is not created \n", cfg->p2p->vir_ifname));
1962
1963 WL_ERR(("left timeout : %d\n", timeout));
1964 WL_ERR(("IF_ADDING status : %d\n", wl_get_p2p_status(cfg, IF_ADDING)));
1965 WL_ERR(("event valid : %d\n", cfg->if_event_info.valid));
1966
1967 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
1968 wl_set_p2p_status(cfg, IF_DELETING);
1969
1970 hang_required = true;
1971 if ((err = wl_cfgp2p_ifdel(cfg,
1972 wl_to_p2p_bss_macaddr(cfg,
1973 cfg_type))) == BCME_OK) {
1974 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1975 ((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
1976 (cfg->if_event_info.valid)),
1977 msecs_to_jiffies(MAX_WAIT_TIME));
1978 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
1979 cfg->if_event_info.valid) {
1980 hang_required = false;
1981 WL_ERR(("IFDEL operation done\n"));
1982 } else {
1983 WL_ERR(("IFDEL didn't complete properly\n"));
1984 }
1985 err = -ENODEV;
1986 #ifdef SUPPORT_SET_CAC
1987 wl_cfg80211_set_cac(cfg, 1);
1988 #endif /* SUPPORT_SET_CAC */
1989 } else {
1990 WL_ERR(("IFDEL operation failed, error code = %d\n", err));
1991 }
1992
1993 memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
1994 wl_to_p2p_bss_bssidx(cfg, cfg_type) = -1;
1995 #ifdef PROP_TXSTATUS_VSDB
1996 #if defined(BCMSDIO) || defined(BCMDBUS)
1997 dhd_wlfc_get_enable(dhd, &enabled);
1998 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
1999 dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->conf->disable_proptx!=0) {
2000 dhd_wlfc_deinit(dhd);
2001 cfg->wlfc_on = false;
2002 }
2003 #endif /* BCMSDIO || BCMDBUS */
2004 #endif /* PROP_TXSTATUS_VSDB */
2005 }
2006 }
2007
2008 fail:
2009 mutex_unlock(&cfg->if_sync);
2010 if (err) {
2011 #ifdef WLTDLS
2012 /* Enable back TDLS on failure */
2013 wl_cfg80211_tdls_config(cfg, TDLS_STATE_IF_DELETE, false);
2014 #endif /* WLTDLS */
2015 if (err != -ENOTSUPP) {
2016 #if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2017 if (dhd->memdump_enabled) {
2018 /* Load the dongle side dump to host
2019 * memory and then BUG_ON()
2020 */
2021 dhd->memdump_type = DUMP_TYPE_HANG_ON_IFACE_OP_FAIL;
2022 dhd_bus_mem_dump(dhd);
2023 }
2024 #endif /* BCMPCIE && DHD_FW_COREDUMP */
2025 if (hang_required) {
2026 /* Notify the user space to recover */
2027 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
2028 WL_ERR(("if add failed, error %d, sent HANG event to %s\n",
2029 err, ndev->name));
2030 dhd->hang_reason = HANG_REASON_IFACE_OP_FAILURE;
2031 net_os_send_hang_message(ndev);
2032 }
2033 }
2034 }
2035 return ERR_PTR(err);
2036 }
2037
2038 static s32
2039 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
2040 {
2041 struct net_device *dev = NULL;
2042 struct ether_addr p2p_mac;
2043 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2044 s32 timeout = -1;
2045 s32 ret = 0;
2046 s32 index = -1;
2047 s32 type = -1;
2048 #if defined(CUSTOM_SET_CPUCORE) || defined(DHD_HANG_SEND_UP_TEST)
2049 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2050 #endif /* CUSTOM_SET_CPUCORE || DHD_HANG_SEND_UP_TEST */
2051 WL_DBG(("Enter\n"));
2052
2053 memset(&p2p_mac, 0, sizeof(struct ether_addr));
2054 #ifdef CUSTOM_SET_CPUCORE
2055 dhd->chan_isvht80 &= ~DHD_FLAG_P2P_MODE;
2056 if (!(dhd->chan_isvht80))
2057 dhd_set_cpucore(dhd, FALSE);
2058 #endif /* CUSTOM_SET_CPUCORE */
2059 mutex_lock(&cfg->if_sync);
2060 #ifdef WL_CFG80211_P2P_DEV_IF
2061 if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
2062 if (dhd_download_fw_on_driverload) {
2063 ret = wl_cfgp2p_del_p2p_disc_if(cfgdev, cfg);
2064 } else {
2065 cfg->down_disc_if = TRUE;
2066 ret = 0;
2067 }
2068 mutex_unlock(&cfg->if_sync);
2069 return ret;
2070 }
2071 #endif /* WL_CFG80211_P2P_DEV_IF */
2072 dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
2073
2074 #ifdef WLAIBSS_MCHAN
2075 if (cfgdev == cfg->ibss_cfgdev) {
2076 ret = bcm_cfg80211_del_ibss_if(wiphy, cfgdev);
2077 goto done;
2078 }
2079 #endif /* WLAIBSS_MCHAN */
2080
2081 if ((index = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
2082 WL_ERR(("Find p2p index from wdev failed\n"));
2083 ret = -ENODEV;
2084 goto done;
2085 }
2086 if ((cfg->p2p_supported) && index && (wl_cfgp2p_find_type(cfg, index, &type) == BCME_OK)) {
2087 /* Handle P2P Interace del */
2088 memcpy(p2p_mac.octet, wl_to_p2p_bss_macaddr(cfg, type).octet, ETHER_ADDR_LEN);
2089
2090 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
2091 */
2092 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
2093 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
2094 if (wl_cfgp2p_vif_created(cfg)) {
2095 if (wl_get_drv_status(cfg, SCANNING, dev)) {
2096 wl_notify_escan_complete(cfg, dev, true, true);
2097 }
2098 /* Delete pm_enable_work */
2099 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
2100
2101 /* for GC */
2102 if (wl_get_drv_status(cfg, DISCONNECTING, dev) &&
2103 (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)) {
2104 WL_ERR(("Wait for Link Down event for GC !\n"));
2105 wait_for_completion_timeout
2106 (&cfg->iface_disable, msecs_to_jiffies(500));
2107 }
2108
2109 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
2110 wl_set_p2p_status(cfg, IF_DELETING);
2111 DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (cfg));
2112
2113 /* for GO */
2114 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
2115 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
2116 cfg->p2p->p2p_go_count--;
2117 /* disable interface before bsscfg free */
2118 ret = wl_cfgp2p_ifdisable(cfg, &p2p_mac);
2119 /* if fw doesn't support "ifdis",
2120 do not wait for link down of ap mode
2121 */
2122 if (ret == 0) {
2123 WL_ERR(("Wait for Link Down event for GO !!!\n"));
2124 wait_for_completion_timeout(&cfg->iface_disable,
2125 msecs_to_jiffies(500));
2126 } else if (ret != BCME_UNSUPPORTED) {
2127 msleep(300);
2128 }
2129 }
2130 wl_cfg80211_clear_per_bss_ies(cfg, index);
2131
2132 if (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)
2133 wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
2134 memcpy(p2p_mac.octet, wl_to_p2p_bss_macaddr(cfg, type).octet,
2135 ETHER_ADDR_LEN);
2136 CFGP2P_INFO(("primary idx %d : cfg p2p_ifdis "MACDBG"\n",
2137 dev->ifindex, MAC2STRDBG(p2p_mac.octet)));
2138
2139 /* delete interface after link down */
2140 ret = wl_cfgp2p_ifdel(cfg, &p2p_mac);
2141 #if defined(DHD_HANG_SEND_UP_TEST)
2142 if (ret != BCME_OK ||
2143 dhd->req_hang_type == HANG_REASON_IFACE_OP_FAILURE)
2144 #else /* DHD_HANG_SEND_UP_TEST */
2145 if (ret != BCME_OK)
2146 #endif /* DHD_HANG_SEND_UP_TEST */
2147 {
2148 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
2149 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2150
2151 WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
2152 ret, ndev->name));
2153 #if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2154 if (dhd->memdump_enabled) {
2155 /* Load the dongle side dump to host
2156 * memory and then BUG_ON()
2157 */
2158 dhd->memdump_type = DUMP_TYPE_HANG_ON_IFACE_OP_FAIL;
2159 dhd_bus_mem_dump(dhd);
2160 }
2161 #endif /* BCMPCIE && DHD_FW_COREDUMP */
2162 dhd->hang_reason = HANG_REASON_IFACE_OP_FAILURE;
2163 net_os_send_hang_message(ndev);
2164 } else {
2165 /* Wait for IF_DEL operation to be finished */
2166 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
2167 ((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
2168 (cfg->if_event_info.valid)),
2169 msecs_to_jiffies(MAX_WAIT_TIME));
2170 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
2171 cfg->if_event_info.valid) {
2172
2173 WL_DBG(("IFDEL operation done\n"));
2174 wl_cfg80211_handle_ifdel(cfg, &cfg->if_event_info, dev);
2175 } else {
2176 WL_ERR(("IFDEL didn't complete properly\n"));
2177 }
2178 #ifdef SUPPORT_SET_CAC
2179 wl_cfg80211_set_cac(cfg, 1);
2180 #endif /* SUPPORT_SET_CAC */
2181 }
2182
2183 ret = dhd_del_monitor(dev);
2184 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
2185 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL((dhd_pub_t *)(cfg->pub));
2186 }
2187 }
2188 } else if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) ||
2189 (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION)) {
2190 #ifdef WL_VIRTUAL_APSTA
2191 ret = wl_cfg80211_del_iface(wiphy, cfgdev);
2192 #else
2193 WL_ERR(("Virtual APSTA not supported!\n"));
2194 #endif /* WL_VIRTUAL_APSTA */
2195 }
2196
2197 done:
2198 mutex_unlock(&cfg->if_sync);
2199 #ifdef WLTDLS
2200 if (ret == BCME_OK) {
2201 /* If interface del is success, try enabling back TDLS */
2202 wl_cfg80211_tdls_config(cfg, TDLS_STATE_IF_DELETE, false);
2203 }
2204 #endif /* WLTDLS */
2205 return ret;
2206 }
2207
2208 static s32
2209 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
2210 enum nl80211_iftype type,
2211 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
2212 u32 *flags,
2213 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) */
2214 struct vif_params *params)
2215 {
2216 s32 ap = 0;
2217 s32 infra_ibss = 1;
2218 s32 wlif_type;
2219 s32 mode = 0;
2220 s32 err = BCME_OK;
2221 s32 index;
2222 s32 conn_idx = -1;
2223 chanspec_t chspec;
2224 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2225 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2226
2227 mutex_lock(&cfg->if_sync);
2228 WL_DBG(("Enter type %d\n", type));
2229 switch (type) {
2230 case NL80211_IFTYPE_MONITOR:
2231 case NL80211_IFTYPE_WDS:
2232 #ifndef WLMESH
2233 case NL80211_IFTYPE_MESH_POINT:
2234 #endif /* WLMESH */
2235 ap = 1;
2236 WL_ERR(("type (%d) : currently we do not support this type\n",
2237 type));
2238 break;
2239 #ifdef WLMESH
2240 case NL80211_IFTYPE_MESH_POINT:
2241 infra_ibss = WL_BSSTYPE_MESH;
2242 break;
2243 #endif /* WLMESH */
2244 case NL80211_IFTYPE_ADHOC:
2245 mode = WL_MODE_IBSS;
2246 infra_ibss = 0;
2247 break;
2248 case NL80211_IFTYPE_STATION:
2249 case NL80211_IFTYPE_P2P_CLIENT:
2250 if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
2251 s32 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2252 if (bssidx < 0) {
2253 /* validate bssidx */
2254 WL_ERR(("Wrong bssidx! \n"));
2255 err = -EINVAL;
2256 goto error;
2257 }
2258 WL_DBG(("del interface. bssidx:%d", bssidx));
2259 /* Downgrade role from AP to STA */
2260 if ((err = wl_cfg80211_add_del_bss(cfg, ndev,
2261 bssidx, NL80211_IFTYPE_STATION, 0, NULL)) < 0) {
2262 WL_ERR(("AP-STA Downgrade failed \n"));
2263 err = -EINVAL;
2264 goto error;
2265 }
2266 }
2267 mode = WL_MODE_BSS;
2268 break;
2269 case NL80211_IFTYPE_AP:
2270 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
2271 /* intentional fall through */
2272 case NL80211_IFTYPE_AP_VLAN:
2273 case NL80211_IFTYPE_P2P_GO:
2274 mode = WL_MODE_AP;
2275 ap = 1;
2276 break;
2277 default:
2278 err = -EINVAL;
2279 goto error;
2280 }
2281
2282 if (!dhd) {
2283 err = -EINVAL;
2284 goto error;
2285 }
2286 if (ap) {
2287 wl_set_mode_by_netdev(cfg, ndev, mode);
2288 if (is_p2p_group_iface(ndev->ieee80211_ptr) &&
2289 cfg->p2p && wl_cfgp2p_vif_created(cfg)) {
2290 WL_DBG(("p2p_vif_created p2p_on (%d)\n", p2p_on(cfg)));
2291 wl_notify_escan_complete(cfg, ndev, true, true);
2292
2293 /* Dual p2p doesn't support multiple P2PGO interfaces,
2294 * p2p_go_count is the counter for GO creation
2295 * requests.
2296 */
2297 if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
2298 wl_set_mode_by_netdev(cfg, ndev, WL_MODE_BSS);
2299 WL_ERR(("Fw doesnot support multiple GO "));
2300 err = BCME_ERROR;
2301 goto error;
2302 }
2303 /* In concurrency case, STA may be already associated in a particular
2304 * channel. so retrieve the current channel of primary interface and
2305 * then start the virtual interface on that.
2306 */
2307 chspec = wl_cfg80211_get_shared_freq(wiphy);
2308 index = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2309 if (index < 0) {
2310 WL_ERR(("Find p2p index from ndev(%p) failed\n", ndev));
2311 err = BCME_ERROR;
2312 goto error;
2313 }
2314 if (wl_cfgp2p_find_type(cfg, index, &conn_idx) != BCME_OK) {
2315 err = BCME_ERROR;
2316 goto error;
2317 }
2318
2319 wlif_type = WL_P2P_IF_GO;
2320 printf("%s: %s ap (%d), infra_ibss (%d), iftype (%d) conn_idx (%d)\n",
2321 __FUNCTION__, ndev->name, ap, infra_ibss, type, conn_idx);
2322 wl_set_p2p_status(cfg, IF_CHANGING);
2323 wl_clr_p2p_status(cfg, IF_CHANGED);
2324 wl_cfgp2p_ifchange(cfg, wl_to_p2p_bss_macaddr(cfg, conn_idx),
2325 htod32(wlif_type), chspec, conn_idx);
2326 wait_event_interruptible_timeout(cfg->netif_change_event,
2327 (wl_get_p2p_status(cfg, IF_CHANGED) == true),
2328 msecs_to_jiffies(MAX_WAIT_TIME));
2329 wl_set_mode_by_netdev(cfg, ndev, mode);
2330 dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
2331 dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
2332 wl_clr_p2p_status(cfg, IF_CHANGING);
2333 wl_clr_p2p_status(cfg, IF_CHANGED);
2334 if (mode == WL_MODE_AP)
2335 wl_set_drv_status(cfg, CONNECTED, ndev);
2336 #ifdef SUPPORT_AP_POWERSAVE
2337 dhd_set_ap_powersave(dhd, 0, TRUE);
2338 #endif /* SUPPORT_AP_POWERSAVE */
2339 } else if ((type == NL80211_IFTYPE_AP) &&
2340 !wl_get_drv_status(cfg, AP_CREATED, ndev)) {
2341 #if 0
2342 err = wl_cfg80211_set_ap_role(cfg, ndev);
2343 if (unlikely(err)) {
2344 WL_ERR(("set ap role failed!\n"));
2345 goto error;
2346 }
2347 #else
2348 wl_set_drv_status(cfg, AP_CREATING, ndev);
2349 #endif
2350 } else {
2351 WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
2352 err = -EINVAL;
2353 goto error;
2354 }
2355 } else {
2356 /* P2P GO interface deletion is handled on the basis of role type (AP).
2357 * So avoid changing role for p2p type.
2358 */
2359 if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2360 wl_set_mode_by_netdev(cfg, ndev, mode);
2361 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA\n"));
2362 #ifdef SUPPORT_AP_POWERSAVE
2363 dhd_set_ap_powersave(dhd, 0, FALSE);
2364 #endif /* SUPPORT_AP_POWERSAVE */
2365 }
2366
2367 if (!infra_ibss) {
2368 err = wldev_ioctl_set(ndev, WLC_SET_INFRA, &infra_ibss, sizeof(s32));
2369 if (err < 0) {
2370 WL_ERR(("SET INFRA/IBSS error %d\n", err));
2371 err = -EINVAL;
2372 goto error;
2373 }
2374 }
2375
2376 WL_DBG(("Setting iftype to %d \n", type));
2377 ndev->ieee80211_ptr->iftype = type;
2378 error:
2379 mutex_unlock(&cfg->if_sync);
2380 return err;
2381 }
2382
2383 s32
2384 wl_cfg80211_notify_ifadd(struct net_device *dev, int ifidx, char *name, uint8 *mac, uint8 bssidx)
2385 {
2386 bool ifadd_expected = FALSE;
2387 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2388
2389 /* P2P may send WLC_E_IF_ADD and/or WLC_E_IF_CHANGE during IF updating ("p2p_ifupd")
2390 * redirect the IF_ADD event to ifchange as it is not a real "new" interface
2391 */
2392 if (wl_get_p2p_status(cfg, IF_CHANGING))
2393 return wl_cfg80211_notify_ifchange(dev, ifidx, name, mac, bssidx);
2394
2395 /* Okay, we are expecting IF_ADD (as IF_ADDING is true) */
2396 if (wl_get_p2p_status(cfg, IF_ADDING)) {
2397 ifadd_expected = TRUE;
2398 wl_clr_p2p_status(cfg, IF_ADDING);
2399 } else if (cfg->bss_pending_op) {
2400 ifadd_expected = TRUE;
2401 cfg->bss_pending_op = FALSE;
2402 }
2403
2404 if (ifadd_expected) {
2405 wl_if_event_info *if_event_info = &cfg->if_event_info;
2406
2407 if_event_info->valid = TRUE;
2408 if_event_info->ifidx = ifidx;
2409 if_event_info->bssidx = bssidx;
2410 strncpy(if_event_info->name, name, IFNAMSIZ);
2411 if_event_info->name[IFNAMSIZ] = '\0';
2412 if (mac)
2413 memcpy(if_event_info->mac, mac, ETHER_ADDR_LEN);
2414 wake_up_interruptible(&cfg->netif_change_event);
2415 return BCME_OK;
2416 }
2417
2418 return BCME_ERROR;
2419 }
2420
2421 s32
2422 wl_cfg80211_notify_ifdel(struct net_device *dev, int ifidx, char *name, uint8 *mac, uint8 bssidx)
2423 {
2424 bool ifdel_expected = FALSE;
2425 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2426 wl_if_event_info *if_event_info = &cfg->if_event_info;
2427
2428 if (wl_get_p2p_status(cfg, IF_DELETING)) {
2429 ifdel_expected = TRUE;
2430 wl_clr_p2p_status(cfg, IF_DELETING);
2431 } else if (cfg->bss_pending_op) {
2432 ifdel_expected = TRUE;
2433 cfg->bss_pending_op = FALSE;
2434 }
2435
2436 if (ifdel_expected) {
2437 if_event_info->valid = TRUE;
2438 if_event_info->ifidx = ifidx;
2439 if_event_info->bssidx = bssidx;
2440 wake_up_interruptible(&cfg->netif_change_event);
2441 return BCME_OK;
2442 }
2443
2444 return BCME_ERROR;
2445 }
2446
2447 s32
2448 wl_cfg80211_notify_ifchange(struct net_device * dev, int ifidx, char *name, uint8 *mac,
2449 uint8 bssidx)
2450 {
2451 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2452
2453 if (wl_get_p2p_status(cfg, IF_CHANGING)) {
2454 wl_set_p2p_status(cfg, IF_CHANGED);
2455 wake_up_interruptible(&cfg->netif_change_event);
2456 return BCME_OK;
2457 }
2458
2459 return BCME_ERROR;
2460 }
2461
2462 static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
2463 struct net_device* ndev)
2464 {
2465 s32 type = -1;
2466 s32 bssidx = -1;
2467 #ifdef PROP_TXSTATUS_VSDB
2468 #if defined(BCMSDIO) || defined(BCMDBUS)
2469 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2470 bool enabled;
2471 #endif /* BCMSDIO || BCMDBUS */
2472 #endif /* PROP_TXSTATUS_VSDB */
2473
2474 bssidx = if_event_info->bssidx;
2475 if (bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) &&
2476 bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2)) {
2477 WL_ERR(("got IF_DEL for if %d, not owned by cfg driver\n", bssidx));
2478 return BCME_ERROR;
2479 }
2480
2481 if (p2p_is_on(cfg) && wl_cfgp2p_vif_created(cfg)) {
2482 if (cfg->scan_request && (cfg->escan_info.ndev == ndev)) {
2483 /* Abort any pending scan requests */
2484 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2485 WL_DBG(("ESCAN COMPLETED\n"));
2486 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, false);
2487 }
2488
2489 memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
2490 if (wl_cfgp2p_find_type(cfg, bssidx, &type) == BCME_OK) {
2491 /* Update P2P data */
2492 wl_clr_drv_status(cfg, CONNECTED, wl_to_p2p_bss_ndev(cfg, type));
2493 wl_to_p2p_bss_ndev(cfg, type) = NULL;
2494 wl_to_p2p_bss_bssidx(cfg, type) = -1;
2495 } else if (wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr) < 0) {
2496 WL_ERR(("bssidx not known for the given ndev as per net_info data \n"));
2497 return BCME_ERROR;
2498 }
2499
2500 #ifdef PROP_TXSTATUS_VSDB
2501 #if defined(BCMSDIO) || defined(BCMDBUS)
2502 dhd_wlfc_get_enable(dhd, &enabled);
2503 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
2504 dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->conf->disable_proptx!=0) {
2505 dhd_wlfc_deinit(dhd);
2506 cfg->wlfc_on = false;
2507 }
2508 #endif /* BCMSDIO || BCMDBUS */
2509 #endif /* PROP_TXSTATUS_VSDB */
2510 }
2511
2512 dhd_net_if_lock(ndev);
2513 wl_cfg80211_remove_if(cfg, if_event_info->ifidx, ndev, FALSE);
2514 dhd_net_if_unlock(ndev);
2515
2516 return BCME_OK;
2517 }
2518
2519 /* Find listen channel */
2520 static s32 wl_find_listen_channel(struct bcm_cfg80211 *cfg,
2521 const u8 *ie, u32 ie_len)
2522 {
2523 wifi_p2p_ie_t *p2p_ie;
2524 u8 *end, *pos;
2525 s32 listen_channel;
2526
2527 /* unfortunately const cast required here - function is
2528 * a callback so its signature must not be changed
2529 * and cascade of changing wl_cfgp2p_find_p2pie
2530 * causes need for const cast in other places
2531 */
2532 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2533 4 && __GNUC_MINOR__ >= 6))
2534 _Pragma("GCC diagnostic push")
2535 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
2536 #endif
2537 pos = (u8 *)ie;
2538 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2539 4 && __GNUC_MINOR__ >= 6))
2540 _Pragma("GCC diagnostic pop")
2541 #endif
2542 p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
2543
2544 if (p2p_ie == NULL)
2545 return 0;
2546
2547 pos = p2p_ie->subelts;
2548 end = p2p_ie->subelts + (p2p_ie->len - 4);
2549
2550 CFGP2P_DBG((" found p2p ie ! lenth %d \n",
2551 p2p_ie->len));
2552
2553 while (pos < end) {
2554 uint16 attr_len;
2555 if (pos + 2 >= end) {
2556 CFGP2P_DBG((" -- Invalid P2P attribute"));
2557 return 0;
2558 }
2559 attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
2560
2561 if (pos + 3 + attr_len > end) {
2562 CFGP2P_DBG(("P2P: Attribute underflow "
2563 "(len=%u left=%d)",
2564 attr_len, (int) (end - pos - 3)));
2565 return 0;
2566 }
2567
2568 /* if Listen Channel att id is 6 and the vailue is valid,
2569 * return the listen channel
2570 */
2571 if (pos[0] == 6) {
2572 /* listen channel subel length format
2573 * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
2574 */
2575 listen_channel = pos[1 + 2 + 3 + 1];
2576
2577 if (listen_channel == SOCIAL_CHAN_1 ||
2578 listen_channel == SOCIAL_CHAN_2 ||
2579 listen_channel == SOCIAL_CHAN_3) {
2580 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
2581 return listen_channel;
2582 }
2583 }
2584 pos += 3 + attr_len;
2585 }
2586 return 0;
2587 }
2588
2589 static void wl_scan_prep(struct bcm_cfg80211 *cfg, struct wl_scan_params *params,
2590 struct cfg80211_scan_request *request)
2591 {
2592 u32 n_ssids;
2593 u32 n_channels;
2594 u16 channel;
2595 chanspec_t chanspec;
2596 s32 i = 0, j = 0, offset;
2597 char *ptr;
2598 wlc_ssid_t ssid;
2599 struct wireless_dev *wdev;
2600
2601 memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
2602 params->bss_type = DOT11_BSSTYPE_ANY;
2603 params->scan_type = 0;
2604 params->nprobes = -1;
2605 params->active_time = -1;
2606 params->passive_time = -1;
2607 params->home_time = -1;
2608 params->channel_num = 0;
2609 memset(&params->ssid, 0, sizeof(wlc_ssid_t));
2610
2611 WL_SCAN(("Preparing Scan request\n"));
2612 WL_SCAN(("nprobes=%d\n", params->nprobes));
2613 WL_SCAN(("active_time=%d\n", params->active_time));
2614 WL_SCAN(("passive_time=%d\n", params->passive_time));
2615 WL_SCAN(("home_time=%d\n", params->home_time));
2616 WL_SCAN(("scan_type=%d\n", params->scan_type));
2617
2618 params->nprobes = htod32(params->nprobes);
2619 params->active_time = htod32(params->active_time);
2620 params->passive_time = htod32(params->passive_time);
2621 params->home_time = htod32(params->home_time);
2622
2623 /* if request is null just exit so it will be all channel broadcast scan */
2624 if (!request)
2625 return;
2626
2627 n_ssids = request->n_ssids;
2628 n_channels = request->n_channels;
2629
2630 /* Copy channel array if applicable */
2631 WL_SCAN(("### List of channelspecs to scan ###\n"));
2632 if (n_channels > 0) {
2633 for (i = 0; i < n_channels; i++) {
2634 channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
2635 /* SKIP DFS channels for Secondary interface */
2636 if ((cfg->escan_info.ndev != bcmcfg_to_prmry_ndev(cfg)) &&
2637 (request->channels[i]->flags &
2638 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
2639 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
2640 #else
2641 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR)))
2642 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
2643 continue;
2644 if (!dhd_conf_match_channel(cfg->pub, channel))
2645 continue;
2646
2647 #if defined(WL_CFG80211_P2P_DEV_IF)
2648 wdev = request->wdev;
2649 #else
2650 wdev = request->dev->ieee80211_ptr;
2651 #endif /* WL_CFG80211_P2P_DEV_IF */
2652 chanspec = wl_cfg80211_ulb_get_min_bw_chspec(cfg, wdev, -1);
2653 if (chanspec == INVCHANSPEC) {
2654 WL_ERR(("Invalid chanspec! Skipping channel\n"));
2655 continue;
2656 }
2657
2658 if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
2659 chanspec |= WL_CHANSPEC_BAND_2G;
2660 } else {
2661 chanspec |= WL_CHANSPEC_BAND_5G;
2662 }
2663 params->channel_list[j] = channel;
2664 params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
2665 params->channel_list[j] |= chanspec;
2666 WL_SCAN(("Chan : %d, Channel spec: %x \n",
2667 channel, params->channel_list[j]));
2668 params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
2669 j++;
2670 }
2671 } else {
2672 WL_SCAN(("Scanning all channels\n"));
2673 }
2674 n_channels = j;
2675 /* Copy ssid array if applicable */
2676 WL_SCAN(("### List of SSIDs to scan ###\n"));
2677 if (n_ssids > 0) {
2678 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
2679 offset = roundup(offset, sizeof(u32));
2680 ptr = (char*)params + offset;
2681 for (i = 0; i < n_ssids; i++) {
2682 memset(&ssid, 0, sizeof(wlc_ssid_t));
2683 ssid.SSID_len = MIN(request->ssids[i].ssid_len, DOT11_MAX_SSID_LEN);
2684 memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
2685 if (!ssid.SSID_len)
2686 WL_SCAN(("%d: Broadcast scan\n", i));
2687 else
2688 WL_SCAN(("%d: scan for %s size =%d\n", i,
2689 ssid.SSID, ssid.SSID_len));
2690 memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
2691 ptr += sizeof(wlc_ssid_t);
2692 }
2693 } else {
2694 WL_SCAN(("Broadcast scan\n"));
2695 }
2696 /* Adding mask to channel numbers */
2697 params->channel_num =
2698 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
2699 (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
2700
2701 if (n_channels == 1) {
2702 params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
2703 params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
2704 }
2705 }
2706
2707 static s32
2708 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
2709 {
2710 wl_uint32_list_t *list;
2711 s32 err = BCME_OK;
2712 if (valid_chan_list == NULL || size <= 0)
2713 return -ENOMEM;
2714
2715 memset(valid_chan_list, 0, size);
2716 list = (wl_uint32_list_t *)(void *) valid_chan_list;
2717 list->count = htod32(WL_NUMCHANNELS);
2718 err = wldev_ioctl_get(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size);
2719 if (err != 0) {
2720 WL_ERR(("get channels failed with %d\n", err));
2721 }
2722
2723 return err;
2724 }
2725
2726 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2727 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
2728 bool g_first_broadcast_scan = TRUE;
2729 #endif
2730
2731 static s32
2732 wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev,
2733 struct cfg80211_scan_request *request, uint16 action)
2734 {
2735 s32 err = BCME_OK;
2736 u32 n_channels;
2737 u32 n_ssids;
2738 s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
2739 wl_escan_params_t *params = NULL;
2740 u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
2741 u32 num_chans = 0;
2742 s32 channel;
2743 u32 n_valid_chan;
2744 s32 search_state = WL_P2P_DISC_ST_SCAN;
2745 u32 i, j, n_nodfs = 0;
2746 u16 *default_chan_list = NULL;
2747 wl_uint32_list_t *list;
2748 s32 bssidx = -1;
2749 struct net_device *dev = NULL;
2750 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2751 bool is_first_init_2g_scan = false;
2752 #endif
2753 p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
2754 scb_val_t scbval;
2755 static int cnt = 0;
2756
2757 WL_DBG(("Enter \n"));
2758
2759 /* scan request can come with empty request : perform all default scan */
2760 if (!cfg) {
2761 err = -EINVAL;
2762 goto exit;
2763 }
2764 if (!cfg->p2p_supported || !p2p_scan(cfg)) {
2765 /* LEGACY SCAN TRIGGER */
2766 WL_SCAN((" LEGACY E-SCAN START\n"));
2767
2768 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2769 if (!request) {
2770 err = -EINVAL;
2771 goto exit;
2772 }
2773 if (ndev == bcmcfg_to_prmry_ndev(cfg) && g_first_broadcast_scan == true) {
2774 is_first_init_2g_scan = true;
2775 g_first_broadcast_scan = false;
2776 }
2777 #endif
2778
2779 /* if scan request is not empty parse scan request paramters */
2780 if (request != NULL) {
2781 n_channels = request->n_channels;
2782 n_ssids = request->n_ssids;
2783 if (n_channels % 2)
2784 /* If n_channels is odd, add a padd of u16 */
2785 params_size += sizeof(u16) * (n_channels + 1);
2786 else
2787 params_size += sizeof(u16) * n_channels;
2788
2789 /* Allocate space for populating ssids in wl_escan_params_t struct */
2790 params_size += sizeof(struct wlc_ssid) * n_ssids;
2791 }
2792 params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
2793 if (params == NULL) {
2794 err = -ENOMEM;
2795 goto exit;
2796 }
2797 wl_scan_prep(cfg, &params->params, request);
2798
2799 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2800 /* Override active_time to reduce scan time if it's first bradcast scan. */
2801 if (is_first_init_2g_scan)
2802 params->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
2803 #endif
2804
2805 params->version = htod32(ESCAN_REQ_VERSION);
2806 params->action = htod16(action);
2807 wl_escan_set_sync_id(params->sync_id, cfg);
2808 wl_escan_set_type(cfg, WL_SCANTYPE_LEGACY);
2809 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
2810 WL_ERR(("ioctl buffer length not sufficient\n"));
2811 kfree(params);
2812 err = -ENOMEM;
2813 goto exit;
2814 }
2815 if (cfg->active_scan == PASSIVE_SCAN) {
2816 params->params.scan_type = DOT11_SCANTYPE_PASSIVE;
2817 WL_DBG(("Passive scan_type %d \n", params->params.scan_type));
2818 }
2819
2820 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2821
2822 err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
2823 cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2824 printf("%s: LEGACY_SCAN sync ID: %d, bssidx: %d\n", __FUNCTION__, params->sync_id, bssidx);
2825 if (unlikely(err)) {
2826 if (err == BCME_EPERM)
2827 /* Scan Not permitted at this point of time */
2828 WL_DBG((" Escan not permitted at this time (%d)\n", err));
2829 else
2830 WL_ERR((" Escan set error (%d)\n", err));
2831 } else {
2832 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_REQUESTED);
2833 }
2834 kfree(params);
2835 }
2836 else if (p2p_is_on(cfg) && p2p_scan(cfg)) {
2837 /* P2P SCAN TRIGGER */
2838 s32 _freq = 0;
2839 n_nodfs = 0;
2840 if (request && request->n_channels) {
2841 num_chans = request->n_channels;
2842 WL_SCAN((" chann number : %d\n", num_chans));
2843 default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
2844 GFP_KERNEL);
2845 if (default_chan_list == NULL) {
2846 WL_ERR(("channel list allocation failed \n"));
2847 err = -ENOMEM;
2848 goto exit;
2849 }
2850 if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
2851 #ifdef P2P_SKIP_DFS
2852 int is_printed = false;
2853 #endif /* P2P_SKIP_DFS */
2854 list = (wl_uint32_list_t *) chan_buf;
2855 n_valid_chan = dtoh32(list->count);
2856 if (n_valid_chan > WL_NUMCHANNELS) {
2857 WL_ERR(("wrong n_valid_chan:%d\n", n_valid_chan));
2858 kfree(default_chan_list);
2859 err = -EINVAL;
2860 goto exit;
2861 }
2862
2863 for (i = 0; i < num_chans; i++)
2864 {
2865 _freq = request->channels[i]->center_freq;
2866 channel = ieee80211_frequency_to_channel(_freq);
2867
2868 /* ignore DFS channels */
2869 if (request->channels[i]->flags &
2870 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2871 (IEEE80211_CHAN_NO_IR
2872 | IEEE80211_CHAN_RADAR))
2873 #else
2874 (IEEE80211_CHAN_RADAR
2875 | IEEE80211_CHAN_PASSIVE_SCAN))
2876 #endif
2877 continue;
2878 #ifdef P2P_SKIP_DFS
2879 if (channel >= 52 && channel <= 144) {
2880 if (is_printed == false) {
2881 WL_ERR(("SKIP DFS CHANs(52~144)\n"));
2882 is_printed = true;
2883 }
2884 continue;
2885 }
2886 #endif /* P2P_SKIP_DFS */
2887
2888 for (j = 0; j < n_valid_chan; j++) {
2889 /* allows only supported channel on
2890 * current reguatory
2891 */
2892 if (n_nodfs >= num_chans) {
2893 break;
2894 }
2895 if (channel == (dtoh32(list->element[j]))) {
2896 default_chan_list[n_nodfs++] =
2897 channel;
2898 }
2899 }
2900
2901 }
2902 }
2903 if (num_chans == SOCIAL_CHAN_CNT && (
2904 (default_chan_list[0] == SOCIAL_CHAN_1) &&
2905 (default_chan_list[1] == SOCIAL_CHAN_2) &&
2906 (default_chan_list[2] == SOCIAL_CHAN_3))) {
2907 /* SOCIAL CHANNELS 1, 6, 11 */
2908 search_state = WL_P2P_DISC_ST_SEARCH;
2909 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2910 WL_INFORM(("P2P SEARCH PHASE START \n"));
2911 } else if (((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1)) &&
2912 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) ||
2913 ((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2)) &&
2914 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP))) {
2915 /* If you are already a GO, then do SEARCH only */
2916 WL_INFORM(("Already a GO. Do SEARCH Only"));
2917 search_state = WL_P2P_DISC_ST_SEARCH;
2918 num_chans = n_nodfs;
2919 p2p_scan_purpose = P2P_SCAN_NORMAL;
2920
2921 } else if (num_chans == 1) {
2922 p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
2923 } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
2924 /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2925 * the supplicant
2926 */
2927 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2928 } else {
2929 WL_INFORM(("P2P SCAN STATE START \n"));
2930 num_chans = n_nodfs;
2931 p2p_scan_purpose = P2P_SCAN_NORMAL;
2932 }
2933 } else {
2934 err = -EINVAL;
2935 goto exit;
2936 }
2937 err = wl_cfgp2p_escan(cfg, ndev, ACTIVE_SCAN, num_chans, default_chan_list,
2938 search_state, action,
2939 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE), NULL,
2940 p2p_scan_purpose);
2941
2942 if (!err)
2943 cfg->p2p->search_state = search_state;
2944
2945 kfree(default_chan_list);
2946 }
2947 exit:
2948 if (unlikely(err)) {
2949 /* Don't print Error incase of Scan suppress */
2950 if ((err == BCME_EPERM) && cfg->scan_suppressed)
2951 WL_DBG(("Escan failed: Scan Suppressed \n"));
2952 else {
2953 cnt++;
2954 WL_ERR(("error (%d), cnt=%d\n", err, cnt));
2955 // terence 20140111: send disassoc to firmware
2956 if (cnt >= 4) {
2957 dev = bcmcfg_to_prmry_ndev(cfg);
2958 memset(&scbval, 0, sizeof(scb_val_t));
2959 wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true);
2960 WL_ERR(("Send disassoc to break the busy dev=%p\n", dev));
2961 cnt = 0;
2962 }
2963 }
2964 } else {
2965 cnt = 0;
2966 }
2967 return err;
2968 }
2969
2970
2971 static s32
2972 wl_do_escan(struct bcm_cfg80211 *cfg, struct wiphy *wiphy, struct net_device *ndev,
2973 struct cfg80211_scan_request *request)
2974 {
2975 s32 err = BCME_OK;
2976 s32 passive_scan = 0;
2977 s32 passive_scan_time = 0;
2978 s32 passive_scan_time_org = 0;
2979 wl_scan_results_t *results;
2980 WL_SCAN(("Enter \n"));
2981
2982 results = wl_escan_get_buf(cfg, FALSE);
2983 results->version = 0;
2984 results->count = 0;
2985 results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
2986
2987 cfg->escan_info.ndev = ndev;
2988 cfg->escan_info.wiphy = wiphy;
2989 cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
2990 passive_scan = cfg->active_scan ? 0 : 1;
2991 err = wldev_ioctl_set(ndev, WLC_SET_PASSIVE_SCAN,
2992 &passive_scan, sizeof(passive_scan));
2993 if (unlikely(err)) {
2994 WL_ERR(("error (%d)\n", err));
2995 goto exit;
2996 }
2997
2998 if (passive_channel_skip) {
2999
3000 err = wldev_ioctl_get(ndev, WLC_GET_SCAN_PASSIVE_TIME,
3001 &passive_scan_time_org, sizeof(passive_scan_time_org));
3002 if (unlikely(err)) {
3003 WL_ERR(("== error (%d)\n", err));
3004 goto exit;
3005 }
3006
3007 WL_SCAN(("PASSIVE SCAN time : %d \n", passive_scan_time_org));
3008
3009 passive_scan_time = 0;
3010 err = wldev_ioctl_set(ndev, WLC_SET_SCAN_PASSIVE_TIME,
3011 &passive_scan_time, sizeof(passive_scan_time));
3012 if (unlikely(err)) {
3013 WL_ERR(("== error (%d)\n", err));
3014 goto exit;
3015 }
3016
3017 WL_SCAN(("PASSIVE SCAN SKIPED!! (passive_channel_skip:%d) \n",
3018 passive_channel_skip));
3019 }
3020
3021 err = wl_run_escan(cfg, ndev, request, WL_SCAN_ACTION_START);
3022
3023 if (passive_channel_skip) {
3024 err = wldev_ioctl_set(ndev, WLC_SET_SCAN_PASSIVE_TIME,
3025 &passive_scan_time_org, sizeof(passive_scan_time_org));
3026 if (unlikely(err)) {
3027 WL_ERR(("== error (%d)\n", err));
3028 goto exit;
3029 }
3030
3031 WL_SCAN(("PASSIVE SCAN RECOVERED!! (passive_scan_time_org:%d) \n",
3032 passive_scan_time_org));
3033 }
3034
3035 exit:
3036 return err;
3037 }
3038
3039 static s32
3040 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
3041 struct cfg80211_scan_request *request,
3042 struct cfg80211_ssid *this_ssid)
3043 {
3044 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3045 struct cfg80211_ssid *ssids;
3046 struct ether_addr primary_mac;
3047 bool p2p_ssid;
3048 #ifdef WL11U
3049 bcm_tlv_t *interworking_ie;
3050 #endif
3051 s32 err = 0;
3052 s32 bssidx = -1;
3053 s32 i;
3054
3055 unsigned long flags;
3056 static s32 busy_count = 0;
3057 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
3058 struct net_device *remain_on_channel_ndev = NULL;
3059 #endif
3060 uint scan_timer_interval_ms = WL_SCAN_TIMER_INTERVAL_MS;
3061
3062 /*
3063 * Hostapd triggers scan before starting automatic channel selection
3064 * to collect channel characteristics. However firmware scan engine
3065 * doesn't support any channel characteristics collection along with
3066 * scan. Hence return scan success.
3067 */
3068 if (request && (scan_req_iftype(request) == NL80211_IFTYPE_AP)) {
3069 WL_INFORM(("Scan Command on SoftAP Interface. Ignoring...\n"));
3070 // terence 20161023: let it scan in SoftAP mode
3071 // return 0;
3072 }
3073
3074 ndev = ndev_to_wlc_ndev(ndev, cfg);
3075
3076 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
3077 WL_ERR(("Sending Action Frames. Try it again.\n"));
3078 return -EAGAIN;
3079 }
3080
3081 WL_DBG(("Enter wiphy (%p)\n", wiphy));
3082 if (wl_get_drv_status_all(cfg, SCANNING)) {
3083 if (cfg->scan_request == NULL) {
3084 wl_clr_drv_status_all(cfg, SCANNING);
3085 WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
3086 } else {
3087 WL_ERR(("Scanning already\n"));
3088 return -EAGAIN;
3089 }
3090 }
3091 if (wl_get_drv_status(cfg, SCAN_ABORTING, ndev)) {
3092 WL_ERR(("Scanning being aborted\n"));
3093 return -EAGAIN;
3094 }
3095 if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
3096 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
3097 return -EOPNOTSUPP;
3098 }
3099
3100 #ifdef P2P_LISTEN_OFFLOADING
3101 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
3102 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
3103 return -EAGAIN;
3104 }
3105 #endif /* P2P_LISTEN_OFFLOADING */
3106
3107 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
3108 remain_on_channel_ndev = wl_cfg80211_get_remain_on_channel_ndev(cfg);
3109 if (remain_on_channel_ndev) {
3110 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
3111 wl_notify_escan_complete(cfg, remain_on_channel_ndev, true, true);
3112 }
3113 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
3114
3115
3116 /* Arm scan timeout timer */
3117 mod_timer(&cfg->scan_timeout, jiffies + msecs_to_jiffies(scan_timer_interval_ms));
3118 if (request) { /* scan bss */
3119 ssids = request->ssids;
3120 p2p_ssid = false;
3121 for (i = 0; i < request->n_ssids; i++) {
3122 if (ssids[i].ssid_len &&
3123 IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
3124 p2p_ssid = true;
3125 break;
3126 }
3127 }
3128 if (p2p_ssid) {
3129 if (cfg->p2p_supported) {
3130 /* p2p scan trigger */
3131 if (p2p_on(cfg) == false) {
3132 /* p2p on at the first time */
3133 p2p_on(cfg) = true;
3134 wl_cfgp2p_set_firm_p2p(cfg);
3135 get_primary_mac(cfg, &primary_mac);
3136 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
3137 #if defined(P2P_IE_MISSING_FIX)
3138 cfg->p2p_prb_noti = false;
3139 #endif
3140 }
3141 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
3142 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
3143 p2p_scan(cfg) = true;
3144 }
3145 } else {
3146 /* legacy scan trigger
3147 * So, we have to disable p2p discovery if p2p discovery is on
3148 */
3149 if (cfg->p2p_supported) {
3150 p2p_scan(cfg) = false;
3151 /* If Netdevice is not equals to primary and p2p is on
3152 * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
3153 */
3154
3155 if (p2p_scan(cfg) == false) {
3156 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
3157 err = wl_cfgp2p_discover_enable_search(cfg,
3158 false);
3159 if (unlikely(err)) {
3160 goto scan_out;
3161 }
3162
3163 }
3164 }
3165 }
3166 if (!cfg->p2p_supported || !p2p_scan(cfg)) {
3167 if ((bssidx = wl_get_bssidx_by_wdev(cfg,
3168 ndev->ieee80211_ptr)) < 0) {
3169 WL_ERR(("Find p2p index from ndev(%p) failed\n",
3170 ndev));
3171 err = BCME_ERROR;
3172 goto scan_out;
3173 }
3174 #ifdef WL11U
3175 if (request && (interworking_ie =
3176 wl_cfg80211_find_interworking_ie(
3177 request->ie, request->ie_len)) != NULL) {
3178 if ((err = wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
3179 VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
3180 interworking_ie->data,
3181 interworking_ie->len)) != BCME_OK) {
3182 WL_ERR(("Failed to add interworking IE"));
3183 }
3184 } else if (cfg->wl11u) {
3185 /* we have to clear IW IE and disable gratuitous APR */
3186 wl_cfg80211_clear_iw_ie(cfg, ndev, bssidx);
3187 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp",
3188 0, bssidx);
3189 /* we don't care about error here
3190 * because the only failure case is unsupported,
3191 * which is fine
3192 */
3193 if (unlikely(err)) {
3194 WL_ERR(("Set grat_arp failed:(%d) Ignore!\n", err));
3195 }
3196 cfg->wl11u = FALSE;
3197 }
3198 #endif /* WL11U */
3199 if (request) {
3200 err = wl_cfg80211_set_mgmt_vndr_ies(cfg,
3201 ndev_to_cfgdev(ndev),
3202 bssidx, VNDR_IE_PRBREQ_FLAG, request->ie,
3203 request->ie_len);
3204 }
3205
3206 if (unlikely(err)) {
3207 // terence 20161023: let it scan in SoftAP mode
3208 // goto scan_out;
3209 }
3210
3211 }
3212 }
3213 } else { /* scan in ibss */
3214 ssids = this_ssid;
3215 }
3216
3217 if (request && cfg->p2p_supported) {
3218 WL_TRACE_HW4(("START SCAN\n"));
3219 DHD_OS_SCAN_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub),
3220 SCAN_WAKE_LOCK_TIMEOUT);
3221 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
3222 }
3223
3224 if (cfg->p2p_supported) {
3225 if (request && p2p_on(cfg) && p2p_scan(cfg)) {
3226
3227 /* find my listen channel */
3228 cfg->afx_hdl->my_listen_chan =
3229 wl_find_listen_channel(cfg, request->ie,
3230 request->ie_len);
3231 err = wl_cfgp2p_enable_discovery(cfg, ndev,
3232 request->ie, request->ie_len);
3233
3234 if (unlikely(err)) {
3235 goto scan_out;
3236 }
3237 }
3238 }
3239 err = wl_do_escan(cfg, wiphy, ndev, request);
3240 if (likely(!err))
3241 goto scan_success;
3242 else
3243 goto scan_out;
3244
3245 scan_success:
3246 busy_count = 0;
3247 cfg->scan_request = request;
3248 wl_set_drv_status(cfg, SCANNING, ndev);
3249
3250 return 0;
3251
3252 scan_out:
3253 if (err == BCME_BUSY || err == BCME_NOTREADY) {
3254 WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
3255 err = -EBUSY;
3256 } else if ((err == BCME_EPERM) && cfg->scan_suppressed) {
3257 WL_ERR(("Scan not permitted due to scan suppress\n"));
3258 err = -EPERM;
3259 } else {
3260 /* For all other fw errors, use a generic error code as return
3261 * value to cfg80211 stack
3262 */
3263 err = -EAGAIN;
3264 }
3265
3266 #define SCAN_EBUSY_RETRY_LIMIT 20
3267 if (err == -EBUSY) {
3268 if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
3269 struct ether_addr bssid;
3270 s32 ret = 0;
3271 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
3272 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
3273 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
3274 busy_count = 0;
3275 WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
3276 wl_get_drv_status(cfg, SCANNING, ndev),
3277 wl_get_drv_status(cfg, SCAN_ABORTING, ndev),
3278 wl_get_drv_status(cfg, CONNECTING, ndev),
3279 wl_get_drv_status(cfg, CONNECTED, ndev),
3280 wl_get_drv_status(cfg, DISCONNECTING, ndev),
3281 wl_get_drv_status(cfg, AP_CREATING, ndev),
3282 wl_get_drv_status(cfg, AP_CREATED, ndev),
3283 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev),
3284 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev)));
3285
3286 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
3287 if (dhdp->memdump_enabled) {
3288 dhdp->memdump_type = DUMP_TYPE_SCAN_BUSY;
3289 dhd_bus_mem_dump(dhdp);
3290 }
3291 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
3292
3293 bzero(&bssid, sizeof(bssid));
3294 if ((ret = wldev_ioctl_get(ndev, WLC_GET_BSSID,
3295 &bssid, ETHER_ADDR_LEN)) == 0)
3296 WL_ERR(("FW is connected with " MACDBG "/n",
3297 MAC2STRDBG(bssid.octet)));
3298 else
3299 WL_ERR(("GET BSSID failed with %d\n", ret));
3300
3301 wl_cfg80211_scan_abort(cfg);
3302
3303 } else {
3304 /* Hold the context for 400msec, so that 10 subsequent scans
3305 * can give a buffer of 4sec which is enough to
3306 * cover any on-going scan in the firmware
3307 */
3308 WL_DBG(("Enforcing delay for EBUSY case \n"));
3309 msleep(400);
3310 }
3311 } else {
3312 busy_count = 0;
3313 }
3314
3315 wl_clr_drv_status(cfg, SCANNING, ndev);
3316 if (timer_pending(&cfg->scan_timeout))
3317 del_timer_sync(&cfg->scan_timeout);
3318 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
3319 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
3320 cfg->scan_request = NULL;
3321 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
3322
3323 return err;
3324 }
3325
3326 static s32
3327 #if defined(WL_CFG80211_P2P_DEV_IF)
3328 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
3329 #else
3330 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
3331 struct cfg80211_scan_request *request)
3332 #endif /* WL_CFG80211_P2P_DEV_IF */
3333 {
3334 s32 err = 0;
3335 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3336 #if defined(WL_CFG80211_P2P_DEV_IF)
3337 struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, cfg);
3338 #endif /* WL_CFG80211_P2P_DEV_IF */
3339
3340 WL_DBG(("Enter\n"));
3341 RETURN_EIO_IF_NOT_UP(cfg);
3342
3343 #ifdef DHD_IFDEBUG
3344 #ifdef WL_CFG80211_P2P_DEV_IF
3345 PRINT_WDEV_INFO(request->wdev);
3346 #else
3347 PRINT_WDEV_INFO(ndev);
3348 #endif /* WL_CFG80211_P2P_DEV_IF */
3349 #endif /* DHD_IFDEBUG */
3350
3351 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
3352 if (wl_cfg_multip2p_operational(cfg)) {
3353 WL_ERR(("wlan0 scan failed, p2p devices are operational"));
3354 return -ENODEV;
3355 }
3356 }
3357
3358 mutex_lock(&cfg->usr_sync);
3359 err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
3360 if (unlikely(err)) {
3361 WL_ERR(("scan error (%d)\n", err));
3362 }
3363 mutex_unlock(&cfg->usr_sync);
3364 #ifdef WL_DRV_AVOID_SCANCACHE
3365 /* Reset roam cache after successful scan request */
3366 #endif /* WL_DRV_AVOID_SCANCACHE */
3367 return err;
3368 }
3369
3370 static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
3371 {
3372 s32 err = 0;
3373
3374 err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
3375 if (unlikely(err)) {
3376 WL_ERR(("Error (%d)\n", err));
3377 return err;
3378 }
3379 return err;
3380 }
3381
3382 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
3383 {
3384 s32 err = 0;
3385
3386 err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
3387 if (unlikely(err)) {
3388 WL_ERR(("Error (%d)\n", err));
3389 return err;
3390 }
3391 return err;
3392 }
3393
3394 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
3395 {
3396 s32 err = 0;
3397 u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
3398
3399 retry = htod32(retry);
3400 err = wldev_ioctl_set(dev, cmd, &retry, sizeof(retry));
3401 if (unlikely(err)) {
3402 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
3403 return err;
3404 }
3405 return err;
3406 }
3407
3408 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
3409 {
3410 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
3411 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
3412 s32 err = 0;
3413
3414 RETURN_EIO_IF_NOT_UP(cfg);
3415 WL_DBG(("Enter\n"));
3416 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
3417 (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
3418 cfg->conf->rts_threshold = wiphy->rts_threshold;
3419 err = wl_set_rts(ndev, cfg->conf->rts_threshold);
3420 if (err != BCME_OK)
3421 return err;
3422 }
3423 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
3424 (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
3425 cfg->conf->frag_threshold = wiphy->frag_threshold;
3426 err = wl_set_frag(ndev, cfg->conf->frag_threshold);
3427 if (err != BCME_OK)
3428 return err;
3429 }
3430 if (changed & WIPHY_PARAM_RETRY_LONG &&
3431 (cfg->conf->retry_long != wiphy->retry_long)) {
3432 cfg->conf->retry_long = wiphy->retry_long;
3433 err = wl_set_retry(ndev, cfg->conf->retry_long, true);
3434 if (err != BCME_OK)
3435 return err;
3436 }
3437 if (changed & WIPHY_PARAM_RETRY_SHORT &&
3438 (cfg->conf->retry_short != wiphy->retry_short)) {
3439 cfg->conf->retry_short = wiphy->retry_short;
3440 err = wl_set_retry(ndev, cfg->conf->retry_short, false);
3441 if (err != BCME_OK) {
3442 return err;
3443 }
3444 }
3445
3446 return err;
3447 }
3448 static chanspec_t
3449 channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
3450 {
3451 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3452 u8 *buf = NULL;
3453 wl_uint32_list_t *list;
3454 int err = BCME_OK;
3455 chanspec_t c = 0, ret_c = 0;
3456 int bw = 0, tmp_bw = 0;
3457 int i;
3458 u32 tmp_c;
3459 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
3460 #define LOCAL_BUF_SIZE 1024
3461 buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
3462 if (!buf) {
3463 WL_ERR(("buf memory alloc failed\n"));
3464 goto exit;
3465 }
3466
3467 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
3468 0, buf, LOCAL_BUF_SIZE, 0, &cfg->ioctl_buf_sync);
3469 if (err != BCME_OK) {
3470 WL_ERR(("get chanspecs failed with %d\n", err));
3471 goto exit;
3472 }
3473
3474 list = (wl_uint32_list_t *)(void *)buf;
3475 for (i = 0; i < dtoh32(list->count); i++) {
3476 c = dtoh32(list->element[i]);
3477 if (channel <= CH_MAX_2G_CHANNEL) {
3478 if (!CHSPEC_IS20(c))
3479 continue;
3480 if (channel == CHSPEC_CHANNEL(c)) {
3481 ret_c = c;
3482 bw = 20;
3483 goto exit;
3484 }
3485 }
3486 tmp_c = wf_chspec_ctlchan(c);
3487 tmp_bw = bw2cap[CHSPEC_BW(c) >> WL_CHANSPEC_BW_SHIFT];
3488 if (tmp_c != channel)
3489 continue;
3490
3491 if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
3492 bw = tmp_bw;
3493 ret_c = c;
3494 if (bw == bw_cap)
3495 goto exit;
3496 }
3497 }
3498 exit:
3499 if (buf)
3500 kfree(buf);
3501 #undef LOCAL_BUF_SIZE
3502 WL_INFORM(("return chanspec %x %d\n", ret_c, bw));
3503 return ret_c;
3504 }
3505
3506 void
3507 wl_cfg80211_ibss_vsie_set_buffer(struct net_device *dev, vndr_ie_setbuf_t *ibss_vsie,
3508 int ibss_vsie_len)
3509 {
3510 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3511
3512 if (cfg != NULL && ibss_vsie != NULL) {
3513 if (cfg->ibss_vsie != NULL) {
3514 kfree(cfg->ibss_vsie);
3515 }
3516 cfg->ibss_vsie = ibss_vsie;
3517 cfg->ibss_vsie_len = ibss_vsie_len;
3518 }
3519 }
3520
3521 static void
3522 wl_cfg80211_ibss_vsie_free(struct bcm_cfg80211 *cfg)
3523 {
3524 /* free & initiralize VSIE (Vendor Specific IE) */
3525 if (cfg->ibss_vsie != NULL) {
3526 kfree(cfg->ibss_vsie);
3527 cfg->ibss_vsie = NULL;
3528 cfg->ibss_vsie_len = 0;
3529 }
3530 }
3531
3532 s32
3533 wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
3534 {
3535 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3536 char *ioctl_buf = NULL;
3537 s32 ret = BCME_OK, bssidx;
3538
3539 if (cfg != NULL && cfg->ibss_vsie != NULL) {
3540 ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
3541 if (!ioctl_buf) {
3542 WL_ERR(("ioctl memory alloc failed\n"));
3543 return -ENOMEM;
3544 }
3545
3546 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
3547 WL_ERR(("Find index failed\n"));
3548 ret = BCME_ERROR;
3549 goto end;
3550 }
3551 /* change the command from "add" to "del" */
3552 strncpy(cfg->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
3553 cfg->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
3554
3555 ret = wldev_iovar_setbuf_bsscfg(dev, "vndr_ie",
3556 cfg->ibss_vsie, cfg->ibss_vsie_len,
3557 ioctl_buf, WLC_IOCTL_MEDLEN, bssidx, &cfg->ioctl_buf_sync);
3558 WL_ERR(("ret=%d\n", ret));
3559
3560 if (ret == BCME_OK) {
3561 /* free & initiralize VSIE */
3562 kfree(cfg->ibss_vsie);
3563 cfg->ibss_vsie = NULL;
3564 cfg->ibss_vsie_len = 0;
3565 }
3566 end:
3567 if (ioctl_buf) {
3568 kfree(ioctl_buf);
3569 }
3570 }
3571
3572 return ret;
3573 }
3574
3575 #ifdef WLAIBSS_MCHAN
3576 static bcm_struct_cfgdev*
3577 bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name)
3578 {
3579 int err = 0;
3580 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3581 struct wireless_dev* wdev = NULL;
3582 struct net_device *new_ndev = NULL;
3583 struct net_device *primary_ndev = NULL;
3584 s32 timeout;
3585 wl_aibss_if_t aibss_if;
3586 wl_if_event_info *event = NULL;
3587
3588 if (cfg->ibss_cfgdev != NULL) {
3589 WL_ERR(("IBSS interface %s already exists\n", name));
3590 return NULL;
3591 }
3592
3593 WL_ERR(("Try to create IBSS interface %s\n", name));
3594 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3595 /* generate a new MAC address for the IBSS interface */
3596 get_primary_mac(cfg, &cfg->ibss_if_addr);
3597 cfg->ibss_if_addr.octet[4] ^= 0x40;
3598 memset(&aibss_if, sizeof(aibss_if), 0);
3599 memcpy(&aibss_if.addr, &cfg->ibss_if_addr, sizeof(aibss_if.addr));
3600 aibss_if.chspec = 0;
3601 aibss_if.len = sizeof(aibss_if);
3602
3603 cfg->bss_pending_op = TRUE;
3604 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3605 err = wldev_iovar_setbuf(primary_ndev, "aibss_ifadd", &aibss_if,
3606 sizeof(aibss_if), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3607 if (err) {
3608 WL_ERR(("IOVAR aibss_ifadd failed with error %d\n", err));
3609 goto fail;
3610 }
3611 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3612 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3613 if (timeout <= 0 || cfg->bss_pending_op)
3614 goto fail;
3615
3616 event = &cfg->if_event_info;
3617 /* By calling wl_cfg80211_allocate_if (dhd_allocate_if eventually) we give the control
3618 * over this net_device interface to dhd_linux, hence the interface is managed by dhd_liux
3619 * and will be freed by dhd_detach unless it gets unregistered before that. The
3620 * wireless_dev instance new_ndev->ieee80211_ptr associated with this net_device will
3621 * be freed by wl_dealloc_netinfo
3622 */
3623 new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, event->name,
3624 event->mac, event->bssidx, event->name);
3625 if (new_ndev == NULL)
3626 goto fail;
3627 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
3628 if (wdev == NULL)
3629 goto fail;
3630 wdev->wiphy = wiphy;
3631 wdev->iftype = NL80211_IFTYPE_ADHOC;
3632 wdev->netdev = new_ndev;
3633 new_ndev->ieee80211_ptr = wdev;
3634 SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
3635
3636 /* rtnl lock must have been acquired, if this is not the case, wl_cfg80211_register_if
3637 * needs to be modified to take one parameter (bool need_rtnl_lock)
3638 */
3639 ASSERT_RTNL();
3640 if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev, FALSE) != BCME_OK)
3641 goto fail;
3642
3643 wl_alloc_netinfo(cfg, new_ndev, wdev, WL_MODE_IBSS, PM_ENABLE, event->bssidx);
3644 cfg->ibss_cfgdev = ndev_to_cfgdev(new_ndev);
3645 WL_ERR(("IBSS interface %s created\n", new_ndev->name));
3646 return cfg->ibss_cfgdev;
3647
3648 fail:
3649 WL_ERR(("failed to create IBSS interface %s \n", name));
3650 cfg->bss_pending_op = FALSE;
3651 if (new_ndev)
3652 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, FALSE);
3653 if (wdev)
3654 kfree(wdev);
3655 return NULL;
3656 }
3657
3658 static s32
3659 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
3660 {
3661 int err = 0;
3662 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3663 struct net_device *ndev = NULL;
3664 struct net_device *primary_ndev = NULL;
3665 s32 timeout;
3666
3667 if (!cfgdev || cfg->ibss_cfgdev != cfgdev || ETHER_ISNULLADDR(&cfg->ibss_if_addr.octet))
3668 return -EINVAL;
3669 ndev = (struct net_device *)cfgdev_to_ndev(cfg->ibss_cfgdev);
3670 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3671
3672 cfg->bss_pending_op = TRUE;
3673 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3674 err = wldev_iovar_setbuf(primary_ndev, "aibss_ifdel", &cfg->ibss_if_addr,
3675 sizeof(cfg->ibss_if_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3676 if (err) {
3677 WL_ERR(("IOVAR aibss_ifdel failed with error %d\n", err));
3678 goto fail;
3679 }
3680 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3681 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3682 if (timeout <= 0 || cfg->bss_pending_op) {
3683 WL_ERR(("timeout in waiting IF_DEL event\n"));
3684 goto fail;
3685 }
3686
3687 wl_cfg80211_remove_if(cfg, cfg->if_event_info.ifidx, ndev, FALSE);
3688 cfg->ibss_cfgdev = NULL;
3689 return 0;
3690
3691 fail:
3692 cfg->bss_pending_op = FALSE;
3693 return -1;
3694 }
3695 #endif /* WLAIBSS_MCHAN */
3696
3697 #ifdef WLMESH
3698 s32
3699 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
3700 struct net_device *ndev, s32 bsscfg_idx,
3701 enum nl80211_iftype iface_type, s32 del, u8 *addr)
3702 {
3703 wl_interface_create_t iface;
3704 s32 ret;
3705 wl_interface_info_t *info;
3706
3707 bzero(&iface, sizeof(wl_interface_create_t));
3708
3709 iface.ver = WL_INTERFACE_CREATE_VER;
3710
3711 if (iface_type == NL80211_IFTYPE_AP)
3712 iface.flags = WL_INTERFACE_CREATE_AP;
3713 else
3714 iface.flags = WL_INTERFACE_CREATE_STA;
3715
3716 if (del) {
3717 ret = wldev_iovar_setbuf(ndev, "interface_remove",
3718 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
3719 } else {
3720 if (addr) {
3721 memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
3722 iface.flags |= WL_INTERFACE_MAC_USE;
3723 }
3724 ret = wldev_iovar_getbuf(ndev, "interface_create",
3725 &iface, sizeof(wl_interface_create_t),
3726 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3727 if (ret == 0) {
3728 /* success */
3729 info = (wl_interface_info_t *)cfg->ioctl_buf;
3730 WL_DBG(("wl interface create success!! bssidx:%d \n",
3731 info->bsscfgidx));
3732 }
3733 }
3734
3735 if (ret < 0)
3736 WL_ERR(("Interface %s failed!! ret %d\n",
3737 del ? "remove" : "create", ret));
3738
3739 return ret;
3740 }
3741 #else
3742 s32
3743 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
3744 struct net_device *ndev, s32 bsscfg_idx,
3745 enum nl80211_iftype iface_type, s32 del, u8 *addr)
3746 {
3747 s32 ret;
3748 struct wl_interface_create_v2 iface;
3749 wl_interface_create_v3_t iface_v3;
3750 struct wl_interface_info_v1 *info;
3751 wl_interface_info_v2_t *info_v2;
3752 enum wl_interface_type iftype;
3753 uint32 ifflags;
3754 bool use_iface_info_v2 = false;
3755 u8 ioctl_buf[WLC_IOCTL_SMLEN];
3756
3757 if (del) {
3758 ret = wldev_iovar_setbuf(ndev, "interface_remove",
3759 NULL, 0, ioctl_buf, sizeof(ioctl_buf), NULL);
3760 if (unlikely(ret))
3761 WL_ERR(("Interface remove failed!! ret %d\n", ret));
3762 return ret;
3763 }
3764
3765 /* Interface create */
3766 bzero(&iface, sizeof(iface));
3767 /*
3768 * flags field is still used along with iftype inorder to support the old version of the
3769 * FW work with the latest app changes.
3770 */
3771 if (iface_type == NL80211_IFTYPE_AP) {
3772 iftype = WL_INTERFACE_TYPE_AP;
3773 ifflags = WL_INTERFACE_CREATE_AP;
3774 } else {
3775 iftype = WL_INTERFACE_TYPE_STA;
3776 ifflags = WL_INTERFACE_CREATE_STA;
3777 }
3778 if (addr) {
3779 ifflags |= WL_INTERFACE_MAC_USE;
3780 }
3781
3782 /* Pass ver = 0 for fetching the interface_create iovar version */
3783 ret = wldev_iovar_getbuf(ndev, "interface_create",
3784 &iface, sizeof(struct wl_interface_create_v2),
3785 ioctl_buf, sizeof(ioctl_buf), NULL);
3786 if (ret == BCME_UNSUPPORTED) {
3787 WL_ERR(("interface_create iovar not supported\n"));
3788 return ret;
3789 } else if ((ret == 0) && *((uint32 *)ioctl_buf) == WL_INTERFACE_CREATE_VER_3) {
3790 WL_DBG(("interface_create version 3\n"));
3791 use_iface_info_v2 = true;
3792 bzero(&iface_v3, sizeof(wl_interface_create_v3_t));
3793 iface_v3.ver = WL_INTERFACE_CREATE_VER_3;
3794 iface_v3.iftype = iftype;
3795 iface_v3.flags = ifflags;
3796 if (addr) {
3797 memcpy(&iface_v3.mac_addr.octet, addr, ETH_ALEN);
3798 }
3799 ret = wldev_iovar_getbuf(ndev, "interface_create",
3800 &iface_v3, sizeof(wl_interface_create_v3_t),
3801 ioctl_buf, sizeof(ioctl_buf), NULL);
3802 } else {
3803 #if 0
3804 /* On any other error, attempt with iovar version 2 */
3805 WL_DBG(("interface_create version 2. get_ver:%d\n", ret));
3806 iface.ver = WL_INTERFACE_CREATE_VER_2;
3807 iface.iftype = iftype;
3808 iface.flags = ifflags;
3809 if (addr) {
3810 memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
3811 }
3812 ret = wldev_iovar_getbuf(ndev, "interface_create",
3813 &iface, sizeof(struct wl_interface_create_v2),
3814 ioctl_buf, sizeof(ioctl_buf), NULL);
3815 #endif
3816 }
3817
3818 if (unlikely(ret)) {
3819 WL_ERR(("Interface create failed!! ret %d\n", ret));
3820 return ret;
3821 }
3822
3823 /* success case */
3824 if (use_iface_info_v2 == true) {
3825 info_v2 = (wl_interface_info_v2_t *)ioctl_buf;
3826 ret = info_v2->bsscfgidx;
3827 } else {
3828 /* Use v1 struct */
3829 info = (struct wl_interface_info_v1 *)ioctl_buf;
3830 ret = info->bsscfgidx;
3831 }
3832
3833 WL_DBG(("wl interface create success!! bssidx:%d \n", ret));
3834 return ret;
3835 }
3836 #endif
3837
3838 bool
3839 wl_customer6_legacy_chip_check(struct bcm_cfg80211 *cfg,
3840 struct net_device *ndev)
3841 {
3842 u32 chipnum;
3843 wlc_rev_info_t revinfo;
3844 int ret;
3845
3846 /* Get the device rev info */
3847 memset(&revinfo, 0, sizeof(revinfo));
3848 ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
3849 if (ret < 0) {
3850 WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret));
3851 ASSERT(0);
3852 return false;
3853 }
3854
3855 WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__,
3856 dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum)));
3857 chipnum = revinfo.chipnum;
3858 if ((chipnum == BCM4350_CHIP_ID) || (chipnum == BCM4355_CHIP_ID) ||
3859 (chipnum == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID)) {
3860 /* WAR required */
3861 return true;
3862 }
3863
3864 return false;
3865 }
3866
3867 void
3868 wl_bss_iovar_war(struct bcm_cfg80211 *cfg,
3869 struct net_device *ndev, s32 *val)
3870 {
3871 if (wl_customer6_legacy_chip_check(cfg, ndev)) {
3872 /* Few firmware branches have issues in bss iovar handling and
3873 * that can't be changed since they are in production.
3874 */
3875 if (*val == WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE) {
3876 *val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
3877 } else if (*val == WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE) {
3878 *val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
3879 } else {
3880 /* Ignore for other bss enums */
3881 return;
3882 }
3883 WL_ERR(("wl bss %d\n", *val));
3884 }
3885 }
3886
3887 s32
3888 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
3889 struct net_device *ndev, s32 bsscfg_idx,
3890 enum nl80211_iftype iface_type, s32 del, u8 *addr)
3891 {
3892 s32 ret = BCME_OK;
3893 s32 val = 0;
3894
3895 struct {
3896 s32 cfg;
3897 s32 val;
3898 struct ether_addr ea;
3899 } bss_setbuf;
3900
3901 WL_INFORM(("iface_type:%d del:%d \n", iface_type, del));
3902
3903 bzero(&bss_setbuf, sizeof(bss_setbuf));
3904
3905 /* AP=2, STA=3, up=1, down=0, val=-1 */
3906 if (del) {
3907 val = WLC_AP_IOV_OP_DELETE;
3908 } else if (iface_type == NL80211_IFTYPE_AP) {
3909 /* Add/role change to AP Interface */
3910 WL_DBG(("Adding AP Interface \n"));
3911 val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
3912 } else if (iface_type == NL80211_IFTYPE_STATION) {
3913 /* Add/role change to STA Interface */
3914 WL_DBG(("Adding STA Interface \n"));
3915 val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
3916 } else {
3917 WL_ERR((" add_del_bss NOT supported for IFACE type:0x%x", iface_type));
3918 return -EINVAL;
3919 }
3920
3921 if (!del) {
3922 wl_bss_iovar_war(cfg, ndev, &val);
3923 }
3924
3925 bss_setbuf.cfg = htod32(bsscfg_idx);
3926 bss_setbuf.val = htod32(val);
3927
3928 if (addr) {
3929 memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
3930 }
3931
3932 WL_DBG(("wl bss %d bssidx:%d iface:%s \n", val, bsscfg_idx, ndev->name));
3933 ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
3934 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3935 if (ret != 0)
3936 WL_ERR(("'bss %d' failed with %d\n", val, ret));
3937
3938 return ret;
3939 }
3940
3941 s32
3942 wl_cfg80211_bss_up(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 bss_up)
3943 {
3944 s32 ret = BCME_OK;
3945 s32 val = bss_up ? 1 : 0;
3946
3947 struct {
3948 s32 cfg;
3949 s32 val;
3950 } bss_setbuf;
3951
3952 bss_setbuf.cfg = htod32(bsscfg_idx);
3953 bss_setbuf.val = htod32(val);
3954
3955 WL_DBG(("wl bss -C %d %s\n", bsscfg_idx, bss_up ? "up" : "down"));
3956 ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
3957 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3958
3959 if (ret != 0) {
3960 WL_ERR(("'bss %d' failed with %d\n", bss_up, ret));
3961 }
3962
3963 return ret;
3964 }
3965
3966 bool
3967 wl_cfg80211_bss_isup(struct net_device *ndev, int bsscfg_idx)
3968 {
3969 s32 result, val;
3970 bool isup = false;
3971 s8 getbuf[64];
3972
3973 /* Check if the BSS is up */
3974 *(int*)getbuf = -1;
3975 result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
3976 sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL);
3977 if (result != 0) {
3978 WL_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx, result));
3979 WL_ERR(("NOTE: this ioctl error is normal "
3980 "when the BSS has not been created yet.\n"));
3981 } else {
3982 val = *(int*)getbuf;
3983 val = dtoh32(val);
3984 WL_DBG(("wl bss -C %d = %d\n", bsscfg_idx, val));
3985 isup = (val ? TRUE : FALSE);
3986 }
3987 return isup;
3988 }
3989
3990 static s32
3991 cfg80211_to_wl_iftype(uint16 type, uint16 *role, uint16 *mode)
3992 {
3993 switch (type) {
3994 case NL80211_IFTYPE_STATION:
3995 *role = WLC_E_IF_ROLE_STA;
3996 *mode = WL_MODE_BSS;
3997 break;
3998 case NL80211_IFTYPE_AP:
3999 *role = WLC_E_IF_ROLE_AP;
4000 *mode = WL_MODE_AP;
4001 break;
4002 case NL80211_IFTYPE_P2P_GO:
4003 *role = WLC_E_IF_ROLE_P2P_GO;
4004 *mode = WL_MODE_AP;
4005 break;
4006 case NL80211_IFTYPE_P2P_CLIENT:
4007 *role = WLC_E_IF_ROLE_P2P_CLIENT;
4008 *mode = WL_MODE_BSS;
4009 break;
4010 case NL80211_IFTYPE_MONITOR:
4011 WL_ERR(("Unsupported mode \n"));
4012 return BCME_UNSUPPORTED;
4013 case NL80211_IFTYPE_ADHOC:
4014 *role = WLC_E_IF_ROLE_IBSS;
4015 *mode = WL_MODE_IBSS;
4016 break;
4017 default:
4018 WL_ERR(("Unknown interface type:0x%x\n", type));
4019 return BCME_ERROR;
4020 }
4021 return BCME_OK;
4022 }
4023
4024 static s32
4025 wl_if_to_cfg80211_type(uint16 role)
4026 {
4027 switch (role) {
4028 case WLC_E_IF_ROLE_STA:
4029 return NL80211_IFTYPE_STATION;
4030 case WLC_E_IF_ROLE_AP:
4031 return NL80211_IFTYPE_AP;
4032 case WLC_E_IF_ROLE_P2P_GO:
4033 return NL80211_IFTYPE_P2P_GO;
4034 case WLC_E_IF_ROLE_P2P_CLIENT:
4035 return NL80211_IFTYPE_P2P_CLIENT;
4036 case WLC_E_IF_ROLE_IBSS:
4037 return NL80211_IFTYPE_ADHOC;
4038 default:
4039 WL_ERR(("Unknown interface role:0x%x. Forcing type station\n", role));
4040 return BCME_ERROR;
4041 }
4042 }
4043
4044 struct net_device *
4045 wl_cfg80211_post_ifcreate(struct net_device *ndev,
4046 wl_if_event_info *event, u8 *addr,
4047 const char *name, bool rtnl_lock_reqd)
4048 {
4049 struct bcm_cfg80211 *cfg;
4050 struct net_device *primary_ndev;
4051 struct net_device *new_ndev = NULL;
4052 struct wireless_dev *wdev = NULL;
4053 s32 iface_type;
4054 s32 ret;
4055 u16 mode;
4056 u16 role;
4057 u8 mac_addr[ETH_ALEN];
4058
4059 if (!ndev || !event) {
4060 WL_ERR(("Wrong arg\n"));
4061 return NULL;
4062 }
4063
4064 cfg = wl_get_cfg(ndev);
4065 if (!cfg) {
4066 WL_ERR(("cfg null\n"));
4067 return NULL;
4068 }
4069
4070 WL_DBG(("Enter. role:%d ifidx:%d bssidx:%d\n",
4071 event->role, event->ifidx, event->bssidx));
4072 if (!event->ifidx || !event->bssidx) {
4073 /* Fw returned primary idx (0) for virtual interface */
4074 WL_ERR(("Wrong index. ifidx:%d bssidx:%d \n",
4075 event->ifidx, event->bssidx));
4076 return NULL;
4077 }
4078
4079 iface_type = wl_if_to_cfg80211_type(event->role);
4080 if (iface_type < 0) {
4081 /* Unknown iface type */
4082 WL_ERR(("Wrong iface type \n"));
4083 return NULL;
4084 }
4085
4086 if (cfg80211_to_wl_iftype(iface_type, &role, &mode) < 0) {
4087 /* Unsupported operating mode */
4088 WL_ERR(("Unsupported operating mode \n"));
4089 return NULL;
4090 }
4091
4092 WL_DBG(("mac_ptr:%p name:%s role:%d nl80211_iftype:%d " MACDBG "\n",
4093 addr, name, event->role, iface_type, MAC2STRDBG(event->mac)));
4094 if (!name) {
4095 /* If iface name is not provided, use dongle ifname */
4096 name = event->name;
4097 }
4098
4099 if (!addr) {
4100 /* If mac address is not set, use primary mac with locally administered
4101 * bit set.
4102 */
4103 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
4104 memcpy(mac_addr, primary_ndev->dev_addr, ETH_ALEN);
4105 #ifndef CUSTOMER_HW6
4106 /* For customer6 builds, use primary mac address for virtual interface */
4107 mac_addr[0] |= 0x02;
4108 #endif /* CUSTOMER_HW6 */
4109 addr = mac_addr;
4110 }
4111
4112 new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx,
4113 name, addr, event->bssidx, event->name);
4114 if (!new_ndev) {
4115 WL_ERR(("I/F allocation failed! \n"));
4116 goto fail;
4117 } else {
4118 WL_DBG(("I/F allocation succeeded! ifidx:0x%x bssidx:0x%x \n",
4119 event->ifidx, event->bssidx));
4120 }
4121
4122 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
4123 if (!wdev) {
4124 WL_ERR(("wireless_dev alloc failed! \n"));
4125 goto fail;
4126 }
4127
4128 wdev->wiphy = bcmcfg_to_wiphy(cfg);
4129 wdev->iftype = iface_type;
4130 new_ndev->ieee80211_ptr = wdev;
4131 SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
4132
4133 /* Check whether mac addr is in sync with fw. If not,
4134 * apply it using cur_etheraddr.
4135 */
4136 if (memcmp(addr, event->mac, ETH_ALEN) != 0) {
4137 ret = wldev_iovar_setbuf_bsscfg(new_ndev, "cur_etheraddr",
4138 addr, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
4139 event->bssidx, &cfg->ioctl_buf_sync);
4140 if (unlikely(ret)) {
4141 WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
4142 goto fail;
4143 }
4144 memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
4145 WL_ERR(("Applying updated mac address to firmware\n"));
4146 }
4147
4148 if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd) != BCME_OK) {
4149 WL_ERR(("IFACE register failed \n"));
4150 goto fail;
4151 }
4152
4153 /* Initialize with the station mode params */
4154 ret = wl_alloc_netinfo(cfg, new_ndev, wdev, mode,
4155 PM_ENABLE, event->bssidx);
4156 if (unlikely(ret)) {
4157 WL_ERR(("wl_alloc_netinfo Error (%d)\n", ret));
4158 goto fail;
4159 }
4160
4161 /* Apply the mode & infra setting based on iftype */
4162 if ((ret = wl_config_ifmode(cfg, new_ndev, iface_type)) < 0) {
4163 WL_ERR(("config ifmode failure (%d)\n", ret));
4164 goto fail;
4165 }
4166
4167 if (mode == WL_MODE_AP) {
4168 wl_set_drv_status(cfg, AP_CREATING, new_ndev);
4169 }
4170
4171 WL_INFORM(("Host Network Interface (%s) for Secondary I/F created."
4172 " cfg_iftype:%d wl_role:%d\n", new_ndev->name, iface_type, event->role));
4173
4174 return new_ndev;
4175
4176 fail:
4177 if (wdev)
4178 kfree(wdev);
4179 if (new_ndev)
4180 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd);
4181
4182 return NULL;
4183 }
4184
4185 void
4186 wl_cfg80211_cleanup_virtual_ifaces(struct net_device *dev, bool rtnl_lock_reqd)
4187 {
4188 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4189 struct net_info *iter, *next;
4190 struct net_device *primary_ndev;
4191
4192 /* Note: This function will clean up only the network interface and host
4193 * data structures. The firmware interface clean up will happen in the
4194 * during chip reset (ifconfig wlan0 down for built-in drivers/rmmod
4195 * context for the module case).
4196 */
4197 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
4198 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4199 #pragma GCC diagnostic push
4200 #pragma GCC diagnostic ignored "-Wcast-qual"
4201 #endif
4202 for_each_ndev(cfg, iter, next) {
4203 if (iter->ndev && (iter->ndev != primary_ndev)) {
4204 WL_DBG(("Cleaning up iface:%s \n", iter->ndev->name));
4205 wl_cfg80211_post_ifdel(iter->ndev, rtnl_lock_reqd);
4206 }
4207 }
4208 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4209 #pragma GCC diagnostic pop
4210 #endif
4211 }
4212
4213 s32
4214 wl_cfg80211_post_ifdel(struct net_device *ndev, bool rtnl_lock_reqd)
4215 {
4216 int ifidx = -1;
4217 struct bcm_cfg80211 *cfg;
4218
4219 if (!ndev || !ndev->ieee80211_ptr) {
4220 /* No wireless dev done for this interface */
4221 return -EINVAL;
4222 }
4223
4224 cfg = wl_get_cfg(ndev);
4225 if (!cfg) {
4226 WL_ERR(("cfg null\n"));
4227 return BCME_ERROR;
4228 }
4229 ifidx = dhd_net2idx(((struct dhd_pub *)(cfg->pub))->info, ndev);
4230 BCM_REFERENCE(ifidx);
4231 if (ifidx <= 0) {
4232 WL_ERR(("Invalid IF idx for iface:%s\n", ndev->name));
4233 ASSERT(0);
4234 return BCME_ERROR;
4235 }
4236 WL_DBG(("cfg80211_remove for iface:%s \n", ndev->name));
4237 wl_cfg80211_remove_if(cfg, ifidx, ndev, rtnl_lock_reqd);
4238 cfg->bss_pending_op = FALSE;
4239
4240 return BCME_OK;
4241 }
4242
4243 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
4244 /* Create a Generic Network Interface and initialize it depending up on
4245 * the interface type
4246 */
4247 bcm_struct_cfgdev*
4248 wl_cfg80211_create_iface(struct wiphy *wiphy,
4249 enum nl80211_iftype iface_type,
4250 u8 *mac_addr, const char *name)
4251 {
4252 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4253 struct net_device *new_ndev = NULL;
4254 struct net_device *primary_ndev = NULL;
4255 s32 ret = BCME_OK;
4256 s32 bsscfg_idx = 0;
4257 u32 timeout;
4258 wl_if_event_info *event = NULL;
4259 u8 addr[ETH_ALEN];
4260 struct net_info *iter, *next;
4261 #ifdef WLMESH
4262 u16 role = 0, mode = 0;
4263 #endif
4264
4265 WL_DBG(("Enter\n"));
4266 if (!name) {
4267 WL_ERR(("Interface name not provided\n"));
4268 return NULL;
4269 }
4270 else {
4271 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4272 #pragma GCC diagnostic push
4273 #pragma GCC diagnostic ignored "-Wcast-qual"
4274 #endif
4275 for_each_ndev(cfg, iter, next) {
4276 if (iter->ndev) {
4277 if (strcmp(iter->ndev->name, name) == 0) {
4278 WL_ERR(("Interface name, %s exists !\n", iter->ndev->name));
4279 return NULL;
4280 }
4281 }
4282 }
4283 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4284 #pragma GCC diagnostic pop
4285 #endif
4286 }
4287 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
4288
4289 if (likely(!mac_addr)) {
4290 /* Use primary MAC with the locally administered bit for the
4291 * Secondary STA I/F
4292 */
4293 memcpy(addr, primary_ndev->dev_addr, ETH_ALEN);
4294 addr[0] |= 0x02;
4295 } else {
4296 /* Use the application provided mac address (if any) */
4297 memcpy(addr, mac_addr, ETH_ALEN);
4298 }
4299
4300 if ((iface_type != NL80211_IFTYPE_STATION) && (iface_type != NL80211_IFTYPE_AP)) {
4301 WL_ERR(("IFACE type:%d not supported. STA "
4302 "or AP IFACE is only supported\n", iface_type));
4303 return NULL;
4304 }
4305
4306 cfg->bss_pending_op = TRUE;
4307 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
4308
4309 /* De-initialize the p2p discovery interface, if operational */
4310 if (p2p_is_on(cfg)) {
4311 WL_DBG(("Disabling P2P Discovery Interface \n"));
4312 #ifdef WL_CFG80211_P2P_DEV_IF
4313 ret = wl_cfg80211_scan_stop(cfg, bcmcfg_to_p2p_wdev(cfg));
4314 #else
4315 ret = wl_cfg80211_scan_stop(cfg, cfg->p2p_net);
4316 #endif
4317 if (unlikely(ret < 0)) {
4318 CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
4319 }
4320
4321 wl_cfgp2p_disable_discovery(cfg);
4322 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
4323 p2p_on(cfg) = false;
4324 }
4325
4326 /*
4327 * Intialize the firmware I/F.
4328 */
4329 if (wl_customer6_legacy_chip_check(cfg, primary_ndev)) {
4330 /* Use bss iovar instead of interface_create iovar */
4331 ret = BCME_UNSUPPORTED;
4332 } else {
4333 ret = wl_cfg80211_interface_ops(cfg, primary_ndev, bsscfg_idx,
4334 iface_type, 0, addr);
4335 }
4336 if (ret == BCME_UNSUPPORTED) {
4337 /* Use bssidx 1 by default */
4338 bsscfg_idx = 1;
4339 if ((ret = wl_cfg80211_add_del_bss(cfg, primary_ndev,
4340 bsscfg_idx, iface_type, 0, addr)) < 0) {
4341 goto exit;
4342 }
4343 } else if (ret < 0) {
4344 WL_ERR(("Interface create failed!! ret:%d \n", ret));
4345 goto exit;
4346 } else {
4347 /* Success */
4348 bsscfg_idx = ret;
4349 }
4350
4351 WL_DBG(("Interface created!! bssidx:%d \n", bsscfg_idx));
4352
4353 /*
4354 * Wait till the firmware send a confirmation event back.
4355 */
4356 WL_DBG(("Wait for the FW I/F Event\n"));
4357 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
4358 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
4359 if (timeout <= 0 || cfg->bss_pending_op) {
4360 WL_ERR(("ADD_IF event, didn't come. Return \n"));
4361 goto exit;
4362 }
4363
4364 event = &cfg->if_event_info;
4365 #ifdef WLMESH
4366 cfg80211_to_wl_iftype(iface_type, &role, &mode);
4367 event->role = role;
4368 #endif
4369
4370 /*
4371 * Since FW operation is successful,we can go ahead with the
4372 * the host interface creation.
4373 */
4374 if ((new_ndev = wl_cfg80211_post_ifcreate(primary_ndev,
4375 event, mac_addr, name, false))) {
4376 /* Iface post ops successful. Return ndev/wdev ptr */
4377 return ndev_to_cfgdev(new_ndev);
4378 }
4379
4380 exit:
4381 cfg->bss_pending_op = FALSE;
4382 return NULL;
4383 }
4384
4385 s32
4386 wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
4387 {
4388 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4389 struct net_device *ndev = NULL;
4390 s32 ret = BCME_OK;
4391 s32 bsscfg_idx = 1;
4392 u32 timeout;
4393 enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
4394
4395 WL_DBG(("Enter\n"));
4396
4397 /* If any scan is going on, abort it */
4398 if (wl_get_drv_status_all(cfg, SCANNING)) {
4399 WL_DBG(("Scan in progress. Aborting the scan!\n"));
4400 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
4401 }
4402
4403 ndev = (struct net_device *)cfgdev_to_ndev(cfgdev);
4404 cfg->bss_pending_op = TRUE;
4405 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
4406
4407 /* Delete the firmware interface. "interface_remove" command
4408 * should go on the interface to be deleted
4409 */
4410 bsscfg_idx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
4411 if (bsscfg_idx <= 0) {
4412 /* validate bsscfgidx */
4413 WL_ERR(("Wrong bssidx! \n"));
4414 return -EINVAL;
4415 }
4416 WL_DBG(("del interface. bssidx:%d", bsscfg_idx));
4417 ret = wl_cfg80211_interface_ops(cfg, ndev, bsscfg_idx,
4418 NL80211_IFTYPE_STATION, 1, NULL);
4419 if (ret == BCME_UNSUPPORTED) {
4420 if ((ret = wl_cfg80211_add_del_bss(cfg, ndev,
4421 bsscfg_idx, iface_type, true, NULL)) < 0) {
4422 WL_ERR(("DEL bss failed ret:%d \n", ret));
4423 goto exit;
4424 }
4425 } else if (ret < 0) {
4426 WL_ERR(("Interface DEL failed ret:%d \n", ret));
4427 goto exit;
4428 }
4429
4430 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
4431 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
4432 if (timeout <= 0 || cfg->bss_pending_op) {
4433 WL_ERR(("timeout in waiting IF_DEL event\n"));
4434 }
4435
4436 exit:
4437 ret = wl_cfg80211_post_ifdel(ndev, false);
4438 if (unlikely(ret)) {
4439 WL_ERR(("post_ifdel failed\n"));
4440 }
4441
4442 return ret;
4443 }
4444 #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
4445
4446 #ifdef WLMESH
4447 s32 wl_cfg80211_set_sae_password(struct net_device *dev, char* buf, int len)
4448 {
4449 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4450
4451 sscanf(buf, "%s %d", cfg->sae_password, &cfg->sae_password_len);
4452 return 0;
4453 }
4454
4455 static s32 wl_cfg80211_join_mesh(
4456 struct wiphy *wiphy, struct net_device *dev,
4457 const struct mesh_config *conf,
4458 const struct mesh_setup *setup)
4459 {
4460 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4461 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
4462 struct ieee80211_channel *chan = setup->chandef.chan;
4463 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0))
4464 struct ieee80211_channel *chan = setup->channel;
4465 #endif
4466 u32 param[2] = {0, 0};
4467 s32 err = 0;
4468 u32 bw_cap = 0;
4469 u32 beacon_interval = setup->beacon_interval;
4470 u32 dtim_period = setup->dtim_period;
4471 size_t join_params_size;
4472 struct wl_join_params join_params;
4473 chanspec_t chanspec = 0;
4474
4475 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
4476
4477 if (wl_get_drv_status(cfg, CONNECTED, dev)) {
4478 struct wlc_ssid *lssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
4479 u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
4480 u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
4481 if ((memcmp(setup->mesh_id, lssid->SSID, lssid->SSID_len) == 0) &&
4482 (*channel == cfg->channel)) {
4483 WL_ERR(("MESH connection already existed to " MACDBG "\n",
4484 MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
4485 return -EISCONN;
4486 }
4487 WL_ERR(("Previous connecton existed, please disconnect mesh %s (" MACDBG ") first\n",
4488 lssid->SSID, MAC2STRDBG(bssid)));
4489 return -EISCONN;
4490 }
4491
4492 if (chan) {
4493 if (chan->band == IEEE80211_BAND_5GHZ)
4494 param[0] = WLC_BAND_5G;
4495 else if (chan->band == IEEE80211_BAND_2GHZ)
4496 param[0] = WLC_BAND_2G;
4497 err = wldev_iovar_getint(dev, "bw_cap", param);
4498 if (unlikely(err)) {
4499 WL_ERR(("Get bw_cap Failed (%d)\n", err));
4500 return err;
4501 }
4502 bw_cap = param[0];
4503 chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
4504 }
4505
4506 memset(&join_params, 0, sizeof(join_params));
4507 memcpy((void *)join_params.ssid.SSID, (void *)setup->mesh_id,
4508 setup->mesh_id_len);
4509
4510 join_params.ssid.SSID_len = htod32(setup->mesh_id_len);
4511 join_params.params.chanspec_list[0] = chanspec;
4512 join_params.params.chanspec_num = 1;
4513 wldev_iovar_setint(dev, "chanspec", chanspec);
4514 join_params_size = sizeof(join_params);
4515
4516 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
4517 wldev_iovar_setint(dev, "wsec", 0);
4518
4519 if (cfg->sae_password_len > 0) {
4520 wldev_iovar_setint(dev, "mesh_auth_proto", 1);
4521 wldev_iovar_setint(dev, "wpa_auth", WPA2_AUTH_PSK);
4522 wldev_iovar_setint(dev, "wsec", AES_ENABLED);
4523 wldev_iovar_setint(dev, "mfp", WL_MFP_REQUIRED);
4524 printf("%s: password=%s, len=%d\n", __FUNCTION__,
4525 cfg->sae_password, cfg->sae_password_len);
4526 wldev_iovar_setbuf(dev, "sae_password", cfg->sae_password, cfg->sae_password_len,
4527 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
4528 } else {
4529 wldev_iovar_setint(dev, "mesh_auth_proto", 0);
4530 wldev_iovar_setint(dev, "mfp", WL_MFP_NONE);
4531 }
4532
4533 if (beacon_interval) {
4534 if ((err = wldev_ioctl_set(dev, WLC_SET_BCNPRD,
4535 &beacon_interval, sizeof(s32))) < 0) {
4536 WL_ERR(("Beacon Interval Set Error, %d\n", err));
4537 return err;
4538 }
4539 }
4540
4541 if (dtim_period) {
4542 if ((err = wldev_ioctl_set(dev, WLC_SET_DTIMPRD,
4543 &dtim_period, sizeof(s32))) < 0) {
4544 WL_ERR(("DTIM Interval Set Error, %d\n", err));
4545 return err;
4546 }
4547 }
4548 wldev_iovar_setint(dev, "mpc", 0);
4549
4550 WL_ERR(("JOIN %s on channel %d with chanspec 0x%4x\n",
4551 join_params.ssid.SSID, cfg->channel, chanspec));
4552
4553 err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
4554 join_params_size);
4555
4556 if (unlikely(err)) {
4557 WL_ERR(("Error (%d)\n", err));
4558 return err;
4559 }
4560
4561 wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
4562 wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
4563 return err;
4564 }
4565
4566
4567 static s32 wl_cfg80211_leave_mesh(
4568 struct wiphy *wiphy, struct net_device *dev)
4569 {
4570 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4571 s32 err = 0;
4572 scb_val_t scbval;
4573 u8 *curbssid;
4574
4575 RETURN_EIO_IF_NOT_UP(cfg);
4576 wl_link_down(cfg);
4577
4578 WL_ERR(("Leave MESH\n"));
4579 curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
4580 wl_set_drv_status(cfg, DISCONNECTING, dev);
4581 scbval.val = 0;
4582 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
4583 err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
4584 sizeof(scb_val_t));
4585 if (unlikely(err)) {
4586 wl_clr_drv_status(cfg, DISCONNECTING, dev);
4587 WL_ERR(("error(%d)\n", err));
4588 return err;
4589 }
4590 memset(cfg->sae_password, 0, SAE_MAX_PASSWD_LEN);
4591 cfg->sae_password_len = 0;
4592
4593 return err;
4594 }
4595 #endif /* WLMESH */
4596
4597 static s32
4598 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
4599 struct cfg80211_ibss_params *params)
4600 {
4601 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4602 struct cfg80211_bss *bss;
4603 struct ieee80211_channel *chan;
4604 struct wl_join_params join_params;
4605 int scan_suppress;
4606 struct cfg80211_ssid ssid;
4607 s32 scan_retry = 0;
4608 s32 err = 0;
4609 size_t join_params_size;
4610 chanspec_t chanspec = 0;
4611 u32 param[2] = {0, 0};
4612 u32 bw_cap = 0;
4613
4614 WL_TRACE(("In\n"));
4615 RETURN_EIO_IF_NOT_UP(cfg);
4616 WL_INFORM(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
4617 if (!params->ssid || params->ssid_len <= 0 ||
4618 params->ssid_len > DOT11_MAX_SSID_LEN) {
4619 WL_ERR(("Invalid parameter\n"));
4620 return -EINVAL;
4621 }
4622 #if defined(WL_CFG80211_P2P_DEV_IF)
4623 chan = params->chandef.chan;
4624 #else
4625 chan = params->channel;
4626 #endif /* WL_CFG80211_P2P_DEV_IF */
4627 if (chan)
4628 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
4629 if (wl_get_drv_status(cfg, CONNECTED, dev)) {
4630 struct wlc_ssid *lssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
4631 u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
4632 u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
4633 if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
4634 (memcmp(params->ssid, lssid->SSID, lssid->SSID_len) == 0) &&
4635 (*channel == cfg->channel))) {
4636 WL_ERR(("Connection already existed to " MACDBG "\n",
4637 MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
4638 return -EISCONN;
4639 }
4640 WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
4641 lssid->SSID, MAC2STRDBG(bssid)));
4642 }
4643
4644 /* remove the VSIE */
4645 wl_cfg80211_ibss_vsie_delete(dev);
4646
4647 bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
4648 if (!bss) {
4649 if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
4650 memcpy(ssid.ssid, params->ssid, params->ssid_len);
4651 ssid.ssid_len = params->ssid_len;
4652 do {
4653 if (unlikely
4654 (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
4655 -EBUSY)) {
4656 wl_delay(150);
4657 } else {
4658 break;
4659 }
4660 } while (++scan_retry < WL_SCAN_RETRY_MAX);
4661
4662 /* rtnl lock code is removed here. don't see why rtnl lock
4663 * needs to be released.
4664 */
4665
4666 /* wait 4 secons till scan done.... */
4667 schedule_timeout_interruptible(msecs_to_jiffies(4000));
4668
4669 bss = cfg80211_get_ibss(wiphy, NULL,
4670 params->ssid, params->ssid_len);
4671 }
4672 }
4673 if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
4674 ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
4675 !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
4676 cfg->ibss_starter = false;
4677 WL_DBG(("Found IBSS\n"));
4678 } else {
4679 cfg->ibss_starter = true;
4680 }
4681
4682 if (bss) {
4683 CFG80211_PUT_BSS(wiphy, bss);
4684 }
4685
4686 if (chan) {
4687 if (chan->band == IEEE80211_BAND_5GHZ)
4688 param[0] = WLC_BAND_5G;
4689 else if (chan->band == IEEE80211_BAND_2GHZ)
4690 param[0] = WLC_BAND_2G;
4691 err = wldev_iovar_getint(dev, "bw_cap", param);
4692 if (unlikely(err)) {
4693 WL_ERR(("Get bw_cap Failed (%d)\n", err));
4694 return err;
4695 }
4696 bw_cap = param[0];
4697 chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
4698 }
4699 /*
4700 * Join with specific BSSID and cached SSID
4701 * If SSID is zero join based on BSSID only
4702 */
4703 memset(&join_params, 0, sizeof(join_params));
4704 memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
4705 params->ssid_len);
4706 join_params.ssid.SSID_len = htod32(params->ssid_len);
4707 if (params->bssid) {
4708 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
4709 err = wldev_ioctl_set(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
4710 ETHER_ADDR_LEN);
4711 if (unlikely(err)) {
4712 WL_ERR(("Error (%d)\n", err));
4713 return err;
4714 }
4715 } else
4716 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
4717
4718 if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
4719 scan_suppress = TRUE;
4720 /* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
4721 err = wldev_ioctl_set(dev, WLC_SET_SCANSUPPRESS,
4722 &scan_suppress, sizeof(int));
4723 if (unlikely(err)) {
4724 WL_ERR(("Scan Suppress Setting Failed (%d)\n", err));
4725 return err;
4726 }
4727 }
4728
4729 join_params.params.chanspec_list[0] = chanspec;
4730 join_params.params.chanspec_num = 1;
4731 wldev_iovar_setint(dev, "chanspec", chanspec);
4732 join_params_size = sizeof(join_params);
4733
4734 /* Disable Authentication, IBSS will add key if it required */
4735 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
4736 wldev_iovar_setint(dev, "wsec", 0);
4737
4738 err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
4739 join_params_size);
4740 if (unlikely(err)) {
4741 WL_ERR(("Error (%d)\n", err));
4742 return err;
4743 }
4744
4745 if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
4746 scan_suppress = FALSE;
4747 /* Reset the SCAN SUPPRESS Flag */
4748 err = wldev_ioctl_set(dev, WLC_SET_SCANSUPPRESS,
4749 &scan_suppress, sizeof(int));
4750 if (unlikely(err)) {
4751 WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err));
4752 return err;
4753 }
4754 }
4755 wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
4756 wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
4757 #ifdef WL_RELMCAST
4758 cfg->rmc_event_seq = 0; /* initialize rmcfail sequence */
4759 #endif /* WL_RELMCAST */
4760 return err;
4761 }
4762
4763 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
4764 {
4765 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4766 s32 err = 0;
4767 scb_val_t scbval;
4768 u8 *curbssid;
4769
4770 RETURN_EIO_IF_NOT_UP(cfg);
4771 wl_link_down(cfg);
4772
4773 WL_ERR(("Leave IBSS\n"));
4774 curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
4775 wl_set_drv_status(cfg, DISCONNECTING, dev);
4776 scbval.val = 0;
4777 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
4778 err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
4779 sizeof(scb_val_t));
4780 if (unlikely(err)) {
4781 wl_clr_drv_status(cfg, DISCONNECTING, dev);
4782 WL_ERR(("error(%d)\n", err));
4783 return err;
4784 }
4785
4786 /* remove the VSIE */
4787 wl_cfg80211_ibss_vsie_delete(dev);
4788
4789 return err;
4790 }
4791
4792 #ifdef MFP
4793 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8** rsn_cap)
4794 {
4795 u16 suite_count;
4796 wpa_suite_mcast_t *mcast;
4797 wpa_suite_ucast_t *ucast;
4798 u16 len;
4799 wpa_suite_auth_key_mgmt_t *mgmt;
4800
4801 if (!wpa2ie)
4802 return -1;
4803
4804 len = wpa2ie->len;
4805 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
4806 if ((len -= WPA_SUITE_LEN) <= 0)
4807 return BCME_BADLEN;
4808 ucast = (wpa_suite_ucast_t *)&mcast[1];
4809 suite_count = ltoh16_ua(&ucast->count);
4810 if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
4811 (len -= (WPA_IE_SUITE_COUNT_LEN +
4812 (WPA_SUITE_LEN * suite_count))) <= 0)
4813 return BCME_BADLEN;
4814
4815 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
4816 suite_count = ltoh16_ua(&mgmt->count);
4817
4818 if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
4819 (len -= (WPA_IE_SUITE_COUNT_LEN +
4820 (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
4821 rsn_cap[0] = (u8 *)&mgmt->list[suite_count];
4822 } else
4823 return BCME_BADLEN;
4824
4825 return 0;
4826 }
4827 #endif /* MFP */
4828
4829 static s32
4830 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
4831 {
4832 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4833 struct wl_security *sec;
4834 s32 val = 0;
4835 s32 err = 0;
4836 s32 bssidx;
4837
4838 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4839 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4840 return BCME_ERROR;
4841 }
4842
4843 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
4844 val = WPA_AUTH_PSK |
4845 WPA_AUTH_UNSPECIFIED;
4846 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
4847 val = WPA2_AUTH_PSK|
4848 WPA2_AUTH_UNSPECIFIED;
4849 else
4850 val = WPA_AUTH_DISABLED;
4851
4852 if (is_wps_conn(sme))
4853 val = WPA_AUTH_DISABLED;
4854
4855 WL_DBG(("setting wpa_auth to 0x%0x\n", val));
4856 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
4857 if (unlikely(err)) {
4858 WL_ERR(("set wpa_auth failed (%d)\n", err));
4859 return err;
4860 }
4861 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4862 sec->wpa_versions = sme->crypto.wpa_versions;
4863 return err;
4864 }
4865
4866
4867 static s32
4868 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
4869 {
4870 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4871 struct wl_security *sec;
4872 s32 val = 0;
4873 s32 err = 0;
4874 s32 bssidx;
4875
4876 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4877 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4878 return BCME_ERROR;
4879 }
4880
4881 switch (sme->auth_type) {
4882 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4883 val = WL_AUTH_OPEN_SYSTEM;
4884 WL_DBG(("open system\n"));
4885 break;
4886 case NL80211_AUTHTYPE_SHARED_KEY:
4887 val = WL_AUTH_SHARED_KEY;
4888 WL_DBG(("shared key\n"));
4889 break;
4890 case NL80211_AUTHTYPE_AUTOMATIC:
4891 val = WL_AUTH_OPEN_SHARED;
4892 WL_DBG(("automatic\n"));
4893 break;
4894 default:
4895 val = 2;
4896 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
4897 break;
4898 }
4899
4900 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
4901 if (unlikely(err)) {
4902 WL_ERR(("set auth failed (%d)\n", err));
4903 return err;
4904 }
4905 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4906 sec->auth_type = sme->auth_type;
4907 return err;
4908 }
4909
4910 static s32
4911 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
4912 {
4913 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4914 struct wl_security *sec;
4915 s32 pval = 0;
4916 s32 gval = 0;
4917 s32 err = 0;
4918 s32 wsec_val = 0;
4919 s32 bssidx;
4920
4921 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4922 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4923 return BCME_ERROR;
4924 }
4925
4926 if (sme->crypto.n_ciphers_pairwise) {
4927 switch (sme->crypto.ciphers_pairwise[0]) {
4928 case WLAN_CIPHER_SUITE_WEP40:
4929 case WLAN_CIPHER_SUITE_WEP104:
4930 pval = WEP_ENABLED;
4931 break;
4932 case WLAN_CIPHER_SUITE_TKIP:
4933 pval = TKIP_ENABLED;
4934 break;
4935 case WLAN_CIPHER_SUITE_CCMP:
4936 case WLAN_CIPHER_SUITE_AES_CMAC:
4937 pval = AES_ENABLED;
4938 break;
4939 default:
4940 WL_ERR(("invalid cipher pairwise (%d)\n",
4941 sme->crypto.ciphers_pairwise[0]));
4942 return -EINVAL;
4943 }
4944 }
4945 if (sme->crypto.cipher_group) {
4946 switch (sme->crypto.cipher_group) {
4947 case WLAN_CIPHER_SUITE_WEP40:
4948 case WLAN_CIPHER_SUITE_WEP104:
4949 gval = WEP_ENABLED;
4950 break;
4951 case WLAN_CIPHER_SUITE_TKIP:
4952 gval = TKIP_ENABLED;
4953 break;
4954 case WLAN_CIPHER_SUITE_CCMP:
4955 gval = AES_ENABLED;
4956 break;
4957 case WLAN_CIPHER_SUITE_AES_CMAC:
4958 gval = AES_ENABLED;
4959 break;
4960 default:
4961 WL_ERR(("invalid cipher group (%d)\n",
4962 sme->crypto.cipher_group));
4963 return -EINVAL;
4964 }
4965 }
4966
4967 WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
4968
4969 if (is_wps_conn(sme)) {
4970 if (sme->privacy)
4971 err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
4972 else
4973 /* WPS-2.0 allows no security */
4974 err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
4975 } else {
4976 WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
4977 wsec_val = pval | gval;
4978
4979 WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
4980 err = wldev_iovar_setint_bsscfg(dev, "wsec",
4981 wsec_val, bssidx);
4982 }
4983 if (unlikely(err)) {
4984 WL_ERR(("error (%d)\n", err));
4985 return err;
4986 }
4987
4988 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4989 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
4990 sec->cipher_group = sme->crypto.cipher_group;
4991
4992 return err;
4993 }
4994
4995 #ifdef MFP
4996 static s32
4997 wl_cfg80211_set_mfp(struct bcm_cfg80211 *cfg,
4998 struct net_device *dev,
4999 struct cfg80211_connect_params *sme)
5000 {
5001 s32 mfp = WL_MFP_NONE;
5002 s32 current_mfp = WL_MFP_NONE;
5003 bcm_tlv_t *wpa2_ie;
5004 u8* rsn_cap = NULL;
5005 bool fw_support = false;
5006 int err, count = 0;
5007 u8 *eptr = NULL, *ptr = NULL;
5008 u8* group_mgmt_cs = NULL;
5009 wpa_pmkid_list_t* pmkid = NULL;
5010
5011 if (!sme) {
5012 /* No connection params from userspace, Do nothing. */
5013 return 0;
5014 }
5015
5016 /* Check fw support and retreive current mfp val */
5017 err = wldev_iovar_getint(dev, "mfp", &current_mfp);
5018 if (!err) {
5019 fw_support = true;
5020 }
5021
5022 /* Parse the wpa2ie to decode the MFP capablity */
5023 if (((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
5024 DOT11_MNG_RSN_ID)) != NULL) &&
5025 (wl_cfg80211_get_rsn_capa(wpa2_ie, &rsn_cap) == 0)) {
5026 /* Check for MFP cap in the RSN capability field */
5027 if (rsn_cap[0] & RSN_CAP_MFPR) {
5028 mfp = WL_MFP_REQUIRED;
5029 } else if (rsn_cap[0] & RSN_CAP_MFPC) {
5030 mfp = WL_MFP_CAPABLE;
5031 }
5032
5033 /*
5034 * eptr --> end/last byte addr of wpa2_ie
5035 * ptr --> to keep track of current/required byte addr
5036 */
5037 eptr = (u8*)wpa2_ie + (wpa2_ie->len + TLV_HDR_LEN);
5038 /* pointing ptr to the next byte after rns_cap */
5039 ptr = (u8*)rsn_cap + RSN_CAP_LEN;
5040 if (mfp && (eptr - ptr) >= WPA2_PMKID_COUNT_LEN) {
5041 /* pmkid now to point to 1st byte addr of pmkid in wpa2_ie */
5042 pmkid = (wpa_pmkid_list_t*)ptr;
5043 count = pmkid->count.low | (pmkid->count.high << 8);
5044 /* ptr now to point to last byte addr of pmkid */
5045 ptr = (u8*)pmkid + (count * WPA2_PMKID_LEN
5046 + WPA2_PMKID_COUNT_LEN);
5047 if ((eptr - ptr) >= WPA_SUITE_LEN) {
5048 /* group_mgmt_cs now to point to first byte addr of bip */
5049 group_mgmt_cs = ptr;
5050 }
5051 }
5052 }
5053
5054 WL_DBG((" mfp:%d wpa2_ie ptr:%p rsn_cap 0x%x%x fw mfp support:%d\n",
5055 mfp, wpa2_ie, rsn_cap[0], rsn_cap[1], fw_support));
5056
5057 if (fw_support == false) {
5058 if (mfp == WL_MFP_REQUIRED) {
5059 /* if mfp > 0, mfp capability set in wpa ie, but
5060 * FW indicated error for mfp. Propagate the error up.
5061 */
5062 WL_ERR(("mfp capability found in wpaie. But fw doesn't "
5063 "seem to support MFP\n"));
5064 return -EINVAL;
5065 } else {
5066 /* Firmware doesn't support mfp. But since connection request
5067 * is for non-mfp case, don't bother.
5068 */
5069 return 0;
5070 }
5071 } else if (mfp != current_mfp) {
5072 err = wldev_iovar_setint(dev, "mfp", mfp);
5073 if (unlikely(err)) {
5074 WL_ERR(("mfp (%d) set failed ret:%d \n", mfp, err));
5075 return err;
5076 }
5077 WL_DBG(("mfp set to 0x%x \n", mfp));
5078 }
5079
5080 if (group_mgmt_cs && bcmp((const uint8 *)WPA2_OUI,
5081 group_mgmt_cs, (WPA_SUITE_LEN - 1)) == 0) {
5082 WL_DBG(("BIP is found\n"));
5083 err = wldev_iovar_setbuf(dev, "bip",
5084 group_mgmt_cs, WPA_SUITE_LEN, cfg->ioctl_buf,
5085 WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
5086 /*
5087 * Dont return failure for unsupported cases
5088 * of bip iovar for backward compatibility
5089 */
5090 if (err != BCME_UNSUPPORTED && err < 0) {
5091 WL_ERR(("bip set error (%d)\n", err));
5092 return err;
5093 }
5094 }
5095
5096 return 0;
5097 }
5098 #endif /* MFP */
5099
5100 static s32
5101 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
5102 {
5103 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5104 struct wl_security *sec;
5105 s32 val = 0;
5106 s32 err = 0;
5107 s32 bssidx;
5108
5109 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5110 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5111 return BCME_ERROR;
5112 }
5113
5114 if (sme->crypto.n_akm_suites) {
5115 err = wldev_iovar_getint(dev, "wpa_auth", &val);
5116 if (unlikely(err)) {
5117 WL_ERR(("could not get wpa_auth (%d)\n", err));
5118 return err;
5119 }
5120 if (val & (WPA_AUTH_PSK |
5121 WPA_AUTH_UNSPECIFIED)) {
5122 switch (sme->crypto.akm_suites[0]) {
5123 case WLAN_AKM_SUITE_8021X:
5124 val = WPA_AUTH_UNSPECIFIED;
5125 break;
5126 case WLAN_AKM_SUITE_PSK:
5127 val = WPA_AUTH_PSK;
5128 break;
5129 default:
5130 WL_ERR(("invalid akm suite (0x%x)\n",
5131 sme->crypto.akm_suites[0]));
5132 return -EINVAL;
5133 }
5134 } else if (val & (WPA2_AUTH_PSK |
5135 WPA2_AUTH_UNSPECIFIED)) {
5136 switch (sme->crypto.akm_suites[0]) {
5137 case WLAN_AKM_SUITE_8021X:
5138 val = WPA2_AUTH_UNSPECIFIED;
5139 break;
5140 #ifdef MFP
5141 #ifdef CUSTOMER_HW6
5142 case WL_AKM_SUITE_SHA256_1X:
5143 if (wl_customer6_legacy_chip_check(cfg, dev)) {
5144 val = WPA2_AUTH_UNSPECIFIED;
5145 } else {
5146 val = WPA2_AUTH_1X_SHA256;
5147 }
5148 break;
5149 case WL_AKM_SUITE_SHA256_PSK:
5150 if (wl_customer6_legacy_chip_check(cfg, dev)) {
5151 val = WPA2_AUTH_PSK;
5152 } else {
5153 val = WPA2_AUTH_PSK_SHA256;
5154 }
5155 break;
5156 #else
5157 case WL_AKM_SUITE_SHA256_1X:
5158 val = WPA2_AUTH_1X_SHA256;
5159 break;
5160 case WL_AKM_SUITE_SHA256_PSK:
5161 val = WPA2_AUTH_PSK_SHA256;
5162 break;
5163 #endif /* CUSTOMER_HW6 */
5164 #endif /* MFP */
5165 case WLAN_AKM_SUITE_PSK:
5166 val = WPA2_AUTH_PSK;
5167 break;
5168 default:
5169 WL_ERR(("invalid akm suite (0x%x)\n",
5170 sme->crypto.akm_suites[0]));
5171 return -EINVAL;
5172 }
5173 }
5174
5175 #ifdef MFP
5176 if ((err = wl_cfg80211_set_mfp(cfg, dev, sme)) < 0) {
5177 WL_ERR(("MFP set failed err:%d\n", err));
5178 return -EINVAL;
5179 }
5180 #endif /* MFP */
5181
5182 WL_DBG(("setting wpa_auth to 0x%x\n", val));
5183 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
5184 if (unlikely(err)) {
5185 WL_ERR(("could not set wpa_auth (0x%x)\n", err));
5186 return err;
5187 }
5188 }
5189 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
5190 sec->wpa_auth = sme->crypto.akm_suites[0];
5191
5192 return err;
5193 }
5194
5195 static s32
5196 wl_set_set_sharedkey(struct net_device *dev,
5197 struct cfg80211_connect_params *sme)
5198 {
5199 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5200 struct wl_security *sec;
5201 struct wl_wsec_key key;
5202 s32 val;
5203 s32 err = 0;
5204 s32 bssidx;
5205
5206 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5207 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5208 return BCME_ERROR;
5209 }
5210
5211 WL_DBG(("key len (%d)\n", sme->key_len));
5212 if (sme->key_len) {
5213 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
5214 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
5215 sec->wpa_versions, sec->cipher_pairwise));
5216 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
5217 NL80211_WPA_VERSION_2)) &&
5218 (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
5219 WLAN_CIPHER_SUITE_WEP104)))
5220 {
5221 memset(&key, 0, sizeof(key));
5222 key.len = (u32) sme->key_len;
5223 key.index = (u32) sme->key_idx;
5224 if (unlikely(key.len > sizeof(key.data))) {
5225 WL_ERR(("Too long key length (%u)\n", key.len));
5226 return -EINVAL;
5227 }
5228 memcpy(key.data, sme->key, key.len);
5229 key.flags = WL_PRIMARY_KEY;
5230 switch (sec->cipher_pairwise) {
5231 case WLAN_CIPHER_SUITE_WEP40:
5232 key.algo = CRYPTO_ALGO_WEP1;
5233 break;
5234 case WLAN_CIPHER_SUITE_WEP104:
5235 key.algo = CRYPTO_ALGO_WEP128;
5236 break;
5237 default:
5238 WL_ERR(("Invalid algorithm (%d)\n",
5239 sme->crypto.ciphers_pairwise[0]));
5240 return -EINVAL;
5241 }
5242 /* Set the new key/index */
5243 WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
5244 key.len, key.index, key.algo));
5245 WL_DBG(("key \"%s\"\n", key.data));
5246 swap_key_from_BE(&key);
5247 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
5248 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5249 if (unlikely(err)) {
5250 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
5251 return err;
5252 }
5253 if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
5254 WL_DBG(("set auth_type to shared key\n"));
5255 val = WL_AUTH_SHARED_KEY; /* shared key */
5256 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
5257 if (unlikely(err)) {
5258 WL_ERR(("set auth failed (%d)\n", err));
5259 return err;
5260 }
5261 }
5262 }
5263 }
5264 return err;
5265 }
5266
5267 #if defined(ESCAN_RESULT_PATCH)
5268 static u8 connect_req_bssid[6];
5269 static u8 broad_bssid[6];
5270 #endif /* ESCAN_RESULT_PATCH */
5271
5272
5273
5274 #if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
5275 static bool wl_get_chan_isvht80(struct net_device *net, dhd_pub_t *dhd)
5276 {
5277 u32 chanspec = 0;
5278 bool isvht80 = 0;
5279
5280 if (wldev_iovar_getint(net, "chanspec", (s32 *)&chanspec) == BCME_OK)
5281 chanspec = wl_chspec_driver_to_host(chanspec);
5282
5283 isvht80 = chanspec & WL_CHANSPEC_BW_80;
5284 WL_INFORM(("%s: chanspec(%x:%d)\n", __FUNCTION__, chanspec, isvht80));
5285
5286 return isvht80;
5287 }
5288 #endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
5289
5290 int wl_cfg80211_cleanup_mismatch_status(struct net_device *dev, struct bcm_cfg80211 *cfg,
5291 bool disassociate)
5292 {
5293 scb_val_t scbval;
5294 int err = TRUE;
5295 int wait_cnt;
5296
5297 if (disassociate) {
5298 WL_ERR(("Disassociate previous connection!\n"));
5299 wl_set_drv_status(cfg, DISCONNECTING, dev);
5300 scbval.val = DOT11_RC_DISASSOC_LEAVING;
5301 scbval.val = htod32(scbval.val);
5302
5303 err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
5304 sizeof(scb_val_t));
5305 if (unlikely(err)) {
5306 wl_clr_drv_status(cfg, DISCONNECTING, dev);
5307 WL_ERR(("error (%d)\n", err));
5308 return err;
5309 }
5310 wait_cnt = 500/10;
5311 } else {
5312 wait_cnt = 200/10;
5313 WL_ERR(("Waiting for previous DISCONNECTING status!\n"));
5314 if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
5315 wl_clr_drv_status(cfg, DISCONNECTING, dev);
5316 }
5317 }
5318
5319 while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
5320 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
5321 wait_cnt));
5322 wait_cnt--;
5323 OSL_SLEEP(10);
5324 }
5325
5326 if (wait_cnt == 0) {
5327 WL_ERR(("DISCONNECING clean up failed!\n"));
5328 return BCME_NOTREADY;
5329 }
5330 return BCME_OK;
5331 }
5332
5333 #define MAX_SCAN_ABORT_WAIT_CNT 20
5334 #define WAIT_SCAN_ABORT_OSL_SLEEP_TIME 10
5335
5336 static s32
5337 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
5338 struct cfg80211_connect_params *sme)
5339 {
5340 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5341 struct ieee80211_channel *chan = sme->channel;
5342 wl_extjoin_params_t *ext_join_params;
5343 struct wl_join_params join_params;
5344 size_t join_params_size;
5345 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
5346 s32 err = 0;
5347 wpa_ie_fixed_t *wpa_ie;
5348 bcm_tlv_t *wpa2_ie;
5349 u8* wpaie = 0;
5350 u32 wpaie_len = 0;
5351 u32 chan_cnt = 0;
5352 struct ether_addr bssid;
5353 s32 bssidx = -1;
5354 #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
5355 int wait_cnt;
5356 #endif
5357
5358 WL_DBG(("In\n"));
5359 BCM_REFERENCE(dhdp);
5360
5361 #ifdef WLMESH
5362 wl_config_ifmode(cfg, dev, dev->ieee80211_ptr->iftype);
5363 #endif
5364 #if defined(SUPPORT_RANDOM_MAC_SCAN)
5365 wl_cfg80211_set_random_mac(dev, FALSE);
5366 #endif /* SUPPORT_RANDOM_MAC_SCAN */
5367
5368 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
5369 if (sme->channel_hint) {
5370 chan = sme->channel_hint;
5371 WL_DBG(("channel_hint (%d), channel_hint center_freq (%d)\n",
5372 ieee80211_frequency_to_channel(sme->channel_hint->center_freq),
5373 sme->channel_hint->center_freq));
5374 }
5375 if (sme->bssid_hint) {
5376 sme->bssid = sme->bssid_hint;
5377 WL_DBG(("bssid_hint "MACDBG" \n", MAC2STRDBG(sme->bssid_hint)));
5378 }
5379 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
5380
5381 if (unlikely(!sme->ssid)) {
5382 WL_ERR(("Invalid ssid\n"));
5383 return -EOPNOTSUPP;
5384 }
5385
5386 if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
5387 WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
5388 sme->ssid, sme->ssid_len));
5389 return -EINVAL;
5390 }
5391
5392 WL_DBG(("SME IE : len=%zu\n", sme->ie_len));
5393 if (sme->ie != NULL && sme->ie_len > 0 && (wl_dbg_level & WL_DBG_DBG)) {
5394 prhex(NULL, (uchar *)sme->ie, sme->ie_len);
5395 }
5396
5397 RETURN_EIO_IF_NOT_UP(cfg);
5398
5399 /*
5400 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
5401 */
5402 #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
5403 if (cfg->scan_request) {
5404 WL_TRACE_HW4(("Aborting the scan! \n"));
5405 wl_cfg80211_scan_abort(cfg);
5406 wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
5407 while (wl_get_drv_status(cfg, SCANNING, dev) && wait_cnt) {
5408 WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
5409 wait_cnt--;
5410 OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
5411 }
5412 if (wl_get_drv_status(cfg, SCANNING, dev)) {
5413 wl_notify_escan_complete(cfg, dev, true, true);
5414 }
5415 }
5416 #endif
5417 #ifdef WL_SCHED_SCAN
5418 /* Locks are taken in wl_cfg80211_sched_scan_stop()
5419 * A start scan occuring during connect is unlikely
5420 */
5421 if (cfg->sched_scan_req) {
5422 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
5423 wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg), 0);
5424 #else
5425 wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg));
5426 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
5427 }
5428 #endif
5429 #if defined(ESCAN_RESULT_PATCH)
5430 if (sme->bssid)
5431 memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
5432 else
5433 bzero(connect_req_bssid, ETHER_ADDR_LEN);
5434 bzero(broad_bssid, ETHER_ADDR_LEN);
5435 #endif
5436 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5437 maxrxpktglom = 0;
5438 #endif
5439 if (wl_get_drv_status(cfg, CONNECTING, dev) || wl_get_drv_status(cfg, CONNECTED, dev)) {
5440 /* set nested connect bit to identify the context */
5441 wl_set_drv_status(cfg, NESTED_CONNECT, dev);
5442 /* DHD prev status is CONNECTING/CONNECTED */
5443 err = wl_cfg80211_cleanup_mismatch_status(dev, cfg, TRUE);
5444 } else if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
5445 /* DHD prev status is DISCONNECTING */
5446 err = wl_cfg80211_cleanup_mismatch_status(dev, cfg, FALSE);
5447 } else if (!wl_get_drv_status(cfg, CONNECTED, dev)) {
5448 /* DHD previous status is not connected and FW connected */
5449 if (wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) == 0) {
5450 /* set nested connect bit to identify the context */
5451 wl_set_drv_status(cfg, NESTED_CONNECT, dev);
5452 err = wl_cfg80211_cleanup_mismatch_status(dev, cfg, TRUE);
5453 }
5454 }
5455
5456 /* 'connect' request received */
5457 wl_set_drv_status(cfg, CONNECTING, dev);
5458 /* clear nested connect bit on proceeding for connection */
5459 wl_clr_drv_status(cfg, NESTED_CONNECT, dev);
5460
5461 /* Clean BSSID */
5462 bzero(&bssid, sizeof(bssid));
5463 if (!wl_get_drv_status(cfg, DISCONNECTING, dev))
5464 wl_update_prof(cfg, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
5465
5466 if (p2p_is_on(cfg) && (dev != bcmcfg_to_prmry_ndev(cfg))) {
5467 /* we only allow to connect using virtual interface in case of P2P */
5468 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5469 WL_ERR(("Find p2p index from wdev(%p) failed\n",
5470 dev->ieee80211_ptr));
5471 err = BCME_ERROR;
5472 goto exit;
5473 }
5474 wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
5475 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
5476 } else if (dev == bcmcfg_to_prmry_ndev(cfg)) {
5477 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5478 WL_ERR(("Find wlan index from wdev(%p) failed\n", dev->ieee80211_ptr));
5479 err = BCME_ERROR;
5480 goto exit;
5481 }
5482
5483 /* find the RSN_IE */
5484 if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
5485 DOT11_MNG_RSN_ID)) != NULL) {
5486 WL_DBG((" WPA2 IE is found\n"));
5487 }
5488 /* find the WPA_IE */
5489 if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
5490 sme->ie_len)) != NULL) {
5491 WL_DBG((" WPA IE is found\n"));
5492 }
5493 if (wpa_ie != NULL || wpa2_ie != NULL) {
5494 wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
5495 wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
5496 wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
5497 err = wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
5498 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
5499 if (unlikely(err)) {
5500 WL_ERR(("wpaie set error (%d)\n", err));
5501 goto exit;
5502 }
5503 } else {
5504 err = wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
5505 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
5506 if (unlikely(err)) {
5507 WL_ERR(("wpaie set error (%d)\n", err));
5508 goto exit;
5509 }
5510 }
5511 err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
5512 VNDR_IE_ASSOCREQ_FLAG, (const u8 *)sme->ie, sme->ie_len);
5513 if (unlikely(err)) {
5514 goto exit;
5515 }
5516 }
5517
5518 if (chan) {
5519 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
5520 chan_cnt = 1;
5521 WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg->channel,
5522 chan->center_freq, chan_cnt));
5523 } else {
5524 WL_DBG(("No channel info from user space\n"));
5525 cfg->channel = 0;
5526 }
5527
5528
5529 WL_DBG(("3. set wpa version \n"));
5530
5531 err = wl_set_wpa_version(dev, sme);
5532 if (unlikely(err)) {
5533 WL_ERR(("Invalid wpa_version\n"));
5534 goto exit;
5535 }
5536 err = wl_set_auth_type(dev, sme);
5537 if (unlikely(err)) {
5538 WL_ERR(("Invalid auth type\n"));
5539 goto exit;
5540 }
5541
5542 err = wl_set_set_cipher(dev, sme);
5543 if (unlikely(err)) {
5544 WL_ERR(("Invalid ciper\n"));
5545 goto exit;
5546 }
5547
5548 err = wl_set_key_mgmt(dev, sme);
5549 if (unlikely(err)) {
5550 WL_ERR(("Invalid key mgmt\n"));
5551 goto exit;
5552 }
5553
5554 err = wl_set_set_sharedkey(dev, sme);
5555 if (unlikely(err)) {
5556 WL_ERR(("Invalid shared key\n"));
5557 goto exit;
5558 }
5559
5560 /*
5561 * Join with specific BSSID and cached SSID
5562 * If SSID is zero join based on BSSID only
5563 */
5564 join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
5565 chan_cnt * sizeof(chanspec_t);
5566 ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
5567 if (ext_join_params == NULL) {
5568 err = -ENOMEM;
5569 wl_clr_drv_status(cfg, CONNECTING, dev);
5570 goto exit;
5571 }
5572 ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
5573 memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
5574 wl_update_prof(cfg, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
5575 ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
5576 /* increate dwell time to receive probe response or detect Beacon
5577 * from target AP at a noisy air only during connect command
5578 */
5579 ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
5580 ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
5581 /* Set up join scan parameters */
5582 ext_join_params->scan.scan_type = -1;
5583 ext_join_params->scan.nprobes = chan_cnt ?
5584 (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
5585 ext_join_params->scan.home_time = -1;
5586
5587 if (sme->bssid)
5588 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
5589 else
5590 memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
5591 ext_join_params->assoc.chanspec_num = chan_cnt;
5592 if (chan_cnt) {
5593 if (cfg->channel) {
5594 /*
5595 * Use the channel provided by userspace
5596 */
5597 u16 channel, band, bw, ctl_sb;
5598 chanspec_t chspec;
5599 channel = cfg->channel;
5600 band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
5601 : WL_CHANSPEC_BAND_5G;
5602
5603 /* Get min_bw set for the interface */
5604 bw = wl_cfg80211_ulb_get_min_bw_chspec(cfg, dev->ieee80211_ptr, bssidx);
5605 if (bw == INVCHANSPEC) {
5606 WL_ERR(("Invalid chanspec \n"));
5607 kfree(ext_join_params);
5608 err = BCME_ERROR;
5609 goto exit;
5610 }
5611
5612 ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
5613 chspec = (channel | band | bw | ctl_sb);
5614 ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
5615 ext_join_params->assoc.chanspec_list[0] |= chspec;
5616 ext_join_params->assoc.chanspec_list[0] =
5617 wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
5618 }
5619 }
5620 ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
5621 if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
5622 WL_INFORM(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
5623 ext_join_params->ssid.SSID_len));
5624 }
5625
5626 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5627 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5628 kfree(ext_join_params);
5629 err = BCME_ERROR;
5630 goto exit;
5631 }
5632 #if defined(CUSTOMER_HW2)
5633 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
5634 #endif /* BCMDONGLEHOST && CUSTOMER_HW2 */
5635 #ifdef WL_EXT_IAPSTA
5636 wl_ext_iapsta_disconnect_sta(dev, cfg->channel);
5637 #endif
5638 err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
5639 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5640
5641 if (cfg->rcc_enabled) {
5642 printf("Connecting with " MACDBG " ssid \"%s\", len (%d) with rcc channels \n\n",
5643 MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
5644 ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len);
5645 } else {
5646 printf("Connecting with " MACDBG " ssid \"%s\", len (%d) channel=%d\n\n",
5647 MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
5648 ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, cfg->channel);
5649 }
5650
5651 kfree(ext_join_params);
5652 if (err) {
5653 wl_clr_drv_status(cfg, CONNECTING, dev);
5654 if (err == BCME_UNSUPPORTED) {
5655 WL_DBG(("join iovar is not supported\n"));
5656 goto set_ssid;
5657 } else {
5658 WL_ERR(("error (%d)\n", err));
5659 goto exit;
5660 }
5661 } else
5662 goto exit;
5663
5664 set_ssid:
5665 memset(&join_params, 0, sizeof(join_params));
5666 join_params_size = sizeof(join_params.ssid);
5667
5668 join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
5669 memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
5670 join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
5671 wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
5672 if (sme->bssid)
5673 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
5674 else
5675 memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
5676
5677 if (wl_ch_to_chanspec(dev, cfg->channel, &join_params, &join_params_size) < 0) {
5678 WL_ERR(("Invalid chanspec\n"));
5679 return -EINVAL;
5680 }
5681
5682 WL_DBG(("join_param_size %zu\n", join_params_size));
5683
5684 if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
5685 WL_INFORM(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
5686 join_params.ssid.SSID_len));
5687 }
5688 err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params, join_params_size);
5689 exit:
5690 if (err) {
5691 WL_ERR(("error (%d)\n", err));
5692 wl_clr_drv_status(cfg, CONNECTING, dev);
5693 }
5694
5695 #ifdef WLTDLS
5696 /* disable TDLS if number of connected interfaces is >= 1 */
5697 wl_cfg80211_tdls_config(cfg, TDLS_STATE_CONNECT, false);
5698 #endif /* WLTDLS */
5699
5700 #ifdef DBG_PKT_MON
5701 if ((dev == bcmcfg_to_prmry_ndev(cfg)) && !err) {
5702 DHD_DBG_PKT_MON_START(dhdp);
5703 }
5704 #endif /* DBG_PKT_MON */
5705 return err;
5706 }
5707
5708 #define WAIT_FOR_DISCONNECT_MAX 10
5709 static void wl_cfg80211_wait_for_disconnection(struct bcm_cfg80211 *cfg, struct net_device *dev)
5710 {
5711 uint8 wait_cnt;
5712
5713 wait_cnt = WAIT_FOR_DISCONNECT_MAX;
5714 while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
5715 WL_DBG(("Waiting for disconnection, wait_cnt: %d\n", wait_cnt));
5716 wait_cnt--;
5717 OSL_SLEEP(50);
5718 }
5719
5720 return;
5721 }
5722
5723 static s32
5724 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
5725 u16 reason_code)
5726 {
5727 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5728 scb_val_t scbval;
5729 bool act = false;
5730 s32 err = 0;
5731 u8 *curbssid;
5732 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
5733 WL_ERR(("Reason %d\n", reason_code));
5734 RETURN_EIO_IF_NOT_UP(cfg);
5735 act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
5736 curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
5737
5738 BCM_REFERENCE(dhdp);
5739
5740 #ifdef ESCAN_RESULT_PATCH
5741 if (wl_get_drv_status(cfg, CONNECTING, dev) && curbssid &&
5742 (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0)) {
5743 WL_ERR(("Disconnecting from connecting device: " MACDBG "\n",
5744 MAC2STRDBG(curbssid)));
5745 act = true;
5746 }
5747 #endif /* ESCAN_RESULT_PATCH */
5748
5749 if (act) {
5750 #ifdef DBG_PKT_MON
5751 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
5752 DHD_DBG_PKT_MON_STOP(dhdp);
5753 }
5754 #endif /* DBG_PKT_MON */
5755 /*
5756 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
5757 */
5758 #if !defined(ESCAN_RESULT_PATCH)
5759 /* Let scan aborted by F/W */
5760 if (cfg->scan_request) {
5761 WL_TRACE_HW4(("Aborting the scan! \n"));
5762 wl_notify_escan_complete(cfg, dev, true, true);
5763 }
5764 #endif /* ESCAN_RESULT_PATCH */
5765 if (wl_get_drv_status(cfg, CONNECTING, dev) ||
5766 wl_get_drv_status(cfg, CONNECTED, dev)) {
5767 wl_set_drv_status(cfg, DISCONNECTING, dev);
5768 scbval.val = reason_code;
5769 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
5770 scbval.val = htod32(scbval.val);
5771 err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
5772 sizeof(scb_val_t));
5773 if (unlikely(err)) {
5774 wl_clr_drv_status(cfg, DISCONNECTING, dev);
5775 WL_ERR(("error (%d)\n", err));
5776 return err;
5777 }
5778 wl_cfg80211_wait_for_disconnection(cfg, dev);
5779 }
5780 }
5781 #ifdef CUSTOM_SET_CPUCORE
5782 /* set default cpucore */
5783 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
5784 dhdp->chan_isvht80 &= ~DHD_FLAG_STA_MODE;
5785 if (!(dhdp->chan_isvht80))
5786 dhd_set_cpucore(dhdp, FALSE);
5787 }
5788 #endif /* CUSTOM_SET_CPUCORE */
5789
5790 return err;
5791 }
5792
5793 static s32
5794 #if defined(WL_CFG80211_P2P_DEV_IF)
5795 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
5796 enum nl80211_tx_power_setting type, s32 mbm)
5797 #else
5798 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
5799 enum nl80211_tx_power_setting type, s32 dbm)
5800 #endif /* WL_CFG80211_P2P_DEV_IF */
5801 {
5802
5803 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5804 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5805 s32 err = 0;
5806 #if defined(WL_CFG80211_P2P_DEV_IF)
5807 s32 dbm = MBM_TO_DBM(mbm);
5808 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
5809 defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
5810 dbm = MBM_TO_DBM(dbm);
5811 #endif /* WL_CFG80211_P2P_DEV_IF */
5812
5813 RETURN_EIO_IF_NOT_UP(cfg);
5814 switch (type) {
5815 case NL80211_TX_POWER_AUTOMATIC:
5816 break;
5817 case NL80211_TX_POWER_LIMITED:
5818 if (dbm < 0) {
5819 WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
5820 return -EINVAL;
5821 }
5822 break;
5823 case NL80211_TX_POWER_FIXED:
5824 if (dbm < 0) {
5825 WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
5826 return -EINVAL;
5827 }
5828 break;
5829 }
5830
5831 err = wl_set_tx_power(ndev, type, dbm);
5832 if (unlikely(err)) {
5833 WL_ERR(("error (%d)\n", err));
5834 return err;
5835 }
5836
5837 cfg->conf->tx_power = dbm;
5838
5839 return err;
5840 }
5841
5842 static s32
5843 #if defined(WL_CFG80211_P2P_DEV_IF)
5844 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
5845 struct wireless_dev *wdev, s32 *dbm)
5846 #else
5847 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
5848 #endif /* WL_CFG80211_P2P_DEV_IF */
5849 {
5850 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5851 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5852 s32 err = 0;
5853
5854 RETURN_EIO_IF_NOT_UP(cfg);
5855 err = wl_get_tx_power(ndev, dbm);
5856 if (unlikely(err))
5857 WL_ERR(("error (%d)\n", err));
5858
5859 return err;
5860 }
5861
5862 static s32
5863 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
5864 u8 key_idx, bool unicast, bool multicast)
5865 {
5866 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5867 u32 index;
5868 s32 wsec;
5869 s32 err = 0;
5870 s32 bssidx;
5871
5872 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5873 WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
5874 return BCME_ERROR;
5875 }
5876
5877 WL_DBG(("key index (%d)\n", key_idx));
5878 RETURN_EIO_IF_NOT_UP(cfg);
5879 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
5880 if (unlikely(err)) {
5881 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
5882 return err;
5883 }
5884 if (wsec == WEP_ENABLED) {
5885 /* Just select a new current key */
5886 index = (u32) key_idx;
5887 index = htod32(index);
5888 err = wldev_ioctl_set(dev, WLC_SET_KEY_PRIMARY, &index,
5889 sizeof(index));
5890 if (unlikely(err)) {
5891 WL_ERR(("error (%d)\n", err));
5892 }
5893 }
5894 return err;
5895 }
5896
5897 static s32
5898 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
5899 u8 key_idx, const u8 *mac_addr, struct key_params *params)
5900 {
5901 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5902 struct wl_wsec_key key;
5903 s32 err = 0;
5904 s32 bssidx;
5905 s32 mode = wl_get_mode_by_netdev(cfg, dev);
5906
5907 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5908 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5909 return BCME_ERROR;
5910 }
5911 memset(&key, 0, sizeof(key));
5912 key.index = (u32) key_idx;
5913
5914 if (!ETHER_ISMULTI(mac_addr))
5915 memcpy((char *)&key.ea, (const void *)mac_addr, ETHER_ADDR_LEN);
5916 key.len = (u32) params->key_len;
5917
5918 /* check for key index change */
5919 if (key.len == 0) {
5920 /* key delete */
5921 swap_key_from_BE(&key);
5922 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
5923 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5924 if (unlikely(err)) {
5925 WL_ERR(("key delete error (%d)\n", err));
5926 return err;
5927 }
5928 } else {
5929 if (key.len > sizeof(key.data)) {
5930 WL_ERR(("Invalid key length (%d)\n", key.len));
5931 return -EINVAL;
5932 }
5933 WL_DBG(("Setting the key index %d\n", key.index));
5934 memcpy(key.data, params->key, key.len);
5935
5936 if ((mode == WL_MODE_BSS) &&
5937 (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
5938 u8 keybuf[8];
5939 memcpy(keybuf, &key.data[24], sizeof(keybuf));
5940 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
5941 memcpy(&key.data[16], keybuf, sizeof(keybuf));
5942 }
5943
5944 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
5945 if (params->seq && params->seq_len == 6) {
5946 /* rx iv */
5947 u8 *ivptr;
5948 ivptr = (u8 *) params->seq;
5949 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
5950 (ivptr[3] << 8) | ivptr[2];
5951 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
5952 key.iv_initialized = true;
5953 }
5954
5955 switch (params->cipher) {
5956 case WLAN_CIPHER_SUITE_WEP40:
5957 key.algo = CRYPTO_ALGO_WEP1;
5958 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
5959 break;
5960 case WLAN_CIPHER_SUITE_WEP104:
5961 key.algo = CRYPTO_ALGO_WEP128;
5962 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
5963 break;
5964 case WLAN_CIPHER_SUITE_TKIP:
5965 key.algo = CRYPTO_ALGO_TKIP;
5966 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
5967 break;
5968 case WLAN_CIPHER_SUITE_AES_CMAC:
5969 key.algo = CRYPTO_ALGO_AES_CCM;
5970 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
5971 break;
5972 case WLAN_CIPHER_SUITE_CCMP:
5973 key.algo = CRYPTO_ALGO_AES_CCM;
5974 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
5975 break;
5976 default:
5977 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
5978 return -EINVAL;
5979 }
5980 swap_key_from_BE(&key);
5981 /* need to guarantee EAPOL 4/4 send out before set key */
5982 dhd_wait_pend8021x(dev);
5983 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
5984 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5985 if (unlikely(err)) {
5986 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
5987 return err;
5988 }
5989 }
5990 return err;
5991 }
5992
5993 int
5994 wl_cfg80211_enable_roam_offload(struct net_device *dev, int enable)
5995 {
5996 int err;
5997 wl_eventmsg_buf_t ev_buf;
5998 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5999
6000 if (dev != bcmcfg_to_prmry_ndev(cfg)) {
6001 /* roam offload is only for the primary device */
6002 return -1;
6003 }
6004 err = wldev_iovar_setint(dev, "roam_offload", enable);
6005 if (err)
6006 return err;
6007
6008 bzero(&ev_buf, sizeof(wl_eventmsg_buf_t));
6009 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_PSK_SUP, !enable);
6010 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
6011 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
6012 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
6013 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
6014 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
6015 err = wl_cfg80211_apply_eventbuffer(dev, cfg, &ev_buf);
6016 if (!err) {
6017 cfg->roam_offload = enable;
6018 }
6019 return err;
6020 }
6021
6022 #if defined(WL_VIRTUAL_APSTA)
6023 int
6024 wl_cfg80211_interface_create(struct net_device *dev, char *name)
6025 {
6026 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6027 bcm_struct_cfgdev *new_cfgdev;
6028 #ifdef WLMESH
6029 char ifname[IFNAMSIZ];
6030 char iftype[IFNAMSIZ];
6031 enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
6032
6033 sscanf(name, "%s %s", ifname, iftype);
6034
6035 if (strnicmp(iftype, "AP", strlen("AP")) == 0) {
6036 iface_type = NL80211_IFTYPE_AP;
6037 }
6038 #endif
6039
6040 new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
6041 #ifdef WLMESH
6042 iface_type, NULL, ifname);
6043 #else
6044 NL80211_IFTYPE_STATION, NULL, name);
6045 #endif
6046 if (!new_cfgdev) {
6047 return BCME_ERROR;
6048 }
6049 else {
6050 WL_DBG(("Iface %s created successfuly\n", name));
6051 return BCME_OK;
6052 }
6053 }
6054
6055 int
6056 wl_cfg80211_interface_delete(struct net_device *dev, char *name)
6057 {
6058 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6059 struct net_info *iter, *next;
6060 int err = BCME_ERROR;
6061
6062 if (name == NULL) {
6063 return BCME_ERROR;
6064 }
6065
6066 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
6067 #pragma GCC diagnostic push
6068 #pragma GCC diagnostic ignored "-Wcast-qual"
6069 #endif
6070 for_each_ndev(cfg, iter, next) {
6071 if (iter->ndev) {
6072 if (strcmp(iter->ndev->name, name) == 0) {
6073 err = wl_cfg80211_del_iface(cfg->wdev->wiphy,
6074 ndev_to_cfgdev(iter->ndev));
6075 break;
6076 }
6077 }
6078 }
6079 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
6080 #pragma GCC diagnostic pop
6081 #endif
6082 if (!err) {
6083 WL_DBG(("Iface %s deleted successfuly", name));
6084 }
6085 return err;
6086 }
6087
6088 #if defined(PKT_FILTER_SUPPORT) && defined(APSTA_BLOCK_ARP_DURING_DHCP)
6089 void
6090 wl_cfg80211_block_arp(struct net_device *dev, int enable)
6091 {
6092 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6093 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
6094
6095 if (!dhd_pkt_filter_enable) {
6096 WL_INFORM(("Packet filter isn't enabled\n"));
6097 return;
6098 }
6099
6100 /* Block/Unblock ARP frames only if STA is connected to
6101 * the upstream AP in case of STA+SoftAP Concurrenct mode
6102 */
6103 if (!wl_get_drv_status(cfg, CONNECTED, dev)) {
6104 WL_INFORM(("STA doesn't connected to upstream AP\n"));
6105 return;
6106 }
6107
6108 if (enable) {
6109 WL_DBG(("Enable ARP Filter\n"));
6110 /* Add ARP filter */
6111 dhd_packet_filter_add_remove(dhdp, TRUE, DHD_BROADCAST_ARP_FILTER_NUM);
6112
6113 /* Enable ARP packet filter - blacklist */
6114 dhd_master_mode = FALSE;
6115 dhd_pktfilter_offload_enable(dhdp, dhdp->pktfilter[DHD_BROADCAST_ARP_FILTER_NUM],
6116 TRUE, dhd_master_mode);
6117 } else {
6118 WL_DBG(("Disable ARP Filter\n"));
6119 /* Disable ARP packet filter */
6120 dhd_master_mode = TRUE;
6121 dhd_pktfilter_offload_enable(dhdp, dhdp->pktfilter[DHD_BROADCAST_ARP_FILTER_NUM],
6122 FALSE, dhd_master_mode);
6123
6124 /* Delete ARP filter */
6125 dhd_packet_filter_add_remove(dhdp, FALSE, DHD_BROADCAST_ARP_FILTER_NUM);
6126 }
6127 }
6128 #endif /* PKT_FILTER_SUPPORT && APSTA_BLOCK_ARP_DURING_DHCP */
6129 #endif /* defined (WL_VIRTUAL_APSTA) */
6130
6131 static s32
6132 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
6133 u8 key_idx, bool pairwise, const u8 *mac_addr,
6134 struct key_params *params)
6135 {
6136 struct wl_wsec_key key;
6137 s32 val = 0;
6138 s32 wsec = 0;
6139 s32 err = 0;
6140 u8 keybuf[8];
6141 s32 bssidx = 0;
6142 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6143 s32 mode = wl_get_mode_by_netdev(cfg, dev);
6144 WL_DBG(("key index (%d)\n", key_idx));
6145 RETURN_EIO_IF_NOT_UP(cfg);
6146
6147 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
6148 WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
6149 return BCME_ERROR;
6150 }
6151
6152 if (mac_addr &&
6153 ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
6154 (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
6155 wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
6156 goto exit;
6157 }
6158 memset(&key, 0, sizeof(key));
6159 /* Clear any buffered wep key */
6160 memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
6161
6162 key.len = (u32) params->key_len;
6163 key.index = (u32) key_idx;
6164
6165 if (unlikely(key.len > sizeof(key.data))) {
6166 WL_ERR(("Too long key length (%u)\n", key.len));
6167 return -EINVAL;
6168 }
6169 memcpy(key.data, params->key, key.len);
6170
6171 key.flags = WL_PRIMARY_KEY;
6172 switch (params->cipher) {
6173 case WLAN_CIPHER_SUITE_WEP40:
6174 key.algo = CRYPTO_ALGO_WEP1;
6175 val = WEP_ENABLED;
6176 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
6177 break;
6178 case WLAN_CIPHER_SUITE_WEP104:
6179 key.algo = CRYPTO_ALGO_WEP128;
6180 val = WEP_ENABLED;
6181 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
6182 break;
6183 case WLAN_CIPHER_SUITE_TKIP:
6184 key.algo = CRYPTO_ALGO_TKIP;
6185 val = TKIP_ENABLED;
6186 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
6187 if (mode == WL_MODE_BSS) {
6188 bcopy(&key.data[24], keybuf, sizeof(keybuf));
6189 bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
6190 bcopy(keybuf, &key.data[16], sizeof(keybuf));
6191 }
6192 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6193 break;
6194 case WLAN_CIPHER_SUITE_AES_CMAC:
6195 key.algo = CRYPTO_ALGO_AES_CCM;
6196 val = AES_ENABLED;
6197 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
6198 break;
6199 case WLAN_CIPHER_SUITE_CCMP:
6200 key.algo = CRYPTO_ALGO_AES_CCM;
6201 val = AES_ENABLED;
6202 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
6203 break;
6204 default:
6205 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
6206 return -EINVAL;
6207 }
6208
6209 /* Set the new key/index */
6210 if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
6211 WL_ERR(("IBSS KEY setted\n"));
6212 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
6213 }
6214 swap_key_from_BE(&key);
6215 if ((params->cipher == WLAN_CIPHER_SUITE_WEP40) ||
6216 (params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
6217 /*
6218 * For AP role, since we are doing a wl down before bringing up AP,
6219 * the plumbed keys will be lost. So for AP once we bring up AP, we
6220 * need to plumb keys again. So buffer the keys for future use. This
6221 * is more like a WAR. If firmware later has the capability to do
6222 * interface upgrade without doing a "wl down" and "wl apsta 0", then
6223 * this will not be required.
6224 */
6225 WL_DBG(("Buffering WEP Keys \n"));
6226 memcpy(&cfg->wep_key, &key, sizeof(struct wl_wsec_key));
6227 }
6228 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
6229 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
6230 if (unlikely(err)) {
6231 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
6232 return err;
6233 }
6234
6235 exit:
6236 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
6237 if (unlikely(err)) {
6238 WL_ERR(("get wsec error (%d)\n", err));
6239 return err;
6240 }
6241
6242 wsec |= val;
6243 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
6244 if (unlikely(err)) {
6245 WL_ERR(("set wsec error (%d)\n", err));
6246 return err;
6247 }
6248
6249 return err;
6250 }
6251
6252 static s32
6253 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
6254 u8 key_idx, bool pairwise, const u8 *mac_addr)
6255 {
6256 struct wl_wsec_key key;
6257 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6258 s32 err = 0;
6259 s32 bssidx;
6260
6261 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
6262 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
6263 return BCME_ERROR;
6264 }
6265 WL_DBG(("Enter\n"));
6266
6267 #ifndef MFP
6268 if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
6269 return -EINVAL;
6270 #endif
6271
6272 RETURN_EIO_IF_NOT_UP(cfg);
6273 memset(&key, 0, sizeof(key));
6274
6275 key.flags = WL_PRIMARY_KEY;
6276 key.algo = CRYPTO_ALGO_OFF;
6277 key.index = (u32) key_idx;
6278
6279 WL_DBG(("key index (%d)\n", key_idx));
6280 /* Set the new key/index */
6281 swap_key_from_BE(&key);
6282 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
6283 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
6284 if (unlikely(err)) {
6285 if (err == -EINVAL) {
6286 if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
6287 /* we ignore this key index in this case */
6288 WL_DBG(("invalid key index (%d)\n", key_idx));
6289 }
6290 } else {
6291 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
6292 }
6293 return err;
6294 }
6295 return err;
6296 }
6297
6298 static s32
6299 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
6300 u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
6301 void (*callback) (void *cookie, struct key_params * params))
6302 {
6303 struct key_params params;
6304 struct wl_wsec_key key;
6305 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6306 struct wl_security *sec;
6307 s32 wsec;
6308 s32 err = 0;
6309 s32 bssidx;
6310
6311 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
6312 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
6313 return BCME_ERROR;
6314 }
6315 WL_DBG(("key index (%d)\n", key_idx));
6316 RETURN_EIO_IF_NOT_UP(cfg);
6317 memset(&key, 0, sizeof(key));
6318 key.index = key_idx;
6319 swap_key_to_BE(&key);
6320 memset(&params, 0, sizeof(params));
6321 params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
6322 memcpy((void *)params.key, key.data, params.key_len);
6323
6324 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
6325 if (unlikely(err)) {
6326 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
6327 return err;
6328 }
6329 switch (WSEC_ENABLED(wsec)) {
6330 case WEP_ENABLED:
6331 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
6332 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
6333 params.cipher = WLAN_CIPHER_SUITE_WEP40;
6334 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
6335 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
6336 params.cipher = WLAN_CIPHER_SUITE_WEP104;
6337 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
6338 }
6339 break;
6340 case TKIP_ENABLED:
6341 params.cipher = WLAN_CIPHER_SUITE_TKIP;
6342 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6343 break;
6344 case AES_ENABLED:
6345 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
6346 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
6347 break;
6348 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
6349 /* to connect to mixed mode AP */
6350 case (AES_ENABLED | TKIP_ENABLED): /* TKIP CCMP */
6351 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
6352 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6353 break;
6354 #endif
6355 default:
6356 WL_ERR(("Invalid algo (0x%x)\n", wsec));
6357 return -EINVAL;
6358 }
6359
6360 callback(cookie, &params);
6361 return err;
6362 }
6363
6364 static s32
6365 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
6366 struct net_device *dev, u8 key_idx)
6367 {
6368 #ifdef MFP
6369 return 0;
6370 #else
6371 WL_INFORM(("Not supported\n"));
6372 return -EOPNOTSUPP;
6373 #endif /* MFP */
6374 }
6375
6376 #if defined(RSSIAVG)
6377 static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
6378 static wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
6379 #endif
6380 #if defined(BSSCACHE)
6381 static wl_bss_cache_ctrl_t g_bss_cache_ctrl;
6382 #endif
6383
6384 static s32
6385 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
6386 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6387 const u8 *mac, struct station_info *sinfo)
6388 #else
6389 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6390 u8 *mac, struct station_info *sinfo)
6391 #endif
6392 {
6393 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6394 scb_val_t scb_val;
6395 s32 rssi;
6396 s32 rate;
6397 s32 err = 0;
6398 sta_info_t *sta;
6399 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
6400 s8 eabuf[ETHER_ADDR_STR_LEN];
6401 #endif
6402 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
6403 bool fw_assoc_state = FALSE;
6404 u32 dhd_assoc_state = 0;
6405 static int err_cnt = 0;
6406
6407 RETURN_EIO_IF_NOT_UP(cfg);
6408 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
6409 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
6410 ETHER_ADDR_LEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
6411 if (err < 0) {
6412 WL_ERR(("GET STA INFO failed, %d\n", err));
6413 return err;
6414 }
6415 sinfo->filled = STA_INFO_BIT(INFO_INACTIVE_TIME);
6416 sta = (sta_info_t *)cfg->ioctl_buf;
6417 sta->len = dtoh16(sta->len);
6418 sta->cap = dtoh16(sta->cap);
6419 sta->flags = dtoh32(sta->flags);
6420 sta->idle = dtoh32(sta->idle);
6421 sta->in = dtoh32(sta->in);
6422 sinfo->inactive_time = sta->idle * 1000;
6423 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
6424 if (sta->flags & WL_STA_ASSOC) {
6425 sinfo->filled |= STA_INFO_BIT(INFO_CONNECTED_TIME);
6426 sinfo->connected_time = sta->in;
6427 }
6428 WL_INFORM(("STA %s : idle time : %d sec, connected time :%d ms\n",
6429 bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
6430 sta->idle * 1000));
6431 #endif
6432 } else if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_BSS ||
6433 wl_get_mode_by_netdev(cfg, dev) == WL_MODE_IBSS) {
6434 get_pktcnt_t pktcnt;
6435 #ifdef DHD_SUPPORT_IF_CNTS
6436 wl_if_stats_t *if_stats = NULL;
6437 #endif /* DHD_SUPPORT_IF_CNTS */
6438 u8 *curmacp;
6439
6440 if (cfg->roam_offload) {
6441 struct ether_addr bssid;
6442 memset(&bssid, 0, sizeof(bssid));
6443 err = wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
6444 if (err) {
6445 WL_ERR(("Failed to get current BSSID\n"));
6446 } else {
6447 if (memcmp(mac, &bssid.octet, ETHER_ADDR_LEN) != 0) {
6448 /* roaming is detected */
6449 err = wl_cfg80211_delayed_roam(cfg, dev, &bssid);
6450 if (err)
6451 WL_ERR(("Failed to handle the delayed roam, "
6452 "err=%d", err));
6453 mac = (u8 *)bssid.octet;
6454 }
6455 }
6456 }
6457 dhd_assoc_state = wl_get_drv_status(cfg, CONNECTED, dev);
6458 DHD_OS_WAKE_LOCK(dhd);
6459 fw_assoc_state = dhd_is_associated(dhd, 0, &err);
6460 DHD_OS_WAKE_UNLOCK(dhd);
6461 if (!dhd_assoc_state || !fw_assoc_state) {
6462 WL_ERR(("NOT assoc\n"));
6463 if (err == -ENODATA)
6464 return err;
6465 if (!dhd_assoc_state) {
6466 WL_TRACE_HW4(("drv state is not connected \n"));
6467 }
6468 if (!fw_assoc_state) {
6469 WL_TRACE_HW4(("fw state is not associated \n"));
6470 }
6471 /* Disconnect due to fw is not associated for FW_ASSOC_WATCHDOG_TIME ms.
6472 * 'err == 0' of dhd_is_associated() and '!fw_assoc_state'
6473 * means that BSSID is null.
6474 */
6475 if (dhd_assoc_state && !fw_assoc_state && !err) {
6476 if (!fw_assoc_watchdog_started) {
6477 fw_assoc_watchdog_ms = OSL_SYSUPTIME();
6478 fw_assoc_watchdog_started = TRUE;
6479 WL_TRACE_HW4(("fw_assoc_watchdog_started \n"));
6480 } else {
6481 if (OSL_SYSUPTIME() - fw_assoc_watchdog_ms >
6482 FW_ASSOC_WATCHDOG_TIME) {
6483 fw_assoc_watchdog_started = FALSE;
6484 err = -ENODEV;
6485 WL_TRACE_HW4(("fw is not associated for %d ms \n",
6486 (OSL_SYSUPTIME() - fw_assoc_watchdog_ms)));
6487 goto get_station_err;
6488 }
6489 }
6490 }
6491 err = -ENODEV;
6492 return err;
6493 }
6494 fw_assoc_watchdog_started = FALSE;
6495 curmacp = wl_read_prof(cfg, dev, WL_PROF_BSSID);
6496 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
6497 WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
6498 MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
6499 }
6500
6501 /* Report the current tx rate */
6502 rate = 0;
6503 err = wldev_ioctl_get(dev, WLC_GET_RATE, &rate, sizeof(rate));
6504 if (err) {
6505 WL_ERR(("Could not get rate (%d)\n", err));
6506 } else {
6507 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
6508 int rxpktglom;
6509 #endif
6510 rate = dtoh32(rate);
6511 sinfo->filled |= STA_INFO_BIT(INFO_TX_BITRATE);
6512 sinfo->txrate.legacy = rate * 5;
6513 WL_DBG(("Rate %d Mbps\n", (rate / 2)));
6514 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
6515 rxpktglom = ((rate/2) > 150) ? 20 : 10;
6516
6517 if (maxrxpktglom != rxpktglom) {
6518 maxrxpktglom = rxpktglom;
6519 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
6520 maxrxpktglom));
6521 err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
6522 (char*)&maxrxpktglom, 4, cfg->ioctl_buf,
6523 WLC_IOCTL_MAXLEN, NULL);
6524 if (err < 0) {
6525 WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
6526 }
6527 }
6528 #endif
6529 }
6530
6531 memset(&scb_val, 0, sizeof(scb_val));
6532 scb_val.val = 0;
6533 err = wldev_ioctl_get(dev, WLC_GET_RSSI, &scb_val,
6534 sizeof(scb_val_t));
6535 if (err) {
6536 WL_ERR(("Could not get rssi (%d)\n", err));
6537 goto get_station_err;
6538 }
6539 rssi = dtoh32(scb_val.val);
6540 #if defined(RSSIAVG)
6541 err = wl_update_connected_rssi_cache(dev, &g_connected_rssi_cache_ctrl, &rssi);
6542 if (err) {
6543 WL_ERR(("Could not get rssi (%d)\n", err));
6544 goto get_station_err;
6545 }
6546 wl_delete_dirty_rssi_cache(&g_connected_rssi_cache_ctrl);
6547 wl_reset_rssi_cache(&g_connected_rssi_cache_ctrl);
6548 #endif
6549 #if defined(RSSIOFFSET)
6550 rssi = wl_update_rssi_offset(dev, rssi);
6551 #endif
6552 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
6553 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
6554 rssi = MIN(rssi, RSSI_MAXVAL);
6555 #endif
6556 sinfo->filled |= STA_INFO_BIT(INFO_SIGNAL);
6557 sinfo->signal = rssi;
6558 WL_DBG(("RSSI %d dBm\n", rssi));
6559
6560 #ifdef DHD_SUPPORT_IF_CNTS
6561 if ((if_stats = kmalloc(sizeof(*if_stats), GFP_KERNEL)) == NULL) {
6562 WL_ERR(("%s(%d): kmalloc failed\n", __FUNCTION__, __LINE__));
6563 goto error;
6564 }
6565 memset(if_stats, 0, sizeof(*if_stats));
6566
6567 err = wldev_iovar_getbuf(dev, "if_counters", NULL, 0,
6568 (char *)if_stats, sizeof(*if_stats), NULL);
6569 if (!err) {
6570 sinfo->rx_packets = (uint32)dtoh64(if_stats->rxframe);
6571 sinfo->rx_dropped_misc = 0;
6572 sinfo->tx_packets = (uint32)dtoh64(if_stats->txfrmsnt);
6573 sinfo->tx_failed = (uint32)dtoh64(if_stats->txnobuf) +
6574 (uint32)dtoh64(if_stats->txrunt) +
6575 (uint32)dtoh64(if_stats->txfail);
6576 } else {
6577 // WL_ERR(("%s: if_counters not supported ret=%d\n",
6578 // __FUNCTION__, err));
6579 #endif /* DHD_SUPPORT_IF_CNTS */
6580
6581 err = wldev_ioctl_get(dev, WLC_GET_PKTCNTS, &pktcnt,
6582 sizeof(pktcnt));
6583 if (err) {
6584 WL_ERR(("Could not get WLC_GET_PKTCNTS (%d)\n", err));
6585 goto get_station_err;
6586 }
6587 sinfo->rx_packets = pktcnt.rx_good_pkt;
6588 sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
6589 sinfo->tx_packets = pktcnt.tx_good_pkt;
6590 sinfo->tx_failed = pktcnt.tx_bad_pkt;
6591 #ifdef DHD_SUPPORT_IF_CNTS
6592 }
6593 #endif /* DHD_SUPPORT_IF_CNTS */
6594
6595 sinfo->filled |= (STA_INFO_BIT(INFO_RX_PACKETS) |
6596 STA_INFO_BIT(INFO_RX_DROP_MISC) |
6597 STA_INFO_BIT(INFO_TX_PACKETS) |
6598 STA_INFO_BIT(INFO_TX_FAILED));
6599
6600 get_station_err:
6601 if (err)
6602 err_cnt++;
6603 else
6604 err_cnt = 0;
6605 if (err_cnt >= 3 && (err != -ENODATA)) {
6606 /* Disconnect due to zero BSSID or error to get RSSI */
6607 scb_val_t scbval;
6608 scbval.val = htod32(DOT11_RC_DISASSOC_LEAVING);
6609 err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
6610 if (unlikely(err)) {
6611 WL_ERR(("disassoc error (%d)\n", err));
6612 }
6613
6614 WL_ERR(("force cfg80211_disconnected: %d\n", err));
6615 wl_clr_drv_status(cfg, CONNECTED, dev);
6616 CFG80211_DISCONNECTED(dev, 0, NULL, 0, false, GFP_KERNEL);
6617 wl_link_down(cfg);
6618 }
6619 #ifdef DHD_SUPPORT_IF_CNTS
6620 error:
6621 if (if_stats) {
6622 kfree(if_stats);
6623 }
6624 #endif /* DHD_SUPPORT_IF_CNTS */
6625 }
6626 else {
6627 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg, dev)));
6628 }
6629
6630 return err;
6631 }
6632
6633 static s32
6634 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
6635 bool enabled, s32 timeout)
6636 {
6637 s32 pm;
6638 s32 err = 0;
6639 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6640 struct net_info *_net_info = wl_get_netinfo_by_netdev(cfg, dev);
6641 #ifdef RTT_SUPPORT
6642 rtt_status_info_t *rtt_status;
6643 #endif /* RTT_SUPPORT */
6644 dhd_pub_t *dhd = cfg->pub;
6645
6646 RETURN_EIO_IF_NOT_UP(cfg);
6647 WL_DBG(("Enter\n"));
6648 if (cfg->p2p_net == dev || _net_info == NULL ||
6649 !wl_get_drv_status(cfg, CONNECTED, dev) ||
6650 (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_BSS &&
6651 wl_get_mode_by_netdev(cfg, dev) != WL_MODE_IBSS)) {
6652 return err;
6653 }
6654
6655 /* Enlarge pm_enable_work */
6656 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_LONG);
6657
6658 pm = enabled ? PM_FAST : PM_OFF;
6659 if (_net_info->pm_block) {
6660 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
6661 dev->name, _net_info->pm_block));
6662 pm = PM_OFF;
6663 }
6664 if (enabled && dhd_conf_get_pm(dhd) >= 0)
6665 pm = dhd_conf_get_pm(dhd);
6666 pm = htod32(pm);
6667 WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
6668 #ifdef RTT_SUPPORT
6669 rtt_status = GET_RTTSTATE(dhd);
6670 if (rtt_status->status != RTT_ENABLED) {
6671 #endif /* RTT_SUPPORT */
6672 err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm));
6673 if (unlikely(err)) {
6674 if (err == -ENODEV)
6675 WL_DBG(("net_device is not ready yet\n"));
6676 else
6677 WL_ERR(("error (%d)\n", err));
6678 return err;
6679 }
6680 #ifdef RTT_SUPPORT
6681 }
6682 #endif /* RTT_SUPPORT */
6683 wl_cfg80211_update_power_mode(dev);
6684 return err;
6685 }
6686
6687 void wl_cfg80211_update_power_mode(struct net_device *dev)
6688 {
6689 int err, pm = -1;
6690
6691 err = wldev_ioctl_get(dev, WLC_GET_PM, &pm, sizeof(pm));
6692 if (err)
6693 WL_ERR(("%s:error (%d)\n", __FUNCTION__, err));
6694 else if (pm != -1 && dev->ieee80211_ptr)
6695 dev->ieee80211_ptr->ps = (pm == PM_OFF) ? false : true;
6696 }
6697
6698 void wl_cfg80211_set_passive_scan(struct net_device *dev, char *command)
6699 {
6700 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6701
6702 if (strcmp(command, "SCAN-ACTIVE") == 0) {
6703 cfg->active_scan = 1;
6704 } else if (strcmp(command, "SCAN-PASSIVE") == 0) {
6705 cfg->active_scan = 0;
6706 } else
6707 WL_ERR(("Unknown command \n"));
6708 }
6709
6710 static __used u32 wl_find_msb(u16 bit16)
6711 {
6712 u32 ret = 0;
6713
6714 if (bit16 & 0xff00) {
6715 ret += 8;
6716 bit16 >>= 8;
6717 }
6718
6719 if (bit16 & 0xf0) {
6720 ret += 4;
6721 bit16 >>= 4;
6722 }
6723
6724 if (bit16 & 0xc) {
6725 ret += 2;
6726 bit16 >>= 2;
6727 }
6728
6729 if (bit16 & 2)
6730 ret += bit16 & 2;
6731 else if (bit16)
6732 ret += bit16;
6733
6734 return ret;
6735 }
6736
6737 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
6738 {
6739 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6740 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
6741 s32 err = BCME_OK;
6742
6743 if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
6744 WL_INFORM(("device is not ready\n"));
6745 return err;
6746 }
6747
6748
6749 return err;
6750 }
6751
6752
6753 static s32
6754 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
6755 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
6756 #else
6757 wl_cfg80211_suspend(struct wiphy *wiphy)
6758 #endif /* KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES */
6759 {
6760 s32 err = BCME_OK;
6761 #ifdef DHD_CLEAR_ON_SUSPEND
6762 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6763 struct net_info *iter, *next;
6764 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
6765 unsigned long flags;
6766 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
6767 struct cfg80211_scan_info info;
6768 #endif
6769
6770 if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
6771 WL_INFORM(("device is not ready : status (%d)\n",
6772 (int)cfg->status));
6773 return err;
6774 }
6775 for_each_ndev(cfg, iter, next) {
6776 /* p2p discovery iface doesn't have a ndev associated with it (for kernel > 3.8) */
6777 if (iter->ndev)
6778 wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
6779 }
6780 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
6781 if (cfg->scan_request) {
6782 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
6783 info.aborted = true;
6784 cfg80211_scan_done(cfg->scan_request, &info);
6785 #else
6786 cfg80211_scan_done(cfg->scan_request, true);
6787 #endif
6788 cfg->scan_request = NULL;
6789 }
6790 for_each_ndev(cfg, iter, next) {
6791 if (iter->ndev) {
6792 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
6793 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
6794 }
6795 }
6796 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
6797 for_each_ndev(cfg, iter, next) {
6798 if (iter->ndev) {
6799 if (wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
6800 wl_bss_connect_done(cfg, iter->ndev, NULL, NULL, false);
6801 }
6802 }
6803 }
6804 #endif /* DHD_CLEAR_ON_SUSPEND */
6805
6806
6807 return err;
6808 }
6809
6810 static s32
6811 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
6812 s32 err)
6813 {
6814 int i, j;
6815 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6816 struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
6817
6818 if (!pmk_list) {
6819 printf("pmk_list is NULL\n");
6820 return -EINVAL;
6821 }
6822 /* pmk list is supported only for STA interface i.e. primary interface
6823 * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
6824 */
6825 if (primary_dev != dev) {
6826 WL_INFORM(("Not supporting Flushing pmklist on virtual"
6827 " interfaces than primary interface\n"));
6828 return err;
6829 }
6830
6831 WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
6832 for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
6833 WL_DBG(("PMKID[%d]: %pM =\n", i,
6834 &pmk_list->pmkids.pmkid[i].BSSID));
6835 for (j = 0; j < WPA2_PMKID_LEN; j++) {
6836 WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
6837 }
6838 }
6839 if (likely(!err)) {
6840 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
6841 sizeof(*pmk_list), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
6842 }
6843
6844 return err;
6845 }
6846
6847 static s32
6848 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
6849 struct cfg80211_pmksa *pmksa)
6850 {
6851 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6852 s32 err = 0;
6853 int i;
6854
6855 RETURN_EIO_IF_NOT_UP(cfg);
6856 for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
6857 if (!memcmp(pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
6858 ETHER_ADDR_LEN))
6859 break;
6860 if (i < WL_NUM_PMKIDS_MAX) {
6861 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
6862 ETHER_ADDR_LEN);
6863 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
6864 WPA2_PMKID_LEN);
6865 if (i == cfg->pmk_list->pmkids.npmkid)
6866 cfg->pmk_list->pmkids.npmkid++;
6867 } else {
6868 err = -EINVAL;
6869 }
6870 WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
6871 &cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].BSSID));
6872 for (i = 0; i < WPA2_PMKID_LEN; i++) {
6873 WL_DBG(("%02x\n",
6874 cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].
6875 PMKID[i]));
6876 }
6877
6878 err = wl_update_pmklist(dev, cfg->pmk_list, err);
6879
6880 return err;
6881 }
6882
6883 static s32
6884 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
6885 struct cfg80211_pmksa *pmksa)
6886 {
6887 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6888
6889 struct _pmkid_list pmkid = {.npmkid = 0};
6890 s32 err = 0;
6891 int i;
6892
6893 RETURN_EIO_IF_NOT_UP(cfg);
6894 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
6895 memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
6896
6897 WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
6898 &pmkid.pmkid[0].BSSID));
6899 for (i = 0; i < WPA2_PMKID_LEN; i++) {
6900 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
6901 }
6902
6903 for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
6904 if (!memcmp
6905 (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
6906 ETHER_ADDR_LEN))
6907 break;
6908
6909 if ((cfg->pmk_list->pmkids.npmkid > 0) &&
6910 (i < cfg->pmk_list->pmkids.npmkid)) {
6911 memset(&cfg->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
6912 for (; i < (cfg->pmk_list->pmkids.npmkid - 1); i++) {
6913 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
6914 &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
6915 ETHER_ADDR_LEN);
6916 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
6917 &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
6918 WPA2_PMKID_LEN);
6919 }
6920 cfg->pmk_list->pmkids.npmkid--;
6921 } else {
6922 err = -EINVAL;
6923 }
6924
6925 err = wl_update_pmklist(dev, cfg->pmk_list, err);
6926
6927 return err;
6928
6929 }
6930
6931 static s32
6932 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6933 {
6934 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6935 s32 err = 0;
6936 RETURN_EIO_IF_NOT_UP(cfg);
6937 memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
6938 err = wl_update_pmklist(dev, cfg->pmk_list, err);
6939 return err;
6940 }
6941
6942 static wl_scan_params_t *
6943 wl_cfg80211_scan_alloc_params(struct bcm_cfg80211 *cfg, int channel, int nprobes,
6944 int *out_params_size)
6945 {
6946 wl_scan_params_t *params;
6947 int params_size;
6948 int num_chans;
6949 int bssidx = 0;
6950
6951 *out_params_size = 0;
6952
6953 /* Our scan params only need space for 1 channel and 0 ssids */
6954 params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
6955 params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
6956 if (params == NULL) {
6957 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
6958 return params;
6959 }
6960 memset(params, 0, params_size);
6961 params->nprobes = nprobes;
6962
6963 num_chans = (channel == 0) ? 0 : 1;
6964
6965 memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
6966 params->bss_type = DOT11_BSSTYPE_ANY;
6967 params->scan_type = DOT11_SCANTYPE_ACTIVE;
6968 params->nprobes = htod32(1);
6969 params->active_time = htod32(-1);
6970 params->passive_time = htod32(-1);
6971 params->home_time = htod32(10);
6972 if (channel == -1)
6973 params->channel_list[0] = htodchanspec(channel);
6974 else
6975 params->channel_list[0] = wl_ch_host_to_driver(cfg, bssidx, channel);
6976
6977 /* Our scan params have 1 channel and 0 ssids */
6978 params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
6979 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
6980
6981 *out_params_size = params_size; /* rtn size to the caller */
6982 return params;
6983 }
6984
6985 static s32
6986 #if defined(WL_CFG80211_P2P_DEV_IF)
6987 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
6988 struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
6989 #else
6990 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
6991 struct ieee80211_channel * channel,
6992 enum nl80211_channel_type channel_type,
6993 unsigned int duration, u64 *cookie)
6994 #endif /* WL_CFG80211_P2P_DEV_IF */
6995 {
6996 s32 target_channel;
6997 u32 id;
6998 s32 err = BCME_OK;
6999 struct ether_addr primary_mac;
7000 struct net_device *ndev = NULL;
7001 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7002
7003 #ifdef DHD_IFDEBUG
7004 PRINT_WDEV_INFO(cfgdev);
7005 #endif /* DHD_IFDEBUG */
7006
7007 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
7008
7009 WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
7010 ieee80211_frequency_to_channel(channel->center_freq),
7011 duration, (wl_get_drv_status(cfg, SCANNING, ndev)) ? "YES":"NO"));
7012
7013 if (!cfg->p2p) {
7014 WL_ERR(("cfg->p2p is not initialized\n"));
7015 err = BCME_ERROR;
7016 goto exit;
7017 }
7018
7019 #ifdef P2P_LISTEN_OFFLOADING
7020 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
7021 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
7022 return -EAGAIN;
7023 }
7024 #endif /* P2P_LISTEN_OFFLOADING */
7025
7026 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7027 if (wl_get_drv_status_all(cfg, SCANNING)) {
7028 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
7029 }
7030 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7031
7032 target_channel = ieee80211_frequency_to_channel(channel->center_freq);
7033 memcpy(&cfg->remain_on_chan, channel, sizeof(struct ieee80211_channel));
7034 #if defined(WL_ENABLE_P2P_IF)
7035 cfg->remain_on_chan_type = channel_type;
7036 #endif /* WL_ENABLE_P2P_IF */
7037 id = ++cfg->last_roc_id;
7038 if (id == 0)
7039 id = ++cfg->last_roc_id;
7040 *cookie = id;
7041
7042 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7043 if (wl_get_drv_status(cfg, SCANNING, ndev)) {
7044 struct timer_list *_timer;
7045 WL_DBG(("scan is running. go to fake listen state\n"));
7046
7047 if (duration > LONG_LISTEN_TIME) {
7048 wl_cfg80211_scan_abort(cfg);
7049 } else {
7050 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
7051
7052 if (timer_pending(&cfg->p2p->listen_timer)) {
7053 WL_DBG(("cancel current listen timer \n"));
7054 del_timer_sync(&cfg->p2p->listen_timer);
7055 }
7056
7057 _timer = &cfg->p2p->listen_timer;
7058 wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
7059
7060 INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
7061
7062 err = BCME_OK;
7063 goto exit;
7064 }
7065 }
7066 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7067
7068 #ifdef WL_CFG80211_SYNC_GON
7069 if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
7070 /* do not enter listen mode again if we are in listen mode already for next af.
7071 * remain on channel completion will be returned by waiting next af completion.
7072 */
7073 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7074 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
7075 #else
7076 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
7077 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7078 goto exit;
7079 }
7080 #endif /* WL_CFG80211_SYNC_GON */
7081 if (cfg->p2p && !cfg->p2p->on) {
7082 /* In case of p2p_listen command, supplicant send remain_on_channel
7083 * without turning on P2P
7084 */
7085 get_primary_mac(cfg, &primary_mac);
7086 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
7087 p2p_on(cfg) = true;
7088 }
7089
7090 if (p2p_is_on(cfg)) {
7091 err = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
7092 if (unlikely(err)) {
7093 goto exit;
7094 }
7095 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7096 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
7097 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7098 err = wl_cfgp2p_discover_listen(cfg, target_channel, duration);
7099
7100 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7101 if (err == BCME_OK) {
7102 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
7103 } else {
7104 /* if failed, firmware may be internal scanning state.
7105 * so other scan request shall not abort it
7106 */
7107 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
7108 }
7109 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7110 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
7111 * and expire timer will send a completion to the upper layer
7112 */
7113 err = BCME_OK;
7114 }
7115
7116 exit:
7117 if (err == BCME_OK) {
7118 WL_INFORM(("Success\n"));
7119 #if defined(WL_CFG80211_P2P_DEV_IF)
7120 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
7121 duration, GFP_KERNEL);
7122 #else
7123 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
7124 channel_type, duration, GFP_KERNEL);
7125 #endif /* WL_CFG80211_P2P_DEV_IF */
7126 } else {
7127 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
7128 }
7129 return err;
7130 }
7131
7132 static s32
7133 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
7134 bcm_struct_cfgdev *cfgdev, u64 cookie)
7135 {
7136 s32 err = 0;
7137
7138 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7139
7140 #ifdef P2PLISTEN_AP_SAMECHN
7141 struct net_device *dev;
7142 #endif /* P2PLISTEN_AP_SAMECHN */
7143
7144 RETURN_EIO_IF_NOT_UP(cfg);
7145
7146 #ifdef DHD_IFDEBUG
7147 PRINT_WDEV_INFO(cfgdev);
7148 #endif /* DHD_IFDEBUG */
7149
7150 #if defined(WL_CFG80211_P2P_DEV_IF)
7151 if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
7152 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
7153 }
7154 #else
7155 WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
7156 #endif /* WL_CFG80211_P2P_DEV_IF */
7157
7158 #ifdef P2PLISTEN_AP_SAMECHN
7159 if (cfg && cfg->p2p_resp_apchn_status) {
7160 dev = bcmcfg_to_prmry_ndev(cfg);
7161 wl_cfg80211_set_p2p_resp_ap_chn(dev, 0);
7162 cfg->p2p_resp_apchn_status = false;
7163 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
7164 }
7165 #endif /* P2PLISTEN_AP_SAMECHN */
7166
7167 if (cfg->last_roc_id == cookie) {
7168 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
7169 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
7170 } else {
7171 WL_ERR(("%s : ignore, request cookie(%llu) is not matched. (cur : %llu)\n",
7172 __FUNCTION__, cookie, cfg->last_roc_id));
7173 }
7174
7175 return err;
7176 }
7177
7178 static void
7179 wl_cfg80211_afx_handler(struct work_struct *work)
7180 {
7181 struct afx_hdl *afx_instance;
7182 struct bcm_cfg80211 *cfg;
7183 s32 ret = BCME_OK;
7184
7185 BCM_SET_CONTAINER_OF(afx_instance, work, struct afx_hdl, work);
7186 if (!afx_instance) {
7187 WL_ERR(("afx_instance is NULL\n"));
7188 return;
7189 }
7190 cfg = wl_get_cfg(afx_instance->dev);
7191 if (afx_instance) {
7192 if (cfg->afx_hdl->is_active) {
7193 if (cfg->afx_hdl->is_listen && cfg->afx_hdl->my_listen_chan) {
7194 ret = wl_cfgp2p_discover_listen(cfg, cfg->afx_hdl->my_listen_chan,
7195 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
7196 } else {
7197 ret = wl_cfgp2p_act_frm_search(cfg, cfg->afx_hdl->dev,
7198 cfg->afx_hdl->bssidx, cfg->afx_hdl->peer_listen_chan,
7199 NULL);
7200 }
7201 if (unlikely(ret != BCME_OK)) {
7202 WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
7203 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL))
7204 complete(&cfg->act_frm_scan);
7205 }
7206 }
7207 }
7208 }
7209
7210 static s32
7211 wl_cfg80211_af_searching_channel(struct bcm_cfg80211 *cfg, struct net_device *dev)
7212 {
7213 u32 max_retry = WL_CHANNEL_SYNC_RETRY;
7214 bool is_p2p_gas = false;
7215
7216 if (dev == NULL)
7217 return -1;
7218
7219 WL_DBG((" enter ) \n"));
7220
7221 wl_set_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
7222 cfg->afx_hdl->is_active = TRUE;
7223
7224 if (cfg->afx_hdl->pending_tx_act_frm) {
7225 wl_action_frame_t *action_frame;
7226 action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
7227 if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len))
7228 is_p2p_gas = true;
7229 }
7230
7231 /* Loop to wait until we find a peer's channel or the
7232 * pending action frame tx is cancelled.
7233 */
7234 while ((cfg->afx_hdl->retry < max_retry) &&
7235 (cfg->afx_hdl->peer_chan == WL_INVALID)) {
7236 cfg->afx_hdl->is_listen = FALSE;
7237 wl_set_drv_status(cfg, SCANNING, dev);
7238 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
7239 cfg->afx_hdl->retry));
7240 /* search peer on peer's listen channel */
7241 schedule_work(&cfg->afx_hdl->work);
7242 wait_for_completion_timeout(&cfg->act_frm_scan,
7243 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
7244
7245 if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
7246 !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
7247 break;
7248
7249 if (is_p2p_gas)
7250 break;
7251
7252 if (cfg->afx_hdl->my_listen_chan) {
7253 WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
7254 cfg->afx_hdl->my_listen_chan));
7255 /* listen on my listen channel */
7256 cfg->afx_hdl->is_listen = TRUE;
7257 schedule_work(&cfg->afx_hdl->work);
7258 wait_for_completion_timeout(&cfg->act_frm_scan,
7259 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
7260 }
7261 if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
7262 !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
7263 break;
7264
7265 cfg->afx_hdl->retry++;
7266
7267 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
7268 }
7269
7270 cfg->afx_hdl->is_active = FALSE;
7271
7272 wl_clr_drv_status(cfg, SCANNING, dev);
7273 wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
7274
7275 return (cfg->afx_hdl->peer_chan);
7276 }
7277
7278 struct p2p_config_af_params {
7279 s32 max_tx_retry; /* max tx retry count if tx no ack */
7280 #ifdef WL_CFG80211_SYNC_GON
7281 bool extra_listen;
7282 #endif
7283 bool search_channel; /* 1: search peer's channel to send af */
7284 };
7285
7286 static s32
7287 wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
7288 wl_action_frame_t *action_frame, wl_af_params_t *af_params,
7289 struct p2p_config_af_params *config_af_params)
7290 {
7291 s32 err = BCME_OK;
7292 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7293 wifi_p2p_pub_act_frame_t *act_frm =
7294 (wifi_p2p_pub_act_frame_t *) (action_frame->data);
7295
7296 /* initialize default value */
7297 #ifdef WL_CFG80211_SYNC_GON
7298 config_af_params->extra_listen = true;
7299 #endif
7300 config_af_params->search_channel = false;
7301 config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
7302 cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
7303
7304 switch (act_frm->subtype) {
7305 case P2P_PAF_GON_REQ: {
7306 WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
7307 wl_set_p2p_status(cfg, GO_NEG_PHASE);
7308
7309 config_af_params->search_channel = true;
7310 cfg->next_af_subtype = act_frm->subtype + 1;
7311
7312 /* increase dwell time to wait for RESP frame */
7313 af_params->dwell_time = WL_MED_DWELL_TIME;
7314
7315 break;
7316 }
7317 case P2P_PAF_GON_RSP: {
7318 cfg->next_af_subtype = act_frm->subtype + 1;
7319 /* increase dwell time to wait for CONF frame */
7320 af_params->dwell_time = WL_MED_DWELL_TIME + 100;
7321 break;
7322 }
7323 case P2P_PAF_GON_CONF: {
7324 /* If we reached till GO Neg confirmation reset the filter */
7325 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
7326 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
7327
7328 /* minimize dwell time */
7329 af_params->dwell_time = WL_MIN_DWELL_TIME;
7330
7331 #ifdef WL_CFG80211_SYNC_GON
7332 config_af_params->extra_listen = false;
7333 #endif /* WL_CFG80211_SYNC_GON */
7334 break;
7335 }
7336 case P2P_PAF_INVITE_REQ: {
7337 config_af_params->search_channel = true;
7338 cfg->next_af_subtype = act_frm->subtype + 1;
7339
7340 /* increase dwell time */
7341 af_params->dwell_time = WL_MED_DWELL_TIME;
7342 break;
7343 }
7344 case P2P_PAF_INVITE_RSP:
7345 /* minimize dwell time */
7346 af_params->dwell_time = WL_MIN_DWELL_TIME;
7347 #ifdef WL_CFG80211_SYNC_GON
7348 config_af_params->extra_listen = false;
7349 #endif /* WL_CFG80211_SYNC_GON */
7350 break;
7351 case P2P_PAF_DEVDIS_REQ: {
7352 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
7353 action_frame->len)) {
7354 config_af_params->search_channel = true;
7355 }
7356
7357 cfg->next_af_subtype = act_frm->subtype + 1;
7358 /* maximize dwell time to wait for RESP frame */
7359 af_params->dwell_time = WL_LONG_DWELL_TIME;
7360 break;
7361 }
7362 case P2P_PAF_DEVDIS_RSP:
7363 /* minimize dwell time */
7364 af_params->dwell_time = WL_MIN_DWELL_TIME;
7365 #ifdef WL_CFG80211_SYNC_GON
7366 config_af_params->extra_listen = false;
7367 #endif /* WL_CFG80211_SYNC_GON */
7368 break;
7369 case P2P_PAF_PROVDIS_REQ: {
7370 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
7371 action_frame->len)) {
7372 config_af_params->search_channel = true;
7373 }
7374
7375 cfg->next_af_subtype = act_frm->subtype + 1;
7376 /* increase dwell time to wait for RESP frame */
7377 af_params->dwell_time = WL_MED_DWELL_TIME;
7378 break;
7379 }
7380 case P2P_PAF_PROVDIS_RSP: {
7381 cfg->next_af_subtype = P2P_PAF_GON_REQ;
7382 af_params->dwell_time = WL_MED_DWELL_TIME;
7383 #ifdef WL_CFG80211_SYNC_GON
7384 config_af_params->extra_listen = false;
7385 #endif /* WL_CFG80211_SYNC_GON */
7386 break;
7387 }
7388 default:
7389 WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
7390 act_frm->subtype));
7391 err = BCME_BADARG;
7392 }
7393 return err;
7394 }
7395
7396 #ifdef WL11U
7397 static bool
7398 wl_cfg80211_check_DFS_channel(struct bcm_cfg80211 *cfg, wl_af_params_t *af_params,
7399 void *frame, u16 frame_len)
7400 {
7401 struct wl_scan_results *bss_list;
7402 struct wl_bss_info *bi = NULL;
7403 bool result = false;
7404 s32 i;
7405 chanspec_t chanspec;
7406
7407 /* If DFS channel is 52~148, check to block it or not */
7408 if (af_params &&
7409 (af_params->channel >= 52 && af_params->channel <= 148)) {
7410 if (!wl_cfgp2p_is_p2p_action(frame, frame_len)) {
7411 bss_list = cfg->bss_list;
7412 bi = next_bss(bss_list, bi);
7413 for_each_bss(bss_list, bi, i) {
7414 chanspec = wl_chspec_driver_to_host(bi->chanspec);
7415 if (CHSPEC_IS5G(chanspec) &&
7416 ((bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(chanspec))
7417 == af_params->channel)) {
7418 result = true; /* do not block the action frame */
7419 break;
7420 }
7421 }
7422 }
7423 }
7424 else {
7425 result = true;
7426 }
7427
7428 WL_DBG(("result=%s", result?"true":"false"));
7429 return result;
7430 }
7431 #endif /* WL11U */
7432 static bool
7433 wl_cfg80211_check_dwell_overflow(int32 requested_dwell, ulong dwell_jiffies)
7434 {
7435 if ((requested_dwell & CUSTOM_RETRY_MASK) &&
7436 (jiffies_to_msecs(jiffies - dwell_jiffies) >
7437 (requested_dwell & ~CUSTOM_RETRY_MASK))) {
7438 WL_ERR(("Action frame TX retry time over dwell time!\n"));
7439 return true;
7440 }
7441 return false;
7442 }
7443
7444 static bool
7445 wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
7446 bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
7447 wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
7448 {
7449 #ifdef WL11U
7450 struct net_device *ndev = NULL;
7451 #endif /* WL11U */
7452 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7453 bool ack = false;
7454 u8 category, action;
7455 s32 tx_retry;
7456 struct p2p_config_af_params config_af_params;
7457 struct net_info *netinfo;
7458 #ifdef VSDB
7459 ulong off_chan_started_jiffies = 0;
7460 #endif
7461 ulong dwell_jiffies = 0;
7462 bool dwell_overflow = false;
7463 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
7464 bool miss_gon_cfm = false;
7465
7466 int32 requested_dwell = af_params->dwell_time;
7467
7468 /* Add the default dwell time
7469 * Dwell time to stay off-channel to wait for a response action frame
7470 * after transmitting an GO Negotiation action frame
7471 */
7472 af_params->dwell_time = WL_DWELL_TIME;
7473
7474 #ifdef WL11U
7475 #if defined(WL_CFG80211_P2P_DEV_IF)
7476 ndev = dev;
7477 #else
7478 ndev = ndev_to_cfgdev(cfgdev);
7479 #endif /* WL_CFG80211_P2P_DEV_IF */
7480 #endif /* WL11U */
7481
7482 category = action_frame->data[DOT11_ACTION_CAT_OFF];
7483 action = action_frame->data[DOT11_ACTION_ACT_OFF];
7484
7485 /* initialize variables */
7486 tx_retry = 0;
7487 cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
7488 config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
7489 config_af_params.search_channel = false;
7490 #ifdef WL_CFG80211_SYNC_GON
7491 config_af_params.extra_listen = false;
7492 #endif
7493
7494 /* config parameters */
7495 /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
7496 if (category == DOT11_ACTION_CAT_PUBLIC) {
7497 if ((action == P2P_PUB_AF_ACTION) &&
7498 (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
7499 /* p2p public action frame process */
7500 if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
7501 action_frame, af_params, &config_af_params)) {
7502 WL_DBG(("Unknown subtype.\n"));
7503 }
7504
7505 } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
7506 /* service discovery process */
7507 if (action == P2PSD_ACTION_ID_GAS_IREQ ||
7508 action == P2PSD_ACTION_ID_GAS_CREQ) {
7509 /* configure service discovery query frame */
7510
7511 config_af_params.search_channel = true;
7512
7513 /* save next af suptype to cancel remained dwell time */
7514 cfg->next_af_subtype = action + 1;
7515
7516 af_params->dwell_time = WL_MED_DWELL_TIME;
7517 if (requested_dwell & CUSTOM_RETRY_MASK) {
7518 config_af_params.max_tx_retry =
7519 (requested_dwell & CUSTOM_RETRY_MASK) >> 24;
7520 af_params->dwell_time =
7521 (requested_dwell & ~CUSTOM_RETRY_MASK);
7522 WL_DBG(("Custom retry(%d) and dwell time(%d) is set.\n",
7523 config_af_params.max_tx_retry,
7524 af_params->dwell_time));
7525 }
7526 } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
7527 action == P2PSD_ACTION_ID_GAS_CRESP) {
7528 /* configure service discovery response frame */
7529 af_params->dwell_time = WL_MIN_DWELL_TIME;
7530 } else {
7531 WL_DBG(("Unknown action type: %d\n", action));
7532 }
7533 } else {
7534 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
7535 category, action, action_frame_len));
7536 }
7537 } else if (category == P2P_AF_CATEGORY) {
7538 /* do not configure anything. it will be sent with a default configuration */
7539 } else {
7540 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
7541 category, action));
7542 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
7543 wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
7544 return false;
7545 }
7546 }
7547 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
7548 /* validate channel and p2p ies */
7549 if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
7550 netinfo && netinfo->bss.ies.probe_req_ie_len) {
7551 config_af_params.search_channel = true;
7552 } else {
7553 config_af_params.search_channel = false;
7554 }
7555 #ifdef WL11U
7556 if (ndev == bcmcfg_to_prmry_ndev(cfg))
7557 config_af_params.search_channel = false;
7558 #endif /* WL11U */
7559
7560 #ifdef VSDB
7561 /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
7562 if (wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {
7563 OSL_SLEEP(50);
7564 }
7565 #endif
7566
7567 /* if scan is ongoing, abort current scan. */
7568 if (wl_get_drv_status_all(cfg, SCANNING)) {
7569 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
7570 }
7571
7572 /* Abort P2P listen */
7573 if (discover_cfgdev(cfgdev, cfg)) {
7574 if (cfg->p2p_supported && cfg->p2p) {
7575 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
7576 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
7577 }
7578 }
7579
7580 #ifdef WL11U
7581 /* handling DFS channel exceptions */
7582 if (!wl_cfg80211_check_DFS_channel(cfg, af_params, action_frame->data, action_frame->len)) {
7583 return false; /* the action frame was blocked */
7584 }
7585 #endif /* WL11U */
7586
7587 /* set status and destination address before sending af */
7588 if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
7589 /* set this status to cancel the remained dwell time in rx process */
7590 wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
7591 }
7592 wl_set_drv_status(cfg, SENDING_ACT_FRM, dev);
7593 memcpy(cfg->afx_hdl->tx_dst_addr.octet,
7594 af_params->action_frame.da.octet,
7595 sizeof(cfg->afx_hdl->tx_dst_addr.octet));
7596
7597 /* save af_params for rx process */
7598 cfg->afx_hdl->pending_tx_act_frm = af_params;
7599
7600 if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) {
7601 WL_DBG(("Set GAS action frame config.\n"));
7602 config_af_params.search_channel = false;
7603 config_af_params.max_tx_retry = 1;
7604 }
7605
7606 /* search peer's channel */
7607 if (config_af_params.search_channel) {
7608 /* initialize afx_hdl */
7609 if ((cfg->afx_hdl->bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
7610 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
7611 goto exit;
7612 }
7613 cfg->afx_hdl->dev = dev;
7614 cfg->afx_hdl->retry = 0;
7615 cfg->afx_hdl->peer_chan = WL_INVALID;
7616
7617 if (wl_cfg80211_af_searching_channel(cfg, dev) == WL_INVALID) {
7618 WL_ERR(("couldn't find peer's channel.\n"));
7619 wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
7620 af_params->channel);
7621 /* Even if we couldn't find peer channel, try to send the frame
7622 * out. P2P cert 5.1.14 testbed device (realtek) doesn't seem to
7623 * respond to probe request (Ideally it has to be in listen and
7624 * responsd to probe request). However if we send Go neg req, the
7625 * peer is sending GO-neg resp. So instead of giving up here, just
7626 * proceed and attempt sending out the action frame.
7627 */
7628 }
7629
7630 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
7631 /*
7632 * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
7633 * but after the check of piggyback algorithm.
7634 * To take care of current piggback algo, lets abort the scan here itself.
7635 */
7636 wl_notify_escan_complete(cfg, dev, true, true);
7637 /* Suspend P2P discovery's search-listen to prevent it from
7638 * starting a scan or changing the channel.
7639 */
7640 if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
7641 WL_ERR(("Can not disable discovery mode\n"));
7642 goto exit;
7643 }
7644
7645 /* update channel */
7646 if (cfg->afx_hdl->peer_chan != WL_INVALID) {
7647 af_params->channel = cfg->afx_hdl->peer_chan;
7648 WL_ERR(("Attempt tx on peer listen channel:%d ",
7649 cfg->afx_hdl->peer_chan));
7650 } else {
7651 WL_ERR(("Attempt tx with the channel provided by userspace."
7652 "Channel: %d\n", af_params->channel));
7653 }
7654 }
7655
7656 #ifdef VSDB
7657 off_chan_started_jiffies = jiffies;
7658 #endif /* VSDB */
7659
7660 wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
7661
7662 wl_cfgp2p_need_wait_actfrmae(cfg, action_frame->data, action_frame->len, true);
7663
7664 dwell_jiffies = jiffies;
7665 /* Now send a tx action frame */
7666 ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ? false : true;
7667 dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
7668
7669 if (ack && (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM))) {
7670 wifi_p2p_pub_act_frame_t *pact_frm;
7671 pact_frm = (wifi_p2p_pub_act_frame_t *)(action_frame->data);
7672 if (pact_frm->subtype == P2P_PAF_GON_RSP) {
7673 WL_ERR(("Miss GO Nego cfm after P2P_PAF_GON_RSP\n"));
7674 miss_gon_cfm = true;
7675 }
7676 }
7677
7678 /* if failed, retry it. tx_retry_max value is configure by .... */
7679 while ((miss_gon_cfm || (ack == false)) && (tx_retry++ < config_af_params.max_tx_retry) &&
7680 !dwell_overflow) {
7681 #ifdef VSDB
7682 if (af_params->channel) {
7683 if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
7684 OFF_CHAN_TIME_THRESHOLD_MS) {
7685 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
7686 off_chan_started_jiffies = jiffies;
7687 } else
7688 OSL_SLEEP(AF_RETRY_DELAY_TIME);
7689 }
7690 #endif /* VSDB */
7691 ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ?
7692 false : true;
7693 if (miss_gon_cfm && !wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
7694 WL_ERR(("Received GO Nego cfm after P2P_PAF_GON_RSP\n"));
7695 miss_gon_cfm = false;
7696 }
7697 dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
7698 }
7699
7700 if (ack == false) {
7701 WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
7702 }
7703 WL_DBG(("Complete to send action frame\n"));
7704 exit:
7705 /* Clear SENDING_ACT_FRM after all sending af is done */
7706 wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
7707
7708 #ifdef WL_CFG80211_SYNC_GON
7709 /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
7710 * if we coundn't get the next action response frame and dongle does not keep
7711 * the dwell time, go to listen state again to get next action response frame.
7712 */
7713 if (ack && config_af_params.extra_listen &&
7714 wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM) &&
7715 cfg->af_sent_channel == cfg->afx_hdl->my_listen_chan) {
7716 s32 extar_listen_time;
7717
7718 extar_listen_time = af_params->dwell_time -
7719 jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies);
7720
7721 if (extar_listen_time > 50) {
7722 wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
7723 WL_DBG(("Wait more time! actual af time:%d,"
7724 "calculated extar listen:%d\n",
7725 af_params->dwell_time, extar_listen_time));
7726 if (wl_cfgp2p_discover_listen(cfg, cfg->af_sent_channel,
7727 extar_listen_time + 100) == BCME_OK) {
7728 wait_for_completion_timeout(&cfg->wait_next_af,
7729 msecs_to_jiffies(extar_listen_time + 100 + 300));
7730 }
7731 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
7732 }
7733 }
7734 #endif /* WL_CFG80211_SYNC_GON */
7735 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
7736 cfg->afx_hdl->pending_tx_act_frm = NULL;
7737
7738 WL_INFORM(("-- sending Action Frame is %s, listen chan: %d\n",
7739 (ack) ? "Succeeded!!":"Failed!!", cfg->afx_hdl->my_listen_chan));
7740
7741 return ack;
7742 }
7743
7744 #define MAX_NUM_OF_ASSOCIATED_DEV 64
7745 static s32
7746 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7747 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
7748 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
7749 #else
7750 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
7751 struct ieee80211_channel *channel, bool offchan,
7752 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0))
7753 enum nl80211_channel_type channel_type,
7754 bool channel_type_valid,
7755 #endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0) */
7756 unsigned int wait, const u8* buf, size_t len,
7757 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
7758 bool no_cck,
7759 #endif
7760 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
7761 bool dont_wait_for_ack,
7762 #endif
7763 u64 *cookie)
7764 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
7765 {
7766 wl_action_frame_t *action_frame;
7767 wl_af_params_t *af_params;
7768 scb_val_t scb_val;
7769 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7770 struct ieee80211_channel *channel = params->chan;
7771 const u8 *buf = params->buf;
7772 size_t len = params->len;
7773 #endif
7774 const struct ieee80211_mgmt *mgmt;
7775 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7776 struct net_device *dev = NULL;
7777 s32 err = BCME_OK;
7778 s32 bssidx = 0;
7779 u32 id;
7780 bool ack = false;
7781 s8 eabuf[ETHER_ADDR_STR_LEN];
7782
7783 WL_DBG(("Enter \n"));
7784
7785 if (len > ACTION_FRAME_SIZE) {
7786 WL_ERR(("bad length:%zu\n", len));
7787 return BCME_BADLEN;
7788 }
7789 #ifdef DHD_IFDEBUG
7790 PRINT_WDEV_INFO(cfgdev);
7791 #endif /* DHD_IFDEBUG */
7792
7793 dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
7794
7795 if (!dev) {
7796 WL_ERR(("dev is NULL\n"));
7797 return -EINVAL;
7798 }
7799
7800 /* set bsscfg idx for iovar (wlan0: P2PAPI_BSSCFG_PRIMARY, p2p: P2PAPI_BSSCFG_DEVICE) */
7801 if (discover_cfgdev(cfgdev, cfg)) {
7802 if (!cfg->p2p_supported || !cfg->p2p) {
7803 WL_ERR(("P2P doesn't setup completed yet\n"));
7804 return -EINVAL;
7805 }
7806 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
7807 }
7808 else {
7809 if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
7810 WL_ERR(("Find p2p index failed\n"));
7811 return BCME_ERROR;
7812 }
7813 }
7814
7815 WL_DBG(("TX target bssidx=%d\n", bssidx));
7816
7817 if (p2p_is_on(cfg)) {
7818 /* Suspend P2P discovery search-listen to prevent it from changing the
7819 * channel.
7820 */
7821 if ((err = wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
7822 WL_ERR(("Can not disable discovery mode\n"));
7823 return -EFAULT;
7824 }
7825 }
7826 *cookie = 0;
7827 id = cfg->send_action_id++;
7828 if (id == 0)
7829 id = cfg->send_action_id++;
7830 *cookie = id;
7831 mgmt = (const struct ieee80211_mgmt *)buf;
7832 if (ieee80211_is_mgmt(mgmt->frame_control)) {
7833 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
7834 s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
7835 s32 ie_len = len - ie_offset;
7836 if ((dev == bcmcfg_to_prmry_ndev(cfg)) && cfg->p2p) {
7837 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
7838 }
7839 wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
7840 VNDR_IE_PRBRSP_FLAG, (const u8 *)(buf + ie_offset), ie_len);
7841 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
7842 #if defined(P2P_IE_MISSING_FIX)
7843 if (!cfg->p2p_prb_noti) {
7844 cfg->p2p_prb_noti = true;
7845 WL_DBG(("%s: TX 802_1X Probe Response first time.\n",
7846 __FUNCTION__));
7847 }
7848 #endif
7849 goto exit;
7850 } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
7851 ieee80211_is_deauth(mgmt->frame_control)) {
7852 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
7853 sizeof(struct ether_addr) + sizeof(uint)] = {0};
7854 int num_associated = 0;
7855 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
7856 if (!bcmp((const uint8 *)BSSID_BROADCAST,
7857 (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
7858 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
7859 err = wldev_ioctl_get(dev, WLC_GET_ASSOCLIST,
7860 assoc_maclist, sizeof(mac_buf));
7861 if (err < 0)
7862 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
7863 else
7864 num_associated = assoc_maclist->count;
7865 }
7866 memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
7867 scb_val.val = mgmt->u.disassoc.reason_code;
7868 err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
7869 sizeof(scb_val_t));
7870 if (err < 0)
7871 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
7872 WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
7873 bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
7874 scb_val.val));
7875
7876 if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
7877 wl_delay(400);
7878
7879 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
7880 goto exit;
7881
7882 } else if (ieee80211_is_action(mgmt->frame_control)) {
7883 /* Abort the dwell time of any previous off-channel
7884 * action frame that may be still in effect. Sending
7885 * off-channel action frames relies on the driver's
7886 * scan engine. If a previous off-channel action frame
7887 * tx is still in progress (including the dwell time),
7888 * then this new action frame will not be sent out.
7889 */
7890 /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
7891 * And previous off-channel action frame must be ended before new af tx.
7892 */
7893 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7894 wl_notify_escan_complete(cfg, dev, true, true);
7895 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7896 }
7897
7898 } else {
7899 WL_ERR(("Driver only allows MGMT packet type\n"));
7900 goto exit;
7901 }
7902
7903 af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
7904
7905 if (af_params == NULL)
7906 {
7907 WL_ERR(("unable to allocate frame\n"));
7908 return -ENOMEM;
7909 }
7910
7911 action_frame = &af_params->action_frame;
7912
7913 /* Add the packet Id */
7914 action_frame->packetId = *cookie;
7915 WL_DBG(("action frame %d\n", action_frame->packetId));
7916 /* Add BSSID */
7917 memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
7918 memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
7919
7920 /* Add the length exepted for 802.11 header */
7921 action_frame->len = len - DOT11_MGMT_HDR_LEN;
7922 WL_DBG(("action_frame->len: %d\n", action_frame->len));
7923
7924 /* Add the channel */
7925 af_params->channel =
7926 ieee80211_frequency_to_channel(channel->center_freq);
7927 /* Save listen_chan for searching common channel */
7928 cfg->afx_hdl->peer_listen_chan = af_params->channel;
7929 WL_DBG(("channel from upper layer %d\n", cfg->afx_hdl->peer_listen_chan));
7930
7931 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7932 af_params->dwell_time = params->wait;
7933 #else
7934 af_params->dwell_time = wait;
7935 #endif
7936
7937 memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
7938
7939 ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
7940 action_frame, action_frame->len, bssidx);
7941 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
7942
7943 kfree(af_params);
7944 exit:
7945 return err;
7946 }
7947
7948
7949 static void
7950 wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
7951 u16 frame, bool reg)
7952 {
7953
7954 WL_DBG(("frame_type: %x, reg: %d\n", frame, reg));
7955
7956 if (frame != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
7957 return;
7958
7959 return;
7960 }
7961
7962
7963 static s32
7964 wl_cfg80211_change_bss(struct wiphy *wiphy,
7965 struct net_device *dev,
7966 struct bss_parameters *params)
7967 {
7968 s32 err = 0;
7969 s32 ap_isolate = 0;
7970 #ifdef PCIE_FULL_DONGLE
7971 s32 ifidx = DHD_BAD_IF;
7972 #endif
7973 #if defined(PCIE_FULL_DONGLE)
7974 dhd_pub_t *dhd;
7975 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7976 dhd = (dhd_pub_t *)(cfg->pub);
7977 #if defined(WL_ENABLE_P2P_IF)
7978 if (cfg->p2p_net == dev)
7979 dev = bcmcfg_to_prmry_ndev(cfg);
7980 #endif
7981 #endif
7982
7983 if (params->use_cts_prot >= 0) {
7984 }
7985
7986 if (params->use_short_preamble >= 0) {
7987 }
7988
7989 if (params->use_short_slot_time >= 0) {
7990 }
7991
7992 if (params->basic_rates) {
7993 }
7994
7995 if (params->ap_isolate >= 0) {
7996 ap_isolate = params->ap_isolate;
7997 #ifdef PCIE_FULL_DONGLE
7998 ifidx = dhd_net2idx(dhd->info, dev);
7999
8000 if (ifidx != DHD_BAD_IF) {
8001 err = dhd_set_ap_isolate(dhd, ifidx, ap_isolate);
8002 } else {
8003 WL_ERR(("Failed to set ap_isolate\n"));
8004 }
8005 #else
8006 err = wldev_iovar_setint(dev, "ap_isolate", ap_isolate);
8007 if (unlikely(err))
8008 {
8009 WL_ERR(("set ap_isolate Error (%d)\n", err));
8010 }
8011 #endif /* PCIE_FULL_DONGLE */
8012 }
8013
8014 if (params->ht_opmode >= 0) {
8015 }
8016
8017
8018 return err;
8019 }
8020
8021 static s32
8022 wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
8023 struct ieee80211_channel *chan,
8024 enum nl80211_channel_type channel_type)
8025 {
8026 s32 _chan;
8027 chanspec_t chspec = 0;
8028 chanspec_t fw_chspec = 0;
8029 u32 bw = WL_CHANSPEC_BW_20;
8030 #ifdef WL11ULB
8031 u32 ulb_bw = wl_cfg80211_get_ulb_bw(wl_get_cfg(dev), dev->ieee80211_ptr);
8032 #endif /* WL11ULB */
8033
8034 s32 err = BCME_OK;
8035 s32 bw_cap = 0;
8036 struct {
8037 u32 band;
8038 u32 bw_cap;
8039 } param = {0, 0};
8040 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8041 #if defined(CUSTOM_SET_CPUCORE) || (defined(WL_VIRTUAL_APSTA) && \
8042 defined(APSTA_RESTRICTED_CHANNEL))
8043 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8044 #endif /* CUSTOM_SET_CPUCORE || (WL_VIRTUAL_APSTA && APSTA_RESTRICTED_CHANNEL) */
8045
8046 dev = ndev_to_wlc_ndev(dev, cfg);
8047 _chan = ieee80211_frequency_to_channel(chan->center_freq);
8048 printf("%s: netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
8049 __FUNCTION__, dev->ifindex, channel_type, _chan);
8050
8051
8052 #if defined(WL_VIRTUAL_APSTA) && defined(APSTA_RESTRICTED_CHANNEL)
8053 #define DEFAULT_2G_SOFTAP_CHANNEL 1
8054 #define DEFAULT_5G_SOFTAP_CHANNEL 149
8055 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP &&
8056 (dhd->op_mode & DHD_FLAG_CONCURR_STA_HOSTAP_MODE) ==
8057 DHD_FLAG_CONCURR_STA_HOSTAP_MODE &&
8058 wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg))) {
8059 u32 *sta_chan = (u32 *)wl_read_prof(cfg,
8060 bcmcfg_to_prmry_ndev(cfg), WL_PROF_CHAN);
8061 u32 sta_band = (*sta_chan > CH_MAX_2G_CHANNEL) ?
8062 IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
8063 if (chan->band == sta_band) {
8064 /* Do not try SCC in 5GHz if channel is not CH149 */
8065 _chan = (sta_band == IEEE80211_BAND_5GHZ &&
8066 *sta_chan != DEFAULT_5G_SOFTAP_CHANNEL) ?
8067 DEFAULT_2G_SOFTAP_CHANNEL : *sta_chan;
8068 WL_ERR(("target channel will be changed to %d\n", _chan));
8069 if (_chan <= CH_MAX_2G_CHANNEL) {
8070 bw = WL_CHANSPEC_BW_20;
8071 goto set_channel;
8072 }
8073 }
8074 }
8075 #undef DEFAULT_2G_SOFTAP_CHANNEL
8076 #undef DEFAULT_5G_SOFTAP_CHANNEL
8077 #endif /* WL_VIRTUAL_APSTA && APSTA_RESTRICTED_CHANNEL */
8078
8079 #ifdef WL11ULB
8080 if (ulb_bw) {
8081 WL_DBG(("[ULB] setting AP/GO BW to ulb_bw 0x%x \n", ulb_bw));
8082 bw = wl_cfg80211_ulbbw_to_ulbchspec(ulb_bw);
8083 goto set_channel;
8084 }
8085 #endif /* WL11ULB */
8086 if (chan->band == IEEE80211_BAND_5GHZ) {
8087 param.band = WLC_BAND_5G;
8088 err = wldev_iovar_getbuf(dev, "bw_cap", &param, sizeof(param),
8089 cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
8090 if (err) {
8091 if (err != BCME_UNSUPPORTED) {
8092 WL_ERR(("bw_cap failed, %d\n", err));
8093 return err;
8094 } else {
8095 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
8096 if (err) {
8097 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
8098 }
8099 if (bw_cap != WLC_N_BW_20ALL)
8100 bw = WL_CHANSPEC_BW_40;
8101 }
8102 } else {
8103 if (WL_BW_CAP_80MHZ(cfg->ioctl_buf[0]))
8104 bw = WL_CHANSPEC_BW_80;
8105 else if (WL_BW_CAP_40MHZ(cfg->ioctl_buf[0]))
8106 bw = WL_CHANSPEC_BW_40;
8107 else
8108 bw = WL_CHANSPEC_BW_20;
8109
8110 }
8111
8112 } else if (chan->band == IEEE80211_BAND_2GHZ)
8113 bw = WL_CHANSPEC_BW_20;
8114 set_channel:
8115 chspec = wf_channel2chspec(_chan, bw);
8116 if (wf_chspec_valid(chspec)) {
8117 fw_chspec = wl_chspec_host_to_driver(chspec);
8118 if (fw_chspec != INVCHANSPEC) {
8119 if ((err = wldev_iovar_setint(dev, "chanspec",
8120 fw_chspec)) == BCME_BADCHAN) {
8121 if (bw == WL_CHANSPEC_BW_80)
8122 goto change_bw;
8123 err = wldev_ioctl_set(dev, WLC_SET_CHANNEL,
8124 &_chan, sizeof(_chan));
8125 if (err < 0) {
8126 WL_ERR(("WLC_SET_CHANNEL error %d"
8127 "chip may not be supporting this channel\n", err));
8128 }
8129 } else if (err) {
8130 WL_ERR(("failed to set chanspec error %d\n", err));
8131 }
8132 } else {
8133 WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
8134 err = BCME_ERROR;
8135 }
8136 } else {
8137 change_bw:
8138 if (bw == WL_CHANSPEC_BW_80)
8139 bw = WL_CHANSPEC_BW_40;
8140 else if (bw == WL_CHANSPEC_BW_40)
8141 bw = WL_CHANSPEC_BW_20;
8142 else
8143 bw = 0;
8144 if (bw)
8145 goto set_channel;
8146 WL_ERR(("Invalid chanspec 0x%x\n", chspec));
8147 err = BCME_ERROR;
8148 }
8149 #ifdef CUSTOM_SET_CPUCORE
8150 if (dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
8151 WL_DBG(("SoftAP mode do not need to set cpucore\n"));
8152 } else if (chspec & WL_CHANSPEC_BW_80) {
8153 /* SoftAp only mode do not need to set cpucore */
8154 if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) &&
8155 dev != bcmcfg_to_prmry_ndev(cfg)) {
8156 /* Soft AP on virtual Iface (AP+STA case) */
8157 dhd->chan_isvht80 |= DHD_FLAG_HOSTAP_MODE;
8158 dhd_set_cpucore(dhd, TRUE);
8159 } else if (is_p2p_group_iface(dev->ieee80211_ptr)) {
8160 /* If P2P IF is vht80 */
8161 dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE;
8162 dhd_set_cpucore(dhd, TRUE);
8163 }
8164 }
8165 #endif /* CUSTOM_SET_CPUCORE */
8166 if (!err && (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) {
8167 /* Update AP/GO operating channel */
8168 cfg->ap_oper_channel = ieee80211_frequency_to_channel(chan->center_freq);
8169 }
8170 return err;
8171 }
8172
8173 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
8174 struct net_device *
8175 wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg)
8176 {
8177 struct net_info *_net_info, *next;
8178 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
8179 #pragma GCC diagnostic push
8180 #pragma GCC diagnostic ignored "-Wcast-qual"
8181 #endif
8182 list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
8183 if (_net_info->ndev &&
8184 test_bit(WL_STATUS_REMAINING_ON_CHANNEL, &_net_info->sme_state))
8185 return _net_info->ndev;
8186 }
8187 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
8188 #pragma GCC diagnostic pop
8189 #endif
8190 return NULL;
8191 }
8192 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
8193
8194 static s32
8195 wl_validate_opensecurity(struct net_device *dev, s32 bssidx, bool privacy)
8196 {
8197 s32 err = BCME_OK;
8198 u32 wpa_val;
8199 s32 wsec = 0;
8200
8201 /* set auth */
8202 err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
8203 if (err < 0) {
8204 WL_ERR(("auth error %d\n", err));
8205 return BCME_ERROR;
8206 }
8207
8208 if (privacy) {
8209 /* If privacy bit is set in open mode, then WEP would be enabled */
8210 wsec = WEP_ENABLED;
8211 WL_DBG(("Setting wsec to %d for WEP \n", wsec));
8212 }
8213
8214 /* set wsec */
8215 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
8216 if (err < 0) {
8217 WL_ERR(("wsec error %d\n", err));
8218 return BCME_ERROR;
8219 }
8220
8221 /* set upper-layer auth */
8222 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC)
8223 wpa_val = WPA_AUTH_NONE;
8224 else
8225 wpa_val = WPA_AUTH_DISABLED;
8226 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_val, bssidx);
8227 if (err < 0) {
8228 WL_ERR(("wpa_auth error %d\n", err));
8229 return BCME_ERROR;
8230 }
8231
8232 return 0;
8233 }
8234
8235 static s32
8236 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
8237 {
8238 s32 len = 0;
8239 s32 err = BCME_OK;
8240 u16 auth = 0; /* d11 open authentication */
8241 u32 wsec;
8242 u32 pval = 0;
8243 u32 gval = 0;
8244 u32 wpa_auth = 0;
8245 wpa_suite_mcast_t *mcast;
8246 wpa_suite_ucast_t *ucast;
8247 wpa_suite_auth_key_mgmt_t *mgmt;
8248 wpa_pmkid_list_t *pmkid;
8249 int cnt = 0;
8250 #ifdef MFP
8251 int mfp = 0;
8252 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
8253 #endif /* MFP */
8254
8255 u16 suite_count;
8256 u8 rsn_cap[2];
8257 u32 wme_bss_disable;
8258
8259 if (wpa2ie == NULL)
8260 goto exit;
8261
8262 WL_DBG(("Enter \n"));
8263 len = wpa2ie->len - WPA2_VERSION_LEN;
8264 /* check the mcast cipher */
8265 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
8266 switch (mcast->type) {
8267 case WPA_CIPHER_NONE:
8268 gval = 0;
8269 break;
8270 case WPA_CIPHER_WEP_40:
8271 case WPA_CIPHER_WEP_104:
8272 gval = WEP_ENABLED;
8273 break;
8274 case WPA_CIPHER_TKIP:
8275 gval = TKIP_ENABLED;
8276 break;
8277 case WPA_CIPHER_AES_CCM:
8278 gval = AES_ENABLED;
8279 break;
8280 default:
8281 WL_ERR(("No Security Info\n"));
8282 break;
8283 }
8284 if ((len -= WPA_SUITE_LEN) <= 0)
8285 return BCME_BADLEN;
8286
8287 /* check the unicast cipher */
8288 ucast = (wpa_suite_ucast_t *)&mcast[1];
8289 suite_count = ltoh16_ua(&ucast->count);
8290 switch (ucast->list[0].type) {
8291 case WPA_CIPHER_NONE:
8292 pval = 0;
8293 break;
8294 case WPA_CIPHER_WEP_40:
8295 case WPA_CIPHER_WEP_104:
8296 pval = WEP_ENABLED;
8297 break;
8298 case WPA_CIPHER_TKIP:
8299 pval = TKIP_ENABLED;
8300 break;
8301 case WPA_CIPHER_AES_CCM:
8302 pval = AES_ENABLED;
8303 break;
8304 default:
8305 WL_ERR(("No Security Info\n"));
8306 }
8307 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
8308 return BCME_BADLEN;
8309
8310 /* FOR WPS , set SEC_OW_ENABLED */
8311 wsec = (pval | gval | SES_OW_ENABLED);
8312 /* check the AKM */
8313 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
8314 suite_count = cnt = ltoh16_ua(&mgmt->count);
8315 while (cnt--) {
8316 switch (mgmt->list[cnt].type) {
8317 case RSN_AKM_NONE:
8318 wpa_auth |= WPA_AUTH_NONE;
8319 break;
8320 case RSN_AKM_UNSPECIFIED:
8321 wpa_auth |= WPA2_AUTH_UNSPECIFIED;
8322 break;
8323 case RSN_AKM_PSK:
8324 wpa_auth |= WPA2_AUTH_PSK;
8325 break;
8326 #ifdef MFP
8327 case RSN_AKM_MFP_PSK:
8328 wpa_auth |= WPA2_AUTH_PSK_SHA256;
8329 break;
8330 case RSN_AKM_MFP_1X:
8331 wpa_auth |= WPA2_AUTH_1X_SHA256;
8332 break;
8333 #endif /* MFP */
8334 default:
8335 WL_ERR(("No Key Mgmt Info\n"));
8336 }
8337 }
8338
8339 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
8340 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
8341 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
8342
8343 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
8344 wme_bss_disable = 0;
8345 } else {
8346 wme_bss_disable = 1;
8347 }
8348
8349 #ifdef MFP
8350 if (rsn_cap[0] & RSN_CAP_MFPR) {
8351 WL_DBG(("MFP Required \n"));
8352 mfp = WL_MFP_REQUIRED;
8353 /* Our firmware has requirement that WPA2_AUTH_PSK/WPA2_AUTH_UNSPECIFIED
8354 * be set, if SHA256 OUI is to be included in the rsn ie.
8355 */
8356 if (wpa_auth & WPA2_AUTH_PSK_SHA256) {
8357 wpa_auth |= WPA2_AUTH_PSK;
8358 } else if (wpa_auth & WPA2_AUTH_1X_SHA256) {
8359 wpa_auth |= WPA2_AUTH_UNSPECIFIED;
8360 }
8361 } else if (rsn_cap[0] & RSN_CAP_MFPC) {
8362 WL_DBG(("MFP Capable \n"));
8363 mfp = WL_MFP_CAPABLE;
8364 }
8365 #endif /* MFP */
8366
8367 /* set wme_bss_disable to sync RSN Capabilities */
8368 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
8369 if (err < 0) {
8370 WL_ERR(("wme_bss_disable error %d\n", err));
8371 return BCME_ERROR;
8372 }
8373 } else {
8374 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
8375 }
8376
8377 len -= RSN_CAP_LEN;
8378 if (len >= WPA2_PMKID_COUNT_LEN) {
8379 pmkid = (wpa_pmkid_list_t *)((u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN);
8380 cnt = ltoh16_ua(&pmkid->count);
8381 if (cnt != 0) {
8382 WL_ERR(("AP has non-zero PMKID count. Wrong!\n"));
8383 return BCME_ERROR;
8384 }
8385 /* since PMKID cnt is known to be 0 for AP, */
8386 /* so don't bother to send down this info to firmware */
8387 }
8388
8389 #ifdef MFP
8390 len -= WPA2_PMKID_COUNT_LEN;
8391 if (len >= WPA_SUITE_LEN) {
8392 cfg->bip_pos = (u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN + WPA2_PMKID_COUNT_LEN;
8393 } else {
8394 cfg->bip_pos = NULL;
8395 }
8396 #endif
8397
8398 /* set auth */
8399 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
8400 if (err < 0) {
8401 WL_ERR(("auth error %d\n", err));
8402 return BCME_ERROR;
8403 }
8404
8405 /* set wsec */
8406 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
8407 if (err < 0) {
8408 WL_ERR(("wsec error %d\n", err));
8409 return BCME_ERROR;
8410 }
8411
8412 #ifdef MFP
8413 cfg->mfp_mode = mfp;
8414 #endif /* MFP */
8415
8416 /* set upper-layer auth */
8417 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
8418 if (err < 0) {
8419 WL_ERR(("wpa_auth error %d\n", err));
8420 return BCME_ERROR;
8421 }
8422 exit:
8423 return 0;
8424 }
8425
8426 static s32
8427 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
8428 {
8429 wpa_suite_mcast_t *mcast;
8430 wpa_suite_ucast_t *ucast;
8431 wpa_suite_auth_key_mgmt_t *mgmt;
8432 u16 auth = 0; /* d11 open authentication */
8433 u16 count;
8434 s32 err = BCME_OK;
8435 s32 len = 0;
8436 u32 i;
8437 u32 wsec;
8438 u32 pval = 0;
8439 u32 gval = 0;
8440 u32 wpa_auth = 0;
8441 u32 tmp = 0;
8442
8443 if (wpaie == NULL)
8444 goto exit;
8445 WL_DBG(("Enter \n"));
8446 len = wpaie->length; /* value length */
8447 len -= WPA_IE_TAG_FIXED_LEN;
8448 /* check for multicast cipher suite */
8449 if (len < WPA_SUITE_LEN) {
8450 WL_INFORM(("no multicast cipher suite\n"));
8451 goto exit;
8452 }
8453
8454 /* pick up multicast cipher */
8455 mcast = (wpa_suite_mcast_t *)&wpaie[1];
8456 len -= WPA_SUITE_LEN;
8457 if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
8458 if (IS_WPA_CIPHER(mcast->type)) {
8459 tmp = 0;
8460 switch (mcast->type) {
8461 case WPA_CIPHER_NONE:
8462 tmp = 0;
8463 break;
8464 case WPA_CIPHER_WEP_40:
8465 case WPA_CIPHER_WEP_104:
8466 tmp = WEP_ENABLED;
8467 break;
8468 case WPA_CIPHER_TKIP:
8469 tmp = TKIP_ENABLED;
8470 break;
8471 case WPA_CIPHER_AES_CCM:
8472 tmp = AES_ENABLED;
8473 break;
8474 default:
8475 WL_ERR(("No Security Info\n"));
8476 }
8477 gval |= tmp;
8478 }
8479 }
8480 /* Check for unicast suite(s) */
8481 if (len < WPA_IE_SUITE_COUNT_LEN) {
8482 WL_INFORM(("no unicast suite\n"));
8483 goto exit;
8484 }
8485 /* walk thru unicast cipher list and pick up what we recognize */
8486 ucast = (wpa_suite_ucast_t *)&mcast[1];
8487 count = ltoh16_ua(&ucast->count);
8488 len -= WPA_IE_SUITE_COUNT_LEN;
8489 for (i = 0; i < count && len >= WPA_SUITE_LEN;
8490 i++, len -= WPA_SUITE_LEN) {
8491 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
8492 if (IS_WPA_CIPHER(ucast->list[i].type)) {
8493 tmp = 0;
8494 switch (ucast->list[i].type) {
8495 case WPA_CIPHER_NONE:
8496 tmp = 0;
8497 break;
8498 case WPA_CIPHER_WEP_40:
8499 case WPA_CIPHER_WEP_104:
8500 tmp = WEP_ENABLED;
8501 break;
8502 case WPA_CIPHER_TKIP:
8503 tmp = TKIP_ENABLED;
8504 break;
8505 case WPA_CIPHER_AES_CCM:
8506 tmp = AES_ENABLED;
8507 break;
8508 default:
8509 WL_ERR(("No Security Info\n"));
8510 }
8511 pval |= tmp;
8512 }
8513 }
8514 }
8515 len -= (count - i) * WPA_SUITE_LEN;
8516 /* Check for auth key management suite(s) */
8517 if (len < WPA_IE_SUITE_COUNT_LEN) {
8518 WL_INFORM((" no auth key mgmt suite\n"));
8519 goto exit;
8520 }
8521 /* walk thru auth management suite list and pick up what we recognize */
8522 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
8523 count = ltoh16_ua(&mgmt->count);
8524 len -= WPA_IE_SUITE_COUNT_LEN;
8525 for (i = 0; i < count && len >= WPA_SUITE_LEN;
8526 i++, len -= WPA_SUITE_LEN) {
8527 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
8528 if (IS_WPA_AKM(mgmt->list[i].type)) {
8529 tmp = 0;
8530 switch (mgmt->list[i].type) {
8531 case RSN_AKM_NONE:
8532 tmp = WPA_AUTH_NONE;
8533 break;
8534 case RSN_AKM_UNSPECIFIED:
8535 tmp = WPA_AUTH_UNSPECIFIED;
8536 break;
8537 case RSN_AKM_PSK:
8538 tmp = WPA_AUTH_PSK;
8539 break;
8540 default:
8541 WL_ERR(("No Key Mgmt Info\n"));
8542 }
8543 wpa_auth |= tmp;
8544 }
8545 }
8546
8547 }
8548 /* FOR WPS , set SEC_OW_ENABLED */
8549 wsec = (pval | gval | SES_OW_ENABLED);
8550 /* set auth */
8551 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
8552 if (err < 0) {
8553 WL_ERR(("auth error %d\n", err));
8554 return BCME_ERROR;
8555 }
8556 /* set wsec */
8557 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
8558 if (err < 0) {
8559 WL_ERR(("wsec error %d\n", err));
8560 return BCME_ERROR;
8561 }
8562 /* set upper-layer auth */
8563 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
8564 if (err < 0) {
8565 WL_ERR(("wpa_auth error %d\n", err));
8566 return BCME_ERROR;
8567 }
8568 exit:
8569 return 0;
8570 }
8571
8572 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8573 static u32 wl_get_cipher_type(uint8 type)
8574 {
8575 u32 ret = 0;
8576 switch (type) {
8577 case WPA_CIPHER_NONE:
8578 ret = 0;
8579 break;
8580 case WPA_CIPHER_WEP_40:
8581 case WPA_CIPHER_WEP_104:
8582 ret = WEP_ENABLED;
8583 break;
8584 case WPA_CIPHER_TKIP:
8585 ret = TKIP_ENABLED;
8586 break;
8587 case WPA_CIPHER_AES_CCM:
8588 ret = AES_ENABLED;
8589 break;
8590 #ifdef BCMWAPI_WPI
8591 case WAPI_CIPHER_SMS4:
8592 ret = SMS4_ENABLED;
8593 break;
8594 #endif
8595 default:
8596 WL_ERR(("No Security Info\n"));
8597 }
8598 return ret;
8599 }
8600
8601 static u32 wl_get_suite_auth_key_mgmt_type(uint8 type)
8602 {
8603 u32 ret = 0;
8604 switch (type) {
8605 case RSN_AKM_NONE:
8606 ret = WPA_AUTH_NONE;
8607 break;
8608 case RSN_AKM_UNSPECIFIED:
8609 ret = WPA_AUTH_UNSPECIFIED;
8610 break;
8611 case RSN_AKM_PSK:
8612 ret = WPA_AUTH_PSK;
8613 break;
8614 default:
8615 WL_ERR(("No Key Mgmt Info\n"));
8616 }
8617 return ret;
8618 }
8619
8620 static u32 wl_get_suite_auth2_key_mgmt_type(uint8 type)
8621 {
8622 u32 ret = 0;
8623 switch (type) {
8624 case RSN_AKM_NONE:
8625 ret = WPA_AUTH_NONE;
8626 break;
8627 case RSN_AKM_UNSPECIFIED:
8628 ret = WPA2_AUTH_UNSPECIFIED;
8629 break;
8630 case RSN_AKM_PSK:
8631 ret = WPA2_AUTH_PSK;
8632 break;
8633 default:
8634 WL_ERR(("No Key Mgmt Info\n"));
8635 }
8636 return ret;
8637 }
8638
8639 static s32
8640 wl_validate_wpaie_wpa2ie(struct net_device *dev, wpa_ie_fixed_t *wpaie,
8641 bcm_tlv_t *wpa2ie, s32 bssidx)
8642 {
8643 wpa_suite_mcast_t *mcast;
8644 wpa_suite_ucast_t *ucast;
8645 wpa_suite_auth_key_mgmt_t *mgmt;
8646 u16 auth = 0; /* d11 open authentication */
8647 u16 count;
8648 s32 err = BCME_OK;
8649 u32 wme_bss_disable;
8650 u16 suite_count;
8651 u8 rsn_cap[2];
8652 s32 len = 0;
8653 u32 i;
8654 u32 wsec1, wsec2, wsec;
8655 u32 pval = 0;
8656 u32 gval = 0;
8657 u32 wpa_auth = 0;
8658 u32 wpa_auth1 = 0;
8659 u32 wpa_auth2 = 0;
8660 u8* ptmp;
8661
8662 if (wpaie == NULL || wpa2ie == NULL)
8663 goto exit;
8664
8665 WL_DBG(("Enter \n"));
8666 len = wpaie->length; /* value length */
8667 len -= WPA_IE_TAG_FIXED_LEN;
8668 /* check for multicast cipher suite */
8669 if (len < WPA_SUITE_LEN) {
8670 WL_INFORM(("no multicast cipher suite\n"));
8671 goto exit;
8672 }
8673
8674 /* pick up multicast cipher */
8675 mcast = (wpa_suite_mcast_t *)&wpaie[1];
8676 len -= WPA_SUITE_LEN;
8677 if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
8678 if (IS_WPA_CIPHER(mcast->type)) {
8679 gval |= wl_get_cipher_type(mcast->type);
8680 }
8681 }
8682 WL_ERR(("\nwpa ie validate\n"));
8683 WL_ERR(("wpa ie mcast cipher = 0x%X\n", gval));
8684
8685 /* Check for unicast suite(s) */
8686 if (len < WPA_IE_SUITE_COUNT_LEN) {
8687 WL_INFORM(("no unicast suite\n"));
8688 goto exit;
8689 }
8690
8691 /* walk thru unicast cipher list and pick up what we recognize */
8692 ucast = (wpa_suite_ucast_t *)&mcast[1];
8693 count = ltoh16_ua(&ucast->count);
8694 len -= WPA_IE_SUITE_COUNT_LEN;
8695 for (i = 0; i < count && len >= WPA_SUITE_LEN;
8696 i++, len -= WPA_SUITE_LEN) {
8697 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
8698 if (IS_WPA_CIPHER(ucast->list[i].type)) {
8699 pval |= wl_get_cipher_type(ucast->list[i].type);
8700 }
8701 }
8702 }
8703 WL_ERR(("wpa ie ucast count =%d, cipher = 0x%X\n", count, pval));
8704
8705 /* FOR WPS , set SEC_OW_ENABLED */
8706 wsec1 = (pval | gval | SES_OW_ENABLED);
8707 WL_ERR(("wpa ie wsec = 0x%X\n", wsec1));
8708
8709 len -= (count - i) * WPA_SUITE_LEN;
8710 /* Check for auth key management suite(s) */
8711 if (len < WPA_IE_SUITE_COUNT_LEN) {
8712 WL_INFORM((" no auth key mgmt suite\n"));
8713 goto exit;
8714 }
8715 /* walk thru auth management suite list and pick up what we recognize */
8716 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
8717 count = ltoh16_ua(&mgmt->count);
8718 len -= WPA_IE_SUITE_COUNT_LEN;
8719 for (i = 0; i < count && len >= WPA_SUITE_LEN;
8720 i++, len -= WPA_SUITE_LEN) {
8721 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
8722 if (IS_WPA_AKM(mgmt->list[i].type)) {
8723
8724 wpa_auth1 |= wl_get_suite_auth_key_mgmt_type(mgmt->list[i].type);
8725 }
8726 }
8727
8728 }
8729 WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count, wpa_auth1));
8730 WL_ERR(("\nwpa2 ie validate\n"));
8731
8732 pval = 0;
8733 gval = 0;
8734 len = wpa2ie->len;
8735 /* check the mcast cipher */
8736 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
8737 ptmp = mcast->oui;
8738 gval = wl_get_cipher_type(ptmp[DOT11_OUI_LEN]);
8739
8740 WL_ERR(("wpa2 ie mcast cipher = 0x%X\n", gval));
8741 if ((len -= WPA_SUITE_LEN) <= 0)
8742 {
8743 WL_ERR(("P:wpa2 ie len[%d]", len));
8744 return BCME_BADLEN;
8745 }
8746
8747 /* check the unicast cipher */
8748 ucast = (wpa_suite_ucast_t *)&mcast[1];
8749 suite_count = ltoh16_ua(&ucast->count);
8750 WL_ERR((" WPA2 ucast cipher count=%d\n", suite_count));
8751 pval |= wl_get_cipher_type(ucast->list[0].type);
8752
8753 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
8754 return BCME_BADLEN;
8755
8756 WL_ERR(("wpa2 ie ucast cipher = 0x%X\n", pval));
8757
8758 /* FOR WPS , set SEC_OW_ENABLED */
8759 wsec2 = (pval | gval | SES_OW_ENABLED);
8760 WL_ERR(("wpa2 ie wsec = 0x%X\n", wsec2));
8761
8762 /* check the AKM */
8763 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
8764 suite_count = ltoh16_ua(&mgmt->count);
8765 ptmp = (u8 *)&mgmt->list[0];
8766 wpa_auth2 = wl_get_suite_auth2_key_mgmt_type(ptmp[DOT11_OUI_LEN]);
8767 WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count, wpa_auth2));
8768
8769 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
8770 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
8771 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
8772 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
8773 wme_bss_disable = 0;
8774 } else {
8775 wme_bss_disable = 1;
8776 }
8777 WL_DBG(("P:rsn_cap[0]=[0x%X]:wme_bss_disabled[%d]\n", rsn_cap[0], wme_bss_disable));
8778
8779 /* set wme_bss_disable to sync RSN Capabilities */
8780 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
8781 if (err < 0) {
8782 WL_ERR(("wme_bss_disable error %d\n", err));
8783 return BCME_ERROR;
8784 }
8785 } else {
8786 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
8787 }
8788
8789 wsec = (wsec1 | wsec2);
8790 wpa_auth = (wpa_auth1 | wpa_auth2);
8791 WL_ERR(("wpa_wpa2 wsec=0x%X wpa_auth=0x%X\n", wsec, wpa_auth));
8792
8793 /* set auth */
8794 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
8795 if (err < 0) {
8796 WL_ERR(("auth error %d\n", err));
8797 return BCME_ERROR;
8798 }
8799 /* set wsec */
8800 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
8801 if (err < 0) {
8802 WL_ERR(("wsec error %d\n", err));
8803 return BCME_ERROR;
8804 }
8805 /* set upper-layer auth */
8806 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
8807 if (err < 0) {
8808 WL_ERR(("wpa_auth error %d\n", err));
8809 return BCME_ERROR;
8810 }
8811 exit:
8812 return 0;
8813 }
8814 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8815
8816 static s32
8817 wl_cfg80211_bcn_validate_sec(
8818 struct net_device *dev,
8819 struct parsed_ies *ies,
8820 u32 dev_role,
8821 s32 bssidx,
8822 bool privacy)
8823 {
8824 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
8825 wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
8826
8827 if (!bss) {
8828 WL_ERR(("cfgbss is NULL \n"));
8829 return BCME_ERROR;
8830 }
8831
8832 if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
8833 /* For P2P GO, the sec type is WPA2-PSK */
8834 WL_DBG(("P2P GO: validating wpa2_ie"));
8835 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0)
8836 return BCME_ERROR;
8837
8838 } else if (dev_role == NL80211_IFTYPE_AP) {
8839
8840 WL_DBG(("SoftAP: validating security"));
8841 /* If wpa2_ie or wpa_ie is present validate it */
8842
8843 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8844 if ((ies->wpa_ie != NULL && ies->wpa2_ie != NULL)) {
8845 if (wl_validate_wpaie_wpa2ie(dev, ies->wpa_ie, ies->wpa2_ie, bssidx) < 0) {
8846 bss->security_mode = false;
8847 return BCME_ERROR;
8848 }
8849 }
8850 else {
8851 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8852 if ((ies->wpa2_ie || ies->wpa_ie) &&
8853 ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
8854 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
8855 bss->security_mode = false;
8856 return BCME_ERROR;
8857 }
8858
8859 bss->security_mode = true;
8860 if (bss->rsn_ie) {
8861 kfree(bss->rsn_ie);
8862 bss->rsn_ie = NULL;
8863 }
8864 if (bss->wpa_ie) {
8865 kfree(bss->wpa_ie);
8866 bss->wpa_ie = NULL;
8867 }
8868 if (bss->wps_ie) {
8869 kfree(bss->wps_ie);
8870 bss->wps_ie = NULL;
8871 }
8872 if (ies->wpa_ie != NULL) {
8873 /* WPAIE */
8874 bss->rsn_ie = NULL;
8875 bss->wpa_ie = kmemdup(ies->wpa_ie,
8876 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
8877 GFP_KERNEL);
8878 } else if (ies->wpa2_ie != NULL) {
8879 /* RSNIE */
8880 bss->wpa_ie = NULL;
8881 bss->rsn_ie = kmemdup(ies->wpa2_ie,
8882 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
8883 GFP_KERNEL);
8884 }
8885 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8886 }
8887 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8888 if (!ies->wpa2_ie && !ies->wpa_ie) {
8889 wl_validate_opensecurity(dev, bssidx, privacy);
8890 bss->security_mode = false;
8891 }
8892
8893 if (ies->wps_ie) {
8894 bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
8895 }
8896 }
8897
8898 return 0;
8899
8900 }
8901
8902 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
8903 static s32 wl_cfg80211_bcn_set_params(
8904 struct cfg80211_ap_settings *info,
8905 struct net_device *dev,
8906 u32 dev_role, s32 bssidx)
8907 {
8908 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
8909 s32 err = BCME_OK;
8910
8911 WL_DBG(("interval (%d) \ndtim_period (%d) \n",
8912 info->beacon_interval, info->dtim_period));
8913
8914 if (info->beacon_interval) {
8915 if ((err = wldev_ioctl_set(dev, WLC_SET_BCNPRD,
8916 &info->beacon_interval, sizeof(s32))) < 0) {
8917 WL_ERR(("Beacon Interval Set Error, %d\n", err));
8918 return err;
8919 }
8920 }
8921
8922 if (info->dtim_period) {
8923 if ((err = wldev_ioctl_set(dev, WLC_SET_DTIMPRD,
8924 &info->dtim_period, sizeof(s32))) < 0) {
8925 WL_ERR(("DTIM Interval Set Error, %d\n", err));
8926 return err;
8927 }
8928 }
8929
8930 if ((info->ssid) && (info->ssid_len > 0) &&
8931 (info->ssid_len <= DOT11_MAX_SSID_LEN)) {
8932 WL_DBG(("SSID (%s) len:%zd \n", info->ssid, info->ssid_len));
8933 if (dev_role == NL80211_IFTYPE_AP) {
8934 /* Store the hostapd SSID */
8935 memset(cfg->hostapd_ssid.SSID, 0x00, DOT11_MAX_SSID_LEN);
8936 memcpy(cfg->hostapd_ssid.SSID, info->ssid, info->ssid_len);
8937 cfg->hostapd_ssid.SSID_len = info->ssid_len;
8938 } else {
8939 /* P2P GO */
8940 memset(cfg->p2p->ssid.SSID, 0x00, DOT11_MAX_SSID_LEN);
8941 memcpy(cfg->p2p->ssid.SSID, info->ssid, info->ssid_len);
8942 cfg->p2p->ssid.SSID_len = info->ssid_len;
8943 }
8944 }
8945
8946 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE) {
8947 if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
8948 WL_ERR(("failed to set hidden : %d\n", err));
8949 WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
8950 }
8951
8952 return err;
8953 }
8954 #endif
8955
8956 static s32
8957 wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
8958 {
8959 s32 err = BCME_OK;
8960
8961 memset(ies, 0, sizeof(struct parsed_ies));
8962
8963 /* find the WPSIE */
8964 if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
8965 WL_DBG(("WPSIE in beacon \n"));
8966 ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
8967 } else {
8968 WL_DBG(("No WPSIE in beacon \n"));
8969 }
8970
8971 /* find the RSN_IE */
8972 if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
8973 DOT11_MNG_RSN_ID)) != NULL) {
8974 WL_DBG((" WPA2 IE found\n"));
8975 ies->wpa2_ie_len = ies->wpa2_ie->len;
8976 }
8977
8978 /* find the WPA_IE */
8979 if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
8980 WL_DBG((" WPA found\n"));
8981 ies->wpa_ie_len = ies->wpa_ie->length;
8982 }
8983
8984 return err;
8985
8986 }
8987 static s32
8988 wl_cfg80211_set_ap_role(
8989 struct bcm_cfg80211 *cfg,
8990 struct net_device *dev)
8991 {
8992 s32 err = BCME_OK;
8993 s32 infra = 1;
8994 s32 ap = 1;
8995 s32 pm;
8996 s32 is_rsdb_supported = BCME_ERROR;
8997 s32 bssidx;
8998 s32 apsta = 0;
8999
9000 is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
9001 if (is_rsdb_supported < 0)
9002 return (-ENODEV);
9003
9004 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
9005 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
9006 return -EINVAL;
9007 }
9008
9009 /* AP on primary Interface */
9010 if (bssidx == 0) {
9011 if (is_rsdb_supported) {
9012 if ((err = wl_cfg80211_add_del_bss(cfg, dev, bssidx,
9013 NL80211_IFTYPE_AP, 0, NULL)) < 0) {
9014 WL_ERR(("wl add_del_bss returned error:%d\n", err));
9015 return err;
9016 }
9017 } else if (is_rsdb_supported == 0) {
9018 /* AP mode switch not supported. Try setting up AP explicitly */
9019 err = wldev_iovar_getint(dev, "apsta", (s32 *)&apsta);
9020 if (unlikely(err)) {
9021 WL_ERR(("Could not get apsta %d\n", err));
9022 }
9023 if (1) { // terence: fix me
9024 /* If apsta is not set, set it */
9025 err = wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
9026 if (err < 0) {
9027 WL_ERR(("WLC_DOWN error %d\n", err));
9028 return err;
9029 }
9030 err = wldev_iovar_setint(dev, "apsta", 0);
9031 if (err < 0) {
9032 WL_ERR(("wl apsta 0 error %d\n", err));
9033 return err;
9034 }
9035 if ((err = wldev_ioctl_set(dev,
9036 WLC_SET_AP, &ap, sizeof(s32))) < 0) {
9037 WL_ERR(("setting AP mode failed %d \n", err));
9038 return err;
9039 }
9040 }
9041 }
9042
9043 pm = 0;
9044 if ((err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm))) != 0) {
9045 WL_ERR(("wl PM 0 returned error:%d\n", err));
9046 /* Ignore error, if any */
9047 err = BCME_OK;
9048 }
9049 err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
9050 if (err < 0) {
9051 WL_ERR(("SET INFRA error %d\n", err));
9052 return err;
9053 }
9054 } else {
9055 WL_DBG(("Bringup SoftAP on virtual Interface bssidx:%d \n", bssidx));
9056 if ((err = wl_cfg80211_add_del_bss(cfg, dev,
9057 bssidx, NL80211_IFTYPE_AP, 0, NULL)) < 0) {
9058 WL_ERR(("wl bss ap returned error:%d\n", err));
9059 return err;
9060 }
9061 }
9062
9063 /* On success, mark AP creation in progress. */
9064 wl_set_drv_status(cfg, AP_CREATING, dev);
9065 return 0;
9066 }
9067
9068
9069 /* In RSDB downgrade cases, the link up event can get delayed upto 7-8 secs */
9070 #define MAX_AP_LINK_WAIT_TIME 10000
9071 static s32
9072 wl_cfg80211_bcn_bringup_ap(
9073 struct net_device *dev,
9074 struct parsed_ies *ies,
9075 u32 dev_role, s32 bssidx)
9076 {
9077 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
9078 struct wl_join_params join_params;
9079 bool is_bssup = false;
9080 s32 infra = 1;
9081 s32 join_params_size = 0;
9082 s32 ap = 1;
9083 s32 wsec;
9084 #ifdef WLMESH
9085 bool retried = false;
9086 #endif
9087 #ifdef SOFTAP_UAPSD_OFF
9088 uint32 wme_apsd = 0;
9089 #endif /* SOFTAP_UAPSD_OFF */
9090 s32 err = BCME_OK;
9091 s32 is_rsdb_supported = BCME_ERROR;
9092 u32 timeout;
9093 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
9094 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
9095 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
9096
9097 is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
9098 if (is_rsdb_supported < 0)
9099 return (-ENODEV);
9100
9101 WL_DBG(("Enter dev_role:%d bssidx:%d ifname:%s\n", dev_role, bssidx, dev->name));
9102
9103 /* Common code for SoftAP and P2P GO */
9104 wl_clr_drv_status(cfg, AP_CREATED, dev);
9105
9106 /* Make sure INFRA is set for AP/GO */
9107 err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
9108 if (err < 0) {
9109 WL_ERR(("SET INFRA error %d\n", err));
9110 goto exit;
9111 }
9112
9113 /* Do abort scan before creating GO */
9114 wl_cfg80211_scan_abort(cfg);
9115
9116 if (dev_role == NL80211_IFTYPE_P2P_GO) {
9117 is_bssup = wl_cfg80211_bss_isup(dev, bssidx);
9118 if (!is_bssup && (ies->wpa2_ie != NULL)) {
9119
9120 err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &cfg->p2p->ssid,
9121 sizeof(cfg->p2p->ssid), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
9122 bssidx, &cfg->ioctl_buf_sync);
9123 if (err < 0) {
9124 WL_ERR(("GO SSID setting error %d\n", err));
9125 goto exit;
9126 }
9127
9128 if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 1)) < 0) {
9129 WL_ERR(("GO Bring up error %d\n", err));
9130 goto exit;
9131 }
9132 } else
9133 WL_DBG(("Bss is already up\n"));
9134 } else if (dev_role == NL80211_IFTYPE_AP) {
9135
9136 // if (!wl_get_drv_status(cfg, AP_CREATING, dev)) {
9137 /* Make sure fw is in proper state */
9138 err = wl_cfg80211_set_ap_role(cfg, dev);
9139 if (unlikely(err)) {
9140 WL_ERR(("set ap role failed!\n"));
9141 goto exit;
9142 }
9143 // }
9144
9145 /* Device role SoftAP */
9146 WL_DBG(("Creating AP bssidx:%d dev_role:%d\n", bssidx, dev_role));
9147 /* Clear the status bit after use */
9148 wl_clr_drv_status(cfg, AP_CREATING, dev);
9149
9150
9151 #ifdef SOFTAP_UAPSD_OFF
9152 err = wldev_iovar_setbuf_bsscfg(dev, "wme_apsd", &wme_apsd, sizeof(wme_apsd),
9153 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
9154 if (err < 0) {
9155 WL_ERR(("failed to disable uapsd, error=%d\n", err));
9156 }
9157 #endif /* SOFTAP_UAPSD_OFF */
9158 dhd_conf_set_wme(cfg->pub, 1);
9159
9160 err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
9161 if (unlikely(err)) {
9162 WL_ERR(("WLC_UP error (%d)\n", err));
9163 goto exit;
9164 }
9165
9166 #ifdef MFP
9167 if (cfg->bip_pos) {
9168 err = wldev_iovar_setbuf_bsscfg(dev, "bip",
9169 (void *)(cfg->bip_pos), WPA_SUITE_LEN, cfg->ioctl_buf,
9170 WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
9171 if (err < 0) {
9172 WL_ERR(("bip set error %d\n", err));
9173 if (wl_customer6_legacy_chip_check(cfg,
9174 bcmcfg_to_prmry_ndev(cfg))) {
9175 /* Ignore bip error: Some older firmwares doesn't
9176 * support bip iovar/ return BCME_NOTUP while trying
9177 * to set bip from AP bring up context. These firmares
9178 * include bip in RSNIE by default. So its okay to ignore
9179 * the error.
9180 */
9181 err = BCME_OK;
9182 } else {
9183 goto exit;
9184 }
9185 }
9186 }
9187 #endif /* MFP */
9188
9189 err = wldev_iovar_getint(dev, "wsec", (s32 *)&wsec);
9190 if (unlikely(err)) {
9191 WL_ERR(("Could not get wsec %d\n", err));
9192 goto exit;
9193 }
9194 if ((wsec == WEP_ENABLED) && cfg->wep_key.len) {
9195 WL_DBG(("Applying buffered WEP KEY \n"));
9196 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &cfg->wep_key,
9197 sizeof(struct wl_wsec_key), cfg->ioctl_buf,
9198 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
9199 /* clear the key after use */
9200 memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
9201 if (unlikely(err)) {
9202 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
9203 goto exit;
9204 }
9205 }
9206
9207 #ifdef MFP
9208 if (cfg->mfp_mode) {
9209 /* This needs to go after wsec otherwise the wsec command will
9210 * overwrite the values set by MFP
9211 */
9212 err = wldev_iovar_setint_bsscfg(dev, "mfp", cfg->mfp_mode, bssidx);
9213 if (err < 0) {
9214 WL_ERR(("MFP Setting failed. ret = %d \n", err));
9215 /* If fw doesn't support mfp, Ignore the error */
9216 if (err != BCME_UNSUPPORTED) {
9217 goto exit;
9218 }
9219 }
9220 }
9221 #endif /* MFP */
9222
9223 #ifdef WLMESH
9224 ssid_retry:
9225 #endif
9226 memset(&join_params, 0, sizeof(join_params));
9227 /* join parameters starts with ssid */
9228 join_params_size = sizeof(join_params.ssid);
9229 join_params.ssid.SSID_len = MIN(cfg->hostapd_ssid.SSID_len,
9230 (uint32)DOT11_MAX_SSID_LEN);
9231 memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
9232 join_params.ssid.SSID_len);
9233 join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
9234
9235 /* create softap */
9236 if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
9237 join_params_size)) != 0) {
9238 WL_ERR(("SoftAP/GO set ssid failed! \n"));
9239 goto exit;
9240 } else {
9241 WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
9242 }
9243
9244 if (bssidx != 0) {
9245 /* AP on Virtual Interface */
9246 if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 1)) < 0) {
9247 WL_ERR(("AP Bring up error %d\n", err));
9248 goto exit;
9249 }
9250 }
9251
9252 }
9253
9254 /* Wait for Linkup event to mark successful AP/GO bring up */
9255 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
9256 wl_get_drv_status(cfg, AP_CREATED, dev), msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
9257 if (timeout <= 0 || !wl_get_drv_status(cfg, AP_CREATED, dev)) {
9258 #ifdef WLMESH
9259 if (!retried) {
9260 retried = true;
9261 WL_ERR(("Link up didn't come for AP interface. Try to set ssid again to recover it! \n"));
9262 goto ssid_retry;
9263 }
9264 #endif
9265 WL_ERR(("Link up didn't come for AP interface. AP/GO creation failed! \n"));
9266 if (timeout == -ERESTARTSYS) {
9267 WL_ERR(("waitqueue was interrupted by a signal, returns -ERESTARTSYS\n"));
9268 err = -ERESTARTSYS;
9269 goto exit;
9270 }
9271 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
9272 if (dhdp->memdump_enabled) {
9273 dhdp->memdump_type = DUMP_TYPE_AP_LINKUP_FAILURE;
9274 dhd_bus_mem_dump(dhdp);
9275 }
9276 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
9277 err = -ENODEV;
9278 goto exit;
9279 }
9280
9281 exit:
9282 if (cfg->wep_key.len) {
9283 memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
9284 }
9285
9286 #ifdef MFP
9287 if (cfg->mfp_mode) {
9288 cfg->mfp_mode = 0;
9289 }
9290
9291 if (cfg->bip_pos) {
9292 cfg->bip_pos = NULL;
9293 }
9294 #endif /* MFP */
9295
9296 return err;
9297 }
9298
9299 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9300 s32
9301 wl_cfg80211_parse_ap_ies(
9302 struct net_device *dev,
9303 struct cfg80211_beacon_data *info,
9304 struct parsed_ies *ies)
9305 {
9306 struct parsed_ies prb_ies;
9307 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
9308 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
9309 const u8 *vndr = NULL;
9310 u32 vndr_ie_len = 0;
9311 s32 err = BCME_OK;
9312
9313 /* Parse Beacon IEs */
9314 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9315 #pragma GCC diagnostic push
9316 #pragma GCC diagnostic ignored "-Wcast-qual"
9317 #endif
9318 if (wl_cfg80211_parse_ies((u8 *)info->tail,
9319 info->tail_len, ies) < 0) {
9320 WL_ERR(("Beacon get IEs failed \n"));
9321 err = -EINVAL;
9322 goto fail;
9323 }
9324 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9325 #pragma GCC diagnostic pop
9326 #endif
9327 vndr = (const u8 *)info->proberesp_ies;
9328 vndr_ie_len = info->proberesp_ies_len;
9329
9330 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
9331 /* SoftAP mode */
9332 const struct ieee80211_mgmt *mgmt;
9333 mgmt = (const struct ieee80211_mgmt *)info->probe_resp;
9334 if (mgmt != NULL) {
9335 vndr = (const u8 *)&mgmt->u.probe_resp.variable;
9336 vndr_ie_len = info->probe_resp_len -
9337 offsetof(const struct ieee80211_mgmt, u.probe_resp.variable);
9338 }
9339 }
9340 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9341 #pragma GCC diagnostic push
9342 #pragma GCC diagnostic ignored "-Wcast-qual"
9343 #endif
9344 /* Parse Probe Response IEs */
9345 if (wl_cfg80211_parse_ies((u8 *)vndr, vndr_ie_len, &prb_ies) < 0) {
9346 WL_ERR(("PROBE RESP get IEs failed \n"));
9347 err = -EINVAL;
9348 }
9349 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9350 #pragma GCC diagnostic pop
9351 #endif
9352 fail:
9353
9354 return err;
9355 }
9356
9357 s32
9358 wl_cfg80211_set_ies(
9359 struct net_device *dev,
9360 struct cfg80211_beacon_data *info,
9361 s32 bssidx)
9362 {
9363 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
9364 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
9365 const u8 *vndr = NULL;
9366 u32 vndr_ie_len = 0;
9367 s32 err = BCME_OK;
9368
9369 /* Set Beacon IEs to FW */
9370 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
9371 VNDR_IE_BEACON_FLAG, (const u8 *)info->tail,
9372 info->tail_len)) < 0) {
9373 WL_ERR(("Set Beacon IE Failed \n"));
9374 } else {
9375 WL_DBG(("Applied Vndr IEs for Beacon \n"));
9376 }
9377
9378 vndr = (const u8 *)info->proberesp_ies;
9379 vndr_ie_len = info->proberesp_ies_len;
9380
9381 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
9382 /* SoftAP mode */
9383 const struct ieee80211_mgmt *mgmt;
9384 mgmt = (const struct ieee80211_mgmt *)info->probe_resp;
9385 if (mgmt != NULL) {
9386 vndr = (const u8 *)&mgmt->u.probe_resp.variable;
9387 vndr_ie_len = info->probe_resp_len -
9388 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
9389 }
9390 }
9391
9392 /* Set Probe Response IEs to FW */
9393 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
9394 VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
9395 WL_ERR(("Set Probe Resp IE Failed \n"));
9396 } else {
9397 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
9398 }
9399
9400 return err;
9401 }
9402 #endif
9403
9404 static s32 wl_cfg80211_hostapd_sec(
9405 struct net_device *dev,
9406 struct parsed_ies *ies,
9407 s32 bssidx)
9408 {
9409 bool update_bss = 0;
9410 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
9411 wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
9412
9413 if (!bss) {
9414 WL_ERR(("cfgbss is NULL \n"));
9415 return -EINVAL;
9416 }
9417
9418 if (ies->wps_ie) {
9419 if (bss->wps_ie &&
9420 memcmp(bss->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
9421 WL_DBG((" WPS IE is changed\n"));
9422 kfree(bss->wps_ie);
9423 bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
9424 } else if (bss->wps_ie == NULL) {
9425 WL_DBG((" WPS IE is added\n"));
9426 bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
9427 }
9428
9429 if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
9430 if (!bss->security_mode) {
9431 /* change from open mode to security mode */
9432 update_bss = true;
9433 if (ies->wpa_ie != NULL) {
9434 bss->wpa_ie = kmemdup(ies->wpa_ie,
9435 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
9436 GFP_KERNEL);
9437 } else {
9438 bss->rsn_ie = kmemdup(ies->wpa2_ie,
9439 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
9440 GFP_KERNEL);
9441 }
9442 } else if (bss->wpa_ie) {
9443 /* change from WPA2 mode to WPA mode */
9444 if (ies->wpa_ie != NULL) {
9445 update_bss = true;
9446 kfree(bss->rsn_ie);
9447 bss->rsn_ie = NULL;
9448 bss->wpa_ie = kmemdup(ies->wpa_ie,
9449 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
9450 GFP_KERNEL);
9451 } else if (memcmp(bss->rsn_ie,
9452 ies->wpa2_ie, ies->wpa2_ie->len
9453 + WPA_RSN_IE_TAG_FIXED_LEN)) {
9454 update_bss = true;
9455 kfree(bss->rsn_ie);
9456 bss->rsn_ie = kmemdup(ies->wpa2_ie,
9457 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
9458 GFP_KERNEL);
9459 bss->wpa_ie = NULL;
9460 }
9461 }
9462 if (update_bss) {
9463 bss->security_mode = true;
9464 wl_cfg80211_bss_up(cfg, dev, bssidx, 0);
9465 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
9466 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
9467 return BCME_ERROR;
9468 }
9469 wl_cfg80211_bss_up(cfg, dev, bssidx, 1);
9470 }
9471 }
9472 } else {
9473 WL_ERR(("No WPSIE in beacon \n"));
9474 }
9475 return 0;
9476 }
9477
9478 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
9479 2, 0))
9480 static s32
9481 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9482 wl_cfg80211_del_station(
9483 struct wiphy *wiphy, struct net_device *ndev,
9484 struct station_del_parameters *params)
9485 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9486 wl_cfg80211_del_station(
9487 struct wiphy *wiphy,
9488 struct net_device *ndev,
9489 const u8* mac_addr)
9490 #else
9491 wl_cfg80211_del_station(
9492 struct wiphy *wiphy,
9493 struct net_device *ndev,
9494 u8* mac_addr)
9495 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9496 {
9497 struct net_device *dev;
9498 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
9499 scb_val_t scb_val;
9500 s8 eabuf[ETHER_ADDR_STR_LEN];
9501 int err;
9502 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
9503 sizeof(struct ether_addr) + sizeof(uint)] = {0};
9504 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
9505 int num_associated = 0;
9506
9507 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9508 const u8 *mac_addr = params->mac;
9509 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9510 u16 rc = params->reason_code;
9511 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9512 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9513 WL_DBG(("Entry\n"));
9514 if (mac_addr == NULL) {
9515 WL_DBG(("mac_addr is NULL ignore it\n"));
9516 return 0;
9517 }
9518
9519 dev = ndev_to_wlc_ndev(ndev, cfg);
9520
9521 if (p2p_is_on(cfg)) {
9522 /* Suspend P2P discovery search-listen to prevent it from changing the
9523 * channel.
9524 */
9525 if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
9526 WL_ERR(("Can not disable discovery mode\n"));
9527 return -EFAULT;
9528 }
9529 }
9530
9531 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
9532 err = wldev_ioctl_get(ndev, WLC_GET_ASSOCLIST,
9533 assoc_maclist, sizeof(mac_buf));
9534 if (err < 0)
9535 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
9536 else
9537 num_associated = assoc_maclist->count;
9538
9539 memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
9540 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9541 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9542 if (rc == DOT11_RC_8021X_AUTH_FAIL) {
9543 WL_ERR(("deauth will be sent at F/W\n"));
9544 scb_val.val = DOT11_RC_8021X_AUTH_FAIL;
9545 } else {
9546 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9547 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9548 dhd_wait_pend8021x(dev);
9549 scb_val.val = DOT11_RC_DEAUTH_LEAVING;
9550 err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
9551 sizeof(scb_val_t));
9552 if (err < 0)
9553 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
9554 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9555 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9556 }
9557 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9558 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9559 printf("%s: Disconnect STA : %s scb_val.val %d\n", __FUNCTION__,
9560 bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
9561 scb_val.val);
9562
9563 if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
9564 wl_delay(400);
9565
9566 return 0;
9567 }
9568
9569 static s32
9570 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9571 wl_cfg80211_change_station(
9572 struct wiphy *wiphy,
9573 struct net_device *dev,
9574 const u8 *mac,
9575 struct station_parameters *params)
9576 #else
9577 wl_cfg80211_change_station(
9578 struct wiphy *wiphy,
9579 struct net_device *dev,
9580 u8 *mac,
9581 struct station_parameters *params)
9582 #endif
9583 {
9584 int err;
9585 #if defined(WL_ENABLE_P2P_IF)
9586 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
9587 #endif
9588 struct net_device *ndev = ndev_to_wlc_ndev(dev, cfg);
9589
9590 WL_DBG(("SCB_AUTHORIZE mac_addr:"MACDBG" sta_flags_mask:0x%x "
9591 "sta_flags_set:0x%x iface:%s \n", MAC2STRDBG(mac),
9592 params->sta_flags_mask, params->sta_flags_set, ndev->name));
9593
9594 /* Processing only authorize/de-authorize flag for now */
9595 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
9596 WL_ERR(("WLC_SCB_AUTHORIZE sta_flags_mask not set \n"));
9597 return -ENOTSUPP;
9598 }
9599
9600 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
9601 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9602 err = wldev_ioctl_set(ndev, WLC_SCB_DEAUTHORIZE, (u8 *)mac, ETH_ALEN);
9603 #else
9604 err = wldev_ioctl_set(ndev, WLC_SCB_DEAUTHORIZE, mac, ETH_ALEN);
9605 #endif
9606 if (err)
9607 WL_ERR(("WLC_SCB_DEAUTHORIZE error (%d)\n", err));
9608 return err;
9609 }
9610
9611 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9612 err = wldev_ioctl_set(ndev, WLC_SCB_AUTHORIZE, (u8 *)mac, ETH_ALEN);
9613 #else
9614 err = wldev_ioctl_set(ndev, WLC_SCB_AUTHORIZE, mac, ETH_ALEN);
9615 #endif
9616 if (err)
9617 WL_ERR(("WLC_SCB_AUTHORIZE error (%d)\n", err));
9618 #ifdef DHD_LOSSLESS_ROAMING
9619 wl_del_roam_timeout(cfg);
9620 #endif
9621 return err;
9622 }
9623 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
9624
9625 static s32
9626 wl_cfg80211_set_scb_timings(
9627 struct bcm_cfg80211 *cfg,
9628 struct net_device *dev)
9629 {
9630 int err;
9631 u32 ps_pretend;
9632 wl_scb_probe_t scb_probe;
9633
9634 bzero(&scb_probe, sizeof(wl_scb_probe_t));
9635 scb_probe.scb_timeout = WL_SCB_TIMEOUT;
9636 scb_probe.scb_activity_time = WL_SCB_ACTIVITY_TIME;
9637 scb_probe.scb_max_probe = WL_SCB_MAX_PROBE;
9638 err = wldev_iovar_setbuf(dev, "scb_probe", (void *)&scb_probe,
9639 sizeof(wl_scb_probe_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
9640 &cfg->ioctl_buf_sync);
9641 if (unlikely(err)) {
9642 WL_ERR(("set 'scb_probe' failed, error = %d\n", err));
9643 return err;
9644 }
9645
9646 ps_pretend = MAX(WL_SCB_MAX_PROBE / 2, WL_MIN_PSPRETEND_THRESHOLD);
9647 err = wldev_iovar_setint(dev, "pspretend_threshold", ps_pretend);
9648 if (unlikely(err)) {
9649 if (err == BCME_UNSUPPORTED) {
9650 /* Ignore error if fw doesn't support the iovar */
9651 WL_DBG(("wl pspretend_threshold %d set error %d\n",
9652 ps_pretend, err));
9653 } else {
9654 WL_ERR(("wl pspretend_threshold %d set error %d\n",
9655 ps_pretend, err));
9656 return err;
9657 }
9658 }
9659
9660 return 0;
9661 }
9662
9663 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9664 static s32
9665 wl_cfg80211_start_ap(
9666 struct wiphy *wiphy,
9667 struct net_device *dev,
9668 struct cfg80211_ap_settings *info)
9669 {
9670 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
9671 s32 err = BCME_OK;
9672 struct parsed_ies ies;
9673 s32 bssidx = 0;
9674 u32 dev_role = 0;
9675 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
9676 #ifdef WLMESH
9677 struct wl_join_params join_params;
9678 s32 join_params_size = 0;
9679 #endif
9680
9681 WL_DBG(("Enter \n"));
9682
9683 #if defined(SUPPORT_RANDOM_MAC_SCAN)
9684 wl_cfg80211_set_random_mac(dev, FALSE);
9685 #endif /* SUPPORT_RANDOM_MAC_SCAN */
9686
9687 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
9688 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
9689 return BCME_ERROR;
9690 }
9691
9692 if (p2p_is_on(cfg) && (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) {
9693 dev_role = NL80211_IFTYPE_P2P_GO;
9694 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
9695 dev_role = NL80211_IFTYPE_AP;
9696 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
9697 err = dhd_ndo_enable(dhd, FALSE);
9698 WL_DBG(("%s: Disabling NDO on Hostapd mode %d\n", __FUNCTION__, err));
9699 if (err) {
9700 WL_ERR(("%s: Disabling NDO Failed %d\n", __FUNCTION__, err));
9701 }
9702 #ifdef PKT_FILTER_SUPPORT
9703 /* Disable packet filter */
9704 if (dhd->early_suspended) {
9705 WL_ERR(("Disable pkt_filter\n"));
9706 dhd_enable_packet_filter(0, dhd);
9707 }
9708 #endif /* PKT_FILTER_SUPPORT */
9709 #ifdef ARP_OFFLOAD_SUPPORT
9710 /* IF SoftAP is enabled, disable arpoe */
9711 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
9712 dhd_arp_offload_set(dhd, 0);
9713 dhd_arp_offload_enable(dhd, FALSE);
9714 }
9715 #endif /* ARP_OFFLOAD_SUPPORT */
9716 #ifdef SUPPORT_SET_CAC
9717 wl_cfg80211_set_cac(cfg, 0);
9718 #endif /* SUPPORT_SET_CAC */
9719 } else {
9720 /* only AP or GO role need to be handled here. */
9721 err = -EINVAL;
9722 goto fail;
9723 }
9724
9725 /* disable TDLS */
9726 #ifdef WLTDLS
9727 if (bssidx == 0) {
9728 /* Disable TDLS for primary Iface. For virtual interface,
9729 * tdls disable will happen from interface create context
9730 */
9731 wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_CREATE, false);
9732 }
9733 #endif /* WLTDLS */
9734
9735 if (!check_dev_role_integrity(cfg, dev_role)) {
9736 err = -EINVAL;
9737 goto fail;
9738 }
9739
9740 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9741 if ((err = wl_cfg80211_set_channel(wiphy, dev,
9742 dev->ieee80211_ptr->preset_chandef.chan,
9743 NL80211_CHAN_HT20) < 0)) {
9744 WL_ERR(("Set channel failed \n"));
9745 goto fail;
9746 }
9747 #endif
9748
9749 if ((err = wl_cfg80211_bcn_set_params(info, dev,
9750 dev_role, bssidx)) < 0) {
9751 WL_ERR(("Beacon params set failed \n"));
9752 goto fail;
9753 }
9754
9755 /* Parse IEs */
9756 if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
9757 WL_ERR(("Set IEs failed \n"));
9758 goto fail;
9759 }
9760
9761 if ((err = wl_cfg80211_bcn_validate_sec(dev, &ies,
9762 dev_role, bssidx, info->privacy)) < 0)
9763 {
9764 WL_ERR(("Beacon set security failed \n"));
9765 goto fail;
9766 }
9767
9768 if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
9769 dev_role, bssidx)) < 0) {
9770 WL_ERR(("Beacon bring up AP/GO failed \n"));
9771 goto fail;
9772 }
9773
9774 /* Set GC/STA SCB expiry timings. */
9775 if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
9776 WL_ERR(("scb setting failed \n"));
9777 // goto fail;
9778 }
9779
9780 #ifdef WLMESH
9781 OSL_SLEEP(1000);
9782 if ((dev_role == NL80211_IFTYPE_P2P_GO) || (dev_role == NL80211_IFTYPE_AP)) {
9783 memset(&join_params, 0, sizeof(join_params));
9784 /* join parameters starts with ssid */
9785 join_params_size = sizeof(join_params.ssid);
9786 if (dev_role == NL80211_IFTYPE_P2P_GO) {
9787 join_params.ssid.SSID_len = min(cfg->p2p->ssid.SSID_len,
9788 (uint32)DOT11_MAX_SSID_LEN);
9789 memcpy(join_params.ssid.SSID, cfg->p2p->ssid.SSID,
9790 join_params.ssid.SSID_len);
9791 } else if (dev_role == NL80211_IFTYPE_AP) {
9792 join_params.ssid.SSID_len = min(cfg->hostapd_ssid.SSID_len,
9793 (uint32)DOT11_MAX_SSID_LEN);
9794 memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
9795 join_params.ssid.SSID_len);
9796 }
9797 join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
9798 /* create softap */
9799 if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
9800 join_params_size)) != 0) {
9801 WL_ERR(("SoftAP/GO set ssid failed! \n"));
9802 goto fail;
9803 } else {
9804 WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
9805 }
9806 }
9807 #endif
9808
9809 WL_DBG(("** AP/GO Created **\n"));
9810
9811 #ifdef WL_CFG80211_ACL
9812 /* Enfoce Admission Control. */
9813 if ((err = wl_cfg80211_set_mac_acl(wiphy, dev, info->acl)) < 0) {
9814 WL_ERR(("Set ACL failed\n"));
9815 }
9816 #endif /* WL_CFG80211_ACL */
9817
9818 /* Set IEs to FW */
9819 if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
9820 WL_ERR(("Set IEs failed \n"));
9821
9822 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
9823 if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
9824 bool pbc = 0;
9825 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
9826 if (pbc) {
9827 WL_DBG(("set WLC_E_PROBREQ_MSG\n"));
9828 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
9829 }
9830 }
9831
9832 #ifdef SUPPORT_AP_RADIO_PWRSAVE
9833 if ((dev_role == NL80211_IFTYPE_AP)) {
9834 wl_set_ap_rps(dev, FALSE, dev->name);
9835 wl_cfg80211_init_ap_rps(cfg);
9836 }
9837 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
9838 fail:
9839 if (err) {
9840 WL_ERR(("ADD/SET beacon failed\n"));
9841 wl_cfg80211_stop_ap(wiphy, dev);
9842 if (dev_role == NL80211_IFTYPE_AP) {
9843 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
9844 #ifdef PKT_FILTER_SUPPORT
9845 /* Enable packet filter */
9846 if (dhd->early_suspended) {
9847 WL_ERR(("Enable pkt_filter\n"));
9848 dhd_enable_packet_filter(1, dhd);
9849 }
9850 #endif /* PKT_FILTER_SUPPORT */
9851 #ifdef ARP_OFFLOAD_SUPPORT
9852 /* IF SoftAP is disabled, enable arpoe back for STA mode. */
9853 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
9854 dhd_arp_offload_set(dhd, dhd_arp_mode);
9855 dhd_arp_offload_enable(dhd, TRUE);
9856 }
9857 #endif /* ARP_OFFLOAD_SUPPORT */
9858 }
9859 #ifdef WLTDLS
9860 if (bssidx == 0) {
9861 /* Since AP creation failed, re-enable TDLS */
9862 wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_DELETE, false);
9863 }
9864 #endif /* WLTDLS */
9865
9866 }
9867
9868 return err;
9869 }
9870
9871 static s32
9872 wl_cfg80211_stop_ap(
9873 struct wiphy *wiphy,
9874 struct net_device *dev)
9875 {
9876 int err = 0;
9877 u32 dev_role = 0;
9878 int ap = 0;
9879 s32 bssidx = 0;
9880 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
9881 s32 is_rsdb_supported = BCME_ERROR;
9882 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
9883
9884 WL_DBG(("Enter \n"));
9885
9886 is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
9887 if (is_rsdb_supported < 0)
9888 return (-ENODEV);
9889
9890 wl_clr_drv_status(cfg, AP_CREATING, dev);
9891 wl_clr_drv_status(cfg, AP_CREATED, dev);
9892 cfg->ap_oper_channel = 0;
9893
9894 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
9895 dev_role = NL80211_IFTYPE_AP;
9896 WL_DBG(("stopping AP operation\n"));
9897 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
9898 dev_role = NL80211_IFTYPE_P2P_GO;
9899 WL_DBG(("stopping P2P GO operation\n"));
9900 } else {
9901 WL_ERR(("no AP/P2P GO interface is operational.\n"));
9902 return -EINVAL;
9903 }
9904
9905 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
9906 WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
9907 return BCME_ERROR;
9908 }
9909
9910 if (!check_dev_role_integrity(cfg, dev_role)) {
9911 WL_ERR(("role integrity check failed \n"));
9912 err = -EINVAL;
9913 goto exit;
9914 }
9915
9916 /* Clear AP/GO connected status */
9917 wl_clr_drv_status(cfg, CONNECTED, dev);
9918 if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 0)) < 0) {
9919 WL_ERR(("bss down error %d\n", err));
9920 }
9921
9922 if (dev_role == NL80211_IFTYPE_AP) {
9923 #ifdef PKT_FILTER_SUPPORT
9924 /* Enable packet filter */
9925 if (dhd->early_suspended) {
9926 WL_ERR(("Enable pkt_filter\n"));
9927 dhd_enable_packet_filter(1, dhd);
9928 }
9929 #endif /* PKT_FILTER_SUPPORT */
9930 #ifdef ARP_OFFLOAD_SUPPORT
9931 /* IF SoftAP is disabled, enable arpoe back for STA mode. */
9932 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
9933 dhd_arp_offload_set(dhd, dhd_arp_mode);
9934 dhd_arp_offload_enable(dhd, TRUE);
9935 }
9936 #endif /* ARP_OFFLOAD_SUPPORT */
9937
9938 if (is_rsdb_supported == 0) {
9939 /* For non-rsdb chips, we use stand alone AP. Do wl down on stop AP */
9940 err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
9941 if (unlikely(err)) {
9942 WL_ERR(("WLC_UP error (%d)\n", err));
9943 err = -EINVAL;
9944 goto exit;
9945 }
9946 }
9947
9948 wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
9949 #ifdef SUPPORT_AP_RADIO_PWRSAVE
9950 wl_set_ap_rps(dev, FALSE, dev->name);
9951 wl_cfg80211_init_ap_rps(cfg);
9952 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
9953 } else {
9954 WL_DBG(("Stopping P2P GO \n"));
9955 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(cfg->pub),
9956 DHD_EVENT_TIMEOUT_MS*3);
9957 DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub));
9958 }
9959 exit:
9960 #ifdef WLTDLS
9961 if (bssidx == 0) {
9962 /* re-enable TDLS if the number of connected interfaces is less than 2 */
9963 wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_DELETE, false);
9964 }
9965 #endif /* WLTDLS */
9966
9967 if (dev_role == NL80211_IFTYPE_AP) {
9968 /* clear the AP mode */
9969 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
9970 }
9971 #ifdef SUPPORT_SET_CAC
9972 wl_cfg80211_set_cac(cfg, 1);
9973 #endif /* SUPPORT_SET_CAC */
9974 return err;
9975 }
9976
9977 static s32
9978 wl_cfg80211_change_beacon(
9979 struct wiphy *wiphy,
9980 struct net_device *dev,
9981 struct cfg80211_beacon_data *info)
9982 {
9983 s32 err = BCME_OK;
9984 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
9985 struct parsed_ies ies;
9986 u32 dev_role = 0;
9987 s32 bssidx = 0;
9988 bool pbc = 0;
9989
9990 WL_DBG(("Enter \n"));
9991
9992 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
9993 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
9994 return BCME_ERROR;
9995 }
9996
9997 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
9998 dev_role = NL80211_IFTYPE_P2P_GO;
9999 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
10000 dev_role = NL80211_IFTYPE_AP;
10001 } else {
10002 err = -EINVAL;
10003 goto fail;
10004 }
10005
10006 if (!check_dev_role_integrity(cfg, dev_role)) {
10007 err = -EINVAL;
10008 goto fail;
10009 }
10010
10011 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
10012 WL_ERR(("P2P already down status!\n"));
10013 err = BCME_ERROR;
10014 goto fail;
10015 }
10016
10017 /* Parse IEs */
10018 if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
10019 WL_ERR(("Parse IEs failed \n"));
10020 goto fail;
10021 }
10022
10023 /* Set IEs to FW */
10024 if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
10025 WL_ERR(("Set IEs failed \n"));
10026 goto fail;
10027 }
10028
10029 if (dev_role == NL80211_IFTYPE_AP) {
10030 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
10031 WL_ERR(("Hostapd update sec failed \n"));
10032 err = -EINVAL;
10033 goto fail;
10034 }
10035 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
10036 if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
10037 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
10038 WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc));
10039 if (pbc)
10040 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
10041 else
10042 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
10043 }
10044 }
10045
10046 fail:
10047 return err;
10048 }
10049 #else
10050 static s32
10051 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
10052 struct beacon_parameters *info)
10053 {
10054 s32 err = BCME_OK;
10055 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10056 s32 ie_offset = 0;
10057 s32 bssidx = 0;
10058 u32 dev_role = NL80211_IFTYPE_AP;
10059 struct parsed_ies ies;
10060 bcm_tlv_t *ssid_ie;
10061 bool pbc = 0;
10062 bool privacy;
10063 bool is_bss_up = 0;
10064 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
10065
10066 WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
10067 info->interval, info->dtim_period, info->head_len, info->tail_len));
10068
10069 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
10070 dev_role = NL80211_IFTYPE_AP;
10071 }
10072 #if defined(WL_ENABLE_P2P_IF)
10073 else if (dev == cfg->p2p_net) {
10074 /* Group Add request on p2p0 */
10075 dev = bcmcfg_to_prmry_ndev(cfg);
10076 dev_role = NL80211_IFTYPE_P2P_GO;
10077 }
10078 #endif /* WL_ENABLE_P2P_IF */
10079
10080 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
10081 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
10082 return BCME_ERROR;
10083 }
10084
10085 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
10086 dev_role = NL80211_IFTYPE_P2P_GO;
10087 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
10088 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
10089 }
10090
10091 if (!check_dev_role_integrity(cfg, dev_role)) {
10092 err = -ENODEV;
10093 goto fail;
10094 }
10095
10096 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
10097 WL_ERR(("P2P already down status!\n"));
10098 err = BCME_ERROR;
10099 goto fail;
10100 }
10101
10102 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
10103 /* find the SSID */
10104 if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
10105 info->head_len - ie_offset,
10106 DOT11_MNG_SSID_ID)) != NULL) {
10107 if (dev_role == NL80211_IFTYPE_AP) {
10108 /* Store the hostapd SSID */
10109 memset(&cfg->hostapd_ssid.SSID[0], 0x00, DOT11_MAX_SSID_LEN);
10110 cfg->hostapd_ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
10111 memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data,
10112 cfg->hostapd_ssid.SSID_len);
10113 } else {
10114 /* P2P GO */
10115 memset(&cfg->p2p->ssid.SSID[0], 0x00, DOT11_MAX_SSID_LEN);
10116 cfg->p2p->ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
10117 memcpy(cfg->p2p->ssid.SSID, ssid_ie->data,
10118 cfg->p2p->ssid.SSID_len);
10119 }
10120 }
10121
10122 if (wl_cfg80211_parse_ies((u8 *)info->tail,
10123 info->tail_len, &ies) < 0) {
10124 WL_ERR(("Beacon get IEs failed \n"));
10125 err = -EINVAL;
10126 goto fail;
10127 }
10128
10129 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
10130 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
10131 info->tail_len)) < 0) {
10132 WL_ERR(("Beacon set IEs failed \n"));
10133 goto fail;
10134 } else {
10135 WL_DBG(("Applied Vndr IEs for Beacon \n"));
10136 }
10137
10138 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10139 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
10140 VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies,
10141 info->proberesp_ies_len)) < 0) {
10142 WL_ERR(("ProbeRsp set IEs failed \n"));
10143 goto fail;
10144 } else {
10145 WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
10146 }
10147 #endif
10148
10149 is_bss_up = wl_cfg80211_bss_isup(dev, bssidx);
10150
10151 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10152 privacy = info->privacy;
10153 #else
10154 privacy = 0;
10155 #endif
10156 if (!is_bss_up &&
10157 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx, privacy) < 0))
10158 {
10159 WL_ERR(("Beacon set security failed \n"));
10160 err = -EINVAL;
10161 goto fail;
10162 }
10163
10164 /* Set BI and DTIM period */
10165 if (info->interval) {
10166 if ((err = wldev_ioctl_set(dev, WLC_SET_BCNPRD,
10167 &info->interval, sizeof(s32))) < 0) {
10168 WL_ERR(("Beacon Interval Set Error, %d\n", err));
10169 return err;
10170 }
10171 }
10172 if (info->dtim_period) {
10173 if ((err = wldev_ioctl_set(dev, WLC_SET_DTIMPRD,
10174 &info->dtim_period, sizeof(s32))) < 0) {
10175 WL_ERR(("DTIM Interval Set Error, %d\n", err));
10176 return err;
10177 }
10178 }
10179
10180 /* If bss is already up, skip bring up */
10181 if (!is_bss_up &&
10182 (err = wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx)) < 0)
10183 {
10184 WL_ERR(("Beacon bring up AP/GO failed \n"));
10185 goto fail;
10186 }
10187
10188 /* Set GC/STA SCB expiry timings. */
10189 if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
10190 WL_ERR(("scb setting failed \n"));
10191 // goto fail;
10192 }
10193
10194 if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
10195 /* Soft AP already running. Update changed params */
10196 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
10197 WL_ERR(("Hostapd update sec failed \n"));
10198 err = -EINVAL;
10199 goto fail;
10200 }
10201 }
10202
10203 /* Enable Probe Req filter */
10204 if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
10205 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
10206 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
10207 if (pbc)
10208 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
10209 }
10210
10211 WL_DBG(("** ADD/SET beacon done **\n"));
10212
10213 fail:
10214 if (err) {
10215 WL_ERR(("ADD/SET beacon failed\n"));
10216 if (dev_role == NL80211_IFTYPE_AP) {
10217 /* clear the AP mode */
10218 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
10219 }
10220 }
10221 return err;
10222
10223 }
10224
10225 static s32
10226 wl_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
10227 {
10228 int err = 0;
10229 s32 bssidx = 0;
10230 int infra = 0;
10231 struct wireless_dev *wdev = dev->ieee80211_ptr;
10232 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10233 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
10234
10235 WL_DBG(("Enter. \n"));
10236
10237 if (!wdev) {
10238 WL_ERR(("wdev null \n"));
10239 return -EINVAL;
10240 }
10241
10242 if ((wdev->iftype != NL80211_IFTYPE_P2P_GO) && (wdev->iftype != NL80211_IFTYPE_AP)) {
10243 WL_ERR(("Unspported iface type iftype:%d \n", wdev->iftype));
10244 }
10245
10246 wl_clr_drv_status(cfg, AP_CREATING, dev);
10247 wl_clr_drv_status(cfg, AP_CREATED, dev);
10248
10249 /* Clear AP/GO connected status */
10250 wl_clr_drv_status(cfg, CONNECTED, dev);
10251
10252 cfg->ap_oper_channel = 0;
10253
10254
10255 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
10256 WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
10257 return BCME_ERROR;
10258 }
10259
10260 /* Do bss down */
10261 if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 0)) < 0) {
10262 WL_ERR(("bss down error %d\n", err));
10263 }
10264
10265 /* fall through is intentional */
10266 err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
10267 if (err < 0) {
10268 WL_ERR(("SET INFRA error %d\n", err));
10269 }
10270 wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
10271
10272 if (wdev->iftype == NL80211_IFTYPE_AP) {
10273 /* clear the AP mode */
10274 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
10275 }
10276
10277 return 0;
10278 }
10279 #endif
10280
10281 #ifdef WL_SCHED_SCAN
10282 #define PNO_TIME 30
10283 #define PNO_REPEAT 4
10284 #define PNO_FREQ_EXPO_MAX 2
10285 static bool
10286 is_ssid_in_list(struct cfg80211_ssid *ssid, struct cfg80211_ssid *ssid_list, int count)
10287 {
10288 int i;
10289
10290 if (!ssid || !ssid_list)
10291 return FALSE;
10292
10293 for (i = 0; i < count; i++) {
10294 if (ssid->ssid_len == ssid_list[i].ssid_len) {
10295 if (strncmp(ssid->ssid, ssid_list[i].ssid, ssid->ssid_len) == 0)
10296 return TRUE;
10297 }
10298 }
10299 return FALSE;
10300 }
10301
10302 static int
10303 wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
10304 struct net_device *dev,
10305 struct cfg80211_sched_scan_request *request)
10306 {
10307 ushort pno_time = PNO_TIME;
10308 int pno_repeat = PNO_REPEAT;
10309 int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
10310 wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
10311 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10312 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
10313 struct cfg80211_ssid *ssid = NULL;
10314 struct cfg80211_ssid *hidden_ssid_list = NULL;
10315 log_conn_event_t *event_data = NULL;
10316 tlv_log *tlv_data = NULL;
10317 u32 alloc_len, tlv_len;
10318 u32 payload_len;
10319 int ssid_cnt = 0;
10320 int i;
10321 int ret = 0;
10322 unsigned long flags;
10323
10324 if (!request) {
10325 WL_ERR(("Sched scan request was NULL\n"));
10326 return -EINVAL;
10327 }
10328
10329 WL_DBG(("Enter \n"));
10330 WL_PNO((">>> SCHED SCAN START\n"));
10331 WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
10332 request->n_match_sets, request->n_ssids));
10333 WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
10334 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
10335
10336
10337 if (!request->n_ssids || !request->n_match_sets) {
10338 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
10339 return -EINVAL;
10340 }
10341
10342 memset(&ssids_local, 0, sizeof(ssids_local));
10343
10344 if (request->n_ssids > 0) {
10345 hidden_ssid_list = request->ssids;
10346 }
10347
10348 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
10349 alloc_len = sizeof(log_conn_event_t) + DOT11_MAX_SSID_LEN;
10350 event_data = MALLOC(dhdp->osh, alloc_len);
10351 if (!event_data) {
10352 WL_ERR(("%s: failed to allocate log_conn_event_t with "
10353 "length(%d)\n", __func__, alloc_len));
10354 return -ENOMEM;
10355 }
10356 memset(event_data, 0, alloc_len);
10357 event_data->tlvs = NULL;
10358 tlv_len = sizeof(tlv_log);
10359 event_data->tlvs = (tlv_log *)MALLOC(dhdp->osh, tlv_len);
10360 if (!event_data->tlvs) {
10361 WL_ERR(("%s: failed to allocate log_tlv with "
10362 "length(%d)\n", __func__, tlv_len));
10363 MFREE(dhdp->osh, event_data, alloc_len);
10364 return -ENOMEM;
10365 }
10366 }
10367 for (i = 0; i < request->n_match_sets && ssid_cnt < MAX_PFN_LIST_COUNT; i++) {
10368 ssid = &request->match_sets[i].ssid;
10369 /* No need to include null ssid */
10370 if (ssid->ssid_len) {
10371 ssids_local[ssid_cnt].SSID_len = MIN(ssid->ssid_len,
10372 (uint32)DOT11_MAX_SSID_LEN);
10373 memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid,
10374 ssids_local[ssid_cnt].SSID_len);
10375 if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
10376 ssids_local[ssid_cnt].hidden = TRUE;
10377 WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
10378 } else {
10379 ssids_local[ssid_cnt].hidden = FALSE;
10380 WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid->ssid));
10381 }
10382 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0))
10383 if (request->match_sets[i].rssi_thold != NL80211_SCAN_RSSI_THOLD_OFF) {
10384 ssids_local[ssid_cnt].rssi_thresh =
10385 (int8)request->match_sets[i].rssi_thold;
10386 }
10387 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0)) */
10388 ssid_cnt++;
10389 }
10390 }
10391
10392 if (ssid_cnt) {
10393 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, ssid_cnt,
10394 pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
10395 WL_ERR(("PNO setup failed!! ret=%d \n", ret));
10396 ret = -EINVAL;
10397 goto exit;
10398 }
10399
10400 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
10401 for (i = 0; i < ssid_cnt; i++) {
10402 payload_len = sizeof(log_conn_event_t);
10403 event_data->event = WIFI_EVENT_DRIVER_PNO_ADD;
10404 tlv_data = event_data->tlvs;
10405 /* ssid */
10406 tlv_data->tag = WIFI_TAG_SSID;
10407 tlv_data->len = ssids_local[i].SSID_len;
10408 memcpy(tlv_data->value, ssids_local[i].SSID,
10409 ssids_local[i].SSID_len);
10410 payload_len += TLV_LOG_SIZE(tlv_data);
10411
10412 dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
10413 event_data, payload_len);
10414 }
10415 }
10416
10417 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
10418 cfg->sched_scan_req = request;
10419 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
10420 } else {
10421 ret = -EINVAL;
10422 }
10423 exit:
10424 if (event_data) {
10425 MFREE(dhdp->osh, event_data->tlvs, tlv_len);
10426 MFREE(dhdp->osh, event_data, alloc_len);
10427 }
10428 return ret;
10429 }
10430
10431 static int
10432 wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev
10433 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
10434 , u64 reqid
10435 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
10436 )
10437 {
10438 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10439 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
10440 unsigned long flags;
10441
10442 WL_DBG(("Enter \n"));
10443 WL_PNO((">>> SCHED SCAN STOP\n"));
10444
10445 BCM_REFERENCE(dhdp);
10446 if (dhd_dev_pno_stop_for_ssid(dev) < 0) {
10447 WL_ERR(("PNO Stop for SSID failed"));
10448 } else {
10449 DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_REMOVE);
10450 }
10451
10452 if (cfg->scan_request && cfg->sched_scan_running) {
10453 WL_PNO((">>> Sched scan running. Aborting it..\n"));
10454 wl_notify_escan_complete(cfg, dev, true, true);
10455 }
10456 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
10457 cfg->sched_scan_req = NULL;
10458 cfg->sched_scan_running = FALSE;
10459 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
10460 return 0;
10461 }
10462 #endif /* WL_SCHED_SCAN */
10463
10464 #ifdef WL_SUPPORT_ACS
10465 /*
10466 * Currently the dump_obss IOVAR is returning string as output so we need to
10467 * parse the output buffer in an unoptimized way. Going forward if we get the
10468 * IOVAR output in binary format this method can be optimized
10469 */
10470 static int wl_parse_dump_obss(char *buf, struct wl_dump_survey *survey)
10471 {
10472 int i;
10473 char *token;
10474 char delim[] = " \n";
10475
10476 token = strsep(&buf, delim);
10477 while (token != NULL) {
10478 if (!strcmp(token, "OBSS")) {
10479 for (i = 0; i < OBSS_TOKEN_IDX; i++)
10480 token = strsep(&buf, delim);
10481 survey->obss = simple_strtoul(token, NULL, 10);
10482 }
10483
10484 if (!strcmp(token, "IBSS")) {
10485 for (i = 0; i < IBSS_TOKEN_IDX; i++)
10486 token = strsep(&buf, delim);
10487 survey->ibss = simple_strtoul(token, NULL, 10);
10488 }
10489
10490 if (!strcmp(token, "TXDur")) {
10491 for (i = 0; i < TX_TOKEN_IDX; i++)
10492 token = strsep(&buf, delim);
10493 survey->tx = simple_strtoul(token, NULL, 10);
10494 }
10495
10496 if (!strcmp(token, "Category")) {
10497 for (i = 0; i < CTG_TOKEN_IDX; i++)
10498 token = strsep(&buf, delim);
10499 survey->no_ctg = simple_strtoul(token, NULL, 10);
10500 }
10501
10502 if (!strcmp(token, "Packet")) {
10503 for (i = 0; i < PKT_TOKEN_IDX; i++)
10504 token = strsep(&buf, delim);
10505 survey->no_pckt = simple_strtoul(token, NULL, 10);
10506 }
10507
10508 if (!strcmp(token, "Opp(time):")) {
10509 for (i = 0; i < IDLE_TOKEN_IDX; i++)
10510 token = strsep(&buf, delim);
10511 survey->idle = simple_strtoul(token, NULL, 10);
10512 }
10513
10514 token = strsep(&buf, delim);
10515 }
10516
10517 return 0;
10518 }
10519
10520 static int wl_dump_obss(struct net_device *ndev, cca_msrmnt_query req,
10521 struct wl_dump_survey *survey)
10522 {
10523 cca_stats_n_flags *results;
10524 char *buf;
10525 int retry, err;
10526
10527 buf = kzalloc(sizeof(char) * WLC_IOCTL_MAXLEN, GFP_KERNEL);
10528 if (unlikely(!buf)) {
10529 WL_ERR(("%s: buf alloc failed\n", __func__));
10530 return -ENOMEM;
10531 }
10532
10533 retry = IOCTL_RETRY_COUNT;
10534 while (retry--) {
10535 err = wldev_iovar_getbuf(ndev, "dump_obss", &req, sizeof(req),
10536 buf, WLC_IOCTL_MAXLEN, NULL);
10537 if (err >= 0) {
10538 break;
10539 }
10540 WL_DBG(("attempt = %d, err = %d, \n",
10541 (IOCTL_RETRY_COUNT - retry), err));
10542 }
10543
10544 if (retry <= 0) {
10545 WL_ERR(("failure, dump_obss IOVAR failed\n"));
10546 err = -EINVAL;
10547 goto exit;
10548 }
10549
10550 results = (cca_stats_n_flags *)(buf);
10551 wl_parse_dump_obss(results->buf, survey);
10552 kfree(buf);
10553
10554 return 0;
10555 exit:
10556 kfree(buf);
10557 return err;
10558 }
10559
10560 static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
10561 int idx, struct survey_info *info)
10562 {
10563 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10564 struct wl_dump_survey *survey;
10565 struct ieee80211_supported_band *band;
10566 struct ieee80211_channel*chan;
10567 cca_msrmnt_query req;
10568 int val, err, noise, retry;
10569
10570 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
10571 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
10572 return -ENOENT;
10573 }
10574 band = wiphy->bands[IEEE80211_BAND_2GHZ];
10575 if (band && idx >= band->n_channels) {
10576 idx -= band->n_channels;
10577 band = NULL;
10578 }
10579
10580 if (!band || idx >= band->n_channels) {
10581 /* Move to 5G band */
10582 band = wiphy->bands[IEEE80211_BAND_5GHZ];
10583 if (idx >= band->n_channels) {
10584 return -ENOENT;
10585 }
10586 }
10587
10588 chan = &band->channels[idx];
10589 /* Setting current channel to the requested channel */
10590 if ((err = wl_cfg80211_set_channel(wiphy, ndev, chan,
10591 NL80211_CHAN_HT20) < 0)) {
10592 WL_ERR(("Set channel failed \n"));
10593 }
10594
10595 if (!idx) {
10596 /* Set interface up, explicitly. */
10597 val = 1;
10598 err = wldev_ioctl_set(ndev, WLC_UP, (void *)&val, sizeof(val));
10599 if (err < 0) {
10600 WL_ERR(("set interface up failed, error = %d\n", err));
10601 }
10602 }
10603
10604 /* Get noise value */
10605 retry = IOCTL_RETRY_COUNT;
10606 while (retry--) {
10607 noise = 0;
10608 err = wldev_ioctl_get(ndev, WLC_GET_PHY_NOISE, &noise,
10609 sizeof(noise));
10610 if (err >= 0) {
10611 break;
10612 }
10613 WL_DBG(("attempt = %d, err = %d, \n",
10614 (IOCTL_RETRY_COUNT - retry), err));
10615 }
10616
10617 if (retry <= 0) {
10618 WL_ERR(("Get Phy Noise failed, error = %d\n", err));
10619 noise = CHAN_NOISE_DUMMY;
10620 }
10621
10622 survey = (struct wl_dump_survey *) kzalloc(sizeof(struct wl_dump_survey),
10623 GFP_KERNEL);
10624 if (unlikely(!survey)) {
10625 WL_ERR(("%s: alloc failed\n", __func__));
10626 return -ENOMEM;
10627 }
10628
10629 /* Start Measurement for obss stats on current channel */
10630 req.msrmnt_query = 0;
10631 req.time_req = ACS_MSRMNT_DELAY;
10632 if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
10633 goto exit;
10634 }
10635
10636 /*
10637 * Wait for the meaurement to complete, adding a buffer value of 10 to take
10638 * into consideration any delay in IOVAR completion
10639 */
10640 msleep(ACS_MSRMNT_DELAY + 10);
10641
10642 /* Issue IOVAR to collect measurement results */
10643 req.msrmnt_query = 1;
10644 if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
10645 goto exit;
10646 }
10647
10648 info->channel = chan;
10649 info->noise = noise;
10650 info->channel_time = ACS_MSRMNT_DELAY;
10651 info->channel_time_busy = ACS_MSRMNT_DELAY - survey->idle;
10652 info->channel_time_rx = survey->obss + survey->ibss + survey->no_ctg +
10653 survey->no_pckt;
10654 info->channel_time_tx = survey->tx;
10655 info->filled = SURVEY_INFO_NOISE_DBM |SURVEY_INFO_CHANNEL_TIME |
10656 SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_RX |
10657 SURVEY_INFO_CHANNEL_TIME_TX;
10658 kfree(survey);
10659
10660 return 0;
10661 exit:
10662 kfree(survey);
10663 return err;
10664 }
10665 #endif /* WL_SUPPORT_ACS */
10666
10667 static struct cfg80211_ops wl_cfg80211_ops = {
10668 .add_virtual_intf = wl_cfg80211_add_virtual_iface,
10669 .del_virtual_intf = wl_cfg80211_del_virtual_iface,
10670 .change_virtual_intf = wl_cfg80211_change_virtual_iface,
10671 #if defined(WL_CFG80211_P2P_DEV_IF)
10672 .start_p2p_device = wl_cfgp2p_start_p2p_device,
10673 .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
10674 #endif /* WL_CFG80211_P2P_DEV_IF */
10675 .scan = wl_cfg80211_scan,
10676 .set_wiphy_params = wl_cfg80211_set_wiphy_params,
10677 .join_ibss = wl_cfg80211_join_ibss,
10678 .leave_ibss = wl_cfg80211_leave_ibss,
10679 .get_station = wl_cfg80211_get_station,
10680 .set_tx_power = wl_cfg80211_set_tx_power,
10681 .get_tx_power = wl_cfg80211_get_tx_power,
10682 .add_key = wl_cfg80211_add_key,
10683 .del_key = wl_cfg80211_del_key,
10684 .get_key = wl_cfg80211_get_key,
10685 .set_default_key = wl_cfg80211_config_default_key,
10686 .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
10687 .set_power_mgmt = wl_cfg80211_set_power_mgmt,
10688 .connect = wl_cfg80211_connect,
10689 .disconnect = wl_cfg80211_disconnect,
10690 .suspend = wl_cfg80211_suspend,
10691 .resume = wl_cfg80211_resume,
10692 .set_pmksa = wl_cfg80211_set_pmksa,
10693 .del_pmksa = wl_cfg80211_del_pmksa,
10694 .flush_pmksa = wl_cfg80211_flush_pmksa,
10695 .remain_on_channel = wl_cfg80211_remain_on_channel,
10696 .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
10697 .mgmt_tx = wl_cfg80211_mgmt_tx,
10698 .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
10699 .change_bss = wl_cfg80211_change_bss,
10700 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
10701 .set_channel = wl_cfg80211_set_channel,
10702 #endif
10703 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
10704 .set_beacon = wl_cfg80211_add_set_beacon,
10705 .add_beacon = wl_cfg80211_add_set_beacon,
10706 .del_beacon = wl_cfg80211_del_beacon,
10707 #else
10708 .change_beacon = wl_cfg80211_change_beacon,
10709 .start_ap = wl_cfg80211_start_ap,
10710 .stop_ap = wl_cfg80211_stop_ap,
10711 #endif
10712 #ifdef WL_SCHED_SCAN
10713 .sched_scan_start = wl_cfg80211_sched_scan_start,
10714 .sched_scan_stop = wl_cfg80211_sched_scan_stop,
10715 #endif /* WL_SCHED_SCAN */
10716 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
10717 2, 0))
10718 .del_station = wl_cfg80211_del_station,
10719 .change_station = wl_cfg80211_change_station,
10720 .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
10721 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
10722 #ifdef WLMESH
10723 .join_mesh = wl_cfg80211_join_mesh,
10724 .leave_mesh = wl_cfg80211_leave_mesh,
10725 #endif /* WLMESH */
10726 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
10727 .tdls_mgmt = wl_cfg80211_tdls_mgmt,
10728 .tdls_oper = wl_cfg80211_tdls_oper,
10729 #endif
10730 #ifdef WL_SUPPORT_ACS
10731 .dump_survey = wl_cfg80211_dump_survey,
10732 #endif /* WL_SUPPORT_ACS */
10733 #ifdef WL_CFG80211_ACL
10734 .set_mac_acl = wl_cfg80211_set_mac_acl,
10735 #endif /* WL_CFG80211_ACL */
10736 #ifdef GTK_OFFLOAD_SUPPORT
10737 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
10738 .set_rekey_data = wl_cfg80211_set_rekey_data,
10739 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
10740 #endif /* GTK_OFFLOAD_SUPPORT */
10741 };
10742
10743 s32 wl_mode_to_nl80211_iftype(s32 mode)
10744 {
10745 s32 err = 0;
10746
10747 switch (mode) {
10748 case WL_MODE_BSS:
10749 return NL80211_IFTYPE_STATION;
10750 case WL_MODE_IBSS:
10751 return NL80211_IFTYPE_ADHOC;
10752 case WL_MODE_AP:
10753 return NL80211_IFTYPE_AP;
10754 #ifdef WLMESH
10755 case WL_MODE_MESH:
10756 return NL80211_IFTYPE_MESH_POINT;
10757 #endif
10758 default:
10759 return NL80211_IFTYPE_UNSPECIFIED;
10760 }
10761
10762 return err;
10763 }
10764
10765 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
10766 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
10767 #define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
10768 #else
10769 #define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
10770 #endif /* kernel version < 3.9.0 */
10771 #endif
10772
10773 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
10774 WL_CFG80211_REG_NOTIFIER()
10775 {
10776 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
10777 int ret = 0;
10778 int revinfo = -1;
10779
10780 if (!request || !cfg) {
10781 WL_ERR(("Invalid arg\n"));
10782 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
10783 return -EINVAL;
10784 #else
10785 return;
10786 #endif /* kernel version < 3.10.11 */
10787 }
10788
10789 WL_DBG(("ccode: %c%c Initiator: %d\n",
10790 request->alpha2[0], request->alpha2[1], request->initiator));
10791
10792 /* We support only REGDOM_SET_BY_USER as of now */
10793 if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
10794 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
10795 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
10796 request->initiator));
10797 /* in case of no supported country by regdb
10798 lets driver setup platform default Locale
10799 */
10800 }
10801
10802 WL_ERR(("Set country code %c%c from %s\n",
10803 request->alpha2[0], request->alpha2[1],
10804 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
10805
10806 if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2,
10807 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false),
10808 revinfo)) < 0) {
10809 WL_ERR(("set country Failed :%d\n", ret));
10810 }
10811
10812 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
10813 return ret;
10814 #else
10815 return;
10816 #endif /* kernel version < 3.10.11 */
10817 }
10818 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
10819
10820 #ifdef CONFIG_PM
10821 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
10822 static const struct wiphy_wowlan_support brcm_wowlan_support = {
10823 .flags = WIPHY_WOWLAN_ANY,
10824 .n_patterns = WL_WOWLAN_MAX_PATTERNS,
10825 .pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN,
10826 .pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN,
10827 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
10828 .max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN,
10829 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
10830 };
10831 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
10832 #endif /* CONFIG_PM */
10833
10834 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, dhd_pub_t *context)
10835 {
10836 s32 err = 0;
10837 #ifdef CONFIG_PM
10838 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10839 struct cfg80211_wowlan *brcm_wowlan_config = NULL;
10840 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
10841 #endif /* CONFIG_PM */
10842
10843 //#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
10844 dhd_pub_t *dhd = (dhd_pub_t *)context;
10845 BCM_REFERENCE(dhd);
10846
10847 if (!dhd) {
10848 WL_ERR(("DHD is NULL!!"));
10849 err = -ENODEV;
10850 return err;
10851 }
10852 //#endif
10853
10854 wdev->wiphy =
10855 wiphy_new(&wl_cfg80211_ops, sizeof(struct bcm_cfg80211));
10856 if (unlikely(!wdev->wiphy)) {
10857 WL_ERR(("Couldn not allocate wiphy device\n"));
10858 err = -ENOMEM;
10859 return err;
10860 }
10861 set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
10862 wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
10863 /* Report how many SSIDs Driver can support per Scan request */
10864 wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
10865 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
10866 #ifdef WL_SCHED_SCAN
10867 wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
10868 wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
10869 wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
10870 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
10871 wdev->wiphy->max_sched_scan_plan_interval = PNO_SCAN_MAX_FW_SEC;
10872 #else
10873 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10874 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
10875 #endif /* WL_SCHED_SCAN */
10876 #ifdef WLMESH
10877 wdev->wiphy->flags |= WIPHY_FLAG_MESH_AUTH;
10878 #endif
10879 wdev->wiphy->interface_modes =
10880 BIT(NL80211_IFTYPE_STATION)
10881 | BIT(NL80211_IFTYPE_ADHOC)
10882 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
10883 | BIT(NL80211_IFTYPE_MONITOR)
10884 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
10885 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
10886 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10887 | BIT(NL80211_IFTYPE_P2P_GO)
10888 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
10889 #if defined(WL_CFG80211_P2P_DEV_IF)
10890 | BIT(NL80211_IFTYPE_P2P_DEVICE)
10891 #endif /* WL_CFG80211_P2P_DEV_IF */
10892 #ifdef WLMESH
10893 | BIT(NL80211_IFTYPE_MESH_POINT)
10894 #endif /* WLMESH */
10895 | BIT(NL80211_IFTYPE_AP);
10896
10897 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
10898 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
10899 WL_DBG(("Setting interface combinations for common mode\n"));
10900 #ifndef BCMDBUS
10901 if (dhd->conf->num_different_channels >= 0)
10902 common_iface_combinations[0].num_different_channels = dhd->conf->num_different_channels;
10903 #endif /* !BCMDBUS */
10904 wdev->wiphy->iface_combinations = common_iface_combinations;
10905 wdev->wiphy->n_iface_combinations =
10906 ARRAY_SIZE(common_iface_combinations);
10907 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
10908
10909 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
10910
10911 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10912 wdev->wiphy->cipher_suites = __wl_cipher_suites;
10913 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
10914 wdev->wiphy->max_remain_on_channel_duration = 5000;
10915 wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
10916 #ifndef WL_POWERSAVE_DISABLED
10917 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
10918 #else
10919 wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
10920 #endif /* !WL_POWERSAVE_DISABLED */
10921 wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
10922 WIPHY_FLAG_4ADDR_AP |
10923 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
10924 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
10925 #endif
10926 WIPHY_FLAG_4ADDR_STATION;
10927 #if ((defined(ROAM_ENABLE) || defined(BCMFW_ROAM_ENABLE)) && (LINUX_VERSION_CODE >= \
10928 KERNEL_VERSION(3, 2, 0)))
10929 /*
10930 * If FW ROAM flag is advertised, upper layer wouldn't provide
10931 * the bssid & freq in the connect command. This will result a
10932 * delay in initial connection time due to firmware doing a full
10933 * channel scan to figure out the channel & bssid. However kernel
10934 * ver >= 3.15, provides bssid_hint & freq_hint and hence kernel
10935 * ver >= 3.15 won't have any issue. So if this flags need to be
10936 * advertised for kernel < 3.15, suggest to use RCC along with it
10937 * to avoid the initial connection delay.
10938 */
10939 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10940 #endif
10941 #ifdef UNSET_FW_ROAM_WIPHY_FLAG
10942 wdev->wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_FW_ROAM;
10943 #endif /* UNSET_FW_ROAM_WIPHY_FLAG */
10944 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
10945 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
10946 WIPHY_FLAG_OFFCHAN_TX;
10947 #endif
10948 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
10949 4, 0))
10950 /* From 3.4 kernel ownards AP_SME flag can be advertised
10951 * to remove the patch from supplicant
10952 */
10953 wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
10954
10955 #ifdef WL_CFG80211_ACL
10956 /* Configure ACL capabilities. */
10957 wdev->wiphy->max_acl_mac_addrs = MAX_NUM_MAC_FILT;
10958 #endif
10959
10960 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
10961 /* Supplicant distinguish between the SoftAP mode and other
10962 * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
10963 * response frame from Supplicant MR1 and Kernel 3.4.0 or
10964 * later version. To add Vendor specific IE into the
10965 * probe response frame in case of SoftAP mode,
10966 * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
10967 */
10968 if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) {
10969 wdev->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
10970 wdev->wiphy->probe_resp_offload = 0;
10971 }
10972 #endif
10973 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
10974
10975 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
10976 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
10977 #endif
10978
10979 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
10980 /*
10981 * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
10982 * disconnection of connected network before suspend. So a dummy wowlan
10983 * filter is configured for kernels linux-3.8 and above.
10984 */
10985
10986 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10987 wdev->wiphy->wowlan = &brcm_wowlan_support;
10988 /* If this is not provided cfg stack will get disconnect
10989 * during suspend.
10990 */
10991 brcm_wowlan_config = kmalloc(sizeof(struct cfg80211_wowlan), GFP_KERNEL);
10992 if (brcm_wowlan_config) {
10993 brcm_wowlan_config->disconnect = true;
10994 brcm_wowlan_config->gtk_rekey_failure = true;
10995 brcm_wowlan_config->eap_identity_req = true;
10996 brcm_wowlan_config->four_way_handshake = true;
10997 brcm_wowlan_config->patterns = NULL;
10998 brcm_wowlan_config->n_patterns = 0;
10999 brcm_wowlan_config->tcp = NULL;
11000 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
11001 brcm_wowlan_config->nd_config = NULL;
11002 #endif
11003 } else {
11004 WL_ERR(("Can not allocate memory for brcm_wowlan_config,"
11005 " So wiphy->wowlan_config is set to NULL\n"));
11006 }
11007 wdev->wiphy->wowlan_config = brcm_wowlan_config;
11008 #else
11009 wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
11010 wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
11011 wdev->wiphy->wowlan.pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN;
11012 wdev->wiphy->wowlan.pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN;
11013 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
11014 wdev->wiphy->wowlan.max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN;
11015 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
11016 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
11017 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
11018
11019 WL_DBG(("Registering custom regulatory)\n"));
11020 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
11021 wdev->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
11022 #else
11023 wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
11024 #endif
11025 wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
11026
11027 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
11028 WL_ERR(("Registering Vendor80211\n"));
11029 err = wl_cfgvendor_attach(wdev->wiphy, dhd);
11030 if (unlikely(err < 0)) {
11031 WL_ERR(("Couldn not attach vendor commands (%d)\n", err));
11032 }
11033 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
11034
11035 /* Now we can register wiphy with cfg80211 module */
11036 err = wiphy_register(wdev->wiphy);
11037 if (unlikely(err < 0)) {
11038 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
11039 wiphy_free(wdev->wiphy);
11040 }
11041
11042 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
11043 KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
11044 wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
11045 #endif
11046
11047 return err;
11048 }
11049
11050 static void wl_free_wdev(struct bcm_cfg80211 *cfg)
11051 {
11052 struct wireless_dev *wdev = cfg->wdev;
11053 struct wiphy *wiphy = NULL;
11054 if (!wdev) {
11055 WL_ERR(("wdev is invalid\n"));
11056 return;
11057 }
11058 if (wdev->wiphy) {
11059 wiphy = wdev->wiphy;
11060
11061 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
11062 wl_cfgvendor_detach(wdev->wiphy);
11063 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
11064 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
11065 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
11066 /* Reset wowlan & wowlan_config before Unregister to avoid Kernel Panic */
11067 WL_DBG(("wl_free_wdev Clearing wowlan Config \n"));
11068 wdev->wiphy->wowlan = NULL;
11069 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
11070 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
11071 wiphy_unregister(wdev->wiphy);
11072 wdev->wiphy->dev.parent = NULL;
11073 wdev->wiphy = NULL;
11074 }
11075
11076 wl_delete_all_netinfo(cfg);
11077 if (wiphy)
11078 wiphy_free(wiphy);
11079
11080 /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
11081 * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
11082 */
11083 }
11084
11085 static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
11086 {
11087 struct wl_scan_results *bss_list;
11088 struct wl_bss_info *bi = NULL; /* must be initialized */
11089 s32 err = 0;
11090 s32 i;
11091 #if defined(RSSIAVG)
11092 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
11093 int rssi;
11094 #endif
11095 #if defined(BSSCACHE)
11096 wl_bss_cache_t *node;
11097 #endif
11098
11099 bss_list = cfg->bss_list;
11100
11101 /* Free cache in p2p scanning*/
11102 if (p2p_is_on(cfg) && p2p_scan(cfg)) {
11103 #if defined(RSSIAVG)
11104 wl_free_rssi_cache(&g_rssi_cache_ctrl);
11105 #endif
11106 #if defined(BSSCACHE)
11107 wl_free_bss_cache(&g_bss_cache_ctrl);
11108 #endif
11109 }
11110
11111 /* Delete disconnected cache */
11112 #if defined(BSSCACHE)
11113 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
11114 #if defined(RSSIAVG)
11115 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
11116 #endif
11117 if (cfg->p2p_disconnected == 0)
11118 memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
11119 #endif
11120
11121 /* Update cache */
11122 #if defined(RSSIAVG)
11123 wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
11124 if (!in_atomic())
11125 wl_update_connected_rssi_cache(ndev, &g_rssi_cache_ctrl, &rssi);
11126 #endif
11127 #if defined(BSSCACHE)
11128 wl_update_bss_cache(&g_bss_cache_ctrl,
11129 #if defined(RSSIAVG)
11130 &g_rssi_cache_ctrl,
11131 #endif
11132 bss_list);
11133 #endif
11134
11135 /* delete dirty cache */
11136 #if defined(RSSIAVG)
11137 wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
11138 wl_reset_rssi_cache(&g_rssi_cache_ctrl);
11139 #endif
11140 #if defined(BSSCACHE)
11141 wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
11142 wl_reset_bss_cache(&g_bss_cache_ctrl);
11143 #endif
11144
11145 #if defined(BSSCACHE)
11146 if (cfg->p2p_disconnected > 0) {
11147 // terence 20130703: Fix for wrong group_capab (timing issue)
11148 wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
11149 #if defined(RSSIAVG)
11150 wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
11151 #endif
11152 }
11153 WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
11154 node = g_bss_cache_ctrl.m_cache_head;
11155 for (i=0; node && i<WL_AP_MAX; i++) {
11156 bi = node->results.bss_info;
11157 err = wl_inform_single_bss(cfg, bi, false);
11158 node = node->next;
11159 }
11160 #else
11161 WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
11162 preempt_disable();
11163 bi = next_bss(bss_list, bi);
11164 for_each_bss(bss_list, bi, i) {
11165 if (cfg->p2p_disconnected > 0 && !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN))
11166 continue;
11167 err = wl_inform_single_bss(cfg, bi, false);
11168 }
11169 preempt_enable();
11170 #endif
11171
11172 if (cfg->p2p_disconnected > 0) {
11173 // terence 20130703: Fix for wrong group_capab (timing issue)
11174 cfg->p2p_disconnected++;
11175 if (cfg->p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1) {
11176 cfg->p2p_disconnected = 0;
11177 memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
11178 }
11179 }
11180
11181 return err;
11182 }
11183
11184 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam)
11185 {
11186 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11187 struct ieee80211_mgmt *mgmt;
11188 struct ieee80211_channel *channel;
11189 struct ieee80211_supported_band *band;
11190 struct wl_cfg80211_bss_info *notif_bss_info;
11191 struct wl_scan_req *sr = wl_to_sr(cfg);
11192 struct beacon_proberesp *beacon_proberesp;
11193 struct cfg80211_bss *cbss = NULL;
11194 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11195 log_conn_event_t *event_data = NULL;
11196 tlv_log *tlv_data = NULL;
11197 u32 alloc_len, tlv_len;
11198 u32 payload_len;
11199 s32 mgmt_type;
11200 s32 signal;
11201 u32 freq;
11202 s32 err = 0;
11203 gfp_t aflags;
11204
11205 if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
11206 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
11207 return err;
11208 }
11209 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
11210 notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
11211 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
11212 if (unlikely(!notif_bss_info)) {
11213 WL_ERR(("notif_bss_info alloc failed\n"));
11214 return -ENOMEM;
11215 }
11216 mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
11217 notif_bss_info->channel =
11218 wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
11219
11220 if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
11221 band = wiphy->bands[IEEE80211_BAND_2GHZ];
11222 else
11223 band = wiphy->bands[IEEE80211_BAND_5GHZ];
11224 if (!band) {
11225 WL_ERR(("No valid band\n"));
11226 kfree(notif_bss_info);
11227 return -EINVAL;
11228 }
11229 notif_bss_info->rssi = dtoh16(bi->RSSI);
11230 #if defined(RSSIAVG)
11231 notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
11232 if (notif_bss_info->rssi == RSSI_MINVAL)
11233 notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
11234 #endif
11235 #if defined(RSSIOFFSET)
11236 notif_bss_info->rssi = wl_update_rssi_offset(bcmcfg_to_prmry_ndev(cfg), notif_bss_info->rssi);
11237 #endif
11238 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
11239 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
11240 notif_bss_info->rssi = MIN(notif_bss_info->rssi, RSSI_MAXVAL);
11241 #endif
11242 memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
11243 mgmt_type = cfg->active_scan ?
11244 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
11245 if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
11246 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
11247 }
11248 beacon_proberesp = cfg->active_scan ?
11249 (struct beacon_proberesp *)&mgmt->u.probe_resp :
11250 (struct beacon_proberesp *)&mgmt->u.beacon;
11251 beacon_proberesp->timestamp = 0;
11252 beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
11253 beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
11254 wl_rst_ie(cfg);
11255 wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length, roam);
11256 wl_mrg_ie(cfg, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
11257 wl_cp_ie(cfg, beacon_proberesp->variable, WL_BSS_INFO_MAX -
11258 offsetof(struct wl_cfg80211_bss_info, frame_buf));
11259 notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
11260 u.beacon.variable) + wl_get_ielen(cfg);
11261 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11262 freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
11263 (void)band->band;
11264 #else
11265 freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
11266 #endif
11267 if (freq == 0) {
11268 WL_ERR(("Invalid channel, fail to change channel to freq\n"));
11269 kfree(notif_bss_info);
11270 return -EINVAL;
11271 }
11272 channel = ieee80211_get_channel(wiphy, freq);
11273 WL_SCAN(("BSSID %pM, channel %2d, rssi %3d, capa 0x04%x, mgmt_type %d, "
11274 "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel,
11275 notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
11276 notif_bss_info->frame_len, bi->SSID));
11277 if (unlikely(!channel)) {
11278 WL_ERR(("ieee80211_get_channel error, freq=%d, channel=%d\n",
11279 freq, notif_bss_info->channel));
11280 kfree(notif_bss_info);
11281 return -EINVAL;
11282 }
11283
11284 signal = notif_bss_info->rssi * 100;
11285 if (!mgmt->u.probe_resp.timestamp) {
11286 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
11287 struct timespec ts;
11288 get_monotonic_boottime(&ts);
11289 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
11290 + ts.tv_nsec / 1000;
11291 #else
11292 struct timeval tv;
11293 do_gettimeofday(&tv);
11294 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
11295 + tv.tv_usec;
11296 #endif
11297 }
11298
11299
11300 cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
11301 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
11302 if (unlikely(!cbss)) {
11303 WL_ERR(("cfg80211_inform_bss_frame error\n"));
11304 err = -EINVAL;
11305 goto out_err;
11306 }
11307
11308 CFG80211_PUT_BSS(wiphy, cbss);
11309
11310 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID) &&
11311 (cfg->sched_scan_req && !cfg->scan_request)) {
11312 alloc_len = sizeof(log_conn_event_t) + IEEE80211_MAX_SSID_LEN + sizeof(uint16) +
11313 sizeof(int16);
11314 event_data = MALLOCZ(dhdp->osh, alloc_len);
11315 if (!event_data) {
11316 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
11317 "length(%d)\n", __func__, alloc_len));
11318 goto out_err;
11319 }
11320 tlv_len = 3 * sizeof(tlv_log);
11321 event_data->tlvs = MALLOC(dhdp->osh, tlv_len);
11322 if (!event_data->tlvs) {
11323 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
11324 "length(%d)\n", __func__, tlv_len));
11325 goto out_err;
11326 }
11327
11328 payload_len = sizeof(log_conn_event_t);
11329 event_data->event = WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND;
11330 tlv_data = event_data->tlvs;
11331
11332 /* ssid */
11333 tlv_data->tag = WIFI_TAG_SSID;
11334 tlv_data->len = bi->SSID_len;
11335 memcpy(tlv_data->value, bi->SSID, bi->SSID_len);
11336 payload_len += TLV_LOG_SIZE(tlv_data);
11337 tlv_data = TLV_LOG_NEXT(tlv_data);
11338
11339 /* channel */
11340 tlv_data->tag = WIFI_TAG_CHANNEL;
11341 tlv_data->len = sizeof(uint16);
11342 memcpy(tlv_data->value, &notif_bss_info->channel, sizeof(uint16));
11343 payload_len += TLV_LOG_SIZE(tlv_data);
11344 tlv_data = TLV_LOG_NEXT(tlv_data);
11345
11346 /* rssi */
11347 tlv_data->tag = WIFI_TAG_RSSI;
11348 tlv_data->len = sizeof(int16);
11349 memcpy(tlv_data->value, &notif_bss_info->rssi, sizeof(int16));
11350 payload_len += TLV_LOG_SIZE(tlv_data);
11351 tlv_data = TLV_LOG_NEXT(tlv_data);
11352
11353 dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
11354 event_data, payload_len);
11355 MFREE(dhdp->osh, event_data->tlvs, tlv_len);
11356 MFREE(dhdp->osh, event_data, alloc_len);
11357 }
11358
11359 out_err:
11360 kfree(notif_bss_info);
11361 return err;
11362 }
11363
11364 static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, struct net_device *ndev)
11365 {
11366 u32 event = ntoh32(e->event_type);
11367 u32 status = ntoh32(e->status);
11368 u16 flags = ntoh16(e->flags);
11369 #if defined(CUSTOM_SET_ANTNPM) || defined(CUSTOM_SET_OCLOFF)
11370 dhd_pub_t *dhd;
11371 dhd = (dhd_pub_t *)(cfg->pub);
11372 #endif /* CUSTOM_SET_ANTNPM */
11373
11374 WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
11375 if (event == WLC_E_SET_SSID) {
11376 if (status == WLC_E_STATUS_SUCCESS) {
11377 #ifdef CUSTOM_SET_ANTNPM
11378 if (dhd->mimo_ant_set) {
11379 int err = 0;
11380
11381 WL_ERR(("[WIFI_SEC] mimo_ant_set = %d\n", dhd->mimo_ant_set));
11382 err = wldev_iovar_setint(ndev, "txchain", dhd->mimo_ant_set);
11383 if (err != 0) {
11384 WL_ERR(("[WIFI_SEC] Fail set txchain\n"));
11385 }
11386 err = wldev_iovar_setint(ndev, "rxchain", dhd->mimo_ant_set);
11387 if (err != 0) {
11388 WL_ERR(("[WIFI_SEC] Fail set rxchain\n"));
11389 }
11390 }
11391 #endif /* CUSTOM_SET_ANTNPM */
11392 #ifdef CUSTOM_SET_OCLOFF
11393 if (dhd->ocl_off) {
11394 int err = 0;
11395 int ocl_enable = 0;
11396 err = wldev_iovar_setint(ndev, "ocl_enable", ocl_enable);
11397 if (err != 0) {
11398 WL_ERR(("[WIFI_SEC] %s: Set ocl_enable %d failed %d\n",
11399 __FUNCTION__, ocl_enable, err));
11400 } else {
11401 WL_ERR(("[WIFI_SEC] %s: Set ocl_enable %d succeeded %d\n",
11402 __FUNCTION__, ocl_enable, err));
11403 }
11404 }
11405 #endif /* CUSTOM_SET_OCLOFF */
11406 if (!wl_is_ibssmode(cfg, ndev))
11407 return true;
11408 }
11409 } else if (event == WLC_E_LINK) {
11410 if (flags & WLC_EVENT_MSG_LINK)
11411 return true;
11412 }
11413
11414 WL_DBG(("wl_is_linkup false\n"));
11415 return false;
11416 }
11417
11418 #ifdef WL_LASTEVT
11419 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, void *data)
11420 {
11421 u32 event = ntoh32(e->event_type);
11422 u16 flags = ntoh16(e->flags);
11423 wl_last_event_t *last_event = (wl_last_event_t *)data;
11424 u32 len = ntoh32(e->datalen);
11425
11426 if (event == WLC_E_DEAUTH_IND ||
11427 event == WLC_E_DISASSOC_IND ||
11428 event == WLC_E_DISASSOC ||
11429 event == WLC_E_DEAUTH) {
11430 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event)));
11431 return true;
11432 } else if (event == WLC_E_LINK) {
11433 if (!(flags & WLC_EVENT_MSG_LINK)) {
11434 if (last_event && len > 0) {
11435 u32 current_time = last_event->current_time;
11436 u32 timestamp = last_event->timestamp;
11437 u32 event_type = last_event->event.event_type;
11438 u32 status = last_event->event.status;
11439 u32 reason = last_event->event.reason;
11440
11441 WL_ERR(("Last roam event before disconnection : current_time %d,"
11442 " time %d, type %d, status %d, reason %d\n",
11443 current_time, timestamp, event_type, status, reason));
11444 }
11445 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event)));
11446 return true;
11447 }
11448 }
11449
11450 return false;
11451 }
11452 #else
11453 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
11454 {
11455 u32 event = ntoh32(e->event_type);
11456 u16 flags = ntoh16(e->flags);
11457
11458 if (event == WLC_E_DEAUTH_IND ||
11459 event == WLC_E_DISASSOC_IND ||
11460 event == WLC_E_DISASSOC ||
11461 event == WLC_E_DEAUTH) {
11462 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event)));
11463 return true;
11464 } else if (event == WLC_E_LINK) {
11465 if (!(flags & WLC_EVENT_MSG_LINK)) {
11466 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event)));
11467 return true;
11468 }
11469 }
11470
11471 return false;
11472 }
11473 #endif /* WL_LASTEVT */
11474
11475 static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
11476 {
11477 u32 event = ntoh32(e->event_type);
11478 u32 status = ntoh32(e->status);
11479
11480 if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
11481 return true;
11482 if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
11483 return true;
11484
11485 return false;
11486 }
11487
11488 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
11489 * to AP/P2P GO via events. If this change is backported to kernel for which
11490 * this driver is being built, then define WL_CFG80211_STA_EVENT. You
11491 * should use this new/del sta event mechanism for BRCM supplicant >= 22.
11492 */
11493 static s32
11494 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
11495 const wl_event_msg_t *e, void *data)
11496 {
11497 s32 err = 0;
11498 u32 event = ntoh32(e->event_type);
11499 u32 reason = ntoh32(e->reason);
11500 u32 len = ntoh32(e->datalen);
11501 u32 status = ntoh32(e->status);
11502
11503 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
11504 bool isfree = false;
11505 u8 *mgmt_frame;
11506 u8 bsscfgidx = e->bsscfgidx;
11507 s32 freq;
11508 s32 channel;
11509 u8 *body = NULL;
11510 u16 fc = 0;
11511
11512 struct ieee80211_supported_band *band;
11513 struct ether_addr da;
11514 struct ether_addr bssid;
11515 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11516 channel_info_t ci;
11517 #else
11518 struct station_info sinfo;
11519 #endif
11520
11521 WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
11522 /* if link down, bsscfg is disabled. */
11523 if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
11524 wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) {
11525 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
11526 WL_INFORM(("AP mode link down !! \n"));
11527 complete(&cfg->iface_disable);
11528 return 0;
11529 }
11530
11531 if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
11532 (reason == WLC_E_REASON_INITIAL_ASSOC) &&
11533 (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) {
11534 if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
11535 /* AP/GO brought up successfull in firmware */
11536 printf("%s: ** AP/GO Link up event **\n", __FUNCTION__);
11537 wl_set_drv_status(cfg, AP_CREATED, ndev);
11538 wake_up_interruptible(&cfg->netif_change_event);
11539 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
11540 dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_GO, -1);
11541 }
11542 return 0;
11543 }
11544 }
11545
11546 if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
11547 printf("%s: event %s(%d) status %d reason %d\n", __FUNCTION__,
11548 bcmevent_get_name(event), event, ntoh32(e->status), reason);
11549 }
11550
11551 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
11552 WL_DBG(("Enter \n"));
11553 if (!len && (event == WLC_E_DEAUTH)) {
11554 len = 2; /* reason code field */
11555 data = &reason;
11556 }
11557 if (len) {
11558 body = kzalloc(len, GFP_KERNEL);
11559
11560 if (body == NULL) {
11561 WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
11562 return WL_INVALID;
11563 }
11564 }
11565 memset(&bssid, 0, ETHER_ADDR_LEN);
11566 WL_DBG(("Enter event %d ndev %p\n", event, ndev));
11567 if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
11568 kfree(body);
11569 return WL_INVALID;
11570 }
11571 if (len)
11572 memcpy(body, data, len);
11573
11574 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
11575 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
11576 memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
11577 memset(&bssid, 0, sizeof(bssid));
11578 err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
11579 switch (event) {
11580 case WLC_E_ASSOC_IND:
11581 fc = FC_ASSOC_REQ;
11582 break;
11583 case WLC_E_REASSOC_IND:
11584 fc = FC_REASSOC_REQ;
11585 break;
11586 case WLC_E_DISASSOC_IND:
11587 fc = FC_DISASSOC;
11588 break;
11589 case WLC_E_DEAUTH_IND:
11590 fc = FC_DISASSOC;
11591 break;
11592 case WLC_E_DEAUTH:
11593 fc = FC_DISASSOC;
11594 break;
11595 default:
11596 fc = 0;
11597 goto exit;
11598 }
11599 memset(&ci, 0, sizeof(ci));
11600 if ((err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) {
11601 kfree(body);
11602 return err;
11603 }
11604
11605 channel = dtoh32(ci.hw_channel);
11606 if (channel <= CH_MAX_2G_CHANNEL)
11607 band = wiphy->bands[IEEE80211_BAND_2GHZ];
11608 else
11609 band = wiphy->bands[IEEE80211_BAND_5GHZ];
11610 if (!band) {
11611 WL_ERR(("No valid band\n"));
11612 if (body)
11613 kfree(body);
11614 return -EINVAL;
11615 }
11616 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11617 freq = ieee80211_channel_to_frequency(channel);
11618 (void)band->band;
11619 #else
11620 freq = ieee80211_channel_to_frequency(channel, band->band);
11621 #endif
11622
11623 err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
11624 &mgmt_frame, &len, body);
11625 if (err < 0)
11626 goto exit;
11627 isfree = true;
11628
11629 if ((event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) ||
11630 (event == WLC_E_DISASSOC_IND) ||
11631 ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH))) {
11632 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
11633 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0);
11634 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
11635 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0, GFP_ATOMIC);
11636 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
11637 defined(WL_COMPAT_WIRELESS)
11638 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
11639 #else
11640 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
11641 #endif
11642 }
11643
11644 exit:
11645 if (isfree)
11646 kfree(mgmt_frame);
11647 if (body)
11648 kfree(body);
11649 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
11650 sinfo.filled = 0;
11651 if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
11652 reason == DOT11_SC_SUCCESS) {
11653 /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
11654 * STATION_INFO_ASSOC_REQ_IES flag
11655 */
11656 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
11657 sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
11658 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
11659 if (!data) {
11660 WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
11661 return -EINVAL;
11662 }
11663 sinfo.assoc_req_ies = data;
11664 sinfo.assoc_req_ies_len = len;
11665 printf("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
11666 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
11667 } else if (event == WLC_E_DISASSOC_IND) {
11668 printf("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
11669 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
11670 } else if ((event == WLC_E_DEAUTH_IND) ||
11671 ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED))) {
11672 printf("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
11673 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
11674 }
11675 #endif
11676 return err;
11677 }
11678
11679 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11680 #define MAX_ASSOC_REJECT_ERR_STATUS 5
11681 int wl_get_connect_failed_status(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
11682 {
11683 u32 status = ntoh32(e->status);
11684
11685 cfg->assoc_reject_status = 0;
11686
11687 if (status == WLC_E_STATUS_FAIL) {
11688 WL_ERR(("auth assoc status event=%d e->status %d e->reason %d \n",
11689 ntoh32(cfg->event_auth_assoc.event_type),
11690 (int)ntoh32(cfg->event_auth_assoc.status),
11691 (int)ntoh32(cfg->event_auth_assoc.reason)));
11692
11693 switch ((int)ntoh32(cfg->event_auth_assoc.status)) {
11694 case WLC_E_STATUS_NO_ACK:
11695 cfg->assoc_reject_status = 1;
11696 break;
11697 case WLC_E_STATUS_FAIL:
11698 cfg->assoc_reject_status = 2;
11699 break;
11700 case WLC_E_STATUS_UNSOLICITED:
11701 cfg->assoc_reject_status = 3;
11702 break;
11703 case WLC_E_STATUS_TIMEOUT:
11704 cfg->assoc_reject_status = 4;
11705 break;
11706 case WLC_E_STATUS_ABORT:
11707 cfg->assoc_reject_status = 5;
11708 break;
11709 default:
11710 break;
11711 }
11712 if (cfg->assoc_reject_status) {
11713 if (ntoh32(cfg->event_auth_assoc.event_type) == WLC_E_ASSOC) {
11714 cfg->assoc_reject_status += MAX_ASSOC_REJECT_ERR_STATUS;
11715 }
11716 }
11717 }
11718
11719 WL_ERR(("assoc_reject_status %d \n", cfg->assoc_reject_status));
11720
11721 return 0;
11722 }
11723
11724 s32 wl_cfg80211_get_connect_failed_status(struct net_device *dev, char* cmd, int total_len)
11725 {
11726 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
11727 int bytes_written = 0;
11728
11729 if (cfg == NULL) {
11730 return -1;
11731 }
11732
11733 memset(cmd, 0, total_len);
11734 bytes_written = snprintf(cmd, 30, "assoc_reject.status %d", cfg->assoc_reject_status);
11735
11736 WL_ERR(("cmd: %s \n", cmd));
11737
11738 return bytes_written;
11739 }
11740 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
11741
11742 static s32
11743 wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev,
11744 const wl_event_msg_t *e)
11745 {
11746 u32 reason = ntoh32(e->reason);
11747 u32 event = ntoh32(e->event_type);
11748 struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
11749 WL_DBG(("event type : %d, reason : %d\n", event, reason));
11750
11751 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11752 memcpy(&cfg->event_auth_assoc, e, sizeof(wl_event_msg_t));
11753 WL_ERR(("event=%d status %d reason %d \n",
11754 ntoh32(cfg->event_auth_assoc.event_type),
11755 ntoh32(cfg->event_auth_assoc.status),
11756 ntoh32(cfg->event_auth_assoc.reason)));
11757 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
11758 if (sec) {
11759 switch (event) {
11760 case WLC_E_ASSOC:
11761 case WLC_E_AUTH:
11762 sec->auth_assoc_res_status = reason;
11763 default:
11764 break;
11765 }
11766 } else
11767 WL_ERR(("sec is NULL\n"));
11768 return 0;
11769 }
11770
11771 static s32
11772 wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
11773 const wl_event_msg_t *e, void *data)
11774 {
11775 s32 err = 0;
11776 u32 event = ntoh32(e->event_type);
11777 u16 flags = ntoh16(e->flags);
11778 u32 status = ntoh32(e->status);
11779 bool active;
11780 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11781 struct ieee80211_channel *channel = NULL;
11782 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11783 u32 chanspec, chan;
11784 u32 freq, band;
11785 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
11786
11787 if (event == WLC_E_JOIN) {
11788 WL_DBG(("joined in IBSS network\n"));
11789 }
11790 if (event == WLC_E_START) {
11791 WL_DBG(("started IBSS network\n"));
11792 }
11793 if (event == WLC_E_JOIN || event == WLC_E_START ||
11794 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
11795 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11796 err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
11797 if (unlikely(err)) {
11798 WL_ERR(("Could not get chanspec %d\n", err));
11799 return err;
11800 }
11801 chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
11802 band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
11803 freq = ieee80211_channel_to_frequency(chan, band);
11804 channel = ieee80211_get_channel(wiphy, freq);
11805 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
11806 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
11807 /* ROAM or Redundant */
11808 u8 *cur_bssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
11809 if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
11810 WL_DBG(("IBSS connected event from same BSSID("
11811 MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
11812 return err;
11813 }
11814 WL_INFORM(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
11815 MAC2STRDBG(cur_bssid), MAC2STRDBG((const u8 *)&e->addr)));
11816 wl_get_assoc_ies(cfg, ndev);
11817 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
11818 wl_update_bss_info(cfg, ndev, false);
11819 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11820 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
11821 #else
11822 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
11823 #endif
11824 }
11825 else {
11826 /* New connection */
11827 WL_INFORM(("IBSS connected to " MACDBG "\n",
11828 MAC2STRDBG((const u8 *)&e->addr)));
11829 wl_link_up(cfg);
11830 wl_get_assoc_ies(cfg, ndev);
11831 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
11832 wl_update_bss_info(cfg, ndev, false);
11833 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11834 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
11835 #else
11836 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
11837 #endif
11838 wl_set_drv_status(cfg, CONNECTED, ndev);
11839 active = true;
11840 wl_update_prof(cfg, ndev, NULL, (const void *)&active, WL_PROF_ACT);
11841 }
11842 } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
11843 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
11844 wl_clr_drv_status(cfg, CONNECTED, ndev);
11845 wl_link_down(cfg);
11846 wl_init_prof(cfg, ndev);
11847 }
11848 else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
11849 WL_DBG(("no action - join fail (IBSS mode)\n"));
11850 }
11851 else {
11852 WL_DBG(("no action (IBSS mode)\n"));
11853 }
11854 return err;
11855 }
11856
11857 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11858 #define WiFiALL_OUI "\x50\x6F\x9A" /* Wi-FiAll OUI */
11859 #define WiFiALL_OUI_LEN 3
11860 #define WiFiALL_OUI_TYPE 16
11861
11862 int wl_get_bss_info(struct bcm_cfg80211 *cfg, struct net_device *dev, uint8 *mac)
11863 {
11864 s32 err = 0;
11865 struct wl_bss_info *bi;
11866 uint8 eabuf[ETHER_ADDR_LEN];
11867 u32 rate, channel, freq, supported_rate, nss = 0, mcs_map, mode_80211 = 0;
11868 char rate_str[4];
11869 u8 *ie = NULL;
11870 u32 ie_len;
11871 struct wiphy *wiphy;
11872 struct cfg80211_bss *bss;
11873 bcm_tlv_t *interworking_ie = NULL;
11874 bcm_tlv_t *tlv_ie = NULL;
11875 bcm_tlv_t *vht_ie = NULL;
11876 vndr_ie_t *vndrie;
11877 int16 ie_11u_rel_num = -1, ie_mu_mimo_cap = -1;
11878 u32 i, remained_len, count = 0;
11879 char roam_count_str[4], akm_str[4];
11880 s32 val = 0;
11881
11882 /* get BSS information */
11883
11884 strncpy(cfg->bss_info, "x x x x x x x x x x x x x", GET_BSS_INFO_LEN);
11885
11886 memset(cfg->extra_buf, 0, WL_EXTRA_BUF_MAX);
11887 *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
11888
11889 err = wldev_ioctl_get(dev, WLC_GET_BSS_INFO, cfg->extra_buf, WL_EXTRA_BUF_MAX);
11890 if (unlikely(err)) {
11891 WL_ERR(("Could not get bss info %d\n", err));
11892 cfg->roam_count = 0;
11893 return -1;
11894 }
11895
11896 if (!mac) {
11897 WL_ERR(("mac is null \n"));
11898 cfg->roam_count = 0;
11899 return -1;
11900 }
11901
11902 memcpy(eabuf, mac, ETHER_ADDR_LEN);
11903
11904 bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
11905 channel = wf_chspec_ctlchan(bi->chanspec);
11906
11907 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11908 freq = ieee80211_channel_to_frequency(channel);
11909 #else
11910 if (channel > 14) {
11911 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
11912 } else {
11913 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
11914 }
11915 #endif
11916 rate = 0;
11917 err = wldev_ioctl_get(dev, WLC_GET_RATE, &rate, sizeof(rate));
11918 if (err) {
11919 WL_ERR(("Could not get rate (%d)\n", err));
11920 snprintf(rate_str, sizeof(rate_str), "x"); // Unknown
11921
11922 } else {
11923 rate = dtoh32(rate);
11924 snprintf(rate_str, sizeof(rate_str), "%d", (rate/2));
11925 }
11926
11927 //supported maximum rate
11928 supported_rate = (bi->rateset.rates[bi->rateset.count - 1] & 0x7f) / 2;
11929
11930 if (supported_rate < 12) {
11931 mode_80211 = 0; //11b maximum rate is 11Mbps. 11b mode
11932 } else {
11933 //It's not HT Capable case.
11934 if (channel > 14) {
11935 mode_80211 = 3; // 11a mode
11936 } else {
11937 mode_80211 = 1; // 11g mode
11938 }
11939 }
11940
11941 if (bi->n_cap) {
11942 /* check Rx MCS Map for HT */
11943 nss = 0;
11944 mode_80211 = 2;
11945 for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
11946 int8 bitmap = 0xFF;
11947 if (i == MAX_STREAMS_SUPPORTED-1) {
11948 bitmap = 0x7F;
11949 }
11950 if (bi->basic_mcs[i] & bitmap) {
11951 nss++;
11952 }
11953 }
11954 }
11955
11956 if (bi->vht_cap) {
11957 nss = 0;
11958 mode_80211 = 4;
11959 for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
11960 mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
11961 if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
11962 nss++;
11963 }
11964 }
11965 }
11966
11967 if (nss) {
11968 nss = nss - 1;
11969 }
11970
11971 wiphy = bcmcfg_to_wiphy(cfg);
11972 bss = CFG80211_GET_BSS(wiphy, NULL, eabuf, bi->SSID, bi->SSID_len);
11973 if (!bss) {
11974 WL_ERR(("Could not find the AP\n"));
11975 } else {
11976 #if defined(WL_CFG80211_P2P_DEV_IF)
11977 ie = (u8 *)bss->ies->data;
11978 ie_len = bss->ies->len;
11979 #else
11980 ie = bss->information_elements;
11981 ie_len = bss->len_information_elements;
11982 #endif /* WL_CFG80211_P2P_DEV_IF */
11983 }
11984
11985 if (ie) {
11986 ie_mu_mimo_cap = 0;
11987 ie_11u_rel_num = 0;
11988
11989 if (bi->vht_cap) {
11990 if ((vht_ie = bcm_parse_tlvs(ie, (u32)ie_len,
11991 DOT11_MNG_VHT_CAP_ID)) != NULL) {
11992 ie_mu_mimo_cap = (vht_ie->data[2] & 0x08) >> 3;
11993 }
11994 }
11995
11996 if ((interworking_ie = bcm_parse_tlvs(ie, (u32)ie_len,
11997 DOT11_MNG_INTERWORKING_ID)) != NULL) {
11998 if ((tlv_ie = bcm_parse_tlvs(ie, (u32)ie_len, DOT11_MNG_VS_ID)) != NULL) {
11999 remained_len = ie_len;
12000
12001 while (tlv_ie) {
12002 if (count > MAX_VNDR_IE_NUMBER)
12003 break;
12004
12005 if (tlv_ie->id == DOT11_MNG_VS_ID) {
12006 vndrie = (vndr_ie_t *) tlv_ie;
12007
12008 if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
12009 WL_ERR(("%s: invalid vndr ie."
12010 "length is too small %d\n",
12011 __FUNCTION__, vndrie->len));
12012 break;
12013 }
12014
12015 if (!bcmp(vndrie->oui,
12016 (u8*)WiFiALL_OUI, WiFiALL_OUI_LEN) &&
12017 (vndrie->data[0] == WiFiALL_OUI_TYPE))
12018 {
12019 WL_ERR(("Found Wi-FiAll OUI oui.\n"));
12020 ie_11u_rel_num = vndrie->data[1];
12021 ie_11u_rel_num = (ie_11u_rel_num & 0xf0)>>4;
12022 ie_11u_rel_num += 1;
12023
12024 break;
12025 }
12026 }
12027 count++;
12028 tlv_ie = bcm_next_tlv(tlv_ie, &remained_len);
12029 }
12030 }
12031 }
12032 }
12033
12034 for (i = 0; i < bi->SSID_len; i++) {
12035 if (bi->SSID[i] == ' ') {
12036 bi->SSID[i] = '_';
12037 }
12038 }
12039
12040 //0 : None, 1 : OKC, 2 : FT, 3 : CCKM
12041 err = wldev_iovar_getint(dev, "wpa_auth", &val);
12042 if (unlikely(err)) {
12043 WL_ERR(("could not get wpa_auth (%d)\n", err));
12044 snprintf(akm_str, sizeof(akm_str), "x"); // Unknown
12045 } else {
12046 WL_ERR(("wpa_auth val %d \n", val));
12047 #if defined(BCMEXTCCX)
12048 if (val & (WPA_AUTH_CCKM | WPA2_AUTH_CCKM)) {
12049 snprintf(akm_str, sizeof(akm_str), "3");
12050 } else
12051 #endif
12052 if (val & WPA2_AUTH_FT) {
12053 snprintf(akm_str, sizeof(akm_str), "2");
12054 } else if (val & (WPA_AUTH_UNSPECIFIED | WPA2_AUTH_UNSPECIFIED)) {
12055 snprintf(akm_str, sizeof(akm_str), "1");
12056 } else {
12057 snprintf(akm_str, sizeof(akm_str), "0");
12058 }
12059 }
12060
12061 if (cfg->roam_offload) {
12062 snprintf(roam_count_str, sizeof(roam_count_str), "x"); // Unknown
12063 } else {
12064 snprintf(roam_count_str, sizeof(roam_count_str), "%d", cfg->roam_count);
12065 }
12066 cfg->roam_count = 0;
12067
12068 WL_ERR(("BSSID:" MACDBG " SSID %s \n", MAC2STRDBG(eabuf), bi->SSID));
12069 WL_ERR(("freq:%d, BW:%s, RSSI:%d dBm, Rate:%d Mbps, 11mode:%d, stream:%d,"
12070 "MU-MIMO:%d, Passpoint:%d, SNR:%d, Noise:%d, \n"
12071 "akm:%s roam:%s \n",
12072 freq, wf_chspec_to_bw_str(bi->chanspec),
12073 dtoh32(bi->RSSI), (rate / 2), mode_80211, nss,
12074 ie_mu_mimo_cap, ie_11u_rel_num, bi->SNR, bi->phy_noise,
12075 akm_str, roam_count_str));
12076
12077 if (ie) {
12078 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
12079 "%02x:%02x:%02x %d %s %d %s %d %d %d %d %d %d %s %s",
12080 eabuf[0], eabuf[1], eabuf[2],
12081 freq, wf_chspec_to_bw_str(bi->chanspec),
12082 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
12083 ie_mu_mimo_cap, ie_11u_rel_num,
12084 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
12085 } else {
12086 //ie_mu_mimo_cap and ie_11u_rel_num is unknow.
12087 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
12088 "%02x:%02x:%02x %d %s %d %s %d %d x x %d %d %s %s",
12089 eabuf[0], eabuf[1], eabuf[2],
12090 freq, wf_chspec_to_bw_str(bi->chanspec),
12091 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
12092 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
12093 }
12094
12095 CFG80211_PUT_BSS(wiphy, bss);
12096
12097 return 0;
12098 }
12099
12100 s32 wl_cfg80211_get_bss_info(struct net_device *dev, char* cmd, int total_len)
12101 {
12102 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
12103
12104 if (cfg == NULL) {
12105 return -1;
12106 }
12107
12108 memset(cmd, 0, total_len);
12109 memcpy(cmd, cfg->bss_info, GET_BSS_INFO_LEN);
12110
12111 WL_ERR(("cmd: %s \n", cmd));
12112
12113 return GET_BSS_INFO_LEN;
12114 }
12115
12116 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12117
12118 static s32
12119 wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12120 const wl_event_msg_t *e, void *data)
12121 {
12122 bool act;
12123 struct net_device *ndev = NULL;
12124 s32 err = 0;
12125 u32 event = ntoh32(e->event_type);
12126 struct wiphy *wiphy = NULL;
12127 struct cfg80211_bss *bss = NULL;
12128 struct wlc_ssid *ssid = NULL;
12129 u8 *bssid = 0;
12130 dhd_pub_t *dhdp;
12131 int vndr_oui_num = 0;
12132 char vndr_oui[MAX_VNDR_OUI_STR_LEN] = {0, };
12133
12134 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12135 dhdp = (dhd_pub_t *)(cfg->pub);
12136 BCM_REFERENCE(dhdp);
12137
12138 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
12139 err = wl_notify_connect_status_ap(cfg, ndev, e, data);
12140 } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS) {
12141 err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
12142 } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) {
12143 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
12144 ntoh32(e->event_type), ntoh32(e->status), ndev));
12145 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
12146 wl_get_auth_assoc_status(cfg, ndev, e);
12147 return 0;
12148 }
12149 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
12150 if (wl_is_linkup(cfg, e, ndev)) {
12151 wl_link_up(cfg);
12152 act = true;
12153 if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
12154 if (event == WLC_E_LINK &&
12155 #ifdef DHD_LOSSLESS_ROAMING
12156 !cfg->roam_offload &&
12157 #endif /* DHD_LOSSLESS_ROAMING */
12158 wl_get_drv_status(cfg, CONNECTED, ndev)) {
12159 wl_bss_roaming_done(cfg, ndev, e, data);
12160 }
12161
12162 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
12163 vndr_oui_num = wl_vndr_ies_get_vendor_oui(cfg,
12164 ndev, vndr_oui, ARRAYSIZE(vndr_oui));
12165 #if defined(STAT_REPORT)
12166 /* notify STA connection only */
12167 wl_stat_report_notify_connected(cfg);
12168 #endif /* STAT_REPORT */
12169 }
12170
12171 printf("wl_bss_connect_done succeeded with "
12172 MACDBG " %s%s\n", MAC2STRDBG((const u8*)(&e->addr)),
12173 vndr_oui_num > 0 ? "vndr_oui: " : "",
12174 vndr_oui_num > 0 ? vndr_oui : "");
12175
12176 wl_bss_connect_done(cfg, ndev, e, data, true);
12177 dhd_conf_set_intiovar(cfg->pub, WLC_SET_VAR, "phy_oclscdenable", cfg->pub->conf->phy_oclscdenable, 0, FALSE);
12178 WL_DBG(("joined in BSS network \"%s\"\n",
12179 ((struct wlc_ssid *)
12180 wl_read_prof(cfg, ndev, WL_PROF_SSID))->SSID));
12181
12182 #ifdef WBTEXT
12183 if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION &&
12184 dhdp->wbtext_support &&
12185 event == WLC_E_SET_SSID) {
12186 /* set wnm_keepalives_max_idle after association */
12187 wl_cfg80211_wbtext_set_wnm_maxidle(cfg, ndev);
12188 /* send nbr request or BTM query to update RCC */
12189 wl_cfg80211_wbtext_update_rcc(cfg, ndev);
12190 }
12191 #endif /* WBTEXT */
12192 }
12193 wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
12194 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
12195 dhd_conf_set_wme(cfg->pub, 0);
12196 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
12197 dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_CLIENT, -1);
12198 }
12199 } else if (WL_IS_LINKDOWN(cfg, e, data) ||
12200 ((event == WLC_E_SET_SSID) &&
12201 (ntoh32(e->status) != WLC_E_STATUS_SUCCESS) &&
12202 (wl_get_drv_status(cfg, CONNECTED, ndev)))) {
12203
12204 WL_INFORM(("connection state bit status: [%d:%d:%d:%d]\n",
12205 wl_get_drv_status(cfg, CONNECTING, ndev),
12206 wl_get_drv_status(cfg, CONNECTED, ndev),
12207 wl_get_drv_status(cfg, DISCONNECTING, ndev),
12208 wl_get_drv_status(cfg, NESTED_CONNECT, ndev)));
12209
12210 if (wl_get_drv_status(cfg, DISCONNECTING, ndev) &&
12211 (wl_get_drv_status(cfg, NESTED_CONNECT, ndev) ||
12212 wl_get_drv_status(cfg, CONNECTING, ndev))) {
12213 /* wl_cfg80211_connect was called before 'DISCONNECTING' was
12214 * cleared. Deauth/Link down event is caused by WLC_DISASSOC
12215 * command issued from the wl_cfg80211_connect context. Ignore
12216 * the event to avoid pre-empting the current connection
12217 */
12218 WL_INFORM(("Nested connection case. Drop event. \n"));
12219 wl_clr_drv_status(cfg, NESTED_CONNECT, ndev);
12220 wl_clr_drv_status(cfg, DISCONNECTING, ndev);
12221 /* Not in 'CONNECTED' state, clear it */
12222 wl_clr_drv_status(cfg, CONNECTED, ndev);
12223 return 0;
12224 }
12225
12226 #ifdef DHD_LOSSLESS_ROAMING
12227 wl_del_roam_timeout(cfg);
12228 #endif
12229 #ifdef P2PLISTEN_AP_SAMECHN
12230 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
12231 wl_cfg80211_set_p2p_resp_ap_chn(ndev, 0);
12232 cfg->p2p_resp_apchn_status = false;
12233 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
12234 }
12235 #endif /* P2PLISTEN_AP_SAMECHN */
12236 wl_cfg80211_cancel_scan(cfg);
12237
12238 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
12239 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
12240 wl_get_bss_info(cfg, ndev, (u8*)(&e->addr));
12241 }
12242 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12243 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
12244 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
12245 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
12246 bool fw_assoc_state = TRUE;
12247 dhd_pub_t *dhd = (dhd_pub_t *)cfg->pub;
12248 fw_assoc_state = dhd_is_associated(dhd, e->ifidx, &err);
12249 if (!fw_assoc_state) {
12250 WL_ERR(("Event sends up even different BSSID"
12251 " cur: " MACDBG " event: " MACDBG"\n",
12252 MAC2STRDBG(curbssid),
12253 MAC2STRDBG((const u8*)(&e->addr))));
12254 } else {
12255 WL_ERR(("BSSID of event is not the connected BSSID"
12256 "(ignore it) cur: " MACDBG
12257 " event: " MACDBG"\n",
12258 MAC2STRDBG(curbssid),
12259 MAC2STRDBG((const u8*)(&e->addr))));
12260 return 0;
12261 }
12262 }
12263 }
12264 /* Explicitly calling unlink to remove BSS in CFG */
12265 wiphy = bcmcfg_to_wiphy(cfg);
12266 ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
12267 bssid = (u8 *)wl_read_prof(cfg, ndev, WL_PROF_BSSID);
12268 if (ssid && bssid) {
12269 bss = CFG80211_GET_BSS(wiphy, NULL, bssid,
12270 ssid->SSID, ssid->SSID_len);
12271 if (bss) {
12272 cfg80211_unlink_bss(wiphy, bss);
12273 CFG80211_PUT_BSS(wiphy, bss);
12274 }
12275 }
12276
12277 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
12278 scb_val_t scbval;
12279 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
12280 s32 reason = 0;
12281 struct ether_addr bssid_dongle = {{0, 0, 0, 0, 0, 0}};
12282 struct ether_addr bssid_null = {{0, 0, 0, 0, 0, 0}};
12283
12284 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
12285 reason = ntoh32(e->reason);
12286 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
12287 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
12288
12289 printf("link down if %s may call cfg80211_disconnected. "
12290 "event : %d, reason=%d from " MACDBG "\n",
12291 ndev->name, event, ntoh32(e->reason),
12292 MAC2STRDBG((const u8*)(&e->addr)));
12293
12294 /* roam offload does not sync BSSID always, get it from dongle */
12295 if (cfg->roam_offload) {
12296 memset(&bssid_dongle, 0, sizeof(bssid_dongle));
12297 if (wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid_dongle,
12298 sizeof(bssid_dongle)) == BCME_OK) {
12299 /* if not roam case, it would return null bssid */
12300 if (memcmp(&bssid_dongle, &bssid_null,
12301 ETHER_ADDR_LEN) != 0) {
12302 curbssid = (u8 *)&bssid_dongle;
12303 }
12304 }
12305 }
12306 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
12307 bool fw_assoc_state = TRUE;
12308 dhd_pub_t *dhd = (dhd_pub_t *)cfg->pub;
12309 fw_assoc_state = dhd_is_associated(dhd, e->ifidx, &err);
12310 if (!fw_assoc_state) {
12311 WL_ERR(("Event sends up even different BSSID"
12312 " cur: " MACDBG " event: " MACDBG"\n",
12313 MAC2STRDBG(curbssid),
12314 MAC2STRDBG((const u8*)(&e->addr))));
12315 } else {
12316 WL_ERR(("BSSID of event is not the connected BSSID"
12317 "(ignore it) cur: " MACDBG
12318 " event: " MACDBG"\n",
12319 MAC2STRDBG(curbssid),
12320 MAC2STRDBG((const u8*)(&e->addr))));
12321 return 0;
12322 }
12323 }
12324
12325 #ifdef DBG_PKT_MON
12326 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
12327 DHD_DBG_PKT_MON_STOP(dhdp);
12328 }
12329 #endif /* DBG_PKT_MON */
12330
12331 /* clear RSSI monitor, framework will set new cfg */
12332 #ifdef RSSI_MONITOR_SUPPORT
12333 dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg),
12334 FALSE, 0, 0);
12335 #endif /* RSSI_MONITOR_SUPPORT */
12336 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
12337 // terence 20130703: Fix for wrong group_capab (timing issue)
12338 cfg->p2p_disconnected = 1;
12339 }
12340 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
12341 if (wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
12342 CFG80211_DISCONNECTED(ndev, reason, NULL, 0, false, GFP_KERNEL);
12343 }
12344 #endif
12345 memcpy(&cfg->disconnected_bssid, curbssid, ETHER_ADDR_LEN);
12346 wl_clr_drv_status(cfg, CONNECTED, ndev);
12347
12348 if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
12349 /* To make sure disconnect, explictly send dissassoc
12350 * for BSSID 00:00:00:00:00:00 issue
12351 */
12352 scbval.val = WLAN_REASON_DEAUTH_LEAVING;
12353
12354 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
12355 scbval.val = htod32(scbval.val);
12356 err = wldev_ioctl_set(ndev, WLC_DISASSOC, &scbval,
12357 sizeof(scb_val_t));
12358 if (err < 0) {
12359 WL_ERR(("WLC_DISASSOC error %d\n", err));
12360 err = 0;
12361 }
12362 }
12363
12364 /* Send up deauth and clear states */
12365 CFG80211_DISCONNECTED(ndev, reason, NULL, 0,
12366 false, GFP_KERNEL);
12367 wl_link_down(cfg);
12368 wl_init_prof(cfg, ndev);
12369 #ifdef WBTEXT
12370 /* when STA was disconnected, clear join pref and set wbtext */
12371 if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION) {
12372 char smbuf[WLC_IOCTL_SMLEN];
12373 char clear[] = { 0x01, 0x02, 0x00, 0x00, 0x03,
12374 0x02, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00 };
12375 if ((err = wldev_iovar_setbuf(ndev, "join_pref",
12376 clear, sizeof(clear), smbuf,
12377 sizeof(smbuf), NULL))
12378 == BCME_OK) {
12379 if ((err = wldev_iovar_setint(ndev,
12380 "wnm_bsstrans_resp",
12381 WL_BSSTRANS_POLICY_PRODUCT_WBTEXT))
12382 == BCME_OK) {
12383 wl_cfg80211_wbtext_set_default(ndev);
12384 } else {
12385 WL_ERR(("%s: Failed to set wbtext = %d\n",
12386 __FUNCTION__, err));
12387 }
12388 } else {
12389 WL_ERR(("%s: Failed to clear join pref = %d\n",
12390 __FUNCTION__, err));
12391 }
12392 wl_cfg80211_wbtext_clear_bssid_list(cfg);
12393 }
12394 #endif /* WBTEXT */
12395 wl_vndr_ies_clear_vendor_oui_list(cfg);
12396 }
12397 else if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
12398 printf("link down, during connecting\n");
12399 /* Issue WLC_DISASSOC to prevent FW roam attempts */
12400 err = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0);
12401 if (err < 0) {
12402 WL_ERR(("CONNECTING state, WLC_DISASSOC error %d\n", err));
12403 err = 0;
12404 }
12405 WL_INFORM(("Clear drv CONNECTING status\n"));
12406 wl_clr_drv_status(cfg, CONNECTING, ndev);
12407 #ifdef ESCAN_RESULT_PATCH
12408 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
12409 (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
12410 (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
12411 /* In case this event comes while associating another AP */
12412 #endif /* ESCAN_RESULT_PATCH */
12413 wl_bss_connect_done(cfg, ndev, e, data, false);
12414 }
12415 wl_clr_drv_status(cfg, DISCONNECTING, ndev);
12416
12417 /* if link down, bsscfg is diabled */
12418 if (ndev != bcmcfg_to_prmry_ndev(cfg))
12419 complete(&cfg->iface_disable);
12420 #ifdef WLTDLS
12421 /* re-enable TDLS if the number of connected interfaces
12422 * is less than 2.
12423 */
12424 wl_cfg80211_tdls_config(cfg, TDLS_STATE_DISCONNECT, false);
12425 #endif /* WLTDLS */
12426 } else if (wl_is_nonetwork(cfg, e)) {
12427 printf("connect failed event=%d e->status %d e->reason %d \n",
12428 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
12429 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
12430 if (event == WLC_E_SET_SSID) {
12431 wl_get_connect_failed_status(cfg, e);
12432 }
12433 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12434
12435 if (wl_get_drv_status(cfg, DISCONNECTING, ndev) &&
12436 wl_get_drv_status(cfg, CONNECTING, ndev)) {
12437 wl_clr_drv_status(cfg, DISCONNECTING, ndev);
12438 wl_clr_drv_status(cfg, CONNECTING, ndev);
12439 wl_cfg80211_scan_abort(cfg);
12440 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
12441 return err;
12442 }
12443 /* Clean up any pending scan request */
12444 wl_cfg80211_cancel_scan(cfg);
12445
12446 if (wl_get_drv_status(cfg, CONNECTING, ndev))
12447 wl_bss_connect_done(cfg, ndev, e, data, false);
12448 } else {
12449 WL_DBG(("%s nothing\n", __FUNCTION__));
12450 }
12451 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
12452 }
12453 else {
12454 WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg, ndev)));
12455 }
12456 return err;
12457 }
12458
12459 #ifdef WL_RELMCAST
12460 void wl_cfg80211_set_rmc_pid(struct net_device *dev, int pid)
12461 {
12462 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
12463 if (pid > 0)
12464 cfg->rmc_event_pid = pid;
12465 WL_DBG(("set pid for rmc event : pid=%d\n", pid));
12466 }
12467 #endif /* WL_RELMCAST */
12468
12469 #ifdef WL_RELMCAST
12470 static s32
12471 wl_notify_rmc_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12472 const wl_event_msg_t *e, void *data)
12473 {
12474 u32 evt = ntoh32(e->event_type);
12475 u32 reason = ntoh32(e->reason);
12476 int ret = -1;
12477
12478 switch (reason) {
12479 case WLC_E_REASON_RMC_AR_LOST:
12480 case WLC_E_REASON_RMC_AR_NO_ACK:
12481 if (cfg->rmc_event_pid != 0) {
12482 ret = wl_netlink_send_msg(cfg->rmc_event_pid,
12483 RMC_EVENT_LEADER_CHECK_FAIL,
12484 cfg->rmc_event_seq++, NULL, 0);
12485 }
12486 break;
12487 default:
12488 break;
12489 }
12490 WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt, cfg->rmc_event_pid, ret));
12491 return ret;
12492 }
12493 #endif /* WL_RELMCAST */
12494
12495 #ifdef GSCAN_SUPPORT
12496 static s32
12497 wl_handle_roam_exp_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12498 const wl_event_msg_t *e, void *data)
12499 {
12500 struct net_device *ndev = NULL;
12501 u32 datalen = be32_to_cpu(e->datalen);
12502
12503 if (datalen) {
12504 wl_roam_exp_event_t *evt_data = (wl_roam_exp_event_t *)data;
12505 if (evt_data->version == ROAM_EXP_EVENT_VERSION) {
12506 wlc_ssid_t *ssid = &evt_data->cur_ssid;
12507 struct wireless_dev *wdev;
12508 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12509 if (ndev) {
12510 wdev = ndev->ieee80211_ptr;
12511 wdev->ssid_len = min(ssid->SSID_len, (uint32)DOT11_MAX_SSID_LEN);
12512 memcpy(wdev->ssid, ssid->SSID, wdev->ssid_len);
12513 WL_ERR(("SSID is %s\n", ssid->SSID));
12514 wl_update_prof(cfg, ndev, NULL, ssid, WL_PROF_SSID);
12515 } else {
12516 WL_ERR(("NULL ndev!\n"));
12517 }
12518 } else {
12519 WL_ERR(("Version mismatch %d, expected %d", evt_data->version,
12520 ROAM_EXP_EVENT_VERSION));
12521 }
12522 }
12523 return BCME_OK;
12524 }
12525 #endif /* GSCAN_SUPPORT */
12526
12527 #ifdef RSSI_MONITOR_SUPPORT
12528 static s32 wl_handle_rssi_monitor_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12529 const wl_event_msg_t *e, void *data)
12530 {
12531
12532 #if defined(WL_VENDOR_EXT_SUPPORT) || defined(CONFIG_BCMDHD_VENDOR_EXT)
12533 u32 datalen = be32_to_cpu(e->datalen);
12534 struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12535 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
12536
12537 if (datalen) {
12538 wl_rssi_monitor_evt_t *evt_data = (wl_rssi_monitor_evt_t *)data;
12539 if (evt_data->version == RSSI_MONITOR_VERSION) {
12540 dhd_rssi_monitor_evt_t monitor_data;
12541 monitor_data.version = DHD_RSSI_MONITOR_EVT_VERSION;
12542 monitor_data.cur_rssi = evt_data->cur_rssi;
12543 memcpy(&monitor_data.BSSID, &e->addr, ETHER_ADDR_LEN);
12544 wl_cfgvendor_send_async_event(wiphy, ndev,
12545 GOOGLE_RSSI_MONITOR_EVENT,
12546 &monitor_data, sizeof(monitor_data));
12547 } else {
12548 WL_ERR(("Version mismatch %d, expected %d", evt_data->version,
12549 RSSI_MONITOR_VERSION));
12550 }
12551 }
12552 #endif /* WL_VENDOR_EXT_SUPPORT || CONFIG_BCMDHD_VENDOR_EXT */
12553 return BCME_OK;
12554 }
12555 #endif /* RSSI_MONITOR_SUPPORT */
12556
12557 static s32
12558 wl_notify_roaming_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12559 const wl_event_msg_t *e, void *data)
12560 {
12561 bool act;
12562 struct net_device *ndev = NULL;
12563 s32 err = 0;
12564 u32 event = be32_to_cpu(e->event_type);
12565 u32 status = be32_to_cpu(e->status);
12566 #ifdef DHD_LOSSLESS_ROAMING
12567 struct wl_security *sec;
12568 #endif
12569 WL_DBG(("Enter \n"));
12570
12571 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12572
12573 if ((!cfg->disable_roam_event) && (event == WLC_E_BSSID)) {
12574 wl_add_remove_eventmsg(ndev, WLC_E_ROAM, false);
12575 cfg->disable_roam_event = TRUE;
12576 }
12577
12578 if ((cfg->disable_roam_event) && (event == WLC_E_ROAM))
12579 return err;
12580
12581 if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status == WLC_E_STATUS_SUCCESS) {
12582 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
12583 #ifdef DHD_LOSSLESS_ROAMING
12584 sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
12585 /* In order to reduce roaming delay, wl_bss_roaming_done is
12586 * early called with WLC_E_LINK event. It is called from
12587 * here only if WLC_E_LINK event is blocked for specific
12588 * security type.
12589 */
12590 if (IS_AKM_SUITE_FT(sec)) {
12591 wl_bss_roaming_done(cfg, ndev, e, data);
12592 }
12593 /* Roam timer is deleted mostly from wl_cfg80211_change_station
12594 * after roaming is finished successfully. We need to delete
12595 * the timer from here only for some security types that aren't
12596 * using wl_cfg80211_change_station to authorize SCB
12597 */
12598 if (IS_AKM_SUITE_FT(sec) || IS_AKM_SUITE_CCKM(sec)) {
12599 wl_del_roam_timeout(cfg);
12600 }
12601 #else
12602 wl_bss_roaming_done(cfg, ndev, e, data);
12603 #endif /* DHD_LOSSLESS_ROAMING */
12604 } else {
12605 wl_bss_connect_done(cfg, ndev, e, data, true);
12606 }
12607 act = true;
12608 wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
12609 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
12610
12611 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
12612 wl_vndr_ies_get_vendor_oui(cfg, ndev, NULL, 0);
12613 }
12614 }
12615 #ifdef DHD_LOSSLESS_ROAMING
12616 else if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status != WLC_E_STATUS_SUCCESS) {
12617 wl_del_roam_timeout(cfg);
12618 }
12619 #endif
12620 return err;
12621 }
12622
12623 #ifdef CUSTOM_EVENT_PM_WAKE
12624 uint32 last_dpm_upd_time = 0; /* ms */
12625 #define DPM_UPD_LMT_TIME 25000 /* ms */
12626 #define DPM_UPD_LMT_RSSI -85 /* dbm */
12627
12628 static s32
12629 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12630 const wl_event_msg_t *e, void *data)
12631 {
12632 s32 err = BCME_OK;
12633 struct net_device *ndev = NULL;
12634 u8 *pbuf = NULL;
12635 uint32 cur_dpm_upd_time = 0;
12636 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
12637 s32 rssi;
12638 scb_val_t scb_val;
12639
12640 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12641
12642 pbuf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
12643 if (pbuf == NULL) {
12644 WL_ERR(("failed to allocate local pbuf\n"));
12645 return -ENOMEM;
12646 }
12647
12648 err = wldev_iovar_getbuf_bsscfg(ndev, "dump",
12649 "pm", strlen("pm"), pbuf, WLC_IOCTL_MEDLEN, 0, &cfg->ioctl_buf_sync);
12650
12651 if (err) {
12652 WL_ERR(("dump ioctl err = %d", err));
12653 } else {
12654 WL_ERR(("PM status : %s\n", pbuf));
12655 }
12656
12657 if (pbuf) {
12658 kfree(pbuf);
12659 }
12660
12661 if (dhd->early_suspended) {
12662 /* LCD off */
12663 memset(&scb_val, 0, sizeof(scb_val_t));
12664 scb_val.val = 0;
12665 err = wldev_ioctl_get(ndev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
12666 if (err) {
12667 WL_ERR(("Could not get rssi (%d)\n", err));
12668 }
12669 rssi = wl_rssi_offset(dtoh32(scb_val.val));
12670 WL_ERR(("[%s] RSSI %d dBm\n", ndev->name, rssi));
12671 if (rssi > DPM_UPD_LMT_RSSI) {
12672 return err;
12673 }
12674 } else {
12675 /* LCD on */
12676 return err;
12677 }
12678
12679 if (last_dpm_upd_time == 0) {
12680 last_dpm_upd_time = OSL_SYSUPTIME();
12681 } else {
12682 cur_dpm_upd_time = OSL_SYSUPTIME();
12683 if (cur_dpm_upd_time - last_dpm_upd_time < DPM_UPD_LMT_TIME) {
12684 scb_val_t scbval;
12685 bzero(&scbval, sizeof(scb_val_t));
12686
12687 err = wldev_ioctl_set(ndev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
12688 if (err < 0) {
12689 WL_ERR(("%s: Disassoc error %d\n", __FUNCTION__, err));
12690 return err;
12691 }
12692 WL_ERR(("%s: Force Disassoc due to updated DPM event.\n", __FUNCTION__));
12693
12694 last_dpm_upd_time = 0;
12695 } else {
12696 last_dpm_upd_time = cur_dpm_upd_time;
12697 }
12698 }
12699
12700 return err;
12701 }
12702 #endif /* CUSTOM_EVENT_PM_WAKE */
12703
12704 #ifdef QOS_MAP_SET
12705 /* get user priority table */
12706 uint8 *
12707 wl_get_up_table(dhd_pub_t * dhdp, int idx)
12708 {
12709 struct net_device *ndev;
12710 struct bcm_cfg80211 *cfg;
12711
12712 ndev = dhd_idx2net(dhdp, idx);
12713 if (ndev) {
12714 cfg = wl_get_cfg(ndev);
12715 if (cfg)
12716 return (uint8 *)(cfg->up_table);
12717 }
12718
12719 return NULL;
12720 }
12721 #endif /* QOS_MAP_SET */
12722
12723 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
12724 static s32
12725 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12726 const wl_event_msg_t *e, void *data)
12727 {
12728 struct wl_security *sec;
12729 struct net_device *ndev;
12730 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
12731 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
12732 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
12733 u32 status = ntoh32(e->status);
12734 u32 reason = ntoh32(e->reason);
12735
12736 BCM_REFERENCE(sec);
12737
12738 if (status == WLC_E_STATUS_SUCCESS && reason != WLC_E_REASON_INITIAL_ASSOC) {
12739 WL_ERR(("Attempting roam with reason code : %d\n", reason));
12740 }
12741
12742 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12743
12744 #ifdef DBG_PKT_MON
12745 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
12746 DHD_DBG_PKT_MON_STOP(dhdp);
12747 DHD_DBG_PKT_MON_START(dhdp);
12748 }
12749 #endif /* DBG_PKT_MON */
12750
12751 #ifdef DHD_LOSSLESS_ROAMING
12752 sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
12753 /* Disable Lossless Roaming for specific AKM suite
12754 * Any other AKM suite can be added below if transition time
12755 * is delayed because of Lossless Roaming
12756 * and it causes any certication failure
12757 */
12758 if (IS_AKM_SUITE_FT(sec)) {
12759 return BCME_OK;
12760 }
12761 dhdp->dequeue_prec_map = 1 << PRIO_8021D_NC;
12762 /* Restore flow control */
12763 dhd_txflowcontrol(dhdp, ALL_INTERFACES, OFF);
12764
12765 mod_timer(&cfg->roam_timeout, jiffies + msecs_to_jiffies(WL_ROAM_TIMEOUT_MS));
12766 #endif /* DHD_LOSSLESS_ROAMING */
12767 return BCME_OK;
12768
12769 }
12770 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
12771 #ifdef ENABLE_TEMP_THROTTLING
12772 static s32
12773 wl_check_rx_throttle_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12774 const wl_event_msg_t *e, void *data)
12775 {
12776 s32 err = 0;
12777 u32 status = ntoh32(e->status);
12778 u32 reason = ntoh32(e->reason);
12779
12780 WL_ERR_EX(("RX THROTTLE : status=%d, reason=0x%x\n", status, reason));
12781
12782 return err;
12783 }
12784 #endif /* ENABLE_TEMP_THROTTLING */
12785
12786 static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev)
12787 {
12788 wl_assoc_info_t assoc_info;
12789 struct wl_connect_info *conn_info = wl_to_conn(cfg);
12790 s32 err = 0;
12791 #ifdef QOS_MAP_SET
12792 bcm_tlv_t * qos_map_ie = NULL;
12793 #endif /* QOS_MAP_SET */
12794
12795 WL_DBG(("Enter \n"));
12796 err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, cfg->extra_buf,
12797 WL_ASSOC_INFO_MAX, NULL);
12798 if (unlikely(err)) {
12799 WL_ERR(("could not get assoc info (%d)\n", err));
12800 return err;
12801 }
12802 memcpy(&assoc_info, cfg->extra_buf, sizeof(wl_assoc_info_t));
12803 assoc_info.req_len = htod32(assoc_info.req_len);
12804 assoc_info.resp_len = htod32(assoc_info.resp_len);
12805 assoc_info.flags = htod32(assoc_info.flags);
12806 if (conn_info->req_ie_len) {
12807 conn_info->req_ie_len = 0;
12808 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
12809 }
12810 if (conn_info->resp_ie_len) {
12811 conn_info->resp_ie_len = 0;
12812 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
12813 }
12814 if (assoc_info.req_len) {
12815 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, cfg->extra_buf,
12816 WL_ASSOC_INFO_MAX, NULL);
12817 if (unlikely(err)) {
12818 WL_ERR(("could not get assoc req (%d)\n", err));
12819 return err;
12820 }
12821 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
12822 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
12823 conn_info->req_ie_len -= ETHER_ADDR_LEN;
12824 }
12825 if (conn_info->req_ie_len <= MAX_REQ_LINE)
12826 memcpy(conn_info->req_ie, cfg->extra_buf, conn_info->req_ie_len);
12827 else {
12828 WL_ERR(("IE size %d above max %d size \n",
12829 conn_info->req_ie_len, MAX_REQ_LINE));
12830 return err;
12831 }
12832 } else {
12833 conn_info->req_ie_len = 0;
12834 }
12835 if (assoc_info.resp_len) {
12836 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, cfg->extra_buf,
12837 WL_ASSOC_INFO_MAX, NULL);
12838 if (unlikely(err)) {
12839 WL_ERR(("could not get assoc resp (%d)\n", err));
12840 return err;
12841 }
12842 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
12843 if (conn_info->resp_ie_len <= MAX_REQ_LINE) {
12844 memcpy(conn_info->resp_ie, cfg->extra_buf, conn_info->resp_ie_len);
12845 } else {
12846 WL_ERR(("IE size %d above max %d size \n",
12847 conn_info->resp_ie_len, MAX_REQ_LINE));
12848 return err;
12849 }
12850
12851 #ifdef QOS_MAP_SET
12852 /* find qos map set ie */
12853 if ((qos_map_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
12854 DOT11_MNG_QOS_MAP_ID)) != NULL) {
12855 WL_DBG((" QoS map set IE found in assoc response\n"));
12856 if (!cfg->up_table) {
12857 cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
12858 }
12859 wl_set_up_table(cfg->up_table, qos_map_ie);
12860 } else {
12861 kfree(cfg->up_table);
12862 cfg->up_table = NULL;
12863 }
12864 #endif /* QOS_MAP_SET */
12865 } else {
12866 conn_info->resp_ie_len = 0;
12867 }
12868 WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
12869 conn_info->resp_ie_len));
12870
12871 return err;
12872 }
12873
12874 static s32 wl_ch_to_chanspec(struct net_device *dev, int ch, struct wl_join_params *join_params,
12875 size_t *join_params_size)
12876 {
12877 s32 bssidx = -1;
12878 chanspec_t chanspec = 0, chspec;
12879
12880 if (ch != 0) {
12881 struct bcm_cfg80211 *cfg =
12882 (struct bcm_cfg80211 *)wiphy_priv(dev->ieee80211_ptr->wiphy);
12883 join_params->params.chanspec_num = 1;
12884 join_params->params.chanspec_list[0] = ch;
12885
12886 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
12887 chanspec |= WL_CHANSPEC_BAND_2G;
12888 else
12889 chanspec |= WL_CHANSPEC_BAND_5G;
12890
12891 /* Get the min_bw set for the interface */
12892 chspec = wl_cfg80211_ulb_get_min_bw_chspec(cfg, dev->ieee80211_ptr, bssidx);
12893 if (chspec == INVCHANSPEC) {
12894 WL_ERR(("Invalid chanspec \n"));
12895 return -EINVAL;
12896 }
12897 chanspec |= chspec;
12898 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
12899
12900 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
12901 join_params->params.chanspec_num * sizeof(chanspec_t);
12902
12903 join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
12904 join_params->params.chanspec_list[0] |= chanspec;
12905 join_params->params.chanspec_list[0] =
12906 wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
12907
12908 join_params->params.chanspec_num =
12909 htod32(join_params->params.chanspec_num);
12910
12911 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
12912 join_params->params.chanspec_list[0],
12913 join_params->params.chanspec_num));
12914 }
12915 return 0;
12916 }
12917
12918 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam)
12919 {
12920 struct cfg80211_bss *bss;
12921 struct wl_bss_info *bi;
12922 struct wlc_ssid *ssid;
12923 struct bcm_tlv *tim;
12924 s32 beacon_interval;
12925 s32 dtim_period;
12926 size_t ie_len;
12927 u8 *ie;
12928 u8 *curbssid;
12929 s32 err = 0;
12930 struct wiphy *wiphy;
12931 u32 channel;
12932 char *buf;
12933 u32 freq, band;
12934
12935 wiphy = bcmcfg_to_wiphy(cfg);
12936
12937 ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
12938 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
12939 bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
12940 ssid->SSID, ssid->SSID_len);
12941 buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_ATOMIC);
12942 if (!buf) {
12943 WL_ERR(("buffer alloc failed.\n"));
12944 return BCME_NOMEM;
12945 }
12946 mutex_lock(&cfg->usr_sync);
12947 *(u32 *)buf = htod32(WL_EXTRA_BUF_MAX);
12948 err = wldev_ioctl_get(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX);
12949 if (unlikely(err)) {
12950 WL_ERR(("Could not get bss info %d\n", err));
12951 goto update_bss_info_out;
12952 }
12953 bi = (struct wl_bss_info *)(buf + 4);
12954 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
12955 wl_update_prof(cfg, ndev, NULL, &channel, WL_PROF_CHAN);
12956
12957 if (!bss) {
12958 WL_DBG(("Could not find the AP\n"));
12959 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
12960 WL_ERR(("Bssid doesn't match\n"));
12961 err = -EIO;
12962 goto update_bss_info_out;
12963 }
12964 err = wl_inform_single_bss(cfg, bi, roam);
12965 if (unlikely(err))
12966 goto update_bss_info_out;
12967
12968 ie = ((u8 *)bi) + bi->ie_offset;
12969 ie_len = bi->ie_length;
12970 beacon_interval = cpu_to_le16(bi->beacon_period);
12971 } else {
12972 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
12973 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
12974 freq = ieee80211_channel_to_frequency(channel);
12975 #else
12976 band = (channel <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
12977 freq = ieee80211_channel_to_frequency(channel, band);
12978 #endif
12979 bss->channel = ieee80211_get_channel(wiphy, freq);
12980 #if defined(WL_CFG80211_P2P_DEV_IF)
12981 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
12982 #pragma GCC diagnostic push
12983 #pragma GCC diagnostic ignored "-Wcast-qual"
12984 #endif
12985 ie = (u8 *)bss->ies->data;
12986 ie_len = bss->ies->len;
12987 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
12988 #pragma GCC diagnostic pop
12989 #endif
12990 #else
12991 ie = bss->information_elements;
12992 ie_len = bss->len_information_elements;
12993 #endif /* WL_CFG80211_P2P_DEV_IF */
12994 beacon_interval = bss->beacon_interval;
12995
12996 CFG80211_PUT_BSS(wiphy, bss);
12997 }
12998
12999 tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
13000 if (tim) {
13001 dtim_period = tim->data[1];
13002 } else {
13003 /*
13004 * active scan was done so we could not get dtim
13005 * information out of probe response.
13006 * so we speficially query dtim information.
13007 */
13008 dtim_period = 0;
13009 err = wldev_ioctl_get(ndev, WLC_GET_DTIMPRD,
13010 &dtim_period, sizeof(dtim_period));
13011 if (unlikely(err)) {
13012 WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
13013 goto update_bss_info_out;
13014 }
13015 }
13016
13017 wl_update_prof(cfg, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
13018 wl_update_prof(cfg, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
13019
13020 update_bss_info_out:
13021 if (unlikely(err)) {
13022 WL_ERR(("Failed with error %d\n", err));
13023 }
13024
13025 kfree(buf);
13026 mutex_unlock(&cfg->usr_sync);
13027 return err;
13028 }
13029
13030 static s32
13031 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
13032 const wl_event_msg_t *e, void *data)
13033 {
13034 struct wl_connect_info *conn_info = wl_to_conn(cfg);
13035 s32 err = 0;
13036 u8 *curbssid;
13037 u32 *channel;
13038 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13039 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
13040 struct ieee80211_supported_band *band;
13041 struct ieee80211_channel *notify_channel = NULL;
13042 u32 freq;
13043 #ifdef BCM4359_CHIP
13044 struct channel_info ci;
13045 u32 cur_channel;
13046 #endif /* BCM4359_CHIP */
13047 #endif
13048 #if defined(WLADPS_SEAK_AP_WAR) || defined(WBTEXT)
13049 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
13050 #endif /* WLADPS_SEAK_AP_WAR || WBTEXT */
13051 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13052 struct cfg80211_roam_info roam_info = {};
13053 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13054
13055 #ifdef WLADPS_SEAK_AP_WAR
13056 BCM_REFERENCE(dhdp);
13057 #endif /* WLADPS_SEAK_AP_WAR */
13058
13059 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
13060 channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
13061 #ifdef BCM4359_CHIP
13062 /* Skip calling cfg80211_roamed If the channels are same and
13063 * the current bssid/last_roamed_bssid & the new bssid are same
13064 * Also clear timer roam_timeout.
13065 * Only used on BCM4359 devices.
13066 */
13067 memset(&ci, 0, sizeof(ci));
13068 if ((wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci,
13069 sizeof(ci))) < 0) {
13070 WL_ERR(("Failed to get current channel !"));
13071 return BCME_ERROR;
13072 }
13073 cur_channel = dtoh32(ci.hw_channel);
13074 if ((*channel == cur_channel) && ((memcmp(curbssid, &e->addr,
13075 ETHER_ADDR_LEN) == 0) || (memcmp(&cfg->last_roamed_addr,
13076 &e->addr, ETHER_ADDR_LEN) == 0))) {
13077 WL_ERR(("BSS already present, Skipping roamed event to"
13078 " upper layer\n"));
13079 #ifdef DHD_LOSSLESS_ROAMING
13080 wl_del_roam_timeout(cfg);
13081 #endif /* DHD_LOSSLESS_ROAMING */
13082 return err;
13083 }
13084 #endif /* BCM4359_CHIP */
13085
13086 wl_get_assoc_ies(cfg, ndev);
13087 wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet), WL_PROF_BSSID);
13088 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
13089 wl_update_bss_info(cfg, ndev, true);
13090 wl_update_pmklist(ndev, cfg->pmk_list, err);
13091
13092 channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
13093 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13094 /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
13095 if (*channel <= CH_MAX_2G_CHANNEL)
13096 band = wiphy->bands[IEEE80211_BAND_2GHZ];
13097 else
13098 band = wiphy->bands[IEEE80211_BAND_5GHZ];
13099 freq = ieee80211_channel_to_frequency(*channel, band->band);
13100 notify_channel = ieee80211_get_channel(wiphy, freq);
13101 #endif
13102 #ifdef WLADPS_SEAK_AP_WAR
13103 if ((dhdp->op_mode & DHD_FLAG_STA_MODE) &&
13104 (!dhdp->disabled_adps)) {
13105 bool find = FALSE;
13106 uint8 enable_mode;
13107 if (!memcmp(curbssid, (u8*)CAMEO_MAC_PREFIX, MAC_PREFIX_LEN)) {
13108 find = wl_find_vndr_ies_specific_vender(cfg, ndev, ATHEROS_OUI);
13109 }
13110 enable_mode = (find == TRUE) ? OFF : ON;
13111 wl_set_adps_mode(cfg, ndev, enable_mode);
13112 }
13113 #endif /* WLADPS_SEAK_AP_WAR */
13114 printf("%s succeeded to " MACDBG " (ch:%d)\n", __FUNCTION__,
13115 MAC2STRDBG((const u8*)(&e->addr)), *channel);
13116 dhd_conf_set_wme(cfg->pub, 0);
13117
13118 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13119 roam_info.channel = notify_channel;
13120 roam_info.bssid = curbssid;
13121 roam_info.req_ie = conn_info->req_ie;
13122 roam_info.req_ie_len = conn_info->req_ie_len;
13123 roam_info.resp_ie = conn_info->resp_ie;
13124 roam_info.resp_ie_len = conn_info->resp_ie_len;
13125 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13126
13127 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13128 cfg80211_roamed(ndev, &roam_info, GFP_KERNEL);
13129 #else
13130 cfg80211_roamed(ndev,
13131 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13132 notify_channel,
13133 #endif
13134 curbssid,
13135 conn_info->req_ie, conn_info->req_ie_len,
13136 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
13137 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13138 WL_DBG(("Report roaming result\n"));
13139
13140 memcpy(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN);
13141 wl_set_drv_status(cfg, CONNECTED, ndev);
13142
13143 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
13144 cfg->roam_count++;
13145 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
13146
13147 #ifdef WBTEXT
13148 if (dhdp->wbtext_support) {
13149 /* set wnm_keepalives_max_idle after association */
13150 wl_cfg80211_wbtext_set_wnm_maxidle(cfg, ndev);
13151 /* send nbr request or BTM query to update RCC */
13152 wl_cfg80211_wbtext_update_rcc(cfg, ndev);
13153 }
13154 #endif /* WBTEXT */
13155
13156 return err;
13157 }
13158
13159 static bool
13160 wl_cfg80211_verify_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev)
13161 {
13162 struct cfg80211_bss *bss;
13163 struct wiphy *wiphy;
13164 struct wlc_ssid *ssid;
13165 uint8 *curbssid;
13166 int count = 0;
13167 int ret = false;
13168
13169 wiphy = bcmcfg_to_wiphy(cfg);
13170 ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
13171 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
13172 if (!ssid) {
13173 WL_ERR(("No SSID found in the saved profile \n"));
13174 return false;
13175 }
13176
13177 do {
13178 bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
13179 ssid->SSID, ssid->SSID_len);
13180 if (bss || (count > 5)) {
13181 break;
13182 }
13183
13184 count++;
13185 msleep(100);
13186 } while (bss == NULL);
13187
13188 WL_DBG(("cfg80211 bss_ptr:%p loop_cnt:%d\n", bss, count));
13189 if (bss) {
13190 /* Update the reference count after use */
13191 CFG80211_PUT_BSS(wiphy, bss);
13192 ret = true;
13193 }
13194
13195 return ret;
13196 }
13197
13198 static s32
13199 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
13200 const wl_event_msg_t *e, void *data, bool completed)
13201 {
13202 struct wl_connect_info *conn_info = wl_to_conn(cfg);
13203 struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
13204 s32 err = 0;
13205 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
13206 dhd_pub_t *dhdp;
13207
13208 dhdp = (dhd_pub_t *)(cfg->pub);
13209 BCM_REFERENCE(dhdp);
13210
13211 if (!sec) {
13212 WL_ERR(("sec is NULL\n"));
13213 return -ENODEV;
13214 }
13215 WL_DBG((" enter\n"));
13216 #ifdef ESCAN_RESULT_PATCH
13217 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
13218 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
13219 WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
13220 ntoh32(e->event_type), ntoh32(e->status)));
13221 return err;
13222 }
13223 }
13224 if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
13225 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
13226 WL_DBG(("copy bssid\n"));
13227 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
13228 }
13229
13230 #else
13231 if (cfg->scan_request) {
13232 wl_notify_escan_complete(cfg, ndev, true, true);
13233 }
13234 #endif /* ESCAN_RESULT_PATCH */
13235 if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
13236 wl_cfg80211_scan_abort(cfg);
13237 wl_clr_drv_status(cfg, CONNECTING, ndev);
13238 if (completed) {
13239 wl_get_assoc_ies(cfg, ndev);
13240 wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet),
13241 WL_PROF_BSSID);
13242 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
13243 wl_update_bss_info(cfg, ndev, false);
13244 wl_update_pmklist(ndev, cfg->pmk_list, err);
13245 wl_set_drv_status(cfg, CONNECTED, ndev);
13246 #ifdef WLADPS_SEAK_AP_WAR
13247 if ((dhdp->op_mode & DHD_FLAG_STA_MODE) &&
13248 (!dhdp->disabled_adps)) {
13249 bool find = FALSE;
13250 uint8 enable_mode;
13251 if (!memcmp(curbssid, (u8*)CAMEO_MAC_PREFIX, MAC_PREFIX_LEN)) {
13252 find = wl_find_vndr_ies_specific_vender(cfg,
13253 ndev, ATHEROS_OUI);
13254 }
13255 enable_mode = (find == TRUE) ? OFF : ON;
13256 wl_set_adps_mode(cfg, ndev, enable_mode);
13257 }
13258 #endif /* WLADPS_SEAK_AP_WAR */
13259 if (ndev != bcmcfg_to_prmry_ndev(cfg)) {
13260 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
13261 init_completion(&cfg->iface_disable);
13262 #else
13263 /* reinitialize completion to clear previous count */
13264 INIT_COMPLETION(cfg->iface_disable);
13265 #endif
13266 }
13267 #ifdef CUSTOM_SET_CPUCORE
13268 if (wl_get_chan_isvht80(ndev, dhdp)) {
13269 if (ndev == bcmcfg_to_prmry_ndev(cfg))
13270 dhdp->chan_isvht80 |= DHD_FLAG_STA_MODE; /* STA mode */
13271 else if (is_p2p_group_iface(ndev->ieee80211_ptr))
13272 dhdp->chan_isvht80 |= DHD_FLAG_P2P_MODE; /* p2p mode */
13273 dhd_set_cpucore(dhdp, TRUE);
13274 }
13275 #endif /* CUSTOM_SET_CPUCORE */
13276 memset(&cfg->last_roamed_addr, 0, ETHER_ADDR_LEN);
13277 }
13278
13279 if (completed && (wl_cfg80211_verify_bss(cfg, ndev) != true)) {
13280 /* If bss entry is not available in the cfg80211 bss cache
13281 * the wireless stack will complain and won't populate
13282 * wdev->current_bss ptr
13283 */
13284 WL_ERR(("BSS entry not found. Indicate assoc event failure\n"));
13285 completed = false;
13286 sec->auth_assoc_res_status = WLAN_STATUS_UNSPECIFIED_FAILURE;
13287 }
13288 cfg80211_connect_result(ndev,
13289 curbssid,
13290 conn_info->req_ie,
13291 conn_info->req_ie_len,
13292 conn_info->resp_ie,
13293 conn_info->resp_ie_len,
13294 completed ? WLAN_STATUS_SUCCESS :
13295 (sec->auth_assoc_res_status) ?
13296 sec->auth_assoc_res_status :
13297 WLAN_STATUS_UNSPECIFIED_FAILURE,
13298 GFP_KERNEL);
13299 if (completed) {
13300 WL_INFORM(("Report connect result - connection succeeded\n"));
13301 dhd_conf_set_wme(cfg->pub, 0);
13302 } else
13303 WL_ERR(("Report connect result - connection failed\n"));
13304 }
13305 #ifdef CONFIG_TCPACK_FASTTX
13306 if (wl_get_chan_isvht80(ndev, dhdp))
13307 wldev_iovar_setint(ndev, "tcpack_fast_tx", 0);
13308 else
13309 wldev_iovar_setint(ndev, "tcpack_fast_tx", 1);
13310 #endif /* CONFIG_TCPACK_FASTTX */
13311
13312 return err;
13313 }
13314
13315 static s32
13316 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13317 const wl_event_msg_t *e, void *data)
13318 {
13319 struct net_device *ndev = NULL;
13320 u16 flags = ntoh16(e->flags);
13321 enum nl80211_key_type key_type;
13322
13323 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13324
13325 mutex_lock(&cfg->usr_sync);
13326 if (flags & WLC_EVENT_MSG_GROUP)
13327 key_type = NL80211_KEYTYPE_GROUP;
13328 else
13329 key_type = NL80211_KEYTYPE_PAIRWISE;
13330
13331 cfg80211_michael_mic_failure(ndev, (const u8 *)&e->addr, key_type, -1,
13332 NULL, GFP_KERNEL);
13333 mutex_unlock(&cfg->usr_sync);
13334
13335 return 0;
13336 }
13337
13338 #ifdef BT_WIFI_HANDOVER
13339 static s32
13340 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13341 const wl_event_msg_t *e, void *data)
13342 {
13343 struct net_device *ndev = NULL;
13344 u32 event = ntoh32(e->event_type);
13345 u32 datalen = ntoh32(e->datalen);
13346 s32 err;
13347
13348 WL_ERR(("wl_notify_bt_wifi_handover_req: event_type : %d, datalen : %d\n", event, datalen));
13349 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13350 err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
13351
13352 return err;
13353 }
13354 #endif /* BT_WIFI_HANDOVER */
13355
13356 #ifdef PNO_SUPPORT
13357 static s32
13358 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13359 const wl_event_msg_t *e, void *data)
13360 {
13361 struct net_device *ndev = NULL;
13362 #ifdef GSCAN_SUPPORT
13363 void *ptr;
13364 int send_evt_bytes = 0;
13365 u32 event = be32_to_cpu(e->event_type);
13366 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
13367 #endif /* GSCAN_SUPPORT */
13368
13369 WL_ERR((">>> PNO Event\n"));
13370
13371 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13372 #ifdef GSCAN_SUPPORT
13373 ptr = dhd_dev_process_epno_result(ndev, data, event, &send_evt_bytes);
13374 if (ptr) {
13375 wl_cfgvendor_send_async_event(wiphy, ndev,
13376 GOOGLE_SCAN_EPNO_EVENT, ptr, send_evt_bytes);
13377 kfree(ptr);
13378 }
13379 if (!dhd_dev_is_legacy_pno_enabled(ndev))
13380 return 0;
13381 #endif /* GSCAN_SUPPORT */
13382
13383
13384 #ifndef WL_SCHED_SCAN
13385 mutex_lock(&cfg->usr_sync);
13386 /* TODO: Use cfg80211_sched_scan_results(wiphy); */
13387 CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
13388 mutex_unlock(&cfg->usr_sync);
13389 #else
13390 /* If cfg80211 scheduled scan is supported, report the pno results via sched
13391 * scan results
13392 */
13393 wl_notify_sched_scan_results(cfg, ndev, e, data);
13394 #endif /* WL_SCHED_SCAN */
13395 return 0;
13396 }
13397 #endif /* PNO_SUPPORT */
13398
13399 #ifdef GSCAN_SUPPORT
13400 static s32
13401 wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13402 const wl_event_msg_t *e, void *data)
13403 {
13404 s32 err = 0;
13405 u32 event = be32_to_cpu(e->event_type);
13406 void *ptr;
13407 int send_evt_bytes = 0;
13408 int event_type;
13409 struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13410 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
13411 u32 len = ntoh32(e->datalen);
13412
13413 switch (event) {
13414 case WLC_E_PFN_BEST_BATCHING:
13415 err = dhd_dev_retrieve_batch_scan(ndev);
13416 if (err < 0) {
13417 WL_ERR(("Batch retrieval already in progress %d\n", err));
13418 } else {
13419 event_type = WIFI_SCAN_THRESHOLD_NUM_SCANS;
13420 if (data && len) {
13421 event_type = *((int *)data);
13422 }
13423 wl_cfgvendor_send_async_event(wiphy, ndev,
13424 GOOGLE_GSCAN_BATCH_SCAN_EVENT,
13425 &event_type, sizeof(int));
13426 }
13427 break;
13428 case WLC_E_PFN_SCAN_COMPLETE:
13429 event_type = WIFI_SCAN_COMPLETE;
13430 wl_cfgvendor_send_async_event(wiphy, ndev,
13431 GOOGLE_SCAN_COMPLETE_EVENT,
13432 &event_type, sizeof(int));
13433 break;
13434 case WLC_E_PFN_BSSID_NET_FOUND:
13435 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
13436 HOTLIST_FOUND);
13437 if (ptr) {
13438 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
13439 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT);
13440 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_FOUND);
13441 } else {
13442 err = -ENOMEM;
13443 }
13444 break;
13445 case WLC_E_PFN_BSSID_NET_LOST:
13446 /* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
13447 * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
13448 */
13449 if (len) {
13450 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
13451 HOTLIST_LOST);
13452 if (ptr) {
13453 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
13454 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT);
13455 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_LOST);
13456 } else {
13457 err = -ENOMEM;
13458 }
13459 } else {
13460 err = -EINVAL;
13461 }
13462 break;
13463 case WLC_E_PFN_GSCAN_FULL_RESULT:
13464 ptr = dhd_dev_process_full_gscan_result(ndev, data, len, &send_evt_bytes);
13465 if (ptr) {
13466 wl_cfgvendor_send_async_event(wiphy, ndev,
13467 GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, send_evt_bytes);
13468 kfree(ptr);
13469 } else {
13470 err = -ENOMEM;
13471 }
13472 break;
13473 case WLC_E_PFN_SSID_EXT:
13474 ptr = dhd_dev_process_epno_result(ndev, data, event, &send_evt_bytes);
13475 if (ptr) {
13476 wl_cfgvendor_send_async_event(wiphy, ndev,
13477 GOOGLE_SCAN_EPNO_EVENT, ptr, send_evt_bytes);
13478 kfree(ptr);
13479 } else {
13480 err = -ENOMEM;
13481 }
13482 break;
13483 default:
13484 WL_ERR(("Unknown event %d\n", event));
13485 break;
13486 }
13487 return err;
13488 }
13489 #endif /* GSCAN_SUPPORT */
13490
13491 static s32
13492 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13493 const wl_event_msg_t *e, void *data)
13494 {
13495 struct channel_info channel_inform;
13496 struct wl_scan_results *bss_list;
13497 struct net_device *ndev = NULL;
13498 u32 len = WL_SCAN_BUF_MAX;
13499 s32 err = 0;
13500 unsigned long flags;
13501 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
13502 struct cfg80211_scan_info info;
13503 #endif
13504
13505 WL_DBG(("Enter \n"));
13506 if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
13507 WL_ERR(("scan is not ready \n"));
13508 return err;
13509 }
13510 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13511
13512 mutex_lock(&cfg->usr_sync);
13513 wl_clr_drv_status(cfg, SCANNING, ndev);
13514 memset(&channel_inform, 0, sizeof(channel_inform));
13515 err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &channel_inform,
13516 sizeof(channel_inform));
13517 if (unlikely(err)) {
13518 WL_ERR(("scan busy (%d)\n", err));
13519 goto scan_done_out;
13520 }
13521 channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
13522 if (unlikely(channel_inform.scan_channel)) {
13523
13524 WL_DBG(("channel_inform.scan_channel (%d)\n",
13525 channel_inform.scan_channel));
13526 }
13527 cfg->bss_list = cfg->scan_results;
13528 bss_list = cfg->bss_list;
13529 memset(bss_list, 0, len);
13530 bss_list->buflen = htod32(len);
13531 err = wldev_ioctl_get(ndev, WLC_SCAN_RESULTS, bss_list, len);
13532 if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {
13533 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
13534 err = -EINVAL;
13535 goto scan_done_out;
13536 }
13537 bss_list->buflen = dtoh32(bss_list->buflen);
13538 bss_list->version = dtoh32(bss_list->version);
13539 bss_list->count = dtoh32(bss_list->count);
13540
13541 err = wl_inform_bss(cfg);
13542
13543 scan_done_out:
13544 del_timer_sync(&cfg->scan_timeout);
13545 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
13546 if (cfg->scan_request) {
13547 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
13548 info.aborted = false;
13549 cfg80211_scan_done(cfg->scan_request, &info);
13550 #else
13551 cfg80211_scan_done(cfg->scan_request, false);
13552 #endif
13553 cfg->scan_request = NULL;
13554 }
13555 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
13556 WL_DBG(("cfg80211_scan_done\n"));
13557 mutex_unlock(&cfg->usr_sync);
13558 return err;
13559 }
13560
13561 static s32
13562 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
13563 const struct ether_addr *sa, const struct ether_addr *bssid,
13564 u8 **pheader, u32 *body_len, u8 *pbody)
13565 {
13566 struct dot11_management_header *hdr;
13567 u32 totlen = 0;
13568 s32 err = 0;
13569 u8 *offset;
13570 u32 prebody_len = *body_len;
13571 switch (fc) {
13572 case FC_ASSOC_REQ:
13573 /* capability , listen interval */
13574 totlen = DOT11_ASSOC_REQ_FIXED_LEN;
13575 *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
13576 break;
13577
13578 case FC_REASSOC_REQ:
13579 /* capability, listen inteval, ap address */
13580 totlen = DOT11_REASSOC_REQ_FIXED_LEN;
13581 *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
13582 break;
13583 }
13584 totlen += DOT11_MGMT_HDR_LEN + prebody_len;
13585 *pheader = kzalloc(totlen, GFP_KERNEL);
13586 if (*pheader == NULL) {
13587 WL_ERR(("memory alloc failed \n"));
13588 return -ENOMEM;
13589 }
13590 hdr = (struct dot11_management_header *) (*pheader);
13591 hdr->fc = htol16(fc);
13592 hdr->durid = 0;
13593 hdr->seq = 0;
13594 offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
13595 bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
13596 bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
13597 bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
13598 if ((pbody != NULL) && prebody_len)
13599 bcopy((const char*)pbody, offset, prebody_len);
13600 *body_len = totlen;
13601 return err;
13602 }
13603
13604
13605 void
13606 wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev, u8 bsscfgidx)
13607 {
13608 s32 err = 0;
13609
13610 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
13611 if (timer_pending(&cfg->p2p->listen_timer)) {
13612 del_timer_sync(&cfg->p2p->listen_timer);
13613 }
13614 if (cfg->afx_hdl != NULL) {
13615 if (cfg->afx_hdl->dev != NULL) {
13616 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
13617 wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, cfg->afx_hdl->dev);
13618 }
13619 cfg->afx_hdl->peer_chan = WL_INVALID;
13620 }
13621 complete(&cfg->act_frm_scan);
13622 WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
13623 } else if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
13624 if (!(wl_get_p2p_status(cfg, ACTION_TX_COMPLETED) ||
13625 wl_get_p2p_status(cfg, ACTION_TX_NOACK)))
13626 wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
13627
13628 WL_DBG(("*** Wake UP ** abort actframe iovar on bsscfxidx %d\n", bsscfgidx));
13629 /* if channel is not zero, "actfame" uses off channel scan.
13630 * So abort scan for off channel completion.
13631 */
13632 if (cfg->af_sent_channel) {
13633 /* Scan engine is not used for sending action frames in the latest driver
13634 * branches. So, actframe_abort is used in the latest driver branches
13635 * instead of scan abort.
13636 * New driver branches:
13637 * Issue actframe_abort and it succeeded. So, don't execute scan abort.
13638 * Old driver branches:
13639 * Issue actframe_abort and it fails. So, execute scan abort.
13640 */
13641 err = wldev_iovar_setint_bsscfg(ndev, "actframe_abort", 1, bsscfgidx);
13642 if (err < 0) {
13643 wl_cfg80211_scan_abort(cfg);
13644 }
13645 }
13646 }
13647 #ifdef WL_CFG80211_SYNC_GON
13648 else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
13649 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
13650 /* So abort scan to cancel listen */
13651 wl_cfg80211_scan_abort(cfg);
13652 }
13653 #endif /* WL_CFG80211_SYNC_GON */
13654 }
13655
13656 #if defined(WLTDLS)
13657 bool wl_cfg80211_is_tdls_tunneled_frame(void *frame, u32 frame_len)
13658 {
13659 unsigned char *data;
13660
13661 if (frame == NULL) {
13662 WL_ERR(("Invalid frame \n"));
13663 return false;
13664 }
13665
13666 if (frame_len < 5) {
13667 WL_ERR(("Invalid frame length [%d] \n", frame_len));
13668 return false;
13669 }
13670
13671 data = frame;
13672
13673 if (!memcmp(data, TDLS_TUNNELED_PRB_REQ, 5) ||
13674 !memcmp(data, TDLS_TUNNELED_PRB_RESP, 5)) {
13675 WL_DBG(("TDLS Vendor Specific Received type\n"));
13676 return true;
13677 }
13678
13679 return false;
13680 }
13681 #endif /* WLTDLS */
13682
13683
13684 int wl_cfg80211_get_ioctl_version(void)
13685 {
13686 return ioctl_version;
13687 }
13688
13689 static s32
13690 wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13691 const wl_event_msg_t *e, void *data)
13692 {
13693 struct ieee80211_supported_band *band;
13694 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
13695 struct ether_addr da;
13696 struct ether_addr bssid;
13697 bool isfree = false;
13698 s32 err = 0;
13699 s32 freq;
13700 #if defined(TDLS_MSG_ONLY_WFD)
13701 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
13702 #endif /* TDLS_MSG_ONLY_WFD && BCMDONGLEHOST */
13703 struct net_device *ndev = NULL;
13704 wifi_p2p_pub_act_frame_t *act_frm = NULL;
13705 wifi_p2p_action_frame_t *p2p_act_frm = NULL;
13706 wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
13707 wl_event_rx_frame_data_t *rxframe;
13708 u32 event;
13709 u8 *mgmt_frame;
13710 u8 bsscfgidx;
13711 u32 mgmt_frame_len;
13712 u16 channel;
13713 if (ntoh32(e->datalen) < sizeof(wl_event_rx_frame_data_t)) {
13714 WL_ERR(("wrong datalen:%d\n", ntoh32(e->datalen)));
13715 return -EINVAL;
13716 }
13717 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
13718 event = ntoh32(e->event_type);
13719 bsscfgidx = e->bsscfgidx;
13720 rxframe = (wl_event_rx_frame_data_t *)data;
13721 if (!rxframe) {
13722 WL_ERR(("rxframe: NULL\n"));
13723 return -EINVAL;
13724 }
13725 channel = (ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK);
13726 memset(&bssid, 0, ETHER_ADDR_LEN);
13727 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13728 if ((ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) &&
13729 (event == WLC_E_PROBREQ_MSG)) {
13730 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
13731 4 && __GNUC_MINOR__ >= 6))
13732 _Pragma("GCC diagnostic push")
13733 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
13734 #endif
13735 struct net_info *iter, *next;
13736 for_each_ndev(cfg, iter, next) {
13737 if (iter->ndev && iter->wdev &&
13738 iter->wdev->iftype == NL80211_IFTYPE_AP) {
13739 ndev = iter->ndev;
13740 cfgdev = ndev_to_cfgdev(ndev);
13741 break;
13742 }
13743 }
13744 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
13745 4 && __GNUC_MINOR__ >= 6))
13746 _Pragma("GCC diagnostic pop")
13747 #endif
13748 }
13749
13750 if (channel <= CH_MAX_2G_CHANNEL)
13751 band = wiphy->bands[IEEE80211_BAND_2GHZ];
13752 else
13753 band = wiphy->bands[IEEE80211_BAND_5GHZ];
13754 if (!band) {
13755 WL_ERR(("No valid band\n"));
13756 return -EINVAL;
13757 }
13758 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
13759 freq = ieee80211_channel_to_frequency(channel);
13760 (void)band->band;
13761 #else
13762 freq = ieee80211_channel_to_frequency(channel, band->band);
13763 #endif
13764 if (event == WLC_E_ACTION_FRAME_RX) {
13765 if ((err = wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
13766 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx,
13767 &cfg->ioctl_buf_sync)) != BCME_OK) {
13768 WL_ERR(("WLC_GET_CUR_ETHERADDR failed, error %d\n", err));
13769 goto exit;
13770 }
13771
13772 err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
13773 if (err < 0)
13774 WL_ERR(("WLC_GET_BSSID error %d\n", err));
13775 memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
13776 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
13777 &mgmt_frame, &mgmt_frame_len,
13778 (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
13779 if (err < 0) {
13780 WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
13781 mgmt_frame_len, channel, freq));
13782 goto exit;
13783 }
13784 isfree = true;
13785 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13786 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
13787 act_frm = (wifi_p2p_pub_act_frame_t *)
13788 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
13789 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13790 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
13791 p2p_act_frm = (wifi_p2p_action_frame_t *)
13792 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
13793 (void) p2p_act_frm;
13794 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13795 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
13796
13797 sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
13798 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
13799 if (sd_act_frm && wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
13800 if (cfg->next_af_subtype == sd_act_frm->action) {
13801 WL_DBG(("We got a right next frame of SD!(%d)\n",
13802 sd_act_frm->action));
13803 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
13804
13805 /* Stop waiting for next AF. */
13806 wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
13807 }
13808 }
13809 (void) sd_act_frm;
13810 #ifdef WLTDLS
13811 } else if ((mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) ||
13812 (wl_cfg80211_is_tdls_tunneled_frame(
13813 &mgmt_frame[DOT11_MGMT_HDR_LEN],
13814 mgmt_frame_len - DOT11_MGMT_HDR_LEN))) {
13815 if (mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) {
13816 WL_ERR((" TDLS Action Frame Received type = %d \n",
13817 mgmt_frame[DOT11_MGMT_HDR_LEN + 1]));
13818 }
13819 #ifdef TDLS_MSG_ONLY_WFD
13820 if (!dhdp->tdls_mode) {
13821 WL_DBG((" TDLS Frame filtered \n"));
13822 return 0;
13823 }
13824 #else
13825 if (mgmt_frame[DOT11_MGMT_HDR_LEN + 1] == TDLS_ACTION_SETUP_RESP) {
13826 cfg->tdls_mgmt_frame = mgmt_frame;
13827 cfg->tdls_mgmt_frame_len = mgmt_frame_len;
13828 cfg->tdls_mgmt_freq = freq;
13829 return 0;
13830 }
13831 #endif /* TDLS_MSG_ONLY_WFD */
13832 #endif /* WLTDLS */
13833 #ifdef QOS_MAP_SET
13834 } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_QOS) {
13835 /* update QoS map set table */
13836 bcm_tlv_t * qos_map_ie = NULL;
13837 if ((qos_map_ie = bcm_parse_tlvs(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13838 mgmt_frame_len - DOT11_MGMT_HDR_LEN,
13839 DOT11_MNG_QOS_MAP_ID)) != NULL) {
13840 WL_DBG((" QoS map set IE found in QoS action frame\n"));
13841 if (!cfg->up_table) {
13842 cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
13843 }
13844 wl_set_up_table(cfg->up_table, qos_map_ie);
13845 } else {
13846 kfree(cfg->up_table);
13847 cfg->up_table = NULL;
13848 }
13849 #endif /* QOS_MAP_SET */
13850 #ifdef WBTEXT
13851 } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_RRM) {
13852 /* radio measurement category */
13853 switch (mgmt_frame[DOT11_MGMT_HDR_LEN+1]) {
13854 case DOT11_RM_ACTION_NR_REP:
13855 if (wl_cfg80211_recv_nbr_resp(ndev,
13856 &mgmt_frame[DOT11_MGMT_HDR_LEN],
13857 mgmt_frame_len - DOT11_MGMT_HDR_LEN)
13858 == BCME_OK) {
13859 WL_DBG(("RCC updated by nbr response\n"));
13860 }
13861 break;
13862 default:
13863 break;
13864 }
13865 #endif /* WBTEXT */
13866 } else {
13867 /*
13868 * if we got normal action frame and ndev is p2p0,
13869 * we have to change ndev from p2p0 to wlan0
13870 */
13871
13872
13873 if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
13874 u8 action = 0;
13875 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13876 mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
13877 WL_DBG(("Recived action is not public action frame\n"));
13878 } else if (cfg->next_af_subtype == action) {
13879 WL_DBG(("Recived action is the waiting action(%d)\n",
13880 action));
13881 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
13882
13883 /* Stop waiting for next AF. */
13884 wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
13885 }
13886 }
13887 }
13888
13889 if (act_frm) {
13890
13891 if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
13892 if (cfg->next_af_subtype == act_frm->subtype) {
13893 WL_DBG(("We got a right next frame!(%d)\n",
13894 act_frm->subtype));
13895 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
13896
13897 if (cfg->next_af_subtype == P2P_PAF_GON_CONF) {
13898 OSL_SLEEP(20);
13899 }
13900
13901 /* Stop waiting for next AF. */
13902 wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
13903 }
13904 }
13905 }
13906
13907 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
13908 mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
13909 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
13910 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
13911 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
13912 }
13913 } else if (event == WLC_E_PROBREQ_MSG) {
13914
13915 /* Handle probe reqs frame
13916 * WPS-AP certification 4.2.13
13917 */
13918 struct parsed_ies prbreq_ies;
13919 u32 prbreq_ie_len = 0;
13920 bool pbc = 0;
13921
13922 WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
13923 mgmt_frame = (u8 *)(data);
13924 mgmt_frame_len = ntoh32(e->datalen);
13925 if (mgmt_frame_len < DOT11_MGMT_HDR_LEN) {
13926 WL_ERR(("wrong datalen:%d\n", mgmt_frame_len));
13927 return -EINVAL;
13928 }
13929 prbreq_ie_len = mgmt_frame_len - DOT11_MGMT_HDR_LEN;
13930
13931 /* Parse prob_req IEs */
13932 if (wl_cfg80211_parse_ies(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13933 prbreq_ie_len, &prbreq_ies) < 0) {
13934 WL_ERR(("Prob req get IEs failed\n"));
13935 return 0;
13936 }
13937 if (prbreq_ies.wps_ie != NULL) {
13938 wl_validate_wps_ie((char *)prbreq_ies.wps_ie, prbreq_ies.wps_ie_len, &pbc);
13939 WL_DBG((" wps_ie exist pbc = %d\n", pbc));
13940 /* if pbc method, send prob_req mgmt frame to upper layer */
13941 if (!pbc)
13942 return 0;
13943 } else
13944 return 0;
13945 } else {
13946 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
13947
13948 /* wpa supplicant use probe request event for restarting another GON Req.
13949 * but it makes GON Req repetition.
13950 * so if src addr of prb req is same as my target device,
13951 * do not send probe request event during sending action frame.
13952 */
13953 if (event == WLC_E_P2P_PROBREQ_MSG) {
13954 WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
13955 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
13956
13957
13958 /* Filter any P2P probe reqs arriving during the
13959 * GO-NEG Phase
13960 */
13961 if (cfg->p2p &&
13962 #if defined(P2P_IE_MISSING_FIX)
13963 cfg->p2p_prb_noti &&
13964 #endif
13965 wl_get_p2p_status(cfg, GO_NEG_PHASE)) {
13966 WL_DBG(("Filtering P2P probe_req while "
13967 "being in GO-Neg state\n"));
13968 return 0;
13969 }
13970 }
13971 }
13972
13973 if (discover_cfgdev(cfgdev, cfg))
13974 WL_DBG(("Rx Managment frame For P2P Discovery Interface \n"));
13975 else
13976 WL_DBG(("Rx Managment frame For Iface (%s) \n", ndev->name));
13977 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
13978 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0);
13979 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
13980 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0, GFP_ATOMIC);
13981 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
13982 defined(WL_COMPAT_WIRELESS)
13983 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
13984 #else
13985 cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
13986 #endif /* LINUX_VERSION >= VERSION(3, 18, 0) */
13987
13988 WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
13989 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
13990 exit:
13991 if (isfree)
13992 kfree(mgmt_frame);
13993 return err;
13994 }
13995
13996 #ifdef WL_SCHED_SCAN
13997 /* If target scan is not reliable, set the below define to "1" to do a
13998 * full escan
13999 */
14000 #define FULL_ESCAN_ON_PFN_NET_FOUND 0
14001 static s32
14002 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
14003 const wl_event_msg_t *e, void *data)
14004 {
14005 wl_pfn_net_info_v2_t *netinfo, *pnetinfo;
14006 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
14007 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
14008 int err = 0;
14009 struct cfg80211_scan_request *request = NULL;
14010 struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
14011 struct ieee80211_channel *channel = NULL;
14012 int channel_req = 0;
14013 int band = 0;
14014 wl_pfn_scanresults_t *pfn_result = (wl_pfn_scanresults_t *)data;
14015 int n_pfn_results = pfn_result->count;
14016 log_conn_event_t *event_data = NULL;
14017 tlv_log *tlv_data = NULL;
14018 u32 alloc_len, tlv_len;
14019 u32 payload_len;
14020
14021 WL_DBG(("Enter\n"));
14022
14023 if (pfn_result->version != PFN_SCANRESULT_VERSION) {
14024 WL_ERR(("Incorrect version %d, expected %d\n", pfn_result->version,
14025 PFN_SCANRESULT_VERSION));
14026 return BCME_VERSION;
14027 }
14028
14029 if (e->event_type == WLC_E_PFN_NET_LOST) {
14030 WL_PNO(("PFN NET LOST event. Do Nothing\n"));
14031 return 0;
14032 }
14033
14034 WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
14035 if (n_pfn_results > 0) {
14036 int i;
14037
14038 if (n_pfn_results > MAX_PFN_LIST_COUNT)
14039 n_pfn_results = MAX_PFN_LIST_COUNT;
14040 pnetinfo = (wl_pfn_net_info_v2_t *)((char *)data + sizeof(wl_pfn_scanresults_v2_t)
14041 - sizeof(wl_pfn_net_info_v2_t));
14042
14043 memset(&ssid, 0x00, sizeof(ssid));
14044
14045 request = kzalloc(sizeof(*request)
14046 + sizeof(*request->channels) * n_pfn_results,
14047 GFP_KERNEL);
14048 channel = (struct ieee80211_channel *)kzalloc(
14049 (sizeof(struct ieee80211_channel) * n_pfn_results),
14050 GFP_KERNEL);
14051 if (!request || !channel) {
14052 WL_ERR(("No memory"));
14053 err = -ENOMEM;
14054 goto out_err;
14055 }
14056
14057 request->wiphy = wiphy;
14058
14059 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
14060 alloc_len = sizeof(log_conn_event_t) + DOT11_MAX_SSID_LEN + sizeof(uint16) +
14061 sizeof(int16);
14062 event_data = MALLOC(dhdp->osh, alloc_len);
14063 if (!event_data) {
14064 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
14065 "length(%d)\n", __func__, alloc_len));
14066 goto out_err;
14067 }
14068 tlv_len = 3 * sizeof(tlv_log);
14069 event_data->tlvs = MALLOC(dhdp->osh, tlv_len);
14070 if (!event_data->tlvs) {
14071 WL_ERR(("%s: failed to allocate the tlv_log with "
14072 "length(%d)\n", __func__, tlv_len));
14073 goto out_err;
14074 }
14075 }
14076
14077 for (i = 0; i < n_pfn_results; i++) {
14078 netinfo = &pnetinfo[i];
14079 if (!netinfo) {
14080 WL_ERR(("Invalid netinfo ptr. index:%d", i));
14081 err = -EINVAL;
14082 goto out_err;
14083 }
14084 WL_PNO((">>> SSID:%s Channel:%d \n",
14085 netinfo->pfnsubnet.u.SSID, netinfo->pfnsubnet.channel));
14086 /* PFN result doesn't have all the info which are required by the supplicant
14087 * (For e.g IEs) Do a target Escan so that sched scan results are reported
14088 * via wl_inform_single_bss in the required format. Escan does require the
14089 * scan request in the form of cfg80211_scan_request. For timebeing, create
14090 * cfg80211_scan_request one out of the received PNO event.
14091 */
14092 ssid[i].ssid_len = MIN(DOT11_MAX_SSID_LEN, netinfo->pfnsubnet.SSID_len);
14093 memcpy(ssid[i].ssid, netinfo->pfnsubnet.u.SSID,
14094 ssid[i].ssid_len);
14095 request->n_ssids++;
14096
14097 channel_req = netinfo->pfnsubnet.channel;
14098 band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
14099 : NL80211_BAND_5GHZ;
14100 channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
14101 channel[i].band = band;
14102 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
14103 request->channels[i] = &channel[i];
14104 request->n_channels++;
14105
14106 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
14107 payload_len = sizeof(log_conn_event_t);
14108 event_data->event = WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND;
14109 tlv_data = event_data->tlvs;
14110
14111 /* ssid */
14112 tlv_data->tag = WIFI_TAG_SSID;
14113 tlv_data->len = netinfo->pfnsubnet.SSID_len;
14114 memcpy(tlv_data->value, ssid[i].ssid, ssid[i].ssid_len);
14115 payload_len += TLV_LOG_SIZE(tlv_data);
14116 tlv_data = TLV_LOG_NEXT(tlv_data);
14117
14118 /* channel */
14119 tlv_data->tag = WIFI_TAG_CHANNEL;
14120 tlv_data->len = sizeof(uint16);
14121 memcpy(tlv_data->value, &channel_req, sizeof(uint16));
14122 payload_len += TLV_LOG_SIZE(tlv_data);
14123 tlv_data = TLV_LOG_NEXT(tlv_data);
14124
14125 /* rssi */
14126 tlv_data->tag = WIFI_TAG_RSSI;
14127 tlv_data->len = sizeof(int16);
14128 memcpy(tlv_data->value, &netinfo->RSSI, sizeof(int16));
14129 payload_len += TLV_LOG_SIZE(tlv_data);
14130 tlv_data = TLV_LOG_NEXT(tlv_data);
14131
14132 dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
14133 &event_data->event, payload_len);
14134 }
14135 }
14136
14137 /* assign parsed ssid array */
14138 if (request->n_ssids)
14139 request->ssids = &ssid[0];
14140
14141 if (wl_get_drv_status_all(cfg, SCANNING)) {
14142 /* Abort any on-going scan */
14143 wl_notify_escan_complete(cfg, ndev, true, true);
14144 }
14145
14146 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
14147 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
14148 err = wl_cfgp2p_discover_enable_search(cfg, false);
14149 if (unlikely(err)) {
14150 wl_clr_drv_status(cfg, SCANNING, ndev);
14151 goto out_err;
14152 }
14153 p2p_scan(cfg) = false;
14154 }
14155
14156 wl_set_drv_status(cfg, SCANNING, ndev);
14157 #if FULL_ESCAN_ON_PFN_NET_FOUND
14158 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
14159 err = wl_do_escan(cfg, wiphy, ndev, NULL);
14160 #else
14161 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
14162 err = wl_do_escan(cfg, wiphy, ndev, request);
14163 #endif
14164 if (err) {
14165 wl_clr_drv_status(cfg, SCANNING, ndev);
14166 goto out_err;
14167 }
14168 DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED);
14169 cfg->sched_scan_running = TRUE;
14170 }
14171 else {
14172 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
14173 }
14174 out_err:
14175 if (request)
14176 kfree(request);
14177 if (channel)
14178 kfree(channel);
14179
14180 if (event_data) {
14181 MFREE(dhdp->osh, event_data->tlvs, tlv_len);
14182 MFREE(dhdp->osh, event_data, alloc_len);
14183 }
14184 return err;
14185 }
14186 #endif /* WL_SCHED_SCAN */
14187
14188 static void wl_init_conf(struct wl_conf *conf)
14189 {
14190 WL_DBG(("Enter \n"));
14191 conf->frag_threshold = (u32)-1;
14192 conf->rts_threshold = (u32)-1;
14193 conf->retry_short = (u32)-1;
14194 conf->retry_long = (u32)-1;
14195 conf->tx_power = -1;
14196 }
14197
14198 static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev)
14199 {
14200 unsigned long flags;
14201 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
14202
14203 if (profile) {
14204 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14205 memset(profile, 0, sizeof(struct wl_profile));
14206 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14207 } else {
14208 WL_ERR(("%s: No profile\n", __FUNCTION__));
14209 }
14210 return;
14211 }
14212
14213 static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
14214 {
14215 memset(cfg->evt_handler, 0, sizeof(cfg->evt_handler));
14216
14217 cfg->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
14218 cfg->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
14219 cfg->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
14220 cfg->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
14221 cfg->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
14222 cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
14223 cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
14224 cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
14225 cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
14226 cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
14227 cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
14228 cfg->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
14229 cfg->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
14230 cfg->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
14231 cfg->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
14232 cfg->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
14233 cfg->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
14234 cfg->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
14235 cfg->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
14236 cfg->evt_handler[WLC_E_START] = wl_notify_connect_status;
14237 #ifdef PNO_SUPPORT
14238 cfg->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
14239 #endif /* PNO_SUPPORT */
14240 #ifdef GSCAN_SUPPORT
14241 cfg->evt_handler[WLC_E_PFN_BEST_BATCHING] = wl_notify_gscan_event;
14242 cfg->evt_handler[WLC_E_PFN_SCAN_COMPLETE] = wl_notify_gscan_event;
14243 cfg->evt_handler[WLC_E_PFN_GSCAN_FULL_RESULT] = wl_notify_gscan_event;
14244 cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event;
14245 cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event;
14246 cfg->evt_handler[WLC_E_PFN_SSID_EXT] = wl_notify_gscan_event;
14247 cfg->evt_handler[WLC_E_GAS_FRAGMENT_RX] = wl_notify_gscan_event;
14248 cfg->evt_handler[WLC_E_ROAM_EXP_EVENT] = wl_handle_roam_exp_event;
14249 #endif /* GSCAN_SUPPORT */
14250 #ifdef RSSI_MONITOR_SUPPORT
14251 cfg->evt_handler[WLC_E_RSSI_LQM] = wl_handle_rssi_monitor_event;
14252 #endif /* RSSI_MONITOR_SUPPORT */
14253 #ifdef WLTDLS
14254 cfg->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
14255 #endif /* WLTDLS */
14256 cfg->evt_handler[WLC_E_BSSID] = wl_notify_roaming_status;
14257 #ifdef WL_RELMCAST
14258 cfg->evt_handler[WLC_E_RMC_EVENT] = wl_notify_rmc_status;
14259 #endif /* WL_RELMCAST */
14260 #ifdef BT_WIFI_HANDOVER
14261 cfg->evt_handler[WLC_E_BT_WIFI_HANDOVER_REQ] = wl_notify_bt_wifi_handover_req;
14262 #endif
14263 cfg->evt_handler[WLC_E_CSA_COMPLETE_IND] = wl_csa_complete_ind;
14264 cfg->evt_handler[WLC_E_AP_STARTED] = wl_ap_start_ind;
14265 #ifdef CUSTOM_EVENT_PM_WAKE
14266 cfg->evt_handler[WLC_E_EXCESS_PM_WAKE_EVENT] = wl_check_pmstatus;
14267 #endif /* CUSTOM_EVENT_PM_WAKE */
14268 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
14269 cfg->evt_handler[WLC_E_ROAM_PREP] = wl_notify_roam_prep_status;
14270 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
14271 #ifdef ENABLE_TEMP_THROTTLING
14272 cfg->evt_handler[WLC_E_TEMP_THROTTLE] = wl_check_rx_throttle_status;
14273 #endif /* ENABLE_TEMP_THROTTLING */
14274
14275 }
14276
14277 #if defined(STATIC_WL_PRIV_STRUCT)
14278 static int
14279 wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
14280 {
14281 cfg->escan_info.escan_buf = DHD_OS_PREALLOC(cfg->pub,
14282 DHD_PREALLOC_WIPHY_ESCAN0, ESCAN_BUF_SIZE);
14283 if (cfg->escan_info.escan_buf == NULL) {
14284 WL_ERR(("Failed to alloc ESCAN_BUF\n"));
14285 return -ENOMEM;
14286 }
14287 bzero(cfg->escan_info.escan_buf, ESCAN_BUF_SIZE);
14288
14289 return 0;
14290 }
14291
14292 static void
14293 wl_deinit_escan_result_buf(struct bcm_cfg80211 *cfg)
14294 {
14295 if (cfg->escan_info.escan_buf != NULL) {
14296 cfg->escan_info.escan_buf = NULL;
14297 }
14298 }
14299 #endif /* STATIC_WL_PRIV_STRUCT */
14300
14301 static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg)
14302 {
14303 WL_DBG(("Enter \n"));
14304
14305 cfg->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
14306 if (unlikely(!cfg->scan_results)) {
14307 WL_ERR(("Scan results alloc failed\n"));
14308 goto init_priv_mem_out;
14309 }
14310 cfg->conf = (void *)kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
14311 if (unlikely(!cfg->conf)) {
14312 WL_ERR(("wl_conf alloc failed\n"));
14313 goto init_priv_mem_out;
14314 }
14315 cfg->scan_req_int =
14316 (void *)kzalloc(sizeof(*cfg->scan_req_int), GFP_KERNEL);
14317 if (unlikely(!cfg->scan_req_int)) {
14318 WL_ERR(("Scan req alloc failed\n"));
14319 goto init_priv_mem_out;
14320 }
14321 cfg->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
14322 if (unlikely(!cfg->ioctl_buf)) {
14323 WL_ERR(("Ioctl buf alloc failed\n"));
14324 goto init_priv_mem_out;
14325 }
14326 cfg->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
14327 if (unlikely(!cfg->escan_ioctl_buf)) {
14328 WL_ERR(("Ioctl buf alloc failed\n"));
14329 goto init_priv_mem_out;
14330 }
14331 cfg->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
14332 if (unlikely(!cfg->extra_buf)) {
14333 WL_ERR(("Extra buf alloc failed\n"));
14334 goto init_priv_mem_out;
14335 }
14336 cfg->pmk_list = (void *)kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
14337 if (unlikely(!cfg->pmk_list)) {
14338 WL_ERR(("pmk list alloc failed\n"));
14339 goto init_priv_mem_out;
14340 }
14341 #if defined(STATIC_WL_PRIV_STRUCT)
14342 cfg->conn_info = (void *)kzalloc(sizeof(*cfg->conn_info), GFP_KERNEL);
14343 if (unlikely(!cfg->conn_info)) {
14344 WL_ERR(("cfg->conn_info alloc failed\n"));
14345 goto init_priv_mem_out;
14346 }
14347 cfg->ie = (void *)kzalloc(sizeof(*cfg->ie), GFP_KERNEL);
14348 if (unlikely(!cfg->ie)) {
14349 WL_ERR(("cfg->ie alloc failed\n"));
14350 goto init_priv_mem_out;
14351 }
14352 if (unlikely(wl_init_escan_result_buf(cfg))) {
14353 WL_ERR(("Failed to init escan resul buf\n"));
14354 goto init_priv_mem_out;
14355 }
14356 #endif /* STATIC_WL_PRIV_STRUCT */
14357 cfg->afx_hdl = (void *)kzalloc(sizeof(*cfg->afx_hdl), GFP_KERNEL);
14358 if (unlikely(!cfg->afx_hdl)) {
14359 WL_ERR(("afx hdl alloc failed\n"));
14360 goto init_priv_mem_out;
14361 } else {
14362 init_completion(&cfg->act_frm_scan);
14363 init_completion(&cfg->wait_next_af);
14364
14365 INIT_WORK(&cfg->afx_hdl->work, wl_cfg80211_afx_handler);
14366 }
14367 #ifdef WLTDLS
14368 if (cfg->tdls_mgmt_frame) {
14369 kfree(cfg->tdls_mgmt_frame);
14370 cfg->tdls_mgmt_frame = NULL;
14371 }
14372 #endif /* WLTDLS */
14373 return 0;
14374
14375 init_priv_mem_out:
14376 wl_deinit_priv_mem(cfg);
14377
14378 return -ENOMEM;
14379 }
14380
14381 static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg)
14382 {
14383 kfree(cfg->scan_results);
14384 cfg->scan_results = NULL;
14385 kfree(cfg->conf);
14386 cfg->conf = NULL;
14387 kfree(cfg->scan_req_int);
14388 cfg->scan_req_int = NULL;
14389 kfree(cfg->ioctl_buf);
14390 cfg->ioctl_buf = NULL;
14391 kfree(cfg->escan_ioctl_buf);
14392 cfg->escan_ioctl_buf = NULL;
14393 kfree(cfg->extra_buf);
14394 cfg->extra_buf = NULL;
14395 kfree(cfg->pmk_list);
14396 cfg->pmk_list = NULL;
14397 #if defined(STATIC_WL_PRIV_STRUCT)
14398 kfree(cfg->conn_info);
14399 cfg->conn_info = NULL;
14400 kfree(cfg->ie);
14401 cfg->ie = NULL;
14402 wl_deinit_escan_result_buf(cfg);
14403 #endif /* STATIC_WL_PRIV_STRUCT */
14404 if (cfg->afx_hdl) {
14405 cancel_work_sync(&cfg->afx_hdl->work);
14406 kfree(cfg->afx_hdl);
14407 cfg->afx_hdl = NULL;
14408 }
14409
14410 }
14411
14412 static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg)
14413 {
14414 int ret = 0;
14415 WL_DBG(("Enter \n"));
14416
14417 /* Allocate workqueue for event */
14418 if (!cfg->event_workq) {
14419 cfg->event_workq = alloc_workqueue("dhd_eventd", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
14420 }
14421
14422 if (!cfg->event_workq) {
14423 ret = -ENOMEM;
14424 } else {
14425 INIT_WORK(&cfg->event_work, wl_event_handler);
14426 }
14427 return ret;
14428 }
14429
14430 static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg)
14431 {
14432 if (cfg && cfg->event_workq) {
14433 cancel_work_sync(&cfg->event_work);
14434 destroy_workqueue(cfg->event_workq);
14435 cfg->event_workq = NULL;
14436 }
14437 }
14438
14439 void wl_terminate_event_handler(struct net_device *dev)
14440 {
14441 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
14442
14443 if (cfg) {
14444 wl_destroy_event_handler(cfg);
14445 wl_flush_eq(cfg);
14446 }
14447 }
14448
14449 static void wl_scan_timeout(unsigned long data)
14450 {
14451 wl_event_msg_t msg;
14452 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
14453 struct wireless_dev *wdev = NULL;
14454 struct net_device *ndev = NULL;
14455 struct wl_scan_results *bss_list;
14456 struct wl_bss_info *bi = NULL;
14457 s32 i;
14458 u32 channel;
14459 #if 0
14460 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
14461 uint32 prev_memdump_mode = dhdp->memdump_enabled;
14462 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
14463
14464 if (!(cfg->scan_request)) {
14465 WL_ERR(("timer expired but no scan request\n"));
14466 return;
14467 }
14468
14469 bss_list = wl_escan_get_buf(cfg, FALSE);
14470 if (!bss_list) {
14471 WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
14472 } else {
14473 WL_ERR(("scanned AP count (%d)\n", bss_list->count));
14474
14475 bi = next_bss(bss_list, bi);
14476 for_each_bss(bss_list, bi, i) {
14477 if (bi != NULL && &(bi->chanspec) != NULL && (bi->SSID)) {
14478 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
14479 WL_ERR(("SSID :%s SSID_LEN :%d Channel :%d\n", bi->SSID, bi->SSID_len, channel));
14480 if (bi->SSID[0] == '\0') {
14481 WL_ERR(("SSID :%s is null ssid_len:%d ,need return\n", bi->SSID, bi->SSID_len));
14482 return;
14483 }
14484 } else {
14485 WL_ERR(("SSID or Channel is null\n"));
14486 return;
14487 }
14488 }
14489 }
14490
14491 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
14492 if (cfg->scan_request->dev)
14493 wdev = cfg->scan_request->dev->ieee80211_ptr;
14494 #else
14495 if (cfg->scan_request)
14496 wdev = cfg->scan_request->wdev;
14497 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
14498 if (!wdev) {
14499 WL_ERR(("No wireless_dev present\n"));
14500 return;
14501 }
14502 ndev = wdev_to_wlc_ndev(wdev, cfg);
14503
14504 bzero(&msg, sizeof(wl_event_msg_t));
14505 WL_ERR(("timer expired\n"));
14506 #if 0
14507 if (dhdp->memdump_enabled) {
14508 dhdp->memdump_enabled = DUMP_MEMFILE;
14509 dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
14510 dhd_bus_mem_dump(dhdp);
14511 dhdp->memdump_enabled = prev_memdump_mode;
14512 }
14513 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
14514 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
14515 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
14516 msg.reason = 0xFFFFFFFF;
14517 wl_cfg80211_event(ndev, &msg, NULL);
14518 #ifdef CUSTOMER_HW4_DEBUG
14519 if (!wl_scan_timeout_dbg_enabled)
14520 wl_scan_timeout_dbg_set();
14521 #endif /* CUSTOMER_HW4_DEBUG */
14522
14523 // terence 20130729: workaround to fix out of memory in firmware
14524 // if (dhd_conf_get_chip(dhd_get_pub(ndev)) == BCM43362_CHIP_ID) {
14525 // WL_ERR(("Send hang event\n"));
14526 // net_os_send_hang_message(ndev);
14527 // }
14528 }
14529
14530 #ifdef DHD_LOSSLESS_ROAMING
14531 static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg)
14532 {
14533 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
14534
14535 /* restore prec_map to ALLPRIO */
14536 dhdp->dequeue_prec_map = ALLPRIO;
14537 if (timer_pending(&cfg->roam_timeout)) {
14538 del_timer_sync(&cfg->roam_timeout);
14539 }
14540
14541 }
14542
14543 static void wl_roam_timeout(unsigned long data)
14544 {
14545 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
14546 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
14547
14548 WL_ERR(("roam timer expired\n"));
14549
14550 /* restore prec_map to ALLPRIO */
14551 dhdp->dequeue_prec_map = ALLPRIO;
14552 }
14553
14554 #endif /* DHD_LOSSLESS_ROAMING */
14555
14556 static s32
14557 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
14558 unsigned long state, void *ptr)
14559 {
14560 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
14561 struct net_device *dev = ptr;
14562 #else
14563 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
14564 #endif /* LINUX_VERSION < VERSION(3, 11, 0) */
14565 struct wireless_dev *wdev = ndev_to_wdev(dev);
14566 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
14567
14568 WL_DBG(("Enter \n"));
14569
14570 if (!wdev || !cfg || dev == bcmcfg_to_prmry_ndev(cfg))
14571 return NOTIFY_DONE;
14572
14573 switch (state) {
14574 case NETDEV_DOWN:
14575 {
14576 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
14577 int max_wait_timeout = 2;
14578 int max_wait_count = 100;
14579 int refcnt = 0;
14580 unsigned long limit = jiffies + max_wait_timeout * HZ;
14581 while (work_pending(&wdev->cleanup_work)) {
14582 if (refcnt%5 == 0) {
14583 WL_ERR(("[NETDEV_DOWN] wait for "
14584 "complete of cleanup_work"
14585 " (%d th)\n", refcnt));
14586 }
14587 if (!time_before(jiffies, limit)) {
14588 WL_ERR(("[NETDEV_DOWN] cleanup_work"
14589 " of CFG80211 is not"
14590 " completed in %d sec\n",
14591 max_wait_timeout));
14592 break;
14593 }
14594 if (refcnt >= max_wait_count) {
14595 WL_ERR(("[NETDEV_DOWN] cleanup_work"
14596 " of CFG80211 is not"
14597 " completed in %d loop\n",
14598 max_wait_count));
14599 break;
14600 }
14601 set_current_state(TASK_INTERRUPTIBLE);
14602 (void)schedule_timeout(100);
14603 set_current_state(TASK_RUNNING);
14604 refcnt++;
14605 }
14606 #endif /* LINUX_VERSION < VERSION(3, 14, 0) */
14607 break;
14608 }
14609 case NETDEV_UNREGISTER:
14610 /* after calling list_del_rcu(&wdev->list) */
14611 wl_cfg80211_clear_per_bss_ies(cfg,
14612 wl_get_bssidx_by_wdev(cfg, wdev));
14613 wl_dealloc_netinfo_by_wdev(cfg, wdev);
14614 break;
14615 case NETDEV_GOING_DOWN:
14616 /*
14617 * At NETDEV_DOWN state, wdev_cleanup_work work will be called.
14618 * In front of door, the function checks whether current scan
14619 * is working or not. If the scanning is still working,
14620 * wdev_cleanup_work call WARN_ON and make the scan done forcibly.
14621 */
14622 if (wl_get_drv_status(cfg, SCANNING, dev))
14623 wl_notify_escan_complete(cfg, dev, true, true);
14624 break;
14625 }
14626 return NOTIFY_DONE;
14627 }
14628
14629 static struct notifier_block wl_cfg80211_netdev_notifier = {
14630 .notifier_call = wl_cfg80211_netdev_notifier_call,
14631 };
14632
14633 /*
14634 * to make sure we won't register the same notifier twice, otherwise a loop is likely to be
14635 * created in kernel notifier link list (with 'next' pointing to itself)
14636 */
14637 static bool wl_cfg80211_netdev_notifier_registered = FALSE;
14638
14639 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg)
14640 {
14641 struct wireless_dev *wdev = NULL;
14642 struct net_device *ndev = NULL;
14643
14644 if (!cfg->scan_request)
14645 return;
14646
14647 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
14648 if (cfg->scan_request->dev)
14649 wdev = cfg->scan_request->dev->ieee80211_ptr;
14650 #else
14651 wdev = cfg->scan_request->wdev;
14652 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
14653
14654 if (!wdev) {
14655 WL_ERR(("No wireless_dev present\n"));
14656 return;
14657 }
14658
14659 ndev = wdev_to_wlc_ndev(wdev, cfg);
14660 wl_notify_escan_complete(cfg, ndev, true, true);
14661 WL_ERR(("Scan aborted! \n"));
14662 }
14663
14664 void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
14665 {
14666 wl_scan_params_t *params = NULL;
14667 s32 params_size = 0;
14668 s32 err = BCME_OK;
14669 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
14670 if (!in_atomic()) {
14671 /* Our scan params only need space for 1 channel and 0 ssids */
14672 params = wl_cfg80211_scan_alloc_params(cfg, -1, 0, &params_size);
14673 if (params == NULL) {
14674 WL_ERR(("scan params allocation failed \n"));
14675 err = -ENOMEM;
14676 } else {
14677 /* Do a scan abort to stop the driver's scan engine */
14678 err = wldev_ioctl_set(dev, WLC_SCAN, params, params_size);
14679 if (err < 0) {
14680 WL_ERR(("scan abort failed \n"));
14681 }
14682 kfree(params);
14683 }
14684 }
14685 #ifdef WLTDLS
14686 if (cfg->tdls_mgmt_frame) {
14687 kfree(cfg->tdls_mgmt_frame);
14688 cfg->tdls_mgmt_frame = NULL;
14689 }
14690 #endif /* WLTDLS */
14691 }
14692
14693 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
14694 struct net_device *ndev,
14695 bool aborted, bool fw_abort)
14696 {
14697 s32 err = BCME_OK;
14698 unsigned long flags;
14699 struct net_device *dev;
14700 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
14701 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
14702 struct cfg80211_scan_info info;
14703 info.aborted = aborted;
14704 #endif
14705
14706 WL_DBG(("Enter \n"));
14707 BCM_REFERENCE(dhdp);
14708
14709 mutex_lock(&cfg->scan_complete);
14710
14711 if (!ndev) {
14712 WL_ERR(("ndev is null\n"));
14713 err = BCME_ERROR;
14714 goto out;
14715 }
14716
14717 if (cfg->escan_info.ndev != ndev) {
14718 WL_ERR(("ndev is different %p %p\n", cfg->escan_info.ndev, ndev));
14719 err = BCME_ERROR;
14720 goto out;
14721 }
14722
14723 if (cfg->scan_request) {
14724 dev = bcmcfg_to_prmry_ndev(cfg);
14725 #if defined(WL_ENABLE_P2P_IF)
14726 if (cfg->scan_request->dev != cfg->p2p_net)
14727 dev = cfg->scan_request->dev;
14728 #elif defined(WL_CFG80211_P2P_DEV_IF)
14729 if (cfg->scan_request->wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
14730 dev = cfg->scan_request->wdev->netdev;
14731 #endif /* WL_ENABLE_P2P_IF */
14732 }
14733 else {
14734 WL_DBG(("cfg->scan_request is NULL may be internal scan."
14735 "doing scan_abort for ndev %p primary %p",
14736 ndev, bcmcfg_to_prmry_ndev(cfg)));
14737 dev = ndev;
14738 }
14739 if (fw_abort && !in_atomic())
14740 wl_cfg80211_scan_abort(cfg);
14741 if (timer_pending(&cfg->scan_timeout))
14742 del_timer_sync(&cfg->scan_timeout);
14743 #if defined(ESCAN_RESULT_PATCH)
14744 if (likely(cfg->scan_request)) {
14745 cfg->bss_list = wl_escan_get_buf(cfg, aborted);
14746 wl_inform_bss(cfg);
14747 }
14748 #endif /* ESCAN_RESULT_PATCH */
14749 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14750 #ifdef WL_SCHED_SCAN
14751 if (cfg->sched_scan_req && !cfg->scan_request) {
14752 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
14753 if (!aborted) {
14754 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
14755 cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy, 0);
14756 #else
14757 cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy);
14758 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
14759 }
14760
14761 DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE);
14762 cfg->sched_scan_running = FALSE;
14763 }
14764 #endif /* WL_SCHED_SCAN */
14765 if (likely(cfg->scan_request)) {
14766 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
14767 cfg80211_scan_done(cfg->scan_request, &info);
14768 #else
14769 cfg80211_scan_done(cfg->scan_request, aborted);
14770 #endif
14771 cfg->scan_request = NULL;
14772 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
14773 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
14774 }
14775 if (p2p_is_on(cfg))
14776 wl_clr_p2p_status(cfg, SCANNING);
14777 wl_clr_drv_status(cfg, SCANNING, dev);
14778 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14779
14780 out:
14781 mutex_unlock(&cfg->scan_complete);
14782 return err;
14783 }
14784
14785 #ifdef ESCAN_BUF_OVERFLOW_MGMT
14786 #ifndef WL_DRV_AVOID_SCANCACHE
14787 static void
14788 wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
14789 {
14790 int idx;
14791 for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
14792 int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
14793 if (bss->RSSI < candidate[idx].RSSI) {
14794 if (len)
14795 memcpy(&candidate[idx + 1], &candidate[idx],
14796 sizeof(removal_element_t) * len);
14797 candidate[idx].RSSI = bss->RSSI;
14798 candidate[idx].length = bss->length;
14799 memcpy(&candidate[idx].BSSID, &bss->BSSID, ETHER_ADDR_LEN);
14800 return;
14801 }
14802 }
14803 }
14804
14805 static void
14806 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
14807 wl_bss_info_t *bi)
14808 {
14809 int idx1, idx2;
14810 int total_delete_len = 0;
14811 for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
14812 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
14813 wl_bss_info_t *bss = NULL;
14814 if (candidate[idx1].RSSI >= bi->RSSI)
14815 continue;
14816 for (idx2 = 0; idx2 < list->count; idx2++) {
14817 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
14818 list->bss_info;
14819 if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
14820 candidate[idx1].RSSI == bss->RSSI &&
14821 candidate[idx1].length == dtoh32(bss->length)) {
14822 u32 delete_len = dtoh32(bss->length);
14823 WL_DBG(("delete scan info of " MACDBG " to add new AP\n",
14824 MAC2STRDBG(bss->BSSID.octet)));
14825 if (idx2 < list->count -1) {
14826 memmove((u8 *)bss, (u8 *)bss + delete_len,
14827 list->buflen - cur_len - delete_len);
14828 }
14829 list->buflen -= delete_len;
14830 list->count--;
14831 total_delete_len += delete_len;
14832 /* if delete_len is greater than or equal to result length */
14833 if (total_delete_len >= bi->length) {
14834 return;
14835 }
14836 break;
14837 }
14838 cur_len += dtoh32(bss->length);
14839 }
14840 }
14841 }
14842 #endif /* WL_DRV_AVOID_SCANCACHE */
14843 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
14844
14845 #ifdef WL_DRV_AVOID_SCANCACHE
14846 static u32 wl_p2p_find_peer_channel(struct bcm_cfg80211 *cfg, s32 status, wl_bss_info_t *bi,
14847 u32 bi_length)
14848 {
14849 u32 ret;
14850 u8 *p2p_dev_addr = NULL;
14851
14852 ret = wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL);
14853 if (!ret) {
14854 return ret;
14855 }
14856 if (status == WLC_E_STATUS_PARTIAL) {
14857 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
14858 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
14859 cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
14860 s32 channel = wf_chspec_ctlchan(
14861 wl_chspec_driver_to_host(bi->chanspec));
14862
14863 if ((channel > MAXCHANNEL) || (channel <= 0))
14864 channel = WL_INVALID;
14865 else
14866 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
14867 " channel : %d\n",
14868 MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
14869 channel));
14870
14871 wl_clr_p2p_status(cfg, SCANNING);
14872 cfg->afx_hdl->peer_chan = channel;
14873 complete(&cfg->act_frm_scan);
14874 }
14875 } else {
14876 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
14877 wl_clr_p2p_status(cfg, SCANNING);
14878 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
14879 if (cfg->afx_hdl->peer_chan == WL_INVALID)
14880 complete(&cfg->act_frm_scan);
14881 }
14882
14883 return ret;
14884 }
14885
14886 static s32 wl_escan_without_scan_cache(struct bcm_cfg80211 *cfg, wl_escan_result_t *escan_result,
14887 struct net_device *ndev, const wl_event_msg_t *e, s32 status)
14888 {
14889 s32 err = BCME_OK;
14890 wl_bss_info_t *bi;
14891 u32 bi_length;
14892 bool aborted = false;
14893 bool fw_abort = false;
14894 bool notify_escan_complete = false;
14895
14896 if (wl_escan_check_sync_id(status, escan_result->sync_id,
14897 cfg->escan_info.cur_sync_id) < 0) {
14898 goto exit;
14899 }
14900
14901 wl_escan_print_sync_id(status, escan_result->sync_id,
14902 cfg->escan_info.cur_sync_id);
14903
14904 if (!(status == WLC_E_STATUS_TIMEOUT) || !(status == WLC_E_STATUS_PARTIAL)) {
14905 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
14906 }
14907
14908 if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
14909 notify_escan_complete = true;
14910 }
14911
14912 if (status == WLC_E_STATUS_PARTIAL) {
14913 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
14914 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND);
14915 if ((!escan_result) || (dtoh16(escan_result->bss_count) != 1)) {
14916 WL_ERR(("Invalid escan result (NULL pointer) or invalid bss_count\n"));
14917 goto exit;
14918 }
14919
14920 bi = escan_result->bss_info;
14921 bi_length = dtoh32(bi->length);
14922 if ((!bi) ||
14923 (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE))) {
14924 WL_ERR(("Invalid escan bss info (NULL pointer)"
14925 "or invalid bss_info length\n"));
14926 goto exit;
14927 }
14928
14929 if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
14930 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
14931 WL_DBG(("Ignoring IBSS result\n"));
14932 goto exit;
14933 }
14934 }
14935
14936 if (wl_p2p_find_peer_channel(cfg, status, bi, bi_length)) {
14937 goto exit;
14938 } else {
14939 if (scan_req_match(cfg)) {
14940 /* p2p scan && allow only probe response */
14941 if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
14942 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
14943 goto exit;
14944 }
14945 err = wl_inform_single_bss(cfg, bi, false);
14946
14947 /*
14948 * !Broadcast && number of ssid = 1 && number of channels =1
14949 * means specific scan to association
14950 */
14951 if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
14952 WL_ERR(("P2P assoc scan fast aborted.\n"));
14953 aborted = false;
14954 fw_abort = true;
14955 }
14956 /* Directly exit from function here and
14957 * avoid sending notify completion to cfg80211
14958 */
14959 goto exit;
14960 }
14961 } else if (status == WLC_E_STATUS_SUCCESS) {
14962 if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
14963 goto exit;
14964 }
14965 WL_INFORM(("ESCAN COMPLETED\n"));
14966 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE);
14967
14968 /* Update escan complete status */
14969 aborted = false;
14970 fw_abort = false;
14971
14972 #ifdef CUSTOMER_HW4_DEBUG
14973 if (wl_scan_timeout_dbg_enabled)
14974 wl_scan_timeout_dbg_clear();
14975 #endif /* CUSTOMER_HW4_DEBUG */
14976 } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
14977 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
14978 (status == WLC_E_STATUS_NEWASSOC)) {
14979 /* Handle all cases of scan abort */
14980
14981 WL_DBG(("ESCAN ABORT reason: %d\n", status));
14982 if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
14983 goto exit;
14984 }
14985 WL_INFORM(("ESCAN ABORTED\n"));
14986
14987 /* Update escan complete status */
14988 aborted = true;
14989 fw_abort = false;
14990
14991 } else if (status == WLC_E_STATUS_TIMEOUT) {
14992 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
14993 WL_ERR(("reason[0x%x]\n", e->reason));
14994 if (e->reason == 0xFFFFFFFF) {
14995 /* Update escan complete status */
14996 aborted = true;
14997 fw_abort = true;
14998 }
14999 } else {
15000 WL_ERR(("unexpected Escan Event %d : abort\n", status));
15001
15002 if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
15003 goto exit;
15004 }
15005 /* Update escan complete status */
15006 aborted = true;
15007 fw_abort = false;
15008 }
15009
15010 /* Notify escan complete status */
15011 if (notify_escan_complete) {
15012 wl_notify_escan_complete(cfg, ndev, aborted, fw_abort);
15013 }
15014
15015 exit:
15016 return err;
15017
15018 }
15019 #endif /* WL_DRV_AVOID_SCANCACHE */
15020 static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
15021 const wl_event_msg_t *e, void *data)
15022 {
15023 s32 err = BCME_OK;
15024 s32 status = ntoh32(e->status);
15025 wl_escan_result_t *escan_result;
15026 struct net_device *ndev = NULL;
15027 #ifndef WL_DRV_AVOID_SCANCACHE
15028 wl_bss_info_t *bi;
15029 u32 bi_length;
15030 wifi_p2p_ie_t * p2p_ie;
15031 u8 *p2p_dev_addr = NULL;
15032 wl_scan_results_t *list;
15033 wl_bss_info_t *bss = NULL;
15034 u32 i;
15035 #endif /* WL_DRV_AVOID_SCANCACHE */
15036 u16 channel;
15037 struct ieee80211_supported_band *band;
15038
15039 WL_DBG((" enter event type : %d, status : %d \n",
15040 ntoh32(e->event_type), ntoh32(e->status)));
15041
15042 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
15043
15044 mutex_lock(&cfg->usr_sync);
15045 /* P2P SCAN is coming from primary interface */
15046 if (wl_get_p2p_status(cfg, SCANNING)) {
15047 if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
15048 ndev = cfg->afx_hdl->dev;
15049 else
15050 ndev = cfg->escan_info.ndev;
15051
15052 }
15053 if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
15054 WL_ERR(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n",
15055 ndev, wl_get_drv_status(cfg, SCANNING, ndev),
15056 ntoh32(e->event_type), ntoh32(e->status)));
15057 goto exit;
15058 }
15059 escan_result = (wl_escan_result_t *)data;
15060
15061 #ifndef WL_DRV_AVOID_SCANCACHE
15062 if (status == WLC_E_STATUS_PARTIAL) {
15063 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
15064 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND);
15065 if (!escan_result) {
15066 WL_ERR(("Invalid escan result (NULL pointer)\n"));
15067 goto exit;
15068 }
15069 if ((dtoh32(escan_result->buflen) > (int)ESCAN_BUF_SIZE) ||
15070 (dtoh32(escan_result->buflen) < sizeof(wl_escan_result_t))) {
15071 WL_ERR(("Invalid escan buffer len:%d\n", dtoh32(escan_result->buflen)));
15072 goto exit;
15073 }
15074 if (dtoh16(escan_result->bss_count) != 1) {
15075 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
15076 goto exit;
15077 }
15078 bi = escan_result->bss_info;
15079 if (!bi) {
15080 WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
15081 goto exit;
15082 }
15083 bi_length = dtoh32(bi->length);
15084 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
15085 WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
15086 goto exit;
15087 }
15088
15089 /* +++++ terence 20130524: skip invalid bss */
15090 channel =
15091 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
15092 if (channel <= CH_MAX_2G_CHANNEL)
15093 band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
15094 else
15095 band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_5GHZ];
15096 if (!band) {
15097 WL_ERR(("No valid band\n"));
15098 goto exit;
15099 }
15100 if (!dhd_conf_match_channel(cfg->pub, channel))
15101 goto exit;
15102 /* ----- terence 20130524: skip invalid bss */
15103
15104 if (wl_escan_check_sync_id(status, escan_result->sync_id,
15105 cfg->escan_info.cur_sync_id) < 0)
15106 goto exit;
15107
15108 if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
15109 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
15110 WL_DBG(("Ignoring IBSS result\n"));
15111 goto exit;
15112 }
15113 }
15114
15115 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
15116 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
15117 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
15118 cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
15119 s32 channel = wf_chspec_ctlchan(
15120 wl_chspec_driver_to_host(bi->chanspec));
15121
15122 if ((channel > MAXCHANNEL) || (channel <= 0))
15123 channel = WL_INVALID;
15124 else
15125 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
15126 " channel : %d\n",
15127 MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
15128 channel));
15129
15130 wl_clr_p2p_status(cfg, SCANNING);
15131 cfg->afx_hdl->peer_chan = channel;
15132 complete(&cfg->act_frm_scan);
15133 goto exit;
15134 }
15135
15136 } else {
15137 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
15138 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15139 removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
15140 int remove_lower_rssi = FALSE;
15141
15142 bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
15143 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15144
15145 list = wl_escan_get_buf(cfg, FALSE);
15146 if (scan_req_match(cfg)) {
15147 /* p2p scan && allow only probe response */
15148 if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
15149 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
15150 goto exit;
15151 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
15152 bi->ie_length)) == NULL) {
15153 WL_ERR(("Couldn't find P2PIE in probe"
15154 " response/beacon\n"));
15155 goto exit;
15156 }
15157 }
15158 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15159 if (bi_length > ESCAN_BUF_SIZE - list->buflen)
15160 remove_lower_rssi = TRUE;
15161 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15162
15163 WL_SCAN(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID,
15164 MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length));
15165 for (i = 0; i < list->count; i++) {
15166 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
15167 : list->bss_info;
15168 if (!bss) {
15169 WL_ERR(("bss is NULL\n"));
15170 goto exit;
15171 }
15172 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15173 WL_TRACE(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
15174 bss->SSID, MAC2STRDBG(bss->BSSID.octet),
15175 i, bss->RSSI, list->count));
15176
15177 if (remove_lower_rssi)
15178 wl_cfg80211_find_removal_candidate(bss, candidate);
15179 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15180
15181 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
15182 (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
15183 == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
15184 bi->SSID_len == bss->SSID_len &&
15185 !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
15186
15187 /* do not allow beacon data to update
15188 *the data recd from a probe response
15189 */
15190 if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
15191 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
15192 goto exit;
15193
15194 WL_SCAN(("%s("MACDBG"), i=%d prev: RSSI %d"
15195 " flags 0x%x, new: RSSI %d flags 0x%x\n",
15196 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
15197 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
15198
15199 if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
15200 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
15201 /* preserve max RSSI if the measurements are
15202 * both on-channel or both off-channel
15203 */
15204 WL_SCAN(("%s("MACDBG"), same onchan"
15205 ", RSSI: prev %d new %d\n",
15206 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
15207 bss->RSSI, bi->RSSI));
15208 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
15209 } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
15210 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
15211 /* preserve the on-channel rssi measurement
15212 * if the new measurement is off channel
15213 */
15214 WL_SCAN(("%s("MACDBG"), prev onchan"
15215 ", RSSI: prev %d new %d\n",
15216 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
15217 bss->RSSI, bi->RSSI));
15218 bi->RSSI = bss->RSSI;
15219 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
15220 }
15221 if (dtoh32(bss->length) != bi_length) {
15222 u32 prev_len = dtoh32(bss->length);
15223
15224 WL_SCAN(("bss info replacement"
15225 " is occured(bcast:%d->probresp%d)\n",
15226 bss->ie_length, bi->ie_length));
15227 WL_SCAN(("%s("MACDBG"), replacement!(%d -> %d)\n",
15228 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
15229 prev_len, bi_length));
15230
15231 if (list->buflen - prev_len + bi_length
15232 > ESCAN_BUF_SIZE) {
15233 WL_ERR(("Buffer is too small: keep the"
15234 " previous result of this AP\n"));
15235 /* Only update RSSI */
15236 bss->RSSI = bi->RSSI;
15237 bss->flags |= (bi->flags
15238 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
15239 goto exit;
15240 }
15241
15242 if (i < list->count - 1) {
15243 /* memory copy required by this case only */
15244 memmove((u8 *)bss + bi_length,
15245 (u8 *)bss + prev_len,
15246 list->buflen - cur_len - prev_len);
15247 }
15248 list->buflen -= prev_len;
15249 list->buflen += bi_length;
15250 }
15251 list->version = dtoh32(bi->version);
15252 memcpy((u8 *)bss, (u8 *)bi, bi_length);
15253 goto exit;
15254 }
15255 cur_len += dtoh32(bss->length);
15256 }
15257 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
15258 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15259 wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
15260 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
15261 WL_DBG(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
15262 MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
15263 goto exit;
15264 }
15265 #else
15266 WL_ERR(("Buffer is too small: ignoring\n"));
15267 goto exit;
15268 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15269 }
15270
15271 memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
15272 list->version = dtoh32(bi->version);
15273 list->buflen += bi_length;
15274 list->count++;
15275
15276 /*
15277 * !Broadcast && number of ssid = 1 && number of channels =1
15278 * means specific scan to association
15279 */
15280 if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
15281 WL_ERR(("P2P assoc scan fast aborted.\n"));
15282 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, false, true);
15283 goto exit;
15284 }
15285 }
15286 }
15287 else if (status == WLC_E_STATUS_SUCCESS) {
15288 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
15289 wl_escan_print_sync_id(status, cfg->escan_info.cur_sync_id,
15290 escan_result->sync_id);
15291
15292 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
15293 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15294 wl_clr_p2p_status(cfg, SCANNING);
15295 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
15296 if (cfg->afx_hdl->peer_chan == WL_INVALID)
15297 complete(&cfg->act_frm_scan);
15298 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
15299 WL_INFORM(("ESCAN COMPLETED\n"));
15300 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE);
15301 cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
15302 if (!scan_req_match(cfg)) {
15303 WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n",
15304 cfg->bss_list->count));
15305 }
15306 wl_inform_bss(cfg);
15307 wl_notify_escan_complete(cfg, ndev, false, false);
15308 }
15309 wl_escan_increment_sync_id(cfg, SCAN_BUF_NEXT);
15310 #ifdef CUSTOMER_HW4_DEBUG
15311 if (wl_scan_timeout_dbg_enabled)
15312 wl_scan_timeout_dbg_clear();
15313 #endif /* CUSTOMER_HW4_DEBUG */
15314 } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
15315 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
15316 (status == WLC_E_STATUS_NEWASSOC)) {
15317 /* Handle all cases of scan abort */
15318 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
15319 wl_escan_print_sync_id(status, escan_result->sync_id,
15320 cfg->escan_info.cur_sync_id);
15321 WL_DBG(("ESCAN ABORT reason: %d\n", status));
15322 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
15323 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15324 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
15325 wl_clr_p2p_status(cfg, SCANNING);
15326 if (cfg->afx_hdl->peer_chan == WL_INVALID)
15327 complete(&cfg->act_frm_scan);
15328 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
15329 WL_INFORM(("ESCAN ABORTED\n"));
15330 cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
15331 if (!scan_req_match(cfg)) {
15332 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
15333 cfg->bss_list->count));
15334 }
15335 wl_inform_bss(cfg);
15336 wl_notify_escan_complete(cfg, ndev, true, false);
15337 } else {
15338 /* If there is no pending host initiated scan, do nothing */
15339 WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
15340 }
15341 wl_escan_increment_sync_id(cfg, SCAN_BUF_CNT);
15342 } else if (status == WLC_E_STATUS_TIMEOUT) {
15343 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
15344 WL_ERR(("reason[0x%x]\n", e->reason));
15345 if (e->reason == 0xFFFFFFFF) {
15346 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
15347 }
15348 } else {
15349 WL_ERR(("unexpected Escan Event %d : abort\n", status));
15350 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
15351 wl_escan_print_sync_id(status, escan_result->sync_id,
15352 cfg->escan_info.cur_sync_id);
15353 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
15354 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15355 wl_clr_p2p_status(cfg, SCANNING);
15356 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
15357 if (cfg->afx_hdl->peer_chan == WL_INVALID)
15358 complete(&cfg->act_frm_scan);
15359 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
15360 cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
15361 if (!scan_req_match(cfg)) {
15362 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
15363 "scanned AP count=%d\n",
15364 cfg->bss_list->count));
15365 }
15366 wl_inform_bss(cfg);
15367 wl_notify_escan_complete(cfg, ndev, true, false);
15368 }
15369 wl_escan_increment_sync_id(cfg, 2);
15370 }
15371 #else /* WL_DRV_AVOID_SCANCACHE */
15372 err = wl_escan_without_scan_cache(cfg, escan_result, ndev, e, status);
15373 #endif /* WL_DRV_AVOID_SCANCACHE */
15374 exit:
15375 mutex_unlock(&cfg->usr_sync);
15376 return err;
15377 }
15378
15379 static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211 *cfg, int enable)
15380 {
15381 u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
15382 bool p2p_connected = wl_cfgp2p_vif_created(cfg);
15383 struct net_info *iter, *next;
15384
15385 if (!(cfg->roam_flags & WL_ROAM_OFF_ON_CONCURRENT))
15386 return;
15387
15388 WL_DBG(("roam off:%d p2p_connected:%d connected_cnt:%d \n",
15389 enable, p2p_connected, connected_cnt));
15390 /* Disable FW roam when we have a concurrent P2P connection */
15391 if (enable && p2p_connected && connected_cnt > 1) {
15392
15393 /* Mark it as to be reverted */
15394 cfg->roam_flags |= WL_ROAM_REVERT_STATUS;
15395 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15396 4 && __GNUC_MINOR__ >= 6))
15397 _Pragma("GCC diagnostic push")
15398 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15399 #endif
15400 for_each_ndev(cfg, iter, next) {
15401 if (iter->ndev && iter->wdev &&
15402 iter->wdev->iftype == NL80211_IFTYPE_STATION) {
15403 if (wldev_iovar_setint(iter->ndev, "roam_off", TRUE)
15404 == BCME_OK) {
15405 iter->roam_off = TRUE;
15406 }
15407 else {
15408 WL_ERR(("error to enable roam_off\n"));
15409 }
15410 }
15411 }
15412 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15413 4 && __GNUC_MINOR__ >= 6))
15414 _Pragma("GCC diagnostic pop")
15415 #endif
15416 }
15417 else if (!enable && (cfg->roam_flags & WL_ROAM_REVERT_STATUS)) {
15418 cfg->roam_flags &= ~WL_ROAM_REVERT_STATUS;
15419 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15420 4 && __GNUC_MINOR__ >= 6))
15421 _Pragma("GCC diagnostic push")
15422 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15423 #endif
15424 for_each_ndev(cfg, iter, next) {
15425 if (iter->ndev && iter->wdev &&
15426 iter->wdev->iftype == NL80211_IFTYPE_STATION) {
15427 if (iter->roam_off != WL_INVALID) {
15428 if (wldev_iovar_setint(iter->ndev, "roam_off", FALSE)
15429 == BCME_OK) {
15430 iter->roam_off = FALSE;
15431 }
15432 else {
15433 WL_ERR(("error to disable roam_off\n"));
15434 }
15435 }
15436 }
15437 }
15438 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15439 4 && __GNUC_MINOR__ >= 6))
15440 _Pragma("GCC diagnostic pop")
15441 #endif
15442 }
15443
15444 return;
15445 }
15446
15447 static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211 *cfg)
15448 {
15449 struct net_info *iter, *next;
15450 u32 ctl_chan = 0;
15451 u32 chanspec = 0;
15452 u32 pre_ctl_chan = 0;
15453 u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
15454 cfg->vsdb_mode = false;
15455
15456 if (connected_cnt <= 1) {
15457 return;
15458 }
15459 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15460 4 && __GNUC_MINOR__ >= 6))
15461 _Pragma("GCC diagnostic push")
15462 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15463 #endif
15464 for_each_ndev(cfg, iter, next) {
15465 /* p2p discovery iface ndev could be null */
15466 if (iter->ndev) {
15467 chanspec = 0;
15468 ctl_chan = 0;
15469 if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
15470 if (wldev_iovar_getint(iter->ndev, "chanspec",
15471 (s32 *)&chanspec) == BCME_OK) {
15472 chanspec = wl_chspec_driver_to_host(chanspec);
15473 ctl_chan = wf_chspec_ctlchan(chanspec);
15474 wl_update_prof(cfg, iter->ndev, NULL,
15475 &ctl_chan, WL_PROF_CHAN);
15476 }
15477 if (!cfg->vsdb_mode) {
15478 if (!pre_ctl_chan && ctl_chan)
15479 pre_ctl_chan = ctl_chan;
15480 else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
15481 cfg->vsdb_mode = true;
15482 }
15483 }
15484 }
15485 }
15486 }
15487 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15488 4 && __GNUC_MINOR__ >= 6))
15489 _Pragma("GCC diagnostic pop")
15490 #endif
15491 printf("%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel");
15492 return;
15493 }
15494
15495 #if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF)
15496 extern int g_frameburst;
15497 #endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */
15498
15499 static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
15500 enum wl_status state, bool set)
15501 {
15502 s32 pm = PM_FAST;
15503 s32 err = BCME_OK;
15504 u32 mode;
15505 u32 chan = 0;
15506 struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
15507 dhd_pub_t *dhd = cfg->pub;
15508 #ifdef RTT_SUPPORT
15509 rtt_status_info_t *rtt_status;
15510 #endif /* RTT_SUPPORT */
15511 if (dhd->busstate == DHD_BUS_DOWN) {
15512 WL_ERR(("%s : busstate is DHD_BUS_DOWN!\n", __FUNCTION__));
15513 return 0;
15514 }
15515 WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
15516 state, set, _net_info->pm_restore, _net_info->ndev->name));
15517
15518 if (state != WL_STATUS_CONNECTED)
15519 return 0;
15520 mode = wl_get_mode_by_netdev(cfg, _net_info->ndev);
15521 if (set) {
15522 wl_cfg80211_concurrent_roam(cfg, 1);
15523 wl_cfg80211_determine_vsdb_mode(cfg);
15524 if (mode == WL_MODE_AP) {
15525 if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
15526 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
15527 }
15528 pm = PM_OFF;
15529 if ((err = wldev_ioctl_set(_net_info->ndev, WLC_SET_PM, &pm,
15530 sizeof(pm))) != 0) {
15531 if (err == -ENODEV)
15532 WL_DBG(("%s:netdev not ready\n",
15533 _net_info->ndev->name));
15534 else
15535 WL_ERR(("%s:error (%d)\n",
15536 _net_info->ndev->name, err));
15537
15538 wl_cfg80211_update_power_mode(_net_info->ndev);
15539 }
15540 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_SHORT);
15541
15542 } else { /* clear */
15543 chan = 0;
15544 /* clear chan information when the net device is disconnected */
15545 wl_update_prof(cfg, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
15546 wl_cfg80211_determine_vsdb_mode(cfg);
15547 if (primary_dev == _net_info->ndev) {
15548 pm = PM_FAST;
15549 #ifdef RTT_SUPPORT
15550 rtt_status = GET_RTTSTATE(dhd);
15551 if (rtt_status->status != RTT_ENABLED) {
15552 #endif /* RTT_SUPPORT */
15553 if (dhd_conf_get_pm(dhd) >= 0)
15554 pm = dhd_conf_get_pm(dhd);
15555 if ((err = wldev_ioctl_set(_net_info->ndev, WLC_SET_PM, &pm,
15556 sizeof(pm))) != 0) {
15557 if (err == -ENODEV)
15558 WL_DBG(("%s:netdev not ready\n",
15559 _net_info->ndev->name));
15560 else
15561 WL_ERR(("%s:error (%d)\n",
15562 _net_info->ndev->name, err));
15563
15564 wl_cfg80211_update_power_mode(_net_info->ndev);
15565 }
15566 #ifdef RTT_SUPPORT
15567 }
15568 #endif /* RTT_SUPPORT */
15569 }
15570 wl_cfg80211_concurrent_roam(cfg, 0);
15571
15572 }
15573 return err;
15574 }
15575 static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
15576 {
15577 int err = 0;
15578
15579 cfg->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
15580 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
15581 wl_escan_init_sync_id(cfg);
15582
15583 /* Init scan_timeout timer */
15584 init_timer(&cfg->scan_timeout);
15585 cfg->scan_timeout.data = (unsigned long) cfg;
15586 cfg->scan_timeout.function = wl_scan_timeout;
15587
15588 return err;
15589 }
15590
15591 #ifdef DHD_LOSSLESS_ROAMING
15592 static s32 wl_init_roam_timeout(struct bcm_cfg80211 *cfg)
15593 {
15594 int err = 0;
15595
15596 /* Init roam timer */
15597 init_timer(&cfg->roam_timeout);
15598 cfg->roam_timeout.data = (unsigned long) cfg;
15599 cfg->roam_timeout.function = wl_roam_timeout;
15600
15601 return err;
15602 }
15603 #endif /* DHD_LOSSLESS_ROAMING */
15604
15605 static s32 wl_init_priv(struct bcm_cfg80211 *cfg)
15606 {
15607 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
15608 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
15609 s32 err = 0;
15610
15611 cfg->scan_request = NULL;
15612 cfg->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
15613 #ifdef DISABLE_BUILTIN_ROAM
15614 cfg->roam_on = false;
15615 #else
15616 cfg->roam_on = true;
15617 #endif /* DISABLE_BUILTIN_ROAM */
15618 cfg->active_scan = true;
15619 cfg->rf_blocked = false;
15620 cfg->vsdb_mode = false;
15621 #if defined(BCMSDIO) || defined(BCMDBUS)
15622 cfg->wlfc_on = false;
15623 #endif /* BCMSDIO || BCMDBUS */
15624 cfg->roam_flags |= WL_ROAM_OFF_ON_CONCURRENT;
15625 cfg->disable_roam_event = false;
15626 /* register interested state */
15627 set_bit(WL_STATUS_CONNECTED, &cfg->interrested_state);
15628 spin_lock_init(&cfg->cfgdrv_lock);
15629 mutex_init(&cfg->ioctl_buf_sync);
15630 init_waitqueue_head(&cfg->netif_change_event);
15631 init_completion(&cfg->send_af_done);
15632 init_completion(&cfg->iface_disable);
15633 wl_init_eq(cfg);
15634 err = wl_init_priv_mem(cfg);
15635 if (err)
15636 return err;
15637 if (wl_create_event_handler(cfg))
15638 return -ENOMEM;
15639 wl_init_event_handler(cfg);
15640 mutex_init(&cfg->usr_sync);
15641 mutex_init(&cfg->event_sync);
15642 mutex_init(&cfg->scan_complete);
15643 mutex_init(&cfg->if_sync);
15644 #ifdef WLTDLS
15645 mutex_init(&cfg->tdls_sync);
15646 #endif /* WLTDLS */
15647 err = wl_init_scan(cfg);
15648 if (err)
15649 return err;
15650 #ifdef DHD_LOSSLESS_ROAMING
15651 err = wl_init_roam_timeout(cfg);
15652 if (err) {
15653 return err;
15654 }
15655 #endif /* DHD_LOSSLESS_ROAMING */
15656 wl_init_conf(cfg->conf);
15657 wl_init_prof(cfg, ndev);
15658 wl_link_down(cfg);
15659 DNGL_FUNC(dhd_cfg80211_init, (cfg));
15660 #ifdef NAN_DP
15661 cfg->nan_dp_state = NAN_DP_STATE_DISABLED;
15662 init_waitqueue_head(&cfg->ndp_if_change_event);
15663 #endif /* NAN_DP */
15664 return err;
15665 }
15666
15667 static void wl_deinit_priv(struct bcm_cfg80211 *cfg)
15668 {
15669 DNGL_FUNC(dhd_cfg80211_deinit, (cfg));
15670 wl_destroy_event_handler(cfg);
15671 wl_flush_eq(cfg);
15672 wl_link_down(cfg);
15673 del_timer_sync(&cfg->scan_timeout);
15674 #ifdef DHD_LOSSLESS_ROAMING
15675 del_timer_sync(&cfg->roam_timeout);
15676 #endif
15677 wl_deinit_priv_mem(cfg);
15678 if (wl_cfg80211_netdev_notifier_registered) {
15679 wl_cfg80211_netdev_notifier_registered = FALSE;
15680 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
15681 }
15682 }
15683
15684 #if defined(WL_ENABLE_P2P_IF)
15685 static s32 wl_cfg80211_attach_p2p(struct bcm_cfg80211 *cfg)
15686 {
15687 WL_TRACE(("Enter \n"));
15688
15689 if (wl_cfgp2p_register_ndev(cfg) < 0) {
15690 WL_ERR(("P2P attach failed. \n"));
15691 return -ENODEV;
15692 }
15693
15694 return 0;
15695 }
15696
15697 static s32 wl_cfg80211_detach_p2p(struct bcm_cfg80211 *cfg)
15698 {
15699 struct wireless_dev *wdev;
15700
15701 WL_DBG(("Enter \n"));
15702 if (!cfg) {
15703 WL_ERR(("Invalid Ptr\n"));
15704 return -EINVAL;
15705 }
15706 else {
15707 wdev = cfg->p2p_wdev;
15708 if (!wdev) {
15709 WL_ERR(("Invalid Ptr\n"));
15710 return -EINVAL;
15711 }
15712 }
15713
15714 wl_cfgp2p_unregister_ndev(cfg);
15715
15716 cfg->p2p_wdev = NULL;
15717 cfg->p2p_net = NULL;
15718 WL_DBG(("Freeing 0x%p \n", wdev));
15719 kfree(wdev);
15720
15721 return 0;
15722 }
15723 #endif
15724
15725 static s32 wl_cfg80211_attach_post(struct net_device *ndev)
15726 {
15727 struct bcm_cfg80211 * cfg;
15728 s32 err = 0;
15729 s32 ret = 0;
15730 WL_TRACE(("In\n"));
15731 if (unlikely(!ndev)) {
15732 WL_ERR(("ndev is invaild\n"));
15733 return -ENODEV;
15734 }
15735 cfg = wl_get_cfg(ndev);
15736 if (unlikely(!cfg)) {
15737 WL_ERR(("cfg is invaild\n"));
15738 return -EINVAL;
15739 }
15740 if (!wl_get_drv_status(cfg, READY, ndev)) {
15741 if (cfg->wdev) {
15742 ret = wl_cfgp2p_supported(cfg, ndev);
15743 if (ret > 0) {
15744 #if !defined(WL_ENABLE_P2P_IF)
15745 cfg->wdev->wiphy->interface_modes |=
15746 (BIT(NL80211_IFTYPE_P2P_CLIENT)|
15747 BIT(NL80211_IFTYPE_P2P_GO));
15748 #endif /* !WL_ENABLE_P2P_IF */
15749 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
15750 goto fail;
15751
15752 #if defined(WL_ENABLE_P2P_IF)
15753 if (cfg->p2p_net) {
15754 /* Update MAC addr for p2p0 interface here. */
15755 memcpy(cfg->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
15756 cfg->p2p_net->dev_addr[0] |= 0x02;
15757 printf("%s: p2p_dev_addr="MACDBG "\n",
15758 cfg->p2p_net->name,
15759 MAC2STRDBG(cfg->p2p_net->dev_addr));
15760 } else {
15761 WL_ERR(("p2p_net not yet populated."
15762 " Couldn't update the MAC Address for p2p0 \n"));
15763 return -ENODEV;
15764 }
15765 #endif /* WL_ENABLE_P2P_IF */
15766 cfg->p2p_supported = true;
15767 } else if (ret == 0) {
15768 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
15769 goto fail;
15770 } else {
15771 /* SDIO bus timeout */
15772 err = -ENODEV;
15773 goto fail;
15774 }
15775 }
15776 }
15777 wl_set_drv_status(cfg, READY, ndev);
15778 fail:
15779 return err;
15780 }
15781
15782 struct bcm_cfg80211 *wl_get_cfg(struct net_device *ndev)
15783 {
15784 struct wireless_dev *wdev = ndev->ieee80211_ptr;
15785
15786 if (!wdev)
15787 return NULL;
15788
15789 return wiphy_priv(wdev->wiphy);
15790 }
15791
15792 s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
15793 {
15794 struct wireless_dev *wdev;
15795 struct bcm_cfg80211 *cfg;
15796 s32 err = 0;
15797 struct device *dev;
15798
15799 WL_TRACE(("In\n"));
15800 if (!ndev) {
15801 WL_ERR(("ndev is invaild\n"));
15802 return -ENODEV;
15803 }
15804 WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
15805 dev = wl_cfg80211_get_parent_dev();
15806
15807 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
15808 if (unlikely(!wdev)) {
15809 WL_ERR(("Could not allocate wireless device\n"));
15810 return -ENOMEM;
15811 }
15812 err = wl_setup_wiphy(wdev, dev, context);
15813 if (unlikely(err)) {
15814 kfree(wdev);
15815 return -ENOMEM;
15816 }
15817 #ifdef WLMESH
15818 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_MESH);
15819 #else
15820 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
15821 #endif
15822 cfg = wiphy_priv(wdev->wiphy);
15823 cfg->wdev = wdev;
15824 cfg->pub = context;
15825 INIT_LIST_HEAD(&cfg->net_list);
15826 #ifdef WBTEXT
15827 INIT_LIST_HEAD(&cfg->wbtext_bssid_list);
15828 #endif /* WBTEXT */
15829 INIT_LIST_HEAD(&cfg->vndr_oui_list);
15830 spin_lock_init(&cfg->net_list_sync);
15831 ndev->ieee80211_ptr = wdev;
15832 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
15833 wdev->netdev = ndev;
15834 cfg->state_notifier = wl_notifier_change_state;
15835 err = wl_alloc_netinfo(cfg, ndev, wdev, wdev->iftype, PM_ENABLE, 0);
15836 if (err) {
15837 WL_ERR(("Failed to alloc net_info (%d)\n", err));
15838 goto cfg80211_attach_out;
15839 }
15840 err = wl_init_priv(cfg);
15841 if (err) {
15842 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
15843 goto cfg80211_attach_out;
15844 }
15845
15846 err = wl_setup_rfkill(cfg, TRUE);
15847 if (err) {
15848 WL_ERR(("Failed to setup rfkill %d\n", err));
15849 goto cfg80211_attach_out;
15850 }
15851 #ifdef DEBUGFS_CFG80211
15852 err = wl_setup_debugfs(cfg);
15853 if (err) {
15854 WL_ERR(("Failed to setup debugfs %d\n", err));
15855 goto cfg80211_attach_out;
15856 }
15857 #endif
15858 if (!wl_cfg80211_netdev_notifier_registered) {
15859 wl_cfg80211_netdev_notifier_registered = TRUE;
15860 err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
15861 if (err) {
15862 wl_cfg80211_netdev_notifier_registered = FALSE;
15863 WL_ERR(("Failed to register notifierl %d\n", err));
15864 goto cfg80211_attach_out;
15865 }
15866 }
15867 #if defined(COEX_DHCP)
15868 cfg->btcoex_info = wl_cfg80211_btcoex_init(cfg->wdev->netdev);
15869 if (!cfg->btcoex_info)
15870 goto cfg80211_attach_out;
15871 #endif
15872 #if defined(SUPPORT_RANDOM_MAC_SCAN)
15873 cfg->random_mac_enabled = FALSE;
15874 #endif /* SUPPORT_RANDOM_MAC_SCAN */
15875
15876 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
15877 wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
15878 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
15879
15880 #if defined(WL_ENABLE_P2P_IF)
15881 err = wl_cfg80211_attach_p2p(cfg);
15882 if (err)
15883 goto cfg80211_attach_out;
15884 #endif
15885
15886 INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
15887 mutex_init(&cfg->pm_sync);
15888
15889 #if defined(STAT_REPORT)
15890 err = wl_attach_stat_report(cfg);
15891 if (err) {
15892 goto cfg80211_attach_out;
15893 }
15894 #endif /* STAT_REPORT */
15895 return err;
15896
15897 cfg80211_attach_out:
15898 wl_setup_rfkill(cfg, FALSE);
15899 wl_free_wdev(cfg);
15900 return err;
15901 }
15902
15903 void wl_cfg80211_detach(struct bcm_cfg80211 *cfg)
15904 {
15905
15906 WL_TRACE(("In\n"));
15907 if (!cfg)
15908 return;
15909
15910 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
15911
15912 #if defined(COEX_DHCP)
15913 wl_cfg80211_btcoex_deinit();
15914 cfg->btcoex_info = NULL;
15915 #endif
15916
15917 wl_setup_rfkill(cfg, FALSE);
15918 #ifdef DEBUGFS_CFG80211
15919 wl_free_debugfs(cfg);
15920 #endif
15921 if (cfg->p2p_supported) {
15922 if (timer_pending(&cfg->p2p->listen_timer))
15923 del_timer_sync(&cfg->p2p->listen_timer);
15924 wl_cfgp2p_deinit_priv(cfg);
15925 }
15926
15927 if (timer_pending(&cfg->scan_timeout))
15928 del_timer_sync(&cfg->scan_timeout);
15929 #ifdef DHD_LOSSLESS_ROAMING
15930 if (timer_pending(&cfg->roam_timeout)) {
15931 del_timer_sync(&cfg->roam_timeout);
15932 }
15933 #endif /* DHD_LOSSLESS_ROAMING */
15934
15935 #if defined(WL_CFG80211_P2P_DEV_IF)
15936 if (cfg->p2p_wdev)
15937 wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
15938 #endif /* WL_CFG80211_P2P_DEV_IF */
15939 #if defined(WL_ENABLE_P2P_IF)
15940 wl_cfg80211_detach_p2p(cfg);
15941 #endif
15942 #if defined(STAT_REPORT)
15943 wl_detach_stat_report(cfg);
15944 #endif /* STAT_REPORT */
15945
15946 wl_cfg80211_ibss_vsie_free(cfg);
15947 wl_cfg80211_clear_mgmt_vndr_ies(cfg);
15948 wl_deinit_priv(cfg);
15949 wl_cfg80211_clear_parent_dev();
15950 wl_free_wdev(cfg);
15951 #if defined(RSSIAVG)
15952 wl_free_rssi_cache(&g_rssi_cache_ctrl);
15953 wl_free_rssi_cache(&g_connected_rssi_cache_ctrl);
15954 #endif
15955 #if defined(BSSCACHE)
15956 wl_release_bss_cache_ctrl(&g_bss_cache_ctrl);
15957 #endif
15958 /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
15959 * structure "cfg", which is the private part of wiphy, has been freed in
15960 * wl_free_wdev !!!!!!!!!!!
15961 */
15962 }
15963
15964 static void wl_event_handler(struct work_struct *work_data)
15965 {
15966 struct bcm_cfg80211 *cfg = NULL;
15967 struct wl_event_q *e;
15968 struct wireless_dev *wdev = NULL;
15969
15970 BCM_SET_CONTAINER_OF(cfg, work_data, struct bcm_cfg80211, event_work);
15971 DHD_EVENT_WAKE_LOCK(cfg->pub);
15972 while ((e = wl_deq_event(cfg))) {
15973 WL_DBG(("event type (%d), ifidx: %d bssidx: %d \n",
15974 e->etype, e->emsg.ifidx, e->emsg.bsscfgidx));
15975
15976 if (e->emsg.ifidx > WL_MAX_IFS) {
15977 WL_ERR((" Event ifidx not in range. val:%d \n", e->emsg.ifidx));
15978 goto fail;
15979 }
15980
15981 /* Make sure iface operations, don't creat race conditions */
15982 mutex_lock(&cfg->if_sync);
15983 if (!(wdev = wl_get_wdev_by_bssidx(cfg, e->emsg.bsscfgidx))) {
15984 /* For WLC_E_IF would be handled by wl_host_event */
15985 if (e->etype != WLC_E_IF)
15986 WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"
15987 " Ignoring event.\n", e->emsg.bsscfgidx));
15988 } else if (e->etype < WLC_E_LAST && cfg->evt_handler[e->etype]) {
15989 dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
15990 if (dhd->busstate == DHD_BUS_DOWN) {
15991 WL_ERR((": BUS is DOWN.\n"));
15992 } else
15993 cfg->evt_handler[e->etype](cfg, wdev_to_cfgdev(wdev),
15994 &e->emsg, e->edata);
15995 } else {
15996 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
15997 }
15998 mutex_unlock(&cfg->if_sync);
15999 fail:
16000 wl_put_event(e);
16001 }
16002 DHD_EVENT_WAKE_UNLOCK(cfg->pub);
16003 }
16004
16005 void
16006 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
16007 {
16008 u32 event_type = ntoh32(e->event_type);
16009 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
16010 struct net_info *netinfo;
16011
16012 WL_DBG(("event_type (%d): %s\n", event_type, bcmevent_get_name(event_type)));
16013
16014 if ((cfg == NULL) || (cfg->p2p_supported && cfg->p2p == NULL)) {
16015 WL_ERR(("Stale event ignored\n"));
16016 return;
16017 }
16018
16019 if (cfg->event_workq == NULL) {
16020 WL_ERR(("Event handler is not created\n"));
16021 return;
16022 }
16023
16024 if (wl_get_p2p_status(cfg, IF_CHANGING) || wl_get_p2p_status(cfg, IF_ADDING)) {
16025 WL_ERR(("during IF change, ignore event %d\n", event_type));
16026 return;
16027 }
16028
16029 netinfo = wl_get_netinfo_by_bssidx(cfg, e->bsscfgidx);
16030 if (!netinfo) {
16031 /* Since the netinfo entry is not there, the netdev entry is not
16032 * created via cfg80211 interface. so the event is not of interest
16033 * to the cfg80211 layer.
16034 */
16035 WL_ERR(("ignore event %d, not interested\n", event_type));
16036 return;
16037 }
16038
16039 if (event_type == WLC_E_PFN_NET_FOUND) {
16040 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
16041 }
16042 else if (event_type == WLC_E_PFN_NET_LOST) {
16043 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
16044 }
16045
16046 if (likely(!wl_enq_event(cfg, ndev, event_type, e, data))) {
16047 queue_work(cfg->event_workq, &cfg->event_work);
16048 }
16049 }
16050
16051 static void wl_init_eq(struct bcm_cfg80211 *cfg)
16052 {
16053 wl_init_eq_lock(cfg);
16054 INIT_LIST_HEAD(&cfg->eq_list);
16055 }
16056
16057 static void wl_flush_eq(struct bcm_cfg80211 *cfg)
16058 {
16059 struct wl_event_q *e;
16060 unsigned long flags;
16061
16062 flags = wl_lock_eq(cfg);
16063 while (!list_empty_careful(&cfg->eq_list)) {
16064 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
16065 list_del(&e->eq_list);
16066 kfree(e);
16067 }
16068 wl_unlock_eq(cfg, flags);
16069 }
16070
16071 /*
16072 * retrieve first queued event from head
16073 */
16074
16075 static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg)
16076 {
16077 struct wl_event_q *e = NULL;
16078 unsigned long flags;
16079
16080 flags = wl_lock_eq(cfg);
16081 if (likely(!list_empty(&cfg->eq_list))) {
16082 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
16083 list_del(&e->eq_list);
16084 }
16085 wl_unlock_eq(cfg, flags);
16086
16087 return e;
16088 }
16089
16090 /*
16091 * push event to tail of the queue
16092 */
16093
16094 static s32
16095 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 event,
16096 const wl_event_msg_t *msg, void *data)
16097 {
16098 struct wl_event_q *e;
16099 s32 err = 0;
16100 uint32 evtq_size;
16101 uint32 data_len;
16102 unsigned long flags;
16103 gfp_t aflags;
16104
16105 data_len = 0;
16106 if (data)
16107 data_len = ntoh32(msg->datalen);
16108 evtq_size = sizeof(struct wl_event_q) + data_len;
16109 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
16110 e = kzalloc(evtq_size, aflags);
16111 if (unlikely(!e)) {
16112 WL_ERR(("event alloc failed\n"));
16113 return -ENOMEM;
16114 }
16115 e->etype = event;
16116 memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
16117 if (data)
16118 memcpy(e->edata, data, data_len);
16119 flags = wl_lock_eq(cfg);
16120 list_add_tail(&e->eq_list, &cfg->eq_list);
16121 wl_unlock_eq(cfg, flags);
16122
16123 return err;
16124 }
16125
16126 static void wl_put_event(struct wl_event_q *e)
16127 {
16128 kfree(e);
16129 }
16130
16131 static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype)
16132 {
16133 s32 infra = 0;
16134 s32 err = 0;
16135 s32 mode = 0;
16136 switch (iftype) {
16137 case NL80211_IFTYPE_MONITOR:
16138 case NL80211_IFTYPE_WDS:
16139 WL_ERR(("type (%d) : currently we do not support this mode\n",
16140 iftype));
16141 err = -EINVAL;
16142 return err;
16143 case NL80211_IFTYPE_ADHOC:
16144 mode = WL_MODE_IBSS;
16145 break;
16146 case NL80211_IFTYPE_STATION:
16147 case NL80211_IFTYPE_P2P_CLIENT:
16148 mode = WL_MODE_BSS;
16149 infra = 1;
16150 break;
16151 #ifdef WLMESH
16152 case NL80211_IFTYPE_MESH_POINT:
16153 mode = WL_MODE_MESH;
16154 infra = WL_BSSTYPE_MESH;
16155 break;
16156 #endif /* WLMESH */
16157 case NL80211_IFTYPE_AP:
16158 case NL80211_IFTYPE_P2P_GO:
16159 mode = WL_MODE_AP;
16160 infra = 1;
16161 break;
16162 default:
16163 err = -EINVAL;
16164 WL_ERR(("invalid type (%d)\n", iftype));
16165 return err;
16166 }
16167 infra = htod32(infra);
16168 err = wldev_ioctl_set(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
16169 if (unlikely(err)) {
16170 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
16171 return err;
16172 }
16173
16174 wl_set_mode_by_netdev(cfg, ndev, mode);
16175
16176 return 0;
16177 }
16178
16179 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
16180 {
16181 if (!ev || (event > WLC_E_LAST))
16182 return;
16183
16184 if (ev->num < MAX_EVENT_BUF_NUM) {
16185 ev->event[ev->num].type = event;
16186 ev->event[ev->num].set = set;
16187 ev->num++;
16188 } else {
16189 WL_ERR(("evenbuffer doesn't support > %u events. Update"
16190 " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
16191 ASSERT(0);
16192 }
16193 }
16194
16195 s32 wl_cfg80211_apply_eventbuffer(
16196 struct net_device *ndev,
16197 struct bcm_cfg80211 *cfg,
16198 wl_eventmsg_buf_t *ev)
16199 {
16200 char eventmask[WL_EVENTING_MASK_LEN];
16201 int i, ret = 0;
16202 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
16203
16204 if (!ev || (!ev->num))
16205 return -EINVAL;
16206
16207 mutex_lock(&cfg->event_sync);
16208
16209 /* Read event_msgs mask */
16210 ret = wldev_iovar_getbuf(ndev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL);
16211 if (unlikely(ret)) {
16212 WL_ERR(("Get event_msgs error (%d)\n", ret));
16213 goto exit;
16214 }
16215 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
16216
16217 /* apply the set bits */
16218 for (i = 0; i < ev->num; i++) {
16219 if (ev->event[i].set)
16220 setbit(eventmask, ev->event[i].type);
16221 else
16222 clrbit(eventmask, ev->event[i].type);
16223 }
16224
16225 /* Write updated Event mask */
16226 ret = wldev_iovar_setbuf(ndev, "event_msgs", eventmask, sizeof(eventmask), iovbuf,
16227 sizeof(iovbuf), NULL);
16228 if (unlikely(ret)) {
16229 WL_ERR(("Set event_msgs error (%d)\n", ret));
16230 }
16231
16232 exit:
16233 mutex_unlock(&cfg->event_sync);
16234 return ret;
16235 }
16236
16237 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
16238 {
16239 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
16240 s8 eventmask[WL_EVENTING_MASK_LEN];
16241 s32 err = 0;
16242 struct bcm_cfg80211 *cfg;
16243
16244 if (!ndev)
16245 return -ENODEV;
16246
16247 cfg = wl_get_cfg(ndev);
16248 if (!cfg)
16249 return -ENODEV;
16250
16251 mutex_lock(&cfg->event_sync);
16252
16253 /* Setup event_msgs */
16254 err = wldev_iovar_getbuf(ndev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL);
16255 if (unlikely(err)) {
16256 WL_ERR(("Get event_msgs error (%d)\n", err));
16257 goto eventmsg_out;
16258 }
16259 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
16260 if (add) {
16261 setbit(eventmask, event);
16262 } else {
16263 clrbit(eventmask, event);
16264 }
16265 err = wldev_iovar_setbuf(ndev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
16266 sizeof(iovbuf), NULL);
16267 if (unlikely(err)) {
16268 WL_ERR(("Set event_msgs error (%d)\n", err));
16269 goto eventmsg_out;
16270 }
16271
16272 eventmsg_out:
16273 mutex_unlock(&cfg->event_sync);
16274 return err;
16275 }
16276
16277 static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap)
16278 {
16279 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
16280 struct ieee80211_channel *band_chan_arr = NULL;
16281 wl_uint32_list_t *list;
16282 u32 i, j, index, n_2g, n_5g, band, channel, array_size;
16283 u32 *n_cnt = NULL;
16284 chanspec_t c = 0;
16285 s32 err = BCME_OK;
16286 bool update;
16287 bool ht40_allowed;
16288 u8 *pbuf = NULL;
16289 bool dfs_radar_disabled = FALSE;
16290
16291 #define LOCAL_BUF_LEN 1024
16292 pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
16293
16294 if (pbuf == NULL) {
16295 WL_ERR(("failed to allocate local buf\n"));
16296 return -ENOMEM;
16297 }
16298
16299 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
16300 0, pbuf, LOCAL_BUF_LEN, 0, &cfg->ioctl_buf_sync);
16301 if (err != 0) {
16302 WL_ERR(("get chanspecs failed with %d\n", err));
16303 kfree(pbuf);
16304 return err;
16305 }
16306 #undef LOCAL_BUF_LEN
16307
16308 list = (wl_uint32_list_t *)(void *)pbuf;
16309 band = array_size = n_2g = n_5g = 0;
16310 for (i = 0; i < dtoh32(list->count); i++) {
16311 index = 0;
16312 update = false;
16313 ht40_allowed = false;
16314 c = (chanspec_t)dtoh32(list->element[i]);
16315 c = wl_chspec_driver_to_host(c);
16316 channel = wf_chspec_ctlchan(c);
16317
16318 if (!CHSPEC_IS40(c) && ! CHSPEC_IS20(c)) {
16319 WL_DBG(("HT80/160/80p80 center channel : %d\n", channel));
16320 continue;
16321 }
16322 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
16323 (channel <= CH_MAX_2G_CHANNEL)) {
16324 band_chan_arr = __wl_2ghz_channels;
16325 array_size = ARRAYSIZE(__wl_2ghz_channels);
16326 n_cnt = &n_2g;
16327 band = IEEE80211_BAND_2GHZ;
16328 ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false;
16329 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
16330 band_chan_arr = __wl_5ghz_a_channels;
16331 array_size = ARRAYSIZE(__wl_5ghz_a_channels);
16332 n_cnt = &n_5g;
16333 band = IEEE80211_BAND_5GHZ;
16334 ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
16335 } else {
16336 WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
16337 continue;
16338 }
16339 if (!ht40_allowed && CHSPEC_IS40(c))
16340 continue;
16341 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
16342 if (band_chan_arr[j].hw_value == channel) {
16343 update = true;
16344 break;
16345 }
16346 }
16347 if (update)
16348 index = j;
16349 else
16350 index = *n_cnt;
16351 if (!dhd_conf_match_channel(cfg->pub, channel))
16352 continue;
16353 if (index < array_size) {
16354 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
16355 band_chan_arr[index].center_freq =
16356 ieee80211_channel_to_frequency(channel);
16357 #else
16358 band_chan_arr[index].center_freq =
16359 ieee80211_channel_to_frequency(channel, band);
16360 #endif
16361 band_chan_arr[index].hw_value = channel;
16362 band_chan_arr[index].beacon_found = false;
16363
16364 if (CHSPEC_IS40(c) && ht40_allowed) {
16365 /* assuming the order is HT20, HT40 Upper,
16366 * HT40 lower from chanspecs
16367 */
16368 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
16369 if (CHSPEC_SB_UPPER(c)) {
16370 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
16371 band_chan_arr[index].flags &=
16372 ~IEEE80211_CHAN_NO_HT40;
16373 band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
16374 } else {
16375 /* It should be one of
16376 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
16377 */
16378 band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
16379 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
16380 band_chan_arr[index].flags |=
16381 IEEE80211_CHAN_NO_HT40MINUS;
16382 }
16383 } else {
16384 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
16385 if (!dfs_radar_disabled) {
16386 if (band == IEEE80211_BAND_2GHZ)
16387 channel |= WL_CHANSPEC_BAND_2G;
16388 else
16389 channel |= WL_CHANSPEC_BAND_5G;
16390 channel |= WL_CHANSPEC_BW_20;
16391 channel = wl_chspec_host_to_driver(channel);
16392 err = wldev_iovar_getint(dev, "per_chan_info", &channel);
16393 if (!err) {
16394 if (channel & WL_CHAN_RADAR) {
16395 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
16396 band_chan_arr[index].flags |=
16397 (IEEE80211_CHAN_RADAR
16398 | IEEE80211_CHAN_NO_IBSS);
16399 #else
16400 band_chan_arr[index].flags |=
16401 IEEE80211_CHAN_RADAR;
16402 #endif
16403 }
16404
16405 if (channel & WL_CHAN_PASSIVE)
16406 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
16407 band_chan_arr[index].flags |=
16408 IEEE80211_CHAN_PASSIVE_SCAN;
16409 #else
16410 band_chan_arr[index].flags |=
16411 IEEE80211_CHAN_NO_IR;
16412 #endif
16413 } else if (err == BCME_UNSUPPORTED) {
16414 dfs_radar_disabled = TRUE;
16415 WL_ERR(("does not support per_chan_info\n"));
16416 }
16417 }
16418 }
16419 if (!update)
16420 (*n_cnt)++;
16421 }
16422
16423 }
16424 __wl_band_2ghz.n_channels = n_2g;
16425 __wl_band_5ghz_a.n_channels = n_5g;
16426 kfree(pbuf);
16427 return err;
16428 }
16429
16430 static s32 __wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
16431 {
16432 struct wiphy *wiphy;
16433 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
16434 u32 bandlist[3];
16435 u32 nband = 0;
16436 u32 i = 0;
16437 s32 err = 0;
16438 s32 index = 0;
16439 s32 nmode = 0;
16440 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16441 u32 j = 0;
16442 s32 vhtmode = 0;
16443 s32 txstreams = 0;
16444 s32 rxstreams = 0;
16445 s32 ldpc_cap = 0;
16446 s32 stbc_rx = 0;
16447 s32 stbc_tx = 0;
16448 s32 txbf_bfe_cap = 0;
16449 s32 txbf_bfr_cap = 0;
16450 #endif
16451 s32 bw_cap = 0;
16452 s32 cur_band = -1;
16453 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
16454
16455 memset(bandlist, 0, sizeof(bandlist));
16456 err = wldev_ioctl_get(dev, WLC_GET_BANDLIST, bandlist,
16457 sizeof(bandlist));
16458 if (unlikely(err)) {
16459 WL_ERR(("error read bandlist (%d)\n", err));
16460 return err;
16461 }
16462 err = wldev_ioctl_get(dev, WLC_GET_BAND, &cur_band,
16463 sizeof(s32));
16464 if (unlikely(err)) {
16465 WL_ERR(("error (%d)\n", err));
16466 return err;
16467 }
16468
16469 err = wldev_iovar_getint(dev, "nmode", &nmode);
16470 if (unlikely(err)) {
16471 WL_ERR(("error reading nmode (%d)\n", err));
16472 }
16473
16474 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16475 err = wldev_iovar_getint(dev, "vhtmode", &vhtmode);
16476 if (unlikely(err)) {
16477 WL_ERR(("error reading vhtmode (%d)\n", err));
16478 }
16479
16480 if (vhtmode) {
16481 err = wldev_iovar_getint(dev, "txstreams", &txstreams);
16482 if (unlikely(err)) {
16483 WL_ERR(("error reading txstreams (%d)\n", err));
16484 }
16485
16486 err = wldev_iovar_getint(dev, "rxstreams", &rxstreams);
16487 if (unlikely(err)) {
16488 WL_ERR(("error reading rxstreams (%d)\n", err));
16489 }
16490
16491 err = wldev_iovar_getint(dev, "ldpc_cap", &ldpc_cap);
16492 if (unlikely(err)) {
16493 WL_ERR(("error reading ldpc_cap (%d)\n", err));
16494 }
16495
16496 err = wldev_iovar_getint(dev, "stbc_rx", &stbc_rx);
16497 if (unlikely(err)) {
16498 WL_ERR(("error reading stbc_rx (%d)\n", err));
16499 }
16500
16501 err = wldev_iovar_getint(dev, "stbc_tx", &stbc_tx);
16502 if (unlikely(err)) {
16503 WL_ERR(("error reading stbc_tx (%d)\n", err));
16504 }
16505
16506 err = wldev_iovar_getint(dev, "txbf_bfe_cap", &txbf_bfe_cap);
16507 if (unlikely(err)) {
16508 WL_ERR(("error reading txbf_bfe_cap (%d)\n", err));
16509 }
16510
16511 err = wldev_iovar_getint(dev, "txbf_bfr_cap", &txbf_bfr_cap);
16512 if (unlikely(err)) {
16513 WL_ERR(("error reading txbf_bfr_cap (%d)\n", err));
16514 }
16515 }
16516 #endif
16517
16518 /* For nmode and vhtmode check bw cap */
16519 if (nmode ||
16520 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16521 vhtmode ||
16522 #endif
16523 0) {
16524 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
16525 if (unlikely(err)) {
16526 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
16527 }
16528 }
16529
16530 err = wl_construct_reginfo(cfg, bw_cap);
16531 if (err) {
16532 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
16533 if (err != BCME_UNSUPPORTED)
16534 return err;
16535 }
16536
16537 wiphy = bcmcfg_to_wiphy(cfg);
16538 nband = bandlist[0];
16539
16540 for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
16541 index = -1;
16542 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
16543 bands[IEEE80211_BAND_5GHZ] =
16544 &__wl_band_5ghz_a;
16545 index = IEEE80211_BAND_5GHZ;
16546 if (nmode && (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G))
16547 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
16548
16549 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16550 /* VHT capabilities. */
16551 if (vhtmode) {
16552 /* Supported */
16553 bands[index]->vht_cap.vht_supported = TRUE;
16554
16555 for (j = 1; j <= VHT_CAP_MCS_MAP_NSS_MAX; j++) {
16556 /* TX stream rates. */
16557 if (j <= txstreams) {
16558 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
16559 bands[index]->vht_cap.vht_mcs.tx_mcs_map);
16560 } else {
16561 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
16562 bands[index]->vht_cap.vht_mcs.tx_mcs_map);
16563 }
16564
16565 /* RX stream rates. */
16566 if (j <= rxstreams) {
16567 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
16568 bands[index]->vht_cap.vht_mcs.rx_mcs_map);
16569 } else {
16570 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
16571 bands[index]->vht_cap.vht_mcs.rx_mcs_map);
16572 }
16573 }
16574
16575
16576 /* Capabilities */
16577 /* 80 MHz is mandatory */
16578 bands[index]->vht_cap.cap |=
16579 IEEE80211_VHT_CAP_SHORT_GI_80;
16580
16581 if (WL_BW_CAP_160MHZ(bw_cap)) {
16582 bands[index]->vht_cap.cap |=
16583 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
16584 bands[index]->vht_cap.cap |=
16585 IEEE80211_VHT_CAP_SHORT_GI_160;
16586 }
16587
16588 bands[index]->vht_cap.cap |=
16589 IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
16590
16591 if (ldpc_cap)
16592 bands[index]->vht_cap.cap |=
16593 IEEE80211_VHT_CAP_RXLDPC;
16594
16595 if (stbc_tx)
16596 bands[index]->vht_cap.cap |=
16597 IEEE80211_VHT_CAP_TXSTBC;
16598
16599 if (stbc_rx)
16600 bands[index]->vht_cap.cap |=
16601 (stbc_rx << VHT_CAP_INFO_RX_STBC_SHIFT);
16602
16603 if (txbf_bfe_cap)
16604 bands[index]->vht_cap.cap |=
16605 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
16606
16607 if (txbf_bfr_cap) {
16608 bands[index]->vht_cap.cap |=
16609 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
16610 }
16611
16612 if (txbf_bfe_cap || txbf_bfr_cap) {
16613 bands[index]->vht_cap.cap |=
16614 (2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT);
16615 bands[index]->vht_cap.cap |=
16616 ((txstreams - 1) <<
16617 VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT);
16618 bands[index]->vht_cap.cap |=
16619 IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
16620 }
16621
16622 /* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
16623 bands[index]->vht_cap.cap |=
16624 (7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT);
16625 WL_INFORM(("%s band[%d] vht_enab=%d vht_cap=%08x "
16626 "vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
16627 __FUNCTION__, index,
16628 bands[index]->vht_cap.vht_supported,
16629 bands[index]->vht_cap.cap,
16630 bands[index]->vht_cap.vht_mcs.rx_mcs_map,
16631 bands[index]->vht_cap.vht_mcs.tx_mcs_map));
16632 }
16633 #endif
16634 }
16635 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
16636 bands[IEEE80211_BAND_2GHZ] =
16637 &__wl_band_2ghz;
16638 index = IEEE80211_BAND_2GHZ;
16639 if (bw_cap == WLC_N_BW_40ALL)
16640 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
16641 }
16642
16643 if ((index >= 0) && nmode) {
16644 bands[index]->ht_cap.cap |=
16645 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
16646 bands[index]->ht_cap.ht_supported = TRUE;
16647 bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
16648 bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
16649 /* An HT shall support all EQM rates for one spatial stream */
16650 bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
16651 }
16652
16653 }
16654
16655 wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
16656 wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
16657
16658 /* check if any bands populated otherwise makes 2Ghz as default */
16659 if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
16660 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
16661 /* Setup 2Ghz band as default */
16662 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
16663 }
16664
16665 if (notify)
16666 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
16667
16668 return 0;
16669 }
16670
16671 s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
16672 {
16673 s32 err;
16674
16675 mutex_lock(&cfg->usr_sync);
16676 err = __wl_update_wiphybands(cfg, notify);
16677 mutex_unlock(&cfg->usr_sync);
16678
16679 return err;
16680 }
16681
16682 static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg)
16683 {
16684 s32 err = 0;
16685 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
16686 struct wireless_dev *wdev = ndev->ieee80211_ptr;
16687 #ifdef WBTEXT
16688 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
16689 #endif /* WBTEXT */
16690 #ifdef WLTDLS
16691 u32 tdls;
16692 #endif /* WLTDLS */
16693
16694 WL_DBG(("In\n"));
16695
16696 err = wl_create_event_handler(cfg);
16697 if (err) {
16698 WL_ERR(("wl_create_event_handler failed\n"));
16699 return err;
16700 }
16701 wl_init_event_handler(cfg);
16702
16703 err = dhd_config_dongle(cfg);
16704 if (unlikely(err))
16705 return err;
16706
16707 err = wl_config_ifmode(cfg, ndev, wdev->iftype);
16708 if (unlikely(err && err != -EINPROGRESS)) {
16709 WL_ERR(("wl_config_ifmode failed\n"));
16710 if (err == -1) {
16711 WL_ERR(("return error %d\n", err));
16712 return err;
16713 }
16714 }
16715
16716 err = wl_init_scan(cfg);
16717 if (err) {
16718 WL_ERR(("wl_init_scan failed\n"));
16719 return err;
16720 }
16721 err = __wl_update_wiphybands(cfg, true);
16722 if (unlikely(err)) {
16723 WL_ERR(("wl_update_wiphybands failed\n"));
16724 if (err == -1) {
16725 WL_ERR(("return error %d\n", err));
16726 return err;
16727 }
16728 }
16729 if (!dhd_download_fw_on_driverload) {
16730 err = wl_create_event_handler(cfg);
16731 if (err) {
16732 WL_ERR(("wl_create_event_handler failed\n"));
16733 return err;
16734 }
16735 wl_init_event_handler(cfg);
16736 }
16737 err = wl_init_scan(cfg);
16738 if (err) {
16739 WL_ERR(("wl_init_scan failed\n"));
16740 return err;
16741 }
16742 #ifdef DHD_LOSSLESS_ROAMING
16743 if (timer_pending(&cfg->roam_timeout)) {
16744 del_timer_sync(&cfg->roam_timeout);
16745 }
16746 #endif /* DHD_LOSSLESS_ROAMING */
16747
16748 err = dhd_monitor_init(cfg->pub);
16749
16750 #ifdef WBTEXT
16751 /* when wifi up, set roam_prof to default value */
16752 if (dhd->wbtext_support) {
16753 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
16754 wl_cfg80211_wbtext_set_default(ndev);
16755 wl_cfg80211_wbtext_clear_bssid_list(cfg);
16756 }
16757 }
16758 #endif /* WBTEXT */
16759 #ifdef WLTDLS
16760 if (wldev_iovar_getint(ndev, "tdls_enable", &tdls) == 0) {
16761 WL_DBG(("TDLS supported in fw\n"));
16762 cfg->tdls_supported = true;
16763 }
16764 #endif /* WLTDLS */
16765 INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
16766 wl_set_drv_status(cfg, READY, ndev);
16767 return err;
16768 }
16769
16770 static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
16771 {
16772 s32 err = 0;
16773 unsigned long flags;
16774 struct net_info *iter, *next;
16775 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
16776 #if defined(WL_CFG80211) && (defined(WL_ENABLE_P2P_IF) || \
16777 defined(WL_NEW_CFG_PRIVCMD_SUPPORT)) && !defined(PLATFORM_SLP)
16778 struct net_device *p2p_net = cfg->p2p_net;
16779 #endif
16780 #ifdef PROP_TXSTATUS_VSDB
16781 #if defined(BCMSDIO) || defined(BCMDBUS)
16782 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
16783 #endif /* BCMSDIO || BCMDBUS */
16784 #endif /* PROP_TXSTATUS_VSDB */
16785 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
16786 struct cfg80211_scan_info info;
16787 #endif
16788
16789 WL_DBG(("In\n"));
16790
16791 /* Check if cfg80211 interface is already down */
16792 if (!wl_get_drv_status(cfg, READY, ndev)) {
16793 WL_DBG(("cfg80211 interface is already down\n"));
16794 return err; /* it is even not ready */
16795 }
16796
16797 #ifdef WLTDLS
16798 cfg->tdls_supported = false;
16799 #endif /* WLTDLS */
16800
16801 /* Delete pm_enable_work */
16802 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
16803
16804 /* clear all the security setting on primary Interface */
16805 wl_cfg80211_clear_security(cfg);
16806
16807
16808 if (cfg->p2p_supported) {
16809 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
16810 #ifdef PROP_TXSTATUS_VSDB
16811 #if defined(BCMSDIO) || defined(BCMDBUS)
16812 if (wl_cfgp2p_vif_created(cfg)) {
16813 bool enabled = false;
16814 dhd_wlfc_get_enable(dhd, &enabled);
16815 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
16816 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
16817 dhd_wlfc_deinit(dhd);
16818 cfg->wlfc_on = false;
16819 }
16820 }
16821 #endif /* BCMSDIO || BCMDBUS */
16822 #endif /* PROP_TXSTATUS_VSDB */
16823 }
16824
16825
16826 /* clean up any left over interfaces */
16827 wl_cfg80211_cleanup_virtual_ifaces(ndev, false);
16828
16829 /* If primary BSS is operational (for e.g SoftAP), bring it down */
16830 if (wl_cfg80211_bss_isup(ndev, 0)) {
16831 if (wl_cfg80211_bss_up(cfg, ndev, 0, 0) < 0)
16832 WL_ERR(("BSS down failed \n"));
16833 }
16834
16835 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16836 4 && __GNUC_MINOR__ >= 6))
16837 _Pragma("GCC diagnostic push")
16838 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16839 #endif
16840 for_each_ndev(cfg, iter, next) {
16841 if (iter->ndev) /* p2p discovery iface is null */
16842 wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
16843 }
16844 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16845 4 && __GNUC_MINOR__ >= 6))
16846 _Pragma("GCC diagnostic pop")
16847 #endif
16848
16849 #ifdef P2P_LISTEN_OFFLOADING
16850 wl_cfg80211_p2plo_deinit(cfg);
16851 #endif /* P2P_LISTEN_OFFLOADING */
16852
16853 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
16854 if (cfg->scan_request) {
16855 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
16856 info.aborted = true;
16857 cfg80211_scan_done(cfg->scan_request, &info);
16858 #else
16859 cfg80211_scan_done(cfg->scan_request, true);
16860 #endif
16861 cfg->scan_request = NULL;
16862 }
16863 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
16864 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16865 4 && __GNUC_MINOR__ >= 6))
16866 _Pragma("GCC diagnostic push")
16867 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16868 #endif
16869 for_each_ndev(cfg, iter, next) {
16870 /* p2p discovery iface ndev ptr could be null */
16871 if (iter->ndev == NULL)
16872 continue;
16873 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
16874 if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
16875 CFG80211_DISCONNECTED(iter->ndev, 0, NULL, 0, false, GFP_KERNEL);
16876 }
16877 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) */
16878 wl_clr_drv_status(cfg, READY, iter->ndev);
16879 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
16880 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
16881 wl_clr_drv_status(cfg, CONNECTING, iter->ndev);
16882 wl_clr_drv_status(cfg, CONNECTED, iter->ndev);
16883 wl_clr_drv_status(cfg, DISCONNECTING, iter->ndev);
16884 wl_clr_drv_status(cfg, AP_CREATED, iter->ndev);
16885 wl_clr_drv_status(cfg, AP_CREATING, iter->ndev);
16886 }
16887 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16888 4 && __GNUC_MINOR__ >= 6))
16889 _Pragma("GCC diagnostic pop")
16890 #endif
16891 bcmcfg_to_prmry_ndev(cfg)->ieee80211_ptr->iftype =
16892 NL80211_IFTYPE_STATION;
16893 #if defined(WL_CFG80211) && (defined(WL_ENABLE_P2P_IF) || \
16894 defined(WL_NEW_CFG_PRIVCMD_SUPPORT)) && !defined(PLATFORM_SLP)
16895 if (p2p_net)
16896 dev_close(p2p_net);
16897 #endif
16898
16899 /* Avoid deadlock from wl_cfg80211_down */
16900 if (!dhd_download_fw_on_driverload) {
16901 mutex_unlock(&cfg->usr_sync);
16902 wl_destroy_event_handler(cfg);
16903 mutex_lock(&cfg->usr_sync);
16904 }
16905
16906 wl_flush_eq(cfg);
16907
16908 if (cfg->link_up) { //army fix wifi stop call trace issue
16909 CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
16910 wl_link_down(cfg);
16911 }
16912 if (cfg->p2p_supported) {
16913 if (timer_pending(&cfg->p2p->listen_timer))
16914 del_timer_sync(&cfg->p2p->listen_timer);
16915 wl_cfgp2p_down(cfg);
16916 }
16917
16918 if (timer_pending(&cfg->scan_timeout)) {
16919 del_timer_sync(&cfg->scan_timeout);
16920 }
16921
16922 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
16923
16924 dhd_monitor_uninit();
16925 #ifdef WLAIBSS_MCHAN
16926 bcm_cfg80211_del_ibss_if(cfg->wdev->wiphy, cfg->ibss_cfgdev);
16927 #endif /* WLAIBSS_MCHAN */
16928
16929
16930 #ifdef WL11U
16931 /* Clear interworking element. */
16932 if (cfg->wl11u) {
16933 cfg->wl11u = FALSE;
16934 }
16935 #endif /* WL11U */
16936
16937 #ifdef CUSTOMER_HW4_DEBUG
16938 if (wl_scan_timeout_dbg_enabled) {
16939 wl_scan_timeout_dbg_clear();
16940 }
16941 #endif /* CUSTOMER_HW4_DEBUG */
16942
16943 cfg->disable_roam_event = false;
16944
16945 DNGL_FUNC(dhd_cfg80211_down, (cfg));
16946
16947 #ifdef DHD_IFDEBUG
16948 /* Printout all netinfo entries */
16949 wl_probe_wdev_all(cfg);
16950 #endif /* DHD_IFDEBUG */
16951
16952 return err;
16953 }
16954
16955 s32 wl_cfg80211_up(struct net_device *net)
16956 {
16957 struct bcm_cfg80211 *cfg;
16958 s32 err = 0;
16959 int val = 1;
16960 dhd_pub_t *dhd;
16961 #ifdef DISABLE_PM_BCNRX
16962 s32 interr = 0;
16963 uint param = 0;
16964 s8 iovbuf[WLC_IOCTL_SMLEN];
16965 #endif /* DISABLE_PM_BCNRX */
16966
16967 WL_DBG(("In\n"));
16968 cfg = wl_get_cfg(net);
16969
16970 if ((err = wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg), WLC_GET_VERSION, &val,
16971 sizeof(int)) < 0)) {
16972 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
16973 return err;
16974 }
16975 val = dtoh32(val);
16976 if (val != WLC_IOCTL_VERSION && val != 1) {
16977 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
16978 val, WLC_IOCTL_VERSION));
16979 return BCME_VERSION;
16980 }
16981 ioctl_version = val;
16982 WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
16983
16984 mutex_lock(&cfg->usr_sync);
16985 dhd = (dhd_pub_t *)(cfg->pub);
16986 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
16987 err = wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg));
16988 if (unlikely(err)) {
16989 mutex_unlock(&cfg->usr_sync);
16990 return err;
16991 }
16992 }
16993 #ifdef WLMESH
16994 cfg->wdev->wiphy->features |= NL80211_FEATURE_USERSPACE_MPM;
16995 #endif /* WLMESH */
16996
16997 err = __wl_cfg80211_up(cfg);
16998 if (unlikely(err))
16999 WL_ERR(("__wl_cfg80211_up failed\n"));
17000
17001
17002
17003 /* IOVAR configurations with 'up' condition */
17004 #ifdef DISABLE_PM_BCNRX
17005 interr = wldev_iovar_setbuf(bcmcfg_to_prmry_ndev(cfg), "pm_bcnrx", (char *)&param,
17006 sizeof(param), iovbuf, sizeof(iovbuf), NULL);
17007 if (unlikely(interr)) {
17008 WL_ERR(("Set pm_bcnrx returned (%d)\n", interr));
17009 }
17010 #endif /* DISABLE_PM_BCNRX */
17011
17012 mutex_unlock(&cfg->usr_sync);
17013
17014 #ifdef WLAIBSS_MCHAN
17015 bcm_cfg80211_add_ibss_if(cfg->wdev->wiphy, IBSS_IF_NAME);
17016 #endif /* WLAIBSS_MCHAN */
17017
17018 #ifdef DUAL_STA_STATIC_IF
17019 #ifdef WL_VIRTUAL_APSTA
17020 #error "Both DUAL STA and DUAL_STA_STATIC_IF can't be enabled together"
17021 #endif
17022 /* Static Interface support is currently supported only for STA only builds (without P2P) */
17023 wl_cfg80211_create_iface(cfg->wdev->wiphy, NL80211_IFTYPE_STATION, NULL, "wlan%d");
17024 #endif /* DUAL_STA_STATIC_IF */
17025
17026 return err;
17027 }
17028
17029 /* Private Event to Supplicant with indication that chip hangs */
17030 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
17031 {
17032 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
17033 dhd_pub_t *dhd;
17034 #if defined(SOFTAP_SEND_HANGEVT)
17035 /* specifc mac address used for hang event */
17036 uint8 hang_mac[ETHER_ADDR_LEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
17037 #endif /* SOFTAP_SEND_HANGEVT */
17038 if (!cfg) {
17039 return BCME_ERROR;
17040 }
17041
17042 dhd = (dhd_pub_t *)(cfg->pub);
17043 #if defined(DHD_HANG_SEND_UP_TEST)
17044 if (dhd->req_hang_type) {
17045 WL_ERR(("%s, Clear HANG test request 0x%x\n",
17046 __FUNCTION__, dhd->req_hang_type));
17047 dhd->req_hang_type = 0;
17048 }
17049 #endif /* DHD_HANG_SEND_UP_TEST */
17050 if ((dhd->hang_reason <= HANG_REASON_MASK) || (dhd->hang_reason >= HANG_REASON_MAX)) {
17051 WL_ERR(("%s, Invalid hang reason 0x%x\n",
17052 __FUNCTION__, dhd->hang_reason));
17053 dhd->hang_reason = HANG_REASON_UNKNOWN;
17054 }
17055 #ifdef DHD_USE_EXTENDED_HANG_REASON
17056 if (dhd->hang_reason != 0) {
17057 reason = dhd->hang_reason;
17058 }
17059 #endif /* DHD_USE_EXTENDED_HANG_REASON */
17060 WL_ERR(("In : chip crash eventing, reason=0x%x\n", (uint32)(dhd->hang_reason)));
17061
17062 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
17063 #ifdef SOFTAP_SEND_HANGEVT
17064 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
17065 cfg80211_del_sta(dev, hang_mac, GFP_ATOMIC);
17066 } else
17067 #endif /* SOFTAP_SEND_HANGEVT */
17068 {
17069 CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
17070 }
17071 #if defined(RSSIAVG)
17072 wl_free_rssi_cache(&g_rssi_cache_ctrl);
17073 #endif
17074 #if defined(BSSCACHE)
17075 wl_free_bss_cache(&g_bss_cache_ctrl);
17076 #endif
17077 if (cfg != NULL) {
17078 wl_link_down(cfg);
17079 }
17080 return 0;
17081 }
17082
17083 s32 wl_cfg80211_down(struct net_device *dev)
17084 {
17085 s32 err = 0;
17086 struct bcm_cfg80211 *cfg = NULL;
17087 if (dev == NULL)
17088 return err;
17089
17090 cfg = wl_get_cfg(dev);
17091
17092 WL_DBG(("In\n"));
17093 if (cfg == NULL)
17094 return err;
17095
17096 mutex_lock(&cfg->usr_sync);
17097 #if defined(RSSIAVG)
17098 wl_free_rssi_cache(&g_rssi_cache_ctrl);
17099 #endif
17100 #if defined(BSSCACHE)
17101 wl_free_bss_cache(&g_bss_cache_ctrl);
17102 #endif
17103 err = __wl_cfg80211_down(cfg);
17104 mutex_unlock(&cfg->usr_sync);
17105
17106 return err;
17107 }
17108
17109 static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item)
17110 {
17111 unsigned long flags;
17112 void *rptr = NULL;
17113 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
17114
17115 if (!profile)
17116 return NULL;
17117 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
17118 switch (item) {
17119 case WL_PROF_SEC:
17120 rptr = &profile->sec;
17121 break;
17122 case WL_PROF_ACT:
17123 rptr = &profile->active;
17124 break;
17125 case WL_PROF_BSSID:
17126 rptr = profile->bssid;
17127 break;
17128 case WL_PROF_SSID:
17129 rptr = &profile->ssid;
17130 break;
17131 case WL_PROF_CHAN:
17132 rptr = &profile->channel;
17133 break;
17134 }
17135 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
17136 if (!rptr)
17137 WL_ERR(("invalid item (%d)\n", item));
17138 return rptr;
17139 }
17140
17141 static s32
17142 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
17143 const wl_event_msg_t *e, const void *data, s32 item)
17144 {
17145 s32 err = 0;
17146 const struct wlc_ssid *ssid;
17147 unsigned long flags;
17148 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
17149
17150 if (!profile)
17151 return WL_INVALID;
17152 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
17153 switch (item) {
17154 case WL_PROF_SSID:
17155 ssid = (const wlc_ssid_t *) data;
17156 memset(profile->ssid.SSID, 0,
17157 sizeof(profile->ssid.SSID));
17158 profile->ssid.SSID_len = MIN(ssid->SSID_len, DOT11_MAX_SSID_LEN);
17159 memcpy(profile->ssid.SSID, ssid->SSID, profile->ssid.SSID_len);
17160 break;
17161 case WL_PROF_BSSID:
17162 if (data)
17163 memcpy(profile->bssid, data, ETHER_ADDR_LEN);
17164 else
17165 memset(profile->bssid, 0, ETHER_ADDR_LEN);
17166 break;
17167 case WL_PROF_SEC:
17168 memcpy(&profile->sec, data, sizeof(profile->sec));
17169 break;
17170 case WL_PROF_ACT:
17171 profile->active = *(const bool *)data;
17172 break;
17173 case WL_PROF_BEACONINT:
17174 profile->beacon_interval = *(const u16 *)data;
17175 break;
17176 case WL_PROF_DTIMPERIOD:
17177 profile->dtim_period = *(const u8 *)data;
17178 break;
17179 case WL_PROF_CHAN:
17180 profile->channel = *(const u32*)data;
17181 break;
17182 default:
17183 err = -EOPNOTSUPP;
17184 break;
17185 }
17186 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
17187
17188 if (err == -EOPNOTSUPP)
17189 WL_ERR(("unsupported item (%d)\n", item));
17190
17191 return err;
17192 }
17193
17194 void wl_cfg80211_dbg_level(u32 level)
17195 {
17196 /*
17197 * prohibit to change debug level
17198 * by insmod parameter.
17199 * eventually debug level will be configured
17200 * in compile time by using CONFIG_XXX
17201 */
17202 /* wl_dbg_level = level; */
17203 }
17204
17205 static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev)
17206 {
17207 return wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS;
17208 }
17209
17210 static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg)
17211 {
17212 return cfg->ibss_starter;
17213 }
17214
17215 static void wl_rst_ie(struct bcm_cfg80211 *cfg)
17216 {
17217 struct wl_ie *ie = wl_to_ie(cfg);
17218
17219 ie->offset = 0;
17220 }
17221
17222 static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v)
17223 {
17224 struct wl_ie *ie = wl_to_ie(cfg);
17225 s32 err = 0;
17226
17227 if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
17228 WL_ERR(("ei crosses buffer boundary\n"));
17229 return -ENOSPC;
17230 }
17231 ie->buf[ie->offset] = t;
17232 ie->buf[ie->offset + 1] = l;
17233 memcpy(&ie->buf[ie->offset + 2], v, l);
17234 ie->offset += l + 2;
17235
17236 return err;
17237 }
17238
17239 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
17240 bool roam)
17241 {
17242 u8 *ssidie;
17243 int32 ssid_len = MIN(bi->SSID_len, DOT11_MAX_SSID_LEN);
17244 int32 remaining_ie_buf_len, available_buffer_len;
17245 /* cfg80211_find_ie defined in kernel returning const u8 */
17246 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
17247 4 && __GNUC_MINOR__ >= 6))
17248 _Pragma("GCC diagnostic push")
17249 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
17250 #endif
17251 ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
17252 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
17253 4 && __GNUC_MINOR__ >= 6))
17254 _Pragma("GCC diagnostic pop")
17255 #endif
17256 /* ERROR out if
17257 * 1. No ssid IE is FOUND or
17258 * 2. New ssid length is > what was allocated for existing ssid (as
17259 * we do not want to overwrite the rest of the IEs) or
17260 * 3. If in case of erroneous buffer input where ssid length doesnt match the space
17261 * allocated to it.
17262 */
17263 if (!ssidie) {
17264 return;
17265 }
17266 available_buffer_len = ((int)(*ie_size)) - (ssidie + 2 - ie_stream);
17267 remaining_ie_buf_len = available_buffer_len - (int)ssidie[1];
17268 if ((ssid_len > ssidie[1]) ||
17269 (ssidie[1] > available_buffer_len)) {
17270 return;
17271 }
17272
17273
17274 if (ssidie[1] != ssid_len) {
17275 if (ssidie[1]) {
17276 WL_ERR(("%s: Wrong SSID len: %d != %d\n",
17277 __FUNCTION__, ssidie[1], bi->SSID_len));
17278 }
17279 if (roam) {
17280 WL_ERR(("Changing the SSID Info.\n"));
17281 memmove(ssidie + ssid_len + 2,
17282 (ssidie + 2) + ssidie[1],
17283 remaining_ie_buf_len);
17284 memcpy(ssidie + 2, bi->SSID, ssid_len);
17285 *ie_size = *ie_size + ssid_len - ssidie[1];
17286 ssidie[1] = ssid_len;
17287 }
17288 return;
17289 }
17290 if (*(ssidie + 2) == '\0')
17291 memcpy(ssidie + 2, bi->SSID, ssid_len);
17292 return;
17293 }
17294
17295 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size)
17296 {
17297 struct wl_ie *ie = wl_to_ie(cfg);
17298 s32 err = 0;
17299
17300 if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
17301 WL_ERR(("ei_stream crosses buffer boundary\n"));
17302 return -ENOSPC;
17303 }
17304 memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
17305 ie->offset += ie_size;
17306
17307 return err;
17308 }
17309
17310 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size)
17311 {
17312 struct wl_ie *ie = wl_to_ie(cfg);
17313 s32 err = 0;
17314
17315 if (unlikely(ie->offset > dst_size)) {
17316 WL_ERR(("dst_size is not enough\n"));
17317 return -ENOSPC;
17318 }
17319 memcpy(dst, &ie->buf[0], ie->offset);
17320
17321 return err;
17322 }
17323
17324 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg)
17325 {
17326 struct wl_ie *ie = wl_to_ie(cfg);
17327
17328 return ie->offset;
17329 }
17330
17331 static void wl_link_up(struct bcm_cfg80211 *cfg)
17332 {
17333 cfg->link_up = true;
17334 }
17335
17336 static void wl_link_down(struct bcm_cfg80211 *cfg)
17337 {
17338 struct wl_connect_info *conn_info = wl_to_conn(cfg);
17339
17340 WL_DBG(("In\n"));
17341 cfg->link_up = false;
17342 if (conn_info) {
17343 conn_info->req_ie_len = 0;
17344 conn_info->resp_ie_len = 0;
17345 }
17346 }
17347
17348 static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg)
17349 {
17350 unsigned long flags;
17351
17352 spin_lock_irqsave(&cfg->eq_lock, flags);
17353 return flags;
17354 }
17355
17356 static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags)
17357 {
17358 spin_unlock_irqrestore(&cfg->eq_lock, flags);
17359 }
17360
17361 static void wl_init_eq_lock(struct bcm_cfg80211 *cfg)
17362 {
17363 spin_lock_init(&cfg->eq_lock);
17364 }
17365
17366 static void wl_delay(u32 ms)
17367 {
17368 if (in_atomic() || (ms < jiffies_to_msecs(1))) {
17369 OSL_DELAY(ms*1000);
17370 } else {
17371 OSL_SLEEP(ms);
17372 }
17373 }
17374
17375 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
17376 {
17377 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17378 struct ether_addr primary_mac;
17379 if (!cfg->p2p)
17380 return -1;
17381 if (!p2p_is_on(cfg)) {
17382 get_primary_mac(cfg, &primary_mac);
17383 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
17384 } else {
17385 memcpy(p2pdev_addr->octet, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE).octet,
17386 ETHER_ADDR_LEN);
17387 }
17388
17389 return 0;
17390 }
17391 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
17392 {
17393 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17394
17395 return wl_cfgp2p_set_p2p_noa(cfg, net, buf, len);
17396 }
17397
17398 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
17399 {
17400 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17401
17402 return wl_cfgp2p_get_p2p_noa(cfg, net, buf, len);
17403 }
17404
17405 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
17406 {
17407 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17408
17409 return wl_cfgp2p_set_p2p_ps(cfg, net, buf, len);
17410 }
17411
17412 s32 wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
17413 {
17414 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17415
17416 return wl_cfgp2p_set_p2p_ecsa(cfg, net, buf, len);
17417 }
17418
17419 s32 wl_cfg80211_increase_p2p_bw(struct net_device *net, char* buf, int len)
17420 {
17421 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17422
17423 return wl_cfgp2p_increase_p2p_bw(cfg, net, buf, len);
17424 }
17425
17426 #ifdef P2PLISTEN_AP_SAMECHN
17427 s32 wl_cfg80211_set_p2p_resp_ap_chn(struct net_device *net, s32 enable)
17428 {
17429 s32 ret = wldev_iovar_setint(net, "p2p_resp_ap_chn", enable);
17430
17431 if ((ret == 0) && enable) {
17432 /* disable PM for p2p responding on infra AP channel */
17433 s32 pm = PM_OFF;
17434
17435 ret = wldev_ioctl_set(net, WLC_SET_PM, &pm, sizeof(pm));
17436 }
17437
17438 return ret;
17439 }
17440 #endif /* P2PLISTEN_AP_SAMECHN */
17441
17442 s32 wl_cfg80211_channel_to_freq(u32 channel)
17443 {
17444 int freq = 0;
17445
17446 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
17447 freq = ieee80211_channel_to_frequency(channel);
17448 #else
17449 {
17450 u16 band = 0;
17451 if (channel <= CH_MAX_2G_CHANNEL)
17452 band = IEEE80211_BAND_2GHZ;
17453 else
17454 band = IEEE80211_BAND_5GHZ;
17455 freq = ieee80211_channel_to_frequency(channel, band);
17456 }
17457 #endif
17458 return freq;
17459 }
17460
17461
17462 #ifdef WLTDLS
17463 static s32
17464 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
17465 const wl_event_msg_t *e, void *data) {
17466
17467 struct net_device *ndev = NULL;
17468 u32 reason = ntoh32(e->reason);
17469 s8 *msg = NULL;
17470
17471 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
17472
17473 switch (reason) {
17474 case WLC_E_TDLS_PEER_DISCOVERED :
17475 msg = " TDLS PEER DISCOVERD ";
17476 break;
17477 case WLC_E_TDLS_PEER_CONNECTED :
17478 if (cfg->tdls_mgmt_frame) {
17479 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
17480 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
17481 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0);
17482 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
17483 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
17484 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0,
17485 GFP_ATOMIC);
17486 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
17487 defined(WL_COMPAT_WIRELESS)
17488 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
17489 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
17490 GFP_ATOMIC);
17491 #else
17492 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq,
17493 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, GFP_ATOMIC);
17494 #endif
17495 }
17496 msg = " TDLS PEER CONNECTED ";
17497 #ifdef SUPPORT_SET_CAC
17498 /* TDLS connect reset CAC */
17499 wl_cfg80211_set_cac(cfg, 0);
17500 #endif /* SUPPORT_SET_CAC */
17501 break;
17502 case WLC_E_TDLS_PEER_DISCONNECTED :
17503 if (cfg->tdls_mgmt_frame) {
17504 kfree(cfg->tdls_mgmt_frame);
17505 cfg->tdls_mgmt_frame = NULL;
17506 cfg->tdls_mgmt_freq = 0;
17507 }
17508 msg = "TDLS PEER DISCONNECTED ";
17509 #ifdef SUPPORT_SET_CAC
17510 /* TDLS disconnec, set CAC */
17511 wl_cfg80211_set_cac(cfg, 1);
17512 #endif /* SUPPORT_SET_CAC */
17513 break;
17514 }
17515 if (msg) {
17516 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((const u8*)(&e->addr)),
17517 (bcmcfg_to_prmry_ndev(cfg) == ndev) ? "primary" : "secondary"));
17518 }
17519 return 0;
17520
17521 }
17522 #endif /* WLTDLS */
17523
17524 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
17525 static s32
17526 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
17527 KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
17528 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
17529 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
17530 u32 peer_capability, const u8 *buf, size_t len)
17531 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
17532 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
17533 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
17534 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
17535 u32 peer_capability, const u8 *buf, size_t len)
17536 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
17537 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
17538 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
17539 u32 peer_capability, bool initiator, const u8 *buf, size_t len)
17540 #else /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17541 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
17542 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
17543 const u8 *buf, size_t len)
17544 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17545 {
17546 s32 ret = 0;
17547 #ifdef WLTDLS
17548 struct bcm_cfg80211 *cfg;
17549 tdls_wfd_ie_iovar_t info;
17550 memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
17551 cfg = wl_get_cfg(dev);
17552
17553 #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
17554 /* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
17555 * and that cuases build error
17556 */
17557 BCM_REFERENCE(peer_capability);
17558 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17559
17560 switch (action_code) {
17561 /* We need to set TDLS Wifi Display IE to firmware
17562 * using tdls_wfd_ie iovar
17563 */
17564 case WLAN_TDLS_SET_PROBE_WFD_IE:
17565 WL_ERR(("%s WLAN_TDLS_SET_PROBE_WFD_IE\n", __FUNCTION__));
17566 info.mode = TDLS_WFD_PROBE_IE_TX;
17567 memcpy(&info.data, buf, len);
17568 info.length = len;
17569 break;
17570 case WLAN_TDLS_SET_SETUP_WFD_IE:
17571 WL_ERR(("%s WLAN_TDLS_SET_SETUP_WFD_IE\n", __FUNCTION__));
17572 info.mode = TDLS_WFD_IE_TX;
17573 memcpy(&info.data, buf, len);
17574 info.length = len;
17575 break;
17576 case WLAN_TDLS_SET_WFD_ENABLED:
17577 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_ENABLED\n", __FUNCTION__));
17578 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), true);
17579 goto out;
17580 case WLAN_TDLS_SET_WFD_DISABLED:
17581 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_DISABLED\n", __FUNCTION__));
17582 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), false);
17583 goto out;
17584 default:
17585 WL_ERR(("Unsupported action code : %d\n", action_code));
17586 goto out;
17587 }
17588 ret = wldev_iovar_setbuf(dev, "tdls_wfd_ie", &info, sizeof(info),
17589 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
17590
17591 if (ret) {
17592 WL_ERR(("tdls_wfd_ie error %d\n", ret));
17593 }
17594
17595 out:
17596 #endif /* WLTDLS */
17597 return ret;
17598 }
17599
17600 static s32
17601 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
17602 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
17603 const u8 *peer, enum nl80211_tdls_operation oper)
17604 #else
17605 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
17606 u8 *peer, enum nl80211_tdls_operation oper)
17607 #endif
17608 {
17609 s32 ret = 0;
17610 #ifdef WLTDLS
17611 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
17612 tdls_iovar_t info;
17613 dhd_pub_t *dhdp;
17614 bool tdls_auto_mode = false;
17615 dhdp = (dhd_pub_t *)(cfg->pub);
17616 memset(&info, 0, sizeof(tdls_iovar_t));
17617 if (peer) {
17618 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
17619 } else {
17620 return -1;
17621 }
17622 switch (oper) {
17623 case NL80211_TDLS_DISCOVERY_REQ:
17624 /* If the discovery request is broadcast then we need to set
17625 * info.mode to Tunneled Probe Request
17626 */
17627 if (memcmp(peer, (const uint8 *)BSSID_BROADCAST, ETHER_ADDR_LEN) == 0) {
17628 info.mode = TDLS_MANUAL_EP_WFD_TPQ;
17629 WL_ERR(("%s TDLS TUNNELED PRBOBE REQUEST\n", __FUNCTION__));
17630 } else {
17631 info.mode = TDLS_MANUAL_EP_DISCOVERY;
17632 }
17633 break;
17634 case NL80211_TDLS_SETUP:
17635 if (dhdp->tdls_mode == true) {
17636 info.mode = TDLS_MANUAL_EP_CREATE;
17637 tdls_auto_mode = false;
17638 /* Do tear down and create a fresh one */
17639 ret = wl_cfg80211_tdls_config(cfg, TDLS_STATE_TEARDOWN, tdls_auto_mode);
17640 if (ret < 0) {
17641 return ret;
17642 }
17643 } else {
17644 tdls_auto_mode = true;
17645 }
17646 break;
17647 case NL80211_TDLS_TEARDOWN:
17648 info.mode = TDLS_MANUAL_EP_DELETE;
17649 break;
17650 default:
17651 WL_ERR(("Unsupported operation : %d\n", oper));
17652 goto out;
17653 }
17654 /* turn on TDLS */
17655 wl_cfg80211_tdls_config(cfg, TDLS_STATE_SETUP, tdls_auto_mode);
17656 if (ret < 0) {
17657 return ret;
17658 }
17659 if (info.mode) {
17660 ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
17661 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
17662 if (ret) {
17663 WL_ERR(("tdls_endpoint error %d\n", ret));
17664 }
17665 }
17666 out:
17667 if (ret) {
17668 return -ENOTSUPP;
17669 }
17670 #endif /* WLTDLS */
17671 return ret;
17672 }
17673 #endif
17674
17675 /*
17676 * This function returns no of bytes written
17677 * In case of failure return zero, not bcme_error
17678 */
17679 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *ndev, char *buf, int len,
17680 enum wl_management_type type)
17681 {
17682 struct bcm_cfg80211 *cfg;
17683 s32 ret = 0;
17684 struct ether_addr primary_mac;
17685 s32 bssidx = 0;
17686 s32 pktflag = 0;
17687 cfg = wl_get_cfg(ndev);
17688
17689 if (wl_get_drv_status(cfg, AP_CREATING, ndev)) {
17690 /* Vendor IEs should be set to FW
17691 * after SoftAP interface is brought up
17692 */
17693 WL_DBG(("Skipping set IE since AP is not up \n"));
17694 goto exit;
17695 } else if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
17696 /* Either stand alone AP case or P2P discovery */
17697 if (wl_get_drv_status(cfg, AP_CREATED, ndev)) {
17698 /* Stand alone AP case on primary interface */
17699 WL_DBG(("Apply IEs for Primary AP Interface \n"));
17700 bssidx = 0;
17701 } else {
17702 if (!cfg->p2p) {
17703 /* If p2p not initialized, return failure */
17704 WL_ERR(("P2P not initialized \n"));
17705 goto exit;
17706 }
17707 /* P2P Discovery case (p2p listen) */
17708 if (!cfg->p2p->on) {
17709 /* Turn on Discovery interface */
17710 get_primary_mac(cfg, &primary_mac);
17711 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
17712 p2p_on(cfg) = true;
17713 ret = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
17714 if (unlikely(ret)) {
17715 WL_ERR(("Enable discovery failed \n"));
17716 goto exit;
17717 }
17718 }
17719 WL_DBG(("Apply IEs for P2P Discovery Iface \n"));
17720 ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
17721 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17722 }
17723 } else {
17724 /* Virtual AP/ P2P Group Interface */
17725 WL_DBG(("Apply IEs for iface:%s\n", ndev->name));
17726 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
17727 }
17728
17729 if (ndev != NULL) {
17730 switch (type) {
17731 case WL_BEACON:
17732 pktflag = VNDR_IE_BEACON_FLAG;
17733 break;
17734 case WL_PROBE_RESP:
17735 pktflag = VNDR_IE_PRBRSP_FLAG;
17736 break;
17737 case WL_ASSOC_RESP:
17738 pktflag = VNDR_IE_ASSOCRSP_FLAG;
17739 break;
17740 }
17741 if (pktflag) {
17742 ret = wl_cfg80211_set_mgmt_vndr_ies(cfg,
17743 ndev_to_cfgdev(ndev), bssidx, pktflag, buf, len);
17744 }
17745 }
17746 exit:
17747 return ret;
17748 }
17749
17750 #ifdef WL_SUPPORT_AUTO_CHANNEL
17751 static s32
17752 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
17753 {
17754 u32 val = 0;
17755 s32 ret = BCME_ERROR;
17756 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
17757 /* Set interface up, explicitly. */
17758 val = 1;
17759
17760 ret = wldev_ioctl_set(ndev, WLC_UP, (void *)&val, sizeof(val));
17761 if (ret < 0) {
17762 WL_ERR(("set interface up failed, error = %d\n", ret));
17763 goto done;
17764 }
17765
17766 /* Stop all scan explicitly, till auto channel selection complete. */
17767 wl_set_drv_status(cfg, SCANNING, ndev);
17768 if (cfg->escan_info.ndev == NULL) {
17769 ret = BCME_OK;
17770 goto done;
17771 }
17772 ret = wl_notify_escan_complete(cfg, ndev, true, true);
17773 if (ret < 0) {
17774 WL_ERR(("set scan abort failed, error = %d\n", ret));
17775 ret = BCME_OK; // terence 20140115: fix escan_complete error
17776 goto done;
17777 }
17778
17779 done:
17780 return ret;
17781 }
17782
17783 static bool
17784 wl_cfg80211_valid_channel_p2p(int channel)
17785 {
17786 bool valid = false;
17787
17788 /* channel 1 to 14 */
17789 if ((channel >= 1) && (channel <= 14)) {
17790 valid = true;
17791 }
17792 /* channel 36 to 48 */
17793 else if ((channel >= 36) && (channel <= 48)) {
17794 valid = true;
17795 }
17796 /* channel 149 to 161 */
17797 else if ((channel >= 149) && (channel <= 161)) {
17798 valid = true;
17799 }
17800 else {
17801 valid = false;
17802 WL_INFORM(("invalid P2P chanspec, channel = %d\n", channel));
17803 }
17804
17805 return valid;
17806 }
17807
17808 s32
17809 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
17810 {
17811 s32 ret = BCME_ERROR;
17812 struct bcm_cfg80211 *cfg = NULL;
17813 chanspec_t chanspec = 0;
17814
17815 cfg = wl_get_cfg(ndev);
17816
17817 /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
17818 chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
17819 WL_CHANSPEC_CTL_SB_NONE);
17820 chanspec = wl_chspec_host_to_driver(chanspec);
17821
17822 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
17823 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
17824 if (ret < 0) {
17825 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
17826 }
17827
17828 return ret;
17829 }
17830
17831 s32
17832 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
17833 {
17834 u32 channel = 0;
17835 s32 ret = BCME_ERROR;
17836 s32 i = 0;
17837 s32 j = 0;
17838 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
17839 wl_uint32_list_t *list = NULL;
17840 chanspec_t chanspec = 0;
17841
17842 /* Restrict channels to 5GHz, 20MHz BW, no SB. */
17843 chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
17844 WL_CHANSPEC_CTL_SB_NONE);
17845 chanspec = wl_chspec_host_to_driver(chanspec);
17846
17847 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
17848 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
17849 if (ret < 0) {
17850 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
17851 goto done;
17852 }
17853
17854 list = (wl_uint32_list_t *)buf;
17855 /* Skip DFS and inavlid P2P channel. */
17856 for (i = 0, j = 0; i < dtoh32(list->count); i++) {
17857 chanspec = (chanspec_t) dtoh32(list->element[i]);
17858 channel = CHSPEC_CHANNEL(chanspec);
17859
17860 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
17861 if (ret < 0) {
17862 WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
17863 goto done;
17864 }
17865
17866 if (CHANNEL_IS_RADAR(channel) ||
17867 !(wl_cfg80211_valid_channel_p2p(CHSPEC_CHANNEL(chanspec)))) {
17868 continue;
17869 } else {
17870 list->element[j] = list->element[i];
17871 }
17872
17873 j++;
17874 }
17875
17876 list->count = j;
17877
17878 done:
17879 return ret;
17880 }
17881
17882 static s32
17883 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
17884 int *channel)
17885 {
17886 s32 ret = BCME_ERROR;
17887 int chosen = 0;
17888 int retry = 0;
17889 uint chip;
17890
17891 /* Start auto channel selection scan. */
17892 ret = wldev_ioctl_set(ndev, WLC_START_CHANNEL_SEL, buf, buflen);
17893 if (ret < 0) {
17894 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
17895 *channel = 0;
17896 goto done;
17897 }
17898
17899 /* Wait for auto channel selection, worst case possible delay is 5250ms. */
17900 retry = CHAN_SEL_RETRY_COUNT;
17901
17902 while (retry--) {
17903 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
17904 chosen = 0;
17905 ret = wldev_ioctl_get(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
17906 if ((ret == 0) && (dtoh32(chosen) != 0)) {
17907 chip = dhd_conf_get_chip(dhd_get_pub(ndev));
17908 if (chip != BCM43362_CHIP_ID && chip != BCM4330_CHIP_ID &&
17909 chip != BCM43143_CHIP_ID) {
17910 u32 chanspec = 0;
17911 int ctl_chan;
17912 chanspec = wl_chspec_driver_to_host(chosen);
17913 WL_INFORM(("selected chanspec = 0x%x\n", chanspec));
17914 ctl_chan = wf_chspec_ctlchan(chanspec);
17915 WL_INFORM(("selected ctl_chan = %d\n", ctl_chan));
17916 *channel = (u16)(ctl_chan & 0x00FF);
17917 } else
17918 *channel = (u16)(chosen & 0x00FF);
17919 WL_INFORM(("selected channel = %d\n", *channel));
17920 break;
17921 }
17922 WL_INFORM(("attempt = %d, ret = %d, chosen = %d\n",
17923 (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
17924 }
17925
17926 if (retry <= 0) {
17927 WL_ERR(("failure, auto channel selection timed out\n"));
17928 *channel = 0;
17929 ret = BCME_ERROR;
17930 }
17931 WL_INFORM(("selected channel = %d\n", *channel));
17932
17933 done:
17934 return ret;
17935 }
17936
17937 static s32
17938 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
17939 {
17940 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
17941 /* Clear scan stop driver status. */
17942 wl_clr_drv_status(cfg, SCANNING, ndev);
17943
17944 return BCME_OK;
17945 }
17946
17947 s32
17948 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
17949 {
17950 int channel = 0, band, band_cur;
17951 s32 ret = BCME_ERROR;
17952 u8 *buf = NULL;
17953 char *pos = cmd;
17954 struct bcm_cfg80211 *cfg = NULL;
17955 struct net_device *ndev = NULL;
17956
17957 memset(cmd, 0, total_len);
17958
17959 buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
17960 if (buf == NULL) {
17961 WL_ERR(("failed to allocate chanspec buffer\n"));
17962 return -ENOMEM;
17963 }
17964
17965 /*
17966 * Always use primary interface, irrespective of interface on which
17967 * command came.
17968 */
17969 cfg = wl_get_cfg(dev);
17970 ndev = bcmcfg_to_prmry_ndev(cfg);
17971
17972 /*
17973 * Make sure that FW and driver are in right state to do auto channel
17974 * selection scan.
17975 */
17976 ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
17977 if (ret < 0) {
17978 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
17979 goto done;
17980 }
17981
17982 ret = wldev_ioctl(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur), false);
17983 if (band_cur != WLC_BAND_5G) {
17984 /* Best channel selection in 2.4GHz band. */
17985 ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
17986 if (ret < 0) {
17987 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
17988 goto done;
17989 }
17990
17991 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
17992 &channel);
17993 if (ret < 0) {
17994 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
17995 goto done;
17996 }
17997
17998 if (CHANNEL_IS_2G(channel)) {
17999 #if 0
18000 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
18001 channel = ieee80211_channel_to_frequency(channel);
18002 #else
18003 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
18004 #endif
18005 #endif
18006 } else {
18007 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
18008 channel = 0;
18009 }
18010 pos += snprintf(pos, total_len, "2g=%d ", channel);
18011 }
18012
18013 if (band_cur != WLC_BAND_2G) {
18014 // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
18015 band = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
18016 ret = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
18017 if (ret < 0)
18018 WL_ERR(("WLC_SET_BAND error %d\n", ret));
18019
18020 /* Best channel selection in 5GHz band. */
18021 ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
18022 if (ret < 0) {
18023 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
18024 goto done;
18025 }
18026
18027 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
18028 &channel);
18029 if (ret < 0) {
18030 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
18031 goto done;
18032 }
18033
18034 if (CHANNEL_IS_5G(channel)) {
18035 #if 0
18036 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
18037 channel = ieee80211_channel_to_frequency(channel);
18038 #else
18039 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
18040 #endif
18041 #endif
18042 } else {
18043 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
18044 channel = 0;
18045 }
18046
18047 ret = wldev_ioctl(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur), true);
18048 if (ret < 0)
18049 WL_ERR(("WLC_SET_BAND error %d\n", ret));
18050 pos += snprintf(pos, total_len, "5g=%d ", channel);
18051 }
18052
18053 done:
18054 if (NULL != buf) {
18055 kfree(buf);
18056 }
18057
18058 /* Restore FW and driver back to normal state. */
18059 ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
18060 if (ret < 0) {
18061 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
18062 }
18063
18064 printf("%s: %s\n", __FUNCTION__, cmd);
18065
18066 return (pos - cmd);
18067 }
18068 #endif /* WL_SUPPORT_AUTO_CHANNEL */
18069
18070 static const struct rfkill_ops wl_rfkill_ops = {
18071 .set_block = wl_rfkill_set
18072 };
18073
18074 static int wl_rfkill_set(void *data, bool blocked)
18075 {
18076 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
18077
18078 WL_DBG(("Enter \n"));
18079 WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
18080
18081 if (!cfg)
18082 return -EINVAL;
18083
18084 cfg->rf_blocked = blocked;
18085
18086 return 0;
18087 }
18088
18089 static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup)
18090 {
18091 s32 err = 0;
18092
18093 WL_DBG(("Enter \n"));
18094 if (!cfg)
18095 return -EINVAL;
18096 if (setup) {
18097 cfg->rfkill = rfkill_alloc("brcmfmac-wifi",
18098 wl_cfg80211_get_parent_dev(),
18099 RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)cfg);
18100
18101 if (!cfg->rfkill) {
18102 err = -ENOMEM;
18103 goto err_out;
18104 }
18105
18106 err = rfkill_register(cfg->rfkill);
18107
18108 if (err)
18109 rfkill_destroy(cfg->rfkill);
18110 } else {
18111 if (!cfg->rfkill) {
18112 err = -ENOMEM;
18113 goto err_out;
18114 }
18115
18116 rfkill_unregister(cfg->rfkill);
18117 rfkill_destroy(cfg->rfkill);
18118 }
18119
18120 err_out:
18121 return err;
18122 }
18123
18124 #ifdef DEBUGFS_CFG80211
18125 /**
18126 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
18127 * to turn on SCAN and DBG log.
18128 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
18129 * To see current setting of debug level,
18130 * cat /sys/kernel/debug/dhd/debug_level
18131 */
18132 static ssize_t
18133 wl_debuglevel_write(struct file *file, const char __user *userbuf,
18134 size_t count, loff_t *ppos)
18135 {
18136 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
18137 char *params, *token, *colon;
18138 uint i, tokens, log_on = 0;
18139 size_t minsize = min_t(size_t, (sizeof(tbuf) - 1), count);
18140
18141 memset(tbuf, 0, sizeof(tbuf));
18142 memset(sublog, 0, sizeof(sublog));
18143 if (copy_from_user(&tbuf, userbuf, minsize)) {
18144 return -EFAULT;
18145 }
18146
18147 tbuf[minsize + 1] = '\0';
18148 params = &tbuf[0];
18149 colon = strchr(params, '\n');
18150 if (colon != NULL)
18151 *colon = '\0';
18152 while ((token = strsep(&params, " ")) != NULL) {
18153 memset(sublog, 0, sizeof(sublog));
18154 if (token == NULL || !*token)
18155 break;
18156 if (*token == '\0')
18157 continue;
18158 colon = strchr(token, ':');
18159 if (colon != NULL) {
18160 *colon = ' ';
18161 }
18162 tokens = sscanf(token, "%s %u", sublog, &log_on);
18163 if (colon != NULL)
18164 *colon = ':';
18165
18166 if (tokens == 2) {
18167 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
18168 if (!strncmp(sublog, sublogname_map[i].sublogname,
18169 strlen(sublogname_map[i].sublogname))) {
18170 if (log_on)
18171 wl_dbg_level |=
18172 (sublogname_map[i].log_level);
18173 else
18174 wl_dbg_level &=
18175 ~(sublogname_map[i].log_level);
18176 }
18177 }
18178 } else
18179 WL_ERR(("%s: can't parse '%s' as a "
18180 "SUBMODULE:LEVEL (%d tokens)\n",
18181 tbuf, token, tokens));
18182
18183
18184 }
18185 return count;
18186 }
18187
18188 static ssize_t
18189 wl_debuglevel_read(struct file *file, char __user *user_buf,
18190 size_t count, loff_t *ppos)
18191 {
18192 char *param;
18193 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
18194 uint i;
18195 memset(tbuf, 0, sizeof(tbuf));
18196 param = &tbuf[0];
18197 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
18198 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
18199 sublogname_map[i].sublogname,
18200 (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
18201 }
18202 *param = '\n';
18203 return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
18204
18205 }
18206 static const struct file_operations fops_debuglevel = {
18207 .open = NULL,
18208 .write = wl_debuglevel_write,
18209 .read = wl_debuglevel_read,
18210 .owner = THIS_MODULE,
18211 .llseek = NULL,
18212 };
18213
18214 static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg)
18215 {
18216 s32 err = 0;
18217 struct dentry *_dentry;
18218 if (!cfg)
18219 return -EINVAL;
18220 cfg->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
18221 if (!cfg->debugfs || IS_ERR(cfg->debugfs)) {
18222 if (cfg->debugfs == ERR_PTR(-ENODEV))
18223 WL_ERR(("Debugfs is not enabled on this kernel\n"));
18224 else
18225 WL_ERR(("Can not create debugfs directory\n"));
18226 cfg->debugfs = NULL;
18227 goto exit;
18228
18229 }
18230 _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
18231 cfg->debugfs, cfg, &fops_debuglevel);
18232 if (!_dentry || IS_ERR(_dentry)) {
18233 WL_ERR(("failed to create debug_level debug file\n"));
18234 wl_free_debugfs(cfg);
18235 }
18236 exit:
18237 return err;
18238 }
18239 static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg)
18240 {
18241 if (!cfg)
18242 return -EINVAL;
18243 if (cfg->debugfs)
18244 debugfs_remove_recursive(cfg->debugfs);
18245 cfg->debugfs = NULL;
18246 return 0;
18247 }
18248 #endif /* DEBUGFS_CFG80211 */
18249
18250 struct device *wl_cfg80211_get_parent_dev(void)
18251 {
18252 return cfg80211_parent_dev;
18253 }
18254
18255 void wl_cfg80211_set_parent_dev(void *dev)
18256 {
18257 cfg80211_parent_dev = dev;
18258 }
18259
18260 static void wl_cfg80211_clear_parent_dev(void)
18261 {
18262 cfg80211_parent_dev = NULL;
18263 }
18264
18265 void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
18266 {
18267 if (wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr", NULL,
18268 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync) == BCME_OK) {
18269 memcpy(mac->octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
18270 } else {
18271 memset(mac->octet, 0, ETHER_ADDR_LEN);
18272 }
18273 }
18274 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role)
18275 {
18276 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
18277 if (((dev_role == NL80211_IFTYPE_AP) &&
18278 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
18279 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
18280 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
18281 {
18282 WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role, dhd->op_mode));
18283 return false;
18284 }
18285 return true;
18286 }
18287
18288 int wl_cfg80211_do_driver_init(struct net_device *net)
18289 {
18290 struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
18291
18292 if (!cfg || !cfg->wdev)
18293 return -EINVAL;
18294
18295 if (dhd_do_driver_init(cfg->wdev->netdev) < 0)
18296 return -1;
18297
18298 return 0;
18299 }
18300
18301 void wl_cfg80211_enable_trace(u32 level)
18302 {
18303 wl_dbg_level = level;
18304 printf("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level);
18305 }
18306
18307 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
18308 2, 0))
18309 static s32
18310 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
18311 bcm_struct_cfgdev *cfgdev, u64 cookie)
18312 {
18313 /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
18314 * is passed with CMD_FRAME. This callback is supposed to cancel
18315 * the OFFCHANNEL Wait. Since we are already taking care of that
18316 * with the tx_mgmt logic, do nothing here.
18317 */
18318
18319 return 0;
18320 }
18321 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
18322
18323 #ifdef WL11U
18324 static bcm_tlv_t *
18325 wl_cfg80211_find_interworking_ie(const u8 *parse, u32 len)
18326 {
18327 bcm_tlv_t *ie;
18328
18329 /* unfortunately it's too much work to dispose the const cast - bcm_parse_tlvs
18330 * is used everywhere and changing its prototype to take const qualifier needs
18331 * a massive change to all its callers...
18332 */
18333 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
18334 4 && __GNUC_MINOR__ >= 6))
18335 _Pragma("GCC diagnostic push")
18336 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
18337 #endif
18338 if ((ie = bcm_parse_tlvs((void *)parse, (int)len, DOT11_MNG_INTERWORKING_ID))) {
18339 return ie;
18340 }
18341 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
18342 4 && __GNUC_MINOR__ >= 6))
18343 _Pragma("GCC diagnostic pop")
18344 #endif
18345 return NULL;
18346 }
18347
18348 static s32
18349 wl_cfg80211_clear_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx)
18350 {
18351 ie_setbuf_t ie_setbuf;
18352
18353 WL_DBG(("clear interworking IE\n"));
18354
18355 memset(&ie_setbuf, 0, sizeof(ie_setbuf_t));
18356
18357 ie_setbuf.ie_buffer.iecount = htod32(1);
18358 ie_setbuf.ie_buffer.ie_list[0].ie_data.id = DOT11_MNG_INTERWORKING_ID;
18359 ie_setbuf.ie_buffer.ie_list[0].ie_data.len = 0;
18360
18361 return wldev_iovar_setbuf_bsscfg(ndev, "ie", &ie_setbuf, sizeof(ie_setbuf),
18362 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
18363 }
18364
18365 static s32
18366 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
18367 uint8 ie_id, uint8 *data, uint8 data_len)
18368 {
18369 s32 err = BCME_OK;
18370 s32 buf_len;
18371 ie_setbuf_t *ie_setbuf;
18372 ie_getbuf_t ie_getbufp;
18373 char getbuf[WLC_IOCTL_SMLEN];
18374
18375 if (ie_id != DOT11_MNG_INTERWORKING_ID) {
18376 WL_ERR(("unsupported (id=%d)\n", ie_id));
18377 return BCME_UNSUPPORTED;
18378 }
18379
18380 /* access network options (1 octet) is the mandatory field */
18381 if (!data || data_len == 0 || data_len > IW_IES_MAX_BUF_LEN) {
18382 WL_ERR(("wrong interworking IE (len=%d)\n", data_len));
18383 return BCME_BADARG;
18384 }
18385
18386 /* Validate the pktflag parameter */
18387 if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
18388 VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
18389 VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
18390 VNDR_IE_CUSTOM_FLAG))) {
18391 WL_ERR(("invalid packet flag 0x%x\n", pktflag));
18392 return BCME_BADARG;
18393 }
18394
18395 buf_len = sizeof(ie_setbuf_t) + data_len - 1;
18396
18397 ie_getbufp.id = DOT11_MNG_INTERWORKING_ID;
18398 if (wldev_iovar_getbuf_bsscfg(ndev, "ie", (void *)&ie_getbufp,
18399 sizeof(ie_getbufp), getbuf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync)
18400 == BCME_OK) {
18401 if (!memcmp(&getbuf[TLV_HDR_LEN], data, data_len)) {
18402 WL_DBG(("skip to set interworking IE\n"));
18403 return BCME_OK;
18404 }
18405 }
18406
18407 /* if already set with previous values, delete it first */
18408 if (cfg->wl11u) {
18409 if ((err = wl_cfg80211_clear_iw_ie(cfg, ndev, bssidx)) != BCME_OK) {
18410 return err;
18411 }
18412 }
18413
18414 ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL);
18415 if (!ie_setbuf) {
18416 WL_ERR(("Error allocating buffer for IE\n"));
18417 return -ENOMEM;
18418 }
18419 strncpy(ie_setbuf->cmd, "add", sizeof(ie_setbuf->cmd));
18420 ie_setbuf->cmd[sizeof(ie_setbuf->cmd) - 1] = '\0';
18421
18422 /* Buffer contains only 1 IE */
18423 ie_setbuf->ie_buffer.iecount = htod32(1);
18424 /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
18425 ie_setbuf->ie_buffer.ie_list[0].pktflag = htod32(pktflag);
18426
18427 /* Now, add the IE to the buffer */
18428 ie_setbuf->ie_buffer.ie_list[0].ie_data.id = DOT11_MNG_INTERWORKING_ID;
18429 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
18430 memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len);
18431
18432 if ((err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
18433 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync))
18434 == BCME_OK) {
18435 WL_DBG(("set interworking IE\n"));
18436 cfg->wl11u = TRUE;
18437 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
18438 }
18439
18440 kfree(ie_setbuf);
18441 return err;
18442 }
18443 #endif /* WL11U */
18444
18445
18446 s32
18447 wl_cfg80211_set_if_band(struct net_device *ndev, int band)
18448 {
18449 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
18450 int ret = 0, wait_cnt;
18451 char ioctl_buf[32];
18452
18453 if ((band < WLC_BAND_AUTO) || (band > WLC_BAND_2G)) {
18454 WL_ERR(("Invalid band\n"));
18455 return -EINVAL;
18456 }
18457 if (wl_get_drv_status(cfg, CONNECTED, ndev) ||
18458 wl_get_drv_status(cfg, CONNECTING, ndev)) {
18459 /* if driver is connected or connecting status, try to disconnect first.
18460 * if dongle is associated, iovar 'if_band' would be rejected.
18461 */
18462 wl_set_drv_status(cfg, DISCONNECTING, ndev);
18463 ret = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0);
18464 if (ret < 0) {
18465 WL_ERR(("WLC_DISASSOC error %d\n", ret));
18466 /* continue to set 'if_band' */
18467 }
18468 else {
18469 /* This is to ensure that 'if_band' iovar is issued only after
18470 * disconnection is completed
18471 */
18472 wait_cnt = WAIT_FOR_DISCONNECT_MAX;
18473 while (wl_get_drv_status(cfg, DISCONNECTING, ndev) && wait_cnt) {
18474 WL_DBG(("Wait until disconnected. wait_cnt: %d\n", wait_cnt));
18475 wait_cnt--;
18476 OSL_SLEEP(10);
18477 }
18478 }
18479 }
18480 if ((ret = wldev_iovar_setbuf(ndev, "if_band", &band,
18481 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
18482 WL_ERR(("seting if_band failed ret=%d\n", ret));
18483 /* issue 'WLC_SET_BAND' if if_band is not supported */
18484 if (ret == BCME_UNSUPPORTED) {
18485 ret = wldev_set_band(ndev, band);
18486 if (ret < 0) {
18487 WL_ERR(("seting band failed ret=%d\n", ret));
18488 }
18489 }
18490 }
18491 return ret;
18492 }
18493
18494 s32
18495 wl_cfg80211_dfs_ap_move(struct net_device *ndev, char *data, char *command, int total_len)
18496 {
18497 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
18498 char ioctl_buf[50];
18499 int err = 0;
18500 uint32 val = 0;
18501 chanspec_t chanspec = 0;
18502 int abort;
18503 int bytes_written = 0;
18504 wl_dfs_ap_move_status_t *status;
18505 char chanbuf[CHANSPEC_STR_LEN];
18506 const char *dfs_state_str[DFS_SCAN_S_MAX] = {
18507 "Radar Free On Channel",
18508 "Radar Found On Channel",
18509 "Radar Scan In Progress",
18510 "Radar Scan Aborted",
18511 "RSDB Mode switch in Progress For Scan"
18512 };
18513 if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
18514 bytes_written = snprintf(command, total_len, "AP is not up\n");
18515 return bytes_written;
18516 }
18517 if (!*data) {
18518 if ((err = wldev_iovar_getbuf(ndev, "dfs_ap_move", NULL, 0,
18519 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
18520 WL_ERR(("setting dfs_ap_move failed with err=%d \n", err));
18521 return err;
18522 }
18523 status = (wl_dfs_ap_move_status_t *)cfg->ioctl_buf;
18524
18525 if (status->version != WL_DFS_AP_MOVE_VERSION) {
18526 err = BCME_UNSUPPORTED;
18527 WL_ERR(("err=%d version=%d\n", err, status->version));
18528 return err;
18529 }
18530
18531 if (status->move_status != (int8) DFS_SCAN_S_IDLE) {
18532 chanspec = wl_chspec_driver_to_host(status->chanspec);
18533 if (chanspec != 0 && chanspec != INVCHANSPEC) {
18534 wf_chspec_ntoa(chanspec, chanbuf);
18535 bytes_written = snprintf(command, total_len,
18536 "AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
18537
18538 }
18539 bytes_written += snprintf(command + bytes_written, total_len,
18540 "%s\n", dfs_state_str[status->move_status]);
18541 return bytes_written;
18542 } else {
18543 bytes_written = snprintf(command, total_len, "dfs AP move in IDLE state\n");
18544 return bytes_written;
18545 }
18546
18547 }
18548
18549 abort = bcm_atoi(data);
18550 if (abort == -1) {
18551 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &abort,
18552 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
18553 WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
18554 return err;
18555 }
18556 } else {
18557 chanspec = wf_chspec_aton(data);
18558 if (chanspec != 0) {
18559 val = wl_chspec_host_to_driver(chanspec);
18560 if (val != INVCHANSPEC) {
18561 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &val,
18562 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
18563 WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
18564 return err;
18565 }
18566 WL_DBG((" set dfs_ap_move successfull"));
18567 } else {
18568 err = BCME_USAGE_ERROR;
18569 }
18570 }
18571 }
18572 return err;
18573 }
18574
18575 #ifdef WBTEXT
18576 s32
18577 wl_cfg80211_wbtext_set_default(struct net_device *ndev)
18578 {
18579 char commandp[WLC_IOCTL_SMLEN];
18580 s32 ret = BCME_OK;
18581 char *data;
18582
18583 WL_DBG(("set wbtext to default\n"));
18584
18585 /* set roam profile */
18586 memset(commandp, 0, sizeof(commandp));
18587 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18588 CMD_WBTEXT_PROFILE_CONFIG, DEFAULT_WBTEXT_PROFILE_A);
18589 data = (commandp + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
18590 ret = wl_cfg80211_wbtext_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18591 if (ret != BCME_OK) {
18592 WL_ERR(("%s: Failed to set roam_prof %s error = %d\n",
18593 __FUNCTION__, data, ret));
18594 return ret;
18595 }
18596
18597 memset(commandp, 0, sizeof(commandp));
18598 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18599 CMD_WBTEXT_PROFILE_CONFIG, DEFAULT_WBTEXT_PROFILE_B);
18600 data = (commandp + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
18601 ret = wl_cfg80211_wbtext_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18602 if (ret != BCME_OK) {
18603 WL_ERR(("%s: Failed to set roam_prof %s error = %d\n",
18604 __FUNCTION__, data, ret));
18605 return ret;
18606 }
18607
18608 /* set RSSI weight */
18609 memset(commandp, 0, sizeof(commandp));
18610 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18611 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_RSSI_A);
18612 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
18613 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18614 if (ret != BCME_OK) {
18615 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18616 __FUNCTION__, data, ret));
18617 return ret;
18618 }
18619
18620 memset(commandp, 0, sizeof(commandp));
18621 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18622 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_RSSI_B);
18623 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
18624 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18625 if (ret != BCME_OK) {
18626 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18627 __FUNCTION__, data, ret));
18628 return ret;
18629 }
18630
18631 /* set CU weight */
18632 memset(commandp, 0, sizeof(commandp));
18633 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18634 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_CU_A);
18635 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
18636 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18637 if (ret != BCME_OK) {
18638 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18639 __FUNCTION__, data, ret));
18640 return ret;
18641 }
18642
18643 memset(commandp, 0, sizeof(commandp));
18644 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18645 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_CU_B);
18646 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
18647 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18648 if (ret != BCME_OK) {
18649 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18650 __FUNCTION__, data, ret));
18651 return ret;
18652 }
18653
18654 /* set RSSI table */
18655 memset(commandp, 0, sizeof(commandp));
18656 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18657 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_RSSI_A);
18658 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
18659 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18660 if (ret != BCME_OK) {
18661 WL_ERR(("%s: Failed to set RSSI table %s error = %d\n",
18662 __FUNCTION__, data, ret));
18663 return ret;
18664 }
18665
18666 memset(commandp, 0, sizeof(commandp));
18667 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18668 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_RSSI_B);
18669 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
18670 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18671 if (ret != BCME_OK) {
18672 WL_ERR(("%s: Failed to set RSSI table %s error = %d\n",
18673 __FUNCTION__, data, ret));
18674 return ret;
18675 }
18676
18677 /* set CU table */
18678 memset(commandp, 0, sizeof(commandp));
18679 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18680 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_CU_A);
18681 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
18682 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18683 if (ret != BCME_OK) {
18684 WL_ERR(("%s: Failed to set CU table %s error = %d\n",
18685 __FUNCTION__, data, ret));
18686 return ret;
18687 }
18688
18689 memset(commandp, 0, sizeof(commandp));
18690 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18691 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_CU_B);
18692 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
18693 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18694 if (ret != BCME_OK) {
18695 WL_ERR(("%s: Failed to set CU table %s error = %d\n",
18696 __FUNCTION__, data, ret));
18697 return ret;
18698 }
18699
18700 return ret;
18701 }
18702
18703 s32
18704 wl_cfg80211_wbtext_config(struct net_device *ndev, char *data, char *command, int total_len)
18705 {
18706 uint i = 0;
18707 long int rssi_lower, roam_trigger;
18708 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
18709 wl_roam_prof_band_t *rp;
18710 int err = -EINVAL, bytes_written = 0;
18711 size_t len = strlen(data);
18712 int rp_len = 0;
18713 data[len] = '\0';
18714 rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
18715 * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
18716 if (unlikely(!rp)) {
18717 WL_ERR(("%s: failed to allocate memory\n", __func__));
18718 err = -ENOMEM;
18719 goto exit;
18720 }
18721 rp->ver = WL_MAX_ROAM_PROF_VER;
18722 if (*data && (!strncmp(data, "b", 1))) {
18723 rp->band = WLC_BAND_2G;
18724 } else if (*data && (!strncmp(data, "a", 1))) {
18725 rp->band = WLC_BAND_5G;
18726 } else {
18727 err = snprintf(command, total_len, "Missing band\n");
18728 goto exit;
18729 }
18730 data++;
18731 rp->len = 0;
18732 /* Getting roam profile from fw */
18733 if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
18734 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
18735 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
18736 goto exit;
18737 }
18738 memcpy(rp, cfg->ioctl_buf, sizeof(*rp) * WL_MAX_ROAM_PROF_BRACKETS);
18739 /* roam_prof version get */
18740 if (rp->ver != WL_MAX_ROAM_PROF_VER) {
18741 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
18742 err = -EINVAL;
18743 goto exit;
18744 }
18745 if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
18746 WL_ERR(("bad length (=%d) in return data\n", rp->len));
18747 err = -EINVAL;
18748 goto exit;
18749 }
18750
18751 if (!*data) {
18752 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
18753 /* printing contents of roam profile data from fw and exits
18754 * if code hits any of one of the below condtion. If remaining
18755 * length of buffer is less than roam profile size or
18756 * if there is no valid entry.
18757 */
18758 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
18759 (rp->roam_prof[i].fullscan_period == 0)) {
18760 break;
18761 }
18762 bytes_written += snprintf(command+bytes_written,
18763 total_len, "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)\n",
18764 rp->roam_prof[i].roam_trigger, rp->roam_prof[i].rssi_lower,
18765 rp->roam_prof[i].channel_usage,
18766 rp->roam_prof[i].cu_avg_calc_dur);
18767 }
18768 err = bytes_written;
18769 goto exit;
18770 } else {
18771 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
18772 /* reading contents of roam profile data from fw and exits
18773 * if code hits any of one of the below condtion, If remaining
18774 * length of buffer is less than roam profile size or if there
18775 * is no valid entry.
18776 */
18777 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
18778 (rp->roam_prof[i].fullscan_period == 0)) {
18779 break;
18780 }
18781 }
18782 /* Do not set roam_prof from upper layer if fw doesn't have 2 rows */
18783 if (i != 2) {
18784 WL_ERR(("FW must have 2 rows to fill roam_prof\n"));
18785 err = -EINVAL;
18786 goto exit;
18787 }
18788 /* setting roam profile to fw */
18789 data++;
18790 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
18791 roam_trigger = simple_strtol(data, &data, 10);
18792 if (roam_trigger >= 0) {
18793 WL_ERR(("roam trigger[%d] value must be negative\n", i));
18794 err = -EINVAL;
18795 goto exit;
18796 }
18797 rp->roam_prof[i].roam_trigger = roam_trigger;
18798 data++;
18799 rssi_lower = simple_strtol(data, &data, 10);
18800 if (rssi_lower >= 0) {
18801 WL_ERR(("rssi lower[%d] value must be negative\n", i));
18802 err = -EINVAL;
18803 goto exit;
18804 }
18805 rp->roam_prof[i].rssi_lower = rssi_lower;
18806 data++;
18807 rp->roam_prof[i].channel_usage = simple_strtol(data, &data, 10);
18808 data++;
18809 rp->roam_prof[i].cu_avg_calc_dur = simple_strtol(data, &data, 10);
18810
18811 rp_len += sizeof(wl_roam_prof_t);
18812
18813 if (*data == '\0') {
18814 break;
18815 }
18816 data++;
18817 }
18818 if (i != 1) {
18819 WL_ERR(("Only two roam_prof rows supported.\n"));
18820 err = -EINVAL;
18821 goto exit;
18822 }
18823 rp->len = rp_len;
18824 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
18825 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN,
18826 &cfg->ioctl_buf_sync)) < 0) {
18827 WL_ERR(("seting roam_profile failed with err %d\n", err));
18828 }
18829 }
18830 exit:
18831 if (rp) {
18832 kfree(rp);
18833 }
18834 return err;
18835 }
18836
18837 #define BUFSZ 5
18838
18839 #define _S(x) #x
18840 #define S(x) _S(x)
18841
18842 int wl_cfg80211_wbtext_weight_config(struct net_device *ndev, char *data,
18843 char *command, int total_len)
18844 {
18845 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
18846 int bytes_written = 0, err = -EINVAL, argc = 0;
18847 char rssi[BUFSZ], band[BUFSZ], weight[BUFSZ];
18848 char *endptr = NULL;
18849 wnm_bss_select_weight_cfg_t *bwcfg;
18850
18851 bwcfg = kzalloc(sizeof(*bwcfg), GFP_KERNEL);
18852 if (unlikely(!bwcfg)) {
18853 WL_ERR(("%s: failed to allocate memory\n", __func__));
18854 err = -ENOMEM;
18855 goto exit;
18856 }
18857 bwcfg->version = WNM_BSSLOAD_MONITOR_VERSION;
18858 bwcfg->type = 0;
18859 bwcfg->weight = 0;
18860
18861 argc = sscanf(data, "%"S(BUFSZ)"s %"S(BUFSZ)"s %"S(BUFSZ)"s", rssi, band, weight);
18862
18863 if (!strcasecmp(rssi, "rssi"))
18864 bwcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
18865 else if (!strcasecmp(rssi, "cu"))
18866 bwcfg->type = WNM_BSS_SELECT_TYPE_CU;
18867 else {
18868 /* Usage DRIVER WBTEXT_WEIGHT_CONFIG <rssi/cu> <band> <weight> */
18869 WL_ERR(("%s: Command usage error\n", __func__));
18870 goto exit;
18871 }
18872
18873 if (!strcasecmp(band, "a"))
18874 bwcfg->band = WLC_BAND_5G;
18875 else if (!strcasecmp(band, "b"))
18876 bwcfg->band = WLC_BAND_2G;
18877 else if (!strcasecmp(band, "all"))
18878 bwcfg->band = WLC_BAND_ALL;
18879 else {
18880 WL_ERR(("%s: Command usage error\n", __func__));
18881 goto exit;
18882 }
18883
18884 if (argc == 2) {
18885 /* If there is no data after band, getting wnm_bss_select_weight from fw */
18886 if (bwcfg->band == WLC_BAND_ALL) {
18887 WL_ERR(("band option \"all\" is for set only, not get\n"));
18888 goto exit;
18889 }
18890 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_weight", bwcfg,
18891 sizeof(*bwcfg),
18892 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
18893 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d \n", err));
18894 goto exit;
18895 }
18896 memcpy(bwcfg, cfg->ioctl_buf, sizeof(*bwcfg));
18897 bytes_written = snprintf(command, total_len, "%s %s weight = %d\n",
18898 (bwcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU",
18899 (bwcfg->band == WLC_BAND_2G) ? "2G" : "5G", bwcfg->weight);
18900 err = bytes_written;
18901 goto exit;
18902 } else {
18903 /* if weight is non integer returns command usage error */
18904 bwcfg->weight = simple_strtol(weight, &endptr, 0);
18905 if (*endptr != '\0') {
18906 WL_ERR(("%s: Command usage error", __func__));
18907 goto exit;
18908 }
18909 /* setting weight for iovar wnm_bss_select_weight to fw */
18910 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_weight", bwcfg,
18911 sizeof(*bwcfg),
18912 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
18913 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d\n", err));
18914 }
18915 }
18916 exit:
18917 if (bwcfg) {
18918 kfree(bwcfg);
18919 }
18920 return err;
18921 }
18922
18923 /* WBTEXT_TUPLE_MIN_LEN_CHECK :strlen(low)+" "+strlen(high)+" "+strlen(factor) */
18924 #define WBTEXT_TUPLE_MIN_LEN_CHECK 5
18925
18926 int wl_cfg80211_wbtext_table_config(struct net_device *ndev, char *data,
18927 char *command, int total_len)
18928 {
18929 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
18930 int bytes_written = 0, err = -EINVAL;
18931 char rssi[BUFSZ], band[BUFSZ];
18932 int btcfg_len = 0, i = 0, parsed_len = 0;
18933 wnm_bss_select_factor_cfg_t *btcfg;
18934 size_t slen = strlen(data);
18935 char *start_addr = NULL;
18936 data[slen] = '\0';
18937
18938 btcfg = kzalloc((sizeof(*btcfg) + sizeof(*btcfg) *
18939 WL_FACTOR_TABLE_MAX_LIMIT), GFP_KERNEL);
18940 if (unlikely(!btcfg)) {
18941 WL_ERR(("%s: failed to allocate memory\n", __func__));
18942 err = -ENOMEM;
18943 goto exit;
18944 }
18945
18946 btcfg->version = WNM_BSS_SELECT_FACTOR_VERSION;
18947 btcfg->band = WLC_BAND_AUTO;
18948 btcfg->type = 0;
18949 btcfg->count = 0;
18950
18951 sscanf(data, "%"S(BUFSZ)"s %"S(BUFSZ)"s", rssi, band);
18952
18953 if (!strcasecmp(rssi, "rssi")) {
18954 btcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
18955 }
18956 else if (!strcasecmp(rssi, "cu")) {
18957 btcfg->type = WNM_BSS_SELECT_TYPE_CU;
18958 }
18959 else {
18960 WL_ERR(("%s: Command usage error\n", __func__));
18961 goto exit;
18962 }
18963
18964 if (!strcasecmp(band, "a")) {
18965 btcfg->band = WLC_BAND_5G;
18966 }
18967 else if (!strcasecmp(band, "b")) {
18968 btcfg->band = WLC_BAND_2G;
18969 }
18970 else if (!strcasecmp(band, "all")) {
18971 btcfg->band = WLC_BAND_ALL;
18972 }
18973 else {
18974 WL_ERR(("%s: Command usage, Wrong band\n", __func__));
18975 goto exit;
18976 }
18977
18978 if ((slen - 1) == (strlen(rssi) + strlen(band))) {
18979 /* Getting factor table using iovar 'wnm_bss_select_table' from fw */
18980 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_table", btcfg,
18981 sizeof(*btcfg),
18982 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
18983 WL_ERR(("Getting wnm_bss_select_table failed with err=%d \n", err));
18984 goto exit;
18985 }
18986 memcpy(btcfg, cfg->ioctl_buf, sizeof(*btcfg));
18987 memcpy(btcfg, cfg->ioctl_buf, (btcfg->count+1) * sizeof(*btcfg));
18988
18989 bytes_written += snprintf(command + bytes_written, total_len,
18990 "No of entries in table: %d\n", btcfg->count);
18991 bytes_written += snprintf(command + bytes_written, total_len, "%s factor table\n",
18992 (btcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU");
18993 bytes_written += snprintf(command + bytes_written, total_len,
18994 "low\thigh\tfactor\n");
18995 for (i = 0; i <= btcfg->count-1; i++) {
18996 bytes_written += snprintf(command + bytes_written, total_len,
18997 "%d\t%d\t%d\n", btcfg->params[i].low, btcfg->params[i].high,
18998 btcfg->params[i].factor);
18999 }
19000 err = bytes_written;
19001 goto exit;
19002 } else {
19003 memset(btcfg->params, 0, sizeof(wnm_bss_select_factor_params_t)
19004 * WL_FACTOR_TABLE_MAX_LIMIT);
19005 data += (strlen(rssi) + strlen(band) + 2);
19006 start_addr = data;
19007 slen = slen - (strlen(rssi) + strlen(band) + 2);
19008 for (i = 0; i < WL_FACTOR_TABLE_MAX_LIMIT; i++) {
19009 if (parsed_len + WBTEXT_TUPLE_MIN_LEN_CHECK <= slen) {
19010 btcfg->params[i].low = simple_strtol(data, &data, 10);
19011 data++;
19012 btcfg->params[i].high = simple_strtol(data, &data, 10);
19013 data++;
19014 btcfg->params[i].factor = simple_strtol(data, &data, 10);
19015 btcfg->count++;
19016 if (*data == '\0') {
19017 break;
19018 }
19019 data++;
19020 parsed_len = data - start_addr;
19021 } else {
19022 WL_ERR(("%s:Command usage:less no of args\n", __func__));
19023 goto exit;
19024 }
19025 }
19026 btcfg_len = sizeof(*btcfg) + ((btcfg->count) * sizeof(*btcfg));
19027 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_table", btcfg, btcfg_len,
19028 cfg->ioctl_buf, WLC_IOCTL_MEDLEN, &cfg->ioctl_buf_sync)) < 0) {
19029 WL_ERR(("seting wnm_bss_select_table failed with err %d\n", err));
19030 goto exit;
19031 }
19032 }
19033 exit:
19034 if (btcfg) {
19035 kfree(btcfg);
19036 }
19037 return err;
19038 }
19039
19040 s32
19041 wl_cfg80211_wbtext_delta_config(struct net_device *ndev, char *data, char *command, int total_len)
19042 {
19043 uint i = 0;
19044 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
19045 int err = -EINVAL, bytes_written = 0, argc = 0, val, len = 0;
19046 char delta[BUFSZ], band[BUFSZ], *endptr = NULL;
19047 wl_roam_prof_band_t *rp;
19048
19049 rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
19050 * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
19051 if (unlikely(!rp)) {
19052 WL_ERR(("%s: failed to allocate memory\n", __func__));
19053 err = -ENOMEM;
19054 goto exit;
19055 }
19056
19057 argc = sscanf(data, "%"S(BUFSZ)"s %"S(BUFSZ)"s", band, delta);
19058 if (!strcasecmp(band, "a"))
19059 rp->band = WLC_BAND_5G;
19060 else if (!strcasecmp(band, "b"))
19061 rp->band = WLC_BAND_2G;
19062 else {
19063 WL_ERR(("%s: Missing band\n", __func__));
19064 goto exit;
19065 }
19066 /* Getting roam profile from fw */
19067 if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
19068 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
19069 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
19070 goto exit;
19071 }
19072 memcpy(rp, cfg->ioctl_buf, sizeof(wl_roam_prof_band_t));
19073 if (rp->ver != WL_MAX_ROAM_PROF_VER) {
19074 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
19075 err = -EINVAL;
19076 goto exit;
19077 }
19078 if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
19079 WL_ERR(("bad length (=%d) in return data\n", rp->len));
19080 err = -EINVAL;
19081 goto exit;
19082 }
19083
19084 if (argc == 2) {
19085 /* if delta is non integer returns command usage error */
19086 val = simple_strtol(delta, &endptr, 0);
19087 if (*endptr != '\0') {
19088 WL_ERR(("%s: Command usage error", __func__));
19089 goto exit;
19090 }
19091 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
19092 /*
19093 * Checking contents of roam profile data from fw and exits
19094 * if code hits below condtion. If remaining length of buffer is
19095 * less than roam profile size or if there is no valid entry.
19096 */
19097 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
19098 (rp->roam_prof[i].fullscan_period == 0)) {
19099 break;
19100 }
19101 if (rp->roam_prof[i].channel_usage != 0) {
19102 rp->roam_prof[i].roam_delta = val;
19103 }
19104 len += sizeof(wl_roam_prof_t);
19105 }
19106 }
19107 else {
19108 if (rp->roam_prof[i].channel_usage != 0) {
19109 bytes_written = snprintf(command, total_len,
19110 "%s Delta %d\n", (rp->band == WLC_BAND_2G) ? "2G" : "5G",
19111 rp->roam_prof[0].roam_delta);
19112 }
19113 err = bytes_written;
19114 goto exit;
19115 }
19116 rp->len = len;
19117 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
19118 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, &cfg->ioctl_buf_sync)) < 0) {
19119 WL_ERR(("seting roam_profile failed with err %d\n", err));
19120 }
19121 exit :
19122 if (rp) {
19123 kfree(rp);
19124 }
19125 return err;
19126 }
19127 #endif /* WBTEXT */
19128
19129
19130 int wl_cfg80211_scan_stop(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev)
19131 {
19132 struct net_device *ndev = NULL;
19133 unsigned long flags;
19134 int clear_flag = 0;
19135 int ret = 0;
19136 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
19137 struct cfg80211_scan_info info;
19138 #endif
19139
19140 WL_TRACE(("Enter\n"));
19141
19142 if (!cfg)
19143 return -EINVAL;
19144
19145 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
19146
19147 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
19148 #ifdef WL_CFG80211_P2P_DEV_IF
19149 if (cfg->scan_request && cfg->scan_request->wdev == cfgdev)
19150 #else
19151 if (cfg->scan_request && cfg->scan_request->dev == cfgdev)
19152 #endif
19153 {
19154 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
19155 info.aborted = true;
19156 cfg80211_scan_done(cfg->scan_request, &info);
19157 #else
19158 cfg80211_scan_done(cfg->scan_request, true);
19159 #endif
19160 cfg->scan_request = NULL;
19161 clear_flag = 1;
19162 }
19163 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
19164
19165 if (clear_flag)
19166 wl_clr_drv_status(cfg, SCANNING, ndev);
19167
19168 return ret;
19169 }
19170
19171 bool wl_cfg80211_is_concurrent_mode(struct net_device *dev)
19172 {
19173 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
19174 if ((cfg) && (wl_get_drv_status_all(cfg, CONNECTED) > 1)) {
19175 return true;
19176 } else {
19177 return false;
19178 }
19179 }
19180
19181 void* wl_cfg80211_get_dhdp(struct net_device *dev)
19182 {
19183 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
19184
19185 return cfg->pub;
19186 }
19187
19188 bool wl_cfg80211_is_p2p_active(struct net_device *dev)
19189 {
19190 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
19191 return (cfg && cfg->p2p);
19192 }
19193
19194 bool wl_cfg80211_is_roam_offload(struct net_device * dev)
19195 {
19196 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
19197 return (cfg && cfg->roam_offload);
19198 }
19199
19200 bool wl_cfg80211_is_event_from_connected_bssid(struct net_device * dev, const wl_event_msg_t *e,
19201 int ifidx)
19202 {
19203 u8 *curbssid = NULL;
19204 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
19205
19206 if (!cfg) {
19207 /* When interface is created using wl
19208 * ndev->ieee80211_ptr will be NULL.
19209 */
19210 return NULL;
19211 }
19212 curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
19213
19214 if (!curbssid) {
19215 return NULL;
19216 }
19217
19218 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0) {
19219 return true;
19220 }
19221 return false;
19222 }
19223
19224 static void wl_cfg80211_work_handler(struct work_struct * work)
19225 {
19226 struct bcm_cfg80211 *cfg = NULL;
19227 struct net_info *iter, *next;
19228 s32 err = BCME_OK;
19229 s32 pm = PM_FAST;
19230 dhd_pub_t *dhd;
19231 BCM_SET_CONTAINER_OF(cfg, work, struct bcm_cfg80211, pm_enable_work.work);
19232 WL_DBG(("Enter \n"));
19233 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19234 4 && __GNUC_MINOR__ >= 6))
19235 _Pragma("GCC diagnostic push")
19236 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19237 #endif
19238 for_each_ndev(cfg, iter, next) {
19239 /* p2p discovery iface ndev could be null */
19240 if (iter->ndev) {
19241 if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev) ||
19242 (wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_BSS &&
19243 wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_IBSS))
19244 continue;
19245 if (iter->ndev) {
19246 dhd = (dhd_pub_t *)(cfg->pub);
19247 if (dhd_conf_get_pm(dhd) >= 0)
19248 pm = dhd_conf_get_pm(dhd);
19249 if ((err = wldev_ioctl_set(iter->ndev, WLC_SET_PM,
19250 &pm, sizeof(pm))) != 0) {
19251 if (err == -ENODEV)
19252 WL_DBG(("%s:netdev not ready\n",
19253 iter->ndev->name));
19254 else
19255 WL_ERR(("%s:error (%d)\n",
19256 iter->ndev->name, err));
19257 } else
19258 wl_cfg80211_update_power_mode(iter->ndev);
19259 }
19260 }
19261 }
19262 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19263 4 && __GNUC_MINOR__ >= 6))
19264 _Pragma("GCC diagnostic pop")
19265 #endif
19266 DHD_PM_WAKE_UNLOCK(cfg->pub);
19267 }
19268
19269 u8
19270 wl_get_action_category(void *frame, u32 frame_len)
19271 {
19272 u8 category;
19273 u8 *ptr = (u8 *)frame;
19274 if (frame == NULL)
19275 return DOT11_ACTION_CAT_ERR_MASK;
19276 if (frame_len < DOT11_ACTION_HDR_LEN)
19277 return DOT11_ACTION_CAT_ERR_MASK;
19278 category = ptr[DOT11_ACTION_CAT_OFF];
19279 WL_INFORM(("Action Category: %d\n", category));
19280 return category;
19281 }
19282
19283 int
19284 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
19285 {
19286 u8 *ptr = (u8 *)frame;
19287 if (frame == NULL || ret_action == NULL)
19288 return BCME_ERROR;
19289 if (frame_len < DOT11_ACTION_HDR_LEN)
19290 return BCME_ERROR;
19291 if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
19292 return BCME_ERROR;
19293 *ret_action = ptr[DOT11_ACTION_ACT_OFF];
19294 WL_INFORM(("Public Action : %d\n", *ret_action));
19295 return BCME_OK;
19296 }
19297
19298
19299 static int
19300 wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
19301 const struct ether_addr *bssid)
19302 {
19303 s32 err;
19304 wl_event_msg_t e;
19305
19306 bzero(&e, sizeof(e));
19307 e.event_type = cpu_to_be32(WLC_E_ROAM);
19308 memcpy(&e.addr, bssid, ETHER_ADDR_LEN);
19309 /* trigger the roam event handler */
19310 err = wl_notify_roaming_status(cfg, ndev_to_cfgdev(ndev), &e, NULL);
19311
19312 return err;
19313 }
19314
19315 static s32
19316 wl_cfg80211_parse_vndr_ies(u8 *parse, u32 len,
19317 struct parsed_vndr_ies *vndr_ies)
19318 {
19319 s32 err = BCME_OK;
19320 vndr_ie_t *vndrie;
19321 bcm_tlv_t *ie;
19322 struct parsed_vndr_ie_info *parsed_info;
19323 u32 count = 0;
19324 s32 remained_len;
19325
19326 remained_len = (s32)len;
19327 memset(vndr_ies, 0, sizeof(*vndr_ies));
19328
19329 WL_DBG(("---> len %d\n", len));
19330 ie = (bcm_tlv_t *) parse;
19331 if (!bcm_valid_tlv(ie, remained_len))
19332 ie = NULL;
19333 while (ie) {
19334 if (count >= MAX_VNDR_IE_NUMBER)
19335 break;
19336 if (ie->id == DOT11_MNG_VS_ID) {
19337 vndrie = (vndr_ie_t *) ie;
19338 /* len should be bigger than OUI length + one data length at least */
19339 if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
19340 WL_ERR(("%s: invalid vndr ie. length is too small %d\n",
19341 __FUNCTION__, vndrie->len));
19342 goto end;
19343 }
19344 /* if wpa or wme ie, do not add ie */
19345 if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) &&
19346 ((vndrie->data[0] == WPA_OUI_TYPE) ||
19347 (vndrie->data[0] == WME_OUI_TYPE))) {
19348 WL_DBG(("Found WPA/WME oui. Do not add it\n"));
19349 goto end;
19350 }
19351
19352 parsed_info = &vndr_ies->ie_info[count++];
19353
19354 /* save vndr ie information */
19355 parsed_info->ie_ptr = (char *)vndrie;
19356 parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN);
19357 memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t));
19358 vndr_ies->count = count;
19359
19360 WL_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x len:%d\n",
19361 parsed_info->vndrie.oui[0], parsed_info->vndrie.oui[1],
19362 parsed_info->vndrie.oui[2], parsed_info->vndrie.data[0],
19363 parsed_info->ie_len));
19364 }
19365 end:
19366 ie = bcm_next_tlv(ie, &remained_len);
19367 }
19368 return err;
19369 }
19370
19371 #ifdef WLADPS_SEAK_AP_WAR
19372 static bool
19373 wl_find_vndr_ies_specific_vender(struct bcm_cfg80211 *cfg,
19374 struct net_device *ndev, const u8 *vndr_oui)
19375 {
19376 struct wl_connect_info *conn_info = wl_to_conn(cfg);
19377 struct parsed_vndr_ie_info *vndr_info_list;
19378 struct parsed_vndr_ies vndr_ies;
19379 bool ret = FALSE;
19380 int i;
19381
19382 if (conn_info->resp_ie_len) {
19383 if ((wl_cfg80211_parse_vndr_ies((u8 *)conn_info->resp_ie,
19384 conn_info->resp_ie_len, &vndr_ies)) == BCME_OK) {
19385 for (i = 0; i < vndr_ies.count; i++) {
19386 vndr_info_list = &vndr_ies.ie_info[i];
19387 if (!bcmp(vndr_info_list->vndrie.oui,
19388 (u8*)vndr_oui, DOT11_OUI_LEN)) {
19389 WL_ERR(("Find OUI %02x %02x %02x\n",
19390 vndr_info_list->vndrie.oui[0],
19391 vndr_info_list->vndrie.oui[1],
19392 vndr_info_list->vndrie.oui[2]));
19393 ret = TRUE;
19394 break;
19395 }
19396 }
19397 }
19398 }
19399 return ret;
19400 }
19401
19402 static s32
19403 wl_set_adps_mode(struct bcm_cfg80211 *cfg, struct net_device *ndev, uint8 enable_mode)
19404 {
19405 int i;
19406 int len;
19407 int ret = BCME_OK;
19408
19409 bcm_iov_buf_t *iov_buf = NULL;
19410 wl_adps_params_v1_t *data = NULL;
19411
19412 len = OFFSETOF(bcm_iov_buf_t, data) + sizeof(*data);
19413 iov_buf = kmalloc(len, GFP_KERNEL);
19414 if (iov_buf == NULL) {
19415 WL_ERR(("%s - failed to allocate %d bytes for iov_buf\n", __FUNCTION__, len));
19416 ret = BCME_NOMEM;
19417 goto exit;
19418 }
19419
19420 iov_buf->version = WL_ADPS_IOV_VER;
19421 iov_buf->len = sizeof(*data);
19422 iov_buf->id = WL_ADPS_IOV_MODE;
19423
19424 data = (wl_adps_params_v1_t *)iov_buf->data;
19425 data->version = ADPS_SUB_IOV_VERSION_1;
19426 data->length = sizeof(*data);
19427 data->mode = enable_mode;
19428
19429 for (i = 1; i <= MAX_BANDS; i++) {
19430 data->band = i;
19431 ret = wldev_iovar_setbuf(ndev, "adps", iov_buf, len,
19432 cfg->ioctl_buf, WLC_IOCTL_SMLEN, NULL);
19433 }
19434
19435 exit:
19436 if (iov_buf) {
19437 kfree(iov_buf);
19438 }
19439 return ret;
19440
19441 }
19442 #endif /* WLADPS_SEAK_AP_WAR */
19443
19444 static bool
19445 wl_vndr_ies_exclude_vndr_oui(struct parsed_vndr_ie_info *vndr_info)
19446 {
19447 int i = 0;
19448
19449 while (exclude_vndr_oui_list[i]) {
19450 if (!memcmp(vndr_info->vndrie.oui,
19451 exclude_vndr_oui_list[i],
19452 DOT11_OUI_LEN)) {
19453 return TRUE;
19454 }
19455 i++;
19456 }
19457
19458 return FALSE;
19459 }
19460
19461 static bool
19462 wl_vndr_ies_check_duplicate_vndr_oui(struct bcm_cfg80211 *cfg,
19463 struct parsed_vndr_ie_info *vndr_info)
19464 {
19465 wl_vndr_oui_entry_t *oui_entry = NULL;
19466
19467 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19468 #pragma GCC diagnostic push
19469 #pragma GCC diagnostic ignored "-Wcast-qual"
19470 #endif
19471 list_for_each_entry(oui_entry, &cfg->vndr_oui_list, list) {
19472 if (!memcmp(oui_entry->oui, vndr_info->vndrie.oui, DOT11_OUI_LEN)) {
19473 return TRUE;
19474 }
19475 }
19476 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19477 #pragma GCC diagnostic pop
19478 #endif
19479
19480 return FALSE;
19481 }
19482
19483 static bool
19484 wl_vndr_ies_add_vendor_oui_list(struct bcm_cfg80211 *cfg,
19485 struct parsed_vndr_ie_info *vndr_info)
19486 {
19487 wl_vndr_oui_entry_t *oui_entry = NULL;
19488
19489 oui_entry = kmalloc(sizeof(*oui_entry), GFP_KERNEL);
19490 if (oui_entry == NULL) {
19491 WL_ERR(("alloc failed\n"));
19492 return FALSE;
19493 }
19494
19495 memcpy(oui_entry->oui, vndr_info->vndrie.oui, DOT11_OUI_LEN);
19496
19497 INIT_LIST_HEAD(&oui_entry->list);
19498 list_add_tail(&oui_entry->list, &cfg->vndr_oui_list);
19499
19500 return TRUE;
19501 }
19502
19503 static void
19504 wl_vndr_ies_clear_vendor_oui_list(struct bcm_cfg80211 *cfg)
19505 {
19506 wl_vndr_oui_entry_t *oui_entry = NULL;
19507
19508 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19509 #pragma GCC diagnostic push
19510 #pragma GCC diagnostic ignored "-Wcast-qual"
19511 #endif
19512 while (!list_empty(&cfg->vndr_oui_list)) {
19513 oui_entry = list_entry(cfg->vndr_oui_list.next, wl_vndr_oui_entry_t, list);
19514 if (oui_entry) {
19515 list_del(&oui_entry->list);
19516 kfree(oui_entry);
19517 }
19518 }
19519 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19520 #pragma GCC diagnostic pop
19521 #endif
19522 }
19523
19524 static int
19525 wl_vndr_ies_get_vendor_oui(struct bcm_cfg80211 *cfg, struct net_device *ndev,
19526 char *vndr_oui, u32 vndr_oui_len)
19527 {
19528 int i;
19529 int vndr_oui_num = 0;
19530
19531 struct wl_connect_info *conn_info = wl_to_conn(cfg);
19532 wl_vndr_oui_entry_t *oui_entry = NULL;
19533 struct parsed_vndr_ie_info *vndr_info;
19534 struct parsed_vndr_ies vndr_ies;
19535
19536 char *pos = vndr_oui;
19537 u32 remained_buf_len = vndr_oui_len;
19538
19539 if (!conn_info->resp_ie_len) {
19540 return BCME_ERROR;
19541 }
19542
19543 wl_vndr_ies_clear_vendor_oui_list(cfg);
19544
19545 if ((wl_cfg80211_parse_vndr_ies((u8 *)conn_info->resp_ie,
19546 conn_info->resp_ie_len, &vndr_ies)) == BCME_OK) {
19547 for (i = 0; i < vndr_ies.count; i++) {
19548 vndr_info = &vndr_ies.ie_info[i];
19549 if (wl_vndr_ies_exclude_vndr_oui(vndr_info)) {
19550 continue;
19551 }
19552
19553 if (wl_vndr_ies_check_duplicate_vndr_oui(cfg, vndr_info)) {
19554 continue;
19555 }
19556
19557 wl_vndr_ies_add_vendor_oui_list(cfg, vndr_info);
19558 vndr_oui_num++;
19559 }
19560 }
19561
19562 if (vndr_oui) {
19563 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19564 #pragma GCC diagnostic push
19565 #pragma GCC diagnostic ignored "-Wcast-qual"
19566 #endif
19567 list_for_each_entry(oui_entry, &cfg->vndr_oui_list, list) {
19568 if (remained_buf_len < VNDR_OUI_STR_LEN) {
19569 return BCME_ERROR;
19570 }
19571 pos += snprintf(pos, VNDR_OUI_STR_LEN, "%02X-%02X-%02X ",
19572 oui_entry->oui[0], oui_entry->oui[1], oui_entry->oui[2]);
19573 remained_buf_len -= VNDR_OUI_STR_LEN;
19574 }
19575 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19576 #pragma GCC diagnostic pop
19577 #endif
19578 }
19579
19580 return vndr_oui_num;
19581 }
19582
19583 int
19584 wl_cfg80211_get_vndr_ouilist(struct bcm_cfg80211 *cfg, uint8 *buf, int max_cnt)
19585 {
19586 wl_vndr_oui_entry_t *oui_entry = NULL;
19587 int cnt = 0;
19588
19589 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19590 #pragma GCC diagnostic push
19591 #pragma GCC diagnostic ignored "-Wcast-qual"
19592 #endif
19593 list_for_each_entry(oui_entry, &cfg->vndr_oui_list, list) {
19594 memcpy(buf, oui_entry->oui, DOT11_OUI_LEN);
19595 cnt++;
19596 if (cnt >= max_cnt) {
19597 return cnt;
19598 }
19599 buf += DOT11_OUI_LEN;
19600 }
19601 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19602 #pragma GCC diagnostic pop
19603 #endif
19604 return cnt;
19605 }
19606
19607 s32
19608 wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, s32 bssidx)
19609 {
19610 s32 index;
19611 struct net_info *netinfo;
19612 s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG,
19613 VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
19614
19615 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
19616 if (!netinfo || !netinfo->wdev) {
19617 WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
19618 return -1;
19619 }
19620
19621 WL_DBG(("clear management vendor IEs for bssidx:%d \n", bssidx));
19622 /* Clear the IEs set in the firmware so that host is in sync with firmware */
19623 for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
19624 if (wl_cfg80211_set_mgmt_vndr_ies(cfg, wdev_to_cfgdev(netinfo->wdev),
19625 bssidx, vndrie_flag[index], NULL, 0) < 0)
19626 WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
19627 }
19628
19629 return 0;
19630 }
19631
19632 s32
19633 wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg)
19634 {
19635 struct net_info *iter, *next;
19636
19637 WL_DBG(("clear management vendor IEs \n"));
19638 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19639 4 && __GNUC_MINOR__ >= 6))
19640 _Pragma("GCC diagnostic push")
19641 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19642 #endif
19643 for_each_ndev(cfg, iter, next) {
19644 wl_cfg80211_clear_per_bss_ies(cfg, iter->bssidx);
19645 }
19646 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19647 4 && __GNUC_MINOR__ >= 6))
19648 _Pragma("GCC diagnostic pop")
19649 #endif
19650 return 0;
19651 }
19652
19653 #define WL_VNDR_IE_MAXLEN 2048
19654 static s8 g_mgmt_ie_buf[WL_VNDR_IE_MAXLEN];
19655 int
19656 wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
19657 s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
19658 {
19659 struct net_device *ndev = NULL;
19660 s32 ret = BCME_OK;
19661 u8 *curr_ie_buf = NULL;
19662 u8 *mgmt_ie_buf = NULL;
19663 u32 mgmt_ie_buf_len = 0;
19664 u32 *mgmt_ie_len = 0;
19665 u32 del_add_ie_buf_len = 0;
19666 u32 total_ie_buf_len = 0;
19667 u32 parsed_ie_buf_len = 0;
19668 struct parsed_vndr_ies old_vndr_ies;
19669 struct parsed_vndr_ies new_vndr_ies;
19670 s32 i;
19671 u8 *ptr;
19672 s32 remained_buf_len;
19673 wl_bss_vndr_ies_t *ies = NULL;
19674 struct net_info *netinfo;
19675
19676 WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d \n",
19677 pktflag, bssidx, vndr_ie_len));
19678
19679 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
19680
19681 if (bssidx > WL_MAX_IFS) {
19682 WL_ERR(("bssidx > supported concurrent Ifaces \n"));
19683 return -EINVAL;
19684 }
19685
19686 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
19687 if (!netinfo) {
19688 WL_ERR(("net_info ptr is NULL \n"));
19689 return -EINVAL;
19690 }
19691
19692 /* Clear the global buffer */
19693 memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf));
19694 curr_ie_buf = g_mgmt_ie_buf;
19695 ies = &netinfo->bss.ies;
19696
19697 switch (pktflag) {
19698 case VNDR_IE_PRBRSP_FLAG :
19699 mgmt_ie_buf = ies->probe_res_ie;
19700 mgmt_ie_len = &ies->probe_res_ie_len;
19701 mgmt_ie_buf_len = sizeof(ies->probe_res_ie);
19702 break;
19703 case VNDR_IE_ASSOCRSP_FLAG :
19704 mgmt_ie_buf = ies->assoc_res_ie;
19705 mgmt_ie_len = &ies->assoc_res_ie_len;
19706 mgmt_ie_buf_len = sizeof(ies->assoc_res_ie);
19707 break;
19708 case VNDR_IE_BEACON_FLAG :
19709 mgmt_ie_buf = ies->beacon_ie;
19710 mgmt_ie_len = &ies->beacon_ie_len;
19711 mgmt_ie_buf_len = sizeof(ies->beacon_ie);
19712 break;
19713 case VNDR_IE_PRBREQ_FLAG :
19714 mgmt_ie_buf = ies->probe_req_ie;
19715 mgmt_ie_len = &ies->probe_req_ie_len;
19716 mgmt_ie_buf_len = sizeof(ies->probe_req_ie);
19717 break;
19718 case VNDR_IE_ASSOCREQ_FLAG :
19719 mgmt_ie_buf = ies->assoc_req_ie;
19720 mgmt_ie_len = &ies->assoc_req_ie_len;
19721 mgmt_ie_buf_len = sizeof(ies->assoc_req_ie);
19722 break;
19723 default:
19724 mgmt_ie_buf = NULL;
19725 mgmt_ie_len = NULL;
19726 WL_ERR(("not suitable packet type (%d)\n", pktflag));
19727 return BCME_ERROR;
19728 }
19729
19730 if (vndr_ie_len > mgmt_ie_buf_len) {
19731 WL_ERR(("extra IE size too big\n"));
19732 ret = -ENOMEM;
19733 } else {
19734 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
19735 if (vndr_ie && vndr_ie_len && curr_ie_buf) {
19736 ptr = curr_ie_buf;
19737 /* must discard vndr_ie constness, attempt to change vndr_ie arg to non-const
19738 * causes cascade of errors in other places, fix involves const casts there
19739 */
19740 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19741 4 && __GNUC_MINOR__ >= 6))
19742 _Pragma("GCC diagnostic push")
19743 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19744 #endif
19745 if ((ret = wl_cfg80211_parse_vndr_ies((u8 *)vndr_ie,
19746 vndr_ie_len, &new_vndr_ies)) < 0) {
19747 WL_ERR(("parse vndr ie failed \n"));
19748 goto exit;
19749 }
19750 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19751 4 && __GNUC_MINOR__ >= 6))
19752 _Pragma("GCC diagnostic pop")
19753 #endif
19754 for (i = 0; i < new_vndr_ies.count; i++) {
19755 struct parsed_vndr_ie_info *vndrie_info =
19756 &new_vndr_ies.ie_info[i];
19757
19758 if ((parsed_ie_buf_len + vndrie_info->ie_len) > WL_VNDR_IE_MAXLEN) {
19759 WL_ERR(("IE size is too big (%d > %d)\n",
19760 parsed_ie_buf_len, WL_VNDR_IE_MAXLEN));
19761 ret = -EINVAL;
19762 goto exit;
19763 }
19764
19765 memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
19766 vndrie_info->ie_len);
19767 parsed_ie_buf_len += vndrie_info->ie_len;
19768 }
19769 }
19770
19771 if (mgmt_ie_buf != NULL) {
19772 if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
19773 (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) {
19774 WL_INFORM(("Previous mgmt IE is equals to current IE"));
19775 goto exit;
19776 }
19777
19778 /* parse old vndr_ie */
19779 if ((ret = wl_cfg80211_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len,
19780 &old_vndr_ies)) < 0) {
19781 WL_ERR(("parse vndr ie failed \n"));
19782 goto exit;
19783 }
19784 /* make a command to delete old ie */
19785 for (i = 0; i < old_vndr_ies.count; i++) {
19786 struct parsed_vndr_ie_info *vndrie_info =
19787 &old_vndr_ies.ie_info[i];
19788
19789 WL_INFORM(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
19790 vndrie_info->vndrie.id, vndrie_info->vndrie.len,
19791 vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
19792 vndrie_info->vndrie.oui[2]));
19793
19794 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
19795 pktflag, vndrie_info->vndrie.oui,
19796 vndrie_info->vndrie.id,
19797 vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
19798 vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
19799 "del");
19800
19801 curr_ie_buf += del_add_ie_buf_len;
19802 total_ie_buf_len += del_add_ie_buf_len;
19803 }
19804 }
19805
19806 *mgmt_ie_len = 0;
19807 /* Add if there is any extra IE */
19808 if (mgmt_ie_buf && parsed_ie_buf_len) {
19809 ptr = mgmt_ie_buf;
19810
19811 remained_buf_len = mgmt_ie_buf_len;
19812
19813 /* make a command to add new ie */
19814 for (i = 0; i < new_vndr_ies.count; i++) {
19815 struct parsed_vndr_ie_info *vndrie_info =
19816 &new_vndr_ies.ie_info[i];
19817
19818 WL_INFORM(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
19819 vndrie_info->vndrie.id, vndrie_info->vndrie.len,
19820 vndrie_info->ie_len - 2,
19821 vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
19822 vndrie_info->vndrie.oui[2]));
19823
19824 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
19825 pktflag, vndrie_info->vndrie.oui,
19826 vndrie_info->vndrie.id,
19827 vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
19828 vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
19829 "add");
19830
19831 /* verify remained buf size before copy data */
19832 if (remained_buf_len >= vndrie_info->ie_len) {
19833 remained_buf_len -= vndrie_info->ie_len;
19834 } else {
19835 WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
19836 "found vndr ies # = %d(cur %d), remained len %d, "
19837 "cur mgmt_ie_len %d, new ie len = %d\n",
19838 pktflag, new_vndr_ies.count, i, remained_buf_len,
19839 *mgmt_ie_len, vndrie_info->ie_len));
19840 break;
19841 }
19842
19843 /* save the parsed IE in cfg struct */
19844 memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
19845 vndrie_info->ie_len);
19846 *mgmt_ie_len += vndrie_info->ie_len;
19847 curr_ie_buf += del_add_ie_buf_len;
19848 total_ie_buf_len += del_add_ie_buf_len;
19849 }
19850 }
19851
19852 if (total_ie_buf_len && cfg->ioctl_buf != NULL) {
19853 ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
19854 total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
19855 bssidx, &cfg->ioctl_buf_sync);
19856 if (ret)
19857 WL_ERR(("vndr ie set error : %d\n", ret));
19858 }
19859 }
19860 exit:
19861
19862 return ret;
19863 }
19864
19865 #ifdef WL_CFG80211_ACL
19866 static int
19867 wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
19868 const struct cfg80211_acl_data *acl)
19869 {
19870 int i;
19871 int ret = 0;
19872 int macnum = 0;
19873 int macmode = MACLIST_MODE_DISABLED;
19874 struct maclist *list;
19875
19876 /* get the MAC filter mode */
19877 if (acl && acl->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED) {
19878 macmode = MACLIST_MODE_ALLOW;
19879 } else if (acl && acl->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
19880 acl->n_acl_entries) {
19881 macmode = MACLIST_MODE_DENY;
19882 }
19883
19884 /* if acl == NULL, macmode is still disabled.. */
19885 if (macmode == MACLIST_MODE_DISABLED) {
19886 if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, NULL)) != 0)
19887 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
19888
19889 return ret;
19890 }
19891
19892 macnum = acl->n_acl_entries;
19893 if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
19894 WL_ERR(("%s : invalid number of MAC address entries %d\n",
19895 __FUNCTION__, macnum));
19896 return -1;
19897 }
19898
19899 /* allocate memory for the MAC list */
19900 list = (struct maclist*)kmalloc(sizeof(int) +
19901 sizeof(struct ether_addr) * macnum, GFP_KERNEL);
19902 if (!list) {
19903 WL_ERR(("%s : failed to allocate memory\n", __FUNCTION__));
19904 return -1;
19905 }
19906
19907 /* prepare the MAC list */
19908 list->count = htod32(macnum);
19909 for (i = 0; i < macnum; i++) {
19910 memcpy(&list->ea[i], &acl->mac_addrs[i], ETHER_ADDR_LEN);
19911 }
19912 /* set the list */
19913 if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, list)) != 0)
19914 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
19915
19916 kfree(list);
19917
19918 return ret;
19919 }
19920 #endif /* WL_CFG80211_ACL */
19921
19922 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
19923 int wl_chspec_chandef(chanspec_t chanspec,
19924 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
19925 struct cfg80211_chan_def *chandef,
19926 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
19927 struct chan_info *chaninfo,
19928 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
19929 struct wiphy *wiphy)
19930
19931 {
19932 uint16 freq = 0;
19933 int chan_type = 0;
19934 int channel = 0;
19935 struct ieee80211_channel *chan;
19936
19937 if (!chandef) {
19938 return -1;
19939 }
19940 channel = CHSPEC_CHANNEL(chanspec);
19941
19942 switch (CHSPEC_BW(chanspec)) {
19943 case WL_CHANSPEC_BW_20:
19944 chan_type = NL80211_CHAN_HT20;
19945 break;
19946 case WL_CHANSPEC_BW_40:
19947 {
19948 if (CHSPEC_SB_UPPER(chanspec)) {
19949 channel += CH_10MHZ_APART;
19950 } else {
19951 channel -= CH_10MHZ_APART;
19952 }
19953 }
19954 chan_type = NL80211_CHAN_HT40PLUS;
19955 break;
19956
19957 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
19958 case WL_CHANSPEC_BW_80:
19959 case WL_CHANSPEC_BW_8080:
19960 {
19961 uint16 sb = CHSPEC_CTL_SB(chanspec);
19962
19963 if (sb == WL_CHANSPEC_CTL_SB_LL) {
19964 channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
19965 } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
19966 channel -= CH_10MHZ_APART;
19967 } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
19968 channel += CH_10MHZ_APART;
19969 } else {
19970 /* WL_CHANSPEC_CTL_SB_UU */
19971 channel += (CH_10MHZ_APART + CH_20MHZ_APART);
19972 }
19973
19974 if (sb == WL_CHANSPEC_CTL_SB_LL || sb == WL_CHANSPEC_CTL_SB_LU)
19975 chan_type = NL80211_CHAN_HT40MINUS;
19976 else if (sb == WL_CHANSPEC_CTL_SB_UL || sb == WL_CHANSPEC_CTL_SB_UU)
19977 chan_type = NL80211_CHAN_HT40PLUS;
19978 }
19979 break;
19980 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
19981 default:
19982 chan_type = NL80211_CHAN_HT20;
19983 break;
19984
19985 }
19986
19987 if (CHSPEC_IS5G(chanspec))
19988 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_5GHZ);
19989 else
19990 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
19991
19992 chan = ieee80211_get_channel(wiphy, freq);
19993 WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
19994 channel, freq, chan_type, chan));
19995
19996 if (unlikely(!chan)) {
19997 /* fw and cfg80211 channel lists are not in sync */
19998 WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
19999 ASSERT(0);
20000 return -EINVAL;
20001 }
20002
20003 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20004 cfg80211_chandef_create(chandef, chan, chan_type);
20005 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
20006 \
20007 \
20008 \
20009 0)))
20010 chaninfo->freq = freq;
20011 chaninfo->chan_type = chan_type;
20012 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20013 return 0;
20014 }
20015
20016 void
20017 wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
20018 {
20019 u32 freq;
20020 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20021 struct cfg80211_chan_def chandef;
20022 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
20023 \
20024 \
20025 \
20026 0)))
20027 struct chan_info chaninfo;
20028 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20029
20030 if (!wiphy) {
20031 printf("wiphy is null\n");
20032 return;
20033 }
20034 #ifndef ALLOW_CHSW_EVT
20035 /* Channel switch support is only for AP/GO/ADHOC/MESH */
20036 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
20037 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
20038 WL_ERR(("No channel switch notify support for STA/GC\n"));
20039 return;
20040 }
20041 #endif /* !ALLOW_CHSW_EVT */
20042 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20043 if (wl_chspec_chandef(chanspec, &chandef, wiphy))
20044 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
20045 if (wl_chspec_chandef(chanspec, &chaninfo, wiphy))
20046 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20047 {
20048 WL_ERR(("chspec_chandef failed\n"));
20049 return;
20050 }
20051 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20052 freq = chandef.chan ? chandef.chan->center_freq : chandef.center_freq1;
20053 cfg80211_ch_switch_notify(dev, &chandef);
20054 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
20055 freq = chan_info.freq;
20056 cfg80211_ch_switch_notify(dev, freq, chan_info.chan_type);
20057 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20058
20059 WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq, chanspec));
20060 return;
20061 }
20062 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20063
20064 #ifdef WL11ULB
20065 s32
20066 wl_cfg80211_set_ulb_mode(struct net_device *dev, int mode)
20067 {
20068 int ret;
20069 int cur_mode;
20070
20071 ret = wldev_iovar_getint(dev, "ulb_mode", &cur_mode);
20072 if (unlikely(ret)) {
20073 WL_ERR(("[ULB] ulb_mode get failed. ret:%d \n", ret));
20074 return ret;
20075 }
20076
20077 if (cur_mode == mode) {
20078 /* If request mode is same as that of the current mode, then
20079 * do nothing (Avoid unnecessary wl down and up).
20080 */
20081 WL_INFORM(("[ULB] No change in ulb_mode. Do nothing.\n"));
20082 return 0;
20083 }
20084
20085 /* setting of ulb_mode requires wl to be down */
20086 ret = wldev_ioctl_set(dev, WLC_DOWN, NULL, 0);
20087 if (unlikely(ret)) {
20088 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
20089 return ret;
20090 }
20091
20092 if (mode >= MAX_SUPP_ULB_MODES) {
20093 WL_ERR(("[ULB] unsupported ulb_mode :[%d]\n", mode));
20094 return -EINVAL;
20095 }
20096
20097 ret = wldev_iovar_setint(dev, "ulb_mode", mode);
20098 if (unlikely(ret)) {
20099 WL_ERR(("[ULB] ulb_mode set failed. ret:%d \n", ret));
20100 return ret;
20101 }
20102
20103 ret = wldev_ioctl_set(dev, WLC_UP, NULL, 0);
20104 if (unlikely(ret)) {
20105 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
20106 return ret;
20107 }
20108
20109 WL_DBG(("[ULB] ulb_mode set to %d successfully \n", mode));
20110
20111 return ret;
20112 }
20113
20114 static s32
20115 wl_cfg80211_ulbbw_to_ulbchspec(u32 bw)
20116 {
20117 if (bw == ULB_BW_DISABLED) {
20118 return WL_CHANSPEC_BW_20;
20119 } else if (bw == ULB_BW_10MHZ) {
20120 return WL_CHANSPEC_BW_10;
20121 } else if (bw == ULB_BW_5MHZ) {
20122 return WL_CHANSPEC_BW_5;
20123 } else if (bw == ULB_BW_2P5MHZ) {
20124 return WL_CHANSPEC_BW_2P5;
20125 } else {
20126 WL_ERR(("[ULB] unsupported value for ulb_bw \n"));
20127 return -EINVAL;
20128 }
20129 }
20130
20131 static chanspec_t
20132 wl_cfg80211_ulb_get_min_bw_chspec(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev, s32 bssidx)
20133 {
20134 struct net_info *_netinfo;
20135
20136 /*
20137 * Return the chspec value corresponding to the
20138 * BW setting for a particular interface
20139 */
20140 if (wdev) {
20141 /* if wdev is provided, use it */
20142 _netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
20143 } else if (bssidx >= 0) {
20144 /* if wdev is not provided, use it */
20145 _netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
20146 } else {
20147 WL_ERR(("[ULB] wdev/bssidx not provided\n"));
20148 return INVCHANSPEC;
20149 }
20150
20151 if (unlikely(!_netinfo)) {
20152 WL_ERR(("[ULB] net_info is null \n"));
20153 return INVCHANSPEC;
20154 }
20155
20156 if (_netinfo->ulb_bw) {
20157 WL_DBG(("[ULB] wdev_ptr:%p ulb_bw:0x%x \n", _netinfo->wdev, _netinfo->ulb_bw));
20158 return wl_cfg80211_ulbbw_to_ulbchspec(_netinfo->ulb_bw);
20159 } else {
20160 return WL_CHANSPEC_BW_20;
20161 }
20162 }
20163
20164 static s32
20165 wl_cfg80211_get_ulb_bw(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev)
20166 {
20167 struct net_info *_netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
20168
20169 /*
20170 * Return the ulb_bw setting for a
20171 * particular interface
20172 */
20173 if (unlikely(!_netinfo)) {
20174 WL_ERR(("[ULB] net_info is null \n"));
20175 return -1;
20176 }
20177
20178 return _netinfo->ulb_bw;
20179 }
20180
20181 s32
20182 wl_cfg80211_set_ulb_bw(struct net_device *dev,
20183 u32 ulb_bw, char *ifname)
20184 {
20185 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20186 int ret;
20187 int mode;
20188 struct net_info *_netinfo = NULL, *iter, *next;
20189 u32 bssidx;
20190
20191 if (!ifname)
20192 return -EINVAL;
20193
20194 WL_DBG(("[ULB] Enter. bw_type:%d \n", ulb_bw));
20195
20196 ret = wldev_iovar_getint(dev, "ulb_mode", &mode);
20197 if (unlikely(ret)) {
20198 WL_ERR(("[ULB] ulb_mode not supported \n"));
20199 return ret;
20200 }
20201
20202 if (mode != ULB_MODE_STD_ALONE_MODE) {
20203 WL_ERR(("[ULB] ulb bw modification allowed only in stand-alone mode\n"));
20204 return -EINVAL;
20205 }
20206
20207 if (ulb_bw >= MAX_SUPP_ULB_BW) {
20208 WL_ERR(("[ULB] unsupported value (%d) for ulb_bw \n", ulb_bw));
20209 return -EINVAL;
20210 }
20211
20212 #ifdef WL_CFG80211_P2P_DEV_IF
20213 if (strcmp(ifname, "p2p-dev-wlan0") == 0) {
20214 /* Use wdev corresponding to the dedicated p2p discovery interface */
20215 if (likely(cfg->p2p_wdev)) {
20216 _netinfo = wl_get_netinfo_by_wdev(cfg, cfg->p2p_wdev);
20217 } else {
20218 return -ENODEV;
20219 }
20220 }
20221 #endif /* WL_CFG80211_P2P_DEV_IF */
20222 if (!_netinfo) {
20223 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20224 #pragma GCC diagnostic push
20225 #pragma GCC diagnostic ignored "-Wcast-qual"
20226 #endif
20227 for_each_ndev(cfg, iter, next) {
20228 if (iter->ndev) {
20229 if (strncmp(iter->ndev->name, ifname, strlen(ifname)) == 0) {
20230 _netinfo = wl_get_netinfo_by_netdev(cfg, iter->ndev);
20231 }
20232 }
20233 }
20234 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20235 #pragma GCC diagnostic pop
20236 #endif
20237 }
20238
20239 if (!_netinfo)
20240 return -ENODEV;
20241 bssidx = _netinfo->bssidx;
20242 _netinfo->ulb_bw = ulb_bw;
20243
20244
20245 WL_DBG(("[ULB] Applying ulb_bw:%d for bssidx:%d \n", ulb_bw, bssidx));
20246 ret = wldev_iovar_setbuf_bsscfg(dev, "ulb_bw", (void *)&ulb_bw, 4,
20247 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx,
20248 &cfg->ioctl_buf_sync);
20249 if (unlikely(ret)) {
20250 WL_ERR(("[ULB] ulb_bw set failed. ret:%d \n", ret));
20251 return ret;
20252 }
20253
20254 return ret;
20255 }
20256 #endif /* WL11ULB */
20257
20258 static void
20259 wl_ap_channel_ind(struct bcm_cfg80211 *cfg,
20260 struct net_device *ndev,
20261 chanspec_t chanspec)
20262 {
20263 u32 channel = LCHSPEC_CHANNEL(chanspec);
20264
20265 WL_DBG(("(%s) AP channel:%d chspec:0x%x \n",
20266 ndev->name, channel, chanspec));
20267 if (cfg->ap_oper_channel && (cfg->ap_oper_channel != channel)) {
20268 /*
20269 * If cached channel is different from the channel indicated
20270 * by the event, notify user space about the channel switch.
20271 */
20272 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
20273 wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
20274 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20275 cfg->ap_oper_channel = channel;
20276 }
20277 }
20278
20279 static s32
20280 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
20281 const wl_event_msg_t *e, void *data)
20282 {
20283 struct net_device *ndev = NULL;
20284 chanspec_t chanspec;
20285
20286 WL_DBG(("Enter\n"));
20287 if (unlikely(e->status)) {
20288 WL_ERR(("status:0x%x \n", e->status));
20289 return -1;
20290 }
20291
20292 if (!data) {
20293 return -EINVAL;
20294 }
20295
20296 if (likely(cfgdev)) {
20297 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
20298 chanspec = *((chanspec_t *)data);
20299
20300 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
20301 /* For AP/GO role */
20302 wl_ap_channel_ind(cfg, ndev, chanspec);
20303 }
20304 }
20305
20306 return 0;
20307 }
20308
20309 static s32
20310 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
20311 const wl_event_msg_t *e, void *data)
20312 {
20313 int error = 0;
20314 u32 chanspec = 0;
20315 struct net_device *ndev = NULL;
20316
20317 WL_DBG(("Enter\n"));
20318 if (unlikely(e->status)) {
20319 WL_ERR(("status:0x%x \n", e->status));
20320 return -1;
20321 }
20322
20323 if (likely(cfgdev)) {
20324 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
20325 error = wldev_iovar_getint(ndev, "chanspec", &chanspec);
20326 if (unlikely(error)) {
20327 WL_ERR(("Get chanspec error: %d \n", error));
20328 return -1;
20329 }
20330
20331 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
20332 /* For AP/GO role */
20333 wl_ap_channel_ind(cfg, ndev, chanspec);
20334 } else {
20335 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
20336 wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
20337 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20338 }
20339
20340 }
20341
20342 return 0;
20343 }
20344
20345
20346 void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg)
20347 {
20348 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
20349 int err;
20350
20351 /* Clear the security settings on the primary Interface */
20352 err = wldev_iovar_setint(dev, "wsec", 0);
20353 if (unlikely(err)) {
20354 WL_ERR(("wsec clear failed \n"));
20355 }
20356 err = wldev_iovar_setint(dev, "auth", 0);
20357 if (unlikely(err)) {
20358 WL_ERR(("auth clear failed \n"));
20359 }
20360 err = wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
20361 if (unlikely(err)) {
20362 WL_ERR(("wpa_auth clear failed \n"));
20363 }
20364 }
20365
20366 #ifdef WL_CFG80211_P2P_DEV_IF
20367 void wl_cfg80211_del_p2p_wdev(struct net_device *dev)
20368 {
20369 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20370 struct wireless_dev *wdev = NULL;
20371
20372 WL_DBG(("Enter \n"));
20373 if (!cfg) {
20374 WL_ERR(("Invalid Ptr\n"));
20375 return;
20376 } else {
20377 wdev = cfg->p2p_wdev;
20378 }
20379
20380 if (wdev && cfg->down_disc_if) {
20381 wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
20382 cfg->down_disc_if = FALSE;
20383 }
20384 }
20385 #endif /* WL_CFG80211_P2P_DEV_IF */
20386
20387 #ifdef GTK_OFFLOAD_SUPPORT
20388 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
20389 static s32
20390 wl_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
20391 struct cfg80211_gtk_rekey_data *data)
20392 {
20393 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
20394 s32 err = 0;
20395 gtk_keyinfo_t keyinfo;
20396
20397 WL_DBG(("Enter\n"));
20398 if (data == NULL || cfg->p2p_net == dev) {
20399 WL_ERR(("data is NULL or wrong net device\n"));
20400 return -EINVAL;
20401 }
20402 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
20403 prhex("kck", (uchar *) (data->kck), RSN_KCK_LENGTH);
20404 prhex("kek", (uchar *) (data->kek), RSN_KEK_LENGTH);
20405 prhex("replay_ctr", (uchar *) (data->replay_ctr), RSN_REPLAY_LEN);
20406 #else
20407 prhex("kck", (uchar *)data->kck, RSN_KCK_LENGTH);
20408 prhex("kek", (uchar *)data->kek, RSN_KEK_LENGTH);
20409 prhex("replay_ctr", (uchar *)data->replay_ctr, RSN_REPLAY_LEN);
20410 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) */
20411 bcopy(data->kck, keyinfo.KCK, RSN_KCK_LENGTH);
20412 bcopy(data->kek, keyinfo.KEK, RSN_KEK_LENGTH);
20413 bcopy(data->replay_ctr, keyinfo.ReplayCounter, RSN_REPLAY_LEN);
20414
20415 if ((err = wldev_iovar_setbuf(dev, "gtk_key_info", &keyinfo, sizeof(keyinfo),
20416 cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync)) < 0) {
20417 WL_ERR(("seting gtk_key_info failed code=%d\n", err));
20418 return err;
20419 }
20420 WL_DBG(("Exit\n"));
20421 return err;
20422 }
20423 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
20424 #endif /* GTK_OFFLOAD_SUPPORT */
20425
20426 #if defined(WL_SUPPORT_AUTO_CHANNEL)
20427 int
20428 wl_cfg80211_set_spect(struct net_device *dev, int spect)
20429 {
20430 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20431 int wlc_down = 1;
20432 int wlc_up = 1;
20433 int err = BCME_OK;
20434
20435 if (!wl_get_drv_status_all(cfg, CONNECTED)) {
20436 err = wldev_ioctl_set(dev, WLC_DOWN, &wlc_down, sizeof(wlc_down));
20437 if (err) {
20438 WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__, err));
20439 return err;
20440 }
20441
20442 err = wldev_ioctl_set(dev, WLC_SET_SPECT_MANAGMENT, &spect, sizeof(spect));
20443 if (err) {
20444 WL_ERR(("%s: error setting spect: code: %d\n", __func__, err));
20445 return err;
20446 }
20447
20448 err = wldev_ioctl_set(dev, WLC_UP, &wlc_up, sizeof(wlc_up));
20449 if (err) {
20450 WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__, err));
20451 return err;
20452 }
20453 }
20454 return err;
20455 }
20456
20457 int
20458 wl_cfg80211_get_sta_channel(struct net_device *dev)
20459 {
20460 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20461 int channel = 0;
20462
20463 if (wl_get_drv_status(cfg, CONNECTED, dev)) {
20464 channel = cfg->channel;
20465 }
20466 return channel;
20467 }
20468 #endif /* WL_SUPPORT_AUTO_CHANNEL */
20469 #ifdef P2P_LISTEN_OFFLOADING
20470 s32
20471 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg)
20472 {
20473 s32 bssidx;
20474 int ret = 0;
20475 int p2plo_pause = 0;
20476 if (!cfg || !cfg->p2p) {
20477 WL_ERR(("Wl %p or cfg->p2p %p is null\n",
20478 cfg, cfg ? cfg->p2p : 0));
20479 return 0;
20480 }
20481
20482 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
20483 ret = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg),
20484 "p2po_stop", (void*)&p2plo_pause, sizeof(p2plo_pause),
20485 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
20486 if (ret < 0) {
20487 WL_ERR(("p2po_stop Failed :%d\n", ret));
20488 }
20489
20490 return ret;
20491 }
20492 s32
20493 wl_cfg80211_p2plo_listen_start(struct net_device *dev, u8 *buf, int len)
20494 {
20495 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20496 s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
20497 wl_p2plo_listen_t p2plo_listen;
20498 int ret = -EAGAIN;
20499 int channel = 0;
20500 int period = 0;
20501 int interval = 0;
20502 int count = 0;
20503 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
20504 WL_ERR(("Sending Action Frames. Try it again.\n"));
20505 goto exit;
20506 }
20507
20508 if (wl_get_drv_status_all(cfg, SCANNING)) {
20509 WL_ERR(("Scanning already\n"));
20510 goto exit;
20511 }
20512
20513 if (wl_get_drv_status(cfg, SCAN_ABORTING, dev)) {
20514 WL_ERR(("Scanning being aborted\n"));
20515 goto exit;
20516 }
20517
20518 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
20519 WL_ERR(("p2p listen offloading already running\n"));
20520 goto exit;
20521 }
20522
20523 /* Just in case if it is not enabled */
20524 if ((ret = wl_cfgp2p_enable_discovery(cfg, dev, NULL, 0)) < 0) {
20525 WL_ERR(("cfgp2p_enable discovery failed"));
20526 goto exit;
20527 }
20528
20529 bzero(&p2plo_listen, sizeof(wl_p2plo_listen_t));
20530
20531 if (len) {
20532 sscanf(buf, " %10d %10d %10d %10d", &channel, &period, &interval, &count);
20533 if ((channel == 0) || (period == 0) ||
20534 (interval == 0) || (count == 0)) {
20535 WL_ERR(("Wrong argument %d/%d/%d/%d \n",
20536 channel, period, interval, count));
20537 ret = -EAGAIN;
20538 goto exit;
20539 }
20540 p2plo_listen.period = period;
20541 p2plo_listen.interval = interval;
20542 p2plo_listen.count = count;
20543
20544 WL_ERR(("channel:%d period:%d, interval:%d count:%d\n",
20545 channel, period, interval, count));
20546 } else {
20547 WL_ERR(("Argument len is wrong.\n"));
20548 ret = -EAGAIN;
20549 goto exit;
20550 }
20551
20552 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
20553 sizeof(channel), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
20554 bssidx, &cfg->ioctl_buf_sync)) < 0) {
20555 WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
20556 goto exit;
20557 }
20558
20559 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&p2plo_listen,
20560 sizeof(wl_p2plo_listen_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
20561 bssidx, &cfg->ioctl_buf_sync)) < 0) {
20562 WL_ERR(("p2po_listen Failed :%d\n", ret));
20563 goto exit;
20564 }
20565
20566 wl_set_p2p_status(cfg, DISC_IN_PROGRESS);
20567 exit :
20568 return ret;
20569 }
20570 s32
20571 wl_cfg80211_p2plo_listen_stop(struct net_device *dev)
20572 {
20573 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20574 s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
20575 int ret = -EAGAIN;
20576
20577 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop", NULL,
20578 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN,
20579 bssidx, &cfg->ioctl_buf_sync)) < 0) {
20580 WL_ERR(("p2po_stop Failed :%d\n", ret));
20581 goto exit;
20582 }
20583
20584 exit:
20585 return ret;
20586 }
20587 #endif /* P2P_LISTEN_OFFLOADING */
20588
20589 u64
20590 wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg)
20591 {
20592 u64 id = 0;
20593 id = ++cfg->last_roc_id;
20594 #ifdef P2P_LISTEN_OFFLOADING
20595 if (id == P2PO_COOKIE) {
20596 id = ++cfg->last_roc_id;
20597 }
20598 #endif /* P2P_LISTEN_OFFLOADING */
20599 if (id == 0)
20600 id = ++cfg->last_roc_id;
20601 return id;
20602 }
20603
20604 #if defined(SUPPORT_RANDOM_MAC_SCAN)
20605 int
20606 wl_cfg80211_set_random_mac(struct net_device *dev, bool enable)
20607 {
20608 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20609 int ret;
20610
20611 if (cfg->random_mac_enabled == enable) {
20612 WL_ERR(("Random MAC already %s\n", enable ? "Enabled" : "Disabled"));
20613 return BCME_OK;
20614 }
20615
20616 if (enable) {
20617 ret = wl_cfg80211_random_mac_enable(dev);
20618 } else {
20619 ret = wl_cfg80211_random_mac_disable(dev);
20620 }
20621
20622 if (!ret) {
20623 cfg->random_mac_enabled = enable;
20624 }
20625
20626 return ret;
20627 }
20628
20629 int
20630 wl_cfg80211_random_mac_enable(struct net_device *dev)
20631 {
20632 u8 random_mac[ETH_ALEN] = {0, };
20633 u8 rand_bytes[3] = {0, };
20634 s32 err = BCME_ERROR;
20635 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20636
20637 if (wl_get_drv_status_all(cfg, CONNECTED) || wl_get_drv_status_all(cfg, CONNECTING) ||
20638 wl_get_drv_status_all(cfg, AP_CREATED) || wl_get_drv_status_all(cfg, AP_CREATING)) {
20639 WL_ERR(("fail to Set random mac, current state is wrong\n"));
20640 return err;
20641 }
20642
20643 memcpy(random_mac, bcmcfg_to_prmry_ndev(cfg)->dev_addr, ETH_ALEN);
20644 get_random_bytes(&rand_bytes, sizeof(rand_bytes));
20645
20646 if (rand_bytes[2] == 0x0 || rand_bytes[2] == 0xff) {
20647 rand_bytes[2] = 0xf0;
20648 }
20649
20650 memcpy(&random_mac[3], rand_bytes, sizeof(rand_bytes));
20651
20652 err = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr",
20653 random_mac, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
20654
20655 if (err != BCME_OK) {
20656 WL_ERR(("failed to set random generate MAC address\n"));
20657 } else {
20658 WL_ERR(("set mac " MACDBG " to " MACDBG "\n",
20659 MAC2STRDBG((const u8 *)bcmcfg_to_prmry_ndev(cfg)->dev_addr),
20660 MAC2STRDBG((const u8 *)&random_mac)));
20661 WL_ERR(("random MAC enable done"));
20662 }
20663
20664 return err;
20665 }
20666
20667 int
20668 wl_cfg80211_random_mac_disable(struct net_device *dev)
20669 {
20670 s32 err = BCME_ERROR;
20671 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20672
20673 WL_ERR(("set original mac " MACDBG "\n",
20674 MAC2STRDBG((const u8 *)bcmcfg_to_prmry_ndev(cfg)->dev_addr)));
20675
20676 err = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr",
20677 bcmcfg_to_prmry_ndev(cfg)->dev_addr, ETH_ALEN,
20678 cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
20679
20680 if (err != BCME_OK) {
20681 WL_ERR(("failed to set original MAC address\n"));
20682 } else {
20683 WL_ERR(("random MAC disable done\n"));
20684 }
20685
20686 return err;
20687 }
20688 #endif /* SUPPORT_RANDOM_MAC_SCAN */
20689
20690 #ifdef WLTDLS
20691 static s32
20692 wl_cfg80211_tdls_config(struct bcm_cfg80211 *cfg, enum wl_tdls_config state, bool auto_mode)
20693 {
20694 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
20695 int err = 0;
20696 struct net_info *iter, *next;
20697 int update_reqd = 0;
20698 int enable = 0;
20699 dhd_pub_t *dhdp;
20700 dhdp = (dhd_pub_t *)(cfg->pub);
20701
20702 /*
20703 * TDLS need to be enabled only if we have a single STA/GC
20704 * connection.
20705 */
20706
20707 WL_DBG(("Enter state:%d\n", state));
20708
20709 if (!cfg->tdls_supported) {
20710 /* FW doesn't support tdls. Do nothing */
20711 return -ENODEV;
20712 }
20713
20714 /* Protect tdls config session */
20715 mutex_lock(&cfg->tdls_sync);
20716
20717 if ((state == TDLS_STATE_TEARDOWN)) {
20718 /* Host initiated TDLS tear down */
20719 err = dhd_tdls_enable(ndev, false, auto_mode, NULL);
20720 goto exit;
20721 } else if (state == TDLS_STATE_AP_CREATE) {
20722 /* We don't support tdls while AP/GO is operational */
20723 update_reqd = true;
20724 enable = false;
20725 } else if ((state == TDLS_STATE_CONNECT) || (state == TDLS_STATE_IF_CREATE)) {
20726 if (wl_get_drv_status_all(cfg,
20727 CONNECTED) >= TDLS_MAX_IFACE_FOR_ENABLE) {
20728 /* For STA/GC connect command request, disable
20729 * tdls if we have any concurrent interfaces
20730 * operational.
20731 */
20732 WL_DBG(("Interface limit restriction. disable tdls.\n"));
20733 update_reqd = true;
20734 enable = false;
20735 }
20736 } else if ((state == TDLS_STATE_DISCONNECT) ||
20737 (state == TDLS_STATE_AP_DELETE) ||
20738 (state == TDLS_STATE_SETUP) ||
20739 (state == TDLS_STATE_IF_DELETE)) {
20740 /* Enable back the tdls connection only if we have less than
20741 * or equal to a single STA/GC connection.
20742 */
20743 if (wl_get_drv_status_all(cfg,
20744 CONNECTED) == 0) {
20745 /* If there are no interfaces connected, enable tdls */
20746 update_reqd = true;
20747 enable = true;
20748 } else if (wl_get_drv_status_all(cfg,
20749 CONNECTED) == TDLS_MAX_IFACE_FOR_ENABLE) {
20750 /* We have one interface in CONNECTED state.
20751 * Verify whether its a non-AP interface before
20752 * we enable back tdls.
20753 */
20754 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20755 #pragma GCC diagnostic push
20756 #pragma GCC diagnostic ignored "-Wcast-qual"
20757 #endif
20758 for_each_ndev(cfg, iter, next) {
20759 if ((iter->ndev) && (wl_get_drv_status(cfg, CONNECTED, ndev)) &&
20760 wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
20761 WL_DBG(("AP/GO operational. Can't enable tdls. \n"));
20762 err = -ENOTSUPP;
20763 goto exit;
20764 }
20765 }
20766 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20767 #pragma GCC diagnostic pop
20768 #endif
20769 /* No AP/GO found. Enable back tdls */
20770 update_reqd = true;
20771 enable = true;
20772 } else {
20773 WL_DBG(("Concurrent connection mode. Can't enable tdls. \n"));
20774 err = -ENOTSUPP;
20775 goto exit;
20776 }
20777 } else {
20778 WL_ERR(("Unknown tdls state:%d \n", state));
20779 err = -EINVAL;
20780 goto exit;
20781 }
20782
20783 if (update_reqd == true) {
20784 if (dhdp->tdls_enable == enable) {
20785 WL_ERR(("No change in tdls state. Do nothing."
20786 " tdls_enable:%d\n", enable));
20787 goto exit;
20788 }
20789 err = wldev_iovar_setint(ndev, "tdls_enable", enable);
20790 if (unlikely(err)) {
20791 WL_ERR(("tdls_enable setting failed. err:%d\n", err));
20792 goto exit;
20793 } else {
20794 WL_DBG(("set tdls_enable: %d done\n", enable));
20795 /* Update the dhd state variable to be in sync */
20796 dhdp->tdls_enable = enable;
20797 if (state == TDLS_STATE_SETUP) {
20798 /* For host initiated setup, apply TDLS params
20799 * Don't propagate errors up for param config
20800 * failures
20801 */
20802 dhd_tdls_enable(ndev, true, auto_mode, NULL);
20803
20804 }
20805 }
20806 } else {
20807 WL_DBG(("Skip tdls config. state:%d update_reqd:%d "
20808 "current_status:%d \n",
20809 state, update_reqd, dhdp->tdls_enable));
20810 }
20811
20812 exit:
20813 mutex_unlock(&cfg->tdls_sync);
20814
20815 return err;
20816 }
20817 #endif /* WLTDLS */
20818
20819 struct net_device* wl_get_ap_netdev(struct bcm_cfg80211 *cfg, char *ifname)
20820 {
20821 struct net_info *iter, *next;
20822 struct net_device *ndev = NULL;
20823
20824 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20825 #pragma GCC diagnostic push
20826 #pragma GCC diagnostic ignored "-Wcast-qual"
20827 #endif
20828 for_each_ndev(cfg, iter, next) {
20829 if (iter->ndev) {
20830 if (strncmp(iter->ndev->name, ifname, strlen(iter->ndev->name)) == 0) {
20831 if (iter->ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
20832 ndev = iter->ndev;
20833 break;
20834 }
20835 }
20836 }
20837 }
20838 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20839 #pragma GCC diagnostic pop
20840 #endif
20841
20842 return ndev;
20843 }
20844
20845 struct net_device*
20846 wl_get_netdev_by_name(struct bcm_cfg80211 *cfg, char *ifname)
20847 {
20848 struct net_info *iter, *next;
20849 struct net_device *ndev = NULL;
20850
20851 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20852 #pragma GCC diagnostic push
20853 #pragma GCC diagnostic ignored "-Wcast-qual"
20854 #endif
20855 for_each_ndev(cfg, iter, next) {
20856 if (iter->ndev) {
20857 if (strncmp(iter->ndev->name, ifname, IFNAMSIZ) == 0) {
20858 ndev = iter->ndev;
20859 break;
20860 }
20861 }
20862 }
20863 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20864 #pragma GCC diagnostic pop
20865 #endif
20866
20867 return ndev;
20868 }
20869
20870 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
20871 #define WLC_RATE_FLAG 0x80
20872 #define RATE_MASK 0x7f
20873
20874 int wl_set_ap_beacon_rate(struct net_device *dev, int val, char *ifname)
20875 {
20876 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20877 dhd_pub_t *dhdp;
20878 wl_rateset_args_t rs;
20879 int error = BCME_ERROR, i;
20880 struct net_device *ndev = NULL;
20881
20882 dhdp = (dhd_pub_t *)(cfg->pub);
20883
20884 if (dhdp && !(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
20885 WL_ERR(("Not Hostapd mode\n"));
20886 return BCME_NOTAP;
20887 }
20888
20889 ndev = wl_get_ap_netdev(cfg, ifname);
20890
20891 if (ndev == NULL) {
20892 WL_ERR(("No softAP interface named %s\n", ifname));
20893 return BCME_NOTAP;
20894 }
20895
20896 bzero(&rs, sizeof(wl_rateset_args_t));
20897 error = wldev_iovar_getbuf(ndev, "rateset", NULL, 0,
20898 &rs, sizeof(wl_rateset_args_t), NULL);
20899 if (error < 0) {
20900 WL_ERR(("get rateset failed = %d\n", error));
20901 return error;
20902 }
20903
20904 if (rs.count < 1) {
20905 WL_ERR(("Failed to get rate count\n"));
20906 return BCME_ERROR;
20907 }
20908
20909 /* Host delivers target rate in the unit of 500kbps */
20910 /* To make it to 1mbps unit, atof should be implemented for 5.5mbps basic rate */
20911 for (i = 0; i < rs.count && i < WL_NUMRATES; i++)
20912 if (rs.rates[i] & WLC_RATE_FLAG)
20913 if ((rs.rates[i] & RATE_MASK) == val)
20914 break;
20915
20916 /* Valid rate has been delivered as an argument */
20917 if (i < rs.count && i < WL_NUMRATES) {
20918 error = wldev_iovar_setint(ndev, "force_bcn_rspec", val);
20919 if (error < 0) {
20920 WL_ERR(("set beacon rate failed = %d\n", error));
20921 return BCME_ERROR;
20922 }
20923 } else {
20924 WL_ERR(("Rate is invalid"));
20925 return BCME_BADARG;
20926 }
20927
20928 return BCME_OK;
20929 }
20930
20931 int
20932 wl_get_ap_basic_rate(struct net_device *dev, char* command, char *ifname, int total_len)
20933 {
20934 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20935 dhd_pub_t *dhdp;
20936 wl_rateset_args_t rs;
20937 int error = BCME_ERROR;
20938 int i, bytes_written = 0;
20939 struct net_device *ndev = NULL;
20940
20941 dhdp = (dhd_pub_t *)(cfg->pub);
20942
20943 if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
20944 WL_ERR(("Not Hostapd mode\n"));
20945 return BCME_NOTAP;
20946 }
20947
20948 ndev = wl_get_ap_netdev(cfg, ifname);
20949
20950 if (ndev == NULL) {
20951 WL_ERR(("No softAP interface named %s\n", ifname));
20952 return BCME_NOTAP;
20953 }
20954
20955 bzero(&rs, sizeof(wl_rateset_args_t));
20956 error = wldev_iovar_getbuf(ndev, "rateset", NULL, 0,
20957 &rs, sizeof(wl_rateset_args_t), NULL);
20958 if (error < 0) {
20959 WL_ERR(("get rateset failed = %d\n", error));
20960 return error;
20961 }
20962
20963 if (rs.count < 1) {
20964 WL_ERR(("Failed to get rate count\n"));
20965 return BCME_ERROR;
20966 }
20967
20968 /* Delivers basic rate in the unit of 500kbps to host */
20969 for (i = 0; i < rs.count && i < WL_NUMRATES; i++)
20970 if (rs.rates[i] & WLC_RATE_FLAG)
20971 bytes_written += snprintf(command + bytes_written, total_len,
20972 "%d ", rs.rates[i] & RATE_MASK);
20973
20974 /* Remove last space in the command buffer */
20975 if (bytes_written) {
20976 command[bytes_written - 1] = '\0';
20977 bytes_written--;
20978 }
20979
20980 return bytes_written;
20981
20982 }
20983 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
20984
20985 #ifdef SUPPORT_AP_RADIO_PWRSAVE
20986 static int
20987 _wl_update_ap_rps_params(struct net_device *dev)
20988 {
20989 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20990 rpsnoa_iovar_params_t iovar;
20991 u8 smbuf[WLC_IOCTL_SMLEN];
20992
20993 if (!dev)
20994 return BCME_BADARG;
20995
20996 memset(&iovar, 0, sizeof(iovar));
20997 memset(smbuf, 0, sizeof(smbuf));
20998
20999 iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
21000 iovar.hdr.subcmd = WL_RPSNOA_CMD_PARAMS;
21001 iovar.hdr.len = sizeof(iovar);
21002 iovar.param->band = WLC_BAND_ALL;
21003 iovar.param->level = cfg->ap_rps_info.level;
21004 iovar.param->stas_assoc_check = cfg->ap_rps_info.sta_assoc_check;
21005 iovar.param->pps = cfg->ap_rps_info.pps;
21006 iovar.param->quiet_time = cfg->ap_rps_info.quiet_time;
21007
21008 if (wldev_iovar_setbuf(dev, "rpsnoa", &iovar, sizeof(iovar),
21009 smbuf, sizeof(smbuf), NULL)) {
21010 WL_ERR(("Failed to set rpsnoa params"));
21011 return BCME_ERROR;
21012 }
21013
21014 return BCME_OK;
21015 }
21016
21017 int
21018 wl_get_ap_rps(struct net_device *dev, char* command, char *ifname, int total_len)
21019 {
21020 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21021 dhd_pub_t *dhdp;
21022 int error = BCME_ERROR;
21023 int bytes_written = 0;
21024 struct net_device *ndev = NULL;
21025 rpsnoa_iovar_t iovar;
21026 u8 smbuf[WLC_IOCTL_SMLEN];
21027 u32 chanspec = 0;
21028 u8 idx = 0;
21029 u8 val;
21030
21031 dhdp = (dhd_pub_t *)(cfg->pub);
21032
21033 if (!dhdp) {
21034 error = BCME_NOTUP;
21035 goto fail;
21036 }
21037
21038 if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
21039 WL_ERR(("Not Hostapd mode\n"));
21040 error = BCME_NOTAP;
21041 goto fail;
21042 }
21043
21044 ndev = wl_get_ap_netdev(cfg, ifname);
21045
21046 if (ndev == NULL) {
21047 WL_ERR(("No softAP interface named %s\n", ifname));
21048 error = BCME_NOTAP;
21049 goto fail;
21050 }
21051
21052 memset(&iovar, 0, sizeof(iovar));
21053 memset(smbuf, 0, sizeof(smbuf));
21054
21055 iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
21056 iovar.hdr.subcmd = WL_RPSNOA_CMD_STATUS;
21057 iovar.hdr.len = sizeof(iovar);
21058 iovar.data->band = WLC_BAND_ALL;
21059
21060 error = wldev_iovar_getbuf(ndev, "rpsnoa", &iovar, sizeof(iovar),
21061 smbuf, sizeof(smbuf), NULL);
21062 if (error < 0) {
21063 WL_ERR(("get ap radio pwrsave failed = %d\n", error));
21064 goto fail;
21065 }
21066
21067 /* RSDB event doesn't seem to be handled correctly.
21068 * So check chanspec of AP directly from the firmware
21069 */
21070 error = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
21071 if (error < 0) {
21072 WL_ERR(("get chanspec from AP failed = %d\n", error));
21073 goto fail;
21074 }
21075
21076 chanspec = wl_chspec_driver_to_host(chanspec);
21077 if (CHSPEC_IS2G(chanspec))
21078 idx = 0;
21079 else if (CHSPEC_IS5G(chanspec))
21080 idx = 1;
21081 else {
21082 error = BCME_BADCHAN;
21083 goto fail;
21084 }
21085
21086 val = ((rpsnoa_iovar_t *)smbuf)->data[idx].value;
21087 bytes_written += snprintf(command + bytes_written, total_len, "%d", val);
21088 error = bytes_written;
21089
21090 fail:
21091 return error;
21092 }
21093
21094 int
21095 wl_set_ap_rps(struct net_device *dev, bool enable, char *ifname)
21096 {
21097 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21098 dhd_pub_t *dhdp;
21099 struct net_device *ndev = NULL;
21100 rpsnoa_iovar_t iovar;
21101 u8 smbuf[WLC_IOCTL_SMLEN];
21102 int ret = BCME_OK;
21103
21104 dhdp = (dhd_pub_t *)(cfg->pub);
21105
21106 if (!dhdp) {
21107 ret = BCME_NOTUP;
21108 goto exit;
21109 }
21110
21111 if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
21112 WL_ERR(("Not Hostapd mode\n"));
21113 ret = BCME_NOTAP;
21114 goto exit;
21115 }
21116
21117 ndev = wl_get_ap_netdev(cfg, ifname);
21118
21119 if (ndev == NULL) {
21120 WL_ERR(("No softAP interface named %s\n", ifname));
21121 ret = BCME_NOTAP;
21122 goto exit;
21123 }
21124
21125 if (cfg->ap_rps_info.enable != enable) {
21126 cfg->ap_rps_info.enable = enable;
21127 if (enable) {
21128 ret = _wl_update_ap_rps_params(ndev);
21129 if (ret) {
21130 WL_ERR(("Filed to update rpsnoa params\n"));
21131 goto exit;
21132 }
21133 }
21134 memset(&iovar, 0, sizeof(iovar));
21135 memset(smbuf, 0, sizeof(smbuf));
21136
21137 iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
21138 iovar.hdr.subcmd = WL_RPSNOA_CMD_ENABLE;
21139 iovar.hdr.len = sizeof(iovar);
21140 iovar.data->band = WLC_BAND_ALL;
21141 iovar.data->value = (int16)enable;
21142
21143 ret = wldev_iovar_setbuf(ndev, "rpsnoa", &iovar, sizeof(iovar),
21144 smbuf, sizeof(smbuf), NULL);
21145 if (ret) {
21146 WL_ERR(("Failed to enable AP radio power save"));
21147 goto exit;
21148 }
21149 cfg->ap_rps_info.enable = enable;
21150 }
21151 exit:
21152 return ret;
21153 }
21154
21155 int
21156 wl_update_ap_rps_params(struct net_device *dev, ap_rps_info_t* rps, char *ifname)
21157 {
21158 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21159 dhd_pub_t *dhdp;
21160 struct net_device *ndev = NULL;
21161
21162 dhdp = (dhd_pub_t *)(cfg->pub);
21163
21164 if (!dhdp)
21165 return BCME_NOTUP;
21166
21167 if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
21168 WL_ERR(("Not Hostapd mode\n"));
21169 return BCME_NOTAP;
21170 }
21171
21172 ndev = wl_get_ap_netdev(cfg, ifname);
21173
21174 if (ndev == NULL) {
21175 WL_ERR(("No softAP interface named %s\n", ifname));
21176 return BCME_NOTAP;
21177 }
21178
21179 if (!rps)
21180 return BCME_BADARG;
21181
21182 if (rps->pps < RADIO_PWRSAVE_PPS_MIN)
21183 return BCME_BADARG;
21184
21185 if (rps->level < RADIO_PWRSAVE_LEVEL_MIN ||
21186 rps->level > RADIO_PWRSAVE_LEVEL_MAX)
21187 return BCME_BADARG;
21188
21189 if (rps->quiet_time < RADIO_PWRSAVE_QUIETTIME_MIN)
21190 return BCME_BADARG;
21191
21192 if (rps->sta_assoc_check > RADIO_PWRSAVE_ASSOCCHECK_MAX ||
21193 rps->sta_assoc_check < RADIO_PWRSAVE_ASSOCCHECK_MIN)
21194 return BCME_BADARG;
21195
21196 cfg->ap_rps_info.pps = rps->pps;
21197 cfg->ap_rps_info.level = rps->level;
21198 cfg->ap_rps_info.quiet_time = rps->quiet_time;
21199 cfg->ap_rps_info.sta_assoc_check = rps->sta_assoc_check;
21200
21201 if (cfg->ap_rps_info.enable) {
21202 if (_wl_update_ap_rps_params(ndev)) {
21203 WL_ERR(("Failed to update rpsnoa params"));
21204 return BCME_ERROR;
21205 }
21206 }
21207
21208 return BCME_OK;
21209 }
21210
21211 void
21212 wl_cfg80211_init_ap_rps(struct bcm_cfg80211 *cfg)
21213 {
21214 cfg->ap_rps_info.enable = FALSE;
21215 cfg->ap_rps_info.sta_assoc_check = RADIO_PWRSAVE_STAS_ASSOC_CHECK;
21216 cfg->ap_rps_info.pps = RADIO_PWRSAVE_PPS;
21217 cfg->ap_rps_info.quiet_time = RADIO_PWRSAVE_QUIET_TIME;
21218 cfg->ap_rps_info.level = RADIO_PWRSAVE_LEVEL;
21219 }
21220 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
21221
21222 int
21223 wl_cfg80211_iface_count(struct net_device *dev)
21224 {
21225 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21226 struct net_info *iter, *next;
21227 int iface_count = 0;
21228
21229 /* Return the count of network interfaces (skip netless p2p discovery
21230 * interface)
21231 */
21232 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21233 #pragma GCC diagnostic push
21234 #pragma GCC diagnostic ignored "-Wcast-qual"
21235 #endif
21236 for_each_ndev(cfg, iter, next) {
21237 if (iter->ndev) {
21238 iface_count++;
21239 }
21240 }
21241 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21242 #pragma GCC diagnostic pop
21243 #endif
21244 return iface_count;
21245 }
21246
21247 #ifdef WBTEXT
21248 static bool wl_cfg80211_wbtext_check_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea)
21249 {
21250 wl_wbtext_bssid_t *bssid = NULL;
21251 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21252 #pragma GCC diagnostic push
21253 #pragma GCC diagnostic ignored "-Wcast-qual"
21254 #endif
21255
21256 /* check duplicate */
21257 list_for_each_entry(bssid, &cfg->wbtext_bssid_list, list) {
21258 if (!memcmp(bssid->ea.octet, ea, ETHER_ADDR_LEN)) {
21259 return FALSE;
21260 }
21261 }
21262
21263 return TRUE;
21264 }
21265
21266 static bool wl_cfg80211_wbtext_add_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea)
21267 {
21268 wl_wbtext_bssid_t *bssid = NULL;
21269 char eabuf[ETHER_ADDR_STR_LEN];
21270
21271 bssid = kmalloc(sizeof(wl_wbtext_bssid_t), GFP_KERNEL);
21272 if (bssid == NULL) {
21273 WL_ERR(("alloc failed\n"));
21274 return FALSE;
21275 }
21276
21277 memcpy(bssid->ea.octet, ea, ETHER_ADDR_LEN);
21278
21279 INIT_LIST_HEAD(&bssid->list);
21280 list_add_tail(&bssid->list, &cfg->wbtext_bssid_list);
21281
21282 WL_DBG(("add wbtext bssid : %s\n", bcm_ether_ntoa(ea, eabuf)));
21283
21284 return TRUE;
21285 }
21286
21287 static void wl_cfg80211_wbtext_clear_bssid_list(struct bcm_cfg80211 *cfg)
21288 {
21289 wl_wbtext_bssid_t *bssid = NULL;
21290 char eabuf[ETHER_ADDR_STR_LEN];
21291
21292 while (!list_empty(&cfg->wbtext_bssid_list)) {
21293 bssid = list_entry(cfg->wbtext_bssid_list.next, wl_wbtext_bssid_t, list);
21294 if (bssid) {
21295 WL_DBG(("clear wbtext bssid : %s\n", bcm_ether_ntoa(&bssid->ea, eabuf)));
21296 list_del(&bssid->list);
21297 kfree(bssid);
21298 }
21299 }
21300 }
21301
21302 static void wl_cfg80211_wbtext_update_rcc(struct bcm_cfg80211 *cfg, struct net_device *dev)
21303 {
21304 struct wl_connect_info *conn_info = wl_to_conn(cfg);
21305 bcm_tlv_t * cap_ie = NULL;
21306 bool req_sent = FALSE;
21307 struct wl_profile *profile;
21308
21309 WL_DBG(("Enter\n"));
21310
21311 profile = wl_get_profile_by_netdev(cfg, dev);
21312 if (!profile) {
21313 WL_ERR(("no profile exists\n"));
21314 return;
21315 }
21316
21317 if (wl_cfg80211_wbtext_check_bssid_list(cfg,
21318 (struct ether_addr *)&profile->bssid) == FALSE) {
21319 WL_DBG(("already updated\n"));
21320 return;
21321 }
21322
21323 /* first, check NBR bit in RRM IE */
21324 if ((cap_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
21325 DOT11_MNG_RRM_CAP_ID)) != NULL) {
21326 if (isset(cap_ie->data, DOT11_RRM_CAP_NEIGHBOR_REPORT)) {
21327 req_sent = wl_cfg80211_wbtext_send_nbr_req(cfg, dev, profile);
21328 }
21329 }
21330
21331 /* if RRM nbr was not supported, check BTM bit in extend cap. IE */
21332 if (!req_sent) {
21333 if ((cap_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
21334 DOT11_MNG_EXT_CAP_ID)) != NULL) {
21335 if (cap_ie->len >= DOT11_EXTCAP_LEN_BSSTRANS &&
21336 isset(cap_ie->data, DOT11_EXT_CAP_BSSTRANS_MGMT)) {
21337 wl_cfg80211_wbtext_send_btm_query(cfg, dev, profile);
21338 }
21339 }
21340 }
21341 }
21342
21343 static bool wl_cfg80211_wbtext_send_nbr_req(struct bcm_cfg80211 *cfg, struct net_device *dev,
21344 struct wl_profile *profile)
21345 {
21346 int error = -1;
21347 char *smbuf = NULL;
21348 struct wl_connect_info *conn_info = wl_to_conn(cfg);
21349 bcm_tlv_t * rrm_cap_ie = NULL;
21350 wlc_ssid_t *ssid = NULL;
21351 bool ret = FALSE;
21352
21353 WL_DBG(("Enter\n"));
21354
21355 /* check RRM nbr bit in extend cap. IE of assoc response */
21356 if ((rrm_cap_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
21357 DOT11_MNG_RRM_CAP_ID)) != NULL) {
21358 if (!isset(rrm_cap_ie->data, DOT11_RRM_CAP_NEIGHBOR_REPORT)) {
21359 WL_DBG(("AP doesn't support neighbor report\n"));
21360 return FALSE;
21361 }
21362 }
21363
21364 smbuf = (char *) kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
21365 if (smbuf == NULL) {
21366 WL_ERR(("failed to allocated memory\n"));
21367 goto nbr_req_out;
21368 }
21369
21370 ssid = (wlc_ssid_t *) kzalloc(sizeof(wlc_ssid_t), GFP_KERNEL);
21371 if (ssid == NULL) {
21372 WL_ERR(("failed to allocated memory\n"));
21373 goto nbr_req_out;
21374 }
21375
21376 ssid->SSID_len = MIN(profile->ssid.SSID_len, DOT11_MAX_SSID_LEN);
21377 memcpy(ssid->SSID, profile->ssid.SSID, ssid->SSID_len);
21378
21379 error = wldev_iovar_setbuf(dev, "rrm_nbr_req", ssid,
21380 sizeof(wlc_ssid_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
21381 if (error == BCME_OK) {
21382 ret = wl_cfg80211_wbtext_add_bssid_list(cfg,
21383 (struct ether_addr *)&profile->bssid);
21384 } else {
21385 WL_ERR(("failed to send neighbor report request, error=%d\n", error));
21386 }
21387
21388 nbr_req_out:
21389 if (ssid) {
21390 kfree(ssid);
21391 }
21392
21393 if (smbuf) {
21394 kfree(smbuf);
21395 }
21396 return ret;
21397 }
21398
21399 static bool wl_cfg80211_wbtext_send_btm_query(struct bcm_cfg80211 *cfg, struct net_device *dev,
21400 struct wl_profile *profile)
21401
21402 {
21403 int error = -1;
21404 bool ret = FALSE;
21405
21406 WL_DBG(("Enter\n"));
21407
21408 error = wldev_iovar_setbuf(dev, "wnm_bsstrans_query", NULL,
21409 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
21410 if (error == BCME_OK) {
21411 ret = wl_cfg80211_wbtext_add_bssid_list(cfg,
21412 (struct ether_addr *)&profile->bssid);
21413 } else {
21414 WL_ERR(("%s: failed to set BTM query, error=%d\n", __FUNCTION__, error));
21415 }
21416 return ret;
21417 }
21418
21419 static void wl_cfg80211_wbtext_set_wnm_maxidle(struct bcm_cfg80211 *cfg, struct net_device *dev)
21420 {
21421 keepalives_max_idle_t keepalive = {0, 0, 0, 0};
21422 s32 bssidx, error;
21423 int wnm_maxidle = 0;
21424 struct wl_connect_info *conn_info = wl_to_conn(cfg);
21425
21426 /* AP supports wnm max idle ? */
21427 if (bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
21428 DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID) != NULL) {
21429 error = wldev_iovar_getint(dev, "wnm_maxidle", &wnm_maxidle);
21430 if (error < 0) {
21431 WL_ERR(("failed to get wnm max idle period : %d\n", error));
21432 }
21433 }
21434
21435 WL_DBG(("wnm max idle period : %d\n", wnm_maxidle));
21436
21437 /* if wnm maxidle has valid period, set it as keep alive */
21438 if (wnm_maxidle > 0) {
21439 keepalive.keepalive_count = 1;
21440 }
21441
21442 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) >= 0) {
21443 error = wldev_iovar_setbuf_bsscfg(dev, "wnm_keepalives_max_idle", &keepalive,
21444 sizeof(keepalives_max_idle_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
21445 bssidx, &cfg->ioctl_buf_sync);
21446 if (error < 0) {
21447 WL_ERR(("set wnm_keepalives_max_idle failed : %d\n", error));
21448 }
21449 }
21450 }
21451
21452 static int
21453 wl_cfg80211_recv_nbr_resp(struct net_device *dev, uint8 *body, int body_len)
21454 {
21455 dot11_rm_action_t *rm_rep;
21456 bcm_tlv_t *tlvs;
21457 int tlv_len, i, error;
21458 dot11_neighbor_rep_ie_t *nbr_rep_ie;
21459 chanspec_t ch;
21460 wl_roam_channel_list_t channel_list;
21461 char iobuf[WLC_IOCTL_SMLEN];
21462
21463 if (body_len < DOT11_RM_ACTION_LEN) {
21464 WL_ERR(("Received Neighbor Report frame with incorrect length %d\n",
21465 body_len));
21466 return BCME_ERROR;
21467 }
21468
21469 rm_rep = (dot11_rm_action_t *)body;
21470 WL_DBG(("received neighbor report (token = %d)\n", rm_rep->token));
21471
21472 tlvs = (bcm_tlv_t *)&rm_rep->data[0];
21473
21474 tlv_len = body_len - DOT11_RM_ACTION_LEN;
21475
21476 while (tlvs && tlvs->id == DOT11_MNG_NEIGHBOR_REP_ID) {
21477 nbr_rep_ie = (dot11_neighbor_rep_ie_t *)tlvs;
21478
21479 if (nbr_rep_ie->len < DOT11_NEIGHBOR_REP_IE_FIXED_LEN) {
21480 WL_ERR(("malformed Neighbor Report element with length %d\n",
21481 nbr_rep_ie->len));
21482 tlvs = bcm_next_tlv(tlvs, &tlv_len);
21483 continue;
21484 }
21485
21486 ch = CH20MHZ_CHSPEC(nbr_rep_ie->channel);
21487 WL_DBG(("ch:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x\n",
21488 ch, nbr_rep_ie->bssid.octet[0], nbr_rep_ie->bssid.octet[1],
21489 nbr_rep_ie->bssid.octet[2], nbr_rep_ie->bssid.octet[3],
21490 nbr_rep_ie->bssid.octet[4], nbr_rep_ie->bssid.octet[5]));
21491
21492 /* get RCC list */
21493 error = wldev_iovar_getbuf(dev, "roamscan_channels", 0, 0,
21494 (void *)&channel_list, sizeof(channel_list), NULL);
21495 if (error) {
21496 WL_ERR(("Failed to get roamscan channels, error = %d\n", error));
21497 return BCME_ERROR;
21498 }
21499
21500 /* update RCC */
21501 if (channel_list.n < MAX_ROAM_CHANNEL) {
21502 for (i = 0; i < channel_list.n; i++) {
21503 if (channel_list.channels[i] == ch) {
21504 break;
21505 }
21506 }
21507 if (i == channel_list.n) {
21508 channel_list.channels[channel_list.n] = ch;
21509 channel_list.n++;
21510 }
21511 }
21512
21513 /* set RCC list */
21514 error = wldev_iovar_setbuf(dev, "roamscan_channels", &channel_list,
21515 sizeof(channel_list), iobuf, sizeof(iobuf), NULL);
21516 if (error) {
21517 WL_DBG(("Failed to set roamscan channels, error = %d\n", error));
21518 }
21519
21520 tlvs = bcm_next_tlv(tlvs, &tlv_len);
21521 }
21522
21523 return BCME_OK;
21524 }
21525 #endif /* WBTEXT */
21526
21527 #ifdef SUPPORT_SET_CAC
21528 static void
21529 wl_cfg80211_set_cac(struct bcm_cfg80211 *cfg, int enable)
21530 {
21531 int ret = 0;
21532 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
21533
21534 WL_DBG(("cac enable %d, op_mode 0x%04x\n", enable, dhd->op_mode));
21535 if (!dhd) {
21536 WL_ERR(("dhd is NULL\n"));
21537 return;
21538 }
21539 if (enable && ((dhd->op_mode & DHD_FLAG_HOSTAP_MODE) ||
21540 (dhd->op_mode & DHD_FLAG_P2P_GC_MODE) ||
21541 (dhd->op_mode & DHD_FLAG_P2P_GO_MODE))) {
21542 WL_ERR(("op_mode 0x%04x\n", dhd->op_mode));
21543 enable = 0;
21544 }
21545 if ((ret = dhd_wl_ioctl_set_intiovar(dhd, "cac", enable,
21546 WLC_SET_VAR, TRUE, 0)) < 0) {
21547 WL_ERR(("Failed set CAC, ret=%d\n", ret));
21548 } else {
21549 WL_DBG(("CAC set successfully\n"));
21550 }
21551 return;
21552 }
21553 #endif /* SUPPORT_SET_CAC */
21554
21555 #ifdef SUPPORT_RSSI_LOGGING
21556 int
21557 wl_get_rssi_per_ant(struct net_device *dev, char *ifname, char *peer_mac, void *param)
21558 {
21559 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21560 wl_rssi_ant_mimo_t *get_param = (wl_rssi_ant_mimo_t *)param;
21561 rssi_ant_param_t *set_param = NULL;
21562 struct net_device *ifdev = NULL;
21563 char iobuf[WLC_IOCTL_SMLEN];
21564 int err = BCME_OK;
21565 int iftype = 0;
21566
21567 memset(iobuf, 0, WLC_IOCTL_SMLEN);
21568
21569 /* Check the interface type */
21570 ifdev = wl_get_netdev_by_name(cfg, ifname);
21571 if (ifdev == NULL) {
21572 WL_ERR(("Could not find net_device for ifname:%s\n", ifname));
21573 err = BCME_BADARG;
21574 goto fail;
21575 }
21576
21577 iftype = ifdev->ieee80211_ptr->iftype;
21578 if (iftype == NL80211_IFTYPE_AP || iftype == NL80211_IFTYPE_P2P_GO) {
21579 if (peer_mac) {
21580 set_param = (rssi_ant_param_t *)kzalloc(sizeof(rssi_ant_param_t),
21581 GFP_KERNEL);
21582 err = wl_cfg80211_ether_atoe(peer_mac, &set_param->ea);
21583 if (!err) {
21584 WL_ERR(("Invalid Peer MAC format\n"));
21585 err = BCME_BADARG;
21586 goto fail;
21587 }
21588 } else {
21589 WL_ERR(("Peer MAC is not provided for iftype %d\n", iftype));
21590 err = BCME_BADARG;
21591 goto fail;
21592 }
21593 }
21594
21595 err = wldev_iovar_getbuf(ifdev, "phy_rssi_ant", peer_mac ?
21596 (void *)&(set_param->ea) : NULL, peer_mac ? ETHER_ADDR_LEN : 0,
21597 (void *)iobuf, sizeof(iobuf), NULL);
21598 if (unlikely(err)) {
21599 WL_ERR(("Failed to get rssi info, err=%d\n", err));
21600 } else {
21601 memcpy(get_param, iobuf, sizeof(wl_rssi_ant_mimo_t));
21602 if (get_param->count == 0) {
21603 WL_ERR(("Not supported on this chip\n"));
21604 err = BCME_UNSUPPORTED;
21605 }
21606 }
21607
21608 fail:
21609 if (set_param) {
21610 kfree(set_param);
21611 }
21612
21613 return err;
21614 }
21615
21616 int
21617 wl_get_rssi_logging(struct net_device *dev, void *param)
21618 {
21619 rssilog_get_param_t *get_param = (rssilog_get_param_t *)param;
21620 char iobuf[WLC_IOCTL_SMLEN];
21621 int err = BCME_OK;
21622
21623 memset(iobuf, 0, WLC_IOCTL_SMLEN);
21624 memset(get_param, 0, sizeof(*get_param));
21625 err = wldev_iovar_getbuf(dev, "rssilog", NULL, 0, (void *)iobuf,
21626 sizeof(iobuf), NULL);
21627 if (err) {
21628 WL_ERR(("Failed to get rssi logging info, err=%d\n", err));
21629 } else {
21630 memcpy(get_param, iobuf, sizeof(*get_param));
21631 }
21632
21633 return err;
21634 }
21635
21636 int
21637 wl_set_rssi_logging(struct net_device *dev, void *param)
21638 {
21639 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21640 rssilog_set_param_t *set_param = (rssilog_set_param_t *)param;
21641 int err;
21642
21643 err = wldev_iovar_setbuf(dev, "rssilog", set_param,
21644 sizeof(*set_param), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
21645 &cfg->ioctl_buf_sync);
21646 if (err) {
21647 WL_ERR(("Failed to set rssi logging param, err=%d\n", err));
21648 }
21649
21650 return err;
21651 }
21652 #endif /* SUPPORT_RSSI_LOGGING */