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