xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd/wl_cfgvif.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Wifi Virtual Interface implementaion
3  *
4  * Copyright (C) 2020, Broadcom.
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  *
21  * <<Broadcom-WL-IPTag/Dual:>>
22  */
23 /* */
24 
25 #include <typedefs.h>
26 #include <linuxver.h>
27 #include <linux/kernel.h>
28 
29 #include <bcmutils.h>
30 #include <bcmstdlib_s.h>
31 #include <bcmwifi_channels.h>
32 #include <bcmendian.h>
33 #include <ethernet.h>
34 #ifdef WL_WPS_SYNC
35 #include <eapol.h>
36 #endif /* WL_WPS_SYNC */
37 #include <802.11.h>
38 #include <bcmiov.h>
39 #include <linux/if_arp.h>
40 #include <asm/uaccess.h>
41 
42 #include <ethernet.h>
43 #include <linux/kernel.h>
44 #include <linux/kthread.h>
45 #include <linux/netdevice.h>
46 #include <linux/sched.h>
47 #include <linux/etherdevice.h>
48 #include <linux/wireless.h>
49 #include <linux/ieee80211.h>
50 #include <linux/wait.h>
51 #include <net/cfg80211.h>
52 #include <net/rtnetlink.h>
53 
54 #include <wlioctl.h>
55 #include <bcmevent.h>
56 #include <wldev_common.h>
57 #include <wl_cfg80211.h>
58 #include <wl_cfgp2p.h>
59 #include <wl_cfgscan.h>
60 #include <wl_cfgvif.h>
61 #include <bcmdevs.h>
62 #include <bcmdevs_legacy.h>
63 #ifdef WL_FILS
64 #include <fils.h>
65 #include <frag.h>
66 #endif /* WL_FILS */
67 
68 #ifdef OEM_ANDROID
69 #include <wl_android.h>
70 #endif
71 
72 #if defined(BCMDONGLEHOST)
73 #include <dngl_stats.h>
74 #include <dhd.h>
75 #include <dhd_linux.h>
76 #include <dhd_linux_pktdump.h>
77 #include <dhd_debug.h>
78 #include <dhdioctl.h>
79 #include <wlioctl.h>
80 #include <dhd_cfg80211.h>
81 #include <dhd_bus.h>
82 #include <wl_cfgvendor.h>
83 #endif /* defined(BCMDONGLEHOST) */
84 
85 #ifdef WL_NAN
86 #include <wl_cfgnan.h>
87 #endif /* WL_NAN */
88 
89 #ifdef BCMPCIE
90 #include <dhd_flowring.h>
91 #endif
92 #if defined(BIGDATA_SOFTAP) || defined(DHD_ENABLE_BIGDATA_LOGGING)
93 #include <wl_bigdata.h>
94 #endif /* BIGDATA_SOFTAP || DHD_ENABLE_BIGDATA_LOGGING */
95 #include <dhd_config.h>
96 
97 #define	MAX_VIF_OFFSET	15
98 #define MAX_WAIT_TIME 1500
99 
100 #if !defined(BCMDONGLEHOST)
101 #ifdef ntoh32
102 #undef ntoh32
103 #endif
104 #ifdef ntoh16
105 #undef ntoh16
106 #endif
107 #ifdef htod32
108 #undef htod32
109 #endif
110 #ifdef htod16
111 #undef htod16
112 #endif
113 #define ntoh32(i) (i)
114 #define ntoh16(i) (i)
115 #define htod32(i) (i)
116 #define htod16(i) (i)
117 #define DNGL_FUNC(func, parameters)
118 #else
119 #define DNGL_FUNC(func, parameters) func parameters
120 #define COEX_DHCP
121 
122 #endif /* defined(BCMDONGLEHOST) */
123 
124 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && \
125 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
126 _Pragma("GCC diagnostic pop")
127 #endif
128 
129 /* SoftAP related parameters */
130 #define DEFAULT_2G_SOFTAP_CHANNEL	1
131 #define DEFAULT_2G_SOFTAP_CHANSPEC	0x1006
132 #define DEFAULT_5G_SOFTAP_CHANNEL	149
133 
134 #define MAX_VNDR_OUI_STR_LEN	256u
135 #define VNDR_OUI_STR_LEN	10u
136 #define DOT11_DISCONNECT_RC     2u
137 
138 #if defined(WL_FW_OCE_AP_SELECT)
139 static bool
140 wl_cfgoce_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type);
141 
142 /* Check whether the given IE looks like WFA OCE IE. */
143 #define wl_cfgoce_is_oce_ie(ie, tlvs, len)      wl_cfgoce_has_ie(ie, tlvs, len, \
144 	(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_MBO_OCE)
145 
146 /* Is any of the tlvs the expected entry? If
147  * not update the tlvs buffer pointer/length.
148  */
149 static bool
wl_cfgoce_has_ie(const u8 * ie,const u8 ** tlvs,u32 * tlvs_len,const u8 * oui,u32 oui_len,u8 type)150 wl_cfgoce_has_ie(const u8 *ie, const u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type)
151 {
152 	/* If the contents match the OUI and the type */
153 	if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
154 			!bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
155 			type == ie[TLV_BODY_OFF + oui_len]) {
156 		return TRUE;
157 	}
158 
159 	return FALSE;
160 }
161 #endif /* WL_FW_OCE_AP_SELECT */
162 
163 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role);
164 
165 #ifdef SUPPORT_AP_BWCTRL
166 static int bw2cap[] = { 0, 0, WLC_BW_CAP_20MHZ, WLC_BW_CAP_40MHZ, WLC_BW_CAP_80MHZ,
167 	WLC_BW_CAP_160MHZ, WLC_BW_CAP_160MHZ };
168 #endif /* SUPPORT_AP_BWCTRL */
169 
170 #if !defined(BCMDONGLEHOST)
171 /* Wake lock are used in Android only, which is dongle based as of now */
172 #define DHD_OS_WAKE_LOCK(pub)
173 #define DHD_OS_WAKE_UNLOCK(pub)
174 #define DHD_EVENT_WAKE_LOCK(pub)
175 #define DHD_EVENT_WAKE_UNLOCK(pub)
176 #define DHD_OS_WAKE_LOCK_TIMEOUT(pub)
177 #endif /* defined(BCMDONGLEHOST) */
178 
179 #define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE ||			\
180 				 (akm) == RSN_AKM_UNSPECIFIED ||	\
181 				 (akm) == RSN_AKM_PSK)
182 
183 #ifdef SUPPORT_AP_BWCTRL
184 static void
185 wl_update_apchan_bwcap(struct bcm_cfg80211 *cfg, struct net_device *ndev, chanspec_t chanspec);
186 #endif /* SUPPORT_AP_BWCTRL */
187 
188 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0)) && (LINUX_VERSION_CODE <= (3, 7, 0)))
189 struct chan_info {
190 	int freq;
191 	int chan_type;
192 };
193 #endif
194 
195 #if defined(WL_FW_OCE_AP_SELECT)
wl_cfg80211_is_oce_ap(struct wiphy * wiphy,const u8 * bssid_hint)196 bool wl_cfg80211_is_oce_ap(struct wiphy *wiphy, const u8 *bssid_hint)
197 {
198 	const u8 *parse = NULL;
199 	bcm_tlv_t *ie;
200 	const struct cfg80211_bss_ies *ies;
201 	u32 len;
202 	struct cfg80211_bss *bss;
203 
204 	bss = CFG80211_GET_BSS(wiphy, NULL, bssid_hint, 0, 0);
205 	if (!bss) {
206 		WL_ERR(("Unable to find AP in the cache"));
207 		return false;
208 	}
209 
210 	if (rcu_access_pointer(bss->ies)) {
211 		ies = rcu_access_pointer(bss->ies);
212 		parse = ies->data;
213 		len = ies->len;
214 	} else {
215 		WL_ERR(("ies is NULL"));
216 		return false;
217 	}
218 
219 	while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
220 		if (wl_cfgoce_is_oce_ie((const uint8*)ie, (u8 const **)&parse, &len) == TRUE) {
221 			return true;
222 		} else {
223 			ie = bcm_next_tlv((const bcm_tlv_t*) ie, &len);
224 			if (!ie) {
225 				return false;
226 			}
227 			parse = (uint8 *)ie;
228 			WL_DBG(("NON OCE IE. next ie ptr:%p", parse));
229 		}
230 	}
231 	WL_DBG(("OCE IE NOT found"));
232 	return false;
233 }
234 #endif /* WL_FW_OCE_AP_SELECT */
235 
236 /* Dump the contents of the encoded wps ie buffer and get pbc value */
237 void
wl_validate_wps_ie(const char * wps_ie,s32 wps_ie_len,bool * pbc)238 wl_validate_wps_ie(const char *wps_ie, s32 wps_ie_len, bool *pbc)
239 {
240 	#define WPS_IE_FIXED_LEN 6
241 	s16 len;
242 	const u8 *subel = NULL;
243 	u16 subelt_id;
244 	u16 subelt_len;
245 	u16 val;
246 	u8 *valptr = (uint8*) &val;
247 	if (wps_ie == NULL || wps_ie_len < WPS_IE_FIXED_LEN) {
248 		WL_ERR(("invalid argument : NULL\n"));
249 		return;
250 	}
251 	len = (s16)wps_ie[TLV_LEN_OFF];
252 
253 	if (len > wps_ie_len) {
254 		WL_ERR(("invalid length len %d, wps ie len %d\n", len, wps_ie_len));
255 		return;
256 	}
257 	WL_DBG(("wps_ie len=%d\n", len));
258 	len -= 4;	/* for the WPS IE's OUI, oui_type fields */
259 	subel = wps_ie + WPS_IE_FIXED_LEN;
260 	while (len >= 4) {		/* must have attr id, attr len fields */
261 		valptr[0] = *subel++;
262 		valptr[1] = *subel++;
263 		subelt_id = HTON16(val);
264 
265 		valptr[0] = *subel++;
266 		valptr[1] = *subel++;
267 		subelt_len = HTON16(val);
268 
269 		len -= 4;			/* for the attr id, attr len fields */
270 		len -= (s16)subelt_len;	/* for the remaining fields in this attribute */
271 		if (len < 0) {
272 			break;
273 		}
274 		WL_DBG((" subel=%p, subelt_id=0x%x subelt_len=%u\n",
275 			subel, subelt_id, subelt_len));
276 
277 		if (subelt_id == WPS_ID_VERSION) {
278 			WL_DBG(("  attr WPS_ID_VERSION: %u\n", *subel));
279 		} else if (subelt_id == WPS_ID_REQ_TYPE) {
280 			WL_DBG(("  attr WPS_ID_REQ_TYPE: %u\n", *subel));
281 		} else if (subelt_id == WPS_ID_CONFIG_METHODS) {
282 			valptr[0] = *subel;
283 			valptr[1] = *(subel + 1);
284 			WL_DBG(("  attr WPS_ID_CONFIG_METHODS: %x\n", HTON16(val)));
285 		} else if (subelt_id == WPS_ID_DEVICE_NAME) {
286 			char devname[33];
287 			int namelen = MIN(subelt_len, (sizeof(devname) - 1));
288 
289 			if (namelen) {
290 				memcpy(devname, subel, namelen);
291 				devname[namelen] = '\0';
292 				/* Printing len as rx'ed in the IE */
293 				WL_DBG(("  attr WPS_ID_DEVICE_NAME: %s (len %u)\n",
294 					devname, subelt_len));
295 			}
296 		} else if (subelt_id == WPS_ID_DEVICE_PWD_ID) {
297 			valptr[0] = *subel;
298 			valptr[1] = *(subel + 1);
299 			WL_DBG(("  attr WPS_ID_DEVICE_PWD_ID: %u\n", HTON16(val)));
300 			*pbc = (HTON16(val) == DEV_PW_PUSHBUTTON) ? true : false;
301 		} else if (subelt_id == WPS_ID_PRIM_DEV_TYPE) {
302 			valptr[0] = *subel;
303 			valptr[1] = *(subel + 1);
304 			WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: cat=%u \n", HTON16(val)));
305 			valptr[0] = *(subel + 6);
306 			valptr[1] = *(subel + 7);
307 			WL_DBG(("  attr WPS_ID_PRIM_DEV_TYPE: subcat=%u\n", HTON16(val)));
308 		} else if (subelt_id == WPS_ID_REQ_DEV_TYPE) {
309 			valptr[0] = *subel;
310 			valptr[1] = *(subel + 1);
311 			WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: cat=%u\n", HTON16(val)));
312 			valptr[0] = *(subel + 6);
313 			valptr[1] = *(subel + 7);
314 			WL_DBG(("  attr WPS_ID_REQ_DEV_TYPE: subcat=%u\n", HTON16(val)));
315 		} else if (subelt_id == WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS) {
316 			valptr[0] = *subel;
317 			valptr[1] = *(subel + 1);
318 			WL_DBG(("  attr WPS_ID_SELECTED_REGISTRAR_CONFIG_METHODS"
319 				": cat=%u\n", HTON16(val)));
320 		} else {
321 			WL_DBG(("  unknown attr 0x%x\n", subelt_id));
322 		}
323 
324 		subel += subelt_len;
325 	}
326 }
327 
328 bool
wl_cfg80211_check_vif_in_use(struct net_device * ndev)329 wl_cfg80211_check_vif_in_use(struct net_device *ndev)
330 {
331 	struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
332 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
333 	bool nan_enabled = FALSE;
334 
335 #ifdef WL_NAN
336 	nan_enabled = wl_cfgnan_is_enabled(cfg);
337 #endif /* WL_NAN */
338 
339 	if (nan_enabled || (wl_cfgp2p_vif_created(cfg)) ||
340 		(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) {
341 		WL_MEM(("%s: Virtual interfaces in use. NAN %d P2P %d softAP %d\n",
342 			__FUNCTION__, nan_enabled, wl_cfgp2p_vif_created(cfg),
343 			(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)));
344 		return TRUE;
345 	}
346 
347 	return FALSE;
348 }
349 
350 #ifdef WL_IFACE_MGMT_CONF
351 #ifdef WL_IFACE_MGMT
352 static s32
wl_cfg80211_is_policy_config_allowed(struct bcm_cfg80211 * cfg)353 wl_cfg80211_is_policy_config_allowed(struct bcm_cfg80211 *cfg)
354 {
355 	s32 ret = BCME_OK;
356 	wl_iftype_t active_sec_iface = WL_IFACE_NOT_PRESENT;
357 	bool p2p_disc_on = false;
358 	bool sta_assoc_state = false;
359 	bool nan_init_state = false;
360 
361 	mutex_lock(&cfg->if_sync);
362 
363 	sta_assoc_state = (wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg)) ||
364 		wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg)));
365 	active_sec_iface = wl_cfg80211_get_sec_iface(cfg);
366 	p2p_disc_on = wl_get_p2p_status(cfg, SCANNING);
367 
368 #ifdef WL_NAN
369 	if (cfg->nancfg) {
370 		nan_init_state = cfg->nancfg->nan_init_state;
371 	}
372 #endif
373 
374 	if ((sta_assoc_state == TRUE) || (p2p_disc_on == TRUE) ||
375 			(nan_init_state == TRUE) ||
376 			(active_sec_iface != WL_IFACE_NOT_PRESENT)) {
377 		WL_INFORM_MEM(("Active iface matrix: sta_assoc_state = %d,"
378 			" p2p_disc = %d, nan_disc = %d, active iface = %s\n",
379 			sta_assoc_state, p2p_disc_on, nan_init_state,
380 			wl_iftype_to_str(active_sec_iface)));
381 		ret = BCME_BUSY;
382 	}
383 	mutex_unlock(&cfg->if_sync);
384 	return ret;
385 }
386 #endif /* WL_IFACE_MGMT */
387 #ifdef WL_NANP2P
388 int
wl_cfg80211_set_iface_conc_disc(struct net_device * ndev,uint8 arg_val)389 wl_cfg80211_set_iface_conc_disc(struct net_device *ndev,
390 	uint8 arg_val)
391 {
392 	struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
393 	if (!cfg) {
394 		WL_ERR(("%s: Cannot find cfg\n", __FUNCTION__));
395 		return BCME_ERROR;
396 	}
397 
398 	if (wl_cfg80211_is_policy_config_allowed(cfg) != BCME_OK) {
399 		WL_ERR(("Cant allow iface management modifications\n"));
400 		return BCME_BUSY;
401 	}
402 
403 	if (arg_val) {
404 		cfg->conc_disc |= arg_val;
405 	} else {
406 		cfg->conc_disc &= ~arg_val;
407 	}
408 	return BCME_OK;
409 }
410 
411 uint8
wl_cfg80211_get_iface_conc_disc(struct net_device * ndev)412 wl_cfg80211_get_iface_conc_disc(struct net_device *ndev)
413 {
414 	struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
415 	if (!cfg) {
416 		WL_ERR(("%s: Cannot find cfg\n", __FUNCTION__));
417 		return BCME_ERROR;
418 	}
419 	return cfg->conc_disc;
420 }
421 #endif /* WL_NANP2P */
422 #ifdef WL_IFACE_MGMT
423 int
wl_cfg80211_set_iface_policy(struct net_device * ndev,char * arg,int len)424 wl_cfg80211_set_iface_policy(struct net_device *ndev,
425 	char *arg, int len)
426 {
427 	int ret = BCME_OK;
428 	uint8 i = 0;
429 	iface_mgmt_data_t *iface_data = NULL;
430 
431 	struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
432 	if (!cfg) {
433 		WL_ERR(("%s: Cannot find cfg\n", __FUNCTION__));
434 		return BCME_ERROR;
435 	}
436 
437 	if (wl_cfg80211_is_policy_config_allowed(cfg) != BCME_OK) {
438 		WL_ERR(("Cant allow iface management modifications\n"));
439 		return BCME_BUSY;
440 	}
441 
442 	if (!arg || len <= 0 || len > sizeof(iface_mgmt_data_t)) {
443 		return BCME_BADARG;
444 	}
445 
446 	iface_data = (iface_mgmt_data_t *)arg;
447 	if (iface_data->policy >= WL_IF_POLICY_INVALID) {
448 		WL_ERR(("Unexpected value of policy = %d\n",
449 			iface_data->policy));
450 		return BCME_BADARG;
451 	}
452 
453 	bzero(&cfg->iface_data, sizeof(iface_mgmt_data_t));
454 	ret = memcpy_s(&cfg->iface_data, sizeof(iface_mgmt_data_t), arg, len);
455 	if (ret != BCME_OK) {
456 		WL_ERR(("Failed to copy iface data, src len = %d\n", len));
457 		return ret;
458 	}
459 
460 	if (cfg->iface_data.policy == WL_IF_POLICY_ROLE_PRIORITY) {
461 		for (i = 0; i < WL_IF_TYPE_MAX; i++) {
462 			WL_DBG(("iface = %s, priority[i] = %d\n",
463 			wl_iftype_to_str(i), cfg->iface_data.priority[i]));
464 		}
465 	}
466 
467 	return ret;
468 }
469 
470 uint8
wl_cfg80211_get_iface_policy(struct net_device * ndev)471 wl_cfg80211_get_iface_policy(struct net_device *ndev)
472 
473 {
474 	struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
475 	if (!cfg) {
476 		WL_ERR(("%s: Cannot find cfg\n", __FUNCTION__));
477 		return BCME_ERROR;
478 	}
479 
480 	return cfg->iface_data.policy;
481 }
482 #endif /* WL_IFACE_MGMT */
483 #endif /* WL_IFACE_MGMT_CONF */
484 
485 #ifdef WL_IFACE_MGMT
486 /* Get active secondary data iface type */
487 wl_iftype_t
wl_cfg80211_get_sec_iface(struct bcm_cfg80211 * cfg)488 wl_cfg80211_get_sec_iface(struct bcm_cfg80211 *cfg)
489 {
490 #ifdef WL_STATIC_IF
491 	struct net_device *static_if_ndev;
492 #else
493 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
494 #endif /* WL_STATIC_IF */
495 	struct net_device *p2p_ndev = NULL;
496 
497 	p2p_ndev = wl_to_p2p_bss_ndev(cfg,
498 		P2PAPI_BSSCFG_CONNECTION1);
499 
500 #ifdef WL_STATIC_IF
501 	static_if_ndev = wl_cfg80211_static_if_active(cfg);
502 	if (static_if_ndev) {
503 		if (IS_AP_IFACE(static_if_ndev->ieee80211_ptr)) {
504 			return WL_IF_TYPE_AP;
505 		}
506 	}
507 #else
508 	if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
509 		return WL_IF_TYPE_AP;
510 	}
511 #endif /* WL_STATIC_IF */
512 
513 	if (p2p_ndev && p2p_ndev->ieee80211_ptr) {
514 		if (p2p_ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
515 			return WL_IF_TYPE_P2P_GO;
516 		}
517 
518 		/* Set role to GC when cfg80211 layer downgrades P2P
519 		 * role to station type while bringing down the interface
520 		 */
521 		if (p2p_ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION) {
522 			WL_DBG_MEM(("%s, Change to GC base role\n", __FUNCTION__));
523 			return WL_IF_TYPE_P2P_GC;
524 		}
525 
526 		if (p2p_ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
527 			return WL_IF_TYPE_P2P_GC;
528 		}
529 	}
530 
531 #ifdef WL_NAN
532 	if (wl_cfgnan_is_dp_active(bcmcfg_to_prmry_ndev(cfg))) {
533 		return WL_IF_TYPE_NAN;
534 	}
535 #endif /* WL_NAN */
536 	return WL_IFACE_NOT_PRESENT;
537 }
538 
539 /*
540 * Handle incoming data interface request based on policy.
541 * If there is any conflicting interface, that will be
542 * deleted.
543 */
544 static s32
wl_cfg80211_data_if_mgmt(struct bcm_cfg80211 * cfg,wl_iftype_t new_wl_iftype)545 wl_cfg80211_data_if_mgmt(struct bcm_cfg80211 *cfg,
546 	wl_iftype_t new_wl_iftype)
547 {
548 	s32 ret = BCME_OK;
549 	bool del_iface = false;
550 	wl_iftype_t sec_wl_if_type = wl_cfg80211_get_sec_iface(cfg);
551 
552 	if (sec_wl_if_type == WL_IF_TYPE_NAN &&
553 		new_wl_iftype == WL_IF_TYPE_NAN) {
554 		/* Multi NDP is allowed irrespective of Policy */
555 		return BCME_OK;
556 	}
557 
558 	if (sec_wl_if_type == WL_IFACE_NOT_PRESENT) {
559 		/*
560 		* If there is no active secondary I/F, there
561 		* is no interface conflict. Do nothing.
562 		*/
563 		return BCME_OK;
564 	}
565 
566 	/* Handle secondary data link case */
567 	switch (cfg->iface_data.policy) {
568 		case WL_IF_POLICY_CUSTOM:
569 		case WL_IF_POLICY_DEFAULT: {
570 			WL_INFORM_MEM(("%s, Delete any existing iface\n", __FUNCTION__));
571 			del_iface = true;
572 			break;
573 		}
574 		case WL_IF_POLICY_FCFS: {
575 			WL_INFORM_MEM(("Found active iface = %s, can't support new iface = %s\n",
576 				wl_iftype_to_str(sec_wl_if_type), wl_iftype_to_str(new_wl_iftype)));
577 			ret = BCME_ERROR;
578 			break;
579 		}
580 		case WL_IF_POLICY_LP: {
581 			WL_INFORM_MEM(("Remove active sec data interface, allow incoming iface\n"));
582 			/* Delete existing data iface and allow incoming sec iface */
583 			del_iface = true;
584 			break;
585 		}
586 		case WL_IF_POLICY_ROLE_PRIORITY: {
587 			WL_INFORM_MEM(("Existing iface = %s (%d) and new iface = %s (%d)\n",
588 				wl_iftype_to_str(sec_wl_if_type),
589 				cfg->iface_data.priority[sec_wl_if_type],
590 				wl_iftype_to_str(new_wl_iftype),
591 				cfg->iface_data.priority[new_wl_iftype]));
592 			if (cfg->iface_data.priority[new_wl_iftype] >
593 				cfg->iface_data.priority[sec_wl_if_type]) {
594 				del_iface = true;
595 			} else {
596 				WL_ERR(("Can't support new iface = %s\n",
597 					wl_iftype_to_str(new_wl_iftype)));
598 					ret = BCME_ERROR;
599 			}
600 			break;
601 		}
602 		default: {
603 			WL_ERR(("Unsupported interface policy = %d\n",
604 				cfg->iface_data.policy));
605 			return BCME_ERROR;
606 		}
607 	}
608 	if (del_iface) {
609 		ret = wl_cfg80211_delete_iface(cfg, sec_wl_if_type);
610 	}
611 	return ret;
612 }
613 
614 /* Handle discovery ifaces based on policy */
615 static s32
wl_cfg80211_disc_if_mgmt(struct bcm_cfg80211 * cfg,wl_iftype_t new_wl_iftype,bool * disable_nan,bool * disable_p2p)616 wl_cfg80211_disc_if_mgmt(struct bcm_cfg80211 *cfg,
617 	wl_iftype_t new_wl_iftype, bool *disable_nan, bool *disable_p2p)
618 {
619 	s32 ret = BCME_OK;
620 	wl_iftype_t sec_wl_if_type =
621 		wl_cfg80211_get_sec_iface(cfg);
622 	*disable_p2p = false;
623 	*disable_nan = false;
624 
625 	if (sec_wl_if_type == WL_IF_TYPE_NAN &&
626 			new_wl_iftype == WL_IF_TYPE_NAN) {
627 		/* Multi NDP is allowed irrespective of Policy */
628 		return BCME_OK;
629 	}
630 
631 	/*
632 	* Check for any policy conflicts with active secondary
633 	* interface for incoming discovery iface
634 	*/
635 	if ((sec_wl_if_type != WL_IFACE_NOT_PRESENT) &&
636 		(is_discovery_iface(new_wl_iftype))) {
637 		switch (cfg->iface_data.policy) {
638 			case WL_IF_POLICY_CUSTOM: {
639 				if (sec_wl_if_type == WL_IF_TYPE_NAN &&
640 					new_wl_iftype == WL_IF_TYPE_P2P_DISC) {
641 					WL_INFORM_MEM(("Allow P2P Discovery with active NDP\n"));
642 					/* No further checks are required. */
643 					return BCME_OK;
644 				}
645 				/*
646 				* Intentional fall through to default policy
647 				* as for AP and associated ifaces, both are same
648 				*/
649 			}
650 			case WL_IF_POLICY_DEFAULT: {
651 				 if (sec_wl_if_type == WL_IF_TYPE_AP) {
652 					WL_INFORM_MEM(("AP is active, cant support new iface\n"));
653 					ret = BCME_ERROR;
654 				} else if (sec_wl_if_type == WL_IF_TYPE_P2P_GC ||
655 					sec_wl_if_type == WL_IF_TYPE_P2P_GO) {
656 					if (new_wl_iftype == WL_IF_TYPE_P2P_DISC) {
657 						/*
658 						* Associated discovery case,
659 						* Fall through
660 						*/
661 					} else {
662 						/* Active iface is present, returning error */
663 						WL_INFORM_MEM(("P2P group is active,"
664 							" cant support new iface\n"));
665 						ret = BCME_ERROR;
666 					}
667 				} else if (sec_wl_if_type == WL_IF_TYPE_NAN) {
668 					ret = wl_cfg80211_delete_iface(cfg, sec_wl_if_type);
669 				}
670 				break;
671 			}
672 			case WL_IF_POLICY_FCFS: {
673 				WL_INFORM_MEM(("Can't support new iface = %s\n",
674 						wl_iftype_to_str(new_wl_iftype)));
675 				ret = BCME_ERROR;
676 				break;
677 			}
678 			case WL_IF_POLICY_LP: {
679 				/* Delete existing data iface n allow incoming sec iface */
680 				WL_INFORM_MEM(("Remove active sec data interface = %s\n",
681 					wl_iftype_to_str(sec_wl_if_type)));
682 				ret = wl_cfg80211_delete_iface(cfg,
683 						sec_wl_if_type);
684 				break;
685 			}
686 			case WL_IF_POLICY_ROLE_PRIORITY: {
687 				WL_INFORM_MEM(("Existing iface = %s (%d) and new iface = %s (%d)\n",
688 					wl_iftype_to_str(sec_wl_if_type),
689 					cfg->iface_data.priority[sec_wl_if_type],
690 					wl_iftype_to_str(new_wl_iftype),
691 					cfg->iface_data.priority[new_wl_iftype]));
692 				if (cfg->iface_data.priority[new_wl_iftype] >
693 					cfg->iface_data.priority[sec_wl_if_type]) {
694 					WL_INFORM_MEM(("Remove active sec data iface\n"));
695 					ret = wl_cfg80211_delete_iface(cfg,
696 						sec_wl_if_type);
697 				} else {
698 					WL_ERR(("Can't support new iface = %s"
699 						" due to low priority\n",
700 						wl_iftype_to_str(new_wl_iftype)));
701 						ret = BCME_ERROR;
702 				}
703 				break;
704 			}
705 			default: {
706 				WL_ERR(("Unsupported policy\n"));
707 				return BCME_ERROR;
708 			}
709 		}
710 	} else {
711 		/*
712 		* Handle incoming new secondary iface request,
713 		* irrespective of existing discovery ifaces
714 		*/
715 		if ((cfg->iface_data.policy == WL_IF_POLICY_CUSTOM) &&
716 			(new_wl_iftype == WL_IF_TYPE_NAN)) {
717 			WL_INFORM_MEM(("Allow NAN Data Path\n"));
718 			/* No further checks are required. */
719 			return BCME_OK;
720 		}
721 	}
722 
723 	/* Check for any conflicting discovery iface */
724 	switch (new_wl_iftype) {
725 		case WL_IF_TYPE_P2P_DISC:
726 		case WL_IF_TYPE_P2P_GO:
727 		case WL_IF_TYPE_P2P_GC: {
728 			*disable_nan = true;
729 			break;
730 		}
731 		case WL_IF_TYPE_NAN_NMI:
732 		case WL_IF_TYPE_NAN: {
733 			*disable_p2p = true;
734 			break;
735 		}
736 		case WL_IF_TYPE_STA:
737 		case WL_IF_TYPE_AP: {
738 			*disable_nan = true;
739 			*disable_p2p = true;
740 			break;
741 		}
742 		default: {
743 			WL_ERR(("Unsupported\n"));
744 			return BCME_ERROR;
745 		}
746 	}
747 	return ret;
748 }
749 
750 static bool
wl_cfg80211_is_associated_discovery(struct bcm_cfg80211 * cfg,wl_iftype_t new_wl_iftype)751 wl_cfg80211_is_associated_discovery(struct bcm_cfg80211 *cfg,
752 	wl_iftype_t new_wl_iftype)
753 {
754 	struct net_device *p2p_ndev = NULL;
755 	p2p_ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION1);
756 
757 	if (new_wl_iftype == WL_IF_TYPE_P2P_DISC && p2p_ndev &&
758 		p2p_ndev->ieee80211_ptr &&
759 		is_p2p_group_iface(p2p_ndev->ieee80211_ptr)) {
760 			return true;
761 	}
762 #ifdef WL_NAN
763 	else if ((new_wl_iftype == WL_IF_TYPE_NAN_NMI) &&
764 		(wl_cfgnan_is_dp_active(bcmcfg_to_prmry_ndev(cfg)))) {
765 			return true;
766 		}
767 #endif /* WL_NAN */
768 	return false;
769 }
770 
771 /* Handle incoming discovery iface request */
772 static s32
wl_cfg80211_handle_discovery_config(struct bcm_cfg80211 * cfg,wl_iftype_t new_wl_iftype)773 wl_cfg80211_handle_discovery_config(struct bcm_cfg80211 *cfg,
774 	wl_iftype_t new_wl_iftype)
775 {
776 	s32 ret = BCME_OK;
777 	bool disable_p2p = false;
778 	bool disable_nan = false;
779 
780 	wl_iftype_t active_sec_iface =
781 		wl_cfg80211_get_sec_iface(cfg);
782 
783 	if (is_discovery_iface(new_wl_iftype) &&
784 		(active_sec_iface != WL_IFACE_NOT_PRESENT)) {
785 		if (wl_cfg80211_is_associated_discovery(cfg,
786 			new_wl_iftype) == TRUE) {
787 			WL_DBG(("Associate iface request is allowed= %s\n",
788 				wl_iftype_to_str(new_wl_iftype)));
789 			return ret;
790 		}
791 	}
792 
793 	ret = wl_cfg80211_disc_if_mgmt(cfg, new_wl_iftype,
794 			&disable_nan, &disable_p2p);
795 	if (ret != BCME_OK) {
796 		WL_ERR(("Failed at disc iface mgmt, ret = %d\n", ret));
797 		return ret;
798 	}
799 #ifdef WL_NANP2P
800 	if (((new_wl_iftype == WL_IF_TYPE_P2P_DISC) && disable_nan) ||
801 		((new_wl_iftype == WL_IF_TYPE_NAN_NMI) && disable_p2p)) {
802 		if ((cfg->nan_p2p_supported == TRUE) &&
803 		(cfg->conc_disc == WL_NANP2P_CONC_SUPPORT)) {
804 			WL_INFORM_MEM(("P2P + NAN conc is supported\n"));
805 			disable_p2p = false;
806 			disable_nan = false;
807 		}
808 	}
809 #endif /* WL_NANP2P */
810 
811 	if (disable_nan) {
812 #ifdef WL_NAN
813 		/* Disable nan to avoid conflict with p2p */
814 		ret = wl_cfgnan_check_nan_disable_pending(cfg, true, true);
815 		if (ret != BCME_OK) {
816 			WL_ERR(("failed to disable nan, error[%d]\n", ret));
817 			return ret;
818 		}
819 #endif /* WL_NAN */
820 	}
821 
822 	if (disable_p2p) {
823 		/* Disable p2p discovery */
824 		ret = wl_cfg80211_deinit_p2p_discovery(cfg);
825 		if (ret != BCME_OK) {
826 			/* Should we fail nan enab here */
827 			WL_ERR(("Failed to disable p2p_disc for allowing nan\n"));
828 			return ret;
829 		}
830 	}
831 	return ret;
832 }
833 
834 /*
835 * Check for any conflicting iface before adding iface.
836 * Based on policy, either conflicting iface is removed
837 * or new iface add request is blocked.
838 */
839 s32
wl_cfg80211_handle_if_role_conflict(struct bcm_cfg80211 * cfg,wl_iftype_t new_wl_iftype)840 wl_cfg80211_handle_if_role_conflict(struct bcm_cfg80211 *cfg,
841 	wl_iftype_t new_wl_iftype)
842 {
843 	s32 ret = BCME_OK;
844 #ifdef P2P_AP_CONCURRENT
845 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
846 #endif
847 
848 	WL_INFORM_MEM(("Incoming iface = %s\n", wl_iftype_to_str(new_wl_iftype)));
849 
850 #ifdef P2P_AP_CONCURRENT
851 	if (dhd->conf->war & P2P_AP_MAC_CONFLICT) {
852 		return ret;
853 	} else
854 #endif
855 #ifdef WL_STATIC_IF
856 	if (wl_cfg80211_get_sec_iface(cfg) == WL_IF_TYPE_AP &&
857 			new_wl_iftype == WL_IF_TYPE_AP) {
858 	} else
859 #endif /* WL_STATIC_IF */
860 	if (!is_discovery_iface(new_wl_iftype)) {
861 		/* Incoming data interface request */
862 		if (wl_cfg80211_get_sec_iface(cfg) != WL_IFACE_NOT_PRESENT) {
863 			/* active interface present - Apply interface data policy */
864 			ret = wl_cfg80211_data_if_mgmt(cfg, new_wl_iftype);
865 			if (ret != BCME_OK) {
866 				WL_ERR(("if_mgmt fail:%d\n", ret));
867 				return ret;
868 			}
869 		}
870 	}
871 	/* Apply discovery config */
872 	ret = wl_cfg80211_handle_discovery_config(cfg, new_wl_iftype);
873 	return ret;
874 }
875 #endif /* WL_IFACE_MGMT */
876 
877 s32
wl_release_vif_macaddr(struct bcm_cfg80211 * cfg,u8 * mac_addr,u16 wl_iftype)878 wl_release_vif_macaddr(struct bcm_cfg80211 *cfg, u8 *mac_addr, u16 wl_iftype)
879 {
880 	struct net_device *ndev =  bcmcfg_to_prmry_ndev(cfg);
881 	u16 org_toggle_bytes;
882 	u16 cur_toggle_bytes;
883 	u16 toggled_bit;
884 
885 	if (!ndev || !mac_addr || ETHER_ISNULLADDR(mac_addr)) {
886 		return -EINVAL;
887 	}
888 	WL_DBG(("%s:Mac addr" MACDBG "\n",
889 			__FUNCTION__, MAC2STRDBG(mac_addr)));
890 
891 	if ((wl_iftype == WL_IF_TYPE_P2P_DISC) || (wl_iftype == WL_IF_TYPE_AP) ||
892 		(wl_iftype == WL_IF_TYPE_P2P_GO) || (wl_iftype == WL_IF_TYPE_P2P_GC)) {
893 		/* Avoid invoking release mac addr code for interfaces using
894 		 * fixed mac addr.
895 		 */
896 		return BCME_OK;
897 	}
898 
899 	/* Fetch last two bytes of mac address */
900 	org_toggle_bytes = ntoh16(*((u16 *)&ndev->dev_addr[4]));
901 	cur_toggle_bytes = ntoh16(*((u16 *)&mac_addr[4]));
902 
903 	toggled_bit = (org_toggle_bytes ^ cur_toggle_bytes);
904 	WL_DBG(("org_toggle_bytes:%04X cur_toggle_bytes:%04X\n",
905 		org_toggle_bytes, cur_toggle_bytes));
906 	if (toggled_bit & cfg->vif_macaddr_mask) {
907 		/* This toggled_bit is marked in the used mac addr
908 		 * mask. Clear it.
909 		 */
910 		cfg->vif_macaddr_mask &= ~toggled_bit;
911 		WL_INFORM(("MAC address - " MACDBG " released. toggled_bit:%04X vif_mask:%04X\n",
912 			MAC2STRDBG(mac_addr), toggled_bit, cfg->vif_macaddr_mask));
913 	} else {
914 		WL_ERR(("MAC address - " MACDBG " not found in the used list."
915 			" toggled_bit:%04x vif_mask:%04x\n", MAC2STRDBG(mac_addr),
916 			toggled_bit, cfg->vif_macaddr_mask));
917 		return -EINVAL;
918 	}
919 
920 	return BCME_OK;
921 }
922 
923 s32
wl_get_vif_macaddr(struct bcm_cfg80211 * cfg,u16 wl_iftype,u8 * mac_addr)924 wl_get_vif_macaddr(struct bcm_cfg80211 *cfg, u16 wl_iftype, u8 *mac_addr)
925 {
926 	struct ether_addr *p2p_dev_addr = wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE);
927 	struct net_device *ndev =  bcmcfg_to_prmry_ndev(cfg);
928 	u16 toggle_mask;
929 	u16 toggle_bit;
930 	u16 toggle_bytes;
931 	u16 used;
932 	u32 offset = 0;
933 	/* Toggle mask starts from MSB of second last byte */
934 	u16 mask = 0x8000;
935 	if (!mac_addr) {
936 		return -EINVAL;
937 	}
938 	if ((wl_iftype == WL_IF_TYPE_P2P_DISC) && p2p_dev_addr &&
939 		ETHER_IS_LOCALADDR(p2p_dev_addr)) {
940 		/* If mac address is already generated return the mac */
941 		(void)memcpy_s(mac_addr, ETH_ALEN, p2p_dev_addr->octet, ETH_ALEN);
942 		return 0;
943 	}
944 	(void)memcpy_s(mac_addr, ETH_ALEN, ndev->perm_addr, ETH_ALEN);
945 /*
946  * VIF MAC address managment
947  * P2P Device addres: Primary MAC with locally admin. bit set
948  * P2P Group address/NAN NMI/Softap/NAN DPI: Primary MAC addr
949  *    with local admin bit set and one additional bit toggled.
950  * cfg->vif_macaddr_mask will hold the info regarding the mac address
951  * released. Ensure to call wl_release_vif_macaddress to free up
952  * the mac address.
953  */
954 #if defined (SPECIFIC_MAC_GEN_SCHEME)
955 	if (wl_iftype == WL_IF_TYPE_P2P_DISC ||	wl_iftype == WL_IF_TYPE_AP) {
956 		mac_addr[0] |= 0x02;
957 	} else if ((wl_iftype == WL_IF_TYPE_P2P_GO) || (wl_iftype == WL_IF_TYPE_P2P_GC)) {
958 		mac_addr[0] |= 0x02;
959 		mac_addr[4] ^= 0x80;
960 	}
961 #else
962 	if (wl_iftype == WL_IF_TYPE_P2P_DISC) {
963 		mac_addr[0] |= 0x02;
964 	}
965 #endif /* SEPCIFIC_MAC_GEN_SCHEME */
966 	else {
967 		/* For locally administered mac addresses, we keep the
968 		 * OUI part constant and just work on the last two bytes.
969 		 */
970 		mac_addr[0] |= 0x02;
971 		toggle_mask = cfg->vif_macaddr_mask;
972 		toggle_bytes = ntoh16(*((u16 *)&mac_addr[4]));
973 		do {
974 			used = toggle_mask & mask;
975 			if (!used) {
976 				/* Use this bit position */
977 				toggle_bit = mask >> offset;
978 				toggle_bytes ^= toggle_bit;
979 				cfg->vif_macaddr_mask |= toggle_bit;
980 				WL_DBG(("toggle_bit:%04X toggle_bytes:%04X toggle_mask:%04X\n",
981 					toggle_bit, toggle_bytes, cfg->vif_macaddr_mask));
982 				/* Macaddress are stored in network order */
983 				mac_addr[5] = *((u8 *)&toggle_bytes);
984 				mac_addr[4] = *(((u8 *)&toggle_bytes + 1));
985 				break;
986 			}
987 
988 			/* Shift by one */
989 			toggle_mask = toggle_mask << 0x1;
990 			offset++;
991 			if (offset > MAX_VIF_OFFSET) {
992 				/* We have used up all macaddresses. Something wrong! */
993 				WL_ERR(("Entire range of macaddress used up.\n"));
994 				ASSERT(0);
995 				break;
996 			}
997 		} while (true);
998 	}
999 	WL_INFORM_MEM(("Get virtual I/F mac addr: "MACDBG"\n", MAC2STRDBG(mac_addr)));
1000 	return 0;
1001 }
1002 
1003 bcm_struct_cfgdev *
wl_cfg80211_add_virtual_iface(struct wiphy * wiphy,const char * name,unsigned char name_assign_type,enum nl80211_iftype type,u32 * flags,struct vif_params * params)1004 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
1005 #if defined(WL_CFG80211_P2P_DEV_IF)
1006 	const char *name,
1007 #else
1008 	char *name,
1009 #endif /* WL_CFG80211_P2P_DEV_IF */
1010 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0))
1011 	unsigned char name_assign_type,
1012 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) */
1013 	enum nl80211_iftype type,
1014 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
1015 	u32 *flags,
1016 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) */
1017 	struct vif_params *params)
1018 {
1019 	u16 wl_iftype;
1020 	u16 wl_mode;
1021 	struct net_device *primary_ndev;
1022 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1023 	struct wireless_dev *wdev;
1024 
1025 	WL_DBG(("Enter iftype: %d\n", type));
1026 	if (!cfg) {
1027 		return ERR_PTR(-EINVAL);
1028 	}
1029 
1030 	/* Use primary I/F for sending cmds down to firmware */
1031 	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1032 	if (unlikely(!wl_get_drv_status(cfg, READY, primary_ndev))) {
1033 		WL_ERR(("device is not ready\n"));
1034 		return ERR_PTR(-ENODEV);
1035 	}
1036 
1037 	if (!name) {
1038 		WL_ERR(("Interface name not provided \n"));
1039 		return ERR_PTR(-EINVAL);
1040 	}
1041 
1042 	if (cfg80211_to_wl_iftype(type, &wl_iftype, &wl_mode) < 0) {
1043 		return ERR_PTR(-EINVAL);
1044 	}
1045 
1046 	wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, name, NULL);
1047 	if (unlikely(!wdev)) {
1048 		return ERR_PTR(-ENODEV);
1049 	}
1050 	return wdev_to_cfgdev(wdev);
1051 }
1052 
1053 s32
wl_cfg80211_del_virtual_iface(struct wiphy * wiphy,bcm_struct_cfgdev * cfgdev)1054 wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev)
1055 {
1056 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1057 	struct wireless_dev *wdev = cfgdev_to_wdev(cfgdev);
1058 	int ret = BCME_OK;
1059 	u16 wl_iftype;
1060 	u16 wl_mode;
1061 	struct net_device *primary_ndev;
1062 
1063 	if (!cfg) {
1064 		return -EINVAL;
1065 	}
1066 
1067 	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1068 	wdev = cfgdev_to_wdev(cfgdev);
1069 	if (!wdev) {
1070 		WL_ERR(("wdev null"));
1071 		return -ENODEV;
1072 	}
1073 
1074 	WL_DBG(("Enter  wdev:%p iftype: %d\n", wdev, wdev->iftype));
1075 	if (cfg80211_to_wl_iftype(wdev->iftype, &wl_iftype, &wl_mode) < 0) {
1076 		WL_ERR(("Wrong iftype: %d\n", wdev->iftype));
1077 		return -ENODEV;
1078 	}
1079 
1080 	if ((ret = wl_cfg80211_del_if(cfg, primary_ndev,
1081 			wdev, NULL)) < 0) {
1082 		WL_ERR(("IF del failed\n"));
1083 	}
1084 
1085 	return ret;
1086 }
1087 
1088 static s32
wl_cfg80211_change_p2prole(struct wiphy * wiphy,struct net_device * ndev,enum nl80211_iftype type)1089 wl_cfg80211_change_p2prole(struct wiphy *wiphy, struct net_device *ndev, enum nl80211_iftype type)
1090 {
1091 	s32 wlif_type;
1092 	s32 mode = 0;
1093 	s32 index;
1094 	s32 err;
1095 	s32 conn_idx = -1;
1096 	chanspec_t chspec;
1097 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1098 	struct ether_addr p2p_dev_addr = {{0, 0, 0, 0, 0, 0}};
1099 #ifdef BCMDONGLEHOST
1100 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1101 #endif /* BCMDONGLEHOST */
1102 
1103 	WL_INFORM_MEM(("Enter. current_role:%d new_role:%d \n", ndev->ieee80211_ptr->iftype, type));
1104 
1105 	(void)memcpy_s(p2p_dev_addr.octet, ETHER_ADDR_LEN,
1106 		ndev->dev_addr, ETHER_ADDR_LEN);
1107 
1108 	if (!cfg->p2p || !wl_cfgp2p_vif_created(cfg)) {
1109 		WL_ERR(("P2P not initialized \n"));
1110 		return -EINVAL;
1111 	}
1112 
1113 	if (!is_p2p_group_iface(ndev->ieee80211_ptr)) {
1114 		WL_ERR(("Wrong if type \n"));
1115 		return -EINVAL;
1116 	}
1117 
1118 	/* Abort any on-going scans to avoid race condition issues */
1119 	wl_cfgscan_cancel_scan(cfg);
1120 
1121 	index = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr);
1122 	if (index < 0) {
1123 		WL_ERR(("Find bsscfg index from ndev(%p) failed\n", ndev));
1124 		return BCME_ERROR;
1125 	}
1126 	if (wl_cfgp2p_find_type(cfg, index, &conn_idx) != BCME_OK) {
1127 		return BCME_ERROR;
1128 	}
1129 
1130 	/* In concurrency case, STA may be already associated in a particular
1131 	 * channel. so retrieve the current channel of primary interface and
1132 	 * then start the virtual interface on that.
1133 	 */
1134 	chspec = wl_cfg80211_get_shared_freq(wiphy);
1135 	if (type == NL80211_IFTYPE_P2P_GO) {
1136 		/* Dual p2p doesn't support multiple P2PGO interfaces,
1137 		 * p2p_go_count is the counter for GO creation
1138 		 * requests.
1139 		 */
1140 		if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
1141 			WL_ERR(("FW does not support multiple GO\n"));
1142 			return BCME_ERROR;
1143 		}
1144 		mode = WL_MODE_AP;
1145 		wlif_type = WL_P2P_IF_GO;
1146 #ifdef BCMDONGLEHOST
1147 		dhd->op_mode &= ~DHD_FLAG_P2P_GC_MODE;
1148 		dhd->op_mode |= DHD_FLAG_P2P_GO_MODE;
1149 #endif /* BCMDONGLEHOST */
1150 	} else {
1151 		wlif_type = WL_P2P_IF_CLIENT;
1152 		/* for GO */
1153 		if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
1154 			WL_INFORM_MEM(("Downgrading P2P GO to cfg_iftype:%d \n", type));
1155 			wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
1156 			cfg->p2p->p2p_go_count--;
1157 			/* disable interface before bsscfg free */
1158 			err = wl_cfgp2p_ifdisable(cfg, &p2p_dev_addr);
1159 			/* if fw doesn't support "ifdis",
1160 			 * do not wait for link down of ap mode
1161 			 */
1162 			if (err == 0) {
1163 				WL_DBG(("Wait for Link Down event for GO !!!\n"));
1164 				wait_for_completion_timeout(&cfg->iface_disable,
1165 					msecs_to_jiffies(500));
1166 			} else if (err != BCME_UNSUPPORTED) {
1167 				msleep(300);
1168 			}
1169 		}
1170 	}
1171 
1172 	wl_set_p2p_status(cfg, IF_CHANGING);
1173 	wl_clr_p2p_status(cfg, IF_CHANGED);
1174 	wl_cfgp2p_ifchange(cfg, &p2p_dev_addr,
1175 		htod32(wlif_type), chspec, conn_idx);
1176 	wait_event_interruptible_timeout(cfg->netif_change_event,
1177 		(wl_get_p2p_status(cfg, IF_CHANGED) == true),
1178 		msecs_to_jiffies(MAX_WAIT_TIME));
1179 
1180 	wl_clr_p2p_status(cfg, IF_CHANGING);
1181 	wl_clr_p2p_status(cfg, IF_CHANGED);
1182 
1183 	if (mode == WL_MODE_AP) {
1184 		wl_set_drv_status(cfg, CONNECTED, ndev);
1185 #ifdef SUPPORT_AP_POWERSAVE
1186 			dhd_set_ap_powersave(dhd, 0, TRUE);
1187 #endif /* SUPPORT_AP_POWERSAVE */
1188 	}
1189 
1190 	return BCME_OK;
1191 }
1192 
1193 s32
wl_cfg80211_change_virtual_iface(struct wiphy * wiphy,struct net_device * ndev,enum nl80211_iftype type,u32 * flags,struct vif_params * params)1194 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
1195 	enum nl80211_iftype type,
1196 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0))
1197 	u32 *flags,
1198 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(4, 12, 0) */
1199 	struct vif_params *params)
1200 {
1201 	s32 infra = 1;
1202 	s32 err = BCME_OK;
1203 	u16 wl_iftype;
1204 	u16 wl_mode;
1205 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1206 	struct net_info *netinfo = NULL;
1207 #ifdef BCMDONGLEHOST
1208 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
1209 #endif /* BCMDONGLEHOST */
1210 	struct net_device *primary_ndev;
1211 
1212 #ifdef BCMDONGLEHOST
1213 	if (!dhd)
1214 		return -EINVAL;
1215 #endif /* BCMDONGLEHOST */
1216 
1217 	WL_INFORM_MEM(("[%s] Enter. current cfg_iftype:%d new cfg_iftype:%d \n",
1218 		ndev->name, ndev->ieee80211_ptr->iftype, type));
1219 	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1220 
1221 	if (cfg80211_to_wl_iftype(type, &wl_iftype, &wl_mode) < 0) {
1222 		WL_ERR(("Unknown role \n"));
1223 		return -EINVAL;
1224 	}
1225 
1226 	mutex_lock(&cfg->if_sync);
1227 	netinfo = wl_get_netinfo_by_wdev(cfg, ndev->ieee80211_ptr);
1228 	if (unlikely(!netinfo)) {
1229 #ifdef WL_STATIC_IF
1230 		if (wl_cfg80211_static_if(cfg, ndev)) {
1231 			/* Incase of static interfaces, the netinfo will be
1232 			 * allocated only when FW interface is initialized. So
1233 			 * store the value and use it during initialization.
1234 			 */
1235 			WL_INFORM_MEM(("skip change vif for static if\n"));
1236 			ndev->ieee80211_ptr->iftype = type;
1237 			err = BCME_OK;
1238 		} else
1239 #endif /* WL_STATIC_IF */
1240 		{
1241 			WL_ERR(("netinfo not found \n"));
1242 			err = -ENODEV;
1243 		}
1244 		goto fail;
1245 	}
1246 
1247 	if ((primary_ndev == ndev) && !(ndev->flags & IFF_UP)) {
1248 		/*
1249 		* If interface is not initialized, store the role and
1250 		* return. The role will be initilized after interface
1251 		* up
1252 		*/
1253 		WL_INFORM_MEM(("skip change role before dev up\n"));
1254 		ndev->ieee80211_ptr->iftype = type;
1255 		err = BCME_OK;
1256 		goto fail;
1257 	}
1258 
1259 	/* perform pre-if-change tasks */
1260 	wl_cfg80211_iface_state_ops(ndev->ieee80211_ptr,
1261 		WL_IF_CHANGE_REQ, wl_iftype, wl_mode);
1262 
1263 	switch (type) {
1264 	case NL80211_IFTYPE_ADHOC:
1265 		infra = 0;
1266 		break;
1267 	case NL80211_IFTYPE_STATION:
1268 		/* Supplicant sets iftype to STATION while removing p2p GO */
1269 		if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
1270 			/* Downgrading P2P GO */
1271 			err = wl_cfg80211_change_p2prole(wiphy, ndev, type);
1272 			if (unlikely(err)) {
1273 				WL_ERR(("P2P downgrade failed \n"));
1274 			}
1275 		} else if (ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
1276 			/* Downgrade role from AP to STA */
1277 			if ((err = wl_cfg80211_add_del_bss(cfg, ndev,
1278 				netinfo->bssidx, wl_iftype, 0, NULL)) < 0) {
1279 				WL_ERR(("AP-STA Downgrade failed \n"));
1280 				goto fail;
1281 			}
1282 		}
1283 		break;
1284 	case NL80211_IFTYPE_AP:
1285 		/* intentional fall through */
1286 	case NL80211_IFTYPE_AP_VLAN:
1287 		{
1288 			if (!wl_get_drv_status(cfg, AP_CREATED, ndev) &&
1289 					wl_get_drv_status(cfg, READY, ndev)) {
1290 #if defined(BCMDONGLEHOST) && !defined(OEM_ANDROID)
1291 				dhd->op_mode = DHD_FLAG_HOSTAP_MODE;
1292 #endif /* BCMDONGLEHOST */
1293 				err = wl_cfg80211_set_ap_role(cfg, ndev);
1294 				if (unlikely(err)) {
1295 					WL_ERR(("set ap role failed!\n"));
1296 					goto fail;
1297 				}
1298 			} else {
1299 				WL_INFORM_MEM(("AP_CREATED bit set. Skip role change\n"));
1300 			}
1301 			break;
1302 		}
1303 	case NL80211_IFTYPE_P2P_GO:
1304 		/* Intentional fall through */
1305 	case NL80211_IFTYPE_P2P_CLIENT:
1306 		infra = 1;
1307 		err = wl_cfg80211_change_p2prole(wiphy, ndev, type);
1308 		break;
1309 	case NL80211_IFTYPE_MONITOR:
1310 	case NL80211_IFTYPE_WDS:
1311 	case NL80211_IFTYPE_MESH_POINT:
1312 		/* Intentional fall through */
1313 	default:
1314 		WL_ERR(("Unsupported type:%d \n", type));
1315 		err = -EINVAL;
1316 		goto fail;
1317 	}
1318 
1319 	if (wl_get_drv_status(cfg, READY, ndev)) {
1320 		err = wldev_ioctl_set(ndev, WLC_SET_INFRA, &infra, sizeof(s32));
1321 		if (err < 0) {
1322 			WL_ERR(("SET INFRA/IBSS  error %d\n", err));
1323 			goto fail;
1324 		}
1325 	}
1326 
1327 	wl_cfg80211_iface_state_ops(primary_ndev->ieee80211_ptr,
1328 		WL_IF_CHANGE_DONE, wl_iftype, wl_mode);
1329 
1330 	/* Update new iftype in relevant structures */
1331 	if (is_p2p_group_iface(ndev->ieee80211_ptr) && (type == NL80211_IFTYPE_STATION)) {
1332 		/* For role downgrade cases, we keep interface role as GC */
1333 		netinfo->iftype = WL_IF_TYPE_P2P_GC;
1334 		WL_DBG_MEM(("[%s] Set  base role to GC, current role"
1335 			"ndev->ieee80211_ptr->iftype = %d\n",
1336 			__FUNCTION__, ndev->ieee80211_ptr->iftype));
1337 	} else {
1338 		netinfo->iftype = wl_iftype;
1339 	}
1340 
1341 	ndev->ieee80211_ptr->iftype = type;
1342 
1343 	WL_INFORM_MEM(("[%s] cfg_iftype changed to %d\n", ndev->name, type));
1344 #ifdef WL_EXT_IAPSTA
1345 	wl_ext_iapsta_update_iftype(ndev, wl_iftype);
1346 #endif
1347 
1348 fail:
1349 	if (err) {
1350 		wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
1351 	}
1352 	mutex_unlock(&cfg->if_sync);
1353 	return err;
1354 }
1355 
1356 #ifdef SUPPORT_AP_BWCTRL
1357 static chanspec_t
wl_channel_to_chanspec(struct wiphy * wiphy,struct net_device * dev,u32 channel,u32 bw_cap)1358 wl_channel_to_chanspec(struct wiphy *wiphy, struct net_device *dev, u32 channel, u32 bw_cap)
1359 {
1360 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1361 	u8 *buf = NULL;
1362 	wl_uint32_list_t *list;
1363 	int err = BCME_OK;
1364 	chanspec_t c = 0, ret_c = 0;
1365 	int bw = 0, tmp_bw = 0;
1366 	int i;
1367 	u32 tmp_c;
1368 
1369 #define LOCAL_BUF_SIZE	1024
1370 	buf = (u8 *)MALLOC(cfg->osh, LOCAL_BUF_SIZE);
1371 	if (!buf) {
1372 		WL_ERR(("buf memory alloc failed\n"));
1373 		goto exit;
1374 	}
1375 
1376 	err = wldev_iovar_getbuf_bsscfg(dev, "chanspecs", NULL,
1377 		0, buf, LOCAL_BUF_SIZE, 0, &cfg->ioctl_buf_sync);
1378 	if (err != BCME_OK) {
1379 		WL_ERR(("get chanspecs failed with %d\n", err));
1380 		goto exit;
1381 	}
1382 
1383 	list = (wl_uint32_list_t *)(void *)buf;
1384 	for (i = 0; i < dtoh32(list->count); i++) {
1385 		c = dtoh32(list->element[i]);
1386 		if (channel <= CH_MAX_2G_CHANNEL) {
1387 			if (!CHSPEC_IS20(c))
1388 				continue;
1389 			if (channel == CHSPEC_CHANNEL(c)) {
1390 				ret_c = c;
1391 				bw = 20;
1392 				goto exit;
1393 			}
1394 		}
1395 		tmp_c = wf_chspec_ctlchan(c);
1396 		tmp_bw = bw2cap[CHSPEC_BW(c) >> WL_CHANSPEC_BW_SHIFT];
1397 		if (tmp_c != channel)
1398 			continue;
1399 
1400 		if ((tmp_bw > bw) && (tmp_bw <= bw_cap)) {
1401 			bw = tmp_bw;
1402 			ret_c = c;
1403 			if (bw == bw_cap)
1404 				goto exit;
1405 		}
1406 	}
1407 exit:
1408 	if (buf) {
1409 		 MFREE(cfg->osh, buf, LOCAL_BUF_SIZE);
1410 	}
1411 #undef LOCAL_BUF_SIZE
1412 	WL_DBG(("return chanspec %x %d\n", ret_c, bw));
1413 	return ret_c;
1414 }
1415 #endif /* SUPPORT_AP_BWCTRL */
1416 
1417 void
wl_cfg80211_cleanup_virtual_ifaces(struct bcm_cfg80211 * cfg,bool rtnl_lock_reqd)1418 wl_cfg80211_cleanup_virtual_ifaces(struct bcm_cfg80211 *cfg, bool rtnl_lock_reqd)
1419 {
1420 	struct net_info *iter, *next;
1421 	struct net_device *primary_ndev;
1422 
1423 	/* Note: This function will clean up only the network interface and host
1424 	 * data structures. The firmware interface clean up will happen in the
1425 	 * during chip reset (ifconfig wlan0 down for built-in drivers/rmmod
1426 	 * context for the module case).
1427 	 */
1428 	primary_ndev = bcmcfg_to_prmry_ndev(cfg);
1429 	WL_DBG(("Enter\n"));
1430 	GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
1431 	for_each_ndev(cfg, iter, next) {
1432 		GCC_DIAGNOSTIC_POP();
1433 		if (iter->ndev && (iter->ndev != primary_ndev)) {
1434 			/* Ensure interfaces are down before deleting */
1435 #ifdef WL_STATIC_IF
1436 			/* Avoiding cleaning static ifaces */
1437 			if (!wl_cfg80211_static_if(cfg, iter->ndev))
1438 #endif /* WL_STATIC_IF */
1439 			{
1440 				dev_close(iter->ndev);
1441 				WL_DBG(("Cleaning up iface:%s \n", iter->ndev->name));
1442 				wl_cfg80211_post_ifdel(iter->ndev, rtnl_lock_reqd, 0);
1443 			}
1444 		}
1445 	}
1446 }
1447 
1448 int
wl_get_bandwidth_cap(struct net_device * ndev,uint32 band,uint32 * bandwidth)1449 wl_get_bandwidth_cap(struct net_device *ndev, uint32 band, uint32 *bandwidth)
1450 {
1451 	u32 bw = WL_CHANSPEC_BW_20;
1452 	s32 err = BCME_OK;
1453 	s32 bw_cap = 0;
1454 	struct {
1455 		u32 band;
1456 		u32 bw_cap;
1457 	} param = {0, 0};
1458 	u8 ioctl_buf[WLC_IOCTL_SMLEN];
1459 
1460 	if (band == WL_CHANSPEC_BAND_5G) {
1461 		param.band = WLC_BAND_5G;
1462 	}
1463 	else if (band == WL_CHANSPEC_BAND_2G) {
1464 		param.band = WLC_BAND_2G;
1465 	}
1466 #ifdef WL_6G_BAND
1467 	else if (band == WL_CHANSPEC_BAND_6G) {
1468 		param.band = WLC_BAND_6G;
1469 	}
1470 #endif
1471 	if (param.band) {
1472 		/* bw_cap is newly defined iovar for checking bandwith
1473 		  * capability of the band in Aardvark_branch_tob
1474 		  */
1475 		err = wldev_iovar_getbuf(ndev, "bw_cap", &param, sizeof(param),
1476 			ioctl_buf, sizeof(ioctl_buf), NULL);
1477 		if (err) {
1478 			if (err != BCME_UNSUPPORTED) {
1479 				WL_ERR(("bw_cap failed, %d\n", err));
1480 				return err;
1481 			} else {
1482 				/* if firmware doesn't support bw_cap iovar,
1483 				 * we have to use mimo_bw_cap
1484 				 */
1485 				err = wldev_iovar_getint(ndev, "mimo_bw_cap", &bw_cap);
1486 				if (err) {
1487 					WL_ERR(("error get mimo_bw_cap (%d)\n", err));
1488 				}
1489 				if (bw_cap != WLC_N_BW_20ALL) {
1490 					bw = WL_CHANSPEC_BW_40;
1491 				}
1492 			}
1493 		} else {
1494 			if (WL_BW_CAP_160MHZ(ioctl_buf[0])) {
1495 				bw = WL_CHANSPEC_BW_160;
1496 			} else if (WL_BW_CAP_80MHZ(ioctl_buf[0])) {
1497 				bw = WL_CHANSPEC_BW_80;
1498 			} else if (WL_BW_CAP_40MHZ(ioctl_buf[0])) {
1499 				bw = WL_CHANSPEC_BW_40;
1500 			} else {
1501 				bw = WL_CHANSPEC_BW_20;
1502 			}
1503 		}
1504 	} else if (band == WL_CHANSPEC_BAND_2G) {
1505 		bw = WL_CHANSPEC_BW_20;
1506 	}
1507 
1508 	*bandwidth = bw;
1509 
1510 	return err;
1511 }
1512 
1513 s32
wl_get_nl80211_band(u32 wl_band)1514 wl_get_nl80211_band(u32 wl_band)
1515 {
1516 	s32 err = BCME_ERROR;
1517 
1518 	switch (wl_band) {
1519 		case WL_CHANSPEC_BAND_2G:
1520 			return IEEE80211_BAND_2GHZ;
1521 		case WL_CHANSPEC_BAND_5G:
1522 			return IEEE80211_BAND_5GHZ;
1523 #ifdef WL_BAND_6G
1524 		case WL_CHANSPEC_BAND_6G:
1525 			/* current kernels doesn't support seperate
1526 			 * band for 6GHz. so till patch is available
1527 			 * map it under 5GHz
1528 			 */
1529 			return IEEE80211_BAND_5GHZ;
1530 #endif /* WL_BAND_6G */
1531 		default:
1532 			WL_ERR(("unsupported Band. %d\n", wl_band));
1533 	}
1534 
1535 	return err;
1536 }
1537 
1538 s32
wl_cfg80211_set_channel(struct wiphy * wiphy,struct net_device * dev,struct ieee80211_channel * chan,enum nl80211_channel_type channel_type)1539 wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
1540 	struct ieee80211_channel *chan,
1541 	enum nl80211_channel_type channel_type)
1542 {
1543 	chanspec_t chspec = INVCHANSPEC;
1544 	chanspec_t cur_chspec = INVCHANSPEC;
1545 	u32 bw = WL_CHANSPEC_BW_20;
1546 	s32 err = BCME_OK;
1547 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
1548 #if defined(CUSTOM_SET_CPUCORE) || defined(APSTA_RESTRICTED_CHANNEL)
1549 	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
1550 #endif /* CUSTOM_SET_CPUCORE || APSTA_RESTRICTED_CHANNEL */
1551 	u16 center_freq = chan->center_freq;
1552 
1553 	dev = ndev_to_wlc_ndev(dev, cfg);
1554 #ifdef WL_EXT_IAPSTA
1555 	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP ||
1556 			dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
1557 		u16 wl_iftype = 0;
1558 		u16 wl_mode = 0;
1559 
1560 		chspec = wl_freq_to_chanspec(chan->center_freq);
1561 		if (cfg80211_to_wl_iftype(dev->ieee80211_ptr->iftype,
1562 				&wl_iftype, &wl_mode) < 0) {
1563 			WL_ERR(("Unknown interface type:0x%x\n", dev->ieee80211_ptr->iftype));
1564 			return -EINVAL;
1565 		}
1566 		wl_ext_iapsta_update_iftype(dev, wl_iftype);
1567 		chspec = wl_ext_iapsta_update_channel(dev, chspec);
1568 		center_freq = wl_channel_to_frequency(wf_chspec_primary20_chan(chspec),
1569 			CHSPEC_BAND(chspec));
1570 	} else
1571 #endif
1572 	chspec = wl_freq_to_chanspec(center_freq);
1573 
1574 	WL_MSG(dev->name, "netdev_ifidx(%d), chan_type(%d) target channel(%s-%d) \n",
1575 		dev->ifindex, channel_type, CHSPEC2BANDSTR(chspec), CHSPEC_CHANNEL(chspec));
1576 
1577 #ifdef WL_P2P_6G
1578 	if (!(cfg->p2p_6g_enabled)) {
1579 #endif /* WL_P2P_6G */
1580 		if (IS_P2P_GO(dev->ieee80211_ptr) && (CHSPEC_IS6G(chspec))) {
1581 			WL_ERR(("P2P GO not allowed on 6G\n"));
1582 			return -ENOTSUPP;
1583 		}
1584 #ifdef WL_P2P_6G
1585 	}
1586 #endif /* WL_P2P_6G */
1587 
1588 #ifdef NOT_YET
1589 	switch (channel_type) {
1590 		case NL80211_CHAN_HT40MINUS:
1591 			/* secondary channel is below the control channel */
1592 			chspec = CH40MHZ_CHSPEC(CHSPEC_CHANNEL(chspec), WL_CHANSPEC_CTL_SB_UPPER);
1593 			break;
1594 		case NL80211_CHAN_HT40PLUS:
1595 			/* secondary channel is above the control channel */
1596 			chspec = CH40MHZ_CHSPEC(CHSPEC_CHANNEL(chspec), WL_CHANSPEC_CTL_SB_LOWER);
1597 			break;
1598 		default:
1599 			chspec = CH20MHZ_CHSPEC(CHSPEC_CHANNEL(chspec));
1600 
1601 	}
1602 #endif /* NOT_YET */
1603 
1604 #if defined(APSTA_RESTRICTED_CHANNEL)
1605 	/* Some customer platform used limited number of channels
1606 	 * for SoftAP interface on STA/SoftAP concurrent mode.
1607 	 * - 2.4GHz Channel: CH1 - CH13
1608 	 * - 5GHz Channel: CH149 (it depends on the country code)
1609 	 * If the Android framework sent invaild channel configuration
1610 	 * to DHD, driver should change the channel which is sutible for
1611 	 * STA/SoftAP concurrent mode.
1612 	 * - Set operating channel to CH1 (default 2.4GHz channel for
1613 	 *   restricted APSTA mode) if STA interface was associated to
1614 	 *   5GHz APs except for CH149.
1615 	 * - Otherwise, set the channel to the same channel as existing AP.
1616 	 */
1617 	if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP &&
1618 		DHD_OPMODE_STA_SOFTAP_CONCURR(dhd) &&
1619 		wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg))) {
1620 		u32 *sta_chanspec = (u32 *)wl_read_prof(cfg,
1621 			bcmcfg_to_prmry_ndev(cfg), WL_PROF_CHAN);
1622 		if (chan->band == wl_get_nl80211_band(CHSPEC_BAND(*sta_chanspec))) {
1623 			/* Do not try SCC in 5GHz if channel is not CH149 */
1624 			chspec = (
1625 #ifdef WL_6G_BAND
1626 				CHSPEC_IS6G(*sta_chanspec) ||
1627 #endif /* WL_6G_BAND */
1628 				(CHSPEC_IS5G(*sta_chanspec) &&
1629 				wf_chspec_primary20_chan(*sta_chanspec) !=
1630 				DEFAULT_5G_SOFTAP_CHANNEL)) ?
1631 				DEFAULT_2G_SOFTAP_CHANSPEC: *sta_chanspec;
1632 			WL_ERR(("target chanspec will be changed to %x\n", chspec));
1633 			if (CHSPEC_IS2G(chspec)) {
1634 				bw = WL_CHANSPEC_BW_20;
1635 				goto set_channel;
1636 			}
1637 		}
1638 	}
1639 #endif /* APSTA_RESTRICTED_CHANNEL */
1640 
1641 	err = wl_get_bandwidth_cap(dev, CHSPEC_BAND(chspec), &bw);
1642 	if (err < 0) {
1643 		WL_ERR(("Failed to get bandwidth information, err=%d\n", err));
1644 		return err;
1645 	}
1646 
1647 	/* In case of 5G downgrade BW to 80MHz as 160MHz channels falls in DFS */
1648 	if (CHSPEC_IS5G(chspec) && (bw == WL_CHANSPEC_BW_160)) {
1649 		bw = WL_CHANSPEC_BW_80;
1650 	}
1651 set_channel:
1652 	cur_chspec = wf_create_chspec_from_primary(wf_chspec_primary20_chan(chspec),
1653 		bw, CHSPEC_BAND(chspec));
1654 #ifdef WL_6G_BAND
1655 	if (cfg->acs_chspec &&
1656 		CHSPEC_IS6G(cfg->acs_chspec) &&
1657 		(wf_chspec_ctlchspec(cfg->acs_chspec) == wf_chspec_ctlchspec(cur_chspec))) {
1658 		WL_DBG(("using acs_chanspec %x\n", cfg->acs_chspec));
1659 		cur_chspec = cfg->acs_chspec;
1660 		cfg->acs_chspec = 0;
1661 	}
1662 #endif /* WL_6G_BAND */
1663 	if (wf_chspec_valid(cur_chspec)) {
1664 		/* convert 802.11 ac chanspec to current fw chanspec type */
1665 		cur_chspec = wl_chspec_host_to_driver(cur_chspec);
1666 		if (cur_chspec != INVCHANSPEC) {
1667 			if ((err = wldev_iovar_setint(dev, "chanspec",
1668 				cur_chspec)) == BCME_BADCHAN) {
1669 				u32 local_channel = CHSPEC_CHANNEL(chspec);
1670 				if ((bw == WL_CHANSPEC_BW_80) || (bw == WL_CHANSPEC_BW_160))
1671 					goto change_bw;
1672 				err = wldev_ioctl_set(dev, WLC_SET_CHANNEL,
1673 					&local_channel, sizeof(local_channel));
1674 				if (err < 0) {
1675 					WL_ERR(("WLC_SET_CHANNEL error %d"
1676 					"chip may not be supporting this channel\n", err));
1677 				}
1678 			} else if (err) {
1679 				WL_ERR(("failed to set chanspec error %d\n", err));
1680 			}
1681 #ifdef BCMDONGLEHOST
1682 #ifdef DISABLE_WL_FRAMEBURST_SOFTAP
1683 			else {
1684 				/* Disable Frameburst only for stand-alone 2GHz SoftAP */
1685 				if (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP &&
1686 					DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_HOSTAP_MODE) &&
1687 					(CHSPEC_IS2G(chspec)) &&
1688 					!wl_get_drv_status(cfg, CONNECTED,
1689 						bcmcfg_to_prmry_ndev(cfg))) {
1690 					WL_DBG(("Disabling frameburst on "
1691 						"stand-alone 2GHz SoftAP\n"));
1692 					wl_cfg80211_set_frameburst(cfg, FALSE);
1693 				}
1694 			}
1695 #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
1696 #endif /* BCMDONGLEHOST */
1697 		} else {
1698 			WL_ERR(("failed to convert host chanspec to fw chanspec\n"));
1699 			err = BCME_ERROR;
1700 		}
1701 	} else {
1702 change_bw:
1703 		if (bw == WL_CHANSPEC_BW_160) {
1704 			bw = WL_CHANSPEC_BW_80;
1705 		} else if (bw == WL_CHANSPEC_BW_80) {
1706 			bw = WL_CHANSPEC_BW_40;
1707 		} else if (bw == WL_CHANSPEC_BW_40) {
1708 			bw = WL_CHANSPEC_BW_20;
1709 		} else {
1710 			bw = 0;
1711 		}
1712 		if (bw)
1713 			goto set_channel;
1714 		WL_ERR(("Invalid chanspec 0x%x\n", chspec));
1715 		err = BCME_ERROR;
1716 	}
1717 #ifdef CUSTOM_SET_CPUCORE
1718 	if (dhd->op_mode == DHD_FLAG_HOSTAP_MODE) {
1719 		WL_DBG(("SoftAP mode do not need to set cpucore\n"));
1720 	} else if (chspec & WL_CHANSPEC_BW_80) {
1721 		/* SoftAp only mode do not need to set cpucore */
1722 		if ((dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) &&
1723 			dev != bcmcfg_to_prmry_ndev(cfg)) {
1724 			/* Soft AP on virtual Iface (AP+STA case) */
1725 			dhd->chan_isvht80 |= DHD_FLAG_HOSTAP_MODE;
1726 			dhd_set_cpucore(dhd, TRUE);
1727 		} else if (is_p2p_group_iface(dev->ieee80211_ptr)) {
1728 			/* If P2P IF is vht80 */
1729 			dhd->chan_isvht80 |= DHD_FLAG_P2P_MODE;
1730 			dhd_set_cpucore(dhd, TRUE);
1731 		}
1732 	}
1733 #endif /* CUSTOM_SET_CPUCORE */
1734 	if (!err && (wl_get_mode_by_netdev(cfg, dev) == WL_MODE_AP)) {
1735 		/* Update AP/GO operating chanspec */
1736 		cfg->ap_oper_channel = wl_freq_to_chanspec(center_freq);
1737 	}
1738 	if (err) {
1739 		wl_flush_fw_log_buffer(bcmcfg_to_prmry_ndev(cfg),
1740 			FW_LOGSET_MASK_ALL);
1741 	} else {
1742 		WL_DBG(("Setting chanspec %x for GO/AP \n", chspec));
1743 	}
1744 	return err;
1745 }
1746 
1747 static s32
wl_validate_opensecurity(struct net_device * dev,s32 bssidx,bool privacy)1748 wl_validate_opensecurity(struct net_device *dev, s32 bssidx, bool privacy)
1749 {
1750 	s32 err = BCME_OK;
1751 	u32 wpa_val;
1752 	s32 wsec = 0;
1753 
1754 	/* set auth */
1755 	err = wldev_iovar_setint_bsscfg(dev, "auth", 0, bssidx);
1756 	if (err < 0) {
1757 		WL_ERR(("auth error %d\n", err));
1758 		return BCME_ERROR;
1759 	}
1760 
1761 	if (privacy) {
1762 		/* If privacy bit is set in open mode, then WEP would be enabled */
1763 		wsec = WEP_ENABLED;
1764 		WL_DBG(("Setting wsec to %d for WEP \n", wsec));
1765 	}
1766 
1767 	/* set wsec */
1768 	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
1769 	if (err < 0) {
1770 		WL_ERR(("wsec error %d\n", err));
1771 		return BCME_ERROR;
1772 	}
1773 
1774 	/* set upper-layer auth */
1775 	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC)
1776 		wpa_val = WPA_AUTH_NONE;
1777 	else
1778 		wpa_val = WPA_AUTH_DISABLED;
1779 	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_val, bssidx);
1780 	if (err < 0) {
1781 		WL_ERR(("wpa_auth error %d\n", err));
1782 		return BCME_ERROR;
1783 	}
1784 
1785 	return 0;
1786 }
1787 
1788 #define MAX_FILS_IND_IE_LEN 1024u
1789 static s32
wl_validate_fils_ind_ie(struct net_device * dev,const bcm_tlv_t * filsindie,s32 bssidx)1790 wl_validate_fils_ind_ie(struct net_device *dev, const bcm_tlv_t *filsindie, s32 bssidx)
1791 {
1792 	s32 err = BCME_OK;
1793 	struct bcm_cfg80211 *cfg = NULL;
1794 	bcm_iov_buf_t *iov_buf = NULL;
1795 	bcm_xtlv_t* pxtlv;
1796 	int iov_buf_size = 0;
1797 
1798 	if (!dev || !filsindie) {
1799 		WL_ERR(("%s: dev/filsidie is null\n", __FUNCTION__));
1800 		goto exit;
1801 	}
1802 
1803 	cfg = wl_get_cfg(dev);
1804 	if (!cfg) {
1805 		WL_ERR(("%s: cfg is null\n", __FUNCTION__));
1806 		goto exit;
1807 	}
1808 
1809 	iov_buf_size = sizeof(bcm_iov_buf_t) + sizeof(bcm_xtlv_t) + filsindie->len - 1;
1810 	iov_buf = MALLOCZ(cfg->osh, iov_buf_size);
1811 	if (!iov_buf) {
1812 		WL_ERR(("%s: iov_buf alloc failed! %d bytes\n", __FUNCTION__, iov_buf_size));
1813 		err = BCME_NOMEM;
1814 		goto exit;
1815 	}
1816 	iov_buf->version = WL_FILS_IOV_VERSION;
1817 	iov_buf->id = WL_FILS_CMD_ADD_IND_IE;
1818 	iov_buf->len = sizeof(bcm_xtlv_t) + filsindie->len - 1;
1819 	pxtlv = (bcm_xtlv_t*)&iov_buf->data[0];
1820 	pxtlv->id = WL_FILS_XTLV_IND_IE;
1821 	pxtlv->len = filsindie->len;
1822 	/* memcpy_s return check not required as buffer is allocated based on ie
1823 	 * len
1824 	 */
1825 	(void)memcpy_s(pxtlv->data, filsindie->len, filsindie->data, filsindie->len);
1826 
1827 	err = wldev_iovar_setbuf(dev, "fils", iov_buf, iov_buf_size,
1828 		cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
1829 	if (unlikely(err)) {
1830 		WL_ERR(("fils indication ioctl error (%d)\n", err));
1831 		 goto exit;
1832 	}
1833 
1834 exit:
1835 	if (err < 0) {
1836 		WL_ERR(("FILS Ind setting error %d\n", err));
1837 	}
1838 
1839 	if (iov_buf) {
1840 		MFREE(cfg->osh, iov_buf, iov_buf_size);
1841 	}
1842 	return err;
1843 }
1844 
1845 #ifdef MFP
1846 static int
wl_get_mfp_capability(u8 rsn_cap,u32 * wpa_auth,u32 * mfp_val)1847 wl_get_mfp_capability(u8 rsn_cap, u32 *wpa_auth, u32 *mfp_val)
1848 {
1849 	u32 mfp = 0;
1850 	if (rsn_cap & RSN_CAP_MFPR) {
1851 		WL_DBG(("MFP Required \n"));
1852 		mfp = WL_MFP_REQUIRED;
1853 		/* Our firmware has requirement that WPA2_AUTH_PSK/WPA2_AUTH_UNSPECIFIED
1854 		 * be set, if SHA256 OUI is to be included in the rsn ie.
1855 		 */
1856 		if (*wpa_auth & WPA2_AUTH_PSK_SHA256) {
1857 			*wpa_auth |= WPA2_AUTH_PSK;
1858 		} else if (*wpa_auth & WPA2_AUTH_1X_SHA256) {
1859 			*wpa_auth |= WPA2_AUTH_UNSPECIFIED;
1860 		}
1861 	} else if (rsn_cap & RSN_CAP_MFPC) {
1862 		WL_DBG(("MFP Capable \n"));
1863 		mfp = WL_MFP_CAPABLE;
1864 	}
1865 
1866 	/* Validate MFP */
1867 	if ((*wpa_auth == WPA3_AUTH_SAE_PSK) && (mfp != WL_MFP_REQUIRED)) {
1868 		WL_ERR(("MFPR should be set for SAE PSK. mfp:%d\n", mfp));
1869 		return BCME_ERROR;
1870 	} else if ((*wpa_auth == (WPA3_AUTH_SAE_PSK | WPA2_AUTH_PSK)) &&
1871 		(mfp != WL_MFP_CAPABLE)) {
1872 		WL_ERR(("mfp(%d) should be set to capable(%d) for SAE transition mode\n",
1873 				mfp, WL_MFP_CAPABLE));
1874 		return BCME_ERROR;
1875 	}
1876 
1877 	*mfp_val = mfp;
1878 	return BCME_OK;
1879 }
1880 #endif /* MFP */
1881 
1882 static s32
wl_validate_wpa2ie(struct net_device * dev,const bcm_tlv_t * wpa2ie,s32 bssidx)1883 wl_validate_wpa2ie(struct net_device *dev, const bcm_tlv_t *wpa2ie, s32 bssidx)
1884 {
1885 	s32 len = 0;
1886 	s32 err = BCME_OK;
1887 	u16 auth = 0; /* d11 open authentication */
1888 	u32 wsec;
1889 	u32 pval = 0;
1890 	u32 gval = 0;
1891 	u32 wpa_auth = 0;
1892 	const wpa_suite_mcast_t *mcast;
1893 	const wpa_suite_ucast_t *ucast;
1894 	const wpa_suite_auth_key_mgmt_t *mgmt;
1895 	const wpa_pmkid_list_t *pmkid;
1896 	int cnt = 0;
1897 #ifdef MFP
1898 	u32 mfp = 0;
1899 #endif /* MFP */
1900 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
1901 	struct wl_security *sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
1902 
1903 	u16 suite_count;
1904 	u8 rsn_cap[2];
1905 	u32 wme_bss_disable;
1906 
1907 	if (wpa2ie == NULL)
1908 		goto exit;
1909 
1910 	WL_DBG(("Enter \n"));
1911 	len =  wpa2ie->len - WPA2_VERSION_LEN;
1912 	/* check the mcast cipher */
1913 	mcast = (const wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
1914 	switch (mcast->type) {
1915 		case WPA_CIPHER_NONE:
1916 			gval = 0;
1917 			break;
1918 		case WPA_CIPHER_WEP_40:
1919 		case WPA_CIPHER_WEP_104:
1920 			gval = WEP_ENABLED;
1921 			break;
1922 		case WPA_CIPHER_TKIP:
1923 			gval = TKIP_ENABLED;
1924 			break;
1925 		case WPA_CIPHER_AES_CCM:
1926 			gval = AES_ENABLED;
1927 			break;
1928 
1929 #ifdef BCMWAPI_WPI
1930 		case WAPI_CIPHER_SMS4:
1931 			gval = SMS4_ENABLED;
1932 			break;
1933 #endif
1934 
1935 		default:
1936 			WL_ERR(("No Security Info\n"));
1937 			break;
1938 	}
1939 	if ((len -= WPA_SUITE_LEN) <= 0)
1940 		return BCME_BADLEN;
1941 
1942 	/* check the unicast cipher */
1943 	ucast = (const wpa_suite_ucast_t *)&mcast[1];
1944 	suite_count = ltoh16_ua(&ucast->count);
1945 	switch (ucast->list[0].type) {
1946 		case WPA_CIPHER_NONE:
1947 			pval = 0;
1948 			break;
1949 		case WPA_CIPHER_WEP_40:
1950 		case WPA_CIPHER_WEP_104:
1951 			pval = WEP_ENABLED;
1952 			break;
1953 		case WPA_CIPHER_TKIP:
1954 			pval = TKIP_ENABLED;
1955 			break;
1956 		case WPA_CIPHER_AES_CCM:
1957 			pval = AES_ENABLED;
1958 			break;
1959 
1960 #ifdef BCMWAPI_WPI
1961 		case WAPI_CIPHER_SMS4:
1962 			pval = SMS4_ENABLED;
1963 			break;
1964 #endif
1965 
1966 		default:
1967 			WL_ERR(("No Security Info\n"));
1968 	}
1969 	if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
1970 		return BCME_BADLEN;
1971 
1972 	/* FOR WPS , set SEC_OW_ENABLED */
1973 	wsec = (pval | gval | SES_OW_ENABLED);
1974 	/* check the AKM */
1975 	mgmt = (const wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
1976 	suite_count = cnt = ltoh16_ua(&mgmt->count);
1977 	while (cnt--) {
1978 		if (bcmp(mgmt->list[cnt].oui, WFA_OUI, WFA_OUI_LEN) == 0) {
1979 			switch (mgmt->list[cnt].type) {
1980 			case RSN_AKM_DPP:
1981 				wpa_auth |= WPA3_AUTH_DPP_AKM;
1982 				break;
1983 			default:
1984 				WL_ERR(("No Key Mgmt Info in WFA_OUI\n"));
1985 			}
1986 		} else {
1987 			switch (mgmt->list[cnt].type) {
1988 			case RSN_AKM_NONE:
1989 				wpa_auth |= WPA_AUTH_NONE;
1990 				break;
1991 			case RSN_AKM_UNSPECIFIED:
1992 				wpa_auth |= WPA2_AUTH_UNSPECIFIED;
1993 				break;
1994 			case RSN_AKM_PSK:
1995 				wpa_auth |= WPA2_AUTH_PSK;
1996 				break;
1997 #ifdef MFP
1998 			case RSN_AKM_MFP_PSK:
1999 				wpa_auth |= WPA2_AUTH_PSK_SHA256;
2000 				break;
2001 			case RSN_AKM_MFP_1X:
2002 				wpa_auth |= WPA2_AUTH_1X_SHA256;
2003 				break;
2004 			case RSN_AKM_FILS_SHA256:
2005 				wpa_auth |= WPA2_AUTH_FILS_SHA256;
2006 				break;
2007 			case RSN_AKM_FILS_SHA384:
2008 				wpa_auth |= WPA2_AUTH_FILS_SHA384;
2009 				break;
2010 #if defined(WL_SAE) || defined(WL_CLIENT_SAE)
2011 			case RSN_AKM_SAE_PSK:
2012 				wpa_auth |= WPA3_AUTH_SAE_PSK;
2013 				break;
2014 #endif /* WL_SAE || WL_CLIENT_SAE */
2015 #endif /* MFP */
2016 			default:
2017 				WL_ERR(("No Key Mgmt Info\n"));
2018 			}
2019 		}
2020 	}
2021 	if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
2022 		rsn_cap[0] = *(const u8 *)&mgmt->list[suite_count];
2023 		rsn_cap[1] = *((const u8 *)&mgmt->list[suite_count] + 1);
2024 
2025 		if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
2026 			wme_bss_disable = 0;
2027 		} else {
2028 			wme_bss_disable = 1;
2029 		}
2030 
2031 #ifdef MFP
2032 		if (wl_get_mfp_capability(rsn_cap[0], &wpa_auth, &mfp) != BCME_OK) {
2033 			WL_ERR(("mfp configuration invalid. rsn_cap:0x%x\n", rsn_cap[0]));
2034 			return BCME_ERROR;
2035 		}
2036 #endif /* MFP */
2037 
2038 		/* set wme_bss_disable to sync RSN Capabilities */
2039 		err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
2040 		if (err < 0) {
2041 			WL_ERR(("wme_bss_disable error %d\n", err));
2042 			return BCME_ERROR;
2043 		}
2044 	} else {
2045 		WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
2046 	}
2047 
2048 	len -= RSN_CAP_LEN;
2049 	if (len >= WPA2_PMKID_COUNT_LEN) {
2050 		pmkid = (const wpa_pmkid_list_t *)
2051 		        ((const u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN);
2052 		cnt = ltoh16_ua(&pmkid->count);
2053 		if (cnt != 0) {
2054 			WL_ERR(("AP has non-zero PMKID count. Wrong!\n"));
2055 			return BCME_ERROR;
2056 		}
2057 		/* since PMKID cnt is known to be 0 for AP, */
2058 		/* so don't bother to send down this info to firmware */
2059 	}
2060 
2061 #ifdef MFP
2062 	len -= WPA2_PMKID_COUNT_LEN;
2063 	if (len >= WPA_SUITE_LEN) {
2064 		cfg->bip_pos =
2065 		        (const u8 *)&mgmt->list[suite_count] + RSN_CAP_LEN + WPA2_PMKID_COUNT_LEN;
2066 	} else {
2067 		cfg->bip_pos = NULL;
2068 	}
2069 #endif
2070 
2071 	/* set auth */
2072 	err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
2073 	if (err < 0) {
2074 		WL_ERR(("auth error %d\n", err));
2075 		return BCME_ERROR;
2076 	}
2077 
2078 	/* set wsec */
2079 	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
2080 	if (err < 0) {
2081 		WL_ERR(("wsec error %d\n", err));
2082 		return BCME_ERROR;
2083 	}
2084 
2085 #ifdef MFP
2086 	cfg->mfp_mode = mfp;
2087 #endif /* MFP */
2088 
2089 	/* set upper-layer auth */
2090 	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
2091 	if (err < 0) {
2092 		WL_ERR(("wpa_auth error %d\n", err));
2093 		return BCME_ERROR;
2094 	}
2095 
2096 	if (sec) {
2097 		/* store applied sec settings */
2098 		sec->fw_wpa_auth = wpa_auth;
2099 		sec->fw_wsec = wsec;
2100 		sec->fw_auth = auth;
2101 #ifdef MFP
2102 		sec->fw_mfp = mfp;
2103 #endif /* mfp */
2104 	}
2105 exit:
2106 	return 0;
2107 }
2108 
2109 static s32
wl_validate_wpaie(struct net_device * dev,const wpa_ie_fixed_t * wpaie,s32 bssidx)2110 wl_validate_wpaie(struct net_device *dev, const wpa_ie_fixed_t *wpaie, s32 bssidx)
2111 {
2112 	const wpa_suite_mcast_t *mcast;
2113 	const wpa_suite_ucast_t *ucast;
2114 	const wpa_suite_auth_key_mgmt_t *mgmt;
2115 	u16 auth = 0; /* d11 open authentication */
2116 	u16 count;
2117 	s32 err = BCME_OK;
2118 	s32 len = 0;
2119 	u32 i;
2120 	u32 wsec;
2121 	u32 pval = 0;
2122 	u32 gval = 0;
2123 	u32 wpa_auth = 0;
2124 	u32 tmp = 0;
2125 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2126 	struct wl_security *sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
2127 
2128 	if (wpaie == NULL)
2129 		goto exit;
2130 	WL_DBG(("Enter \n"));
2131 	len = wpaie->length;    /* value length */
2132 	len -= WPA_IE_TAG_FIXED_LEN;
2133 	/* check for multicast cipher suite */
2134 	if (len < WPA_SUITE_LEN) {
2135 		WL_INFORM_MEM(("no multicast cipher suite\n"));
2136 		goto exit;
2137 	}
2138 
2139 	/* pick up multicast cipher */
2140 	mcast = (const wpa_suite_mcast_t *)&wpaie[1];
2141 	len -= WPA_SUITE_LEN;
2142 	if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
2143 		if (IS_WPA_CIPHER(mcast->type)) {
2144 			tmp = 0;
2145 			switch (mcast->type) {
2146 				case WPA_CIPHER_NONE:
2147 					tmp = 0;
2148 					break;
2149 				case WPA_CIPHER_WEP_40:
2150 				case WPA_CIPHER_WEP_104:
2151 					tmp = WEP_ENABLED;
2152 					break;
2153 				case WPA_CIPHER_TKIP:
2154 					tmp = TKIP_ENABLED;
2155 					break;
2156 				case WPA_CIPHER_AES_CCM:
2157 					tmp = AES_ENABLED;
2158 					break;
2159 				default:
2160 					WL_ERR(("No Security Info\n"));
2161 			}
2162 			gval |= tmp;
2163 		}
2164 	}
2165 	/* Check for unicast suite(s) */
2166 	if (len < WPA_IE_SUITE_COUNT_LEN) {
2167 		WL_INFORM_MEM(("no unicast suite\n"));
2168 		goto exit;
2169 	}
2170 	/* walk thru unicast cipher list and pick up what we recognize */
2171 	ucast = (const wpa_suite_ucast_t *)&mcast[1];
2172 	count = ltoh16_ua(&ucast->count);
2173 	len -= WPA_IE_SUITE_COUNT_LEN;
2174 	for (i = 0; i < count && len >= WPA_SUITE_LEN;
2175 		i++, len -= WPA_SUITE_LEN) {
2176 		if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
2177 			if (IS_WPA_CIPHER(ucast->list[i].type)) {
2178 				tmp = 0;
2179 				switch (ucast->list[i].type) {
2180 					case WPA_CIPHER_NONE:
2181 						tmp = 0;
2182 						break;
2183 					case WPA_CIPHER_WEP_40:
2184 					case WPA_CIPHER_WEP_104:
2185 						tmp = WEP_ENABLED;
2186 						break;
2187 					case WPA_CIPHER_TKIP:
2188 						tmp = TKIP_ENABLED;
2189 						break;
2190 					case WPA_CIPHER_AES_CCM:
2191 						tmp = AES_ENABLED;
2192 						break;
2193 					default:
2194 						WL_ERR(("No Security Info\n"));
2195 				}
2196 				pval |= tmp;
2197 			}
2198 		}
2199 	}
2200 	len -= (count - i) * WPA_SUITE_LEN;
2201 	/* Check for auth key management suite(s) */
2202 	if (len < WPA_IE_SUITE_COUNT_LEN) {
2203 		WL_INFORM_MEM((" no auth key mgmt suite\n"));
2204 		goto exit;
2205 	}
2206 	/* walk thru auth management suite list and pick up what we recognize */
2207 	mgmt = (const wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
2208 	count = ltoh16_ua(&mgmt->count);
2209 	len -= WPA_IE_SUITE_COUNT_LEN;
2210 	for (i = 0; i < count && len >= WPA_SUITE_LEN;
2211 		i++, len -= WPA_SUITE_LEN) {
2212 		if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
2213 			if (IS_WPA_AKM(mgmt->list[i].type)) {
2214 				tmp = 0;
2215 				switch (mgmt->list[i].type) {
2216 					case RSN_AKM_NONE:
2217 						tmp = WPA_AUTH_NONE;
2218 						break;
2219 					case RSN_AKM_UNSPECIFIED:
2220 						tmp = WPA_AUTH_UNSPECIFIED;
2221 						break;
2222 					case RSN_AKM_PSK:
2223 						tmp = WPA_AUTH_PSK;
2224 						break;
2225 					default:
2226 						WL_ERR(("No Key Mgmt Info\n"));
2227 				}
2228 				wpa_auth |= tmp;
2229 			}
2230 		}
2231 
2232 	}
2233 	/* FOR WPS , set SEC_OW_ENABLED */
2234 	wsec = (pval | gval | SES_OW_ENABLED);
2235 	/* set auth */
2236 	err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
2237 	if (err < 0) {
2238 		WL_ERR(("auth error %d\n", err));
2239 		return BCME_ERROR;
2240 	}
2241 	/* set wsec */
2242 	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
2243 	if (err < 0) {
2244 		WL_ERR(("wsec error %d\n", err));
2245 		return BCME_ERROR;
2246 	}
2247 	/* set upper-layer auth */
2248 	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
2249 	if (err < 0) {
2250 		WL_ERR(("wpa_auth error %d\n", err));
2251 		return BCME_ERROR;
2252 	}
2253 
2254 	if (sec) {
2255 		/* store applied sec settings */
2256 		sec->fw_wpa_auth = wpa_auth;
2257 		sec->fw_wsec = wsec;
2258 		sec->fw_auth = auth;
2259 	}
2260 
2261 exit:
2262 	return 0;
2263 }
2264 
2265 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
wl_get_cipher_type(uint8 type)2266 static u32 wl_get_cipher_type(uint8 type)
2267 {
2268 	u32 ret = 0;
2269 	switch (type) {
2270 		case WPA_CIPHER_NONE:
2271 			ret = 0;
2272 			break;
2273 		case WPA_CIPHER_WEP_40:
2274 		case WPA_CIPHER_WEP_104:
2275 			ret = WEP_ENABLED;
2276 			break;
2277 		case WPA_CIPHER_TKIP:
2278 			ret = TKIP_ENABLED;
2279 			break;
2280 		case WPA_CIPHER_AES_CCM:
2281 			ret = AES_ENABLED;
2282 			break;
2283 
2284 #ifdef BCMWAPI_WPI
2285 		case WAPI_CIPHER_SMS4:
2286 			ret = SMS4_ENABLED;
2287 			break;
2288 #endif
2289 
2290 		default:
2291 			WL_ERR(("No Security Info\n"));
2292 	}
2293 	return ret;
2294 }
2295 
wl_get_suite_auth_key_mgmt_type(uint8 type,const wpa_suite_mcast_t * mcast)2296 static u32 wl_get_suite_auth_key_mgmt_type(uint8 type, const wpa_suite_mcast_t *mcast)
2297 {
2298 	u32 ret = 0;
2299 	u32 is_wpa2 = 0;
2300 
2301 	if (!bcmp(mcast->oui, WPA2_OUI, WPA2_OUI_LEN)) {
2302 		is_wpa2 = 1;
2303 	}
2304 
2305 	WL_INFORM_MEM(("%s, type = %d\n", is_wpa2 ? "WPA2":"WPA", type));
2306 	if (bcmp(mcast->oui, WFA_OUI, WFA_OUI_LEN) == 0) {
2307 		switch (type) {
2308 			case RSN_AKM_DPP:
2309 				ret = WPA3_AUTH_DPP_AKM;
2310 				break;
2311 			default:
2312 				WL_ERR(("No Key Mgmt Info in WFA_OUI\n"));
2313 		}
2314 	} else {
2315 		switch (type) {
2316 		case RSN_AKM_NONE:
2317 			/* For WPA and WPA2, AUTH_NONE is common */
2318 			ret = WPA_AUTH_NONE;
2319 			break;
2320 		case RSN_AKM_UNSPECIFIED:
2321 			if (is_wpa2) {
2322 				ret = WPA2_AUTH_UNSPECIFIED;
2323 			} else {
2324 				ret = WPA_AUTH_UNSPECIFIED;
2325 			}
2326 			break;
2327 		case RSN_AKM_PSK:
2328 			if (is_wpa2) {
2329 				ret = WPA2_AUTH_PSK;
2330 			} else {
2331 				ret = WPA_AUTH_PSK;
2332 			}
2333 			break;
2334 #ifdef WL_SAE
2335 		case RSN_AKM_SAE_PSK:
2336 			ret = WPA3_AUTH_SAE_PSK;
2337 			break;
2338 #endif /* WL_SAE */
2339 		default:
2340 			WL_ERR(("No Key Mgmt Info\n"));
2341 		}
2342 	}
2343 	return ret;
2344 }
2345 
2346 static s32
wl_validate_wpaie_wpa2ie(struct net_device * dev,const wpa_ie_fixed_t * wpaie,const bcm_tlv_t * wpa2ie,s32 bssidx)2347 wl_validate_wpaie_wpa2ie(struct net_device *dev, const wpa_ie_fixed_t *wpaie,
2348 	const bcm_tlv_t *wpa2ie, s32 bssidx)
2349 {
2350 	const wpa_suite_mcast_t *mcast;
2351 	const wpa_suite_ucast_t *ucast;
2352 	const wpa_suite_auth_key_mgmt_t *mgmt;
2353 	u16 auth = 0; /* d11 open authentication */
2354 	u16 count;
2355 	s32 err = BCME_OK;
2356 	u32 wme_bss_disable;
2357 	u16 suite_count;
2358 	u8 rsn_cap[2];
2359 	s32 len = 0;
2360 	u32 i;
2361 	u32 wsec1, wsec2, wsec;
2362 	u32 pval = 0;
2363 	u32 gval = 0;
2364 	u32 wpa_auth = 0;
2365 	u32 wpa_auth1 = 0;
2366 	u32 wpa_auth2 = 0;
2367 #ifdef MFP
2368 	u32 mfp = 0;
2369 #endif /* MFP */
2370 
2371 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2372 	struct wl_security *sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
2373 
2374 	if (wpaie == NULL || wpa2ie == NULL)
2375 		goto exit;
2376 
2377 	WL_DBG(("Enter \n"));
2378 	len = wpaie->length;    /* value length */
2379 	len -= WPA_IE_TAG_FIXED_LEN;
2380 	/* check for multicast cipher suite */
2381 	if (len < WPA_SUITE_LEN) {
2382 		WL_INFORM_MEM(("no multicast cipher suite\n"));
2383 		goto exit;
2384 	}
2385 
2386 	/* pick up multicast cipher */
2387 	mcast = (const wpa_suite_mcast_t *)&wpaie[1];
2388 	len -= WPA_SUITE_LEN;
2389 	if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
2390 		if (IS_WPA_CIPHER(mcast->type)) {
2391 			gval |= wl_get_cipher_type(mcast->type);
2392 		}
2393 	}
2394 	WL_DBG(("\nwpa ie validate\n"));
2395 	WL_DBG(("wpa ie mcast cipher = 0x%X\n", gval));
2396 
2397 	/* Check for unicast suite(s) */
2398 	if (len < WPA_IE_SUITE_COUNT_LEN) {
2399 		WL_INFORM_MEM(("no unicast suite\n"));
2400 		goto exit;
2401 	}
2402 
2403 	/* walk thru unicast cipher list and pick up what we recognize */
2404 	ucast = (const wpa_suite_ucast_t *)&mcast[1];
2405 	count = ltoh16_ua(&ucast->count);
2406 	len -= WPA_IE_SUITE_COUNT_LEN;
2407 	for (i = 0; i < count && len >= WPA_SUITE_LEN;
2408 		i++, len -= WPA_SUITE_LEN) {
2409 		if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
2410 			if (IS_WPA_CIPHER(ucast->list[i].type)) {
2411 				pval |= wl_get_cipher_type(ucast->list[i].type);
2412 			}
2413 		}
2414 	}
2415 	WL_ERR(("wpa ie ucast count =%d, cipher = 0x%X\n", count, pval));
2416 
2417 	/* FOR WPS , set SEC_OW_ENABLED */
2418 	wsec1 = (pval | gval | SES_OW_ENABLED);
2419 	WL_ERR(("wpa ie wsec = 0x%X\n", wsec1));
2420 
2421 	len -= (count - i) * WPA_SUITE_LEN;
2422 	/* Check for auth key management suite(s) */
2423 	if (len < WPA_IE_SUITE_COUNT_LEN) {
2424 		WL_INFORM_MEM((" no auth key mgmt suite\n"));
2425 		goto exit;
2426 	}
2427 	/* walk thru auth management suite list and pick up what we recognize */
2428 	mgmt = (const wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
2429 	count = ltoh16_ua(&mgmt->count);
2430 	len -= WPA_IE_SUITE_COUNT_LEN;
2431 	for (i = 0; i < count && len >= WPA_SUITE_LEN;
2432 		i++, len -= WPA_SUITE_LEN) {
2433 		if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
2434 			if (IS_WPA_AKM(mgmt->list[i].type)) {
2435 				wpa_auth1 |=
2436 					wl_get_suite_auth_key_mgmt_type(mgmt->list[i].type, mcast);
2437 			}
2438 		}
2439 
2440 	}
2441 	WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count, wpa_auth1));
2442 	WL_ERR(("\nwpa2 ie validate\n"));
2443 
2444 	pval = 0;
2445 	gval = 0;
2446 	len =  wpa2ie->len;
2447 	/* check the mcast cipher */
2448 	mcast = (const wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
2449 	gval = wl_get_cipher_type(mcast->type);
2450 
2451 	WL_ERR(("wpa2 ie mcast cipher = 0x%X\n", gval));
2452 	if ((len -= WPA_SUITE_LEN) <= 0)
2453 	{
2454 		WL_ERR(("P:wpa2 ie len[%d]", len));
2455 		return BCME_BADLEN;
2456 	}
2457 
2458 	/* check the unicast cipher */
2459 	ucast = (const wpa_suite_ucast_t *)&mcast[1];
2460 	suite_count = ltoh16_ua(&ucast->count);
2461 	WL_ERR((" WPA2 ucast cipher count=%d\n", suite_count));
2462 	pval |= wl_get_cipher_type(ucast->list[0].type);
2463 
2464 	if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
2465 		return BCME_BADLEN;
2466 
2467 	WL_ERR(("wpa2 ie ucast cipher = 0x%X\n", pval));
2468 
2469 	/* FOR WPS , set SEC_OW_ENABLED */
2470 	wsec2 = (pval | gval | SES_OW_ENABLED);
2471 	WL_ERR(("wpa2 ie wsec = 0x%X\n", wsec2));
2472 
2473 	/* check the AKM */
2474 	mgmt = (const wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
2475 	suite_count = ltoh16_ua(&mgmt->count);
2476 	wpa_auth2 = wl_get_suite_auth_key_mgmt_type(mgmt->list[0].type, mcast);
2477 	WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count, wpa_auth2));
2478 
2479 	wsec = (wsec1 | wsec2);
2480 	wpa_auth = (wpa_auth1 | wpa_auth2);
2481 	WL_ERR(("wpa_wpa2 wsec=0x%X wpa_auth=0x%X\n", wsec, wpa_auth));
2482 
2483 	if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
2484 		rsn_cap[0] = *(const u8 *)&mgmt->list[suite_count];
2485 		rsn_cap[1] = *((const u8 *)&mgmt->list[suite_count] + 1);
2486 		if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
2487 			wme_bss_disable = 0;
2488 		} else {
2489 			wme_bss_disable = 1;
2490 		}
2491 		WL_DBG(("P:rsn_cap[0]=[0x%X]:wme_bss_disabled[%d]\n", rsn_cap[0], wme_bss_disable));
2492 
2493 #ifdef MFP
2494 		if (wl_get_mfp_capability(rsn_cap[0], &wpa_auth, &mfp) != BCME_OK) {
2495 			WL_ERR(("mfp configuration invalid. rsn_cap:0x%x\n", rsn_cap[0]));
2496 			return BCME_ERROR;
2497 		}
2498 		cfg->mfp_mode = mfp;
2499 #endif /* MFP */
2500 
2501 		/* set wme_bss_disable to sync RSN Capabilities */
2502 		err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
2503 		if (err < 0) {
2504 			WL_ERR(("wme_bss_disable error %d\n", err));
2505 			return BCME_ERROR;
2506 		}
2507 	} else {
2508 		WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
2509 	}
2510 
2511 	/* set auth */
2512 	err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
2513 	if (err < 0) {
2514 		WL_ERR(("auth error %d\n", err));
2515 		return BCME_ERROR;
2516 	}
2517 	/* set wsec */
2518 	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
2519 	if (err < 0) {
2520 		WL_ERR(("wsec error %d\n", err));
2521 		return BCME_ERROR;
2522 	}
2523 	/* set upper-layer auth */
2524 	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
2525 	if (err < 0) {
2526 		WL_ERR(("wpa_auth error %d\n", err));
2527 		return BCME_ERROR;
2528 	}
2529 
2530 	if (sec) {
2531 		sec->fw_wpa_auth = wpa_auth;
2532 		sec->fw_auth = auth;
2533 		sec->fw_wsec = wsec;
2534 	}
2535 
2536 exit:
2537 	return 0;
2538 }
2539 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
2540 
2541 static s32
wl_cfg80211_bcn_validate_sec(struct net_device * dev,struct parsed_ies * ies,u32 dev_role,s32 bssidx,bool privacy)2542 wl_cfg80211_bcn_validate_sec(
2543 	struct net_device *dev,
2544 	struct parsed_ies *ies,
2545 	u32 dev_role,
2546 	s32 bssidx,
2547 	bool privacy)
2548 {
2549 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2550 	wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
2551 	struct wl_security *sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
2552 
2553 	if (!bss) {
2554 		WL_ERR(("cfgbss is NULL \n"));
2555 		return BCME_ERROR;
2556 	}
2557 
2558 	if (dev_role == NL80211_IFTYPE_P2P_GO && (ies->wpa2_ie)) {
2559 		/* For P2P GO, the sec type is WPA2-PSK */
2560 		WL_DBG(("P2P GO: validating wpa2_ie\n"));
2561 		if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0)
2562 			return BCME_ERROR;
2563 
2564 	} else if (dev_role == NL80211_IFTYPE_AP) {
2565 
2566 		WL_DBG(("SoftAP: validating security\n"));
2567 		/* If wpa2_ie or wpa_ie is present validate it */
2568 
2569 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
2570 		if ((ies->wpa_ie != NULL && ies->wpa2_ie != NULL)) {
2571 			if (wl_validate_wpaie_wpa2ie(dev, ies->wpa_ie, ies->wpa2_ie, bssidx)  < 0) {
2572 				bss->security_mode = false;
2573 				return BCME_ERROR;
2574 			}
2575 		}
2576 		else {
2577 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
2578 		if ((ies->wpa2_ie || ies->wpa_ie) &&
2579 			((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
2580 			wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
2581 			bss->security_mode = false;
2582 			return BCME_ERROR;
2583 		}
2584 
2585 		if (ies->fils_ind_ie &&
2586 			(wl_validate_fils_ind_ie(dev, ies->fils_ind_ie, bssidx)  < 0)) {
2587 			bss->security_mode = false;
2588 			return BCME_ERROR;
2589 		}
2590 
2591 		bss->security_mode = true;
2592 		if (bss->rsn_ie) {
2593 			MFREE(cfg->osh, bss->rsn_ie, bss->rsn_ie[1]
2594 				+ WPA_RSN_IE_TAG_FIXED_LEN);
2595 			bss->rsn_ie = NULL;
2596 		}
2597 		if (bss->wpa_ie) {
2598 			MFREE(cfg->osh, bss->wpa_ie, bss->wpa_ie[1]
2599 				+ WPA_RSN_IE_TAG_FIXED_LEN);
2600 			bss->wpa_ie = NULL;
2601 		}
2602 		if (bss->wps_ie) {
2603 			MFREE(cfg->osh, bss->wps_ie, bss->wps_ie[1] + 2);
2604 			bss->wps_ie = NULL;
2605 		}
2606 		if (bss->fils_ind_ie) {
2607 			MFREE(cfg->osh, bss->fils_ind_ie, bss->fils_ind_ie[1]
2608 				+ FILS_INDICATION_IE_TAG_FIXED_LEN);
2609 			bss->fils_ind_ie = NULL;
2610 		}
2611 		if (ies->wpa_ie != NULL) {
2612 			/* WPAIE */
2613 			bss->rsn_ie = NULL;
2614 			bss->wpa_ie = MALLOCZ(cfg->osh,
2615 					ies->wpa_ie->length
2616 					+ WPA_RSN_IE_TAG_FIXED_LEN);
2617 			if (bss->wpa_ie) {
2618 				memcpy(bss->wpa_ie, ies->wpa_ie,
2619 					ies->wpa_ie->length
2620 					+ WPA_RSN_IE_TAG_FIXED_LEN);
2621 			}
2622 		} else if (ies->wpa2_ie != NULL) {
2623 			/* RSNIE */
2624 			bss->wpa_ie = NULL;
2625 			bss->rsn_ie = MALLOCZ(cfg->osh,
2626 					ies->wpa2_ie->len
2627 					+ WPA_RSN_IE_TAG_FIXED_LEN);
2628 			if (bss->rsn_ie) {
2629 				memcpy(bss->rsn_ie, ies->wpa2_ie,
2630 					ies->wpa2_ie->len
2631 					+ WPA_RSN_IE_TAG_FIXED_LEN);
2632 			}
2633 		}
2634 #ifdef WL_FILS
2635 		if (ies->fils_ind_ie) {
2636 			bss->fils_ind_ie = MALLOCZ(cfg->osh,
2637 					ies->fils_ind_ie->len
2638 					+ FILS_INDICATION_IE_TAG_FIXED_LEN);
2639 			if (bss->fils_ind_ie) {
2640 				memcpy(bss->fils_ind_ie, ies->fils_ind_ie,
2641 					ies->fils_ind_ie->len
2642 					+ FILS_INDICATION_IE_TAG_FIXED_LEN);
2643 			}
2644 		}
2645 #endif /* WL_FILS */
2646 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
2647 		}
2648 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
2649 		if (!ies->wpa2_ie && !ies->wpa_ie) {
2650 			wl_validate_opensecurity(dev, bssidx, privacy);
2651 			bss->security_mode = false;
2652 		}
2653 
2654 		if (ies->wps_ie) {
2655 			bss->wps_ie = MALLOCZ(cfg->osh, ies->wps_ie_len);
2656 			if (bss->wps_ie) {
2657 				memcpy(bss->wps_ie, ies->wps_ie, ies->wps_ie_len);
2658 			}
2659 		}
2660 	}
2661 
2662 	WL_INFORM_MEM(("[%s] wpa_auth:0x%x auth:0x%x wsec:0x%x mfp:0x%x\n",
2663 		dev->name, sec->fw_wpa_auth, sec->fw_auth, sec->fw_wsec, sec->fw_mfp));
2664 	return 0;
2665 
2666 }
2667 
2668 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
2669 	defined(WL_COMPAT_WIRELESS)
wl_cfg80211_bcn_set_params(struct cfg80211_ap_settings * info,struct net_device * dev,u32 dev_role,s32 bssidx)2670 static s32 wl_cfg80211_bcn_set_params(
2671 	struct cfg80211_ap_settings *info,
2672 	struct net_device *dev,
2673 	u32 dev_role, s32 bssidx)
2674 {
2675 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2676 	s32 err = BCME_OK;
2677 
2678 	WL_DBG(("interval (%d) dtim_period (%d) \n",
2679 		info->beacon_interval, info->dtim_period));
2680 
2681 	if (info->beacon_interval) {
2682 		if ((err = wldev_ioctl_set(dev, WLC_SET_BCNPRD,
2683 			&info->beacon_interval, sizeof(s32))) < 0) {
2684 			WL_ERR(("Beacon Interval Set Error, %d\n", err));
2685 			return err;
2686 		}
2687 	}
2688 
2689 	if (info->dtim_period) {
2690 		if ((err = wldev_ioctl_set(dev, WLC_SET_DTIMPRD,
2691 			&info->dtim_period, sizeof(s32))) < 0) {
2692 			WL_ERR(("DTIM Interval Set Error, %d\n", err));
2693 			return err;
2694 		}
2695 	}
2696 
2697 	if ((info->ssid) && (info->ssid_len > 0) &&
2698 		(info->ssid_len <= DOT11_MAX_SSID_LEN)) {
2699 		WL_DBG(("SSID (%s) len:%zd \n", info->ssid, info->ssid_len));
2700 		if (dev_role == NL80211_IFTYPE_AP) {
2701 			/* Store the hostapd SSID */
2702 			bzero(cfg->hostapd_ssid.SSID, DOT11_MAX_SSID_LEN);
2703 			memcpy(cfg->hostapd_ssid.SSID, info->ssid, info->ssid_len);
2704 			cfg->hostapd_ssid.SSID_len = (uint32)info->ssid_len;
2705 		} else {
2706 				/* P2P GO */
2707 			bzero(cfg->p2p->ssid.SSID, DOT11_MAX_SSID_LEN);
2708 			memcpy(cfg->p2p->ssid.SSID, info->ssid, info->ssid_len);
2709 			cfg->p2p->ssid.SSID_len = (uint32)info->ssid_len;
2710 		}
2711 	}
2712 
2713 	return err;
2714 }
2715 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
2716 
2717 s32
wl_cfg80211_parse_ies(const u8 * ptr,u32 len,struct parsed_ies * ies)2718 wl_cfg80211_parse_ies(const u8 *ptr, u32 len, struct parsed_ies *ies)
2719 {
2720 	s32 err = BCME_OK;
2721 
2722 	bzero(ies, sizeof(struct parsed_ies));
2723 
2724 	/* find the WPSIE */
2725 	if ((ies->wps_ie = wl_cfgp2p_find_wpsie(ptr, len)) != NULL) {
2726 		WL_DBG(("WPSIE in beacon \n"));
2727 		ies->wps_ie_len = ies->wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
2728 	} else {
2729 		WL_DBG(("No WPSIE in beacon \n"));
2730 	}
2731 
2732 	/* find the RSN_IE */
2733 	if ((ies->wpa2_ie = bcm_parse_tlvs(ptr, len,
2734 		DOT11_MNG_RSN_ID)) != NULL) {
2735 		WL_DBG((" WPA2 IE found\n"));
2736 		ies->wpa2_ie_len = ies->wpa2_ie->len;
2737 	}
2738 
2739 	/* find the FILS_IND_IE */
2740 	if ((ies->fils_ind_ie = bcm_parse_tlvs(ptr, len,
2741 		DOT11_MNG_FILS_IND_ID)) != NULL) {
2742 		WL_DBG((" FILS IND IE found\n"));
2743 		ies->fils_ind_ie_len = ies->fils_ind_ie->len;
2744 	}
2745 
2746 	/* find the WPA_IE */
2747 	if ((ies->wpa_ie = wl_cfgp2p_find_wpaie(ptr, len)) != NULL) {
2748 		WL_DBG((" WPA found\n"));
2749 		ies->wpa_ie_len = ies->wpa_ie->length;
2750 	}
2751 
2752 	return err;
2753 
2754 }
2755 
2756 s32
wl_cfg80211_set_ap_role(struct bcm_cfg80211 * cfg,struct net_device * dev)2757 wl_cfg80211_set_ap_role(
2758 	struct bcm_cfg80211 *cfg,
2759 	struct net_device *dev)
2760 {
2761 	s32 err = BCME_OK;
2762 	s32 infra = 1;
2763 	s32 ap = 0;
2764 	s32 pm;
2765 	s32 bssidx;
2766 	s32 apsta = 0;
2767 	bool new_chip;
2768 #ifdef WLEASYMESH
2769 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2770 #endif /* WLEASYMESH */
2771 
2772 	new_chip = wl_new_chip_check(dev);
2773 
2774 	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
2775 		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
2776 		return -EINVAL;
2777 	}
2778 
2779 	WL_INFORM_MEM(("[%s] Bringup SoftAP on bssidx:%d \n", dev->name, bssidx));
2780 
2781 	if (bssidx != 0 || new_chip) {
2782 		if ((err = wl_cfg80211_add_del_bss(cfg, dev, bssidx,
2783 				WL_IF_TYPE_AP, 0, NULL)) < 0) {
2784 			WL_ERR(("wl add_del_bss returned error:%d\n", err));
2785 			return err;
2786 		}
2787 	}
2788 
2789 	/*
2790 	 * For older chips, "bss" iovar does not support
2791 	 * bsscfg role change/upgradation, and still
2792 	 * return BCME_OK on attempt
2793 	 * Hence, below traditional way to handle the same
2794 	 */
2795 
2796 	if ((err = wldev_ioctl_get(dev,
2797 			WLC_GET_AP, &ap, sizeof(s32))) < 0) {
2798 		WL_ERR(("Getting AP mode failed %d \n", err));
2799 		return err;
2800 	}
2801 #ifdef WLEASYMESH
2802 	else if (dhd->conf->fw_type == FW_TYPE_EZMESH) {
2803 		WL_MSG(dev->name, "Getting AP mode ok, set map and dwds\n");
2804 		err = wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
2805 		if (err < 0) {
2806 			WL_ERR(("WLC_DOWN error %d\n", err));
2807 			return err;
2808 		}
2809 		//For FrontHaulAP
2810 		err = wldev_iovar_setint(dev, "map", 2);
2811 		if (err < 0) {
2812 			WL_ERR(("wl map 2 error %d\n", err));
2813 			return err;
2814 		}
2815 		err = wldev_iovar_setint(dev, "dwds", 1);
2816 		if (err < 0) {
2817 			WL_ERR(("wl dwds 1 error %d\n", err));
2818 			return err;
2819 		}
2820 		WL_MSG(dev->name, "Get AP %d\n", (int)ap);
2821 	}
2822 #endif /* WLEASYMESH*/
2823 
2824 	if (!ap) {
2825 		/* AP mode switch not supported. Try setting up AP explicitly */
2826 		err = wldev_iovar_getint(dev, "apsta", (s32 *)&apsta);
2827 		if (unlikely(err)) {
2828 			WL_ERR(("Could not get apsta %d\n", err));
2829 			return err;
2830 		}
2831 		if (apsta == 0) {
2832 			/* If apsta is not set, set it */
2833 
2834 			/* Check for any connected interfaces before wl down */
2835 			if (wl_get_drv_status_all(cfg, CONNECTED) > 0) {
2836 #ifdef WLEASYMESH
2837 				if (dhd->conf->fw_type == FW_TYPE_EZMESH) {
2838 					WL_MSG(dev->name, "do wl down\n");
2839 				} else {
2840 #endif /* WLEASYMESH */
2841 					WL_ERR(("Concurrent i/f operational. can't do wl down\n"));
2842 					return BCME_ERROR;
2843 #ifdef WLEASYMESH
2844 				}
2845 #endif /* WLEASYMESH */
2846 			}
2847 			err = wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
2848 			if (err < 0) {
2849 				WL_ERR(("WLC_DOWN error %d\n", err));
2850 				return err;
2851 			}
2852 #ifdef WLEASYMESH
2853 			if (dhd->conf->fw_type == FW_TYPE_EZMESH)
2854 				err = wldev_iovar_setint(dev, "apsta", 1);
2855 			else
2856 #endif /* WLEASYMESH */
2857 				err = wldev_iovar_setint(dev, "apsta", 0);
2858 			if (err < 0) {
2859 				WL_ERR(("wl apsta 0 error %d\n", err));
2860 				return err;
2861 			}
2862 			ap = 1;
2863 			if ((err = wldev_ioctl_set(dev,
2864 					WLC_SET_AP, &ap, sizeof(s32))) < 0) {
2865 				WL_ERR(("setting AP mode failed %d \n", err));
2866 				return err;
2867 			}
2868 #ifdef WLEASYMESH
2869 			//For FrontHaulAP
2870 			if (dhd->conf->fw_type == FW_TYPE_EZMESH) {
2871 				WL_MSG(dev->name, "wl map 2\n");
2872 				err = wldev_iovar_setint(dev, "map", 2);
2873 				if (err < 0) {
2874 					WL_ERR(("wl map 2 error %d\n", err));
2875 					return err;
2876 				}
2877 				err = wldev_iovar_setint(dev, "dwds", 1);
2878 				if (err < 0) {
2879 					WL_ERR(("wl dwds 1 error %d\n", err));
2880 					return err;
2881 				}
2882 			}
2883 #endif /* WLEASYMESH */
2884 		}
2885 	}
2886 	else if (bssidx == 0 && !new_chip
2887 #ifdef WL_EXT_IAPSTA
2888 			&& !wl_ext_iapsta_other_if_enabled(dev)
2889 #endif
2890 			) {
2891 		err = wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
2892 		if (err < 0) {
2893 			WL_ERR(("WLC_DOWN error %d\n", err));
2894 			return err;
2895 		}
2896 		err = wldev_iovar_setint(dev, "apsta", 0);
2897 		if (err < 0) {
2898 			WL_ERR(("wl apsta 0 error %d\n", err));
2899 			return err;
2900 		}
2901 		ap = 1;
2902 		if ((err = wldev_ioctl_set(dev, WLC_SET_AP, &ap, sizeof(s32))) < 0) {
2903 			WL_ERR(("setting AP mode failed %d \n", err));
2904 			return err;
2905 		}
2906 	}
2907 
2908 	if (bssidx == 0) {
2909 		pm = 0;
2910 		if ((err = wldev_ioctl_set(dev, WLC_SET_PM, &pm, sizeof(pm))) != 0) {
2911 			WL_ERR(("wl PM 0 returned error:%d\n", err));
2912 			/* Ignore error, if any */
2913 			err = BCME_OK;
2914 		}
2915 		err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
2916 		if (err < 0) {
2917 			WL_ERR(("SET INFRA error %d\n", err));
2918 			return err;
2919 		}
2920 	}
2921 
2922 	/* On success, mark AP creation in progress. */
2923 	wl_set_drv_status(cfg, AP_CREATING, dev);
2924 	return 0;
2925 }
2926 
2927 void
wl_cfg80211_ap_timeout_work(struct work_struct * work)2928 wl_cfg80211_ap_timeout_work(struct work_struct *work)
2929 {
2930 #if defined (BCMDONGLEHOST)
2931 	struct bcm_cfg80211 *cfg = NULL;
2932 	dhd_pub_t *dhdp = NULL;
2933 	BCM_SET_CONTAINER_OF(cfg, work, struct bcm_cfg80211, ap_work.work);
2934 
2935 	WL_ERR(("** AP LINK UP TIMEOUT **\n"));
2936 	dhdp = (dhd_pub_t *)(cfg->pub);
2937 	if (dhd_query_bus_erros(dhdp)) {
2938 		return;
2939 	}
2940 #ifdef DHD_PCIE_RUNTIMEPM
2941 	dhdpcie_runtime_bus_wake(dhdp, CAN_SLEEP(), __builtin_return_address(0));
2942 #endif /* DHD_PCIE_RUNTIMEPM */
2943 	dhdp->iface_op_failed = TRUE;
2944 
2945 #if defined(DHD_DEBUG) && defined(DHD_FW_COREDUMP)
2946 	if (dhdp->memdump_enabled) {
2947 		dhdp->memdump_type = DUMP_TYPE_AP_LINKUP_FAILURE;
2948 		dhd_bus_mem_dump(dhdp);
2949 	}
2950 #endif /* DHD_DEBUG && DHD_FW_COREDUMP */
2951 
2952 #if defined(OEM_ANDROID)
2953 	WL_ERR(("Notify hang event to upper layer \n"));
2954 	dhdp->hang_reason = HANG_REASON_IFACE_ADD_FAILURE;
2955 	net_os_send_hang_message(bcmcfg_to_prmry_ndev(cfg));
2956 #endif /* OEM_ANDROID */
2957 #endif /* BCMDONGLEHOST */
2958 }
2959 
2960 /* In RSDB downgrade cases, the link up event can get delayed upto 7-8 secs */
2961 #define MAX_AP_LINK_WAIT_TIME   10000
2962 static s32
wl_cfg80211_bcn_bringup_ap(struct net_device * dev,struct parsed_ies * ies,u32 dev_role,s32 bssidx)2963 wl_cfg80211_bcn_bringup_ap(
2964 	struct net_device *dev,
2965 	struct parsed_ies *ies,
2966 	u32 dev_role, s32 bssidx)
2967 {
2968 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
2969 	struct wl_join_params join_params;
2970 	bool is_bssup = false;
2971 	s32 infra = 1;
2972 	s32 join_params_size = 0;
2973 	s32 ap = 1;
2974 	s32 wsec;
2975 #ifdef DISABLE_11H_SOFTAP
2976 	s32 spect = 0;
2977 #endif /* DISABLE_11H_SOFTAP */
2978 #ifdef SOFTAP_UAPSD_OFF
2979 	uint32 wme_apsd = 0;
2980 #endif /* SOFTAP_UAPSD_OFF */
2981 	s32 err = BCME_OK;
2982 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
2983 	s32 is_rsdb_supported = BCME_ERROR;
2984 	char sec[64];
2985 
2986 #if defined (BCMDONGLEHOST)
2987 	is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
2988 	if (is_rsdb_supported < 0)
2989 		return (-ENODEV);
2990 #endif /* BCMDONGLEHOST */
2991 
2992 	WL_DBG(("Enter dev_role:%d bssidx:%d ifname:%s\n", dev_role, bssidx, dev->name));
2993 
2994 	/* Common code for SoftAP and P2P GO */
2995 	wl_clr_drv_status(cfg, AP_CREATED, dev);
2996 
2997 	/* Make sure INFRA is set for AP/GO */
2998 	err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
2999 	if (err < 0) {
3000 		WL_ERR(("SET INFRA error %d\n", err));
3001 		goto exit;
3002 	}
3003 
3004 	/* Do abort scan before creating GO */
3005 	wl_cfgscan_cancel_scan(cfg);
3006 
3007 	/* Schedule delayed work to handle link time out. schedule
3008 	 * before ssid iovar. Sometimes before iovar context should
3009 	 * resume, the event may come and get processed.
3010 	 */
3011 	if (schedule_delayed_work(&cfg->ap_work,
3012 			msecs_to_jiffies((const unsigned int)MAX_AP_LINK_WAIT_TIME))) {
3013 		WL_DBG(("ap timeout work scheduled\n"));
3014 	}
3015 
3016 	if (dev_role == NL80211_IFTYPE_P2P_GO) {
3017 		wl_ext_get_sec(dev, 0, sec, sizeof(sec), TRUE);
3018 		WL_MSG(dev->name, "Creating GO with sec=%s\n", sec);
3019 		is_bssup = wl_cfg80211_bss_isup(dev, bssidx);
3020 		if (!is_bssup && (ies->wpa2_ie != NULL)) {
3021 
3022 			err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &cfg->p2p->ssid,
3023 				sizeof(cfg->p2p->ssid), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
3024 				bssidx, &cfg->ioctl_buf_sync);
3025 			if (err < 0) {
3026 				WL_ERR(("GO SSID setting error %d\n", err));
3027 				goto exit;
3028 			}
3029 
3030 			if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 1)) < 0) {
3031 				WL_ERR(("GO Bring up error %d\n", err));
3032 				goto exit;
3033 			}
3034 			wl_clr_drv_status(cfg, AP_CREATING, dev);
3035 		} else
3036 			WL_DBG(("Bss is already up\n"));
3037 	} else if (dev_role == NL80211_IFTYPE_AP) {
3038 
3039 //		if (!wl_get_drv_status(cfg, AP_CREATING, dev)) {
3040 			/* Make sure fw is in proper state */
3041 			err = wl_cfg80211_set_ap_role(cfg, dev);
3042 			if (unlikely(err)) {
3043 				WL_ERR(("set ap role failed!\n"));
3044 				goto exit;
3045 			}
3046 //		}
3047 
3048 		/* Device role SoftAP */
3049 		WL_DBG(("Creating AP bssidx:%d dev_role:%d\n", bssidx, dev_role));
3050 		/* Clear the status bit after use */
3051 		wl_clr_drv_status(cfg, AP_CREATING, dev);
3052 
3053 #ifdef DISABLE_11H_SOFTAP
3054 		/* Some old WLAN card (e.g. Intel PRO/Wireless 2200BG)
3055 		 * does not try to connect SoftAP because they cannot detect
3056 		 * 11h IEs. For this reason, we disable 11h feature in case
3057 		 * of SoftAP mode. (Related CSP case number: 661635)
3058 		 */
3059 		if (is_rsdb_supported == 0) {
3060 			err = wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
3061 			if (err < 0) {
3062 				WL_ERR(("WLC_DOWN error %d\n", err));
3063 				goto exit;
3064 			}
3065 		}
3066 		err = wldev_ioctl_set(dev, WLC_SET_SPECT_MANAGMENT,
3067 			&spect, sizeof(s32));
3068 		if (err < 0) {
3069 			WL_ERR(("SET SPECT_MANAGMENT error %d\n", err));
3070 			goto exit;
3071 		}
3072 #endif /* DISABLE_11H_SOFTAP */
3073 
3074 #ifdef WL_DISABLE_HE_SOFTAP
3075 		err = wl_cfg80211_set_he_mode(dev, cfg, bssidx, WL_HE_FEATURES_HE_AP, FALSE);
3076 		if (err < 0) {
3077 			WL_ERR(("failed to set he features, error=%d\n", err));
3078 		}
3079 #endif /* WL_DISABLE_HE_SOFTAP */
3080 
3081 #ifdef SOFTAP_UAPSD_OFF
3082 		err = wldev_iovar_setbuf_bsscfg(dev, "wme_apsd", &wme_apsd, sizeof(wme_apsd),
3083 			cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
3084 		if (err < 0) {
3085 			WL_ERR(("failed to disable uapsd, error=%d\n", err));
3086 		}
3087 #endif /* SOFTAP_UAPSD_OFF */
3088 
3089 #ifdef WLDWDS
3090 		err = wldev_iovar_setint(dev, "dwds", 1);
3091 		if (err < 0) {
3092 			WL_ERR(("set dwds error %d\n", err));
3093 			goto exit;
3094 		}
3095 #endif /* WLDWDS */
3096 
3097 		err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
3098 		if (unlikely(err)) {
3099 			WL_ERR(("WLC_UP error (%d)\n", err));
3100 			goto exit;
3101 		}
3102 
3103 #ifdef MFP
3104 		if (cfg->bip_pos) {
3105 			err = wldev_iovar_setbuf_bsscfg(dev, "bip",
3106 				(const void *)(cfg->bip_pos), WPA_SUITE_LEN, cfg->ioctl_buf,
3107 				WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
3108 			if (err < 0) {
3109 				WL_ERR(("bip set error %d\n", err));
3110 
3111 #ifdef CUSTOMER_HW6
3112 				if (wl_customer6_legacy_chip_check(cfg,
3113 					bcmcfg_to_prmry_ndev(cfg))) {
3114 					/* Ignore bip error: Some older firmwares doesn't
3115 					 * support bip iovar/ return BCME_NOTUP while trying
3116 					 * to set bip from AP bring up context. These firmares
3117 					 * include bip in RSNIE by default. So its okay to ignore
3118 					 * the error.
3119 					 */
3120 					err = BCME_OK;
3121 				} else
3122 #endif /* CUSTOMER_HW6 */
3123 
3124 				{
3125 					goto exit;
3126 				}
3127 			}
3128 		}
3129 #endif /* MFP */
3130 
3131 		err = wldev_iovar_getint(dev, "wsec", (s32 *)&wsec);
3132 		if (unlikely(err)) {
3133 			WL_ERR(("Could not get wsec %d\n", err));
3134 			goto exit;
3135 		}
3136 		if (dhd->conf->chip == BCM43430_CHIP_ID && bssidx > 0 &&
3137 				(wsec & (TKIP_ENABLED|AES_ENABLED))) {
3138 			struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
3139 			struct ether_addr bssid;
3140 			int ret = 0;
3141 			wsec |= WSEC_SWFLAG; // terence 20180628: fix me, this is a workaround
3142 			err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
3143 			if (err < 0) {
3144 				WL_ERR(("wsec error %d\n", err));
3145 				goto exit;
3146 			}
3147 			bzero(&bssid, sizeof(bssid));
3148 			ret = wldev_ioctl_get(primary_ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
3149 			if (ret != BCME_NOTASSOCIATED && memcmp(&ether_null, &bssid, ETHER_ADDR_LEN)) {
3150 				scb_val_t scbval;
3151 				bzero(&scbval, sizeof(scb_val_t));
3152 				scbval.val = WLAN_REASON_DEAUTH_LEAVING;
3153 				wldev_ioctl_set(primary_ndev, WLC_DISASSOC, &scbval, sizeof(scb_val_t));
3154 			}
3155 		}
3156 		if ((wsec == WEP_ENABLED) && cfg->wep_key.len) {
3157 			WL_DBG(("Applying buffered WEP KEY \n"));
3158 			err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &cfg->wep_key,
3159 				sizeof(struct wl_wsec_key), cfg->ioctl_buf,
3160 				WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
3161 			/* clear the key after use */
3162 			bzero(&cfg->wep_key, sizeof(struct wl_wsec_key));
3163 			if (unlikely(err)) {
3164 				WL_ERR(("WLC_SET_KEY error (%d)\n", err));
3165 				goto exit;
3166 			}
3167 		}
3168 
3169 #ifdef MFP
3170 		if (cfg->mfp_mode) {
3171 			/* This needs to go after wsec otherwise the wsec command will
3172 			 * overwrite the values set by MFP
3173 			 */
3174 			err = wldev_iovar_setint_bsscfg(dev, "mfp", cfg->mfp_mode, bssidx);
3175 			if (err < 0) {
3176 				WL_ERR(("MFP Setting failed. ret = %d \n", err));
3177 				/* If fw doesn't support mfp, Ignore the error */
3178 				if (err != BCME_UNSUPPORTED) {
3179 					goto exit;
3180 				}
3181 			}
3182 		}
3183 #endif /* MFP */
3184 
3185 		bzero(&join_params, sizeof(join_params));
3186 		/* join parameters starts with ssid */
3187 		join_params_size = sizeof(join_params.ssid);
3188 		join_params.ssid.SSID_len = MIN(cfg->hostapd_ssid.SSID_len,
3189 			(uint32)DOT11_MAX_SSID_LEN);
3190 		memcpy(join_params.ssid.SSID, cfg->hostapd_ssid.SSID,
3191 			join_params.ssid.SSID_len);
3192 		join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
3193 
3194 		wl_ext_get_sec(dev, 0, sec, sizeof(sec), TRUE);
3195 		WL_MSG(dev->name, "Creating AP with sec=%s\n", sec);
3196 		/* create softap */
3197 		if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
3198 			join_params_size)) != 0) {
3199 			WL_ERR(("SoftAP/GO set ssid failed! \n"));
3200 			goto exit;
3201 		} else {
3202 			WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
3203 		}
3204 
3205 		if (bssidx != 0) {
3206 			/* AP on Virtual Interface */
3207 			if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 1)) < 0) {
3208 				WL_ERR(("AP Bring up error %d\n", err));
3209 				goto exit;
3210 			}
3211 		}
3212 
3213 	} else {
3214 		WL_ERR(("Wrong interface type %d\n", dev_role));
3215 		goto exit;
3216 	}
3217 
3218 	SUPP_LOG(("AP/GO UP\n"));
3219 
3220 exit:
3221 	if (cfg->wep_key.len) {
3222 		bzero(&cfg->wep_key, sizeof(struct wl_wsec_key));
3223 	}
3224 
3225 #ifdef MFP
3226 	if (cfg->mfp_mode) {
3227 		cfg->mfp_mode = 0;
3228 	}
3229 
3230 	if (cfg->bip_pos) {
3231 		cfg->bip_pos = NULL;
3232 	}
3233 #endif /* MFP */
3234 
3235 	if (err) {
3236 		SUPP_LOG(("AP/GO bring up fail. err:%d\n", err));
3237 		/* Cancel work if scheduled */
3238 		if (delayed_work_pending(&cfg->ap_work)) {
3239 			cancel_delayed_work_sync(&cfg->ap_work);
3240 			WL_DBG(("cancelled ap_work\n"));
3241 		}
3242 	}
3243 	return err;
3244 }
3245 
3246 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
3247 	defined(WL_COMPAT_WIRELESS)
3248 s32
wl_cfg80211_parse_ap_ies(struct net_device * dev,struct cfg80211_beacon_data * info,struct parsed_ies * ies)3249 wl_cfg80211_parse_ap_ies(
3250 	struct net_device *dev,
3251 	struct cfg80211_beacon_data *info,
3252 	struct parsed_ies *ies)
3253 {
3254 	struct parsed_ies prb_ies;
3255 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3256 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
3257 	const u8 *vndr = NULL;
3258 	u32 vndr_ie_len = 0;
3259 	s32 err = BCME_OK;
3260 
3261 	/* Parse Beacon IEs */
3262 	if (wl_cfg80211_parse_ies((const u8 *)info->tail,
3263 		info->tail_len, ies) < 0) {
3264 		WL_ERR(("Beacon get IEs failed \n"));
3265 		err = -EINVAL;
3266 		goto fail;
3267 	}
3268 
3269 	if ((err = wl_cfg80211_config_rsnxe_ie(cfg, dev,
3270 		(const u8 *)info->tail, info->tail_len)) < 0) {
3271 		WL_ERR(("Failed to configure rsnxe ie: %d\n", err));
3272 		err = -EINVAL;
3273 		goto fail;
3274 	}
3275 
3276 	vndr = (const u8 *)info->proberesp_ies;
3277 	vndr_ie_len = (uint32)info->proberesp_ies_len;
3278 
3279 	if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
3280 		/* SoftAP mode */
3281 		const struct ieee80211_mgmt *mgmt;
3282 		mgmt = (const struct ieee80211_mgmt *)info->probe_resp;
3283 		if (mgmt != NULL) {
3284 			vndr = (const u8 *)&mgmt->u.probe_resp.variable;
3285 			vndr_ie_len = (uint32)(info->probe_resp_len -
3286 				offsetof(const struct ieee80211_mgmt, u.probe_resp.variable));
3287 		}
3288 	}
3289 	/* Parse Probe Response IEs */
3290 	if (wl_cfg80211_parse_ies((const u8 *)vndr, vndr_ie_len, &prb_ies) < 0) {
3291 		WL_ERR(("PROBE RESP get IEs failed \n"));
3292 		err = -EINVAL;
3293 	}
3294 fail:
3295 
3296 	return err;
3297 }
3298 
3299 s32
wl_cfg80211_set_ies(struct net_device * dev,struct cfg80211_beacon_data * info,s32 bssidx)3300 wl_cfg80211_set_ies(
3301 	struct net_device *dev,
3302 	struct cfg80211_beacon_data *info,
3303 	s32 bssidx)
3304 {
3305 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3306 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
3307 	const u8 *vndr = NULL;
3308 	u32 vndr_ie_len = 0;
3309 	s32 err = BCME_OK;
3310 
3311 	/* Set Beacon IEs to FW */
3312 	if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
3313 		VNDR_IE_BEACON_FLAG, (const u8 *)info->tail,
3314 		info->tail_len)) < 0) {
3315 		WL_ERR(("Set Beacon IE Failed \n"));
3316 	} else {
3317 		WL_DBG(("Applied Vndr IEs for Beacon \n"));
3318 	}
3319 
3320 	vndr = (const u8 *)info->proberesp_ies;
3321 	vndr_ie_len = (uint32)info->proberesp_ies_len;
3322 
3323 	if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {
3324 		/* SoftAP mode */
3325 		const struct ieee80211_mgmt *mgmt;
3326 		mgmt = (const struct ieee80211_mgmt *)info->probe_resp;
3327 		if (mgmt != NULL) {
3328 			vndr = (const u8 *)&mgmt->u.probe_resp.variable;
3329 			vndr_ie_len = (uint32)(info->probe_resp_len -
3330 				offsetof(struct ieee80211_mgmt, u.probe_resp.variable));
3331 		}
3332 	}
3333 
3334 	/* Set Probe Response IEs to FW */
3335 	if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
3336 		VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) {
3337 		WL_ERR(("Set Probe Resp IE Failed \n"));
3338 	} else {
3339 		WL_DBG(("Applied Vndr IEs for Probe Resp \n"));
3340 	}
3341 
3342 	return err;
3343 }
3344 #endif /* LINUX_VERSION >= VERSION(3,4,0) || WL_COMPAT_WIRELESS */
3345 
wl_cfg80211_hostapd_sec(struct net_device * dev,struct parsed_ies * ies,s32 bssidx)3346 static s32 wl_cfg80211_hostapd_sec(
3347 	struct net_device *dev,
3348 	struct parsed_ies *ies,
3349 	s32 bssidx)
3350 {
3351 	bool update_bss = 0;
3352 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
3353 	wl_cfgbss_t *bss = wl_get_cfgbss_by_wdev(cfg, dev->ieee80211_ptr);
3354 
3355 	if (!bss) {
3356 		WL_ERR(("cfgbss is NULL \n"));
3357 		return -EINVAL;
3358 	}
3359 
3360 	if (ies->wps_ie) {
3361 		/* Remove after verification.
3362 		 * Setting IE part moved to set_ies func
3363 		 */
3364 		if (bss->wps_ie &&
3365 			memcmp(bss->wps_ie, ies->wps_ie, ies->wps_ie_len)) {
3366 			WL_DBG((" WPS IE is changed\n"));
3367 			MFREE(cfg->osh, bss->wps_ie, bss->wps_ie[1] + 2);
3368 			bss->wps_ie = MALLOCZ(cfg->osh, ies->wps_ie_len);
3369 			if (bss->wps_ie) {
3370 				memcpy(bss->wps_ie, ies->wps_ie, ies->wps_ie_len);
3371 			}
3372 		} else if (bss->wps_ie == NULL) {
3373 			WL_DBG((" WPS IE is added\n"));
3374 			bss->wps_ie = MALLOCZ(cfg->osh, ies->wps_ie_len);
3375 			if (bss->wps_ie) {
3376 				memcpy(bss->wps_ie, ies->wps_ie, ies->wps_ie_len);
3377 			}
3378 		}
3379 
3380 #if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
3381 		if (ies->wpa_ie != NULL && ies->wpa2_ie != NULL) {
3382 			WL_ERR(("update bss - wpa_ie and  wpa2_ie is not null\n"));
3383 			if (!bss->security_mode) {
3384 				/* change from open mode to security mode */
3385 				update_bss = true;
3386 				bss->wpa_ie = MALLOCZ(cfg->osh,
3387 					ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN);
3388 				if (bss->wpa_ie) {
3389 					memcpy(bss->wpa_ie, ies->wpa_ie,
3390 						ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN);
3391 				}
3392 				bss->rsn_ie = MALLOCZ(cfg->osh,
3393 						ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN);
3394 				if (bss->rsn_ie) {
3395 					memcpy(bss->rsn_ie, ies->wpa2_ie,
3396 						ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN);
3397 				}
3398 			} else {
3399 				/* change from (WPA or WPA2 or WPA/WPA2) to WPA/WPA2 mixed mode */
3400 				if (bss->wpa_ie) {
3401 					if (memcmp(bss->wpa_ie,
3402 					ies->wpa_ie, ies->wpa_ie->length +
3403 					WPA_RSN_IE_TAG_FIXED_LEN)) {
3404 						MFREE(cfg->osh, bss->wpa_ie,
3405 							bss->wpa_ie[1] + WPA_RSN_IE_TAG_FIXED_LEN);
3406 						update_bss = true;
3407 						bss->wpa_ie = MALLOCZ(cfg->osh,
3408 							ies->wpa_ie->length
3409 							+ WPA_RSN_IE_TAG_FIXED_LEN);
3410 						if (bss->wpa_ie) {
3411 							memcpy(bss->wpa_ie, ies->wpa_ie,
3412 								ies->wpa_ie->length
3413 								+ WPA_RSN_IE_TAG_FIXED_LEN);
3414 						}
3415 					}
3416 				}
3417 				else {
3418 					update_bss = true;
3419 					bss->wpa_ie = MALLOCZ(cfg->osh,
3420 						ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN);
3421 					if (bss->wpa_ie) {
3422 						memcpy(bss->wpa_ie, ies->wpa_ie,
3423 							ies->wpa_ie->length
3424 							+ WPA_RSN_IE_TAG_FIXED_LEN);
3425 					}
3426 				}
3427 				if (bss->rsn_ie) {
3428 					if (memcmp(bss->rsn_ie,
3429 					ies->wpa2_ie,
3430 					ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN)) {
3431 						update_bss = true;
3432 						MFREE(cfg->osh, bss->rsn_ie,
3433 							bss->rsn_ie[1] + WPA_RSN_IE_TAG_FIXED_LEN);
3434 						bss->rsn_ie = MALLOCZ(cfg->osh,
3435 							ies->wpa2_ie->len
3436 							+ WPA_RSN_IE_TAG_FIXED_LEN);
3437 						if (bss->rsn_ie) {
3438 							memcpy(bss->rsn_ie, ies->wpa2_ie,
3439 								ies->wpa2_ie->len
3440 								+ WPA_RSN_IE_TAG_FIXED_LEN);
3441 						}
3442 					}
3443 				}
3444 				else {
3445 					update_bss = true;
3446 					bss->rsn_ie = MALLOCZ(cfg->osh,
3447 						ies->wpa2_ie->len
3448 						+ WPA_RSN_IE_TAG_FIXED_LEN);
3449 					if (bss->rsn_ie) {
3450 						memcpy(bss->rsn_ie, ies->wpa2_ie,
3451 							ies->wpa2_ie->len
3452 							+ WPA_RSN_IE_TAG_FIXED_LEN);
3453 					}
3454 				}
3455 			}
3456 			WL_ERR(("update_bss=%d\n", update_bss));
3457 			if (update_bss) {
3458 				bss->security_mode = true;
3459 				wl_cfg80211_bss_up(cfg, dev, bssidx, 0);
3460 				if (wl_validate_wpaie_wpa2ie(dev, ies->wpa_ie,
3461 					ies->wpa2_ie, bssidx)  < 0) {
3462 					return BCME_ERROR;
3463 				}
3464 				wl_cfg80211_bss_up(cfg, dev, bssidx, 1);
3465 			}
3466 
3467 		}
3468 		else
3469 #endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
3470 		if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
3471 			if (!bss->security_mode) {
3472 				/* change from open mode to security mode */
3473 				update_bss = true;
3474 				if (ies->wpa_ie != NULL) {
3475 					bss->wpa_ie = MALLOCZ(cfg->osh,
3476 						ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN);
3477 					if (bss->wpa_ie) {
3478 						memcpy(bss->wpa_ie,
3479 							ies->wpa_ie,
3480 							ies->wpa_ie->length
3481 							+ WPA_RSN_IE_TAG_FIXED_LEN);
3482 					}
3483 				} else {
3484 					bss->rsn_ie = MALLOCZ(cfg->osh,
3485 						ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN);
3486 					if (bss->rsn_ie) {
3487 						memcpy(bss->rsn_ie,
3488 							ies->wpa2_ie,
3489 							ies->wpa2_ie->len
3490 							+ WPA_RSN_IE_TAG_FIXED_LEN);
3491 					}
3492 				}
3493 			} else if (bss->wpa_ie) {
3494 				/* change from WPA2 mode to WPA mode */
3495 				if (ies->wpa_ie != NULL) {
3496 					update_bss = true;
3497 					MFREE(cfg->osh, bss->rsn_ie,
3498 						bss->rsn_ie[1] + WPA_RSN_IE_TAG_FIXED_LEN);
3499 					bss->rsn_ie = NULL;
3500 					bss->wpa_ie = MALLOCZ(cfg->osh,
3501 						ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN);
3502 					if (bss->wpa_ie) {
3503 						memcpy(bss->wpa_ie,
3504 							ies->wpa_ie,
3505 							ies->wpa_ie->length
3506 							+ WPA_RSN_IE_TAG_FIXED_LEN);
3507 					}
3508 				} else if (memcmp(bss->rsn_ie,
3509 					ies->wpa2_ie, ies->wpa2_ie->len
3510 					+ WPA_RSN_IE_TAG_FIXED_LEN)) {
3511 					update_bss = true;
3512 					MFREE(cfg->osh, bss->rsn_ie,
3513 						bss->rsn_ie[1] + WPA_RSN_IE_TAG_FIXED_LEN);
3514 					bss->rsn_ie = MALLOCZ(cfg->osh,
3515 						ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN);
3516 					if (bss->rsn_ie) {
3517 						memcpy(bss->rsn_ie,
3518 							ies->wpa2_ie,
3519 							ies->wpa2_ie->len
3520 							+ WPA_RSN_IE_TAG_FIXED_LEN);
3521 					}
3522 					bss->wpa_ie = NULL;
3523 				}
3524 			}
3525 			if (update_bss) {
3526 				bss->security_mode = true;
3527 				wl_cfg80211_bss_up(cfg, dev, bssidx, 0);
3528 				if (wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
3529 					wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0) {
3530 					return BCME_ERROR;
3531 				}
3532 				wl_cfg80211_bss_up(cfg, dev, bssidx, 1);
3533 			}
3534 		}
3535 	} else {
3536 		WL_ERR(("No WPSIE in beacon \n"));
3537 	}
3538 	return 0;
3539 }
3540 
3541 static s32
wl_cfg80211_set_scb_timings(struct bcm_cfg80211 * cfg,struct net_device * dev)3542 wl_cfg80211_set_scb_timings(
3543 	struct bcm_cfg80211 *cfg,
3544 	struct net_device *dev)
3545 {
3546 	int err;
3547 	u32 ps_pretend;
3548 	wl_scb_probe_t scb_probe;
3549 	u32 ps_pretend_retries;
3550 
3551 	bzero(&scb_probe, sizeof(wl_scb_probe_t));
3552 	scb_probe.scb_timeout = WL_SCB_TIMEOUT;
3553 	scb_probe.scb_activity_time = WL_SCB_ACTIVITY_TIME;
3554 	scb_probe.scb_max_probe = WL_SCB_MAX_PROBE;
3555 	err = wldev_iovar_setbuf(dev, "scb_probe", (void *)&scb_probe,
3556 		sizeof(wl_scb_probe_t), cfg->ioctl_buf, WLC_IOCTL_SMLEN,
3557 		&cfg->ioctl_buf_sync);
3558 	if (unlikely(err)) {
3559 		WL_ERR(("set 'scb_probe' failed, error = %d\n", err));
3560 		return err;
3561 	}
3562 
3563 	ps_pretend_retries = WL_PSPRETEND_RETRY_LIMIT;
3564 	err = wldev_iovar_setint(dev, "pspretend_retry_limit", ps_pretend_retries);
3565 	if (unlikely(err)) {
3566 		if (err == BCME_UNSUPPORTED) {
3567 			/* Ignore error if fw doesn't support the iovar */
3568 			WL_DBG(("set 'pspretend_retry_limit %d' failed, error = %d\n",
3569 				ps_pretend_retries, err));
3570 		} else {
3571 			WL_ERR(("set 'pspretend_retry_limit %d' failed, error = %d\n",
3572 				ps_pretend_retries, err));
3573 			return err;
3574 		}
3575 	}
3576 
3577 	ps_pretend = MAX(WL_SCB_MAX_PROBE / 2, WL_MIN_PSPRETEND_THRESHOLD);
3578 	err = wldev_iovar_setint(dev, "pspretend_threshold", ps_pretend);
3579 	if (unlikely(err)) {
3580 		if (err == BCME_UNSUPPORTED) {
3581 			/* Ignore error if fw doesn't support the iovar */
3582 			WL_DBG(("wl pspretend_threshold %d set error %d\n",
3583 				ps_pretend, err));
3584 		} else {
3585 			WL_ERR(("wl pspretend_threshold %d set error %d\n",
3586 				ps_pretend, err));
3587 			return err;
3588 		}
3589 	}
3590 
3591 	return 0;
3592 }
3593 
3594 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
3595 	defined(WL_COMPAT_WIRELESS)
3596 s32
wl_cfg80211_start_ap(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_ap_settings * info)3597 wl_cfg80211_start_ap(
3598 	struct wiphy *wiphy,
3599 	struct net_device *dev,
3600 	struct cfg80211_ap_settings *info)
3601 {
3602 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3603 	s32 err = BCME_OK;
3604 	struct parsed_ies ies;
3605 	s32 bssidx = 0;
3606 	u32 dev_role = 0;
3607 #ifdef BCMDONGLEHOST
3608 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
3609 #endif /* BCMDONGLEHOST */
3610 
3611 	WL_DBG(("Enter \n"));
3612 
3613 	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
3614 		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
3615 		return BCME_ERROR;
3616 	}
3617 
3618 	if (p2p_is_on(cfg) && (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO)) {
3619 		dev_role = NL80211_IFTYPE_P2P_GO;
3620 	} else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
3621 
3622 		if (!wl_get_drv_status(cfg, AP_CREATING, dev)) {
3623 			/* Make sure fw is in proper state */
3624 			err = wl_cfg80211_set_ap_role(cfg, dev);
3625 			if (unlikely(err)) {
3626 				WL_ERR(("set ap role failed!\n"));
3627 				return BCME_ERROR;
3628 			}
3629 		}
3630 		dev_role = NL80211_IFTYPE_AP;
3631 #ifdef BCMDONGLEHOST
3632 		dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
3633 		err = dhd_ndo_enable(dhd, FALSE);
3634 		WL_DBG(("Disabling NDO on Hostapd mode %d\n", err));
3635 		if (err) {
3636 			WL_ERR(("Disabling NDO Failed %d\n", err));
3637 		}
3638 		wl_wlfc_enable(cfg, TRUE);
3639 #ifdef WL_EXT_IAPSTA
3640 		wl_ext_iapsta_update_iftype(dev, WL_IF_TYPE_AP);
3641 #endif /* WL_EXT_IAPSTA */
3642 #ifdef PKT_FILTER_SUPPORT
3643 		/* Disable packet filter */
3644 		if (dhd->early_suspended) {
3645 			WL_ERR(("Disable pkt_filter\n"));
3646 			dhd_enable_packet_filter(0, dhd);
3647 #ifdef APF
3648 			dhd_dev_apf_disable_filter(dhd_linux_get_primary_netdev(dhd));
3649 #endif /* APF */
3650 		}
3651 #endif /* PKT_FILTER_SUPPORT */
3652 #endif /* BCMDONGLEHOST */
3653 	} else {
3654 		/* only AP or GO role need to be handled here. */
3655 		err = -EINVAL;
3656 		goto fail;
3657 	}
3658 
3659 	/* disable TDLS */
3660 #ifdef WLTDLS
3661 	if (bssidx == 0) {
3662 		/* Disable TDLS for primary Iface. For virtual interface,
3663 		 * tdls disable will happen from interface create context
3664 		 */
3665 		wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_CREATE, false);
3666 	}
3667 #endif /*  WLTDLS */
3668 
3669 	if (!check_dev_role_integrity(cfg, dev_role)) {
3670 		err = -EINVAL;
3671 		goto fail;
3672 	}
3673 
3674 /*
3675  * TODO:
3676  * Check whether 802.11ac-160MHz bandwidth channel setting has to use the
3677  *      center frequencies present in 'preset_chandef' instead of using the
3678  *      hardcoded values in 'wl_cfg80211_set_channel()'.
3679  */
3680 #if ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && !defined(WL_COMPAT_WIRELESS))
3681 	if (!dev->ieee80211_ptr->preset_chandef.chan) {
3682 		WL_ERR(("chan is NULL\n"));
3683 		err = -EINVAL;
3684 		goto fail;
3685 	}
3686 	if ((err = wl_cfg80211_set_channel(wiphy, dev,
3687 		dev->ieee80211_ptr->preset_chandef.chan,
3688 		NL80211_CHAN_HT20) < 0)) {
3689 		WL_ERR(("Set channel failed \n"));
3690 		goto fail;
3691 	}
3692 #endif /* ((LINUX_VERSION >= VERSION(3, 6, 0) && !WL_COMPAT_WIRELESS) */
3693 
3694 	if ((err = wl_cfg80211_bcn_set_params(info, dev,
3695 		dev_role, bssidx)) < 0) {
3696 		WL_ERR(("Beacon params set failed \n"));
3697 		goto fail;
3698 	}
3699 
3700 	/* Parse IEs */
3701 	if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies)) < 0) {
3702 		WL_ERR(("Set IEs failed \n"));
3703 		goto fail;
3704 	}
3705 
3706 	if ((err = wl_cfg80211_bcn_validate_sec(dev, &ies,
3707 		dev_role, bssidx, info->privacy)) < 0)
3708 	{
3709 		WL_ERR(("Beacon set security failed \n"));
3710 		goto fail;
3711 	}
3712 
3713 	if ((err = wl_cfg80211_bcn_bringup_ap(dev, &ies,
3714 		dev_role, bssidx)) < 0) {
3715 		WL_ERR(("Beacon bring up AP/GO failed \n"));
3716 		goto fail;
3717 	}
3718 
3719 	/* Set GC/STA SCB expiry timings. */
3720 	if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
3721 		WL_ERR(("scb setting failed \n"));
3722 //		goto fail;
3723 	}
3724 
3725 	wl_set_drv_status(cfg, CONNECTED, dev);
3726 	WL_DBG(("** AP/GO Created **\n"));
3727 
3728 #ifdef WL_CFG80211_ACL
3729 	/* Enfoce Admission Control. */
3730 	if ((err = wl_cfg80211_set_mac_acl(wiphy, dev, info->acl)) < 0) {
3731 		WL_ERR(("Set ACL failed\n"));
3732 	}
3733 #endif /* WL_CFG80211_ACL */
3734 
3735 	/* Set IEs to FW */
3736 	if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx)) < 0)
3737 		WL_ERR(("Set IEs failed \n"));
3738 
3739 #ifdef WLDWDS
3740 	if (dev->ieee80211_ptr->use_4addr) {
3741 		if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
3742 				VNDR_IE_ASSOCRSP_FLAG, (const u8 *)info->beacon.assocresp_ies,
3743 				info->beacon.assocresp_ies_len)) < 0) {
3744 			WL_ERR(("Set ASSOC RESP IE Failed\n"));
3745 		}
3746 	}
3747 #endif /* WLDWDS */
3748 
3749 	/* Enable Probe Req filter, WPS-AP certification 4.2.13 */
3750 	if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
3751 		bool pbc = 0;
3752 		wl_validate_wps_ie((const char *) ies.wps_ie, ies.wps_ie_len, &pbc);
3753 		if (pbc) {
3754 			WL_DBG(("set WLC_E_PROBREQ_MSG\n"));
3755 			wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
3756 		}
3757 	}
3758 
3759 	/* Configure hidden SSID */
3760 	if (info->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE) {
3761 		if ((err = wldev_iovar_setint(dev, "closednet", 1)) < 0)
3762 			WL_ERR(("failed to set hidden : %d\n", err));
3763 		WL_DBG(("hidden_ssid_enum_val: %d \n", info->hidden_ssid));
3764 	}
3765 
3766 #ifdef SUPPORT_AP_RADIO_PWRSAVE
3767 	if (dev_role == NL80211_IFTYPE_AP) {
3768 		if (!wl_set_ap_rps(dev, FALSE, dev->name)) {
3769 			wl_cfg80211_init_ap_rps(cfg);
3770 		} else {
3771 			WL_ERR(("Set rpsnoa failed \n"));
3772 		}
3773 	}
3774 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
3775 #ifdef WL_EXT_IAPSTA
3776 		wl_ext_in4way_sync(dev, 0, WL_EXT_STATUS_AP_ENABLING, NULL);
3777 #endif
3778 fail:
3779 	if (err) {
3780 		WL_ERR(("ADD/SET beacon failed\n"));
3781 		wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
3782 		wl_cfg80211_stop_ap(wiphy, dev);
3783 		if (dev_role == NL80211_IFTYPE_AP) {
3784 #ifdef WL_EXT_IAPSTA
3785 		if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
3786 #endif /* WL_EXT_IAPSTA */
3787 #ifdef BCMDONGLEHOST
3788 			dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
3789 #ifdef PKT_FILTER_SUPPORT
3790 			/* Enable packet filter */
3791 			if (dhd->early_suspended) {
3792 				WL_ERR(("Enable pkt_filter\n"));
3793 				dhd_enable_packet_filter(1, dhd);
3794 #ifdef APF
3795 				dhd_dev_apf_enable_filter(dhd_linux_get_primary_netdev(dhd));
3796 #endif /* APF */
3797 			}
3798 #endif /* PKT_FILTER_SUPPORT */
3799 #ifdef DISABLE_WL_FRAMEBURST_SOFTAP
3800 			wl_cfg80211_set_frameburst(cfg, TRUE);
3801 #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
3802 #endif /* BCMDONGLEHOST */
3803 			wl_wlfc_enable(cfg, FALSE);
3804 #ifdef WL_EXT_IAPSTA
3805 		}
3806 #endif /* WL_EXT_IAPSTA */
3807 		}
3808 #ifdef WLTDLS
3809 		if (bssidx == 0) {
3810 			/* Since AP creation failed, re-enable TDLS */
3811 			wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_DELETE, false);
3812 		}
3813 #endif /*  WLTDLS */
3814 
3815 	}
3816 
3817 	return err;
3818 }
3819 
3820 s32
wl_cfg80211_stop_ap(struct wiphy * wiphy,struct net_device * dev)3821 wl_cfg80211_stop_ap(
3822 	struct wiphy *wiphy,
3823 	struct net_device *dev)
3824 {
3825 	int err = 0;
3826 	u32 dev_role = 0;
3827 	int ap = 0;
3828 	s32 bssidx = 0;
3829 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3830 	s32 is_rsdb_supported = BCME_ERROR;
3831 #ifdef BCMDONGLEHOST
3832 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
3833 #endif /* BCMDONGLEHOST */
3834 
3835 	WL_DBG(("Enter \n"));
3836 
3837 	if (wl_cfg80211_get_bus_state(cfg)) {
3838 		/* since bus is down, iovar will fail. recovery path will bringup the bus. */
3839 		WL_ERR(("bus is not ready\n"));
3840 		return BCME_OK;
3841 	}
3842 #if defined (BCMDONGLEHOST)
3843 	is_rsdb_supported = DHD_OPMODE_SUPPORTED(cfg->pub, DHD_FLAG_RSDB_MODE);
3844 	if (is_rsdb_supported < 0)
3845 		return (-ENODEV);
3846 #endif
3847 
3848 	wl_clr_drv_status(cfg, AP_CREATING, dev);
3849 	wl_clr_drv_status(cfg, AP_CREATED, dev);
3850 	cfg->ap_oper_channel = INVCHANSPEC;
3851 
3852 	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
3853 		dev_role = NL80211_IFTYPE_AP;
3854 		WL_MSG(dev->name, "stopping AP operation\n");
3855 	} else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
3856 		dev_role = NL80211_IFTYPE_P2P_GO;
3857 		WL_MSG(dev->name, "stopping P2P GO operation\n");
3858 	} else {
3859 		WL_ERR(("no AP/P2P GO interface is operational.\n"));
3860 		return -EINVAL;
3861 	}
3862 
3863 	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
3864 		WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
3865 		return BCME_ERROR;
3866 	}
3867 
3868 	if (!check_dev_role_integrity(cfg, dev_role)) {
3869 		WL_ERR(("role integrity check failed \n"));
3870 		err = -EINVAL;
3871 		goto exit;
3872 	}
3873 #ifdef WL_EXT_IAPSTA
3874 	wl_ext_in4way_sync(dev, 0, WL_EXT_STATUS_AP_DISABLING, NULL);
3875 #endif
3876 
3877 	/* Free up resources */
3878 	wl_cfg80211_cleanup_if(dev);
3879 
3880 	/* Clear AP/GO connected status */
3881 	wl_clr_drv_status(cfg, CONNECTED, dev);
3882 	if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 0)) < 0) {
3883 		WL_ERR(("bss down error %d\n", err));
3884 	}
3885 
3886 	if (dev_role == NL80211_IFTYPE_AP) {
3887 #ifdef BCMDONGLEHOST
3888 #ifdef DISABLE_WL_FRAMEBURST_SOFTAP
3889 		wl_cfg80211_set_frameburst(cfg, TRUE);
3890 #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
3891 #endif /* BCMDONGLEHOST */
3892 #ifdef PKT_FILTER_SUPPORT
3893 		/* Enable packet filter */
3894 		if (dhd->early_suspended) {
3895 			WL_ERR(("Enable pkt_filter\n"));
3896 			dhd_enable_packet_filter(1, dhd);
3897 #ifdef APF
3898 			dhd_dev_apf_enable_filter(dhd_linux_get_primary_netdev(dhd));
3899 #endif /* APF */
3900 		}
3901 #endif /* PKT_FILTER_SUPPORT */
3902 
3903 		if (is_rsdb_supported == 0) {
3904 			/* For non-rsdb chips, we use stand alone AP. Do wl down on stop AP */
3905 			err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
3906 			if (unlikely(err)) {
3907 				WL_ERR(("WLC_UP error (%d)\n", err));
3908 				err = -EINVAL;
3909 				goto exit;
3910 			}
3911 		}
3912 
3913 #ifdef WL_DISABLE_HE_SOFTAP
3914 		if (wl_cfg80211_set_he_mode(dev, cfg, bssidx, WL_HE_FEATURES_HE_AP,
3915 			TRUE) != BCME_OK) {
3916 			WL_ERR(("failed to set he features\n"));
3917 		}
3918 #endif /* WL_DISABLE_HE_SOFTAP */
3919 
3920 		wl_cfg80211_clear_per_bss_ies(cfg, dev->ieee80211_ptr);
3921 #ifdef SUPPORT_AP_RADIO_PWRSAVE
3922 		if (!wl_set_ap_rps(dev, FALSE, dev->name)) {
3923 			wl_cfg80211_init_ap_rps(cfg);
3924 		} else {
3925 			WL_ERR(("Set rpsnoa failed \n"));
3926 		}
3927 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
3928 	} else {
3929 		/* Do we need to do something here */
3930 		WL_DBG(("Stopping P2P GO \n"));
3931 
3932 #if defined(BCMDONGLEHOST) && defined(OEM_ANDROID)
3933 		DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE((dhd_pub_t *)(cfg->pub),
3934 			DHD_EVENT_TIMEOUT_MS*3);
3935 		DHD_OS_WAKE_LOCK_TIMEOUT((dhd_pub_t *)(cfg->pub));
3936 #endif
3937 
3938 	}
3939 
3940 	SUPP_LOG(("AP/GO Link down\n"));
3941 exit:
3942 	if (err) {
3943 		/* In case of failure, flush fw logs */
3944 		wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
3945 		SUPP_LOG(("AP/GO Link down fail. err:%d\n", err));
3946 	}
3947 #ifdef WLTDLS
3948 	if (bssidx == 0) {
3949 		/* re-enable TDLS if the number of connected interfaces is less than 2 */
3950 		wl_cfg80211_tdls_config(cfg, TDLS_STATE_AP_DELETE, false);
3951 	}
3952 #endif /* WLTDLS */
3953 
3954 #ifdef BCMDONGLEHOST
3955 	if (dev_role == NL80211_IFTYPE_AP) {
3956 #ifdef WL_EXT_IAPSTA
3957 		if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
3958 #endif /* WL_EXT_IAPSTA */
3959 		/* clear the AP mode */
3960 		dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
3961 		wl_wlfc_enable(cfg, FALSE);
3962 #ifdef WL_EXT_IAPSTA
3963 		}
3964 #endif /* WL_EXT_IAPSTA */
3965 	}
3966 #endif /* BCMDONGLEHOST */
3967 	return err;
3968 }
3969 
3970 s32
wl_cfg80211_change_beacon(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_beacon_data * info)3971 wl_cfg80211_change_beacon(
3972 	struct wiphy *wiphy,
3973 	struct net_device *dev,
3974 	struct cfg80211_beacon_data *info)
3975 {
3976 	s32 err = BCME_OK;
3977 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
3978 	struct parsed_ies ies;
3979 	u32 dev_role = 0;
3980 	s32 bssidx = 0;
3981 	bool pbc = 0;
3982 
3983 	WL_DBG(("Enter \n"));
3984 
3985 	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
3986 		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
3987 		return BCME_ERROR;
3988 	}
3989 
3990 	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
3991 		dev_role = NL80211_IFTYPE_P2P_GO;
3992 	} else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
3993 		dev_role = NL80211_IFTYPE_AP;
3994 	} else {
3995 		err = -EINVAL;
3996 		goto fail;
3997 	}
3998 
3999 	if (!check_dev_role_integrity(cfg, dev_role)) {
4000 		err = -EINVAL;
4001 		goto fail;
4002 	}
4003 
4004 	if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
4005 		WL_ERR(("P2P already down status!\n"));
4006 		err = BCME_ERROR;
4007 		goto fail;
4008 	}
4009 
4010 	/* Parse IEs */
4011 	if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies)) < 0) {
4012 		WL_ERR(("Parse IEs failed \n"));
4013 		goto fail;
4014 	}
4015 
4016 	/* Set IEs to FW */
4017 	if ((err = wl_cfg80211_set_ies(dev, info, bssidx)) < 0) {
4018 		WL_ERR(("Set IEs failed \n"));
4019 		goto fail;
4020 	}
4021 
4022 	if (dev_role == NL80211_IFTYPE_AP) {
4023 		if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
4024 			WL_ERR(("Hostapd update sec failed \n"));
4025 			err = -EINVAL;
4026 			goto fail;
4027 		}
4028 		/* Enable Probe Req filter, WPS-AP certification 4.2.13 */
4029 		if ((dev_role == NL80211_IFTYPE_AP) && (ies.wps_ie != NULL)) {
4030 			wl_validate_wps_ie((const char *) ies.wps_ie, ies.wps_ie_len, &pbc);
4031 			WL_DBG((" WPS AP, wps_ie is exists pbc=%d\n", pbc));
4032 			if (pbc)
4033 				wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
4034 			else
4035 				wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
4036 		}
4037 	}
4038 
4039 fail:
4040 	if (err) {
4041 		wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
4042 	}
4043 	return err;
4044 }
4045 #else
4046 s32
wl_cfg80211_add_set_beacon(struct wiphy * wiphy,struct net_device * dev,struct beacon_parameters * info)4047 wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
4048 	struct beacon_parameters *info)
4049 {
4050 	s32 err = BCME_OK;
4051 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4052 	s32 ie_offset = 0;
4053 	s32 bssidx = 0;
4054 	u32 dev_role = NL80211_IFTYPE_AP;
4055 	struct parsed_ies ies;
4056 	bcm_tlv_t *ssid_ie;
4057 	bool pbc = 0;
4058 	bool privacy;
4059 	bool is_bss_up = 0;
4060 #ifdef BCMDONGLEHOST
4061 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
4062 #endif /* BCMDONGLEHOST */
4063 
4064 	WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
4065 		info->interval, info->dtim_period, info->head_len, info->tail_len));
4066 
4067 	if (dev == bcmcfg_to_prmry_ndev(cfg)) {
4068 		dev_role = NL80211_IFTYPE_AP;
4069 	}
4070 #if defined(WL_ENABLE_P2P_IF)
4071 	else if (dev == cfg->p2p_net) {
4072 		/* Group Add request on p2p0 */
4073 		dev = bcmcfg_to_prmry_ndev(cfg);
4074 		dev_role = NL80211_IFTYPE_P2P_GO;
4075 	}
4076 #endif /* WL_ENABLE_P2P_IF */
4077 
4078 	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4079 		WL_ERR(("Find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4080 		return BCME_ERROR;
4081 	}
4082 
4083 	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO) {
4084 		dev_role = NL80211_IFTYPE_P2P_GO;
4085 	} else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
4086 #ifdef BCMDONGLEHOST
4087 		dhd->op_mode |= DHD_FLAG_HOSTAP_MODE;
4088 #endif
4089 	}
4090 
4091 	if (!check_dev_role_integrity(cfg, dev_role)) {
4092 		err = -ENODEV;
4093 		goto fail;
4094 	}
4095 
4096 	if ((dev_role == NL80211_IFTYPE_P2P_GO) && (cfg->p2p_wdev == NULL)) {
4097 		WL_ERR(("P2P already down status!\n"));
4098 		err = BCME_ERROR;
4099 		goto fail;
4100 	}
4101 
4102 	ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
4103 	/* find the SSID */
4104 	if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
4105 		info->head_len - ie_offset,
4106 		DOT11_MNG_SSID_ID)) != NULL) {
4107 		if (dev_role == NL80211_IFTYPE_AP) {
4108 			/* Store the hostapd SSID */
4109 			bzero(&cfg->hostapd_ssid.SSID[0], DOT11_MAX_SSID_LEN);
4110 			cfg->hostapd_ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
4111 			memcpy(&cfg->hostapd_ssid.SSID[0], ssid_ie->data,
4112 				cfg->hostapd_ssid.SSID_len);
4113 		} else {
4114 			/* P2P GO */
4115 			bzero(&cfg->p2p->ssid.SSID[0], DOT11_MAX_SSID_LEN);
4116 			cfg->p2p->ssid.SSID_len = MIN(ssid_ie->len, DOT11_MAX_SSID_LEN);
4117 			memcpy(cfg->p2p->ssid.SSID, ssid_ie->data,
4118 				cfg->p2p->ssid.SSID_len);
4119 		}
4120 	}
4121 
4122 	if (wl_cfg80211_parse_ies((u8 *)info->tail,
4123 		info->tail_len, &ies) < 0) {
4124 		WL_ERR(("Beacon get IEs failed \n"));
4125 		err = -EINVAL;
4126 		goto fail;
4127 	}
4128 
4129 	if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
4130 		VNDR_IE_BEACON_FLAG, (u8 *)info->tail,
4131 		info->tail_len)) < 0) {
4132 		WL_ERR(("Beacon set IEs failed \n"));
4133 		goto fail;
4134 	} else {
4135 		WL_DBG(("Applied Vndr IEs for Beacon \n"));
4136 	}
4137 
4138 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
4139 	if ((err = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev), bssidx,
4140 		VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies,
4141 		info->proberesp_ies_len)) < 0) {
4142 		WL_ERR(("ProbeRsp set IEs failed \n"));
4143 		goto fail;
4144 	} else {
4145 		WL_DBG(("Applied Vndr IEs for ProbeRsp \n"));
4146 	}
4147 #endif
4148 
4149 	is_bss_up = wl_cfg80211_bss_isup(dev, bssidx);
4150 
4151 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
4152 	privacy = info->privacy;
4153 #else
4154 	privacy = 0;
4155 #endif
4156 	if (!is_bss_up &&
4157 		(wl_cfg80211_bcn_validate_sec(dev, &ies, dev_role, bssidx, privacy) < 0))
4158 	{
4159 		WL_ERR(("Beacon set security failed \n"));
4160 		err = -EINVAL;
4161 		goto fail;
4162 	}
4163 
4164 	/* Set BI and DTIM period */
4165 	if (info->interval) {
4166 		if ((err = wldev_ioctl_set(dev, WLC_SET_BCNPRD,
4167 			&info->interval, sizeof(s32))) < 0) {
4168 			WL_ERR(("Beacon Interval Set Error, %d\n", err));
4169 			return err;
4170 		}
4171 	}
4172 	if (info->dtim_period) {
4173 		if ((err = wldev_ioctl_set(dev, WLC_SET_DTIMPRD,
4174 			&info->dtim_period, sizeof(s32))) < 0) {
4175 			WL_ERR(("DTIM Interval Set Error, %d\n", err));
4176 			return err;
4177 		}
4178 	}
4179 
4180 	/* If bss is already up, skip bring up */
4181 	if (!is_bss_up &&
4182 		(err = wl_cfg80211_bcn_bringup_ap(dev, &ies, dev_role, bssidx)) < 0)
4183 	{
4184 		WL_ERR(("Beacon bring up AP/GO failed \n"));
4185 		goto fail;
4186 	}
4187 
4188 	/* Set GC/STA SCB expiry timings. */
4189 	if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
4190 		WL_ERR(("scb setting failed \n"));
4191 		if (err == BCME_UNSUPPORTED)
4192 			err = 0;
4193 //		goto fail;
4194 	}
4195 
4196 	if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
4197 		/* Soft AP already running. Update changed params */
4198 		if (wl_cfg80211_hostapd_sec(dev, &ies, bssidx) < 0) {
4199 			WL_ERR(("Hostapd update sec failed \n"));
4200 			err = -EINVAL;
4201 			goto fail;
4202 		}
4203 	}
4204 
4205 	/* Enable Probe Req filter */
4206 	if (((dev_role == NL80211_IFTYPE_P2P_GO) ||
4207 		(dev_role == NL80211_IFTYPE_AP)) && (ies.wps_ie != NULL)) {
4208 		wl_validate_wps_ie((char *) ies.wps_ie, ies.wps_ie_len, &pbc);
4209 		if (pbc)
4210 			wl_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
4211 	}
4212 
4213 	WL_DBG(("** ADD/SET beacon done **\n"));
4214 	wl_set_drv_status(cfg, CONNECTED, dev);
4215 
4216 fail:
4217 	if (err) {
4218 		WL_ERR(("ADD/SET beacon failed\n"));
4219 #ifdef BCMDONGLEHOST
4220 		if (dev_role == NL80211_IFTYPE_AP) {
4221 #ifdef WL_EXT_IAPSTA
4222 		if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
4223 #endif /* WL_EXT_IAPSTA */
4224 			/* clear the AP mode */
4225 			dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
4226 #ifdef WL_EXT_IAPSTA
4227 		}
4228 #endif /* WL_EXT_IAPSTA */
4229 		}
4230 #endif /* BCMDONGLEHOST */
4231 	}
4232 	return err;
4233 
4234 }
4235 
4236 s32
wl_cfg80211_del_beacon(struct wiphy * wiphy,struct net_device * dev)4237 wl_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
4238 {
4239 	int err = 0;
4240 	s32 bssidx = 0;
4241 	int infra = 0;
4242 	struct wireless_dev *wdev = dev->ieee80211_ptr;
4243 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
4244 #ifdef BCMDONGLEHOST
4245 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
4246 #endif /* BCMDONGLEHOST */
4247 
4248 	WL_DBG(("Enter. \n"));
4249 
4250 	if (!wdev) {
4251 		WL_ERR(("wdev null \n"));
4252 		return -EINVAL;
4253 	}
4254 
4255 	if ((wdev->iftype != NL80211_IFTYPE_P2P_GO) && (wdev->iftype != NL80211_IFTYPE_AP)) {
4256 		WL_ERR(("Unspported iface type iftype:%d \n", wdev->iftype));
4257 	}
4258 
4259 	wl_clr_drv_status(cfg, AP_CREATING, dev);
4260 	wl_clr_drv_status(cfg, AP_CREATED, dev);
4261 
4262 	/* Clear AP/GO connected status */
4263 	wl_clr_drv_status(cfg, CONNECTED, dev);
4264 
4265 	cfg->ap_oper_channel = INVCHANSPEC;
4266 
4267 	if ((bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr)) < 0) {
4268 		WL_ERR(("find p2p index from wdev(%p) failed\n", dev->ieee80211_ptr));
4269 		return BCME_ERROR;
4270 	}
4271 
4272 	/* Do bss down */
4273 	if ((err = wl_cfg80211_bss_up(cfg, dev, bssidx, 0)) < 0) {
4274 		WL_ERR(("bss down error %d\n", err));
4275 	}
4276 
4277 	/* fall through is intentional */
4278 	err = wldev_ioctl_set(dev, WLC_SET_INFRA, &infra, sizeof(s32));
4279 	if (err < 0) {
4280 		WL_ERR(("SET INFRA error %d\n", err));
4281 	}
4282 	 wl_cfg80211_clear_per_bss_ies(cfg, dev->ieee80211_ptr);
4283 
4284 #ifdef BCMDONGLEHOST
4285 	if (wdev->iftype == NL80211_IFTYPE_AP) {
4286 #ifdef WL_EXT_IAPSTA
4287 		if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
4288 #endif /* WL_EXT_IAPSTA */
4289 		/* clear the AP mode */
4290 		dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
4291 #ifdef WL_EXT_IAPSTA
4292 		}
4293 #endif /* WL_EXT_IAPSTA */
4294 	}
4295 #endif /* BCMDONGLEHOST */
4296 
4297 	return 0;
4298 }
4299 #endif /* LINUX_VERSION < VERSION(3,4,0) || WL_COMPAT_WIRELESS */
4300 
4301 s32
wl_get_auth_assoc_status(struct bcm_cfg80211 * cfg,struct net_device * ndev,const wl_event_msg_t * e,void * data)4302 wl_get_auth_assoc_status(struct bcm_cfg80211 *cfg, struct net_device *ndev,
4303 	const wl_event_msg_t *e, void *data)
4304 {
4305 	u32 reason = ntoh32(e->reason);
4306 	u32 event = ntoh32(e->event_type);
4307 	struct wl_security *sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
4308 
4309 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
4310 	(void)memcpy_s(&cfg->event_auth_assoc, sizeof(wl_event_msg_t),
4311 		e, sizeof(wl_event_msg_t));
4312 	WL_DBG(("event=%d status %d reason %d \n",
4313 		ntoh32(cfg->event_auth_assoc.event_type),
4314 		ntoh32(cfg->event_auth_assoc.status),
4315 		ntoh32(cfg->event_auth_assoc.reason)));
4316 #endif /* DHD_ENABLE_BIGDATA_LOGGING */
4317 	if (sec) {
4318 		switch (event) {
4319 		case WLC_E_ASSOC:
4320 		case WLC_E_AUTH:
4321 		case WLC_E_AUTH_IND:
4322 			sec->auth_assoc_res_status = reason;
4323 			break;
4324 		default:
4325 			break;
4326 		}
4327 	} else {
4328 		WL_ERR(("sec is NULL\n"));
4329 	}
4330 	return 0;
4331 }
4332 
4333 /* The mainline kernel >= 3.2.0 has support for indicating new/del station
4334  * to AP/P2P GO via events. If this change is backported to kernel for which
4335  * this driver is being built, then define WL_CFG80211_STA_EVENT. You
4336  * should use this new/del sta event mechanism for BRCM supplicant >= 22.
4337  */
4338 #if !defined(WL_CFG80211_STA_EVENT) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
4339 static s32
wl_notify_connect_status_ap_legacy(struct bcm_cfg80211 * cfg,struct net_device * ndev const wl_event_msg_t * e,void * data)4340 wl_notify_connect_status_ap_legacy(struct bcm_cfg80211 *cfg, struct net_device *ndev
4341 	const wl_event_msg_t *e, void *data)
4342 {
4343 	s32 err = 0;
4344 	u32 event = ntoh32(e->event_type);
4345 	u32 reason = ntoh32(e->reason);
4346 	u32 len = ntoh32(e->datalen);
4347 	u32 status = ntoh32(e->status);
4348 
4349 	bool isfree = false;
4350 	u8 *mgmt_frame;
4351 	u8 bsscfgidx = e->bsscfgidx;
4352 	s32 freq;
4353 	s32 channel;
4354 	u8 *body = NULL;
4355 	u16 fc = 0;
4356 	u32 body_len = 0;
4357 
4358 	struct ieee80211_supported_band *band;
4359 	struct ether_addr da;
4360 	struct ether_addr bssid;
4361 	struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
4362 	channel_info_t ci;
4363 	u8 ioctl_buf[WLC_IOCTL_SMLEN];
4364 
4365 	WL_DBG(("Enter \n"));
4366 	if (!len && (event == WLC_E_DEAUTH)) {
4367 		len = 2; /* reason code field */
4368 		data = &reason;
4369 	}
4370 	if (len) {
4371 		body = (u8 *)MALLOCZ(cfg->osh, len);
4372 		if (body == NULL) {
4373 			WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
4374 			return WL_INVALID;
4375 		}
4376 	}
4377 	bzero(&bssid, ETHER_ADDR_LEN);
4378 	WL_DBG(("Enter event %d ndev %p\n", event, ndev));
4379 	if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
4380 		MFREE(cfg->osh, body, len);
4381 		return WL_INVALID;
4382 	}
4383 	if (len)
4384 		memcpy(body, data, len);
4385 
4386 	wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
4387 		NULL, 0, ioctl_buf, sizeof(ioctl_buf), bsscfgidx, NULL);
4388 	memcpy(da.octet, ioctl_buf, ETHER_ADDR_LEN);
4389 	bzero(&bssid, sizeof(bssid));
4390 	err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
4391 	switch (event) {
4392 		case WLC_E_ASSOC_IND:
4393 			fc = FC_ASSOC_REQ;
4394 			break;
4395 		case WLC_E_REASSOC_IND:
4396 			fc = FC_REASSOC_REQ;
4397 			break;
4398 		case WLC_E_DISASSOC_IND:
4399 			fc = FC_DISASSOC;
4400 			break;
4401 		case WLC_E_DEAUTH_IND:
4402 			fc = FC_DISASSOC;
4403 			break;
4404 		case WLC_E_DEAUTH:
4405 			fc = FC_DISASSOC;
4406 			break;
4407 		default:
4408 			fc = 0;
4409 			goto exit;
4410 	}
4411 	err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
4412 	if (unlikely(err)) {
4413 		MFREE(cfg->osh, body, len);
4414 		WL_ERR(("%s: Could not get chanspec %d\n", __FUNCTION__, err));
4415 		return err;
4416 	}
4417 	chanspec = wl_chspec_driver_to_host(chanspec);
4418 	freq = wl_channel_to_frequency(wf_chspec_ctlchan(chanspec), CHSPEC_BAND(chanspec));
4419 	body_len = len;
4420 	err = wl_frame_get_mgmt(cfg, fc, &da, &e->addr, &bssid,
4421 		&mgmt_frame, &len, body);
4422 	if (err < 0)
4423 		goto exit;
4424 	isfree = true;
4425 
4426 	if ((event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) ||
4427 			(event == WLC_E_DISASSOC_IND) ||
4428 			((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH))) {
4429 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
4430 		cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0);
4431 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
4432 		cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0, GFP_ATOMIC);
4433 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
4434 		defined(WL_COMPAT_WIRELESS)
4435 		cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
4436 #else
4437 		cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
4438 #endif /* LINUX_VERSION >= VERSION(3, 18,0) || WL_COMPAT_WIRELESS */
4439 	}
4440 
4441 exit:
4442 	if (isfree) {
4443 		MFREE(cfg->osh, mgmt_frame, len);
4444 	}
4445 	if (body) {
4446 		MFREE(cfg->osh, body, body_len);
4447 	}
4448 
4449 }
4450 #endif /* WL_CFG80211_STA_EVENT || KERNEL_VER < 3.2 */
4451 
4452 s32
wl_notify_connect_status_ap(struct bcm_cfg80211 * cfg,struct net_device * ndev,const wl_event_msg_t * e,void * data)4453 wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
4454 	const wl_event_msg_t *e, void *data)
4455 {
4456 	s32 err = 0;
4457 	u32 event = ntoh32(e->event_type);
4458 	u32 reason = ntoh32(e->reason);
4459 	u32 len = ntoh32(e->datalen);
4460 	u32 status = ntoh32(e->status);
4461 #if defined(WL_CFG80211_STA_EVENT) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0))
4462 	struct station_info sinfo;
4463 #endif /* (LINUX_VERSION >= VERSION(3,2,0)) || !WL_CFG80211_STA_EVENT */
4464 #ifdef BIGDATA_SOFTAP
4465 	dhd_pub_t *dhdp;
4466 #endif /* BIGDATA_SOFTAP */
4467 
4468 	WL_INFORM_MEM(("[%s] Mode AP/GO. Event:%d status:%d reason:%d\n",
4469 		ndev->name, event, ntoh32(e->status), reason));
4470 
4471 #ifdef WL_CLIENT_SAE
4472 	if (event == WLC_E_AUTH && ntoh32(e->auth_type) == DOT11_SAE) {
4473 		WL_MSG_RLMT(ndev->name, &e->addr, ETHER_ADDR_LEN,
4474 			"add sta auth event for "MACDBG "\n", MAC2STRDBG(e->addr.octet));
4475 		err = wl_handle_auth_event(cfg, ndev, e, data);
4476 		if (err != BCME_OK) {
4477 			return err;
4478 		}
4479 	}
4480 #endif /* WL_CLIENT_SAE */
4481 
4482 	if (event == WLC_E_AUTH_IND) {
4483 #ifdef WL_SAE
4484 		if (ntoh32(e->auth_type) == DOT11_SAE) {
4485 			wl_bss_handle_sae_auth(cfg, ndev, e, data);
4486 		}
4487 #endif /* WL_SAE */
4488 		wl_get_auth_assoc_status(cfg, ndev, e, data);
4489 		return 0;
4490 	}
4491 	/* if link down, bsscfg is disabled. */
4492 	if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
4493 		wl_get_p2p_status(cfg, IF_DELETING) && (ndev != bcmcfg_to_prmry_ndev(cfg))) {
4494 		wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false);
4495 		WL_MSG(ndev->name, "AP mode link down !! \n");
4496 		complete(&cfg->iface_disable);
4497 #ifdef WL_EXT_IAPSTA
4498 		wl_ext_in4way_sync(ndev, 0, WL_EXT_STATUS_AP_DISABLED, NULL);
4499 #endif
4500 		return 0;
4501 	}
4502 
4503 	if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
4504 		(reason == WLC_E_REASON_INITIAL_ASSOC) &&
4505 		(wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP)) {
4506 		if (!wl_get_drv_status(cfg, AP_CREATED, ndev)) {
4507 			/* AP/GO brought up successfull in firmware */
4508 			WL_MSG(ndev->name, "AP/GO Link up\n");
4509 			wl_set_drv_status(cfg, AP_CREATED, ndev);
4510 			if (delayed_work_pending(&cfg->ap_work)) {
4511 				cancel_delayed_work_sync(&cfg->ap_work);
4512 				WL_DBG(("cancelled ap_work\n"));
4513 			}
4514 #ifdef BIGDATA_SOFTAP
4515 			wl_ap_stainfo_init(cfg);
4516 #endif /* BIGDATA_SOFTAP */
4517 #ifdef WL_EXT_IAPSTA
4518 			wl_ext_in4way_sync(ndev, 0, WL_EXT_STATUS_AP_ENABLED, NULL);
4519 #endif
4520 			return 0;
4521 		}
4522 	}
4523 
4524 	if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
4525 		WL_MSG_RLMT(ndev->name, &e->addr, ETHER_ADDR_LEN,
4526 			"event %s(%d) status %d reason %d\n",
4527 			bcmevent_get_name(event), event, ntoh32(e->status), reason);
4528 	}
4529 
4530 #ifdef BIGDATA_SOFTAP
4531 	if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) {
4532 		WL_ERR(("AP link down - skip get sta data\n"));
4533 	} else {
4534 		dhdp = (dhd_pub_t *)(cfg->pub);
4535 		if (dhdp && dhdp->op_mode & DHD_FLAG_HOSTAP_MODE) {
4536 			dhd_schedule_gather_ap_stadata(cfg, ndev, e);
4537 		}
4538 	}
4539 #endif /* BIGDATA_SOFTAP */
4540 
4541 #if !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \
4542 	(LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
4543 	err = wl_notify_connect_status_ap_legacy(cfg, ndev, e, data);
4544 #else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
4545 	memset_s(&sinfo, sizeof(sinfo), 0, sizeof(sinfo));
4546 	if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
4547 		reason == DOT11_SC_SUCCESS) {
4548 		/* Linux ver >= 4.0 assoc_req_ies_len is used instead of
4549 		 * STATION_INFO_ASSOC_REQ_IES flag
4550 		 */
4551 #if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
4552 		sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
4553 #endif /*  (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
4554 		if (!data) {
4555 			WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
4556 			return -EINVAL;
4557 		}
4558 		sinfo.assoc_req_ies = data;
4559 		sinfo.assoc_req_ies_len = len;
4560 		WL_MSG(ndev->name, "new sta event for "MACDBG "\n",
4561 			MAC2STRDBG(e->addr.octet));
4562 #ifdef WL_EXT_IAPSTA
4563 		wl_ext_in4way_sync(ndev, AP_WAIT_STA_RECONNECT,
4564 			WL_EXT_STATUS_STA_CONNECTED, (void *)&e->addr);
4565 #endif
4566 #ifdef STA_MGMT
4567 		if (!wl_ext_add_sta_info(ndev, (u8 *)&e->addr)) {
4568 			return -EINVAL;
4569 		}
4570 #endif /* STA_MGMT */
4571 		cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
4572 #ifdef WL_WPS_SYNC
4573 		wl_wps_session_update(ndev, WPS_STATE_LINKUP, e->addr.octet);
4574 #endif /* WL_WPS_SYNC */
4575 	} else if ((event == WLC_E_DEAUTH_IND) ||
4576 		((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED)) ||
4577 		(event == WLC_E_DISASSOC_IND)) {
4578 		/*
4579 		 * WAR: Dongle sends WLC_E_DEAUTH event with DOT11_RC_RESERVED
4580 		 * to delete flowring in case of PCIE Full dongle.
4581 		 * By deleting flowring on SoftAP interface we can avoid any issues
4582 		 * due to stale/bad state of flowring.
4583 		 * Therefore, we don't need to notify the client dissaociation to Hostapd
4584 		 * in this case.
4585 		 * Please refer to the RB:115182 to understand the case more clearly.
4586 		 */
4587 		WL_MSG_RLMT(ndev->name, &e->addr, ETHER_ADDR_LEN,
4588 			"del sta event for "MACDBG "\n", MAC2STRDBG(e->addr.octet));
4589 #ifdef WL_EXT_IAPSTA
4590 		wl_ext_in4way_sync(ndev, AP_WAIT_STA_RECONNECT,
4591 			WL_EXT_STATUS_STA_DISCONNECTED, (void *)&e->addr);
4592 #endif
4593 #ifdef STA_MGMT
4594 		if (!wl_ext_del_sta_info(ndev, (u8 *)&e->addr)) {
4595 			return -EINVAL;
4596 		}
4597 #endif /* STA_MGMT */
4598 		cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
4599 #ifdef WL_WPS_SYNC
4600 		wl_wps_session_update(ndev, WPS_STATE_LINKDOWN, e->addr.octet);
4601 #endif /* WL_WPS_SYNC */
4602 	}
4603 
4604 #endif /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
4605 	return err;
4606 }
4607 
4608 s32
wl_frame_get_mgmt(struct bcm_cfg80211 * cfg,u16 fc,const struct ether_addr * da,const struct ether_addr * sa,const struct ether_addr * bssid,u8 ** pheader,u32 * body_len,u8 * pbody)4609 wl_frame_get_mgmt(struct bcm_cfg80211 *cfg, u16 fc,
4610 	const struct ether_addr *da, const struct ether_addr *sa,
4611 	const struct ether_addr *bssid, u8 **pheader, u32 *body_len, u8 *pbody)
4612 {
4613 	struct dot11_management_header *hdr;
4614 	u32 totlen = 0;
4615 	s32 err = 0;
4616 	u8 *offset;
4617 	u32 prebody_len = *body_len;
4618 	switch (fc) {
4619 		case FC_ASSOC_REQ:
4620 			/* capability , listen interval */
4621 			totlen = DOT11_ASSOC_REQ_FIXED_LEN;
4622 			*body_len += DOT11_ASSOC_REQ_FIXED_LEN;
4623 			break;
4624 
4625 		case FC_REASSOC_REQ:
4626 			/* capability, listen inteval, ap address */
4627 			totlen = DOT11_REASSOC_REQ_FIXED_LEN;
4628 			*body_len += DOT11_REASSOC_REQ_FIXED_LEN;
4629 			break;
4630 	}
4631 	totlen += DOT11_MGMT_HDR_LEN + prebody_len;
4632 	*pheader = (u8 *)MALLOCZ(cfg->osh, totlen);
4633 	if (*pheader == NULL) {
4634 		WL_ERR(("memory alloc failed \n"));
4635 		return -ENOMEM;
4636 	}
4637 	hdr = (struct dot11_management_header *) (*pheader);
4638 	hdr->fc = htol16(fc);
4639 	hdr->durid = 0;
4640 	hdr->seq = 0;
4641 	offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
4642 	bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
4643 	bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
4644 	bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
4645 	if ((pbody != NULL) && prebody_len)
4646 		bcopy((const char*)pbody, offset, prebody_len);
4647 	*body_len = totlen;
4648 	return err;
4649 }
4650 
4651 #if defined(WLTDLS)
wl_cfg80211_is_tdls_tunneled_frame(void * frame,u32 frame_len)4652 bool wl_cfg80211_is_tdls_tunneled_frame(void *frame, u32 frame_len)
4653 {
4654 	unsigned char *data;
4655 
4656 	if (frame == NULL) {
4657 		WL_ERR(("Invalid frame \n"));
4658 		return false;
4659 	}
4660 
4661 	if (frame_len < 5) {
4662 		WL_ERR(("Invalid frame length [%d] \n", frame_len));
4663 		return false;
4664 	}
4665 
4666 	data = frame;
4667 
4668 	if (!memcmp(data, TDLS_TUNNELED_PRB_REQ, 5) ||
4669 		!memcmp(data, TDLS_TUNNELED_PRB_RESP, 5)) {
4670 		WL_DBG(("TDLS Vendor Specific Received type\n"));
4671 		return true;
4672 	}
4673 
4674 	return false;
4675 }
4676 #endif /* WLTDLS */
4677 
4678 #ifdef WLTDLS
4679 s32
wl_tdls_event_handler(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)4680 wl_tdls_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
4681 	const wl_event_msg_t *e, void *data) {
4682 
4683 	struct net_device *ndev = NULL;
4684 	u32 reason = ntoh32(e->reason);
4685 	s8 *msg = NULL;
4686 
4687 	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
4688 
4689 	switch (reason) {
4690 	case WLC_E_TDLS_PEER_DISCOVERED :
4691 		msg = " TDLS PEER DISCOVERD ";
4692 		break;
4693 	case WLC_E_TDLS_PEER_CONNECTED :
4694 		if (cfg->tdls_mgmt_frame) {
4695 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
4696 			cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
4697 					cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, 0);
4698 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
4699 			cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
4700 					cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,	0,
4701 					GFP_ATOMIC);
4702 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
4703 			defined(WL_COMPAT_WIRELESS)
4704 			cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq, 0,
4705 					cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len,
4706 					GFP_ATOMIC);
4707 #else
4708 			cfg80211_rx_mgmt(cfgdev, cfg->tdls_mgmt_freq,
4709 					cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len, GFP_ATOMIC);
4710 
4711 #endif /* LINUX_VERSION >= VERSION(3, 18,0) || WL_COMPAT_WIRELESS */
4712 		}
4713 		msg = " TDLS PEER CONNECTED ";
4714 #ifdef SUPPORT_SET_CAC
4715 		/* TDLS connect reset CAC */
4716 		wl_cfg80211_set_cac(cfg, 0);
4717 #endif /* SUPPORT_SET_CAC */
4718 		break;
4719 	case WLC_E_TDLS_PEER_DISCONNECTED :
4720 		if (cfg->tdls_mgmt_frame) {
4721 			MFREE(cfg->osh, cfg->tdls_mgmt_frame, cfg->tdls_mgmt_frame_len);
4722 			cfg->tdls_mgmt_frame_len = 0;
4723 			cfg->tdls_mgmt_freq = 0;
4724 		}
4725 		msg = "TDLS PEER DISCONNECTED ";
4726 #ifdef SUPPORT_SET_CAC
4727 		/* TDLS disconnec, set CAC */
4728 		wl_cfg80211_set_cac(cfg, 1);
4729 #endif /* SUPPORT_SET_CAC */
4730 		break;
4731 	}
4732 	if (msg) {
4733 		WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((const u8*)(&e->addr)),
4734 			(bcmcfg_to_prmry_ndev(cfg) == ndev) ? "primary" : "secondary"));
4735 	}
4736 	return 0;
4737 
4738 }
4739 
4740 #if defined(CUSTOMER_HW10)
wl_tdls_enable(struct bcm_cfg80211 * cfg)4741 static void wl_tdls_enable(struct bcm_cfg80211 *cfg)
4742 {
4743 	int enable = true;
4744 	int err = 0;
4745 	struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
4746 	dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
4747 
4748 /* #define IS_P2P_OPERATING (p2p_is_on(cfg) && cfg->p2p->vif_created ) */
4749 #define IS_P2P_OPERATING (dhd->op_mode & (DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE))
4750 #if !defined(DISABLE_TDLS_IN_P2P)
4751 	if (cfg->vsdb_mode)
4752 #else
4753 	if (cfg->vsdb_mode || IS_P2P_OPERATING)
4754 #endif
4755 	{
4756 		enable = false;
4757 	}
4758 
4759 	err = wldev_iovar_setint(primary_dev, "tdls_enable", enable);
4760 	if (err) {
4761 		WL_ERR(("tdls_enable failed!!: %d\n", enable));
4762 	}
4763 #undef IS_P2P_OPERATING
4764 }
4765 #endif  /* defined(CUSTOMER_HW10) */
4766 
4767 #endif  /* WLTDLS */
4768 
4769 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || \
4770 	defined(WL_COMPAT_WIRELESS)
4771 s32
4772 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || \
4773 	((LINUX_VERSION_CODE < KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)))
wl_cfg80211_tdls_mgmt(struct wiphy * wiphy,struct net_device * dev,u8 * peer,u8 action_code,u8 dialog_token,u16 status_code,u32 peer_capability,const u8 * buf,size_t len)4774 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
4775 	u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
4776 	u32 peer_capability, const u8 *buf, size_t len)
4777 #elif ((LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)) && \
4778 		(LINUX_VERSION_CODE < KERNEL_VERSION(3, 18, 0)))
4779 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
4780 	const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
4781 	u32 peer_capability, const u8 *buf, size_t len)
4782 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
4783 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
4784        const u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
4785        u32 peer_capability, bool initiator, const u8 *buf, size_t len)
4786 #else /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
4787 wl_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
4788 	u8 *peer, u8 action_code, u8 dialog_token, u16 status_code,
4789 	const u8 *buf, size_t len)
4790 #endif /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
4791 {
4792 	s32 ret = 0;
4793 #if defined(BCMDONGLEHOST)
4794 #if defined(TDLS_MSG_ONLY_WFD) && defined(WLTDLS)
4795 	struct bcm_cfg80211 *cfg;
4796 	tdls_wfd_ie_iovar_t info;
4797 	bzero(&info, sizeof(info));
4798 	cfg = wl_get_cfg(dev);
4799 
4800 #if defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)
4801 	/* Some customer platform back ported this feature from kernel 3.15 to kernel 3.10
4802 	 * and that cuases build error
4803 	 */
4804 	BCM_REFERENCE(peer_capability);
4805 #endif  /* CONFIG_ARCH_MSM && TDLS_MGMT_VERSION2 */
4806 
4807 	switch (action_code) {
4808 		/* We need to set TDLS Wifi Display IE to firmware
4809 		 * using tdls_wfd_ie iovar
4810 		 */
4811 		case WLAN_TDLS_SET_PROBE_WFD_IE:
4812 			WL_ERR(("wl_cfg80211_tdls_mgmt: WLAN_TDLS_SET_PROBE_WFD_IE\n"));
4813 			info.mode = TDLS_WFD_PROBE_IE_TX;
4814 
4815 			if (len > sizeof(info.data)) {
4816 				return -EINVAL;
4817 			}
4818 			memcpy(&info.data, buf, len);
4819 			info.length = len;
4820 			break;
4821 		case WLAN_TDLS_SET_SETUP_WFD_IE:
4822 			WL_ERR(("wl_cfg80211_tdls_mgmt: WLAN_TDLS_SET_SETUP_WFD_IE\n"));
4823 			info.mode = TDLS_WFD_IE_TX;
4824 
4825 			if (len > sizeof(info.data)) {
4826 				return -EINVAL;
4827 			}
4828 			memcpy(&info.data, buf, len);
4829 			info.length = len;
4830 			break;
4831 		case WLAN_TDLS_SET_WFD_ENABLED:
4832 			WL_ERR(("wl_cfg80211_tdls_mgmt: WLAN_TDLS_SET_MODE_WFD_ENABLED\n"));
4833 			dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), true);
4834 			goto out;
4835 		case WLAN_TDLS_SET_WFD_DISABLED:
4836 			WL_ERR(("wl_cfg80211_tdls_mgmt: WLAN_TDLS_SET_MODE_WFD_DISABLED\n"));
4837 			dhd_tdls_set_mode((dhd_pub_t *)(cfg->pub), false);
4838 			goto out;
4839 		default:
4840 			WL_ERR(("Unsupported action code : %d\n", action_code));
4841 			goto out;
4842 	}
4843 	ret = wldev_iovar_setbuf(dev, "tdls_wfd_ie", &info, sizeof(info),
4844 			cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
4845 
4846 	if (ret) {
4847 		WL_ERR(("tdls_wfd_ie error %d\n", ret));
4848 	}
4849 
4850 out:
4851 #endif /* TDLS_MSG_ONLY_WFD && WLTDLS */
4852 #endif /* BCMDONGLEHOST */
4853 	return ret;
4854 }
4855 
4856 s32
4857 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
wl_cfg80211_tdls_oper(struct wiphy * wiphy,struct net_device * dev,const u8 * peer,enum nl80211_tdls_operation oper)4858 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
4859 	const u8 *peer, enum nl80211_tdls_operation oper)
4860 #else
4861 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
4862 	u8 *peer, enum nl80211_tdls_operation oper)
4863 #endif
4864 {
4865 	s32 ret = 0;
4866 #ifdef WLTDLS
4867 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
4868 	tdls_iovar_t info;
4869 	dhd_pub_t *dhdp;
4870 	bool tdls_auto_mode = false;
4871 	dhdp = (dhd_pub_t *)(cfg->pub);
4872 	bzero(&info, sizeof(tdls_iovar_t));
4873 	if (peer) {
4874 		memcpy(&info.ea, peer, ETHER_ADDR_LEN);
4875 	} else {
4876 		return -1;
4877 	}
4878 	switch (oper) {
4879 	case NL80211_TDLS_DISCOVERY_REQ:
4880 		/* If the discovery request is broadcast then we need to set
4881 		 * info.mode to Tunneled Probe Request
4882 		 */
4883 		if (memcmp(peer, (const uint8 *)BSSID_BROADCAST, ETHER_ADDR_LEN) == 0) {
4884 			info.mode = TDLS_MANUAL_EP_WFD_TPQ;
4885 			WL_ERR(("wl_cfg80211_tdls_oper: TDLS TUNNELED PRBOBE REQUEST\n"));
4886 		} else {
4887 			info.mode = TDLS_MANUAL_EP_DISCOVERY;
4888 		}
4889 		break;
4890 	case NL80211_TDLS_SETUP:
4891 		if (dhdp->tdls_mode == true) {
4892 			info.mode = TDLS_MANUAL_EP_CREATE;
4893 			tdls_auto_mode = false;
4894 			/* Do tear down and create a fresh one */
4895 			ret = wl_cfg80211_tdls_config(cfg, TDLS_STATE_TEARDOWN, tdls_auto_mode);
4896 			if (ret < 0) {
4897 				return ret;
4898 			}
4899 		} else {
4900 			tdls_auto_mode = true;
4901 		}
4902 		break;
4903 	case NL80211_TDLS_TEARDOWN:
4904 		info.mode = TDLS_MANUAL_EP_DELETE;
4905 		break;
4906 	default:
4907 		WL_ERR(("Unsupported operation : %d\n", oper));
4908 		goto out;
4909 	}
4910 	/* turn on TDLS */
4911 	ret = wl_cfg80211_tdls_config(cfg, TDLS_STATE_SETUP, tdls_auto_mode);
4912 	if (ret < 0) {
4913 		return ret;
4914 	}
4915 	if (info.mode) {
4916 		ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info),
4917 			cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
4918 		if (ret) {
4919 			WL_ERR(("tdls_endpoint error %d\n", ret));
4920 		}
4921 	}
4922 out:
4923 	/* use linux generic error code instead of firmware error code */
4924 	if (ret) {
4925 		wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
4926 		return -ENOTSUPP;
4927 	}
4928 #endif /* WLTDLS */
4929 	return ret;
4930 }
4931 #endif /* LINUX_VERSION > VERSION(3,2,0) || WL_COMPAT_WIRELESS */
4932 
check_dev_role_integrity(struct bcm_cfg80211 * cfg,u32 dev_role)4933 static bool check_dev_role_integrity(struct bcm_cfg80211 *cfg, u32 dev_role)
4934 {
4935 #if defined(BCMDONGLEHOST)
4936 	dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
4937 	if (((dev_role == NL80211_IFTYPE_AP) &&
4938 		!(dhd->op_mode & DHD_FLAG_HOSTAP_MODE)) ||
4939 		((dev_role == NL80211_IFTYPE_P2P_GO) &&
4940 		!(dhd->op_mode & DHD_FLAG_P2P_GO_MODE)))
4941 	{
4942 		WL_ERR(("device role select failed role:%d op_mode:%d \n", dev_role, dhd->op_mode));
4943 		return false;
4944 	}
4945 #endif /* defined(BCMDONGLEHOST) */
4946 	return true;
4947 }
4948 
4949 s32
wl_cfg80211_dfs_ap_move(struct net_device * ndev,char * data,char * command,int total_len)4950 wl_cfg80211_dfs_ap_move(struct net_device *ndev, char *data, char *command, int total_len)
4951 {
4952 	char ioctl_buf[WLC_IOCTL_SMLEN];
4953 	int err = 0;
4954 	uint32 val = 0;
4955 	chanspec_t chanspec = 0;
4956 	int abort;
4957 	int bytes_written = 0;
4958 	struct wl_dfs_ap_move_status_v2 *status;
4959 	char chanbuf[CHANSPEC_STR_LEN];
4960 	const char *dfs_state_str[DFS_SCAN_S_MAX] = {
4961 		"Radar Free On Channel",
4962 		"Radar Found On Channel",
4963 		"Radar Scan In Progress",
4964 		"Radar Scan Aborted",
4965 		"RSDB Mode switch in Progress For Scan"
4966 	};
4967 	if (ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP) {
4968 		bytes_written = snprintf(command, total_len, "AP is not up\n");
4969 		return bytes_written;
4970 	}
4971 	if (!*data) {
4972 		if ((err = wldev_iovar_getbuf(ndev, "dfs_ap_move", NULL, 0,
4973 				ioctl_buf, sizeof(ioctl_buf), NULL))) {
4974 			WL_ERR(("setting dfs_ap_move failed with err=%d \n", err));
4975 			return err;
4976 		}
4977 		status = (struct wl_dfs_ap_move_status_v2 *)ioctl_buf;
4978 
4979 		if (status->version != WL_DFS_AP_MOVE_VERSION) {
4980 			err = BCME_UNSUPPORTED;
4981 			WL_ERR(("err=%d version=%d\n", err, status->version));
4982 			return err;
4983 		}
4984 
4985 		if (status->move_status != (int8) DFS_SCAN_S_IDLE) {
4986 			chanspec = wl_chspec_driver_to_host(status->chanspec);
4987 			if (chanspec != 0 && chanspec != INVCHANSPEC) {
4988 				wf_chspec_ntoa(chanspec, chanbuf);
4989 				bytes_written = snprintf(command, total_len,
4990 					"AP Target Chanspec %s (0x%x)\n", chanbuf, chanspec);
4991 			}
4992 			bytes_written += snprintf(command + bytes_written,
4993 					total_len - bytes_written,
4994 					"%s\n", dfs_state_str[status->move_status]);
4995 			return bytes_written;
4996 		} else {
4997 			bytes_written = snprintf(command, total_len, "dfs AP move in IDLE state\n");
4998 			return bytes_written;
4999 		}
5000 	}
5001 
5002 	abort = bcm_atoi(data);
5003 	if (abort == -1) {
5004 		if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &abort,
5005 				sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
5006 			WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
5007 			return err;
5008 		}
5009 	} else {
5010 		chanspec = wf_chspec_aton(data);
5011 		if (chanspec != 0) {
5012 			val = wl_chspec_host_to_driver(chanspec);
5013 			if (val != INVCHANSPEC) {
5014 				if ((err = wldev_iovar_setbuf(ndev, "dfs_ap_move", &val,
5015 					sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) {
5016 					WL_ERR(("seting dfs_ap_move failed with err %d\n", err));
5017 					return err;
5018 				}
5019 				WL_DBG((" set dfs_ap_move successfull"));
5020 			} else {
5021 				err = BCME_USAGE_ERROR;
5022 			}
5023 		}
5024 	}
5025 	return err;
5026 }
5027 
5028 #ifdef WL_CFG80211_ACL
5029 static int
wl_cfg80211_set_mac_acl(struct wiphy * wiphy,struct net_device * cfgdev,const struct cfg80211_acl_data * acl)5030 wl_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *cfgdev,
5031 	const struct cfg80211_acl_data *acl)
5032 {
5033 	int i;
5034 	int ret = 0;
5035 	int macnum = 0;
5036 	int macmode = MACLIST_MODE_DISABLED;
5037 	struct maclist *list;
5038 	struct bcm_cfg80211 *cfg = wl_get_cfg(cfgdev);
5039 
5040 	/* get the MAC filter mode */
5041 	if (acl && acl->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED) {
5042 		macmode = MACLIST_MODE_ALLOW;
5043 	} else if (acl && acl->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED &&
5044 	acl->n_acl_entries) {
5045 		macmode = MACLIST_MODE_DENY;
5046 	}
5047 
5048 	/* if acl == NULL, macmode is still disabled.. */
5049 	if (macmode == MACLIST_MODE_DISABLED) {
5050 		if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, NULL)) != 0)
5051 			WL_ERR(("wl_cfg80211_set_mac_acl: Setting MAC list"
5052 				" failed error=%d\n", ret));
5053 
5054 		return ret;
5055 	}
5056 
5057 	macnum = acl->n_acl_entries;
5058 	if (macnum < 0 || macnum > MAX_NUM_MAC_FILT) {
5059 		WL_ERR(("wl_cfg80211_set_mac_acl: invalid number of MAC address entries %d\n",
5060 			macnum));
5061 		return -1;
5062 	}
5063 
5064 	/* allocate memory for the MAC list */
5065 	list = (struct maclist *)MALLOC(cfg->osh, sizeof(int) +
5066 		sizeof(struct ether_addr) * macnum);
5067 	if (!list) {
5068 		WL_ERR(("wl_cfg80211_set_mac_acl: failed to allocate memory\n"));
5069 		return -1;
5070 	}
5071 
5072 	/* prepare the MAC list */
5073 	list->count = htod32(macnum);
5074 	for (i = 0; i < macnum; i++) {
5075 		memcpy(&list->ea[i], &acl->mac_addrs[i], ETHER_ADDR_LEN);
5076 	}
5077 	/* set the list */
5078 	if ((ret = wl_android_set_ap_mac_list(cfgdev, macmode, list)) != 0)
5079 		WL_ERR(("wl_cfg80211_set_mac_acl: Setting MAC list failed error=%d\n", ret));
5080 
5081 	MFREE(cfg->osh, list, sizeof(int) +
5082 		sizeof(struct ether_addr) * macnum);
5083 
5084 	return ret;
5085 }
5086 #endif /* WL_CFG80211_ACL */
5087 
5088 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
wl_chspec_chandef(chanspec_t chanspec,struct cfg80211_chan_def * chandef,struct wiphy * wiphy)5089 int wl_chspec_chandef(chanspec_t chanspec,
5090 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
5091 	struct cfg80211_chan_def *chandef,
5092 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
5093 	struct chan_info *chaninfo,
5094 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)) */
5095 	struct wiphy *wiphy)
5096 {
5097 	uint16 freq = 0;
5098 	int chan_type = 0;
5099 	int channel = 0;
5100 	struct ieee80211_channel *chan;
5101 
5102 	if (!chandef) {
5103 		return -1;
5104 	}
5105 	channel = CHSPEC_CHANNEL(chanspec);
5106 
5107 	switch (CHSPEC_BW(chanspec)) {
5108 		case WL_CHANSPEC_BW_20:
5109 			chan_type = NL80211_CHAN_HT20;
5110 			break;
5111 		case WL_CHANSPEC_BW_40:
5112 		{
5113 			if (CHSPEC_SB_UPPER(chanspec)) {
5114 				channel += CH_10MHZ_APART;
5115 			} else {
5116 				channel -= CH_10MHZ_APART;
5117 			}
5118 		}
5119 			chan_type = NL80211_CHAN_HT40PLUS;
5120 			break;
5121 
5122 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
5123 		case WL_CHANSPEC_BW_80:
5124 		case WL_CHANSPEC_BW_8080:
5125 		{
5126 			uint16 sb = CHSPEC_CTL_SB(chanspec);
5127 
5128 			if (sb == WL_CHANSPEC_CTL_SB_LL) {
5129 				channel -= (CH_10MHZ_APART + CH_20MHZ_APART);
5130 			} else if (sb == WL_CHANSPEC_CTL_SB_LU) {
5131 				channel -= CH_10MHZ_APART;
5132 			} else if (sb == WL_CHANSPEC_CTL_SB_UL) {
5133 				channel += CH_10MHZ_APART;
5134 			} else {
5135 				/* WL_CHANSPEC_CTL_SB_UU */
5136 				channel += (CH_10MHZ_APART + CH_20MHZ_APART);
5137 			}
5138 
5139 			if (sb == WL_CHANSPEC_CTL_SB_LL || sb == WL_CHANSPEC_CTL_SB_LU)
5140 				chan_type = NL80211_CHAN_HT40MINUS;
5141 			else if (sb == WL_CHANSPEC_CTL_SB_UL || sb == WL_CHANSPEC_CTL_SB_UU)
5142 				chan_type = NL80211_CHAN_HT40PLUS;
5143 		}
5144 			break;
5145 		case WL_CHANSPEC_BW_160:
5146 			channel = wf_chspec_primary20_chan(chanspec);
5147 			/* Using base chan_type as kernel does not define chan_type for 160 MHz */
5148 			chan_type = NL80211_CHAN_HT20;
5149 			break;
5150 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
5151 		default:
5152 			chan_type = NL80211_CHAN_HT20;
5153 			break;
5154 
5155 	}
5156 	freq = wl_channel_to_frequency(channel, CHSPEC_BAND(chanspec));
5157 	chan = ieee80211_get_channel(wiphy, freq);
5158 	WL_DBG(("channel:%d freq:%d chan_type: %d chan_ptr:%p \n",
5159 		channel, freq, chan_type, chan));
5160 	if (unlikely(!chan)) {
5161 		/* fw and cfg80211 channel lists are not in sync */
5162 		WL_ERR(("Couldn't find matching channel in wiphy channel list \n"));
5163 		ASSERT(0);
5164 		return -EINVAL;
5165 	}
5166 
5167 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
5168 	cfg80211_chandef_create(chandef, chan, chan_type);
5169 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
5170 	chaninfo->freq = freq;
5171 	chaninfo->chan_type = chan_type;
5172 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
5173 	return 0;
5174 }
5175 
5176 void
wl_cfg80211_ch_switch_notify(struct net_device * dev,uint16 chanspec,struct wiphy * wiphy)5177 wl_cfg80211_ch_switch_notify(struct net_device *dev, uint16 chanspec, struct wiphy *wiphy)
5178 {
5179 	u32 freq;
5180 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
5181 	struct cfg80211_chan_def chandef;
5182 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
5183 	struct chan_info chaninfo;
5184 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
5185 
5186 	if (!wiphy) {
5187 		WL_ERR(("wiphy is null\n"));
5188 		return;
5189 	}
5190 #if (LINUX_VERSION_CODE <= KERNEL_VERSION (3, 18, 0))
5191 	/* Channel switch support is only for AP/GO/ADHOC/MESH */
5192 	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION ||
5193 		dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
5194 		WL_ERR(("No channel switch notify support for STA/GC\n"));
5195 		return;
5196 	}
5197 #endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION (3, 18, 0)) */
5198 
5199 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
5200 	if (wl_chspec_chandef(chanspec, &chandef, wiphy))
5201 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
5202 	if (wl_chspec_chandef(chanspec, &chaninfo, wiphy))
5203 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
5204 	{
5205 		WL_ERR(("chspec_chandef failed\n"));
5206 		return;
5207 	}
5208 #if (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0))
5209 	freq = chandef.chan ? chandef.chan->center_freq : chandef.center_freq1;
5210 	cfg80211_ch_switch_notify(dev, &chandef);
5211 #elif (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 5, 0) && (LINUX_VERSION_CODE <= (3, 7, 0)))
5212 	freq = chan_info.freq;
5213 	cfg80211_ch_switch_notify(dev, freq, chan_info.chan_type);
5214 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION (3, 8, 0)) */
5215 
5216 	WL_MSG(dev->name, "Channel switch notification for freq: %d chanspec: 0x%x\n",
5217 		freq, chanspec);
5218 #ifdef WL_EXT_IAPSTA
5219 	wl_ext_fw_reinit_incsa(dev);
5220 #endif
5221 	return;
5222 }
5223 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
5224 
5225 static void
wl_ap_channel_ind(struct bcm_cfg80211 * cfg,struct net_device * ndev,chanspec_t chanspec)5226 wl_ap_channel_ind(struct bcm_cfg80211 *cfg,
5227 	struct net_device *ndev,
5228 	chanspec_t chanspec)
5229 {
5230 	u32 channel = LCHSPEC_CHANNEL(chanspec);
5231 
5232 	WL_INFORM_MEM(("(%s) AP channel:%d chspec:0x%x \n",
5233 		ndev->name, channel, chanspec));
5234 
5235 #ifdef SUPPORT_AP_BWCTRL
5236 	wl_update_apchan_bwcap(cfg, ndev, chanspec);
5237 #endif /* SUPPORT_AP_BWCTRL */
5238 
5239 	if (!(cfg->ap_oper_channel == INVCHANSPEC) && (cfg->ap_oper_channel != chanspec)) {
5240 		/*
5241 		 * If cached channel is different from the channel indicated
5242 		 * by the event, notify user space about the channel switch.
5243 		 */
5244 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
5245 		wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
5246 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
5247 		cfg->ap_oper_channel = chanspec;
5248 	}
5249 }
5250 
5251 s32
wl_ap_start_ind(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)5252 wl_ap_start_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
5253 const wl_event_msg_t *e, void *data)
5254 {
5255 	struct net_device *ndev = NULL;
5256 	chanspec_t chanspec;
5257 
5258 	WL_DBG(("Enter\n"));
5259 	if (unlikely(e->status)) {
5260 		WL_ERR(("status:0x%x \n", e->status));
5261 		return -1;
5262 	}
5263 
5264 	if (!data) {
5265 		return -EINVAL;
5266 	}
5267 
5268 	if (likely(cfgdev)) {
5269 		ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
5270 		chanspec = *((chanspec_t *)data);
5271 
5272 		if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
5273 			/* For AP/GO role */
5274 			wl_ap_channel_ind(cfg, ndev, chanspec);
5275 		}
5276 	}
5277 
5278 	return 0;
5279 }
5280 
5281 s32
wl_csa_complete_ind(struct bcm_cfg80211 * cfg,bcm_struct_cfgdev * cfgdev,const wl_event_msg_t * e,void * data)5282 wl_csa_complete_ind(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
5283 const wl_event_msg_t *e, void *data)
5284 {
5285 	int error = 0;
5286 	u32 chanspec = 0;
5287 	struct net_device *ndev = NULL;
5288 	struct ether_addr bssid;
5289 
5290 	WL_DBG(("Enter\n"));
5291 	if (unlikely(e->status)) {
5292 		WL_ERR(("status:0x%x \n", e->status));
5293 		return -1;
5294 	}
5295 
5296 	if (likely(cfgdev)) {
5297 		ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
5298 		/* Get association state if not AP and then query chanspec */
5299 		if (!((wl_get_mode_by_netdev(cfg, ndev)) == WL_MODE_AP)) {
5300 			error = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
5301 			if (error) {
5302 				WL_ERR(("CSA on %s. Not associated. error=%d\n",
5303 					ndev->name, error));
5304 				return BCME_ERROR;
5305 			}
5306 		}
5307 
5308 		error = wldev_iovar_getint(ndev, "chanspec", &chanspec);
5309 		if (unlikely(error)) {
5310 			WL_ERR(("Get chanspec error: %d \n", error));
5311 			return -1;
5312 		}
5313 
5314 		WL_INFORM_MEM(("[%s] CSA ind. ch:0x%x\n", ndev->name, chanspec));
5315 		if (wl_get_mode_by_netdev(cfg, ndev) == WL_MODE_AP) {
5316 			/* For AP/GO role */
5317 			wl_ap_channel_ind(cfg, ndev, chanspec);
5318 		} else {
5319 			/* STA/GC roles */
5320 			if (!wl_get_drv_status(cfg, CONNECTED, ndev)) {
5321 				WL_ERR(("CSA on %s. Not associated.\n", ndev->name));
5322 				return BCME_ERROR;
5323 			}
5324 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 5, 0))
5325 			wl_cfg80211_ch_switch_notify(ndev, chanspec, bcmcfg_to_wiphy(cfg));
5326 #endif /* LINUX_VERSION_CODE >= (3, 5, 0) */
5327 		}
5328 
5329 	}
5330 
5331 	return 0;
5332 }
5333 
5334 #ifdef WLTDLS
5335 s32
wl_cfg80211_tdls_config(struct bcm_cfg80211 * cfg,enum wl_tdls_config state,bool auto_mode)5336 wl_cfg80211_tdls_config(struct bcm_cfg80211 *cfg, enum wl_tdls_config state, bool auto_mode)
5337 {
5338 	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
5339 	int err = 0;
5340 	struct net_info *iter, *next;
5341 	int update_reqd = 0;
5342 	int enable = 0;
5343 	dhd_pub_t *dhdp;
5344 	dhdp = (dhd_pub_t *)(cfg->pub);
5345 
5346 	/*
5347 	 * TDLS need to be enabled only if we have a single STA/GC
5348 	 * connection.
5349 	 */
5350 
5351 	WL_DBG(("Enter state:%d\n", state));
5352 	if (!cfg->tdls_supported) {
5353 		/* FW doesn't support tdls. Do nothing */
5354 		return -ENODEV;
5355 	}
5356 
5357 	/* Protect tdls config session */
5358 	mutex_lock(&cfg->tdls_sync);
5359 
5360 	if (state == TDLS_STATE_TEARDOWN) {
5361 		/* Host initiated TDLS tear down */
5362 		err = dhd_tdls_enable(ndev, false, auto_mode, NULL);
5363 		goto exit;
5364 	} else if ((state == TDLS_STATE_AP_CREATE) ||
5365 		(state == TDLS_STATE_NMI_CREATE)) {
5366 		/* We don't support tdls while AP/GO/NAN is operational */
5367 		update_reqd = true;
5368 		enable = false;
5369 	} else if ((state == TDLS_STATE_CONNECT) || (state == TDLS_STATE_IF_CREATE)) {
5370 		if (wl_get_drv_status_all(cfg,
5371 			CONNECTED) >= TDLS_MAX_IFACE_FOR_ENABLE) {
5372 			/* For STA/GC connect command request, disable
5373 			 * tdls if we have any concurrent interfaces
5374 			 * operational.
5375 			 */
5376 			WL_DBG(("Interface limit restriction. disable tdls.\n"));
5377 			update_reqd = true;
5378 			enable = false;
5379 		}
5380 	} else if ((state == TDLS_STATE_DISCONNECT) ||
5381 		(state == TDLS_STATE_AP_DELETE) ||
5382 		(state == TDLS_STATE_SETUP) ||
5383 		(state == TDLS_STATE_IF_DELETE)) {
5384 		/* Enable back the tdls connection only if we have less than
5385 		 * or equal to a single STA/GC connection.
5386 		 */
5387 		if (wl_get_drv_status_all(cfg,
5388 			CONNECTED) == 0) {
5389 			/* If there are no interfaces connected, enable tdls */
5390 			update_reqd = true;
5391 			enable = true;
5392 		} else if (wl_get_drv_status_all(cfg,
5393 			CONNECTED) == TDLS_MAX_IFACE_FOR_ENABLE) {
5394 			/* We have one interface in CONNECTED state.
5395 			 * Verify whether its a STA interface before
5396 			 * we enable back tdls.
5397 			 */
5398 			GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
5399 			for_each_ndev(cfg, iter, next) {
5400 				GCC_DIAGNOSTIC_POP();
5401 				if ((iter->ndev) && (wl_get_drv_status(cfg, CONNECTED, ndev)) &&
5402 					(ndev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)) {
5403 					WL_DBG(("Non STA iface operational. cfg_iftype:%d"
5404 						" Can't enable tdls.\n",
5405 						ndev->ieee80211_ptr->iftype));
5406 					err = -ENOTSUPP;
5407 					goto exit;
5408 				}
5409 			}
5410 			/* No AP/GO found. Enable back tdls */
5411 			update_reqd = true;
5412 			enable = true;
5413 		} else {
5414 			WL_DBG(("Concurrent connection mode. Can't enable tdls. \n"));
5415 			err = -ENOTSUPP;
5416 			goto exit;
5417 		}
5418 	} else {
5419 		WL_ERR(("Unknown tdls state:%d \n", state));
5420 		err = -EINVAL;
5421 		goto exit;
5422 	}
5423 
5424 	if (update_reqd == true) {
5425 		if (dhdp->tdls_enable == enable) {
5426 			WL_DBG(("No change in tdls state. Do nothing."
5427 				" tdls_enable:%d\n", enable));
5428 			goto exit;
5429 		}
5430 		err = wldev_iovar_setint(ndev, "tdls_enable", enable);
5431 		if (unlikely(err)) {
5432 			WL_ERR(("tdls_enable setting failed. err:%d\n", err));
5433 			goto exit;
5434 		} else {
5435 			WL_INFORM_MEM(("tdls_enable %d state:%d\n", enable, state));
5436 			/* Update the dhd state variable to be in sync */
5437 			dhdp->tdls_enable = enable;
5438 			if (state == TDLS_STATE_SETUP) {
5439 				/* For host initiated setup, apply TDLS params
5440 				 * Don't propagate errors up for param config
5441 				 * failures
5442 				 */
5443 				dhd_tdls_enable(ndev, true, auto_mode, NULL);
5444 
5445 			}
5446 		}
5447 	} else {
5448 		WL_DBG(("Skip tdls config. state:%d update_reqd:%d "
5449 			"current_status:%d \n",
5450 			state, update_reqd, dhdp->tdls_enable));
5451 	}
5452 
5453 exit:
5454 	if (err) {
5455 		wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
5456 	}
5457 	mutex_unlock(&cfg->tdls_sync);
5458 	return err;
5459 }
5460 #endif /* WLTDLS */
5461 
wl_get_ap_netdev(struct bcm_cfg80211 * cfg,char * ifname)5462 struct net_device* wl_get_ap_netdev(struct bcm_cfg80211 *cfg, char *ifname)
5463 {
5464 	struct net_info *iter, *next;
5465 	struct net_device *ndev = NULL;
5466 
5467 	GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
5468 	for_each_ndev(cfg, iter, next) {
5469 		GCC_DIAGNOSTIC_POP();
5470 		if (iter->ndev) {
5471 			if (strncmp(iter->ndev->name, ifname, IFNAMSIZ) == 0) {
5472 				if (iter->ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
5473 					ndev = iter->ndev;
5474 					break;
5475 				}
5476 			}
5477 		}
5478 	}
5479 
5480 	return ndev;
5481 }
5482 
5483 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
5484 #define WLC_RATE_FLAG	0x80
5485 #define RATE_MASK		0x7f
5486 
wl_set_ap_beacon_rate(struct net_device * dev,int val,char * ifname)5487 int wl_set_ap_beacon_rate(struct net_device *dev, int val, char *ifname)
5488 {
5489 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5490 	dhd_pub_t *dhdp;
5491 	wl_rateset_args_t rs;
5492 	int error = BCME_ERROR, i;
5493 	struct net_device *ndev = NULL;
5494 
5495 	dhdp = (dhd_pub_t *)(cfg->pub);
5496 
5497 	if (dhdp && !(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
5498 		WL_ERR(("Not Hostapd mode\n"));
5499 		return BCME_NOTAP;
5500 	}
5501 
5502 	ndev = wl_get_ap_netdev(cfg, ifname);
5503 
5504 	if (ndev == NULL) {
5505 		WL_ERR(("No softAP interface named %s\n", ifname));
5506 		return BCME_NOTAP;
5507 	}
5508 
5509 	bzero(&rs, sizeof(wl_rateset_args_t));
5510 	error = wldev_iovar_getbuf(ndev, "rateset", NULL, 0,
5511 		&rs, sizeof(wl_rateset_args_t), NULL);
5512 	if (error < 0) {
5513 		WL_ERR(("get rateset failed = %d\n", error));
5514 		return error;
5515 	}
5516 
5517 	if (rs.count < 1) {
5518 		WL_ERR(("Failed to get rate count\n"));
5519 		return BCME_ERROR;
5520 	}
5521 
5522 	/* Host delivers target rate in the unit of 500kbps */
5523 	/* To make it to 1mbps unit, atof should be implemented for 5.5mbps basic rate */
5524 	for (i = 0; i < rs.count && i < WL_NUMRATES; i++)
5525 		if (rs.rates[i] & WLC_RATE_FLAG)
5526 			if ((rs.rates[i] & RATE_MASK) == val)
5527 				break;
5528 
5529 	/* Valid rate has been delivered as an argument */
5530 	if (i < rs.count && i < WL_NUMRATES) {
5531 		error = wldev_iovar_setint(ndev, "force_bcn_rspec", val);
5532 		if (error < 0) {
5533 			WL_ERR(("set beacon rate failed = %d\n", error));
5534 			return BCME_ERROR;
5535 		}
5536 	} else {
5537 		WL_ERR(("Rate is invalid"));
5538 		return BCME_BADARG;
5539 	}
5540 
5541 	return BCME_OK;
5542 }
5543 
5544 int
wl_get_ap_basic_rate(struct net_device * dev,char * command,char * ifname,int total_len)5545 wl_get_ap_basic_rate(struct net_device *dev, char* command, char *ifname, int total_len)
5546 {
5547 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5548 	dhd_pub_t *dhdp;
5549 	wl_rateset_args_t rs;
5550 	int error = BCME_ERROR;
5551 	int i, bytes_written = 0;
5552 	struct net_device *ndev = NULL;
5553 
5554 	dhdp = (dhd_pub_t *)(cfg->pub);
5555 
5556 	if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
5557 		WL_ERR(("Not Hostapd mode\n"));
5558 		return BCME_NOTAP;
5559 	}
5560 
5561 	ndev = wl_get_ap_netdev(cfg, ifname);
5562 
5563 	if (ndev == NULL) {
5564 		WL_ERR(("No softAP interface named %s\n", ifname));
5565 		return BCME_NOTAP;
5566 	}
5567 
5568 	bzero(&rs, sizeof(wl_rateset_args_t));
5569 	error = wldev_iovar_getbuf(ndev, "rateset", NULL, 0,
5570 		&rs, sizeof(wl_rateset_args_t), NULL);
5571 	if (error < 0) {
5572 		WL_ERR(("get rateset failed = %d\n", error));
5573 		return error;
5574 	}
5575 
5576 	if (rs.count < 1) {
5577 		WL_ERR(("Failed to get rate count\n"));
5578 		return BCME_ERROR;
5579 	}
5580 
5581 	/* Delivers basic rate in the unit of 500kbps to host */
5582 	for (i = 0; i < rs.count && i < WL_NUMRATES; i++)
5583 		if (rs.rates[i] & WLC_RATE_FLAG)
5584 			bytes_written += snprintf(command + bytes_written, total_len,
5585 							"%d ", rs.rates[i] & RATE_MASK);
5586 
5587 	/* Remove last space in the command buffer */
5588 	if (bytes_written && (bytes_written < total_len)) {
5589 		command[bytes_written - 1] = '\0';
5590 		bytes_written--;
5591 	}
5592 
5593 	return bytes_written;
5594 
5595 }
5596 #endif /* SUPPORT_AP_HIGHER_BEACONRATE */
5597 
5598 #ifdef SUPPORT_AP_RADIO_PWRSAVE
5599 #define MSEC_PER_MIN	(60000L)
5600 
5601 static int
_wl_update_ap_rps_params(struct net_device * dev)5602 _wl_update_ap_rps_params(struct net_device *dev)
5603 {
5604 	struct bcm_cfg80211 *cfg = NULL;
5605 	rpsnoa_iovar_params_t iovar;
5606 	u8 smbuf[WLC_IOCTL_SMLEN];
5607 
5608 	if (!dev)
5609 		return BCME_BADARG;
5610 
5611 	cfg = wl_get_cfg(dev);
5612 
5613 	bzero(&iovar, sizeof(iovar));
5614 	bzero(smbuf, sizeof(smbuf));
5615 
5616 	iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
5617 	iovar.hdr.subcmd = WL_RPSNOA_CMD_PARAMS;
5618 	iovar.hdr.len = sizeof(iovar);
5619 	iovar.param->band = WLC_BAND_ALL;
5620 	iovar.param->level = cfg->ap_rps_info.level;
5621 	iovar.param->stas_assoc_check = cfg->ap_rps_info.sta_assoc_check;
5622 	iovar.param->pps = cfg->ap_rps_info.pps;
5623 	iovar.param->quiet_time = cfg->ap_rps_info.quiet_time;
5624 
5625 	if (wldev_iovar_setbuf(dev, "rpsnoa", &iovar, sizeof(iovar),
5626 		smbuf, sizeof(smbuf), NULL)) {
5627 		WL_ERR(("Failed to set rpsnoa params"));
5628 		return BCME_ERROR;
5629 	}
5630 
5631 	return BCME_OK;
5632 }
5633 
5634 int
wl_get_ap_rps(struct net_device * dev,char * command,char * ifname,int total_len)5635 wl_get_ap_rps(struct net_device *dev, char* command, char *ifname, int total_len)
5636 {
5637 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5638 	dhd_pub_t *dhdp;
5639 	int error = BCME_ERROR;
5640 	int bytes_written = 0;
5641 	struct net_device *ndev = NULL;
5642 	rpsnoa_iovar_status_t iovar;
5643 	u8 smbuf[WLC_IOCTL_SMLEN];
5644 	u32 chanspec = 0;
5645 	u8 idx = 0;
5646 	u16 state;
5647 	u32 sleep;
5648 	u32 time_since_enable;
5649 
5650 	dhdp = (dhd_pub_t *)(cfg->pub);
5651 
5652 	if (!dhdp) {
5653 		error = BCME_NOTUP;
5654 		goto fail;
5655 	}
5656 
5657 	if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
5658 		WL_ERR(("Not Hostapd mode\n"));
5659 		error = BCME_NOTAP;
5660 		goto fail;
5661 	}
5662 
5663 	ndev = wl_get_ap_netdev(cfg, ifname);
5664 
5665 	if (ndev == NULL) {
5666 		WL_ERR(("No softAP interface named %s\n", ifname));
5667 		error = BCME_NOTAP;
5668 		goto fail;
5669 	}
5670 
5671 	bzero(&iovar, sizeof(iovar));
5672 	bzero(smbuf, sizeof(smbuf));
5673 
5674 	iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
5675 	iovar.hdr.subcmd = WL_RPSNOA_CMD_STATUS;
5676 	iovar.hdr.len = sizeof(iovar);
5677 	iovar.stats->band = WLC_BAND_ALL;
5678 
5679 	error = wldev_iovar_getbuf(ndev, "rpsnoa", &iovar, sizeof(iovar),
5680 		smbuf, sizeof(smbuf), NULL);
5681 	if (error < 0) {
5682 		WL_ERR(("get ap radio pwrsave failed = %d\n", error));
5683 		goto fail;
5684 	}
5685 
5686 	/* RSDB event doesn't seem to be handled correctly.
5687 	 * So check chanspec of AP directly from the firmware
5688 	 */
5689 	error = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
5690 	if (error < 0) {
5691 		WL_ERR(("get chanspec from AP failed = %d\n", error));
5692 		goto fail;
5693 	}
5694 
5695 	chanspec = wl_chspec_driver_to_host(chanspec);
5696 	if (CHSPEC_IS2G(chanspec))
5697 		idx = 0;
5698 	else if (
5699 #ifdef WL_6G_BAND
5700 		CHSPEC_IS6G(chanspec) ||
5701 #endif /* WL_6G_BAND */
5702 		CHSPEC_IS5G(chanspec))
5703 		idx = 1;
5704 	else {
5705 		error = BCME_BADCHAN;
5706 		goto fail;
5707 	}
5708 
5709 	state = ((rpsnoa_iovar_status_t *)smbuf)->stats[idx].state;
5710 	sleep = ((rpsnoa_iovar_status_t *)smbuf)->stats[idx].sleep_dur;
5711 	time_since_enable = ((rpsnoa_iovar_status_t *)smbuf)->stats[idx].sleep_avail_dur;
5712 
5713 	/* Conver ms to minute, round down only */
5714 	sleep = DIV_U64_BY_U32(sleep, MSEC_PER_MIN);
5715 	time_since_enable = DIV_U64_BY_U32(time_since_enable, MSEC_PER_MIN);
5716 
5717 	bytes_written += snprintf(command + bytes_written, total_len,
5718 		"state=%d sleep=%d time_since_enable=%d", state, sleep, time_since_enable);
5719 	error = bytes_written;
5720 
5721 fail:
5722 	return error;
5723 }
5724 
5725 int
wl_set_ap_rps(struct net_device * dev,bool enable,char * ifname)5726 wl_set_ap_rps(struct net_device *dev, bool enable, char *ifname)
5727 {
5728 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5729 	dhd_pub_t *dhdp;
5730 	struct net_device *ndev = NULL;
5731 	rpsnoa_iovar_t iovar;
5732 	u8 smbuf[WLC_IOCTL_SMLEN];
5733 	int ret = BCME_OK;
5734 
5735 	dhdp = (dhd_pub_t *)(cfg->pub);
5736 
5737 	if (!dhdp) {
5738 		ret = BCME_NOTUP;
5739 		goto exit;
5740 	}
5741 
5742 	if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
5743 		WL_ERR(("Not Hostapd mode\n"));
5744 		ret = BCME_NOTAP;
5745 		goto exit;
5746 	}
5747 
5748 	ndev = wl_get_ap_netdev(cfg, ifname);
5749 
5750 	if (ndev == NULL) {
5751 		WL_ERR(("No softAP interface named %s\n", ifname));
5752 		ret = BCME_NOTAP;
5753 		goto exit;
5754 	}
5755 
5756 	if (cfg->ap_rps_info.enable != enable) {
5757 		cfg->ap_rps_info.enable = enable;
5758 		if (enable) {
5759 			ret = _wl_update_ap_rps_params(ndev);
5760 			if (ret) {
5761 				WL_ERR(("Filed to update rpsnoa params\n"));
5762 				goto exit;
5763 			}
5764 		}
5765 		bzero(&iovar, sizeof(iovar));
5766 		bzero(smbuf, sizeof(smbuf));
5767 
5768 		iovar.hdr.ver = RADIO_PWRSAVE_VERSION;
5769 		iovar.hdr.subcmd = WL_RPSNOA_CMD_ENABLE;
5770 		iovar.hdr.len = sizeof(iovar);
5771 		iovar.data->band = WLC_BAND_ALL;
5772 		iovar.data->value = (int16)enable;
5773 
5774 		ret = wldev_iovar_setbuf(ndev, "rpsnoa", &iovar, sizeof(iovar),
5775 			smbuf, sizeof(smbuf), NULL);
5776 		if (ret) {
5777 			WL_ERR(("Failed to enable AP radio power save"));
5778 			goto exit;
5779 		}
5780 		cfg->ap_rps_info.enable = enable;
5781 	}
5782 exit:
5783 	return ret;
5784 }
5785 
5786 int
wl_update_ap_rps_params(struct net_device * dev,ap_rps_info_t * rps,char * ifname)5787 wl_update_ap_rps_params(struct net_device *dev, ap_rps_info_t* rps, char *ifname)
5788 {
5789 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5790 	dhd_pub_t *dhdp;
5791 	struct net_device *ndev = NULL;
5792 
5793 	dhdp = (dhd_pub_t *)(cfg->pub);
5794 
5795 	if (!dhdp)
5796 		return BCME_NOTUP;
5797 
5798 	if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
5799 		WL_ERR(("Not Hostapd mode\n"));
5800 		return BCME_NOTAP;
5801 	}
5802 
5803 	ndev = wl_get_ap_netdev(cfg, ifname);
5804 
5805 	if (ndev == NULL) {
5806 		WL_ERR(("No softAP interface named %s\n", ifname));
5807 		return BCME_NOTAP;
5808 	}
5809 
5810 	if (!rps)
5811 		return BCME_BADARG;
5812 
5813 	if (rps->pps < RADIO_PWRSAVE_PPS_MIN)
5814 		return BCME_BADARG;
5815 
5816 	if (rps->level < RADIO_PWRSAVE_LEVEL_MIN ||
5817 		rps->level > RADIO_PWRSAVE_LEVEL_MAX)
5818 		return BCME_BADARG;
5819 
5820 	if (rps->quiet_time < RADIO_PWRSAVE_QUIETTIME_MIN)
5821 		return BCME_BADARG;
5822 
5823 	if (rps->sta_assoc_check > RADIO_PWRSAVE_ASSOCCHECK_MAX ||
5824 		rps->sta_assoc_check < RADIO_PWRSAVE_ASSOCCHECK_MIN)
5825 		return BCME_BADARG;
5826 
5827 	cfg->ap_rps_info.pps = rps->pps;
5828 	cfg->ap_rps_info.level = rps->level;
5829 	cfg->ap_rps_info.quiet_time = rps->quiet_time;
5830 	cfg->ap_rps_info.sta_assoc_check = rps->sta_assoc_check;
5831 
5832 	if (cfg->ap_rps_info.enable) {
5833 		if (_wl_update_ap_rps_params(ndev)) {
5834 			WL_ERR(("Failed to update rpsnoa params"));
5835 			return BCME_ERROR;
5836 		}
5837 	}
5838 
5839 	return BCME_OK;
5840 }
5841 
5842 void
wl_cfg80211_init_ap_rps(struct bcm_cfg80211 * cfg)5843 wl_cfg80211_init_ap_rps(struct bcm_cfg80211 *cfg)
5844 {
5845 	cfg->ap_rps_info.enable = FALSE;
5846 	cfg->ap_rps_info.sta_assoc_check = RADIO_PWRSAVE_STAS_ASSOC_CHECK;
5847 	cfg->ap_rps_info.pps = RADIO_PWRSAVE_PPS;
5848 	cfg->ap_rps_info.quiet_time = RADIO_PWRSAVE_QUIET_TIME;
5849 	cfg->ap_rps_info.level = RADIO_PWRSAVE_LEVEL;
5850 }
5851 #endif /* SUPPORT_AP_RADIO_PWRSAVE */
5852 
5853 int
wl_cfg80211_iface_count(struct net_device * dev)5854 wl_cfg80211_iface_count(struct net_device *dev)
5855 {
5856 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
5857 	struct net_info *iter, *next;
5858 	int iface_count = 0;
5859 
5860 	/* Return the count of network interfaces (skip netless p2p discovery
5861 	 * interface)
5862 	 */
5863 	GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
5864 	for_each_ndev(cfg, iter, next) {
5865 		GCC_DIAGNOSTIC_POP();
5866 		if (iter->ndev) {
5867 			iface_count++;
5868 		}
5869 	}
5870 	return iface_count;
5871 }
5872 
5873 typedef struct {
5874 	uint16 id;
5875 	uint16 len;
5876 	uint32 val;
5877 } he_xtlv_v32;
5878 
5879 static bool
wl_he_get_uint_cb(void * ctx,uint16 * id,uint16 * len)5880 wl_he_get_uint_cb(void *ctx, uint16 *id, uint16 *len)
5881 {
5882 	he_xtlv_v32 *v32 = ctx;
5883 
5884 	*id = v32->id;
5885 	*len = v32->len;
5886 
5887 	return FALSE;
5888 }
5889 
5890 	static void
wl_he_pack_uint_cb(void * ctx,uint16 id,uint16 len,uint8 * buf)5891 wl_he_pack_uint_cb(void *ctx, uint16 id, uint16 len, uint8 *buf)
5892 {
5893 	he_xtlv_v32 *v32 = ctx;
5894 
5895 	BCM_REFERENCE(id);
5896 	BCM_REFERENCE(len);
5897 
5898 	v32->val = htod32(v32->val);
5899 
5900 	switch (v32->len) {
5901 		case sizeof(uint8):
5902 			*buf = (uint8)v32->val;
5903 			break;
5904 		case sizeof(uint16):
5905 			store16_ua(buf, (uint16)v32->val);
5906 			break;
5907 		case sizeof(uint32):
5908 			store32_ua(buf, v32->val);
5909 			break;
5910 		default:
5911 			/* ASSERT(0); */
5912 			break;
5913 	}
5914 }
5915 
wl_cfg80211_set_he_mode(struct net_device * dev,struct bcm_cfg80211 * cfg,s32 bssidx,u32 he_flag,bool set)5916 int wl_cfg80211_set_he_mode(struct net_device *dev, struct bcm_cfg80211 *cfg,
5917 		s32 bssidx, u32 he_flag, bool set)
5918 {
5919 	bcm_xtlv_t read_he_xtlv;
5920 	uint8 se_he_xtlv[32];
5921 	int se_he_xtlv_len = sizeof(se_he_xtlv);
5922 	he_xtlv_v32 v32;
5923 	u32 he_feature = 0;
5924 	s32 err = 0;
5925 
5926 	read_he_xtlv.id = WL_HE_CMD_FEATURES;
5927 	read_he_xtlv.len = 0;
5928 	err = wldev_iovar_getbuf_bsscfg(dev, "he", &read_he_xtlv, sizeof(read_he_xtlv),
5929 			cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, NULL);
5930 	if (err < 0) {
5931 		WL_ERR(("HE get failed. error=%d\n", err));
5932 		return err;
5933 	} else {
5934 		he_feature =  *(int*)cfg->ioctl_buf;
5935 		he_feature = dtoh32(he_feature);
5936 	}
5937 
5938 	v32.id = WL_HE_CMD_FEATURES;
5939 	v32.len = sizeof(s32);
5940 
5941 	if (set) {
5942 		v32.val = (he_feature | he_flag);
5943 	} else {
5944 		v32.val = (he_feature & ~he_flag);
5945 	}
5946 
5947 	err = bcm_pack_xtlv_buf((void *)&v32, se_he_xtlv, sizeof(se_he_xtlv),
5948 			BCM_XTLV_OPTION_ALIGN32, wl_he_get_uint_cb, wl_he_pack_uint_cb,
5949 			&se_he_xtlv_len);
5950 	if (err != BCME_OK) {
5951 		WL_ERR(("failed to pack he settvl=%d\n", err));
5952 	}
5953 
5954 	err = wldev_iovar_setbuf_bsscfg(dev, "he", &se_he_xtlv, sizeof(se_he_xtlv),
5955 			cfg->ioctl_buf, WLC_IOCTL_SMLEN, bssidx, &cfg->ioctl_buf_sync);
5956 	if (err < 0) {
5957 		WL_ERR(("failed to set he features, error=%d\n", err));
5958 	}
5959 	WL_INFORM(("Set HE[%d] done\n", set));
5960 
5961 	return err;
5962 }
5963 
5964 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
5965 int
wl_cfg80211_channel_switch(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_csa_settings * params)5966 wl_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
5967 	struct cfg80211_csa_settings *params)
5968 {
5969 	s32 err = BCME_OK;
5970 	u32 bw = WL_CHANSPEC_BW_20;
5971 	chanspec_t chspec = 0;
5972 	wl_chan_switch_t csa_arg;
5973 	struct cfg80211_chan_def *chandef = &params->chandef;
5974 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
5975 	struct net_device *primary_dev = bcmcfg_to_prmry_ndev(cfg);
5976 
5977 	dev = ndev_to_wlc_ndev(dev, cfg);
5978 	chspec = wl_freq_to_chanspec(chandef->chan->center_freq);
5979 
5980 	WL_ERR(("netdev_ifidx(%d), target channel(%d) target bandwidth(%d),"
5981 		" mode(%d), count(%d)\n", dev->ifindex, CHSPEC_CHANNEL(chspec), chandef->width,
5982 		params->block_tx, params->count));
5983 
5984 	if (wl_get_mode_by_netdev(cfg, dev) != WL_MODE_AP) {
5985 		WL_ERR(("Channel Switch doesn't support on "
5986 			"the non-SoftAP mode\n"));
5987 		return -EINVAL;
5988 	}
5989 
5990 	/* Check if STA is trying to associate with an AP */
5991 	if (wl_get_drv_status(cfg, CONNECTING, primary_dev)) {
5992 		WL_ERR(("Connecting is in progress\n"));
5993 		return BCME_BUSY;
5994 	}
5995 
5996 	if (chspec == cfg->ap_oper_channel) {
5997 		WL_ERR(("Channel %d is same as current operating channel,"
5998 			" so skip\n", CHSPEC_CHANNEL(chspec)));
5999 		return BCME_OK;
6000 	}
6001 
6002 	if (
6003 #ifdef WL_6G_BAND
6004 		CHSPEC_IS6G(chspec) ||
6005 #endif
6006 		CHSPEC_IS5G(chspec)) {
6007 #ifdef APSTA_RESTRICTED_CHANNEL
6008 		if (CHSPEC_CHANNEL(chspec) != DEFAULT_5G_SOFTAP_CHANNEL) {
6009 			WL_ERR(("Invalid 5G Channel, chan=%d\n", CHSPEC_CHANNEL(chspec)));
6010 			return -EINVAL;
6011 		}
6012 #endif /* APSTA_RESTRICTED_CHANNEL */
6013 		err = wl_get_bandwidth_cap(primary_dev, CHSPEC_BAND(chspec), &bw);
6014 		if (err < 0) {
6015 			WL_ERR(("Failed to get bandwidth information,"
6016 				" err=%d\n", err));
6017 			return err;
6018 		}
6019 	} else if (CHSPEC_IS2G(chspec)) {
6020 #ifdef BCMDONGLEHOST
6021 #ifdef APSTA_RESTRICTED_CHANNEL
6022 		dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
6023 		chanspec_t *sta_chanspec = (chanspec_t *)wl_read_prof(cfg,
6024 			primary_dev, WL_PROF_CHAN);
6025 
6026 		/* In 2GHz STA/SoftAP concurrent mode, the operating channel
6027 		 * of STA and SoftAP should be confgiured to the same 2GHz
6028 		 * channel. Otherwise, it is an invalid configuration.
6029 		 */
6030 		if (DHD_OPMODE_STA_SOFTAP_CONCURR(dhdp) &&
6031 			wl_get_drv_status(cfg, CONNECTED, primary_dev) &&
6032 			sta_chanspec && (CHSPEC_CHANNEL(*sta_chanspec) != CHSPEC_CHANNEL(chspec))) {
6033 			WL_ERR(("Invalid 2G Channel in case of STA/SoftAP"
6034 				" concurrent mode, sta_chan=%d, chan=%d\n",
6035 				CHSPEC_CHANNEL(*sta_chanspec), CHSPEC_CHANNEL(chspec)));
6036 			return -EINVAL;
6037 		}
6038 #endif /* APSTA_RESTRICTED_CHANNEL */
6039 #endif /* BCMDONGLEHOST */
6040 		bw = WL_CHANSPEC_BW_20;
6041 	} else {
6042 		WL_ERR(("invalid band (%d)\n", CHSPEC_BAND(chspec)));
6043 		return -EINVAL;
6044 	}
6045 
6046 #ifdef WL_6G_BAND
6047 	/* Avoid in case of 6G as for each center frequency bw is unique and is
6048 	* detected based on centre frequency.
6049 	*/
6050 	if (!CHSPEC_IS6G(chspec))
6051 #endif /* WL_6G_BAND */
6052 	{
6053 		chspec = wf_channel2chspec(CHSPEC_CHANNEL(chspec), bw);
6054 	}
6055 	if (!wf_chspec_valid(chspec)) {
6056 		WL_ERR(("Invalid chanspec 0x%x\n", chspec));
6057 		return -EINVAL;
6058 	}
6059 
6060 	/* Send CSA to associated STAs */
6061 	memset(&csa_arg, 0, sizeof(wl_chan_switch_t));
6062 	csa_arg.mode = params->block_tx;
6063 	csa_arg.count = params->count;
6064 	csa_arg.chspec = chspec;
6065 	csa_arg.frame_type = CSA_BROADCAST_ACTION_FRAME;
6066 	csa_arg.reg = 0;
6067 
6068 	err = wldev_iovar_setbuf(dev, "csa", &csa_arg, sizeof(wl_chan_switch_t),
6069 		cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
6070 	if (err < 0) {
6071 		WL_ERR(("Failed to switch channel, err=%d\n", err));
6072 	}
6073 
6074 	return err;
6075 }
6076 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) */
6077 
6078 #ifdef SUPPORT_AP_SUSPEND
6079 void
wl_set_ap_suspend_error_handler(struct net_device * ndev,bool suspend)6080 wl_set_ap_suspend_error_handler(struct net_device *ndev, bool suspend)
6081 {
6082 	struct bcm_cfg80211 *cfg = wl_get_cfg(ndev);
6083 	dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
6084 
6085 	if (wl_get_drv_status(cfg, READY, ndev)) {
6086 #if defined(BCMDONGLEHOST)
6087 		/* IF dongle is down due to previous hang or other conditions, sending
6088 		* one more hang notification is not needed.
6089 		*/
6090 		if (dhd_query_bus_erros(dhdp)) {
6091 			return;
6092 		}
6093 		dhdp->iface_op_failed = TRUE;
6094 #if defined(DHD_FW_COREDUMP)
6095 		if (dhdp->memdump_enabled) {
6096 			dhdp->memdump_type = DUMP_TYPE_IFACE_OP_FAILURE;
6097 			dhd_bus_mem_dump(dhdp);
6098 		}
6099 #endif /* DHD_FW_COREDUMP */
6100 #endif /* BCMDONGLEHOST */
6101 
6102 #if defined(BCMDONGLEHOST) && defined(OEM_ANDROID)
6103 		WL_ERR(("Notify hang event to upper layer \n"));
6104 		dhdp->hang_reason = suspend ?
6105 			HANG_REASON_BSS_DOWN_FAILURE : HANG_REASON_BSS_UP_FAILURE;
6106 		net_os_send_hang_message(ndev);
6107 #endif /* BCMDONGLEHOST && OEM_ANDROID */
6108 
6109 	}
6110 }
6111 
6112 #define MAX_AP_RESUME_TIME   5000
6113 int
wl_set_ap_suspend(struct net_device * dev,bool suspend,char * ifname)6114 wl_set_ap_suspend(struct net_device *dev, bool suspend, char *ifname)
6115 {
6116 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6117 	dhd_pub_t *dhdp;
6118 	struct net_device *ndev = NULL;
6119 	int ret = BCME_OK;
6120 	bool is_bssup = FALSE;
6121 	int bssidx;
6122 	unsigned long start_j;
6123 	int time_to_sleep = MAX_AP_RESUME_TIME;
6124 
6125 	dhdp = (dhd_pub_t *)(cfg->pub);
6126 
6127 	if (!dhdp) {
6128 		return BCME_NOTUP;
6129 	}
6130 
6131 	if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
6132 		WL_ERR(("Not Hostapd mode\n"));
6133 		return BCME_NOTAP;
6134 	}
6135 
6136 	ndev = wl_get_ap_netdev(cfg, ifname);
6137 
6138 	if (ndev == NULL) {
6139 		WL_ERR(("No softAP interface named %s\n", ifname));
6140 		return BCME_NOTAP;
6141 	}
6142 
6143 	if ((bssidx = wl_get_bssidx_by_wdev(cfg, ndev->ieee80211_ptr)) < 0) {
6144 		WL_ERR(("Find p2p index from wdev(%p) failed\n", ndev->ieee80211_ptr));
6145 		return BCME_NOTFOUND;
6146 	}
6147 
6148 	is_bssup = wl_cfg80211_bss_isup(ndev, bssidx);
6149 	if (is_bssup && suspend) {
6150 		wl_clr_drv_status(cfg, AP_CREATED, ndev);
6151 		wl_clr_drv_status(cfg, CONNECTED, ndev);
6152 
6153 		if ((ret = wl_cfg80211_bss_up(cfg, ndev, bssidx, 0)) < 0) {
6154 			WL_ERR(("AP suspend error %d, suspend %d\n", ret, suspend));
6155 			ret = BCME_NOTDOWN;
6156 			goto exit;
6157 		}
6158 	} else if (!is_bssup && !suspend) {
6159 		/* Abort scan before starting AP again */
6160 		wl_cfgscan_cancel_scan(cfg);
6161 
6162 		if ((ret = wl_cfg80211_bss_up(cfg, ndev, bssidx, 1)) < 0) {
6163 			WL_ERR(("AP resume error %d, suspend %d\n", ret, suspend));
6164 			ret = BCME_NOTUP;
6165 			goto exit;
6166 		}
6167 
6168 		while (TRUE) {
6169 			start_j = get_jiffies_64();
6170 			/* Wait for Linkup event to mark successful AP bring up */
6171 			ret = wait_event_interruptible_timeout(cfg->netif_change_event,
6172 				wl_get_drv_status(cfg, AP_CREATED, ndev),
6173 				msecs_to_jiffies(time_to_sleep));
6174 			if (ret == -ERESTARTSYS) {
6175 				WL_ERR(("waitqueue was interrupted by a signal\n"));
6176 				time_to_sleep -= jiffies_to_msecs(get_jiffies_64() - start_j);
6177 				if (time_to_sleep <= 0) {
6178 					WL_ERR(("time to sleep hits 0\n"));
6179 					ret = BCME_NOTUP;
6180 					goto exit;
6181 				}
6182 			} else if (ret == 0 || !wl_get_drv_status(cfg, AP_CREATED, ndev)) {
6183 				WL_ERR(("AP resume failed!\n"));
6184 				ret = BCME_NOTUP;
6185 				goto exit;
6186 			} else {
6187 				wl_set_drv_status(cfg, CONNECTED, ndev);
6188 				wl_clr_drv_status(cfg, AP_CREATING, ndev);
6189 				ret = BCME_OK;
6190 				break;
6191 			}
6192 		}
6193 	} else {
6194 		/* bssup + resume or bssdown + suspend,
6195 		 * So, returns OK
6196 		 */
6197 		ret = BCME_OK;
6198 	}
6199 exit:
6200 	if (ret != BCME_OK)
6201 		wl_set_ap_suspend_error_handler(bcmcfg_to_prmry_ndev(cfg), suspend);
6202 
6203 	return ret;
6204 }
6205 #endif /* SUPPORT_AP_SUSPEND */
6206 
6207 #ifdef SUPPORT_SOFTAP_ELNA_BYPASS
wl_set_softap_elna_bypass(struct net_device * dev,char * ifname,int enable)6208 int wl_set_softap_elna_bypass(struct net_device *dev, char *ifname, int enable)
6209 {
6210 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6211 	struct net_device *ifdev = NULL;
6212 	char iobuf[WLC_IOCTL_SMLEN];
6213 	int err = BCME_OK;
6214 	int iftype = 0;
6215 
6216 	memset(iobuf, 0, WLC_IOCTL_SMLEN);
6217 
6218 	/* Check the interface type */
6219 	ifdev = wl_get_netdev_by_name(cfg, ifname);
6220 	if (ifdev == NULL) {
6221 		WL_ERR(("%s: Could not find net_device for ifname:%s\n", __FUNCTION__, ifname));
6222 		err = BCME_BADARG;
6223 		goto fail;
6224 	}
6225 
6226 	iftype = ifdev->ieee80211_ptr->iftype;
6227 	if (iftype == NL80211_IFTYPE_AP) {
6228 		err = wldev_iovar_setint(ifdev, "softap_elnabypass", enable);
6229 		if (unlikely(err)) {
6230 			WL_ERR(("%s: Failed to set softap_elnabypass, err=%d\n",
6231 				__FUNCTION__, err));
6232 		}
6233 	} else {
6234 		WL_ERR(("%s: softap_elnabypass should control in SoftAP mode only\n",
6235 			__FUNCTION__));
6236 		err = BCME_BADARG;
6237 	}
6238 fail:
6239 	return err;
6240 }
wl_get_softap_elna_bypass(struct net_device * dev,char * ifname,void * param)6241 int wl_get_softap_elna_bypass(struct net_device *dev, char *ifname, void *param)
6242 {
6243 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6244 	int *enable = (int*)param;
6245 	struct net_device *ifdev = NULL;
6246 	char iobuf[WLC_IOCTL_SMLEN];
6247 	int err = BCME_OK;
6248 	int iftype = 0;
6249 
6250 	memset(iobuf, 0, WLC_IOCTL_SMLEN);
6251 
6252 	/* Check the interface type */
6253 	ifdev = wl_get_netdev_by_name(cfg, ifname);
6254 	if (ifdev == NULL) {
6255 		WL_ERR(("%s: Could not find net_device for ifname:%s\n", __FUNCTION__, ifname));
6256 		err = BCME_BADARG;
6257 		goto fail;
6258 	}
6259 
6260 	iftype = ifdev->ieee80211_ptr->iftype;
6261 	if (iftype == NL80211_IFTYPE_AP) {
6262 		err = wldev_iovar_getint(ifdev, "softap_elnabypass", enable);
6263 		if (unlikely(err)) {
6264 			WL_ERR(("%s: Failed to get softap_elnabypass, err=%d\n",
6265 				__FUNCTION__, err));
6266 		}
6267 	} else {
6268 		WL_ERR(("%s: softap_elnabypass should control in SoftAP mode only\n",
6269 			__FUNCTION__));
6270 		err = BCME_BADARG;
6271 	}
6272 fail:
6273 	return err;
6274 
6275 }
6276 #endif /* SUPPORT_SOFTAP_ELNA_BYPASS */
6277 
6278 #ifdef SUPPORT_AP_BWCTRL
6279 #define OPER_MODE_ENABLE	(1 << 8)
6280 static int op2bw[] = {20, 40, 80, 160};
6281 
6282 static int
wl_get_ap_he_mode(struct net_device * ndev,struct bcm_cfg80211 * cfg,bool * he)6283 wl_get_ap_he_mode(struct net_device *ndev, struct bcm_cfg80211 *cfg, bool *he)
6284 {
6285 	bcm_xtlv_t read_he_xtlv;
6286 	int ret = 0;
6287 	u8  he_enab = 0;
6288 	u32 he_feature = 0;
6289 	*he = FALSE;
6290 
6291 	/* Check he enab first */
6292 	read_he_xtlv.id = WL_HE_CMD_ENAB;
6293 	read_he_xtlv.len = 0;
6294 
6295 	ret = wldev_iovar_getbuf(ndev, "he", &read_he_xtlv, sizeof(read_he_xtlv),
6296 			cfg->ioctl_buf, WLC_IOCTL_SMLEN, NULL);
6297 	if (ret < 0) {
6298 		if (ret == BCME_UNSUPPORTED) {
6299 			/* HE not supported */
6300 			ret = BCME_OK;
6301 		} else {
6302 			WL_ERR(("HE ENAB get failed. ret=%d\n", ret));
6303 		}
6304 		goto exit;
6305 	} else {
6306 		he_enab =  *(u8*)cfg->ioctl_buf;
6307 	}
6308 
6309 	if (!he_enab) {
6310 		goto exit;
6311 	}
6312 
6313 	/* Then check BIT3 of he features */
6314 	read_he_xtlv.id = WL_HE_CMD_FEATURES;
6315 	read_he_xtlv.len = 0;
6316 
6317 	ret = wldev_iovar_getbuf(ndev, "he", &read_he_xtlv, sizeof(read_he_xtlv),
6318 			cfg->ioctl_buf, WLC_IOCTL_SMLEN, NULL);
6319 	if (ret < 0) {
6320 		WL_ERR(("HE FEATURE get failed. error=%d\n", ret));
6321 		goto exit;
6322 	} else {
6323 		he_feature =  *(int*)cfg->ioctl_buf;
6324 		he_feature = dtoh32(he_feature);
6325 	}
6326 
6327 	if (he_feature & WL_HE_FEATURES_HE_AP) {
6328 		WL_DBG(("HE is enabled in AP\n"));
6329 		*he = TRUE;
6330 	}
6331 exit:
6332 	return ret;
6333 }
6334 
6335 static void
wl_update_apchan_bwcap(struct bcm_cfg80211 * cfg,struct net_device * ndev,chanspec_t chanspec)6336 wl_update_apchan_bwcap(struct bcm_cfg80211 *cfg, struct net_device *ndev, chanspec_t chanspec)
6337 {
6338 	struct net_device *dev = bcmcfg_to_prmry_ndev(cfg);
6339 	struct wireless_dev *wdev = ndev_to_wdev(dev);
6340 	struct wiphy *wiphy = wdev->wiphy;
6341 	int ret = BCME_OK;
6342 	u32 bw_cap;
6343 	u32 ctl_chan;
6344 	chanspec_t chanbw = WL_CHANSPEC_BW_20;
6345 
6346 	/* Update channel in profile */
6347 	ctl_chan = wf_chspec_ctlchan(chanspec);
6348 	wl_update_prof(cfg, ndev, NULL, &chanspec, WL_PROF_CHAN);
6349 
6350 	/* BW cap is only updated in 5GHz */
6351 	if (ctl_chan <= CH_MAX_2G_CHANNEL)
6352 		return;
6353 
6354 	/* Get WL BW CAP */
6355 	ret = wl_get_bandwidth_cap(bcmcfg_to_prmry_ndev(cfg),
6356 		CHSPEC_BAND(chanspec), &bw_cap);
6357 	if (ret < 0) {
6358 		WL_ERR(("get bw_cap failed = %d\n", ret));
6359 		goto exit;
6360 	}
6361 
6362 	chanbw = CHSPEC_BW(wl_channel_to_chanspec(wiphy,
6363 		ndev, wf_chspec_ctlchan(chanspec), bw_cap));
6364 
6365 exit:
6366 	cfg->bw_cap_5g = bw2cap[chanbw >> WL_CHANSPEC_BW_SHIFT];
6367 	WL_INFORM_MEM(("supported bw cap is:0x%x\n", cfg->bw_cap_5g));
6368 
6369 }
6370 
6371 int
wl_rxchain_to_opmode_nss(int rxchain)6372 wl_rxchain_to_opmode_nss(int rxchain)
6373 {
6374 	/*
6375 	 * Nss 1 -> 0, Nss 2 -> 1
6376 	 * This is from operating mode field
6377 	 * in 8.4.1.50 of 802.11ac-2013
6378 	 */
6379 	/* TODO : Nss 3 ? */
6380 	if (rxchain == 3)
6381 		return (1 << 4);
6382 	else
6383 		return 0;
6384 }
6385 
6386 int
wl_update_opmode(struct net_device * ndev,u32 bw)6387 wl_update_opmode(struct net_device *ndev, u32 bw)
6388 {
6389 	int ret = BCME_OK;
6390 	int oper_mode;
6391 	int rxchain;
6392 
6393 	ret = wldev_iovar_getint(ndev, "rxchain", (s32 *)&rxchain);
6394 	if (ret < 0) {
6395 		WL_ERR(("get rxchain failed = %d\n", ret));
6396 		goto exit;
6397 	}
6398 
6399 	oper_mode = bw;
6400 	oper_mode |= wl_rxchain_to_opmode_nss(rxchain);
6401 	/* Enable flag */
6402 	oper_mode |= OPER_MODE_ENABLE;
6403 
6404 	ret = wldev_iovar_setint(ndev, "oper_mode", oper_mode);
6405 	if (ret < 0) {
6406 		WL_ERR(("set oper_mode failed = %d\n", ret));
6407 		goto exit;
6408 	}
6409 
6410 exit:
6411 	return ret;
6412 }
6413 
6414 int
wl_set_ap_bw(struct net_device * dev,u32 bw,char * ifname)6415 wl_set_ap_bw(struct net_device *dev, u32 bw, char *ifname)
6416 {
6417 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6418 	dhd_pub_t *dhdp;
6419 	struct net_device *ndev = NULL;
6420 	int ret = BCME_OK;
6421 	chanspec_t *chanspec;
6422 	bool he;
6423 
6424 	dhdp = (dhd_pub_t *)(cfg->pub);
6425 
6426 	if (!dhdp) {
6427 		return BCME_NOTUP;
6428 	}
6429 
6430 	if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
6431 		WL_ERR(("Not Hostapd mode\n"));
6432 		return BCME_NOTAP;
6433 	}
6434 
6435 	ndev = wl_get_ap_netdev(cfg, ifname);
6436 
6437 	if (ndev == NULL) {
6438 		WL_ERR(("No softAP interface named %s\n", ifname));
6439 		return BCME_NOTAP;
6440 	}
6441 
6442 	if (bw > DOT11_OPER_MODE_160MHZ) {
6443 		WL_ERR(("BW is too big %d\n", bw));
6444 		return BCME_BADARG;
6445 	}
6446 
6447 	chanspec = (chanspec_t *)wl_read_prof(cfg, ndev, WL_PROF_CHAN);
6448 	if (CHSPEC_IS2G(*chanspec)) {
6449 		WL_ERR(("current chanspec is %d, not supported\n", *chanspec));
6450 		ret = BCME_BADCHAN;
6451 		goto exit;
6452 	}
6453 
6454 	if ((DHD_OPMODE_STA_SOFTAP_CONCURR(dhdp) &&
6455 		wl_get_drv_status(cfg, CONNECTED, bcmcfg_to_prmry_ndev(cfg))) ||
6456 		wl_cfgnan_is_enabled(cfg)) {
6457 		WL_ERR(("BW control in concurrent mode is not supported\n"));
6458 		return BCME_BUSY;
6459 	}
6460 
6461 	/* When SCAN is on going either in STA or in AP, return BUSY */
6462 	if (wl_get_drv_status_all(cfg, SCANNING)) {
6463 		WL_ERR(("STA is SCANNING, not support BW control\n"));
6464 		return BCME_BUSY;
6465 	}
6466 
6467 	/* When SCANABORT is on going either in STA or in AP, return BUSY */
6468 	if (wl_get_drv_status_all(cfg, SCAN_ABORTING)) {
6469 		WL_ERR(("STA is SCAN_ABORTING, not support BW control\n"));
6470 		return BCME_BUSY;
6471 	}
6472 
6473 	/* When CONNECTION is on going in STA, return BUSY */
6474 	if (wl_get_drv_status(cfg, CONNECTING, bcmcfg_to_prmry_ndev(cfg))) {
6475 		WL_ERR(("STA is CONNECTING, not support BW control\n"));
6476 		return BCME_BUSY;
6477 	}
6478 
6479 	/* BW control in AX mode needs more verification */
6480 	ret = wl_get_ap_he_mode(ndev, cfg, &he);
6481 	if (ret == BCME_OK && he) {
6482 		WL_ERR(("BW control in HE mode is not supported\n"));
6483 		return BCME_UNSUPPORTED;
6484 	}
6485 	if (ret < 0) {
6486 		WL_ERR(("Check AX mode is failed\n"));
6487 		goto exit;
6488 	}
6489 
6490 	if ((!WL_BW_CAP_160MHZ(cfg->bw_cap_5g) && (bw == DOT11_OPER_MODE_160MHZ)) ||
6491 		(!WL_BW_CAP_80MHZ(cfg->bw_cap_5g) && (bw >= DOT11_OPER_MODE_80MHZ)) ||
6492 		(!WL_BW_CAP_40MHZ(cfg->bw_cap_5g) && (bw >= DOT11_OPER_MODE_40MHZ)) ||
6493 		(!WL_BW_CAP_20MHZ(cfg->bw_cap_5g))) {
6494 		WL_ERR(("bw_cap %x does not support bw = %d\n", cfg->bw_cap_5g, bw));
6495 		ret = BCME_BADARG;
6496 		goto exit;
6497 	}
6498 
6499 	WL_DBG(("Updating AP BW to %d\n", op2bw[bw]));
6500 
6501 	ret = wl_update_opmode(ndev, bw);
6502 	if (ret < 0) {
6503 		WL_ERR(("opmode set failed = %d\n", ret));
6504 		goto exit;
6505 	}
6506 
6507 exit:
6508 	return ret;
6509 }
6510 
6511 int
wl_get_ap_bw(struct net_device * dev,char * command,char * ifname,int total_len)6512 wl_get_ap_bw(struct net_device *dev, char* command, char *ifname, int total_len)
6513 {
6514 	struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
6515 	dhd_pub_t *dhdp;
6516 	struct net_device *ndev = NULL;
6517 	int ret = BCME_OK;
6518 	u32 chanspec = 0;
6519 	u32 bw = DOT11_OPER_MODE_20MHZ;
6520 	int bytes_written = 0;
6521 
6522 	dhdp = (dhd_pub_t *)(cfg->pub);
6523 
6524 	if (!dhdp) {
6525 		return BCME_NOTUP;
6526 	}
6527 
6528 	if (!(dhdp->op_mode & DHD_FLAG_HOSTAP_MODE)) {
6529 		WL_ERR(("Not Hostapd mode\n"));
6530 		return BCME_NOTAP;
6531 	}
6532 
6533 	ndev = wl_get_ap_netdev(cfg, ifname);
6534 
6535 	if (ndev == NULL) {
6536 		WL_ERR(("No softAP interface named %s\n", ifname));
6537 		return BCME_NOTAP;
6538 	}
6539 
6540 	ret = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
6541 	if (ret < 0) {
6542 		WL_ERR(("get chanspec from AP failed = %d\n", ret));
6543 		goto exit;
6544 	}
6545 
6546 	chanspec = wl_chspec_driver_to_host(chanspec);
6547 
6548 	if (CHSPEC_IS20(chanspec)) {
6549 		bw = DOT11_OPER_MODE_20MHZ;
6550 	} else if (CHSPEC_IS40(chanspec)) {
6551 		bw = DOT11_OPER_MODE_40MHZ;
6552 	} else if (CHSPEC_IS80(chanspec)) {
6553 		bw = DOT11_OPER_MODE_80MHZ;
6554 	} else if (CHSPEC_IS_BW_160_WIDE(chanspec)) {
6555 		bw = DOT11_OPER_MODE_160MHZ;
6556 	} else {
6557 		WL_ERR(("chanspec error %x\n", chanspec));
6558 		ret = BCME_BADCHAN;
6559 		goto exit;
6560 	}
6561 
6562 	bytes_written += snprintf(command + bytes_written, total_len,
6563 		"bw=%d", bw);
6564 	ret = bytes_written;
6565 exit:
6566 	return ret;
6567 }
6568 
6569 void
wl_restore_ap_bw(struct bcm_cfg80211 * cfg)6570 wl_restore_ap_bw(struct bcm_cfg80211 *cfg)
6571 {
6572 	int ret = BCME_OK;
6573 	u32 bw;
6574 	bool he = FALSE;
6575 	struct net_info *iter, *next;
6576 	struct net_device *ndev = NULL;
6577 	chanspec_t *chanspec;
6578 
6579 	if (!cfg) {
6580 		return;
6581 	}
6582 
6583 	GCC_DIAGNOSTIC_PUSH_SUPPRESS_CAST();
6584 	for_each_ndev(cfg, iter, next) {
6585 		GCC_DIAGNOSTIC_POP();
6586 		if (iter->ndev) {
6587 			if (iter->ndev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
6588 				chanspec = (chanspec_t *)wl_read_prof(cfg, iter->ndev,
6589 					WL_PROF_CHAN);
6590 				if (CHSPEC_IS2G(*chanspec)) {
6591 					ndev = iter->ndev;
6592 					break;
6593 				}
6594 			}
6595 		}
6596 	}
6597 
6598 	if (!ndev) {
6599 		return;
6600 	}
6601 
6602 	/* BW control in AX mode not allowed */
6603 	ret = wl_get_ap_he_mode(bcmcfg_to_prmry_ndev(cfg), cfg, &he);
6604 	if (ret == BCME_OK && he) {
6605 		return;
6606 	}
6607 	if (ret < 0) {
6608 		WL_ERR(("Check AX mode is failed\n"));
6609 		return;
6610 	}
6611 
6612 	if (WL_BW_CAP_160MHZ(cfg->bw_cap_5g)) {
6613 		bw = DOT11_OPER_MODE_160MHZ;
6614 	} else if (WL_BW_CAP_80MHZ(cfg->bw_cap_5g)) {
6615 		bw = DOT11_OPER_MODE_80MHZ;
6616 	} else if (WL_BW_CAP_40MHZ(cfg->bw_cap_5g)) {
6617 		bw = DOT11_OPER_MODE_40MHZ;
6618 	} else {
6619 		return;
6620 	}
6621 
6622 	WL_DBG(("Restoring AP BW to %d\n", op2bw[bw]));
6623 
6624 	ret = wl_update_opmode(ndev, bw);
6625 	if (ret < 0) {
6626 		WL_ERR(("bw restore failed = %d\n", ret));
6627 		return;
6628 	}
6629 }
6630 #endif /* SUPPORT_AP_BWCTRL */
6631