adt3-S dhd_driver source code [1/1]
[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 const 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 static int wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg,
916 struct net_device *dev, uint action, enum wl_ext_status status, void *context);
917
918
919 extern int passive_channel_skip;
920
921 static s32
922 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
923 const wl_event_msg_t *e, void *data);
924 static s32
925 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
926 const wl_event_msg_t *e, void *data);
927 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, \
928 0)))
929 struct chan_info {
930 int freq;
931 int chan_type;
932 };
933 #endif
934
935 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
936 #define CFG80211_PUT_BSS(wiphy, bss) cfg80211_put_bss(wiphy, bss);
937 #else
938 #define CFG80211_PUT_BSS(wiphy, bss) cfg80211_put_bss(bss);
939 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
940
941 #define CHAN2G(_channel, _freq, _flags) { \
942 .band = IEEE80211_BAND_2GHZ, \
943 .center_freq = (_freq), \
944 .hw_value = (_channel), \
945 .flags = (_flags), \
946 .max_antenna_gain = 0, \
947 .max_power = 30, \
948 }
949
950 #define CHAN5G(_channel, _flags) { \
951 .band = IEEE80211_BAND_5GHZ, \
952 .center_freq = 5000 + (5 * (_channel)), \
953 .hw_value = (_channel), \
954 .flags = (_flags), \
955 .max_antenna_gain = 0, \
956 .max_power = 30, \
957 }
958
959 #define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2)
960 #define RATETAB_ENT(_rateid, _flags) \
961 { \
962 .bitrate = RATE_TO_BASE100KBPS(_rateid), \
963 .hw_value = (_rateid), \
964 .flags = (_flags), \
965 }
966
967 static struct ieee80211_rate __wl_rates[] = {
968 RATETAB_ENT(DOT11_RATE_1M, 0),
969 RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE),
970 RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE),
971 RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE),
972 RATETAB_ENT(DOT11_RATE_6M, 0),
973 RATETAB_ENT(DOT11_RATE_9M, 0),
974 RATETAB_ENT(DOT11_RATE_12M, 0),
975 RATETAB_ENT(DOT11_RATE_18M, 0),
976 RATETAB_ENT(DOT11_RATE_24M, 0),
977 RATETAB_ENT(DOT11_RATE_36M, 0),
978 RATETAB_ENT(DOT11_RATE_48M, 0),
979 RATETAB_ENT(DOT11_RATE_54M, 0)
980 };
981
982 #define wl_a_rates (__wl_rates + 4)
983 #define wl_a_rates_size 8
984 #define wl_g_rates (__wl_rates + 0)
985 #define wl_g_rates_size 12
986
987 static struct ieee80211_channel __wl_2ghz_channels[] = {
988 CHAN2G(1, 2412, 0),
989 CHAN2G(2, 2417, 0),
990 CHAN2G(3, 2422, 0),
991 CHAN2G(4, 2427, 0),
992 CHAN2G(5, 2432, 0),
993 CHAN2G(6, 2437, 0),
994 CHAN2G(7, 2442, 0),
995 CHAN2G(8, 2447, 0),
996 CHAN2G(9, 2452, 0),
997 CHAN2G(10, 2457, 0),
998 CHAN2G(11, 2462, 0),
999 CHAN2G(12, 2467, 0),
1000 CHAN2G(13, 2472, 0),
1001 CHAN2G(14, 2484, 0)
1002 };
1003
1004 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
1005 CHAN5G(34, 0), CHAN5G(36, 0),
1006 CHAN5G(38, 0), CHAN5G(40, 0),
1007 CHAN5G(42, 0), CHAN5G(44, 0),
1008 CHAN5G(46, 0), CHAN5G(48, 0),
1009 CHAN5G(52, 0), CHAN5G(56, 0),
1010 CHAN5G(60, 0), CHAN5G(64, 0),
1011 CHAN5G(100, 0), CHAN5G(104, 0),
1012 CHAN5G(108, 0), CHAN5G(112, 0),
1013 CHAN5G(116, 0), CHAN5G(120, 0),
1014 CHAN5G(124, 0), CHAN5G(128, 0),
1015 CHAN5G(132, 0), CHAN5G(136, 0),
1016 CHAN5G(140, 0), CHAN5G(144, 0),
1017 CHAN5G(149, 0), CHAN5G(153, 0),
1018 CHAN5G(157, 0), CHAN5G(161, 0),
1019 CHAN5G(165, 0)
1020 };
1021
1022 static struct ieee80211_supported_band __wl_band_2ghz = {
1023 .band = IEEE80211_BAND_2GHZ,
1024 .channels = __wl_2ghz_channels,
1025 .n_channels = ARRAY_SIZE(__wl_2ghz_channels),
1026 .bitrates = wl_g_rates,
1027 .n_bitrates = wl_g_rates_size
1028 };
1029
1030 static struct ieee80211_supported_band __wl_band_5ghz_a = {
1031 .band = IEEE80211_BAND_5GHZ,
1032 .channels = __wl_5ghz_a_channels,
1033 .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
1034 .bitrates = wl_a_rates,
1035 .n_bitrates = wl_a_rates_size
1036 };
1037
1038 static const u32 __wl_cipher_suites[] = {
1039 WLAN_CIPHER_SUITE_WEP40,
1040 WLAN_CIPHER_SUITE_WEP104,
1041 WLAN_CIPHER_SUITE_TKIP,
1042 WLAN_CIPHER_SUITE_CCMP,
1043 #ifdef MFP
1044 /*
1045 * Advertising AES_CMAC cipher suite to userspace would imply that we
1046 * are supporting MFP. So advertise only when MFP support is enabled.
1047 */
1048 WLAN_CIPHER_SUITE_AES_CMAC,
1049 #endif /* MFP */
1050 };
1051
1052 #ifdef WL_SUPPORT_ACS
1053 /*
1054 * The firmware code required for this feature to work is currently under
1055 * BCMINTERNAL flag. In future if this is to enabled we need to bring the
1056 * required firmware code out of the BCMINTERNAL flag.
1057 */
1058 struct wl_dump_survey {
1059 u32 obss;
1060 u32 ibss;
1061 u32 no_ctg;
1062 u32 no_pckt;
1063 u32 tx;
1064 u32 idle;
1065 };
1066 #endif /* WL_SUPPORT_ACS */
1067
1068
1069 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
1070 static int maxrxpktglom = 0;
1071 #endif
1072
1073 /* IOCtl version read from targeted driver */
1074 int ioctl_version;
1075 #ifdef DEBUGFS_CFG80211
1076 #define S_SUBLOGLEVEL 20
1077 static const struct {
1078 u32 log_level;
1079 char *sublogname;
1080 } sublogname_map[] = {
1081 {WL_DBG_ERR, "ERR"},
1082 {WL_DBG_INFO, "INFO"},
1083 {WL_DBG_DBG, "DBG"},
1084 {WL_DBG_SCAN, "SCAN"},
1085 {WL_DBG_TRACE, "TRACE"},
1086 {WL_DBG_P2P_ACTION, "P2PACTION"}
1087 };
1088 #endif
1089
1090 #ifdef CUSTOMER_HW4_DEBUG
1091 uint prev_dhd_console_ms = 0;
1092 u32 prev_wl_dbg_level = 0;
1093 bool wl_scan_timeout_dbg_enabled = 0;
1094 static void wl_scan_timeout_dbg_set(void);
1095 static void wl_scan_timeout_dbg_clear(void);
1096
1097 static void wl_scan_timeout_dbg_set(void)
1098 {
1099 WL_ERR(("Enter \n"));
1100 prev_dhd_console_ms = dhd_console_ms;
1101 prev_wl_dbg_level = wl_dbg_level;
1102
1103 dhd_console_ms = 1;
1104 wl_dbg_level |= (WL_DBG_ERR | WL_DBG_P2P_ACTION | WL_DBG_SCAN);
1105
1106 wl_scan_timeout_dbg_enabled = 1;
1107 }
1108 static void wl_scan_timeout_dbg_clear(void)
1109 {
1110 WL_ERR(("Enter \n"));
1111 dhd_console_ms = prev_dhd_console_ms;
1112 wl_dbg_level = prev_wl_dbg_level;
1113
1114 wl_scan_timeout_dbg_enabled = 0;
1115 }
1116 #endif /* CUSTOMER_HW4_DEBUG */
1117
1118 /* watchdog timer for disconnecting when fw is not associated for FW_ASSOC_WATCHDOG_TIME ms */
1119 uint32 fw_assoc_watchdog_ms = 0;
1120 bool fw_assoc_watchdog_started = 0;
1121 #define FW_ASSOC_WATCHDOG_TIME 10 * 1000 /* msec */
1122
1123 static void wl_add_remove_pm_enable_work(struct bcm_cfg80211 *cfg,
1124 enum wl_pm_workq_act_type type)
1125 {
1126 u16 wq_duration = 0;
1127 dhd_pub_t *dhd = NULL;
1128
1129 if (cfg == NULL)
1130 return;
1131
1132 dhd = (dhd_pub_t *)(cfg->pub);
1133
1134 mutex_lock(&cfg->pm_sync);
1135 /*
1136 * Make cancel and schedule work part mutually exclusive
1137 * so that while cancelling, we are sure that there is no
1138 * work getting scheduled.
1139 */
1140 if (delayed_work_pending(&cfg->pm_enable_work)) {
1141 cancel_delayed_work_sync(&cfg->pm_enable_work);
1142 DHD_PM_WAKE_UNLOCK(cfg->pub);
1143 }
1144
1145 if (type == WL_PM_WORKQ_SHORT) {
1146 wq_duration = WL_PM_ENABLE_TIMEOUT;
1147 } else if (type == WL_PM_WORKQ_LONG) {
1148 wq_duration = (WL_PM_ENABLE_TIMEOUT*2);
1149 }
1150
1151 /* It should schedule work item only if driver is up */
1152 if (wq_duration && dhd->up) {
1153 if (schedule_delayed_work(&cfg->pm_enable_work,
1154 msecs_to_jiffies((const unsigned int)wq_duration))) {
1155 DHD_PM_WAKE_LOCK_TIMEOUT(cfg->pub, wq_duration);
1156 } else {
1157 WL_ERR(("Can't schedule pm work handler\n"));
1158 }
1159 }
1160 mutex_unlock(&cfg->pm_sync);
1161 }
1162
1163 /* Return a new chanspec given a legacy chanspec
1164 * Returns INVCHANSPEC on error
1165 */
1166 chanspec_t
1167 wl_chspec_from_legacy(chanspec_t legacy_chspec)
1168 {
1169 chanspec_t chspec;
1170
1171 /* get the channel number */
1172 chspec = LCHSPEC_CHANNEL(legacy_chspec);
1173
1174 /* convert the band */
1175 if (LCHSPEC_IS2G(legacy_chspec)) {
1176 chspec |= WL_CHANSPEC_BAND_2G;
1177 } else {
1178 chspec |= WL_CHANSPEC_BAND_5G;
1179 }
1180
1181 /* convert the bw and sideband */
1182 if (LCHSPEC_IS20(legacy_chspec)) {
1183 chspec |= WL_CHANSPEC_BW_20;
1184 } else {
1185 chspec |= WL_CHANSPEC_BW_40;
1186 if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
1187 chspec |= WL_CHANSPEC_CTL_SB_L;
1188 } else {
1189 chspec |= WL_CHANSPEC_CTL_SB_U;
1190 }
1191 }
1192
1193 if (wf_chspec_malformed(chspec)) {
1194 WL_ERR(("wl_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
1195 chspec));
1196 return INVCHANSPEC;
1197 }
1198
1199 return chspec;
1200 }
1201
1202 /* Return a legacy chanspec given a new chanspec
1203 * Returns INVCHANSPEC on error
1204 */
1205 static chanspec_t
1206 wl_chspec_to_legacy(chanspec_t chspec)
1207 {
1208 chanspec_t lchspec;
1209
1210 if (wf_chspec_malformed(chspec)) {
1211 WL_ERR(("wl_chspec_to_legacy: input chanspec (0x%04X) malformed\n",
1212 chspec));
1213 return INVCHANSPEC;
1214 }
1215
1216 /* get the channel number */
1217 lchspec = CHSPEC_CHANNEL(chspec);
1218
1219 /* convert the band */
1220 if (CHSPEC_IS2G(chspec)) {
1221 lchspec |= WL_LCHANSPEC_BAND_2G;
1222 } else {
1223 lchspec |= WL_LCHANSPEC_BAND_5G;
1224 }
1225
1226 /* convert the bw and sideband */
1227 if (CHSPEC_IS20(chspec)) {
1228 lchspec |= WL_LCHANSPEC_BW_20;
1229 lchspec |= WL_LCHANSPEC_CTL_SB_NONE;
1230 } else if (CHSPEC_IS40(chspec)) {
1231 lchspec |= WL_LCHANSPEC_BW_40;
1232 if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_L) {
1233 lchspec |= WL_LCHANSPEC_CTL_SB_LOWER;
1234 } else {
1235 lchspec |= WL_LCHANSPEC_CTL_SB_UPPER;
1236 }
1237 } else {
1238 /* cannot express the bandwidth */
1239 char chanbuf[CHANSPEC_STR_LEN];
1240 WL_ERR((
1241 "wl_chspec_to_legacy: unable to convert chanspec %s (0x%04X) "
1242 "to pre-11ac format\n",
1243 wf_chspec_ntoa(chspec, chanbuf), chspec));
1244 return INVCHANSPEC;
1245 }
1246
1247 return lchspec;
1248 }
1249
1250 /* given a chanspec value, do the endian and chanspec version conversion to
1251 * a chanspec_t value
1252 * Returns INVCHANSPEC on error
1253 */
1254 chanspec_t
1255 wl_chspec_host_to_driver(chanspec_t chanspec)
1256 {
1257 if (ioctl_version == 1) {
1258 chanspec = wl_chspec_to_legacy(chanspec);
1259 if (chanspec == INVCHANSPEC) {
1260 return chanspec;
1261 }
1262 }
1263 chanspec = htodchanspec(chanspec);
1264
1265 return chanspec;
1266 }
1267
1268 /* given a channel value, do the endian and chanspec version conversion to
1269 * a chanspec_t value
1270 * Returns INVCHANSPEC on error
1271 */
1272 chanspec_t
1273 wl_ch_host_to_driver(struct bcm_cfg80211 *cfg, s32 bssidx, u16 channel)
1274 {
1275 chanspec_t chanspec;
1276
1277 chanspec = channel & WL_CHANSPEC_CHAN_MASK;
1278
1279 if (channel <= CH_MAX_2G_CHANNEL)
1280 chanspec |= WL_CHANSPEC_BAND_2G;
1281 else
1282 chanspec |= WL_CHANSPEC_BAND_5G;
1283
1284 chanspec |= wl_cfg80211_ulb_get_min_bw_chspec(cfg, NULL, bssidx);
1285
1286 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
1287
1288 return wl_chspec_host_to_driver(chanspec);
1289 }
1290
1291 /* given a chanspec value from the driver, do the endian and chanspec version conversion to
1292 * a chanspec_t value
1293 * Returns INVCHANSPEC on error
1294 */
1295 chanspec_t
1296 wl_chspec_driver_to_host(chanspec_t chanspec)
1297 {
1298 chanspec = dtohchanspec(chanspec);
1299 if (ioctl_version == 1) {
1300 chanspec = wl_chspec_from_legacy(chanspec);
1301 }
1302
1303 return chanspec;
1304 }
1305
1306 /*
1307 * convert ASCII string to MAC address (colon-delimited format)
1308 * eg: 00:11:22:33:44:55
1309 */
1310 int
1311 wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n)
1312 {
1313 char *c = NULL;
1314 int count = 0;
1315
1316 memset(n, 0, ETHER_ADDR_LEN);
1317 for (;;) {
1318 n->octet[count++] = (uint8)simple_strtoul(a, &c, 16);
1319 if (!*c++ || count == ETHER_ADDR_LEN)
1320 break;
1321 a = c;
1322 }
1323 return (count == ETHER_ADDR_LEN);
1324 }
1325
1326 /* There isn't a lot of sense in it, but you can transmit anything you like */
1327 static const struct ieee80211_txrx_stypes
1328 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
1329 #ifdef WLMESH
1330 [NL80211_IFTYPE_MESH_POINT] = {
1331 .tx = 0xffff,
1332 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1333 BIT(IEEE80211_STYPE_AUTH >> 4)
1334 },
1335 #endif /* WLMESH */
1336 [NL80211_IFTYPE_ADHOC] = {
1337 .tx = 0xffff,
1338 .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
1339 },
1340 [NL80211_IFTYPE_STATION] = {
1341 .tx = 0xffff,
1342 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1343 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1344 },
1345 [NL80211_IFTYPE_AP] = {
1346 .tx = 0xffff,
1347 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1348 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1349 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1350 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1351 BIT(IEEE80211_STYPE_AUTH >> 4) |
1352 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1353 BIT(IEEE80211_STYPE_ACTION >> 4)
1354 },
1355 [NL80211_IFTYPE_AP_VLAN] = {
1356 /* copy AP */
1357 .tx = 0xffff,
1358 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1359 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1360 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1361 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1362 BIT(IEEE80211_STYPE_AUTH >> 4) |
1363 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1364 BIT(IEEE80211_STYPE_ACTION >> 4)
1365 },
1366 [NL80211_IFTYPE_P2P_CLIENT] = {
1367 .tx = 0xffff,
1368 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1369 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1370 },
1371 [NL80211_IFTYPE_P2P_GO] = {
1372 .tx = 0xffff,
1373 .rx = BIT(IEEE80211_STYPE_ASSOC_REQ >> 4) |
1374 BIT(IEEE80211_STYPE_REASSOC_REQ >> 4) |
1375 BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
1376 BIT(IEEE80211_STYPE_DISASSOC >> 4) |
1377 BIT(IEEE80211_STYPE_AUTH >> 4) |
1378 BIT(IEEE80211_STYPE_DEAUTH >> 4) |
1379 BIT(IEEE80211_STYPE_ACTION >> 4)
1380 },
1381 #if defined(WL_CFG80211_P2P_DEV_IF)
1382 [NL80211_IFTYPE_P2P_DEVICE] = {
1383 .tx = 0xffff,
1384 .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
1385 BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
1386 },
1387 #endif /* WL_CFG80211_P2P_DEV_IF */
1388 };
1389
1390 static void swap_key_from_BE(struct wl_wsec_key *key)
1391 {
1392 key->index = htod32(key->index);
1393 key->len = htod32(key->len);
1394 key->algo = htod32(key->algo);
1395 key->flags = htod32(key->flags);
1396 key->rxiv.hi = htod32(key->rxiv.hi);
1397 key->rxiv.lo = htod16(key->rxiv.lo);
1398 key->iv_initialized = htod32(key->iv_initialized);
1399 }
1400
1401 static void swap_key_to_BE(struct wl_wsec_key *key)
1402 {
1403 key->index = dtoh32(key->index);
1404 key->len = dtoh32(key->len);
1405 key->algo = dtoh32(key->algo);
1406 key->flags = dtoh32(key->flags);
1407 key->rxiv.hi = dtoh32(key->rxiv.hi);
1408 key->rxiv.lo = dtoh16(key->rxiv.lo);
1409 key->iv_initialized = dtoh32(key->iv_initialized);
1410 }
1411
1412 /* Dump the contents of the encoded wps ie buffer and get pbc value */
1413 static void
1414 wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc)
1415 {
1416 #define WPS_IE_FIXED_LEN 6
1417 s16 len;
1418 u8 *subel = NULL;
1419 u16 subelt_id;
1420 u16 subelt_len;
1421 u16 val;
1422 u8 *valptr = (uint8*) &val;
1423 if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
1424 WL_ERR(("invalid argument : NULL\n"));
1425 return;
1426 }
1427 len = (s16)wps_ie[TLV_LEN_OFF];
1428
1429 if (len > wps_ie_len) {
1430 WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
1431 return;
1432 }
1433 WL_DBG(("wps_ie len=%d\n", len));
1434 len -= 4; /* for the WPS IE's OUI, oui_type fields */
1435 subel = wps_ie + WPS_IE_FIXED_LEN;
1436 while (len >= 4) { /* must have attr id, attr len fields */
1437 valptr[0] = *subel++;
1438 valptr[1] = *subel++;
1439 subelt_id = HTON16(val);
1440
1441 valptr[0] = *subel++;
1442 valptr[1] = *subel++;
1443 subelt_len = HTON16(val);
1444
1445 len -= 4; /* for the attr id, attr len fields */
1446 len -= (s16)subelt_len; /* for the remaining fields in this attribute */
1447 if (len < 0) {
1448 break;
1449 }
1450 WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
1451 subel, subelt_id, subelt_len));
1452
1453 if (subelt_id == WPS_ID_VERSION) {
1454 WL_DBG((" attr WPS_ID_VERSION: %u\n", *subel));
1455 } else if (subelt_id == WPS_ID_REQ_TYPE) {
1456 WL_DBG((" attr WPS_ID_REQ_TYPE: %u\n", *subel));
1457 } else if (subelt_id == WPS_ID_CONFIG_METHODS) {
1458 valptr[0] = *subel;
1459 valptr[1] = *(subel + 1);
1460 WL_DBG((" attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
1461 } else if (subelt_id == WPS_ID_DEVICE_NAME) {
1462 char devname[100];
1463 int namelen = MIN(subelt_len, (sizeof(devname) - 1));
1464
1465 if (namelen) {
1466 memcpy(devname, subel, namelen);
1467 devname[namelen] = '\0';
1468 /* Printing len as rx'ed in the IE */
1469 WL_DBG((" attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
1470 devname, subelt_len));
1471 }
1472 } else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
1473 valptr[0] = *subel;
1474 valptr[1] = *(subel + 1);
1475 WL_DBG((" attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
1476 *pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
1477 } else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
1478 valptr[0] = *subel;
1479 valptr[1] = *(subel + 1);
1480 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
1481 valptr[0] = *(subel + 6);
1482 valptr[1] = *(subel + 7);
1483 WL_DBG((" attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
1484 } else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
1485 valptr[0] = *subel;
1486 valptr[1] = *(subel + 1);
1487 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
1488 valptr[0] = *(subel + 6);
1489 valptr[1] = *(subel + 7);
1490 WL_DBG((" attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
1491 } else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
1492 valptr[0] = *subel;
1493 valptr[1] = *(subel + 1);
1494 WL_DBG((" attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
1495 ": cat=%u\n", HTON16(val)));
1496 } else {
1497 WL_DBG((" unknown attr 0x%x\n", subelt_id));
1498 }
1499
1500 subel += subelt_len;
1501 }
1502 }
1503
1504 s32 wl_set_tx_power(struct net_device *dev,
1505 enum nl80211_tx_power_setting type, s32 dbm)
1506 {
1507 s32 err = 0;
1508 s32 disable = 0;
1509 s32 txpwrqdbm;
1510 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
1511
1512 /* Make sure radio is off or on as far as software is concerned */
1513 disable = WL_RADIO_SW_DISABLE << 16;
1514 disable = htod32(disable);
1515 err = wldev_ioctl_set(dev, WLC_SET_RADIO, &disable, sizeof(disable));
1516 if (unlikely(err)) {
1517 WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
1518 return err;
1519 }
1520
1521 if (dbm > 0xffff)
1522 dbm = 0xffff;
1523 txpwrqdbm = dbm * 4;
1524 err = wldev_iovar_setbuf_bsscfg(dev, "qtxpower", (void *)&txpwrqdbm,
1525 sizeof(txpwrqdbm), cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0,
1526 &cfg->ioctl_buf_sync);
1527 if (unlikely(err))
1528 WL_ERR(("qtxpower error (%d)\n", err));
1529 else
1530 WL_ERR(("dBm=%d, txpwrqdbm=0x%x\n", dbm, txpwrqdbm));
1531
1532 return err;
1533 }
1534
1535 s32 wl_get_tx_power(struct net_device *dev, s32 *dbm)
1536 {
1537 s32 err = 0;
1538 s32 txpwrdbm;
1539 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
1540
1541 err = wldev_iovar_getbuf_bsscfg(dev, "qtxpower",
1542 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
1543 if (unlikely(err)) {
1544 WL_ERR(("error (%d)\n", err));
1545 return err;
1546 }
1547
1548 memcpy(&txpwrdbm, cfg->ioctl_buf, sizeof(txpwrdbm));
1549 txpwrdbm = dtoh32(txpwrdbm);
1550 *dbm = (txpwrdbm & ~WL_TXPWR_OVERRIDE) / 4;
1551
1552 WL_INFORM(("dBm=%d, txpwrdbm=0x%x\n", *dbm, txpwrdbm));
1553
1554 return err;
1555 }
1556
1557 static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy)
1558 {
1559 chanspec_t chspec;
1560 int cur_band, err = 0;
1561 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1562 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
1563 struct ether_addr bssid;
1564 struct wl_bss_info *bss = NULL;
1565 s32 bssidx = 0; /* Explicitly set to primary bssidx */
1566 char *buf;
1567
1568 memset(&bssid, 0, sizeof(bssid));
1569 if ((err = wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, sizeof(bssid)))) {
1570 /* STA interface is not associated. So start the new interface on a temp
1571 * channel . Later proper channel will be applied by the above framework
1572 * via set_channel (cfg80211 API).
1573 */
1574 WL_DBG(("Not associated. Return a temp channel. \n"));
1575 cur_band = 0;
1576 err = wldev_ioctl_get(dev, WLC_GET_BAND, &cur_band, sizeof(int));
1577 if (unlikely(err)) {
1578 WL_ERR(("Get band failed\n"));
1579 return wl_ch_host_to_driver(cfg, bssidx, WL_P2P_TEMP_CHAN);
1580 }
1581 if (cur_band == WLC_BAND_5G)
1582 return wl_ch_host_to_driver(cfg, bssidx, WL_P2P_TEMP_CHAN_5G);
1583 else
1584 return wl_ch_host_to_driver(cfg, bssidx, WL_P2P_TEMP_CHAN);
1585 }
1586
1587 buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
1588 if (!buf) {
1589 WL_ERR(("buf alloc failed. use temp channel\n"));
1590 return wl_ch_host_to_driver(cfg, bssidx, WL_P2P_TEMP_CHAN);
1591 }
1592
1593 *(u32 *)buf = htod32(WL_EXTRA_BUF_MAX);
1594 if ((err = wldev_ioctl_get(dev, WLC_GET_BSS_INFO, buf,
1595 WL_EXTRA_BUF_MAX))) {
1596 WL_ERR(("Failed to get associated bss info, use temp channel \n"));
1597 chspec = wl_ch_host_to_driver(cfg, bssidx, WL_P2P_TEMP_CHAN);
1598 }
1599 else {
1600 bss = (struct wl_bss_info *) (buf + 4);
1601 chspec = bss->chanspec;
1602
1603 WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec));
1604 }
1605
1606 kfree(buf);
1607 return chspec;
1608 }
1609
1610 static bcm_struct_cfgdev *
1611 wl_cfg80211_add_monitor_if(const char *name)
1612 {
1613 #if defined(WL_ENABLE_P2P_IF) || defined(WL_CFG80211_P2P_DEV_IF)
1614 WL_INFORM(("wl_cfg80211_add_monitor_if: No more support monitor interface\n"));
1615 return ERR_PTR(-EOPNOTSUPP);
1616 #else
1617 struct net_device* ndev = NULL;
1618
1619 dhd_add_monitor(name, &ndev);
1620 WL_INFORM(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
1621 return ndev_to_cfgdev(ndev);
1622 #endif /* WL_ENABLE_P2P_IF || WL_CFG80211_P2P_DEV_IF */
1623 }
1624
1625 static bcm_struct_cfgdev *
1626 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
1627 #if defined(WL_CFG80211_P2P_DEV_IF)
1628 const char *name,
1629 #else
1630 char *name,
1631 #endif /* WL_CFG80211_P2P_DEV_IF */
1632 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
1633 unsigned char name_assign_type,
1634 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
1635 enum nl80211_iftype type,
1636 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
1637 u32 *flags,
1638 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) */
1639 struct vif_params *params)
1640 {
1641 s32 err = -ENODEV;
1642 s32 timeout = -1;
1643 s32 wlif_type = -1;
1644 s32 mode = 0;
1645 s32 val = 0;
1646 s32 cfg_type;
1647 s32 dhd_mode = 0;
1648 chanspec_t chspec;
1649 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1650 struct net_device *primary_ndev;
1651 struct net_device *new_ndev;
1652 struct ether_addr primary_mac;
1653 bcm_struct_cfgdev *new_cfgdev;
1654 #ifdef PROP_TXSTATUS_VSDB
1655 #if defined(BCMSDIO) || defined(BCMDBUS)
1656 s32 up = 1;
1657 bool enabled;
1658 #endif /* BCMSDIO || BCMDBUS */
1659 #endif /* PROP_TXSTATUS_VSDB */
1660 dhd_pub_t *dhd;
1661 bool hang_required = false;
1662
1663 if (!cfg)
1664 return ERR_PTR(-EINVAL);
1665
1666 dhd = (dhd_pub_t *)(cfg->pub);
1667
1668 /* Use primary I/F for sending cmds down to firmware */
1669 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1670
1671 if (unlikely(!wl_get_drv_status(cfg, READY, primary_ndev))) {
1672 WL_ERR(("device is not ready\n"));
1673 return ERR_PTR(-ENODEV);
1674 }
1675
1676 if (!name) {
1677 WL_ERR(("Interface name not provided \n"));
1678 return ERR_PTR(-EINVAL);
1679 }
1680
1681 #ifdef WLTDLS
1682 /* disable TDLS if number of connected interfaces is >= 1 */
1683 wl_cfg80211_tdls_config(cfg, TDLS_STATE_IF_CREATE, false);
1684 #endif /* WLTDLS */
1685
1686 mutex_lock(&cfg->if_sync);
1687 WL_DBG(("if name: %s, type: %d\n", name, type));
1688 switch (type) {
1689 case NL80211_IFTYPE_ADHOC:
1690 #ifdef WLAIBSS_MCHAN
1691 new_cfgdev = bcm_cfg80211_add_ibss_if(wiphy, (char *)name);
1692 mutex_unlock(&cfg->if_sync);
1693 return new_cfgdev;
1694 #endif /* WLAIBSS_MCHAN */
1695 case NL80211_IFTYPE_AP_VLAN:
1696 case NL80211_IFTYPE_WDS:
1697 case NL80211_IFTYPE_MESH_POINT:
1698 WL_ERR(("Unsupported interface type\n"));
1699 mode = WL_MODE_IBSS;
1700 err = -EINVAL;
1701 goto fail;
1702 case NL80211_IFTYPE_MONITOR:
1703 new_cfgdev = wl_cfg80211_add_monitor_if(name);
1704 mutex_unlock(&cfg->if_sync);
1705 return new_cfgdev;
1706 #if defined(WL_CFG80211_P2P_DEV_IF)
1707 case NL80211_IFTYPE_P2P_DEVICE:
1708 cfg->down_disc_if = FALSE;
1709 new_cfgdev = wl_cfgp2p_add_p2p_disc_if(cfg);
1710 mutex_unlock(&cfg->if_sync);
1711 return new_cfgdev;
1712 #endif /* WL_CFG80211_P2P_DEV_IF */
1713 case NL80211_IFTYPE_STATION:
1714 #ifdef WL_VIRTUAL_APSTA
1715 #ifdef WLAIBSS_MCHAN
1716 if (cfg->ibss_cfgdev) {
1717 WL_ERR(("AIBSS is already operational. "
1718 " AIBSS & DUALSTA can't be used together \n"));
1719 err = -ENOMEM;
1720 goto fail;
1721 }
1722 #endif /* WLAIBSS_MCHAN */
1723
1724 if (wl_cfgp2p_vif_created(cfg)) {
1725 WL_ERR(("Could not create new iface."
1726 "Already one p2p interface is running"));
1727 err = -ENOMEM;
1728 goto fail;
1729 }
1730 new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
1731 NL80211_IFTYPE_STATION, NULL, name);
1732 if (!new_cfgdev) {
1733 err = -ENOMEM;
1734 goto fail;
1735 } else {
1736 mutex_unlock(&cfg->if_sync);
1737 return new_cfgdev;
1738 }
1739 #endif /* WL_VIRTUAL_APSTA */
1740 case NL80211_IFTYPE_P2P_CLIENT:
1741 wlif_type = WL_P2P_IF_CLIENT;
1742 mode = WL_MODE_BSS;
1743 break;
1744 case NL80211_IFTYPE_P2P_GO:
1745 wlif_type = WL_P2P_IF_GO;
1746 mode = WL_MODE_AP;
1747 break;
1748 #ifdef WL_VIRTUAL_APSTA
1749 case NL80211_IFTYPE_AP:
1750 dhd->op_mode = DHD_FLAG_HOSTAP_MODE;
1751 new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
1752 NL80211_IFTYPE_AP, NULL, name);
1753 if (!new_cfgdev) {
1754 err = -ENOMEM;
1755 goto fail;
1756 } else {
1757 mutex_unlock(&cfg->if_sync);
1758 return new_cfgdev;
1759 }
1760 #endif /* WL_VIRTUAL_APSTA */
1761 default:
1762 WL_ERR(("Unsupported interface type\n"));
1763 err = -EINVAL;
1764 goto fail;
1765 }
1766
1767 if (cfg->p2p_supported && (wlif_type != -1)) {
1768 ASSERT(cfg->p2p); /* ensure expectation of p2p initialization */
1769
1770 #ifdef PROP_TXSTATUS_VSDB
1771 #if defined(BCMSDIO)
1772 if (!dhd) {
1773 err = -EINVAL;
1774 goto fail;
1775 }
1776 #endif
1777 #endif /* PROP_TXSTATUS_VSDB */
1778
1779 if (!cfg->p2p) {
1780 WL_ERR(("Failed to start p2p"));
1781 err = -ENODEV;
1782 goto fail;
1783 }
1784
1785 if (cfg->p2p && !cfg->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
1786 p2p_on(cfg) = true;
1787 wl_cfgp2p_set_firm_p2p(cfg);
1788 wl_cfgp2p_init_discovery(cfg);
1789 get_primary_mac(cfg, &primary_mac);
1790 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
1791 }
1792
1793 strncpy(cfg->p2p->vir_ifname, name, IFNAMSIZ - 1);
1794 cfg->p2p->vir_ifname[IFNAMSIZ - 1] = '\0';
1795
1796 wl_cfg80211_scan_abort(cfg);
1797 #ifdef PROP_TXSTATUS_VSDB
1798 #if defined(BCMSDIO) || defined(BCMDBUS)
1799 if (!cfg->wlfc_on && !disable_proptx) {
1800 dhd_wlfc_get_enable(dhd, &enabled);
1801 if (!enabled && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
1802 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
1803 dhd_wlfc_init(dhd);
1804 err = wldev_ioctl_set(primary_ndev, WLC_UP, &up, sizeof(s32));
1805 if (err < 0)
1806 WL_ERR(("WLC_UP return err:%d\n", err));
1807 }
1808 cfg->wlfc_on = true;
1809 }
1810 #endif /* BCMSDIO || BCMDBUS */
1811 #endif /* PROP_TXSTATUS_VSDB */
1812
1813 /* Dual p2p doesn't support multiple P2PGO interfaces,
1814 * p2p_go_count is the counter for GO creation
1815 * requests.
1816 */
1817 if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
1818 WL_ERR(("Fw does not support multiple Go\n"));
1819 err = -ENOTSUPP;
1820 goto fail;
1821 }
1822 /* In concurrency case, STA may be already associated in a particular channel.
1823 * so retrieve the current channel of primary interface and then start the virtual
1824 * interface on that.
1825 */
1826 chspec = wl_cfg80211_get_shared_freq(wiphy);
1827
1828 /* For P2P mode, use P2P-specific driver features to create the
1829 * bss: "cfg p2p_ifadd"
1830 */
1831 wl_set_p2p_status(cfg, IF_ADDING);
1832 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
1833 cfg_type = wl_cfgp2p_get_conn_idx(cfg);
1834 if (cfg_type == BCME_ERROR) {
1835 wl_clr_p2p_status(cfg, IF_ADDING);
1836 WL_ERR(("Failed to get connection idx for p2p interface\n"));
1837 err = -ENOTSUPP;
1838 goto fail;
1839 }
1840 err = wl_cfgp2p_ifadd(cfg, wl_to_p2p_bss_macaddr(cfg, cfg_type),
1841 htod32(wlif_type), chspec);
1842 if (unlikely(err)) {
1843 wl_clr_p2p_status(cfg, IF_ADDING);
1844 WL_ERR((" virtual iface add failed (%d) \n", err));
1845 err = -ENOMEM;
1846 goto fail;
1847 }
1848
1849 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1850 ((wl_get_p2p_status(cfg, IF_ADDING) == false) &&
1851 (cfg->if_event_info.valid)),
1852 msecs_to_jiffies(MAX_WAIT_TIME));
1853
1854 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_ADDING) && cfg->if_event_info.valid) {
1855 struct wireless_dev *vwdev;
1856 int pm_mode = PM_ENABLE;
1857 wl_if_event_info *event = &cfg->if_event_info;
1858 /* IF_ADD event has come back, we can proceed to to register
1859 * the new interface now, use the interface name provided by caller (thus
1860 * ignore the one from wlc)
1861 */
1862 new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, cfg->p2p->vir_ifname,
1863 event->mac, event->bssidx, event->name);
1864 if (new_ndev == NULL) {
1865 err = -ENODEV;
1866 goto fail;
1867 }
1868
1869 wl_to_p2p_bss_ndev(cfg, cfg_type) = new_ndev;
1870 wl_to_p2p_bss_bssidx(cfg, cfg_type) = event->bssidx;
1871 vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
1872 if (unlikely(!vwdev)) {
1873 WL_ERR(("Could not allocate wireless device\n"));
1874 err = -ENOMEM;
1875 goto fail;
1876 }
1877 vwdev->wiphy = cfg->wdev->wiphy;
1878 WL_INFORM(("virtual interface(%s) is created\n", cfg->p2p->vir_ifname));
1879 if (type == NL80211_IFTYPE_P2P_GO) {
1880 cfg->p2p->p2p_go_count++;
1881 }
1882 vwdev->iftype = type;
1883 vwdev->netdev = new_ndev;
1884 new_ndev->ieee80211_ptr = vwdev;
1885 SET_NETDEV_DEV(new_ndev, wiphy_dev(vwdev->wiphy));
1886 wl_set_drv_status(cfg, READY, new_ndev);
1887 if (wl_config_ifmode(cfg, new_ndev, type) < 0) {
1888 WL_ERR(("conf ifmode failed\n"));
1889 kfree(vwdev);
1890 err = -ENOTSUPP;
1891 goto fail;
1892 }
1893
1894 if (wl_cfg80211_register_if(cfg,
1895 event->ifidx, new_ndev, FALSE) != BCME_OK) {
1896 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, FALSE);
1897 err = -ENODEV;
1898 goto fail;
1899 }
1900 err = wl_alloc_netinfo(cfg, new_ndev, vwdev, mode, pm_mode, event->bssidx);
1901 if (unlikely(err != 0)) {
1902 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, FALSE);
1903 WL_ERR(("Allocation of netinfo failed (%d) \n", err));
1904 goto fail;
1905 }
1906 val = 1;
1907 /* Disable firmware roaming for P2P interface */
1908 wldev_iovar_setint(new_ndev, "roam_off", val);
1909 wldev_iovar_setint(new_ndev, "bcn_timeout", dhd->conf->bcn_timeout);
1910 #ifdef WL11ULB
1911 if (cfg->p2p_wdev && is_p2p_group_iface(new_ndev->ieee80211_ptr)) {
1912 u32 ulb_bw = wl_cfg80211_get_ulb_bw(cfg, cfg->p2p_wdev);
1913 if (ulb_bw) {
1914 /* Apply ULB BW settings on the newly spawned interface */
1915 WL_DBG(("[ULB] Applying ULB BW for the newly"
1916 "created P2P interface \n"));
1917 if (wl_cfg80211_set_ulb_bw(new_ndev,
1918 ulb_bw, new_ndev->name) < 0) {
1919 /*
1920 * If ulb_bw set failed, fail the iface creation.
1921 * wl_dealloc_netinfo_by_wdev will be called by the
1922 * unregister notifier.
1923 */
1924 wl_cfg80211_remove_if(cfg,
1925 event->ifidx, new_ndev, FALSE);
1926 err = -EINVAL;
1927 goto fail;
1928 }
1929 }
1930 }
1931 #endif /* WL11ULB */
1932
1933 if (mode != WL_MODE_AP)
1934 wldev_iovar_setint(new_ndev, "buf_key_b4_m4", 1);
1935
1936 WL_ERR((" virtual interface(%s) is "
1937 "created net attach done\n", cfg->p2p->vir_ifname));
1938 if (mode == WL_MODE_AP)
1939 wl_set_drv_status(cfg, CONNECTED, new_ndev);
1940 #ifdef SUPPORT_AP_POWERSAVE
1941 if (mode == WL_MODE_AP) {
1942 dhd_set_ap_powersave(dhd, 0, TRUE);
1943 }
1944 #endif /* SUPPORT_AP_POWERSAVE */
1945 if (type == NL80211_IFTYPE_P2P_CLIENT)
1946 dhd_mode = DHD_FLAG_P2P_GC_MODE;
1947 else if (type == NL80211_IFTYPE_P2P_GO)
1948 dhd_mode = DHD_FLAG_P2P_GO_MODE;
1949 DNGL_FUNC(dhd_cfg80211_set_p2p_info, (cfg, dhd_mode));
1950 /* reinitialize completion to clear previous count */
1951 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0))
1952 INIT_COMPLETION(cfg->iface_disable);
1953 #else
1954 init_completion(&cfg->iface_disable);
1955 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 13, 0) */
1956 #ifdef SUPPORT_SET_CAC
1957 wl_cfg80211_set_cac(cfg, 0);
1958 #endif /* SUPPORT_SET_CAC */
1959 mutex_unlock(&cfg->if_sync);
1960 return ndev_to_cfgdev(new_ndev);
1961 } else {
1962 wl_clr_p2p_status(cfg, IF_ADDING);
1963 WL_ERR((" virtual interface(%s) is not created \n", cfg->p2p->vir_ifname));
1964
1965 WL_ERR(("left timeout : %d\n", timeout));
1966 WL_ERR(("IF_ADDING status : %d\n", wl_get_p2p_status(cfg, IF_ADDING)));
1967 WL_ERR(("event valid : %d\n", cfg->if_event_info.valid));
1968
1969 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
1970 wl_set_p2p_status(cfg, IF_DELETING);
1971
1972 hang_required = true;
1973 if ((err = wl_cfgp2p_ifdel(cfg,
1974 wl_to_p2p_bss_macaddr(cfg,
1975 cfg_type))) == BCME_OK) {
1976 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
1977 ((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
1978 (cfg->if_event_info.valid)),
1979 msecs_to_jiffies(MAX_WAIT_TIME));
1980 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
1981 cfg->if_event_info.valid) {
1982 hang_required = false;
1983 WL_ERR(("IFDEL operation done\n"));
1984 } else {
1985 WL_ERR(("IFDEL didn't complete properly\n"));
1986 }
1987 err = -ENODEV;
1988 #ifdef SUPPORT_SET_CAC
1989 wl_cfg80211_set_cac(cfg, 1);
1990 #endif /* SUPPORT_SET_CAC */
1991 } else {
1992 WL_ERR(("IFDEL operation failed, error code = %d\n", err));
1993 }
1994
1995 memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
1996 wl_to_p2p_bss_bssidx(cfg, cfg_type) = -1;
1997 #ifdef PROP_TXSTATUS_VSDB
1998 #if defined(BCMSDIO) || defined(BCMDBUS)
1999 dhd_wlfc_get_enable(dhd, &enabled);
2000 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
2001 dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->conf->disable_proptx!=0) {
2002 dhd_wlfc_deinit(dhd);
2003 cfg->wlfc_on = false;
2004 }
2005 #endif /* BCMSDIO || BCMDBUS */
2006 #endif /* PROP_TXSTATUS_VSDB */
2007 }
2008 }
2009
2010 fail:
2011 mutex_unlock(&cfg->if_sync);
2012 if (err) {
2013 #ifdef WLTDLS
2014 /* Enable back TDLS on failure */
2015 wl_cfg80211_tdls_config(cfg, TDLS_STATE_IF_DELETE, false);
2016 #endif /* WLTDLS */
2017 if (err != -ENOTSUPP) {
2018 #if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2019 if (dhd->memdump_enabled) {
2020 /* Load the dongle side dump to host
2021 * memory and then BUG_ON()
2022 */
2023 dhd->memdump_type = DUMP_TYPE_HANG_ON_IFACE_OP_FAIL;
2024 dhd_bus_mem_dump(dhd);
2025 }
2026 #endif /* BCMPCIE && DHD_FW_COREDUMP */
2027 if (hang_required) {
2028 /* Notify the user space to recover */
2029 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
2030 WL_ERR(("if add failed, error %d, sent HANG event to %s\n",
2031 err, ndev->name));
2032 dhd->hang_reason = HANG_REASON_IFACE_OP_FAILURE;
2033 net_os_send_hang_message(ndev);
2034 }
2035 }
2036 }
2037 return ERR_PTR(err);
2038 }
2039
2040 static s32
2041 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
2042 {
2043 struct net_device *dev = NULL;
2044 struct ether_addr p2p_mac;
2045 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2046 s32 timeout = -1;
2047 s32 ret = 0;
2048 s32 index = -1;
2049 s32 type = -1;
2050 #if defined(CUSTOM_SET_CPUCORE) || defined(DHD_HANG_SEND_UP_TEST)
2051 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2052 #endif /* CUSTOM_SET_CPUCORE || DHD_HANG_SEND_UP_TEST */
2053 WL_DBG(("Enter\n"));
2054
2055 memset(&p2p_mac, 0, sizeof(struct ether_addr));
2056 #ifdef CUSTOM_SET_CPUCORE
2057 dhd->chan_isvht80 &= ~DHD_FLAG_P2P_MODE;
2058 if (!(dhd->chan_isvht80))
2059 dhd_set_cpucore(dhd, FALSE);
2060 #endif /* CUSTOM_SET_CPUCORE */
2061 mutex_lock(&cfg->if_sync);
2062 #ifdef WL_CFG80211_P2P_DEV_IF
2063 if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
2064 if (dhd_download_fw_on_driverload) {
2065 ret = wl_cfgp2p_del_p2p_disc_if(cfgdev, cfg);
2066 } else {
2067 cfg->down_disc_if = TRUE;
2068 ret = 0;
2069 }
2070 mutex_unlock(&cfg->if_sync);
2071 return ret;
2072 }
2073 #endif /* WL_CFG80211_P2P_DEV_IF */
2074 dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
2075
2076 #ifdef WLAIBSS_MCHAN
2077 if (cfgdev == cfg->ibss_cfgdev) {
2078 ret = bcm_cfg80211_del_ibss_if(wiphy, cfgdev);
2079 goto done;
2080 }
2081 #endif /* WLAIBSS_MCHAN */
2082
2083 if ((index = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
2084 WL_ERR(("Find p2p index from wdev failed\n"));
2085 ret = -ENODEV;
2086 goto done;
2087 }
2088 if ((cfg->p2p_supported) && index && (wl_cfgp2p_find_type(cfg, index, &type) == BCME_OK)) {
2089 /* Handle P2P Interace del */
2090 memcpy(p2p_mac.octet, wl_to_p2p_bss_macaddr(cfg, type).octet, ETHER_ADDR_LEN);
2091
2092 /* Clear GO_NEG_PHASE bit to take care of GO-NEG-FAIL cases
2093 */
2094 WL_DBG(("P2P: GO_NEG_PHASE status cleared "));
2095 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
2096 if (wl_cfgp2p_vif_created(cfg)) {
2097 if (wl_get_drv_status(cfg, SCANNING, dev)) {
2098 wl_notify_escan_complete(cfg, dev, true, true);
2099 }
2100 /* Delete pm_enable_work */
2101 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
2102
2103 /* for GC */
2104 if (wl_get_drv_status(cfg, DISCONNECTING, dev) &&
2105 (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)) {
2106 WL_ERR(("Wait for Link Down event for GC !\n"));
2107 wait_for_completion_timeout
2108 (&cfg->iface_disable, msecs_to_jiffies(500));
2109 }
2110
2111 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
2112 wl_set_p2p_status(cfg, IF_DELETING);
2113 DNGL_FUNC(dhd_cfg80211_clean_p2p_info, (cfg));
2114
2115 /* for GO */
2116 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
2117 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
2118 cfg->p2p->p2p_go_count--;
2119 /* disable interface before bsscfg free */
2120 ret = wl_cfgp2p_ifdisable(cfg, &p2p_mac);
2121 /* if fw doesn't support "ifdis",
2122 do not wait for link down of ap mode
2123 */
2124 if (ret == 0) {
2125 WL_ERR(("Wait for Link Down event for GO !!!\n"));
2126 wait_for_completion_timeout(&cfg->iface_disable,
2127 msecs_to_jiffies(500));
2128 } else if (ret != BCME_UNSUPPORTED) {
2129 msleep(300);
2130 }
2131 }
2132 wl_cfg80211_clear_per_bss_ies(cfg, index);
2133
2134 if (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP)
2135 wldev_iovar_setint(dev, "buf_key_b4_m4", 0);
2136 memcpy(p2p_mac.octet, wl_to_p2p_bss_macaddr(cfg, type).octet,
2137 ETHER_ADDR_LEN);
2138 CFGP2P_INFO(("primary idx %d : cfg p2p_ifdis "MACDBG"\n",
2139 dev->ifindex, MAC2STRDBG(p2p_mac.octet)));
2140
2141 /* delete interface after link down */
2142 ret = wl_cfgp2p_ifdel(cfg, &p2p_mac);
2143 #if defined(DHD_HANG_SEND_UP_TEST)
2144 if (ret != BCME_OK ||
2145 dhd->req_hang_type == HANG_REASON_IFACE_OP_FAILURE)
2146 #else /* DHD_HANG_SEND_UP_TEST */
2147 if (ret != BCME_OK)
2148 #endif /* DHD_HANG_SEND_UP_TEST */
2149 {
2150 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
2151 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2152
2153 WL_ERR(("p2p_ifdel failed, error %d, sent HANG event to %s\n",
2154 ret, ndev->name));
2155 #if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
2156 if (dhd->memdump_enabled) {
2157 /* Load the dongle side dump to host
2158 * memory and then BUG_ON()
2159 */
2160 dhd->memdump_type = DUMP_TYPE_HANG_ON_IFACE_OP_FAIL;
2161 dhd_bus_mem_dump(dhd);
2162 }
2163 #endif /* BCMPCIE && DHD_FW_COREDUMP */
2164 dhd->hang_reason = HANG_REASON_IFACE_OP_FAILURE;
2165 net_os_send_hang_message(ndev);
2166 } else {
2167 /* Wait for IF_DEL operation to be finished */
2168 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
2169 ((wl_get_p2p_status(cfg, IF_DELETING) == false) &&
2170 (cfg->if_event_info.valid)),
2171 msecs_to_jiffies(MAX_WAIT_TIME));
2172 if (timeout > 0 && !wl_get_p2p_status(cfg, IF_DELETING) &&
2173 cfg->if_event_info.valid) {
2174
2175 WL_DBG(("IFDEL operation done\n"));
2176 wl_cfg80211_handle_ifdel(cfg, &cfg->if_event_info, dev);
2177 } else {
2178 WL_ERR(("IFDEL didn't complete properly\n"));
2179 }
2180 #ifdef SUPPORT_SET_CAC
2181 wl_cfg80211_set_cac(cfg, 1);
2182 #endif /* SUPPORT_SET_CAC */
2183 }
2184
2185 ret = dhd_del_monitor(dev);
2186 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
2187 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_CANCEL((dhd_pub_t *)(cfg->pub));
2188 }
2189 }
2190 } else if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) ||
2191 (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION)) {
2192 #ifdef WL_VIRTUAL_APSTA
2193 ret = wl_cfg80211_del_iface(wiphy, cfgdev);
2194 #else
2195 WL_ERR(("Virtual APSTA not supported!\n"));
2196 #endif /* WL_VIRTUAL_APSTA */
2197 }
2198
2199 done:
2200 mutex_unlock(&cfg->if_sync);
2201 #ifdef WLTDLS
2202 if (ret == BCME_OK) {
2203 /* If interface del is success, try enabling back TDLS */
2204 wl_cfg80211_tdls_config(cfg, TDLS_STATE_IF_DELETE, false);
2205 }
2206 #endif /* WLTDLS */
2207 return ret;
2208 }
2209
2210 static s32
2211 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
2212 enum nl80211_iftype type,
2213 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
2214 u32 *flags,
2215 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0)) */
2216 struct vif_params *params)
2217 {
2218 s32 ap = 0;
2219 s32 infra_ibss = 1;
2220 s32 wlif_type;
2221 s32 mode = 0;
2222 s32 err = BCME_OK;
2223 s32 index;
2224 s32 conn_idx = -1;
2225 chanspec_t chspec;
2226 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
2227 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2228
2229 mutex_lock(&cfg->if_sync);
2230 WL_DBG(("Enter type %d\n", type));
2231 switch (type) {
2232 case NL80211_IFTYPE_MONITOR:
2233 case NL80211_IFTYPE_WDS:
2234 #ifndef WLMESH
2235 case NL80211_IFTYPE_MESH_POINT:
2236 #endif /* WLMESH */
2237 ap = 1;
2238 WL_ERR(("type (%d) : currently we do not support this type\n",
2239 type));
2240 break;
2241 #ifdef WLMESH
2242 case NL80211_IFTYPE_MESH_POINT:
2243 infra_ibss = WL_BSSTYPE_MESH;
2244 break;
2245 #endif /* WLMESH */
2246 case NL80211_IFTYPE_ADHOC:
2247 mode = WL_MODE_IBSS;
2248 infra_ibss = 0;
2249 break;
2250 case NL80211_IFTYPE_STATION:
2251 case NL80211_IFTYPE_P2P_CLIENT:
2252 if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
2253 s32 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2254 if (bssidx < 0) {
2255 /* validate bssidx */
2256 WL_ERR(("Wrong bssidx! \n"));
2257 err = -EINVAL;
2258 goto error;
2259 }
2260 WL_DBG(("del interface. bssidx:%d", bssidx));
2261 /* Downgrade role from AP to STA */
2262 if ((err = wl_cfg80211_add_del_bss(cfg, ndev,
2263 bssidx, NL80211_IFTYPE_STATION, 0, NULL)) < 0) {
2264 WL_ERR(("AP-STA Downgrade failed \n"));
2265 err = -EINVAL;
2266 goto error;
2267 }
2268 }
2269 mode = WL_MODE_BSS;
2270 break;
2271 case NL80211_IFTYPE_AP:
2272 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
2273 /* intentional fall through */
2274 case NL80211_IFTYPE_AP_VLAN:
2275 case NL80211_IFTYPE_P2P_GO:
2276 mode = WL_MODE_AP;
2277 ap = 1;
2278 break;
2279 default:
2280 err = -EINVAL;
2281 goto error;
2282 }
2283
2284 if (!dhd) {
2285 err = -EINVAL;
2286 goto error;
2287 }
2288 if (ap) {
2289 wl_set_mode_by_netdev(cfg, ndev, mode);
2290 if (is_p2p_group_iface(ndev->ieee80211_ptr) &&
2291 cfg->p2p && wl_cfgp2p_vif_created(cfg)) {
2292 WL_DBG(("p2p_vif_created p2p_on (%d)\n", p2p_on(cfg)));
2293 wl_notify_escan_complete(cfg, ndev, true, true);
2294
2295 /* Dual p2p doesn't support multiple P2PGO interfaces,
2296 * p2p_go_count is the counter for GO creation
2297 * requests.
2298 */
2299 if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
2300 wl_set_mode_by_netdev(cfg, ndev, WL_MODE_BSS);
2301 WL_ERR(("Fw does not support multiple GO\n"));
2302 err = BCME_ERROR;
2303 goto error;
2304 }
2305 /* In concurrency case, STA may be already associated in a particular
2306 * channel. so retrieve the current channel of primary interface and
2307 * then start the virtual interface on that.
2308 */
2309 chspec = wl_cfg80211_get_shared_freq(wiphy);
2310 index = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2311 if (index < 0) {
2312 WL_ERR(("Find p2p index from ndev(%p) failed\n", ndev));
2313 err = BCME_ERROR;
2314 goto error;
2315 }
2316 if (wl_cfgp2p_find_type(cfg, index, &conn_idx) != BCME_OK) {
2317 err = BCME_ERROR;
2318 goto error;
2319 }
2320
2321 wlif_type = WL_P2P_IF_GO;
2322 printf("%s: %s ap (%d), infra_ibss (%d), iftype (%d) conn_idx (%d)\n",
2323 __FUNCTION__, ndev->name, ap, infra_ibss, type, conn_idx);
2324 wl_set_p2p_status(cfg, IF_CHANGING);
2325 wl_clr_p2p_status(cfg, IF_CHANGED);
2326 wl_cfgp2p_ifchange(cfg, wl_to_p2p_bss_macaddr(cfg, conn_idx),
2327 htod32(wlif_type), chspec, conn_idx);
2328 wait_event_interruptible_timeout(cfg->netif_change_event,
2329 (wl_get_p2p_status(cfg, IF_CHANGED) == true),
2330 msecs_to_jiffies(MAX_WAIT_TIME));
2331 wl_set_mode_by_netdev(cfg, ndev, mode);
2332 dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
2333 dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
2334 wl_clr_p2p_status(cfg, IF_CHANGING);
2335 wl_clr_p2p_status(cfg, IF_CHANGED);
2336 if (mode == WL_MODE_AP)
2337 wl_set_drv_status(cfg, CONNECTED, ndev);
2338 #ifdef SUPPORT_AP_POWERSAVE
2339 dhd_set_ap_powersave(dhd, 0, TRUE);
2340 #endif /* SUPPORT_AP_POWERSAVE */
2341 } else if ((type == NL80211_IFTYPE_AP) &&
2342 !wl_get_drv_status(cfg, AP_CREATED, ndev)) {
2343 #if 0
2344 err = wl_cfg80211_set_ap_role(cfg, ndev);
2345 if (unlikely(err)) {
2346 WL_ERR(("set ap role failed!\n"));
2347 goto error;
2348 }
2349 #else
2350 wl_set_drv_status(cfg, AP_CREATING, ndev);
2351 #endif
2352 } else {
2353 WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
2354 err = -EINVAL;
2355 goto error;
2356 }
2357 } else {
2358 /* P2P GO interface deletion is handled on the basis of role type (AP).
2359 * So avoid changing role for p2p type.
2360 */
2361 if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
2362 wl_set_mode_by_netdev(cfg, ndev, mode);
2363 WL_DBG(("Change_virtual_iface for transition from GO/AP to client/STA\n"));
2364 #ifdef SUPPORT_AP_POWERSAVE
2365 dhd_set_ap_powersave(dhd, 0, FALSE);
2366 #endif /* SUPPORT_AP_POWERSAVE */
2367 }
2368
2369 if (!infra_ibss) {
2370 err = wldev_ioctl_set(ndev, WLC_SET_INFRA, &infra_ibss, sizeof(s32));
2371 if (err < 0) {
2372 WL_ERR(("SET INFRA/IBSS error %d\n", err));
2373 err = -EINVAL;
2374 goto error;
2375 }
2376 }
2377
2378 WL_DBG(("Setting iftype to %d \n", type));
2379 ndev->ieee80211_ptr->iftype = type;
2380 error:
2381 mutex_unlock(&cfg->if_sync);
2382 return err;
2383 }
2384
2385 s32
2386 wl_cfg80211_notify_ifadd(struct net_device *dev, int ifidx, char *name, uint8 *mac, uint8 bssidx)
2387 {
2388 bool ifadd_expected = FALSE;
2389 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2390
2391 /* P2P may send WLC_E_IF_ADD and/or WLC_E_IF_CHANGE during IF updating ("p2p_ifupd")
2392 * redirect the IF_ADD event to ifchange as it is not a real "new" interface
2393 */
2394 if (wl_get_p2p_status(cfg, IF_CHANGING))
2395 return wl_cfg80211_notify_ifchange(dev, ifidx, name, mac, bssidx);
2396
2397 /* Okay, we are expecting IF_ADD (as IF_ADDING is true) */
2398 if (wl_get_p2p_status(cfg, IF_ADDING)) {
2399 ifadd_expected = TRUE;
2400 wl_clr_p2p_status(cfg, IF_ADDING);
2401 } else if (cfg->bss_pending_op) {
2402 ifadd_expected = TRUE;
2403 cfg->bss_pending_op = FALSE;
2404 }
2405
2406 if (ifadd_expected) {
2407 wl_if_event_info *if_event_info = &cfg->if_event_info;
2408
2409 if_event_info->valid = TRUE;
2410 if_event_info->ifidx = ifidx;
2411 if_event_info->bssidx = bssidx;
2412 strncpy(if_event_info->name, name, IFNAMSIZ);
2413 if_event_info->name[IFNAMSIZ] = '\0';
2414 if (mac)
2415 memcpy(if_event_info->mac, mac, ETHER_ADDR_LEN);
2416 wake_up_interruptible(&cfg->netif_change_event);
2417 return BCME_OK;
2418 }
2419
2420 return BCME_ERROR;
2421 }
2422
2423 s32
2424 wl_cfg80211_notify_ifdel(struct net_device *dev, int ifidx, char *name, uint8 *mac, uint8 bssidx)
2425 {
2426 bool ifdel_expected = FALSE;
2427 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2428 wl_if_event_info *if_event_info = &cfg->if_event_info;
2429
2430 if (wl_get_p2p_status(cfg, IF_DELETING)) {
2431 ifdel_expected = TRUE;
2432 wl_clr_p2p_status(cfg, IF_DELETING);
2433 } else if (cfg->bss_pending_op) {
2434 ifdel_expected = TRUE;
2435 cfg->bss_pending_op = FALSE;
2436 }
2437
2438 if (ifdel_expected) {
2439 if_event_info->valid = TRUE;
2440 if_event_info->ifidx = ifidx;
2441 if_event_info->bssidx = bssidx;
2442 wake_up_interruptible(&cfg->netif_change_event);
2443 return BCME_OK;
2444 }
2445
2446 return BCME_ERROR;
2447 }
2448
2449 s32
2450 wl_cfg80211_notify_ifchange(struct net_device * dev, int ifidx, char *name, uint8 *mac,
2451 uint8 bssidx)
2452 {
2453 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2454
2455 if (wl_get_p2p_status(cfg, IF_CHANGING)) {
2456 wl_set_p2p_status(cfg, IF_CHANGED);
2457 wake_up_interruptible(&cfg->netif_change_event);
2458 return BCME_OK;
2459 }
2460
2461 return BCME_ERROR;
2462 }
2463
2464 static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *if_event_info,
2465 struct net_device* ndev)
2466 {
2467 s32 type = -1;
2468 s32 bssidx = -1;
2469 #ifdef PROP_TXSTATUS_VSDB
2470 #if defined(BCMSDIO) || defined(BCMDBUS)
2471 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2472 bool enabled;
2473 #endif /* BCMSDIO || BCMDBUS */
2474 #endif /* PROP_TXSTATUS_VSDB */
2475
2476 bssidx = if_event_info->bssidx;
2477 if (bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) &&
2478 bssidx != wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2)) {
2479 WL_ERR(("got IF_DEL for if %d, not owned by cfg driver\n", bssidx));
2480 return BCME_ERROR;
2481 }
2482
2483 if (p2p_is_on(cfg) && wl_cfgp2p_vif_created(cfg)) {
2484 if (cfg->scan_request && (cfg->escan_info.ndev == ndev)) {
2485 /* Abort any pending scan requests */
2486 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
2487 WL_DBG(("ESCAN COMPLETED\n"));
2488 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, false);
2489 }
2490
2491 memset(cfg->p2p->vir_ifname, '\0', IFNAMSIZ);
2492 if (wl_cfgp2p_find_type(cfg, bssidx, &type) == BCME_OK) {
2493 /* Update P2P data */
2494 wl_clr_drv_status(cfg, CONNECTED, wl_to_p2p_bss_ndev(cfg, type));
2495 wl_to_p2p_bss_ndev(cfg, type) = NULL;
2496 wl_to_p2p_bss_bssidx(cfg, type) = -1;
2497 } else if (wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr) < 0) {
2498 WL_ERR(("bssidx not known for the given ndev as per net_info data \n"));
2499 return BCME_ERROR;
2500 }
2501
2502 #ifdef PROP_TXSTATUS_VSDB
2503 #if defined(BCMSDIO) || defined(BCMDBUS)
2504 dhd_wlfc_get_enable(dhd, &enabled);
2505 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
2506 dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->conf->disable_proptx!=0) {
2507 dhd_wlfc_deinit(dhd);
2508 cfg->wlfc_on = false;
2509 }
2510 #endif /* BCMSDIO || BCMDBUS */
2511 #endif /* PROP_TXSTATUS_VSDB */
2512 }
2513
2514 dhd_net_if_lock(ndev);
2515 wl_cfg80211_remove_if(cfg, if_event_info->ifidx, ndev, FALSE);
2516 dhd_net_if_unlock(ndev);
2517
2518 return BCME_OK;
2519 }
2520
2521 /* Find listen channel */
2522 static s32 wl_find_listen_channel(struct bcm_cfg80211 *cfg,
2523 const u8 *ie, u32 ie_len)
2524 {
2525 wifi_p2p_ie_t *p2p_ie;
2526 u8 *end, *pos;
2527 s32 listen_channel;
2528
2529 /* unfortunately const cast required here - function is
2530 * a callback so its signature must not be changed
2531 * and cascade of changing wl_cfgp2p_find_p2pie
2532 * causes need for const cast in other places
2533 */
2534 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2535 4 && __GNUC_MINOR__ >= 6))
2536 _Pragma("GCC diagnostic push")
2537 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
2538 #endif
2539 pos = (u8 *)ie;
2540 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
2541 4 && __GNUC_MINOR__ >= 6))
2542 _Pragma("GCC diagnostic pop")
2543 #endif
2544 p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len);
2545
2546 if (p2p_ie == NULL)
2547 return 0;
2548
2549 pos = p2p_ie->subelts;
2550 end = p2p_ie->subelts + (p2p_ie->len - 4);
2551
2552 CFGP2P_DBG((" found p2p ie ! lenth %d \n",
2553 p2p_ie->len));
2554
2555 while (pos < end) {
2556 uint16 attr_len;
2557 if (pos + 2 >= end) {
2558 CFGP2P_DBG((" -- Invalid P2P attribute"));
2559 return 0;
2560 }
2561 attr_len = ((uint16) (((pos + 1)[1] << 8) | (pos + 1)[0]));
2562
2563 if (pos + 3 + attr_len > end) {
2564 CFGP2P_DBG(("P2P: Attribute underflow "
2565 "(len=%u left=%d)",
2566 attr_len, (int) (end - pos - 3)));
2567 return 0;
2568 }
2569
2570 /* if Listen Channel att id is 6 and the vailue is valid,
2571 * return the listen channel
2572 */
2573 if (pos[0] == 6) {
2574 /* listen channel subel length format
2575 * 1(id) + 2(len) + 3(country) + 1(op. class) + 1(chan num)
2576 */
2577 listen_channel = pos[1 + 2 + 3 + 1];
2578
2579 if (listen_channel == SOCIAL_CHAN_1 ||
2580 listen_channel == SOCIAL_CHAN_2 ||
2581 listen_channel == SOCIAL_CHAN_3) {
2582 CFGP2P_DBG((" Found my Listen Channel %d \n", listen_channel));
2583 return listen_channel;
2584 }
2585 }
2586 pos += 3 + attr_len;
2587 }
2588 return 0;
2589 }
2590
2591 static void wl_scan_prep(struct bcm_cfg80211 *cfg, struct wl_scan_params *params,
2592 struct cfg80211_scan_request *request)
2593 {
2594 u32 n_ssids;
2595 u32 n_channels;
2596 u16 channel;
2597 chanspec_t chanspec;
2598 s32 i = 0, j = 0, offset;
2599 char *ptr;
2600 wlc_ssid_t ssid;
2601 struct wireless_dev *wdev;
2602
2603 memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
2604 params->bss_type = DOT11_BSSTYPE_ANY;
2605 params->scan_type = 0;
2606 params->nprobes = -1;
2607 params->active_time = -1;
2608 params->passive_time = -1;
2609 params->home_time = -1;
2610 params->channel_num = 0;
2611 memset(&params->ssid, 0, sizeof(wlc_ssid_t));
2612
2613 WL_SCAN(("Preparing Scan request\n"));
2614 WL_SCAN(("nprobes=%d\n", params->nprobes));
2615 WL_SCAN(("active_time=%d\n", params->active_time));
2616 WL_SCAN(("passive_time=%d\n", params->passive_time));
2617 WL_SCAN(("home_time=%d\n", params->home_time));
2618 WL_SCAN(("scan_type=%d\n", params->scan_type));
2619
2620 params->nprobes = htod32(params->nprobes);
2621 params->active_time = htod32(params->active_time);
2622 params->passive_time = htod32(params->passive_time);
2623 params->home_time = htod32(params->home_time);
2624
2625 /* if request is null just exit so it will be all channel broadcast scan */
2626 if (!request)
2627 return;
2628
2629 n_ssids = request->n_ssids;
2630 n_channels = request->n_channels;
2631
2632 /* Copy channel array if applicable */
2633 WL_SCAN(("### List of channelspecs to scan ###\n"));
2634 if (n_channels > 0) {
2635 for (i = 0; i < n_channels; i++) {
2636 channel = ieee80211_frequency_to_channel(request->channels[i]->center_freq);
2637 /* SKIP DFS channels for Secondary interface */
2638 if ((cfg->escan_info.ndev != bcmcfg_to_prmry_ndev(cfg)) &&
2639 (request->channels[i]->flags &
2640 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
2641 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)))
2642 #else
2643 (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_NO_IR)))
2644 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0) */
2645 continue;
2646 if (!dhd_conf_match_channel(cfg->pub, channel))
2647 continue;
2648
2649 #if defined(WL_CFG80211_P2P_DEV_IF)
2650 wdev = request->wdev;
2651 #else
2652 wdev = request->dev->ieee80211_ptr;
2653 #endif /* WL_CFG80211_P2P_DEV_IF */
2654 chanspec = wl_cfg80211_ulb_get_min_bw_chspec(cfg, wdev, -1);
2655 if (chanspec == INVCHANSPEC) {
2656 WL_ERR(("Invalid chanspec! Skipping channel\n"));
2657 continue;
2658 }
2659
2660 if (request->channels[i]->band == IEEE80211_BAND_2GHZ) {
2661 chanspec |= WL_CHANSPEC_BAND_2G;
2662 } else {
2663 chanspec |= WL_CHANSPEC_BAND_5G;
2664 }
2665 params->channel_list[j] = channel;
2666 params->channel_list[j] &= WL_CHANSPEC_CHAN_MASK;
2667 params->channel_list[j] |= chanspec;
2668 WL_SCAN(("Chan : %d, Channel spec: %x \n",
2669 channel, params->channel_list[j]));
2670 params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
2671 j++;
2672 }
2673 } else {
2674 WL_SCAN(("Scanning all channels\n"));
2675 }
2676 n_channels = j;
2677 /* Copy ssid array if applicable */
2678 WL_SCAN(("### List of SSIDs to scan ###\n"));
2679 if (n_ssids > 0) {
2680 offset = offsetof(wl_scan_params_t, channel_list) + n_channels * sizeof(u16);
2681 offset = roundup(offset, sizeof(u32));
2682 ptr = (char*)params + offset;
2683 for (i = 0; i < n_ssids; i++) {
2684 memset(&ssid, 0, sizeof(wlc_ssid_t));
2685 ssid.SSID_len = MIN(request->ssids[i].ssid_len, DOT11_MAX_SSID_LEN);
2686 memcpy(ssid.SSID, request->ssids[i].ssid, ssid.SSID_len);
2687 if (!ssid.SSID_len)
2688 WL_SCAN(("%d: Broadcast scan\n", i));
2689 else
2690 WL_SCAN(("%d: scan for %s size =%d\n", i,
2691 ssid.SSID, ssid.SSID_len));
2692 memcpy(ptr, &ssid, sizeof(wlc_ssid_t));
2693 ptr += sizeof(wlc_ssid_t);
2694 }
2695 } else {
2696 WL_SCAN(("Broadcast scan\n"));
2697 }
2698 /* Adding mask to channel numbers */
2699 params->channel_num =
2700 htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) |
2701 (n_channels & WL_SCAN_PARAMS_COUNT_MASK));
2702
2703 if (n_channels == 1) {
2704 params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
2705 params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS);
2706 }
2707 }
2708
2709 static s32
2710 wl_get_valid_channels(struct net_device *ndev, u8 *valid_chan_list, s32 size)
2711 {
2712 wl_uint32_list_t *list;
2713 s32 err = BCME_OK;
2714 if (valid_chan_list == NULL || size <= 0)
2715 return -ENOMEM;
2716
2717 memset(valid_chan_list, 0, size);
2718 list = (wl_uint32_list_t *)(void *) valid_chan_list;
2719 list->count = htod32(WL_NUMCHANNELS);
2720 err = wldev_ioctl_get(ndev, WLC_GET_VALID_CHANNELS, valid_chan_list, size);
2721 if (err != 0) {
2722 WL_ERR(("get channels failed with %d\n", err));
2723 }
2724
2725 return err;
2726 }
2727
2728 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2729 #define FIRST_SCAN_ACTIVE_DWELL_TIME_MS 40
2730 bool g_first_broadcast_scan = TRUE;
2731 #endif
2732
2733 static s32
2734 wl_run_escan(struct bcm_cfg80211 *cfg, struct net_device *ndev,
2735 struct cfg80211_scan_request *request, uint16 action)
2736 {
2737 s32 err = BCME_OK;
2738 u32 n_channels;
2739 u32 n_ssids;
2740 s32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params));
2741 wl_escan_params_t *params = NULL;
2742 u8 chan_buf[sizeof(u32)*(WL_NUMCHANNELS + 1)];
2743 u32 num_chans = 0;
2744 s32 channel;
2745 u32 n_valid_chan;
2746 s32 search_state = WL_P2P_DISC_ST_SCAN;
2747 u32 i, j, n_nodfs = 0;
2748 u16 *default_chan_list = NULL;
2749 wl_uint32_list_t *list;
2750 s32 bssidx = -1;
2751 struct net_device *dev = NULL;
2752 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2753 bool is_first_init_2g_scan = false;
2754 #endif
2755 p2p_scan_purpose_t p2p_scan_purpose = P2P_SCAN_PURPOSE_MIN;
2756 scb_val_t scbval;
2757 static int cnt = 0;
2758
2759 WL_DBG(("Enter \n"));
2760
2761 /* scan request can come with empty request : perform all default scan */
2762 if (!cfg) {
2763 err = -EINVAL;
2764 goto exit;
2765 }
2766 if (!cfg->p2p_supported || !p2p_scan(cfg)) {
2767 /* LEGACY SCAN TRIGGER */
2768 WL_SCAN((" LEGACY E-SCAN START\n"));
2769
2770 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2771 if (!request) {
2772 err = -EINVAL;
2773 goto exit;
2774 }
2775 if (ndev == bcmcfg_to_prmry_ndev(cfg) && g_first_broadcast_scan == true) {
2776 is_first_init_2g_scan = true;
2777 g_first_broadcast_scan = false;
2778 }
2779 #endif
2780
2781 /* if scan request is not empty parse scan request paramters */
2782 if (request != NULL) {
2783 n_channels = request->n_channels;
2784 n_ssids = request->n_ssids;
2785 if (n_channels % 2)
2786 /* If n_channels is odd, add a padd of u16 */
2787 params_size += sizeof(u16) * (n_channels + 1);
2788 else
2789 params_size += sizeof(u16) * n_channels;
2790
2791 /* Allocate space for populating ssids in wl_escan_params_t struct */
2792 params_size += sizeof(struct wlc_ssid) * n_ssids;
2793 }
2794 params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL);
2795 if (params == NULL) {
2796 err = -ENOMEM;
2797 goto exit;
2798 }
2799 wl_scan_prep(cfg, &params->params, request);
2800
2801 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
2802 /* Override active_time to reduce scan time if it's first bradcast scan. */
2803 if (is_first_init_2g_scan)
2804 params->params.active_time = FIRST_SCAN_ACTIVE_DWELL_TIME_MS;
2805 #endif
2806
2807 params->version = htod32(ESCAN_REQ_VERSION);
2808 params->action = htod16(action);
2809 wl_escan_set_sync_id(params->sync_id, cfg);
2810 wl_escan_set_type(cfg, WL_SCANTYPE_LEGACY);
2811 if (params_size + sizeof("escan") >= WLC_IOCTL_MEDLEN) {
2812 WL_ERR(("ioctl buffer length not sufficient\n"));
2813 kfree(params);
2814 err = -ENOMEM;
2815 goto exit;
2816 }
2817 if (cfg->active_scan == PASSIVE_SCAN) {
2818 params->params.scan_type = DOT11_SCANTYPE_PASSIVE;
2819 WL_DBG(("Passive scan_type %d \n", params->params.scan_type));
2820 }
2821
2822 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
2823
2824 err = wldev_iovar_setbuf(ndev, "escan", params, params_size,
2825 cfg->escan_ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
2826 printf("%s: LEGACY_SCAN sync ID: %d, bssidx: %d\n", __FUNCTION__, params->sync_id, bssidx);
2827 if (unlikely(err)) {
2828 if (err == BCME_EPERM)
2829 /* Scan Not permitted at this point of time */
2830 WL_DBG((" Escan not permitted at this time (%d)\n", err));
2831 else
2832 WL_ERR((" Escan set error (%d)\n", err));
2833 } else {
2834 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_REQUESTED);
2835 }
2836 kfree(params);
2837 }
2838 else if (p2p_is_on(cfg) && p2p_scan(cfg)) {
2839 /* P2P SCAN TRIGGER */
2840 s32 _freq = 0;
2841 n_nodfs = 0;
2842 if (request && request->n_channels) {
2843 num_chans = request->n_channels;
2844 WL_SCAN((" chann number : %d\n", num_chans));
2845 default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
2846 GFP_KERNEL);
2847 if (default_chan_list == NULL) {
2848 WL_ERR(("channel list allocation failed \n"));
2849 err = -ENOMEM;
2850 goto exit;
2851 }
2852 if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) {
2853 #ifdef P2P_SKIP_DFS
2854 int is_printed = false;
2855 #endif /* P2P_SKIP_DFS */
2856 list = (wl_uint32_list_t *) chan_buf;
2857 n_valid_chan = dtoh32(list->count);
2858 if (n_valid_chan > WL_NUMCHANNELS) {
2859 WL_ERR(("wrong n_valid_chan:%d\n", n_valid_chan));
2860 kfree(default_chan_list);
2861 err = -EINVAL;
2862 goto exit;
2863 }
2864
2865 for (i = 0; i < num_chans; i++)
2866 {
2867 _freq = request->channels[i]->center_freq;
2868 channel = ieee80211_frequency_to_channel(_freq);
2869
2870 /* ignore DFS channels */
2871 if (request->channels[i]->flags &
2872 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
2873 (IEEE80211_CHAN_NO_IR
2874 | IEEE80211_CHAN_RADAR))
2875 #else
2876 (IEEE80211_CHAN_RADAR
2877 | IEEE80211_CHAN_PASSIVE_SCAN))
2878 #endif
2879 continue;
2880 #ifdef P2P_SKIP_DFS
2881 if (channel >= 52 && channel <= 144) {
2882 if (is_printed == false) {
2883 WL_ERR(("SKIP DFS CHANs(52~144)\n"));
2884 is_printed = true;
2885 }
2886 continue;
2887 }
2888 #endif /* P2P_SKIP_DFS */
2889
2890 for (j = 0; j < n_valid_chan; j++) {
2891 /* allows only supported channel on
2892 * current reguatory
2893 */
2894 if (n_nodfs >= num_chans) {
2895 break;
2896 }
2897 if (channel == (dtoh32(list->element[j]))) {
2898 default_chan_list[n_nodfs++] =
2899 channel;
2900 }
2901 }
2902
2903 }
2904 }
2905 if (num_chans == SOCIAL_CHAN_CNT && (
2906 (default_chan_list[0] == SOCIAL_CHAN_1) &&
2907 (default_chan_list[1] == SOCIAL_CHAN_2) &&
2908 (default_chan_list[2] == SOCIAL_CHAN_3))) {
2909 /* SOCIAL CHANNELS 1, 6, 11 */
2910 search_state = WL_P2P_DISC_ST_SEARCH;
2911 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2912 WL_INFORM(("P2P SEARCH PHASE START \n"));
2913 } else if (((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1)) &&
2914 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) ||
2915 ((dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2)) &&
2916 (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP))) {
2917 /* If you are already a GO, then do SEARCH only */
2918 WL_INFORM(("Already a GO. Do SEARCH Only"));
2919 search_state = WL_P2P_DISC_ST_SEARCH;
2920 num_chans = n_nodfs;
2921 p2p_scan_purpose = P2P_SCAN_NORMAL;
2922
2923 } else if (num_chans == 1) {
2924 p2p_scan_purpose = P2P_SCAN_CONNECT_TRY;
2925 } else if (num_chans == SOCIAL_CHAN_CNT + 1) {
2926 /* SOCIAL_CHAN_CNT + 1 takes care of the Progressive scan supported by
2927 * the supplicant
2928 */
2929 p2p_scan_purpose = P2P_SCAN_SOCIAL_CHANNEL;
2930 } else {
2931 WL_INFORM(("P2P SCAN STATE START \n"));
2932 num_chans = n_nodfs;
2933 p2p_scan_purpose = P2P_SCAN_NORMAL;
2934 }
2935 } else {
2936 err = -EINVAL;
2937 goto exit;
2938 }
2939 err = wl_cfgp2p_escan(cfg, ndev, ACTIVE_SCAN, num_chans, default_chan_list,
2940 search_state, action,
2941 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE), NULL,
2942 p2p_scan_purpose);
2943
2944 if (!err)
2945 cfg->p2p->search_state = search_state;
2946
2947 kfree(default_chan_list);
2948 }
2949 exit:
2950 if (unlikely(err)) {
2951 int suppressed = 0;
2952 wldev_ioctl(dev, WLC_GET_SCANSUPPRESS, &suppressed, sizeof(int), false);
2953 /* Don't print Error incase of Scan suppress */
2954 if ((err == BCME_EPERM) && (cfg->scan_suppressed || suppressed)) {
2955 cnt = 0;
2956 WL_DBG(("Escan failed: Scan Suppressed \n"));
2957 } else {
2958 cnt++;
2959 WL_ERR(("error (%d), cnt=%d\n", err, cnt));
2960 // terence 20140111: send disassoc to firmware
2961 if (cnt >= 4) {
2962 dev = bcmcfg_to_prmry_ndev(cfg);
2963 memset(&scbval, 0, sizeof(scb_val_t));
2964 wldev_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t), true);
2965 WL_ERR(("Send disassoc to break the busy dev=%p\n", dev));
2966 cnt = 0;
2967 }
2968 }
2969 } else {
2970 cnt = 0;
2971 }
2972 return err;
2973 }
2974
2975
2976 static s32
2977 wl_do_escan(struct bcm_cfg80211 *cfg, struct wiphy *wiphy, struct net_device *ndev,
2978 struct cfg80211_scan_request *request)
2979 {
2980 s32 err = BCME_OK;
2981 s32 passive_scan = 0;
2982 s32 passive_scan_time = 0;
2983 s32 passive_scan_time_org = 0;
2984 wl_scan_results_t *results;
2985 WL_SCAN(("Enter \n"));
2986
2987 results = wl_escan_get_buf(cfg, FALSE);
2988 results->version = 0;
2989 results->count = 0;
2990 results->buflen = WL_SCAN_RESULTS_FIXED_SIZE;
2991
2992 cfg->escan_info.ndev = ndev;
2993 cfg->escan_info.wiphy = wiphy;
2994 cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
2995 passive_scan = cfg->active_scan ? 0 : 1;
2996 err = wldev_ioctl_set(ndev, WLC_SET_PASSIVE_SCAN,
2997 &passive_scan, sizeof(passive_scan));
2998 if (unlikely(err)) {
2999 WL_ERR(("error (%d)\n", err));
3000 goto exit;
3001 }
3002
3003 if (passive_channel_skip) {
3004
3005 err = wldev_ioctl_get(ndev, WLC_GET_SCAN_PASSIVE_TIME,
3006 &passive_scan_time_org, sizeof(passive_scan_time_org));
3007 if (unlikely(err)) {
3008 WL_ERR(("== error (%d)\n", err));
3009 goto exit;
3010 }
3011
3012 WL_SCAN(("PASSIVE SCAN time : %d \n", passive_scan_time_org));
3013
3014 passive_scan_time = 0;
3015 err = wldev_ioctl_set(ndev, WLC_SET_SCAN_PASSIVE_TIME,
3016 &passive_scan_time, sizeof(passive_scan_time));
3017 if (unlikely(err)) {
3018 WL_ERR(("== error (%d)\n", err));
3019 goto exit;
3020 }
3021
3022 WL_SCAN(("PASSIVE SCAN SKIPED!! (passive_channel_skip:%d) \n",
3023 passive_channel_skip));
3024 }
3025
3026 err = wl_run_escan(cfg, ndev, request, WL_SCAN_ACTION_START);
3027
3028 if (passive_channel_skip) {
3029 err = wldev_ioctl_set(ndev, WLC_SET_SCAN_PASSIVE_TIME,
3030 &passive_scan_time_org, sizeof(passive_scan_time_org));
3031 if (unlikely(err)) {
3032 WL_ERR(("== error (%d)\n", err));
3033 goto exit;
3034 }
3035
3036 WL_SCAN(("PASSIVE SCAN RECOVERED!! (passive_scan_time_org:%d) \n",
3037 passive_scan_time_org));
3038 }
3039
3040 exit:
3041 return err;
3042 }
3043
3044 static s32
3045 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
3046 struct cfg80211_scan_request *request,
3047 struct cfg80211_ssid *this_ssid)
3048 {
3049 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3050 struct cfg80211_ssid *ssids;
3051 struct ether_addr primary_mac;
3052 bool p2p_ssid;
3053 #ifdef WL11U
3054 bcm_tlv_t *interworking_ie;
3055 #endif
3056 s32 err = 0;
3057 s32 bssidx = -1;
3058 s32 i;
3059
3060 unsigned long flags;
3061 static s32 busy_count = 0;
3062 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
3063 struct net_device *remain_on_channel_ndev = NULL;
3064 #endif
3065 uint scan_timer_interval_ms = WL_SCAN_TIMER_INTERVAL_MS;
3066
3067 /*
3068 * Hostapd triggers scan before starting automatic channel selection
3069 * to collect channel characteristics. However firmware scan engine
3070 * doesn't support any channel characteristics collection along with
3071 * scan. Hence return scan success.
3072 */
3073 if (request && (scan_req_iftype(request) == NL80211_IFTYPE_AP)) {
3074 WL_INFORM(("Scan Command on SoftAP Interface. Ignoring...\n"));
3075 // terence 20161023: let it scan in SoftAP mode
3076 // return 0;
3077 }
3078
3079 ndev = ndev_to_wlc_ndev(ndev, cfg);
3080
3081 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
3082 WL_ERR(("Sending Action Frames. Try it again.\n"));
3083 return -EAGAIN;
3084 }
3085
3086 WL_DBG(("Enter wiphy (%p)\n", wiphy));
3087 if (wl_get_drv_status_all(cfg, SCANNING)) {
3088 if (cfg->scan_request == NULL) {
3089 wl_clr_drv_status_all(cfg, SCANNING);
3090 WL_DBG(("<<<<<<<<<<<Force Clear Scanning Status>>>>>>>>>>>\n"));
3091 } else {
3092 WL_ERR(("Scanning already\n"));
3093 return -EAGAIN;
3094 }
3095 }
3096 if (wl_get_drv_status(cfg, SCAN_ABORTING, ndev)) {
3097 WL_ERR(("Scanning being aborted\n"));
3098 return -EAGAIN;
3099 }
3100 if (request && request->n_ssids > WL_SCAN_PARAMS_SSID_MAX) {
3101 WL_ERR(("request null or n_ssids > WL_SCAN_PARAMS_SSID_MAX\n"));
3102 return -EOPNOTSUPP;
3103 }
3104
3105 #ifdef P2P_LISTEN_OFFLOADING
3106 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
3107 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
3108 return -EAGAIN;
3109 }
3110 #endif /* P2P_LISTEN_OFFLOADING */
3111
3112 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
3113 remain_on_channel_ndev = wl_cfg80211_get_remain_on_channel_ndev(cfg);
3114 if (remain_on_channel_ndev) {
3115 WL_DBG(("Remain_on_channel bit is set, somehow it didn't get cleared\n"));
3116 wl_notify_escan_complete(cfg, remain_on_channel_ndev, true, true);
3117 }
3118 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
3119
3120
3121 /* Arm scan timeout timer */
3122 mod_timer(&cfg->scan_timeout, jiffies + msecs_to_jiffies(scan_timer_interval_ms));
3123 if (request) { /* scan bss */
3124 ssids = request->ssids;
3125 p2p_ssid = false;
3126 for (i = 0; i < request->n_ssids; i++) {
3127 if (ssids[i].ssid_len &&
3128 IS_P2P_SSID(ssids[i].ssid, ssids[i].ssid_len)) {
3129 p2p_ssid = true;
3130 break;
3131 }
3132 }
3133 if (p2p_ssid) {
3134 if (cfg->p2p_supported) {
3135 /* p2p scan trigger */
3136 if (p2p_on(cfg) == false) {
3137 /* p2p on at the first time */
3138 p2p_on(cfg) = true;
3139 wl_cfgp2p_set_firm_p2p(cfg);
3140 get_primary_mac(cfg, &primary_mac);
3141 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
3142 #if defined(P2P_IE_MISSING_FIX)
3143 cfg->p2p_prb_noti = false;
3144 #endif
3145 }
3146 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
3147 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
3148 p2p_scan(cfg) = true;
3149 }
3150 } else {
3151 /* legacy scan trigger
3152 * So, we have to disable p2p discovery if p2p discovery is on
3153 */
3154 if (cfg->p2p_supported) {
3155 p2p_scan(cfg) = false;
3156 /* If Netdevice is not equals to primary and p2p is on
3157 * , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
3158 */
3159
3160 if (p2p_scan(cfg) == false) {
3161 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
3162 err = wl_cfgp2p_discover_enable_search(cfg,
3163 false);
3164 if (unlikely(err)) {
3165 goto scan_out;
3166 }
3167
3168 }
3169 }
3170 }
3171 if (!cfg->p2p_supported || !p2p_scan(cfg)) {
3172 if ((bssidx = wl_get_bssidx_by_wdev(cfg,
3173 ndev->ieee80211_ptr)) < 0) {
3174 WL_ERR(("Find p2p index from ndev(%p) failed\n",
3175 ndev));
3176 err = BCME_ERROR;
3177 goto scan_out;
3178 }
3179 #ifdef WL11U
3180 if (request && (interworking_ie =
3181 wl_cfg80211_find_interworking_ie(
3182 request->ie, request->ie_len)) != NULL) {
3183 if ((err = wl_cfg80211_add_iw_ie(cfg, ndev, bssidx,
3184 VNDR_IE_CUSTOM_FLAG, interworking_ie->id,
3185 interworking_ie->data,
3186 interworking_ie->len)) != BCME_OK) {
3187 WL_ERR(("Failed to add interworking IE"));
3188 }
3189 } else if (cfg->wl11u) {
3190 /* we have to clear IW IE and disable gratuitous APR */
3191 wl_cfg80211_clear_iw_ie(cfg, ndev, bssidx);
3192 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp",
3193 0, bssidx);
3194 /* we don't care about error here
3195 * because the only failure case is unsupported,
3196 * which is fine
3197 */
3198 if (unlikely(err)) {
3199 WL_ERR(("Set grat_arp failed:(%d) Ignore!\n", err));
3200 }
3201 cfg->wl11u = FALSE;
3202 }
3203 #endif /* WL11U */
3204 if (request) {
3205 err = wl_cfg80211_set_mgmt_vndr_ies(cfg,
3206 ndev_to_cfgdev(ndev),
3207 bssidx, VNDR_IE_PRBREQ_FLAG, request->ie,
3208 request->ie_len);
3209 }
3210
3211 if (unlikely(err)) {
3212 // terence 20161023: let it scan in SoftAP mode
3213 // goto scan_out;
3214 }
3215
3216 }
3217 }
3218 } else { /* scan in ibss */
3219 ssids = this_ssid;
3220 }
3221
3222 if (request && cfg->p2p_supported) {
3223 WL_TRACE_HW4(("START SCAN\n"));
3224 DHD_OS_SCAN_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub),
3225 SCAN_WAKE_LOCK_TIMEOUT);
3226 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
3227 }
3228
3229 if (cfg->p2p_supported) {
3230 if (request && p2p_on(cfg) && p2p_scan(cfg)) {
3231
3232 /* find my listen channel */
3233 cfg->afx_hdl->my_listen_chan =
3234 wl_find_listen_channel(cfg, request->ie,
3235 request->ie_len);
3236 err = wl_cfgp2p_enable_discovery(cfg, ndev,
3237 request->ie, request->ie_len);
3238
3239 if (unlikely(err)) {
3240 goto scan_out;
3241 }
3242 }
3243 }
3244 err = wl_do_escan(cfg, wiphy, ndev, request);
3245 if (likely(!err))
3246 goto scan_success;
3247 else
3248 goto scan_out;
3249
3250 scan_success:
3251 busy_count = 0;
3252 cfg->scan_request = request;
3253 wl_set_drv_status(cfg, SCANNING, ndev);
3254
3255 return 0;
3256
3257 scan_out:
3258 if (err == BCME_BUSY || err == BCME_NOTREADY) {
3259 WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY));
3260 err = -EBUSY;
3261 } else if ((err == BCME_EPERM) && cfg->scan_suppressed) {
3262 WL_ERR(("Scan not permitted due to scan suppress\n"));
3263 err = -EPERM;
3264 } else {
3265 /* For all other fw errors, use a generic error code as return
3266 * value to cfg80211 stack
3267 */
3268 err = -EAGAIN;
3269 }
3270
3271 #define SCAN_EBUSY_RETRY_LIMIT 20
3272 if (err == -EBUSY) {
3273 if (busy_count++ > SCAN_EBUSY_RETRY_LIMIT) {
3274 struct ether_addr bssid;
3275 s32 ret = 0;
3276 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
3277 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
3278 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
3279 busy_count = 0;
3280 WL_ERR(("Unusual continuous EBUSY error, %d %d %d %d %d %d %d %d %d\n",
3281 wl_get_drv_status(cfg, SCANNING, ndev),
3282 wl_get_drv_status(cfg, SCAN_ABORTING, ndev),
3283 wl_get_drv_status(cfg, CONNECTING, ndev),
3284 wl_get_drv_status(cfg, CONNECTED, ndev),
3285 wl_get_drv_status(cfg, DISCONNECTING, ndev),
3286 wl_get_drv_status(cfg, AP_CREATING, ndev),
3287 wl_get_drv_status(cfg, AP_CREATED, ndev),
3288 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev),
3289 wl_get_drv_status(cfg, SENDING_ACT_FRM, ndev)));
3290
3291 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
3292 if (dhdp->memdump_enabled) {
3293 dhdp->memdump_type = DUMP_TYPE_SCAN_BUSY;
3294 dhd_bus_mem_dump(dhdp);
3295 }
3296 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
3297
3298 bzero(&bssid, sizeof(bssid));
3299 if ((ret = wldev_ioctl_get(ndev, WLC_GET_BSSID,
3300 &bssid, ETHER_ADDR_LEN)) == 0)
3301 WL_ERR(("FW is connected with " MACDBG "/n",
3302 MAC2STRDBG(bssid.octet)));
3303 else
3304 WL_ERR(("GET BSSID failed with %d\n", ret));
3305
3306 wl_cfg80211_scan_abort(cfg);
3307
3308 } else {
3309 /* Hold the context for 400msec, so that 10 subsequent scans
3310 * can give a buffer of 4sec which is enough to
3311 * cover any on-going scan in the firmware
3312 */
3313 WL_DBG(("Enforcing delay for EBUSY case \n"));
3314 msleep(400);
3315 }
3316 } else {
3317 busy_count = 0;
3318 }
3319
3320 wl_clr_drv_status(cfg, SCANNING, ndev);
3321 if (timer_pending(&cfg->scan_timeout))
3322 del_timer_sync(&cfg->scan_timeout);
3323 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
3324 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
3325 cfg->scan_request = NULL;
3326 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
3327
3328 return err;
3329 }
3330
3331 static s32
3332 #if defined(WL_CFG80211_P2P_DEV_IF)
3333 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
3334 #else
3335 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
3336 struct cfg80211_scan_request *request)
3337 #endif /* WL_CFG80211_P2P_DEV_IF */
3338 {
3339 s32 err = 0;
3340 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3341 #if defined(WL_CFG80211_P2P_DEV_IF)
3342 struct net_device *ndev = wdev_to_wlc_ndev(request->wdev, cfg);
3343 #endif /* WL_CFG80211_P2P_DEV_IF */
3344
3345 WL_DBG(("Enter\n"));
3346 RETURN_EIO_IF_NOT_UP(cfg);
3347
3348 #ifdef DHD_IFDEBUG
3349 #ifdef WL_CFG80211_P2P_DEV_IF
3350 PRINT_WDEV_INFO(request->wdev);
3351 #else
3352 PRINT_WDEV_INFO(ndev);
3353 #endif /* WL_CFG80211_P2P_DEV_IF */
3354 #endif /* DHD_IFDEBUG */
3355
3356 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
3357 if (wl_cfg_multip2p_operational(cfg)) {
3358 WL_ERR(("wlan0 scan failed, p2p devices are operational"));
3359 return -ENODEV;
3360 }
3361 }
3362 err = wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY,
3363 WL_EXT_STATUS_SCAN, NULL);
3364 if (err)
3365 return err;
3366
3367 mutex_lock(&cfg->usr_sync);
3368 err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
3369 if (unlikely(err)) {
3370 WL_ERR(("scan error (%d)\n", err));
3371 }
3372 mutex_unlock(&cfg->usr_sync);
3373 #ifdef WL_DRV_AVOID_SCANCACHE
3374 /* Reset roam cache after successful scan request */
3375 #endif /* WL_DRV_AVOID_SCANCACHE */
3376 return err;
3377 }
3378
3379 static s32 wl_set_rts(struct net_device *dev, u32 rts_threshold)
3380 {
3381 s32 err = 0;
3382
3383 err = wldev_iovar_setint(dev, "rtsthresh", rts_threshold);
3384 if (unlikely(err)) {
3385 WL_ERR(("Error (%d)\n", err));
3386 return err;
3387 }
3388 return err;
3389 }
3390
3391 static s32 wl_set_frag(struct net_device *dev, u32 frag_threshold)
3392 {
3393 s32 err = 0;
3394
3395 err = wldev_iovar_setint_bsscfg(dev, "fragthresh", frag_threshold, 0);
3396 if (unlikely(err)) {
3397 WL_ERR(("Error (%d)\n", err));
3398 return err;
3399 }
3400 return err;
3401 }
3402
3403 static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
3404 {
3405 s32 err = 0;
3406 u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
3407
3408 retry = htod32(retry);
3409 err = wldev_ioctl_set(dev, cmd, &retry, sizeof(retry));
3410 if (unlikely(err)) {
3411 WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
3412 return err;
3413 }
3414 return err;
3415 }
3416
3417 static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
3418 {
3419 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
3420 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
3421 s32 err = 0;
3422
3423 RETURN_EIO_IF_NOT_UP(cfg);
3424 WL_DBG(("Enter\n"));
3425 if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
3426 (cfg->conf->rts_threshold != wiphy->rts_threshold)) {
3427 cfg->conf->rts_threshold = wiphy->rts_threshold;
3428 err = wl_set_rts(ndev, cfg->conf->rts_threshold);
3429 if (err != BCME_OK)
3430 return err;
3431 }
3432 if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
3433 (cfg->conf->frag_threshold != wiphy->frag_threshold)) {
3434 cfg->conf->frag_threshold = wiphy->frag_threshold;
3435 err = wl_set_frag(ndev, cfg->conf->frag_threshold);
3436 if (err != BCME_OK)
3437 return err;
3438 }
3439 if (changed & WIPHY_PARAM_RETRY_LONG &&
3440 (cfg->conf->retry_long != wiphy->retry_long)) {
3441 cfg->conf->retry_long = wiphy->retry_long;
3442 err = wl_set_retry(ndev, cfg->conf->retry_long, true);
3443 if (err != BCME_OK)
3444 return err;
3445 }
3446 if (changed & WIPHY_PARAM_RETRY_SHORT &&
3447 (cfg->conf->retry_short != wiphy->retry_short)) {
3448 cfg->conf->retry_short = wiphy->retry_short;
3449 err = wl_set_retry(ndev, cfg->conf->retry_short, false);
3450 if (err != BCME_OK) {
3451 return err;
3452 }
3453 }
3454
3455 return err;
3456 }
3457 static chanspec_t
3458 channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
3459 {
3460 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3461 u8 *buf = NULL;
3462 wl_uint32_list_t *list;
3463 int err = BCME_OK;
3464 chanspec_t c = 0, ret_c = 0;
3465 int bw = 0, tmp_bw = 0;
3466 int i;
3467 u32 tmp_c;
3468 u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
3469 #define LOCAL_BUF_SIZE 1024
3470 buf = (u8 *) kzalloc(LOCAL_BUF_SIZE, kflags);
3471 if (!buf) {
3472 WL_ERR(("buf memory alloc failed\n"));
3473 goto exit;
3474 }
3475
3476 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
3477 0, buf, LOCAL_BUF_SIZE, 0, &cfg->ioctl_buf_sync);
3478 if (err != BCME_OK) {
3479 WL_ERR(("get chanspecs failed with %d\n", err));
3480 goto exit;
3481 }
3482
3483 list = (wl_uint32_list_t *)(void *)buf;
3484 for (i = 0; i < dtoh32(list->count); i++) {
3485 c = dtoh32(list->element[i]);
3486 if (channel <= CH_MAX_2G_CHANNEL) {
3487 if (!CHSPEC_IS20(c))
3488 continue;
3489 if (channel == CHSPEC_CHANNEL(c)) {
3490 ret_c = c;
3491 bw = 20;
3492 goto exit;
3493 }
3494 }
3495 tmp_c = wf_chspec_ctlchan(c);
3496 tmp_bw = bw2cap[CHSPEC_BW(c) >> WL_CHANSPEC_BW_SHIFT];
3497 if (tmp_c != channel)
3498 continue;
3499
3500 if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
3501 bw = tmp_bw;
3502 ret_c = c;
3503 if (bw == bw_cap)
3504 goto exit;
3505 }
3506 }
3507 exit:
3508 if (buf)
3509 kfree(buf);
3510 #undef LOCAL_BUF_SIZE
3511 WL_INFORM(("return chanspec %x %d\n", ret_c, bw));
3512 return ret_c;
3513 }
3514
3515 void
3516 wl_cfg80211_ibss_vsie_set_buffer(struct net_device *dev, vndr_ie_setbuf_t *ibss_vsie,
3517 int ibss_vsie_len)
3518 {
3519 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3520
3521 if (cfg != NULL && ibss_vsie != NULL) {
3522 if (cfg->ibss_vsie != NULL) {
3523 kfree(cfg->ibss_vsie);
3524 }
3525 cfg->ibss_vsie = ibss_vsie;
3526 cfg->ibss_vsie_len = ibss_vsie_len;
3527 }
3528 }
3529
3530 static void
3531 wl_cfg80211_ibss_vsie_free(struct bcm_cfg80211 *cfg)
3532 {
3533 /* free & initiralize VSIE (Vendor Specific IE) */
3534 if (cfg->ibss_vsie != NULL) {
3535 kfree(cfg->ibss_vsie);
3536 cfg->ibss_vsie = NULL;
3537 cfg->ibss_vsie_len = 0;
3538 }
3539 }
3540
3541 s32
3542 wl_cfg80211_ibss_vsie_delete(struct net_device *dev)
3543 {
3544 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3545 char *ioctl_buf = NULL;
3546 s32 ret = BCME_OK, bssidx;
3547
3548 if (cfg != NULL && cfg->ibss_vsie != NULL) {
3549 ioctl_buf = kmalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
3550 if (!ioctl_buf) {
3551 WL_ERR(("ioctl memory alloc failed\n"));
3552 return -ENOMEM;
3553 }
3554
3555 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
3556 WL_ERR(("Find index failed\n"));
3557 ret = BCME_ERROR;
3558 goto end;
3559 }
3560 /* change the command from "add" to "del" */
3561 strncpy(cfg->ibss_vsie->cmd, "del", VNDR_IE_CMD_LEN - 1);
3562 cfg->ibss_vsie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
3563
3564 ret = wldev_iovar_setbuf_bsscfg(dev, "vndr_ie",
3565 cfg->ibss_vsie, cfg->ibss_vsie_len,
3566 ioctl_buf, WLC_IOCTL_MEDLEN, bssidx, &cfg->ioctl_buf_sync);
3567 WL_ERR(("ret=%d\n", ret));
3568
3569 if (ret == BCME_OK) {
3570 /* free & initiralize VSIE */
3571 kfree(cfg->ibss_vsie);
3572 cfg->ibss_vsie = NULL;
3573 cfg->ibss_vsie_len = 0;
3574 }
3575 end:
3576 if (ioctl_buf) {
3577 kfree(ioctl_buf);
3578 }
3579 }
3580
3581 return ret;
3582 }
3583
3584 #ifdef WLAIBSS_MCHAN
3585 static bcm_struct_cfgdev*
3586 bcm_cfg80211_add_ibss_if(struct wiphy *wiphy, char *name)
3587 {
3588 int err = 0;
3589 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3590 struct wireless_dev* wdev = NULL;
3591 struct net_device *new_ndev = NULL;
3592 struct net_device *primary_ndev = NULL;
3593 s32 timeout;
3594 wl_aibss_if_t aibss_if;
3595 wl_if_event_info *event = NULL;
3596
3597 if (cfg->ibss_cfgdev != NULL) {
3598 WL_ERR(("IBSS interface %s already exists\n", name));
3599 return NULL;
3600 }
3601
3602 WL_ERR(("Try to create IBSS interface %s\n", name));
3603 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3604 /* generate a new MAC address for the IBSS interface */
3605 get_primary_mac(cfg, &cfg->ibss_if_addr);
3606 cfg->ibss_if_addr.octet[4] ^= 0x40;
3607 memset(&aibss_if, sizeof(aibss_if), 0);
3608 memcpy(&aibss_if.addr, &cfg->ibss_if_addr, sizeof(aibss_if.addr));
3609 aibss_if.chspec = 0;
3610 aibss_if.len = sizeof(aibss_if);
3611
3612 cfg->bss_pending_op = TRUE;
3613 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3614 err = wldev_iovar_setbuf(primary_ndev, "aibss_ifadd", &aibss_if,
3615 sizeof(aibss_if), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3616 if (err) {
3617 WL_ERR(("IOVAR aibss_ifadd failed with error %d\n", err));
3618 goto fail;
3619 }
3620 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3621 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3622 if (timeout <= 0 || cfg->bss_pending_op)
3623 goto fail;
3624
3625 event = &cfg->if_event_info;
3626 /* By calling wl_cfg80211_allocate_if (dhd_allocate_if eventually) we give the control
3627 * over this net_device interface to dhd_linux, hence the interface is managed by dhd_liux
3628 * and will be freed by dhd_detach unless it gets unregistered before that. The
3629 * wireless_dev instance new_ndev->ieee80211_ptr associated with this net_device will
3630 * be freed by wl_dealloc_netinfo
3631 */
3632 new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx, event->name,
3633 event->mac, event->bssidx, event->name);
3634 if (new_ndev == NULL)
3635 goto fail;
3636 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
3637 if (wdev == NULL)
3638 goto fail;
3639 wdev->wiphy = wiphy;
3640 wdev->iftype = NL80211_IFTYPE_ADHOC;
3641 wdev->netdev = new_ndev;
3642 new_ndev->ieee80211_ptr = wdev;
3643 SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
3644
3645 /* rtnl lock must have been acquired, if this is not the case, wl_cfg80211_register_if
3646 * needs to be modified to take one parameter (bool need_rtnl_lock)
3647 */
3648 ASSERT_RTNL();
3649 if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev, FALSE) != BCME_OK)
3650 goto fail;
3651
3652 wl_alloc_netinfo(cfg, new_ndev, wdev, WL_MODE_IBSS, PM_ENABLE, event->bssidx);
3653 cfg->ibss_cfgdev = ndev_to_cfgdev(new_ndev);
3654 WL_ERR(("IBSS interface %s created\n", new_ndev->name));
3655 return cfg->ibss_cfgdev;
3656
3657 fail:
3658 WL_ERR(("failed to create IBSS interface %s \n", name));
3659 cfg->bss_pending_op = FALSE;
3660 if (new_ndev)
3661 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, FALSE);
3662 if (wdev)
3663 kfree(wdev);
3664 return NULL;
3665 }
3666
3667 static s32
3668 bcm_cfg80211_del_ibss_if(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
3669 {
3670 int err = 0;
3671 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3672 struct net_device *ndev = NULL;
3673 struct net_device *primary_ndev = NULL;
3674 s32 timeout;
3675
3676 if (!cfgdev || cfg->ibss_cfgdev != cfgdev || ETHER_ISNULLADDR(&cfg->ibss_if_addr.octet))
3677 return -EINVAL;
3678 ndev = (struct net_device *)cfgdev_to_ndev(cfg->ibss_cfgdev);
3679 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3680
3681 cfg->bss_pending_op = TRUE;
3682 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
3683 err = wldev_iovar_setbuf(primary_ndev, "aibss_ifdel", &cfg->ibss_if_addr,
3684 sizeof(cfg->ibss_if_addr), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3685 if (err) {
3686 WL_ERR(("IOVAR aibss_ifdel failed with error %d\n", err));
3687 goto fail;
3688 }
3689 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
3690 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
3691 if (timeout <= 0 || cfg->bss_pending_op) {
3692 WL_ERR(("timeout in waiting IF_DEL event\n"));
3693 goto fail;
3694 }
3695
3696 wl_cfg80211_remove_if(cfg, cfg->if_event_info.ifidx, ndev, FALSE);
3697 cfg->ibss_cfgdev = NULL;
3698 return 0;
3699
3700 fail:
3701 cfg->bss_pending_op = FALSE;
3702 return -1;
3703 }
3704 #endif /* WLAIBSS_MCHAN */
3705
3706 #ifdef WLMESH
3707 s32
3708 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
3709 struct net_device *ndev, s32 bsscfg_idx,
3710 enum nl80211_iftype iface_type, s32 del, u8 *addr)
3711 {
3712 wl_interface_create_t iface;
3713 s32 ret;
3714 wl_interface_info_t *info;
3715
3716 bzero(&iface, sizeof(wl_interface_create_t));
3717
3718 iface.ver = WL_INTERFACE_CREATE_VER;
3719
3720 if (iface_type == NL80211_IFTYPE_AP)
3721 iface.flags = WL_INTERFACE_CREATE_AP;
3722 else
3723 iface.flags = WL_INTERFACE_CREATE_STA;
3724
3725 if (del) {
3726 ret = wldev_iovar_setbuf(ndev, "interface_remove",
3727 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_MEDLEN, NULL);
3728 } else {
3729 if (addr) {
3730 memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
3731 iface.flags |= WL_INTERFACE_MAC_USE;
3732 }
3733 ret = wldev_iovar_getbuf(ndev, "interface_create",
3734 &iface, sizeof(wl_interface_create_t),
3735 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3736 if (ret == 0) {
3737 /* success */
3738 info = (wl_interface_info_t *)cfg->ioctl_buf;
3739 WL_DBG(("wl interface create success!! bssidx:%d \n",
3740 info->bsscfgidx));
3741 }
3742 }
3743
3744 if (ret < 0)
3745 WL_ERR(("Interface %s failed!! ret %d\n",
3746 del ? "remove" : "create", ret));
3747
3748 return ret;
3749 }
3750 #else
3751 s32
3752 wl_cfg80211_interface_ops(struct bcm_cfg80211 *cfg,
3753 struct net_device *ndev, s32 bsscfg_idx,
3754 enum nl80211_iftype iface_type, s32 del, u8 *addr)
3755 {
3756 s32 ret;
3757 struct wl_interface_create_v2 iface;
3758 wl_interface_create_v3_t iface_v3;
3759 struct wl_interface_info_v1 *info;
3760 wl_interface_info_v2_t *info_v2;
3761 enum wl_interface_type iftype;
3762 uint32 ifflags;
3763 bool use_iface_info_v2 = false;
3764 u8 ioctl_buf[WLC_IOCTL_SMLEN];
3765
3766 if (del) {
3767 ret = wldev_iovar_setbuf(ndev, "interface_remove",
3768 NULL, 0, ioctl_buf, sizeof(ioctl_buf), NULL);
3769 if (unlikely(ret))
3770 WL_ERR(("Interface remove failed!! ret %d\n", ret));
3771 return ret;
3772 }
3773
3774 /* Interface create */
3775 bzero(&iface, sizeof(iface));
3776 /*
3777 * flags field is still used along with iftype inorder to support the old version of the
3778 * FW work with the latest app changes.
3779 */
3780 if (iface_type == NL80211_IFTYPE_AP) {
3781 iftype = WL_INTERFACE_TYPE_AP;
3782 ifflags = WL_INTERFACE_CREATE_AP;
3783 } else {
3784 iftype = WL_INTERFACE_TYPE_STA;
3785 ifflags = WL_INTERFACE_CREATE_STA;
3786 }
3787 if (addr) {
3788 ifflags |= WL_INTERFACE_MAC_USE;
3789 }
3790
3791 /* Pass ver = 0 for fetching the interface_create iovar version */
3792 ret = wldev_iovar_getbuf(ndev, "interface_create",
3793 &iface, sizeof(struct wl_interface_create_v2),
3794 ioctl_buf, sizeof(ioctl_buf), NULL);
3795 if (ret == BCME_UNSUPPORTED) {
3796 WL_ERR(("interface_create iovar not supported\n"));
3797 return ret;
3798 } else if ((ret == 0) && *((uint32 *)ioctl_buf) == WL_INTERFACE_CREATE_VER_3) {
3799 WL_DBG(("interface_create version 3\n"));
3800 use_iface_info_v2 = true;
3801 bzero(&iface_v3, sizeof(wl_interface_create_v3_t));
3802 iface_v3.ver = WL_INTERFACE_CREATE_VER_3;
3803 iface_v3.iftype = iftype;
3804 iface_v3.flags = ifflags;
3805 if (addr) {
3806 memcpy(&iface_v3.mac_addr.octet, addr, ETH_ALEN);
3807 }
3808 ret = wldev_iovar_getbuf(ndev, "interface_create",
3809 &iface_v3, sizeof(wl_interface_create_v3_t),
3810 ioctl_buf, sizeof(ioctl_buf), NULL);
3811 } else {
3812 #if 0
3813 /* On any other error, attempt with iovar version 2 */
3814 WL_DBG(("interface_create version 2. get_ver:%d\n", ret));
3815 iface.ver = WL_INTERFACE_CREATE_VER_2;
3816 iface.iftype = iftype;
3817 iface.flags = ifflags;
3818 if (addr) {
3819 memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
3820 }
3821 ret = wldev_iovar_getbuf(ndev, "interface_create",
3822 &iface, sizeof(struct wl_interface_create_v2),
3823 ioctl_buf, sizeof(ioctl_buf), NULL);
3824 #endif
3825 }
3826
3827 if (unlikely(ret)) {
3828 WL_ERR(("Interface create failed!! ret %d\n", ret));
3829 return ret;
3830 }
3831
3832 /* success case */
3833 if (use_iface_info_v2 == true) {
3834 info_v2 = (wl_interface_info_v2_t *)ioctl_buf;
3835 ret = info_v2->bsscfgidx;
3836 } else {
3837 /* Use v1 struct */
3838 info = (struct wl_interface_info_v1 *)ioctl_buf;
3839 ret = info->bsscfgidx;
3840 }
3841
3842 WL_DBG(("wl interface create success!! bssidx:%d \n", ret));
3843 return ret;
3844 }
3845 #endif
3846
3847 bool
3848 wl_customer6_legacy_chip_check(struct bcm_cfg80211 *cfg,
3849 struct net_device *ndev)
3850 {
3851 u32 chipnum;
3852 wlc_rev_info_t revinfo;
3853 int ret;
3854
3855 /* Get the device rev info */
3856 memset(&revinfo, 0, sizeof(revinfo));
3857 ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
3858 if (ret < 0) {
3859 WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret));
3860 ASSERT(0);
3861 return false;
3862 }
3863
3864 WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__,
3865 dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum)));
3866 chipnum = revinfo.chipnum;
3867 if ((chipnum == BCM4350_CHIP_ID) || (chipnum == BCM4355_CHIP_ID) ||
3868 (chipnum == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID) ||
3869 (chipnum == BCM43362_CHIP_ID)) {
3870 /* WAR required */
3871 return true;
3872 }
3873
3874 return false;
3875 }
3876
3877 void
3878 wl_bss_iovar_war(struct bcm_cfg80211 *cfg,
3879 struct net_device *ndev, s32 *val)
3880 {
3881 u32 chipnum;
3882 wlc_rev_info_t revinfo;
3883 int ret;
3884 bool need_war = false;
3885
3886 /* Get the device rev info */
3887 memset(&revinfo, 0, sizeof(revinfo));
3888 ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
3889 if (ret < 0) {
3890 WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret));
3891 } else {
3892 WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__,
3893 dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum)));
3894 chipnum = revinfo.chipnum;
3895 if ((chipnum == BCM4359_CHIP_ID) || (chipnum == BCM43596_CHIP_ID)) {
3896 /* WAR required */
3897 need_war = true;
3898 }
3899 }
3900
3901 if (wl_customer6_legacy_chip_check(cfg, ndev) || need_war) {
3902 /* Few firmware branches have issues in bss iovar handling and
3903 * that can't be changed since they are in production.
3904 */
3905 if (*val == WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE) {
3906 *val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
3907 } else if (*val == WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE) {
3908 *val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
3909 } else {
3910 /* Ignore for other bss enums */
3911 return;
3912 }
3913 WL_ERR(("wl bss %d\n", *val));
3914 }
3915 }
3916
3917 s32
3918 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
3919 struct net_device *ndev, s32 bsscfg_idx,
3920 enum nl80211_iftype iface_type, s32 del, u8 *addr)
3921 {
3922 s32 ret = BCME_OK;
3923 s32 val = 0;
3924
3925 struct {
3926 s32 cfg;
3927 s32 val;
3928 struct ether_addr ea;
3929 } bss_setbuf;
3930
3931 WL_INFORM(("iface_type:%d del:%d \n", iface_type, del));
3932
3933 bzero(&bss_setbuf, sizeof(bss_setbuf));
3934
3935 /* AP=2, STA=3, up=1, down=0, val=-1 */
3936 if (del) {
3937 val = WLC_AP_IOV_OP_DELETE;
3938 } else if (iface_type == NL80211_IFTYPE_AP) {
3939 /* Add/role change to AP Interface */
3940 WL_DBG(("Adding AP Interface \n"));
3941 val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
3942 } else if (iface_type == NL80211_IFTYPE_STATION) {
3943 /* Add/role change to STA Interface */
3944 WL_DBG(("Adding STA Interface \n"));
3945 val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
3946 } else {
3947 WL_ERR((" add_del_bss NOT supported for IFACE type:0x%x", iface_type));
3948 return -EINVAL;
3949 }
3950
3951 if (!del) {
3952 wl_bss_iovar_war(cfg, ndev, &val);
3953 }
3954
3955 bss_setbuf.cfg = htod32(bsscfg_idx);
3956 bss_setbuf.val = htod32(val);
3957
3958 if (addr) {
3959 memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
3960 }
3961
3962 WL_DBG(("wl bss %d bssidx:%d iface:%s \n", val, bsscfg_idx, ndev->name));
3963 ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
3964 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3965 if (ret != 0)
3966 WL_ERR(("'bss %d' failed with %d\n", val, ret));
3967
3968 return ret;
3969 }
3970
3971 s32
3972 wl_cfg80211_bss_up(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 bss_up)
3973 {
3974 s32 ret = BCME_OK;
3975 s32 val = bss_up ? 1 : 0;
3976
3977 struct {
3978 s32 cfg;
3979 s32 val;
3980 } bss_setbuf;
3981
3982 bss_setbuf.cfg = htod32(bsscfg_idx);
3983 bss_setbuf.val = htod32(val);
3984
3985 WL_DBG(("wl bss -C %d %s\n", bsscfg_idx, bss_up ? "up" : "down"));
3986 ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
3987 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
3988
3989 if (ret != 0) {
3990 WL_ERR(("'bss %d' failed with %d\n", bss_up, ret));
3991 }
3992
3993 return ret;
3994 }
3995
3996 bool
3997 wl_cfg80211_bss_isup(struct net_device *ndev, int bsscfg_idx)
3998 {
3999 s32 result, val;
4000 bool isup = false;
4001 s8 getbuf[64];
4002
4003 /* Check if the BSS is up */
4004 *(int*)getbuf = -1;
4005 result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
4006 sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL);
4007 if (result != 0) {
4008 WL_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx, result));
4009 WL_ERR(("NOTE: this ioctl error is normal "
4010 "when the BSS has not been created yet.\n"));
4011 } else {
4012 val = *(int*)getbuf;
4013 val = dtoh32(val);
4014 WL_DBG(("wl bss -C %d = %d\n", bsscfg_idx, val));
4015 isup = (val ? TRUE : FALSE);
4016 }
4017 return isup;
4018 }
4019
4020 static s32
4021 cfg80211_to_wl_iftype(uint16 type, uint16 *role, uint16 *mode)
4022 {
4023 switch (type) {
4024 case NL80211_IFTYPE_STATION:
4025 *role = WLC_E_IF_ROLE_STA;
4026 *mode = WL_MODE_BSS;
4027 break;
4028 case NL80211_IFTYPE_AP:
4029 *role = WLC_E_IF_ROLE_AP;
4030 *mode = WL_MODE_AP;
4031 break;
4032 case NL80211_IFTYPE_P2P_GO:
4033 *role = WLC_E_IF_ROLE_P2P_GO;
4034 *mode = WL_MODE_AP;
4035 break;
4036 case NL80211_IFTYPE_P2P_CLIENT:
4037 *role = WLC_E_IF_ROLE_P2P_CLIENT;
4038 *mode = WL_MODE_BSS;
4039 break;
4040 case NL80211_IFTYPE_MONITOR:
4041 WL_ERR(("Unsupported mode \n"));
4042 return BCME_UNSUPPORTED;
4043 case NL80211_IFTYPE_ADHOC:
4044 *role = WLC_E_IF_ROLE_IBSS;
4045 *mode = WL_MODE_IBSS;
4046 break;
4047 default:
4048 WL_ERR(("Unknown interface type:0x%x\n", type));
4049 return BCME_ERROR;
4050 }
4051 return BCME_OK;
4052 }
4053
4054 static s32
4055 wl_if_to_cfg80211_type(uint16 role)
4056 {
4057 switch (role) {
4058 case WLC_E_IF_ROLE_STA:
4059 return NL80211_IFTYPE_STATION;
4060 case WLC_E_IF_ROLE_AP:
4061 return NL80211_IFTYPE_AP;
4062 case WLC_E_IF_ROLE_P2P_GO:
4063 return NL80211_IFTYPE_P2P_GO;
4064 case WLC_E_IF_ROLE_P2P_CLIENT:
4065 return NL80211_IFTYPE_P2P_CLIENT;
4066 case WLC_E_IF_ROLE_IBSS:
4067 return NL80211_IFTYPE_ADHOC;
4068 default:
4069 WL_ERR(("Unknown interface role:0x%x. Forcing type station\n", role));
4070 return BCME_ERROR;
4071 }
4072 }
4073
4074 struct net_device *
4075 wl_cfg80211_post_ifcreate(struct net_device *ndev,
4076 wl_if_event_info *event, u8 *addr,
4077 const char *name, bool rtnl_lock_reqd)
4078 {
4079 struct bcm_cfg80211 *cfg;
4080 struct net_device *primary_ndev;
4081 struct net_device *new_ndev = NULL;
4082 struct wireless_dev *wdev = NULL;
4083 s32 iface_type;
4084 s32 ret;
4085 u16 mode;
4086 u16 role;
4087 u8 mac_addr[ETH_ALEN];
4088
4089 if (!ndev || !event) {
4090 WL_ERR(("Wrong arg\n"));
4091 return NULL;
4092 }
4093
4094 cfg = wl_get_cfg(ndev);
4095 if (!cfg) {
4096 WL_ERR(("cfg null\n"));
4097 return NULL;
4098 }
4099
4100 WL_DBG(("Enter. role:%d ifidx:%d bssidx:%d\n",
4101 event->role, event->ifidx, event->bssidx));
4102 if (!event->ifidx || !event->bssidx) {
4103 /* Fw returned primary idx (0) for virtual interface */
4104 WL_ERR(("Wrong index. ifidx:%d bssidx:%d \n",
4105 event->ifidx, event->bssidx));
4106 return NULL;
4107 }
4108
4109 iface_type = wl_if_to_cfg80211_type(event->role);
4110 if (iface_type < 0) {
4111 /* Unknown iface type */
4112 WL_ERR(("Wrong iface type \n"));
4113 return NULL;
4114 }
4115
4116 if (cfg80211_to_wl_iftype(iface_type, &role, &mode) < 0) {
4117 /* Unsupported operating mode */
4118 WL_ERR(("Unsupported operating mode \n"));
4119 return NULL;
4120 }
4121
4122 WL_DBG(("mac_ptr:%p name:%s role:%d nl80211_iftype:%d " MACDBG "\n",
4123 addr, name, event->role, iface_type, MAC2STRDBG(event->mac)));
4124 if (!name) {
4125 /* If iface name is not provided, use dongle ifname */
4126 name = event->name;
4127 }
4128
4129 if (!addr) {
4130 /* If mac address is not set, use primary mac with locally administered
4131 * bit set.
4132 */
4133 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
4134 memcpy(mac_addr, primary_ndev->dev_addr, ETH_ALEN);
4135 #ifndef CUSTOMER_HW6
4136 /* For customer6 builds, use primary mac address for virtual interface */
4137 mac_addr[0] |= 0x02;
4138 #endif /* CUSTOMER_HW6 */
4139 addr = mac_addr;
4140 }
4141
4142 new_ndev = wl_cfg80211_allocate_if(cfg, event->ifidx,
4143 name, addr, event->bssidx, event->name);
4144 if (!new_ndev) {
4145 WL_ERR(("I/F allocation failed! \n"));
4146 goto fail;
4147 } else {
4148 WL_DBG(("I/F allocation succeeded! ifidx:0x%x bssidx:0x%x \n",
4149 event->ifidx, event->bssidx));
4150 }
4151
4152 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
4153 if (!wdev) {
4154 WL_ERR(("wireless_dev alloc failed! \n"));
4155 goto fail;
4156 }
4157
4158 wdev->wiphy = bcmcfg_to_wiphy(cfg);
4159 wdev->iftype = iface_type;
4160 new_ndev->ieee80211_ptr = wdev;
4161 SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
4162
4163 /* Check whether mac addr is in sync with fw. If not,
4164 * apply it using cur_etheraddr.
4165 */
4166 if (memcmp(addr, event->mac, ETH_ALEN) != 0) {
4167 ret = wldev_iovar_setbuf_bsscfg(new_ndev, "cur_etheraddr",
4168 addr, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
4169 event->bssidx, &cfg->ioctl_buf_sync);
4170 if (unlikely(ret)) {
4171 WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
4172 goto fail;
4173 }
4174 memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
4175 WL_ERR(("Applying updated mac address to firmware\n"));
4176 }
4177
4178 if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd) != BCME_OK) {
4179 WL_ERR(("IFACE register failed \n"));
4180 goto fail;
4181 }
4182
4183 /* Initialize with the station mode params */
4184 ret = wl_alloc_netinfo(cfg, new_ndev, wdev, mode,
4185 PM_ENABLE, event->bssidx);
4186 if (unlikely(ret)) {
4187 WL_ERR(("wl_alloc_netinfo Error (%d)\n", ret));
4188 goto fail;
4189 }
4190
4191 /* Apply the mode & infra setting based on iftype */
4192 if ((ret = wl_config_ifmode(cfg, new_ndev, iface_type)) < 0) {
4193 WL_ERR(("config ifmode failure (%d)\n", ret));
4194 goto fail;
4195 }
4196
4197 if (mode == WL_MODE_AP) {
4198 wl_set_drv_status(cfg, AP_CREATING, new_ndev);
4199 }
4200
4201 WL_INFORM(("Host Network Interface (%s) for Secondary I/F created."
4202 " cfg_iftype:%d wl_role:%d\n", new_ndev->name, iface_type, event->role));
4203
4204 return new_ndev;
4205
4206 fail:
4207 if (wdev)
4208 kfree(wdev);
4209 if (new_ndev)
4210 wl_cfg80211_remove_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd);
4211
4212 return NULL;
4213 }
4214
4215 void
4216 wl_cfg80211_cleanup_virtual_ifaces(struct net_device *dev, bool rtnl_lock_reqd)
4217 {
4218 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4219 struct net_info *iter, *next;
4220 struct net_device *primary_ndev;
4221
4222 /* Note: This function will clean up only the network interface and host
4223 * data structures. The firmware interface clean up will happen in the
4224 * during chip reset (ifconfig wlan0 down for built-in drivers/rmmod
4225 * context for the module case).
4226 */
4227 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
4228 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4229 #pragma GCC diagnostic push
4230 #pragma GCC diagnostic ignored "-Wcast-qual"
4231 #endif
4232 for_each_ndev(cfg, iter, next) {
4233 if (iter->ndev && (iter->ndev != primary_ndev)) {
4234 WL_DBG(("Cleaning up iface:%s \n", iter->ndev->name));
4235 wl_cfg80211_post_ifdel(iter->ndev, rtnl_lock_reqd);
4236 }
4237 }
4238 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4239 #pragma GCC diagnostic pop
4240 #endif
4241 }
4242
4243 s32
4244 wl_cfg80211_post_ifdel(struct net_device *ndev, bool rtnl_lock_reqd)
4245 {
4246 int ifidx = -1;
4247 struct bcm_cfg80211 *cfg;
4248
4249 if (!ndev || !ndev->ieee80211_ptr) {
4250 /* No wireless dev done for this interface */
4251 return -EINVAL;
4252 }
4253
4254 cfg = wl_get_cfg(ndev);
4255 if (!cfg) {
4256 WL_ERR(("cfg null\n"));
4257 return BCME_ERROR;
4258 }
4259 ifidx = dhd_net2idx(((struct dhd_pub *)(cfg->pub))->info, ndev);
4260 BCM_REFERENCE(ifidx);
4261 if (ifidx <= 0) {
4262 WL_ERR(("Invalid IF idx for iface:%s\n", ndev->name));
4263 ASSERT(0);
4264 return BCME_ERROR;
4265 }
4266 WL_DBG(("cfg80211_remove for iface:%s \n", ndev->name));
4267 wl_cfg80211_remove_if(cfg, ifidx, ndev, rtnl_lock_reqd);
4268 cfg->bss_pending_op = FALSE;
4269
4270 return BCME_OK;
4271 }
4272
4273 #if defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF)
4274 /* Create a Generic Network Interface and initialize it depending up on
4275 * the interface type
4276 */
4277 bcm_struct_cfgdev*
4278 wl_cfg80211_create_iface(struct wiphy *wiphy,
4279 enum nl80211_iftype iface_type,
4280 u8 *mac_addr, const char *name)
4281 {
4282 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4283 struct net_device *new_ndev = NULL;
4284 struct net_device *primary_ndev = NULL;
4285 s32 ret = BCME_OK;
4286 s32 bsscfg_idx = 0;
4287 u32 timeout;
4288 wl_if_event_info *event = NULL;
4289 u8 addr[ETH_ALEN];
4290 struct net_info *iter, *next;
4291 #ifdef WLMESH
4292 u16 role = 0, mode = 0;
4293 #endif
4294
4295 WL_DBG(("Enter\n"));
4296 if (!name) {
4297 WL_ERR(("Interface name not provided\n"));
4298 return NULL;
4299 }
4300 else {
4301 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4302 #pragma GCC diagnostic push
4303 #pragma GCC diagnostic ignored "-Wcast-qual"
4304 #endif
4305 for_each_ndev(cfg, iter, next) {
4306 if (iter->ndev) {
4307 if (strcmp(iter->ndev->name, name) == 0) {
4308 WL_ERR(("Interface name, %s exists !\n", iter->ndev->name));
4309 return NULL;
4310 }
4311 }
4312 }
4313 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
4314 #pragma GCC diagnostic pop
4315 #endif
4316 }
4317 primary_ndev = bcmcfg_to_prmry_ndev(cfg);
4318
4319 if (likely(!mac_addr)) {
4320 /* Use primary MAC with the locally administered bit for the
4321 * Secondary STA I/F
4322 */
4323 memcpy(addr, primary_ndev->dev_addr, ETH_ALEN);
4324 addr[0] |= 0x02;
4325 } else {
4326 /* Use the application provided mac address (if any) */
4327 memcpy(addr, mac_addr, ETH_ALEN);
4328 }
4329
4330 if ((iface_type != NL80211_IFTYPE_STATION) && (iface_type != NL80211_IFTYPE_AP)) {
4331 WL_ERR(("IFACE type:%d not supported. STA "
4332 "or AP IFACE is only supported\n", iface_type));
4333 return NULL;
4334 }
4335
4336 cfg->bss_pending_op = TRUE;
4337 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
4338
4339 /* De-initialize the p2p discovery interface, if operational */
4340 if (p2p_is_on(cfg)) {
4341 WL_DBG(("Disabling P2P Discovery Interface \n"));
4342 #ifdef WL_CFG80211_P2P_DEV_IF
4343 ret = wl_cfg80211_scan_stop(cfg, bcmcfg_to_p2p_wdev(cfg));
4344 #else
4345 ret = wl_cfg80211_scan_stop(cfg, cfg->p2p_net);
4346 #endif
4347 if (unlikely(ret < 0)) {
4348 CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
4349 }
4350
4351 wl_cfgp2p_disable_discovery(cfg);
4352 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
4353 p2p_on(cfg) = false;
4354 }
4355
4356 /*
4357 * Intialize the firmware I/F.
4358 */
4359 if (wl_customer6_legacy_chip_check(cfg, primary_ndev)) {
4360 /* Use bss iovar instead of interface_create iovar */
4361 ret = BCME_UNSUPPORTED;
4362 } else {
4363 ret = wl_cfg80211_interface_ops(cfg, primary_ndev, bsscfg_idx,
4364 iface_type, 0, addr);
4365 }
4366 if (ret == BCME_UNSUPPORTED) {
4367 /* Use bssidx 1 by default */
4368 bsscfg_idx = 1;
4369 if ((ret = wl_cfg80211_add_del_bss(cfg, primary_ndev,
4370 bsscfg_idx, iface_type, 0, addr)) < 0) {
4371 goto exit;
4372 }
4373 } else if (ret < 0) {
4374 WL_ERR(("Interface create failed!! ret:%d \n", ret));
4375 goto exit;
4376 } else {
4377 /* Success */
4378 bsscfg_idx = ret;
4379 }
4380
4381 WL_DBG(("Interface created!! bssidx:%d \n", bsscfg_idx));
4382
4383 /*
4384 * Wait till the firmware send a confirmation event back.
4385 */
4386 WL_DBG(("Wait for the FW I/F Event\n"));
4387 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
4388 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
4389 if (timeout <= 0 || cfg->bss_pending_op) {
4390 WL_ERR(("ADD_IF event, didn't come. Return \n"));
4391 goto exit;
4392 }
4393
4394 event = &cfg->if_event_info;
4395 #ifdef WLMESH
4396 cfg80211_to_wl_iftype(iface_type, &role, &mode);
4397 event->role = role;
4398 #endif
4399
4400 /*
4401 * Since FW operation is successful,we can go ahead with the
4402 * the host interface creation.
4403 */
4404 if ((new_ndev = wl_cfg80211_post_ifcreate(primary_ndev,
4405 event, mac_addr, name, false))) {
4406 /* Iface post ops successful. Return ndev/wdev ptr */
4407 return ndev_to_cfgdev(new_ndev);
4408 }
4409
4410 exit:
4411 cfg->bss_pending_op = FALSE;
4412 return NULL;
4413 }
4414
4415 s32
4416 wl_cfg80211_del_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
4417 {
4418 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4419 struct net_device *ndev = NULL;
4420 s32 ret = BCME_OK;
4421 s32 bsscfg_idx = 1;
4422 u32 timeout;
4423 enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
4424
4425 WL_DBG(("Enter\n"));
4426
4427 /* If any scan is going on, abort it */
4428 if (wl_get_drv_status_all(cfg, SCANNING)) {
4429 WL_DBG(("Scan in progress. Aborting the scan!\n"));
4430 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
4431 }
4432
4433 ndev = (struct net_device *)cfgdev_to_ndev(cfgdev);
4434 cfg->bss_pending_op = TRUE;
4435 memset(&cfg->if_event_info, 0, sizeof(cfg->if_event_info));
4436
4437 /* Delete the firmware interface. "interface_remove" command
4438 * should go on the interface to be deleted
4439 */
4440 bsscfg_idx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
4441 if (bsscfg_idx <= 0) {
4442 /* validate bsscfgidx */
4443 WL_ERR(("Wrong bssidx! \n"));
4444 return -EINVAL;
4445 }
4446 WL_DBG(("del interface. bssidx:%d", bsscfg_idx));
4447 ret = wl_cfg80211_interface_ops(cfg, ndev, bsscfg_idx,
4448 NL80211_IFTYPE_STATION, 1, NULL);
4449 if (ret == BCME_UNSUPPORTED) {
4450 if ((ret = wl_cfg80211_add_del_bss(cfg, ndev,
4451 bsscfg_idx, iface_type, true, NULL)) < 0) {
4452 WL_ERR(("DEL bss failed ret:%d \n", ret));
4453 goto exit;
4454 }
4455 } else if (ret < 0) {
4456 WL_ERR(("Interface DEL failed ret:%d \n", ret));
4457 goto exit;
4458 }
4459
4460 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
4461 !cfg->bss_pending_op, msecs_to_jiffies(MAX_WAIT_TIME));
4462 if (timeout <= 0 || cfg->bss_pending_op) {
4463 WL_ERR(("timeout in waiting IF_DEL event\n"));
4464 }
4465
4466 exit:
4467 ret = wl_cfg80211_post_ifdel(ndev, false);
4468 if (unlikely(ret)) {
4469 WL_ERR(("post_ifdel failed\n"));
4470 }
4471
4472 return ret;
4473 }
4474 #endif /* defined(WL_VIRTUAL_APSTA) || defined(DUAL_STA_STATIC_IF) */
4475
4476 #ifdef WLMESH
4477 s32 wl_cfg80211_set_sae_password(struct net_device *dev, char* buf, int len)
4478 {
4479 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4480
4481 sscanf(buf, "%s %d", cfg->sae_password, &cfg->sae_password_len);
4482 return 0;
4483 }
4484
4485 static s32 wl_cfg80211_join_mesh(
4486 struct wiphy *wiphy, struct net_device *dev,
4487 const struct mesh_config *conf,
4488 const struct mesh_setup *setup)
4489 {
4490 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4491 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
4492 struct ieee80211_channel *chan = setup->chandef.chan;
4493 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 6, 0))
4494 struct ieee80211_channel *chan = setup->channel;
4495 #endif
4496 u32 param[2] = {0, 0};
4497 s32 err = 0;
4498 u32 bw_cap = 0;
4499 u32 beacon_interval = setup->beacon_interval;
4500 u32 dtim_period = setup->dtim_period;
4501 size_t join_params_size;
4502 struct wl_join_params join_params;
4503 chanspec_t chanspec = 0;
4504
4505 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
4506
4507 if (wl_get_drv_status(cfg, CONNECTED, dev)) {
4508 struct wlc_ssid *lssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
4509 u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
4510 u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
4511 if ((memcmp(setup->mesh_id, lssid->SSID, lssid->SSID_len) == 0) &&
4512 (*channel == cfg->channel)) {
4513 WL_ERR(("MESH connection already existed to " MACDBG "\n",
4514 MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
4515 return -EISCONN;
4516 }
4517 WL_ERR(("Previous connecton existed, please disconnect mesh %s (" MACDBG ") first\n",
4518 lssid->SSID, MAC2STRDBG(bssid)));
4519 return -EISCONN;
4520 }
4521
4522 if (chan) {
4523 if (chan->band == IEEE80211_BAND_5GHZ)
4524 param[0] = WLC_BAND_5G;
4525 else if (chan->band == IEEE80211_BAND_2GHZ)
4526 param[0] = WLC_BAND_2G;
4527 err = wldev_iovar_getint(dev, "bw_cap", param);
4528 if (unlikely(err)) {
4529 WL_ERR(("Get bw_cap Failed (%d)\n", err));
4530 return err;
4531 }
4532 bw_cap = param[0];
4533 chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
4534 }
4535
4536 memset(&join_params, 0, sizeof(join_params));
4537 memcpy((void *)join_params.ssid.SSID, (void *)setup->mesh_id,
4538 setup->mesh_id_len);
4539
4540 join_params.ssid.SSID_len = htod32(setup->mesh_id_len);
4541 join_params.params.chanspec_list[0] = chanspec;
4542 join_params.params.chanspec_num = 1;
4543 wldev_iovar_setint(dev, "chanspec", chanspec);
4544 join_params_size = sizeof(join_params);
4545
4546 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
4547 wldev_iovar_setint(dev, "wsec", 0);
4548
4549 if (cfg->sae_password_len > 0) {
4550 wldev_iovar_setint(dev, "mesh_auth_proto", 1);
4551 wldev_iovar_setint(dev, "wpa_auth", WPA2_AUTH_PSK);
4552 wldev_iovar_setint(dev, "wsec", AES_ENABLED);
4553 wldev_iovar_setint(dev, "mfp", WL_MFP_REQUIRED);
4554 printf("%s: password=%s, len=%d\n", __FUNCTION__,
4555 cfg->sae_password, cfg->sae_password_len);
4556 wldev_iovar_setbuf(dev, "sae_password", cfg->sae_password, cfg->sae_password_len,
4557 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, NULL);
4558 } else {
4559 wldev_iovar_setint(dev, "mesh_auth_proto", 0);
4560 wldev_iovar_setint(dev, "mfp", WL_MFP_NONE);
4561 }
4562
4563 if (beacon_interval) {
4564 if ((err = wldev_ioctl_set(dev, WLC_SET_BCNPRD,
4565 &beacon_interval, sizeof(s32))) < 0) {
4566 WL_ERR(("Beacon Interval Set Error, %d\n", err));
4567 return err;
4568 }
4569 }
4570
4571 if (dtim_period) {
4572 if ((err = wldev_ioctl_set(dev, WLC_SET_DTIMPRD,
4573 &dtim_period, sizeof(s32))) < 0) {
4574 WL_ERR(("DTIM Interval Set Error, %d\n", err));
4575 return err;
4576 }
4577 }
4578 wldev_iovar_setint(dev, "mpc", 0);
4579
4580 WL_ERR(("JOIN %s on channel %d with chanspec 0x%4x\n",
4581 join_params.ssid.SSID, cfg->channel, chanspec));
4582
4583 err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
4584 join_params_size);
4585
4586 if (unlikely(err)) {
4587 WL_ERR(("Error (%d)\n", err));
4588 return err;
4589 }
4590
4591 wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
4592 wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
4593 return err;
4594 }
4595
4596
4597 static s32 wl_cfg80211_leave_mesh(
4598 struct wiphy *wiphy, struct net_device *dev)
4599 {
4600 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4601 s32 err = 0;
4602 scb_val_t scbval;
4603 u8 *curbssid;
4604
4605 RETURN_EIO_IF_NOT_UP(cfg);
4606 wl_link_down(cfg);
4607
4608 WL_ERR(("Leave MESH\n"));
4609 curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
4610 wl_set_drv_status(cfg, DISCONNECTING, dev);
4611 scbval.val = 0;
4612 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
4613 err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
4614 sizeof(scb_val_t));
4615 if (unlikely(err)) {
4616 wl_clr_drv_status(cfg, DISCONNECTING, dev);
4617 WL_ERR(("error(%d)\n", err));
4618 return err;
4619 }
4620 memset(cfg->sae_password, 0, SAE_MAX_PASSWD_LEN);
4621 cfg->sae_password_len = 0;
4622
4623 return err;
4624 }
4625 #endif /* WLMESH */
4626
4627 static s32
4628 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
4629 struct cfg80211_ibss_params *params)
4630 {
4631 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4632 struct cfg80211_bss *bss;
4633 struct ieee80211_channel *chan;
4634 struct wl_join_params join_params;
4635 int scan_suppress;
4636 struct cfg80211_ssid ssid;
4637 s32 scan_retry = 0;
4638 s32 err = 0;
4639 size_t join_params_size;
4640 chanspec_t chanspec = 0;
4641 u32 param[2] = {0, 0};
4642 u32 bw_cap = 0;
4643
4644 WL_TRACE(("In\n"));
4645 RETURN_EIO_IF_NOT_UP(cfg);
4646 WL_INFORM(("JOIN BSSID:" MACDBG "\n", MAC2STRDBG(params->bssid)));
4647 if (!params->ssid || params->ssid_len <= 0 ||
4648 params->ssid_len > DOT11_MAX_SSID_LEN) {
4649 WL_ERR(("Invalid parameter\n"));
4650 return -EINVAL;
4651 }
4652 #if defined(WL_CFG80211_P2P_DEV_IF)
4653 chan = params->chandef.chan;
4654 #else
4655 chan = params->channel;
4656 #endif /* WL_CFG80211_P2P_DEV_IF */
4657 if (chan)
4658 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
4659 if (wl_get_drv_status(cfg, CONNECTED, dev)) {
4660 struct wlc_ssid *lssid = (struct wlc_ssid *)wl_read_prof(cfg, dev, WL_PROF_SSID);
4661 u8 *bssid = (u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID);
4662 u32 *channel = (u32 *)wl_read_prof(cfg, dev, WL_PROF_CHAN);
4663 if (!params->bssid || ((memcmp(params->bssid, bssid, ETHER_ADDR_LEN) == 0) &&
4664 (memcmp(params->ssid, lssid->SSID, lssid->SSID_len) == 0) &&
4665 (*channel == cfg->channel))) {
4666 WL_ERR(("Connection already existed to " MACDBG "\n",
4667 MAC2STRDBG((u8 *)wl_read_prof(cfg, dev, WL_PROF_BSSID))));
4668 return -EISCONN;
4669 }
4670 WL_ERR(("Ignore Previous connecton to %s (" MACDBG ")\n",
4671 lssid->SSID, MAC2STRDBG(bssid)));
4672 }
4673
4674 /* remove the VSIE */
4675 wl_cfg80211_ibss_vsie_delete(dev);
4676
4677 bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len);
4678 if (!bss) {
4679 if (IBSS_INITIAL_SCAN_ALLOWED == TRUE) {
4680 memcpy(ssid.ssid, params->ssid, params->ssid_len);
4681 ssid.ssid_len = params->ssid_len;
4682 do {
4683 if (unlikely
4684 (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
4685 -EBUSY)) {
4686 wl_delay(150);
4687 } else {
4688 break;
4689 }
4690 } while (++scan_retry < WL_SCAN_RETRY_MAX);
4691
4692 /* rtnl lock code is removed here. don't see why rtnl lock
4693 * needs to be released.
4694 */
4695
4696 /* wait 4 secons till scan done.... */
4697 schedule_timeout_interruptible(msecs_to_jiffies(4000));
4698
4699 bss = cfg80211_get_ibss(wiphy, NULL,
4700 params->ssid, params->ssid_len);
4701 }
4702 }
4703 if (bss && ((IBSS_COALESCE_ALLOWED == TRUE) ||
4704 ((IBSS_COALESCE_ALLOWED == FALSE) && params->bssid &&
4705 !memcmp(bss->bssid, params->bssid, ETHER_ADDR_LEN)))) {
4706 cfg->ibss_starter = false;
4707 WL_DBG(("Found IBSS\n"));
4708 } else {
4709 cfg->ibss_starter = true;
4710 }
4711
4712 if (bss) {
4713 CFG80211_PUT_BSS(wiphy, bss);
4714 }
4715
4716 if (chan) {
4717 if (chan->band == IEEE80211_BAND_5GHZ)
4718 param[0] = WLC_BAND_5G;
4719 else if (chan->band == IEEE80211_BAND_2GHZ)
4720 param[0] = WLC_BAND_2G;
4721 err = wldev_iovar_getint(dev, "bw_cap", param);
4722 if (unlikely(err)) {
4723 WL_ERR(("Get bw_cap Failed (%d)\n", err));
4724 return err;
4725 }
4726 bw_cap = param[0];
4727 chanspec = channel_to_chanspec(wiphy, dev, cfg->channel, bw_cap);
4728 }
4729 /*
4730 * Join with specific BSSID and cached SSID
4731 * If SSID is zero join based on BSSID only
4732 */
4733 memset(&join_params, 0, sizeof(join_params));
4734 memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
4735 params->ssid_len);
4736 join_params.ssid.SSID_len = htod32(params->ssid_len);
4737 if (params->bssid) {
4738 memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN);
4739 err = wldev_ioctl_set(dev, WLC_SET_DESIRED_BSSID, &join_params.params.bssid,
4740 ETHER_ADDR_LEN);
4741 if (unlikely(err)) {
4742 WL_ERR(("Error (%d)\n", err));
4743 return err;
4744 }
4745 } else
4746 memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
4747
4748 if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
4749 scan_suppress = TRUE;
4750 /* Set the SCAN SUPPRESS Flag in the firmware to skip join scan */
4751 err = wldev_ioctl_set(dev, WLC_SET_SCANSUPPRESS,
4752 &scan_suppress, sizeof(int));
4753 if (unlikely(err)) {
4754 WL_ERR(("Scan Suppress Setting Failed (%d)\n", err));
4755 return err;
4756 }
4757 }
4758
4759 join_params.params.chanspec_list[0] = chanspec;
4760 join_params.params.chanspec_num = 1;
4761 wldev_iovar_setint(dev, "chanspec", chanspec);
4762 join_params_size = sizeof(join_params);
4763
4764 /* Disable Authentication, IBSS will add key if it required */
4765 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
4766 wldev_iovar_setint(dev, "wsec", 0);
4767
4768 err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
4769 join_params_size);
4770 if (unlikely(err)) {
4771 WL_ERR(("Error (%d)\n", err));
4772 return err;
4773 }
4774
4775 if (IBSS_INITIAL_SCAN_ALLOWED == FALSE) {
4776 scan_suppress = FALSE;
4777 /* Reset the SCAN SUPPRESS Flag */
4778 err = wldev_ioctl_set(dev, WLC_SET_SCANSUPPRESS,
4779 &scan_suppress, sizeof(int));
4780 if (unlikely(err)) {
4781 WL_ERR(("Reset Scan Suppress Flag Failed (%d)\n", err));
4782 return err;
4783 }
4784 }
4785 wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
4786 wl_update_prof(cfg, dev, NULL, &cfg->channel, WL_PROF_CHAN);
4787 #ifdef WL_RELMCAST
4788 cfg->rmc_event_seq = 0; /* initialize rmcfail sequence */
4789 #endif /* WL_RELMCAST */
4790 return err;
4791 }
4792
4793 static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
4794 {
4795 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4796 s32 err = 0;
4797 scb_val_t scbval;
4798 u8 *curbssid;
4799
4800 RETURN_EIO_IF_NOT_UP(cfg);
4801 wl_link_down(cfg);
4802
4803 WL_ERR(("Leave IBSS\n"));
4804 curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
4805 wl_set_drv_status(cfg, DISCONNECTING, dev);
4806 scbval.val = 0;
4807 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
4808 err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
4809 sizeof(scb_val_t));
4810 if (unlikely(err)) {
4811 wl_clr_drv_status(cfg, DISCONNECTING, dev);
4812 WL_ERR(("error(%d)\n", err));
4813 return err;
4814 }
4815
4816 /* remove the VSIE */
4817 wl_cfg80211_ibss_vsie_delete(dev);
4818
4819 return err;
4820 }
4821
4822 #ifdef MFP
4823 static int wl_cfg80211_get_rsn_capa(bcm_tlv_t *wpa2ie, u8** rsn_cap)
4824 {
4825 u16 suite_count;
4826 wpa_suite_mcast_t *mcast;
4827 wpa_suite_ucast_t *ucast;
4828 u16 len;
4829 wpa_suite_auth_key_mgmt_t *mgmt;
4830
4831 if (!wpa2ie)
4832 return -1;
4833
4834 len = wpa2ie->len;
4835 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
4836 if ((len -= WPA_SUITE_LEN) <= 0)
4837 return BCME_BADLEN;
4838 ucast = (wpa_suite_ucast_t *)&mcast[1];
4839 suite_count = ltoh16_ua(&ucast->count);
4840 if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
4841 (len -= (WPA_IE_SUITE_COUNT_LEN +
4842 (WPA_SUITE_LEN * suite_count))) <= 0)
4843 return BCME_BADLEN;
4844
4845 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
4846 suite_count = ltoh16_ua(&mgmt->count);
4847
4848 if ((suite_count > NL80211_MAX_NR_CIPHER_SUITES) ||
4849 (len -= (WPA_IE_SUITE_COUNT_LEN +
4850 (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
4851 rsn_cap[0] = (u8 *)&mgmt->list[suite_count];
4852 } else
4853 return BCME_BADLEN;
4854
4855 return 0;
4856 }
4857 #endif /* MFP */
4858
4859 static s32
4860 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
4861 {
4862 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4863 struct wl_security *sec;
4864 s32 val = 0;
4865 s32 err = 0;
4866 s32 bssidx;
4867
4868 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4869 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4870 return BCME_ERROR;
4871 }
4872
4873 if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1)
4874 val = WPA_AUTH_PSK |
4875 WPA_AUTH_UNSPECIFIED;
4876 else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)
4877 val = WPA2_AUTH_PSK|
4878 WPA2_AUTH_UNSPECIFIED;
4879 else
4880 val = WPA_AUTH_DISABLED;
4881
4882 if (is_wps_conn(sme))
4883 val = WPA_AUTH_DISABLED;
4884
4885 WL_DBG(("setting wpa_auth to 0x%0x\n", val));
4886 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
4887 if (unlikely(err)) {
4888 WL_ERR(("set wpa_auth failed (%d)\n", err));
4889 return err;
4890 }
4891 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4892 sec->wpa_versions = sme->crypto.wpa_versions;
4893 return err;
4894 }
4895
4896
4897 static s32
4898 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
4899 {
4900 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4901 struct wl_security *sec;
4902 s32 val = 0;
4903 s32 err = 0;
4904 s32 bssidx;
4905
4906 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4907 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4908 return BCME_ERROR;
4909 }
4910
4911 switch (sme->auth_type) {
4912 case NL80211_AUTHTYPE_OPEN_SYSTEM:
4913 val = WL_AUTH_OPEN_SYSTEM;
4914 WL_DBG(("open system\n"));
4915 break;
4916 case NL80211_AUTHTYPE_SHARED_KEY:
4917 val = WL_AUTH_SHARED_KEY;
4918 WL_DBG(("shared key\n"));
4919 break;
4920 case NL80211_AUTHTYPE_AUTOMATIC:
4921 val = WL_AUTH_OPEN_SHARED;
4922 WL_DBG(("automatic\n"));
4923 break;
4924 default:
4925 val = 2;
4926 WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
4927 break;
4928 }
4929
4930 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
4931 if (unlikely(err)) {
4932 WL_ERR(("set auth failed (%d)\n", err));
4933 return err;
4934 }
4935 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
4936 sec->auth_type = sme->auth_type;
4937 return err;
4938 }
4939
4940 static s32
4941 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
4942 {
4943 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4944 struct wl_security *sec;
4945 s32 pval = 0;
4946 s32 gval = 0;
4947 s32 err = 0;
4948 s32 wsec_val = 0;
4949 s32 bssidx;
4950
4951 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4952 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4953 return BCME_ERROR;
4954 }
4955
4956 if (sme->crypto.n_ciphers_pairwise) {
4957 switch (sme->crypto.ciphers_pairwise[0]) {
4958 case WLAN_CIPHER_SUITE_WEP40:
4959 case WLAN_CIPHER_SUITE_WEP104:
4960 pval = WEP_ENABLED;
4961 break;
4962 case WLAN_CIPHER_SUITE_TKIP:
4963 pval = TKIP_ENABLED;
4964 break;
4965 case WLAN_CIPHER_SUITE_CCMP:
4966 case WLAN_CIPHER_SUITE_AES_CMAC:
4967 pval = AES_ENABLED;
4968 break;
4969 default:
4970 WL_ERR(("invalid cipher pairwise (%d)\n",
4971 sme->crypto.ciphers_pairwise[0]));
4972 return -EINVAL;
4973 }
4974 }
4975 if (sme->crypto.cipher_group) {
4976 switch (sme->crypto.cipher_group) {
4977 case WLAN_CIPHER_SUITE_WEP40:
4978 case WLAN_CIPHER_SUITE_WEP104:
4979 gval = WEP_ENABLED;
4980 break;
4981 case WLAN_CIPHER_SUITE_TKIP:
4982 gval = TKIP_ENABLED;
4983 break;
4984 case WLAN_CIPHER_SUITE_CCMP:
4985 gval = AES_ENABLED;
4986 break;
4987 case WLAN_CIPHER_SUITE_AES_CMAC:
4988 gval = AES_ENABLED;
4989 break;
4990 default:
4991 WL_ERR(("invalid cipher group (%d)\n",
4992 sme->crypto.cipher_group));
4993 return -EINVAL;
4994 }
4995 }
4996
4997 WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
4998
4999 if (is_wps_conn(sme)) {
5000 if (sme->privacy)
5001 err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
5002 else
5003 /* WPS-2.0 allows no security */
5004 err = wldev_iovar_setint_bsscfg(dev, "wsec", 0, bssidx);
5005 } else {
5006 WL_DBG((" NO, is_wps_conn, Set pval | gval to WSEC"));
5007 wsec_val = pval | gval;
5008
5009 WL_DBG((" Set WSEC to fW 0x%x \n", wsec_val));
5010 err = wldev_iovar_setint_bsscfg(dev, "wsec",
5011 wsec_val, bssidx);
5012 }
5013 if (unlikely(err)) {
5014 WL_ERR(("error (%d)\n", err));
5015 return err;
5016 }
5017
5018 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
5019 sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
5020 sec->cipher_group = sme->crypto.cipher_group;
5021
5022 return err;
5023 }
5024
5025 #ifdef MFP
5026 static s32
5027 wl_cfg80211_set_mfp(struct bcm_cfg80211 *cfg,
5028 struct net_device *dev,
5029 struct cfg80211_connect_params *sme)
5030 {
5031 s32 mfp = WL_MFP_NONE;
5032 s32 current_mfp = WL_MFP_NONE;
5033 bcm_tlv_t *wpa2_ie;
5034 u8* rsn_cap = NULL;
5035 bool fw_support = false;
5036 int err, count = 0;
5037 u8 *eptr = NULL, *ptr = NULL;
5038 u8* group_mgmt_cs = NULL;
5039 wpa_pmkid_list_t* pmkid = NULL;
5040
5041 if (!sme) {
5042 /* No connection params from userspace, Do nothing. */
5043 return 0;
5044 }
5045
5046 /* Check fw support and retreive current mfp val */
5047 err = wldev_iovar_getint(dev, "mfp", &current_mfp);
5048 if (!err) {
5049 fw_support = true;
5050 }
5051
5052 /* Parse the wpa2ie to decode the MFP capablity */
5053 if (((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
5054 DOT11_MNG_RSN_ID)) != NULL) &&
5055 (wl_cfg80211_get_rsn_capa(wpa2_ie, &rsn_cap) == 0)) {
5056 /* Check for MFP cap in the RSN capability field */
5057 if (rsn_cap[0] & RSN_CAP_MFPR) {
5058 mfp = WL_MFP_REQUIRED;
5059 } else if (rsn_cap[0] & RSN_CAP_MFPC) {
5060 mfp = WL_MFP_CAPABLE;
5061 }
5062
5063 /*
5064 * eptr --> end/last byte addr of wpa2_ie
5065 * ptr --> to keep track of current/required byte addr
5066 */
5067 eptr = (u8*)wpa2_ie + (wpa2_ie->len + TLV_HDR_LEN);
5068 /* pointing ptr to the next byte after rns_cap */
5069 ptr = (u8*)rsn_cap + RSN_CAP_LEN;
5070 if (mfp && (eptr - ptr) >= WPA2_PMKID_COUNT_LEN) {
5071 /* pmkid now to point to 1st byte addr of pmkid in wpa2_ie */
5072 pmkid = (wpa_pmkid_list_t*)ptr;
5073 count = pmkid->count.low | (pmkid->count.high << 8);
5074 /* ptr now to point to last byte addr of pmkid */
5075 ptr = (u8*)pmkid + (count * WPA2_PMKID_LEN
5076 + WPA2_PMKID_COUNT_LEN);
5077 if ((eptr - ptr) >= WPA_SUITE_LEN) {
5078 /* group_mgmt_cs now to point to first byte addr of bip */
5079 group_mgmt_cs = ptr;
5080 }
5081 }
5082 }
5083
5084 WL_DBG((" mfp:%d wpa2_ie ptr:%p rsn_cap 0x%x%x fw mfp support:%d\n",
5085 mfp, wpa2_ie, rsn_cap[0], rsn_cap[1], fw_support));
5086
5087 if (fw_support == false) {
5088 if (mfp == WL_MFP_REQUIRED) {
5089 /* if mfp > 0, mfp capability set in wpa ie, but
5090 * FW indicated error for mfp. Propagate the error up.
5091 */
5092 WL_ERR(("mfp capability found in wpaie. But fw doesn't "
5093 "seem to support MFP\n"));
5094 return -EINVAL;
5095 } else {
5096 /* Firmware doesn't support mfp. But since connection request
5097 * is for non-mfp case, don't bother.
5098 */
5099 return 0;
5100 }
5101 } else if (mfp != current_mfp) {
5102 err = wldev_iovar_setint(dev, "mfp", mfp);
5103 if (unlikely(err)) {
5104 WL_ERR(("mfp (%d) set failed ret:%d \n", mfp, err));
5105 return err;
5106 }
5107 WL_DBG(("mfp set to 0x%x \n", mfp));
5108 }
5109
5110 if (group_mgmt_cs && bcmp((const uint8 *)WPA2_OUI,
5111 group_mgmt_cs, (WPA_SUITE_LEN - 1)) == 0) {
5112 WL_DBG(("BIP is found\n"));
5113 err = wldev_iovar_setbuf(dev, "bip",
5114 group_mgmt_cs, WPA_SUITE_LEN, cfg->ioctl_buf,
5115 WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
5116 /*
5117 * Dont return failure for unsupported cases
5118 * of bip iovar for backward compatibility
5119 */
5120 if (err != BCME_UNSUPPORTED && err < 0) {
5121 WL_ERR(("bip set error (%d)\n", err));
5122 return err;
5123 }
5124 }
5125
5126 return 0;
5127 }
5128 #endif /* MFP */
5129
5130 static s32
5131 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
5132 {
5133 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5134 struct wl_security *sec;
5135 s32 val = 0;
5136 s32 err = 0;
5137 s32 bssidx;
5138
5139 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5140 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5141 return BCME_ERROR;
5142 }
5143
5144 if (sme->crypto.n_akm_suites) {
5145 err = wldev_iovar_getint(dev, "wpa_auth", &val);
5146 if (unlikely(err)) {
5147 WL_ERR(("could not get wpa_auth (%d)\n", err));
5148 return err;
5149 }
5150 if (val & (WPA_AUTH_PSK |
5151 WPA_AUTH_UNSPECIFIED)) {
5152 switch (sme->crypto.akm_suites[0]) {
5153 case WLAN_AKM_SUITE_8021X:
5154 val = WPA_AUTH_UNSPECIFIED;
5155 break;
5156 case WLAN_AKM_SUITE_PSK:
5157 val = WPA_AUTH_PSK;
5158 break;
5159 default:
5160 WL_ERR(("invalid akm suite (0x%x)\n",
5161 sme->crypto.akm_suites[0]));
5162 return -EINVAL;
5163 }
5164 } else if (val & (WPA2_AUTH_PSK |
5165 WPA2_AUTH_UNSPECIFIED)) {
5166 switch (sme->crypto.akm_suites[0]) {
5167 case WLAN_AKM_SUITE_8021X:
5168 val = WPA2_AUTH_UNSPECIFIED;
5169 break;
5170 #ifdef MFP
5171 #ifdef CUSTOMER_HW6
5172 case WL_AKM_SUITE_SHA256_1X:
5173 if (wl_customer6_legacy_chip_check(cfg, dev)) {
5174 val = WPA2_AUTH_UNSPECIFIED;
5175 } else {
5176 val = WPA2_AUTH_1X_SHA256;
5177 }
5178 break;
5179 case WL_AKM_SUITE_SHA256_PSK:
5180 if (wl_customer6_legacy_chip_check(cfg, dev)) {
5181 val = WPA2_AUTH_PSK;
5182 } else {
5183 val = WPA2_AUTH_PSK_SHA256;
5184 }
5185 break;
5186 #else
5187 case WL_AKM_SUITE_SHA256_1X:
5188 val = WPA2_AUTH_1X_SHA256;
5189 break;
5190 case WL_AKM_SUITE_SHA256_PSK:
5191 val = WPA2_AUTH_PSK_SHA256;
5192 break;
5193 #endif /* CUSTOMER_HW6 */
5194 #endif /* MFP */
5195 case WLAN_AKM_SUITE_PSK:
5196 val = WPA2_AUTH_PSK;
5197 break;
5198 default:
5199 WL_ERR(("invalid akm suite (0x%x)\n",
5200 sme->crypto.akm_suites[0]));
5201 return -EINVAL;
5202 }
5203 }
5204
5205 #ifdef MFP
5206 if ((err = wl_cfg80211_set_mfp(cfg, dev, sme)) < 0) {
5207 WL_ERR(("MFP set failed err:%d\n", err));
5208 return -EINVAL;
5209 }
5210 #endif /* MFP */
5211
5212 WL_DBG(("setting wpa_auth to 0x%x\n", val));
5213 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
5214 if (unlikely(err)) {
5215 WL_ERR(("could not set wpa_auth (0x%x)\n", err));
5216 return err;
5217 }
5218 }
5219 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
5220 sec->wpa_auth = sme->crypto.akm_suites[0];
5221
5222 return err;
5223 }
5224
5225 static s32
5226 wl_set_set_sharedkey(struct net_device *dev,
5227 struct cfg80211_connect_params *sme)
5228 {
5229 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5230 struct wl_security *sec;
5231 struct wl_wsec_key key;
5232 s32 val;
5233 s32 err = 0;
5234 s32 bssidx;
5235
5236 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5237 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5238 return BCME_ERROR;
5239 }
5240
5241 WL_DBG(("key len (%d)\n", sme->key_len));
5242 if (sme->key_len) {
5243 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
5244 WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n",
5245 sec->wpa_versions, sec->cipher_pairwise));
5246 if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 |
5247 NL80211_WPA_VERSION_2)) &&
5248 (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 |
5249 WLAN_CIPHER_SUITE_WEP104)))
5250 {
5251 memset(&key, 0, sizeof(key));
5252 key.len = (u32) sme->key_len;
5253 key.index = (u32) sme->key_idx;
5254 if (unlikely(key.len > sizeof(key.data))) {
5255 WL_ERR(("Too long key length (%u)\n", key.len));
5256 return -EINVAL;
5257 }
5258 memcpy(key.data, sme->key, key.len);
5259 key.flags = WL_PRIMARY_KEY;
5260 switch (sec->cipher_pairwise) {
5261 case WLAN_CIPHER_SUITE_WEP40:
5262 key.algo = CRYPTO_ALGO_WEP1;
5263 break;
5264 case WLAN_CIPHER_SUITE_WEP104:
5265 key.algo = CRYPTO_ALGO_WEP128;
5266 break;
5267 default:
5268 WL_ERR(("Invalid algorithm (%d)\n",
5269 sme->crypto.ciphers_pairwise[0]));
5270 return -EINVAL;
5271 }
5272 /* Set the new key/index */
5273 WL_DBG(("key length (%d) key index (%d) algo (%d)\n",
5274 key.len, key.index, key.algo));
5275 WL_DBG(("key \"%s\"\n", key.data));
5276 swap_key_from_BE(&key);
5277 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
5278 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5279 if (unlikely(err)) {
5280 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
5281 return err;
5282 }
5283 if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) {
5284 WL_DBG(("set auth_type to shared key\n"));
5285 val = WL_AUTH_SHARED_KEY; /* shared key */
5286 err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
5287 if (unlikely(err)) {
5288 WL_ERR(("set auth failed (%d)\n", err));
5289 return err;
5290 }
5291 }
5292 }
5293 }
5294 return err;
5295 }
5296
5297 #if defined(ESCAN_RESULT_PATCH)
5298 static u8 connect_req_bssid[6];
5299 static u8 broad_bssid[6];
5300 #endif /* ESCAN_RESULT_PATCH */
5301
5302
5303
5304 #if defined(CUSTOM_SET_CPUCORE) || defined(CONFIG_TCPACK_FASTTX)
5305 static bool wl_get_chan_isvht80(struct net_device *net, dhd_pub_t *dhd)
5306 {
5307 u32 chanspec = 0;
5308 bool isvht80 = 0;
5309
5310 if (wldev_iovar_getint(net, "chanspec", (s32 *)&chanspec) == BCME_OK)
5311 chanspec = wl_chspec_driver_to_host(chanspec);
5312
5313 isvht80 = chanspec & WL_CHANSPEC_BW_80;
5314 WL_INFORM(("%s: chanspec(%x:%d)\n", __FUNCTION__, chanspec, isvht80));
5315
5316 return isvht80;
5317 }
5318 #endif /* CUSTOM_SET_CPUCORE || CONFIG_TCPACK_FASTTX */
5319
5320 int wl_cfg80211_cleanup_mismatch_status(struct net_device *dev, struct bcm_cfg80211 *cfg,
5321 bool disassociate)
5322 {
5323 scb_val_t scbval;
5324 int err = TRUE;
5325 int wait_cnt;
5326
5327 if (disassociate) {
5328 WL_ERR(("Disassociate previous connection!\n"));
5329 wl_set_drv_status(cfg, DISCONNECTING, dev);
5330 scbval.val = DOT11_RC_DISASSOC_LEAVING;
5331 scbval.val = htod32(scbval.val);
5332
5333 err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
5334 sizeof(scb_val_t));
5335 if (unlikely(err)) {
5336 wl_clr_drv_status(cfg, DISCONNECTING, dev);
5337 WL_ERR(("error (%d)\n", err));
5338 return err;
5339 }
5340 wait_cnt = 500/10;
5341 } else {
5342 wait_cnt = 200/10;
5343 WL_ERR(("Waiting for previous DISCONNECTING status!\n"));
5344 if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
5345 wl_clr_drv_status(cfg, DISCONNECTING, dev);
5346 }
5347 }
5348
5349 while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
5350 WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n",
5351 wait_cnt));
5352 wait_cnt--;
5353 OSL_SLEEP(10);
5354 }
5355
5356 if (wait_cnt == 0) {
5357 WL_ERR(("DISCONNECING clean up failed!\n"));
5358 return BCME_NOTREADY;
5359 }
5360 return BCME_OK;
5361 }
5362
5363 #define MAX_SCAN_ABORT_WAIT_CNT 20
5364 #define WAIT_SCAN_ABORT_OSL_SLEEP_TIME 10
5365
5366 static s32
5367 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
5368 struct cfg80211_connect_params *sme)
5369 {
5370 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5371 struct ieee80211_channel *chan = sme->channel;
5372 wl_extjoin_params_t *ext_join_params;
5373 struct wl_join_params join_params;
5374 size_t join_params_size;
5375 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
5376 s32 err = 0;
5377 wpa_ie_fixed_t *wpa_ie;
5378 bcm_tlv_t *wpa2_ie;
5379 u8* wpaie = 0;
5380 u32 wpaie_len = 0;
5381 u32 chan_cnt = 0;
5382 struct ether_addr bssid;
5383 s32 bssidx = -1;
5384 #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
5385 int wait_cnt;
5386 #endif
5387
5388 WL_DBG(("In\n"));
5389 BCM_REFERENCE(dhdp);
5390
5391 #ifdef WLMESH
5392 wl_config_ifmode(cfg, dev, dev->ieee80211_ptr->iftype);
5393 #endif
5394 #if defined(SUPPORT_RANDOM_MAC_SCAN)
5395 wl_cfg80211_set_random_mac(dev, FALSE);
5396 #endif /* SUPPORT_RANDOM_MAC_SCAN */
5397
5398 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
5399 if (sme->channel_hint) {
5400 chan = sme->channel_hint;
5401 WL_DBG(("channel_hint (%d), channel_hint center_freq (%d)\n",
5402 ieee80211_frequency_to_channel(sme->channel_hint->center_freq),
5403 sme->channel_hint->center_freq));
5404 }
5405 if (sme->bssid_hint) {
5406 sme->bssid = sme->bssid_hint;
5407 WL_DBG(("bssid_hint "MACDBG" \n", MAC2STRDBG(sme->bssid_hint)));
5408 }
5409 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
5410
5411 if (unlikely(!sme->ssid)) {
5412 WL_ERR(("Invalid ssid\n"));
5413 return -EOPNOTSUPP;
5414 }
5415
5416 if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) {
5417 WL_ERR(("Invalid SSID info: SSID=%s, length=%zd\n",
5418 sme->ssid, sme->ssid_len));
5419 return -EINVAL;
5420 }
5421
5422 WL_DBG(("SME IE : len=%zu\n", sme->ie_len));
5423 if (sme->ie != NULL && sme->ie_len > 0 && (wl_dbg_level & WL_DBG_DBG)) {
5424 prhex(NULL, (uchar *)sme->ie, sme->ie_len);
5425 }
5426
5427 RETURN_EIO_IF_NOT_UP(cfg);
5428
5429 /*
5430 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
5431 */
5432 #if (defined(BCM4359_CHIP) || !defined(ESCAN_RESULT_PATCH))
5433 if (cfg->scan_request) {
5434 WL_TRACE_HW4(("Aborting the scan! \n"));
5435 wl_cfg80211_scan_abort(cfg);
5436 wait_cnt = MAX_SCAN_ABORT_WAIT_CNT;
5437 while (wl_get_drv_status(cfg, SCANNING, dev) && wait_cnt) {
5438 WL_DBG(("Waiting for SCANNING terminated, wait_cnt: %d\n", wait_cnt));
5439 wait_cnt--;
5440 OSL_SLEEP(WAIT_SCAN_ABORT_OSL_SLEEP_TIME);
5441 }
5442 if (wl_get_drv_status(cfg, SCANNING, dev)) {
5443 wl_notify_escan_complete(cfg, dev, true, true);
5444 }
5445 }
5446 #endif
5447 #ifdef WL_SCHED_SCAN
5448 /* Locks are taken in wl_cfg80211_sched_scan_stop()
5449 * A start scan occuring during connect is unlikely
5450 */
5451 if (cfg->sched_scan_req) {
5452 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
5453 wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg), 0);
5454 #else
5455 wl_cfg80211_sched_scan_stop(wiphy, bcmcfg_to_prmry_ndev(cfg));
5456 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
5457 }
5458 #endif
5459 #if defined(ESCAN_RESULT_PATCH)
5460 if (sme->bssid)
5461 memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN);
5462 else
5463 bzero(connect_req_bssid, ETHER_ADDR_LEN);
5464 bzero(broad_bssid, ETHER_ADDR_LEN);
5465 #endif
5466 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
5467 maxrxpktglom = 0;
5468 #endif
5469 if (wl_get_drv_status(cfg, CONNECTING, dev) || wl_get_drv_status(cfg, CONNECTED, dev)) {
5470 /* set nested connect bit to identify the context */
5471 wl_set_drv_status(cfg, NESTED_CONNECT, dev);
5472 /* DHD prev status is CONNECTING/CONNECTED */
5473 err = wl_cfg80211_cleanup_mismatch_status(dev, cfg, TRUE);
5474 } else if (wl_get_drv_status(cfg, DISCONNECTING, dev)) {
5475 /* DHD prev status is DISCONNECTING */
5476 err = wl_cfg80211_cleanup_mismatch_status(dev, cfg, FALSE);
5477 } else if (!wl_get_drv_status(cfg, CONNECTED, dev)) {
5478 /* DHD previous status is not connected and FW connected */
5479 if (wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) == 0) {
5480 /* set nested connect bit to identify the context */
5481 wl_set_drv_status(cfg, NESTED_CONNECT, dev);
5482 err = wl_cfg80211_cleanup_mismatch_status(dev, cfg, TRUE);
5483 }
5484 }
5485
5486 /* 'connect' request received */
5487 wl_set_drv_status(cfg, CONNECTING, dev);
5488 /* clear nested connect bit on proceeding for connection */
5489 wl_clr_drv_status(cfg, NESTED_CONNECT, dev);
5490
5491 /* Clean BSSID */
5492 bzero(&bssid, sizeof(bssid));
5493 if (!wl_get_drv_status(cfg, DISCONNECTING, dev))
5494 wl_update_prof(cfg, dev, NULL, (void *)&bssid, WL_PROF_BSSID);
5495
5496 if (p2p_is_on(cfg) && (dev != bcmcfg_to_prmry_ndev(cfg))) {
5497 /* we only allow to connect using virtual interface in case of P2P */
5498 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5499 WL_ERR(("Find p2p index from wdev(%p) failed\n",
5500 dev->ieee80211_ptr));
5501 err = BCME_ERROR;
5502 goto exit;
5503 }
5504 wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
5505 VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
5506 } else if (dev == bcmcfg_to_prmry_ndev(cfg)) {
5507 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5508 WL_ERR(("Find wlan index from wdev(%p) failed\n", dev->ieee80211_ptr));
5509 err = BCME_ERROR;
5510 goto exit;
5511 }
5512
5513 /* find the RSN_IE */
5514 if ((wpa2_ie = bcm_parse_tlvs((u8 *)sme->ie, sme->ie_len,
5515 DOT11_MNG_RSN_ID)) != NULL) {
5516 WL_DBG((" WPA2 IE is found\n"));
5517 }
5518 /* find the WPA_IE */
5519 if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)sme->ie,
5520 sme->ie_len)) != NULL) {
5521 WL_DBG((" WPA IE is found\n"));
5522 }
5523 if (wpa_ie != NULL || wpa2_ie != NULL) {
5524 wpaie = (wpa_ie != NULL) ? (u8 *)wpa_ie : (u8 *)wpa2_ie;
5525 wpaie_len = (wpa_ie != NULL) ? wpa_ie->length : wpa2_ie->len;
5526 wpaie_len += WPA_RSN_IE_TAG_FIXED_LEN;
5527 err = wldev_iovar_setbuf(dev, "wpaie", wpaie, wpaie_len,
5528 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
5529 if (unlikely(err)) {
5530 WL_ERR(("wpaie set error (%d)\n", err));
5531 goto exit;
5532 }
5533 } else {
5534 err = wldev_iovar_setbuf(dev, "wpaie", NULL, 0,
5535 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
5536 if (unlikely(err)) {
5537 WL_ERR(("wpaie set error (%d)\n", err));
5538 goto exit;
5539 }
5540 }
5541 err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
5542 VNDR_IE_ASSOCREQ_FLAG, (const u8 *)sme->ie, sme->ie_len);
5543 if (unlikely(err)) {
5544 goto exit;
5545 }
5546 }
5547
5548 if (chan) {
5549 cfg->channel = ieee80211_frequency_to_channel(chan->center_freq);
5550 chan_cnt = 1;
5551 WL_DBG(("channel (%d), center_req (%d), %d channels\n", cfg->channel,
5552 chan->center_freq, chan_cnt));
5553 } else {
5554 WL_DBG(("No channel info from user space\n"));
5555 cfg->channel = 0;
5556 }
5557
5558
5559 WL_DBG(("3. set wpa version \n"));
5560
5561 err = wl_set_wpa_version(dev, sme);
5562 if (unlikely(err)) {
5563 WL_ERR(("Invalid wpa_version\n"));
5564 goto exit;
5565 }
5566 err = wl_set_auth_type(dev, sme);
5567 if (unlikely(err)) {
5568 WL_ERR(("Invalid auth type\n"));
5569 goto exit;
5570 }
5571
5572 err = wl_set_set_cipher(dev, sme);
5573 if (unlikely(err)) {
5574 WL_ERR(("Invalid ciper\n"));
5575 goto exit;
5576 }
5577
5578 err = wl_set_key_mgmt(dev, sme);
5579 if (unlikely(err)) {
5580 WL_ERR(("Invalid key mgmt\n"));
5581 goto exit;
5582 }
5583
5584 err = wl_set_set_sharedkey(dev, sme);
5585 if (unlikely(err)) {
5586 WL_ERR(("Invalid shared key\n"));
5587 goto exit;
5588 }
5589
5590 /*
5591 * Join with specific BSSID and cached SSID
5592 * If SSID is zero join based on BSSID only
5593 */
5594 join_params_size = WL_EXTJOIN_PARAMS_FIXED_SIZE +
5595 chan_cnt * sizeof(chanspec_t);
5596 ext_join_params = (wl_extjoin_params_t*)kzalloc(join_params_size, GFP_KERNEL);
5597 if (ext_join_params == NULL) {
5598 err = -ENOMEM;
5599 wl_clr_drv_status(cfg, CONNECTING, dev);
5600 goto exit;
5601 }
5602 ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len);
5603 memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len);
5604 wl_update_prof(cfg, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID);
5605 ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
5606 /* increate dwell time to receive probe response or detect Beacon
5607 * from target AP at a noisy air only during connect command
5608 */
5609 ext_join_params->scan.active_time = chan_cnt ? WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS : -1;
5610 ext_join_params->scan.passive_time = chan_cnt ? WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS : -1;
5611 /* Set up join scan parameters */
5612 ext_join_params->scan.scan_type = -1;
5613 ext_join_params->scan.nprobes = chan_cnt ?
5614 (ext_join_params->scan.active_time/WL_SCAN_JOIN_PROBE_INTERVAL_MS) : -1;
5615 ext_join_params->scan.home_time = -1;
5616
5617 if (sme->bssid)
5618 memcpy(&ext_join_params->assoc.bssid, sme->bssid, ETH_ALEN);
5619 else
5620 memcpy(&ext_join_params->assoc.bssid, &ether_bcast, ETH_ALEN);
5621 ext_join_params->assoc.chanspec_num = chan_cnt;
5622 if (chan_cnt) {
5623 if (cfg->channel) {
5624 /*
5625 * Use the channel provided by userspace
5626 */
5627 u16 channel, band, bw, ctl_sb;
5628 chanspec_t chspec;
5629 channel = cfg->channel;
5630 band = (channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G
5631 : WL_CHANSPEC_BAND_5G;
5632
5633 /* Get min_bw set for the interface */
5634 bw = wl_cfg80211_ulb_get_min_bw_chspec(cfg, dev->ieee80211_ptr, bssidx);
5635 if (bw == INVCHANSPEC) {
5636 WL_ERR(("Invalid chanspec \n"));
5637 kfree(ext_join_params);
5638 err = BCME_ERROR;
5639 goto exit;
5640 }
5641
5642 ctl_sb = WL_CHANSPEC_CTL_SB_NONE;
5643 chspec = (channel | band | bw | ctl_sb);
5644 ext_join_params->assoc.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
5645 ext_join_params->assoc.chanspec_list[0] |= chspec;
5646 ext_join_params->assoc.chanspec_list[0] =
5647 wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]);
5648 }
5649 }
5650 ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num);
5651 if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
5652 WL_INFORM(("ssid \"%s\", len (%d)\n", ext_join_params->ssid.SSID,
5653 ext_join_params->ssid.SSID_len));
5654 }
5655
5656 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5657 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5658 kfree(ext_join_params);
5659 err = BCME_ERROR;
5660 goto exit;
5661 }
5662 #if defined(CUSTOMER_HW2)
5663 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
5664 #endif /* BCMDONGLEHOST && CUSTOMER_HW2 */
5665 #ifdef WL_EXT_IAPSTA
5666 wl_ext_iapsta_update_channel(dev, cfg->channel);
5667 #endif
5668 err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
5669 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5670
5671 if (cfg->rcc_enabled) {
5672 printf("Connecting with " MACDBG " ssid \"%s\", len (%d) with rcc channels \n\n",
5673 MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
5674 ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len);
5675 } else {
5676 printf("Connecting with " MACDBG " ssid \"%s\", len (%d) channel=%d\n\n",
5677 MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)),
5678 ext_join_params->ssid.SSID, ext_join_params->ssid.SSID_len, cfg->channel);
5679 }
5680
5681 kfree(ext_join_params);
5682 if (err) {
5683 wl_clr_drv_status(cfg, CONNECTING, dev);
5684 if (err == BCME_UNSUPPORTED) {
5685 WL_DBG(("join iovar is not supported\n"));
5686 goto set_ssid;
5687 } else {
5688 WL_ERR(("error (%d)\n", err));
5689 goto exit;
5690 }
5691 } else
5692 goto exit;
5693
5694 set_ssid:
5695 memset(&join_params, 0, sizeof(join_params));
5696 join_params_size = sizeof(join_params.ssid);
5697
5698 join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
5699 memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
5700 join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
5701 wl_update_prof(cfg, dev, NULL, &join_params.ssid, WL_PROF_SSID);
5702 if (sme->bssid)
5703 memcpy(&join_params.params.bssid, sme->bssid, ETH_ALEN);
5704 else
5705 memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
5706
5707 if (wl_ch_to_chanspec(dev, cfg->channel, &join_params, &join_params_size) < 0) {
5708 WL_ERR(("Invalid chanspec\n"));
5709 return -EINVAL;
5710 }
5711
5712 WL_DBG(("join_param_size %zu\n", join_params_size));
5713
5714 if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
5715 WL_INFORM(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
5716 join_params.ssid.SSID_len));
5717 }
5718 err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params, join_params_size);
5719 exit:
5720 if (err) {
5721 WL_ERR(("error (%d)\n", err));
5722 wl_clr_drv_status(cfg, CONNECTING, dev);
5723 }
5724 if (!err)
5725 wl_cfg80211_check_in4way(cfg, dev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY,
5726 WL_EXT_STATUS_CONNECTING, NULL);
5727
5728 #ifdef WLTDLS
5729 /* disable TDLS if number of connected interfaces is >= 1 */
5730 wl_cfg80211_tdls_config(cfg, TDLS_STATE_CONNECT, false);
5731 #endif /* WLTDLS */
5732
5733 #ifdef DBG_PKT_MON
5734 if ((dev == bcmcfg_to_prmry_ndev(cfg)) && !err) {
5735 DHD_DBG_PKT_MON_START(dhdp);
5736 }
5737 #endif /* DBG_PKT_MON */
5738 return err;
5739 }
5740
5741 #define WAIT_FOR_DISCONNECT_MAX 10
5742 static void wl_cfg80211_wait_for_disconnection(struct bcm_cfg80211 *cfg, struct net_device *dev)
5743 {
5744 uint8 wait_cnt;
5745
5746 wait_cnt = WAIT_FOR_DISCONNECT_MAX;
5747 while (wl_get_drv_status(cfg, DISCONNECTING, dev) && wait_cnt) {
5748 WL_DBG(("Waiting for disconnection, wait_cnt: %d\n", wait_cnt));
5749 wait_cnt--;
5750 OSL_SLEEP(50);
5751 }
5752
5753 return;
5754 }
5755
5756 static s32
5757 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
5758 u16 reason_code)
5759 {
5760 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5761 scb_val_t scbval;
5762 bool act = false;
5763 s32 err = 0;
5764 u8 *curbssid;
5765 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
5766 WL_ERR(("Reason %d\n", reason_code));
5767 RETURN_EIO_IF_NOT_UP(cfg);
5768 act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
5769 curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
5770
5771 BCM_REFERENCE(dhdp);
5772
5773 #ifdef ESCAN_RESULT_PATCH
5774 if (wl_get_drv_status(cfg, CONNECTING, dev) && curbssid &&
5775 (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0)) {
5776 WL_ERR(("Disconnecting from connecting device: " MACDBG "\n",
5777 MAC2STRDBG(curbssid)));
5778 act = true;
5779 }
5780 #endif /* ESCAN_RESULT_PATCH */
5781
5782 if (act) {
5783 #ifdef DBG_PKT_MON
5784 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
5785 DHD_DBG_PKT_MON_STOP(dhdp);
5786 }
5787 #endif /* DBG_PKT_MON */
5788 /*
5789 * Cancel ongoing scan to sync up with sme state machine of cfg80211.
5790 */
5791 #if !defined(ESCAN_RESULT_PATCH)
5792 /* Let scan aborted by F/W */
5793 if (cfg->scan_request) {
5794 WL_TRACE_HW4(("Aborting the scan! \n"));
5795 wl_notify_escan_complete(cfg, dev, true, true);
5796 }
5797 #endif /* ESCAN_RESULT_PATCH */
5798 if (wl_get_drv_status(cfg, CONNECTING, dev) ||
5799 wl_get_drv_status(cfg, CONNECTED, dev)) {
5800 wl_set_drv_status(cfg, DISCONNECTING, dev);
5801 scbval.val = reason_code;
5802 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
5803 scbval.val = htod32(scbval.val);
5804 err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval,
5805 sizeof(scb_val_t));
5806 if (unlikely(err)) {
5807 wl_clr_drv_status(cfg, DISCONNECTING, dev);
5808 WL_ERR(("error (%d)\n", err));
5809 return err;
5810 }
5811 wl_cfg80211_wait_for_disconnection(cfg, dev);
5812 }
5813 }
5814 #ifdef CUSTOM_SET_CPUCORE
5815 /* set default cpucore */
5816 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
5817 dhdp->chan_isvht80 &= ~DHD_FLAG_STA_MODE;
5818 if (!(dhdp->chan_isvht80))
5819 dhd_set_cpucore(dhdp, FALSE);
5820 }
5821 #endif /* CUSTOM_SET_CPUCORE */
5822
5823 return err;
5824 }
5825
5826 static s32
5827 #if defined(WL_CFG80211_P2P_DEV_IF)
5828 wl_cfg80211_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
5829 enum nl80211_tx_power_setting type, s32 mbm)
5830 #else
5831 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
5832 enum nl80211_tx_power_setting type, s32 dbm)
5833 #endif /* WL_CFG80211_P2P_DEV_IF */
5834 {
5835
5836 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5837 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5838 s32 err = 0;
5839 #if defined(WL_CFG80211_P2P_DEV_IF)
5840 s32 dbm = MBM_TO_DBM(mbm);
5841 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0)) || \
5842 defined(WL_COMPAT_WIRELESS) || defined(WL_SUPPORT_BACKPORTED_KPATCHES)
5843 dbm = MBM_TO_DBM(dbm);
5844 #endif /* WL_CFG80211_P2P_DEV_IF */
5845
5846 RETURN_EIO_IF_NOT_UP(cfg);
5847 switch (type) {
5848 case NL80211_TX_POWER_AUTOMATIC:
5849 break;
5850 case NL80211_TX_POWER_LIMITED:
5851 if (dbm < 0) {
5852 WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n"));
5853 return -EINVAL;
5854 }
5855 break;
5856 case NL80211_TX_POWER_FIXED:
5857 if (dbm < 0) {
5858 WL_ERR(("TX_POWER_FIXED - dbm is negative..\n"));
5859 return -EINVAL;
5860 }
5861 break;
5862 }
5863
5864 err = wl_set_tx_power(ndev, type, dbm);
5865 if (unlikely(err)) {
5866 WL_ERR(("error (%d)\n", err));
5867 return err;
5868 }
5869
5870 cfg->conf->tx_power = dbm;
5871
5872 return err;
5873 }
5874
5875 static s32
5876 #if defined(WL_CFG80211_P2P_DEV_IF)
5877 wl_cfg80211_get_tx_power(struct wiphy *wiphy,
5878 struct wireless_dev *wdev, s32 *dbm)
5879 #else
5880 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
5881 #endif /* WL_CFG80211_P2P_DEV_IF */
5882 {
5883 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5884 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5885 s32 err = 0;
5886
5887 RETURN_EIO_IF_NOT_UP(cfg);
5888 err = wl_get_tx_power(ndev, dbm);
5889 if (unlikely(err))
5890 WL_ERR(("error (%d)\n", err));
5891
5892 return err;
5893 }
5894
5895 static s32
5896 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
5897 u8 key_idx, bool unicast, bool multicast)
5898 {
5899 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5900 u32 index;
5901 s32 wsec;
5902 s32 err = 0;
5903 s32 bssidx;
5904
5905 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5906 WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
5907 return BCME_ERROR;
5908 }
5909
5910 WL_DBG(("key index (%d)\n", key_idx));
5911 RETURN_EIO_IF_NOT_UP(cfg);
5912 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
5913 if (unlikely(err)) {
5914 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
5915 return err;
5916 }
5917 if (wsec == WEP_ENABLED) {
5918 /* Just select a new current key */
5919 index = (u32) key_idx;
5920 index = htod32(index);
5921 err = wldev_ioctl_set(dev, WLC_SET_KEY_PRIMARY, &index,
5922 sizeof(index));
5923 if (unlikely(err)) {
5924 WL_ERR(("error (%d)\n", err));
5925 }
5926 }
5927 return err;
5928 }
5929
5930 static s32
5931 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
5932 u8 key_idx, const u8 *mac_addr, struct key_params *params)
5933 {
5934 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5935 struct wl_wsec_key key;
5936 s32 err = 0;
5937 s32 bssidx;
5938 s32 mode = wl_get_mode_by_netdev(cfg, dev);
5939
5940 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
5941 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
5942 return BCME_ERROR;
5943 }
5944 memset(&key, 0, sizeof(key));
5945 key.index = (u32) key_idx;
5946
5947 if (!ETHER_ISMULTI(mac_addr))
5948 memcpy((char *)&key.ea, (const void *)mac_addr, ETHER_ADDR_LEN);
5949 key.len = (u32) params->key_len;
5950
5951 /* check for key index change */
5952 if (key.len == 0) {
5953 /* key delete */
5954 swap_key_from_BE(&key);
5955 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
5956 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
5957 if (unlikely(err)) {
5958 WL_ERR(("key delete error (%d)\n", err));
5959 return err;
5960 }
5961 } else {
5962 if (key.len > sizeof(key.data)) {
5963 WL_ERR(("Invalid key length (%d)\n", key.len));
5964 return -EINVAL;
5965 }
5966 WL_DBG(("Setting the key index %d\n", key.index));
5967 memcpy(key.data, params->key, key.len);
5968
5969 if ((mode == WL_MODE_BSS) &&
5970 (params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
5971 u8 keybuf[8];
5972 memcpy(keybuf, &key.data[24], sizeof(keybuf));
5973 memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
5974 memcpy(&key.data[16], keybuf, sizeof(keybuf));
5975 }
5976
5977 /* if IW_ENCODE_EXT_RX_SEQ_VALID set */
5978 if (params->seq && params->seq_len == 6) {
5979 /* rx iv */
5980 u8 *ivptr;
5981 ivptr = (u8 *) params->seq;
5982 key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
5983 (ivptr[3] << 8) | ivptr[2];
5984 key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
5985 key.iv_initialized = true;
5986 }
5987
5988 switch (params->cipher) {
5989 case WLAN_CIPHER_SUITE_WEP40:
5990 key.algo = CRYPTO_ALGO_WEP1;
5991 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
5992 break;
5993 case WLAN_CIPHER_SUITE_WEP104:
5994 key.algo = CRYPTO_ALGO_WEP128;
5995 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
5996 break;
5997 case WLAN_CIPHER_SUITE_TKIP:
5998 key.algo = CRYPTO_ALGO_TKIP;
5999 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6000 break;
6001 case WLAN_CIPHER_SUITE_AES_CMAC:
6002 key.algo = CRYPTO_ALGO_AES_CCM;
6003 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
6004 break;
6005 case WLAN_CIPHER_SUITE_CCMP:
6006 key.algo = CRYPTO_ALGO_AES_CCM;
6007 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
6008 break;
6009 default:
6010 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
6011 return -EINVAL;
6012 }
6013 swap_key_from_BE(&key);
6014 /* need to guarantee EAPOL 4/4 send out before set key */
6015 dhd_wait_pend8021x(dev);
6016 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
6017 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
6018 if (unlikely(err)) {
6019 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
6020 return err;
6021 }
6022 }
6023 return err;
6024 }
6025
6026 int
6027 wl_cfg80211_enable_roam_offload(struct net_device *dev, int enable)
6028 {
6029 int err;
6030 wl_eventmsg_buf_t ev_buf;
6031 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6032
6033 if (dev != bcmcfg_to_prmry_ndev(cfg)) {
6034 /* roam offload is only for the primary device */
6035 return -1;
6036 }
6037 err = wldev_iovar_setint(dev, "roam_offload", enable);
6038 if (err)
6039 return err;
6040
6041 bzero(&ev_buf, sizeof(wl_eventmsg_buf_t));
6042 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_PSK_SUP, !enable);
6043 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_REQ_IE, !enable);
6044 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ASSOC_RESP_IE, !enable);
6045 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_REASSOC, !enable);
6046 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_JOIN, !enable);
6047 wl_cfg80211_add_to_eventbuffer(&ev_buf, WLC_E_ROAM, !enable);
6048 err = wl_cfg80211_apply_eventbuffer(dev, cfg, &ev_buf);
6049 if (!err) {
6050 cfg->roam_offload = enable;
6051 }
6052 return err;
6053 }
6054
6055 #if defined(WL_VIRTUAL_APSTA)
6056 int
6057 wl_cfg80211_interface_create(struct net_device *dev, char *name)
6058 {
6059 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6060 bcm_struct_cfgdev *new_cfgdev;
6061 char ifname[IFNAMSIZ];
6062 char iftype[IFNAMSIZ];
6063 enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
6064
6065 sscanf(name, "%s %s", ifname, iftype);
6066
6067 if (strnicmp(iftype, "AP", strlen("AP")) == 0) {
6068 iface_type = NL80211_IFTYPE_AP;
6069 }
6070
6071 new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
6072 iface_type, NULL, ifname);
6073 if (!new_cfgdev) {
6074 return BCME_ERROR;
6075 }
6076 else {
6077 WL_DBG(("Iface %s created successfuly\n", name));
6078 return BCME_OK;
6079 }
6080 }
6081
6082 int
6083 wl_cfg80211_interface_delete(struct net_device *dev, char *name)
6084 {
6085 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6086 struct net_info *iter, *next;
6087 int err = BCME_ERROR;
6088
6089 if (name == NULL) {
6090 return BCME_ERROR;
6091 }
6092
6093 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
6094 #pragma GCC diagnostic push
6095 #pragma GCC diagnostic ignored "-Wcast-qual"
6096 #endif
6097 for_each_ndev(cfg, iter, next) {
6098 if (iter->ndev) {
6099 if (strcmp(iter->ndev->name, name) == 0) {
6100 err = wl_cfg80211_del_iface(cfg->wdev->wiphy,
6101 ndev_to_cfgdev(iter->ndev));
6102 break;
6103 }
6104 }
6105 }
6106 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
6107 #pragma GCC diagnostic pop
6108 #endif
6109 if (!err) {
6110 WL_DBG(("Iface %s deleted successfuly", name));
6111 }
6112 return err;
6113 }
6114
6115 #if defined(PKT_FILTER_SUPPORT) && defined(APSTA_BLOCK_ARP_DURING_DHCP)
6116 void
6117 wl_cfg80211_block_arp(struct net_device *dev, int enable)
6118 {
6119 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6120 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
6121
6122 if (!dhd_pkt_filter_enable) {
6123 WL_INFORM(("Packet filter isn't enabled\n"));
6124 return;
6125 }
6126
6127 /* Block/Unblock ARP frames only if STA is connected to
6128 * the upstream AP in case of STA+SoftAP Concurrenct mode
6129 */
6130 if (!wl_get_drv_status(cfg, CONNECTED, dev)) {
6131 WL_INFORM(("STA doesn't connected to upstream AP\n"));
6132 return;
6133 }
6134
6135 if (enable) {
6136 WL_DBG(("Enable ARP Filter\n"));
6137 /* Add ARP filter */
6138 dhd_packet_filter_add_remove(dhdp, TRUE, DHD_BROADCAST_ARP_FILTER_NUM);
6139
6140 /* Enable ARP packet filter - blacklist */
6141 dhd_master_mode = FALSE;
6142 dhd_pktfilter_offload_enable(dhdp, dhdp->pktfilter[DHD_BROADCAST_ARP_FILTER_NUM],
6143 TRUE, dhd_master_mode);
6144 } else {
6145 WL_DBG(("Disable ARP Filter\n"));
6146 /* Disable ARP packet filter */
6147 dhd_master_mode = TRUE;
6148 dhd_pktfilter_offload_enable(dhdp, dhdp->pktfilter[DHD_BROADCAST_ARP_FILTER_NUM],
6149 FALSE, dhd_master_mode);
6150
6151 /* Delete ARP filter */
6152 dhd_packet_filter_add_remove(dhdp, FALSE, DHD_BROADCAST_ARP_FILTER_NUM);
6153 }
6154 }
6155 #endif /* PKT_FILTER_SUPPORT && APSTA_BLOCK_ARP_DURING_DHCP */
6156 #endif /* defined (WL_VIRTUAL_APSTA) */
6157
6158 static s32
6159 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
6160 u8 key_idx, bool pairwise, const u8 *mac_addr,
6161 struct key_params *params)
6162 {
6163 struct wl_wsec_key key;
6164 s32 val = 0;
6165 s32 wsec = 0;
6166 s32 err = 0;
6167 u8 keybuf[8];
6168 s32 bssidx = 0;
6169 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6170 s32 mode = wl_get_mode_by_netdev(cfg, dev);
6171
6172 WL_DBG(("key index (%d)\n", key_idx));
6173 RETURN_EIO_IF_NOT_UP(cfg);
6174
6175 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
6176 WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
6177 return BCME_ERROR;
6178 }
6179 wl_cfg80211_check_in4way(cfg, dev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY,
6180 WL_EXT_STATUS_4WAY_DONE, NULL);
6181
6182 if (mac_addr &&
6183 ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
6184 (params->cipher != WLAN_CIPHER_SUITE_WEP104))) {
6185 wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
6186 goto exit;
6187 }
6188 memset(&key, 0, sizeof(key));
6189 /* Clear any buffered wep key */
6190 memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
6191
6192 key.len = (u32) params->key_len;
6193 key.index = (u32) key_idx;
6194
6195 if (unlikely(key.len > sizeof(key.data))) {
6196 WL_ERR(("Too long key length (%u)\n", key.len));
6197 return -EINVAL;
6198 }
6199 memcpy(key.data, params->key, key.len);
6200
6201 key.flags = WL_PRIMARY_KEY;
6202 switch (params->cipher) {
6203 case WLAN_CIPHER_SUITE_WEP40:
6204 key.algo = CRYPTO_ALGO_WEP1;
6205 val = WEP_ENABLED;
6206 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
6207 break;
6208 case WLAN_CIPHER_SUITE_WEP104:
6209 key.algo = CRYPTO_ALGO_WEP128;
6210 val = WEP_ENABLED;
6211 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
6212 break;
6213 case WLAN_CIPHER_SUITE_TKIP:
6214 key.algo = CRYPTO_ALGO_TKIP;
6215 val = TKIP_ENABLED;
6216 /* wpa_supplicant switches the third and fourth quarters of the TKIP key */
6217 if (mode == WL_MODE_BSS) {
6218 bcopy(&key.data[24], keybuf, sizeof(keybuf));
6219 bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
6220 bcopy(keybuf, &key.data[16], sizeof(keybuf));
6221 }
6222 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6223 break;
6224 case WLAN_CIPHER_SUITE_AES_CMAC:
6225 key.algo = CRYPTO_ALGO_AES_CCM;
6226 val = AES_ENABLED;
6227 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
6228 break;
6229 case WLAN_CIPHER_SUITE_CCMP:
6230 key.algo = CRYPTO_ALGO_AES_CCM;
6231 val = AES_ENABLED;
6232 WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n"));
6233 break;
6234 default:
6235 WL_ERR(("Invalid cipher (0x%x)\n", params->cipher));
6236 return -EINVAL;
6237 }
6238
6239 /* Set the new key/index */
6240 if ((mode == WL_MODE_IBSS) && (val & (TKIP_ENABLED | AES_ENABLED))) {
6241 WL_ERR(("IBSS KEY setted\n"));
6242 wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_NONE);
6243 }
6244 swap_key_from_BE(&key);
6245 if ((params->cipher == WLAN_CIPHER_SUITE_WEP40) ||
6246 (params->cipher == WLAN_CIPHER_SUITE_WEP104)) {
6247 /*
6248 * For AP role, since we are doing a wl down before bringing up AP,
6249 * the plumbed keys will be lost. So for AP once we bring up AP, we
6250 * need to plumb keys again. So buffer the keys for future use. This
6251 * is more like a WAR. If firmware later has the capability to do
6252 * interface upgrade without doing a "wl down" and "wl apsta 0", then
6253 * this will not be required.
6254 */
6255 WL_DBG(("Buffering WEP Keys \n"));
6256 memcpy(&cfg->wep_key, &key, sizeof(struct wl_wsec_key));
6257 }
6258 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
6259 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
6260 if (unlikely(err)) {
6261 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
6262 return err;
6263 }
6264
6265 exit:
6266 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
6267 if (unlikely(err)) {
6268 WL_ERR(("get wsec error (%d)\n", err));
6269 return err;
6270 }
6271
6272 wsec |= val;
6273 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
6274 if (unlikely(err)) {
6275 WL_ERR(("set wsec error (%d)\n", err));
6276 return err;
6277 }
6278
6279 return err;
6280 }
6281
6282 static s32
6283 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
6284 u8 key_idx, bool pairwise, const u8 *mac_addr)
6285 {
6286 struct wl_wsec_key key;
6287 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6288 s32 err = 0;
6289 s32 bssidx;
6290
6291 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
6292 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
6293 return BCME_ERROR;
6294 }
6295 WL_DBG(("Enter\n"));
6296
6297 #ifndef MFP
6298 if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2))
6299 return -EINVAL;
6300 #endif
6301
6302 RETURN_EIO_IF_NOT_UP(cfg);
6303 memset(&key, 0, sizeof(key));
6304
6305 key.flags = WL_PRIMARY_KEY;
6306 key.algo = CRYPTO_ALGO_OFF;
6307 key.index = (u32) key_idx;
6308
6309 WL_DBG(("key index (%d)\n", key_idx));
6310 /* Set the new key/index */
6311 swap_key_from_BE(&key);
6312 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), cfg->ioctl_buf,
6313 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
6314 if (unlikely(err)) {
6315 if (err == -EINVAL) {
6316 if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
6317 /* we ignore this key index in this case */
6318 WL_DBG(("invalid key index (%d)\n", key_idx));
6319 }
6320 } else {
6321 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
6322 }
6323 return err;
6324 }
6325 return err;
6326 }
6327
6328 static s32
6329 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
6330 u8 key_idx, bool pairwise, const u8 *mac_addr, void *cookie,
6331 void (*callback) (void *cookie, struct key_params * params))
6332 {
6333 struct key_params params;
6334 struct wl_wsec_key key;
6335 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6336 struct wl_security *sec;
6337 s32 wsec;
6338 s32 err = 0;
6339 s32 bssidx;
6340
6341 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
6342 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
6343 return BCME_ERROR;
6344 }
6345 WL_DBG(("key index (%d)\n", key_idx));
6346 RETURN_EIO_IF_NOT_UP(cfg);
6347 memset(&key, 0, sizeof(key));
6348 key.index = key_idx;
6349 swap_key_to_BE(&key);
6350 memset(&params, 0, sizeof(params));
6351 params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
6352 memcpy((void *)params.key, key.data, params.key_len);
6353
6354 err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
6355 if (unlikely(err)) {
6356 WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
6357 return err;
6358 }
6359 switch (WSEC_ENABLED(wsec)) {
6360 case WEP_ENABLED:
6361 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
6362 if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
6363 params.cipher = WLAN_CIPHER_SUITE_WEP40;
6364 WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
6365 } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
6366 params.cipher = WLAN_CIPHER_SUITE_WEP104;
6367 WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
6368 }
6369 break;
6370 case TKIP_ENABLED:
6371 params.cipher = WLAN_CIPHER_SUITE_TKIP;
6372 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6373 break;
6374 case AES_ENABLED:
6375 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
6376 WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
6377 break;
6378 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
6379 /* to connect to mixed mode AP */
6380 case (AES_ENABLED | TKIP_ENABLED): /* TKIP CCMP */
6381 params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
6382 WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
6383 break;
6384 #endif
6385 default:
6386 WL_ERR(("Invalid algo (0x%x)\n", wsec));
6387 return -EINVAL;
6388 }
6389
6390 callback(cookie, &params);
6391 return err;
6392 }
6393
6394 static s32
6395 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
6396 struct net_device *dev, u8 key_idx)
6397 {
6398 #ifdef MFP
6399 return 0;
6400 #else
6401 WL_INFORM(("Not supported\n"));
6402 return -EOPNOTSUPP;
6403 #endif /* MFP */
6404 }
6405
6406 static s32
6407 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
6408 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6409 const u8 *mac, struct station_info *sinfo)
6410 #else
6411 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
6412 u8 *mac, struct station_info *sinfo)
6413 #endif
6414 {
6415 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6416 scb_val_t scb_val;
6417 s32 rssi;
6418 s32 rate;
6419 s32 err = 0;
6420 sta_info_t *sta;
6421 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
6422 s8 eabuf[ETHER_ADDR_STR_LEN];
6423 #endif
6424 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
6425 bool fw_assoc_state = FALSE;
6426 u32 dhd_assoc_state = 0;
6427 static int err_cnt = 0;
6428
6429 RETURN_EIO_IF_NOT_UP(cfg);
6430 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP) {
6431 err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac,
6432 ETHER_ADDR_LEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
6433 if (err < 0) {
6434 WL_ERR(("GET STA INFO failed, %d\n", err));
6435 return err;
6436 }
6437 sinfo->filled = STA_INFO_BIT(INFO_INACTIVE_TIME);
6438 sta = (sta_info_t *)cfg->ioctl_buf;
6439 sta->len = dtoh16(sta->len);
6440 sta->cap = dtoh16(sta->cap);
6441 sta->flags = dtoh32(sta->flags);
6442 sta->idle = dtoh32(sta->idle);
6443 sta->in = dtoh32(sta->in);
6444 sinfo->inactive_time = sta->idle * 1000;
6445 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0))
6446 if (sta->flags & WL_STA_ASSOC) {
6447 sinfo->filled |= STA_INFO_BIT(INFO_CONNECTED_TIME);
6448 sinfo->connected_time = sta->in;
6449 }
6450 WL_INFORM(("STA %s : idle time : %d sec, connected time :%d ms\n",
6451 bcm_ether_ntoa((const struct ether_addr *)mac, eabuf), sinfo->inactive_time,
6452 sta->idle * 1000));
6453 #endif
6454 } else if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_BSS ||
6455 wl_get_mode_by_netdev(cfg, dev) == WL_MODE_IBSS) {
6456 get_pktcnt_t pktcnt;
6457 #ifdef DHD_SUPPORT_IF_CNTS
6458 wl_if_stats_t *if_stats = NULL;
6459 #endif /* DHD_SUPPORT_IF_CNTS */
6460 u8 *curmacp;
6461
6462 if (cfg->roam_offload) {
6463 struct ether_addr bssid;
6464 memset(&bssid, 0, sizeof(bssid));
6465 err = wldev_ioctl_get(dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
6466 if (err) {
6467 WL_ERR(("Failed to get current BSSID\n"));
6468 } else {
6469 if (memcmp(mac, &bssid.octet, ETHER_ADDR_LEN) != 0) {
6470 /* roaming is detected */
6471 err = wl_cfg80211_delayed_roam(cfg, dev, &bssid);
6472 if (err)
6473 WL_ERR(("Failed to handle the delayed roam, "
6474 "err=%d", err));
6475 mac = (u8 *)bssid.octet;
6476 }
6477 }
6478 }
6479 dhd_assoc_state = wl_get_drv_status(cfg, CONNECTED, dev);
6480 DHD_OS_WAKE_LOCK(dhd);
6481 fw_assoc_state = dhd_is_associated(dhd, 0, &err);
6482 DHD_OS_WAKE_UNLOCK(dhd);
6483 if (!dhd_assoc_state || !fw_assoc_state) {
6484 WL_ERR(("NOT assoc\n"));
6485 if (err == -ENODATA)
6486 return err;
6487 if (!dhd_assoc_state) {
6488 WL_TRACE_HW4(("drv state is not connected \n"));
6489 }
6490 if (!fw_assoc_state) {
6491 WL_TRACE_HW4(("fw state is not associated \n"));
6492 }
6493 /* Disconnect due to fw is not associated for FW_ASSOC_WATCHDOG_TIME ms.
6494 * 'err == 0' of dhd_is_associated() and '!fw_assoc_state'
6495 * means that BSSID is null.
6496 */
6497 if (dhd_assoc_state && !fw_assoc_state && !err) {
6498 if (!fw_assoc_watchdog_started) {
6499 fw_assoc_watchdog_ms = OSL_SYSUPTIME();
6500 fw_assoc_watchdog_started = TRUE;
6501 WL_TRACE_HW4(("fw_assoc_watchdog_started \n"));
6502 } else {
6503 if (OSL_SYSUPTIME() - fw_assoc_watchdog_ms >
6504 FW_ASSOC_WATCHDOG_TIME) {
6505 fw_assoc_watchdog_started = FALSE;
6506 err = -ENODEV;
6507 WL_TRACE_HW4(("fw is not associated for %d ms \n",
6508 (OSL_SYSUPTIME() - fw_assoc_watchdog_ms)));
6509 goto get_station_err;
6510 }
6511 }
6512 }
6513 err = -ENODEV;
6514 return err;
6515 }
6516 fw_assoc_watchdog_started = FALSE;
6517 curmacp = wl_read_prof(cfg, dev, WL_PROF_BSSID);
6518 if (memcmp(mac, curmacp, ETHER_ADDR_LEN)) {
6519 WL_ERR(("Wrong Mac address: "MACDBG" != "MACDBG"\n",
6520 MAC2STRDBG(mac), MAC2STRDBG(curmacp)));
6521 }
6522
6523 /* Report the current tx rate */
6524 rate = 0;
6525 err = wldev_ioctl_get(dev, WLC_GET_RATE, &rate, sizeof(rate));
6526 if (err) {
6527 WL_ERR(("Could not get rate (%d)\n", err));
6528 } else {
6529 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
6530 int rxpktglom;
6531 #endif
6532 rate = dtoh32(rate);
6533 sinfo->filled |= STA_INFO_BIT(INFO_TX_BITRATE);
6534 sinfo->txrate.legacy = rate * 5;
6535 WL_DBG(("Rate %d Mbps\n", (rate / 2)));
6536 #if defined(USE_DYNAMIC_MAXPKT_RXGLOM)
6537 rxpktglom = ((rate/2) > 150) ? 20 : 10;
6538
6539 if (maxrxpktglom != rxpktglom) {
6540 maxrxpktglom = rxpktglom;
6541 WL_DBG(("Rate %d Mbps, update bus:maxtxpktglom=%d\n", (rate/2),
6542 maxrxpktglom));
6543 err = wldev_iovar_setbuf(dev, "bus:maxtxpktglom",
6544 (char*)&maxrxpktglom, 4, cfg->ioctl_buf,
6545 WLC_IOCTL_MAXLEN, NULL);
6546 if (err < 0) {
6547 WL_ERR(("set bus:maxtxpktglom failed, %d\n", err));
6548 }
6549 }
6550 #endif
6551 }
6552
6553 memset(&scb_val, 0, sizeof(scb_val));
6554 scb_val.val = 0;
6555 err = wldev_ioctl_get(dev, WLC_GET_RSSI, &scb_val,
6556 sizeof(scb_val_t));
6557 if (err) {
6558 WL_ERR(("Could not get rssi (%d)\n", err));
6559 goto get_station_err;
6560 }
6561 rssi = dtoh32(scb_val.val);
6562 #if defined(RSSIAVG)
6563 err = wl_update_connected_rssi_cache(dev, &cfg->g_connected_rssi_cache_ctrl, &rssi);
6564 if (err) {
6565 WL_ERR(("Could not get rssi (%d)\n", err));
6566 goto get_station_err;
6567 }
6568 wl_delete_dirty_rssi_cache(&cfg->g_connected_rssi_cache_ctrl);
6569 wl_reset_rssi_cache(&cfg->g_connected_rssi_cache_ctrl);
6570 #endif
6571 #if defined(RSSIOFFSET)
6572 rssi = wl_update_rssi_offset(dev, rssi);
6573 #endif
6574 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
6575 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
6576 rssi = MIN(rssi, RSSI_MAXVAL);
6577 #endif
6578 sinfo->filled |= STA_INFO_BIT(INFO_SIGNAL);
6579 sinfo->signal = rssi;
6580 WL_DBG(("RSSI %d dBm\n", rssi));
6581
6582 #ifdef DHD_SUPPORT_IF_CNTS
6583 if ((if_stats = kmalloc(sizeof(*if_stats), GFP_KERNEL)) == NULL) {
6584 WL_ERR(("%s(%d): kmalloc failed\n", __FUNCTION__, __LINE__));
6585 goto error;
6586 }
6587 memset(if_stats, 0, sizeof(*if_stats));
6588
6589 err = wldev_iovar_getbuf(dev, "if_counters", NULL, 0,
6590 (char *)if_stats, sizeof(*if_stats), NULL);
6591 if (!err) {
6592 sinfo->rx_packets = (uint32)dtoh64(if_stats->rxframe);
6593 sinfo->rx_dropped_misc = 0;
6594 sinfo->tx_packets = (uint32)dtoh64(if_stats->txfrmsnt);
6595 sinfo->tx_failed = (uint32)dtoh64(if_stats->txnobuf) +
6596 (uint32)dtoh64(if_stats->txrunt) +
6597 (uint32)dtoh64(if_stats->txfail);
6598 } else {
6599 // WL_ERR(("%s: if_counters not supported ret=%d\n",
6600 // __FUNCTION__, err));
6601 #endif /* DHD_SUPPORT_IF_CNTS */
6602
6603 err = wldev_ioctl_get(dev, WLC_GET_PKTCNTS, &pktcnt,
6604 sizeof(pktcnt));
6605 if (err) {
6606 WL_ERR(("Could not get WLC_GET_PKTCNTS (%d)\n", err));
6607 goto get_station_err;
6608 }
6609 sinfo->rx_packets = pktcnt.rx_good_pkt;
6610 sinfo->rx_dropped_misc = pktcnt.rx_bad_pkt;
6611 sinfo->tx_packets = pktcnt.tx_good_pkt;
6612 sinfo->tx_failed = pktcnt.tx_bad_pkt;
6613 #ifdef DHD_SUPPORT_IF_CNTS
6614 }
6615 #endif /* DHD_SUPPORT_IF_CNTS */
6616
6617 sinfo->filled |= (STA_INFO_BIT(INFO_RX_PACKETS) |
6618 STA_INFO_BIT(INFO_RX_DROP_MISC) |
6619 STA_INFO_BIT(INFO_TX_PACKETS) |
6620 STA_INFO_BIT(INFO_TX_FAILED));
6621
6622 get_station_err:
6623 if (err)
6624 err_cnt++;
6625 else
6626 err_cnt = 0;
6627 if (err_cnt >= 3 && (err != -ENODATA)) {
6628 /* Disconnect due to zero BSSID or error to get RSSI */
6629 scb_val_t scbval;
6630 scbval.val = htod32(DOT11_RC_DISASSOC_LEAVING);
6631 err = wldev_ioctl_set(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
6632 if (unlikely(err)) {
6633 WL_ERR(("disassoc error (%d)\n", err));
6634 }
6635
6636 WL_ERR(("force cfg80211_disconnected: %d\n", err));
6637 wl_clr_drv_status(cfg, CONNECTED, dev);
6638 CFG80211_DISCONNECTED(dev, 0, NULL, 0, false, GFP_KERNEL);
6639 wl_link_down(cfg);
6640 }
6641 #ifdef DHD_SUPPORT_IF_CNTS
6642 error:
6643 if (if_stats) {
6644 kfree(if_stats);
6645 }
6646 #endif /* DHD_SUPPORT_IF_CNTS */
6647 }
6648 else {
6649 WL_ERR(("Invalid device mode %d\n", wl_get_mode_by_netdev(cfg, dev)));
6650 }
6651
6652 return err;
6653 }
6654
6655 static s32
6656 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
6657 bool enabled, s32 timeout)
6658 {
6659 s32 pm;
6660 s32 err = 0;
6661 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6662 struct net_info *_net_info = wl_get_netinfo_by_netdev(cfg, dev);
6663 #ifdef RTT_SUPPORT
6664 rtt_status_info_t *rtt_status;
6665 #endif /* RTT_SUPPORT */
6666 dhd_pub_t *dhd = cfg->pub;
6667
6668 RETURN_EIO_IF_NOT_UP(cfg);
6669 WL_DBG(("Enter\n"));
6670 if (cfg->p2p_net == dev || _net_info == NULL ||
6671 !wl_get_drv_status(cfg, CONNECTED, dev) ||
6672 (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_BSS &&
6673 wl_get_mode_by_netdev(cfg, dev) != WL_MODE_IBSS)) {
6674 return err;
6675 }
6676
6677 /* Enlarge pm_enable_work */
6678 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_LONG);
6679
6680 pm = enabled ? PM_FAST : PM_OFF;
6681 if (_net_info->pm_block) {
6682 WL_ERR(("%s:Do not enable the power save for pm_block %d\n",
6683 dev->name, _net_info->pm_block));
6684 pm = PM_OFF;
6685 }
6686 if (enabled && dhd_conf_get_pm(dhd) >= 0)
6687 pm = dhd_conf_get_pm(dhd);
6688 pm = htod32(pm);
6689 WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled")));
6690 #ifdef RTT_SUPPORT
6691 rtt_status = GET_RTTSTATE(dhd);
6692 if (rtt_status->status != RTT_ENABLED) {
6693 #endif /* RTT_SUPPORT */
6694 err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm));
6695 if (unlikely(err)) {
6696 if (err == -ENODEV)
6697 WL_DBG(("net_device is not ready yet\n"));
6698 else
6699 WL_ERR(("error (%d)\n", err));
6700 return err;
6701 }
6702 #ifdef RTT_SUPPORT
6703 }
6704 #endif /* RTT_SUPPORT */
6705 wl_cfg80211_update_power_mode(dev);
6706 return err;
6707 }
6708
6709 void wl_cfg80211_update_power_mode(struct net_device *dev)
6710 {
6711 int err, pm = -1;
6712
6713 err = wldev_ioctl_get(dev, WLC_GET_PM, &pm, sizeof(pm));
6714 if (err)
6715 WL_ERR(("%s:error (%d)\n", __FUNCTION__, err));
6716 else if (pm != -1 && dev->ieee80211_ptr)
6717 dev->ieee80211_ptr->ps = (pm == PM_OFF) ? false : true;
6718 }
6719
6720 void wl_cfg80211_set_passive_scan(struct net_device *dev, char *command)
6721 {
6722 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6723
6724 if (strcmp(command, "SCAN-ACTIVE") == 0) {
6725 cfg->active_scan = 1;
6726 } else if (strcmp(command, "SCAN-PASSIVE") == 0) {
6727 cfg->active_scan = 0;
6728 } else
6729 WL_ERR(("Unknown command \n"));
6730 }
6731
6732 static __used u32 wl_find_msb(u16 bit16)
6733 {
6734 u32 ret = 0;
6735
6736 if (bit16 & 0xff00) {
6737 ret += 8;
6738 bit16 >>= 8;
6739 }
6740
6741 if (bit16 & 0xf0) {
6742 ret += 4;
6743 bit16 >>= 4;
6744 }
6745
6746 if (bit16 & 0xc) {
6747 ret += 2;
6748 bit16 >>= 2;
6749 }
6750
6751 if (bit16 & 2)
6752 ret += bit16 & 2;
6753 else if (bit16)
6754 ret += bit16;
6755
6756 return ret;
6757 }
6758
6759 static s32 wl_cfg80211_resume(struct wiphy *wiphy)
6760 {
6761 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6762 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
6763 s32 err = BCME_OK;
6764
6765 if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
6766 WL_INFORM(("device is not ready\n"));
6767 return err;
6768 }
6769
6770
6771 return err;
6772 }
6773
6774
6775 static s32
6776 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
6777 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow)
6778 #else
6779 wl_cfg80211_suspend(struct wiphy *wiphy)
6780 #endif /* KERNEL_VERSION(2, 6, 39) || WL_COMPAT_WIRELES */
6781 {
6782 s32 err = BCME_OK;
6783 #ifdef DHD_CLEAR_ON_SUSPEND
6784 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6785 struct net_info *iter, *next;
6786 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
6787 unsigned long flags;
6788 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
6789 struct cfg80211_scan_info info;
6790 #endif
6791
6792 if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
6793 WL_INFORM(("device is not ready : status (%d)\n",
6794 (int)cfg->status));
6795 return err;
6796 }
6797 for_each_ndev(cfg, iter, next) {
6798 /* p2p discovery iface doesn't have a ndev associated with it (for kernel > 3.8) */
6799 if (iter->ndev)
6800 wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
6801 }
6802 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
6803 if (cfg->scan_request) {
6804 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
6805 info.aborted = true;
6806 cfg80211_scan_done(cfg->scan_request, &info);
6807 #else
6808 cfg80211_scan_done(cfg->scan_request, true);
6809 #endif
6810 cfg->scan_request = NULL;
6811 }
6812 for_each_ndev(cfg, iter, next) {
6813 if (iter->ndev) {
6814 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
6815 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
6816 }
6817 }
6818 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
6819 for_each_ndev(cfg, iter, next) {
6820 if (iter->ndev) {
6821 if (wl_get_drv_status(cfg, CONNECTING, iter->ndev)) {
6822 wl_bss_connect_done(cfg, iter->ndev, NULL, NULL, false);
6823 }
6824 }
6825 }
6826 #endif /* DHD_CLEAR_ON_SUSPEND */
6827
6828
6829 return err;
6830 }
6831
6832 static s32
6833 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
6834 s32 err)
6835 {
6836 int i, j;
6837 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6838 struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
6839
6840 if (!pmk_list) {
6841 printf("pmk_list is NULL\n");
6842 return -EINVAL;
6843 }
6844 /* pmk list is supported only for STA interface i.e. primary interface
6845 * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
6846 */
6847 if (primary_dev != dev) {
6848 WL_INFORM(("Not supporting Flushing pmklist on virtual"
6849 " interfaces than primary interface\n"));
6850 return err;
6851 }
6852
6853 WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
6854 for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
6855 WL_DBG(("PMKID[%d]: %pM =\n", i,
6856 &pmk_list->pmkids.pmkid[i].BSSID));
6857 for (j = 0; j < WPA2_PMKID_LEN; j++) {
6858 WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]));
6859 }
6860 }
6861 if (likely(!err)) {
6862 err = wldev_iovar_setbuf(dev, "pmkid_info", (char *)pmk_list,
6863 sizeof(*pmk_list), cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
6864 }
6865
6866 return err;
6867 }
6868
6869 static s32
6870 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
6871 struct cfg80211_pmksa *pmksa)
6872 {
6873 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6874 s32 err = 0;
6875 int i;
6876
6877 RETURN_EIO_IF_NOT_UP(cfg);
6878 for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
6879 if (!memcmp(pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
6880 ETHER_ADDR_LEN))
6881 break;
6882 if (i < WL_NUM_PMKIDS_MAX) {
6883 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
6884 ETHER_ADDR_LEN);
6885 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
6886 WPA2_PMKID_LEN);
6887 if (i == cfg->pmk_list->pmkids.npmkid)
6888 cfg->pmk_list->pmkids.npmkid++;
6889 } else {
6890 err = -EINVAL;
6891 }
6892 WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
6893 &cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].BSSID));
6894 for (i = 0; i < WPA2_PMKID_LEN; i++) {
6895 WL_DBG(("%02x\n",
6896 cfg->pmk_list->pmkids.pmkid[cfg->pmk_list->pmkids.npmkid - 1].
6897 PMKID[i]));
6898 }
6899
6900 err = wl_update_pmklist(dev, cfg->pmk_list, err);
6901
6902 return err;
6903 }
6904
6905 static s32
6906 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
6907 struct cfg80211_pmksa *pmksa)
6908 {
6909 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6910
6911 struct _pmkid_list pmkid = {.npmkid = 0};
6912 s32 err = 0;
6913 int i;
6914
6915 RETURN_EIO_IF_NOT_UP(cfg);
6916 memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN);
6917 memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
6918
6919 WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
6920 &pmkid.pmkid[0].BSSID));
6921 for (i = 0; i < WPA2_PMKID_LEN; i++) {
6922 WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i]));
6923 }
6924
6925 for (i = 0; i < cfg->pmk_list->pmkids.npmkid; i++)
6926 if (!memcmp
6927 (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID,
6928 ETHER_ADDR_LEN))
6929 break;
6930
6931 if ((cfg->pmk_list->pmkids.npmkid > 0) &&
6932 (i < cfg->pmk_list->pmkids.npmkid)) {
6933 memset(&cfg->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t));
6934 for (; i < (cfg->pmk_list->pmkids.npmkid - 1); i++) {
6935 memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID,
6936 &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID,
6937 ETHER_ADDR_LEN);
6938 memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID,
6939 &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID,
6940 WPA2_PMKID_LEN);
6941 }
6942 cfg->pmk_list->pmkids.npmkid--;
6943 } else {
6944 err = -EINVAL;
6945 }
6946
6947 err = wl_update_pmklist(dev, cfg->pmk_list, err);
6948
6949 return err;
6950
6951 }
6952
6953 static s32
6954 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
6955 {
6956 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
6957 s32 err = 0;
6958 RETURN_EIO_IF_NOT_UP(cfg);
6959 memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list));
6960 err = wl_update_pmklist(dev, cfg->pmk_list, err);
6961 return err;
6962 }
6963
6964 static wl_scan_params_t *
6965 wl_cfg80211_scan_alloc_params(struct bcm_cfg80211 *cfg, int channel, int nprobes,
6966 int *out_params_size)
6967 {
6968 wl_scan_params_t *params;
6969 int params_size;
6970 int num_chans;
6971 int bssidx = 0;
6972
6973 *out_params_size = 0;
6974
6975 /* Our scan params only need space for 1 channel and 0 ssids */
6976 params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16);
6977 params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL);
6978 if (params == NULL) {
6979 WL_ERR(("mem alloc failed (%d bytes)\n", params_size));
6980 return params;
6981 }
6982 memset(params, 0, params_size);
6983 params->nprobes = nprobes;
6984
6985 num_chans = (channel == 0) ? 0 : 1;
6986
6987 memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
6988 params->bss_type = DOT11_BSSTYPE_ANY;
6989 params->scan_type = DOT11_SCANTYPE_ACTIVE;
6990 params->nprobes = htod32(1);
6991 params->active_time = htod32(-1);
6992 params->passive_time = htod32(-1);
6993 params->home_time = htod32(10);
6994 if (channel == -1)
6995 params->channel_list[0] = htodchanspec(channel);
6996 else
6997 params->channel_list[0] = wl_ch_host_to_driver(cfg, bssidx, channel);
6998
6999 /* Our scan params have 1 channel and 0 ssids */
7000 params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
7001 (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
7002
7003 *out_params_size = params_size; /* rtn size to the caller */
7004 return params;
7005 }
7006
7007 static s32
7008 #if defined(WL_CFG80211_P2P_DEV_IF)
7009 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
7010 struct ieee80211_channel *channel, unsigned int duration, u64 *cookie)
7011 #else
7012 wl_cfg80211_remain_on_channel(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
7013 struct ieee80211_channel * channel,
7014 enum nl80211_channel_type channel_type,
7015 unsigned int duration, u64 *cookie)
7016 #endif /* WL_CFG80211_P2P_DEV_IF */
7017 {
7018 s32 target_channel;
7019 u32 id;
7020 s32 err = BCME_OK;
7021 struct ether_addr primary_mac;
7022 struct net_device *ndev = NULL;
7023 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7024
7025 #ifdef DHD_IFDEBUG
7026 PRINT_WDEV_INFO(cfgdev);
7027 #endif /* DHD_IFDEBUG */
7028
7029 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
7030
7031 WL_DBG(("Enter, channel: %d, duration ms (%d) SCANNING ?? %s \n",
7032 ieee80211_frequency_to_channel(channel->center_freq),
7033 duration, (wl_get_drv_status(cfg, SCANNING, ndev)) ? "YES":"NO"));
7034
7035 if (!cfg->p2p) {
7036 WL_ERR(("cfg->p2p is not initialized\n"));
7037 err = BCME_ERROR;
7038 goto exit;
7039 }
7040
7041 #ifdef P2P_LISTEN_OFFLOADING
7042 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
7043 WL_ERR(("P2P_FIND: Discovery offload is in progress\n"));
7044 return -EAGAIN;
7045 }
7046 #endif /* P2P_LISTEN_OFFLOADING */
7047
7048 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7049 if (wl_get_drv_status_all(cfg, SCANNING)) {
7050 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
7051 }
7052 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7053
7054 target_channel = ieee80211_frequency_to_channel(channel->center_freq);
7055 memcpy(&cfg->remain_on_chan, channel, sizeof(struct ieee80211_channel));
7056 #if defined(WL_ENABLE_P2P_IF)
7057 cfg->remain_on_chan_type = channel_type;
7058 #endif /* WL_ENABLE_P2P_IF */
7059 id = ++cfg->last_roc_id;
7060 if (id == 0)
7061 id = ++cfg->last_roc_id;
7062 *cookie = id;
7063
7064 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7065 if (wl_get_drv_status(cfg, SCANNING, ndev)) {
7066 struct timer_list *_timer;
7067 WL_DBG(("scan is running. go to fake listen state\n"));
7068
7069 if (duration > LONG_LISTEN_TIME) {
7070 wl_cfg80211_scan_abort(cfg);
7071 } else {
7072 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
7073
7074 if (timer_pending(&cfg->p2p->listen_timer)) {
7075 WL_DBG(("cancel current listen timer \n"));
7076 del_timer_sync(&cfg->p2p->listen_timer);
7077 }
7078
7079 _timer = &cfg->p2p->listen_timer;
7080 wl_clr_p2p_status(cfg, LISTEN_EXPIRED);
7081
7082 INIT_TIMER(_timer, wl_cfgp2p_listen_expired, duration, 0);
7083
7084 err = BCME_OK;
7085 goto exit;
7086 }
7087 }
7088 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7089
7090 #ifdef WL_CFG80211_SYNC_GON
7091 if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
7092 /* do not enter listen mode again if we are in listen mode already for next af.
7093 * remain on channel completion will be returned by waiting next af completion.
7094 */
7095 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7096 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
7097 #else
7098 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
7099 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7100 goto exit;
7101 }
7102 #endif /* WL_CFG80211_SYNC_GON */
7103 if (cfg->p2p && !cfg->p2p->on) {
7104 /* In case of p2p_listen command, supplicant send remain_on_channel
7105 * without turning on P2P
7106 */
7107 get_primary_mac(cfg, &primary_mac);
7108 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
7109 p2p_on(cfg) = true;
7110 }
7111
7112 if (p2p_is_on(cfg)) {
7113 err = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
7114 if (unlikely(err)) {
7115 goto exit;
7116 }
7117 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7118 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
7119 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7120 err = wl_cfgp2p_discover_listen(cfg, target_channel, duration);
7121
7122 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7123 if (err == BCME_OK) {
7124 wl_set_drv_status(cfg, REMAINING_ON_CHANNEL, ndev);
7125 } else {
7126 /* if failed, firmware may be internal scanning state.
7127 * so other scan request shall not abort it
7128 */
7129 wl_set_drv_status(cfg, FAKE_REMAINING_ON_CHANNEL, ndev);
7130 }
7131 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7132 /* WAR: set err = ok to prevent cookie mismatch in wpa_supplicant
7133 * and expire timer will send a completion to the upper layer
7134 */
7135 err = BCME_OK;
7136 }
7137
7138 exit:
7139 if (err == BCME_OK) {
7140 WL_INFORM(("Success\n"));
7141 #if defined(WL_CFG80211_P2P_DEV_IF)
7142 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
7143 duration, GFP_KERNEL);
7144 #else
7145 cfg80211_ready_on_channel(cfgdev, *cookie, channel,
7146 channel_type, duration, GFP_KERNEL);
7147 #endif /* WL_CFG80211_P2P_DEV_IF */
7148 } else {
7149 WL_ERR(("Fail to Set (err=%d cookie:%llu)\n", err, *cookie));
7150 }
7151 return err;
7152 }
7153
7154 static s32
7155 wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy,
7156 bcm_struct_cfgdev *cfgdev, u64 cookie)
7157 {
7158 s32 err = 0;
7159
7160 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7161
7162 #ifdef P2PLISTEN_AP_SAMECHN
7163 struct net_device *dev;
7164 #endif /* P2PLISTEN_AP_SAMECHN */
7165
7166 RETURN_EIO_IF_NOT_UP(cfg);
7167
7168 #ifdef DHD_IFDEBUG
7169 PRINT_WDEV_INFO(cfgdev);
7170 #endif /* DHD_IFDEBUG */
7171
7172 #if defined(WL_CFG80211_P2P_DEV_IF)
7173 if (cfgdev->iftype == NL80211_IFTYPE_P2P_DEVICE) {
7174 WL_DBG((" enter ) on P2P dedicated discover interface\n"));
7175 }
7176 #else
7177 WL_DBG((" enter ) netdev_ifidx: %d \n", cfgdev->ifindex));
7178 #endif /* WL_CFG80211_P2P_DEV_IF */
7179
7180 #ifdef P2PLISTEN_AP_SAMECHN
7181 if (cfg && cfg->p2p_resp_apchn_status) {
7182 dev = bcmcfg_to_prmry_ndev(cfg);
7183 wl_cfg80211_set_p2p_resp_ap_chn(dev, 0);
7184 cfg->p2p_resp_apchn_status = false;
7185 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
7186 }
7187 #endif /* P2PLISTEN_AP_SAMECHN */
7188
7189 if (cfg->last_roc_id == cookie) {
7190 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
7191 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
7192 } else {
7193 WL_ERR(("%s : ignore, request cookie(%llu) is not matched. (cur : %llu)\n",
7194 __FUNCTION__, cookie, cfg->last_roc_id));
7195 }
7196
7197 return err;
7198 }
7199
7200 static void
7201 wl_cfg80211_afx_handler(struct work_struct *work)
7202 {
7203 struct afx_hdl *afx_instance;
7204 struct bcm_cfg80211 *cfg;
7205 s32 ret = BCME_OK;
7206
7207 BCM_SET_CONTAINER_OF(afx_instance, work, struct afx_hdl, work);
7208 if (!afx_instance) {
7209 WL_ERR(("afx_instance is NULL\n"));
7210 return;
7211 }
7212 cfg = wl_get_cfg(afx_instance->dev);
7213 if (afx_instance) {
7214 if (cfg->afx_hdl->is_active) {
7215 if (cfg->afx_hdl->is_listen && cfg->afx_hdl->my_listen_chan) {
7216 ret = wl_cfgp2p_discover_listen(cfg, cfg->afx_hdl->my_listen_chan,
7217 (100 * (1 + (RANDOM32() % 3)))); /* 100ms ~ 300ms */
7218 } else {
7219 ret = wl_cfgp2p_act_frm_search(cfg, cfg->afx_hdl->dev,
7220 cfg->afx_hdl->bssidx, cfg->afx_hdl->peer_listen_chan,
7221 NULL);
7222 }
7223 if (unlikely(ret != BCME_OK)) {
7224 WL_ERR(("ERROR occurred! returned value is (%d)\n", ret));
7225 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL))
7226 complete(&cfg->act_frm_scan);
7227 }
7228 }
7229 }
7230 }
7231
7232 static s32
7233 wl_cfg80211_af_searching_channel(struct bcm_cfg80211 *cfg, struct net_device *dev)
7234 {
7235 u32 max_retry = WL_CHANNEL_SYNC_RETRY;
7236 bool is_p2p_gas = false;
7237
7238 if (dev == NULL)
7239 return -1;
7240
7241 WL_DBG((" enter ) \n"));
7242
7243 wl_set_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
7244 cfg->afx_hdl->is_active = TRUE;
7245
7246 if (cfg->afx_hdl->pending_tx_act_frm) {
7247 wl_action_frame_t *action_frame;
7248 action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
7249 if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len))
7250 is_p2p_gas = true;
7251 }
7252
7253 /* Loop to wait until we find a peer's channel or the
7254 * pending action frame tx is cancelled.
7255 */
7256 while ((cfg->afx_hdl->retry < max_retry) &&
7257 (cfg->afx_hdl->peer_chan == WL_INVALID)) {
7258 cfg->afx_hdl->is_listen = FALSE;
7259 wl_set_drv_status(cfg, SCANNING, dev);
7260 WL_DBG(("Scheduling the action frame for sending.. retry %d\n",
7261 cfg->afx_hdl->retry));
7262 /* search peer on peer's listen channel */
7263 schedule_work(&cfg->afx_hdl->work);
7264 wait_for_completion_timeout(&cfg->act_frm_scan,
7265 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
7266
7267 if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
7268 !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
7269 break;
7270
7271 if (is_p2p_gas)
7272 break;
7273
7274 if (cfg->afx_hdl->my_listen_chan) {
7275 WL_DBG(("Scheduling Listen peer in my listen channel = %d\n",
7276 cfg->afx_hdl->my_listen_chan));
7277 /* listen on my listen channel */
7278 cfg->afx_hdl->is_listen = TRUE;
7279 schedule_work(&cfg->afx_hdl->work);
7280 wait_for_completion_timeout(&cfg->act_frm_scan,
7281 msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX));
7282 }
7283 if ((cfg->afx_hdl->peer_chan != WL_INVALID) ||
7284 !(wl_get_drv_status(cfg, FINDING_COMMON_CHANNEL, dev)))
7285 break;
7286
7287 cfg->afx_hdl->retry++;
7288
7289 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
7290 }
7291
7292 cfg->afx_hdl->is_active = FALSE;
7293
7294 wl_clr_drv_status(cfg, SCANNING, dev);
7295 wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, dev);
7296
7297 return (cfg->afx_hdl->peer_chan);
7298 }
7299
7300 struct p2p_config_af_params {
7301 s32 max_tx_retry; /* max tx retry count if tx no ack */
7302 #ifdef WL_CFG80211_SYNC_GON
7303 bool extra_listen;
7304 #endif
7305 bool search_channel; /* 1: search peer's channel to send af */
7306 };
7307
7308 static s32
7309 wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy,
7310 wl_action_frame_t *action_frame, wl_af_params_t *af_params,
7311 struct p2p_config_af_params *config_af_params)
7312 {
7313 s32 err = BCME_OK;
7314 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7315 wifi_p2p_pub_act_frame_t *act_frm =
7316 (wifi_p2p_pub_act_frame_t *) (action_frame->data);
7317
7318 /* initialize default value */
7319 #ifdef WL_CFG80211_SYNC_GON
7320 config_af_params->extra_listen = true;
7321 #endif
7322 config_af_params->search_channel = false;
7323 config_af_params->max_tx_retry = WL_AF_TX_MAX_RETRY;
7324 cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
7325
7326 switch (act_frm->subtype) {
7327 case P2P_PAF_GON_REQ: {
7328 WL_DBG(("P2P: GO_NEG_PHASE status set \n"));
7329 wl_set_p2p_status(cfg, GO_NEG_PHASE);
7330
7331 config_af_params->search_channel = true;
7332 cfg->next_af_subtype = act_frm->subtype + 1;
7333
7334 /* increase dwell time to wait for RESP frame */
7335 af_params->dwell_time = WL_MED_DWELL_TIME;
7336
7337 break;
7338 }
7339 case P2P_PAF_GON_RSP: {
7340 cfg->next_af_subtype = act_frm->subtype + 1;
7341 /* increase dwell time to wait for CONF frame */
7342 af_params->dwell_time = WL_MED_DWELL_TIME + 100;
7343 break;
7344 }
7345 case P2P_PAF_GON_CONF: {
7346 /* If we reached till GO Neg confirmation reset the filter */
7347 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
7348 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
7349
7350 /* minimize dwell time */
7351 af_params->dwell_time = WL_MIN_DWELL_TIME;
7352
7353 #ifdef WL_CFG80211_SYNC_GON
7354 config_af_params->extra_listen = false;
7355 #endif /* WL_CFG80211_SYNC_GON */
7356 break;
7357 }
7358 case P2P_PAF_INVITE_REQ: {
7359 config_af_params->search_channel = true;
7360 cfg->next_af_subtype = act_frm->subtype + 1;
7361
7362 /* increase dwell time */
7363 af_params->dwell_time = WL_MED_DWELL_TIME;
7364 break;
7365 }
7366 case P2P_PAF_INVITE_RSP:
7367 /* minimize dwell time */
7368 af_params->dwell_time = WL_MIN_DWELL_TIME;
7369 #ifdef WL_CFG80211_SYNC_GON
7370 config_af_params->extra_listen = false;
7371 #endif /* WL_CFG80211_SYNC_GON */
7372 break;
7373 case P2P_PAF_DEVDIS_REQ: {
7374 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
7375 action_frame->len)) {
7376 config_af_params->search_channel = true;
7377 }
7378
7379 cfg->next_af_subtype = act_frm->subtype + 1;
7380 /* maximize dwell time to wait for RESP frame */
7381 af_params->dwell_time = WL_LONG_DWELL_TIME;
7382 break;
7383 }
7384 case P2P_PAF_DEVDIS_RSP:
7385 /* minimize dwell time */
7386 af_params->dwell_time = WL_MIN_DWELL_TIME;
7387 #ifdef WL_CFG80211_SYNC_GON
7388 config_af_params->extra_listen = false;
7389 #endif /* WL_CFG80211_SYNC_GON */
7390 break;
7391 case P2P_PAF_PROVDIS_REQ: {
7392 if (IS_ACTPUB_WITHOUT_GROUP_ID(&act_frm->elts[0],
7393 action_frame->len)) {
7394 config_af_params->search_channel = true;
7395 }
7396
7397 cfg->next_af_subtype = act_frm->subtype + 1;
7398 /* increase dwell time to wait for RESP frame */
7399 af_params->dwell_time = WL_MED_DWELL_TIME;
7400 break;
7401 }
7402 case P2P_PAF_PROVDIS_RSP: {
7403 cfg->next_af_subtype = P2P_PAF_GON_REQ;
7404 af_params->dwell_time = WL_MED_DWELL_TIME;
7405 #ifdef WL_CFG80211_SYNC_GON
7406 config_af_params->extra_listen = false;
7407 #endif /* WL_CFG80211_SYNC_GON */
7408 break;
7409 }
7410 default:
7411 WL_DBG(("Unknown p2p pub act frame subtype: %d\n",
7412 act_frm->subtype));
7413 err = BCME_BADARG;
7414 }
7415 return err;
7416 }
7417
7418 #ifdef WL11U
7419 static bool
7420 wl_cfg80211_check_DFS_channel(struct bcm_cfg80211 *cfg, wl_af_params_t *af_params,
7421 void *frame, u16 frame_len)
7422 {
7423 struct wl_scan_results *bss_list;
7424 struct wl_bss_info *bi = NULL;
7425 bool result = false;
7426 s32 i;
7427 chanspec_t chanspec;
7428
7429 /* If DFS channel is 52~148, check to block it or not */
7430 if (af_params &&
7431 (af_params->channel >= 52 && af_params->channel <= 148)) {
7432 if (!wl_cfgp2p_is_p2p_action(frame, frame_len)) {
7433 bss_list = cfg->bss_list;
7434 bi = next_bss(bss_list, bi);
7435 for_each_bss(bss_list, bi, i) {
7436 chanspec = wl_chspec_driver_to_host(bi->chanspec);
7437 if (CHSPEC_IS5G(chanspec) &&
7438 ((bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(chanspec))
7439 == af_params->channel)) {
7440 result = true; /* do not block the action frame */
7441 break;
7442 }
7443 }
7444 }
7445 }
7446 else {
7447 result = true;
7448 }
7449
7450 WL_DBG(("result=%s", result?"true":"false"));
7451 return result;
7452 }
7453 #endif /* WL11U */
7454 static bool
7455 wl_cfg80211_check_dwell_overflow(int32 requested_dwell, ulong dwell_jiffies)
7456 {
7457 if ((requested_dwell & CUSTOM_RETRY_MASK) &&
7458 (jiffies_to_msecs(jiffies - dwell_jiffies) >
7459 (requested_dwell & ~CUSTOM_RETRY_MASK))) {
7460 WL_ERR(("Action frame TX retry time over dwell time!\n"));
7461 return true;
7462 }
7463 return false;
7464 }
7465
7466 static bool
7467 wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev,
7468 bcm_struct_cfgdev *cfgdev, wl_af_params_t *af_params,
7469 wl_action_frame_t *action_frame, u16 action_frame_len, s32 bssidx)
7470 {
7471 #ifdef WL11U
7472 struct net_device *ndev = NULL;
7473 #endif /* WL11U */
7474 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7475 bool ack = false;
7476 u8 category, action;
7477 s32 tx_retry;
7478 struct p2p_config_af_params config_af_params;
7479 struct net_info *netinfo;
7480 #ifdef VSDB
7481 ulong off_chan_started_jiffies = 0;
7482 #endif
7483 ulong dwell_jiffies = 0;
7484 bool dwell_overflow = false;
7485 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
7486 bool miss_gon_cfm = false;
7487
7488 int32 requested_dwell = af_params->dwell_time;
7489
7490 /* Add the default dwell time
7491 * Dwell time to stay off-channel to wait for a response action frame
7492 * after transmitting an GO Negotiation action frame
7493 */
7494 af_params->dwell_time = WL_DWELL_TIME;
7495
7496 #ifdef WL11U
7497 #if defined(WL_CFG80211_P2P_DEV_IF)
7498 ndev = dev;
7499 #else
7500 ndev = ndev_to_cfgdev(cfgdev);
7501 #endif /* WL_CFG80211_P2P_DEV_IF */
7502 #endif /* WL11U */
7503
7504 category = action_frame->data[DOT11_ACTION_CAT_OFF];
7505 action = action_frame->data[DOT11_ACTION_ACT_OFF];
7506
7507 /* initialize variables */
7508 tx_retry = 0;
7509 cfg->next_af_subtype = P2P_PAF_SUBTYPE_INVALID;
7510 config_af_params.max_tx_retry = WL_AF_TX_MAX_RETRY;
7511 config_af_params.search_channel = false;
7512 #ifdef WL_CFG80211_SYNC_GON
7513 config_af_params.extra_listen = false;
7514 #endif
7515
7516 /* config parameters */
7517 /* Public Action Frame Process - DOT11_ACTION_CAT_PUBLIC */
7518 if (category == DOT11_ACTION_CAT_PUBLIC) {
7519 if ((action == P2P_PUB_AF_ACTION) &&
7520 (action_frame_len >= sizeof(wifi_p2p_pub_act_frame_t))) {
7521 /* p2p public action frame process */
7522 if (BCME_OK != wl_cfg80211_config_p2p_pub_af_tx(wiphy,
7523 action_frame, af_params, &config_af_params)) {
7524 WL_DBG(("Unknown subtype.\n"));
7525 }
7526
7527 } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) {
7528 /* service discovery process */
7529 if (action == P2PSD_ACTION_ID_GAS_IREQ ||
7530 action == P2PSD_ACTION_ID_GAS_CREQ) {
7531 /* configure service discovery query frame */
7532
7533 config_af_params.search_channel = true;
7534
7535 /* save next af suptype to cancel remained dwell time */
7536 cfg->next_af_subtype = action + 1;
7537
7538 af_params->dwell_time = WL_MED_DWELL_TIME;
7539 if (requested_dwell & CUSTOM_RETRY_MASK) {
7540 config_af_params.max_tx_retry =
7541 (requested_dwell & CUSTOM_RETRY_MASK) >> 24;
7542 af_params->dwell_time =
7543 (requested_dwell & ~CUSTOM_RETRY_MASK);
7544 WL_DBG(("Custom retry(%d) and dwell time(%d) is set.\n",
7545 config_af_params.max_tx_retry,
7546 af_params->dwell_time));
7547 }
7548 } else if (action == P2PSD_ACTION_ID_GAS_IRESP ||
7549 action == P2PSD_ACTION_ID_GAS_CRESP) {
7550 /* configure service discovery response frame */
7551 af_params->dwell_time = WL_MIN_DWELL_TIME;
7552 } else {
7553 WL_DBG(("Unknown action type: %d\n", action));
7554 }
7555 } else {
7556 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n",
7557 category, action, action_frame_len));
7558 }
7559 } else if (category == P2P_AF_CATEGORY) {
7560 /* do not configure anything. it will be sent with a default configuration */
7561 } else {
7562 WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n",
7563 category, action));
7564 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
7565 wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
7566 return false;
7567 }
7568 }
7569 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
7570 /* validate channel and p2p ies */
7571 if (config_af_params.search_channel && IS_P2P_SOCIAL(af_params->channel) &&
7572 netinfo && netinfo->bss.ies.probe_req_ie_len) {
7573 config_af_params.search_channel = true;
7574 } else {
7575 config_af_params.search_channel = false;
7576 }
7577 #ifdef WL11U
7578 if (ndev == bcmcfg_to_prmry_ndev(cfg))
7579 config_af_params.search_channel = false;
7580 #endif /* WL11U */
7581
7582 #ifdef VSDB
7583 /* if connecting on primary iface, sleep for a while before sending af tx for VSDB */
7584 if (wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {
7585 OSL_SLEEP(50);
7586 }
7587 #endif
7588
7589 /* if scan is ongoing, abort current scan. */
7590 if (wl_get_drv_status_all(cfg, SCANNING)) {
7591 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
7592 }
7593
7594 /* Abort P2P listen */
7595 if (discover_cfgdev(cfgdev, cfg)) {
7596 if (cfg->p2p_supported && cfg->p2p) {
7597 wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
7598 wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE));
7599 }
7600 }
7601
7602 #ifdef WL11U
7603 /* handling DFS channel exceptions */
7604 if (!wl_cfg80211_check_DFS_channel(cfg, af_params, action_frame->data, action_frame->len)) {
7605 return false; /* the action frame was blocked */
7606 }
7607 #endif /* WL11U */
7608
7609 /* set status and destination address before sending af */
7610 if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
7611 /* set this status to cancel the remained dwell time in rx process */
7612 wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
7613 }
7614 wl_set_drv_status(cfg, SENDING_ACT_FRM, dev);
7615 memcpy(cfg->afx_hdl->tx_dst_addr.octet,
7616 af_params->action_frame.da.octet,
7617 sizeof(cfg->afx_hdl->tx_dst_addr.octet));
7618
7619 /* save af_params for rx process */
7620 cfg->afx_hdl->pending_tx_act_frm = af_params;
7621
7622 if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len)) {
7623 WL_DBG(("Set GAS action frame config.\n"));
7624 config_af_params.search_channel = false;
7625 config_af_params.max_tx_retry = 1;
7626 }
7627
7628 /* search peer's channel */
7629 if (config_af_params.search_channel) {
7630 /* initialize afx_hdl */
7631 if ((cfg->afx_hdl->bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
7632 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
7633 goto exit;
7634 }
7635 cfg->afx_hdl->dev = dev;
7636 cfg->afx_hdl->retry = 0;
7637 cfg->afx_hdl->peer_chan = WL_INVALID;
7638
7639 if (wl_cfg80211_af_searching_channel(cfg, dev) == WL_INVALID) {
7640 WL_ERR(("couldn't find peer's channel.\n"));
7641 wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len,
7642 af_params->channel);
7643 /* Even if we couldn't find peer channel, try to send the frame
7644 * out. P2P cert 5.1.14 testbed device (realtek) doesn't seem to
7645 * respond to probe request (Ideally it has to be in listen and
7646 * responsd to probe request). However if we send Go neg req, the
7647 * peer is sending GO-neg resp. So instead of giving up here, just
7648 * proceed and attempt sending out the action frame.
7649 */
7650 }
7651
7652 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
7653 /*
7654 * Abort scan even for VSDB scenarios. Scan gets aborted in firmware
7655 * but after the check of piggyback algorithm.
7656 * To take care of current piggback algo, lets abort the scan here itself.
7657 */
7658 wl_notify_escan_complete(cfg, dev, true, true);
7659 /* Suspend P2P discovery's search-listen to prevent it from
7660 * starting a scan or changing the channel.
7661 */
7662 if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
7663 WL_ERR(("Can not disable discovery mode\n"));
7664 goto exit;
7665 }
7666
7667 /* update channel */
7668 if (cfg->afx_hdl->peer_chan != WL_INVALID) {
7669 af_params->channel = cfg->afx_hdl->peer_chan;
7670 WL_ERR(("Attempt tx on peer listen channel:%d ",
7671 cfg->afx_hdl->peer_chan));
7672 } else {
7673 WL_ERR(("Attempt tx with the channel provided by userspace."
7674 "Channel: %d\n", af_params->channel));
7675 }
7676 }
7677
7678 #ifdef VSDB
7679 off_chan_started_jiffies = jiffies;
7680 #endif /* VSDB */
7681
7682 wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel);
7683
7684 wl_cfgp2p_need_wait_actfrmae(cfg, action_frame->data, action_frame->len, true);
7685
7686 dwell_jiffies = jiffies;
7687 /* Now send a tx action frame */
7688 ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ? false : true;
7689 dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
7690
7691 if (ack && (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM))) {
7692 wifi_p2p_pub_act_frame_t *pact_frm;
7693 pact_frm = (wifi_p2p_pub_act_frame_t *)(action_frame->data);
7694 if (pact_frm->subtype == P2P_PAF_GON_RSP) {
7695 WL_ERR(("Miss GO Nego cfm after P2P_PAF_GON_RSP\n"));
7696 miss_gon_cfm = true;
7697 }
7698 }
7699
7700 /* if failed, retry it. tx_retry_max value is configure by .... */
7701 while ((miss_gon_cfm || (ack == false)) && (tx_retry++ < config_af_params.max_tx_retry) &&
7702 !dwell_overflow) {
7703 #ifdef VSDB
7704 if (af_params->channel) {
7705 if (jiffies_to_msecs(jiffies - off_chan_started_jiffies) >
7706 OFF_CHAN_TIME_THRESHOLD_MS) {
7707 WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(cfg);
7708 off_chan_started_jiffies = jiffies;
7709 } else
7710 OSL_SLEEP(AF_RETRY_DELAY_TIME);
7711 }
7712 #endif /* VSDB */
7713 ack = wl_cfgp2p_tx_action_frame(cfg, dev, af_params, bssidx) ?
7714 false : true;
7715 if (miss_gon_cfm && !wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
7716 WL_ERR(("Received GO Nego cfm after P2P_PAF_GON_RSP\n"));
7717 miss_gon_cfm = false;
7718 }
7719 dwell_overflow = wl_cfg80211_check_dwell_overflow(requested_dwell, dwell_jiffies);
7720 }
7721
7722 if (ack == false) {
7723 WL_ERR(("Failed to send Action Frame(retry %d)\n", tx_retry));
7724 }
7725 WL_DBG(("Complete to send action frame\n"));
7726 exit:
7727 /* Clear SENDING_ACT_FRM after all sending af is done */
7728 wl_clr_drv_status(cfg, SENDING_ACT_FRM, dev);
7729
7730 #ifdef WL_CFG80211_SYNC_GON
7731 /* WAR: sometimes dongle does not keep the dwell time of 'actframe'.
7732 * if we coundn't get the next action response frame and dongle does not keep
7733 * the dwell time, go to listen state again to get next action response frame.
7734 */
7735 if (ack && config_af_params.extra_listen &&
7736 wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM) &&
7737 cfg->af_sent_channel == cfg->afx_hdl->my_listen_chan) {
7738 s32 extar_listen_time;
7739
7740 extar_listen_time = af_params->dwell_time -
7741 jiffies_to_msecs(jiffies - cfg->af_tx_sent_jiffies);
7742
7743 if (extar_listen_time > 50) {
7744 wl_set_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
7745 WL_DBG(("Wait more time! actual af time:%d,"
7746 "calculated extar listen:%d\n",
7747 af_params->dwell_time, extar_listen_time));
7748 if (wl_cfgp2p_discover_listen(cfg, cfg->af_sent_channel,
7749 extar_listen_time + 100) == BCME_OK) {
7750 wait_for_completion_timeout(&cfg->wait_next_af,
7751 msecs_to_jiffies(extar_listen_time + 100 + 300));
7752 }
7753 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM_LISTEN, dev);
7754 }
7755 }
7756 #endif /* WL_CFG80211_SYNC_GON */
7757 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, dev);
7758 cfg->afx_hdl->pending_tx_act_frm = NULL;
7759
7760 WL_INFORM(("-- sending Action Frame is %s, listen chan: %d\n",
7761 (ack) ? "Succeeded!!":"Failed!!", cfg->afx_hdl->my_listen_chan));
7762
7763 return ack;
7764 }
7765
7766 #define MAX_NUM_OF_ASSOCIATED_DEV 64
7767 static s32
7768 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7769 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
7770 struct cfg80211_mgmt_tx_params *params, u64 *cookie)
7771 #else
7772 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
7773 struct ieee80211_channel *channel, bool offchan,
7774 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0))
7775 enum nl80211_channel_type channel_type,
7776 bool channel_type_valid,
7777 #endif /* LINUX_VERSION_CODE <= KERNEL_VERSION(3, 7, 0) */
7778 unsigned int wait, const u8* buf, size_t len,
7779 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
7780 bool no_cck,
7781 #endif
7782 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
7783 bool dont_wait_for_ack,
7784 #endif
7785 u64 *cookie)
7786 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0) */
7787 {
7788 wl_action_frame_t *action_frame;
7789 wl_af_params_t *af_params;
7790 scb_val_t scb_val;
7791 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7792 struct ieee80211_channel *channel = params->chan;
7793 const u8 *buf = params->buf;
7794 size_t len = params->len;
7795 #endif
7796 const struct ieee80211_mgmt *mgmt;
7797 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7798 struct net_device *dev = NULL;
7799 s32 err = BCME_OK;
7800 s32 bssidx = 0;
7801 u32 id;
7802 bool ack = false;
7803 s8 eabuf[ETHER_ADDR_STR_LEN];
7804
7805 WL_DBG(("Enter \n"));
7806
7807 if (len > ACTION_FRAME_SIZE) {
7808 WL_ERR(("bad length:%zu\n", len));
7809 return BCME_BADLEN;
7810 }
7811 #ifdef DHD_IFDEBUG
7812 PRINT_WDEV_INFO(cfgdev);
7813 #endif /* DHD_IFDEBUG */
7814
7815 dev = cfgdev_to_wlc_ndev(cfgdev, cfg);
7816
7817 if (!dev) {
7818 WL_ERR(("dev is NULL\n"));
7819 return -EINVAL;
7820 }
7821
7822 /* set bsscfg idx for iovar (wlan0: P2PAPI_BSSCFG_PRIMARY, p2p: P2PAPI_BSSCFG_DEVICE) */
7823 if (discover_cfgdev(cfgdev, cfg)) {
7824 if (!cfg->p2p_supported || !cfg->p2p) {
7825 WL_ERR(("P2P doesn't setup completed yet\n"));
7826 return -EINVAL;
7827 }
7828 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
7829 }
7830 else {
7831 if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfgdev_to_wdev(cfgdev))) < 0) {
7832 WL_ERR(("Find p2p index failed\n"));
7833 return BCME_ERROR;
7834 }
7835 }
7836
7837 WL_DBG(("TX target bssidx=%d\n", bssidx));
7838
7839 if (p2p_is_on(cfg)) {
7840 /* Suspend P2P discovery search-listen to prevent it from changing the
7841 * channel.
7842 */
7843 if ((err = wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
7844 WL_ERR(("Can not disable discovery mode\n"));
7845 return -EFAULT;
7846 }
7847 }
7848 *cookie = 0;
7849 id = cfg->send_action_id++;
7850 if (id == 0)
7851 id = cfg->send_action_id++;
7852 *cookie = id;
7853 mgmt = (const struct ieee80211_mgmt *)buf;
7854 if (ieee80211_is_mgmt(mgmt->frame_control)) {
7855 if (ieee80211_is_probe_resp(mgmt->frame_control)) {
7856 s32 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
7857 s32 ie_len = len - ie_offset;
7858 if ((dev == bcmcfg_to_prmry_ndev(cfg)) && cfg->p2p) {
7859 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
7860 }
7861 wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
7862 VNDR_IE_PRBRSP_FLAG, (const u8 *)(buf + ie_offset), ie_len);
7863 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
7864 #if defined(P2P_IE_MISSING_FIX)
7865 if (!cfg->p2p_prb_noti) {
7866 cfg->p2p_prb_noti = true;
7867 WL_DBG(("%s: TX 802_1X Probe Response first time.\n",
7868 __FUNCTION__));
7869 }
7870 #endif
7871 goto exit;
7872 } else if (ieee80211_is_disassoc(mgmt->frame_control) ||
7873 ieee80211_is_deauth(mgmt->frame_control)) {
7874 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
7875 sizeof(struct ether_addr) + sizeof(uint)] = {0};
7876 int num_associated = 0;
7877 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
7878 if (!bcmp((const uint8 *)BSSID_BROADCAST,
7879 (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) {
7880 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
7881 err = wldev_ioctl_get(dev, WLC_GET_ASSOCLIST,
7882 assoc_maclist, sizeof(mac_buf));
7883 if (err < 0)
7884 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
7885 else
7886 num_associated = assoc_maclist->count;
7887 }
7888 memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN);
7889 scb_val.val = mgmt->u.disassoc.reason_code;
7890 err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
7891 sizeof(scb_val_t));
7892 if (err < 0)
7893 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err));
7894 WL_ERR(("Disconnect STA : %s scb_val.val %d\n",
7895 bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf),
7896 scb_val.val));
7897
7898 if (num_associated > 0 && ETHER_ISBCAST(mgmt->da))
7899 wl_delay(400);
7900
7901 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, true, GFP_KERNEL);
7902 goto exit;
7903
7904 } else if (ieee80211_is_action(mgmt->frame_control)) {
7905 /* Abort the dwell time of any previous off-channel
7906 * action frame that may be still in effect. Sending
7907 * off-channel action frames relies on the driver's
7908 * scan engine. If a previous off-channel action frame
7909 * tx is still in progress (including the dwell time),
7910 * then this new action frame will not be sent out.
7911 */
7912 /* Do not abort scan for VSDB. Scan will be aborted in firmware if necessary.
7913 * And previous off-channel action frame must be ended before new af tx.
7914 */
7915 #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
7916 wl_notify_escan_complete(cfg, dev, true, true);
7917 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
7918 }
7919
7920 } else {
7921 WL_ERR(("Driver only allows MGMT packet type\n"));
7922 goto exit;
7923 }
7924
7925 af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
7926
7927 if (af_params == NULL)
7928 {
7929 WL_ERR(("unable to allocate frame\n"));
7930 return -ENOMEM;
7931 }
7932
7933 action_frame = &af_params->action_frame;
7934
7935 /* Add the packet Id */
7936 action_frame->packetId = *cookie;
7937 WL_DBG(("action frame %d\n", action_frame->packetId));
7938 /* Add BSSID */
7939 memcpy(&action_frame->da, &mgmt->da[0], ETHER_ADDR_LEN);
7940 memcpy(&af_params->BSSID, &mgmt->bssid[0], ETHER_ADDR_LEN);
7941
7942 /* Add the length exepted for 802.11 header */
7943 action_frame->len = len - DOT11_MGMT_HDR_LEN;
7944 WL_DBG(("action_frame->len: %d\n", action_frame->len));
7945
7946 /* Add the channel */
7947 af_params->channel =
7948 ieee80211_frequency_to_channel(channel->center_freq);
7949 /* Save listen_chan for searching common channel */
7950 cfg->afx_hdl->peer_listen_chan = af_params->channel;
7951 WL_DBG(("channel from upper layer %d\n", cfg->afx_hdl->peer_listen_chan));
7952
7953 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
7954 af_params->dwell_time = params->wait;
7955 #else
7956 af_params->dwell_time = wait;
7957 #endif
7958
7959 memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
7960
7961 ack = wl_cfg80211_send_action_frame(wiphy, dev, cfgdev, af_params,
7962 action_frame, action_frame->len, bssidx);
7963 cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
7964
7965 kfree(af_params);
7966 exit:
7967 return err;
7968 }
7969
7970
7971 static void
7972 wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
7973 u16 frame, bool reg)
7974 {
7975
7976 WL_DBG(("frame_type: %x, reg: %d\n", frame, reg));
7977
7978 if (frame != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ))
7979 return;
7980
7981 return;
7982 }
7983
7984
7985 static s32
7986 wl_cfg80211_change_bss(struct wiphy *wiphy,
7987 struct net_device *dev,
7988 struct bss_parameters *params)
7989 {
7990 s32 err = 0;
7991 s32 ap_isolate = 0;
7992 #ifdef PCIE_FULL_DONGLE
7993 s32 ifidx = DHD_BAD_IF;
7994 #endif
7995 #if defined(PCIE_FULL_DONGLE)
7996 dhd_pub_t *dhd;
7997 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
7998 dhd = (dhd_pub_t *)(cfg->pub);
7999 #if defined(WL_ENABLE_P2P_IF)
8000 if (cfg->p2p_net == dev)
8001 dev = bcmcfg_to_prmry_ndev(cfg);
8002 #endif
8003 #endif
8004
8005 if (params->use_cts_prot >= 0) {
8006 }
8007
8008 if (params->use_short_preamble >= 0) {
8009 }
8010
8011 if (params->use_short_slot_time >= 0) {
8012 }
8013
8014 if (params->basic_rates) {
8015 }
8016
8017 if (params->ap_isolate >= 0) {
8018 ap_isolate = params->ap_isolate;
8019 #ifdef PCIE_FULL_DONGLE
8020 ifidx = dhd_net2idx(dhd->info, dev);
8021
8022 if (ifidx != DHD_BAD_IF) {
8023 err = dhd_set_ap_isolate(dhd, ifidx, ap_isolate);
8024 } else {
8025 WL_ERR(("Failed to set ap_isolate\n"));
8026 }
8027 #else
8028 err = wldev_iovar_setint(dev, "ap_isolate", ap_isolate);
8029 if (unlikely(err))
8030 {
8031 WL_ERR(("set ap_isolate Error (%d)\n", err));
8032 }
8033 #endif /* PCIE_FULL_DONGLE */
8034 }
8035
8036 if (params->ht_opmode >= 0) {
8037 }
8038
8039
8040 return err;
8041 }
8042
8043 static s32
8044 wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
8045 struct ieee80211_channel *chan,
8046 enum nl80211_channel_type channel_type)
8047 {
8048 s32 _chan;
8049 chanspec_t chspec = 0;
8050 chanspec_t fw_chspec = 0;
8051 u32 bw = WL_CHANSPEC_BW_20;
8052 #ifdef WL11ULB
8053 u32 ulb_bw = wl_cfg80211_get_ulb_bw(wl_get_cfg(dev), dev->ieee80211_ptr);
8054 #endif /* WL11ULB */
8055
8056 s32 err = BCME_OK;
8057 s32 bw_cap = 0;
8058 struct {
8059 u32 band;
8060 u32 bw_cap;
8061 } param = {0, 0};
8062 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
8063 #if defined(CUSTOM_SET_CPUCORE) || (defined(WL_VIRTUAL_APSTA) && \
8064 defined(APSTA_RESTRICTED_CHANNEL))
8065 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
8066 #endif /* CUSTOM_SET_CPUCORE || (WL_VIRTUAL_APSTA && APSTA_RESTRICTED_CHANNEL) */
8067
8068 dev = ndev_to_wlc_ndev(dev, cfg);
8069 _chan = ieee80211_frequency_to_channel(chan->center_freq);
8070 #ifdef WL_EXT_IAPSTA
8071 _chan = wl_ext_iapsta_update_channel(dev, _chan);
8072 #endif
8073 printf("%s: netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
8074 __FUNCTION__, dev->ifindex, channel_type, _chan);
8075
8076
8077 #if defined(WL_VIRTUAL_APSTA) && defined(APSTA_RESTRICTED_CHANNEL)
8078 #define DEFAULT_2G_SOFTAP_CHANNEL 1
8079 #define DEFAULT_5G_SOFTAP_CHANNEL 149
8080 if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP &&
8081 (dhd->op_mode & DHD_FLAG_CONCURR_STA_HOSTAP_MODE) ==
8082 DHD_FLAG_CONCURR_STA_HOSTAP_MODE &&
8083 wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg))) {
8084 u32 *sta_chan = (u32 *)wl_read_prof(cfg,
8085 bcmcfg_to_prmry_ndev(cfg), WL_PROF_CHAN);
8086 u32 sta_band = (*sta_chan > CH_MAX_2G_CHANNEL) ?
8087 IEEE80211_BAND_5GHZ : IEEE80211_BAND_2GHZ;
8088 if (chan->band == sta_band) {
8089 /* Do not try SCC in 5GHz if channel is not CH149 */
8090 _chan = (sta_band == IEEE80211_BAND_5GHZ &&
8091 *sta_chan != DEFAULT_5G_SOFTAP_CHANNEL) ?
8092 DEFAULT_2G_SOFTAP_CHANNEL : *sta_chan;
8093 WL_ERR(("target channel will be changed to %d\n", _chan));
8094 if (_chan <= CH_MAX_2G_CHANNEL) {
8095 bw = WL_CHANSPEC_BW_20;
8096 goto set_channel;
8097 }
8098 }
8099 }
8100 #undef DEFAULT_2G_SOFTAP_CHANNEL
8101 #undef DEFAULT_5G_SOFTAP_CHANNEL
8102 #endif /* WL_VIRTUAL_APSTA && APSTA_RESTRICTED_CHANNEL */
8103
8104 #ifdef WL11ULB
8105 if (ulb_bw) {
8106 WL_DBG(("[ULB] setting AP/GO BW to ulb_bw 0x%x \n", ulb_bw));
8107 bw = wl_cfg80211_ulbbw_to_ulbchspec(ulb_bw);
8108 goto set_channel;
8109 }
8110 #endif /* WL11ULB */
8111 if (chan->band == IEEE80211_BAND_5GHZ) {
8112 param.band = WLC_BAND_5G;
8113 err = wldev_iovar_getbuf(dev, "bw_cap", &param, sizeof(param),
8114 cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
8115 if (err) {
8116 if (err != BCME_UNSUPPORTED) {
8117 WL_ERR(("bw_cap failed, %d\n", err));
8118 return err;
8119 } else {
8120 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
8121 if (err) {
8122 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
8123 }
8124 if (bw_cap != WLC_N_BW_20ALL)
8125 bw = WL_CHANSPEC_BW_40;
8126 }
8127 } else {
8128 if (WL_BW_CAP_80MHZ(cfg->ioctl_buf[0]))
8129 bw = WL_CHANSPEC_BW_80;
8130 else if (WL_BW_CAP_40MHZ(cfg->ioctl_buf[0]))
8131 bw = WL_CHANSPEC_BW_40;
8132 else
8133 bw = WL_CHANSPEC_BW_20;
8134
8135 }
8136
8137 } else if (chan->band == IEEE80211_BAND_2GHZ)
8138 bw = WL_CHANSPEC_BW_20;
8139 set_channel:
8140 chspec = wf_channel2chspec(_chan, bw);
8141 if (wf_chspec_valid(chspec)) {
8142 fw_chspec = wl_chspec_host_to_driver(chspec);
8143 if (fw_chspec != INVCHANSPEC) {
8144 if ((err = wldev_iovar_setint(dev, "chanspec",
8145 fw_chspec)) == BCME_BADCHAN) {
8146 if (bw == WL_CHANSPEC_BW_80)
8147 goto change_bw;
8148 err = wldev_ioctl_set(dev, WLC_SET_CHANNEL,
8149 &_chan, sizeof(_chan));
8150 if (err < 0) {
8151 WL_ERR(("WLC_SET_CHANNEL error %d"
8152 "chip may not be supporting this channel\n", err));
8153 }
8154 } else if (err) {
8155 WL_ERR(("failed to set chanspec error %d\n", err));
8156 }
8157 } else {
8158 WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
8159 err = BCME_ERROR;
8160 }
8161 } else {
8162 change_bw:
8163 if (bw == WL_CHANSPEC_BW_80)
8164 bw = WL_CHANSPEC_BW_40;
8165 else if (bw == WL_CHANSPEC_BW_40)
8166 bw = WL_CHANSPEC_BW_20;
8167 else
8168 bw = 0;
8169 if (bw)
8170 goto set_channel;
8171 WL_ERR(("Invalid chanspec 0x%x\n", chspec));
8172 err = BCME_ERROR;
8173 }
8174 #ifdef CUSTOM_SET_CPUCORE
8175 if (dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
8176 WL_DBG(("SoftAP mode do not need to set cpucore\n"));
8177 } else if (chspec & WL_CHANSPEC_BW_80) {
8178 /* SoftAp only mode do not need to set cpucore */
8179 if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) &&
8180 dev != bcmcfg_to_prmry_ndev(cfg)) {
8181 /* Soft AP on virtual Iface (AP+STA case) */
8182 dhd->chan_isvht80 |= DHD_FLAG_HOSTAP_MODE;
8183 dhd_set_cpucore(dhd, TRUE);
8184 } else if (is_p2p_group_iface(dev->ieee80211_ptr)) {
8185 /* If P2P IF is vht80 */
8186 dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE;
8187 dhd_set_cpucore(dhd, TRUE);
8188 }
8189 }
8190 #endif /* CUSTOM_SET_CPUCORE */
8191 if (!err && (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) {
8192 /* Update AP/GO operating channel */
8193 cfg->ap_oper_channel = ieee80211_frequency_to_channel(chan->center_freq);
8194 }
8195 return err;
8196 }
8197
8198 #ifdef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
8199 struct net_device *
8200 wl_cfg80211_get_remain_on_channel_ndev(struct bcm_cfg80211 *cfg)
8201 {
8202 struct net_info *_net_info, *next;
8203 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
8204 #pragma GCC diagnostic push
8205 #pragma GCC diagnostic ignored "-Wcast-qual"
8206 #endif
8207 list_for_each_entry_safe(_net_info, next, &cfg->net_list, list) {
8208 if (_net_info->ndev &&
8209 test_bit(WL_STATUS_REMAINING_ON_CHANNEL, &_net_info->sme_state))
8210 return _net_info->ndev;
8211 }
8212 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
8213 #pragma GCC diagnostic pop
8214 #endif
8215 return NULL;
8216 }
8217 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
8218
8219 static s32
8220 wl_validate_opensecurity(struct net_device *dev, s32 bssidx, bool privacy)
8221 {
8222 s32 err = BCME_OK;
8223 u32 wpa_val;
8224 s32 wsec = 0;
8225
8226 /* set auth */
8227 err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
8228 if (err < 0) {
8229 WL_ERR(("auth error %d\n", err));
8230 return BCME_ERROR;
8231 }
8232
8233 if (privacy) {
8234 /* If privacy bit is set in open mode, then WEP would be enabled */
8235 wsec = WEP_ENABLED;
8236 WL_DBG(("Setting wsec to %d for WEP \n", wsec));
8237 }
8238
8239 /* set wsec */
8240 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
8241 if (err < 0) {
8242 WL_ERR(("wsec error %d\n", err));
8243 return BCME_ERROR;
8244 }
8245
8246 /* set upper-layer auth */
8247 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC)
8248 wpa_val = WPA_AUTH_NONE;
8249 else
8250 wpa_val = WPA_AUTH_DISABLED;
8251 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_val, bssidx);
8252 if (err < 0) {
8253 WL_ERR(("wpa_auth error %d\n", err));
8254 return BCME_ERROR;
8255 }
8256
8257 return 0;
8258 }
8259
8260 static s32
8261 wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
8262 {
8263 s32 len = 0;
8264 s32 err = BCME_OK;
8265 u16 auth = 0; /* d11 open authentication */
8266 u32 wsec;
8267 u32 pval = 0;
8268 u32 gval = 0;
8269 u32 wpa_auth = 0;
8270 wpa_suite_mcast_t *mcast;
8271 wpa_suite_ucast_t *ucast;
8272 wpa_suite_auth_key_mgmt_t *mgmt;
8273 wpa_pmkid_list_t *pmkid;
8274 int cnt = 0;
8275 #ifdef MFP
8276 int mfp = 0;
8277 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
8278 #endif /* MFP */
8279
8280 u16 suite_count;
8281 u8 rsn_cap[2];
8282 u32 wme_bss_disable;
8283
8284 if (wpa2ie == NULL)
8285 goto exit;
8286
8287 WL_DBG(("Enter \n"));
8288 len = wpa2ie->len - WPA2_VERSION_LEN;
8289 /* check the mcast cipher */
8290 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
8291 switch (mcast->type) {
8292 case WPA_CIPHER_NONE:
8293 gval = 0;
8294 break;
8295 case WPA_CIPHER_WEP_40:
8296 case WPA_CIPHER_WEP_104:
8297 gval = WEP_ENABLED;
8298 break;
8299 case WPA_CIPHER_TKIP:
8300 gval = TKIP_ENABLED;
8301 break;
8302 case WPA_CIPHER_AES_CCM:
8303 gval = AES_ENABLED;
8304 break;
8305 default:
8306 WL_ERR(("No Security Info\n"));
8307 break;
8308 }
8309 if ((len -= WPA_SUITE_LEN) <= 0)
8310 return BCME_BADLEN;
8311
8312 /* check the unicast cipher */
8313 ucast = (wpa_suite_ucast_t *)&mcast[1];
8314 suite_count = ltoh16_ua(&ucast->count);
8315 switch (ucast->list[0].type) {
8316 case WPA_CIPHER_NONE:
8317 pval = 0;
8318 break;
8319 case WPA_CIPHER_WEP_40:
8320 case WPA_CIPHER_WEP_104:
8321 pval = WEP_ENABLED;
8322 break;
8323 case WPA_CIPHER_TKIP:
8324 pval = TKIP_ENABLED;
8325 break;
8326 case WPA_CIPHER_AES_CCM:
8327 pval = AES_ENABLED;
8328 break;
8329 default:
8330 WL_ERR(("No Security Info\n"));
8331 }
8332 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
8333 return BCME_BADLEN;
8334
8335 /* FOR WPS , set SEC_OW_ENABLED */
8336 wsec = (pval | gval | SES_OW_ENABLED);
8337 /* check the AKM */
8338 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
8339 suite_count = cnt = ltoh16_ua(&mgmt->count);
8340 while (cnt--) {
8341 switch (mgmt->list[cnt].type) {
8342 case RSN_AKM_NONE:
8343 wpa_auth |= WPA_AUTH_NONE;
8344 break;
8345 case RSN_AKM_UNSPECIFIED:
8346 wpa_auth |= WPA2_AUTH_UNSPECIFIED;
8347 break;
8348 case RSN_AKM_PSK:
8349 wpa_auth |= WPA2_AUTH_PSK;
8350 break;
8351 #ifdef MFP
8352 case RSN_AKM_MFP_PSK:
8353 wpa_auth |= WPA2_AUTH_PSK_SHA256;
8354 break;
8355 case RSN_AKM_MFP_1X:
8356 wpa_auth |= WPA2_AUTH_1X_SHA256;
8357 break;
8358 #endif /* MFP */
8359 default:
8360 WL_ERR(("No Key Mgmt Info\n"));
8361 }
8362 }
8363
8364 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
8365 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
8366 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
8367
8368 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
8369 wme_bss_disable = 0;
8370 } else {
8371 wme_bss_disable = 1;
8372 }
8373
8374 #ifdef MFP
8375 if (rsn_cap[0] & RSN_CAP_MFPR) {
8376 WL_DBG(("MFP Required \n"));
8377 mfp = WL_MFP_REQUIRED;
8378 /* Our firmware has requirement that WPA2_AUTH_PSK/WPA2_AUTH_UNSPECIFIED
8379 * be set, if SHA256 OUI is to be included in the rsn ie.
8380 */
8381 if (wpa_auth & WPA2_AUTH_PSK_SHA256) {
8382 wpa_auth |= WPA2_AUTH_PSK;
8383 } else if (wpa_auth & WPA2_AUTH_1X_SHA256) {
8384 wpa_auth |= WPA2_AUTH_UNSPECIFIED;
8385 }
8386 } else if (rsn_cap[0] & RSN_CAP_MFPC) {
8387 WL_DBG(("MFP Capable \n"));
8388 mfp = WL_MFP_CAPABLE;
8389 }
8390 #endif /* MFP */
8391
8392 /* set wme_bss_disable to sync RSN Capabilities */
8393 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
8394 if (err < 0) {
8395 WL_ERR(("wme_bss_disable error %d\n", err));
8396 return BCME_ERROR;
8397 }
8398 } else {
8399 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
8400 }
8401
8402 len -= RSN_CAP_LEN;
8403 if (len >= WPA2_PMKID_COUNT_LEN) {
8404 pmkid = (wpa_pmkid_list_t *)((u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN);
8405 cnt = ltoh16_ua(&pmkid->count);
8406 if (cnt != 0) {
8407 WL_ERR(("AP has non-zero PMKID count. Wrong!\n"));
8408 return BCME_ERROR;
8409 }
8410 /* since PMKID cnt is known to be 0 for AP, */
8411 /* so don't bother to send down this info to firmware */
8412 }
8413
8414 #ifdef MFP
8415 len -= WPA2_PMKID_COUNT_LEN;
8416 if (len >= WPA_SUITE_LEN) {
8417 cfg->bip_pos = (u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN + WPA2_PMKID_COUNT_LEN;
8418 } else {
8419 cfg->bip_pos = NULL;
8420 }
8421 #endif
8422
8423 /* set auth */
8424 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
8425 if (err < 0) {
8426 WL_ERR(("auth error %d\n", err));
8427 return BCME_ERROR;
8428 }
8429
8430 /* set wsec */
8431 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
8432 if (err < 0) {
8433 WL_ERR(("wsec error %d\n", err));
8434 return BCME_ERROR;
8435 }
8436
8437 #ifdef MFP
8438 cfg->mfp_mode = mfp;
8439 #endif /* MFP */
8440
8441 /* set upper-layer auth */
8442 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
8443 if (err < 0) {
8444 WL_ERR(("wpa_auth error %d\n", err));
8445 return BCME_ERROR;
8446 }
8447 exit:
8448 return 0;
8449 }
8450
8451 static s32
8452 wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
8453 {
8454 wpa_suite_mcast_t *mcast;
8455 wpa_suite_ucast_t *ucast;
8456 wpa_suite_auth_key_mgmt_t *mgmt;
8457 u16 auth = 0; /* d11 open authentication */
8458 u16 count;
8459 s32 err = BCME_OK;
8460 s32 len = 0;
8461 u32 i;
8462 u32 wsec;
8463 u32 pval = 0;
8464 u32 gval = 0;
8465 u32 wpa_auth = 0;
8466 u32 tmp = 0;
8467
8468 if (wpaie == NULL)
8469 goto exit;
8470 WL_DBG(("Enter \n"));
8471 len = wpaie->length; /* value length */
8472 len -= WPA_IE_TAG_FIXED_LEN;
8473 /* check for multicast cipher suite */
8474 if (len < WPA_SUITE_LEN) {
8475 WL_INFORM(("no multicast cipher suite\n"));
8476 goto exit;
8477 }
8478
8479 /* pick up multicast cipher */
8480 mcast = (wpa_suite_mcast_t *)&wpaie[1];
8481 len -= WPA_SUITE_LEN;
8482 if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
8483 if (IS_WPA_CIPHER(mcast->type)) {
8484 tmp = 0;
8485 switch (mcast->type) {
8486 case WPA_CIPHER_NONE:
8487 tmp = 0;
8488 break;
8489 case WPA_CIPHER_WEP_40:
8490 case WPA_CIPHER_WEP_104:
8491 tmp = WEP_ENABLED;
8492 break;
8493 case WPA_CIPHER_TKIP:
8494 tmp = TKIP_ENABLED;
8495 break;
8496 case WPA_CIPHER_AES_CCM:
8497 tmp = AES_ENABLED;
8498 break;
8499 default:
8500 WL_ERR(("No Security Info\n"));
8501 }
8502 gval |= tmp;
8503 }
8504 }
8505 /* Check for unicast suite(s) */
8506 if (len < WPA_IE_SUITE_COUNT_LEN) {
8507 WL_INFORM(("no unicast suite\n"));
8508 goto exit;
8509 }
8510 /* walk thru unicast cipher list and pick up what we recognize */
8511 ucast = (wpa_suite_ucast_t *)&mcast[1];
8512 count = ltoh16_ua(&ucast->count);
8513 len -= WPA_IE_SUITE_COUNT_LEN;
8514 for (i = 0; i < count && len >= WPA_SUITE_LEN;
8515 i++, len -= WPA_SUITE_LEN) {
8516 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
8517 if (IS_WPA_CIPHER(ucast->list[i].type)) {
8518 tmp = 0;
8519 switch (ucast->list[i].type) {
8520 case WPA_CIPHER_NONE:
8521 tmp = 0;
8522 break;
8523 case WPA_CIPHER_WEP_40:
8524 case WPA_CIPHER_WEP_104:
8525 tmp = WEP_ENABLED;
8526 break;
8527 case WPA_CIPHER_TKIP:
8528 tmp = TKIP_ENABLED;
8529 break;
8530 case WPA_CIPHER_AES_CCM:
8531 tmp = AES_ENABLED;
8532 break;
8533 default:
8534 WL_ERR(("No Security Info\n"));
8535 }
8536 pval |= tmp;
8537 }
8538 }
8539 }
8540 len -= (count - i) * WPA_SUITE_LEN;
8541 /* Check for auth key management suite(s) */
8542 if (len < WPA_IE_SUITE_COUNT_LEN) {
8543 WL_INFORM((" no auth key mgmt suite\n"));
8544 goto exit;
8545 }
8546 /* walk thru auth management suite list and pick up what we recognize */
8547 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
8548 count = ltoh16_ua(&mgmt->count);
8549 len -= WPA_IE_SUITE_COUNT_LEN;
8550 for (i = 0; i < count && len >= WPA_SUITE_LEN;
8551 i++, len -= WPA_SUITE_LEN) {
8552 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
8553 if (IS_WPA_AKM(mgmt->list[i].type)) {
8554 tmp = 0;
8555 switch (mgmt->list[i].type) {
8556 case RSN_AKM_NONE:
8557 tmp = WPA_AUTH_NONE;
8558 break;
8559 case RSN_AKM_UNSPECIFIED:
8560 tmp = WPA_AUTH_UNSPECIFIED;
8561 break;
8562 case RSN_AKM_PSK:
8563 tmp = WPA_AUTH_PSK;
8564 break;
8565 default:
8566 WL_ERR(("No Key Mgmt Info\n"));
8567 }
8568 wpa_auth |= tmp;
8569 }
8570 }
8571
8572 }
8573 /* FOR WPS , set SEC_OW_ENABLED */
8574 wsec = (pval | gval | SES_OW_ENABLED);
8575 /* set auth */
8576 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
8577 if (err < 0) {
8578 WL_ERR(("auth error %d\n", err));
8579 return BCME_ERROR;
8580 }
8581 /* set wsec */
8582 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
8583 if (err < 0) {
8584 WL_ERR(("wsec error %d\n", err));
8585 return BCME_ERROR;
8586 }
8587 /* set upper-layer auth */
8588 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
8589 if (err < 0) {
8590 WL_ERR(("wpa_auth error %d\n", err));
8591 return BCME_ERROR;
8592 }
8593 exit:
8594 return 0;
8595 }
8596
8597 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8598 static u32 wl_get_cipher_type(uint8 type)
8599 {
8600 u32 ret = 0;
8601 switch (type) {
8602 case WPA_CIPHER_NONE:
8603 ret = 0;
8604 break;
8605 case WPA_CIPHER_WEP_40:
8606 case WPA_CIPHER_WEP_104:
8607 ret = WEP_ENABLED;
8608 break;
8609 case WPA_CIPHER_TKIP:
8610 ret = TKIP_ENABLED;
8611 break;
8612 case WPA_CIPHER_AES_CCM:
8613 ret = AES_ENABLED;
8614 break;
8615 #ifdef BCMWAPI_WPI
8616 case WAPI_CIPHER_SMS4:
8617 ret = SMS4_ENABLED;
8618 break;
8619 #endif
8620 default:
8621 WL_ERR(("No Security Info\n"));
8622 }
8623 return ret;
8624 }
8625
8626 static u32 wl_get_suite_auth_key_mgmt_type(uint8 type)
8627 {
8628 u32 ret = 0;
8629 switch (type) {
8630 case RSN_AKM_NONE:
8631 ret = WPA_AUTH_NONE;
8632 break;
8633 case RSN_AKM_UNSPECIFIED:
8634 ret = WPA_AUTH_UNSPECIFIED;
8635 break;
8636 case RSN_AKM_PSK:
8637 ret = WPA_AUTH_PSK;
8638 break;
8639 default:
8640 WL_ERR(("No Key Mgmt Info\n"));
8641 }
8642 return ret;
8643 }
8644
8645 static u32 wl_get_suite_auth2_key_mgmt_type(uint8 type)
8646 {
8647 u32 ret = 0;
8648 switch (type) {
8649 case RSN_AKM_NONE:
8650 ret = WPA_AUTH_NONE;
8651 break;
8652 case RSN_AKM_UNSPECIFIED:
8653 ret = WPA2_AUTH_UNSPECIFIED;
8654 break;
8655 case RSN_AKM_PSK:
8656 ret = WPA2_AUTH_PSK;
8657 break;
8658 default:
8659 WL_ERR(("No Key Mgmt Info\n"));
8660 }
8661 return ret;
8662 }
8663
8664 static s32
8665 wl_validate_wpaie_wpa2ie(struct net_device *dev, wpa_ie_fixed_t *wpaie,
8666 bcm_tlv_t *wpa2ie, s32 bssidx)
8667 {
8668 wpa_suite_mcast_t *mcast;
8669 wpa_suite_ucast_t *ucast;
8670 wpa_suite_auth_key_mgmt_t *mgmt;
8671 u16 auth = 0; /* d11 open authentication */
8672 u16 count;
8673 s32 err = BCME_OK;
8674 u32 wme_bss_disable;
8675 u16 suite_count;
8676 u8 rsn_cap[2];
8677 s32 len = 0;
8678 u32 i;
8679 u32 wsec1, wsec2, wsec;
8680 u32 pval = 0;
8681 u32 gval = 0;
8682 u32 wpa_auth = 0;
8683 u32 wpa_auth1 = 0;
8684 u32 wpa_auth2 = 0;
8685 u8* ptmp;
8686
8687 if (wpaie == NULL || wpa2ie == NULL)
8688 goto exit;
8689
8690 WL_DBG(("Enter \n"));
8691 len = wpaie->length; /* value length */
8692 len -= WPA_IE_TAG_FIXED_LEN;
8693 /* check for multicast cipher suite */
8694 if (len < WPA_SUITE_LEN) {
8695 WL_INFORM(("no multicast cipher suite\n"));
8696 goto exit;
8697 }
8698
8699 /* pick up multicast cipher */
8700 mcast = (wpa_suite_mcast_t *)&wpaie[1];
8701 len -= WPA_SUITE_LEN;
8702 if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
8703 if (IS_WPA_CIPHER(mcast->type)) {
8704 gval |= wl_get_cipher_type(mcast->type);
8705 }
8706 }
8707 WL_ERR(("\nwpa ie validate\n"));
8708 WL_ERR(("wpa ie mcast cipher = 0x%X\n", gval));
8709
8710 /* Check for unicast suite(s) */
8711 if (len < WPA_IE_SUITE_COUNT_LEN) {
8712 WL_INFORM(("no unicast suite\n"));
8713 goto exit;
8714 }
8715
8716 /* walk thru unicast cipher list and pick up what we recognize */
8717 ucast = (wpa_suite_ucast_t *)&mcast[1];
8718 count = ltoh16_ua(&ucast->count);
8719 len -= WPA_IE_SUITE_COUNT_LEN;
8720 for (i = 0; i < count && len >= WPA_SUITE_LEN;
8721 i++, len -= WPA_SUITE_LEN) {
8722 if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
8723 if (IS_WPA_CIPHER(ucast->list[i].type)) {
8724 pval |= wl_get_cipher_type(ucast->list[i].type);
8725 }
8726 }
8727 }
8728 WL_ERR(("wpa ie ucast count =%d, cipher = 0x%X\n", count, pval));
8729
8730 /* FOR WPS , set SEC_OW_ENABLED */
8731 wsec1 = (pval | gval | SES_OW_ENABLED);
8732 WL_ERR(("wpa ie wsec = 0x%X\n", wsec1));
8733
8734 len -= (count - i) * WPA_SUITE_LEN;
8735 /* Check for auth key management suite(s) */
8736 if (len < WPA_IE_SUITE_COUNT_LEN) {
8737 WL_INFORM((" no auth key mgmt suite\n"));
8738 goto exit;
8739 }
8740 /* walk thru auth management suite list and pick up what we recognize */
8741 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
8742 count = ltoh16_ua(&mgmt->count);
8743 len -= WPA_IE_SUITE_COUNT_LEN;
8744 for (i = 0; i < count && len >= WPA_SUITE_LEN;
8745 i++, len -= WPA_SUITE_LEN) {
8746 if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
8747 if (IS_WPA_AKM(mgmt->list[i].type)) {
8748
8749 wpa_auth1 |= wl_get_suite_auth_key_mgmt_type(mgmt->list[i].type);
8750 }
8751 }
8752
8753 }
8754 WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count, wpa_auth1));
8755 WL_ERR(("\nwpa2 ie validate\n"));
8756
8757 pval = 0;
8758 gval = 0;
8759 len = wpa2ie->len;
8760 /* check the mcast cipher */
8761 mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
8762 ptmp = mcast->oui;
8763 gval = wl_get_cipher_type(ptmp[DOT11_OUI_LEN]);
8764
8765 WL_ERR(("wpa2 ie mcast cipher = 0x%X\n", gval));
8766 if ((len -= WPA_SUITE_LEN) <= 0)
8767 {
8768 WL_ERR(("P:wpa2 ie len[%d]", len));
8769 return BCME_BADLEN;
8770 }
8771
8772 /* check the unicast cipher */
8773 ucast = (wpa_suite_ucast_t *)&mcast[1];
8774 suite_count = ltoh16_ua(&ucast->count);
8775 WL_ERR((" WPA2 ucast cipher count=%d\n", suite_count));
8776 pval |= wl_get_cipher_type(ucast->list[0].type);
8777
8778 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
8779 return BCME_BADLEN;
8780
8781 WL_ERR(("wpa2 ie ucast cipher = 0x%X\n", pval));
8782
8783 /* FOR WPS , set SEC_OW_ENABLED */
8784 wsec2 = (pval | gval | SES_OW_ENABLED);
8785 WL_ERR(("wpa2 ie wsec = 0x%X\n", wsec2));
8786
8787 /* check the AKM */
8788 mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
8789 suite_count = ltoh16_ua(&mgmt->count);
8790 ptmp = (u8 *)&mgmt->list[0];
8791 wpa_auth2 = wl_get_suite_auth2_key_mgmt_type(ptmp[DOT11_OUI_LEN]);
8792 WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count, wpa_auth2));
8793
8794 if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
8795 rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
8796 rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
8797 if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
8798 wme_bss_disable = 0;
8799 } else {
8800 wme_bss_disable = 1;
8801 }
8802 WL_DBG(("P:rsn_cap[0]=[0x%X]:wme_bss_disabled[%d]\n", rsn_cap[0], wme_bss_disable));
8803
8804 /* set wme_bss_disable to sync RSN Capabilities */
8805 err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
8806 if (err < 0) {
8807 WL_ERR(("wme_bss_disable error %d\n", err));
8808 return BCME_ERROR;
8809 }
8810 } else {
8811 WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
8812 }
8813
8814 wsec = (wsec1 | wsec2);
8815 wpa_auth = (wpa_auth1 | wpa_auth2);
8816 WL_ERR(("wpa_wpa2 wsec=0x%X wpa_auth=0x%X\n", wsec, wpa_auth));
8817
8818 /* set auth */
8819 err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
8820 if (err < 0) {
8821 WL_ERR(("auth error %d\n", err));
8822 return BCME_ERROR;
8823 }
8824 /* set wsec */
8825 err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
8826 if (err < 0) {
8827 WL_ERR(("wsec error %d\n", err));
8828 return BCME_ERROR;
8829 }
8830 /* set upper-layer auth */
8831 err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
8832 if (err < 0) {
8833 WL_ERR(("wpa_auth error %d\n", err));
8834 return BCME_ERROR;
8835 }
8836 exit:
8837 return 0;
8838 }
8839 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8840
8841 static s32
8842 wl_cfg80211_bcn_validate_sec(
8843 struct net_device *dev,
8844 struct parsed_ies *ies,
8845 u32 dev_role,
8846 s32 bssidx,
8847 bool privacy)
8848 {
8849 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
8850 wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
8851
8852 if (!bss) {
8853 WL_ERR(("cfgbss is NULL \n"));
8854 return BCME_ERROR;
8855 }
8856
8857 if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
8858 /* For P2P GO, the sec type is WPA2-PSK */
8859 WL_DBG(("P2P GO: validating wpa2_ie"));
8860 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0)
8861 return BCME_ERROR;
8862
8863 } else if (dev_role == NL80211_IFTYPE_AP) {
8864
8865 WL_DBG(("SoftAP: validating security"));
8866 /* If wpa2_ie or wpa_ie is present validate it */
8867
8868 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8869 if ((ies->wpa_ie != NULL && ies->wpa2_ie != NULL)) {
8870 if (wl_validate_wpaie_wpa2ie(dev, ies->wpa_ie, ies->wpa2_ie, bssidx) < 0) {
8871 bss->security_mode = false;
8872 return BCME_ERROR;
8873 }
8874 }
8875 else {
8876 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8877 if ((ies->wpa2_ie || ies->wpa_ie) &&
8878 ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
8879 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
8880 bss->security_mode = false;
8881 return BCME_ERROR;
8882 }
8883
8884 bss->security_mode = true;
8885 if (bss->rsn_ie) {
8886 kfree(bss->rsn_ie);
8887 bss->rsn_ie = NULL;
8888 }
8889 if (bss->wpa_ie) {
8890 kfree(bss->wpa_ie);
8891 bss->wpa_ie = NULL;
8892 }
8893 if (bss->wps_ie) {
8894 kfree(bss->wps_ie);
8895 bss->wps_ie = NULL;
8896 }
8897 if (ies->wpa_ie != NULL) {
8898 /* WPAIE */
8899 bss->rsn_ie = NULL;
8900 bss->wpa_ie = kmemdup(ies->wpa_ie,
8901 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
8902 GFP_KERNEL);
8903 } else if (ies->wpa2_ie != NULL) {
8904 /* RSNIE */
8905 bss->wpa_ie = NULL;
8906 bss->rsn_ie = kmemdup(ies->wpa2_ie,
8907 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
8908 GFP_KERNEL);
8909 }
8910 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
8911 }
8912 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
8913 if (!ies->wpa2_ie && !ies->wpa_ie) {
8914 wl_validate_opensecurity(dev, bssidx, privacy);
8915 bss->security_mode = false;
8916 }
8917
8918 if (ies->wps_ie) {
8919 bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
8920 }
8921 }
8922
8923 return 0;
8924
8925 }
8926
8927 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
8928 static s32 wl_cfg80211_bcn_set_params(
8929 struct cfg80211_ap_settings *info,
8930 struct net_device *dev,
8931 u32 dev_role, s32 bssidx)
8932 {
8933 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
8934 s32 err = BCME_OK;
8935
8936 WL_DBG(("interval (%d) \ndtim_period (%d) \n",
8937 info->beacon_interval, info->dtim_period));
8938
8939 if (info->beacon_interval) {
8940 if ((err = wldev_ioctl_set(dev, WLC_SET_BCNPRD,
8941 &info->beacon_interval, sizeof(s32))) < 0) {
8942 WL_ERR(("Beacon Interval Set Error, %d\n", err));
8943 return err;
8944 }
8945 }
8946
8947 if (info->dtim_period) {
8948 if ((err = wldev_ioctl_set(dev, WLC_SET_DTIMPRD,
8949 &info->dtim_period, sizeof(s32))) < 0) {
8950 WL_ERR(("DTIM Interval Set Error, %d\n", err));
8951 return err;
8952 }
8953 }
8954
8955 if ((info->ssid) && (info->ssid_len > 0) &&
8956 (info->ssid_len <= DOT11_MAX_SSID_LEN)) {
8957 WL_DBG(("SSID (%s) len:%zd \n", info->ssid, info->ssid_len));
8958 if (dev_role == NL80211_IFTYPE_AP) {
8959 /* Store the hostapd SSID */
8960 memset(cfg->hostapd_ssid.SSID, 0x00, DOT11_MAX_SSID_LEN);
8961 memcpy(cfg->hostapd_ssid.SSID, info->ssid, info->ssid_len);
8962 cfg->hostapd_ssid.SSID_len = info->ssid_len;
8963 } else {
8964 /* P2P GO */
8965 memset(cfg->p2p->ssid.SSID, 0x00, DOT11_MAX_SSID_LEN);
8966 memcpy(cfg->p2p->ssid.SSID, info->ssid, info->ssid_len);
8967 cfg->p2p->ssid.SSID_len = info->ssid_len;
8968 }
8969 }
8970
8971 if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE) {
8972 if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
8973 WL_ERR(("failed to set hidden : %d\n", err));
8974 WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
8975 }
8976
8977 return err;
8978 }
8979 #endif
8980
8981 static s32
8982 wl_cfg80211_parse_ies(u8 *ptr, u32 len, struct parsed_ies *ies)
8983 {
8984 s32 err = BCME_OK;
8985
8986 memset(ies, 0, sizeof(struct parsed_ies));
8987
8988 /* find the WPSIE */
8989 if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
8990 WL_DBG(("WPSIE in beacon \n"));
8991 ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
8992 } else {
8993 WL_DBG(("No WPSIE in beacon \n"));
8994 }
8995
8996 /* find the RSN_IE */
8997 if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
8998 DOT11_MNG_RSN_ID)) != NULL) {
8999 WL_DBG((" WPA2 IE found\n"));
9000 ies->wpa2_ie_len = ies->wpa2_ie->len;
9001 }
9002
9003 /* find the WPA_IE */
9004 if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
9005 WL_DBG((" WPA found\n"));
9006 ies->wpa_ie_len = ies->wpa_ie->length;
9007 }
9008
9009 return err;
9010
9011 }
9012 static s32
9013 wl_cfg80211_set_ap_role(
9014 struct bcm_cfg80211 *cfg,
9015 struct net_device *dev)
9016 {
9017 s32 err = BCME_OK;
9018 s32 infra = 1;
9019 s32 ap = 1;
9020 s32 pm;
9021 s32 is_rsdb_supported = BCME_ERROR;
9022 s32 bssidx;
9023 s32 apsta = 0;
9024
9025 is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
9026 if (is_rsdb_supported < 0)
9027 return (-ENODEV);
9028
9029 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
9030 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
9031 return -EINVAL;
9032 }
9033
9034 /* AP on primary Interface */
9035 if (bssidx == 0) {
9036 if (is_rsdb_supported) {
9037 if ((err = wl_cfg80211_add_del_bss(cfg, dev, bssidx,
9038 NL80211_IFTYPE_AP, 0, NULL)) < 0) {
9039 WL_ERR(("wl add_del_bss returned error:%d\n", err));
9040 return err;
9041 }
9042 } else if (is_rsdb_supported == 0) {
9043 /* AP mode switch not supported. Try setting up AP explicitly */
9044 err = wldev_iovar_getint(dev, "apsta", (s32 *)&apsta);
9045 if (unlikely(err)) {
9046 WL_ERR(("Could not get apsta %d\n", err));
9047 }
9048 if (1) { // terence: fix me
9049 /* If apsta is not set, set it */
9050 err = wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
9051 if (err < 0) {
9052 WL_ERR(("WLC_DOWN error %d\n", err));
9053 return err;
9054 }
9055 err = wldev_iovar_setint(dev, "apsta", 0);
9056 if (err < 0) {
9057 WL_ERR(("wl apsta 0 error %d\n", err));
9058 return err;
9059 }
9060 if ((err = wldev_ioctl_set(dev,
9061 WLC_SET_AP, &ap, sizeof(s32))) < 0) {
9062 WL_ERR(("setting AP mode failed %d \n", err));
9063 return err;
9064 }
9065 }
9066 }
9067
9068 pm = 0;
9069 if ((err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm))) != 0) {
9070 WL_ERR(("wl PM 0 returned error:%d\n", err));
9071 /* Ignore error, if any */
9072 err = BCME_OK;
9073 }
9074 err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
9075 if (err < 0) {
9076 WL_ERR(("SET INFRA error %d\n", err));
9077 return err;
9078 }
9079 } else {
9080 WL_DBG(("Bringup SoftAP on virtual Interface bssidx:%d \n", bssidx));
9081 if ((err = wl_cfg80211_add_del_bss(cfg, dev,
9082 bssidx, NL80211_IFTYPE_AP, 0, NULL)) < 0) {
9083 WL_ERR(("wl bss ap returned error:%d\n", err));
9084 return err;
9085 }
9086 }
9087
9088 /* On success, mark AP creation in progress. */
9089 wl_set_drv_status(cfg, AP_CREATING, dev);
9090 return 0;
9091 }
9092
9093
9094 /* In RSDB downgrade cases, the link up event can get delayed upto 7-8 secs */
9095 #define MAX_AP_LINK_WAIT_TIME 10000
9096 static s32
9097 wl_cfg80211_bcn_bringup_ap(
9098 struct net_device *dev,
9099 struct parsed_ies *ies,
9100 u32 dev_role, s32 bssidx)
9101 {
9102 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
9103 struct wl_join_params join_params;
9104 bool is_bssup = false;
9105 s32 infra = 1;
9106 s32 join_params_size = 0;
9107 s32 ap = 1;
9108 s32 wsec;
9109 #ifdef WLMESH
9110 bool retried = false;
9111 #endif
9112 #ifdef SOFTAP_UAPSD_OFF
9113 uint32 wme_apsd = 0;
9114 #endif /* SOFTAP_UAPSD_OFF */
9115 s32 err = BCME_OK;
9116 s32 is_rsdb_supported = BCME_ERROR;
9117 u32 timeout;
9118 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
9119 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
9120 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
9121
9122 is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
9123 if (is_rsdb_supported < 0)
9124 return (-ENODEV);
9125
9126 WL_DBG(("Enter dev_role:%d bssidx:%d ifname:%s\n", dev_role, bssidx, dev->name));
9127
9128 /* Common code for SoftAP and P2P GO */
9129 wl_clr_drv_status(cfg, AP_CREATED, dev);
9130
9131 /* Make sure INFRA is set for AP/GO */
9132 err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
9133 if (err < 0) {
9134 WL_ERR(("SET INFRA error %d\n", err));
9135 goto exit;
9136 }
9137
9138 /* Do abort scan before creating GO */
9139 wl_cfg80211_scan_abort(cfg);
9140
9141 if (dev_role == NL80211_IFTYPE_P2P_GO) {
9142 is_bssup = wl_cfg80211_bss_isup(dev, bssidx);
9143 if (!is_bssup && (ies->wpa2_ie != NULL)) {
9144
9145 err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &cfg->p2p->ssid,
9146 sizeof(cfg->p2p->ssid), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
9147 bssidx, &cfg->ioctl_buf_sync);
9148 if (err < 0) {
9149 WL_ERR(("GO SSID setting error %d\n", err));
9150 goto exit;
9151 }
9152
9153 if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 1)) < 0) {
9154 WL_ERR(("GO Bring up error %d\n", err));
9155 goto exit;
9156 }
9157 } else
9158 WL_DBG(("Bss is already up\n"));
9159 } else if (dev_role == NL80211_IFTYPE_AP) {
9160
9161 // if (!wl_get_drv_status(cfg, AP_CREATING, dev)) {
9162 /* Make sure fw is in proper state */
9163 err = wl_cfg80211_set_ap_role(cfg, dev);
9164 if (unlikely(err)) {
9165 WL_ERR(("set ap role failed!\n"));
9166 goto exit;
9167 }
9168 // }
9169
9170 /* Device role SoftAP */
9171 WL_DBG(("Creating AP bssidx:%d dev_role:%d\n", bssidx, dev_role));
9172 /* Clear the status bit after use */
9173 wl_clr_drv_status(cfg, AP_CREATING, dev);
9174
9175
9176 #ifdef SOFTAP_UAPSD_OFF
9177 err = wldev_iovar_setbuf_bsscfg(dev, "wme_apsd", &wme_apsd, sizeof(wme_apsd),
9178 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
9179 if (err < 0) {
9180 WL_ERR(("failed to disable uapsd, error=%d\n", err));
9181 }
9182 #endif /* SOFTAP_UAPSD_OFF */
9183 dhd_conf_set_wme(cfg->pub, 1);
9184
9185 err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
9186 if (unlikely(err)) {
9187 WL_ERR(("WLC_UP error (%d)\n", err));
9188 goto exit;
9189 }
9190
9191 #ifdef MFP
9192 if (cfg->bip_pos) {
9193 err = wldev_iovar_setbuf_bsscfg(dev, "bip",
9194 (void *)(cfg->bip_pos), WPA_SUITE_LEN, cfg->ioctl_buf,
9195 WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
9196 if (err < 0) {
9197 WL_ERR(("bip set error %d\n", err));
9198 if (wl_customer6_legacy_chip_check(cfg,
9199 bcmcfg_to_prmry_ndev(cfg))) {
9200 /* Ignore bip error: Some older firmwares doesn't
9201 * support bip iovar/ return BCME_NOTUP while trying
9202 * to set bip from AP bring up context. These firmares
9203 * include bip in RSNIE by default. So its okay to ignore
9204 * the error.
9205 */
9206 err = BCME_OK;
9207 } else {
9208 goto exit;
9209 }
9210 }
9211 }
9212 #endif /* MFP */
9213
9214 err = wldev_iovar_getint(dev, "wsec", (s32 *)&wsec);
9215 if (unlikely(err)) {
9216 WL_ERR(("Could not get wsec %d\n", err));
9217 goto exit;
9218 }
9219 if ((wsec == WEP_ENABLED) && cfg->wep_key.len) {
9220 WL_DBG(("Applying buffered WEP KEY \n"));
9221 err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &cfg->wep_key,
9222 sizeof(struct wl_wsec_key), cfg->ioctl_buf,
9223 WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
9224 /* clear the key after use */
9225 memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
9226 if (unlikely(err)) {
9227 WL_ERR(("WLC_SET_KEY error (%d)\n", err));
9228 goto exit;
9229 }
9230 }
9231
9232 #ifdef MFP
9233 if (cfg->mfp_mode) {
9234 /* This needs to go after wsec otherwise the wsec command will
9235 * overwrite the values set by MFP
9236 */
9237 err = wldev_iovar_setint_bsscfg(dev, "mfp", cfg->mfp_mode, bssidx);
9238 if (err < 0) {
9239 WL_ERR(("MFP Setting failed. ret = %d \n", err));
9240 /* If fw doesn't support mfp, Ignore the error */
9241 if (err != BCME_UNSUPPORTED) {
9242 goto exit;
9243 }
9244 }
9245 }
9246 #endif /* MFP */
9247
9248 #ifdef WLMESH
9249 ssid_retry:
9250 #endif
9251 memset(&join_params, 0, sizeof(join_params));
9252 /* join parameters starts with ssid */
9253 join_params_size = sizeof(join_params.ssid);
9254 join_params.ssid.SSID_len = MIN(cfg->hostapd_ssid.SSID_len,
9255 (uint32)DOT11_MAX_SSID_LEN);
9256 memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
9257 join_params.ssid.SSID_len);
9258 join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
9259
9260 /* create softap */
9261 if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
9262 join_params_size)) != 0) {
9263 WL_ERR(("SoftAP/GO set ssid failed! %d\n", err));
9264 goto exit;
9265 } else {
9266 WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
9267 }
9268
9269 if (bssidx != 0) {
9270 /* AP on Virtual Interface */
9271 if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 1)) < 0) {
9272 WL_ERR(("AP Bring up error %d\n", err));
9273 goto exit;
9274 }
9275 }
9276
9277 }
9278
9279 /* Wait for Linkup event to mark successful AP/GO bring up */
9280 timeout = wait_event_interruptible_timeout(cfg->netif_change_event,
9281 wl_get_drv_status(cfg, AP_CREATED, dev), msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
9282 if (timeout <= 0 || !wl_get_drv_status(cfg, AP_CREATED, dev)) {
9283 #ifdef WLMESH
9284 if (!retried) {
9285 retried = true;
9286 WL_ERR(("Link up didn't come for AP interface. Try to set ssid again to recover it! \n"));
9287 goto ssid_retry;
9288 }
9289 #endif
9290 WL_ERR(("Link up didn't come for AP interface. AP/GO creation failed! \n"));
9291 if (timeout == -ERESTARTSYS) {
9292 WL_ERR(("waitqueue was interrupted by a signal, returns -ERESTARTSYS\n"));
9293 err = -ERESTARTSYS;
9294 goto exit;
9295 }
9296 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
9297 if (dhdp->memdump_enabled) {
9298 dhdp->memdump_type = DUMP_TYPE_AP_LINKUP_FAILURE;
9299 dhd_bus_mem_dump(dhdp);
9300 }
9301 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
9302 err = -ENODEV;
9303 goto exit;
9304 }
9305
9306 exit:
9307 if (cfg->wep_key.len) {
9308 memset(&cfg->wep_key, 0, sizeof(struct wl_wsec_key));
9309 }
9310
9311 #ifdef MFP
9312 if (cfg->mfp_mode) {
9313 cfg->mfp_mode = 0;
9314 }
9315
9316 if (cfg->bip_pos) {
9317 cfg->bip_pos = NULL;
9318 }
9319 #endif /* MFP */
9320
9321 return err;
9322 }
9323
9324 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9325 s32
9326 wl_cfg80211_parse_ap_ies(
9327 struct net_device *dev,
9328 struct cfg80211_beacon_data *info,
9329 struct parsed_ies *ies)
9330 {
9331 struct parsed_ies prb_ies;
9332 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
9333 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
9334 const u8 *vndr = NULL;
9335 u32 vndr_ie_len = 0;
9336 s32 err = BCME_OK;
9337
9338 /* Parse Beacon IEs */
9339 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9340 #pragma GCC diagnostic push
9341 #pragma GCC diagnostic ignored "-Wcast-qual"
9342 #endif
9343 if (wl_cfg80211_parse_ies((u8 *)info->tail,
9344 info->tail_len, ies) < 0) {
9345 WL_ERR(("Beacon get IEs failed \n"));
9346 err = -EINVAL;
9347 goto fail;
9348 }
9349 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9350 #pragma GCC diagnostic pop
9351 #endif
9352 vndr = (const u8 *)info->proberesp_ies;
9353 vndr_ie_len = info->proberesp_ies_len;
9354
9355 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
9356 /* SoftAP mode */
9357 const struct ieee80211_mgmt *mgmt;
9358 mgmt = (const struct ieee80211_mgmt *)info->probe_resp;
9359 if (mgmt != NULL) {
9360 vndr = (const u8 *)&mgmt->u.probe_resp.variable;
9361 vndr_ie_len = info->probe_resp_len -
9362 offsetof(const struct ieee80211_mgmt, u.probe_resp.variable);
9363 }
9364 }
9365 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9366 #pragma GCC diagnostic push
9367 #pragma GCC diagnostic ignored "-Wcast-qual"
9368 #endif
9369 /* Parse Probe Response IEs */
9370 if (wl_cfg80211_parse_ies((u8 *)vndr, vndr_ie_len, &prb_ies) < 0) {
9371 WL_ERR(("PROBE RESP get IEs failed \n"));
9372 err = -EINVAL;
9373 }
9374 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
9375 #pragma GCC diagnostic pop
9376 #endif
9377 fail:
9378
9379 return err;
9380 }
9381
9382 s32
9383 wl_cfg80211_set_ies(
9384 struct net_device *dev,
9385 struct cfg80211_beacon_data *info,
9386 s32 bssidx)
9387 {
9388 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
9389 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
9390 const u8 *vndr = NULL;
9391 u32 vndr_ie_len = 0;
9392 s32 err = BCME_OK;
9393
9394 /* Set Beacon IEs to FW */
9395 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
9396 VNDR_IE_BEACON_FLAG, (const u8 *)info->tail,
9397 info->tail_len)) < 0) {
9398 WL_ERR(("Set Beacon IE Failed \n"));
9399 } else {
9400 WL_DBG(("Applied Vndr IEs for Beacon \n"));
9401 }
9402
9403 vndr = (const u8 *)info->proberesp_ies;
9404 vndr_ie_len = info->proberesp_ies_len;
9405
9406 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
9407 /* SoftAP mode */
9408 const struct ieee80211_mgmt *mgmt;
9409 mgmt = (const struct ieee80211_mgmt *)info->probe_resp;
9410 if (mgmt != NULL) {
9411 vndr = (const u8 *)&mgmt->u.probe_resp.variable;
9412 vndr_ie_len = info->probe_resp_len -
9413 offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
9414 }
9415 }
9416
9417 /* Set Probe Response IEs to FW */
9418 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
9419 VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
9420 WL_ERR(("Set Probe Resp IE Failed \n"));
9421 } else {
9422 WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
9423 }
9424
9425 return err;
9426 }
9427 #endif
9428
9429 static s32 wl_cfg80211_hostapd_sec(
9430 struct net_device *dev,
9431 struct parsed_ies *ies,
9432 s32 bssidx)
9433 {
9434 bool update_bss = 0;
9435 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
9436 wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
9437
9438 if (!bss) {
9439 WL_ERR(("cfgbss is NULL \n"));
9440 return -EINVAL;
9441 }
9442
9443 if (ies->wps_ie) {
9444 if (bss->wps_ie &&
9445 memcmp(bss->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
9446 WL_DBG((" WPS IE is changed\n"));
9447 kfree(bss->wps_ie);
9448 bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
9449 } else if (bss->wps_ie == NULL) {
9450 WL_DBG((" WPS IE is added\n"));
9451 bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
9452 }
9453
9454 if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
9455 if (!bss->security_mode) {
9456 /* change from open mode to security mode */
9457 update_bss = true;
9458 if (ies->wpa_ie != NULL) {
9459 bss->wpa_ie = kmemdup(ies->wpa_ie,
9460 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
9461 GFP_KERNEL);
9462 } else {
9463 bss->rsn_ie = kmemdup(ies->wpa2_ie,
9464 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
9465 GFP_KERNEL);
9466 }
9467 } else if (bss->wpa_ie) {
9468 /* change from WPA2 mode to WPA mode */
9469 if (ies->wpa_ie != NULL) {
9470 update_bss = true;
9471 kfree(bss->rsn_ie);
9472 bss->rsn_ie = NULL;
9473 bss->wpa_ie = kmemdup(ies->wpa_ie,
9474 ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
9475 GFP_KERNEL);
9476 } else if (memcmp(bss->rsn_ie,
9477 ies->wpa2_ie, ies->wpa2_ie->len
9478 + WPA_RSN_IE_TAG_FIXED_LEN)) {
9479 update_bss = true;
9480 kfree(bss->rsn_ie);
9481 bss->rsn_ie = kmemdup(ies->wpa2_ie,
9482 ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
9483 GFP_KERNEL);
9484 bss->wpa_ie = NULL;
9485 }
9486 }
9487 if (update_bss) {
9488 bss->security_mode = true;
9489 wl_cfg80211_bss_up(cfg, dev, bssidx, 0);
9490 if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx) < 0 ||
9491 wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
9492 return BCME_ERROR;
9493 }
9494 wl_cfg80211_bss_up(cfg, dev, bssidx, 1);
9495 }
9496 }
9497 } else {
9498 WL_ERR(("No WPSIE in beacon \n"));
9499 }
9500 return 0;
9501 }
9502
9503 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
9504 2, 0))
9505 static s32
9506 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9507 wl_cfg80211_del_station(
9508 struct wiphy *wiphy, struct net_device *ndev,
9509 struct station_del_parameters *params)
9510 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9511 wl_cfg80211_del_station(
9512 struct wiphy *wiphy,
9513 struct net_device *ndev,
9514 const u8* mac_addr)
9515 #else
9516 wl_cfg80211_del_station(
9517 struct wiphy *wiphy,
9518 struct net_device *ndev,
9519 u8* mac_addr)
9520 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9521 {
9522 struct net_device *dev;
9523 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
9524 scb_val_t scb_val;
9525 s8 eabuf[ETHER_ADDR_STR_LEN];
9526 int err;
9527 char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV *
9528 sizeof(struct ether_addr) + sizeof(uint)] = {0};
9529 struct maclist *assoc_maclist = (struct maclist *)mac_buf;
9530 int num_associated = 0;
9531
9532 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9533 const u8 *mac_addr = params->mac;
9534 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9535 u16 rc = params->reason_code;
9536 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9537 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9538
9539 WL_DBG(("Entry\n"));
9540 if (mac_addr == NULL) {
9541 WL_DBG(("mac_addr is NULL ignore it\n"));
9542 return 0;
9543 }
9544
9545 dev = ndev_to_wlc_ndev(ndev, cfg);
9546
9547 if (p2p_is_on(cfg)) {
9548 /* Suspend P2P discovery search-listen to prevent it from changing the
9549 * channel.
9550 */
9551 if ((wl_cfgp2p_discover_enable_search(cfg, false)) < 0) {
9552 WL_ERR(("Can not disable discovery mode\n"));
9553 return -EFAULT;
9554 }
9555 }
9556 err = wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS,
9557 WL_EXT_STATUS_DELETE_GC, (void *)mac_addr);
9558 if (err) {
9559 return 0;
9560 }
9561
9562 assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV;
9563 err = wldev_ioctl_get(ndev, WLC_GET_ASSOCLIST,
9564 assoc_maclist, sizeof(mac_buf));
9565 if (err < 0)
9566 WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err));
9567 else
9568 num_associated = assoc_maclist->count;
9569
9570 memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN);
9571 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9572 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9573 if (rc == DOT11_RC_8021X_AUTH_FAIL) {
9574 WL_ERR(("deauth will be sent at F/W\n"));
9575 scb_val.val = DOT11_RC_8021X_AUTH_FAIL;
9576 } else {
9577 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9578 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9579 #ifndef BCMDBUS
9580 dhd_wait_pend8021x(dev);
9581 #endif /* !BCMDBUS */
9582 scb_val.val = DOT11_RC_DEAUTH_LEAVING;
9583 err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
9584 sizeof(scb_val_t));
9585 if (err < 0)
9586 WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
9587 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
9588 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
9589 }
9590 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
9591 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
9592 printf("%s: Disconnect STA : %s scb_val.val %d\n", __FUNCTION__,
9593 bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf),
9594 scb_val.val);
9595
9596 if (num_associated > 0 && ETHER_ISBCAST(mac_addr))
9597 wl_delay(400);
9598
9599 return 0;
9600 }
9601
9602 static s32
9603 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9604 wl_cfg80211_change_station(
9605 struct wiphy *wiphy,
9606 struct net_device *dev,
9607 const u8 *mac,
9608 struct station_parameters *params)
9609 #else
9610 wl_cfg80211_change_station(
9611 struct wiphy *wiphy,
9612 struct net_device *dev,
9613 u8 *mac,
9614 struct station_parameters *params)
9615 #endif
9616 {
9617 int err;
9618 #if defined(WL_ENABLE_P2P_IF)
9619 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
9620 #endif
9621 struct net_device *ndev = ndev_to_wlc_ndev(dev, cfg);
9622
9623 WL_DBG(("SCB_AUTHORIZE mac_addr:"MACDBG" sta_flags_mask:0x%x "
9624 "sta_flags_set:0x%x iface:%s \n", MAC2STRDBG(mac),
9625 params->sta_flags_mask, params->sta_flags_set, ndev->name));
9626
9627 /* Processing only authorize/de-authorize flag for now */
9628 if (!(params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
9629 WL_ERR(("WLC_SCB_AUTHORIZE sta_flags_mask not set \n"));
9630 return -ENOTSUPP;
9631 }
9632
9633 if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED))) {
9634 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9635 err = wldev_ioctl_set(ndev, WLC_SCB_DEAUTHORIZE, (u8 *)mac, ETH_ALEN);
9636 #else
9637 err = wldev_ioctl_set(ndev, WLC_SCB_DEAUTHORIZE, mac, ETH_ALEN);
9638 #endif
9639 if (err)
9640 WL_ERR(("WLC_SCB_DEAUTHORIZE error (%d)\n", err));
9641 return err;
9642 }
9643
9644 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
9645 err = wldev_ioctl_set(ndev, WLC_SCB_AUTHORIZE, (u8 *)mac, ETH_ALEN);
9646 #else
9647 err = wldev_ioctl_set(ndev, WLC_SCB_AUTHORIZE, mac, ETH_ALEN);
9648 #endif
9649 if (err)
9650 WL_ERR(("WLC_SCB_AUTHORIZE error (%d)\n", err));
9651 #ifdef DHD_LOSSLESS_ROAMING
9652 wl_del_roam_timeout(cfg);
9653 #endif
9654 return err;
9655 }
9656 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */
9657
9658 static s32
9659 wl_cfg80211_set_scb_timings(
9660 struct bcm_cfg80211 *cfg,
9661 struct net_device *dev)
9662 {
9663 int err;
9664 u32 ps_pretend;
9665 wl_scb_probe_t scb_probe;
9666
9667 bzero(&scb_probe, sizeof(wl_scb_probe_t));
9668 scb_probe.scb_timeout = WL_SCB_TIMEOUT;
9669 scb_probe.scb_activity_time = WL_SCB_ACTIVITY_TIME;
9670 scb_probe.scb_max_probe = WL_SCB_MAX_PROBE;
9671 err = wldev_iovar_setbuf(dev, "scb_probe", (void *)&scb_probe,
9672 sizeof(wl_scb_probe_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
9673 &cfg->ioctl_buf_sync);
9674 if (unlikely(err)) {
9675 WL_ERR(("set 'scb_probe' failed, error = %d\n", err));
9676 return err;
9677 }
9678
9679 ps_pretend = MAX(WL_SCB_MAX_PROBE / 2, WL_MIN_PSPRETEND_THRESHOLD);
9680 err = wldev_iovar_setint(dev, "pspretend_threshold", ps_pretend);
9681 if (unlikely(err)) {
9682 if (err == BCME_UNSUPPORTED) {
9683 /* Ignore error if fw doesn't support the iovar */
9684 WL_DBG(("wl pspretend_threshold %d set error %d\n",
9685 ps_pretend, err));
9686 } else {
9687 WL_ERR(("wl pspretend_threshold %d set error %d\n",
9688 ps_pretend, err));
9689 return err;
9690 }
9691 }
9692
9693 return 0;
9694 }
9695
9696 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
9697 static s32
9698 wl_cfg80211_start_ap(
9699 struct wiphy *wiphy,
9700 struct net_device *dev,
9701 struct cfg80211_ap_settings *info)
9702 {
9703 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
9704 s32 err = BCME_OK;
9705 struct parsed_ies ies;
9706 s32 bssidx = 0;
9707 u32 dev_role = 0;
9708 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
9709 #ifdef WLMESH
9710 struct wl_join_params join_params;
9711 s32 join_params_size = 0;
9712 #endif
9713
9714 WL_DBG(("Enter \n"));
9715
9716 #if defined(SUPPORT_RANDOM_MAC_SCAN)
9717 wl_cfg80211_set_random_mac(dev, FALSE);
9718 #endif /* SUPPORT_RANDOM_MAC_SCAN */
9719
9720 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
9721 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
9722 return BCME_ERROR;
9723 }
9724
9725 if (p2p_is_on(cfg) && (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) {
9726 dev_role = NL80211_IFTYPE_P2P_GO;
9727 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
9728 dev_role = NL80211_IFTYPE_AP;
9729 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
9730 err = dhd_ndo_enable(dhd, FALSE);
9731 WL_DBG(("%s: Disabling NDO on Hostapd mode %d\n", __FUNCTION__, err));
9732 if (err) {
9733 WL_ERR(("%s: Disabling NDO Failed %d\n", __FUNCTION__, err));
9734 }
9735 #ifdef PKT_FILTER_SUPPORT
9736 /* Disable packet filter */
9737 if (dhd->early_suspended) {
9738 WL_ERR(("Disable pkt_filter\n"));
9739 dhd_enable_packet_filter(0, dhd);
9740 }
9741 #endif /* PKT_FILTER_SUPPORT */
9742 #ifdef ARP_OFFLOAD_SUPPORT
9743 /* IF SoftAP is enabled, disable arpoe */
9744 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
9745 dhd_arp_offload_set(dhd, 0);
9746 dhd_arp_offload_enable(dhd, FALSE);
9747 }
9748 #endif /* ARP_OFFLOAD_SUPPORT */
9749 #ifdef SUPPORT_SET_CAC
9750 wl_cfg80211_set_cac(cfg, 0);
9751 #endif /* SUPPORT_SET_CAC */
9752 } else {
9753 /* only AP or GO role need to be handled here. */
9754 err = -EINVAL;
9755 goto fail;
9756 }
9757
9758 /* disable TDLS */
9759 #ifdef WLTDLS
9760 if (bssidx == 0) {
9761 /* Disable TDLS for primary Iface. For virtual interface,
9762 * tdls disable will happen from interface create context
9763 */
9764 wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_CREATE, false);
9765 }
9766 #endif /* WLTDLS */
9767
9768 if (!check_dev_role_integrity(cfg, dev_role)) {
9769 err = -EINVAL;
9770 goto fail;
9771 }
9772
9773 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
9774 if ((err = wl_cfg80211_set_channel(wiphy, dev,
9775 dev->ieee80211_ptr->preset_chandef.chan,
9776 NL80211_CHAN_HT20) < 0)) {
9777 WL_ERR(("Set channel failed \n"));
9778 goto fail;
9779 }
9780 #endif
9781
9782 if ((err = wl_cfg80211_bcn_set_params(info, dev,
9783 dev_role, bssidx)) < 0) {
9784 WL_ERR(("Beacon params set failed \n"));
9785 goto fail;
9786 }
9787
9788 /* Parse IEs */
9789 if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
9790 WL_ERR(("Set IEs failed \n"));
9791 goto fail;
9792 }
9793
9794 if ((err = wl_cfg80211_bcn_validate_sec(dev, &ies,
9795 dev_role, bssidx, info->privacy)) < 0)
9796 {
9797 WL_ERR(("Beacon set security failed \n"));
9798 goto fail;
9799 }
9800
9801 if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
9802 dev_role, bssidx)) < 0) {
9803 WL_ERR(("Beacon bring up AP/GO failed \n"));
9804 goto fail;
9805 }
9806
9807 /* Set GC/STA SCB expiry timings. */
9808 if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
9809 WL_ERR(("scb setting failed \n"));
9810 // goto fail;
9811 }
9812
9813 #ifdef WLMESH
9814 OSL_SLEEP(1000);
9815 if ((dev_role == NL80211_IFTYPE_P2P_GO) || (dev_role == NL80211_IFTYPE_AP)) {
9816 memset(&join_params, 0, sizeof(join_params));
9817 /* join parameters starts with ssid */
9818 join_params_size = sizeof(join_params.ssid);
9819 if (dev_role == NL80211_IFTYPE_P2P_GO) {
9820 join_params.ssid.SSID_len = min(cfg->p2p->ssid.SSID_len,
9821 (uint32)DOT11_MAX_SSID_LEN);
9822 memcpy(join_params.ssid.SSID, cfg->p2p->ssid.SSID,
9823 join_params.ssid.SSID_len);
9824 } else if (dev_role == NL80211_IFTYPE_AP) {
9825 join_params.ssid.SSID_len = min(cfg->hostapd_ssid.SSID_len,
9826 (uint32)DOT11_MAX_SSID_LEN);
9827 memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
9828 join_params.ssid.SSID_len);
9829 }
9830 join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
9831 /* create softap */
9832 if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
9833 join_params_size)) != 0) {
9834 WL_ERR(("SoftAP/GO set ssid failed! \n"));
9835 goto fail;
9836 } else {
9837 WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
9838 }
9839 }
9840 #endif
9841
9842 WL_DBG(("** AP/GO Created **\n"));
9843
9844 #ifdef WL_CFG80211_ACL
9845 /* Enfoce Admission Control. */
9846 if ((err = wl_cfg80211_set_mac_acl(wiphy, dev, info->acl)) < 0) {
9847 WL_ERR(("Set ACL failed\n"));
9848 }
9849 #endif /* WL_CFG80211_ACL */
9850
9851 /* Set IEs to FW */
9852 if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
9853 WL_ERR(("Set IEs failed \n"));
9854
9855 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
9856 if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
9857 bool pbc = 0;
9858 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
9859 if (pbc) {
9860 WL_DBG(("set WLC_E_PROBREQ_MSG\n"));
9861 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
9862 }
9863 }
9864
9865 #ifdef SUPPORT_AP_RADIO_PWRSAVE
9866 if ((dev_role == NL80211_IFTYPE_AP)) {
9867 wl_set_ap_rps(dev, FALSE, dev->name);
9868 wl_cfg80211_init_ap_rps(cfg);
9869 }
9870 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
9871 fail:
9872 if (err) {
9873 WL_ERR(("ADD/SET beacon failed\n"));
9874 wl_cfg80211_stop_ap(wiphy, dev);
9875 if (dev_role == NL80211_IFTYPE_AP) {
9876 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
9877 #ifdef PKT_FILTER_SUPPORT
9878 /* Enable packet filter */
9879 if (dhd->early_suspended) {
9880 WL_ERR(("Enable pkt_filter\n"));
9881 dhd_enable_packet_filter(1, dhd);
9882 }
9883 #endif /* PKT_FILTER_SUPPORT */
9884 #ifdef ARP_OFFLOAD_SUPPORT
9885 /* IF SoftAP is disabled, enable arpoe back for STA mode. */
9886 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
9887 dhd_arp_offload_set(dhd, dhd_arp_mode);
9888 dhd_arp_offload_enable(dhd, TRUE);
9889 }
9890 #endif /* ARP_OFFLOAD_SUPPORT */
9891 }
9892 #ifdef WLTDLS
9893 if (bssidx == 0) {
9894 /* Since AP creation failed, re-enable TDLS */
9895 wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_DELETE, false);
9896 }
9897 #endif /* WLTDLS */
9898
9899 }
9900
9901 return err;
9902 }
9903
9904 static s32
9905 wl_cfg80211_stop_ap(
9906 struct wiphy *wiphy,
9907 struct net_device *dev)
9908 {
9909 int err = 0;
9910 u32 dev_role = 0;
9911 int ap = 0;
9912 s32 bssidx = 0;
9913 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
9914 s32 is_rsdb_supported = BCME_ERROR;
9915 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
9916
9917 WL_DBG(("Enter \n"));
9918
9919 is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
9920 if (is_rsdb_supported < 0)
9921 return (-ENODEV);
9922
9923 wl_clr_drv_status(cfg, AP_CREATING, dev);
9924 wl_clr_drv_status(cfg, AP_CREATED, dev);
9925 cfg->ap_oper_channel = 0;
9926
9927 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
9928 dev_role = NL80211_IFTYPE_AP;
9929 WL_DBG(("stopping AP operation\n"));
9930 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
9931 dev_role = NL80211_IFTYPE_P2P_GO;
9932 WL_DBG(("stopping P2P GO operation\n"));
9933 } else {
9934 WL_ERR(("no AP/P2P GO interface is operational.\n"));
9935 return -EINVAL;
9936 }
9937
9938 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
9939 WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
9940 return BCME_ERROR;
9941 }
9942
9943 if (!check_dev_role_integrity(cfg, dev_role)) {
9944 WL_ERR(("role integrity check failed \n"));
9945 err = -EINVAL;
9946 goto exit;
9947 }
9948
9949 /* Clear AP/GO connected status */
9950 wl_clr_drv_status(cfg, CONNECTED, dev);
9951 if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 0)) < 0) {
9952 WL_ERR(("bss down error %d\n", err));
9953 }
9954
9955 if (dev_role == NL80211_IFTYPE_AP) {
9956 #ifdef PKT_FILTER_SUPPORT
9957 /* Enable packet filter */
9958 if (dhd->early_suspended) {
9959 WL_ERR(("Enable pkt_filter\n"));
9960 dhd_enable_packet_filter(1, dhd);
9961 }
9962 #endif /* PKT_FILTER_SUPPORT */
9963 #ifdef ARP_OFFLOAD_SUPPORT
9964 /* IF SoftAP is disabled, enable arpoe back for STA mode. */
9965 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
9966 dhd_arp_offload_set(dhd, dhd_arp_mode);
9967 dhd_arp_offload_enable(dhd, TRUE);
9968 }
9969 #endif /* ARP_OFFLOAD_SUPPORT */
9970
9971 if (is_rsdb_supported == 0) {
9972 if (dhd_download_fw_on_driverload && bssidx == 0) {
9973 wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
9974 wldev_iovar_setint(dev, "apsta", 1);
9975 }
9976 /* For non-rsdb chips, we use stand alone AP. Do wl down on stop AP */
9977 err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
9978 if (unlikely(err)) {
9979 WL_ERR(("WLC_UP error (%d)\n", err));
9980 err = -EINVAL;
9981 goto exit;
9982 }
9983 }
9984
9985 wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
9986 #ifdef SUPPORT_AP_RADIO_PWRSAVE
9987 wl_set_ap_rps(dev, FALSE, dev->name);
9988 wl_cfg80211_init_ap_rps(cfg);
9989 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
9990 } else {
9991 WL_DBG(("Stopping P2P GO \n"));
9992 DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(cfg->pub),
9993 DHD_EVENT_TIMEOUT_MS*3);
9994 DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub));
9995 }
9996 exit:
9997 #ifdef WLTDLS
9998 if (bssidx == 0) {
9999 /* re-enable TDLS if the number of connected interfaces is less than 2 */
10000 wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_DELETE, false);
10001 }
10002 #endif /* WLTDLS */
10003
10004 if (dev_role == NL80211_IFTYPE_AP) {
10005 /* clear the AP mode */
10006 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
10007 }
10008 #ifdef SUPPORT_SET_CAC
10009 wl_cfg80211_set_cac(cfg, 1);
10010 #endif /* SUPPORT_SET_CAC */
10011 return err;
10012 }
10013
10014 static s32
10015 wl_cfg80211_change_beacon(
10016 struct wiphy *wiphy,
10017 struct net_device *dev,
10018 struct cfg80211_beacon_data *info)
10019 {
10020 s32 err = BCME_OK;
10021 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10022 struct parsed_ies ies;
10023 u32 dev_role = 0;
10024 s32 bssidx = 0;
10025 bool pbc = 0;
10026
10027 WL_DBG(("Enter \n"));
10028
10029 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
10030 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
10031 return BCME_ERROR;
10032 }
10033
10034 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
10035 dev_role = NL80211_IFTYPE_P2P_GO;
10036 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
10037 dev_role = NL80211_IFTYPE_AP;
10038 } else {
10039 err = -EINVAL;
10040 goto fail;
10041 }
10042
10043 if (!check_dev_role_integrity(cfg, dev_role)) {
10044 err = -EINVAL;
10045 goto fail;
10046 }
10047
10048 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
10049 WL_ERR(("P2P already down status!\n"));
10050 err = BCME_ERROR;
10051 goto fail;
10052 }
10053
10054 /* Parse IEs */
10055 if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
10056 WL_ERR(("Parse IEs failed \n"));
10057 goto fail;
10058 }
10059
10060 /* Set IEs to FW */
10061 if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
10062 WL_ERR(("Set IEs failed \n"));
10063 goto fail;
10064 }
10065
10066 if (dev_role == NL80211_IFTYPE_AP) {
10067 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
10068 WL_ERR(("Hostapd update sec failed \n"));
10069 err = -EINVAL;
10070 goto fail;
10071 }
10072 /* Enable Probe Req filter, WPS-AP certification 4.2.13 */
10073 if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
10074 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
10075 WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc));
10076 if (pbc)
10077 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
10078 else
10079 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
10080 }
10081 }
10082
10083 fail:
10084 return err;
10085 }
10086 #else
10087 static s32
10088 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
10089 struct beacon_parameters *info)
10090 {
10091 s32 err = BCME_OK;
10092 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10093 s32 ie_offset = 0;
10094 s32 bssidx = 0;
10095 u32 dev_role = NL80211_IFTYPE_AP;
10096 struct parsed_ies ies;
10097 bcm_tlv_t *ssid_ie;
10098 bool pbc = 0;
10099 bool privacy;
10100 bool is_bss_up = 0;
10101 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
10102
10103 WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
10104 info->interval, info->dtim_period, info->head_len, info->tail_len));
10105
10106 if (dev == bcmcfg_to_prmry_ndev(cfg)) {
10107 dev_role = NL80211_IFTYPE_AP;
10108 }
10109 #if defined(WL_ENABLE_P2P_IF)
10110 else if (dev == cfg->p2p_net) {
10111 /* Group Add request on p2p0 */
10112 dev = bcmcfg_to_prmry_ndev(cfg);
10113 dev_role = NL80211_IFTYPE_P2P_GO;
10114 }
10115 #endif /* WL_ENABLE_P2P_IF */
10116
10117 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
10118 WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
10119 return BCME_ERROR;
10120 }
10121
10122 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
10123 dev_role = NL80211_IFTYPE_P2P_GO;
10124 } else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
10125 dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
10126 }
10127
10128 if (!check_dev_role_integrity(cfg, dev_role)) {
10129 err = -ENODEV;
10130 goto fail;
10131 }
10132
10133 if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
10134 WL_ERR(("P2P already down status!\n"));
10135 err = BCME_ERROR;
10136 goto fail;
10137 }
10138
10139 ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
10140 /* find the SSID */
10141 if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
10142 info->head_len - ie_offset,
10143 DOT11_MNG_SSID_ID)) != NULL) {
10144 if (dev_role == NL80211_IFTYPE_AP) {
10145 /* Store the hostapd SSID */
10146 memset(&cfg->hostapd_ssid.SSID[0], 0x00, DOT11_MAX_SSID_LEN);
10147 cfg->hostapd_ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
10148 memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data,
10149 cfg->hostapd_ssid.SSID_len);
10150 } else {
10151 /* P2P GO */
10152 memset(&cfg->p2p->ssid.SSID[0], 0x00, DOT11_MAX_SSID_LEN);
10153 cfg->p2p->ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
10154 memcpy(cfg->p2p->ssid.SSID, ssid_ie->data,
10155 cfg->p2p->ssid.SSID_len);
10156 }
10157 }
10158
10159 if (wl_cfg80211_parse_ies((u8 *)info->tail,
10160 info->tail_len, &ies) < 0) {
10161 WL_ERR(("Beacon get IEs failed \n"));
10162 err = -EINVAL;
10163 goto fail;
10164 }
10165
10166 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
10167 VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
10168 info->tail_len)) < 0) {
10169 WL_ERR(("Beacon set IEs failed \n"));
10170 goto fail;
10171 } else {
10172 WL_DBG(("Applied Vndr IEs for Beacon \n"));
10173 }
10174
10175 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10176 if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
10177 VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies,
10178 info->proberesp_ies_len)) < 0) {
10179 WL_ERR(("ProbeRsp set IEs failed \n"));
10180 goto fail;
10181 } else {
10182 WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
10183 }
10184 #endif
10185
10186 is_bss_up = wl_cfg80211_bss_isup(dev, bssidx);
10187
10188 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
10189 privacy = info->privacy;
10190 #else
10191 privacy = 0;
10192 #endif
10193 if (!is_bss_up &&
10194 (wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx, privacy) < 0))
10195 {
10196 WL_ERR(("Beacon set security failed \n"));
10197 err = -EINVAL;
10198 goto fail;
10199 }
10200
10201 /* Set BI and DTIM period */
10202 if (info->interval) {
10203 if ((err = wldev_ioctl_set(dev, WLC_SET_BCNPRD,
10204 &info->interval, sizeof(s32))) < 0) {
10205 WL_ERR(("Beacon Interval Set Error, %d\n", err));
10206 return err;
10207 }
10208 }
10209 if (info->dtim_period) {
10210 if ((err = wldev_ioctl_set(dev, WLC_SET_DTIMPRD,
10211 &info->dtim_period, sizeof(s32))) < 0) {
10212 WL_ERR(("DTIM Interval Set Error, %d\n", err));
10213 return err;
10214 }
10215 }
10216
10217 /* If bss is already up, skip bring up */
10218 if (!is_bss_up &&
10219 (err = wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx)) < 0)
10220 {
10221 WL_ERR(("Beacon bring up AP/GO failed \n"));
10222 goto fail;
10223 }
10224
10225 /* Set GC/STA SCB expiry timings. */
10226 if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
10227 WL_ERR(("scb setting failed \n"));
10228 // goto fail;
10229 }
10230
10231 if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
10232 /* Soft AP already running. Update changed params */
10233 if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
10234 WL_ERR(("Hostapd update sec failed \n"));
10235 err = -EINVAL;
10236 goto fail;
10237 }
10238 }
10239
10240 /* Enable Probe Req filter */
10241 if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
10242 (dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
10243 wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
10244 if (pbc)
10245 wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
10246 }
10247
10248 WL_DBG(("** ADD/SET beacon done **\n"));
10249
10250 fail:
10251 if (err) {
10252 WL_ERR(("ADD/SET beacon failed\n"));
10253 if (dev_role == NL80211_IFTYPE_AP) {
10254 /* clear the AP mode */
10255 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
10256 }
10257 }
10258 return err;
10259
10260 }
10261
10262 static s32
10263 wl_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
10264 {
10265 int err = 0;
10266 s32 bssidx = 0;
10267 int infra = 0;
10268 struct wireless_dev *wdev = dev->ieee80211_ptr;
10269 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10270 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
10271
10272 WL_DBG(("Enter. \n"));
10273
10274 if (!wdev) {
10275 WL_ERR(("wdev null \n"));
10276 return -EINVAL;
10277 }
10278
10279 if ((wdev->iftype != NL80211_IFTYPE_P2P_GO) && (wdev->iftype != NL80211_IFTYPE_AP)) {
10280 WL_ERR(("Unspported iface type iftype:%d \n", wdev->iftype));
10281 }
10282
10283 wl_clr_drv_status(cfg, AP_CREATING, dev);
10284 wl_clr_drv_status(cfg, AP_CREATED, dev);
10285
10286 /* Clear AP/GO connected status */
10287 wl_clr_drv_status(cfg, CONNECTED, dev);
10288
10289 cfg->ap_oper_channel = 0;
10290
10291
10292 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
10293 WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
10294 return BCME_ERROR;
10295 }
10296
10297 /* Do bss down */
10298 if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 0)) < 0) {
10299 WL_ERR(("bss down error %d\n", err));
10300 }
10301
10302 /* fall through is intentional */
10303 err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
10304 if (err < 0) {
10305 WL_ERR(("SET INFRA error %d\n", err));
10306 }
10307 wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
10308
10309 if (wdev->iftype == NL80211_IFTYPE_AP) {
10310 /* clear the AP mode */
10311 dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
10312 }
10313
10314 return 0;
10315 }
10316 #endif
10317
10318 #ifdef WL_SCHED_SCAN
10319 #define PNO_TIME 30
10320 #define PNO_REPEAT 4
10321 #define PNO_FREQ_EXPO_MAX 2
10322 static bool
10323 is_ssid_in_list(struct cfg80211_ssid *ssid, struct cfg80211_ssid *ssid_list, int count)
10324 {
10325 int i;
10326
10327 if (!ssid || !ssid_list)
10328 return FALSE;
10329
10330 for (i = 0; i < count; i++) {
10331 if (ssid->ssid_len == ssid_list[i].ssid_len) {
10332 if (strncmp(ssid->ssid, ssid_list[i].ssid, ssid->ssid_len) == 0)
10333 return TRUE;
10334 }
10335 }
10336 return FALSE;
10337 }
10338
10339 static int
10340 wl_cfg80211_sched_scan_start(struct wiphy *wiphy,
10341 struct net_device *dev,
10342 struct cfg80211_sched_scan_request *request)
10343 {
10344 ushort pno_time = PNO_TIME;
10345 int pno_repeat = PNO_REPEAT;
10346 int pno_freq_expo_max = PNO_FREQ_EXPO_MAX;
10347 wlc_ssid_ext_t ssids_local[MAX_PFN_LIST_COUNT];
10348 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10349 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
10350 struct cfg80211_ssid *ssid = NULL;
10351 struct cfg80211_ssid *hidden_ssid_list = NULL;
10352 log_conn_event_t *event_data = NULL;
10353 tlv_log *tlv_data = NULL;
10354 u32 alloc_len, tlv_len;
10355 u32 payload_len;
10356 int ssid_cnt = 0;
10357 int i;
10358 int ret = 0;
10359 unsigned long flags;
10360
10361 if (!request) {
10362 WL_ERR(("Sched scan request was NULL\n"));
10363 return -EINVAL;
10364 }
10365
10366 WL_DBG(("Enter \n"));
10367 WL_PNO((">>> SCHED SCAN START\n"));
10368 WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n",
10369 request->n_match_sets, request->n_ssids));
10370 WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n",
10371 request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max));
10372
10373
10374 if (!request->n_ssids || !request->n_match_sets) {
10375 WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids));
10376 return -EINVAL;
10377 }
10378
10379 memset(&ssids_local, 0, sizeof(ssids_local));
10380
10381 if (request->n_ssids > 0) {
10382 hidden_ssid_list = request->ssids;
10383 }
10384
10385 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
10386 alloc_len = sizeof(log_conn_event_t) + DOT11_MAX_SSID_LEN;
10387 event_data = MALLOC(dhdp->osh, alloc_len);
10388 if (!event_data) {
10389 WL_ERR(("%s: failed to allocate log_conn_event_t with "
10390 "length(%d)\n", __func__, alloc_len));
10391 return -ENOMEM;
10392 }
10393 memset(event_data, 0, alloc_len);
10394 event_data->tlvs = NULL;
10395 tlv_len = sizeof(tlv_log);
10396 event_data->tlvs = (tlv_log *)MALLOC(dhdp->osh, tlv_len);
10397 if (!event_data->tlvs) {
10398 WL_ERR(("%s: failed to allocate log_tlv with "
10399 "length(%d)\n", __func__, tlv_len));
10400 MFREE(dhdp->osh, event_data, alloc_len);
10401 return -ENOMEM;
10402 }
10403 }
10404 for (i = 0; i < request->n_match_sets && ssid_cnt < MAX_PFN_LIST_COUNT; i++) {
10405 ssid = &request->match_sets[i].ssid;
10406 /* No need to include null ssid */
10407 if (ssid->ssid_len) {
10408 ssids_local[ssid_cnt].SSID_len = MIN(ssid->ssid_len,
10409 (uint32)DOT11_MAX_SSID_LEN);
10410 memcpy(ssids_local[ssid_cnt].SSID, ssid->ssid,
10411 ssids_local[ssid_cnt].SSID_len);
10412 if (is_ssid_in_list(ssid, hidden_ssid_list, request->n_ssids)) {
10413 ssids_local[ssid_cnt].hidden = TRUE;
10414 WL_PNO((">>> PNO hidden SSID (%s) \n", ssid->ssid));
10415 } else {
10416 ssids_local[ssid_cnt].hidden = FALSE;
10417 WL_PNO((">>> PNO non-hidden SSID (%s) \n", ssid->ssid));
10418 }
10419 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0))
10420 if (request->match_sets[i].rssi_thold != NL80211_SCAN_RSSI_THOLD_OFF) {
10421 ssids_local[ssid_cnt].rssi_thresh =
10422 (int8)request->match_sets[i].rssi_thold;
10423 }
10424 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 15, 0)) */
10425 ssid_cnt++;
10426 }
10427 }
10428
10429 if (ssid_cnt) {
10430 if ((ret = dhd_dev_pno_set_for_ssid(dev, ssids_local, ssid_cnt,
10431 pno_time, pno_repeat, pno_freq_expo_max, NULL, 0)) < 0) {
10432 WL_ERR(("PNO setup failed!! ret=%d \n", ret));
10433 ret = -EINVAL;
10434 goto exit;
10435 }
10436
10437 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
10438 for (i = 0; i < ssid_cnt; i++) {
10439 payload_len = sizeof(log_conn_event_t);
10440 event_data->event = WIFI_EVENT_DRIVER_PNO_ADD;
10441 tlv_data = event_data->tlvs;
10442 /* ssid */
10443 tlv_data->tag = WIFI_TAG_SSID;
10444 tlv_data->len = ssids_local[i].SSID_len;
10445 memcpy(tlv_data->value, ssids_local[i].SSID,
10446 ssids_local[i].SSID_len);
10447 payload_len += TLV_LOG_SIZE(tlv_data);
10448
10449 dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
10450 event_data, payload_len);
10451 }
10452 }
10453
10454 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
10455 cfg->sched_scan_req = request;
10456 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
10457 } else {
10458 ret = -EINVAL;
10459 }
10460 exit:
10461 if (event_data) {
10462 MFREE(dhdp->osh, event_data->tlvs, tlv_len);
10463 MFREE(dhdp->osh, event_data, alloc_len);
10464 }
10465 return ret;
10466 }
10467
10468 static int
10469 wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev
10470 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
10471 , u64 reqid
10472 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
10473 )
10474 {
10475 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10476 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
10477 unsigned long flags;
10478
10479 WL_DBG(("Enter \n"));
10480 WL_PNO((">>> SCHED SCAN STOP\n"));
10481
10482 BCM_REFERENCE(dhdp);
10483 if (dhd_dev_pno_stop_for_ssid(dev) < 0) {
10484 WL_ERR(("PNO Stop for SSID failed"));
10485 } else {
10486 DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_REMOVE);
10487 }
10488
10489 if (cfg->scan_request && cfg->sched_scan_running) {
10490 WL_PNO((">>> Sched scan running. Aborting it..\n"));
10491 wl_notify_escan_complete(cfg, dev, true, true);
10492 }
10493 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
10494 cfg->sched_scan_req = NULL;
10495 cfg->sched_scan_running = FALSE;
10496 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
10497 return 0;
10498 }
10499 #endif /* WL_SCHED_SCAN */
10500
10501 #ifdef WL_SUPPORT_ACS
10502 /*
10503 * Currently the dump_obss IOVAR is returning string as output so we need to
10504 * parse the output buffer in an unoptimized way. Going forward if we get the
10505 * IOVAR output in binary format this method can be optimized
10506 */
10507 static int wl_parse_dump_obss(char *buf, struct wl_dump_survey *survey)
10508 {
10509 int i;
10510 char *token;
10511 char delim[] = " \n";
10512
10513 token = strsep(&buf, delim);
10514 while (token != NULL) {
10515 if (!strcmp(token, "OBSS")) {
10516 for (i = 0; i < OBSS_TOKEN_IDX; i++)
10517 token = strsep(&buf, delim);
10518 survey->obss = simple_strtoul(token, NULL, 10);
10519 }
10520
10521 if (!strcmp(token, "IBSS")) {
10522 for (i = 0; i < IBSS_TOKEN_IDX; i++)
10523 token = strsep(&buf, delim);
10524 survey->ibss = simple_strtoul(token, NULL, 10);
10525 }
10526
10527 if (!strcmp(token, "TXDur")) {
10528 for (i = 0; i < TX_TOKEN_IDX; i++)
10529 token = strsep(&buf, delim);
10530 survey->tx = simple_strtoul(token, NULL, 10);
10531 }
10532
10533 if (!strcmp(token, "Category")) {
10534 for (i = 0; i < CTG_TOKEN_IDX; i++)
10535 token = strsep(&buf, delim);
10536 survey->no_ctg = simple_strtoul(token, NULL, 10);
10537 }
10538
10539 if (!strcmp(token, "Packet")) {
10540 for (i = 0; i < PKT_TOKEN_IDX; i++)
10541 token = strsep(&buf, delim);
10542 survey->no_pckt = simple_strtoul(token, NULL, 10);
10543 }
10544
10545 if (!strcmp(token, "Opp(time):")) {
10546 for (i = 0; i < IDLE_TOKEN_IDX; i++)
10547 token = strsep(&buf, delim);
10548 survey->idle = simple_strtoul(token, NULL, 10);
10549 }
10550
10551 token = strsep(&buf, delim);
10552 }
10553
10554 return 0;
10555 }
10556
10557 static int wl_dump_obss(struct net_device *ndev, cca_msrmnt_query req,
10558 struct wl_dump_survey *survey)
10559 {
10560 cca_stats_n_flags *results;
10561 char *buf;
10562 int retry, err;
10563
10564 buf = kzalloc(sizeof(char) * WLC_IOCTL_MAXLEN, GFP_KERNEL);
10565 if (unlikely(!buf)) {
10566 WL_ERR(("%s: buf alloc failed\n", __func__));
10567 return -ENOMEM;
10568 }
10569
10570 retry = IOCTL_RETRY_COUNT;
10571 while (retry--) {
10572 err = wldev_iovar_getbuf(ndev, "dump_obss", &req, sizeof(req),
10573 buf, WLC_IOCTL_MAXLEN, NULL);
10574 if (err >= 0) {
10575 break;
10576 }
10577 WL_DBG(("attempt = %d, err = %d, \n",
10578 (IOCTL_RETRY_COUNT - retry), err));
10579 }
10580
10581 if (retry <= 0) {
10582 WL_ERR(("failure, dump_obss IOVAR failed\n"));
10583 err = -EINVAL;
10584 goto exit;
10585 }
10586
10587 results = (cca_stats_n_flags *)(buf);
10588 wl_parse_dump_obss(results->buf, survey);
10589 kfree(buf);
10590
10591 return 0;
10592 exit:
10593 kfree(buf);
10594 return err;
10595 }
10596
10597 static int wl_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *ndev,
10598 int idx, struct survey_info *info)
10599 {
10600 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
10601 struct wl_dump_survey *survey;
10602 struct ieee80211_supported_band *band;
10603 struct ieee80211_channel*chan;
10604 cca_msrmnt_query req;
10605 int val, err, noise, retry;
10606
10607 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
10608 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
10609 return -ENOENT;
10610 }
10611 band = wiphy->bands[IEEE80211_BAND_2GHZ];
10612 if (band && idx >= band->n_channels) {
10613 idx -= band->n_channels;
10614 band = NULL;
10615 }
10616
10617 if (!band || idx >= band->n_channels) {
10618 /* Move to 5G band */
10619 band = wiphy->bands[IEEE80211_BAND_5GHZ];
10620 if (idx >= band->n_channels) {
10621 return -ENOENT;
10622 }
10623 }
10624
10625 chan = &band->channels[idx];
10626 /* Setting current channel to the requested channel */
10627 if ((err = wl_cfg80211_set_channel(wiphy, ndev, chan,
10628 NL80211_CHAN_HT20) < 0)) {
10629 WL_ERR(("Set channel failed \n"));
10630 }
10631
10632 if (!idx) {
10633 /* Set interface up, explicitly. */
10634 val = 1;
10635 err = wldev_ioctl_set(ndev, WLC_UP, (void *)&val, sizeof(val));
10636 if (err < 0) {
10637 WL_ERR(("set interface up failed, error = %d\n", err));
10638 }
10639 }
10640
10641 /* Get noise value */
10642 retry = IOCTL_RETRY_COUNT;
10643 while (retry--) {
10644 noise = 0;
10645 err = wldev_ioctl_get(ndev, WLC_GET_PHY_NOISE, &noise,
10646 sizeof(noise));
10647 if (err >= 0) {
10648 break;
10649 }
10650 WL_DBG(("attempt = %d, err = %d, \n",
10651 (IOCTL_RETRY_COUNT - retry), err));
10652 }
10653
10654 if (retry <= 0) {
10655 WL_ERR(("Get Phy Noise failed, error = %d\n", err));
10656 noise = CHAN_NOISE_DUMMY;
10657 }
10658
10659 survey = (struct wl_dump_survey *) kzalloc(sizeof(struct wl_dump_survey),
10660 GFP_KERNEL);
10661 if (unlikely(!survey)) {
10662 WL_ERR(("%s: alloc failed\n", __func__));
10663 return -ENOMEM;
10664 }
10665
10666 /* Start Measurement for obss stats on current channel */
10667 req.msrmnt_query = 0;
10668 req.time_req = ACS_MSRMNT_DELAY;
10669 if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
10670 goto exit;
10671 }
10672
10673 /*
10674 * Wait for the meaurement to complete, adding a buffer value of 10 to take
10675 * into consideration any delay in IOVAR completion
10676 */
10677 msleep(ACS_MSRMNT_DELAY + 10);
10678
10679 /* Issue IOVAR to collect measurement results */
10680 req.msrmnt_query = 1;
10681 if ((err = wl_dump_obss(ndev, req, survey)) < 0) {
10682 goto exit;
10683 }
10684
10685 info->channel = chan;
10686 info->noise = noise;
10687 info->channel_time = ACS_MSRMNT_DELAY;
10688 info->channel_time_busy = ACS_MSRMNT_DELAY - survey->idle;
10689 info->channel_time_rx = survey->obss + survey->ibss + survey->no_ctg +
10690 survey->no_pckt;
10691 info->channel_time_tx = survey->tx;
10692 info->filled = SURVEY_INFO_NOISE_DBM |SURVEY_INFO_CHANNEL_TIME |
10693 SURVEY_INFO_CHANNEL_TIME_BUSY | SURVEY_INFO_CHANNEL_TIME_RX |
10694 SURVEY_INFO_CHANNEL_TIME_TX;
10695 kfree(survey);
10696
10697 return 0;
10698 exit:
10699 kfree(survey);
10700 return err;
10701 }
10702 #endif /* WL_SUPPORT_ACS */
10703
10704 static struct cfg80211_ops wl_cfg80211_ops = {
10705 .add_virtual_intf = wl_cfg80211_add_virtual_iface,
10706 .del_virtual_intf = wl_cfg80211_del_virtual_iface,
10707 .change_virtual_intf = wl_cfg80211_change_virtual_iface,
10708 #if defined(WL_CFG80211_P2P_DEV_IF)
10709 .start_p2p_device = wl_cfgp2p_start_p2p_device,
10710 .stop_p2p_device = wl_cfgp2p_stop_p2p_device,
10711 #endif /* WL_CFG80211_P2P_DEV_IF */
10712 .scan = wl_cfg80211_scan,
10713 .set_wiphy_params = wl_cfg80211_set_wiphy_params,
10714 .join_ibss = wl_cfg80211_join_ibss,
10715 .leave_ibss = wl_cfg80211_leave_ibss,
10716 .get_station = wl_cfg80211_get_station,
10717 .set_tx_power = wl_cfg80211_set_tx_power,
10718 .get_tx_power = wl_cfg80211_get_tx_power,
10719 .add_key = wl_cfg80211_add_key,
10720 .del_key = wl_cfg80211_del_key,
10721 .get_key = wl_cfg80211_get_key,
10722 .set_default_key = wl_cfg80211_config_default_key,
10723 .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key,
10724 .set_power_mgmt = wl_cfg80211_set_power_mgmt,
10725 .connect = wl_cfg80211_connect,
10726 .disconnect = wl_cfg80211_disconnect,
10727 .suspend = wl_cfg80211_suspend,
10728 .resume = wl_cfg80211_resume,
10729 .set_pmksa = wl_cfg80211_set_pmksa,
10730 .del_pmksa = wl_cfg80211_del_pmksa,
10731 .flush_pmksa = wl_cfg80211_flush_pmksa,
10732 .remain_on_channel = wl_cfg80211_remain_on_channel,
10733 .cancel_remain_on_channel = wl_cfg80211_cancel_remain_on_channel,
10734 .mgmt_tx = wl_cfg80211_mgmt_tx,
10735 .mgmt_frame_register = wl_cfg80211_mgmt_frame_register,
10736 .change_bss = wl_cfg80211_change_bss,
10737 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
10738 .set_channel = wl_cfg80211_set_channel,
10739 #endif
10740 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0))
10741 .set_beacon = wl_cfg80211_add_set_beacon,
10742 .add_beacon = wl_cfg80211_add_set_beacon,
10743 .del_beacon = wl_cfg80211_del_beacon,
10744 #else
10745 .change_beacon = wl_cfg80211_change_beacon,
10746 .start_ap = wl_cfg80211_start_ap,
10747 .stop_ap = wl_cfg80211_stop_ap,
10748 #endif
10749 #ifdef WL_SCHED_SCAN
10750 .sched_scan_start = wl_cfg80211_sched_scan_start,
10751 .sched_scan_stop = wl_cfg80211_sched_scan_stop,
10752 #endif /* WL_SCHED_SCAN */
10753 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
10754 2, 0))
10755 .del_station = wl_cfg80211_del_station,
10756 .change_station = wl_cfg80211_change_station,
10757 .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait,
10758 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */
10759 #ifdef WLMESH
10760 .join_mesh = wl_cfg80211_join_mesh,
10761 .leave_mesh = wl_cfg80211_leave_mesh,
10762 #endif /* WLMESH */
10763 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
10764 .tdls_mgmt = wl_cfg80211_tdls_mgmt,
10765 .tdls_oper = wl_cfg80211_tdls_oper,
10766 #endif
10767 #ifdef WL_SUPPORT_ACS
10768 .dump_survey = wl_cfg80211_dump_survey,
10769 #endif /* WL_SUPPORT_ACS */
10770 #ifdef WL_CFG80211_ACL
10771 .set_mac_acl = wl_cfg80211_set_mac_acl,
10772 #endif /* WL_CFG80211_ACL */
10773 #ifdef GTK_OFFLOAD_SUPPORT
10774 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
10775 .set_rekey_data = wl_cfg80211_set_rekey_data,
10776 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
10777 #endif /* GTK_OFFLOAD_SUPPORT */
10778 };
10779
10780 s32 wl_mode_to_nl80211_iftype(s32 mode)
10781 {
10782 s32 err = 0;
10783
10784 switch (mode) {
10785 case WL_MODE_BSS:
10786 return NL80211_IFTYPE_STATION;
10787 case WL_MODE_IBSS:
10788 return NL80211_IFTYPE_ADHOC;
10789 case WL_MODE_AP:
10790 return NL80211_IFTYPE_AP;
10791 #ifdef WLMESH
10792 case WL_MODE_MESH:
10793 return NL80211_IFTYPE_MESH_POINT;
10794 #endif
10795 default:
10796 return NL80211_IFTYPE_UNSPECIFIED;
10797 }
10798
10799 return err;
10800 }
10801
10802 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
10803 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
10804 #define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
10805 #else
10806 #define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
10807 #endif /* kernel version < 3.9.0 */
10808 #endif
10809
10810 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
10811 WL_CFG80211_REG_NOTIFIER()
10812 {
10813 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
10814 int ret = 0;
10815 int revinfo = -1;
10816
10817 if (!request || !cfg) {
10818 WL_ERR(("Invalid arg\n"));
10819 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
10820 return -EINVAL;
10821 #else
10822 return;
10823 #endif /* kernel version < 3.10.11 */
10824 }
10825
10826 WL_DBG(("ccode: %c%c Initiator: %d\n",
10827 request->alpha2[0], request->alpha2[1], request->initiator));
10828
10829 /* We support only REGDOM_SET_BY_USER as of now */
10830 if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
10831 (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
10832 WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
10833 request->initiator));
10834 /* in case of no supported country by regdb
10835 lets driver setup platform default Locale
10836 */
10837 }
10838
10839 WL_ERR(("Set country code %c%c from %s\n",
10840 request->alpha2[0], request->alpha2[1],
10841 ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
10842
10843 if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2,
10844 false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false),
10845 revinfo)) < 0) {
10846 WL_ERR(("set country Failed :%d\n", ret));
10847 }
10848
10849 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
10850 return ret;
10851 #else
10852 return;
10853 #endif /* kernel version < 3.10.11 */
10854 }
10855 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
10856
10857 #ifdef CONFIG_PM
10858 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
10859 static const struct wiphy_wowlan_support brcm_wowlan_support = {
10860 .flags = WIPHY_WOWLAN_ANY,
10861 .n_patterns = WL_WOWLAN_MAX_PATTERNS,
10862 .pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN,
10863 .pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN,
10864 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
10865 .max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN,
10866 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
10867 };
10868 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
10869 #endif /* CONFIG_PM */
10870
10871 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, dhd_pub_t *context)
10872 {
10873 s32 err = 0;
10874 #ifdef CONFIG_PM
10875 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
10876 struct cfg80211_wowlan *brcm_wowlan_config = NULL;
10877 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
10878 #endif /* CONFIG_PM */
10879
10880 //#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
10881 dhd_pub_t *dhd = (dhd_pub_t *)context;
10882 BCM_REFERENCE(dhd);
10883
10884 if (!dhd) {
10885 WL_ERR(("DHD is NULL!!"));
10886 err = -ENODEV;
10887 return err;
10888 }
10889 //#endif
10890
10891 wdev->wiphy =
10892 wiphy_new(&wl_cfg80211_ops, sizeof(struct bcm_cfg80211));
10893 if (unlikely(!wdev->wiphy)) {
10894 WL_ERR(("Couldn not allocate wiphy device\n"));
10895 err = -ENOMEM;
10896 return err;
10897 }
10898 set_wiphy_dev(wdev->wiphy, sdiofunc_dev);
10899 wdev->wiphy->max_scan_ie_len = WL_SCAN_IE_LEN_MAX;
10900 /* Report how many SSIDs Driver can support per Scan request */
10901 wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX;
10902 wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
10903 #ifdef WL_SCHED_SCAN
10904 wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT;
10905 wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT;
10906 wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX;
10907 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
10908 wdev->wiphy->max_sched_scan_plan_interval = PNO_SCAN_MAX_FW_SEC;
10909 #else
10910 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
10911 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
10912 #endif /* WL_SCHED_SCAN */
10913 #ifdef WLMESH
10914 wdev->wiphy->flags |= WIPHY_FLAG_MESH_AUTH;
10915 #endif
10916 wdev->wiphy->interface_modes =
10917 BIT(NL80211_IFTYPE_STATION)
10918 | BIT(NL80211_IFTYPE_ADHOC)
10919 #if !defined(WL_ENABLE_P2P_IF) && !defined(WL_CFG80211_P2P_DEV_IF)
10920 | BIT(NL80211_IFTYPE_MONITOR)
10921 #endif /* !WL_ENABLE_P2P_IF && !WL_CFG80211_P2P_DEV_IF */
10922 #if defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF)
10923 | BIT(NL80211_IFTYPE_P2P_CLIENT)
10924 | BIT(NL80211_IFTYPE_P2P_GO)
10925 #endif /* WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF */
10926 #if defined(WL_CFG80211_P2P_DEV_IF)
10927 | BIT(NL80211_IFTYPE_P2P_DEVICE)
10928 #endif /* WL_CFG80211_P2P_DEV_IF */
10929 #ifdef WLMESH
10930 | BIT(NL80211_IFTYPE_MESH_POINT)
10931 #endif /* WLMESH */
10932 | BIT(NL80211_IFTYPE_AP);
10933
10934 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
10935 (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
10936 WL_DBG(("Setting interface combinations for common mode\n"));
10937 wdev->wiphy->iface_combinations = common_iface_combinations;
10938 wdev->wiphy->n_iface_combinations =
10939 ARRAY_SIZE(common_iface_combinations);
10940 #endif /* LINUX_VER >= 3.0 && (WL_IFACE_COMB_NUM_CHANNELS || WL_CFG80211_P2P_DEV_IF) */
10941
10942 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
10943
10944 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
10945 wdev->wiphy->cipher_suites = __wl_cipher_suites;
10946 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
10947 wdev->wiphy->max_remain_on_channel_duration = 5000;
10948 wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
10949 #ifndef WL_POWERSAVE_DISABLED
10950 wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
10951 #else
10952 wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
10953 #endif /* !WL_POWERSAVE_DISABLED */
10954 wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
10955 WIPHY_FLAG_4ADDR_AP |
10956 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 39))
10957 WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS |
10958 #endif
10959 WIPHY_FLAG_4ADDR_STATION;
10960 #if ((defined(ROAM_ENABLE) || defined(BCMFW_ROAM_ENABLE)) && (LINUX_VERSION_CODE >= \
10961 KERNEL_VERSION(3, 2, 0)))
10962 /*
10963 * If FW ROAM flag is advertised, upper layer wouldn't provide
10964 * the bssid & freq in the connect command. This will result a
10965 * delay in initial connection time due to firmware doing a full
10966 * channel scan to figure out the channel & bssid. However kernel
10967 * ver >= 3.15, provides bssid_hint & freq_hint and hence kernel
10968 * ver >= 3.15 won't have any issue. So if this flags need to be
10969 * advertised for kernel < 3.15, suggest to use RCC along with it
10970 * to avoid the initial connection delay.
10971 */
10972 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
10973 #endif
10974 #ifdef UNSET_FW_ROAM_WIPHY_FLAG
10975 wdev->wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_FW_ROAM;
10976 #endif /* UNSET_FW_ROAM_WIPHY_FLAG */
10977 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0))
10978 wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
10979 WIPHY_FLAG_OFFCHAN_TX;
10980 #endif
10981 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
10982 4, 0))
10983 /* From 3.4 kernel ownards AP_SME flag can be advertised
10984 * to remove the patch from supplicant
10985 */
10986 wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME;
10987
10988 #ifdef WL_CFG80211_ACL
10989 /* Configure ACL capabilities. */
10990 wdev->wiphy->max_acl_mac_addrs = MAX_NUM_MAC_FILT;
10991 #endif
10992
10993 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
10994 /* Supplicant distinguish between the SoftAP mode and other
10995 * modes (e.g. P2P, WPS, HS2.0) when it builds the probe
10996 * response frame from Supplicant MR1 and Kernel 3.4.0 or
10997 * later version. To add Vendor specific IE into the
10998 * probe response frame in case of SoftAP mode,
10999 * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable.
11000 */
11001 if (dhd_get_fw_mode(dhd->info) == DHD_FLAG_HOSTAP_MODE) {
11002 wdev->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
11003 wdev->wiphy->probe_resp_offload = 0;
11004 }
11005 #endif
11006 #endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */
11007
11008 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
11009 wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
11010 #endif
11011
11012 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
11013 /*
11014 * From linux-3.10 kernel, wowlan packet filter is mandated to avoid the
11015 * disconnection of connected network before suspend. So a dummy wowlan
11016 * filter is configured for kernels linux-3.8 and above.
11017 */
11018
11019 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
11020 wdev->wiphy->wowlan = &brcm_wowlan_support;
11021 /* If this is not provided cfg stack will get disconnect
11022 * during suspend.
11023 */
11024 brcm_wowlan_config = kmalloc(sizeof(struct cfg80211_wowlan), GFP_KERNEL);
11025 if (brcm_wowlan_config) {
11026 brcm_wowlan_config->disconnect = true;
11027 brcm_wowlan_config->gtk_rekey_failure = true;
11028 brcm_wowlan_config->eap_identity_req = true;
11029 brcm_wowlan_config->four_way_handshake = true;
11030 brcm_wowlan_config->patterns = NULL;
11031 brcm_wowlan_config->n_patterns = 0;
11032 brcm_wowlan_config->tcp = NULL;
11033 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
11034 brcm_wowlan_config->nd_config = NULL;
11035 #endif
11036 } else {
11037 WL_ERR(("Can not allocate memory for brcm_wowlan_config,"
11038 " So wiphy->wowlan_config is set to NULL\n"));
11039 }
11040 wdev->wiphy->wowlan_config = brcm_wowlan_config;
11041 #else
11042 wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
11043 wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
11044 wdev->wiphy->wowlan.pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN;
11045 wdev->wiphy->wowlan.pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN;
11046 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
11047 wdev->wiphy->wowlan.max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN;
11048 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
11049 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
11050 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
11051
11052 WL_DBG(("Registering custom regulatory)\n"));
11053 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
11054 wdev->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
11055 #else
11056 wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
11057 #endif
11058 wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom);
11059
11060 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
11061 WL_ERR(("Registering Vendor80211\n"));
11062 err = wl_cfgvendor_attach(wdev->wiphy, dhd);
11063 if (unlikely(err < 0)) {
11064 WL_ERR(("Couldn not attach vendor commands (%d)\n", err));
11065 }
11066 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
11067
11068 /* Now we can register wiphy with cfg80211 module */
11069 err = wiphy_register(wdev->wiphy);
11070 if (unlikely(err < 0)) {
11071 WL_ERR(("Couldn not register wiphy device (%d)\n", err));
11072 wiphy_free(wdev->wiphy);
11073 }
11074
11075 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && (LINUX_VERSION_CODE <= \
11076 KERNEL_VERSION(3, 3, 0))) && defined(WL_IFACE_COMB_NUM_CHANNELS)
11077 wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
11078 #endif
11079
11080 return err;
11081 }
11082
11083 static void wl_free_wdev(struct bcm_cfg80211 *cfg)
11084 {
11085 struct wireless_dev *wdev = cfg->wdev;
11086 struct wiphy *wiphy = NULL;
11087 if (!wdev) {
11088 WL_ERR(("wdev is invalid\n"));
11089 return;
11090 }
11091 if (wdev->wiphy) {
11092 wiphy = wdev->wiphy;
11093
11094 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT)
11095 wl_cfgvendor_detach(wdev->wiphy);
11096 #endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(3, 14, 0)) || defined(WL_VENDOR_EXT_SUPPORT) */
11097 #if defined(CONFIG_PM) && defined(WL_CFG80211_P2P_DEV_IF)
11098 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
11099 /* Reset wowlan & wowlan_config before Unregister to avoid Kernel Panic */
11100 WL_DBG(("wl_free_wdev Clearing wowlan Config \n"));
11101 wdev->wiphy->wowlan = NULL;
11102 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
11103 #endif /* CONFIG_PM && WL_CFG80211_P2P_DEV_IF */
11104 wiphy_unregister(wdev->wiphy);
11105 wdev->wiphy->dev.parent = NULL;
11106 wdev->wiphy = NULL;
11107 }
11108
11109 wl_delete_all_netinfo(cfg);
11110 if (wiphy)
11111 wiphy_free(wiphy);
11112
11113 /* PLEASE do NOT call any function after wiphy_free, the driver's private structure "cfg",
11114 * which is the private part of wiphy, has been freed in wiphy_free !!!!!!!!!!!
11115 */
11116 }
11117
11118 static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
11119 {
11120 struct wl_scan_results *bss_list;
11121 struct wl_bss_info *bi = NULL; /* must be initialized */
11122 s32 err = 0;
11123 s32 i;
11124 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
11125 #if defined(RSSIAVG)
11126 int rssi;
11127 #endif
11128 #if defined(BSSCACHE)
11129 wl_bss_cache_t *node;
11130 #endif
11131
11132 bss_list = cfg->bss_list;
11133
11134 /* Free cache in p2p scanning*/
11135 if (p2p_is_on(cfg) && p2p_scan(cfg)) {
11136 #if defined(RSSIAVG)
11137 wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
11138 #endif
11139 #if defined(BSSCACHE)
11140 wl_free_bss_cache(&cfg->g_bss_cache_ctrl);
11141 #endif
11142 }
11143
11144 /* Delete disconnected cache */
11145 #if defined(BSSCACHE)
11146 wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
11147 #if defined(RSSIAVG)
11148 wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
11149 #endif
11150 if (cfg->p2p_disconnected == 0)
11151 memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
11152 #endif
11153
11154 /* Update cache */
11155 #if defined(RSSIAVG)
11156 wl_update_rssi_cache(&cfg->g_rssi_cache_ctrl, bss_list);
11157 if (!in_atomic())
11158 wl_update_connected_rssi_cache(ndev, &cfg->g_rssi_cache_ctrl, &rssi);
11159 #endif
11160 #if defined(BSSCACHE)
11161 wl_update_bss_cache(&cfg->g_bss_cache_ctrl,
11162 #if defined(RSSIAVG)
11163 &cfg->g_rssi_cache_ctrl,
11164 #endif
11165 bss_list);
11166 #endif
11167
11168 /* delete dirty cache */
11169 #if defined(RSSIAVG)
11170 wl_delete_dirty_rssi_cache(&cfg->g_rssi_cache_ctrl);
11171 wl_reset_rssi_cache(&cfg->g_rssi_cache_ctrl);
11172 #endif
11173 #if defined(BSSCACHE)
11174 wl_delete_dirty_bss_cache(&cfg->g_bss_cache_ctrl);
11175 wl_reset_bss_cache(&cfg->g_bss_cache_ctrl);
11176 #endif
11177
11178 #if defined(BSSCACHE)
11179 if (cfg->p2p_disconnected > 0) {
11180 // terence 20130703: Fix for wrong group_capab (timing issue)
11181 wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
11182 #if defined(RSSIAVG)
11183 wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
11184 #endif
11185 }
11186 WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
11187 node = cfg->g_bss_cache_ctrl.m_cache_head;
11188 for (i=0; node && i<WL_AP_MAX; i++) {
11189 bi = node->results.bss_info;
11190 err = wl_inform_single_bss(cfg, bi, false);
11191 node = node->next;
11192 }
11193 if (cfg->autochannel)
11194 wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl, ioctl_version,
11195 &cfg->best_2g_ch, &cfg->best_5g_ch);
11196 #else
11197 WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
11198 preempt_disable();
11199 bi = next_bss(bss_list, bi);
11200 for_each_bss(bss_list, bi, i) {
11201 if (cfg->p2p_disconnected > 0 && !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN))
11202 continue;
11203 err = wl_inform_single_bss(cfg, bi, false);
11204 }
11205 preempt_enable();
11206 if (cfg->autochannel)
11207 wl_ext_get_best_channel(ndev, bss_list, ioctl_version,
11208 &cfg->best_2g_ch, &cfg->best_5g_ch);
11209 #endif
11210
11211 if (cfg->p2p_disconnected > 0) {
11212 // terence 20130703: Fix for wrong group_capab (timing issue)
11213 cfg->p2p_disconnected++;
11214 if (cfg->p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1) {
11215 cfg->p2p_disconnected = 0;
11216 memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
11217 }
11218 }
11219
11220 return err;
11221 }
11222
11223 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi, bool roam)
11224 {
11225 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11226 struct ieee80211_mgmt *mgmt;
11227 struct ieee80211_channel *channel;
11228 struct ieee80211_supported_band *band;
11229 struct wl_cfg80211_bss_info *notif_bss_info;
11230 struct wl_scan_req *sr = wl_to_sr(cfg);
11231 struct beacon_proberesp *beacon_proberesp;
11232 struct cfg80211_bss *cbss = NULL;
11233 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
11234 log_conn_event_t *event_data = NULL;
11235 tlv_log *tlv_data = NULL;
11236 u32 alloc_len, tlv_len;
11237 u32 payload_len;
11238 s32 mgmt_type;
11239 s32 signal;
11240 u32 freq;
11241 s32 err = 0;
11242 gfp_t aflags;
11243 chanspec_t chanspec;
11244
11245 if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
11246 WL_DBG(("Beacon is larger than buffer. Discarding\n"));
11247 return err;
11248 }
11249 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
11250 notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt)
11251 - sizeof(u8) + WL_BSS_INFO_MAX, aflags);
11252 if (unlikely(!notif_bss_info)) {
11253 WL_ERR(("notif_bss_info alloc failed\n"));
11254 return -ENOMEM;
11255 }
11256 mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
11257 chanspec = wl_chspec_driver_to_host(bi->chanspec);
11258 notif_bss_info->channel = wf_chspec_ctlchan(chanspec);
11259
11260 if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
11261 band = wiphy->bands[IEEE80211_BAND_2GHZ];
11262 else
11263 band = wiphy->bands[IEEE80211_BAND_5GHZ];
11264 if (!band) {
11265 WL_ERR(("No valid band\n"));
11266 kfree(notif_bss_info);
11267 return -EINVAL;
11268 }
11269 notif_bss_info->rssi = dtoh16(bi->RSSI);
11270 #if defined(RSSIAVG)
11271 notif_bss_info->rssi = wl_get_avg_rssi(&cfg->g_rssi_cache_ctrl, &bi->BSSID);
11272 if (notif_bss_info->rssi == RSSI_MINVAL)
11273 notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
11274 #endif
11275 #if defined(RSSIOFFSET)
11276 notif_bss_info->rssi = wl_update_rssi_offset(bcmcfg_to_prmry_ndev(cfg), notif_bss_info->rssi);
11277 #endif
11278 #if !defined(RSSIAVG) && !defined(RSSIOFFSET)
11279 // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
11280 notif_bss_info->rssi = MIN(notif_bss_info->rssi, RSSI_MAXVAL);
11281 #endif
11282 memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN);
11283 mgmt_type = cfg->active_scan ?
11284 IEEE80211_STYPE_PROBE_RESP : IEEE80211_STYPE_BEACON;
11285 if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) {
11286 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | mgmt_type);
11287 }
11288 beacon_proberesp = cfg->active_scan ?
11289 (struct beacon_proberesp *)&mgmt->u.probe_resp :
11290 (struct beacon_proberesp *)&mgmt->u.beacon;
11291 beacon_proberesp->timestamp = 0;
11292 beacon_proberesp->beacon_int = cpu_to_le16(bi->beacon_period);
11293 beacon_proberesp->capab_info = cpu_to_le16(bi->capability);
11294 wl_rst_ie(cfg);
11295 wl_update_hidden_ap_ie(bi, ((u8 *) bi) + bi->ie_offset, &bi->ie_length, roam);
11296 wl_mrg_ie(cfg, ((u8 *) bi) + bi->ie_offset, bi->ie_length);
11297 wl_cp_ie(cfg, beacon_proberesp->variable, WL_BSS_INFO_MAX -
11298 offsetof(struct wl_cfg80211_bss_info, frame_buf));
11299 notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
11300 u.beacon.variable) + wl_get_ielen(cfg);
11301 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11302 freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
11303 (void)band->band;
11304 #else
11305 freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
11306 #endif
11307 if (freq == 0) {
11308 WL_ERR(("Invalid channel, fail to change channel to freq\n"));
11309 kfree(notif_bss_info);
11310 return -EINVAL;
11311 }
11312 channel = ieee80211_get_channel(wiphy, freq);
11313 WL_SCAN(("BSSID %pM, channel %2d(%2d %sMHz), rssi %3d, capa 0x04%x, mgmt_type %d, "
11314 "frame_len %d, SSID \"%s\"\n",
11315 &bi->BSSID, notif_bss_info->channel, CHSPEC_CHANNEL(chanspec),
11316 CHSPEC_IS20(chanspec)?"20":
11317 CHSPEC_IS40(chanspec)?"40":
11318 CHSPEC_IS80(chanspec)?"80":"160",
11319 notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
11320 notif_bss_info->frame_len, bi->SSID));
11321 if (unlikely(!channel)) {
11322 WL_ERR(("ieee80211_get_channel error, freq=%d, channel=%d\n",
11323 freq, notif_bss_info->channel));
11324 kfree(notif_bss_info);
11325 return -EINVAL;
11326 }
11327
11328 signal = notif_bss_info->rssi * 100;
11329 if (!mgmt->u.probe_resp.timestamp) {
11330 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39))
11331 struct timespec ts;
11332 get_monotonic_boottime(&ts);
11333 mgmt->u.probe_resp.timestamp = ((u64)ts.tv_sec*1000000)
11334 + ts.tv_nsec / 1000;
11335 #else
11336 struct timeval tv;
11337 do_gettimeofday(&tv);
11338 mgmt->u.probe_resp.timestamp = ((u64)tv.tv_sec*1000000)
11339 + tv.tv_usec;
11340 #endif
11341 }
11342
11343
11344 cbss = cfg80211_inform_bss_frame(wiphy, channel, mgmt,
11345 le16_to_cpu(notif_bss_info->frame_len), signal, aflags);
11346 if (unlikely(!cbss)) {
11347 WL_ERR(("cfg80211_inform_bss_frame error\n"));
11348 err = -EINVAL;
11349 goto out_err;
11350 }
11351
11352 CFG80211_PUT_BSS(wiphy, cbss);
11353
11354 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID) &&
11355 (cfg->sched_scan_req && !cfg->scan_request)) {
11356 alloc_len = sizeof(log_conn_event_t) + IEEE80211_MAX_SSID_LEN + sizeof(uint16) +
11357 sizeof(int16);
11358 event_data = MALLOCZ(dhdp->osh, alloc_len);
11359 if (!event_data) {
11360 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
11361 "length(%d)\n", __func__, alloc_len));
11362 goto out_err;
11363 }
11364 tlv_len = 3 * sizeof(tlv_log);
11365 event_data->tlvs = MALLOC(dhdp->osh, tlv_len);
11366 if (!event_data->tlvs) {
11367 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
11368 "length(%d)\n", __func__, tlv_len));
11369 goto out_err;
11370 }
11371
11372 payload_len = sizeof(log_conn_event_t);
11373 event_data->event = WIFI_EVENT_DRIVER_PNO_SCAN_RESULT_FOUND;
11374 tlv_data = event_data->tlvs;
11375
11376 /* ssid */
11377 tlv_data->tag = WIFI_TAG_SSID;
11378 tlv_data->len = bi->SSID_len;
11379 memcpy(tlv_data->value, bi->SSID, bi->SSID_len);
11380 payload_len += TLV_LOG_SIZE(tlv_data);
11381 tlv_data = TLV_LOG_NEXT(tlv_data);
11382
11383 /* channel */
11384 tlv_data->tag = WIFI_TAG_CHANNEL;
11385 tlv_data->len = sizeof(uint16);
11386 memcpy(tlv_data->value, &notif_bss_info->channel, sizeof(uint16));
11387 payload_len += TLV_LOG_SIZE(tlv_data);
11388 tlv_data = TLV_LOG_NEXT(tlv_data);
11389
11390 /* rssi */
11391 tlv_data->tag = WIFI_TAG_RSSI;
11392 tlv_data->len = sizeof(int16);
11393 memcpy(tlv_data->value, &notif_bss_info->rssi, sizeof(int16));
11394 payload_len += TLV_LOG_SIZE(tlv_data);
11395 tlv_data = TLV_LOG_NEXT(tlv_data);
11396
11397 dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
11398 event_data, payload_len);
11399 MFREE(dhdp->osh, event_data->tlvs, tlv_len);
11400 MFREE(dhdp->osh, event_data, alloc_len);
11401 }
11402
11403 out_err:
11404 kfree(notif_bss_info);
11405 return err;
11406 }
11407
11408 static bool wl_is_linkup(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, struct net_device *ndev)
11409 {
11410 u32 event = ntoh32(e->event_type);
11411 u32 status = ntoh32(e->status);
11412 u16 flags = ntoh16(e->flags);
11413 #if defined(CUSTOM_SET_ANTNPM) || defined(CUSTOM_SET_OCLOFF)
11414 dhd_pub_t *dhd;
11415 dhd = (dhd_pub_t *)(cfg->pub);
11416 #endif /* CUSTOM_SET_ANTNPM */
11417
11418 WL_DBG(("event %d, status %d flags %x\n", event, status, flags));
11419 if (event == WLC_E_SET_SSID) {
11420 if (status == WLC_E_STATUS_SUCCESS) {
11421 #ifdef CUSTOM_SET_ANTNPM
11422 if (dhd->mimo_ant_set) {
11423 int err = 0;
11424
11425 WL_ERR(("[WIFI_SEC] mimo_ant_set = %d\n", dhd->mimo_ant_set));
11426 err = wldev_iovar_setint(ndev, "txchain", dhd->mimo_ant_set);
11427 if (err != 0) {
11428 WL_ERR(("[WIFI_SEC] Fail set txchain\n"));
11429 }
11430 err = wldev_iovar_setint(ndev, "rxchain", dhd->mimo_ant_set);
11431 if (err != 0) {
11432 WL_ERR(("[WIFI_SEC] Fail set rxchain\n"));
11433 }
11434 }
11435 #endif /* CUSTOM_SET_ANTNPM */
11436 #ifdef CUSTOM_SET_OCLOFF
11437 if (dhd->ocl_off) {
11438 int err = 0;
11439 int ocl_enable = 0;
11440 err = wldev_iovar_setint(ndev, "ocl_enable", ocl_enable);
11441 if (err != 0) {
11442 WL_ERR(("[WIFI_SEC] %s: Set ocl_enable %d failed %d\n",
11443 __FUNCTION__, ocl_enable, err));
11444 } else {
11445 WL_ERR(("[WIFI_SEC] %s: Set ocl_enable %d succeeded %d\n",
11446 __FUNCTION__, ocl_enable, err));
11447 }
11448 }
11449 #endif /* CUSTOM_SET_OCLOFF */
11450 if (!wl_is_ibssmode(cfg, ndev))
11451 return true;
11452 }
11453 } else if (event == WLC_E_LINK) {
11454 if (flags & WLC_EVENT_MSG_LINK)
11455 return true;
11456 }
11457
11458 WL_DBG(("wl_is_linkup false\n"));
11459 return false;
11460 }
11461
11462 #ifdef WL_LASTEVT
11463 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e, void *data)
11464 {
11465 u32 event = ntoh32(e->event_type);
11466 u16 flags = ntoh16(e->flags);
11467 wl_last_event_t *last_event = (wl_last_event_t *)data;
11468 u32 len = ntoh32(e->datalen);
11469
11470 if (event == WLC_E_DEAUTH_IND ||
11471 event == WLC_E_DISASSOC_IND ||
11472 event == WLC_E_DISASSOC ||
11473 event == WLC_E_DEAUTH) {
11474 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event)));
11475 return true;
11476 } else if (event == WLC_E_LINK) {
11477 if (!(flags & WLC_EVENT_MSG_LINK)) {
11478 if (last_event && len > 0) {
11479 u32 current_time = last_event->current_time;
11480 u32 timestamp = last_event->timestamp;
11481 u32 event_type = last_event->event.event_type;
11482 u32 status = last_event->event.status;
11483 u32 reason = last_event->event.reason;
11484
11485 WL_ERR(("Last roam event before disconnection : current_time %d,"
11486 " time %d, type %d, status %d, reason %d\n",
11487 current_time, timestamp, event_type, status, reason));
11488 }
11489 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event)));
11490 return true;
11491 }
11492 }
11493
11494 return false;
11495 }
11496 #else
11497 static bool wl_is_linkdown(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
11498 {
11499 u32 event = ntoh32(e->event_type);
11500 u16 flags = ntoh16(e->flags);
11501
11502 if (event == WLC_E_DEAUTH_IND ||
11503 event == WLC_E_DISASSOC_IND ||
11504 event == WLC_E_DISASSOC ||
11505 event == WLC_E_DEAUTH) {
11506 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event)));
11507 return true;
11508 } else if (event == WLC_E_LINK) {
11509 if (!(flags & WLC_EVENT_MSG_LINK)) {
11510 WL_ERR(("Link down Reason : %s\n", bcmevent_get_name(event)));
11511 return true;
11512 }
11513 }
11514
11515 return false;
11516 }
11517 #endif /* WL_LASTEVT */
11518
11519 static bool wl_is_nonetwork(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
11520 {
11521 u32 event = ntoh32(e->event_type);
11522 u32 status = ntoh32(e->status);
11523
11524 if (event == WLC_E_LINK && status == WLC_E_STATUS_NO_NETWORKS)
11525 return true;
11526 if (event == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS)
11527 return true;
11528
11529 return false;
11530 }
11531
11532 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
11533 * to AP/P2P GO via events. If this change is backported to kernel for which
11534 * this driver is being built, then define WL_CFG80211_STA_EVENT. You
11535 * should use this new/del sta event mechanism for BRCM supplicant >= 22.
11536 */
11537 static s32
11538 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
11539 const wl_event_msg_t *e, void *data)
11540 {
11541 s32 err = 0;
11542 u32 event = ntoh32(e->event_type);
11543 u32 reason = ntoh32(e->reason);
11544 u32 len = ntoh32(e->datalen);
11545 u32 status = ntoh32(e->status);
11546
11547 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
11548 bool isfree = false;
11549 u8 *mgmt_frame;
11550 u8 bsscfgidx = e->bsscfgidx;
11551 s32 freq;
11552 s32 channel;
11553 u8 *body = NULL;
11554 u16 fc = 0;
11555
11556 struct ieee80211_supported_band *band;
11557 struct ether_addr da;
11558 struct ether_addr bssid;
11559 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11560 channel_info_t ci;
11561 #else
11562 struct station_info sinfo;
11563 #endif
11564
11565 WL_DBG(("event %d status %d reason %d\n", event, ntoh32(e->status), reason));
11566 /* if link down, bsscfg is disabled. */
11567 if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
11568 wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) {
11569 wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
11570 WL_INFORM(("AP mode link down !! \n"));
11571 complete(&cfg->iface_disable);
11572 return 0;
11573 }
11574
11575 if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
11576 (reason == WLC_E_REASON_INITIAL_ASSOC) &&
11577 (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) {
11578 if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
11579 /* AP/GO brought up successfull in firmware */
11580 printf("%s: ** AP/GO Link up event **\n", __FUNCTION__);
11581 wl_set_drv_status(cfg, AP_CREATED, ndev);
11582 wake_up_interruptible(&cfg->netif_change_event);
11583 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
11584 dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_GO, -1);
11585 }
11586 return 0;
11587 }
11588 }
11589
11590 if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
11591 printf("%s: event %s(%d) status %d reason %d\n", __FUNCTION__,
11592 bcmevent_get_name(event), event, ntoh32(e->status), reason);
11593 }
11594
11595 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT)
11596 WL_DBG(("Enter \n"));
11597 if (!len && (event == WLC_E_DEAUTH)) {
11598 len = 2; /* reason code field */
11599 data = &reason;
11600 }
11601 if (len) {
11602 body = kzalloc(len, GFP_KERNEL);
11603
11604 if (body == NULL) {
11605 WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
11606 return WL_INVALID;
11607 }
11608 }
11609 memset(&bssid, 0, ETHER_ADDR_LEN);
11610 WL_DBG(("Enter event %d ndev %p\n", event, ndev));
11611 if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
11612 kfree(body);
11613 return WL_INVALID;
11614 }
11615 if (len)
11616 memcpy(body, data, len);
11617
11618 wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
11619 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
11620 memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
11621 memset(&bssid, 0, sizeof(bssid));
11622 err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
11623 switch (event) {
11624 case WLC_E_ASSOC_IND:
11625 fc = FC_ASSOC_REQ;
11626 break;
11627 case WLC_E_REASSOC_IND:
11628 fc = FC_REASSOC_REQ;
11629 break;
11630 case WLC_E_DISASSOC_IND:
11631 fc = FC_DISASSOC;
11632 break;
11633 case WLC_E_DEAUTH_IND:
11634 fc = FC_DISASSOC;
11635 break;
11636 case WLC_E_DEAUTH:
11637 fc = FC_DISASSOC;
11638 break;
11639 default:
11640 fc = 0;
11641 goto exit;
11642 }
11643 memset(&ci, 0, sizeof(ci));
11644 if ((err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) {
11645 kfree(body);
11646 return err;
11647 }
11648
11649 channel = dtoh32(ci.hw_channel);
11650 if (channel <= CH_MAX_2G_CHANNEL)
11651 band = wiphy->bands[IEEE80211_BAND_2GHZ];
11652 else
11653 band = wiphy->bands[IEEE80211_BAND_5GHZ];
11654 if (!band) {
11655 WL_ERR(("No valid band\n"));
11656 if (body)
11657 kfree(body);
11658 return -EINVAL;
11659 }
11660 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11661 freq = ieee80211_channel_to_frequency(channel);
11662 (void)band->band;
11663 #else
11664 freq = ieee80211_channel_to_frequency(channel, band->band);
11665 #endif
11666
11667 err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
11668 &mgmt_frame, &len, body);
11669 if (err < 0)
11670 goto exit;
11671 isfree = true;
11672
11673 if ((event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) ||
11674 (event == WLC_E_DISASSOC_IND) ||
11675 ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH))) {
11676 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
11677 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0);
11678 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
11679 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0, GFP_ATOMIC);
11680 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
11681 defined(WL_COMPAT_WIRELESS)
11682 cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
11683 #else
11684 cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
11685 #endif
11686 }
11687
11688 exit:
11689 if (isfree)
11690 kfree(mgmt_frame);
11691 if (body)
11692 kfree(body);
11693 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
11694 sinfo.filled = 0;
11695 if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
11696 reason == DOT11_SC_SUCCESS) {
11697 /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
11698 * STATION_INFO_ASSOC_REQ_IES flag
11699 */
11700 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
11701 sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
11702 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
11703 if (!data) {
11704 WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
11705 return -EINVAL;
11706 }
11707 sinfo.assoc_req_ies = data;
11708 sinfo.assoc_req_ies_len = len;
11709 printf("%s: connected device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
11710 wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS,
11711 WL_EXT_STATUS_GC_CONNECTED, NULL);
11712 cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
11713 } else if (event == WLC_E_DISASSOC_IND) {
11714 printf("%s: disassociated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
11715 wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS,
11716 WL_EXT_STATUS_GC_DISCONNECTED, NULL);
11717 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
11718 } else if ((event == WLC_E_DEAUTH_IND) ||
11719 ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED))) {
11720 printf("%s: deauthenticated device "MACDBG"\n", __FUNCTION__, MAC2STRDBG(e->addr.octet));
11721 wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS,
11722 WL_EXT_STATUS_GC_DISCONNECTED, NULL);
11723 cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
11724 }
11725 #endif
11726 return err;
11727 }
11728
11729 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11730 #define MAX_ASSOC_REJECT_ERR_STATUS 5
11731 int wl_get_connect_failed_status(struct bcm_cfg80211 *cfg, const wl_event_msg_t *e)
11732 {
11733 u32 status = ntoh32(e->status);
11734
11735 cfg->assoc_reject_status = 0;
11736
11737 if (status == WLC_E_STATUS_FAIL) {
11738 WL_ERR(("auth assoc status event=%d e->status %d e->reason %d \n",
11739 ntoh32(cfg->event_auth_assoc.event_type),
11740 (int)ntoh32(cfg->event_auth_assoc.status),
11741 (int)ntoh32(cfg->event_auth_assoc.reason)));
11742
11743 switch ((int)ntoh32(cfg->event_auth_assoc.status)) {
11744 case WLC_E_STATUS_NO_ACK:
11745 cfg->assoc_reject_status = 1;
11746 break;
11747 case WLC_E_STATUS_FAIL:
11748 cfg->assoc_reject_status = 2;
11749 break;
11750 case WLC_E_STATUS_UNSOLICITED:
11751 cfg->assoc_reject_status = 3;
11752 break;
11753 case WLC_E_STATUS_TIMEOUT:
11754 cfg->assoc_reject_status = 4;
11755 break;
11756 case WLC_E_STATUS_ABORT:
11757 cfg->assoc_reject_status = 5;
11758 break;
11759 default:
11760 break;
11761 }
11762 if (cfg->assoc_reject_status) {
11763 if (ntoh32(cfg->event_auth_assoc.event_type) == WLC_E_ASSOC) {
11764 cfg->assoc_reject_status += MAX_ASSOC_REJECT_ERR_STATUS;
11765 }
11766 }
11767 }
11768
11769 WL_ERR(("assoc_reject_status %d \n", cfg->assoc_reject_status));
11770
11771 return 0;
11772 }
11773
11774 s32 wl_cfg80211_get_connect_failed_status(struct net_device *dev, char* cmd, int total_len)
11775 {
11776 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
11777 int bytes_written = 0;
11778
11779 if (cfg == NULL) {
11780 return -1;
11781 }
11782
11783 memset(cmd, 0, total_len);
11784 bytes_written = snprintf(cmd, 30, "assoc_reject.status %d", cfg->assoc_reject_status);
11785
11786 WL_ERR(("cmd: %s \n", cmd));
11787
11788 return bytes_written;
11789 }
11790 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
11791
11792 static s32
11793 wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev,
11794 const wl_event_msg_t *e)
11795 {
11796 u32 reason = ntoh32(e->reason);
11797 u32 event = ntoh32(e->event_type);
11798 struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
11799 WL_DBG(("event type : %d, reason : %d\n", event, reason));
11800
11801 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11802 memcpy(&cfg->event_auth_assoc, e, sizeof(wl_event_msg_t));
11803 WL_ERR(("event=%d status %d reason %d \n",
11804 ntoh32(cfg->event_auth_assoc.event_type),
11805 ntoh32(cfg->event_auth_assoc.status),
11806 ntoh32(cfg->event_auth_assoc.reason)));
11807 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
11808 if (sec) {
11809 switch (event) {
11810 case WLC_E_ASSOC:
11811 case WLC_E_AUTH:
11812 sec->auth_assoc_res_status = reason;
11813 default:
11814 break;
11815 }
11816 } else
11817 WL_ERR(("sec is NULL\n"));
11818 return 0;
11819 }
11820
11821 static s32
11822 wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
11823 const wl_event_msg_t *e, void *data)
11824 {
11825 s32 err = 0;
11826 u32 event = ntoh32(e->event_type);
11827 u16 flags = ntoh16(e->flags);
11828 u32 status = ntoh32(e->status);
11829 bool active;
11830 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11831 struct ieee80211_channel *channel = NULL;
11832 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
11833 u32 chanspec, chan;
11834 u32 freq, band;
11835 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
11836
11837 if (event == WLC_E_JOIN) {
11838 WL_DBG(("joined in IBSS network\n"));
11839 }
11840 if (event == WLC_E_START) {
11841 WL_DBG(("started IBSS network\n"));
11842 }
11843 if (event == WLC_E_JOIN || event == WLC_E_START ||
11844 (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
11845 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11846 err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
11847 if (unlikely(err)) {
11848 WL_ERR(("Could not get chanspec %d\n", err));
11849 return err;
11850 }
11851 chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
11852 band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
11853 freq = ieee80211_channel_to_frequency(chan, band);
11854 channel = ieee80211_get_channel(wiphy, freq);
11855 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
11856 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
11857 /* ROAM or Redundant */
11858 u8 *cur_bssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
11859 if (memcmp(cur_bssid, &e->addr, ETHER_ADDR_LEN) == 0) {
11860 WL_DBG(("IBSS connected event from same BSSID("
11861 MACDBG "), ignore it\n", MAC2STRDBG(cur_bssid)));
11862 return err;
11863 }
11864 WL_INFORM(("IBSS BSSID is changed from " MACDBG " to " MACDBG "\n",
11865 MAC2STRDBG(cur_bssid), MAC2STRDBG((const u8 *)&e->addr)));
11866 wl_get_assoc_ies(cfg, ndev);
11867 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
11868 wl_update_bss_info(cfg, ndev, false);
11869 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11870 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
11871 #else
11872 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
11873 #endif
11874 }
11875 else {
11876 /* New connection */
11877 WL_INFORM(("IBSS connected to " MACDBG "\n",
11878 MAC2STRDBG((const u8 *)&e->addr)));
11879 wl_link_up(cfg);
11880 wl_get_assoc_ies(cfg, ndev);
11881 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
11882 wl_update_bss_info(cfg, ndev, false);
11883 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
11884 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, channel, GFP_KERNEL);
11885 #else
11886 cfg80211_ibss_joined(ndev, (const s8 *)&e->addr, GFP_KERNEL);
11887 #endif
11888 wl_set_drv_status(cfg, CONNECTED, ndev);
11889 active = true;
11890 wl_update_prof(cfg, ndev, NULL, (const void *)&active, WL_PROF_ACT);
11891 }
11892 } else if ((event == WLC_E_LINK && !(flags & WLC_EVENT_MSG_LINK)) ||
11893 event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
11894 wl_clr_drv_status(cfg, CONNECTED, ndev);
11895 wl_link_down(cfg);
11896 wl_init_prof(cfg, ndev);
11897 }
11898 else if (event == WLC_E_SET_SSID && status == WLC_E_STATUS_NO_NETWORKS) {
11899 WL_DBG(("no action - join fail (IBSS mode)\n"));
11900 }
11901 else {
11902 WL_DBG(("no action (IBSS mode)\n"));
11903 }
11904 return err;
11905 }
11906
11907 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
11908 #define WiFiALL_OUI "\x50\x6F\x9A" /* Wi-FiAll OUI */
11909 #define WiFiALL_OUI_LEN 3
11910 #define WiFiALL_OUI_TYPE 16
11911
11912 int wl_get_bss_info(struct bcm_cfg80211 *cfg, struct net_device *dev, uint8 *mac)
11913 {
11914 s32 err = 0;
11915 struct wl_bss_info *bi;
11916 uint8 eabuf[ETHER_ADDR_LEN];
11917 u32 rate, channel, freq, supported_rate, nss = 0, mcs_map, mode_80211 = 0;
11918 char rate_str[4];
11919 u8 *ie = NULL;
11920 u32 ie_len;
11921 struct wiphy *wiphy;
11922 struct cfg80211_bss *bss;
11923 bcm_tlv_t *interworking_ie = NULL;
11924 bcm_tlv_t *tlv_ie = NULL;
11925 bcm_tlv_t *vht_ie = NULL;
11926 vndr_ie_t *vndrie;
11927 int16 ie_11u_rel_num = -1, ie_mu_mimo_cap = -1;
11928 u32 i, remained_len, count = 0;
11929 char roam_count_str[4], akm_str[4];
11930 s32 val = 0;
11931
11932 /* get BSS information */
11933
11934 strncpy(cfg->bss_info, "x x x x x x x x x x x x x", GET_BSS_INFO_LEN);
11935
11936 memset(cfg->extra_buf, 0, WL_EXTRA_BUF_MAX);
11937 *(u32 *) cfg->extra_buf = htod32(WL_EXTRA_BUF_MAX);
11938
11939 err = wldev_ioctl_get(dev, WLC_GET_BSS_INFO, cfg->extra_buf, WL_EXTRA_BUF_MAX);
11940 if (unlikely(err)) {
11941 WL_ERR(("Could not get bss info %d\n", err));
11942 cfg->roam_count = 0;
11943 return -1;
11944 }
11945
11946 if (!mac) {
11947 WL_ERR(("mac is null \n"));
11948 cfg->roam_count = 0;
11949 return -1;
11950 }
11951
11952 memcpy(eabuf, mac, ETHER_ADDR_LEN);
11953
11954 bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
11955 channel = wf_chspec_ctlchan(bi->chanspec);
11956
11957 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
11958 freq = ieee80211_channel_to_frequency(channel);
11959 #else
11960 if (channel > 14) {
11961 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
11962 } else {
11963 freq = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
11964 }
11965 #endif
11966 rate = 0;
11967 err = wldev_ioctl_get(dev, WLC_GET_RATE, &rate, sizeof(rate));
11968 if (err) {
11969 WL_ERR(("Could not get rate (%d)\n", err));
11970 snprintf(rate_str, sizeof(rate_str), "x"); // Unknown
11971
11972 } else {
11973 rate = dtoh32(rate);
11974 snprintf(rate_str, sizeof(rate_str), "%d", (rate/2));
11975 }
11976
11977 //supported maximum rate
11978 supported_rate = (bi->rateset.rates[bi->rateset.count - 1] & 0x7f) / 2;
11979
11980 if (supported_rate < 12) {
11981 mode_80211 = 0; //11b maximum rate is 11Mbps. 11b mode
11982 } else {
11983 //It's not HT Capable case.
11984 if (channel > 14) {
11985 mode_80211 = 3; // 11a mode
11986 } else {
11987 mode_80211 = 1; // 11g mode
11988 }
11989 }
11990
11991 if (bi->n_cap) {
11992 /* check Rx MCS Map for HT */
11993 nss = 0;
11994 mode_80211 = 2;
11995 for (i = 0; i < MAX_STREAMS_SUPPORTED; i++) {
11996 int8 bitmap = 0xFF;
11997 if (i == MAX_STREAMS_SUPPORTED-1) {
11998 bitmap = 0x7F;
11999 }
12000 if (bi->basic_mcs[i] & bitmap) {
12001 nss++;
12002 }
12003 }
12004 }
12005
12006 if (bi->vht_cap) {
12007 nss = 0;
12008 mode_80211 = 4;
12009 for (i = 1; i <= VHT_CAP_MCS_MAP_NSS_MAX; i++) {
12010 mcs_map = VHT_MCS_MAP_GET_MCS_PER_SS(i, dtoh16(bi->vht_rxmcsmap));
12011 if (mcs_map != VHT_CAP_MCS_MAP_NONE) {
12012 nss++;
12013 }
12014 }
12015 }
12016
12017 if (nss) {
12018 nss = nss - 1;
12019 }
12020
12021 wiphy = bcmcfg_to_wiphy(cfg);
12022 bss = CFG80211_GET_BSS(wiphy, NULL, eabuf, bi->SSID, bi->SSID_len);
12023 if (!bss) {
12024 WL_ERR(("Could not find the AP\n"));
12025 } else {
12026 #if defined(WL_CFG80211_P2P_DEV_IF)
12027 ie = (u8 *)bss->ies->data;
12028 ie_len = bss->ies->len;
12029 #else
12030 ie = bss->information_elements;
12031 ie_len = bss->len_information_elements;
12032 #endif /* WL_CFG80211_P2P_DEV_IF */
12033 }
12034
12035 if (ie) {
12036 ie_mu_mimo_cap = 0;
12037 ie_11u_rel_num = 0;
12038
12039 if (bi->vht_cap) {
12040 if ((vht_ie = bcm_parse_tlvs(ie, (u32)ie_len,
12041 DOT11_MNG_VHT_CAP_ID)) != NULL) {
12042 ie_mu_mimo_cap = (vht_ie->data[2] & 0x08) >> 3;
12043 }
12044 }
12045
12046 if ((interworking_ie = bcm_parse_tlvs(ie, (u32)ie_len,
12047 DOT11_MNG_INTERWORKING_ID)) != NULL) {
12048 if ((tlv_ie = bcm_parse_tlvs(ie, (u32)ie_len, DOT11_MNG_VS_ID)) != NULL) {
12049 remained_len = ie_len;
12050
12051 while (tlv_ie) {
12052 if (count > MAX_VNDR_IE_NUMBER)
12053 break;
12054
12055 if (tlv_ie->id == DOT11_MNG_VS_ID) {
12056 vndrie = (vndr_ie_t *) tlv_ie;
12057
12058 if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
12059 WL_ERR(("%s: invalid vndr ie."
12060 "length is too small %d\n",
12061 __FUNCTION__, vndrie->len));
12062 break;
12063 }
12064
12065 if (!bcmp(vndrie->oui,
12066 (u8*)WiFiALL_OUI, WiFiALL_OUI_LEN) &&
12067 (vndrie->data[0] == WiFiALL_OUI_TYPE))
12068 {
12069 WL_ERR(("Found Wi-FiAll OUI oui.\n"));
12070 ie_11u_rel_num = vndrie->data[1];
12071 ie_11u_rel_num = (ie_11u_rel_num & 0xf0)>>4;
12072 ie_11u_rel_num += 1;
12073
12074 break;
12075 }
12076 }
12077 count++;
12078 tlv_ie = bcm_next_tlv(tlv_ie, &remained_len);
12079 }
12080 }
12081 }
12082 }
12083
12084 for (i = 0; i < bi->SSID_len; i++) {
12085 if (bi->SSID[i] == ' ') {
12086 bi->SSID[i] = '_';
12087 }
12088 }
12089
12090 //0 : None, 1 : OKC, 2 : FT, 3 : CCKM
12091 err = wldev_iovar_getint(dev, "wpa_auth", &val);
12092 if (unlikely(err)) {
12093 WL_ERR(("could not get wpa_auth (%d)\n", err));
12094 snprintf(akm_str, sizeof(akm_str), "x"); // Unknown
12095 } else {
12096 WL_ERR(("wpa_auth val %d \n", val));
12097 #if defined(BCMEXTCCX)
12098 if (val & (WPA_AUTH_CCKM | WPA2_AUTH_CCKM)) {
12099 snprintf(akm_str, sizeof(akm_str), "3");
12100 } else
12101 #endif
12102 if (val & WPA2_AUTH_FT) {
12103 snprintf(akm_str, sizeof(akm_str), "2");
12104 } else if (val & (WPA_AUTH_UNSPECIFIED | WPA2_AUTH_UNSPECIFIED)) {
12105 snprintf(akm_str, sizeof(akm_str), "1");
12106 } else {
12107 snprintf(akm_str, sizeof(akm_str), "0");
12108 }
12109 }
12110
12111 if (cfg->roam_offload) {
12112 snprintf(roam_count_str, sizeof(roam_count_str), "x"); // Unknown
12113 } else {
12114 snprintf(roam_count_str, sizeof(roam_count_str), "%d", cfg->roam_count);
12115 }
12116 cfg->roam_count = 0;
12117
12118 WL_ERR(("BSSID:" MACDBG " SSID %s \n", MAC2STRDBG(eabuf), bi->SSID));
12119 WL_ERR(("freq:%d, BW:%s, RSSI:%d dBm, Rate:%d Mbps, 11mode:%d, stream:%d,"
12120 "MU-MIMO:%d, Passpoint:%d, SNR:%d, Noise:%d, \n"
12121 "akm:%s roam:%s \n",
12122 freq, wf_chspec_to_bw_str(bi->chanspec),
12123 dtoh32(bi->RSSI), (rate / 2), mode_80211, nss,
12124 ie_mu_mimo_cap, ie_11u_rel_num, bi->SNR, bi->phy_noise,
12125 akm_str, roam_count_str));
12126
12127 if (ie) {
12128 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
12129 "%02x:%02x:%02x %d %s %d %s %d %d %d %d %d %d %s %s",
12130 eabuf[0], eabuf[1], eabuf[2],
12131 freq, wf_chspec_to_bw_str(bi->chanspec),
12132 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
12133 ie_mu_mimo_cap, ie_11u_rel_num,
12134 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
12135 } else {
12136 //ie_mu_mimo_cap and ie_11u_rel_num is unknow.
12137 snprintf(cfg->bss_info, GET_BSS_INFO_LEN,
12138 "%02x:%02x:%02x %d %s %d %s %d %d x x %d %d %s %s",
12139 eabuf[0], eabuf[1], eabuf[2],
12140 freq, wf_chspec_to_bw_str(bi->chanspec),
12141 dtoh32(bi->RSSI), rate_str, mode_80211, nss,
12142 bi->SNR, bi->phy_noise, akm_str, roam_count_str);
12143 }
12144
12145 CFG80211_PUT_BSS(wiphy, bss);
12146
12147 return 0;
12148 }
12149
12150 s32 wl_cfg80211_get_bss_info(struct net_device *dev, char* cmd, int total_len)
12151 {
12152 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
12153
12154 if (cfg == NULL) {
12155 return -1;
12156 }
12157
12158 memset(cmd, 0, total_len);
12159 memcpy(cmd, cfg->bss_info, GET_BSS_INFO_LEN);
12160
12161 WL_ERR(("cmd: %s \n", cmd));
12162
12163 return GET_BSS_INFO_LEN;
12164 }
12165
12166 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12167
12168 static s32
12169 wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12170 const wl_event_msg_t *e, void *data)
12171 {
12172 bool act;
12173 struct net_device *ndev = NULL;
12174 s32 err = 0;
12175 u32 event = ntoh32(e->event_type);
12176 struct wiphy *wiphy = NULL;
12177 struct cfg80211_bss *bss = NULL;
12178 struct wlc_ssid *ssid = NULL;
12179 u8 *bssid = 0;
12180 dhd_pub_t *dhdp;
12181 int vndr_oui_num = 0;
12182 char vndr_oui[MAX_VNDR_OUI_STR_LEN] = {0, };
12183
12184 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12185 dhdp = (dhd_pub_t *)(cfg->pub);
12186 BCM_REFERENCE(dhdp);
12187
12188 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
12189 err = wl_notify_connect_status_ap(cfg, ndev, e, data);
12190 } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS) {
12191 err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
12192 } else if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_BSS) {
12193 WL_DBG(("wl_notify_connect_status : event %d status : %d ndev %p\n",
12194 ntoh32(e->event_type), ntoh32(e->status), ndev));
12195 if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
12196 wl_get_auth_assoc_status(cfg, ndev, e);
12197 return 0;
12198 }
12199 DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
12200 if (wl_is_linkup(cfg, e, ndev)) {
12201 wl_link_up(cfg);
12202 act = true;
12203 if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
12204 if (event == WLC_E_LINK &&
12205 #ifdef DHD_LOSSLESS_ROAMING
12206 !cfg->roam_offload &&
12207 #endif /* DHD_LOSSLESS_ROAMING */
12208 wl_get_drv_status(cfg, CONNECTED, ndev)) {
12209 wl_bss_roaming_done(cfg, ndev, e, data);
12210 }
12211
12212 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
12213 vndr_oui_num = wl_vndr_ies_get_vendor_oui(cfg,
12214 ndev, vndr_oui, ARRAYSIZE(vndr_oui));
12215 #if defined(STAT_REPORT)
12216 /* notify STA connection only */
12217 wl_stat_report_notify_connected(cfg);
12218 #endif /* STAT_REPORT */
12219 }
12220
12221 printf("wl_bss_connect_done succeeded with "
12222 MACDBG " %s%s\n", MAC2STRDBG((const u8*)(&e->addr)),
12223 vndr_oui_num > 0 ? "vndr_oui: " : "",
12224 vndr_oui_num > 0 ? vndr_oui : "");
12225
12226 wl_bss_connect_done(cfg, ndev, e, data, true);
12227 dhd_conf_set_intiovar(cfg->pub, WLC_SET_VAR, "phy_oclscdenable", cfg->pub->conf->phy_oclscdenable, 0, FALSE);
12228 WL_DBG(("joined in BSS network \"%s\"\n",
12229 ((struct wlc_ssid *)
12230 wl_read_prof(cfg, ndev, WL_PROF_SSID))->SSID));
12231
12232 #ifdef WBTEXT
12233 if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION &&
12234 dhdp->wbtext_support &&
12235 event == WLC_E_SET_SSID) {
12236 /* set wnm_keepalives_max_idle after association */
12237 wl_cfg80211_wbtext_set_wnm_maxidle(cfg, ndev);
12238 /* send nbr request or BTM query to update RCC */
12239 wl_cfg80211_wbtext_update_rcc(cfg, ndev);
12240 }
12241 #endif /* WBTEXT */
12242 }
12243 wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
12244 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
12245 dhd_conf_set_wme(cfg->pub, 0);
12246 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
12247 dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_CLIENT, -1);
12248 }
12249 } else if (WL_IS_LINKDOWN(cfg, e, data) ||
12250 ((event == WLC_E_SET_SSID) &&
12251 (ntoh32(e->status) != WLC_E_STATUS_SUCCESS) &&
12252 (wl_get_drv_status(cfg, CONNECTED, ndev)))) {
12253
12254 WL_INFORM(("connection state bit status: [%d:%d:%d:%d]\n",
12255 wl_get_drv_status(cfg, CONNECTING, ndev),
12256 wl_get_drv_status(cfg, CONNECTED, ndev),
12257 wl_get_drv_status(cfg, DISCONNECTING, ndev),
12258 wl_get_drv_status(cfg, NESTED_CONNECT, ndev)));
12259
12260 if (wl_get_drv_status(cfg, DISCONNECTING, ndev) &&
12261 (wl_get_drv_status(cfg, NESTED_CONNECT, ndev) ||
12262 wl_get_drv_status(cfg, CONNECTING, ndev))) {
12263 /* wl_cfg80211_connect was called before 'DISCONNECTING' was
12264 * cleared. Deauth/Link down event is caused by WLC_DISASSOC
12265 * command issued from the wl_cfg80211_connect context. Ignore
12266 * the event to avoid pre-empting the current connection
12267 */
12268 WL_INFORM(("Nested connection case. Drop event. \n"));
12269 wl_clr_drv_status(cfg, NESTED_CONNECT, ndev);
12270 wl_clr_drv_status(cfg, DISCONNECTING, ndev);
12271 /* Not in 'CONNECTED' state, clear it */
12272 wl_clr_drv_status(cfg, CONNECTED, ndev);
12273 return 0;
12274 }
12275
12276 #ifdef DHD_LOSSLESS_ROAMING
12277 wl_del_roam_timeout(cfg);
12278 #endif
12279 #ifdef P2PLISTEN_AP_SAMECHN
12280 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
12281 wl_cfg80211_set_p2p_resp_ap_chn(ndev, 0);
12282 cfg->p2p_resp_apchn_status = false;
12283 WL_DBG(("p2p_resp_apchn_status Turn OFF \n"));
12284 }
12285 #endif /* P2PLISTEN_AP_SAMECHN */
12286 wl_cfg80211_cancel_scan(cfg);
12287
12288 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
12289 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
12290 wl_get_bss_info(cfg, ndev, (u8*)(&e->addr));
12291 }
12292 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12293 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
12294 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
12295 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
12296 bool fw_assoc_state = TRUE;
12297 dhd_pub_t *dhd = (dhd_pub_t *)cfg->pub;
12298 fw_assoc_state = dhd_is_associated(dhd, e->ifidx, &err);
12299 if (!fw_assoc_state) {
12300 WL_ERR(("Event sends up even different BSSID"
12301 " cur: " MACDBG " event: " MACDBG"\n",
12302 MAC2STRDBG(curbssid),
12303 MAC2STRDBG((const u8*)(&e->addr))));
12304 } else {
12305 WL_ERR(("BSSID of event is not the connected BSSID"
12306 "(ignore it) cur: " MACDBG
12307 " event: " MACDBG"\n",
12308 MAC2STRDBG(curbssid),
12309 MAC2STRDBG((const u8*)(&e->addr))));
12310 return 0;
12311 }
12312 }
12313 }
12314 /* Explicitly calling unlink to remove BSS in CFG */
12315 wiphy = bcmcfg_to_wiphy(cfg);
12316 ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
12317 bssid = (u8 *)wl_read_prof(cfg, ndev, WL_PROF_BSSID);
12318 if (ssid && bssid) {
12319 bss = CFG80211_GET_BSS(wiphy, NULL, bssid,
12320 ssid->SSID, ssid->SSID_len);
12321 if (bss) {
12322 cfg80211_unlink_bss(wiphy, bss);
12323 CFG80211_PUT_BSS(wiphy, bss);
12324 }
12325 }
12326
12327 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
12328 scb_val_t scbval;
12329 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
12330 s32 reason = 0;
12331 struct ether_addr bssid_dongle = {{0, 0, 0, 0, 0, 0}};
12332 struct ether_addr bssid_null = {{0, 0, 0, 0, 0, 0}};
12333
12334 if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND)
12335 reason = ntoh32(e->reason);
12336 /* WLAN_REASON_UNSPECIFIED is used for hang up event in Android */
12337 reason = (reason == WLAN_REASON_UNSPECIFIED)? 0 : reason;
12338
12339 printf("link down if %s may call cfg80211_disconnected. "
12340 "event : %d, reason=%d from " MACDBG "\n",
12341 ndev->name, event, ntoh32(e->reason),
12342 MAC2STRDBG((const u8*)(&e->addr)));
12343 wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY,
12344 WL_EXT_STATUS_DISCONNECTED, NULL);
12345
12346 /* roam offload does not sync BSSID always, get it from dongle */
12347 if (cfg->roam_offload) {
12348 memset(&bssid_dongle, 0, sizeof(bssid_dongle));
12349 if (wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid_dongle,
12350 sizeof(bssid_dongle)) == BCME_OK) {
12351 /* if not roam case, it would return null bssid */
12352 if (memcmp(&bssid_dongle, &bssid_null,
12353 ETHER_ADDR_LEN) != 0) {
12354 curbssid = (u8 *)&bssid_dongle;
12355 }
12356 }
12357 }
12358 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) != 0) {
12359 bool fw_assoc_state = TRUE;
12360 dhd_pub_t *dhd = (dhd_pub_t *)cfg->pub;
12361 fw_assoc_state = dhd_is_associated(dhd, e->ifidx, &err);
12362 if (!fw_assoc_state) {
12363 WL_ERR(("Event sends up even different BSSID"
12364 " cur: " MACDBG " event: " MACDBG"\n",
12365 MAC2STRDBG(curbssid),
12366 MAC2STRDBG((const u8*)(&e->addr))));
12367 } else {
12368 WL_ERR(("BSSID of event is not the connected BSSID"
12369 "(ignore it) cur: " MACDBG
12370 " event: " MACDBG"\n",
12371 MAC2STRDBG(curbssid),
12372 MAC2STRDBG((const u8*)(&e->addr))));
12373 return 0;
12374 }
12375 }
12376
12377 #ifdef DBG_PKT_MON
12378 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
12379 DHD_DBG_PKT_MON_STOP(dhdp);
12380 }
12381 #endif /* DBG_PKT_MON */
12382
12383 /* clear RSSI monitor, framework will set new cfg */
12384 #ifdef RSSI_MONITOR_SUPPORT
12385 dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg),
12386 FALSE, 0, 0);
12387 #endif /* RSSI_MONITOR_SUPPORT */
12388 if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
12389 // terence 20130703: Fix for wrong group_capab (timing issue)
12390 cfg->p2p_disconnected = 1;
12391 }
12392 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
12393 if (wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
12394 CFG80211_DISCONNECTED(ndev, reason, NULL, 0, false, GFP_KERNEL);
12395 }
12396 #endif
12397 memcpy(&cfg->disconnected_bssid, curbssid, ETHER_ADDR_LEN);
12398 wl_clr_drv_status(cfg, CONNECTED, ndev);
12399
12400 if (!wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
12401 /* To make sure disconnect, explictly send dissassoc
12402 * for BSSID 00:00:00:00:00:00 issue
12403 */
12404 scbval.val = WLAN_REASON_DEAUTH_LEAVING;
12405
12406 memcpy(&scbval.ea, curbssid, ETHER_ADDR_LEN);
12407 scbval.val = htod32(scbval.val);
12408 err = wldev_ioctl_set(ndev, WLC_DISASSOC, &scbval,
12409 sizeof(scb_val_t));
12410 if (err < 0) {
12411 WL_ERR(("WLC_DISASSOC error %d\n", err));
12412 err = 0;
12413 }
12414 }
12415
12416 /* Send up deauth and clear states */
12417 CFG80211_DISCONNECTED(ndev, reason, NULL, 0,
12418 false, GFP_KERNEL);
12419 wl_link_down(cfg);
12420 wl_init_prof(cfg, ndev);
12421 #ifdef WBTEXT
12422 /* when STA was disconnected, clear join pref and set wbtext */
12423 if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION) {
12424 char smbuf[WLC_IOCTL_SMLEN];
12425 char clear[] = { 0x01, 0x02, 0x00, 0x00, 0x03,
12426 0x02, 0x00, 0x00, 0x04, 0x02, 0x00, 0x00 };
12427 if ((err = wldev_iovar_setbuf(ndev, "join_pref",
12428 clear, sizeof(clear), smbuf,
12429 sizeof(smbuf), NULL))
12430 == BCME_OK) {
12431 if ((err = wldev_iovar_setint(ndev,
12432 "wnm_bsstrans_resp",
12433 WL_BSSTRANS_POLICY_PRODUCT_WBTEXT))
12434 == BCME_OK) {
12435 wl_cfg80211_wbtext_set_default(ndev);
12436 } else {
12437 WL_ERR(("%s: Failed to set wbtext = %d\n",
12438 __FUNCTION__, err));
12439 }
12440 } else {
12441 WL_ERR(("%s: Failed to clear join pref = %d\n",
12442 __FUNCTION__, err));
12443 }
12444 wl_cfg80211_wbtext_clear_bssid_list(cfg);
12445 }
12446 #endif /* WBTEXT */
12447 wl_vndr_ies_clear_vendor_oui_list(cfg);
12448 }
12449 else if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
12450 printf("link down, during connecting\n");
12451 wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY,
12452 WL_EXT_STATUS_DISCONNECTED, NULL);
12453 /* Issue WLC_DISASSOC to prevent FW roam attempts */
12454 err = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0);
12455 if (err < 0) {
12456 WL_ERR(("CONNECTING state, WLC_DISASSOC error %d\n", err));
12457 err = 0;
12458 }
12459 WL_INFORM(("Clear drv CONNECTING status\n"));
12460 wl_clr_drv_status(cfg, CONNECTING, ndev);
12461 #ifdef ESCAN_RESULT_PATCH
12462 if ((memcmp(connect_req_bssid, broad_bssid, ETHER_ADDR_LEN) == 0) ||
12463 (memcmp(&e->addr, broad_bssid, ETHER_ADDR_LEN) == 0) ||
12464 (memcmp(&e->addr, connect_req_bssid, ETHER_ADDR_LEN) == 0))
12465 /* In case this event comes while associating another AP */
12466 #endif /* ESCAN_RESULT_PATCH */
12467 wl_bss_connect_done(cfg, ndev, e, data, false);
12468 }
12469 wl_clr_drv_status(cfg, DISCONNECTING, ndev);
12470
12471 /* if link down, bsscfg is diabled */
12472 if (ndev != bcmcfg_to_prmry_ndev(cfg))
12473 complete(&cfg->iface_disable);
12474 #ifdef WLTDLS
12475 /* re-enable TDLS if the number of connected interfaces
12476 * is less than 2.
12477 */
12478 wl_cfg80211_tdls_config(cfg, TDLS_STATE_DISCONNECT, false);
12479 #endif /* WLTDLS */
12480 } else if (wl_is_nonetwork(cfg, e)) {
12481 printf("connect failed event=%d e->status %d e->reason %d \n",
12482 event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
12483 wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY,
12484 WL_EXT_STATUS_DISCONNECTED, NULL);
12485 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
12486 if (event == WLC_E_SET_SSID) {
12487 wl_get_connect_failed_status(cfg, e);
12488 }
12489 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
12490
12491 if (wl_get_drv_status(cfg, DISCONNECTING, ndev) &&
12492 wl_get_drv_status(cfg, CONNECTING, ndev)) {
12493 wl_clr_drv_status(cfg, DISCONNECTING, ndev);
12494 wl_clr_drv_status(cfg, CONNECTING, ndev);
12495 wl_cfg80211_scan_abort(cfg);
12496 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
12497 return err;
12498 }
12499 /* Clean up any pending scan request */
12500 wl_cfg80211_cancel_scan(cfg);
12501
12502 if (wl_get_drv_status(cfg, CONNECTING, ndev))
12503 wl_bss_connect_done(cfg, ndev, e, data, false);
12504 } else {
12505 WL_DBG(("%s nothing\n", __FUNCTION__));
12506 }
12507 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
12508 }
12509 else {
12510 printf("wl_notify_connect_status : Invalid %s mode %d event %d status %d\n",
12511 ndev->name, wl_get_mode_by_netdev(cfg, ndev), ntoh32(e->event_type),
12512 ntoh32(e->status));
12513 }
12514 return err;
12515 }
12516
12517 #ifdef WL_RELMCAST
12518 void wl_cfg80211_set_rmc_pid(struct net_device *dev, int pid)
12519 {
12520 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
12521 if (pid > 0)
12522 cfg->rmc_event_pid = pid;
12523 WL_DBG(("set pid for rmc event : pid=%d\n", pid));
12524 }
12525 #endif /* WL_RELMCAST */
12526
12527 #ifdef WL_RELMCAST
12528 static s32
12529 wl_notify_rmc_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12530 const wl_event_msg_t *e, void *data)
12531 {
12532 u32 evt = ntoh32(e->event_type);
12533 u32 reason = ntoh32(e->reason);
12534 int ret = -1;
12535
12536 switch (reason) {
12537 case WLC_E_REASON_RMC_AR_LOST:
12538 case WLC_E_REASON_RMC_AR_NO_ACK:
12539 if (cfg->rmc_event_pid != 0) {
12540 ret = wl_netlink_send_msg(cfg->rmc_event_pid,
12541 RMC_EVENT_LEADER_CHECK_FAIL,
12542 cfg->rmc_event_seq++, NULL, 0);
12543 }
12544 break;
12545 default:
12546 break;
12547 }
12548 WL_DBG(("rmcevent : evt=%d, pid=%d, ret=%d\n", evt, cfg->rmc_event_pid, ret));
12549 return ret;
12550 }
12551 #endif /* WL_RELMCAST */
12552
12553 #ifdef GSCAN_SUPPORT
12554 static s32
12555 wl_handle_roam_exp_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12556 const wl_event_msg_t *e, void *data)
12557 {
12558 struct net_device *ndev = NULL;
12559 u32 datalen = be32_to_cpu(e->datalen);
12560
12561 if (datalen) {
12562 wl_roam_exp_event_t *evt_data = (wl_roam_exp_event_t *)data;
12563 if (evt_data->version == ROAM_EXP_EVENT_VERSION) {
12564 wlc_ssid_t *ssid = &evt_data->cur_ssid;
12565 struct wireless_dev *wdev;
12566 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12567 if (ndev) {
12568 wdev = ndev->ieee80211_ptr;
12569 wdev->ssid_len = min(ssid->SSID_len, (uint32)DOT11_MAX_SSID_LEN);
12570 memcpy(wdev->ssid, ssid->SSID, wdev->ssid_len);
12571 WL_ERR(("SSID is %s\n", ssid->SSID));
12572 wl_update_prof(cfg, ndev, NULL, ssid, WL_PROF_SSID);
12573 } else {
12574 WL_ERR(("NULL ndev!\n"));
12575 }
12576 } else {
12577 WL_ERR(("Version mismatch %d, expected %d", evt_data->version,
12578 ROAM_EXP_EVENT_VERSION));
12579 }
12580 }
12581 return BCME_OK;
12582 }
12583 #endif /* GSCAN_SUPPORT */
12584
12585 #ifdef RSSI_MONITOR_SUPPORT
12586 static s32 wl_handle_rssi_monitor_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12587 const wl_event_msg_t *e, void *data)
12588 {
12589
12590 #if defined(WL_VENDOR_EXT_SUPPORT) || defined(CONFIG_BCMDHD_VENDOR_EXT)
12591 u32 datalen = be32_to_cpu(e->datalen);
12592 struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12593 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
12594
12595 if (datalen) {
12596 wl_rssi_monitor_evt_t *evt_data = (wl_rssi_monitor_evt_t *)data;
12597 if (evt_data->version == RSSI_MONITOR_VERSION) {
12598 dhd_rssi_monitor_evt_t monitor_data;
12599 monitor_data.version = DHD_RSSI_MONITOR_EVT_VERSION;
12600 monitor_data.cur_rssi = evt_data->cur_rssi;
12601 memcpy(&monitor_data.BSSID, &e->addr, ETHER_ADDR_LEN);
12602 wl_cfgvendor_send_async_event(wiphy, ndev,
12603 GOOGLE_RSSI_MONITOR_EVENT,
12604 &monitor_data, sizeof(monitor_data));
12605 } else {
12606 WL_ERR(("Version mismatch %d, expected %d", evt_data->version,
12607 RSSI_MONITOR_VERSION));
12608 }
12609 }
12610 #endif /* WL_VENDOR_EXT_SUPPORT || CONFIG_BCMDHD_VENDOR_EXT */
12611 return BCME_OK;
12612 }
12613 #endif /* RSSI_MONITOR_SUPPORT */
12614
12615 static s32
12616 wl_notify_roaming_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12617 const wl_event_msg_t *e, void *data)
12618 {
12619 bool act;
12620 struct net_device *ndev = NULL;
12621 s32 err = 0;
12622 u32 event = be32_to_cpu(e->event_type);
12623 u32 status = be32_to_cpu(e->status);
12624 #ifdef DHD_LOSSLESS_ROAMING
12625 struct wl_security *sec;
12626 #endif
12627 WL_DBG(("Enter \n"));
12628
12629 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12630
12631 if ((!cfg->disable_roam_event) && (event == WLC_E_BSSID)) {
12632 wl_add_remove_eventmsg(ndev, WLC_E_ROAM, false);
12633 cfg->disable_roam_event = TRUE;
12634 }
12635
12636 if ((cfg->disable_roam_event) && (event == WLC_E_ROAM))
12637 return err;
12638
12639 if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status == WLC_E_STATUS_SUCCESS) {
12640 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
12641 #ifdef DHD_LOSSLESS_ROAMING
12642 sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
12643 /* In order to reduce roaming delay, wl_bss_roaming_done is
12644 * early called with WLC_E_LINK event. It is called from
12645 * here only if WLC_E_LINK event is blocked for specific
12646 * security type.
12647 */
12648 if (IS_AKM_SUITE_FT(sec)) {
12649 wl_bss_roaming_done(cfg, ndev, e, data);
12650 }
12651 /* Roam timer is deleted mostly from wl_cfg80211_change_station
12652 * after roaming is finished successfully. We need to delete
12653 * the timer from here only for some security types that aren't
12654 * using wl_cfg80211_change_station to authorize SCB
12655 */
12656 if (IS_AKM_SUITE_FT(sec) || IS_AKM_SUITE_CCKM(sec)) {
12657 wl_del_roam_timeout(cfg);
12658 }
12659 #else
12660 wl_bss_roaming_done(cfg, ndev, e, data);
12661 #endif /* DHD_LOSSLESS_ROAMING */
12662 } else {
12663 wl_bss_connect_done(cfg, ndev, e, data, true);
12664 }
12665 act = true;
12666 wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
12667 wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
12668
12669 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
12670 wl_vndr_ies_get_vendor_oui(cfg, ndev, NULL, 0);
12671 }
12672 }
12673 #ifdef DHD_LOSSLESS_ROAMING
12674 else if ((event == WLC_E_ROAM || event == WLC_E_BSSID) && status != WLC_E_STATUS_SUCCESS) {
12675 wl_del_roam_timeout(cfg);
12676 }
12677 #endif
12678 return err;
12679 }
12680
12681 #ifdef CUSTOM_EVENT_PM_WAKE
12682 uint32 last_dpm_upd_time = 0; /* ms */
12683 #define DPM_UPD_LMT_TIME 25000 /* ms */
12684 #define DPM_UPD_LMT_RSSI -85 /* dbm */
12685
12686 static s32
12687 wl_check_pmstatus(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12688 const wl_event_msg_t *e, void *data)
12689 {
12690 s32 err = BCME_OK;
12691 struct net_device *ndev = NULL;
12692 u8 *pbuf = NULL;
12693 uint32 cur_dpm_upd_time = 0;
12694 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
12695 s32 rssi;
12696 scb_val_t scb_val;
12697
12698 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12699
12700 pbuf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
12701 if (pbuf == NULL) {
12702 WL_ERR(("failed to allocate local pbuf\n"));
12703 return -ENOMEM;
12704 }
12705
12706 err = wldev_iovar_getbuf_bsscfg(ndev, "dump",
12707 "pm", strlen("pm"), pbuf, WLC_IOCTL_MEDLEN, 0, &cfg->ioctl_buf_sync);
12708
12709 if (err) {
12710 WL_ERR(("dump ioctl err = %d", err));
12711 } else {
12712 WL_ERR(("PM status : %s\n", pbuf));
12713 }
12714
12715 if (pbuf) {
12716 kfree(pbuf);
12717 }
12718
12719 if (dhd->early_suspended) {
12720 /* LCD off */
12721 memset(&scb_val, 0, sizeof(scb_val_t));
12722 scb_val.val = 0;
12723 err = wldev_ioctl_get(ndev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t));
12724 if (err) {
12725 WL_ERR(("Could not get rssi (%d)\n", err));
12726 }
12727 rssi = wl_rssi_offset(dtoh32(scb_val.val));
12728 WL_ERR(("[%s] RSSI %d dBm\n", ndev->name, rssi));
12729 if (rssi > DPM_UPD_LMT_RSSI) {
12730 return err;
12731 }
12732 } else {
12733 /* LCD on */
12734 return err;
12735 }
12736
12737 if (last_dpm_upd_time == 0) {
12738 last_dpm_upd_time = OSL_SYSUPTIME();
12739 } else {
12740 cur_dpm_upd_time = OSL_SYSUPTIME();
12741 if (cur_dpm_upd_time - last_dpm_upd_time < DPM_UPD_LMT_TIME) {
12742 scb_val_t scbval;
12743 bzero(&scbval, sizeof(scb_val_t));
12744
12745 err = wldev_ioctl_set(ndev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
12746 if (err < 0) {
12747 WL_ERR(("%s: Disassoc error %d\n", __FUNCTION__, err));
12748 return err;
12749 }
12750 WL_ERR(("%s: Force Disassoc due to updated DPM event.\n", __FUNCTION__));
12751
12752 last_dpm_upd_time = 0;
12753 } else {
12754 last_dpm_upd_time = cur_dpm_upd_time;
12755 }
12756 }
12757
12758 return err;
12759 }
12760 #endif /* CUSTOM_EVENT_PM_WAKE */
12761
12762 #ifdef QOS_MAP_SET
12763 /* get user priority table */
12764 uint8 *
12765 wl_get_up_table(dhd_pub_t * dhdp, int idx)
12766 {
12767 struct net_device *ndev;
12768 struct bcm_cfg80211 *cfg;
12769
12770 ndev = dhd_idx2net(dhdp, idx);
12771 if (ndev) {
12772 cfg = wl_get_cfg(ndev);
12773 if (cfg)
12774 return (uint8 *)(cfg->up_table);
12775 }
12776
12777 return NULL;
12778 }
12779 #endif /* QOS_MAP_SET */
12780
12781 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
12782 static s32
12783 wl_notify_roam_prep_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12784 const wl_event_msg_t *e, void *data)
12785 {
12786 struct wl_security *sec;
12787 struct net_device *ndev;
12788 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
12789 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
12790 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
12791 u32 status = ntoh32(e->status);
12792 u32 reason = ntoh32(e->reason);
12793
12794 BCM_REFERENCE(sec);
12795
12796 if (status == WLC_E_STATUS_SUCCESS && reason != WLC_E_REASON_INITIAL_ASSOC) {
12797 WL_ERR(("Attempting roam with reason code : %d\n", reason));
12798 }
12799
12800 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
12801
12802 #ifdef DBG_PKT_MON
12803 if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
12804 DHD_DBG_PKT_MON_STOP(dhdp);
12805 DHD_DBG_PKT_MON_START(dhdp);
12806 }
12807 #endif /* DBG_PKT_MON */
12808
12809 #ifdef DHD_LOSSLESS_ROAMING
12810 sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
12811 /* Disable Lossless Roaming for specific AKM suite
12812 * Any other AKM suite can be added below if transition time
12813 * is delayed because of Lossless Roaming
12814 * and it causes any certication failure
12815 */
12816 if (IS_AKM_SUITE_FT(sec)) {
12817 return BCME_OK;
12818 }
12819 dhdp->dequeue_prec_map = 1 << PRIO_8021D_NC;
12820 /* Restore flow control */
12821 dhd_txflowcontrol(dhdp, ALL_INTERFACES, OFF);
12822
12823 mod_timer(&cfg->roam_timeout, jiffies + msecs_to_jiffies(WL_ROAM_TIMEOUT_MS));
12824 #endif /* DHD_LOSSLESS_ROAMING */
12825 return BCME_OK;
12826
12827 }
12828 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
12829 #ifdef ENABLE_TEMP_THROTTLING
12830 static s32
12831 wl_check_rx_throttle_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
12832 const wl_event_msg_t *e, void *data)
12833 {
12834 s32 err = 0;
12835 u32 status = ntoh32(e->status);
12836 u32 reason = ntoh32(e->reason);
12837
12838 WL_ERR_EX(("RX THROTTLE : status=%d, reason=0x%x\n", status, reason));
12839
12840 return err;
12841 }
12842 #endif /* ENABLE_TEMP_THROTTLING */
12843
12844 static s32 wl_get_assoc_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev)
12845 {
12846 wl_assoc_info_t assoc_info;
12847 struct wl_connect_info *conn_info = wl_to_conn(cfg);
12848 s32 err = 0;
12849 #ifdef QOS_MAP_SET
12850 bcm_tlv_t * qos_map_ie = NULL;
12851 #endif /* QOS_MAP_SET */
12852
12853 WL_DBG(("Enter \n"));
12854 err = wldev_iovar_getbuf(ndev, "assoc_info", NULL, 0, cfg->extra_buf,
12855 WL_ASSOC_INFO_MAX, NULL);
12856 if (unlikely(err)) {
12857 WL_ERR(("could not get assoc info (%d)\n", err));
12858 return err;
12859 }
12860 memcpy(&assoc_info, cfg->extra_buf, sizeof(wl_assoc_info_t));
12861 assoc_info.req_len = htod32(assoc_info.req_len);
12862 assoc_info.resp_len = htod32(assoc_info.resp_len);
12863 assoc_info.flags = htod32(assoc_info.flags);
12864 if (conn_info->req_ie_len) {
12865 conn_info->req_ie_len = 0;
12866 bzero(conn_info->req_ie, sizeof(conn_info->req_ie));
12867 }
12868 if (conn_info->resp_ie_len) {
12869 conn_info->resp_ie_len = 0;
12870 bzero(conn_info->resp_ie, sizeof(conn_info->resp_ie));
12871 }
12872 if (assoc_info.req_len) {
12873 err = wldev_iovar_getbuf(ndev, "assoc_req_ies", NULL, 0, cfg->extra_buf,
12874 WL_ASSOC_INFO_MAX, NULL);
12875 if (unlikely(err)) {
12876 WL_ERR(("could not get assoc req (%d)\n", err));
12877 return err;
12878 }
12879 conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
12880 if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
12881 conn_info->req_ie_len -= ETHER_ADDR_LEN;
12882 }
12883 if (conn_info->req_ie_len <= MAX_REQ_LINE)
12884 memcpy(conn_info->req_ie, cfg->extra_buf, conn_info->req_ie_len);
12885 else {
12886 WL_ERR(("IE size %d above max %d size \n",
12887 conn_info->req_ie_len, MAX_REQ_LINE));
12888 return err;
12889 }
12890 } else {
12891 conn_info->req_ie_len = 0;
12892 }
12893 if (assoc_info.resp_len) {
12894 err = wldev_iovar_getbuf(ndev, "assoc_resp_ies", NULL, 0, cfg->extra_buf,
12895 WL_ASSOC_INFO_MAX, NULL);
12896 if (unlikely(err)) {
12897 WL_ERR(("could not get assoc resp (%d)\n", err));
12898 return err;
12899 }
12900 conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
12901 if (conn_info->resp_ie_len <= MAX_REQ_LINE) {
12902 memcpy(conn_info->resp_ie, cfg->extra_buf, conn_info->resp_ie_len);
12903 } else {
12904 WL_ERR(("IE size %d above max %d size \n",
12905 conn_info->resp_ie_len, MAX_REQ_LINE));
12906 return err;
12907 }
12908
12909 #ifdef QOS_MAP_SET
12910 /* find qos map set ie */
12911 if ((qos_map_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
12912 DOT11_MNG_QOS_MAP_ID)) != NULL) {
12913 WL_DBG((" QoS map set IE found in assoc response\n"));
12914 if (!cfg->up_table) {
12915 cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
12916 }
12917 wl_set_up_table(cfg->up_table, qos_map_ie);
12918 } else {
12919 kfree(cfg->up_table);
12920 cfg->up_table = NULL;
12921 }
12922 #endif /* QOS_MAP_SET */
12923 } else {
12924 conn_info->resp_ie_len = 0;
12925 }
12926 WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len,
12927 conn_info->resp_ie_len));
12928
12929 return err;
12930 }
12931
12932 static s32 wl_ch_to_chanspec(struct net_device *dev, int ch, struct wl_join_params *join_params,
12933 size_t *join_params_size)
12934 {
12935 s32 bssidx = -1;
12936 chanspec_t chanspec = 0, chspec;
12937
12938 if (ch != 0) {
12939 struct bcm_cfg80211 *cfg =
12940 (struct bcm_cfg80211 *)wiphy_priv(dev->ieee80211_ptr->wiphy);
12941 join_params->params.chanspec_num = 1;
12942 join_params->params.chanspec_list[0] = ch;
12943
12944 if (join_params->params.chanspec_list[0] <= CH_MAX_2G_CHANNEL)
12945 chanspec |= WL_CHANSPEC_BAND_2G;
12946 else
12947 chanspec |= WL_CHANSPEC_BAND_5G;
12948
12949 /* Get the min_bw set for the interface */
12950 chspec = wl_cfg80211_ulb_get_min_bw_chspec(cfg, dev->ieee80211_ptr, bssidx);
12951 if (chspec == INVCHANSPEC) {
12952 WL_ERR(("Invalid chanspec \n"));
12953 return -EINVAL;
12954 }
12955 chanspec |= chspec;
12956 chanspec |= WL_CHANSPEC_CTL_SB_NONE;
12957
12958 *join_params_size += WL_ASSOC_PARAMS_FIXED_SIZE +
12959 join_params->params.chanspec_num * sizeof(chanspec_t);
12960
12961 join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
12962 join_params->params.chanspec_list[0] |= chanspec;
12963 join_params->params.chanspec_list[0] =
12964 wl_chspec_host_to_driver(join_params->params.chanspec_list[0]);
12965
12966 join_params->params.chanspec_num =
12967 htod32(join_params->params.chanspec_num);
12968
12969 WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n",
12970 join_params->params.chanspec_list[0],
12971 join_params->params.chanspec_num));
12972 }
12973 return 0;
12974 }
12975
12976 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool roam)
12977 {
12978 struct cfg80211_bss *bss;
12979 struct wl_bss_info *bi;
12980 struct wlc_ssid *ssid;
12981 struct bcm_tlv *tim;
12982 s32 beacon_interval;
12983 s32 dtim_period;
12984 size_t ie_len;
12985 u8 *ie;
12986 u8 *curbssid;
12987 s32 err = 0;
12988 struct wiphy *wiphy;
12989 u32 channel;
12990 char *buf;
12991 u32 freq, band;
12992
12993 wiphy = bcmcfg_to_wiphy(cfg);
12994
12995 ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
12996 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
12997 bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
12998 ssid->SSID, ssid->SSID_len);
12999 buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_ATOMIC);
13000 if (!buf) {
13001 WL_ERR(("buffer alloc failed.\n"));
13002 return BCME_NOMEM;
13003 }
13004 mutex_lock(&cfg->usr_sync);
13005 *(u32 *)buf = htod32(WL_EXTRA_BUF_MAX);
13006 err = wldev_ioctl_get(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX);
13007 if (unlikely(err)) {
13008 WL_ERR(("Could not get bss info %d\n", err));
13009 goto update_bss_info_out;
13010 }
13011 bi = (struct wl_bss_info *)(buf + 4);
13012 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
13013 wl_update_prof(cfg, ndev, NULL, &channel, WL_PROF_CHAN);
13014
13015 if (!bss) {
13016 WL_DBG(("Could not find the AP\n"));
13017 if (memcmp(bi->BSSID.octet, curbssid, ETHER_ADDR_LEN)) {
13018 WL_ERR(("Bssid doesn't match\n"));
13019 err = -EIO;
13020 goto update_bss_info_out;
13021 }
13022 err = wl_inform_single_bss(cfg, bi, roam);
13023 if (unlikely(err))
13024 goto update_bss_info_out;
13025
13026 ie = ((u8 *)bi) + bi->ie_offset;
13027 ie_len = bi->ie_length;
13028 beacon_interval = cpu_to_le16(bi->beacon_period);
13029 } else {
13030 WL_DBG(("Found the AP in the list - BSSID %pM\n", bss->bssid));
13031 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
13032 freq = ieee80211_channel_to_frequency(channel);
13033 #else
13034 band = (channel <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
13035 freq = ieee80211_channel_to_frequency(channel, band);
13036 #endif
13037 bss->channel = ieee80211_get_channel(wiphy, freq);
13038 #if defined(WL_CFG80211_P2P_DEV_IF)
13039 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
13040 #pragma GCC diagnostic push
13041 #pragma GCC diagnostic ignored "-Wcast-qual"
13042 #endif
13043 ie = (u8 *)bss->ies->data;
13044 ie_len = bss->ies->len;
13045 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
13046 #pragma GCC diagnostic pop
13047 #endif
13048 #else
13049 ie = bss->information_elements;
13050 ie_len = bss->len_information_elements;
13051 #endif /* WL_CFG80211_P2P_DEV_IF */
13052 beacon_interval = bss->beacon_interval;
13053
13054 CFG80211_PUT_BSS(wiphy, bss);
13055 }
13056
13057 tim = bcm_parse_tlvs(ie, ie_len, WLAN_EID_TIM);
13058 if (tim) {
13059 dtim_period = tim->data[1];
13060 } else {
13061 /*
13062 * active scan was done so we could not get dtim
13063 * information out of probe response.
13064 * so we speficially query dtim information.
13065 */
13066 dtim_period = 0;
13067 err = wldev_ioctl_get(ndev, WLC_GET_DTIMPRD,
13068 &dtim_period, sizeof(dtim_period));
13069 if (unlikely(err)) {
13070 WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
13071 goto update_bss_info_out;
13072 }
13073 }
13074
13075 wl_update_prof(cfg, ndev, NULL, &beacon_interval, WL_PROF_BEACONINT);
13076 wl_update_prof(cfg, ndev, NULL, &dtim_period, WL_PROF_DTIMPERIOD);
13077
13078 update_bss_info_out:
13079 if (unlikely(err)) {
13080 WL_ERR(("Failed with error %d\n", err));
13081 }
13082
13083 kfree(buf);
13084 mutex_unlock(&cfg->usr_sync);
13085 return err;
13086 }
13087
13088 static s32
13089 wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
13090 const wl_event_msg_t *e, void *data)
13091 {
13092 struct wl_connect_info *conn_info = wl_to_conn(cfg);
13093 s32 err = 0;
13094 u8 *curbssid;
13095 u32 *channel;
13096 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13097 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
13098 struct ieee80211_supported_band *band;
13099 struct ieee80211_channel *notify_channel = NULL;
13100 u32 freq;
13101 #ifdef BCM4359_CHIP
13102 struct channel_info ci;
13103 u32 cur_channel;
13104 #endif /* BCM4359_CHIP */
13105 #endif
13106 #if defined(WLADPS_SEAK_AP_WAR) || defined(WBTEXT)
13107 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
13108 #endif /* WLADPS_SEAK_AP_WAR || WBTEXT */
13109 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13110 struct cfg80211_roam_info roam_info = {};
13111 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13112
13113 #ifdef WLADPS_SEAK_AP_WAR
13114 BCM_REFERENCE(dhdp);
13115 #endif /* WLADPS_SEAK_AP_WAR */
13116
13117 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
13118 channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
13119 #ifdef BCM4359_CHIP
13120 /* Skip calling cfg80211_roamed If the channels are same and
13121 * the current bssid/last_roamed_bssid & the new bssid are same
13122 * Also clear timer roam_timeout.
13123 * Only used on BCM4359 devices.
13124 */
13125 memset(&ci, 0, sizeof(ci));
13126 if ((wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci,
13127 sizeof(ci))) < 0) {
13128 WL_ERR(("Failed to get current channel !"));
13129 return BCME_ERROR;
13130 }
13131 cur_channel = dtoh32(ci.hw_channel);
13132 if ((*channel == cur_channel) && ((memcmp(curbssid, &e->addr,
13133 ETHER_ADDR_LEN) == 0) || (memcmp(&cfg->last_roamed_addr,
13134 &e->addr, ETHER_ADDR_LEN) == 0))) {
13135 WL_ERR(("BSS already present, Skipping roamed event to"
13136 " upper layer\n"));
13137 #ifdef DHD_LOSSLESS_ROAMING
13138 wl_del_roam_timeout(cfg);
13139 #endif /* DHD_LOSSLESS_ROAMING */
13140 return err;
13141 }
13142 #endif /* BCM4359_CHIP */
13143
13144 wl_get_assoc_ies(cfg, ndev);
13145 wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet), WL_PROF_BSSID);
13146 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
13147 wl_update_bss_info(cfg, ndev, true);
13148 wl_update_pmklist(ndev, cfg->pmk_list, err);
13149
13150 channel = (u32 *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
13151 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13152 /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */
13153 if (*channel <= CH_MAX_2G_CHANNEL)
13154 band = wiphy->bands[IEEE80211_BAND_2GHZ];
13155 else
13156 band = wiphy->bands[IEEE80211_BAND_5GHZ];
13157 freq = ieee80211_channel_to_frequency(*channel, band->band);
13158 notify_channel = ieee80211_get_channel(wiphy, freq);
13159 #endif
13160 #ifdef WLADPS_SEAK_AP_WAR
13161 if ((dhdp->op_mode & DHD_FLAG_STA_MODE) &&
13162 (!dhdp->disabled_adps)) {
13163 bool find = FALSE;
13164 uint8 enable_mode;
13165 if (!memcmp(curbssid, (u8*)CAMEO_MAC_PREFIX, MAC_PREFIX_LEN)) {
13166 find = wl_find_vndr_ies_specific_vender(cfg, ndev, ATHEROS_OUI);
13167 }
13168 enable_mode = (find == TRUE) ? OFF : ON;
13169 wl_set_adps_mode(cfg, ndev, enable_mode);
13170 }
13171 #endif /* WLADPS_SEAK_AP_WAR */
13172 printf("%s succeeded to " MACDBG " (ch:%d)\n", __FUNCTION__,
13173 MAC2STRDBG((const u8*)(&e->addr)), *channel);
13174 dhd_conf_set_wme(cfg->pub, 0);
13175
13176 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13177 roam_info.channel = notify_channel;
13178 roam_info.bssid = curbssid;
13179 roam_info.req_ie = conn_info->req_ie;
13180 roam_info.req_ie_len = conn_info->req_ie_len;
13181 roam_info.resp_ie = conn_info->resp_ie;
13182 roam_info.resp_ie_len = conn_info->resp_ie_len;
13183 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13184
13185 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
13186 cfg80211_roamed(ndev, &roam_info, GFP_KERNEL);
13187 #else
13188 cfg80211_roamed(ndev,
13189 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
13190 notify_channel,
13191 #endif
13192 curbssid,
13193 conn_info->req_ie, conn_info->req_ie_len,
13194 conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
13195 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
13196 WL_DBG(("Report roaming result\n"));
13197
13198 memcpy(&cfg->last_roamed_addr, &e->addr, ETHER_ADDR_LEN);
13199 wl_set_drv_status(cfg, CONNECTED, ndev);
13200
13201 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
13202 cfg->roam_count++;
13203 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
13204
13205 #ifdef WBTEXT
13206 if (dhdp->wbtext_support) {
13207 /* set wnm_keepalives_max_idle after association */
13208 wl_cfg80211_wbtext_set_wnm_maxidle(cfg, ndev);
13209 /* send nbr request or BTM query to update RCC */
13210 wl_cfg80211_wbtext_update_rcc(cfg, ndev);
13211 }
13212 #endif /* WBTEXT */
13213
13214 return err;
13215 }
13216
13217 static bool
13218 wl_cfg80211_verify_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev)
13219 {
13220 struct cfg80211_bss *bss;
13221 struct wiphy *wiphy;
13222 struct wlc_ssid *ssid;
13223 uint8 *curbssid;
13224 int count = 0;
13225 int ret = false;
13226
13227 wiphy = bcmcfg_to_wiphy(cfg);
13228 ssid = (struct wlc_ssid *)wl_read_prof(cfg, ndev, WL_PROF_SSID);
13229 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
13230 if (!ssid) {
13231 WL_ERR(("No SSID found in the saved profile \n"));
13232 return false;
13233 }
13234
13235 do {
13236 bss = CFG80211_GET_BSS(wiphy, NULL, curbssid,
13237 ssid->SSID, ssid->SSID_len);
13238 if (bss || (count > 5)) {
13239 break;
13240 }
13241
13242 count++;
13243 msleep(100);
13244 } while (bss == NULL);
13245
13246 WL_DBG(("cfg80211 bss_ptr:%p loop_cnt:%d\n", bss, count));
13247 if (bss) {
13248 /* Update the reference count after use */
13249 CFG80211_PUT_BSS(wiphy, bss);
13250 ret = true;
13251 }
13252
13253 return ret;
13254 }
13255
13256 static s32
13257 wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
13258 const wl_event_msg_t *e, void *data, bool completed)
13259 {
13260 struct wl_connect_info *conn_info = wl_to_conn(cfg);
13261 struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
13262 s32 err = 0;
13263 u8 *curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
13264 dhd_pub_t *dhdp;
13265
13266 dhdp = (dhd_pub_t *)(cfg->pub);
13267 BCM_REFERENCE(dhdp);
13268
13269 if (!sec) {
13270 WL_ERR(("sec is NULL\n"));
13271 return -ENODEV;
13272 }
13273 WL_DBG((" enter\n"));
13274 #ifdef ESCAN_RESULT_PATCH
13275 if (wl_get_drv_status(cfg, CONNECTED, ndev)) {
13276 if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) {
13277 WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n",
13278 ntoh32(e->event_type), ntoh32(e->status)));
13279 return err;
13280 }
13281 }
13282 if (memcmp(curbssid, broad_bssid, ETHER_ADDR_LEN) == 0 &&
13283 memcmp(broad_bssid, connect_req_bssid, ETHER_ADDR_LEN) != 0) {
13284 WL_DBG(("copy bssid\n"));
13285 memcpy(curbssid, connect_req_bssid, ETHER_ADDR_LEN);
13286 }
13287
13288 #else
13289 if (cfg->scan_request) {
13290 wl_notify_escan_complete(cfg, ndev, true, true);
13291 }
13292 #endif /* ESCAN_RESULT_PATCH */
13293 if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
13294 wl_cfg80211_scan_abort(cfg);
13295 wl_clr_drv_status(cfg, CONNECTING, ndev);
13296 if (completed) {
13297 wl_get_assoc_ies(cfg, ndev);
13298 wl_update_prof(cfg, ndev, NULL, (const void *)(e->addr.octet),
13299 WL_PROF_BSSID);
13300 curbssid = wl_read_prof(cfg, ndev, WL_PROF_BSSID);
13301 wl_update_bss_info(cfg, ndev, false);
13302 wl_update_pmklist(ndev, cfg->pmk_list, err);
13303 wl_set_drv_status(cfg, CONNECTED, ndev);
13304 #ifdef WLADPS_SEAK_AP_WAR
13305 if ((dhdp->op_mode & DHD_FLAG_STA_MODE) &&
13306 (!dhdp->disabled_adps)) {
13307 bool find = FALSE;
13308 uint8 enable_mode;
13309 if (!memcmp(curbssid, (u8*)CAMEO_MAC_PREFIX, MAC_PREFIX_LEN)) {
13310 find = wl_find_vndr_ies_specific_vender(cfg,
13311 ndev, ATHEROS_OUI);
13312 }
13313 enable_mode = (find == TRUE) ? OFF : ON;
13314 wl_set_adps_mode(cfg, ndev, enable_mode);
13315 }
13316 #endif /* WLADPS_SEAK_AP_WAR */
13317 if (ndev != bcmcfg_to_prmry_ndev(cfg)) {
13318 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
13319 init_completion(&cfg->iface_disable);
13320 #else
13321 /* reinitialize completion to clear previous count */
13322 INIT_COMPLETION(cfg->iface_disable);
13323 #endif
13324 }
13325 #ifdef CUSTOM_SET_CPUCORE
13326 if (wl_get_chan_isvht80(ndev, dhdp)) {
13327 if (ndev == bcmcfg_to_prmry_ndev(cfg))
13328 dhdp->chan_isvht80 |= DHD_FLAG_STA_MODE; /* STA mode */
13329 else if (is_p2p_group_iface(ndev->ieee80211_ptr))
13330 dhdp->chan_isvht80 |= DHD_FLAG_P2P_MODE; /* p2p mode */
13331 dhd_set_cpucore(dhdp, TRUE);
13332 }
13333 #endif /* CUSTOM_SET_CPUCORE */
13334 memset(&cfg->last_roamed_addr, 0, ETHER_ADDR_LEN);
13335 }
13336
13337 if (completed && (wl_cfg80211_verify_bss(cfg, ndev) != true)) {
13338 /* If bss entry is not available in the cfg80211 bss cache
13339 * the wireless stack will complain and won't populate
13340 * wdev->current_bss ptr
13341 */
13342 WL_ERR(("BSS entry not found. Indicate assoc event failure\n"));
13343 completed = false;
13344 sec->auth_assoc_res_status = WLAN_STATUS_UNSPECIFIED_FAILURE;
13345 }
13346 cfg80211_connect_result(ndev,
13347 curbssid,
13348 conn_info->req_ie,
13349 conn_info->req_ie_len,
13350 conn_info->resp_ie,
13351 conn_info->resp_ie_len,
13352 completed ? WLAN_STATUS_SUCCESS :
13353 (sec->auth_assoc_res_status) ?
13354 sec->auth_assoc_res_status :
13355 WLAN_STATUS_UNSPECIFIED_FAILURE,
13356 GFP_KERNEL);
13357 if (completed) {
13358 WL_INFORM(("Report connect result - connection succeeded\n"));
13359 dhd_conf_set_wme(cfg->pub, 0);
13360 } else {
13361 WL_ERR(("Report connect result - connection failed\n"));
13362 wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY,
13363 WL_EXT_STATUS_DISCONNECTED, NULL);
13364 }
13365 }
13366 #ifdef CONFIG_TCPACK_FASTTX
13367 if (wl_get_chan_isvht80(ndev, dhdp))
13368 wldev_iovar_setint(ndev, "tcpack_fast_tx", 0);
13369 else
13370 wldev_iovar_setint(ndev, "tcpack_fast_tx", 1);
13371 #endif /* CONFIG_TCPACK_FASTTX */
13372
13373 return err;
13374 }
13375
13376 static s32
13377 wl_notify_mic_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13378 const wl_event_msg_t *e, void *data)
13379 {
13380 struct net_device *ndev = NULL;
13381 u16 flags = ntoh16(e->flags);
13382 enum nl80211_key_type key_type;
13383
13384 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13385
13386 mutex_lock(&cfg->usr_sync);
13387 if (flags & WLC_EVENT_MSG_GROUP)
13388 key_type = NL80211_KEYTYPE_GROUP;
13389 else
13390 key_type = NL80211_KEYTYPE_PAIRWISE;
13391
13392 cfg80211_michael_mic_failure(ndev, (const u8 *)&e->addr, key_type, -1,
13393 NULL, GFP_KERNEL);
13394 mutex_unlock(&cfg->usr_sync);
13395
13396 return 0;
13397 }
13398
13399 #ifdef BT_WIFI_HANDOVER
13400 static s32
13401 wl_notify_bt_wifi_handover_req(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13402 const wl_event_msg_t *e, void *data)
13403 {
13404 struct net_device *ndev = NULL;
13405 u32 event = ntoh32(e->event_type);
13406 u32 datalen = ntoh32(e->datalen);
13407 s32 err;
13408
13409 WL_ERR(("wl_notify_bt_wifi_handover_req: event_type : %d, datalen : %d\n", event, datalen));
13410 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13411 err = wl_genl_send_msg(ndev, event, data, (u16)datalen, 0, 0);
13412
13413 return err;
13414 }
13415 #endif /* BT_WIFI_HANDOVER */
13416
13417 #ifdef PNO_SUPPORT
13418 static s32
13419 wl_notify_pfn_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13420 const wl_event_msg_t *e, void *data)
13421 {
13422 struct net_device *ndev = NULL;
13423 #ifdef GSCAN_SUPPORT
13424 void *ptr;
13425 int send_evt_bytes = 0;
13426 u32 event = be32_to_cpu(e->event_type);
13427 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
13428 #endif /* GSCAN_SUPPORT */
13429
13430 WL_ERR((">>> PNO Event\n"));
13431
13432 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13433 #ifdef GSCAN_SUPPORT
13434 ptr = dhd_dev_process_epno_result(ndev, data, event, &send_evt_bytes);
13435 if (ptr) {
13436 wl_cfgvendor_send_async_event(wiphy, ndev,
13437 GOOGLE_SCAN_EPNO_EVENT, ptr, send_evt_bytes);
13438 kfree(ptr);
13439 }
13440 if (!dhd_dev_is_legacy_pno_enabled(ndev))
13441 return 0;
13442 #endif /* GSCAN_SUPPORT */
13443
13444
13445 #ifndef WL_SCHED_SCAN
13446 mutex_lock(&cfg->usr_sync);
13447 /* TODO: Use cfg80211_sched_scan_results(wiphy); */
13448 CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
13449 mutex_unlock(&cfg->usr_sync);
13450 #else
13451 /* If cfg80211 scheduled scan is supported, report the pno results via sched
13452 * scan results
13453 */
13454 wl_notify_sched_scan_results(cfg, ndev, e, data);
13455 #endif /* WL_SCHED_SCAN */
13456 return 0;
13457 }
13458 #endif /* PNO_SUPPORT */
13459
13460 #ifdef GSCAN_SUPPORT
13461 static s32
13462 wl_notify_gscan_event(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13463 const wl_event_msg_t *e, void *data)
13464 {
13465 s32 err = 0;
13466 u32 event = be32_to_cpu(e->event_type);
13467 void *ptr;
13468 int send_evt_bytes = 0;
13469 int event_type;
13470 struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13471 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
13472 u32 len = ntoh32(e->datalen);
13473
13474 switch (event) {
13475 case WLC_E_PFN_BEST_BATCHING:
13476 err = dhd_dev_retrieve_batch_scan(ndev);
13477 if (err < 0) {
13478 WL_ERR(("Batch retrieval already in progress %d\n", err));
13479 } else {
13480 event_type = WIFI_SCAN_THRESHOLD_NUM_SCANS;
13481 if (data && len) {
13482 event_type = *((int *)data);
13483 }
13484 wl_cfgvendor_send_async_event(wiphy, ndev,
13485 GOOGLE_GSCAN_BATCH_SCAN_EVENT,
13486 &event_type, sizeof(int));
13487 }
13488 break;
13489 case WLC_E_PFN_SCAN_COMPLETE:
13490 event_type = WIFI_SCAN_COMPLETE;
13491 wl_cfgvendor_send_async_event(wiphy, ndev,
13492 GOOGLE_SCAN_COMPLETE_EVENT,
13493 &event_type, sizeof(int));
13494 break;
13495 case WLC_E_PFN_BSSID_NET_FOUND:
13496 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
13497 HOTLIST_FOUND);
13498 if (ptr) {
13499 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
13500 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_FOUND_EVENT);
13501 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_FOUND);
13502 } else {
13503 err = -ENOMEM;
13504 }
13505 break;
13506 case WLC_E_PFN_BSSID_NET_LOST:
13507 /* WLC_E_PFN_BSSID_NET_LOST is conflict shared with WLC_E_PFN_SCAN_ALLGONE
13508 * We currently do not use WLC_E_PFN_SCAN_ALLGONE, so if we get it, ignore
13509 */
13510 if (len) {
13511 ptr = dhd_dev_hotlist_scan_event(ndev, data, &send_evt_bytes,
13512 HOTLIST_LOST);
13513 if (ptr) {
13514 wl_cfgvendor_send_hotlist_event(wiphy, ndev,
13515 ptr, send_evt_bytes, GOOGLE_GSCAN_GEOFENCE_LOST_EVENT);
13516 dhd_dev_gscan_hotlist_cache_cleanup(ndev, HOTLIST_LOST);
13517 } else {
13518 err = -ENOMEM;
13519 }
13520 } else {
13521 err = -EINVAL;
13522 }
13523 break;
13524 case WLC_E_PFN_GSCAN_FULL_RESULT:
13525 ptr = dhd_dev_process_full_gscan_result(ndev, data, len, &send_evt_bytes);
13526 if (ptr) {
13527 wl_cfgvendor_send_async_event(wiphy, ndev,
13528 GOOGLE_SCAN_FULL_RESULTS_EVENT, ptr, send_evt_bytes);
13529 kfree(ptr);
13530 } else {
13531 err = -ENOMEM;
13532 }
13533 break;
13534 case WLC_E_PFN_SSID_EXT:
13535 ptr = dhd_dev_process_epno_result(ndev, data, event, &send_evt_bytes);
13536 if (ptr) {
13537 wl_cfgvendor_send_async_event(wiphy, ndev,
13538 GOOGLE_SCAN_EPNO_EVENT, ptr, send_evt_bytes);
13539 kfree(ptr);
13540 } else {
13541 err = -ENOMEM;
13542 }
13543 break;
13544 default:
13545 WL_ERR(("Unknown event %d\n", event));
13546 break;
13547 }
13548 return err;
13549 }
13550 #endif /* GSCAN_SUPPORT */
13551
13552 static s32
13553 wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13554 const wl_event_msg_t *e, void *data)
13555 {
13556 struct channel_info channel_inform;
13557 struct wl_scan_results *bss_list;
13558 struct net_device *ndev = NULL;
13559 u32 len = WL_SCAN_BUF_MAX;
13560 s32 err = 0;
13561 unsigned long flags;
13562 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
13563 struct cfg80211_scan_info info;
13564 #endif
13565
13566 WL_DBG(("Enter \n"));
13567 if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
13568 WL_ERR(("scan is not ready \n"));
13569 return err;
13570 }
13571 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13572
13573 mutex_lock(&cfg->usr_sync);
13574 wl_clr_drv_status(cfg, SCANNING, ndev);
13575 memset(&channel_inform, 0, sizeof(channel_inform));
13576 err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &channel_inform,
13577 sizeof(channel_inform));
13578 if (unlikely(err)) {
13579 WL_ERR(("scan busy (%d)\n", err));
13580 goto scan_done_out;
13581 }
13582 channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
13583 if (unlikely(channel_inform.scan_channel)) {
13584
13585 WL_DBG(("channel_inform.scan_channel (%d)\n",
13586 channel_inform.scan_channel));
13587 }
13588 cfg->bss_list = cfg->scan_results;
13589 bss_list = cfg->bss_list;
13590 memset(bss_list, 0, len);
13591 bss_list->buflen = htod32(len);
13592 err = wldev_ioctl_get(ndev, WLC_SCAN_RESULTS, bss_list, len);
13593 if (unlikely(err) && unlikely(!cfg->scan_suppressed)) {
13594 WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
13595 err = -EINVAL;
13596 goto scan_done_out;
13597 }
13598 bss_list->buflen = dtoh32(bss_list->buflen);
13599 bss_list->version = dtoh32(bss_list->version);
13600 bss_list->count = dtoh32(bss_list->count);
13601
13602 err = wl_inform_bss(cfg);
13603
13604 scan_done_out:
13605 del_timer_sync(&cfg->scan_timeout);
13606 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
13607 if (cfg->scan_request) {
13608 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
13609 info.aborted = false;
13610 cfg80211_scan_done(cfg->scan_request, &info);
13611 #else
13612 cfg80211_scan_done(cfg->scan_request, false);
13613 #endif
13614 cfg->scan_request = NULL;
13615 }
13616 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
13617 WL_DBG(("cfg80211_scan_done\n"));
13618 mutex_unlock(&cfg->usr_sync);
13619 return err;
13620 }
13621
13622 static s32
13623 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
13624 const struct ether_addr *sa, const struct ether_addr *bssid,
13625 u8 **pheader, u32 *body_len, u8 *pbody)
13626 {
13627 struct dot11_management_header *hdr;
13628 u32 totlen = 0;
13629 s32 err = 0;
13630 u8 *offset;
13631 u32 prebody_len = *body_len;
13632 switch (fc) {
13633 case FC_ASSOC_REQ:
13634 /* capability , listen interval */
13635 totlen = DOT11_ASSOC_REQ_FIXED_LEN;
13636 *body_len += DOT11_ASSOC_REQ_FIXED_LEN;
13637 break;
13638
13639 case FC_REASSOC_REQ:
13640 /* capability, listen inteval, ap address */
13641 totlen = DOT11_REASSOC_REQ_FIXED_LEN;
13642 *body_len += DOT11_REASSOC_REQ_FIXED_LEN;
13643 break;
13644 }
13645 totlen += DOT11_MGMT_HDR_LEN + prebody_len;
13646 *pheader = kzalloc(totlen, GFP_KERNEL);
13647 if (*pheader == NULL) {
13648 WL_ERR(("memory alloc failed \n"));
13649 return -ENOMEM;
13650 }
13651 hdr = (struct dot11_management_header *) (*pheader);
13652 hdr->fc = htol16(fc);
13653 hdr->durid = 0;
13654 hdr->seq = 0;
13655 offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
13656 bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
13657 bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
13658 bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
13659 if ((pbody != NULL) && prebody_len)
13660 bcopy((const char*)pbody, offset, prebody_len);
13661 *body_len = totlen;
13662 return err;
13663 }
13664
13665
13666 void
13667 wl_stop_wait_next_action_frame(struct bcm_cfg80211 *cfg, struct net_device *ndev, u8 bsscfgidx)
13668 {
13669 s32 err = 0;
13670
13671 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
13672 if (timer_pending(&cfg->p2p->listen_timer)) {
13673 del_timer_sync(&cfg->p2p->listen_timer);
13674 }
13675 if (cfg->afx_hdl != NULL) {
13676 if (cfg->afx_hdl->dev != NULL) {
13677 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
13678 wl_clr_drv_status(cfg, FINDING_COMMON_CHANNEL, cfg->afx_hdl->dev);
13679 }
13680 cfg->afx_hdl->peer_chan = WL_INVALID;
13681 }
13682 complete(&cfg->act_frm_scan);
13683 WL_DBG(("*** Wake UP ** Working afx searching is cleared\n"));
13684 } else if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
13685 if (!(wl_get_p2p_status(cfg, ACTION_TX_COMPLETED) ||
13686 wl_get_p2p_status(cfg, ACTION_TX_NOACK)))
13687 wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
13688
13689 WL_DBG(("*** Wake UP ** abort actframe iovar on bsscfxidx %d\n", bsscfgidx));
13690 /* if channel is not zero, "actfame" uses off channel scan.
13691 * So abort scan for off channel completion.
13692 */
13693 if (cfg->af_sent_channel) {
13694 /* Scan engine is not used for sending action frames in the latest driver
13695 * branches. So, actframe_abort is used in the latest driver branches
13696 * instead of scan abort.
13697 * New driver branches:
13698 * Issue actframe_abort and it succeeded. So, don't execute scan abort.
13699 * Old driver branches:
13700 * Issue actframe_abort and it fails. So, execute scan abort.
13701 */
13702 err = wldev_iovar_setint_bsscfg(ndev, "actframe_abort", 1, bsscfgidx);
13703 if (err < 0) {
13704 wl_cfg80211_scan_abort(cfg);
13705 }
13706 }
13707 }
13708 #ifdef WL_CFG80211_SYNC_GON
13709 else if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM_LISTEN)) {
13710 WL_DBG(("*** Wake UP ** abort listen for next af frame\n"));
13711 /* So abort scan to cancel listen */
13712 wl_cfg80211_scan_abort(cfg);
13713 }
13714 #endif /* WL_CFG80211_SYNC_GON */
13715 }
13716
13717 #if defined(WLTDLS)
13718 bool wl_cfg80211_is_tdls_tunneled_frame(void *frame, u32 frame_len)
13719 {
13720 unsigned char *data;
13721
13722 if (frame == NULL) {
13723 WL_ERR(("Invalid frame \n"));
13724 return false;
13725 }
13726
13727 if (frame_len < 5) {
13728 WL_ERR(("Invalid frame length [%d] \n", frame_len));
13729 return false;
13730 }
13731
13732 data = frame;
13733
13734 if (!memcmp(data, TDLS_TUNNELED_PRB_REQ, 5) ||
13735 !memcmp(data, TDLS_TUNNELED_PRB_RESP, 5)) {
13736 WL_DBG(("TDLS Vendor Specific Received type\n"));
13737 return true;
13738 }
13739
13740 return false;
13741 }
13742 #endif /* WLTDLS */
13743
13744
13745 int wl_cfg80211_get_ioctl_version(void)
13746 {
13747 return ioctl_version;
13748 }
13749
13750 static s32
13751 wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
13752 const wl_event_msg_t *e, void *data)
13753 {
13754 struct ieee80211_supported_band *band;
13755 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
13756 struct ether_addr da;
13757 struct ether_addr bssid;
13758 bool isfree = false;
13759 s32 err = 0;
13760 s32 freq;
13761 #if defined(TDLS_MSG_ONLY_WFD)
13762 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
13763 #endif /* TDLS_MSG_ONLY_WFD && BCMDONGLEHOST */
13764 struct net_device *ndev = NULL;
13765 wifi_p2p_pub_act_frame_t *act_frm = NULL;
13766 wifi_p2p_action_frame_t *p2p_act_frm = NULL;
13767 wifi_p2psd_gas_pub_act_frame_t *sd_act_frm = NULL;
13768 wl_event_rx_frame_data_t *rxframe;
13769 u32 event;
13770 u8 *mgmt_frame;
13771 u8 bsscfgidx;
13772 u32 mgmt_frame_len;
13773 u16 channel;
13774 if (ntoh32(e->datalen) < sizeof(wl_event_rx_frame_data_t)) {
13775 WL_ERR(("wrong datalen:%d\n", ntoh32(e->datalen)));
13776 return -EINVAL;
13777 }
13778 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
13779 event = ntoh32(e->event_type);
13780 bsscfgidx = e->bsscfgidx;
13781 rxframe = (wl_event_rx_frame_data_t *)data;
13782 if (!rxframe) {
13783 WL_ERR(("rxframe: NULL\n"));
13784 return -EINVAL;
13785 }
13786 channel = (ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK);
13787 memset(&bssid, 0, ETHER_ADDR_LEN);
13788 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
13789 if ((ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) &&
13790 (event == WLC_E_PROBREQ_MSG)) {
13791 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
13792 4 && __GNUC_MINOR__ >= 6))
13793 _Pragma("GCC diagnostic push")
13794 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
13795 #endif
13796 struct net_info *iter, *next;
13797 for_each_ndev(cfg, iter, next) {
13798 if (iter->ndev && iter->wdev &&
13799 iter->wdev->iftype == NL80211_IFTYPE_AP) {
13800 ndev = iter->ndev;
13801 cfgdev = ndev_to_cfgdev(ndev);
13802 break;
13803 }
13804 }
13805 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
13806 4 && __GNUC_MINOR__ >= 6))
13807 _Pragma("GCC diagnostic pop")
13808 #endif
13809 }
13810
13811 if (channel <= CH_MAX_2G_CHANNEL)
13812 band = wiphy->bands[IEEE80211_BAND_2GHZ];
13813 else
13814 band = wiphy->bands[IEEE80211_BAND_5GHZ];
13815 if (!band) {
13816 WL_ERR(("No valid band\n"));
13817 return -EINVAL;
13818 }
13819 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
13820 freq = ieee80211_channel_to_frequency(channel);
13821 (void)band->band;
13822 #else
13823 freq = ieee80211_channel_to_frequency(channel, band->band);
13824 #endif
13825 if (event == WLC_E_ACTION_FRAME_RX) {
13826 if ((err = wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
13827 NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx,
13828 &cfg->ioctl_buf_sync)) != BCME_OK) {
13829 WL_ERR(("WLC_GET_CUR_ETHERADDR failed, error %d\n", err));
13830 goto exit;
13831 }
13832
13833 err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
13834 if (err < 0)
13835 WL_ERR(("WLC_GET_BSSID error %d\n", err));
13836 memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
13837 err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
13838 &mgmt_frame, &mgmt_frame_len,
13839 (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
13840 if (err < 0) {
13841 WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n",
13842 mgmt_frame_len, channel, freq));
13843 goto exit;
13844 }
13845 isfree = true;
13846 if (wl_cfgp2p_is_pub_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13847 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
13848 act_frm = (wifi_p2p_pub_act_frame_t *)
13849 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
13850 } else if (wl_cfgp2p_is_p2p_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13851 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
13852 p2p_act_frm = (wifi_p2p_action_frame_t *)
13853 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
13854 (void) p2p_act_frm;
13855 } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13856 mgmt_frame_len - DOT11_MGMT_HDR_LEN)) {
13857
13858 sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)
13859 (&mgmt_frame[DOT11_MGMT_HDR_LEN]);
13860 if (sd_act_frm && wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
13861 if (cfg->next_af_subtype == sd_act_frm->action) {
13862 WL_DBG(("We got a right next frame of SD!(%d)\n",
13863 sd_act_frm->action));
13864 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
13865
13866 /* Stop waiting for next AF. */
13867 wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
13868 }
13869 }
13870 (void) sd_act_frm;
13871 #ifdef WLTDLS
13872 } else if ((mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) ||
13873 (wl_cfg80211_is_tdls_tunneled_frame(
13874 &mgmt_frame[DOT11_MGMT_HDR_LEN],
13875 mgmt_frame_len - DOT11_MGMT_HDR_LEN))) {
13876 if (mgmt_frame[DOT11_MGMT_HDR_LEN] == TDLS_AF_CATEGORY) {
13877 WL_ERR((" TDLS Action Frame Received type = %d \n",
13878 mgmt_frame[DOT11_MGMT_HDR_LEN + 1]));
13879 }
13880 #ifdef TDLS_MSG_ONLY_WFD
13881 if (!dhdp->tdls_mode) {
13882 WL_DBG((" TDLS Frame filtered \n"));
13883 return 0;
13884 }
13885 #else
13886 if (mgmt_frame[DOT11_MGMT_HDR_LEN + 1] == TDLS_ACTION_SETUP_RESP) {
13887 cfg->tdls_mgmt_frame = mgmt_frame;
13888 cfg->tdls_mgmt_frame_len = mgmt_frame_len;
13889 cfg->tdls_mgmt_freq = freq;
13890 return 0;
13891 }
13892 #endif /* TDLS_MSG_ONLY_WFD */
13893 #endif /* WLTDLS */
13894 #ifdef QOS_MAP_SET
13895 } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_QOS) {
13896 /* update QoS map set table */
13897 bcm_tlv_t * qos_map_ie = NULL;
13898 if ((qos_map_ie = bcm_parse_tlvs(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13899 mgmt_frame_len - DOT11_MGMT_HDR_LEN,
13900 DOT11_MNG_QOS_MAP_ID)) != NULL) {
13901 WL_DBG((" QoS map set IE found in QoS action frame\n"));
13902 if (!cfg->up_table) {
13903 cfg->up_table = kmalloc(UP_TABLE_MAX, GFP_KERNEL);
13904 }
13905 wl_set_up_table(cfg->up_table, qos_map_ie);
13906 } else {
13907 kfree(cfg->up_table);
13908 cfg->up_table = NULL;
13909 }
13910 #endif /* QOS_MAP_SET */
13911 #ifdef WBTEXT
13912 } else if (mgmt_frame[DOT11_MGMT_HDR_LEN] == DOT11_ACTION_CAT_RRM) {
13913 /* radio measurement category */
13914 switch (mgmt_frame[DOT11_MGMT_HDR_LEN+1]) {
13915 case DOT11_RM_ACTION_NR_REP:
13916 if (wl_cfg80211_recv_nbr_resp(ndev,
13917 &mgmt_frame[DOT11_MGMT_HDR_LEN],
13918 mgmt_frame_len - DOT11_MGMT_HDR_LEN)
13919 == BCME_OK) {
13920 WL_DBG(("RCC updated by nbr response\n"));
13921 }
13922 break;
13923 default:
13924 break;
13925 }
13926 #endif /* WBTEXT */
13927 } else {
13928 /*
13929 * if we got normal action frame and ndev is p2p0,
13930 * we have to change ndev from p2p0 to wlan0
13931 */
13932
13933
13934 if (cfg->next_af_subtype != P2P_PAF_SUBTYPE_INVALID) {
13935 u8 action = 0;
13936 if (wl_get_public_action(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13937 mgmt_frame_len - DOT11_MGMT_HDR_LEN, &action) != BCME_OK) {
13938 WL_DBG(("Recived action is not public action frame\n"));
13939 } else if (cfg->next_af_subtype == action) {
13940 WL_DBG(("Recived action is the waiting action(%d)\n",
13941 action));
13942 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
13943
13944 /* Stop waiting for next AF. */
13945 wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
13946 }
13947 }
13948 }
13949
13950 if (act_frm) {
13951
13952 if (wl_get_drv_status_all(cfg, WAITING_NEXT_ACT_FRM)) {
13953 if (cfg->next_af_subtype == act_frm->subtype) {
13954 WL_DBG(("We got a right next frame!(%d)\n",
13955 act_frm->subtype));
13956 wl_clr_drv_status(cfg, WAITING_NEXT_ACT_FRM, ndev);
13957
13958 if (cfg->next_af_subtype == P2P_PAF_GON_CONF) {
13959 OSL_SLEEP(20);
13960 }
13961
13962 /* Stop waiting for next AF. */
13963 wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
13964 }
13965 }
13966 }
13967
13968 wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN],
13969 mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel);
13970 if (act_frm && (act_frm->subtype == P2P_PAF_GON_CONF)) {
13971 WL_DBG(("P2P: GO_NEG_PHASE status cleared \n"));
13972 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
13973 }
13974 } else if (event == WLC_E_PROBREQ_MSG) {
13975
13976 /* Handle probe reqs frame
13977 * WPS-AP certification 4.2.13
13978 */
13979 struct parsed_ies prbreq_ies;
13980 u32 prbreq_ie_len = 0;
13981 bool pbc = 0;
13982
13983 WL_DBG((" Event WLC_E_PROBREQ_MSG received\n"));
13984 mgmt_frame = (u8 *)(data);
13985 mgmt_frame_len = ntoh32(e->datalen);
13986 if (mgmt_frame_len < DOT11_MGMT_HDR_LEN) {
13987 WL_ERR(("wrong datalen:%d\n", mgmt_frame_len));
13988 return -EINVAL;
13989 }
13990 prbreq_ie_len = mgmt_frame_len - DOT11_MGMT_HDR_LEN;
13991
13992 /* Parse prob_req IEs */
13993 if (wl_cfg80211_parse_ies(&mgmt_frame[DOT11_MGMT_HDR_LEN],
13994 prbreq_ie_len, &prbreq_ies) < 0) {
13995 WL_ERR(("Prob req get IEs failed\n"));
13996 return 0;
13997 }
13998 if (prbreq_ies.wps_ie != NULL) {
13999 wl_validate_wps_ie((char *)prbreq_ies.wps_ie, prbreq_ies.wps_ie_len, &pbc);
14000 WL_DBG((" wps_ie exist pbc = %d\n", pbc));
14001 /* if pbc method, send prob_req mgmt frame to upper layer */
14002 if (!pbc)
14003 return 0;
14004 } else
14005 return 0;
14006 } else {
14007 mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
14008
14009 /* wpa supplicant use probe request event for restarting another GON Req.
14010 * but it makes GON Req repetition.
14011 * so if src addr of prb req is same as my target device,
14012 * do not send probe request event during sending action frame.
14013 */
14014 if (event == WLC_E_P2P_PROBREQ_MSG) {
14015 WL_DBG((" Event %s\n", (event == WLC_E_P2P_PROBREQ_MSG) ?
14016 "WLC_E_P2P_PROBREQ_MSG":"WLC_E_PROBREQ_MSG"));
14017
14018
14019 /* Filter any P2P probe reqs arriving during the
14020 * GO-NEG Phase
14021 */
14022 if (cfg->p2p &&
14023 #if defined(P2P_IE_MISSING_FIX)
14024 cfg->p2p_prb_noti &&
14025 #endif
14026 wl_get_p2p_status(cfg, GO_NEG_PHASE)) {
14027 WL_DBG(("Filtering P2P probe_req while "
14028 "being in GO-Neg state\n"));
14029 return 0;
14030 }
14031 }
14032 }
14033
14034 if (discover_cfgdev(cfgdev, cfg))
14035 WL_DBG(("Rx Managment frame For P2P Discovery Interface \n"));
14036 else
14037 WL_DBG(("Rx Managment frame For Iface (%s) \n", ndev->name));
14038 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
14039 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0);
14040 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
14041 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, 0, GFP_ATOMIC);
14042 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
14043 defined(WL_COMPAT_WIRELESS)
14044 cfg80211_rx_mgmt(cfgdev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
14045 #else
14046 cfg80211_rx_mgmt(cfgdev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
14047 #endif /* LINUX_VERSION >= VERSION(3, 18, 0) */
14048
14049 WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n",
14050 mgmt_frame_len, ntoh32(e->datalen), channel, freq));
14051 exit:
14052 if (isfree)
14053 kfree(mgmt_frame);
14054 return err;
14055 }
14056
14057 #ifdef WL_SCHED_SCAN
14058 /* If target scan is not reliable, set the below define to "1" to do a
14059 * full escan
14060 */
14061 #define FULL_ESCAN_ON_PFN_NET_FOUND 0
14062 static s32
14063 wl_notify_sched_scan_results(struct bcm_cfg80211 *cfg, struct net_device *ndev,
14064 const wl_event_msg_t *e, void *data)
14065 {
14066 wl_pfn_net_info_v2_t *netinfo, *pnetinfo;
14067 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
14068 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
14069 int err = 0;
14070 struct cfg80211_scan_request *request = NULL;
14071 struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT];
14072 struct ieee80211_channel *channel = NULL;
14073 int channel_req = 0;
14074 int band = 0;
14075 wl_pfn_scanresults_t *pfn_result = (wl_pfn_scanresults_t *)data;
14076 int n_pfn_results = pfn_result->count;
14077 log_conn_event_t *event_data = NULL;
14078 tlv_log *tlv_data = NULL;
14079 u32 alloc_len, tlv_len;
14080 u32 payload_len;
14081
14082 WL_DBG(("Enter\n"));
14083
14084 if (pfn_result->version != PFN_SCANRESULT_VERSION) {
14085 WL_ERR(("Incorrect version %d, expected %d\n", pfn_result->version,
14086 PFN_SCANRESULT_VERSION));
14087 return BCME_VERSION;
14088 }
14089
14090 if (e->event_type == WLC_E_PFN_NET_LOST) {
14091 WL_PNO(("PFN NET LOST event. Do Nothing\n"));
14092 return 0;
14093 }
14094
14095 WL_PNO((">>> PFN NET FOUND event. count:%d \n", n_pfn_results));
14096 if (n_pfn_results > 0) {
14097 int i;
14098
14099 if (n_pfn_results > MAX_PFN_LIST_COUNT)
14100 n_pfn_results = MAX_PFN_LIST_COUNT;
14101 pnetinfo = (wl_pfn_net_info_v2_t *)((char *)data + sizeof(wl_pfn_scanresults_v2_t)
14102 - sizeof(wl_pfn_net_info_v2_t));
14103
14104 memset(&ssid, 0x00, sizeof(ssid));
14105
14106 request = kzalloc(sizeof(*request)
14107 + sizeof(*request->channels) * n_pfn_results,
14108 GFP_KERNEL);
14109 channel = (struct ieee80211_channel *)kzalloc(
14110 (sizeof(struct ieee80211_channel) * n_pfn_results),
14111 GFP_KERNEL);
14112 if (!request || !channel) {
14113 WL_ERR(("No memory"));
14114 err = -ENOMEM;
14115 goto out_err;
14116 }
14117
14118 request->wiphy = wiphy;
14119
14120 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
14121 alloc_len = sizeof(log_conn_event_t) + DOT11_MAX_SSID_LEN + sizeof(uint16) +
14122 sizeof(int16);
14123 event_data = MALLOC(dhdp->osh, alloc_len);
14124 if (!event_data) {
14125 WL_ERR(("%s: failed to allocate the log_conn_event_t with "
14126 "length(%d)\n", __func__, alloc_len));
14127 goto out_err;
14128 }
14129 tlv_len = 3 * sizeof(tlv_log);
14130 event_data->tlvs = MALLOC(dhdp->osh, tlv_len);
14131 if (!event_data->tlvs) {
14132 WL_ERR(("%s: failed to allocate the tlv_log with "
14133 "length(%d)\n", __func__, tlv_len));
14134 goto out_err;
14135 }
14136 }
14137
14138 for (i = 0; i < n_pfn_results; i++) {
14139 netinfo = &pnetinfo[i];
14140 if (!netinfo) {
14141 WL_ERR(("Invalid netinfo ptr. index:%d", i));
14142 err = -EINVAL;
14143 goto out_err;
14144 }
14145 WL_PNO((">>> SSID:%s Channel:%d \n",
14146 netinfo->pfnsubnet.u.SSID, netinfo->pfnsubnet.channel));
14147 /* PFN result doesn't have all the info which are required by the supplicant
14148 * (For e.g IEs) Do a target Escan so that sched scan results are reported
14149 * via wl_inform_single_bss in the required format. Escan does require the
14150 * scan request in the form of cfg80211_scan_request. For timebeing, create
14151 * cfg80211_scan_request one out of the received PNO event.
14152 */
14153 ssid[i].ssid_len = MIN(DOT11_MAX_SSID_LEN, netinfo->pfnsubnet.SSID_len);
14154 memcpy(ssid[i].ssid, netinfo->pfnsubnet.u.SSID,
14155 ssid[i].ssid_len);
14156 request->n_ssids++;
14157
14158 channel_req = netinfo->pfnsubnet.channel;
14159 band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ
14160 : NL80211_BAND_5GHZ;
14161 channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band);
14162 channel[i].band = band;
14163 channel[i].flags |= IEEE80211_CHAN_NO_HT40;
14164 request->channels[i] = &channel[i];
14165 request->n_channels++;
14166
14167 if (DBG_RING_ACTIVE(dhdp, DHD_EVENT_RING_ID)) {
14168 payload_len = sizeof(log_conn_event_t);
14169 event_data->event = WIFI_EVENT_DRIVER_PNO_NETWORK_FOUND;
14170 tlv_data = event_data->tlvs;
14171
14172 /* ssid */
14173 tlv_data->tag = WIFI_TAG_SSID;
14174 tlv_data->len = netinfo->pfnsubnet.SSID_len;
14175 memcpy(tlv_data->value, ssid[i].ssid, ssid[i].ssid_len);
14176 payload_len += TLV_LOG_SIZE(tlv_data);
14177 tlv_data = TLV_LOG_NEXT(tlv_data);
14178
14179 /* channel */
14180 tlv_data->tag = WIFI_TAG_CHANNEL;
14181 tlv_data->len = sizeof(uint16);
14182 memcpy(tlv_data->value, &channel_req, sizeof(uint16));
14183 payload_len += TLV_LOG_SIZE(tlv_data);
14184 tlv_data = TLV_LOG_NEXT(tlv_data);
14185
14186 /* rssi */
14187 tlv_data->tag = WIFI_TAG_RSSI;
14188 tlv_data->len = sizeof(int16);
14189 memcpy(tlv_data->value, &netinfo->RSSI, sizeof(int16));
14190 payload_len += TLV_LOG_SIZE(tlv_data);
14191 tlv_data = TLV_LOG_NEXT(tlv_data);
14192
14193 dhd_os_push_push_ring_data(dhdp, DHD_EVENT_RING_ID,
14194 &event_data->event, payload_len);
14195 }
14196 }
14197
14198 /* assign parsed ssid array */
14199 if (request->n_ssids)
14200 request->ssids = &ssid[0];
14201
14202 if (wl_get_drv_status_all(cfg, SCANNING)) {
14203 /* Abort any on-going scan */
14204 wl_notify_escan_complete(cfg, ndev, true, true);
14205 }
14206
14207 if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
14208 WL_PNO((">>> P2P discovery was ON. Disabling it\n"));
14209 err = wl_cfgp2p_discover_enable_search(cfg, false);
14210 if (unlikely(err)) {
14211 wl_clr_drv_status(cfg, SCANNING, ndev);
14212 goto out_err;
14213 }
14214 p2p_scan(cfg) = false;
14215 }
14216
14217 wl_set_drv_status(cfg, SCANNING, ndev);
14218 #if FULL_ESCAN_ON_PFN_NET_FOUND
14219 WL_PNO((">>> Doing Full ESCAN on PNO event\n"));
14220 err = wl_do_escan(cfg, wiphy, ndev, NULL);
14221 #else
14222 WL_PNO((">>> Doing targeted ESCAN on PNO event\n"));
14223 err = wl_do_escan(cfg, wiphy, ndev, request);
14224 #endif
14225 if (err) {
14226 wl_clr_drv_status(cfg, SCANNING, ndev);
14227 goto out_err;
14228 }
14229 DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_SCAN_REQUESTED);
14230 cfg->sched_scan_running = TRUE;
14231 }
14232 else {
14233 WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n"));
14234 }
14235 out_err:
14236 if (request)
14237 kfree(request);
14238 if (channel)
14239 kfree(channel);
14240
14241 if (event_data) {
14242 MFREE(dhdp->osh, event_data->tlvs, tlv_len);
14243 MFREE(dhdp->osh, event_data, alloc_len);
14244 }
14245 return err;
14246 }
14247 #endif /* WL_SCHED_SCAN */
14248
14249 static void wl_init_conf(struct wl_conf *conf)
14250 {
14251 WL_DBG(("Enter \n"));
14252 conf->frag_threshold = (u32)-1;
14253 conf->rts_threshold = (u32)-1;
14254 conf->retry_short = (u32)-1;
14255 conf->retry_long = (u32)-1;
14256 conf->tx_power = -1;
14257 }
14258
14259 static void wl_init_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev)
14260 {
14261 unsigned long flags;
14262 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
14263
14264 if (profile) {
14265 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14266 memset(profile, 0, sizeof(struct wl_profile));
14267 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14268 } else {
14269 WL_ERR(("%s: No profile\n", __FUNCTION__));
14270 }
14271 return;
14272 }
14273
14274 static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
14275 {
14276 memset(cfg->evt_handler, 0, sizeof(cfg->evt_handler));
14277
14278 cfg->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
14279 cfg->evt_handler[WLC_E_AUTH] = wl_notify_connect_status;
14280 cfg->evt_handler[WLC_E_ASSOC] = wl_notify_connect_status;
14281 cfg->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
14282 cfg->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
14283 cfg->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
14284 cfg->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
14285 cfg->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
14286 cfg->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
14287 cfg->evt_handler[WLC_E_ROAM] = wl_notify_roaming_status;
14288 cfg->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
14289 cfg->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
14290 cfg->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
14291 cfg->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
14292 cfg->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
14293 cfg->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
14294 cfg->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
14295 cfg->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
14296 cfg->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
14297 cfg->evt_handler[WLC_E_START] = wl_notify_connect_status;
14298 #ifdef PNO_SUPPORT
14299 cfg->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status;
14300 #endif /* PNO_SUPPORT */
14301 #ifdef GSCAN_SUPPORT
14302 cfg->evt_handler[WLC_E_PFN_BEST_BATCHING] = wl_notify_gscan_event;
14303 cfg->evt_handler[WLC_E_PFN_SCAN_COMPLETE] = wl_notify_gscan_event;
14304 cfg->evt_handler[WLC_E_PFN_GSCAN_FULL_RESULT] = wl_notify_gscan_event;
14305 cfg->evt_handler[WLC_E_PFN_BSSID_NET_FOUND] = wl_notify_gscan_event;
14306 cfg->evt_handler[WLC_E_PFN_BSSID_NET_LOST] = wl_notify_gscan_event;
14307 cfg->evt_handler[WLC_E_PFN_SSID_EXT] = wl_notify_gscan_event;
14308 cfg->evt_handler[WLC_E_GAS_FRAGMENT_RX] = wl_notify_gscan_event;
14309 cfg->evt_handler[WLC_E_ROAM_EXP_EVENT] = wl_handle_roam_exp_event;
14310 #endif /* GSCAN_SUPPORT */
14311 #ifdef RSSI_MONITOR_SUPPORT
14312 cfg->evt_handler[WLC_E_RSSI_LQM] = wl_handle_rssi_monitor_event;
14313 #endif /* RSSI_MONITOR_SUPPORT */
14314 #ifdef WLTDLS
14315 cfg->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler;
14316 #endif /* WLTDLS */
14317 cfg->evt_handler[WLC_E_BSSID] = wl_notify_roaming_status;
14318 #ifdef WL_RELMCAST
14319 cfg->evt_handler[WLC_E_RMC_EVENT] = wl_notify_rmc_status;
14320 #endif /* WL_RELMCAST */
14321 #ifdef BT_WIFI_HANDOVER
14322 cfg->evt_handler[WLC_E_BT_WIFI_HANDOVER_REQ] = wl_notify_bt_wifi_handover_req;
14323 #endif
14324 cfg->evt_handler[WLC_E_CSA_COMPLETE_IND] = wl_csa_complete_ind;
14325 cfg->evt_handler[WLC_E_AP_STARTED] = wl_ap_start_ind;
14326 #ifdef CUSTOM_EVENT_PM_WAKE
14327 cfg->evt_handler[WLC_E_EXCESS_PM_WAKE_EVENT] = wl_check_pmstatus;
14328 #endif /* CUSTOM_EVENT_PM_WAKE */
14329 #if defined(DHD_LOSSLESS_ROAMING) || defined(DBG_PKT_MON)
14330 cfg->evt_handler[WLC_E_ROAM_PREP] = wl_notify_roam_prep_status;
14331 #endif /* DHD_LOSSLESS_ROAMING || DBG_PKT_MON */
14332 #ifdef ENABLE_TEMP_THROTTLING
14333 cfg->evt_handler[WLC_E_TEMP_THROTTLE] = wl_check_rx_throttle_status;
14334 #endif /* ENABLE_TEMP_THROTTLING */
14335
14336 }
14337
14338 #if defined(STATIC_WL_PRIV_STRUCT)
14339 static int
14340 wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
14341 {
14342 cfg->escan_info.escan_buf = DHD_OS_PREALLOC(cfg->pub,
14343 DHD_PREALLOC_WIPHY_ESCAN0, ESCAN_BUF_SIZE);
14344 if (cfg->escan_info.escan_buf == NULL) {
14345 WL_ERR(("Failed to alloc ESCAN_BUF\n"));
14346 return -ENOMEM;
14347 }
14348 bzero(cfg->escan_info.escan_buf, ESCAN_BUF_SIZE);
14349
14350 return 0;
14351 }
14352
14353 static void
14354 wl_deinit_escan_result_buf(struct bcm_cfg80211 *cfg)
14355 {
14356 if (cfg->escan_info.escan_buf != NULL) {
14357 cfg->escan_info.escan_buf = NULL;
14358 }
14359 }
14360 #endif /* STATIC_WL_PRIV_STRUCT */
14361
14362 static s32 wl_init_priv_mem(struct bcm_cfg80211 *cfg)
14363 {
14364 WL_DBG(("Enter \n"));
14365
14366 cfg->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL);
14367 if (unlikely(!cfg->scan_results)) {
14368 WL_ERR(("Scan results alloc failed\n"));
14369 goto init_priv_mem_out;
14370 }
14371 cfg->conf = (void *)kzalloc(sizeof(*cfg->conf), GFP_KERNEL);
14372 if (unlikely(!cfg->conf)) {
14373 WL_ERR(("wl_conf alloc failed\n"));
14374 goto init_priv_mem_out;
14375 }
14376 cfg->scan_req_int =
14377 (void *)kzalloc(sizeof(*cfg->scan_req_int), GFP_KERNEL);
14378 if (unlikely(!cfg->scan_req_int)) {
14379 WL_ERR(("Scan req alloc failed\n"));
14380 goto init_priv_mem_out;
14381 }
14382 cfg->ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
14383 if (unlikely(!cfg->ioctl_buf)) {
14384 WL_ERR(("Ioctl buf alloc failed\n"));
14385 goto init_priv_mem_out;
14386 }
14387 cfg->escan_ioctl_buf = (void *)kzalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
14388 if (unlikely(!cfg->escan_ioctl_buf)) {
14389 WL_ERR(("Ioctl buf alloc failed\n"));
14390 goto init_priv_mem_out;
14391 }
14392 cfg->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL);
14393 if (unlikely(!cfg->extra_buf)) {
14394 WL_ERR(("Extra buf alloc failed\n"));
14395 goto init_priv_mem_out;
14396 }
14397 cfg->pmk_list = (void *)kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL);
14398 if (unlikely(!cfg->pmk_list)) {
14399 WL_ERR(("pmk list alloc failed\n"));
14400 goto init_priv_mem_out;
14401 }
14402 #if defined(STATIC_WL_PRIV_STRUCT)
14403 cfg->conn_info = (void *)kzalloc(sizeof(*cfg->conn_info), GFP_KERNEL);
14404 if (unlikely(!cfg->conn_info)) {
14405 WL_ERR(("cfg->conn_info alloc failed\n"));
14406 goto init_priv_mem_out;
14407 }
14408 cfg->ie = (void *)kzalloc(sizeof(*cfg->ie), GFP_KERNEL);
14409 if (unlikely(!cfg->ie)) {
14410 WL_ERR(("cfg->ie alloc failed\n"));
14411 goto init_priv_mem_out;
14412 }
14413 if (unlikely(wl_init_escan_result_buf(cfg))) {
14414 WL_ERR(("Failed to init escan resul buf\n"));
14415 goto init_priv_mem_out;
14416 }
14417 #endif /* STATIC_WL_PRIV_STRUCT */
14418 cfg->afx_hdl = (void *)kzalloc(sizeof(*cfg->afx_hdl), GFP_KERNEL);
14419 if (unlikely(!cfg->afx_hdl)) {
14420 WL_ERR(("afx hdl alloc failed\n"));
14421 goto init_priv_mem_out;
14422 } else {
14423 init_completion(&cfg->act_frm_scan);
14424 init_completion(&cfg->wait_next_af);
14425
14426 INIT_WORK(&cfg->afx_hdl->work, wl_cfg80211_afx_handler);
14427 }
14428 #ifdef WLTDLS
14429 if (cfg->tdls_mgmt_frame) {
14430 kfree(cfg->tdls_mgmt_frame);
14431 cfg->tdls_mgmt_frame = NULL;
14432 }
14433 #endif /* WLTDLS */
14434 return 0;
14435
14436 init_priv_mem_out:
14437 wl_deinit_priv_mem(cfg);
14438
14439 return -ENOMEM;
14440 }
14441
14442 static void wl_deinit_priv_mem(struct bcm_cfg80211 *cfg)
14443 {
14444 kfree(cfg->scan_results);
14445 cfg->scan_results = NULL;
14446 kfree(cfg->conf);
14447 cfg->conf = NULL;
14448 kfree(cfg->scan_req_int);
14449 cfg->scan_req_int = NULL;
14450 kfree(cfg->ioctl_buf);
14451 cfg->ioctl_buf = NULL;
14452 kfree(cfg->escan_ioctl_buf);
14453 cfg->escan_ioctl_buf = NULL;
14454 kfree(cfg->extra_buf);
14455 cfg->extra_buf = NULL;
14456 kfree(cfg->pmk_list);
14457 cfg->pmk_list = NULL;
14458 #if defined(STATIC_WL_PRIV_STRUCT)
14459 kfree(cfg->conn_info);
14460 cfg->conn_info = NULL;
14461 kfree(cfg->ie);
14462 cfg->ie = NULL;
14463 wl_deinit_escan_result_buf(cfg);
14464 #endif /* STATIC_WL_PRIV_STRUCT */
14465 if (cfg->afx_hdl) {
14466 cancel_work_sync(&cfg->afx_hdl->work);
14467 kfree(cfg->afx_hdl);
14468 cfg->afx_hdl = NULL;
14469 }
14470
14471 }
14472
14473 static s32 wl_create_event_handler(struct bcm_cfg80211 *cfg)
14474 {
14475 int ret = 0;
14476 WL_DBG(("Enter \n"));
14477
14478 /* Allocate workqueue for event */
14479 if (!cfg->event_workq) {
14480 cfg->event_workq = alloc_workqueue("dhd_eventd", WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
14481 }
14482
14483 if (!cfg->event_workq) {
14484 WL_ERR(("event_workq alloc_workqueue failed\n"));
14485 ret = -ENOMEM;
14486 } else {
14487 INIT_WORK(&cfg->event_work, wl_event_handler);
14488 }
14489 return ret;
14490 }
14491
14492 static void wl_destroy_event_handler(struct bcm_cfg80211 *cfg)
14493 {
14494 if (cfg && cfg->event_workq) {
14495 cancel_work_sync(&cfg->event_work);
14496 destroy_workqueue(cfg->event_workq);
14497 cfg->event_workq = NULL;
14498 }
14499 }
14500
14501 void wl_terminate_event_handler(struct net_device *dev)
14502 {
14503 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
14504
14505 if (cfg) {
14506 wl_destroy_event_handler(cfg);
14507 wl_flush_eq(cfg);
14508 }
14509 }
14510
14511 static void wl_scan_timeout(
14512 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
14513 struct timer_list *t
14514 #else
14515 unsigned long data
14516 #endif
14517 )
14518 {
14519 wl_event_msg_t msg;
14520 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
14521 struct bcm_cfg80211 *cfg = from_timer(cfg, t, scan_timeout);
14522 #else
14523 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
14524 #endif
14525 struct wireless_dev *wdev = NULL;
14526 struct net_device *ndev = NULL;
14527 struct wl_scan_results *bss_list;
14528 struct wl_bss_info *bi = NULL;
14529 s32 i;
14530 u32 channel;
14531 #if 0
14532 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
14533 uint32 prev_memdump_mode = dhdp->memdump_enabled;
14534 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
14535
14536 if (!(cfg->scan_request)) {
14537 WL_ERR(("timer expired but no scan request\n"));
14538 return;
14539 }
14540
14541 bss_list = wl_escan_get_buf(cfg, FALSE);
14542 if (!bss_list) {
14543 WL_ERR(("bss_list is null. Didn't receive any partial scan results\n"));
14544 } else {
14545 WL_ERR(("scanned AP count (%d)\n", bss_list->count));
14546
14547 bi = next_bss(bss_list, bi);
14548 for_each_bss(bss_list, bi, i) {
14549 if (bi != NULL && &(bi->chanspec) != NULL && (bi->SSID)) {
14550 channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
14551 WL_ERR(("SSID :%s SSID_LEN :%d Channel :%d\n", bi->SSID, bi->SSID_len, channel));
14552 if (bi->SSID[0] == '\0') {
14553 WL_ERR(("SSID :%s is null ssid_len:%d ,need return\n", bi->SSID, bi->SSID_len));
14554 return;
14555 }
14556 } else {
14557 WL_ERR(("SSID or Channel is null\n"));
14558 return;
14559 }
14560 }
14561 }
14562
14563 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
14564 if (cfg->scan_request->dev)
14565 wdev = cfg->scan_request->dev->ieee80211_ptr;
14566 #else
14567 if (cfg->scan_request)
14568 wdev = cfg->scan_request->wdev;
14569 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
14570 if (!wdev) {
14571 WL_ERR(("No wireless_dev present\n"));
14572 return;
14573 }
14574 ndev = wdev_to_wlc_ndev(wdev, cfg);
14575
14576 bzero(&msg, sizeof(wl_event_msg_t));
14577 WL_ERR(("timer expired\n"));
14578 #if 0
14579 if (dhdp->memdump_enabled) {
14580 dhdp->memdump_enabled = DUMP_MEMFILE;
14581 dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
14582 dhd_bus_mem_dump(dhdp);
14583 dhdp->memdump_enabled = prev_memdump_mode;
14584 }
14585 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
14586 msg.event_type = hton32(WLC_E_ESCAN_RESULT);
14587 msg.status = hton32(WLC_E_STATUS_TIMEOUT);
14588 msg.reason = 0xFFFFFFFF;
14589 wl_cfg80211_event(ndev, &msg, NULL);
14590 #ifdef CUSTOMER_HW4_DEBUG
14591 if (!wl_scan_timeout_dbg_enabled)
14592 wl_scan_timeout_dbg_set();
14593 #endif /* CUSTOMER_HW4_DEBUG */
14594
14595 // terence 20130729: workaround to fix out of memory in firmware
14596 // if (dhd_conf_get_chip(dhd_get_pub(ndev)) == BCM43362_CHIP_ID) {
14597 // WL_ERR(("Send hang event\n"));
14598 // net_os_send_hang_message(ndev);
14599 // }
14600 }
14601
14602 #ifdef DHD_LOSSLESS_ROAMING
14603 static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg)
14604 {
14605 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
14606
14607 /* restore prec_map to ALLPRIO */
14608 dhdp->dequeue_prec_map = ALLPRIO;
14609 if (timer_pending(&cfg->roam_timeout)) {
14610 del_timer_sync(&cfg->roam_timeout);
14611 }
14612
14613 }
14614
14615 static void wl_roam_timeout(
14616 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
14617 struct timer_list *t
14618 #else
14619 unsigned long data
14620 #endif
14621 )
14622 {
14623 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
14624 struct bcm_cfg80211 *cfg = from_timer(cfg, t, roam_timeout);
14625 #else
14626 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
14627 #endif
14628 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
14629
14630 WL_ERR(("roam timer expired\n"));
14631
14632 /* restore prec_map to ALLPRIO */
14633 dhdp->dequeue_prec_map = ALLPRIO;
14634 }
14635
14636 #endif /* DHD_LOSSLESS_ROAMING */
14637
14638 static s32
14639 wl_cfg80211_netdev_notifier_call(struct notifier_block * nb,
14640 unsigned long state, void *ptr)
14641 {
14642 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
14643 struct net_device *dev = ptr;
14644 #else
14645 struct net_device *dev = netdev_notifier_info_to_dev(ptr);
14646 #endif /* LINUX_VERSION < VERSION(3, 11, 0) */
14647 struct wireless_dev *wdev = ndev_to_wdev(dev);
14648 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
14649
14650 WL_DBG(("Enter \n"));
14651
14652 if (!wdev || !cfg || dev == bcmcfg_to_prmry_ndev(cfg))
14653 return NOTIFY_DONE;
14654
14655 switch (state) {
14656 case NETDEV_DOWN:
14657 {
14658 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 11, 0))
14659 int max_wait_timeout = 2;
14660 int max_wait_count = 100;
14661 int refcnt = 0;
14662 unsigned long limit = jiffies + max_wait_timeout * HZ;
14663 while (work_pending(&wdev->cleanup_work)) {
14664 if (refcnt%5 == 0) {
14665 WL_ERR(("[NETDEV_DOWN] wait for "
14666 "complete of cleanup_work"
14667 " (%d th)\n", refcnt));
14668 }
14669 if (!time_before(jiffies, limit)) {
14670 WL_ERR(("[NETDEV_DOWN] cleanup_work"
14671 " of CFG80211 is not"
14672 " completed in %d sec\n",
14673 max_wait_timeout));
14674 break;
14675 }
14676 if (refcnt >= max_wait_count) {
14677 WL_ERR(("[NETDEV_DOWN] cleanup_work"
14678 " of CFG80211 is not"
14679 " completed in %d loop\n",
14680 max_wait_count));
14681 break;
14682 }
14683 set_current_state(TASK_INTERRUPTIBLE);
14684 (void)schedule_timeout(100);
14685 set_current_state(TASK_RUNNING);
14686 refcnt++;
14687 }
14688 #endif /* LINUX_VERSION < VERSION(3, 14, 0) */
14689 break;
14690 }
14691 case NETDEV_UNREGISTER:
14692 /* after calling list_del_rcu(&wdev->list) */
14693 wl_cfg80211_clear_per_bss_ies(cfg,
14694 wl_get_bssidx_by_wdev(cfg, wdev));
14695 wl_dealloc_netinfo_by_wdev(cfg, wdev);
14696 break;
14697 case NETDEV_GOING_DOWN:
14698 /*
14699 * At NETDEV_DOWN state, wdev_cleanup_work work will be called.
14700 * In front of door, the function checks whether current scan
14701 * is working or not. If the scanning is still working,
14702 * wdev_cleanup_work call WARN_ON and make the scan done forcibly.
14703 */
14704 if (wl_get_drv_status(cfg, SCANNING, dev))
14705 wl_notify_escan_complete(cfg, dev, true, true);
14706 break;
14707 }
14708 return NOTIFY_DONE;
14709 }
14710
14711 static struct notifier_block wl_cfg80211_netdev_notifier = {
14712 .notifier_call = wl_cfg80211_netdev_notifier_call,
14713 };
14714
14715 /*
14716 * to make sure we won't register the same notifier twice, otherwise a loop is likely to be
14717 * created in kernel notifier link list (with 'next' pointing to itself)
14718 */
14719 static bool wl_cfg80211_netdev_notifier_registered = FALSE;
14720
14721 static void wl_cfg80211_cancel_scan(struct bcm_cfg80211 *cfg)
14722 {
14723 struct wireless_dev *wdev = NULL;
14724 struct net_device *ndev = NULL;
14725
14726 if (!cfg->scan_request)
14727 return;
14728
14729 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 6, 0))
14730 if (cfg->scan_request->dev)
14731 wdev = cfg->scan_request->dev->ieee80211_ptr;
14732 #else
14733 wdev = cfg->scan_request->wdev;
14734 #endif /* LINUX_VERSION < KERNEL_VERSION(3, 6, 0) */
14735
14736 if (!wdev) {
14737 WL_ERR(("No wireless_dev present\n"));
14738 return;
14739 }
14740
14741 ndev = wdev_to_wlc_ndev(wdev, cfg);
14742 wl_notify_escan_complete(cfg, ndev, true, true);
14743 WL_ERR(("Scan aborted! \n"));
14744 }
14745
14746 void wl_cfg80211_scan_abort(struct bcm_cfg80211 *cfg)
14747 {
14748 wl_scan_params_t *params = NULL;
14749 s32 params_size = 0;
14750 s32 err = BCME_OK;
14751 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
14752 if (!in_atomic()) {
14753 /* Our scan params only need space for 1 channel and 0 ssids */
14754 params = wl_cfg80211_scan_alloc_params(cfg, -1, 0, &params_size);
14755 if (params == NULL) {
14756 WL_ERR(("scan params allocation failed \n"));
14757 err = -ENOMEM;
14758 } else {
14759 /* Do a scan abort to stop the driver's scan engine */
14760 err = wldev_ioctl_set(dev, WLC_SCAN, params, params_size);
14761 if (err < 0) {
14762 WL_ERR(("scan abort failed \n"));
14763 }
14764 kfree(params);
14765 }
14766 }
14767 #ifdef WLTDLS
14768 if (cfg->tdls_mgmt_frame) {
14769 kfree(cfg->tdls_mgmt_frame);
14770 cfg->tdls_mgmt_frame = NULL;
14771 }
14772 #endif /* WLTDLS */
14773 }
14774
14775 static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
14776 struct net_device *ndev,
14777 bool aborted, bool fw_abort)
14778 {
14779 s32 err = BCME_OK;
14780 unsigned long flags;
14781 struct net_device *dev;
14782 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
14783 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
14784 struct cfg80211_scan_info info;
14785 info.aborted = aborted;
14786 #endif
14787
14788 WL_DBG(("Enter \n"));
14789 BCM_REFERENCE(dhdp);
14790
14791 mutex_lock(&cfg->scan_complete);
14792
14793 if (!ndev) {
14794 WL_ERR(("ndev is null\n"));
14795 err = BCME_ERROR;
14796 goto out;
14797 }
14798
14799 if (cfg->escan_info.ndev != ndev) {
14800 WL_ERR(("ndev is different %p %p\n", cfg->escan_info.ndev, ndev));
14801 err = BCME_ERROR;
14802 goto out;
14803 }
14804
14805 if (cfg->scan_request) {
14806 dev = bcmcfg_to_prmry_ndev(cfg);
14807 #if defined(WL_ENABLE_P2P_IF)
14808 if (cfg->scan_request->dev != cfg->p2p_net)
14809 dev = cfg->scan_request->dev;
14810 #elif defined(WL_CFG80211_P2P_DEV_IF)
14811 if (cfg->scan_request->wdev->iftype != NL80211_IFTYPE_P2P_DEVICE)
14812 dev = cfg->scan_request->wdev->netdev;
14813 #endif /* WL_ENABLE_P2P_IF */
14814 }
14815 else {
14816 WL_DBG(("cfg->scan_request is NULL may be internal scan."
14817 "doing scan_abort for ndev %p primary %p",
14818 ndev, bcmcfg_to_prmry_ndev(cfg)));
14819 dev = ndev;
14820 }
14821 if (fw_abort && !in_atomic())
14822 wl_cfg80211_scan_abort(cfg);
14823 if (timer_pending(&cfg->scan_timeout))
14824 del_timer_sync(&cfg->scan_timeout);
14825 #if defined(ESCAN_RESULT_PATCH)
14826 if (likely(cfg->scan_request)) {
14827 cfg->bss_list = wl_escan_get_buf(cfg, aborted);
14828 wl_inform_bss(cfg);
14829 }
14830 #endif /* ESCAN_RESULT_PATCH */
14831 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
14832 #ifdef WL_SCHED_SCAN
14833 if (cfg->sched_scan_req && !cfg->scan_request) {
14834 WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n"));
14835 if (!aborted) {
14836 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0))
14837 cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy, 0);
14838 #else
14839 cfg80211_sched_scan_results(cfg->sched_scan_req->wiphy);
14840 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)) */
14841 }
14842
14843 DBG_EVENT_LOG(dhdp, WIFI_EVENT_DRIVER_PNO_SCAN_COMPLETE);
14844 cfg->sched_scan_running = FALSE;
14845 }
14846 #endif /* WL_SCHED_SCAN */
14847 if (likely(cfg->scan_request)) {
14848 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
14849 cfg80211_scan_done(cfg->scan_request, &info);
14850 #else
14851 cfg80211_scan_done(cfg->scan_request, aborted);
14852 #endif
14853 cfg->scan_request = NULL;
14854 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
14855 DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
14856 }
14857 if (p2p_is_on(cfg))
14858 wl_clr_p2p_status(cfg, SCANNING);
14859 wl_clr_drv_status(cfg, SCANNING, dev);
14860 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
14861
14862 out:
14863 mutex_unlock(&cfg->scan_complete);
14864 return err;
14865 }
14866
14867 #ifdef ESCAN_BUF_OVERFLOW_MGMT
14868 #ifndef WL_DRV_AVOID_SCANCACHE
14869 static void
14870 wl_cfg80211_find_removal_candidate(wl_bss_info_t *bss, removal_element_t *candidate)
14871 {
14872 int idx;
14873 for (idx = 0; idx < BUF_OVERFLOW_MGMT_COUNT; idx++) {
14874 int len = BUF_OVERFLOW_MGMT_COUNT - idx - 1;
14875 if (bss->RSSI < candidate[idx].RSSI) {
14876 if (len)
14877 memcpy(&candidate[idx + 1], &candidate[idx],
14878 sizeof(removal_element_t) * len);
14879 candidate[idx].RSSI = bss->RSSI;
14880 candidate[idx].length = bss->length;
14881 memcpy(&candidate[idx].BSSID, &bss->BSSID, ETHER_ADDR_LEN);
14882 return;
14883 }
14884 }
14885 }
14886
14887 static void
14888 wl_cfg80211_remove_lowRSSI_info(wl_scan_results_t *list, removal_element_t *candidate,
14889 wl_bss_info_t *bi)
14890 {
14891 int idx1, idx2;
14892 int total_delete_len = 0;
14893 for (idx1 = 0; idx1 < BUF_OVERFLOW_MGMT_COUNT; idx1++) {
14894 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
14895 wl_bss_info_t *bss = NULL;
14896 if (candidate[idx1].RSSI >= bi->RSSI)
14897 continue;
14898 for (idx2 = 0; idx2 < list->count; idx2++) {
14899 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length)) :
14900 list->bss_info;
14901 if (!bcmp(&candidate[idx1].BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
14902 candidate[idx1].RSSI == bss->RSSI &&
14903 candidate[idx1].length == dtoh32(bss->length)) {
14904 u32 delete_len = dtoh32(bss->length);
14905 WL_DBG(("delete scan info of " MACDBG " to add new AP\n",
14906 MAC2STRDBG(bss->BSSID.octet)));
14907 if (idx2 < list->count -1) {
14908 memmove((u8 *)bss, (u8 *)bss + delete_len,
14909 list->buflen - cur_len - delete_len);
14910 }
14911 list->buflen -= delete_len;
14912 list->count--;
14913 total_delete_len += delete_len;
14914 /* if delete_len is greater than or equal to result length */
14915 if (total_delete_len >= bi->length) {
14916 return;
14917 }
14918 break;
14919 }
14920 cur_len += dtoh32(bss->length);
14921 }
14922 }
14923 }
14924 #endif /* WL_DRV_AVOID_SCANCACHE */
14925 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
14926
14927 #ifdef WL_DRV_AVOID_SCANCACHE
14928 static u32 wl_p2p_find_peer_channel(struct bcm_cfg80211 *cfg, s32 status, wl_bss_info_t *bi,
14929 u32 bi_length)
14930 {
14931 u32 ret;
14932 u8 *p2p_dev_addr = NULL;
14933
14934 ret = wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL);
14935 if (!ret) {
14936 return ret;
14937 }
14938 if (status == WLC_E_STATUS_PARTIAL) {
14939 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
14940 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
14941 cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
14942 s32 channel = wf_chspec_ctlchan(
14943 wl_chspec_driver_to_host(bi->chanspec));
14944
14945 if ((channel > MAXCHANNEL) || (channel <= 0))
14946 channel = WL_INVALID;
14947 else
14948 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
14949 " channel : %d\n",
14950 MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
14951 channel));
14952
14953 wl_clr_p2p_status(cfg, SCANNING);
14954 cfg->afx_hdl->peer_chan = channel;
14955 complete(&cfg->act_frm_scan);
14956 }
14957 } else {
14958 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
14959 wl_clr_p2p_status(cfg, SCANNING);
14960 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
14961 if (cfg->afx_hdl->peer_chan == WL_INVALID)
14962 complete(&cfg->act_frm_scan);
14963 }
14964
14965 return ret;
14966 }
14967
14968 static s32 wl_escan_without_scan_cache(struct bcm_cfg80211 *cfg, wl_escan_result_t *escan_result,
14969 struct net_device *ndev, const wl_event_msg_t *e, s32 status)
14970 {
14971 s32 err = BCME_OK;
14972 wl_bss_info_t *bi;
14973 u32 bi_length;
14974 bool aborted = false;
14975 bool fw_abort = false;
14976 bool notify_escan_complete = false;
14977
14978 if (wl_escan_check_sync_id(status, escan_result->sync_id,
14979 cfg->escan_info.cur_sync_id) < 0) {
14980 goto exit;
14981 }
14982
14983 wl_escan_print_sync_id(status, escan_result->sync_id,
14984 cfg->escan_info.cur_sync_id);
14985
14986 if (!(status == WLC_E_STATUS_TIMEOUT) || !(status == WLC_E_STATUS_PARTIAL)) {
14987 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
14988 }
14989
14990 if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
14991 notify_escan_complete = true;
14992 }
14993
14994 if (status == WLC_E_STATUS_PARTIAL) {
14995 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
14996 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND);
14997 if ((!escan_result) || (dtoh16(escan_result->bss_count) != 1)) {
14998 WL_ERR(("Invalid escan result (NULL pointer) or invalid bss_count\n"));
14999 goto exit;
15000 }
15001
15002 bi = escan_result->bss_info;
15003 bi_length = dtoh32(bi->length);
15004 if ((!bi) ||
15005 (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE))) {
15006 WL_ERR(("Invalid escan bss info (NULL pointer)"
15007 "or invalid bss_info length\n"));
15008 goto exit;
15009 }
15010
15011 if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
15012 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
15013 WL_DBG(("Ignoring IBSS result\n"));
15014 goto exit;
15015 }
15016 }
15017
15018 if (wl_p2p_find_peer_channel(cfg, status, bi, bi_length)) {
15019 goto exit;
15020 } else {
15021 if (scan_req_match(cfg)) {
15022 /* p2p scan && allow only probe response */
15023 if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
15024 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
15025 goto exit;
15026 }
15027 err = wl_inform_single_bss(cfg, bi, false);
15028
15029 /*
15030 * !Broadcast && number of ssid = 1 && number of channels =1
15031 * means specific scan to association
15032 */
15033 if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
15034 WL_ERR(("P2P assoc scan fast aborted.\n"));
15035 aborted = false;
15036 fw_abort = true;
15037 }
15038 /* Directly exit from function here and
15039 * avoid sending notify completion to cfg80211
15040 */
15041 goto exit;
15042 }
15043 } else if (status == WLC_E_STATUS_SUCCESS) {
15044 if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
15045 goto exit;
15046 }
15047 WL_INFORM(("ESCAN COMPLETED\n"));
15048 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE);
15049
15050 /* Update escan complete status */
15051 aborted = false;
15052 fw_abort = false;
15053
15054 #ifdef CUSTOMER_HW4_DEBUG
15055 if (wl_scan_timeout_dbg_enabled)
15056 wl_scan_timeout_dbg_clear();
15057 #endif /* CUSTOMER_HW4_DEBUG */
15058 } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
15059 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
15060 (status == WLC_E_STATUS_NEWASSOC)) {
15061 /* Handle all cases of scan abort */
15062
15063 WL_DBG(("ESCAN ABORT reason: %d\n", status));
15064 if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
15065 goto exit;
15066 }
15067 WL_INFORM(("ESCAN ABORTED\n"));
15068
15069 /* Update escan complete status */
15070 aborted = true;
15071 fw_abort = false;
15072
15073 } else if (status == WLC_E_STATUS_TIMEOUT) {
15074 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
15075 WL_ERR(("reason[0x%x]\n", e->reason));
15076 if (e->reason == 0xFFFFFFFF) {
15077 /* Update escan complete status */
15078 aborted = true;
15079 fw_abort = true;
15080 }
15081 } else {
15082 WL_ERR(("unexpected Escan Event %d : abort\n", status));
15083
15084 if (wl_p2p_find_peer_channel(cfg, status, NULL, 0)) {
15085 goto exit;
15086 }
15087 /* Update escan complete status */
15088 aborted = true;
15089 fw_abort = false;
15090 }
15091
15092 /* Notify escan complete status */
15093 if (notify_escan_complete) {
15094 wl_notify_escan_complete(cfg, ndev, aborted, fw_abort);
15095 }
15096
15097 exit:
15098 return err;
15099
15100 }
15101 #endif /* WL_DRV_AVOID_SCANCACHE */
15102
15103 static s32 wl_escan_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
15104 const wl_event_msg_t *e, void *data)
15105 {
15106 s32 err = BCME_OK;
15107 s32 status = ntoh32(e->status);
15108 wl_escan_result_t *escan_result;
15109 struct net_device *ndev = NULL;
15110 #ifndef WL_DRV_AVOID_SCANCACHE
15111 wl_bss_info_t *bi;
15112 u32 bi_length;
15113 wifi_p2p_ie_t * p2p_ie;
15114 u8 *p2p_dev_addr = NULL;
15115 wl_scan_results_t *list;
15116 wl_bss_info_t *bss = NULL;
15117 u32 i;
15118 #endif /* WL_DRV_AVOID_SCANCACHE */
15119 u16 channel;
15120 struct ieee80211_supported_band *band;
15121
15122 WL_DBG((" enter event type : %d, status : %d \n",
15123 ntoh32(e->event_type), ntoh32(e->status)));
15124
15125 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
15126
15127 mutex_lock(&cfg->usr_sync);
15128 /* P2P SCAN is coming from primary interface */
15129 if (wl_get_p2p_status(cfg, SCANNING)) {
15130 if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
15131 ndev = cfg->afx_hdl->dev;
15132 else
15133 ndev = cfg->escan_info.ndev;
15134
15135 }
15136 if (!ndev || (!wl_get_drv_status(cfg, SCANNING, ndev) && !cfg->sched_scan_running)) {
15137 WL_ERR(("escan is not ready ndev %p drv_status 0x%x e_type %d e_states %d\n",
15138 ndev, wl_get_drv_status(cfg, SCANNING, ndev),
15139 ntoh32(e->event_type), ntoh32(e->status)));
15140 goto exit;
15141 }
15142 escan_result = (wl_escan_result_t *)data;
15143
15144 #ifndef WL_DRV_AVOID_SCANCACHE
15145 if (status == WLC_E_STATUS_PARTIAL) {
15146 WL_INFORM(("WLC_E_STATUS_PARTIAL \n"));
15147 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_RESULT_FOUND);
15148 if (!escan_result) {
15149 WL_ERR(("Invalid escan result (NULL pointer)\n"));
15150 goto exit;
15151 }
15152 if ((dtoh32(escan_result->buflen) > (int)ESCAN_BUF_SIZE) ||
15153 (dtoh32(escan_result->buflen) < sizeof(wl_escan_result_t))) {
15154 WL_ERR(("Invalid escan buffer len:%d\n", dtoh32(escan_result->buflen)));
15155 goto exit;
15156 }
15157 if (dtoh16(escan_result->bss_count) != 1) {
15158 WL_ERR(("Invalid bss_count %d: ignoring\n", escan_result->bss_count));
15159 goto exit;
15160 }
15161 bi = escan_result->bss_info;
15162 if (!bi) {
15163 WL_ERR(("Invalid escan bss info (NULL pointer)\n"));
15164 goto exit;
15165 }
15166 bi_length = dtoh32(bi->length);
15167 if (bi_length != (dtoh32(escan_result->buflen) - WL_ESCAN_RESULTS_FIXED_SIZE)) {
15168 WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length));
15169 goto exit;
15170 }
15171
15172 /* +++++ terence 20130524: skip invalid bss */
15173 channel =
15174 bi->ctl_ch ? bi->ctl_ch : CHSPEC_CHANNEL(wl_chspec_driver_to_host(bi->chanspec));
15175 if (channel <= CH_MAX_2G_CHANNEL)
15176 band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_2GHZ];
15177 else
15178 band = bcmcfg_to_wiphy(cfg)->bands[IEEE80211_BAND_5GHZ];
15179 if (!band) {
15180 WL_ERR(("No valid band\n"));
15181 goto exit;
15182 }
15183 if (!dhd_conf_match_channel(cfg->pub, channel))
15184 goto exit;
15185 /* ----- terence 20130524: skip invalid bss */
15186
15187 if (wl_escan_check_sync_id(status, escan_result->sync_id,
15188 cfg->escan_info.cur_sync_id) < 0)
15189 goto exit;
15190
15191 if (!(bcmcfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) {
15192 if (dtoh16(bi->capability) & DOT11_CAP_IBSS) {
15193 WL_DBG(("Ignoring IBSS result\n"));
15194 goto exit;
15195 }
15196 }
15197
15198 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
15199 p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length);
15200 if (p2p_dev_addr && !memcmp(p2p_dev_addr,
15201 cfg->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) {
15202 s32 channel = wf_chspec_ctlchan(
15203 wl_chspec_driver_to_host(bi->chanspec));
15204
15205 if ((channel > MAXCHANNEL) || (channel <= 0))
15206 channel = WL_INVALID;
15207 else
15208 WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found,"
15209 " channel : %d\n",
15210 MAC2STRDBG(cfg->afx_hdl->tx_dst_addr.octet),
15211 channel));
15212
15213 wl_clr_p2p_status(cfg, SCANNING);
15214 cfg->afx_hdl->peer_chan = channel;
15215 complete(&cfg->act_frm_scan);
15216 goto exit;
15217 }
15218
15219 } else {
15220 int cur_len = WL_SCAN_RESULTS_FIXED_SIZE;
15221 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15222 removal_element_t candidate[BUF_OVERFLOW_MGMT_COUNT];
15223 int remove_lower_rssi = FALSE;
15224
15225 bzero(candidate, sizeof(removal_element_t)*BUF_OVERFLOW_MGMT_COUNT);
15226 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15227
15228 list = wl_escan_get_buf(cfg, FALSE);
15229 if (scan_req_match(cfg)) {
15230 /* p2p scan && allow only probe response */
15231 if ((cfg->p2p->search_state != WL_P2P_DISC_ST_SCAN) &&
15232 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
15233 goto exit;
15234 if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset,
15235 bi->ie_length)) == NULL) {
15236 WL_ERR(("Couldn't find P2PIE in probe"
15237 " response/beacon\n"));
15238 goto exit;
15239 }
15240 }
15241 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15242 if (bi_length > ESCAN_BUF_SIZE - list->buflen)
15243 remove_lower_rssi = TRUE;
15244 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15245
15246 WL_SCAN(("%s("MACDBG") RSSI %d flags 0x%x length %d\n", bi->SSID,
15247 MAC2STRDBG(bi->BSSID.octet), bi->RSSI, bi->flags, bi->length));
15248 for (i = 0; i < list->count; i++) {
15249 bss = bss ? (wl_bss_info_t *)((uintptr)bss + dtoh32(bss->length))
15250 : list->bss_info;
15251 if (!bss) {
15252 WL_ERR(("bss is NULL\n"));
15253 goto exit;
15254 }
15255 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15256 WL_SCAN(("%s("MACDBG"), i=%d bss: RSSI %d list->count %d\n",
15257 bss->SSID, MAC2STRDBG(bss->BSSID.octet),
15258 i, bss->RSSI, list->count));
15259
15260 if (remove_lower_rssi)
15261 wl_cfg80211_find_removal_candidate(bss, candidate);
15262 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15263
15264 if (!bcmp(&bi->BSSID, &bss->BSSID, ETHER_ADDR_LEN) &&
15265 (CHSPEC_BAND(wl_chspec_driver_to_host(bi->chanspec))
15266 == CHSPEC_BAND(wl_chspec_driver_to_host(bss->chanspec))) &&
15267 bi->SSID_len == bss->SSID_len &&
15268 !bcmp(bi->SSID, bss->SSID, bi->SSID_len)) {
15269
15270 /* do not allow beacon data to update
15271 *the data recd from a probe response
15272 */
15273 if (!(bss->flags & WL_BSS_FLAGS_FROM_BEACON) &&
15274 (bi->flags & WL_BSS_FLAGS_FROM_BEACON))
15275 goto exit;
15276
15277 WL_SCAN(("%s("MACDBG"), i=%d prev: RSSI %d"
15278 " flags 0x%x, new: RSSI %d flags 0x%x\n",
15279 bss->SSID, MAC2STRDBG(bi->BSSID.octet), i,
15280 bss->RSSI, bss->flags, bi->RSSI, bi->flags));
15281
15282 if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
15283 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) {
15284 /* preserve max RSSI if the measurements are
15285 * both on-channel or both off-channel
15286 */
15287 WL_SCAN(("%s("MACDBG"), same onchan"
15288 ", RSSI: prev %d new %d\n",
15289 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
15290 bss->RSSI, bi->RSSI));
15291 bi->RSSI = MAX(bss->RSSI, bi->RSSI);
15292 } else if ((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
15293 (bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
15294 /* preserve the on-channel rssi measurement
15295 * if the new measurement is off channel
15296 */
15297 WL_SCAN(("%s("MACDBG"), prev onchan"
15298 ", RSSI: prev %d new %d\n",
15299 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
15300 bss->RSSI, bi->RSSI));
15301 bi->RSSI = bss->RSSI;
15302 bi->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
15303 }
15304 if (dtoh32(bss->length) != bi_length) {
15305 u32 prev_len = dtoh32(bss->length);
15306
15307 WL_SCAN(("bss info replacement"
15308 " is occured(bcast:%d->probresp%d)\n",
15309 bss->ie_length, bi->ie_length));
15310 WL_SCAN(("%s("MACDBG"), replacement!(%d -> %d)\n",
15311 bss->SSID, MAC2STRDBG(bi->BSSID.octet),
15312 prev_len, bi_length));
15313
15314 if (list->buflen - prev_len + bi_length
15315 > ESCAN_BUF_SIZE) {
15316 WL_ERR(("Buffer is too small: keep the"
15317 " previous result of this AP\n"));
15318 /* Only update RSSI */
15319 bss->RSSI = bi->RSSI;
15320 bss->flags |= (bi->flags
15321 & WL_BSS_FLAGS_RSSI_ONCHANNEL);
15322 goto exit;
15323 }
15324
15325 if (i < list->count - 1) {
15326 /* memory copy required by this case only */
15327 memmove((u8 *)bss + bi_length,
15328 (u8 *)bss + prev_len,
15329 list->buflen - cur_len - prev_len);
15330 }
15331 list->buflen -= prev_len;
15332 list->buflen += bi_length;
15333 }
15334 list->version = dtoh32(bi->version);
15335 memcpy((u8 *)bss, (u8 *)bi, bi_length);
15336 goto exit;
15337 }
15338 cur_len += dtoh32(bss->length);
15339 }
15340 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
15341 #ifdef ESCAN_BUF_OVERFLOW_MGMT
15342 wl_cfg80211_remove_lowRSSI_info(list, candidate, bi);
15343 if (bi_length > ESCAN_BUF_SIZE - list->buflen) {
15344 WL_DBG(("RSSI(" MACDBG ") is too low(%d) to add Buffer\n",
15345 MAC2STRDBG(bi->BSSID.octet), bi->RSSI));
15346 goto exit;
15347 }
15348 #else
15349 WL_ERR(("Buffer is too small: ignoring\n"));
15350 goto exit;
15351 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
15352 }
15353
15354 memcpy(&(((char *)list)[list->buflen]), bi, bi_length);
15355 list->version = dtoh32(bi->version);
15356 list->buflen += bi_length;
15357 list->count++;
15358
15359 /*
15360 * !Broadcast && number of ssid = 1 && number of channels =1
15361 * means specific scan to association
15362 */
15363 if (wl_cfgp2p_is_p2p_specific_scan(cfg->scan_request)) {
15364 WL_ERR(("P2P assoc scan fast aborted.\n"));
15365 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, false, true);
15366 goto exit;
15367 }
15368 }
15369 }
15370 else if (status == WLC_E_STATUS_SUCCESS) {
15371 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
15372 wl_escan_print_sync_id(status, cfg->escan_info.cur_sync_id,
15373 escan_result->sync_id);
15374
15375 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
15376 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15377 wl_clr_p2p_status(cfg, SCANNING);
15378 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
15379 if (cfg->afx_hdl->peer_chan == WL_INVALID)
15380 complete(&cfg->act_frm_scan);
15381 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
15382 WL_INFORM(("ESCAN COMPLETED\n"));
15383 DBG_EVENT_LOG((dhd_pub_t *)cfg->pub, WIFI_EVENT_DRIVER_SCAN_COMPLETE);
15384 cfg->bss_list = wl_escan_get_buf(cfg, FALSE);
15385 if (!scan_req_match(cfg)) {
15386 WL_SCAN(("SCAN COMPLETED: scanned AP count=%d\n",
15387 cfg->bss_list->count));
15388 }
15389 wl_inform_bss(cfg);
15390 wl_notify_escan_complete(cfg, ndev, false, false);
15391 }
15392 wl_escan_increment_sync_id(cfg, SCAN_BUF_NEXT);
15393 #ifdef CUSTOMER_HW4_DEBUG
15394 if (wl_scan_timeout_dbg_enabled)
15395 wl_scan_timeout_dbg_clear();
15396 #endif /* CUSTOMER_HW4_DEBUG */
15397 } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
15398 (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
15399 (status == WLC_E_STATUS_NEWASSOC)) {
15400 /* Handle all cases of scan abort */
15401 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
15402 wl_escan_print_sync_id(status, escan_result->sync_id,
15403 cfg->escan_info.cur_sync_id);
15404 WL_DBG(("ESCAN ABORT reason: %d\n", status));
15405 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
15406 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15407 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
15408 wl_clr_p2p_status(cfg, SCANNING);
15409 if (cfg->afx_hdl->peer_chan == WL_INVALID)
15410 complete(&cfg->act_frm_scan);
15411 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
15412 WL_INFORM(("ESCAN ABORTED\n"));
15413 cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
15414 if (!scan_req_match(cfg)) {
15415 WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n",
15416 cfg->bss_list->count));
15417 }
15418 wl_inform_bss(cfg);
15419 wl_notify_escan_complete(cfg, ndev, true, false);
15420 } else {
15421 /* If there is no pending host initiated scan, do nothing */
15422 WL_DBG(("ESCAN ABORT: No pending scans. Ignoring event.\n"));
15423 }
15424 wl_escan_increment_sync_id(cfg, SCAN_BUF_CNT);
15425 } else if (status == WLC_E_STATUS_TIMEOUT) {
15426 WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", cfg->scan_request));
15427 WL_ERR(("reason[0x%x]\n", e->reason));
15428 if (e->reason == 0xFFFFFFFF) {
15429 wl_notify_escan_complete(cfg, cfg->escan_info.ndev, true, true);
15430 }
15431 } else {
15432 WL_ERR(("unexpected Escan Event %d : abort\n", status));
15433 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
15434 wl_escan_print_sync_id(status, escan_result->sync_id,
15435 cfg->escan_info.cur_sync_id);
15436 if (wl_get_drv_status_all(cfg, FINDING_COMMON_CHANNEL)) {
15437 WL_INFORM(("ACTION FRAME SCAN DONE\n"));
15438 wl_clr_p2p_status(cfg, SCANNING);
15439 wl_clr_drv_status(cfg, SCANNING, cfg->afx_hdl->dev);
15440 if (cfg->afx_hdl->peer_chan == WL_INVALID)
15441 complete(&cfg->act_frm_scan);
15442 } else if ((likely(cfg->scan_request)) || (cfg->sched_scan_running)) {
15443 cfg->bss_list = wl_escan_get_buf(cfg, TRUE);
15444 if (!scan_req_match(cfg)) {
15445 WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): "
15446 "scanned AP count=%d\n",
15447 cfg->bss_list->count));
15448 }
15449 wl_inform_bss(cfg);
15450 wl_notify_escan_complete(cfg, ndev, true, false);
15451 }
15452 wl_escan_increment_sync_id(cfg, 2);
15453 }
15454 #else /* WL_DRV_AVOID_SCANCACHE */
15455 err = wl_escan_without_scan_cache(cfg, escan_result, ndev, e, status);
15456 #endif /* WL_DRV_AVOID_SCANCACHE */
15457 exit:
15458 mutex_unlock(&cfg->usr_sync);
15459 return err;
15460 }
15461
15462 static void wl_cfg80211_concurrent_roam(struct bcm_cfg80211 *cfg, int enable)
15463 {
15464 u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
15465 bool p2p_connected = wl_cfgp2p_vif_created(cfg);
15466 struct net_info *iter, *next;
15467
15468 if (!(cfg->roam_flags & WL_ROAM_OFF_ON_CONCURRENT))
15469 return;
15470
15471 WL_DBG(("roam off:%d p2p_connected:%d connected_cnt:%d \n",
15472 enable, p2p_connected, connected_cnt));
15473 /* Disable FW roam when we have a concurrent P2P connection */
15474 if (enable && p2p_connected && connected_cnt > 1) {
15475
15476 /* Mark it as to be reverted */
15477 cfg->roam_flags |= WL_ROAM_REVERT_STATUS;
15478 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15479 4 && __GNUC_MINOR__ >= 6))
15480 _Pragma("GCC diagnostic push")
15481 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15482 #endif
15483 for_each_ndev(cfg, iter, next) {
15484 if (iter->ndev && iter->wdev &&
15485 iter->wdev->iftype == NL80211_IFTYPE_STATION) {
15486 if (wldev_iovar_setint(iter->ndev, "roam_off", TRUE)
15487 == BCME_OK) {
15488 iter->roam_off = TRUE;
15489 }
15490 else {
15491 WL_ERR(("error to enable roam_off\n"));
15492 }
15493 }
15494 }
15495 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15496 4 && __GNUC_MINOR__ >= 6))
15497 _Pragma("GCC diagnostic pop")
15498 #endif
15499 }
15500 else if (!enable && (cfg->roam_flags & WL_ROAM_REVERT_STATUS)) {
15501 cfg->roam_flags &= ~WL_ROAM_REVERT_STATUS;
15502 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15503 4 && __GNUC_MINOR__ >= 6))
15504 _Pragma("GCC diagnostic push")
15505 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15506 #endif
15507 for_each_ndev(cfg, iter, next) {
15508 if (iter->ndev && iter->wdev &&
15509 iter->wdev->iftype == NL80211_IFTYPE_STATION) {
15510 if (iter->roam_off != WL_INVALID) {
15511 if (wldev_iovar_setint(iter->ndev, "roam_off", FALSE)
15512 == BCME_OK) {
15513 iter->roam_off = FALSE;
15514 }
15515 else {
15516 WL_ERR(("error to disable roam_off\n"));
15517 }
15518 }
15519 }
15520 }
15521 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15522 4 && __GNUC_MINOR__ >= 6))
15523 _Pragma("GCC diagnostic pop")
15524 #endif
15525 }
15526
15527 return;
15528 }
15529
15530 static void wl_cfg80211_determine_vsdb_mode(struct bcm_cfg80211 *cfg)
15531 {
15532 struct net_info *iter, *next;
15533 u32 ctl_chan = 0;
15534 u32 chanspec = 0;
15535 u32 pre_ctl_chan = 0;
15536 u32 connected_cnt = wl_get_drv_status_all(cfg, CONNECTED);
15537 cfg->vsdb_mode = false;
15538
15539 if (connected_cnt <= 1) {
15540 return;
15541 }
15542 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15543 4 && __GNUC_MINOR__ >= 6))
15544 _Pragma("GCC diagnostic push")
15545 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
15546 #endif
15547 for_each_ndev(cfg, iter, next) {
15548 /* p2p discovery iface ndev could be null */
15549 if (iter->ndev) {
15550 chanspec = 0;
15551 ctl_chan = 0;
15552 if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
15553 if (wldev_iovar_getint(iter->ndev, "chanspec",
15554 (s32 *)&chanspec) == BCME_OK) {
15555 chanspec = wl_chspec_driver_to_host(chanspec);
15556 ctl_chan = wf_chspec_ctlchan(chanspec);
15557 wl_update_prof(cfg, iter->ndev, NULL,
15558 &ctl_chan, WL_PROF_CHAN);
15559 }
15560 if (!cfg->vsdb_mode) {
15561 if (!pre_ctl_chan && ctl_chan)
15562 pre_ctl_chan = ctl_chan;
15563 else if (pre_ctl_chan && (pre_ctl_chan != ctl_chan)) {
15564 cfg->vsdb_mode = true;
15565 }
15566 }
15567 }
15568 }
15569 }
15570 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
15571 4 && __GNUC_MINOR__ >= 6))
15572 _Pragma("GCC diagnostic pop")
15573 #endif
15574 printf("%s concurrency is enabled\n", cfg->vsdb_mode ? "Multi Channel" : "Same Channel");
15575 return;
15576 }
15577
15578 #if defined(DISABLE_FRAMEBURST_VSDB) && defined(USE_WFA_CERT_CONF)
15579 extern int g_frameburst;
15580 #endif /* DISABLE_FRAMEBURST_VSDB && USE_WFA_CERT_CONF */
15581
15582 static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_net_info,
15583 enum wl_status state, bool set)
15584 {
15585 s32 pm = PM_FAST;
15586 s32 err = BCME_OK;
15587 u32 mode;
15588 u32 chan = 0;
15589 struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
15590 dhd_pub_t *dhd = cfg->pub;
15591 #ifdef RTT_SUPPORT
15592 rtt_status_info_t *rtt_status;
15593 #endif /* RTT_SUPPORT */
15594 if (dhd->busstate == DHD_BUS_DOWN) {
15595 WL_ERR(("%s : busstate is DHD_BUS_DOWN!\n", __FUNCTION__));
15596 return 0;
15597 }
15598 WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n",
15599 state, set, _net_info->pm_restore, _net_info->ndev->name));
15600
15601 if (state != WL_STATUS_CONNECTED)
15602 return 0;
15603 mode = wl_get_mode_by_netdev(cfg, _net_info->ndev);
15604 if (set) {
15605 wl_cfg80211_concurrent_roam(cfg, 1);
15606 wl_cfg80211_determine_vsdb_mode(cfg);
15607 if (mode == WL_MODE_AP) {
15608 if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false))
15609 WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n"));
15610 }
15611 pm = PM_OFF;
15612 if ((err = wldev_ioctl_set(_net_info->ndev, WLC_SET_PM, &pm,
15613 sizeof(pm))) != 0) {
15614 if (err == -ENODEV)
15615 WL_DBG(("%s:netdev not ready\n",
15616 _net_info->ndev->name));
15617 else
15618 WL_ERR(("%s:error (%d)\n",
15619 _net_info->ndev->name, err));
15620
15621 wl_cfg80211_update_power_mode(_net_info->ndev);
15622 }
15623 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_SHORT);
15624
15625 } else { /* clear */
15626 chan = 0;
15627 /* clear chan information when the net device is disconnected */
15628 wl_update_prof(cfg, _net_info->ndev, NULL, &chan, WL_PROF_CHAN);
15629 wl_cfg80211_determine_vsdb_mode(cfg);
15630 if (primary_dev == _net_info->ndev) {
15631 pm = PM_FAST;
15632 #ifdef RTT_SUPPORT
15633 rtt_status = GET_RTTSTATE(dhd);
15634 if (rtt_status->status != RTT_ENABLED) {
15635 #endif /* RTT_SUPPORT */
15636 if (dhd_conf_get_pm(dhd) >= 0)
15637 pm = dhd_conf_get_pm(dhd);
15638 if ((err = wldev_ioctl_set(_net_info->ndev, WLC_SET_PM, &pm,
15639 sizeof(pm))) != 0) {
15640 if (err == -ENODEV)
15641 WL_DBG(("%s:netdev not ready\n",
15642 _net_info->ndev->name));
15643 else
15644 WL_ERR(("%s:error (%d)\n",
15645 _net_info->ndev->name, err));
15646
15647 wl_cfg80211_update_power_mode(_net_info->ndev);
15648 }
15649 #ifdef RTT_SUPPORT
15650 }
15651 #endif /* RTT_SUPPORT */
15652 }
15653 wl_cfg80211_concurrent_roam(cfg, 0);
15654
15655 }
15656 return err;
15657 }
15658
15659 static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
15660 {
15661 int err = 0;
15662
15663 cfg->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler;
15664 cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
15665 wl_escan_init_sync_id(cfg);
15666
15667 /* Init scan_timeout timer */
15668 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
15669 timer_setup(&cfg->scan_timeout, wl_scan_timeout, 0);
15670 #else
15671 init_timer(&cfg->scan_timeout);
15672 cfg->scan_timeout.data = (unsigned long) cfg;
15673 cfg->scan_timeout.function = wl_scan_timeout;
15674 #endif
15675
15676 return err;
15677 }
15678
15679 #ifdef DHD_LOSSLESS_ROAMING
15680 static s32 wl_init_roam_timeout(struct bcm_cfg80211 *cfg)
15681 {
15682 int err = 0;
15683
15684 /* Init roam timer */
15685 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
15686 timer_setup(&cfg->roam_timeout, wl_roam_timeout, 0);
15687 #else
15688 init_timer(&cfg->roam_timeout);
15689 cfg->roam_timeout.data = (unsigned long) cfg;
15690 cfg->roam_timeout.function = wl_roam_timeout;
15691 #endif
15692
15693 return err;
15694 }
15695 #endif /* DHD_LOSSLESS_ROAMING */
15696
15697 static s32 wl_init_priv(struct bcm_cfg80211 *cfg)
15698 {
15699 struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
15700 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
15701 s32 err = 0;
15702
15703 cfg->scan_request = NULL;
15704 cfg->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
15705 #ifdef DISABLE_BUILTIN_ROAM
15706 cfg->roam_on = false;
15707 #else
15708 cfg->roam_on = true;
15709 #endif /* DISABLE_BUILTIN_ROAM */
15710 cfg->active_scan = true;
15711 cfg->rf_blocked = false;
15712 cfg->vsdb_mode = false;
15713 #if defined(BCMSDIO) || defined(BCMDBUS)
15714 cfg->wlfc_on = false;
15715 #endif /* BCMSDIO || BCMDBUS */
15716 cfg->roam_flags |= WL_ROAM_OFF_ON_CONCURRENT;
15717 cfg->disable_roam_event = false;
15718 /* register interested state */
15719 set_bit(WL_STATUS_CONNECTED, &cfg->interrested_state);
15720 spin_lock_init(&cfg->cfgdrv_lock);
15721 mutex_init(&cfg->ioctl_buf_sync);
15722 init_waitqueue_head(&cfg->netif_change_event);
15723 init_waitqueue_head(&cfg->wps_done_event);
15724 init_completion(&cfg->send_af_done);
15725 init_completion(&cfg->iface_disable);
15726 mutex_init(&cfg->usr_sync);
15727 mutex_init(&cfg->event_sync);
15728 mutex_init(&cfg->scan_complete);
15729 mutex_init(&cfg->if_sync);
15730 mutex_init(&cfg->pm_sync);
15731 mutex_init(&cfg->in4way_sync);
15732 #ifdef WLTDLS
15733 mutex_init(&cfg->tdls_sync);
15734 #endif /* WLTDLS */
15735 wl_init_eq(cfg);
15736 err = wl_init_priv_mem(cfg);
15737 if (err)
15738 return err;
15739 if (wl_create_event_handler(cfg))
15740 return -ENOMEM;
15741 wl_init_event_handler(cfg);
15742 err = wl_init_scan(cfg);
15743 if (err)
15744 return err;
15745 #ifdef DHD_LOSSLESS_ROAMING
15746 err = wl_init_roam_timeout(cfg);
15747 if (err) {
15748 return err;
15749 }
15750 #endif /* DHD_LOSSLESS_ROAMING */
15751 wl_init_conf(cfg->conf);
15752 wl_init_prof(cfg, ndev);
15753 wl_link_down(cfg);
15754 DNGL_FUNC(dhd_cfg80211_init, (cfg));
15755 #ifdef NAN_DP
15756 cfg->nan_dp_state = NAN_DP_STATE_DISABLED;
15757 init_waitqueue_head(&cfg->ndp_if_change_event);
15758 #endif /* NAN_DP */
15759 return err;
15760 }
15761
15762 static void wl_deinit_priv(struct bcm_cfg80211 *cfg)
15763 {
15764 DNGL_FUNC(dhd_cfg80211_deinit, (cfg));
15765 wl_destroy_event_handler(cfg);
15766 wl_flush_eq(cfg);
15767 wl_link_down(cfg);
15768 if (cfg->scan_timeout.function)
15769 del_timer_sync(&cfg->scan_timeout);
15770 #ifdef DHD_LOSSLESS_ROAMING
15771 if (cfg->roam_timeout.function)
15772 del_timer_sync(&cfg->roam_timeout);
15773 #endif
15774 wl_deinit_priv_mem(cfg);
15775 if (wl_cfg80211_netdev_notifier_registered) {
15776 wl_cfg80211_netdev_notifier_registered = FALSE;
15777 unregister_netdevice_notifier(&wl_cfg80211_netdev_notifier);
15778 }
15779 }
15780
15781 #if defined(WL_ENABLE_P2P_IF)
15782 static s32 wl_cfg80211_attach_p2p(struct bcm_cfg80211 *cfg)
15783 {
15784 WL_TRACE(("Enter \n"));
15785
15786 if (wl_cfgp2p_register_ndev(cfg) < 0) {
15787 WL_ERR(("P2P attach failed. \n"));
15788 return -ENODEV;
15789 }
15790
15791 return 0;
15792 }
15793
15794 static s32 wl_cfg80211_detach_p2p(struct bcm_cfg80211 *cfg)
15795 {
15796 struct wireless_dev *wdev;
15797
15798 WL_DBG(("Enter \n"));
15799 if (!cfg) {
15800 WL_ERR(("Invalid Ptr\n"));
15801 return -EINVAL;
15802 }
15803 else {
15804 wdev = cfg->p2p_wdev;
15805 if (!wdev) {
15806 WL_ERR(("Invalid Ptr\n"));
15807 return -EINVAL;
15808 }
15809 }
15810
15811 wl_cfgp2p_unregister_ndev(cfg);
15812
15813 cfg->p2p_wdev = NULL;
15814 cfg->p2p_net = NULL;
15815 WL_DBG(("Freeing 0x%p \n", wdev));
15816 kfree(wdev);
15817
15818 return 0;
15819 }
15820 #endif
15821
15822 static s32 wl_cfg80211_attach_post(struct net_device *ndev)
15823 {
15824 struct bcm_cfg80211 * cfg;
15825 s32 err = 0;
15826 s32 ret = 0;
15827 WL_TRACE(("In\n"));
15828 if (unlikely(!ndev)) {
15829 WL_ERR(("ndev is invaild\n"));
15830 return -ENODEV;
15831 }
15832 cfg = wl_get_cfg(ndev);
15833 if (unlikely(!cfg)) {
15834 WL_ERR(("cfg is invaild\n"));
15835 return -EINVAL;
15836 }
15837 if (!wl_get_drv_status(cfg, READY, ndev)) {
15838 if (cfg->wdev) {
15839 ret = wl_cfgp2p_supported(cfg, ndev);
15840 if (ret > 0) {
15841 #if !defined(WL_ENABLE_P2P_IF)
15842 cfg->wdev->wiphy->interface_modes |=
15843 (BIT(NL80211_IFTYPE_P2P_CLIENT)|
15844 BIT(NL80211_IFTYPE_P2P_GO));
15845 #endif /* !WL_ENABLE_P2P_IF */
15846 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
15847 goto fail;
15848
15849 #if defined(WL_ENABLE_P2P_IF)
15850 if (cfg->p2p_net) {
15851 /* Update MAC addr for p2p0 interface here. */
15852 memcpy(cfg->p2p_net->dev_addr, ndev->dev_addr, ETH_ALEN);
15853 cfg->p2p_net->dev_addr[0] |= 0x02;
15854 printf("%s: p2p_dev_addr="MACDBG "\n",
15855 cfg->p2p_net->name,
15856 MAC2STRDBG(cfg->p2p_net->dev_addr));
15857 } else {
15858 WL_ERR(("p2p_net not yet populated."
15859 " Couldn't update the MAC Address for p2p0 \n"));
15860 return -ENODEV;
15861 }
15862 #endif /* WL_ENABLE_P2P_IF */
15863 cfg->p2p_supported = true;
15864 } else if (ret == 0) {
15865 if ((err = wl_cfgp2p_init_priv(cfg)) != 0)
15866 goto fail;
15867 } else {
15868 /* SDIO bus timeout */
15869 err = -ENODEV;
15870 goto fail;
15871 }
15872 }
15873 }
15874 wl_set_drv_status(cfg, READY, ndev);
15875 fail:
15876 return err;
15877 }
15878
15879 struct bcm_cfg80211 *wl_get_cfg(struct net_device *ndev)
15880 {
15881 struct wireless_dev *wdev = ndev->ieee80211_ptr;
15882
15883 if (!wdev || !wdev->wiphy)
15884 return NULL;
15885
15886 return wiphy_priv(wdev->wiphy);
15887 }
15888
15889 s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
15890 {
15891 struct wireless_dev *wdev;
15892 struct bcm_cfg80211 *cfg;
15893 s32 err = 0;
15894 struct device *dev;
15895
15896 WL_TRACE(("In\n"));
15897 if (!ndev) {
15898 WL_ERR(("ndev is invaild\n"));
15899 return -ENODEV;
15900 }
15901 WL_DBG(("func %p\n", wl_cfg80211_get_parent_dev()));
15902 dev = wl_cfg80211_get_parent_dev();
15903
15904 wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
15905 if (unlikely(!wdev)) {
15906 WL_ERR(("Could not allocate wireless device\n"));
15907 return -ENOMEM;
15908 }
15909 err = wl_setup_wiphy(wdev, dev, context);
15910 if (unlikely(err)) {
15911 kfree(wdev);
15912 return -ENOMEM;
15913 }
15914 #ifdef WLMESH
15915 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_MESH);
15916 #else
15917 wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
15918 #endif
15919 cfg = wiphy_priv(wdev->wiphy);
15920 cfg->wdev = wdev;
15921 cfg->pub = context;
15922 INIT_LIST_HEAD(&cfg->net_list);
15923 #ifdef WBTEXT
15924 INIT_LIST_HEAD(&cfg->wbtext_bssid_list);
15925 #endif /* WBTEXT */
15926 INIT_LIST_HEAD(&cfg->vndr_oui_list);
15927 spin_lock_init(&cfg->net_list_sync);
15928 ndev->ieee80211_ptr = wdev;
15929 SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
15930 wdev->netdev = ndev;
15931 cfg->state_notifier = wl_notifier_change_state;
15932 err = wl_init_priv(cfg);
15933 if (err) {
15934 WL_ERR(("Failed to init iwm_priv (%d)\n", err));
15935 goto cfg80211_attach_out;
15936 }
15937 err = wl_alloc_netinfo(cfg, ndev, wdev, wdev->iftype, PM_ENABLE, 0);
15938 if (err) {
15939 WL_ERR(("Failed to alloc net_info (%d)\n", err));
15940 goto cfg80211_attach_out;
15941 }
15942
15943 err = wl_setup_rfkill(cfg, TRUE);
15944 if (err) {
15945 WL_ERR(("Failed to setup rfkill %d\n", err));
15946 goto cfg80211_attach_out;
15947 }
15948 #ifdef DEBUGFS_CFG80211
15949 err = wl_setup_debugfs(cfg);
15950 if (err) {
15951 WL_ERR(("Failed to setup debugfs %d\n", err));
15952 goto cfg80211_attach_out;
15953 }
15954 #endif
15955 if (!wl_cfg80211_netdev_notifier_registered) {
15956 wl_cfg80211_netdev_notifier_registered = TRUE;
15957 err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier);
15958 if (err) {
15959 wl_cfg80211_netdev_notifier_registered = FALSE;
15960 WL_ERR(("Failed to register notifierl %d\n", err));
15961 goto cfg80211_attach_out;
15962 }
15963 }
15964 #if defined(COEX_DHCP)
15965 cfg->btcoex_info = wl_cfg80211_btcoex_init(cfg->wdev->netdev);
15966 if (!cfg->btcoex_info)
15967 goto cfg80211_attach_out;
15968 #endif
15969 #if defined(SUPPORT_RANDOM_MAC_SCAN)
15970 cfg->random_mac_enabled = FALSE;
15971 #endif /* SUPPORT_RANDOM_MAC_SCAN */
15972
15973 #ifdef CONFIG_CFG80211_INTERNAL_REGDB
15974 wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
15975 #endif /* CONFIG_CFG80211_INTERNAL_REGDB */
15976
15977 #if defined(WL_ENABLE_P2P_IF)
15978 err = wl_cfg80211_attach_p2p(cfg);
15979 if (err)
15980 goto cfg80211_attach_out;
15981 #endif
15982
15983 INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
15984
15985 #if defined(STAT_REPORT)
15986 err = wl_attach_stat_report(cfg);
15987 if (err) {
15988 goto cfg80211_attach_out;
15989 }
15990 #endif /* STAT_REPORT */
15991 return err;
15992
15993 cfg80211_attach_out:
15994 wl_cfg80211_detach(cfg);
15995 return err;
15996 }
15997
15998 void wl_cfg80211_detach(struct bcm_cfg80211 *cfg)
15999 {
16000
16001 WL_TRACE(("In\n"));
16002 if (!cfg)
16003 return;
16004
16005 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
16006
16007 #if defined(COEX_DHCP)
16008 wl_cfg80211_btcoex_deinit();
16009 cfg->btcoex_info = NULL;
16010 #endif
16011
16012 wl_setup_rfkill(cfg, FALSE);
16013 #ifdef DEBUGFS_CFG80211
16014 wl_free_debugfs(cfg);
16015 #endif
16016 if (cfg->p2p_supported) {
16017 if (timer_pending(&cfg->p2p->listen_timer))
16018 del_timer_sync(&cfg->p2p->listen_timer);
16019 wl_cfgp2p_deinit_priv(cfg);
16020 }
16021
16022 if (timer_pending(&cfg->scan_timeout))
16023 del_timer_sync(&cfg->scan_timeout);
16024 #ifdef DHD_LOSSLESS_ROAMING
16025 if (timer_pending(&cfg->roam_timeout)) {
16026 del_timer_sync(&cfg->roam_timeout);
16027 }
16028 #endif /* DHD_LOSSLESS_ROAMING */
16029
16030 #if defined(WL_CFG80211_P2P_DEV_IF)
16031 if (cfg->p2p_wdev)
16032 wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
16033 #endif /* WL_CFG80211_P2P_DEV_IF */
16034 #if defined(WL_ENABLE_P2P_IF)
16035 wl_cfg80211_detach_p2p(cfg);
16036 #endif
16037 #if defined(STAT_REPORT)
16038 wl_detach_stat_report(cfg);
16039 #endif /* STAT_REPORT */
16040
16041 wl_cfg80211_ibss_vsie_free(cfg);
16042 wl_cfg80211_clear_mgmt_vndr_ies(cfg);
16043 wl_deinit_priv(cfg);
16044 wl_cfg80211_clear_parent_dev();
16045 #if defined(RSSIAVG)
16046 wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
16047 wl_free_rssi_cache(&cfg->g_connected_rssi_cache_ctrl);
16048 #endif
16049 #if defined(BSSCACHE)
16050 wl_release_bss_cache_ctrl(&cfg->g_bss_cache_ctrl);
16051 #endif
16052 wl_free_wdev(cfg);
16053 /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
16054 * structure "cfg", which is the private part of wiphy, has been freed in
16055 * wl_free_wdev !!!!!!!!!!!
16056 */
16057 }
16058
16059 static void wl_event_handler(struct work_struct *work_data)
16060 {
16061 struct bcm_cfg80211 *cfg = NULL;
16062 struct wl_event_q *e;
16063 struct wireless_dev *wdev = NULL;
16064
16065 BCM_SET_CONTAINER_OF(cfg, work_data, struct bcm_cfg80211, event_work);
16066 DHD_EVENT_WAKE_LOCK(cfg->pub);
16067 while ((e = wl_deq_event(cfg))) {
16068 WL_DBG(("event type (%d), ifidx: %d bssidx: %d \n",
16069 e->etype, e->emsg.ifidx, e->emsg.bsscfgidx));
16070
16071 if (e->emsg.ifidx > WL_MAX_IFS) {
16072 WL_ERR((" Event ifidx not in range. val:%d \n", e->emsg.ifidx));
16073 goto fail;
16074 }
16075
16076 /* Make sure iface operations, don't creat race conditions */
16077 mutex_lock(&cfg->if_sync);
16078 if (!(wdev = wl_get_wdev_by_bssidx(cfg, e->emsg.bsscfgidx))) {
16079 /* For WLC_E_IF would be handled by wl_host_event */
16080 if (e->etype != WLC_E_IF)
16081 WL_ERR(("No wdev corresponding to bssidx: 0x%x found!"
16082 " Ignoring event.\n", e->emsg.bsscfgidx));
16083 } else if (e->etype < WLC_E_LAST && cfg->evt_handler[e->etype]) {
16084 dhd_pub_t *dhd = (struct dhd_pub *)(cfg->pub);
16085 if (dhd->busstate == DHD_BUS_DOWN) {
16086 WL_ERR((": BUS is DOWN.\n"));
16087 } else
16088 cfg->evt_handler[e->etype](cfg, wdev_to_cfgdev(wdev),
16089 &e->emsg, e->edata);
16090 } else {
16091 WL_DBG(("Unknown Event (%d): ignoring\n", e->etype));
16092 }
16093 mutex_unlock(&cfg->if_sync);
16094 fail:
16095 wl_put_event(e);
16096 }
16097 DHD_EVENT_WAKE_UNLOCK(cfg->pub);
16098 }
16099
16100 void
16101 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
16102 {
16103 u32 event_type = ntoh32(e->event_type);
16104 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
16105 struct net_info *netinfo;
16106
16107 WL_DBG(("event_type (%d): %s\n", event_type, bcmevent_get_name(event_type)));
16108
16109 if ((cfg == NULL) || (cfg->p2p_supported && cfg->p2p == NULL)) {
16110 WL_ERR(("Stale event ignored\n"));
16111 return;
16112 }
16113
16114 if (cfg->event_workq == NULL) {
16115 WL_ERR(("Event handler is not created\n"));
16116 return;
16117 }
16118
16119 if (wl_get_p2p_status(cfg, IF_CHANGING) || wl_get_p2p_status(cfg, IF_ADDING)) {
16120 WL_ERR(("during IF change, ignore event %d\n", event_type));
16121 return;
16122 }
16123
16124 netinfo = wl_get_netinfo_by_bssidx(cfg, e->bsscfgidx);
16125 if (!netinfo) {
16126 /* Since the netinfo entry is not there, the netdev entry is not
16127 * created via cfg80211 interface. so the event is not of interest
16128 * to the cfg80211 layer.
16129 */
16130 WL_ERR(("ignore event %d, not interested\n", event_type));
16131 return;
16132 }
16133
16134 if (event_type == WLC_E_PFN_NET_FOUND) {
16135 WL_DBG((" PNOEVENT: PNO_NET_FOUND\n"));
16136 }
16137 else if (event_type == WLC_E_PFN_NET_LOST) {
16138 WL_DBG((" PNOEVENT: PNO_NET_LOST\n"));
16139 }
16140
16141 if (likely(!wl_enq_event(cfg, ndev, event_type, e, data))) {
16142 queue_work(cfg->event_workq, &cfg->event_work);
16143 }
16144 }
16145
16146 static void wl_init_eq(struct bcm_cfg80211 *cfg)
16147 {
16148 wl_init_eq_lock(cfg);
16149 INIT_LIST_HEAD(&cfg->eq_list);
16150 }
16151
16152 static void wl_flush_eq(struct bcm_cfg80211 *cfg)
16153 {
16154 struct wl_event_q *e;
16155 unsigned long flags;
16156
16157 flags = wl_lock_eq(cfg);
16158 while (!list_empty_careful(&cfg->eq_list)) {
16159 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
16160 list_del(&e->eq_list);
16161 kfree(e);
16162 }
16163 wl_unlock_eq(cfg, flags);
16164 }
16165
16166 /*
16167 * retrieve first queued event from head
16168 */
16169
16170 static struct wl_event_q *wl_deq_event(struct bcm_cfg80211 *cfg)
16171 {
16172 struct wl_event_q *e = NULL;
16173 unsigned long flags;
16174
16175 flags = wl_lock_eq(cfg);
16176 if (likely(!list_empty(&cfg->eq_list))) {
16177 BCM_SET_LIST_FIRST_ENTRY(e, &cfg->eq_list, struct wl_event_q, eq_list);
16178 list_del(&e->eq_list);
16179 }
16180 wl_unlock_eq(cfg, flags);
16181
16182 return e;
16183 }
16184
16185 /*
16186 * push event to tail of the queue
16187 */
16188
16189 static s32
16190 wl_enq_event(struct bcm_cfg80211 *cfg, struct net_device *ndev, u32 event,
16191 const wl_event_msg_t *msg, void *data)
16192 {
16193 struct wl_event_q *e;
16194 s32 err = 0;
16195 uint32 evtq_size;
16196 uint32 data_len;
16197 unsigned long flags;
16198 gfp_t aflags;
16199
16200 data_len = 0;
16201 if (data)
16202 data_len = ntoh32(msg->datalen);
16203 evtq_size = sizeof(struct wl_event_q) + data_len;
16204 aflags = (in_atomic()) ? GFP_ATOMIC : GFP_KERNEL;
16205 e = kzalloc(evtq_size, aflags);
16206 if (unlikely(!e)) {
16207 WL_ERR(("event alloc failed\n"));
16208 return -ENOMEM;
16209 }
16210 e->etype = event;
16211 memcpy(&e->emsg, msg, sizeof(wl_event_msg_t));
16212 if (data)
16213 memcpy(e->edata, data, data_len);
16214 flags = wl_lock_eq(cfg);
16215 list_add_tail(&e->eq_list, &cfg->eq_list);
16216 wl_unlock_eq(cfg, flags);
16217
16218 return err;
16219 }
16220
16221 static void wl_put_event(struct wl_event_q *e)
16222 {
16223 kfree(e);
16224 }
16225
16226 static s32 wl_config_ifmode(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 iftype)
16227 {
16228 s32 infra = 0;
16229 s32 err = 0;
16230 s32 mode = 0;
16231 switch (iftype) {
16232 case NL80211_IFTYPE_MONITOR:
16233 case NL80211_IFTYPE_WDS:
16234 WL_ERR(("type (%d) : currently we do not support this mode\n",
16235 iftype));
16236 err = -EINVAL;
16237 return err;
16238 case NL80211_IFTYPE_ADHOC:
16239 mode = WL_MODE_IBSS;
16240 break;
16241 case NL80211_IFTYPE_STATION:
16242 case NL80211_IFTYPE_P2P_CLIENT:
16243 mode = WL_MODE_BSS;
16244 infra = 1;
16245 break;
16246 #ifdef WLMESH
16247 case NL80211_IFTYPE_MESH_POINT:
16248 mode = WL_MODE_MESH;
16249 infra = WL_BSSTYPE_MESH;
16250 break;
16251 #endif /* WLMESH */
16252 case NL80211_IFTYPE_AP:
16253 case NL80211_IFTYPE_P2P_GO:
16254 mode = WL_MODE_AP;
16255 infra = 1;
16256 break;
16257 default:
16258 err = -EINVAL;
16259 WL_ERR(("invalid type (%d)\n", iftype));
16260 return err;
16261 }
16262 infra = htod32(infra);
16263 err = wldev_ioctl_set(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
16264 if (unlikely(err)) {
16265 WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
16266 return err;
16267 }
16268
16269 wl_set_mode_by_netdev(cfg, ndev, mode);
16270
16271 return 0;
16272 }
16273
16274 void wl_cfg80211_add_to_eventbuffer(struct wl_eventmsg_buf *ev, u16 event, bool set)
16275 {
16276 if (!ev || (event > WLC_E_LAST))
16277 return;
16278
16279 if (ev->num < MAX_EVENT_BUF_NUM) {
16280 ev->event[ev->num].type = event;
16281 ev->event[ev->num].set = set;
16282 ev->num++;
16283 } else {
16284 WL_ERR(("evenbuffer doesn't support > %u events. Update"
16285 " the define MAX_EVENT_BUF_NUM \n", MAX_EVENT_BUF_NUM));
16286 ASSERT(0);
16287 }
16288 }
16289
16290 s32 wl_cfg80211_apply_eventbuffer(
16291 struct net_device *ndev,
16292 struct bcm_cfg80211 *cfg,
16293 wl_eventmsg_buf_t *ev)
16294 {
16295 char eventmask[WL_EVENTING_MASK_LEN];
16296 int i, ret = 0;
16297 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
16298
16299 if (!ev || (!ev->num))
16300 return -EINVAL;
16301
16302 mutex_lock(&cfg->event_sync);
16303
16304 /* Read event_msgs mask */
16305 ret = wldev_iovar_getbuf(ndev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL);
16306 if (unlikely(ret)) {
16307 WL_ERR(("Get event_msgs error (%d)\n", ret));
16308 goto exit;
16309 }
16310 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
16311
16312 /* apply the set bits */
16313 for (i = 0; i < ev->num; i++) {
16314 if (ev->event[i].set)
16315 setbit(eventmask, ev->event[i].type);
16316 else
16317 clrbit(eventmask, ev->event[i].type);
16318 }
16319
16320 /* Write updated Event mask */
16321 ret = wldev_iovar_setbuf(ndev, "event_msgs", eventmask, sizeof(eventmask), iovbuf,
16322 sizeof(iovbuf), NULL);
16323 if (unlikely(ret)) {
16324 WL_ERR(("Set event_msgs error (%d)\n", ret));
16325 }
16326
16327 exit:
16328 mutex_unlock(&cfg->event_sync);
16329 return ret;
16330 }
16331
16332 s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
16333 {
16334 s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
16335 s8 eventmask[WL_EVENTING_MASK_LEN];
16336 s32 err = 0;
16337 struct bcm_cfg80211 *cfg;
16338
16339 if (!ndev)
16340 return -ENODEV;
16341
16342 cfg = wl_get_cfg(ndev);
16343 if (!cfg)
16344 return -ENODEV;
16345
16346 mutex_lock(&cfg->event_sync);
16347
16348 /* Setup event_msgs */
16349 err = wldev_iovar_getbuf(ndev, "event_msgs", NULL, 0, iovbuf, sizeof(iovbuf), NULL);
16350 if (unlikely(err)) {
16351 WL_ERR(("Get event_msgs error (%d)\n", err));
16352 goto eventmsg_out;
16353 }
16354 memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
16355 if (add) {
16356 setbit(eventmask, event);
16357 } else {
16358 clrbit(eventmask, event);
16359 }
16360 err = wldev_iovar_setbuf(ndev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
16361 sizeof(iovbuf), NULL);
16362 if (unlikely(err)) {
16363 WL_ERR(("Set event_msgs error (%d)\n", err));
16364 goto eventmsg_out;
16365 }
16366
16367 eventmsg_out:
16368 mutex_unlock(&cfg->event_sync);
16369 return err;
16370 }
16371
16372 static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap)
16373 {
16374 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
16375 struct ieee80211_channel *band_chan_arr = NULL;
16376 wl_uint32_list_t *list;
16377 u32 i, j, index, n_2g, n_5g, band, channel, array_size;
16378 u32 *n_cnt = NULL;
16379 chanspec_t c = 0;
16380 s32 err = BCME_OK;
16381 bool update;
16382 bool ht40_allowed;
16383 u8 *pbuf = NULL;
16384 bool dfs_radar_disabled = FALSE;
16385
16386 #define LOCAL_BUF_LEN 1024
16387 pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL);
16388
16389 if (pbuf == NULL) {
16390 WL_ERR(("failed to allocate local buf\n"));
16391 return -ENOMEM;
16392 }
16393
16394 err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
16395 0, pbuf, LOCAL_BUF_LEN, 0, &cfg->ioctl_buf_sync);
16396 if (err != 0) {
16397 WL_ERR(("get chanspecs failed with %d\n", err));
16398 kfree(pbuf);
16399 return err;
16400 }
16401 #undef LOCAL_BUF_LEN
16402
16403 list = (wl_uint32_list_t *)(void *)pbuf;
16404 band = array_size = n_2g = n_5g = 0;
16405 for (i = 0; i < dtoh32(list->count); i++) {
16406 index = 0;
16407 update = false;
16408 ht40_allowed = false;
16409 c = (chanspec_t)dtoh32(list->element[i]);
16410 c = wl_chspec_driver_to_host(c);
16411 channel = wf_chspec_ctlchan(c);
16412
16413 if (!CHSPEC_IS40(c) && ! CHSPEC_IS20(c)) {
16414 WL_DBG(("HT80/160/80p80 center channel : %d\n", channel));
16415 continue;
16416 }
16417 if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) &&
16418 (channel <= CH_MAX_2G_CHANNEL)) {
16419 band_chan_arr = __wl_2ghz_channels;
16420 array_size = ARRAYSIZE(__wl_2ghz_channels);
16421 n_cnt = &n_2g;
16422 band = IEEE80211_BAND_2GHZ;
16423 ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false;
16424 } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) {
16425 band_chan_arr = __wl_5ghz_a_channels;
16426 array_size = ARRAYSIZE(__wl_5ghz_a_channels);
16427 n_cnt = &n_5g;
16428 band = IEEE80211_BAND_5GHZ;
16429 ht40_allowed = (bw_cap == WLC_N_BW_20ALL)? false : true;
16430 } else {
16431 WL_ERR(("Invalid channel Sepc. 0x%x.\n", c));
16432 continue;
16433 }
16434 if (!ht40_allowed && CHSPEC_IS40(c))
16435 continue;
16436 for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
16437 if (band_chan_arr[j].hw_value == channel) {
16438 update = true;
16439 break;
16440 }
16441 }
16442 if (update)
16443 index = j;
16444 else
16445 index = *n_cnt;
16446 if (!dhd_conf_match_channel(cfg->pub, channel))
16447 continue;
16448 if (index < array_size) {
16449 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
16450 band_chan_arr[index].center_freq =
16451 ieee80211_channel_to_frequency(channel);
16452 #else
16453 band_chan_arr[index].center_freq =
16454 ieee80211_channel_to_frequency(channel, band);
16455 #endif
16456 band_chan_arr[index].hw_value = channel;
16457 band_chan_arr[index].beacon_found = false;
16458
16459 if (CHSPEC_IS40(c) && ht40_allowed) {
16460 /* assuming the order is HT20, HT40 Upper,
16461 * HT40 lower from chanspecs
16462 */
16463 u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40;
16464 if (CHSPEC_SB_UPPER(c)) {
16465 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
16466 band_chan_arr[index].flags &=
16467 ~IEEE80211_CHAN_NO_HT40;
16468 band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS;
16469 } else {
16470 /* It should be one of
16471 * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS
16472 */
16473 band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40;
16474 if (ht40_flag == IEEE80211_CHAN_NO_HT40)
16475 band_chan_arr[index].flags |=
16476 IEEE80211_CHAN_NO_HT40MINUS;
16477 }
16478 } else {
16479 band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40;
16480 if (!dfs_radar_disabled) {
16481 if (band == IEEE80211_BAND_2GHZ)
16482 channel |= WL_CHANSPEC_BAND_2G;
16483 else
16484 channel |= WL_CHANSPEC_BAND_5G;
16485 channel |= WL_CHANSPEC_BW_20;
16486 channel = wl_chspec_host_to_driver(channel);
16487 err = wldev_iovar_getint(dev, "per_chan_info", &channel);
16488 if (!err) {
16489 if (channel & WL_CHAN_RADAR) {
16490 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
16491 band_chan_arr[index].flags |=
16492 (IEEE80211_CHAN_RADAR
16493 | IEEE80211_CHAN_NO_IBSS);
16494 #else
16495 band_chan_arr[index].flags |=
16496 IEEE80211_CHAN_RADAR;
16497 #endif
16498 }
16499
16500 if (channel & WL_CHAN_PASSIVE)
16501 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
16502 band_chan_arr[index].flags |=
16503 IEEE80211_CHAN_PASSIVE_SCAN;
16504 #else
16505 band_chan_arr[index].flags |=
16506 IEEE80211_CHAN_NO_IR;
16507 #endif
16508 } else if (err == BCME_UNSUPPORTED) {
16509 dfs_radar_disabled = TRUE;
16510 WL_ERR(("does not support per_chan_info\n"));
16511 }
16512 }
16513 }
16514 if (!update)
16515 (*n_cnt)++;
16516 }
16517
16518 }
16519 __wl_band_2ghz.n_channels = n_2g;
16520 __wl_band_5ghz_a.n_channels = n_5g;
16521 kfree(pbuf);
16522 return err;
16523 }
16524
16525 static s32 __wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
16526 {
16527 struct wiphy *wiphy;
16528 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
16529 u32 bandlist[3];
16530 u32 nband = 0;
16531 u32 i = 0;
16532 s32 err = 0;
16533 s32 index = 0;
16534 s32 nmode = 0;
16535 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16536 u32 j = 0;
16537 s32 vhtmode = 0;
16538 s32 txstreams = 0;
16539 s32 rxstreams = 0;
16540 s32 ldpc_cap = 0;
16541 s32 stbc_rx = 0;
16542 s32 stbc_tx = 0;
16543 s32 txbf_bfe_cap = 0;
16544 s32 txbf_bfr_cap = 0;
16545 #endif
16546 s32 bw_cap = 0;
16547 s32 cur_band = -1;
16548 struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, };
16549
16550 memset(bandlist, 0, sizeof(bandlist));
16551 err = wldev_ioctl_get(dev, WLC_GET_BANDLIST, bandlist,
16552 sizeof(bandlist));
16553 if (unlikely(err)) {
16554 WL_ERR(("error read bandlist (%d)\n", err));
16555 return err;
16556 }
16557 err = wldev_ioctl_get(dev, WLC_GET_BAND, &cur_band,
16558 sizeof(s32));
16559 if (unlikely(err)) {
16560 WL_ERR(("error (%d)\n", err));
16561 return err;
16562 }
16563
16564 err = wldev_iovar_getint(dev, "nmode", &nmode);
16565 if (unlikely(err)) {
16566 WL_ERR(("error reading nmode (%d)\n", err));
16567 }
16568
16569 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16570 err = wldev_iovar_getint(dev, "vhtmode", &vhtmode);
16571 if (unlikely(err)) {
16572 WL_ERR(("error reading vhtmode (%d)\n", err));
16573 }
16574
16575 if (vhtmode) {
16576 err = wldev_iovar_getint(dev, "txstreams", &txstreams);
16577 if (unlikely(err)) {
16578 WL_ERR(("error reading txstreams (%d)\n", err));
16579 }
16580
16581 err = wldev_iovar_getint(dev, "rxstreams", &rxstreams);
16582 if (unlikely(err)) {
16583 WL_ERR(("error reading rxstreams (%d)\n", err));
16584 }
16585
16586 err = wldev_iovar_getint(dev, "ldpc_cap", &ldpc_cap);
16587 if (unlikely(err)) {
16588 WL_ERR(("error reading ldpc_cap (%d)\n", err));
16589 }
16590
16591 err = wldev_iovar_getint(dev, "stbc_rx", &stbc_rx);
16592 if (unlikely(err)) {
16593 WL_ERR(("error reading stbc_rx (%d)\n", err));
16594 }
16595
16596 err = wldev_iovar_getint(dev, "stbc_tx", &stbc_tx);
16597 if (unlikely(err)) {
16598 WL_ERR(("error reading stbc_tx (%d)\n", err));
16599 }
16600
16601 err = wldev_iovar_getint(dev, "txbf_bfe_cap", &txbf_bfe_cap);
16602 if (unlikely(err)) {
16603 WL_ERR(("error reading txbf_bfe_cap (%d)\n", err));
16604 }
16605
16606 err = wldev_iovar_getint(dev, "txbf_bfr_cap", &txbf_bfr_cap);
16607 if (unlikely(err)) {
16608 WL_ERR(("error reading txbf_bfr_cap (%d)\n", err));
16609 }
16610 }
16611 #endif
16612
16613 /* For nmode and vhtmode check bw cap */
16614 if (nmode ||
16615 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16616 vhtmode ||
16617 #endif
16618 0) {
16619 err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
16620 if (unlikely(err)) {
16621 WL_ERR(("error get mimo_bw_cap (%d)\n", err));
16622 }
16623 }
16624
16625 err = wl_construct_reginfo(cfg, bw_cap);
16626 if (err) {
16627 WL_ERR(("wl_construct_reginfo() fails err=%d\n", err));
16628 if (err != BCME_UNSUPPORTED)
16629 return err;
16630 }
16631
16632 wiphy = bcmcfg_to_wiphy(cfg);
16633 nband = bandlist[0];
16634
16635 for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) {
16636 index = -1;
16637 if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) {
16638 bands[IEEE80211_BAND_5GHZ] =
16639 &__wl_band_5ghz_a;
16640 index = IEEE80211_BAND_5GHZ;
16641 if (nmode && (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G))
16642 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
16643
16644 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
16645 /* VHT capabilities. */
16646 if (vhtmode) {
16647 /* Supported */
16648 bands[index]->vht_cap.vht_supported = TRUE;
16649
16650 for (j = 1; j <= VHT_CAP_MCS_MAP_NSS_MAX; j++) {
16651 /* TX stream rates. */
16652 if (j <= txstreams) {
16653 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
16654 bands[index]->vht_cap.vht_mcs.tx_mcs_map);
16655 } else {
16656 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
16657 bands[index]->vht_cap.vht_mcs.tx_mcs_map);
16658 }
16659
16660 /* RX stream rates. */
16661 if (j <= rxstreams) {
16662 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_0_9,
16663 bands[index]->vht_cap.vht_mcs.rx_mcs_map);
16664 } else {
16665 VHT_MCS_MAP_SET_MCS_PER_SS(j, VHT_CAP_MCS_MAP_NONE,
16666 bands[index]->vht_cap.vht_mcs.rx_mcs_map);
16667 }
16668 }
16669
16670
16671 /* Capabilities */
16672 /* 80 MHz is mandatory */
16673 bands[index]->vht_cap.cap |=
16674 IEEE80211_VHT_CAP_SHORT_GI_80;
16675
16676 if (WL_BW_CAP_160MHZ(bw_cap)) {
16677 bands[index]->vht_cap.cap |=
16678 IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
16679 bands[index]->vht_cap.cap |=
16680 IEEE80211_VHT_CAP_SHORT_GI_160;
16681 }
16682
16683 bands[index]->vht_cap.cap |=
16684 IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454;
16685
16686 if (ldpc_cap)
16687 bands[index]->vht_cap.cap |=
16688 IEEE80211_VHT_CAP_RXLDPC;
16689
16690 if (stbc_tx)
16691 bands[index]->vht_cap.cap |=
16692 IEEE80211_VHT_CAP_TXSTBC;
16693
16694 if (stbc_rx)
16695 bands[index]->vht_cap.cap |=
16696 (stbc_rx << VHT_CAP_INFO_RX_STBC_SHIFT);
16697
16698 if (txbf_bfe_cap)
16699 bands[index]->vht_cap.cap |=
16700 IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE;
16701
16702 if (txbf_bfr_cap) {
16703 bands[index]->vht_cap.cap |=
16704 IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE;
16705 }
16706
16707 if (txbf_bfe_cap || txbf_bfr_cap) {
16708 bands[index]->vht_cap.cap |=
16709 (2 << VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT);
16710 bands[index]->vht_cap.cap |=
16711 ((txstreams - 1) <<
16712 VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT);
16713 bands[index]->vht_cap.cap |=
16714 IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB;
16715 }
16716
16717 /* AMPDU length limit, support max 1MB (2 ^ (13 + 7)) */
16718 bands[index]->vht_cap.cap |=
16719 (7 << VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT);
16720 WL_INFORM(("%s band[%d] vht_enab=%d vht_cap=%08x "
16721 "vht_rx_mcs_map=%04x vht_tx_mcs_map=%04x\n",
16722 __FUNCTION__, index,
16723 bands[index]->vht_cap.vht_supported,
16724 bands[index]->vht_cap.cap,
16725 bands[index]->vht_cap.vht_mcs.rx_mcs_map,
16726 bands[index]->vht_cap.vht_mcs.tx_mcs_map));
16727 }
16728 #endif
16729 }
16730 else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) {
16731 bands[IEEE80211_BAND_2GHZ] =
16732 &__wl_band_2ghz;
16733 index = IEEE80211_BAND_2GHZ;
16734 if (bw_cap == WLC_N_BW_40ALL)
16735 bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
16736 }
16737
16738 if ((index >= 0) && nmode) {
16739 bands[index]->ht_cap.cap |=
16740 (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40);
16741 bands[index]->ht_cap.ht_supported = TRUE;
16742 bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
16743 bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
16744 /* An HT shall support all EQM rates for one spatial stream */
16745 bands[index]->ht_cap.mcs.rx_mask[0] = 0xff;
16746 }
16747
16748 }
16749
16750 wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ];
16751 wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ];
16752
16753 /* check if any bands populated otherwise makes 2Ghz as default */
16754 if (wiphy->bands[IEEE80211_BAND_2GHZ] == NULL &&
16755 wiphy->bands[IEEE80211_BAND_5GHZ] == NULL) {
16756 /* Setup 2Ghz band as default */
16757 wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
16758 }
16759
16760 if (notify)
16761 wiphy_apply_custom_regulatory(wiphy, &brcm_regdom);
16762
16763 return 0;
16764 }
16765
16766 s32 wl_update_wiphybands(struct bcm_cfg80211 *cfg, bool notify)
16767 {
16768 s32 err;
16769
16770 mutex_lock(&cfg->usr_sync);
16771 err = __wl_update_wiphybands(cfg, notify);
16772 mutex_unlock(&cfg->usr_sync);
16773
16774 return err;
16775 }
16776
16777 static s32 __wl_cfg80211_up(struct bcm_cfg80211 *cfg)
16778 {
16779 s32 err = 0;
16780 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
16781 struct wireless_dev *wdev = ndev->ieee80211_ptr;
16782 #ifdef WBTEXT
16783 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
16784 #endif /* WBTEXT */
16785 #ifdef WLTDLS
16786 u32 tdls;
16787 #endif /* WLTDLS */
16788
16789 WL_DBG(("In\n"));
16790
16791 if (!dhd_download_fw_on_driverload) {
16792 err = wl_create_event_handler(cfg);
16793 if (err) {
16794 WL_ERR(("wl_create_event_handler failed\n"));
16795 return err;
16796 }
16797 wl_init_event_handler(cfg);
16798 }
16799
16800 err = dhd_config_dongle(cfg);
16801 if (unlikely(err))
16802 return err;
16803
16804 err = wl_config_ifmode(cfg, ndev, wdev->iftype);
16805 if (unlikely(err && err != -EINPROGRESS)) {
16806 WL_ERR(("wl_config_ifmode failed\n"));
16807 if (err == -1) {
16808 WL_ERR(("return error %d\n", err));
16809 return err;
16810 }
16811 }
16812
16813 err = wl_init_scan(cfg);
16814 if (err) {
16815 WL_ERR(("wl_init_scan failed\n"));
16816 return err;
16817 }
16818 err = __wl_update_wiphybands(cfg, true);
16819 if (unlikely(err)) {
16820 WL_ERR(("wl_update_wiphybands failed\n"));
16821 if (err == -1) {
16822 WL_ERR(("return error %d\n", err));
16823 return err;
16824 }
16825 }
16826
16827 #ifdef DHD_LOSSLESS_ROAMING
16828 if (timer_pending(&cfg->roam_timeout)) {
16829 del_timer_sync(&cfg->roam_timeout);
16830 }
16831 #endif /* DHD_LOSSLESS_ROAMING */
16832
16833 err = dhd_monitor_init(cfg->pub);
16834
16835 #ifdef WBTEXT
16836 /* when wifi up, set roam_prof to default value */
16837 if (dhd->wbtext_support) {
16838 if (dhd->op_mode & DHD_FLAG_STA_MODE) {
16839 wl_cfg80211_wbtext_set_default(ndev);
16840 wl_cfg80211_wbtext_clear_bssid_list(cfg);
16841 }
16842 }
16843 #endif /* WBTEXT */
16844 #ifdef WLTDLS
16845 if (wldev_iovar_getint(ndev, "tdls_enable", &tdls) == 0) {
16846 WL_DBG(("TDLS supported in fw\n"));
16847 cfg->tdls_supported = true;
16848 }
16849 #endif /* WLTDLS */
16850 INIT_DELAYED_WORK(&cfg->pm_enable_work, wl_cfg80211_work_handler);
16851 wl_set_drv_status(cfg, READY, ndev);
16852 return err;
16853 }
16854
16855 static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
16856 {
16857 s32 err = 0;
16858 unsigned long flags;
16859 struct net_info *iter, *next;
16860 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
16861 #if defined(WL_CFG80211) && (defined(WL_ENABLE_P2P_IF) || \
16862 defined(WL_NEW_CFG_PRIVCMD_SUPPORT)) && !defined(PLATFORM_SLP)
16863 struct net_device *p2p_net = cfg->p2p_net;
16864 #endif
16865 #ifdef PROP_TXSTATUS_VSDB
16866 #if defined(BCMSDIO) || defined(BCMDBUS)
16867 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
16868 #endif /* BCMSDIO || BCMDBUS */
16869 #endif /* PROP_TXSTATUS_VSDB */
16870 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
16871 struct cfg80211_scan_info info;
16872 #endif
16873
16874 WL_DBG(("In\n"));
16875
16876 /* Check if cfg80211 interface is already down */
16877 if (!wl_get_drv_status(cfg, READY, ndev)) {
16878 WL_DBG(("cfg80211 interface is already down\n"));
16879 return err; /* it is even not ready */
16880 }
16881
16882 #ifdef WLTDLS
16883 cfg->tdls_supported = false;
16884 #endif /* WLTDLS */
16885
16886 /* Delete pm_enable_work */
16887 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
16888
16889 /* clear all the security setting on primary Interface */
16890 wl_cfg80211_clear_security(cfg);
16891
16892
16893 if (cfg->p2p_supported) {
16894 wl_clr_p2p_status(cfg, GO_NEG_PHASE);
16895 #ifdef PROP_TXSTATUS_VSDB
16896 #if defined(BCMSDIO) || defined(BCMDBUS)
16897 if (wl_cfgp2p_vif_created(cfg)) {
16898 bool enabled = false;
16899 dhd_wlfc_get_enable(dhd, &enabled);
16900 if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
16901 dhd->op_mode != DHD_FLAG_IBSS_MODE) {
16902 dhd_wlfc_deinit(dhd);
16903 cfg->wlfc_on = false;
16904 }
16905 }
16906 #endif /* BCMSDIO || BCMDBUS */
16907 #endif /* PROP_TXSTATUS_VSDB */
16908 }
16909
16910
16911 /* clean up any left over interfaces */
16912 wl_cfg80211_cleanup_virtual_ifaces(ndev, false);
16913
16914 /* If primary BSS is operational (for e.g SoftAP), bring it down */
16915 if (wl_cfg80211_bss_isup(ndev, 0)) {
16916 if (wl_cfg80211_bss_up(cfg, ndev, 0, 0) < 0)
16917 WL_ERR(("BSS down failed \n"));
16918 }
16919
16920 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16921 4 && __GNUC_MINOR__ >= 6))
16922 _Pragma("GCC diagnostic push")
16923 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16924 #endif
16925 for_each_ndev(cfg, iter, next) {
16926 if (iter->ndev) /* p2p discovery iface is null */
16927 wl_set_drv_status(cfg, SCAN_ABORTING, iter->ndev);
16928 }
16929 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16930 4 && __GNUC_MINOR__ >= 6))
16931 _Pragma("GCC diagnostic pop")
16932 #endif
16933
16934 #ifdef P2P_LISTEN_OFFLOADING
16935 wl_cfg80211_p2plo_deinit(cfg);
16936 #endif /* P2P_LISTEN_OFFLOADING */
16937
16938 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
16939 if (cfg->scan_request) {
16940 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
16941 info.aborted = true;
16942 cfg80211_scan_done(cfg->scan_request, &info);
16943 #else
16944 cfg80211_scan_done(cfg->scan_request, true);
16945 #endif
16946 cfg->scan_request = NULL;
16947 }
16948 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
16949 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16950 4 && __GNUC_MINOR__ >= 6))
16951 _Pragma("GCC diagnostic push")
16952 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
16953 #endif
16954 for_each_ndev(cfg, iter, next) {
16955 /* p2p discovery iface ndev ptr could be null */
16956 if (iter->ndev == NULL)
16957 continue;
16958 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0))
16959 if (wl_get_drv_status(cfg, CONNECTED, iter->ndev)) {
16960 CFG80211_DISCONNECTED(iter->ndev, 0, NULL, 0, false, GFP_KERNEL);
16961 }
16962 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)) */
16963 wl_clr_drv_status(cfg, READY, iter->ndev);
16964 wl_clr_drv_status(cfg, SCANNING, iter->ndev);
16965 wl_clr_drv_status(cfg, SCAN_ABORTING, iter->ndev);
16966 wl_clr_drv_status(cfg, CONNECTING, iter->ndev);
16967 wl_clr_drv_status(cfg, CONNECTED, iter->ndev);
16968 wl_clr_drv_status(cfg, DISCONNECTING, iter->ndev);
16969 wl_clr_drv_status(cfg, AP_CREATED, iter->ndev);
16970 wl_clr_drv_status(cfg, AP_CREATING, iter->ndev);
16971 }
16972 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
16973 4 && __GNUC_MINOR__ >= 6))
16974 _Pragma("GCC diagnostic pop")
16975 #endif
16976 bcmcfg_to_prmry_ndev(cfg)->ieee80211_ptr->iftype =
16977 NL80211_IFTYPE_STATION;
16978 #if defined(WL_CFG80211) && (defined(WL_ENABLE_P2P_IF) || \
16979 defined(WL_NEW_CFG_PRIVCMD_SUPPORT)) && !defined(PLATFORM_SLP)
16980 if (p2p_net)
16981 dev_close(p2p_net);
16982 #endif
16983
16984 /* Avoid deadlock from wl_cfg80211_down */
16985 if (!dhd_download_fw_on_driverload) {
16986 mutex_unlock(&cfg->usr_sync);
16987 wl_destroy_event_handler(cfg);
16988 mutex_lock(&cfg->usr_sync);
16989 }
16990
16991 wl_flush_eq(cfg);
16992 if (cfg->link_up) { //army fix wifi stop call trace issue
16993 CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
16994 wl_link_down(cfg);
16995 }
16996 if (cfg->p2p_supported) {
16997 if (timer_pending(&cfg->p2p->listen_timer))
16998 del_timer_sync(&cfg->p2p->listen_timer);
16999 wl_cfgp2p_down(cfg);
17000 }
17001
17002 if (timer_pending(&cfg->scan_timeout)) {
17003 del_timer_sync(&cfg->scan_timeout);
17004 }
17005
17006 DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
17007
17008 dhd_monitor_uninit();
17009 #ifdef WLAIBSS_MCHAN
17010 bcm_cfg80211_del_ibss_if(cfg->wdev->wiphy, cfg->ibss_cfgdev);
17011 #endif /* WLAIBSS_MCHAN */
17012
17013
17014 #ifdef WL11U
17015 /* Clear interworking element. */
17016 if (cfg->wl11u) {
17017 cfg->wl11u = FALSE;
17018 }
17019 #endif /* WL11U */
17020
17021 #ifdef CUSTOMER_HW4_DEBUG
17022 if (wl_scan_timeout_dbg_enabled) {
17023 wl_scan_timeout_dbg_clear();
17024 }
17025 #endif /* CUSTOMER_HW4_DEBUG */
17026
17027 cfg->disable_roam_event = false;
17028
17029 DNGL_FUNC(dhd_cfg80211_down, (cfg));
17030
17031 #ifdef DHD_IFDEBUG
17032 /* Printout all netinfo entries */
17033 wl_probe_wdev_all(cfg);
17034 #endif /* DHD_IFDEBUG */
17035
17036 return err;
17037 }
17038
17039 s32 wl_cfg80211_up(struct net_device *net)
17040 {
17041 struct bcm_cfg80211 *cfg;
17042 s32 err = 0;
17043 int val = 1;
17044 dhd_pub_t *dhd;
17045 #ifdef DISABLE_PM_BCNRX
17046 s32 interr = 0;
17047 uint param = 0;
17048 s8 iovbuf[WLC_IOCTL_SMLEN];
17049 #endif /* DISABLE_PM_BCNRX */
17050
17051 WL_DBG(("In\n"));
17052 cfg = wl_get_cfg(net);
17053
17054 if ((err = wldev_ioctl_get(bcmcfg_to_prmry_ndev(cfg), WLC_GET_VERSION, &val,
17055 sizeof(int)) < 0)) {
17056 WL_ERR(("WLC_GET_VERSION failed, err=%d\n", err));
17057 return err;
17058 }
17059 val = dtoh32(val);
17060 if (val != WLC_IOCTL_VERSION && val != 1) {
17061 WL_ERR(("Version mismatch, please upgrade. Got %d, expected %d or 1\n",
17062 val, WLC_IOCTL_VERSION));
17063 return BCME_VERSION;
17064 }
17065 ioctl_version = val;
17066 wl_cfg80211_check_in4way(cfg, net, NO_SCAN_IN4WAY|NO_BTC_IN4WAY,
17067 WL_EXT_STATUS_DISCONNECTED, NULL);
17068 WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
17069
17070 mutex_lock(&cfg->usr_sync);
17071 dhd = (dhd_pub_t *)(cfg->pub);
17072 if (!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
17073 err = wl_cfg80211_attach_post(bcmcfg_to_prmry_ndev(cfg));
17074 if (unlikely(err)) {
17075 mutex_unlock(&cfg->usr_sync);
17076 return err;
17077 }
17078 }
17079 #ifdef WLMESH
17080 cfg->wdev->wiphy->features |= NL80211_FEATURE_USERSPACE_MPM;
17081 #endif /* WLMESH */
17082
17083 err = __wl_cfg80211_up(cfg);
17084 if (unlikely(err))
17085 WL_ERR(("__wl_cfg80211_up failed\n"));
17086
17087
17088
17089 /* IOVAR configurations with 'up' condition */
17090 #ifdef DISABLE_PM_BCNRX
17091 interr = wldev_iovar_setbuf(bcmcfg_to_prmry_ndev(cfg), "pm_bcnrx", (char *)&param,
17092 sizeof(param), iovbuf, sizeof(iovbuf), NULL);
17093 if (unlikely(interr)) {
17094 WL_ERR(("Set pm_bcnrx returned (%d)\n", interr));
17095 }
17096 #endif /* DISABLE_PM_BCNRX */
17097
17098 mutex_unlock(&cfg->usr_sync);
17099
17100 #ifdef WLAIBSS_MCHAN
17101 bcm_cfg80211_add_ibss_if(cfg->wdev->wiphy, IBSS_IF_NAME);
17102 #endif /* WLAIBSS_MCHAN */
17103
17104 #ifdef DUAL_STA_STATIC_IF
17105 #ifdef WL_VIRTUAL_APSTA
17106 #error "Both DUAL STA and DUAL_STA_STATIC_IF can't be enabled together"
17107 #endif
17108 /* Static Interface support is currently supported only for STA only builds (without P2P) */
17109 wl_cfg80211_create_iface(cfg->wdev->wiphy, NL80211_IFTYPE_STATION, NULL, "wlan%d");
17110 #endif /* DUAL_STA_STATIC_IF */
17111
17112 return err;
17113 }
17114
17115 /* Private Event to Supplicant with indication that chip hangs */
17116 int wl_cfg80211_hang(struct net_device *dev, u16 reason)
17117 {
17118 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
17119 dhd_pub_t *dhd;
17120 #if defined(SOFTAP_SEND_HANGEVT)
17121 /* specifc mac address used for hang event */
17122 uint8 hang_mac[ETHER_ADDR_LEN] = {0x11, 0x11, 0x11, 0x11, 0x11, 0x11};
17123 #endif /* SOFTAP_SEND_HANGEVT */
17124 if (!cfg) {
17125 return BCME_ERROR;
17126 }
17127
17128 dhd = (dhd_pub_t *)(cfg->pub);
17129 #if defined(DHD_HANG_SEND_UP_TEST)
17130 if (dhd->req_hang_type) {
17131 WL_ERR(("%s, Clear HANG test request 0x%x\n",
17132 __FUNCTION__, dhd->req_hang_type));
17133 dhd->req_hang_type = 0;
17134 }
17135 #endif /* DHD_HANG_SEND_UP_TEST */
17136 if ((dhd->hang_reason <= HANG_REASON_MASK) || (dhd->hang_reason >= HANG_REASON_MAX)) {
17137 WL_ERR(("%s, Invalid hang reason 0x%x\n",
17138 __FUNCTION__, dhd->hang_reason));
17139 dhd->hang_reason = HANG_REASON_UNKNOWN;
17140 }
17141 #ifdef DHD_USE_EXTENDED_HANG_REASON
17142 if (dhd->hang_reason != 0) {
17143 reason = dhd->hang_reason;
17144 }
17145 #endif /* DHD_USE_EXTENDED_HANG_REASON */
17146 WL_ERR(("In : chip crash eventing, reason=0x%x\n", (uint32)(dhd->hang_reason)));
17147
17148 wl_add_remove_pm_enable_work(cfg, WL_PM_WORKQ_DEL);
17149 #ifdef SOFTAP_SEND_HANGEVT
17150 if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
17151 cfg80211_del_sta(dev, hang_mac, GFP_ATOMIC);
17152 } else
17153 #endif /* SOFTAP_SEND_HANGEVT */
17154 {
17155 CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
17156 }
17157 #if defined(RSSIAVG)
17158 wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
17159 #endif
17160 #if defined(BSSCACHE)
17161 wl_free_bss_cache(&cfg->g_bss_cache_ctrl);
17162 #endif
17163 if (cfg != NULL) {
17164 wl_link_down(cfg);
17165 }
17166 return 0;
17167 }
17168
17169 s32 wl_cfg80211_down(struct net_device *dev)
17170 {
17171 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
17172 s32 err = 0;
17173
17174 WL_DBG(("In\n"));
17175 if (cfg == NULL)
17176 return err;
17177 mutex_lock(&cfg->usr_sync);
17178 #if defined(RSSIAVG)
17179 wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
17180 #endif
17181 #if defined(BSSCACHE)
17182 wl_free_bss_cache(&cfg->g_bss_cache_ctrl);
17183 #endif
17184 err = __wl_cfg80211_down(cfg);
17185 mutex_unlock(&cfg->usr_sync);
17186
17187 return err;
17188 }
17189
17190 static void *wl_read_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 item)
17191 {
17192 unsigned long flags;
17193 void *rptr = NULL;
17194 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
17195
17196 if (!profile)
17197 return NULL;
17198 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
17199 switch (item) {
17200 case WL_PROF_SEC:
17201 rptr = &profile->sec;
17202 break;
17203 case WL_PROF_ACT:
17204 rptr = &profile->active;
17205 break;
17206 case WL_PROF_BSSID:
17207 rptr = profile->bssid;
17208 break;
17209 case WL_PROF_SSID:
17210 rptr = &profile->ssid;
17211 break;
17212 case WL_PROF_CHAN:
17213 rptr = &profile->channel;
17214 break;
17215 }
17216 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
17217 if (!rptr)
17218 WL_ERR(("invalid item (%d)\n", item));
17219 return rptr;
17220 }
17221
17222 static s32
17223 wl_update_prof(struct bcm_cfg80211 *cfg, struct net_device *ndev,
17224 const wl_event_msg_t *e, const void *data, s32 item)
17225 {
17226 s32 err = 0;
17227 const struct wlc_ssid *ssid;
17228 unsigned long flags;
17229 struct wl_profile *profile = wl_get_profile_by_netdev(cfg, ndev);
17230
17231 if (!profile)
17232 return WL_INVALID;
17233 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
17234 switch (item) {
17235 case WL_PROF_SSID:
17236 ssid = (const wlc_ssid_t *) data;
17237 memset(profile->ssid.SSID, 0,
17238 sizeof(profile->ssid.SSID));
17239 profile->ssid.SSID_len = MIN(ssid->SSID_len, DOT11_MAX_SSID_LEN);
17240 memcpy(profile->ssid.SSID, ssid->SSID, profile->ssid.SSID_len);
17241 break;
17242 case WL_PROF_BSSID:
17243 if (data)
17244 memcpy(profile->bssid, data, ETHER_ADDR_LEN);
17245 else
17246 memset(profile->bssid, 0, ETHER_ADDR_LEN);
17247 break;
17248 case WL_PROF_SEC:
17249 memcpy(&profile->sec, data, sizeof(profile->sec));
17250 break;
17251 case WL_PROF_ACT:
17252 profile->active = *(const bool *)data;
17253 break;
17254 case WL_PROF_BEACONINT:
17255 profile->beacon_interval = *(const u16 *)data;
17256 break;
17257 case WL_PROF_DTIMPERIOD:
17258 profile->dtim_period = *(const u8 *)data;
17259 break;
17260 case WL_PROF_CHAN:
17261 profile->channel = *(const u32*)data;
17262 break;
17263 default:
17264 err = -EOPNOTSUPP;
17265 break;
17266 }
17267 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
17268
17269 if (err == -EOPNOTSUPP)
17270 WL_ERR(("unsupported item (%d)\n", item));
17271
17272 return err;
17273 }
17274
17275 void wl_cfg80211_dbg_level(u32 level)
17276 {
17277 /*
17278 * prohibit to change debug level
17279 * by insmod parameter.
17280 * eventually debug level will be configured
17281 * in compile time by using CONFIG_XXX
17282 */
17283 /* wl_dbg_level = level; */
17284 }
17285
17286 static bool wl_is_ibssmode(struct bcm_cfg80211 *cfg, struct net_device *ndev)
17287 {
17288 return wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_IBSS;
17289 }
17290
17291 static __used bool wl_is_ibssstarter(struct bcm_cfg80211 *cfg)
17292 {
17293 return cfg->ibss_starter;
17294 }
17295
17296 static void wl_rst_ie(struct bcm_cfg80211 *cfg)
17297 {
17298 struct wl_ie *ie = wl_to_ie(cfg);
17299
17300 ie->offset = 0;
17301 }
17302
17303 static __used s32 wl_add_ie(struct bcm_cfg80211 *cfg, u8 t, u8 l, u8 *v)
17304 {
17305 struct wl_ie *ie = wl_to_ie(cfg);
17306 s32 err = 0;
17307
17308 if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) {
17309 WL_ERR(("ei crosses buffer boundary\n"));
17310 return -ENOSPC;
17311 }
17312 ie->buf[ie->offset] = t;
17313 ie->buf[ie->offset + 1] = l;
17314 memcpy(&ie->buf[ie->offset + 2], v, l);
17315 ie->offset += l + 2;
17316
17317 return err;
17318 }
17319
17320 static void wl_update_hidden_ap_ie(struct wl_bss_info *bi, const u8 *ie_stream, u32 *ie_size,
17321 bool roam)
17322 {
17323 u8 *ssidie;
17324 int32 ssid_len = MIN(bi->SSID_len, DOT11_MAX_SSID_LEN);
17325 int32 remaining_ie_buf_len, available_buffer_len;
17326 /* cfg80211_find_ie defined in kernel returning const u8 */
17327 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
17328 4 && __GNUC_MINOR__ >= 6))
17329 _Pragma("GCC diagnostic push")
17330 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
17331 #endif
17332 ssidie = (u8 *)cfg80211_find_ie(WLAN_EID_SSID, ie_stream, *ie_size);
17333 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
17334 4 && __GNUC_MINOR__ >= 6))
17335 _Pragma("GCC diagnostic pop")
17336 #endif
17337 /* ERROR out if
17338 * 1. No ssid IE is FOUND or
17339 * 2. New ssid length is > what was allocated for existing ssid (as
17340 * we do not want to overwrite the rest of the IEs) or
17341 * 3. If in case of erroneous buffer input where ssid length doesnt match the space
17342 * allocated to it.
17343 */
17344 if (!ssidie) {
17345 return;
17346 }
17347 available_buffer_len = ((int)(*ie_size)) - (ssidie + 2 - ie_stream);
17348 remaining_ie_buf_len = available_buffer_len - (int)ssidie[1];
17349 if ((ssid_len > ssidie[1]) ||
17350 (ssidie[1] > available_buffer_len)) {
17351 return;
17352 }
17353
17354
17355 if (ssidie[1] != ssid_len) {
17356 if (ssidie[1]) {
17357 WL_ERR(("%s: Wrong SSID len: %d != %d\n",
17358 __FUNCTION__, ssidie[1], bi->SSID_len));
17359 }
17360 if (roam) {
17361 WL_ERR(("Changing the SSID Info.\n"));
17362 memmove(ssidie + ssid_len + 2,
17363 (ssidie + 2) + ssidie[1],
17364 remaining_ie_buf_len);
17365 memcpy(ssidie + 2, bi->SSID, ssid_len);
17366 *ie_size = *ie_size + ssid_len - ssidie[1];
17367 ssidie[1] = ssid_len;
17368 }
17369 return;
17370 }
17371 if (*(ssidie + 2) == '\0')
17372 memcpy(ssidie + 2, bi->SSID, ssid_len);
17373 return;
17374 }
17375
17376 static s32 wl_mrg_ie(struct bcm_cfg80211 *cfg, u8 *ie_stream, u16 ie_size)
17377 {
17378 struct wl_ie *ie = wl_to_ie(cfg);
17379 s32 err = 0;
17380
17381 if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) {
17382 WL_ERR(("ei_stream crosses buffer boundary\n"));
17383 return -ENOSPC;
17384 }
17385 memcpy(&ie->buf[ie->offset], ie_stream, ie_size);
17386 ie->offset += ie_size;
17387
17388 return err;
17389 }
17390
17391 static s32 wl_cp_ie(struct bcm_cfg80211 *cfg, u8 *dst, u16 dst_size)
17392 {
17393 struct wl_ie *ie = wl_to_ie(cfg);
17394 s32 err = 0;
17395
17396 if (unlikely(ie->offset > dst_size)) {
17397 WL_ERR(("dst_size is not enough\n"));
17398 return -ENOSPC;
17399 }
17400 memcpy(dst, &ie->buf[0], ie->offset);
17401
17402 return err;
17403 }
17404
17405 static u32 wl_get_ielen(struct bcm_cfg80211 *cfg)
17406 {
17407 struct wl_ie *ie = wl_to_ie(cfg);
17408
17409 return ie->offset;
17410 }
17411
17412 static void wl_link_up(struct bcm_cfg80211 *cfg)
17413 {
17414 cfg->link_up = true;
17415 }
17416
17417 static void wl_link_down(struct bcm_cfg80211 *cfg)
17418 {
17419 struct wl_connect_info *conn_info = wl_to_conn(cfg);
17420
17421 WL_DBG(("In\n"));
17422 cfg->link_up = false;
17423 if (conn_info) {
17424 conn_info->req_ie_len = 0;
17425 conn_info->resp_ie_len = 0;
17426 }
17427 }
17428
17429 static unsigned long wl_lock_eq(struct bcm_cfg80211 *cfg)
17430 {
17431 unsigned long flags;
17432
17433 spin_lock_irqsave(&cfg->eq_lock, flags);
17434 return flags;
17435 }
17436
17437 static void wl_unlock_eq(struct bcm_cfg80211 *cfg, unsigned long flags)
17438 {
17439 spin_unlock_irqrestore(&cfg->eq_lock, flags);
17440 }
17441
17442 static void wl_init_eq_lock(struct bcm_cfg80211 *cfg)
17443 {
17444 spin_lock_init(&cfg->eq_lock);
17445 }
17446
17447 static void wl_delay(u32 ms)
17448 {
17449 if (in_atomic() || (ms < jiffies_to_msecs(1))) {
17450 OSL_DELAY(ms*1000);
17451 } else {
17452 OSL_SLEEP(ms);
17453 }
17454 }
17455
17456 s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
17457 {
17458 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17459 struct ether_addr primary_mac;
17460 if (!cfg->p2p)
17461 return -1;
17462 if (!p2p_is_on(cfg)) {
17463 get_primary_mac(cfg, &primary_mac);
17464 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
17465 } else {
17466 memcpy(p2pdev_addr->octet, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE).octet,
17467 ETHER_ADDR_LEN);
17468 }
17469
17470 return 0;
17471 }
17472 s32 wl_cfg80211_set_p2p_noa(struct net_device *net, char* buf, int len)
17473 {
17474 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17475
17476 return wl_cfgp2p_set_p2p_noa(cfg, net, buf, len);
17477 }
17478
17479 s32 wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len)
17480 {
17481 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17482
17483 return wl_cfgp2p_get_p2p_noa(cfg, net, buf, len);
17484 }
17485
17486 s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len)
17487 {
17488 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17489
17490 return wl_cfgp2p_set_p2p_ps(cfg, net, buf, len);
17491 }
17492
17493 s32 wl_cfg80211_set_p2p_ecsa(struct net_device *net, char* buf, int len)
17494 {
17495 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17496
17497 return wl_cfgp2p_set_p2p_ecsa(cfg, net, buf, len);
17498 }
17499
17500 s32 wl_cfg80211_increase_p2p_bw(struct net_device *net, char* buf, int len)
17501 {
17502 struct bcm_cfg80211 *cfg = wl_get_cfg(net);
17503
17504 return wl_cfgp2p_increase_p2p_bw(cfg, net, buf, len);
17505 }
17506
17507 #ifdef P2PLISTEN_AP_SAMECHN
17508 s32 wl_cfg80211_set_p2p_resp_ap_chn(struct net_device *net, s32 enable)
17509 {
17510 s32 ret = wldev_iovar_setint(net, "p2p_resp_ap_chn", enable);
17511
17512 if ((ret == 0) && enable) {
17513 /* disable PM for p2p responding on infra AP channel */
17514 s32 pm = PM_OFF;
17515
17516 ret = wldev_ioctl_set(net, WLC_SET_PM, &pm, sizeof(pm));
17517 }
17518
17519 return ret;
17520 }
17521 #endif /* P2PLISTEN_AP_SAMECHN */
17522
17523 s32 wl_cfg80211_channel_to_freq(u32 channel)
17524 {
17525 int freq = 0;
17526
17527 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
17528 freq = ieee80211_channel_to_frequency(channel);
17529 #else
17530 {
17531 u16 band = 0;
17532 if (channel <= CH_MAX_2G_CHANNEL)
17533 band = IEEE80211_BAND_2GHZ;
17534 else
17535 band = IEEE80211_BAND_5GHZ;
17536 freq = ieee80211_channel_to_frequency(channel, band);
17537 }
17538 #endif
17539 return freq;
17540 }
17541
17542
17543 #ifdef WLTDLS
17544 static s32
17545 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
17546 const wl_event_msg_t *e, void *data) {
17547
17548 struct net_device *ndev = NULL;
17549 u32 reason = ntoh32(e->reason);
17550 s8 *msg = NULL;
17551
17552 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
17553
17554 switch (reason) {
17555 case WLC_E_TDLS_PEER_DISCOVERED :
17556 msg = " TDLS PEER DISCOVERD ";
17557 break;
17558 case WLC_E_TDLS_PEER_CONNECTED :
17559 if (cfg->tdls_mgmt_frame) {
17560 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
17561 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
17562 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0);
17563 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
17564 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
17565 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0,
17566 GFP_ATOMIC);
17567 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
17568 defined(WL_COMPAT_WIRELESS)
17569 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
17570 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
17571 GFP_ATOMIC);
17572 #else
17573 cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq,
17574 cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, GFP_ATOMIC);
17575 #endif
17576 }
17577 msg = " TDLS PEER CONNECTED ";
17578 #ifdef SUPPORT_SET_CAC
17579 /* TDLS connect reset CAC */
17580 wl_cfg80211_set_cac(cfg, 0);
17581 #endif /* SUPPORT_SET_CAC */
17582 break;
17583 case WLC_E_TDLS_PEER_DISCONNECTED :
17584 if (cfg->tdls_mgmt_frame) {
17585 kfree(cfg->tdls_mgmt_frame);
17586 cfg->tdls_mgmt_frame = NULL;
17587 cfg->tdls_mgmt_freq = 0;
17588 }
17589 msg = "TDLS PEER DISCONNECTED ";
17590 #ifdef SUPPORT_SET_CAC
17591 /* TDLS disconnec, set CAC */
17592 wl_cfg80211_set_cac(cfg, 1);
17593 #endif /* SUPPORT_SET_CAC */
17594 break;
17595 }
17596 if (msg) {
17597 WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((const u8*)(&e->addr)),
17598 (bcmcfg_to_prmry_ndev(cfg) == ndev) ? "primary" : "secondary"));
17599 }
17600 return 0;
17601
17602 }
17603 #endif /* WLTDLS */
17604
17605 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0))
17606 static s32
17607 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
17608 KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
17609 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
17610 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
17611 u32 peer_capability, const u8 *buf, size_t len)
17612 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
17613 (LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
17614 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
17615 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
17616 u32 peer_capability, const u8 *buf, size_t len)
17617 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
17618 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
17619 const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
17620 u32 peer_capability, bool initiator, const u8 *buf, size_t len)
17621 #else /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17622 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
17623 u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
17624 const u8 *buf, size_t len)
17625 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17626 {
17627 s32 ret = 0;
17628 #ifdef WLTDLS
17629 struct bcm_cfg80211 *cfg;
17630 tdls_wfd_ie_iovar_t info;
17631 memset(&info, 0, sizeof(tdls_wfd_ie_iovar_t));
17632 cfg = wl_get_cfg(dev);
17633
17634 #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
17635 /* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
17636 * and that cuases build error
17637 */
17638 BCM_REFERENCE(peer_capability);
17639 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
17640
17641 switch (action_code) {
17642 /* We need to set TDLS Wifi Display IE to firmware
17643 * using tdls_wfd_ie iovar
17644 */
17645 case WLAN_TDLS_SET_PROBE_WFD_IE:
17646 WL_ERR(("%s WLAN_TDLS_SET_PROBE_WFD_IE\n", __FUNCTION__));
17647 info.mode = TDLS_WFD_PROBE_IE_TX;
17648 memcpy(&info.data, buf, len);
17649 info.length = len;
17650 break;
17651 case WLAN_TDLS_SET_SETUP_WFD_IE:
17652 WL_ERR(("%s WLAN_TDLS_SET_SETUP_WFD_IE\n", __FUNCTION__));
17653 info.mode = TDLS_WFD_IE_TX;
17654 memcpy(&info.data, buf, len);
17655 info.length = len;
17656 break;
17657 case WLAN_TDLS_SET_WFD_ENABLED:
17658 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_ENABLED\n", __FUNCTION__));
17659 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), true);
17660 goto out;
17661 case WLAN_TDLS_SET_WFD_DISABLED:
17662 WL_ERR(("%s WLAN_TDLS_SET_MODE_WFD_DISABLED\n", __FUNCTION__));
17663 dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), false);
17664 goto out;
17665 default:
17666 WL_ERR(("Unsupported action code : %d\n", action_code));
17667 goto out;
17668 }
17669 ret = wldev_iovar_setbuf(dev, "tdls_wfd_ie", &info, sizeof(info),
17670 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
17671
17672 if (ret) {
17673 WL_ERR(("tdls_wfd_ie error %d\n", ret));
17674 }
17675
17676 out:
17677 #endif /* WLTDLS */
17678 return ret;
17679 }
17680
17681 static s32
17682 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
17683 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
17684 const u8 *peer, enum nl80211_tdls_operation oper)
17685 #else
17686 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
17687 u8 *peer, enum nl80211_tdls_operation oper)
17688 #endif
17689 {
17690 s32 ret = 0;
17691 #ifdef WLTDLS
17692 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
17693 tdls_iovar_t info;
17694 dhd_pub_t *dhdp;
17695 bool tdls_auto_mode = false;
17696 dhdp = (dhd_pub_t *)(cfg->pub);
17697 memset(&info, 0, sizeof(tdls_iovar_t));
17698 if (peer) {
17699 memcpy(&info.ea, peer, ETHER_ADDR_LEN);
17700 } else {
17701 return -1;
17702 }
17703 switch (oper) {
17704 case NL80211_TDLS_DISCOVERY_REQ:
17705 /* If the discovery request is broadcast then we need to set
17706 * info.mode to Tunneled Probe Request
17707 */
17708 if (memcmp(peer, (const uint8 *)BSSID_BROADCAST, ETHER_ADDR_LEN) == 0) {
17709 info.mode = TDLS_MANUAL_EP_WFD_TPQ;
17710 WL_ERR(("%s TDLS TUNNELED PRBOBE REQUEST\n", __FUNCTION__));
17711 } else {
17712 info.mode = TDLS_MANUAL_EP_DISCOVERY;
17713 }
17714 break;
17715 case NL80211_TDLS_SETUP:
17716 if (dhdp->tdls_mode == true) {
17717 info.mode = TDLS_MANUAL_EP_CREATE;
17718 tdls_auto_mode = false;
17719 /* Do tear down and create a fresh one */
17720 ret = wl_cfg80211_tdls_config(cfg, TDLS_STATE_TEARDOWN, tdls_auto_mode);
17721 if (ret < 0) {
17722 return ret;
17723 }
17724 } else {
17725 tdls_auto_mode = true;
17726 }
17727 break;
17728 case NL80211_TDLS_TEARDOWN:
17729 info.mode = TDLS_MANUAL_EP_DELETE;
17730 break;
17731 default:
17732 WL_ERR(("Unsupported operation : %d\n", oper));
17733 goto out;
17734 }
17735 /* turn on TDLS */
17736 wl_cfg80211_tdls_config(cfg, TDLS_STATE_SETUP, tdls_auto_mode);
17737 if (ret < 0) {
17738 return ret;
17739 }
17740 if (info.mode) {
17741 ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
17742 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
17743 if (ret) {
17744 WL_ERR(("tdls_endpoint error %d\n", ret));
17745 }
17746 }
17747 out:
17748 if (ret) {
17749 return -ENOTSUPP;
17750 }
17751 #endif /* WLTDLS */
17752 return ret;
17753 }
17754 #endif
17755
17756 /*
17757 * This function returns no of bytes written
17758 * In case of failure return zero, not bcme_error
17759 */
17760 s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *ndev, char *buf, int len,
17761 enum wl_management_type type)
17762 {
17763 struct bcm_cfg80211 *cfg;
17764 s32 ret = 0;
17765 struct ether_addr primary_mac;
17766 s32 bssidx = 0;
17767 s32 pktflag = 0;
17768 cfg = wl_get_cfg(ndev);
17769
17770 if (wl_get_drv_status(cfg, AP_CREATING, ndev)) {
17771 /* Vendor IEs should be set to FW
17772 * after SoftAP interface is brought up
17773 */
17774 WL_DBG(("Skipping set IE since AP is not up \n"));
17775 goto exit;
17776 } else if (ndev == bcmcfg_to_prmry_ndev(cfg)) {
17777 /* Either stand alone AP case or P2P discovery */
17778 if (wl_get_drv_status(cfg, AP_CREATED, ndev)) {
17779 /* Stand alone AP case on primary interface */
17780 WL_DBG(("Apply IEs for Primary AP Interface \n"));
17781 bssidx = 0;
17782 } else {
17783 if (!cfg->p2p) {
17784 /* If p2p not initialized, return failure */
17785 WL_ERR(("P2P not initialized \n"));
17786 goto exit;
17787 }
17788 /* P2P Discovery case (p2p listen) */
17789 if (!cfg->p2p->on) {
17790 /* Turn on Discovery interface */
17791 get_primary_mac(cfg, &primary_mac);
17792 wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
17793 p2p_on(cfg) = true;
17794 ret = wl_cfgp2p_enable_discovery(cfg, ndev, NULL, 0);
17795 if (unlikely(ret)) {
17796 WL_ERR(("Enable discovery failed \n"));
17797 goto exit;
17798 }
17799 }
17800 WL_DBG(("Apply IEs for P2P Discovery Iface \n"));
17801 ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
17802 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
17803 }
17804 } else {
17805 /* Virtual AP/ P2P Group Interface */
17806 WL_DBG(("Apply IEs for iface:%s\n", ndev->name));
17807 bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
17808 }
17809
17810 if (ndev != NULL) {
17811 switch (type) {
17812 case WL_BEACON:
17813 pktflag = VNDR_IE_BEACON_FLAG;
17814 break;
17815 case WL_PROBE_RESP:
17816 pktflag = VNDR_IE_PRBRSP_FLAG;
17817 break;
17818 case WL_ASSOC_RESP:
17819 pktflag = VNDR_IE_ASSOCRSP_FLAG;
17820 break;
17821 }
17822 if (pktflag) {
17823 ret = wl_cfg80211_set_mgmt_vndr_ies(cfg,
17824 ndev_to_cfgdev(ndev), bssidx, pktflag, buf, len);
17825 }
17826 }
17827 exit:
17828 return ret;
17829 }
17830
17831 #ifdef WL_SUPPORT_AUTO_CHANNEL
17832 static s32
17833 wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
17834 {
17835 u32 val = 0;
17836 s32 ret = BCME_ERROR;
17837 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
17838 /* Set interface up, explicitly. */
17839 val = 1;
17840
17841 ret = wldev_ioctl_set(ndev, WLC_UP, (void *)&val, sizeof(val));
17842 if (ret < 0) {
17843 WL_ERR(("set interface up failed, error = %d\n", ret));
17844 goto done;
17845 }
17846
17847 /* Stop all scan explicitly, till auto channel selection complete. */
17848 wl_set_drv_status(cfg, SCANNING, ndev);
17849 if (cfg->escan_info.ndev == NULL) {
17850 ret = BCME_OK;
17851 goto done;
17852 }
17853 ret = wl_notify_escan_complete(cfg, ndev, true, true);
17854 if (ret < 0) {
17855 WL_ERR(("set scan abort failed, error = %d\n", ret));
17856 ret = BCME_OK; // terence 20140115: fix escan_complete error
17857 goto done;
17858 }
17859
17860 done:
17861 return ret;
17862 }
17863
17864 static bool
17865 wl_cfg80211_valid_channel_p2p(int channel)
17866 {
17867 bool valid = false;
17868
17869 /* channel 1 to 14 */
17870 if ((channel >= 1) && (channel <= 14)) {
17871 valid = true;
17872 }
17873 /* channel 36 to 48 */
17874 else if ((channel >= 36) && (channel <= 48)) {
17875 valid = true;
17876 }
17877 /* channel 149 to 161 */
17878 else if ((channel >= 149) && (channel <= 161)) {
17879 valid = true;
17880 }
17881 else {
17882 valid = false;
17883 WL_INFORM(("invalid P2P chanspec, channel = %d\n", channel));
17884 }
17885
17886 return valid;
17887 }
17888
17889 s32
17890 wl_cfg80211_get_chanspecs_2g(struct net_device *ndev, void *buf, s32 buflen)
17891 {
17892 s32 ret = BCME_ERROR;
17893 struct bcm_cfg80211 *cfg = NULL;
17894 chanspec_t chanspec = 0;
17895
17896 cfg = wl_get_cfg(ndev);
17897
17898 /* Restrict channels to 2.4GHz, 20MHz BW, no SB. */
17899 chanspec |= (WL_CHANSPEC_BAND_2G | WL_CHANSPEC_BW_20 |
17900 WL_CHANSPEC_CTL_SB_NONE);
17901 chanspec = wl_chspec_host_to_driver(chanspec);
17902
17903 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
17904 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
17905 if (ret < 0) {
17906 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
17907 }
17908
17909 return ret;
17910 }
17911
17912 s32
17913 wl_cfg80211_get_chanspecs_5g(struct net_device *ndev, void *buf, s32 buflen)
17914 {
17915 u32 channel = 0;
17916 s32 ret = BCME_ERROR;
17917 s32 i = 0;
17918 s32 j = 0;
17919 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
17920 wl_uint32_list_t *list = NULL;
17921 chanspec_t chanspec = 0;
17922
17923 /* Restrict channels to 5GHz, 20MHz BW, no SB. */
17924 chanspec |= (WL_CHANSPEC_BAND_5G | WL_CHANSPEC_BW_20 |
17925 WL_CHANSPEC_CTL_SB_NONE);
17926 chanspec = wl_chspec_host_to_driver(chanspec);
17927
17928 ret = wldev_iovar_getbuf_bsscfg(ndev, "chanspecs", (void *)&chanspec,
17929 sizeof(chanspec), buf, buflen, 0, &cfg->ioctl_buf_sync);
17930 if (ret < 0) {
17931 WL_ERR(("get 'chanspecs' failed, error = %d\n", ret));
17932 goto done;
17933 }
17934
17935 list = (wl_uint32_list_t *)buf;
17936 /* Skip DFS and inavlid P2P channel. */
17937 for (i = 0, j = 0; i < dtoh32(list->count); i++) {
17938 chanspec = (chanspec_t) dtoh32(list->element[i]);
17939 channel = CHSPEC_CHANNEL(chanspec);
17940
17941 ret = wldev_iovar_getint(ndev, "per_chan_info", &channel);
17942 if (ret < 0) {
17943 WL_ERR(("get 'per_chan_info' failed, error = %d\n", ret));
17944 goto done;
17945 }
17946
17947 if (CHANNEL_IS_RADAR(channel) ||
17948 !(wl_cfg80211_valid_channel_p2p(CHSPEC_CHANNEL(chanspec)))) {
17949 continue;
17950 } else {
17951 list->element[j] = list->element[i];
17952 }
17953
17954 j++;
17955 }
17956
17957 list->count = j;
17958
17959 done:
17960 return ret;
17961 }
17962
17963 static s32
17964 wl_cfg80211_get_best_channel(struct net_device *ndev, void *buf, int buflen,
17965 int *channel)
17966 {
17967 s32 ret = BCME_ERROR;
17968 int chosen = 0;
17969 int retry = 0;
17970 uint chip;
17971
17972 /* Start auto channel selection scan. */
17973 ret = wldev_ioctl_set(ndev, WLC_START_CHANNEL_SEL, buf, buflen);
17974 if (ret < 0) {
17975 WL_ERR(("can't start auto channel scan, error = %d\n", ret));
17976 *channel = 0;
17977 goto done;
17978 }
17979
17980 /* Wait for auto channel selection, worst case possible delay is 5250ms. */
17981 retry = CHAN_SEL_RETRY_COUNT;
17982
17983 while (retry--) {
17984 OSL_SLEEP(CHAN_SEL_IOCTL_DELAY);
17985 chosen = 0;
17986 ret = wldev_ioctl_get(ndev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen));
17987 if ((ret == 0) && (dtoh32(chosen) != 0)) {
17988 chip = dhd_conf_get_chip(dhd_get_pub(ndev));
17989 if (chip != BCM43362_CHIP_ID && chip != BCM4330_CHIP_ID &&
17990 chip != BCM43143_CHIP_ID) {
17991 u32 chanspec = 0;
17992 int ctl_chan;
17993 chanspec = wl_chspec_driver_to_host(chosen);
17994 WL_INFORM(("selected chanspec = 0x%x\n", chanspec));
17995 ctl_chan = wf_chspec_ctlchan(chanspec);
17996 WL_INFORM(("selected ctl_chan = %d\n", ctl_chan));
17997 *channel = (u16)(ctl_chan & 0x00FF);
17998 } else
17999 *channel = (u16)(chosen & 0x00FF);
18000 WL_INFORM(("selected channel = %d\n", *channel));
18001 break;
18002 }
18003 WL_INFORM(("attempt = %d, ret = %d, chosen = %d\n",
18004 (CHAN_SEL_RETRY_COUNT - retry), ret, dtoh32(chosen)));
18005 }
18006
18007 if (retry <= 0) {
18008 WL_ERR(("failure, auto channel selection timed out\n"));
18009 *channel = 0;
18010 ret = BCME_ERROR;
18011 }
18012 WL_INFORM(("selected channel = %d\n", *channel));
18013
18014 done:
18015 return ret;
18016 }
18017
18018 static s32
18019 wl_cfg80211_restore_auto_channel_scan_state(struct net_device *ndev)
18020 {
18021 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
18022 /* Clear scan stop driver status. */
18023 wl_clr_drv_status(cfg, SCANNING, ndev);
18024
18025 return BCME_OK;
18026 }
18027
18028 s32
18029 wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
18030 {
18031 int channel = 0, band, band_cur;
18032 s32 ret = BCME_ERROR;
18033 u8 *buf = NULL;
18034 char *pos = cmd;
18035 struct bcm_cfg80211 *cfg = NULL;
18036 struct net_device *ndev = NULL;
18037
18038 memset(cmd, 0, total_len);
18039
18040 buf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
18041 if (buf == NULL) {
18042 WL_ERR(("failed to allocate chanspec buffer\n"));
18043 return -ENOMEM;
18044 }
18045
18046 /*
18047 * Always use primary interface, irrespective of interface on which
18048 * command came.
18049 */
18050 cfg = wl_get_cfg(dev);
18051 ndev = bcmcfg_to_prmry_ndev(cfg);
18052
18053 /*
18054 * Make sure that FW and driver are in right state to do auto channel
18055 * selection scan.
18056 */
18057 ret = wl_cfg80211_set_auto_channel_scan_state(ndev);
18058 if (ret < 0) {
18059 WL_ERR(("can't set auto channel scan state, error = %d\n", ret));
18060 goto done;
18061 }
18062
18063 ret = wldev_ioctl(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur), false);
18064 if (band_cur != WLC_BAND_5G) {
18065 /* Best channel selection in 2.4GHz band. */
18066 ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
18067 if (ret < 0) {
18068 WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
18069 goto done;
18070 }
18071
18072 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
18073 &channel);
18074 if (ret < 0) {
18075 WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
18076 goto done;
18077 }
18078
18079 if (CHANNEL_IS_2G(channel)) {
18080 #if 0
18081 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
18082 channel = ieee80211_channel_to_frequency(channel);
18083 #else
18084 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
18085 #endif
18086 #endif
18087 } else {
18088 WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
18089 channel = 0;
18090 }
18091 pos += snprintf(pos, total_len, "2g=%d ", channel);
18092 }
18093
18094 if (band_cur != WLC_BAND_2G) {
18095 // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
18096 band = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
18097 ret = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
18098 if (ret < 0) {
18099 WL_ERR(("WLC_SET_BAND error %d\n", ret));
18100 goto done;
18101 }
18102
18103 /* Best channel selection in 5GHz band. */
18104 ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
18105 if (ret < 0) {
18106 WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
18107 goto done;
18108 }
18109
18110 ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
18111 &channel);
18112 if (ret < 0) {
18113 WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
18114 goto done;
18115 }
18116
18117 if (CHANNEL_IS_5G(channel)) {
18118 #if 0
18119 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
18120 channel = ieee80211_channel_to_frequency(channel);
18121 #else
18122 channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
18123 #endif
18124 #endif
18125 } else {
18126 WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
18127 channel = 0;
18128 }
18129
18130 ret = wldev_ioctl(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur), true);
18131 if (ret < 0)
18132 WL_ERR(("WLC_SET_BAND error %d\n", ret));
18133 pos += snprintf(pos, total_len, "5g=%d ", channel);
18134 }
18135
18136 done:
18137 if (NULL != buf) {
18138 kfree(buf);
18139 }
18140
18141 /* Restore FW and driver back to normal state. */
18142 ret = wl_cfg80211_restore_auto_channel_scan_state(ndev);
18143 if (ret < 0) {
18144 WL_ERR(("can't restore auto channel scan state, error = %d\n", ret));
18145 }
18146
18147 printf("%s: %s\n", __FUNCTION__, cmd);
18148
18149 return (pos - cmd);
18150 }
18151 #endif /* WL_SUPPORT_AUTO_CHANNEL */
18152
18153 static const struct rfkill_ops wl_rfkill_ops = {
18154 .set_block = wl_rfkill_set
18155 };
18156
18157 static int wl_rfkill_set(void *data, bool blocked)
18158 {
18159 struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
18160
18161 WL_DBG(("Enter \n"));
18162 WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
18163
18164 if (!cfg)
18165 return -EINVAL;
18166
18167 cfg->rf_blocked = blocked;
18168
18169 return 0;
18170 }
18171
18172 static int wl_setup_rfkill(struct bcm_cfg80211 *cfg, bool setup)
18173 {
18174 s32 err = 0;
18175
18176 WL_DBG(("Enter \n"));
18177 if (!cfg)
18178 return -EINVAL;
18179 if (setup) {
18180 cfg->rfkill = rfkill_alloc("brcmfmac-wifi",
18181 wl_cfg80211_get_parent_dev(),
18182 RFKILL_TYPE_WLAN, &wl_rfkill_ops, (void *)cfg);
18183
18184 if (!cfg->rfkill) {
18185 err = -ENOMEM;
18186 goto err_out;
18187 }
18188
18189 err = rfkill_register(cfg->rfkill);
18190
18191 if (err)
18192 rfkill_destroy(cfg->rfkill);
18193 } else {
18194 if (!cfg->rfkill) {
18195 err = -ENOMEM;
18196 goto err_out;
18197 }
18198
18199 rfkill_unregister(cfg->rfkill);
18200 rfkill_destroy(cfg->rfkill);
18201 }
18202
18203 err_out:
18204 return err;
18205 }
18206
18207 #ifdef DEBUGFS_CFG80211
18208 /**
18209 * Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level
18210 * to turn on SCAN and DBG log.
18211 * To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level
18212 * To see current setting of debug level,
18213 * cat /sys/kernel/debug/dhd/debug_level
18214 */
18215 static ssize_t
18216 wl_debuglevel_write(struct file *file, const char __user *userbuf,
18217 size_t count, loff_t *ppos)
18218 {
18219 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL];
18220 char *params, *token, *colon;
18221 uint i, tokens, log_on = 0;
18222 size_t minsize = min_t(size_t, (sizeof(tbuf) - 1), count);
18223
18224 memset(tbuf, 0, sizeof(tbuf));
18225 memset(sublog, 0, sizeof(sublog));
18226 if (copy_from_user(&tbuf, userbuf, minsize)) {
18227 return -EFAULT;
18228 }
18229
18230 tbuf[minsize + 1] = '\0';
18231 params = &tbuf[0];
18232 colon = strchr(params, '\n');
18233 if (colon != NULL)
18234 *colon = '\0';
18235 while ((token = strsep(&params, " ")) != NULL) {
18236 memset(sublog, 0, sizeof(sublog));
18237 if (token == NULL || !*token)
18238 break;
18239 if (*token == '\0')
18240 continue;
18241 colon = strchr(token, ':');
18242 if (colon != NULL) {
18243 *colon = ' ';
18244 }
18245 tokens = sscanf(token, "%s %u", sublog, &log_on);
18246 if (colon != NULL)
18247 *colon = ':';
18248
18249 if (tokens == 2) {
18250 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
18251 if (!strncmp(sublog, sublogname_map[i].sublogname,
18252 strlen(sublogname_map[i].sublogname))) {
18253 if (log_on)
18254 wl_dbg_level |=
18255 (sublogname_map[i].log_level);
18256 else
18257 wl_dbg_level &=
18258 ~(sublogname_map[i].log_level);
18259 }
18260 }
18261 } else
18262 WL_ERR(("%s: can't parse '%s' as a "
18263 "SUBMODULE:LEVEL (%d tokens)\n",
18264 tbuf, token, tokens));
18265
18266
18267 }
18268 return count;
18269 }
18270
18271 static ssize_t
18272 wl_debuglevel_read(struct file *file, char __user *user_buf,
18273 size_t count, loff_t *ppos)
18274 {
18275 char *param;
18276 char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)];
18277 uint i;
18278 memset(tbuf, 0, sizeof(tbuf));
18279 param = &tbuf[0];
18280 for (i = 0; i < ARRAYSIZE(sublogname_map); i++) {
18281 param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ",
18282 sublogname_map[i].sublogname,
18283 (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0);
18284 }
18285 *param = '\n';
18286 return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0]));
18287
18288 }
18289 static const struct file_operations fops_debuglevel = {
18290 .open = NULL,
18291 .write = wl_debuglevel_write,
18292 .read = wl_debuglevel_read,
18293 .owner = THIS_MODULE,
18294 .llseek = NULL,
18295 };
18296
18297 static s32 wl_setup_debugfs(struct bcm_cfg80211 *cfg)
18298 {
18299 s32 err = 0;
18300 struct dentry *_dentry;
18301 if (!cfg)
18302 return -EINVAL;
18303 cfg->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL);
18304 if (!cfg->debugfs || IS_ERR(cfg->debugfs)) {
18305 if (cfg->debugfs == ERR_PTR(-ENODEV))
18306 WL_ERR(("Debugfs is not enabled on this kernel\n"));
18307 else
18308 WL_ERR(("Can not create debugfs directory\n"));
18309 cfg->debugfs = NULL;
18310 goto exit;
18311
18312 }
18313 _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR,
18314 cfg->debugfs, cfg, &fops_debuglevel);
18315 if (!_dentry || IS_ERR(_dentry)) {
18316 WL_ERR(("failed to create debug_level debug file\n"));
18317 wl_free_debugfs(cfg);
18318 }
18319 exit:
18320 return err;
18321 }
18322 static s32 wl_free_debugfs(struct bcm_cfg80211 *cfg)
18323 {
18324 if (!cfg)
18325 return -EINVAL;
18326 if (cfg->debugfs)
18327 debugfs_remove_recursive(cfg->debugfs);
18328 cfg->debugfs = NULL;
18329 return 0;
18330 }
18331 #endif /* DEBUGFS_CFG80211 */
18332
18333 struct device *wl_cfg80211_get_parent_dev(void)
18334 {
18335 return cfg80211_parent_dev;
18336 }
18337
18338 void wl_cfg80211_set_parent_dev(void *dev)
18339 {
18340 cfg80211_parent_dev = dev;
18341 }
18342
18343 static void wl_cfg80211_clear_parent_dev(void)
18344 {
18345 cfg80211_parent_dev = NULL;
18346 }
18347
18348 void get_primary_mac(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
18349 {
18350 if (wldev_iovar_getbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr", NULL,
18351 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync) == BCME_OK) {
18352 memcpy(mac->octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
18353 } else {
18354 memset(mac->octet, 0, ETHER_ADDR_LEN);
18355 }
18356 }
18357 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role)
18358 {
18359 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
18360 if (((dev_role == NL80211_IFTYPE_AP) &&
18361 !(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
18362 ((dev_role == NL80211_IFTYPE_P2P_GO) &&
18363 !(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
18364 {
18365 WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role, dhd->op_mode));
18366 return false;
18367 }
18368 return true;
18369 }
18370
18371 int wl_cfg80211_do_driver_init(struct net_device *net)
18372 {
18373 struct bcm_cfg80211 *cfg = *(struct bcm_cfg80211 **)netdev_priv(net);
18374
18375 if (!cfg || !cfg->wdev)
18376 return -EINVAL;
18377
18378 if (dhd_do_driver_init(cfg->wdev->netdev) < 0)
18379 return -1;
18380
18381 return 0;
18382 }
18383
18384 void wl_cfg80211_enable_trace(u32 level)
18385 {
18386 wl_dbg_level = level;
18387 printf("%s: wl_dbg_level = 0x%x\n", __FUNCTION__, wl_dbg_level);
18388 }
18389
18390 #if defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \
18391 2, 0))
18392 static s32
18393 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy,
18394 bcm_struct_cfgdev *cfgdev, u64 cookie)
18395 {
18396 /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION
18397 * is passed with CMD_FRAME. This callback is supposed to cancel
18398 * the OFFCHANNEL Wait. Since we are already taking care of that
18399 * with the tx_mgmt logic, do nothing here.
18400 */
18401
18402 return 0;
18403 }
18404 #endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */
18405
18406 #ifdef WL11U
18407 static bcm_tlv_t *
18408 wl_cfg80211_find_interworking_ie(const u8 *parse, u32 len)
18409 {
18410 bcm_tlv_t *ie;
18411
18412 /* unfortunately it's too much work to dispose the const cast - bcm_parse_tlvs
18413 * is used everywhere and changing its prototype to take const qualifier needs
18414 * a massive change to all its callers...
18415 */
18416 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
18417 4 && __GNUC_MINOR__ >= 6))
18418 _Pragma("GCC diagnostic push")
18419 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
18420 #endif
18421 if ((ie = bcm_parse_tlvs((void *)parse, (int)len, DOT11_MNG_INTERWORKING_ID))) {
18422 return ie;
18423 }
18424 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
18425 4 && __GNUC_MINOR__ >= 6))
18426 _Pragma("GCC diagnostic pop")
18427 #endif
18428 return NULL;
18429 }
18430
18431 static s32
18432 wl_cfg80211_clear_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx)
18433 {
18434 ie_setbuf_t ie_setbuf;
18435
18436 WL_DBG(("clear interworking IE\n"));
18437
18438 memset(&ie_setbuf, 0, sizeof(ie_setbuf_t));
18439
18440 ie_setbuf.ie_buffer.iecount = htod32(1);
18441 ie_setbuf.ie_buffer.ie_list[0].ie_data.id = DOT11_MNG_INTERWORKING_ID;
18442 ie_setbuf.ie_buffer.ie_list[0].ie_data.len = 0;
18443
18444 return wldev_iovar_setbuf_bsscfg(ndev, "ie", &ie_setbuf, sizeof(ie_setbuf),
18445 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
18446 }
18447
18448 static s32
18449 wl_cfg80211_add_iw_ie(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag,
18450 uint8 ie_id, uint8 *data, uint8 data_len)
18451 {
18452 s32 err = BCME_OK;
18453 s32 buf_len;
18454 ie_setbuf_t *ie_setbuf;
18455 ie_getbuf_t ie_getbufp;
18456 char getbuf[WLC_IOCTL_SMLEN];
18457
18458 if (ie_id != DOT11_MNG_INTERWORKING_ID) {
18459 WL_ERR(("unsupported (id=%d)\n", ie_id));
18460 return BCME_UNSUPPORTED;
18461 }
18462
18463 /* access network options (1 octet) is the mandatory field */
18464 if (!data || data_len == 0 || data_len > IW_IES_MAX_BUF_LEN) {
18465 WL_ERR(("wrong interworking IE (len=%d)\n", data_len));
18466 return BCME_BADARG;
18467 }
18468
18469 /* Validate the pktflag parameter */
18470 if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
18471 VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
18472 VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG|
18473 VNDR_IE_CUSTOM_FLAG))) {
18474 WL_ERR(("invalid packet flag 0x%x\n", pktflag));
18475 return BCME_BADARG;
18476 }
18477
18478 buf_len = sizeof(ie_setbuf_t) + data_len - 1;
18479
18480 ie_getbufp.id = DOT11_MNG_INTERWORKING_ID;
18481 if (wldev_iovar_getbuf_bsscfg(ndev, "ie", (void *)&ie_getbufp,
18482 sizeof(ie_getbufp), getbuf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync)
18483 == BCME_OK) {
18484 if (!memcmp(&getbuf[TLV_HDR_LEN], data, data_len)) {
18485 WL_DBG(("skip to set interworking IE\n"));
18486 return BCME_OK;
18487 }
18488 }
18489
18490 /* if already set with previous values, delete it first */
18491 if (cfg->wl11u) {
18492 if ((err = wl_cfg80211_clear_iw_ie(cfg, ndev, bssidx)) != BCME_OK) {
18493 return err;
18494 }
18495 }
18496
18497 ie_setbuf = (ie_setbuf_t *) kzalloc(buf_len, GFP_KERNEL);
18498 if (!ie_setbuf) {
18499 WL_ERR(("Error allocating buffer for IE\n"));
18500 return -ENOMEM;
18501 }
18502 strncpy(ie_setbuf->cmd, "add", sizeof(ie_setbuf->cmd));
18503 ie_setbuf->cmd[sizeof(ie_setbuf->cmd) - 1] = '\0';
18504
18505 /* Buffer contains only 1 IE */
18506 ie_setbuf->ie_buffer.iecount = htod32(1);
18507 /* use VNDR_IE_CUSTOM_FLAG flags for none vendor IE . currently fixed value */
18508 ie_setbuf->ie_buffer.ie_list[0].pktflag = htod32(pktflag);
18509
18510 /* Now, add the IE to the buffer */
18511 ie_setbuf->ie_buffer.ie_list[0].ie_data.id = DOT11_MNG_INTERWORKING_ID;
18512 ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len;
18513 memcpy((uchar *)&ie_setbuf->ie_buffer.ie_list[0].ie_data.data[0], data, data_len);
18514
18515 if ((err = wldev_iovar_setbuf_bsscfg(ndev, "ie", ie_setbuf, buf_len,
18516 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync))
18517 == BCME_OK) {
18518 WL_DBG(("set interworking IE\n"));
18519 cfg->wl11u = TRUE;
18520 err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx);
18521 }
18522
18523 kfree(ie_setbuf);
18524 return err;
18525 }
18526 #endif /* WL11U */
18527
18528
18529 s32
18530 wl_cfg80211_set_if_band(struct net_device *ndev, int band)
18531 {
18532 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
18533 int ret = 0, wait_cnt;
18534 char ioctl_buf[32];
18535
18536 if ((band < WLC_BAND_AUTO) || (band > WLC_BAND_2G)) {
18537 WL_ERR(("Invalid band\n"));
18538 return -EINVAL;
18539 }
18540 if (wl_get_drv_status(cfg, CONNECTED, ndev) ||
18541 wl_get_drv_status(cfg, CONNECTING, ndev)) {
18542 /* if driver is connected or connecting status, try to disconnect first.
18543 * if dongle is associated, iovar 'if_band' would be rejected.
18544 */
18545 wl_set_drv_status(cfg, DISCONNECTING, ndev);
18546 ret = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0);
18547 if (ret < 0) {
18548 WL_ERR(("WLC_DISASSOC error %d\n", ret));
18549 /* continue to set 'if_band' */
18550 }
18551 else {
18552 /* This is to ensure that 'if_band' iovar is issued only after
18553 * disconnection is completed
18554 */
18555 wait_cnt = WAIT_FOR_DISCONNECT_MAX;
18556 while (wl_get_drv_status(cfg, DISCONNECTING, ndev) && wait_cnt) {
18557 WL_DBG(("Wait until disconnected. wait_cnt: %d\n", wait_cnt));
18558 wait_cnt--;
18559 OSL_SLEEP(10);
18560 }
18561 }
18562 }
18563 if ((ret = wldev_iovar_setbuf(ndev, "if_band", &band,
18564 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
18565 WL_ERR(("seting if_band failed ret=%d\n", ret));
18566 /* issue 'WLC_SET_BAND' if if_band is not supported */
18567 if (ret == BCME_UNSUPPORTED) {
18568 ret = wldev_set_band(ndev, band);
18569 if (ret < 0) {
18570 WL_ERR(("seting band failed ret=%d\n", ret));
18571 }
18572 }
18573 }
18574 return ret;
18575 }
18576
18577 s32
18578 wl_cfg80211_dfs_ap_move(struct net_device *ndev, char *data, char *command, int total_len)
18579 {
18580 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
18581 char ioctl_buf[50];
18582 int err = 0;
18583 uint32 val = 0;
18584 chanspec_t chanspec = 0;
18585 int abort;
18586 int bytes_written = 0;
18587 wl_dfs_ap_move_status_t *status;
18588 char chanbuf[CHANSPEC_STR_LEN];
18589 const char *dfs_state_str[DFS_SCAN_S_MAX] = {
18590 "Radar Free On Channel",
18591 "Radar Found On Channel",
18592 "Radar Scan In Progress",
18593 "Radar Scan Aborted",
18594 "RSDB Mode switch in Progress For Scan"
18595 };
18596 if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
18597 bytes_written = snprintf(command, total_len, "AP is not up\n");
18598 return bytes_written;
18599 }
18600 if (!*data) {
18601 if ((err = wldev_iovar_getbuf(ndev, "dfs_ap_move", NULL, 0,
18602 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
18603 WL_ERR(("setting dfs_ap_move failed with err=%d \n", err));
18604 return err;
18605 }
18606 status = (wl_dfs_ap_move_status_t *)cfg->ioctl_buf;
18607
18608 if (status->version != WL_DFS_AP_MOVE_VERSION) {
18609 err = BCME_UNSUPPORTED;
18610 WL_ERR(("err=%d version=%d\n", err, status->version));
18611 return err;
18612 }
18613
18614 if (status->move_status != (int8) DFS_SCAN_S_IDLE) {
18615 chanspec = wl_chspec_driver_to_host(status->chanspec);
18616 if (chanspec != 0 && chanspec != INVCHANSPEC) {
18617 wf_chspec_ntoa(chanspec, chanbuf);
18618 bytes_written = snprintf(command, total_len,
18619 "AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
18620
18621 }
18622 bytes_written += snprintf(command + bytes_written, total_len,
18623 "%s\n", dfs_state_str[status->move_status]);
18624 return bytes_written;
18625 } else {
18626 bytes_written = snprintf(command, total_len, "dfs AP move in IDLE state\n");
18627 return bytes_written;
18628 }
18629
18630 }
18631
18632 abort = bcm_atoi(data);
18633 if (abort == -1) {
18634 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &abort,
18635 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
18636 WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
18637 return err;
18638 }
18639 } else {
18640 chanspec = wf_chspec_aton(data);
18641 if (chanspec != 0) {
18642 val = wl_chspec_host_to_driver(chanspec);
18643 if (val != INVCHANSPEC) {
18644 if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &val,
18645 sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
18646 WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
18647 return err;
18648 }
18649 WL_DBG((" set dfs_ap_move successfull"));
18650 } else {
18651 err = BCME_USAGE_ERROR;
18652 }
18653 }
18654 }
18655 return err;
18656 }
18657
18658 #ifdef WBTEXT
18659 s32
18660 wl_cfg80211_wbtext_set_default(struct net_device *ndev)
18661 {
18662 char commandp[WLC_IOCTL_SMLEN];
18663 s32 ret = BCME_OK;
18664 char *data;
18665
18666 WL_DBG(("set wbtext to default\n"));
18667
18668 /* set roam profile */
18669 memset(commandp, 0, sizeof(commandp));
18670 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18671 CMD_WBTEXT_PROFILE_CONFIG, DEFAULT_WBTEXT_PROFILE_A);
18672 data = (commandp + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
18673 ret = wl_cfg80211_wbtext_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18674 if (ret != BCME_OK) {
18675 WL_ERR(("%s: Failed to set roam_prof %s error = %d\n",
18676 __FUNCTION__, data, ret));
18677 return ret;
18678 }
18679
18680 memset(commandp, 0, sizeof(commandp));
18681 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18682 CMD_WBTEXT_PROFILE_CONFIG, DEFAULT_WBTEXT_PROFILE_B);
18683 data = (commandp + strlen(CMD_WBTEXT_PROFILE_CONFIG) + 1);
18684 ret = wl_cfg80211_wbtext_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18685 if (ret != BCME_OK) {
18686 WL_ERR(("%s: Failed to set roam_prof %s error = %d\n",
18687 __FUNCTION__, data, ret));
18688 return ret;
18689 }
18690
18691 /* set RSSI weight */
18692 memset(commandp, 0, sizeof(commandp));
18693 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18694 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_RSSI_A);
18695 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
18696 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18697 if (ret != BCME_OK) {
18698 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18699 __FUNCTION__, data, ret));
18700 return ret;
18701 }
18702
18703 memset(commandp, 0, sizeof(commandp));
18704 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18705 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_RSSI_B);
18706 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
18707 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18708 if (ret != BCME_OK) {
18709 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18710 __FUNCTION__, data, ret));
18711 return ret;
18712 }
18713
18714 /* set CU weight */
18715 memset(commandp, 0, sizeof(commandp));
18716 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18717 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_CU_A);
18718 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
18719 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18720 if (ret != BCME_OK) {
18721 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18722 __FUNCTION__, data, ret));
18723 return ret;
18724 }
18725
18726 memset(commandp, 0, sizeof(commandp));
18727 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18728 CMD_WBTEXT_WEIGHT_CONFIG, DEFAULT_WBTEXT_WEIGHT_CU_B);
18729 data = (commandp + strlen(CMD_WBTEXT_WEIGHT_CONFIG) + 1);
18730 ret = wl_cfg80211_wbtext_weight_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18731 if (ret != BCME_OK) {
18732 WL_ERR(("%s: Failed to set weight config %s error = %d\n",
18733 __FUNCTION__, data, ret));
18734 return ret;
18735 }
18736
18737 /* set RSSI table */
18738 memset(commandp, 0, sizeof(commandp));
18739 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18740 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_RSSI_A);
18741 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
18742 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18743 if (ret != BCME_OK) {
18744 WL_ERR(("%s: Failed to set RSSI table %s error = %d\n",
18745 __FUNCTION__, data, ret));
18746 return ret;
18747 }
18748
18749 memset(commandp, 0, sizeof(commandp));
18750 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18751 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_RSSI_B);
18752 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
18753 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18754 if (ret != BCME_OK) {
18755 WL_ERR(("%s: Failed to set RSSI table %s error = %d\n",
18756 __FUNCTION__, data, ret));
18757 return ret;
18758 }
18759
18760 /* set CU table */
18761 memset(commandp, 0, sizeof(commandp));
18762 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18763 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_CU_A);
18764 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
18765 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18766 if (ret != BCME_OK) {
18767 WL_ERR(("%s: Failed to set CU table %s error = %d\n",
18768 __FUNCTION__, data, ret));
18769 return ret;
18770 }
18771
18772 memset(commandp, 0, sizeof(commandp));
18773 snprintf(commandp, WLC_IOCTL_SMLEN, "%s %s",
18774 CMD_WBTEXT_TABLE_CONFIG, DEFAULT_WBTEXT_TABLE_CU_B);
18775 data = (commandp + strlen(CMD_WBTEXT_TABLE_CONFIG) + 1);
18776 ret = wl_cfg80211_wbtext_table_config(ndev, data, commandp, WLC_IOCTL_SMLEN);
18777 if (ret != BCME_OK) {
18778 WL_ERR(("%s: Failed to set CU table %s error = %d\n",
18779 __FUNCTION__, data, ret));
18780 return ret;
18781 }
18782
18783 return ret;
18784 }
18785
18786 s32
18787 wl_cfg80211_wbtext_config(struct net_device *ndev, char *data, char *command, int total_len)
18788 {
18789 uint i = 0;
18790 long int rssi_lower, roam_trigger;
18791 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
18792 wl_roam_prof_band_t *rp;
18793 int err = -EINVAL, bytes_written = 0;
18794 size_t len = strlen(data);
18795 int rp_len = 0;
18796 data[len] = '\0';
18797 rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
18798 * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
18799 if (unlikely(!rp)) {
18800 WL_ERR(("%s: failed to allocate memory\n", __func__));
18801 err = -ENOMEM;
18802 goto exit;
18803 }
18804 rp->ver = WL_MAX_ROAM_PROF_VER;
18805 if (*data && (!strncmp(data, "b", 1))) {
18806 rp->band = WLC_BAND_2G;
18807 } else if (*data && (!strncmp(data, "a", 1))) {
18808 rp->band = WLC_BAND_5G;
18809 } else {
18810 err = snprintf(command, total_len, "Missing band\n");
18811 goto exit;
18812 }
18813 data++;
18814 rp->len = 0;
18815 /* Getting roam profile from fw */
18816 if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
18817 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
18818 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
18819 goto exit;
18820 }
18821 memcpy(rp, cfg->ioctl_buf, sizeof(*rp) * WL_MAX_ROAM_PROF_BRACKETS);
18822 /* roam_prof version get */
18823 if (rp->ver != WL_MAX_ROAM_PROF_VER) {
18824 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
18825 err = -EINVAL;
18826 goto exit;
18827 }
18828 if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
18829 WL_ERR(("bad length (=%d) in return data\n", rp->len));
18830 err = -EINVAL;
18831 goto exit;
18832 }
18833
18834 if (!*data) {
18835 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
18836 /* printing contents of roam profile data from fw and exits
18837 * if code hits any of one of the below condtion. If remaining
18838 * length of buffer is less than roam profile size or
18839 * if there is no valid entry.
18840 */
18841 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
18842 (rp->roam_prof[i].fullscan_period == 0)) {
18843 break;
18844 }
18845 bytes_written += snprintf(command+bytes_written,
18846 total_len, "RSSI[%d,%d] CU(trigger:%d%%: duration:%ds)\n",
18847 rp->roam_prof[i].roam_trigger, rp->roam_prof[i].rssi_lower,
18848 rp->roam_prof[i].channel_usage,
18849 rp->roam_prof[i].cu_avg_calc_dur);
18850 }
18851 err = bytes_written;
18852 goto exit;
18853 } else {
18854 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
18855 /* reading contents of roam profile data from fw and exits
18856 * if code hits any of one of the below condtion, If remaining
18857 * length of buffer is less than roam profile size or if there
18858 * is no valid entry.
18859 */
18860 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
18861 (rp->roam_prof[i].fullscan_period == 0)) {
18862 break;
18863 }
18864 }
18865 /* Do not set roam_prof from upper layer if fw doesn't have 2 rows */
18866 if (i != 2) {
18867 WL_ERR(("FW must have 2 rows to fill roam_prof\n"));
18868 err = -EINVAL;
18869 goto exit;
18870 }
18871 /* setting roam profile to fw */
18872 data++;
18873 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
18874 roam_trigger = simple_strtol(data, &data, 10);
18875 if (roam_trigger >= 0) {
18876 WL_ERR(("roam trigger[%d] value must be negative\n", i));
18877 err = -EINVAL;
18878 goto exit;
18879 }
18880 rp->roam_prof[i].roam_trigger = roam_trigger;
18881 data++;
18882 rssi_lower = simple_strtol(data, &data, 10);
18883 if (rssi_lower >= 0) {
18884 WL_ERR(("rssi lower[%d] value must be negative\n", i));
18885 err = -EINVAL;
18886 goto exit;
18887 }
18888 rp->roam_prof[i].rssi_lower = rssi_lower;
18889 data++;
18890 rp->roam_prof[i].channel_usage = simple_strtol(data, &data, 10);
18891 data++;
18892 rp->roam_prof[i].cu_avg_calc_dur = simple_strtol(data, &data, 10);
18893
18894 rp_len += sizeof(wl_roam_prof_t);
18895
18896 if (*data == '\0') {
18897 break;
18898 }
18899 data++;
18900 }
18901 if (i != 1) {
18902 WL_ERR(("Only two roam_prof rows supported.\n"));
18903 err = -EINVAL;
18904 goto exit;
18905 }
18906 rp->len = rp_len;
18907 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
18908 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN,
18909 &cfg->ioctl_buf_sync)) < 0) {
18910 WL_ERR(("seting roam_profile failed with err %d\n", err));
18911 }
18912 }
18913 exit:
18914 if (rp) {
18915 kfree(rp);
18916 }
18917 return err;
18918 }
18919
18920 #define BUFSZ 5
18921
18922 #define _S(x) #x
18923 #define S(x) _S(x)
18924
18925 int wl_cfg80211_wbtext_weight_config(struct net_device *ndev, char *data,
18926 char *command, int total_len)
18927 {
18928 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
18929 int bytes_written = 0, err = -EINVAL, argc = 0;
18930 char rssi[BUFSZ], band[BUFSZ], weight[BUFSZ];
18931 char *endptr = NULL;
18932 wnm_bss_select_weight_cfg_t *bwcfg;
18933
18934 bwcfg = kzalloc(sizeof(*bwcfg), GFP_KERNEL);
18935 if (unlikely(!bwcfg)) {
18936 WL_ERR(("%s: failed to allocate memory\n", __func__));
18937 err = -ENOMEM;
18938 goto exit;
18939 }
18940 bwcfg->version = WNM_BSSLOAD_MONITOR_VERSION;
18941 bwcfg->type = 0;
18942 bwcfg->weight = 0;
18943
18944 argc = sscanf(data, "%"S(BUFSZ)"s %"S(BUFSZ)"s %"S(BUFSZ)"s", rssi, band, weight);
18945
18946 if (!strcasecmp(rssi, "rssi"))
18947 bwcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
18948 else if (!strcasecmp(rssi, "cu"))
18949 bwcfg->type = WNM_BSS_SELECT_TYPE_CU;
18950 else {
18951 /* Usage DRIVER WBTEXT_WEIGHT_CONFIG <rssi/cu> <band> <weight> */
18952 WL_ERR(("%s: Command usage error\n", __func__));
18953 goto exit;
18954 }
18955
18956 if (!strcasecmp(band, "a"))
18957 bwcfg->band = WLC_BAND_5G;
18958 else if (!strcasecmp(band, "b"))
18959 bwcfg->band = WLC_BAND_2G;
18960 else if (!strcasecmp(band, "all"))
18961 bwcfg->band = WLC_BAND_ALL;
18962 else {
18963 WL_ERR(("%s: Command usage error\n", __func__));
18964 goto exit;
18965 }
18966
18967 if (argc == 2) {
18968 /* If there is no data after band, getting wnm_bss_select_weight from fw */
18969 if (bwcfg->band == WLC_BAND_ALL) {
18970 WL_ERR(("band option \"all\" is for set only, not get\n"));
18971 goto exit;
18972 }
18973 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_weight", bwcfg,
18974 sizeof(*bwcfg),
18975 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
18976 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d \n", err));
18977 goto exit;
18978 }
18979 memcpy(bwcfg, cfg->ioctl_buf, sizeof(*bwcfg));
18980 bytes_written = snprintf(command, total_len, "%s %s weight = %d\n",
18981 (bwcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU",
18982 (bwcfg->band == WLC_BAND_2G) ? "2G" : "5G", bwcfg->weight);
18983 err = bytes_written;
18984 goto exit;
18985 } else {
18986 /* if weight is non integer returns command usage error */
18987 bwcfg->weight = simple_strtol(weight, &endptr, 0);
18988 if (*endptr != '\0') {
18989 WL_ERR(("%s: Command usage error", __func__));
18990 goto exit;
18991 }
18992 /* setting weight for iovar wnm_bss_select_weight to fw */
18993 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_weight", bwcfg,
18994 sizeof(*bwcfg),
18995 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
18996 WL_ERR(("Getting wnm_bss_select_weight failed with err=%d\n", err));
18997 }
18998 }
18999 exit:
19000 if (bwcfg) {
19001 kfree(bwcfg);
19002 }
19003 return err;
19004 }
19005
19006 /* WBTEXT_TUPLE_MIN_LEN_CHECK :strlen(low)+" "+strlen(high)+" "+strlen(factor) */
19007 #define WBTEXT_TUPLE_MIN_LEN_CHECK 5
19008
19009 int wl_cfg80211_wbtext_table_config(struct net_device *ndev, char *data,
19010 char *command, int total_len)
19011 {
19012 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
19013 int bytes_written = 0, err = -EINVAL;
19014 char rssi[BUFSZ], band[BUFSZ];
19015 int btcfg_len = 0, i = 0, parsed_len = 0;
19016 wnm_bss_select_factor_cfg_t *btcfg;
19017 size_t slen = strlen(data);
19018 char *start_addr = NULL;
19019 data[slen] = '\0';
19020
19021 btcfg = kzalloc((sizeof(*btcfg) + sizeof(*btcfg) *
19022 WL_FACTOR_TABLE_MAX_LIMIT), GFP_KERNEL);
19023 if (unlikely(!btcfg)) {
19024 WL_ERR(("%s: failed to allocate memory\n", __func__));
19025 err = -ENOMEM;
19026 goto exit;
19027 }
19028
19029 btcfg->version = WNM_BSS_SELECT_FACTOR_VERSION;
19030 btcfg->band = WLC_BAND_AUTO;
19031 btcfg->type = 0;
19032 btcfg->count = 0;
19033
19034 sscanf(data, "%"S(BUFSZ)"s %"S(BUFSZ)"s", rssi, band);
19035
19036 if (!strcasecmp(rssi, "rssi")) {
19037 btcfg->type = WNM_BSS_SELECT_TYPE_RSSI;
19038 }
19039 else if (!strcasecmp(rssi, "cu")) {
19040 btcfg->type = WNM_BSS_SELECT_TYPE_CU;
19041 }
19042 else {
19043 WL_ERR(("%s: Command usage error\n", __func__));
19044 goto exit;
19045 }
19046
19047 if (!strcasecmp(band, "a")) {
19048 btcfg->band = WLC_BAND_5G;
19049 }
19050 else if (!strcasecmp(band, "b")) {
19051 btcfg->band = WLC_BAND_2G;
19052 }
19053 else if (!strcasecmp(band, "all")) {
19054 btcfg->band = WLC_BAND_ALL;
19055 }
19056 else {
19057 WL_ERR(("%s: Command usage, Wrong band\n", __func__));
19058 goto exit;
19059 }
19060
19061 if ((slen - 1) == (strlen(rssi) + strlen(band))) {
19062 /* Getting factor table using iovar 'wnm_bss_select_table' from fw */
19063 if ((err = wldev_iovar_getbuf(ndev, "wnm_bss_select_table", btcfg,
19064 sizeof(*btcfg),
19065 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
19066 WL_ERR(("Getting wnm_bss_select_table failed with err=%d \n", err));
19067 goto exit;
19068 }
19069 memcpy(btcfg, cfg->ioctl_buf, sizeof(*btcfg));
19070 memcpy(btcfg, cfg->ioctl_buf, (btcfg->count+1) * sizeof(*btcfg));
19071
19072 bytes_written += snprintf(command + bytes_written, total_len,
19073 "No of entries in table: %d\n", btcfg->count);
19074 bytes_written += snprintf(command + bytes_written, total_len, "%s factor table\n",
19075 (btcfg->type == WNM_BSS_SELECT_TYPE_RSSI) ? "RSSI" : "CU");
19076 bytes_written += snprintf(command + bytes_written, total_len,
19077 "low\thigh\tfactor\n");
19078 for (i = 0; i <= btcfg->count-1; i++) {
19079 bytes_written += snprintf(command + bytes_written, total_len,
19080 "%d\t%d\t%d\n", btcfg->params[i].low, btcfg->params[i].high,
19081 btcfg->params[i].factor);
19082 }
19083 err = bytes_written;
19084 goto exit;
19085 } else {
19086 memset(btcfg->params, 0, sizeof(wnm_bss_select_factor_params_t)
19087 * WL_FACTOR_TABLE_MAX_LIMIT);
19088 data += (strlen(rssi) + strlen(band) + 2);
19089 start_addr = data;
19090 slen = slen - (strlen(rssi) + strlen(band) + 2);
19091 for (i = 0; i < WL_FACTOR_TABLE_MAX_LIMIT; i++) {
19092 if (parsed_len + WBTEXT_TUPLE_MIN_LEN_CHECK <= slen) {
19093 btcfg->params[i].low = simple_strtol(data, &data, 10);
19094 data++;
19095 btcfg->params[i].high = simple_strtol(data, &data, 10);
19096 data++;
19097 btcfg->params[i].factor = simple_strtol(data, &data, 10);
19098 btcfg->count++;
19099 if (*data == '\0') {
19100 break;
19101 }
19102 data++;
19103 parsed_len = data - start_addr;
19104 } else {
19105 WL_ERR(("%s:Command usage:less no of args\n", __func__));
19106 goto exit;
19107 }
19108 }
19109 btcfg_len = sizeof(*btcfg) + ((btcfg->count) * sizeof(*btcfg));
19110 if ((err = wldev_iovar_setbuf(ndev, "wnm_bss_select_table", btcfg, btcfg_len,
19111 cfg->ioctl_buf, WLC_IOCTL_MEDLEN, &cfg->ioctl_buf_sync)) < 0) {
19112 WL_ERR(("seting wnm_bss_select_table failed with err %d\n", err));
19113 goto exit;
19114 }
19115 }
19116 exit:
19117 if (btcfg) {
19118 kfree(btcfg);
19119 }
19120 return err;
19121 }
19122
19123 s32
19124 wl_cfg80211_wbtext_delta_config(struct net_device *ndev, char *data, char *command, int total_len)
19125 {
19126 uint i = 0;
19127 struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
19128 int err = -EINVAL, bytes_written = 0, argc = 0, val, len = 0;
19129 char delta[BUFSZ], band[BUFSZ], *endptr = NULL;
19130 wl_roam_prof_band_t *rp;
19131
19132 rp = (wl_roam_prof_band_t *) kzalloc(sizeof(*rp)
19133 * WL_MAX_ROAM_PROF_BRACKETS, GFP_KERNEL);
19134 if (unlikely(!rp)) {
19135 WL_ERR(("%s: failed to allocate memory\n", __func__));
19136 err = -ENOMEM;
19137 goto exit;
19138 }
19139
19140 argc = sscanf(data, "%"S(BUFSZ)"s %"S(BUFSZ)"s", band, delta);
19141 if (!strcasecmp(band, "a"))
19142 rp->band = WLC_BAND_5G;
19143 else if (!strcasecmp(band, "b"))
19144 rp->band = WLC_BAND_2G;
19145 else {
19146 WL_ERR(("%s: Missing band\n", __func__));
19147 goto exit;
19148 }
19149 /* Getting roam profile from fw */
19150 if ((err = wldev_iovar_getbuf(ndev, "roam_prof", rp, sizeof(*rp),
19151 cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync))) {
19152 WL_ERR(("Getting roam_profile failed with err=%d \n", err));
19153 goto exit;
19154 }
19155 memcpy(rp, cfg->ioctl_buf, sizeof(wl_roam_prof_band_t));
19156 if (rp->ver != WL_MAX_ROAM_PROF_VER) {
19157 WL_ERR(("bad version (=%d) in return data\n", rp->ver));
19158 err = -EINVAL;
19159 goto exit;
19160 }
19161 if ((rp->len % sizeof(wl_roam_prof_t)) != 0) {
19162 WL_ERR(("bad length (=%d) in return data\n", rp->len));
19163 err = -EINVAL;
19164 goto exit;
19165 }
19166
19167 if (argc == 2) {
19168 /* if delta is non integer returns command usage error */
19169 val = simple_strtol(delta, &endptr, 0);
19170 if (*endptr != '\0') {
19171 WL_ERR(("%s: Command usage error", __func__));
19172 goto exit;
19173 }
19174 for (i = 0; i < WL_MAX_ROAM_PROF_BRACKETS; i++) {
19175 /*
19176 * Checking contents of roam profile data from fw and exits
19177 * if code hits below condtion. If remaining length of buffer is
19178 * less than roam profile size or if there is no valid entry.
19179 */
19180 if (((i * sizeof(wl_roam_prof_t)) > rp->len) ||
19181 (rp->roam_prof[i].fullscan_period == 0)) {
19182 break;
19183 }
19184 if (rp->roam_prof[i].channel_usage != 0) {
19185 rp->roam_prof[i].roam_delta = val;
19186 }
19187 len += sizeof(wl_roam_prof_t);
19188 }
19189 }
19190 else {
19191 if (rp->roam_prof[i].channel_usage != 0) {
19192 bytes_written = snprintf(command, total_len,
19193 "%s Delta %d\n", (rp->band == WLC_BAND_2G) ? "2G" : "5G",
19194 rp->roam_prof[0].roam_delta);
19195 }
19196 err = bytes_written;
19197 goto exit;
19198 }
19199 rp->len = len;
19200 if ((err = wldev_iovar_setbuf(ndev, "roam_prof", rp,
19201 sizeof(*rp), cfg->ioctl_buf, WLC_IOCTL_MEDLEN, &cfg->ioctl_buf_sync)) < 0) {
19202 WL_ERR(("seting roam_profile failed with err %d\n", err));
19203 }
19204 exit :
19205 if (rp) {
19206 kfree(rp);
19207 }
19208 return err;
19209 }
19210 #endif /* WBTEXT */
19211
19212
19213 int wl_cfg80211_scan_stop(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev)
19214 {
19215 struct net_device *ndev = NULL;
19216 unsigned long flags;
19217 int clear_flag = 0;
19218 int ret = 0;
19219 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
19220 struct cfg80211_scan_info info;
19221 #endif
19222
19223 WL_TRACE(("Enter\n"));
19224
19225 if (!cfg)
19226 return -EINVAL;
19227
19228 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
19229
19230 spin_lock_irqsave(&cfg->cfgdrv_lock, flags);
19231 #ifdef WL_CFG80211_P2P_DEV_IF
19232 if (cfg->scan_request && cfg->scan_request->wdev == cfgdev)
19233 #else
19234 if (cfg->scan_request && cfg->scan_request->dev == cfgdev)
19235 #endif
19236 {
19237 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
19238 info.aborted = true;
19239 cfg80211_scan_done(cfg->scan_request, &info);
19240 #else
19241 cfg80211_scan_done(cfg->scan_request, true);
19242 #endif
19243 cfg->scan_request = NULL;
19244 clear_flag = 1;
19245 }
19246 spin_unlock_irqrestore(&cfg->cfgdrv_lock, flags);
19247
19248 if (clear_flag)
19249 wl_clr_drv_status(cfg, SCANNING, ndev);
19250
19251 return ret;
19252 }
19253
19254 bool wl_cfg80211_is_concurrent_mode(struct net_device *dev)
19255 {
19256 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
19257 if ((cfg) && (wl_get_drv_status_all(cfg, CONNECTED) > 1)) {
19258 return true;
19259 } else {
19260 return false;
19261 }
19262 }
19263
19264 void* wl_cfg80211_get_dhdp(struct net_device *dev)
19265 {
19266 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
19267
19268 return cfg->pub;
19269 }
19270
19271 bool wl_cfg80211_is_p2p_active(struct net_device *dev)
19272 {
19273 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
19274 return (cfg && cfg->p2p);
19275 }
19276
19277 bool wl_cfg80211_is_roam_offload(struct net_device * dev)
19278 {
19279 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
19280 return (cfg && cfg->roam_offload);
19281 }
19282
19283 bool wl_cfg80211_is_event_from_connected_bssid(struct net_device * dev, const wl_event_msg_t *e,
19284 int ifidx)
19285 {
19286 u8 *curbssid = NULL;
19287 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
19288
19289 if (!cfg) {
19290 /* When interface is created using wl
19291 * ndev->ieee80211_ptr will be NULL.
19292 */
19293 return NULL;
19294 }
19295 curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
19296
19297 if (!curbssid) {
19298 return NULL;
19299 }
19300
19301 if (memcmp(curbssid, &e->addr, ETHER_ADDR_LEN) == 0) {
19302 return true;
19303 }
19304 return false;
19305 }
19306
19307 static void wl_cfg80211_work_handler(struct work_struct * work)
19308 {
19309 struct bcm_cfg80211 *cfg = NULL;
19310 struct net_info *iter, *next;
19311 s32 err = BCME_OK;
19312 s32 pm = PM_FAST;
19313 dhd_pub_t *dhd;
19314 BCM_SET_CONTAINER_OF(cfg, work, struct bcm_cfg80211, pm_enable_work.work);
19315 WL_DBG(("Enter \n"));
19316 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19317 4 && __GNUC_MINOR__ >= 6))
19318 _Pragma("GCC diagnostic push")
19319 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19320 #endif
19321 for_each_ndev(cfg, iter, next) {
19322 /* p2p discovery iface ndev could be null */
19323 if (iter->ndev) {
19324 if (!wl_get_drv_status(cfg, CONNECTED, iter->ndev) ||
19325 (wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_BSS &&
19326 wl_get_mode_by_netdev(cfg, iter->ndev) != WL_MODE_IBSS))
19327 continue;
19328 if (iter->ndev) {
19329 dhd = (dhd_pub_t *)(cfg->pub);
19330 if (dhd_conf_get_pm(dhd) >= 0)
19331 pm = dhd_conf_get_pm(dhd);
19332 if ((err = wldev_ioctl_set(iter->ndev, WLC_SET_PM,
19333 &pm, sizeof(pm))) != 0) {
19334 if (err == -ENODEV)
19335 WL_DBG(("%s:netdev not ready\n",
19336 iter->ndev->name));
19337 else
19338 WL_ERR(("%s:error (%d)\n",
19339 iter->ndev->name, err));
19340 } else
19341 wl_cfg80211_update_power_mode(iter->ndev);
19342 }
19343 }
19344 }
19345 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19346 4 && __GNUC_MINOR__ >= 6))
19347 _Pragma("GCC diagnostic pop")
19348 #endif
19349 DHD_PM_WAKE_UNLOCK(cfg->pub);
19350 }
19351
19352 u8
19353 wl_get_action_category(void *frame, u32 frame_len)
19354 {
19355 u8 category;
19356 u8 *ptr = (u8 *)frame;
19357 if (frame == NULL)
19358 return DOT11_ACTION_CAT_ERR_MASK;
19359 if (frame_len < DOT11_ACTION_HDR_LEN)
19360 return DOT11_ACTION_CAT_ERR_MASK;
19361 category = ptr[DOT11_ACTION_CAT_OFF];
19362 WL_INFORM(("Action Category: %d\n", category));
19363 return category;
19364 }
19365
19366 int
19367 wl_get_public_action(void *frame, u32 frame_len, u8 *ret_action)
19368 {
19369 u8 *ptr = (u8 *)frame;
19370 if (frame == NULL || ret_action == NULL)
19371 return BCME_ERROR;
19372 if (frame_len < DOT11_ACTION_HDR_LEN)
19373 return BCME_ERROR;
19374 if (DOT11_ACTION_CAT_PUBLIC != wl_get_action_category(frame, frame_len))
19375 return BCME_ERROR;
19376 *ret_action = ptr[DOT11_ACTION_ACT_OFF];
19377 WL_INFORM(("Public Action : %d\n", *ret_action));
19378 return BCME_OK;
19379 }
19380
19381
19382 static int
19383 wl_cfg80211_delayed_roam(struct bcm_cfg80211 *cfg, struct net_device *ndev,
19384 const struct ether_addr *bssid)
19385 {
19386 s32 err;
19387 wl_event_msg_t e;
19388
19389 bzero(&e, sizeof(e));
19390 e.event_type = cpu_to_be32(WLC_E_ROAM);
19391 memcpy(&e.addr, bssid, ETHER_ADDR_LEN);
19392 /* trigger the roam event handler */
19393 err = wl_notify_roaming_status(cfg, ndev_to_cfgdev(ndev), &e, NULL);
19394
19395 return err;
19396 }
19397
19398 static s32
19399 wl_cfg80211_parse_vndr_ies(u8 *parse, u32 len,
19400 struct parsed_vndr_ies *vndr_ies)
19401 {
19402 s32 err = BCME_OK;
19403 vndr_ie_t *vndrie;
19404 bcm_tlv_t *ie;
19405 struct parsed_vndr_ie_info *parsed_info;
19406 u32 count = 0;
19407 s32 remained_len;
19408
19409 remained_len = (s32)len;
19410 memset(vndr_ies, 0, sizeof(*vndr_ies));
19411
19412 WL_DBG(("---> len %d\n", len));
19413 ie = (bcm_tlv_t *) parse;
19414 if (!bcm_valid_tlv(ie, remained_len))
19415 ie = NULL;
19416 while (ie) {
19417 if (count >= MAX_VNDR_IE_NUMBER)
19418 break;
19419 if (ie->id == DOT11_MNG_VS_ID) {
19420 vndrie = (vndr_ie_t *) ie;
19421 /* len should be bigger than OUI length + one data length at least */
19422 if (vndrie->len < (VNDR_IE_MIN_LEN + 1)) {
19423 WL_ERR(("%s: invalid vndr ie. length is too small %d\n",
19424 __FUNCTION__, vndrie->len));
19425 goto end;
19426 }
19427 /* if wpa or wme ie, do not add ie */
19428 if (!bcmp(vndrie->oui, (u8*)WPA_OUI, WPA_OUI_LEN) &&
19429 ((vndrie->data[0] == WPA_OUI_TYPE) ||
19430 (vndrie->data[0] == WME_OUI_TYPE))) {
19431 WL_DBG(("Found WPA/WME oui. Do not add it\n"));
19432 goto end;
19433 }
19434
19435 parsed_info = &vndr_ies->ie_info[count++];
19436
19437 /* save vndr ie information */
19438 parsed_info->ie_ptr = (char *)vndrie;
19439 parsed_info->ie_len = (vndrie->len + TLV_HDR_LEN);
19440 memcpy(&parsed_info->vndrie, vndrie, sizeof(vndr_ie_t));
19441 vndr_ies->count = count;
19442
19443 WL_DBG(("\t ** OUI %02x %02x %02x, type 0x%02x len:%d\n",
19444 parsed_info->vndrie.oui[0], parsed_info->vndrie.oui[1],
19445 parsed_info->vndrie.oui[2], parsed_info->vndrie.data[0],
19446 parsed_info->ie_len));
19447 }
19448 end:
19449 ie = bcm_next_tlv(ie, &remained_len);
19450 }
19451 return err;
19452 }
19453
19454 #ifdef WLADPS_SEAK_AP_WAR
19455 static bool
19456 wl_find_vndr_ies_specific_vender(struct bcm_cfg80211 *cfg,
19457 struct net_device *ndev, const u8 *vndr_oui)
19458 {
19459 struct wl_connect_info *conn_info = wl_to_conn(cfg);
19460 struct parsed_vndr_ie_info *vndr_info_list;
19461 struct parsed_vndr_ies vndr_ies;
19462 bool ret = FALSE;
19463 int i;
19464
19465 if (conn_info->resp_ie_len) {
19466 if ((wl_cfg80211_parse_vndr_ies((u8 *)conn_info->resp_ie,
19467 conn_info->resp_ie_len, &vndr_ies)) == BCME_OK) {
19468 for (i = 0; i < vndr_ies.count; i++) {
19469 vndr_info_list = &vndr_ies.ie_info[i];
19470 if (!bcmp(vndr_info_list->vndrie.oui,
19471 (u8*)vndr_oui, DOT11_OUI_LEN)) {
19472 WL_ERR(("Find OUI %02x %02x %02x\n",
19473 vndr_info_list->vndrie.oui[0],
19474 vndr_info_list->vndrie.oui[1],
19475 vndr_info_list->vndrie.oui[2]));
19476 ret = TRUE;
19477 break;
19478 }
19479 }
19480 }
19481 }
19482 return ret;
19483 }
19484
19485 static s32
19486 wl_set_adps_mode(struct bcm_cfg80211 *cfg, struct net_device *ndev, uint8 enable_mode)
19487 {
19488 int i;
19489 int len;
19490 int ret = BCME_OK;
19491
19492 bcm_iov_buf_t *iov_buf = NULL;
19493 wl_adps_params_v1_t *data = NULL;
19494
19495 len = OFFSETOF(bcm_iov_buf_t, data) + sizeof(*data);
19496 iov_buf = kmalloc(len, GFP_KERNEL);
19497 if (iov_buf == NULL) {
19498 WL_ERR(("%s - failed to allocate %d bytes for iov_buf\n", __FUNCTION__, len));
19499 ret = BCME_NOMEM;
19500 goto exit;
19501 }
19502
19503 iov_buf->version = WL_ADPS_IOV_VER;
19504 iov_buf->len = sizeof(*data);
19505 iov_buf->id = WL_ADPS_IOV_MODE;
19506
19507 data = (wl_adps_params_v1_t *)iov_buf->data;
19508 data->version = ADPS_SUB_IOV_VERSION_1;
19509 data->length = sizeof(*data);
19510 data->mode = enable_mode;
19511
19512 for (i = 1; i <= MAX_BANDS; i++) {
19513 data->band = i;
19514 ret = wldev_iovar_setbuf(ndev, "adps", iov_buf, len,
19515 cfg->ioctl_buf, WLC_IOCTL_SMLEN, NULL);
19516 }
19517
19518 exit:
19519 if (iov_buf) {
19520 kfree(iov_buf);
19521 }
19522 return ret;
19523
19524 }
19525 #endif /* WLADPS_SEAK_AP_WAR */
19526
19527 static bool
19528 wl_vndr_ies_exclude_vndr_oui(struct parsed_vndr_ie_info *vndr_info)
19529 {
19530 int i = 0;
19531
19532 while (exclude_vndr_oui_list[i]) {
19533 if (!memcmp(vndr_info->vndrie.oui,
19534 exclude_vndr_oui_list[i],
19535 DOT11_OUI_LEN)) {
19536 return TRUE;
19537 }
19538 i++;
19539 }
19540
19541 return FALSE;
19542 }
19543
19544 static bool
19545 wl_vndr_ies_check_duplicate_vndr_oui(struct bcm_cfg80211 *cfg,
19546 struct parsed_vndr_ie_info *vndr_info)
19547 {
19548 wl_vndr_oui_entry_t *oui_entry = NULL;
19549
19550 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19551 #pragma GCC diagnostic push
19552 #pragma GCC diagnostic ignored "-Wcast-qual"
19553 #endif
19554 list_for_each_entry(oui_entry, &cfg->vndr_oui_list, list) {
19555 if (!memcmp(oui_entry->oui, vndr_info->vndrie.oui, DOT11_OUI_LEN)) {
19556 return TRUE;
19557 }
19558 }
19559 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19560 #pragma GCC diagnostic pop
19561 #endif
19562
19563 return FALSE;
19564 }
19565
19566 static bool
19567 wl_vndr_ies_add_vendor_oui_list(struct bcm_cfg80211 *cfg,
19568 struct parsed_vndr_ie_info *vndr_info)
19569 {
19570 wl_vndr_oui_entry_t *oui_entry = NULL;
19571
19572 oui_entry = kmalloc(sizeof(*oui_entry), GFP_KERNEL);
19573 if (oui_entry == NULL) {
19574 WL_ERR(("alloc failed\n"));
19575 return FALSE;
19576 }
19577
19578 memcpy(oui_entry->oui, vndr_info->vndrie.oui, DOT11_OUI_LEN);
19579
19580 INIT_LIST_HEAD(&oui_entry->list);
19581 list_add_tail(&oui_entry->list, &cfg->vndr_oui_list);
19582
19583 return TRUE;
19584 }
19585
19586 static void
19587 wl_vndr_ies_clear_vendor_oui_list(struct bcm_cfg80211 *cfg)
19588 {
19589 wl_vndr_oui_entry_t *oui_entry = NULL;
19590
19591 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19592 #pragma GCC diagnostic push
19593 #pragma GCC diagnostic ignored "-Wcast-qual"
19594 #endif
19595 while (!list_empty(&cfg->vndr_oui_list)) {
19596 oui_entry = list_entry(cfg->vndr_oui_list.next, wl_vndr_oui_entry_t, list);
19597 if (oui_entry) {
19598 list_del(&oui_entry->list);
19599 kfree(oui_entry);
19600 }
19601 }
19602 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19603 #pragma GCC diagnostic pop
19604 #endif
19605 }
19606
19607 static int
19608 wl_vndr_ies_get_vendor_oui(struct bcm_cfg80211 *cfg, struct net_device *ndev,
19609 char *vndr_oui, u32 vndr_oui_len)
19610 {
19611 int i;
19612 int vndr_oui_num = 0;
19613
19614 struct wl_connect_info *conn_info = wl_to_conn(cfg);
19615 wl_vndr_oui_entry_t *oui_entry = NULL;
19616 struct parsed_vndr_ie_info *vndr_info;
19617 struct parsed_vndr_ies vndr_ies;
19618
19619 char *pos = vndr_oui;
19620 u32 remained_buf_len = vndr_oui_len;
19621
19622 if (!conn_info->resp_ie_len) {
19623 return BCME_ERROR;
19624 }
19625
19626 wl_vndr_ies_clear_vendor_oui_list(cfg);
19627
19628 if ((wl_cfg80211_parse_vndr_ies((u8 *)conn_info->resp_ie,
19629 conn_info->resp_ie_len, &vndr_ies)) == BCME_OK) {
19630 for (i = 0; i < vndr_ies.count; i++) {
19631 vndr_info = &vndr_ies.ie_info[i];
19632 if (wl_vndr_ies_exclude_vndr_oui(vndr_info)) {
19633 continue;
19634 }
19635
19636 if (wl_vndr_ies_check_duplicate_vndr_oui(cfg, vndr_info)) {
19637 continue;
19638 }
19639
19640 wl_vndr_ies_add_vendor_oui_list(cfg, vndr_info);
19641 vndr_oui_num++;
19642 }
19643 }
19644
19645 if (vndr_oui) {
19646 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19647 #pragma GCC diagnostic push
19648 #pragma GCC diagnostic ignored "-Wcast-qual"
19649 #endif
19650 list_for_each_entry(oui_entry, &cfg->vndr_oui_list, list) {
19651 if (remained_buf_len < VNDR_OUI_STR_LEN) {
19652 return BCME_ERROR;
19653 }
19654 pos += snprintf(pos, VNDR_OUI_STR_LEN, "%02X-%02X-%02X ",
19655 oui_entry->oui[0], oui_entry->oui[1], oui_entry->oui[2]);
19656 remained_buf_len -= VNDR_OUI_STR_LEN;
19657 }
19658 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19659 #pragma GCC diagnostic pop
19660 #endif
19661 }
19662
19663 return vndr_oui_num;
19664 }
19665
19666 int
19667 wl_cfg80211_get_vndr_ouilist(struct bcm_cfg80211 *cfg, uint8 *buf, int max_cnt)
19668 {
19669 wl_vndr_oui_entry_t *oui_entry = NULL;
19670 int cnt = 0;
19671
19672 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19673 #pragma GCC diagnostic push
19674 #pragma GCC diagnostic ignored "-Wcast-qual"
19675 #endif
19676 list_for_each_entry(oui_entry, &cfg->vndr_oui_list, list) {
19677 memcpy(buf, oui_entry->oui, DOT11_OUI_LEN);
19678 cnt++;
19679 if (cnt >= max_cnt) {
19680 return cnt;
19681 }
19682 buf += DOT11_OUI_LEN;
19683 }
19684 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
19685 #pragma GCC diagnostic pop
19686 #endif
19687 return cnt;
19688 }
19689
19690 s32
19691 wl_cfg80211_clear_per_bss_ies(struct bcm_cfg80211 *cfg, s32 bssidx)
19692 {
19693 s32 index;
19694 struct net_info *netinfo;
19695 s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG,
19696 VNDR_IE_ASSOCRSP_FLAG, VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG};
19697
19698 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
19699 if (!netinfo || !netinfo->wdev) {
19700 WL_ERR(("netinfo or netinfo->wdev is NULL\n"));
19701 return -1;
19702 }
19703
19704 WL_DBG(("clear management vendor IEs for bssidx:%d \n", bssidx));
19705 /* Clear the IEs set in the firmware so that host is in sync with firmware */
19706 for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) {
19707 if (wl_cfg80211_set_mgmt_vndr_ies(cfg, wdev_to_cfgdev(netinfo->wdev),
19708 bssidx, vndrie_flag[index], NULL, 0) < 0)
19709 WL_ERR(("vndr_ies clear failed. Ignoring.. \n"));
19710 }
19711
19712 return 0;
19713 }
19714
19715 s32
19716 wl_cfg80211_clear_mgmt_vndr_ies(struct bcm_cfg80211 *cfg)
19717 {
19718 struct net_info *iter, *next;
19719
19720 WL_DBG(("clear management vendor IEs \n"));
19721 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19722 4 && __GNUC_MINOR__ >= 6))
19723 _Pragma("GCC diagnostic push")
19724 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19725 #endif
19726 for_each_ndev(cfg, iter, next) {
19727 wl_cfg80211_clear_per_bss_ies(cfg, iter->bssidx);
19728 }
19729 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19730 4 && __GNUC_MINOR__ >= 6))
19731 _Pragma("GCC diagnostic pop")
19732 #endif
19733 return 0;
19734 }
19735
19736 #define WL_VNDR_IE_MAXLEN 2048
19737 static s8 g_mgmt_ie_buf[WL_VNDR_IE_MAXLEN];
19738 int
19739 wl_cfg80211_set_mgmt_vndr_ies(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
19740 s32 bssidx, s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
19741 {
19742 struct net_device *ndev = NULL;
19743 s32 ret = BCME_OK;
19744 u8 *curr_ie_buf = NULL;
19745 u8 *mgmt_ie_buf = NULL;
19746 u32 mgmt_ie_buf_len = 0;
19747 u32 *mgmt_ie_len = 0;
19748 u32 del_add_ie_buf_len = 0;
19749 u32 total_ie_buf_len = 0;
19750 u32 parsed_ie_buf_len = 0;
19751 struct parsed_vndr_ies old_vndr_ies;
19752 struct parsed_vndr_ies new_vndr_ies;
19753 s32 i;
19754 u8 *ptr;
19755 s32 remained_buf_len;
19756 wl_bss_vndr_ies_t *ies = NULL;
19757 struct net_info *netinfo;
19758
19759 WL_DBG(("Enter. pktflag:0x%x bssidx:%x vnd_ie_len:%d \n",
19760 pktflag, bssidx, vndr_ie_len));
19761
19762 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
19763
19764 if (bssidx > WL_MAX_IFS) {
19765 WL_ERR(("bssidx > supported concurrent Ifaces \n"));
19766 return -EINVAL;
19767 }
19768
19769 netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
19770 if (!netinfo) {
19771 WL_ERR(("net_info ptr is NULL \n"));
19772 return -EINVAL;
19773 }
19774
19775 /* Clear the global buffer */
19776 memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf));
19777 curr_ie_buf = g_mgmt_ie_buf;
19778 ies = &netinfo->bss.ies;
19779
19780 switch (pktflag) {
19781 case VNDR_IE_PRBRSP_FLAG :
19782 mgmt_ie_buf = ies->probe_res_ie;
19783 mgmt_ie_len = &ies->probe_res_ie_len;
19784 mgmt_ie_buf_len = sizeof(ies->probe_res_ie);
19785 break;
19786 case VNDR_IE_ASSOCRSP_FLAG :
19787 mgmt_ie_buf = ies->assoc_res_ie;
19788 mgmt_ie_len = &ies->assoc_res_ie_len;
19789 mgmt_ie_buf_len = sizeof(ies->assoc_res_ie);
19790 break;
19791 case VNDR_IE_BEACON_FLAG :
19792 mgmt_ie_buf = ies->beacon_ie;
19793 mgmt_ie_len = &ies->beacon_ie_len;
19794 mgmt_ie_buf_len = sizeof(ies->beacon_ie);
19795 break;
19796 case VNDR_IE_PRBREQ_FLAG :
19797 mgmt_ie_buf = ies->probe_req_ie;
19798 mgmt_ie_len = &ies->probe_req_ie_len;
19799 mgmt_ie_buf_len = sizeof(ies->probe_req_ie);
19800 break;
19801 case VNDR_IE_ASSOCREQ_FLAG :
19802 mgmt_ie_buf = ies->assoc_req_ie;
19803 mgmt_ie_len = &ies->assoc_req_ie_len;
19804 mgmt_ie_buf_len = sizeof(ies->assoc_req_ie);
19805 break;
19806 default:
19807 mgmt_ie_buf = NULL;
19808 mgmt_ie_len = NULL;
19809 WL_ERR(("not suitable packet type (%d)\n", pktflag));
19810 return BCME_ERROR;
19811 }
19812
19813 if (vndr_ie_len > mgmt_ie_buf_len) {
19814 WL_ERR(("extra IE size too big\n"));
19815 ret = -ENOMEM;
19816 } else {
19817 /* parse and save new vndr_ie in curr_ie_buff before comparing it */
19818 if (vndr_ie && vndr_ie_len && curr_ie_buf) {
19819 ptr = curr_ie_buf;
19820 /* must discard vndr_ie constness, attempt to change vndr_ie arg to non-const
19821 * causes cascade of errors in other places, fix involves const casts there
19822 */
19823 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19824 4 && __GNUC_MINOR__ >= 6))
19825 _Pragma("GCC diagnostic push")
19826 _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
19827 #endif
19828 if ((ret = wl_cfg80211_parse_vndr_ies((u8 *)vndr_ie,
19829 vndr_ie_len, &new_vndr_ies)) < 0) {
19830 WL_ERR(("parse vndr ie failed \n"));
19831 goto exit;
19832 }
19833 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
19834 4 && __GNUC_MINOR__ >= 6))
19835 _Pragma("GCC diagnostic pop")
19836 #endif
19837 for (i = 0; i < new_vndr_ies.count; i++) {
19838 struct parsed_vndr_ie_info *vndrie_info =
19839 &new_vndr_ies.ie_info[i];
19840
19841 if ((parsed_ie_buf_len + vndrie_info->ie_len) > WL_VNDR_IE_MAXLEN) {
19842 WL_ERR(("IE size is too big (%d > %d)\n",
19843 parsed_ie_buf_len, WL_VNDR_IE_MAXLEN));
19844 ret = -EINVAL;
19845 goto exit;
19846 }
19847
19848 memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr,
19849 vndrie_info->ie_len);
19850 parsed_ie_buf_len += vndrie_info->ie_len;
19851 }
19852 }
19853
19854 if (mgmt_ie_buf != NULL) {
19855 if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) &&
19856 (memcmp(mgmt_ie_buf, curr_ie_buf, parsed_ie_buf_len) == 0)) {
19857 WL_INFORM(("Previous mgmt IE is equals to current IE"));
19858 goto exit;
19859 }
19860
19861 /* parse old vndr_ie */
19862 if ((ret = wl_cfg80211_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len,
19863 &old_vndr_ies)) < 0) {
19864 WL_ERR(("parse vndr ie failed \n"));
19865 goto exit;
19866 }
19867 /* make a command to delete old ie */
19868 for (i = 0; i < old_vndr_ies.count; i++) {
19869 struct parsed_vndr_ie_info *vndrie_info =
19870 &old_vndr_ies.ie_info[i];
19871
19872 WL_INFORM(("DELETED ID : %d, Len: %d , OUI:%02x:%02x:%02x\n",
19873 vndrie_info->vndrie.id, vndrie_info->vndrie.len,
19874 vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
19875 vndrie_info->vndrie.oui[2]));
19876
19877 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
19878 pktflag, vndrie_info->vndrie.oui,
19879 vndrie_info->vndrie.id,
19880 vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
19881 vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
19882 "del");
19883
19884 curr_ie_buf += del_add_ie_buf_len;
19885 total_ie_buf_len += del_add_ie_buf_len;
19886 }
19887 }
19888
19889 *mgmt_ie_len = 0;
19890 /* Add if there is any extra IE */
19891 if (mgmt_ie_buf && parsed_ie_buf_len) {
19892 ptr = mgmt_ie_buf;
19893
19894 remained_buf_len = mgmt_ie_buf_len;
19895
19896 /* make a command to add new ie */
19897 for (i = 0; i < new_vndr_ies.count; i++) {
19898 struct parsed_vndr_ie_info *vndrie_info =
19899 &new_vndr_ies.ie_info[i];
19900
19901 WL_INFORM(("ADDED ID : %d, Len: %d(%d), OUI:%02x:%02x:%02x\n",
19902 vndrie_info->vndrie.id, vndrie_info->vndrie.len,
19903 vndrie_info->ie_len - 2,
19904 vndrie_info->vndrie.oui[0], vndrie_info->vndrie.oui[1],
19905 vndrie_info->vndrie.oui[2]));
19906
19907 del_add_ie_buf_len = wl_cfgp2p_vndr_ie(cfg, curr_ie_buf,
19908 pktflag, vndrie_info->vndrie.oui,
19909 vndrie_info->vndrie.id,
19910 vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN,
19911 vndrie_info->ie_len - VNDR_IE_FIXED_LEN,
19912 "add");
19913
19914 /* verify remained buf size before copy data */
19915 if (remained_buf_len >= vndrie_info->ie_len) {
19916 remained_buf_len -= vndrie_info->ie_len;
19917 } else {
19918 WL_ERR(("no space in mgmt_ie_buf: pktflag = %d, "
19919 "found vndr ies # = %d(cur %d), remained len %d, "
19920 "cur mgmt_ie_len %d, new ie len = %d\n",
19921 pktflag, new_vndr_ies.count, i, remained_buf_len,
19922 *mgmt_ie_len, vndrie_info->ie_len));
19923 break;
19924 }
19925
19926 /* save the parsed IE in cfg struct */
19927 memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr,
19928 vndrie_info->ie_len);
19929 *mgmt_ie_len += vndrie_info->ie_len;
19930 curr_ie_buf += del_add_ie_buf_len;
19931 total_ie_buf_len += del_add_ie_buf_len;
19932 }
19933 }
19934
19935 if (total_ie_buf_len && cfg->ioctl_buf != NULL) {
19936 ret = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", g_mgmt_ie_buf,
19937 total_ie_buf_len, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
19938 bssidx, &cfg->ioctl_buf_sync);
19939 if (ret)
19940 WL_ERR(("vndr ie set error : %d\n", ret));
19941 }
19942 }
19943 exit:
19944
19945 return ret;
19946 }
19947
19948 #ifdef WL_CFG80211_ACL
19949 static int
19950 wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
19951 const struct cfg80211_acl_data *acl)
19952 {
19953 int i;
19954 int ret = 0;
19955 int macnum = 0;
19956 int macmode = MACLIST_MODE_DISABLED;
19957 struct maclist *list;
19958
19959 /* get the MAC filter mode */
19960 if (acl && acl->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED) {
19961 macmode = MACLIST_MODE_ALLOW;
19962 } else if (acl && acl->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
19963 acl->n_acl_entries) {
19964 macmode = MACLIST_MODE_DENY;
19965 }
19966
19967 /* if acl == NULL, macmode is still disabled.. */
19968 if (macmode == MACLIST_MODE_DISABLED) {
19969 if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, NULL)) != 0)
19970 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
19971
19972 return ret;
19973 }
19974
19975 macnum = acl->n_acl_entries;
19976 if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
19977 WL_ERR(("%s : invalid number of MAC address entries %d\n",
19978 __FUNCTION__, macnum));
19979 return -1;
19980 }
19981
19982 /* allocate memory for the MAC list */
19983 list = (struct maclist*)kmalloc(sizeof(int) +
19984 sizeof(struct ether_addr) * macnum, GFP_KERNEL);
19985 if (!list) {
19986 WL_ERR(("%s : failed to allocate memory\n", __FUNCTION__));
19987 return -1;
19988 }
19989
19990 /* prepare the MAC list */
19991 list->count = htod32(macnum);
19992 for (i = 0; i < macnum; i++) {
19993 memcpy(&list->ea[i], &acl->mac_addrs[i], ETHER_ADDR_LEN);
19994 }
19995 /* set the list */
19996 if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, list)) != 0)
19997 WL_ERR(("%s : Setting MAC list failed error=%d\n", __FUNCTION__, ret));
19998
19999 kfree(list);
20000
20001 return ret;
20002 }
20003 #endif /* WL_CFG80211_ACL */
20004
20005 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
20006 int wl_chspec_chandef(chanspec_t chanspec,
20007 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
20008 struct cfg80211_chan_def *chandef,
20009 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
20010 struct chan_info *chaninfo,
20011 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
20012 struct wiphy *wiphy)
20013
20014 {
20015 uint16 freq = 0;
20016 int chan_type = 0;
20017 int channel = 0;
20018 struct ieee80211_channel *chan;
20019
20020 if (!chandef) {
20021 return -1;
20022 }
20023 channel = CHSPEC_CHANNEL(chanspec);
20024
20025 switch (CHSPEC_BW(chanspec)) {
20026 case WL_CHANSPEC_BW_20:
20027 chan_type = NL80211_CHAN_HT20;
20028 break;
20029 case WL_CHANSPEC_BW_40:
20030 {
20031 if (CHSPEC_SB_UPPER(chanspec)) {
20032 channel += CH_10MHZ_APART;
20033 } else {
20034 channel -= CH_10MHZ_APART;
20035 }
20036 }
20037 chan_type = NL80211_CHAN_HT40PLUS;
20038 break;
20039
20040 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20041 case WL_CHANSPEC_BW_80:
20042 case WL_CHANSPEC_BW_8080:
20043 {
20044 uint16 sb = CHSPEC_CTL_SB(chanspec);
20045
20046 if (sb == WL_CHANSPEC_CTL_SB_LL) {
20047 channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
20048 } else if (sb == WL_CHANSPEC_CTL_SB_LU) {
20049 channel -= CH_10MHZ_APART;
20050 } else if (sb == WL_CHANSPEC_CTL_SB_UL) {
20051 channel += CH_10MHZ_APART;
20052 } else {
20053 /* WL_CHANSPEC_CTL_SB_UU */
20054 channel += (CH_10MHZ_APART + CH_20MHZ_APART);
20055 }
20056
20057 if (sb == WL_CHANSPEC_CTL_SB_LL || sb == WL_CHANSPEC_CTL_SB_LU)
20058 chan_type = NL80211_CHAN_HT40MINUS;
20059 else if (sb == WL_CHANSPEC_CTL_SB_UL || sb == WL_CHANSPEC_CTL_SB_UU)
20060 chan_type = NL80211_CHAN_HT40PLUS;
20061 }
20062 break;
20063 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20064 default:
20065 chan_type = NL80211_CHAN_HT20;
20066 break;
20067
20068 }
20069
20070 if (CHSPEC_IS5G(chanspec))
20071 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_5GHZ);
20072 else
20073 freq = ieee80211_channel_to_frequency(channel, NL80211_BAND_2GHZ);
20074
20075 chan = ieee80211_get_channel(wiphy, freq);
20076 WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
20077 channel, freq, chan_type, chan));
20078
20079 if (unlikely(!chan)) {
20080 /* fw and cfg80211 channel lists are not in sync */
20081 WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
20082 ASSERT(0);
20083 return -EINVAL;
20084 }
20085
20086 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20087 cfg80211_chandef_create(chandef, chan, chan_type);
20088 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
20089 \
20090 \
20091 \
20092 0)))
20093 chaninfo->freq = freq;
20094 chaninfo->chan_type = chan_type;
20095 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20096 return 0;
20097 }
20098
20099 void
20100 wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
20101 {
20102 u32 freq;
20103 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20104 struct cfg80211_chan_def chandef;
20105 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, \
20106 \
20107 \
20108 \
20109 0)))
20110 struct chan_info chaninfo;
20111 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20112
20113 if (!wiphy) {
20114 printf("wiphy is null\n");
20115 return;
20116 }
20117 #ifndef ALLOW_CHSW_EVT
20118 /* Channel switch support is only for AP/GO/ADHOC/MESH */
20119 if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
20120 dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
20121 WL_ERR(("No channel switch notify support for STA/GC\n"));
20122 return;
20123 }
20124 #endif /* !ALLOW_CHSW_EVT */
20125 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20126 if (wl_chspec_chandef(chanspec, &chandef, wiphy))
20127 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
20128 if (wl_chspec_chandef(chanspec, &chaninfo, wiphy))
20129 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20130 {
20131 WL_ERR(("chspec_chandef failed\n"));
20132 return;
20133 }
20134 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
20135 freq = chandef.chan ? chandef.chan->center_freq : chandef.center_freq1;
20136 cfg80211_ch_switch_notify(dev, &chandef);
20137 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
20138 freq = chan_info.freq;
20139 cfg80211_ch_switch_notify(dev, freq, chan_info.chan_type);
20140 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
20141
20142 WL_ERR(("Channel switch notification for freq: %d chanspec: 0x%x\n", freq, chanspec));
20143 return;
20144 }
20145 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20146
20147 #ifdef WL11ULB
20148 s32
20149 wl_cfg80211_set_ulb_mode(struct net_device *dev, int mode)
20150 {
20151 int ret;
20152 int cur_mode;
20153
20154 ret = wldev_iovar_getint(dev, "ulb_mode", &cur_mode);
20155 if (unlikely(ret)) {
20156 WL_ERR(("[ULB] ulb_mode get failed. ret:%d \n", ret));
20157 return ret;
20158 }
20159
20160 if (cur_mode == mode) {
20161 /* If request mode is same as that of the current mode, then
20162 * do nothing (Avoid unnecessary wl down and up).
20163 */
20164 WL_INFORM(("[ULB] No change in ulb_mode. Do nothing.\n"));
20165 return 0;
20166 }
20167
20168 /* setting of ulb_mode requires wl to be down */
20169 ret = wldev_ioctl_set(dev, WLC_DOWN, NULL, 0);
20170 if (unlikely(ret)) {
20171 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
20172 return ret;
20173 }
20174
20175 if (mode >= MAX_SUPP_ULB_MODES) {
20176 WL_ERR(("[ULB] unsupported ulb_mode :[%d]\n", mode));
20177 return -EINVAL;
20178 }
20179
20180 ret = wldev_iovar_setint(dev, "ulb_mode", mode);
20181 if (unlikely(ret)) {
20182 WL_ERR(("[ULB] ulb_mode set failed. ret:%d \n", ret));
20183 return ret;
20184 }
20185
20186 ret = wldev_ioctl_set(dev, WLC_UP, NULL, 0);
20187 if (unlikely(ret)) {
20188 WL_ERR(("[ULB] WLC_DOWN command failed:[%d]\n", ret));
20189 return ret;
20190 }
20191
20192 WL_DBG(("[ULB] ulb_mode set to %d successfully \n", mode));
20193
20194 return ret;
20195 }
20196
20197 static s32
20198 wl_cfg80211_ulbbw_to_ulbchspec(u32 bw)
20199 {
20200 if (bw == ULB_BW_DISABLED) {
20201 return WL_CHANSPEC_BW_20;
20202 } else if (bw == ULB_BW_10MHZ) {
20203 return WL_CHANSPEC_BW_10;
20204 } else if (bw == ULB_BW_5MHZ) {
20205 return WL_CHANSPEC_BW_5;
20206 } else if (bw == ULB_BW_2P5MHZ) {
20207 return WL_CHANSPEC_BW_2P5;
20208 } else {
20209 WL_ERR(("[ULB] unsupported value for ulb_bw \n"));
20210 return -EINVAL;
20211 }
20212 }
20213
20214 static chanspec_t
20215 wl_cfg80211_ulb_get_min_bw_chspec(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev, s32 bssidx)
20216 {
20217 struct net_info *_netinfo;
20218
20219 /*
20220 * Return the chspec value corresponding to the
20221 * BW setting for a particular interface
20222 */
20223 if (wdev) {
20224 /* if wdev is provided, use it */
20225 _netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
20226 } else if (bssidx >= 0) {
20227 /* if wdev is not provided, use it */
20228 _netinfo = wl_get_netinfo_by_bssidx(cfg, bssidx);
20229 } else {
20230 WL_ERR(("[ULB] wdev/bssidx not provided\n"));
20231 return INVCHANSPEC;
20232 }
20233
20234 if (unlikely(!_netinfo)) {
20235 WL_ERR(("[ULB] net_info is null \n"));
20236 return INVCHANSPEC;
20237 }
20238
20239 if (_netinfo->ulb_bw) {
20240 WL_DBG(("[ULB] wdev_ptr:%p ulb_bw:0x%x \n", _netinfo->wdev, _netinfo->ulb_bw));
20241 return wl_cfg80211_ulbbw_to_ulbchspec(_netinfo->ulb_bw);
20242 } else {
20243 return WL_CHANSPEC_BW_20;
20244 }
20245 }
20246
20247 static s32
20248 wl_cfg80211_get_ulb_bw(struct bcm_cfg80211 *cfg, struct wireless_dev *wdev)
20249 {
20250 struct net_info *_netinfo = wl_get_netinfo_by_wdev(cfg, wdev);
20251
20252 /*
20253 * Return the ulb_bw setting for a
20254 * particular interface
20255 */
20256 if (unlikely(!_netinfo)) {
20257 WL_ERR(("[ULB] net_info is null \n"));
20258 return -1;
20259 }
20260
20261 return _netinfo->ulb_bw;
20262 }
20263
20264 s32
20265 wl_cfg80211_set_ulb_bw(struct net_device *dev,
20266 u32 ulb_bw, char *ifname)
20267 {
20268 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20269 int ret;
20270 int mode;
20271 struct net_info *_netinfo = NULL, *iter, *next;
20272 u32 bssidx;
20273
20274 if (!ifname)
20275 return -EINVAL;
20276
20277 WL_DBG(("[ULB] Enter. bw_type:%d \n", ulb_bw));
20278
20279 ret = wldev_iovar_getint(dev, "ulb_mode", &mode);
20280 if (unlikely(ret)) {
20281 WL_ERR(("[ULB] ulb_mode not supported \n"));
20282 return ret;
20283 }
20284
20285 if (mode != ULB_MODE_STD_ALONE_MODE) {
20286 WL_ERR(("[ULB] ulb bw modification allowed only in stand-alone mode\n"));
20287 return -EINVAL;
20288 }
20289
20290 if (ulb_bw >= MAX_SUPP_ULB_BW) {
20291 WL_ERR(("[ULB] unsupported value (%d) for ulb_bw \n", ulb_bw));
20292 return -EINVAL;
20293 }
20294
20295 #ifdef WL_CFG80211_P2P_DEV_IF
20296 if (strcmp(ifname, "p2p-dev-wlan0") == 0) {
20297 /* Use wdev corresponding to the dedicated p2p discovery interface */
20298 if (likely(cfg->p2p_wdev)) {
20299 _netinfo = wl_get_netinfo_by_wdev(cfg, cfg->p2p_wdev);
20300 } else {
20301 return -ENODEV;
20302 }
20303 }
20304 #endif /* WL_CFG80211_P2P_DEV_IF */
20305 if (!_netinfo) {
20306 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20307 #pragma GCC diagnostic push
20308 #pragma GCC diagnostic ignored "-Wcast-qual"
20309 #endif
20310 for_each_ndev(cfg, iter, next) {
20311 if (iter->ndev) {
20312 if (strncmp(iter->ndev->name, ifname, strlen(ifname)) == 0) {
20313 _netinfo = wl_get_netinfo_by_netdev(cfg, iter->ndev);
20314 }
20315 }
20316 }
20317 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20318 #pragma GCC diagnostic pop
20319 #endif
20320 }
20321
20322 if (!_netinfo)
20323 return -ENODEV;
20324 bssidx = _netinfo->bssidx;
20325 _netinfo->ulb_bw = ulb_bw;
20326
20327
20328 WL_DBG(("[ULB] Applying ulb_bw:%d for bssidx:%d \n", ulb_bw, bssidx));
20329 ret = wldev_iovar_setbuf_bsscfg(dev, "ulb_bw", (void *)&ulb_bw, 4,
20330 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx,
20331 &cfg->ioctl_buf_sync);
20332 if (unlikely(ret)) {
20333 WL_ERR(("[ULB] ulb_bw set failed. ret:%d \n", ret));
20334 return ret;
20335 }
20336
20337 return ret;
20338 }
20339 #endif /* WL11ULB */
20340
20341 static void
20342 wl_ap_channel_ind(struct bcm_cfg80211 *cfg,
20343 struct net_device *ndev,
20344 chanspec_t chanspec)
20345 {
20346 u32 channel = LCHSPEC_CHANNEL(chanspec);
20347
20348 WL_DBG(("(%s) AP channel:%d chspec:0x%x \n",
20349 ndev->name, channel, chanspec));
20350 if (cfg->ap_oper_channel && (cfg->ap_oper_channel != channel)) {
20351 /*
20352 * If cached channel is different from the channel indicated
20353 * by the event, notify user space about the channel switch.
20354 */
20355 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
20356 wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
20357 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20358 cfg->ap_oper_channel = channel;
20359 }
20360 }
20361
20362 static s32
20363 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
20364 const wl_event_msg_t *e, void *data)
20365 {
20366 struct net_device *ndev = NULL;
20367 chanspec_t chanspec;
20368
20369 WL_DBG(("Enter\n"));
20370 if (unlikely(e->status)) {
20371 WL_ERR(("status:0x%x \n", e->status));
20372 return -1;
20373 }
20374
20375 if (!data) {
20376 return -EINVAL;
20377 }
20378
20379 if (likely(cfgdev)) {
20380 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
20381 chanspec = *((chanspec_t *)data);
20382
20383 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
20384 /* For AP/GO role */
20385 wl_ap_channel_ind(cfg, ndev, chanspec);
20386 }
20387 }
20388
20389 return 0;
20390 }
20391
20392 static s32
20393 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
20394 const wl_event_msg_t *e, void *data)
20395 {
20396 int error = 0;
20397 u32 chanspec = 0;
20398 struct net_device *ndev = NULL;
20399
20400 WL_DBG(("Enter\n"));
20401 if (unlikely(e->status)) {
20402 WL_ERR(("status:0x%x \n", e->status));
20403 return -1;
20404 }
20405
20406 if (likely(cfgdev)) {
20407 ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
20408 error = wldev_iovar_getint(ndev, "chanspec", &chanspec);
20409 if (unlikely(error)) {
20410 WL_ERR(("Get chanspec error: %d \n", error));
20411 return -1;
20412 }
20413
20414 if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
20415 /* For AP/GO role */
20416 wl_ap_channel_ind(cfg, ndev, chanspec);
20417 } else {
20418 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
20419 wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
20420 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
20421 }
20422
20423 }
20424
20425 return 0;
20426 }
20427
20428
20429 void wl_cfg80211_clear_security(struct bcm_cfg80211 *cfg)
20430 {
20431 struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
20432 int err;
20433
20434 /* Clear the security settings on the primary Interface */
20435 err = wldev_iovar_setint(dev, "wsec", 0);
20436 if (unlikely(err)) {
20437 WL_ERR(("wsec clear failed \n"));
20438 }
20439 err = wldev_iovar_setint(dev, "auth", 0);
20440 if (unlikely(err)) {
20441 WL_ERR(("auth clear failed \n"));
20442 }
20443 err = wldev_iovar_setint(dev, "wpa_auth", WPA_AUTH_DISABLED);
20444 if (unlikely(err)) {
20445 WL_ERR(("wpa_auth clear failed \n"));
20446 }
20447 }
20448
20449 #ifdef WL_CFG80211_P2P_DEV_IF
20450 void wl_cfg80211_del_p2p_wdev(struct net_device *dev)
20451 {
20452 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20453 struct wireless_dev *wdev = NULL;
20454
20455 WL_DBG(("Enter \n"));
20456 if (!cfg) {
20457 WL_ERR(("Invalid Ptr\n"));
20458 return;
20459 } else {
20460 wdev = cfg->p2p_wdev;
20461 }
20462
20463 if (wdev && cfg->down_disc_if) {
20464 wl_cfgp2p_del_p2p_disc_if(wdev, cfg);
20465 cfg->down_disc_if = FALSE;
20466 }
20467 }
20468 #endif /* WL_CFG80211_P2P_DEV_IF */
20469
20470 #ifdef GTK_OFFLOAD_SUPPORT
20471 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0))
20472 static s32
20473 wl_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev,
20474 struct cfg80211_gtk_rekey_data *data)
20475 {
20476 struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
20477 s32 err = 0;
20478 gtk_keyinfo_t keyinfo;
20479
20480 WL_DBG(("Enter\n"));
20481 if (data == NULL || cfg->p2p_net == dev) {
20482 WL_ERR(("data is NULL or wrong net device\n"));
20483 return -EINVAL;
20484 }
20485 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
20486 prhex("kck", (uchar *) (data->kck), RSN_KCK_LENGTH);
20487 prhex("kek", (uchar *) (data->kek), RSN_KEK_LENGTH);
20488 prhex("replay_ctr", (uchar *) (data->replay_ctr), RSN_REPLAY_LEN);
20489 #else
20490 prhex("kck", (uchar *)data->kck, RSN_KCK_LENGTH);
20491 prhex("kek", (uchar *)data->kek, RSN_KEK_LENGTH);
20492 prhex("replay_ctr", (uchar *)data->replay_ctr, RSN_REPLAY_LEN);
20493 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0) */
20494 bcopy(data->kck, keyinfo.KCK, RSN_KCK_LENGTH);
20495 bcopy(data->kek, keyinfo.KEK, RSN_KEK_LENGTH);
20496 bcopy(data->replay_ctr, keyinfo.ReplayCounter, RSN_REPLAY_LEN);
20497
20498 if ((err = wldev_iovar_setbuf(dev, "gtk_key_info", &keyinfo, sizeof(keyinfo),
20499 cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync)) < 0) {
20500 WL_ERR(("seting gtk_key_info failed code=%d\n", err));
20501 return err;
20502 }
20503 WL_DBG(("Exit\n"));
20504 return err;
20505 }
20506 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 1, 0) */
20507 #endif /* GTK_OFFLOAD_SUPPORT */
20508
20509 #if defined(WL_SUPPORT_AUTO_CHANNEL)
20510 int
20511 wl_cfg80211_set_spect(struct net_device *dev, int spect)
20512 {
20513 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20514 int wlc_down = 1;
20515 int wlc_up = 1;
20516 int err = BCME_OK;
20517
20518 if (!wl_get_drv_status_all(cfg, CONNECTED)) {
20519 err = wldev_ioctl_set(dev, WLC_DOWN, &wlc_down, sizeof(wlc_down));
20520 if (err) {
20521 WL_ERR(("%s: WLC_DOWN failed: code: %d\n", __func__, err));
20522 return err;
20523 }
20524
20525 err = wldev_ioctl_set(dev, WLC_SET_SPECT_MANAGMENT, &spect, sizeof(spect));
20526 if (err) {
20527 WL_ERR(("%s: error setting spect: code: %d\n", __func__, err));
20528 return err;
20529 }
20530
20531 err = wldev_ioctl_set(dev, WLC_UP, &wlc_up, sizeof(wlc_up));
20532 if (err) {
20533 WL_ERR(("%s: WLC_UP failed: code: %d\n", __func__, err));
20534 return err;
20535 }
20536 }
20537 return err;
20538 }
20539
20540 int
20541 wl_cfg80211_get_sta_channel(struct net_device *dev)
20542 {
20543 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20544 int channel = 0;
20545
20546 if (wl_get_drv_status(cfg, CONNECTED, dev)) {
20547 channel = cfg->channel;
20548 }
20549 return channel;
20550 }
20551 #endif /* WL_SUPPORT_AUTO_CHANNEL */
20552 #ifdef P2P_LISTEN_OFFLOADING
20553 s32
20554 wl_cfg80211_p2plo_deinit(struct bcm_cfg80211 *cfg)
20555 {
20556 s32 bssidx;
20557 int ret = 0;
20558 int p2plo_pause = 0;
20559 if (!cfg || !cfg->p2p) {
20560 WL_ERR(("Wl %p or cfg->p2p %p is null\n",
20561 cfg, cfg ? cfg->p2p : 0));
20562 return 0;
20563 }
20564
20565 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
20566 ret = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg),
20567 "p2po_stop", (void*)&p2plo_pause, sizeof(p2plo_pause),
20568 cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
20569 if (ret < 0) {
20570 WL_ERR(("p2po_stop Failed :%d\n", ret));
20571 }
20572
20573 return ret;
20574 }
20575 s32
20576 wl_cfg80211_p2plo_listen_start(struct net_device *dev, u8 *buf, int len)
20577 {
20578 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20579 s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
20580 wl_p2plo_listen_t p2plo_listen;
20581 int ret = -EAGAIN;
20582 int channel = 0;
20583 int period = 0;
20584 int interval = 0;
20585 int count = 0;
20586 if (WL_DRV_STATUS_SENDING_AF_FRM_EXT(cfg)) {
20587 WL_ERR(("Sending Action Frames. Try it again.\n"));
20588 goto exit;
20589 }
20590
20591 if (wl_get_drv_status_all(cfg, SCANNING)) {
20592 WL_ERR(("Scanning already\n"));
20593 goto exit;
20594 }
20595
20596 if (wl_get_drv_status(cfg, SCAN_ABORTING, dev)) {
20597 WL_ERR(("Scanning being aborted\n"));
20598 goto exit;
20599 }
20600
20601 if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
20602 WL_ERR(("p2p listen offloading already running\n"));
20603 goto exit;
20604 }
20605
20606 /* Just in case if it is not enabled */
20607 if ((ret = wl_cfgp2p_enable_discovery(cfg, dev, NULL, 0)) < 0) {
20608 WL_ERR(("cfgp2p_enable discovery failed"));
20609 goto exit;
20610 }
20611
20612 bzero(&p2plo_listen, sizeof(wl_p2plo_listen_t));
20613
20614 if (len) {
20615 sscanf(buf, " %10d %10d %10d %10d", &channel, &period, &interval, &count);
20616 if ((channel == 0) || (period == 0) ||
20617 (interval == 0) || (count == 0)) {
20618 WL_ERR(("Wrong argument %d/%d/%d/%d \n",
20619 channel, period, interval, count));
20620 ret = -EAGAIN;
20621 goto exit;
20622 }
20623 p2plo_listen.period = period;
20624 p2plo_listen.interval = interval;
20625 p2plo_listen.count = count;
20626
20627 WL_ERR(("channel:%d period:%d, interval:%d count:%d\n",
20628 channel, period, interval, count));
20629 } else {
20630 WL_ERR(("Argument len is wrong.\n"));
20631 ret = -EAGAIN;
20632 goto exit;
20633 }
20634
20635 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen_channel", (void*)&channel,
20636 sizeof(channel), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
20637 bssidx, &cfg->ioctl_buf_sync)) < 0) {
20638 WL_ERR(("p2po_listen_channel Failed :%d\n", ret));
20639 goto exit;
20640 }
20641
20642 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_listen", (void*)&p2plo_listen,
20643 sizeof(wl_p2plo_listen_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
20644 bssidx, &cfg->ioctl_buf_sync)) < 0) {
20645 WL_ERR(("p2po_listen Failed :%d\n", ret));
20646 goto exit;
20647 }
20648
20649 wl_set_p2p_status(cfg, DISC_IN_PROGRESS);
20650 exit :
20651 return ret;
20652 }
20653 s32
20654 wl_cfg80211_p2plo_listen_stop(struct net_device *dev)
20655 {
20656 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20657 s32 bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
20658 int ret = -EAGAIN;
20659
20660 if ((ret = wldev_iovar_setbuf_bsscfg(dev, "p2po_stop", NULL,
20661 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN,
20662 bssidx, &cfg->ioctl_buf_sync)) < 0) {
20663 WL_ERR(("p2po_stop Failed :%d\n", ret));
20664 goto exit;
20665 }
20666
20667 exit:
20668 return ret;
20669 }
20670 #endif /* P2P_LISTEN_OFFLOADING */
20671
20672 u64
20673 wl_cfg80211_get_new_roc_id(struct bcm_cfg80211 *cfg)
20674 {
20675 u64 id = 0;
20676 id = ++cfg->last_roc_id;
20677 #ifdef P2P_LISTEN_OFFLOADING
20678 if (id == P2PO_COOKIE) {
20679 id = ++cfg->last_roc_id;
20680 }
20681 #endif /* P2P_LISTEN_OFFLOADING */
20682 if (id == 0)
20683 id = ++cfg->last_roc_id;
20684 return id;
20685 }
20686
20687 #if defined(SUPPORT_RANDOM_MAC_SCAN)
20688 int
20689 wl_cfg80211_set_random_mac(struct net_device *dev, bool enable)
20690 {
20691 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20692 int ret;
20693
20694 if (cfg->random_mac_enabled == enable) {
20695 WL_ERR(("Random MAC already %s\n", enable ? "Enabled" : "Disabled"));
20696 return BCME_OK;
20697 }
20698
20699 if (enable) {
20700 ret = wl_cfg80211_random_mac_enable(dev);
20701 } else {
20702 ret = wl_cfg80211_random_mac_disable(dev);
20703 }
20704
20705 if (!ret) {
20706 cfg->random_mac_enabled = enable;
20707 }
20708
20709 return ret;
20710 }
20711
20712 int
20713 wl_cfg80211_random_mac_enable(struct net_device *dev)
20714 {
20715 u8 random_mac[ETH_ALEN] = {0, };
20716 u8 rand_bytes[3] = {0, };
20717 s32 err = BCME_ERROR;
20718 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20719
20720 if (wl_get_drv_status_all(cfg, CONNECTED) || wl_get_drv_status_all(cfg, CONNECTING) ||
20721 wl_get_drv_status_all(cfg, AP_CREATED) || wl_get_drv_status_all(cfg, AP_CREATING)) {
20722 WL_ERR(("fail to Set random mac, current state is wrong\n"));
20723 return err;
20724 }
20725
20726 memcpy(random_mac, bcmcfg_to_prmry_ndev(cfg)->dev_addr, ETH_ALEN);
20727 get_random_bytes(&rand_bytes, sizeof(rand_bytes));
20728
20729 if (rand_bytes[2] == 0x0 || rand_bytes[2] == 0xff) {
20730 rand_bytes[2] = 0xf0;
20731 }
20732
20733 memcpy(&random_mac[3], rand_bytes, sizeof(rand_bytes));
20734
20735 err = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr",
20736 random_mac, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
20737
20738 if (err != BCME_OK) {
20739 WL_ERR(("failed to set random generate MAC address\n"));
20740 } else {
20741 WL_ERR(("set mac " MACDBG " to " MACDBG "\n",
20742 MAC2STRDBG((const u8 *)bcmcfg_to_prmry_ndev(cfg)->dev_addr),
20743 MAC2STRDBG((const u8 *)&random_mac)));
20744 WL_ERR(("random MAC enable done"));
20745 }
20746
20747 return err;
20748 }
20749
20750 int
20751 wl_cfg80211_random_mac_disable(struct net_device *dev)
20752 {
20753 s32 err = BCME_ERROR;
20754 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20755
20756 WL_ERR(("set original mac " MACDBG "\n",
20757 MAC2STRDBG((const u8 *)bcmcfg_to_prmry_ndev(cfg)->dev_addr)));
20758
20759 err = wldev_iovar_setbuf_bsscfg(bcmcfg_to_prmry_ndev(cfg), "cur_etheraddr",
20760 bcmcfg_to_prmry_ndev(cfg)->dev_addr, ETH_ALEN,
20761 cfg->ioctl_buf, WLC_IOCTL_SMLEN, 0, &cfg->ioctl_buf_sync);
20762
20763 if (err != BCME_OK) {
20764 WL_ERR(("failed to set original MAC address\n"));
20765 } else {
20766 WL_ERR(("random MAC disable done\n"));
20767 }
20768
20769 return err;
20770 }
20771 #endif /* SUPPORT_RANDOM_MAC_SCAN */
20772
20773 #ifdef WLTDLS
20774 static s32
20775 wl_cfg80211_tdls_config(struct bcm_cfg80211 *cfg, enum wl_tdls_config state, bool auto_mode)
20776 {
20777 struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
20778 int err = 0;
20779 struct net_info *iter, *next;
20780 int update_reqd = 0;
20781 int enable = 0;
20782 dhd_pub_t *dhdp;
20783 dhdp = (dhd_pub_t *)(cfg->pub);
20784
20785 /*
20786 * TDLS need to be enabled only if we have a single STA/GC
20787 * connection.
20788 */
20789
20790 WL_DBG(("Enter state:%d\n", state));
20791
20792 if (!cfg->tdls_supported) {
20793 /* FW doesn't support tdls. Do nothing */
20794 return -ENODEV;
20795 }
20796
20797 /* Protect tdls config session */
20798 mutex_lock(&cfg->tdls_sync);
20799
20800 if ((state == TDLS_STATE_TEARDOWN)) {
20801 /* Host initiated TDLS tear down */
20802 err = dhd_tdls_enable(ndev, false, auto_mode, NULL);
20803 goto exit;
20804 } else if (state == TDLS_STATE_AP_CREATE) {
20805 /* We don't support tdls while AP/GO is operational */
20806 update_reqd = true;
20807 enable = false;
20808 } else if ((state == TDLS_STATE_CONNECT) || (state == TDLS_STATE_IF_CREATE)) {
20809 if (wl_get_drv_status_all(cfg,
20810 CONNECTED) >= TDLS_MAX_IFACE_FOR_ENABLE) {
20811 /* For STA/GC connect command request, disable
20812 * tdls if we have any concurrent interfaces
20813 * operational.
20814 */
20815 WL_DBG(("Interface limit restriction. disable tdls.\n"));
20816 update_reqd = true;
20817 enable = false;
20818 }
20819 } else if ((state == TDLS_STATE_DISCONNECT) ||
20820 (state == TDLS_STATE_AP_DELETE) ||
20821 (state == TDLS_STATE_SETUP) ||
20822 (state == TDLS_STATE_IF_DELETE)) {
20823 /* Enable back the tdls connection only if we have less than
20824 * or equal to a single STA/GC connection.
20825 */
20826 if (wl_get_drv_status_all(cfg,
20827 CONNECTED) == 0) {
20828 /* If there are no interfaces connected, enable tdls */
20829 update_reqd = true;
20830 enable = true;
20831 } else if (wl_get_drv_status_all(cfg,
20832 CONNECTED) == TDLS_MAX_IFACE_FOR_ENABLE) {
20833 /* We have one interface in CONNECTED state.
20834 * Verify whether its a non-AP interface before
20835 * we enable back tdls.
20836 */
20837 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20838 #pragma GCC diagnostic push
20839 #pragma GCC diagnostic ignored "-Wcast-qual"
20840 #endif
20841 for_each_ndev(cfg, iter, next) {
20842 if ((iter->ndev) && (wl_get_drv_status(cfg, CONNECTED, ndev)) &&
20843 wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
20844 WL_DBG(("AP/GO operational. Can't enable tdls. \n"));
20845 err = -ENOTSUPP;
20846 goto exit;
20847 }
20848 }
20849 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20850 #pragma GCC diagnostic pop
20851 #endif
20852 /* No AP/GO found. Enable back tdls */
20853 update_reqd = true;
20854 enable = true;
20855 } else {
20856 WL_DBG(("Concurrent connection mode. Can't enable tdls. \n"));
20857 err = -ENOTSUPP;
20858 goto exit;
20859 }
20860 } else {
20861 WL_ERR(("Unknown tdls state:%d \n", state));
20862 err = -EINVAL;
20863 goto exit;
20864 }
20865
20866 if (update_reqd == true) {
20867 if (dhdp->tdls_enable == enable) {
20868 WL_ERR(("No change in tdls state. Do nothing."
20869 " tdls_enable:%d\n", enable));
20870 goto exit;
20871 }
20872 err = wldev_iovar_setint(ndev, "tdls_enable", enable);
20873 if (unlikely(err)) {
20874 WL_ERR(("tdls_enable setting failed. err:%d\n", err));
20875 goto exit;
20876 } else {
20877 WL_DBG(("set tdls_enable: %d done\n", enable));
20878 /* Update the dhd state variable to be in sync */
20879 dhdp->tdls_enable = enable;
20880 if (state == TDLS_STATE_SETUP) {
20881 /* For host initiated setup, apply TDLS params
20882 * Don't propagate errors up for param config
20883 * failures
20884 */
20885 dhd_tdls_enable(ndev, true, auto_mode, NULL);
20886
20887 }
20888 }
20889 } else {
20890 WL_DBG(("Skip tdls config. state:%d update_reqd:%d "
20891 "current_status:%d \n",
20892 state, update_reqd, dhdp->tdls_enable));
20893 }
20894
20895 exit:
20896 mutex_unlock(&cfg->tdls_sync);
20897
20898 return err;
20899 }
20900 #endif /* WLTDLS */
20901
20902 struct net_device* wl_get_ap_netdev(struct bcm_cfg80211 *cfg, char *ifname)
20903 {
20904 struct net_info *iter, *next;
20905 struct net_device *ndev = NULL;
20906
20907 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20908 #pragma GCC diagnostic push
20909 #pragma GCC diagnostic ignored "-Wcast-qual"
20910 #endif
20911 for_each_ndev(cfg, iter, next) {
20912 if (iter->ndev) {
20913 if (strncmp(iter->ndev->name, ifname, strlen(iter->ndev->name)) == 0) {
20914 if (iter->ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
20915 ndev = iter->ndev;
20916 break;
20917 }
20918 }
20919 }
20920 }
20921 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20922 #pragma GCC diagnostic pop
20923 #endif
20924
20925 return ndev;
20926 }
20927
20928 struct net_device*
20929 wl_get_netdev_by_name(struct bcm_cfg80211 *cfg, char *ifname)
20930 {
20931 struct net_info *iter, *next;
20932 struct net_device *ndev = NULL;
20933
20934 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20935 #pragma GCC diagnostic push
20936 #pragma GCC diagnostic ignored "-Wcast-qual"
20937 #endif
20938 for_each_ndev(cfg, iter, next) {
20939 if (iter->ndev) {
20940 if (strncmp(iter->ndev->name, ifname, IFNAMSIZ) == 0) {
20941 ndev = iter->ndev;
20942 break;
20943 }
20944 }
20945 }
20946 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
20947 #pragma GCC diagnostic pop
20948 #endif
20949
20950 return ndev;
20951 }
20952
20953 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
20954 #define WLC_RATE_FLAG 0x80
20955 #define RATE_MASK 0x7f
20956
20957 int wl_set_ap_beacon_rate(struct net_device *dev, int val, char *ifname)
20958 {
20959 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
20960 dhd_pub_t *dhdp;
20961 wl_rateset_args_t rs;
20962 int error = BCME_ERROR, i;
20963 struct net_device *ndev = NULL;
20964
20965 dhdp = (dhd_pub_t *)(cfg->pub);
20966
20967 if (dhdp && !(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
20968 WL_ERR(("Not Hostapd mode\n"));
20969 return BCME_NOTAP;
20970 }
20971
20972 ndev = wl_get_ap_netdev(cfg, ifname);
20973
20974 if (ndev == NULL) {
20975 WL_ERR(("No softAP interface named %s\n", ifname));
20976 return BCME_NOTAP;
20977 }
20978
20979 bzero(&rs, sizeof(wl_rateset_args_t));
20980 error = wldev_iovar_getbuf(ndev, "rateset", NULL, 0,
20981 &rs, sizeof(wl_rateset_args_t), NULL);
20982 if (error < 0) {
20983 WL_ERR(("get rateset failed = %d\n", error));
20984 return error;
20985 }
20986
20987 if (rs.count < 1) {
20988 WL_ERR(("Failed to get rate count\n"));
20989 return BCME_ERROR;
20990 }
20991
20992 /* Host delivers target rate in the unit of 500kbps */
20993 /* To make it to 1mbps unit, atof should be implemented for 5.5mbps basic rate */
20994 for (i = 0; i < rs.count && i < WL_NUMRATES; i++)
20995 if (rs.rates[i] & WLC_RATE_FLAG)
20996 if ((rs.rates[i] & RATE_MASK) == val)
20997 break;
20998
20999 /* Valid rate has been delivered as an argument */
21000 if (i < rs.count && i < WL_NUMRATES) {
21001 error = wldev_iovar_setint(ndev, "force_bcn_rspec", val);
21002 if (error < 0) {
21003 WL_ERR(("set beacon rate failed = %d\n", error));
21004 return BCME_ERROR;
21005 }
21006 } else {
21007 WL_ERR(("Rate is invalid"));
21008 return BCME_BADARG;
21009 }
21010
21011 return BCME_OK;
21012 }
21013
21014 int
21015 wl_get_ap_basic_rate(struct net_device *dev, char* command, char *ifname, int total_len)
21016 {
21017 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21018 dhd_pub_t *dhdp;
21019 wl_rateset_args_t rs;
21020 int error = BCME_ERROR;
21021 int i, bytes_written = 0;
21022 struct net_device *ndev = NULL;
21023
21024 dhdp = (dhd_pub_t *)(cfg->pub);
21025
21026 if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
21027 WL_ERR(("Not Hostapd mode\n"));
21028 return BCME_NOTAP;
21029 }
21030
21031 ndev = wl_get_ap_netdev(cfg, ifname);
21032
21033 if (ndev == NULL) {
21034 WL_ERR(("No softAP interface named %s\n", ifname));
21035 return BCME_NOTAP;
21036 }
21037
21038 bzero(&rs, sizeof(wl_rateset_args_t));
21039 error = wldev_iovar_getbuf(ndev, "rateset", NULL, 0,
21040 &rs, sizeof(wl_rateset_args_t), NULL);
21041 if (error < 0) {
21042 WL_ERR(("get rateset failed = %d\n", error));
21043 return error;
21044 }
21045
21046 if (rs.count < 1) {
21047 WL_ERR(("Failed to get rate count\n"));
21048 return BCME_ERROR;
21049 }
21050
21051 /* Delivers basic rate in the unit of 500kbps to host */
21052 for (i = 0; i < rs.count && i < WL_NUMRATES; i++)
21053 if (rs.rates[i] & WLC_RATE_FLAG)
21054 bytes_written += snprintf(command + bytes_written, total_len,
21055 "%d ", rs.rates[i] & RATE_MASK);
21056
21057 /* Remove last space in the command buffer */
21058 if (bytes_written) {
21059 command[bytes_written - 1] = '\0';
21060 bytes_written--;
21061 }
21062
21063 return bytes_written;
21064
21065 }
21066 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
21067
21068 #ifdef SUPPORT_AP_RADIO_PWRSAVE
21069 static int
21070 _wl_update_ap_rps_params(struct net_device *dev)
21071 {
21072 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21073 rpsnoa_iovar_params_t iovar;
21074 u8 smbuf[WLC_IOCTL_SMLEN];
21075
21076 if (!dev)
21077 return BCME_BADARG;
21078
21079 memset(&iovar, 0, sizeof(iovar));
21080 memset(smbuf, 0, sizeof(smbuf));
21081
21082 iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
21083 iovar.hdr.subcmd = WL_RPSNOA_CMD_PARAMS;
21084 iovar.hdr.len = sizeof(iovar);
21085 iovar.param->band = WLC_BAND_ALL;
21086 iovar.param->level = cfg->ap_rps_info.level;
21087 iovar.param->stas_assoc_check = cfg->ap_rps_info.sta_assoc_check;
21088 iovar.param->pps = cfg->ap_rps_info.pps;
21089 iovar.param->quiet_time = cfg->ap_rps_info.quiet_time;
21090
21091 if (wldev_iovar_setbuf(dev, "rpsnoa", &iovar, sizeof(iovar),
21092 smbuf, sizeof(smbuf), NULL)) {
21093 WL_ERR(("Failed to set rpsnoa params"));
21094 return BCME_ERROR;
21095 }
21096
21097 return BCME_OK;
21098 }
21099
21100 int
21101 wl_get_ap_rps(struct net_device *dev, char* command, char *ifname, int total_len)
21102 {
21103 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21104 dhd_pub_t *dhdp;
21105 int error = BCME_ERROR;
21106 int bytes_written = 0;
21107 struct net_device *ndev = NULL;
21108 rpsnoa_iovar_t iovar;
21109 u8 smbuf[WLC_IOCTL_SMLEN];
21110 u32 chanspec = 0;
21111 u8 idx = 0;
21112 u8 val;
21113
21114 dhdp = (dhd_pub_t *)(cfg->pub);
21115
21116 if (!dhdp) {
21117 error = BCME_NOTUP;
21118 goto fail;
21119 }
21120
21121 if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
21122 WL_ERR(("Not Hostapd mode\n"));
21123 error = BCME_NOTAP;
21124 goto fail;
21125 }
21126
21127 ndev = wl_get_ap_netdev(cfg, ifname);
21128
21129 if (ndev == NULL) {
21130 WL_ERR(("No softAP interface named %s\n", ifname));
21131 error = BCME_NOTAP;
21132 goto fail;
21133 }
21134
21135 memset(&iovar, 0, sizeof(iovar));
21136 memset(smbuf, 0, sizeof(smbuf));
21137
21138 iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
21139 iovar.hdr.subcmd = WL_RPSNOA_CMD_STATUS;
21140 iovar.hdr.len = sizeof(iovar);
21141 iovar.data->band = WLC_BAND_ALL;
21142
21143 error = wldev_iovar_getbuf(ndev, "rpsnoa", &iovar, sizeof(iovar),
21144 smbuf, sizeof(smbuf), NULL);
21145 if (error < 0) {
21146 WL_ERR(("get ap radio pwrsave failed = %d\n", error));
21147 goto fail;
21148 }
21149
21150 /* RSDB event doesn't seem to be handled correctly.
21151 * So check chanspec of AP directly from the firmware
21152 */
21153 error = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
21154 if (error < 0) {
21155 WL_ERR(("get chanspec from AP failed = %d\n", error));
21156 goto fail;
21157 }
21158
21159 chanspec = wl_chspec_driver_to_host(chanspec);
21160 if (CHSPEC_IS2G(chanspec))
21161 idx = 0;
21162 else if (CHSPEC_IS5G(chanspec))
21163 idx = 1;
21164 else {
21165 error = BCME_BADCHAN;
21166 goto fail;
21167 }
21168
21169 val = ((rpsnoa_iovar_t *)smbuf)->data[idx].value;
21170 bytes_written += snprintf(command + bytes_written, total_len, "%d", val);
21171 error = bytes_written;
21172
21173 fail:
21174 return error;
21175 }
21176
21177 int
21178 wl_set_ap_rps(struct net_device *dev, bool enable, char *ifname)
21179 {
21180 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21181 dhd_pub_t *dhdp;
21182 struct net_device *ndev = NULL;
21183 rpsnoa_iovar_t iovar;
21184 u8 smbuf[WLC_IOCTL_SMLEN];
21185 int ret = BCME_OK;
21186
21187 dhdp = (dhd_pub_t *)(cfg->pub);
21188
21189 if (!dhdp) {
21190 ret = BCME_NOTUP;
21191 goto exit;
21192 }
21193
21194 if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
21195 WL_ERR(("Not Hostapd mode\n"));
21196 ret = BCME_NOTAP;
21197 goto exit;
21198 }
21199
21200 ndev = wl_get_ap_netdev(cfg, ifname);
21201
21202 if (ndev == NULL) {
21203 WL_ERR(("No softAP interface named %s\n", ifname));
21204 ret = BCME_NOTAP;
21205 goto exit;
21206 }
21207
21208 if (cfg->ap_rps_info.enable != enable) {
21209 cfg->ap_rps_info.enable = enable;
21210 if (enable) {
21211 ret = _wl_update_ap_rps_params(ndev);
21212 if (ret) {
21213 WL_ERR(("Filed to update rpsnoa params\n"));
21214 goto exit;
21215 }
21216 }
21217 memset(&iovar, 0, sizeof(iovar));
21218 memset(smbuf, 0, sizeof(smbuf));
21219
21220 iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
21221 iovar.hdr.subcmd = WL_RPSNOA_CMD_ENABLE;
21222 iovar.hdr.len = sizeof(iovar);
21223 iovar.data->band = WLC_BAND_ALL;
21224 iovar.data->value = (int16)enable;
21225
21226 ret = wldev_iovar_setbuf(ndev, "rpsnoa", &iovar, sizeof(iovar),
21227 smbuf, sizeof(smbuf), NULL);
21228 if (ret) {
21229 WL_ERR(("Failed to enable AP radio power save"));
21230 goto exit;
21231 }
21232 cfg->ap_rps_info.enable = enable;
21233 }
21234 exit:
21235 return ret;
21236 }
21237
21238 int
21239 wl_update_ap_rps_params(struct net_device *dev, ap_rps_info_t* rps, char *ifname)
21240 {
21241 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21242 dhd_pub_t *dhdp;
21243 struct net_device *ndev = NULL;
21244
21245 dhdp = (dhd_pub_t *)(cfg->pub);
21246
21247 if (!dhdp)
21248 return BCME_NOTUP;
21249
21250 if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
21251 WL_ERR(("Not Hostapd mode\n"));
21252 return BCME_NOTAP;
21253 }
21254
21255 ndev = wl_get_ap_netdev(cfg, ifname);
21256
21257 if (ndev == NULL) {
21258 WL_ERR(("No softAP interface named %s\n", ifname));
21259 return BCME_NOTAP;
21260 }
21261
21262 if (!rps)
21263 return BCME_BADARG;
21264
21265 if (rps->pps < RADIO_PWRSAVE_PPS_MIN)
21266 return BCME_BADARG;
21267
21268 if (rps->level < RADIO_PWRSAVE_LEVEL_MIN ||
21269 rps->level > RADIO_PWRSAVE_LEVEL_MAX)
21270 return BCME_BADARG;
21271
21272 if (rps->quiet_time < RADIO_PWRSAVE_QUIETTIME_MIN)
21273 return BCME_BADARG;
21274
21275 if (rps->sta_assoc_check > RADIO_PWRSAVE_ASSOCCHECK_MAX ||
21276 rps->sta_assoc_check < RADIO_PWRSAVE_ASSOCCHECK_MIN)
21277 return BCME_BADARG;
21278
21279 cfg->ap_rps_info.pps = rps->pps;
21280 cfg->ap_rps_info.level = rps->level;
21281 cfg->ap_rps_info.quiet_time = rps->quiet_time;
21282 cfg->ap_rps_info.sta_assoc_check = rps->sta_assoc_check;
21283
21284 if (cfg->ap_rps_info.enable) {
21285 if (_wl_update_ap_rps_params(ndev)) {
21286 WL_ERR(("Failed to update rpsnoa params"));
21287 return BCME_ERROR;
21288 }
21289 }
21290
21291 return BCME_OK;
21292 }
21293
21294 void
21295 wl_cfg80211_init_ap_rps(struct bcm_cfg80211 *cfg)
21296 {
21297 cfg->ap_rps_info.enable = FALSE;
21298 cfg->ap_rps_info.sta_assoc_check = RADIO_PWRSAVE_STAS_ASSOC_CHECK;
21299 cfg->ap_rps_info.pps = RADIO_PWRSAVE_PPS;
21300 cfg->ap_rps_info.quiet_time = RADIO_PWRSAVE_QUIET_TIME;
21301 cfg->ap_rps_info.level = RADIO_PWRSAVE_LEVEL;
21302 }
21303 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
21304
21305 int
21306 wl_cfg80211_iface_count(struct net_device *dev)
21307 {
21308 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21309 struct net_info *iter, *next;
21310 int iface_count = 0;
21311
21312 /* Return the count of network interfaces (skip netless p2p discovery
21313 * interface)
21314 */
21315 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21316 #pragma GCC diagnostic push
21317 #pragma GCC diagnostic ignored "-Wcast-qual"
21318 #endif
21319 for_each_ndev(cfg, iter, next) {
21320 if (iter->ndev) {
21321 iface_count++;
21322 }
21323 }
21324 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21325 #pragma GCC diagnostic pop
21326 #endif
21327 return iface_count;
21328 }
21329
21330 #ifdef WBTEXT
21331 static bool wl_cfg80211_wbtext_check_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea)
21332 {
21333 wl_wbtext_bssid_t *bssid = NULL;
21334 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__)
21335 #pragma GCC diagnostic push
21336 #pragma GCC diagnostic ignored "-Wcast-qual"
21337 #endif
21338
21339 /* check duplicate */
21340 list_for_each_entry(bssid, &cfg->wbtext_bssid_list, list) {
21341 if (!memcmp(bssid->ea.octet, ea, ETHER_ADDR_LEN)) {
21342 return FALSE;
21343 }
21344 }
21345
21346 return TRUE;
21347 }
21348
21349 static bool wl_cfg80211_wbtext_add_bssid_list(struct bcm_cfg80211 *cfg, struct ether_addr *ea)
21350 {
21351 wl_wbtext_bssid_t *bssid = NULL;
21352 char eabuf[ETHER_ADDR_STR_LEN];
21353
21354 bssid = kmalloc(sizeof(wl_wbtext_bssid_t), GFP_KERNEL);
21355 if (bssid == NULL) {
21356 WL_ERR(("alloc failed\n"));
21357 return FALSE;
21358 }
21359
21360 memcpy(bssid->ea.octet, ea, ETHER_ADDR_LEN);
21361
21362 INIT_LIST_HEAD(&bssid->list);
21363 list_add_tail(&bssid->list, &cfg->wbtext_bssid_list);
21364
21365 WL_DBG(("add wbtext bssid : %s\n", bcm_ether_ntoa(ea, eabuf)));
21366
21367 return TRUE;
21368 }
21369
21370 static void wl_cfg80211_wbtext_clear_bssid_list(struct bcm_cfg80211 *cfg)
21371 {
21372 wl_wbtext_bssid_t *bssid = NULL;
21373 char eabuf[ETHER_ADDR_STR_LEN];
21374
21375 while (!list_empty(&cfg->wbtext_bssid_list)) {
21376 bssid = list_entry(cfg->wbtext_bssid_list.next, wl_wbtext_bssid_t, list);
21377 if (bssid) {
21378 WL_DBG(("clear wbtext bssid : %s\n", bcm_ether_ntoa(&bssid->ea, eabuf)));
21379 list_del(&bssid->list);
21380 kfree(bssid);
21381 }
21382 }
21383 }
21384
21385 static void wl_cfg80211_wbtext_update_rcc(struct bcm_cfg80211 *cfg, struct net_device *dev)
21386 {
21387 struct wl_connect_info *conn_info = wl_to_conn(cfg);
21388 bcm_tlv_t * cap_ie = NULL;
21389 bool req_sent = FALSE;
21390 struct wl_profile *profile;
21391
21392 WL_DBG(("Enter\n"));
21393
21394 profile = wl_get_profile_by_netdev(cfg, dev);
21395 if (!profile) {
21396 WL_ERR(("no profile exists\n"));
21397 return;
21398 }
21399
21400 if (wl_cfg80211_wbtext_check_bssid_list(cfg,
21401 (struct ether_addr *)&profile->bssid) == FALSE) {
21402 WL_DBG(("already updated\n"));
21403 return;
21404 }
21405
21406 /* first, check NBR bit in RRM IE */
21407 if ((cap_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
21408 DOT11_MNG_RRM_CAP_ID)) != NULL) {
21409 if (isset(cap_ie->data, DOT11_RRM_CAP_NEIGHBOR_REPORT)) {
21410 req_sent = wl_cfg80211_wbtext_send_nbr_req(cfg, dev, profile);
21411 }
21412 }
21413
21414 /* if RRM nbr was not supported, check BTM bit in extend cap. IE */
21415 if (!req_sent) {
21416 if ((cap_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
21417 DOT11_MNG_EXT_CAP_ID)) != NULL) {
21418 if (cap_ie->len >= DOT11_EXTCAP_LEN_BSSTRANS &&
21419 isset(cap_ie->data, DOT11_EXT_CAP_BSSTRANS_MGMT)) {
21420 wl_cfg80211_wbtext_send_btm_query(cfg, dev, profile);
21421 }
21422 }
21423 }
21424 }
21425
21426 static bool wl_cfg80211_wbtext_send_nbr_req(struct bcm_cfg80211 *cfg, struct net_device *dev,
21427 struct wl_profile *profile)
21428 {
21429 int error = -1;
21430 char *smbuf = NULL;
21431 struct wl_connect_info *conn_info = wl_to_conn(cfg);
21432 bcm_tlv_t * rrm_cap_ie = NULL;
21433 wlc_ssid_t *ssid = NULL;
21434 bool ret = FALSE;
21435
21436 WL_DBG(("Enter\n"));
21437
21438 /* check RRM nbr bit in extend cap. IE of assoc response */
21439 if ((rrm_cap_ie = bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
21440 DOT11_MNG_RRM_CAP_ID)) != NULL) {
21441 if (!isset(rrm_cap_ie->data, DOT11_RRM_CAP_NEIGHBOR_REPORT)) {
21442 WL_DBG(("AP doesn't support neighbor report\n"));
21443 return FALSE;
21444 }
21445 }
21446
21447 smbuf = (char *) kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
21448 if (smbuf == NULL) {
21449 WL_ERR(("failed to allocated memory\n"));
21450 goto nbr_req_out;
21451 }
21452
21453 ssid = (wlc_ssid_t *) kzalloc(sizeof(wlc_ssid_t), GFP_KERNEL);
21454 if (ssid == NULL) {
21455 WL_ERR(("failed to allocated memory\n"));
21456 goto nbr_req_out;
21457 }
21458
21459 ssid->SSID_len = MIN(profile->ssid.SSID_len, DOT11_MAX_SSID_LEN);
21460 memcpy(ssid->SSID, profile->ssid.SSID, ssid->SSID_len);
21461
21462 error = wldev_iovar_setbuf(dev, "rrm_nbr_req", ssid,
21463 sizeof(wlc_ssid_t), smbuf, WLC_IOCTL_MAXLEN, NULL);
21464 if (error == BCME_OK) {
21465 ret = wl_cfg80211_wbtext_add_bssid_list(cfg,
21466 (struct ether_addr *)&profile->bssid);
21467 } else {
21468 WL_ERR(("failed to send neighbor report request, error=%d\n", error));
21469 }
21470
21471 nbr_req_out:
21472 if (ssid) {
21473 kfree(ssid);
21474 }
21475
21476 if (smbuf) {
21477 kfree(smbuf);
21478 }
21479 return ret;
21480 }
21481
21482 static bool wl_cfg80211_wbtext_send_btm_query(struct bcm_cfg80211 *cfg, struct net_device *dev,
21483 struct wl_profile *profile)
21484
21485 {
21486 int error = -1;
21487 bool ret = FALSE;
21488
21489 WL_DBG(("Enter\n"));
21490
21491 error = wldev_iovar_setbuf(dev, "wnm_bsstrans_query", NULL,
21492 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
21493 if (error == BCME_OK) {
21494 ret = wl_cfg80211_wbtext_add_bssid_list(cfg,
21495 (struct ether_addr *)&profile->bssid);
21496 } else {
21497 WL_ERR(("%s: failed to set BTM query, error=%d\n", __FUNCTION__, error));
21498 }
21499 return ret;
21500 }
21501
21502 static void wl_cfg80211_wbtext_set_wnm_maxidle(struct bcm_cfg80211 *cfg, struct net_device *dev)
21503 {
21504 keepalives_max_idle_t keepalive = {0, 0, 0, 0};
21505 s32 bssidx, error;
21506 int wnm_maxidle = 0;
21507 struct wl_connect_info *conn_info = wl_to_conn(cfg);
21508
21509 /* AP supports wnm max idle ? */
21510 if (bcm_parse_tlvs(conn_info->resp_ie, conn_info->resp_ie_len,
21511 DOT11_MNG_BSS_MAX_IDLE_PERIOD_ID) != NULL) {
21512 error = wldev_iovar_getint(dev, "wnm_maxidle", &wnm_maxidle);
21513 if (error < 0) {
21514 WL_ERR(("failed to get wnm max idle period : %d\n", error));
21515 }
21516 }
21517
21518 WL_DBG(("wnm max idle period : %d\n", wnm_maxidle));
21519
21520 /* if wnm maxidle has valid period, set it as keep alive */
21521 if (wnm_maxidle > 0) {
21522 keepalive.keepalive_count = 1;
21523 }
21524
21525 if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) >= 0) {
21526 error = wldev_iovar_setbuf_bsscfg(dev, "wnm_keepalives_max_idle", &keepalive,
21527 sizeof(keepalives_max_idle_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
21528 bssidx, &cfg->ioctl_buf_sync);
21529 if (error < 0) {
21530 WL_ERR(("set wnm_keepalives_max_idle failed : %d\n", error));
21531 }
21532 }
21533 }
21534
21535 static int
21536 wl_cfg80211_recv_nbr_resp(struct net_device *dev, uint8 *body, int body_len)
21537 {
21538 dot11_rm_action_t *rm_rep;
21539 bcm_tlv_t *tlvs;
21540 int tlv_len, i, error;
21541 dot11_neighbor_rep_ie_t *nbr_rep_ie;
21542 chanspec_t ch;
21543 wl_roam_channel_list_t channel_list;
21544 char iobuf[WLC_IOCTL_SMLEN];
21545
21546 if (body_len < DOT11_RM_ACTION_LEN) {
21547 WL_ERR(("Received Neighbor Report frame with incorrect length %d\n",
21548 body_len));
21549 return BCME_ERROR;
21550 }
21551
21552 rm_rep = (dot11_rm_action_t *)body;
21553 WL_DBG(("received neighbor report (token = %d)\n", rm_rep->token));
21554
21555 tlvs = (bcm_tlv_t *)&rm_rep->data[0];
21556
21557 tlv_len = body_len - DOT11_RM_ACTION_LEN;
21558
21559 while (tlvs && tlvs->id == DOT11_MNG_NEIGHBOR_REP_ID) {
21560 nbr_rep_ie = (dot11_neighbor_rep_ie_t *)tlvs;
21561
21562 if (nbr_rep_ie->len < DOT11_NEIGHBOR_REP_IE_FIXED_LEN) {
21563 WL_ERR(("malformed Neighbor Report element with length %d\n",
21564 nbr_rep_ie->len));
21565 tlvs = bcm_next_tlv(tlvs, &tlv_len);
21566 continue;
21567 }
21568
21569 ch = CH20MHZ_CHSPEC(nbr_rep_ie->channel);
21570 WL_DBG(("ch:%d, bssid:%02x:%02x:%02x:%02x:%02x:%02x\n",
21571 ch, nbr_rep_ie->bssid.octet[0], nbr_rep_ie->bssid.octet[1],
21572 nbr_rep_ie->bssid.octet[2], nbr_rep_ie->bssid.octet[3],
21573 nbr_rep_ie->bssid.octet[4], nbr_rep_ie->bssid.octet[5]));
21574
21575 /* get RCC list */
21576 error = wldev_iovar_getbuf(dev, "roamscan_channels", 0, 0,
21577 (void *)&channel_list, sizeof(channel_list), NULL);
21578 if (error) {
21579 WL_ERR(("Failed to get roamscan channels, error = %d\n", error));
21580 return BCME_ERROR;
21581 }
21582
21583 /* update RCC */
21584 if (channel_list.n < MAX_ROAM_CHANNEL) {
21585 for (i = 0; i < channel_list.n; i++) {
21586 if (channel_list.channels[i] == ch) {
21587 break;
21588 }
21589 }
21590 if (i == channel_list.n) {
21591 channel_list.channels[channel_list.n] = ch;
21592 channel_list.n++;
21593 }
21594 }
21595
21596 /* set RCC list */
21597 error = wldev_iovar_setbuf(dev, "roamscan_channels", &channel_list,
21598 sizeof(channel_list), iobuf, sizeof(iobuf), NULL);
21599 if (error) {
21600 WL_DBG(("Failed to set roamscan channels, error = %d\n", error));
21601 }
21602
21603 tlvs = bcm_next_tlv(tlvs, &tlv_len);
21604 }
21605
21606 return BCME_OK;
21607 }
21608 #endif /* WBTEXT */
21609
21610 #ifdef SUPPORT_SET_CAC
21611 static void
21612 wl_cfg80211_set_cac(struct bcm_cfg80211 *cfg, int enable)
21613 {
21614 int ret = 0;
21615 dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
21616
21617 WL_DBG(("cac enable %d, op_mode 0x%04x\n", enable, dhd->op_mode));
21618 if (!dhd) {
21619 WL_ERR(("dhd is NULL\n"));
21620 return;
21621 }
21622 if (enable && ((dhd->op_mode & DHD_FLAG_HOSTAP_MODE) ||
21623 (dhd->op_mode & DHD_FLAG_P2P_GC_MODE) ||
21624 (dhd->op_mode & DHD_FLAG_P2P_GO_MODE))) {
21625 WL_ERR(("op_mode 0x%04x\n", dhd->op_mode));
21626 enable = 0;
21627 }
21628 if ((ret = dhd_wl_ioctl_set_intiovar(dhd, "cac", enable,
21629 WLC_SET_VAR, TRUE, 0)) < 0) {
21630 WL_ERR(("Failed set CAC, ret=%d\n", ret));
21631 } else {
21632 WL_DBG(("CAC set successfully\n"));
21633 }
21634 return;
21635 }
21636 #endif /* SUPPORT_SET_CAC */
21637
21638 #ifdef SUPPORT_RSSI_LOGGING
21639 int
21640 wl_get_rssi_per_ant(struct net_device *dev, char *ifname, char *peer_mac, void *param)
21641 {
21642 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21643 wl_rssi_ant_mimo_t *get_param = (wl_rssi_ant_mimo_t *)param;
21644 rssi_ant_param_t *set_param = NULL;
21645 struct net_device *ifdev = NULL;
21646 char iobuf[WLC_IOCTL_SMLEN];
21647 int err = BCME_OK;
21648 int iftype = 0;
21649
21650 memset(iobuf, 0, WLC_IOCTL_SMLEN);
21651
21652 /* Check the interface type */
21653 ifdev = wl_get_netdev_by_name(cfg, ifname);
21654 if (ifdev == NULL) {
21655 WL_ERR(("Could not find net_device for ifname:%s\n", ifname));
21656 err = BCME_BADARG;
21657 goto fail;
21658 }
21659
21660 iftype = ifdev->ieee80211_ptr->iftype;
21661 if (iftype == NL80211_IFTYPE_AP || iftype == NL80211_IFTYPE_P2P_GO) {
21662 if (peer_mac) {
21663 set_param = (rssi_ant_param_t *)kzalloc(sizeof(rssi_ant_param_t),
21664 GFP_KERNEL);
21665 err = wl_cfg80211_ether_atoe(peer_mac, &set_param->ea);
21666 if (!err) {
21667 WL_ERR(("Invalid Peer MAC format\n"));
21668 err = BCME_BADARG;
21669 goto fail;
21670 }
21671 } else {
21672 WL_ERR(("Peer MAC is not provided for iftype %d\n", iftype));
21673 err = BCME_BADARG;
21674 goto fail;
21675 }
21676 }
21677
21678 err = wldev_iovar_getbuf(ifdev, "phy_rssi_ant", peer_mac ?
21679 (void *)&(set_param->ea) : NULL, peer_mac ? ETHER_ADDR_LEN : 0,
21680 (void *)iobuf, sizeof(iobuf), NULL);
21681 if (unlikely(err)) {
21682 WL_ERR(("Failed to get rssi info, err=%d\n", err));
21683 } else {
21684 memcpy(get_param, iobuf, sizeof(wl_rssi_ant_mimo_t));
21685 if (get_param->count == 0) {
21686 WL_ERR(("Not supported on this chip\n"));
21687 err = BCME_UNSUPPORTED;
21688 }
21689 }
21690
21691 fail:
21692 if (set_param) {
21693 kfree(set_param);
21694 }
21695
21696 return err;
21697 }
21698
21699 int
21700 wl_get_rssi_logging(struct net_device *dev, void *param)
21701 {
21702 rssilog_get_param_t *get_param = (rssilog_get_param_t *)param;
21703 char iobuf[WLC_IOCTL_SMLEN];
21704 int err = BCME_OK;
21705
21706 memset(iobuf, 0, WLC_IOCTL_SMLEN);
21707 memset(get_param, 0, sizeof(*get_param));
21708 err = wldev_iovar_getbuf(dev, "rssilog", NULL, 0, (void *)iobuf,
21709 sizeof(iobuf), NULL);
21710 if (err) {
21711 WL_ERR(("Failed to get rssi logging info, err=%d\n", err));
21712 } else {
21713 memcpy(get_param, iobuf, sizeof(*get_param));
21714 }
21715
21716 return err;
21717 }
21718
21719 int
21720 wl_set_rssi_logging(struct net_device *dev, void *param)
21721 {
21722 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21723 rssilog_set_param_t *set_param = (rssilog_set_param_t *)param;
21724 int err;
21725
21726 err = wldev_iovar_setbuf(dev, "rssilog", set_param,
21727 sizeof(*set_param), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
21728 &cfg->ioctl_buf_sync);
21729 if (err) {
21730 WL_ERR(("Failed to set rssi logging param, err=%d\n", err));
21731 }
21732
21733 return err;
21734 }
21735 #endif /* SUPPORT_RSSI_LOGGING */
21736
21737 s32
21738 wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len)
21739 {
21740 struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
21741 int ret = 0;
21742 int bytes_written = -1;
21743
21744 sscanf(command, "%*s %d", &cfg->autochannel);
21745
21746 if (cfg->autochannel == 0) {
21747 cfg->best_2g_ch = 0;
21748 cfg->best_5g_ch = 0;
21749 } else if (cfg->autochannel == 2) {
21750 bytes_written = snprintf(command, total_len, "2g=%d 5g=%d",
21751 cfg->best_2g_ch, cfg->best_5g_ch);
21752 ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
21753 ret = bytes_written;
21754 }
21755
21756 return ret;
21757 }
21758
21759 static int
21760 wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg,
21761 struct net_device *dev, uint action, enum wl_ext_status status, void *context)
21762 {
21763 dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
21764 struct wl_security *sec;
21765 s32 bssidx = -1;
21766 int ret = 0;
21767 int max_wait_gc_time = dhdp->conf->max_wait_gc_time;
21768
21769 if (!(dhdp->conf->in4way & action))
21770 return 0;
21771
21772 mutex_lock(&cfg->in4way_sync);
21773 WL_DBG(("status=%d, action=0x%x\n", status, action));
21774
21775 switch (status) {
21776 case WL_EXT_STATUS_SCAN:
21777 if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) {
21778 if (cfg->handshaking > 0 && cfg->handshaking <= 3) {
21779 WL_ERR(("%s: return -EBUSY cnt %d\n",
21780 __FUNCTION__, cfg->handshaking));
21781 cfg->handshaking++;
21782 ret = -EBUSY;
21783 break;
21784 }
21785 }
21786 break;
21787 case WL_EXT_STATUS_CONNECTING:
21788 if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) {
21789 bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr);
21790 sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
21791 if ((sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) &&
21792 bssidx == 0) {
21793 cfg->handshaking = 1;
21794 if (action & NO_BTC_IN4WAY)
21795 wldev_iovar_setint(dev, "btc_mode", 0);
21796 }
21797 }
21798 break;
21799 case WL_EXT_STATUS_DELETE_GC:
21800 if ((action & DONT_DELETE_GC_AFTER_WPS) &&
21801 (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) {
21802 u8* mac_addr = context;
21803 if (memcmp(&ether_bcast, mac_addr, ETHER_ADDR_LEN) &&
21804 dhdp->conf->eapol_status == EAPOL_STATUS_WPS_DONE) {
21805 u32 timeout;
21806 WL_TRACE(("status=%d, wps_done=%d, waiting %dms ...\n",
21807 status, cfg->wps_done, max_wait_gc_time));
21808 mutex_unlock(&cfg->in4way_sync);
21809 timeout = wait_event_interruptible_timeout(cfg->wps_done_event,
21810 cfg->wps_done, msecs_to_jiffies(max_wait_gc_time));
21811 mutex_lock(&cfg->in4way_sync);
21812 WL_TRACE(("status=%d, wps_done=%d, timeout=%d\n",
21813 status, cfg->wps_done, timeout));
21814 if (timeout > 0) {
21815 ret = -1;
21816 break;
21817 }
21818 } else {
21819 WL_TRACE(("status=%d, wps_done=%d => 0\n", status, cfg->wps_done));
21820 cfg->wps_done = FALSE;
21821 dhdp->conf->eapol_status = EAPOL_STATUS_NONE;
21822 }
21823 }
21824 break;
21825 case WL_EXT_STATUS_GC_DISCONNECTED:
21826 if ((action & DONT_DELETE_GC_AFTER_WPS) &&
21827 (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) &&
21828 dhdp->conf->eapol_status == EAPOL_STATUS_WPS_DONE) {
21829 WL_TRACE(("status=%d, wps_done=%d => 0\n", status, cfg->wps_done));
21830 cfg->wps_done = FALSE;
21831 }
21832 break;
21833 case WL_EXT_STATUS_GC_CONNECTED:
21834 if ((action & DONT_DELETE_GC_AFTER_WPS) &&
21835 (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) &&
21836 dhdp->conf->eapol_status == EAPOL_STATUS_WPS_DONE) {
21837 WL_TRACE(("status=%d, wps_done=%d => 1\n", status, cfg->wps_done));
21838 cfg->wps_done = TRUE;
21839 wake_up_interruptible(&cfg->wps_done_event);
21840 }
21841 break;
21842 case WL_EXT_STATUS_DISCONNECTED:
21843 case WL_EXT_STATUS_4WAY_DONE:
21844 if (action & (NO_SCAN_IN4WAY|NO_BTC_IN4WAY)) {
21845 if (cfg->handshaking) {
21846 if (action & NO_BTC_IN4WAY)
21847 wldev_iovar_setint(dev, "btc_mode", 1);
21848 cfg->handshaking = 0;
21849 }
21850 }
21851 break;
21852 default:
21853 WL_ERR(("Unknown action=0x%x, status=%d\n", action, status));
21854 }
21855
21856 mutex_unlock(&cfg->in4way_sync);
21857
21858 return ret;
21859 }