xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlinux/moal_uap_cfg80211.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file moal_uap_cfg80211.c
2  *
3  * @brief This file contains the functions for uAP CFG80211.
4  *
5  *
6  * Copyright 2011-2022 NXP
7  *
8  * This software file (the File) is distributed by NXP
9  * under the terms of the GNU General Public License Version 2, June 1991
10  * (the License).  You may use, redistribute and/or modify the File in
11  * accordance with the terms and conditions of the License, a copy of which
12  * is available by writing to the Free Software Foundation, Inc.,
13  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
14  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
15  *
16  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
18  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
19  * this warranty disclaimer.
20  *
21  */
22 
23 #include "moal_cfg80211.h"
24 #include "moal_uap_cfg80211.h"
25 /** deauth reason code */
26 #define REASON_CODE_DEAUTH_LEAVING 3
27 /********************************************************
28 				Local Variables
29 ********************************************************/
30 
31 /********************************************************
32 				Global Variables
33 ********************************************************/
34 /********************************************************
35 				Local Functions
36 ********************************************************/
37 
38 /********************************************************
39 				Global Functions
40 ********************************************************/
41 /**
42  * @brief send deauth to station
43  *
44  * @param                 A pointer to moal_private
45  * @param mac			  A pointer to station mac address
46  * @param reason_code     ieee deauth reason code
47  * @return                0 -- success, otherwise fail
48  */
woal_deauth_station(moal_private * priv,u8 * mac_addr,u16 reason_code)49 static int woal_deauth_station(moal_private *priv, u8 *mac_addr,
50 			       u16 reason_code)
51 {
52 	mlan_ioctl_req *ioctl_req = NULL;
53 	mlan_ds_bss *bss = NULL;
54 	int ret = 0;
55 	mlan_status status = MLAN_STATUS_SUCCESS;
56 
57 	ENTER();
58 
59 	ioctl_req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
60 	if (ioctl_req == NULL) {
61 		ret = -ENOMEM;
62 		goto done;
63 	}
64 	bss = (mlan_ds_bss *)ioctl_req->pbuf;
65 	bss->sub_command = MLAN_OID_UAP_DEAUTH_STA;
66 	ioctl_req->req_id = MLAN_IOCTL_BSS;
67 	ioctl_req->action = MLAN_ACT_SET;
68 
69 	moal_memcpy_ext(priv->phandle, bss->param.deauth_param.mac_addr,
70 			mac_addr, MLAN_MAC_ADDR_LENGTH,
71 			sizeof(bss->param.deauth_param.mac_addr));
72 	bss->param.deauth_param.reason_code = reason_code;
73 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
74 	if (status != MLAN_STATUS_SUCCESS) {
75 		ret = -EFAULT;
76 		goto done;
77 	}
78 
79 done:
80 	if (status != MLAN_STATUS_PENDING)
81 		kfree(ioctl_req);
82 	LEAVE();
83 	return ret;
84 }
85 
86 /**
87  * @brief send deauth to station, that has been added and associated
88  *
89  * @param                 A pointer to moal_private
90  * @param mac			        A pointer to station mac address
91  * @param reason_code     ieee deauth reason code
92  * @return                0 -- success, otherwise fail
93  */
woal_deauth_assoc_station(moal_private * priv,u8 * mac_addr,u16 reason_code)94 static int woal_deauth_assoc_station(moal_private *priv, u8 *mac_addr,
95 				     u16 reason_code)
96 {
97 	int ret = 0;
98 	int i = 0;
99 	mlan_ds_get_info *info = NULL;
100 	mlan_ioctl_req *ioctl_req = NULL;
101 	mlan_status status = MLAN_STATUS_SUCCESS;
102 
103 	ENTER();
104 
105 	if (!mac_addr) {
106 		LEAVE();
107 		return -EINVAL;
108 	}
109 
110 	ioctl_req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
111 		sizeof(mlan_ds_get_info));
112 	if (ioctl_req == NULL) {
113 		LEAVE();
114 		return -ENOMEM;
115 	}
116 
117 	info = (mlan_ds_get_info *)ioctl_req->pbuf;
118 	info->sub_command = MLAN_OID_UAP_STA_LIST;
119 	ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
120 	ioctl_req->action = MLAN_ACT_GET;
121 
122 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
123 	if (status != MLAN_STATUS_SUCCESS) {
124 		ret = -EFAULT;
125 		goto done;
126 	}
127 	if (!info->param.sta_list.sta_count) {
128 		PRINTM(MCMND, "wlan: skip deauth to station " MACSTR "\n",
129 		       MAC2STR(mac_addr));
130 		goto done;
131 	}
132 
133 	for (i = 0; i < info->param.sta_list.sta_count; i++) {
134 		if (!memcmp(info->param.sta_list.info[i].mac_address, mac_addr,
135 			    ETH_ALEN)) {
136 			PRINTM(MMSG, "wlan: deauth station " MACSTR "\n",
137 			       MAC2STR(mac_addr));
138 			ret = woal_deauth_station(priv, mac_addr, reason_code);
139 #if KERNEL_VERSION(3, 8, 0) <= CFG80211_VERSION_CODE
140 			if (moal_extflg_isset(priv->phandle, EXT_HOST_MLME))
141 				cfg80211_del_sta(priv->netdev, mac_addr,
142 						 GFP_KERNEL);
143 #endif
144 			break;
145 		}
146 	}
147 
148 done:
149 	if (status != MLAN_STATUS_PENDING)
150 		kfree(ioctl_req);
151 
152 	LEAVE();
153 	return ret;
154 }
155 
156 /**
157  * @brief send deauth to all station
158  *
159  * @param                 A pointer to moal_private
160  * @param mac			  A pointer to station mac address
161  *
162  * @return                0 -- success, otherwise fail
163  */
woal_deauth_all_station(moal_private * priv)164 static int woal_deauth_all_station(moal_private *priv)
165 {
166 	int ret = -EFAULT;
167 	int i = 0;
168 	mlan_ds_get_info *info = NULL;
169 	mlan_ioctl_req *ioctl_req = NULL;
170 	mlan_status status = MLAN_STATUS_SUCCESS;
171 
172 	ENTER();
173 	if (priv->media_connected == MFALSE) {
174 		PRINTM(MINFO, "cfg80211: Media not connected!\n");
175 		LEAVE();
176 		return 0;
177 	}
178 	PRINTM(MIOCTL, "del all station\n");
179 	/* Allocate an IOCTL request buffer */
180 	ioctl_req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
181 		sizeof(mlan_ds_get_info));
182 	if (ioctl_req == NULL) {
183 		ret = -ENOMEM;
184 		goto done;
185 	}
186 
187 	info = (mlan_ds_get_info *)ioctl_req->pbuf;
188 	info->sub_command = MLAN_OID_UAP_STA_LIST;
189 	ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
190 	ioctl_req->action = MLAN_ACT_GET;
191 
192 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
193 	if (status != MLAN_STATUS_SUCCESS)
194 		goto done;
195 	if (!info->param.sta_list.sta_count)
196 		goto done;
197 	for (i = 0; i < info->param.sta_list.sta_count; i++) {
198 		PRINTM(MIOCTL, "deauth station " MACSTR "\n",
199 		       MAC2STR(info->param.sta_list.info[i].mac_address));
200 		ret = woal_deauth_station(
201 			priv, info->param.sta_list.info[i].mac_address,
202 			REASON_CODE_DEAUTH_LEAVING);
203 	}
204 	woal_sched_timeout(200);
205 done:
206 	if (status != MLAN_STATUS_PENDING)
207 		kfree(ioctl_req);
208 	return ret;
209 }
210 
211 /**
212  * @brief Verify RSN IE
213  *
214  * @param rsn_ie          Pointer RSN IE
215  * @param sys_config      Pointer to mlan_uap_bss_param structure
216  *
217  * @return                MTRUE/MFALSE
218  */
woal_check_rsn_ie(IEEEtypes_Rsn_t * rsn_ie,mlan_uap_bss_param * sys_config)219 static t_u8 woal_check_rsn_ie(IEEEtypes_Rsn_t *rsn_ie,
220 			      mlan_uap_bss_param *sys_config)
221 {
222 	int left = 0;
223 	int count = 0;
224 	int i = 0;
225 	wpa_suite_auth_key_mgmt_t *key_mgmt = NULL;
226 	left = rsn_ie->len + 2;
227 	if (left < (int)sizeof(IEEEtypes_Rsn_t))
228 		return MFALSE;
229 	sys_config->wpa_cfg.group_cipher = 0;
230 	sys_config->wpa_cfg.pairwise_cipher_wpa2 = 0;
231 	sys_config->key_mgmt = 0;
232 	/* check the group cipher */
233 	switch (rsn_ie->group_cipher.type) {
234 	case WPA_CIPHER_TKIP:
235 		sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
236 		break;
237 	case WPA_CIPHER_AES_CCM:
238 		sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
239 		break;
240 	default:
241 		break;
242 	}
243 	count = woal_le16_to_cpu(rsn_ie->pairwise_cipher.count);
244 	for (i = 0; i < count; i++) {
245 		switch (rsn_ie->pairwise_cipher.list[i].type) {
246 		case WPA_CIPHER_TKIP:
247 			sys_config->wpa_cfg.pairwise_cipher_wpa2 |= CIPHER_TKIP;
248 			break;
249 		case WPA_CIPHER_AES_CCM:
250 			sys_config->wpa_cfg.pairwise_cipher_wpa2 |=
251 				CIPHER_AES_CCMP;
252 			break;
253 		default:
254 			break;
255 		}
256 	}
257 	left -= sizeof(IEEEtypes_Rsn_t) + (count - 1) * sizeof(wpa_suite);
258 	if (left < (int)sizeof(wpa_suite_auth_key_mgmt_t))
259 		return MFALSE;
260 	key_mgmt =
261 		(wpa_suite_auth_key_mgmt_t *)((u8 *)rsn_ie +
262 					      sizeof(IEEEtypes_Rsn_t) +
263 					      (count - 1) * sizeof(wpa_suite));
264 	count = woal_le16_to_cpu(key_mgmt->count);
265 	if (left < (int)(sizeof(wpa_suite_auth_key_mgmt_t) +
266 			 (count - 1) * sizeof(wpa_suite)))
267 		return MFALSE;
268 	for (i = 0; i < count; i++) {
269 		switch (key_mgmt->list[i].type) {
270 		case RSN_AKM_8021X:
271 			sys_config->key_mgmt |= KEY_MGMT_EAP;
272 			break;
273 		case RSN_AKM_PSK:
274 			sys_config->key_mgmt |= KEY_MGMT_PSK;
275 			break;
276 		case RSN_AKM_PSK_SHA256:
277 			sys_config->key_mgmt |= KEY_MGMT_PSK_SHA256;
278 			break;
279 		case RSN_AKM_SAE:
280 			sys_config->key_mgmt |= KEY_MGMT_SAE;
281 			break;
282 		case RSN_AKM_OWE:
283 			sys_config->key_mgmt |= KEY_MGMT_OWE;
284 			break;
285 		}
286 	}
287 	return MTRUE;
288 }
289 
290 /**
291  * @brief Verify WPA IE
292  *
293  * @param wpa_ie          Pointer WPA IE
294  * @param sys_config      Pointer to mlan_uap_bss_param structure
295  *
296  * @return                MTRUE/MFALSE
297  */
woal_check_wpa_ie(IEEEtypes_Wpa_t * wpa_ie,mlan_uap_bss_param * sys_config)298 static t_u8 woal_check_wpa_ie(IEEEtypes_Wpa_t *wpa_ie,
299 			      mlan_uap_bss_param *sys_config)
300 {
301 	int left = 0;
302 	int count = 0;
303 	int i = 0;
304 	wpa_suite_auth_key_mgmt_t *key_mgmt = NULL;
305 	left = wpa_ie->len + 2;
306 	if (left < (int)sizeof(IEEEtypes_Wpa_t))
307 		return MFALSE;
308 	sys_config->wpa_cfg.group_cipher = 0;
309 	sys_config->wpa_cfg.pairwise_cipher_wpa = 0;
310 	switch (wpa_ie->group_cipher.type) {
311 	case WPA_CIPHER_TKIP:
312 		sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
313 		break;
314 	case WPA_CIPHER_AES_CCM:
315 		sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
316 		break;
317 	default:
318 		break;
319 	}
320 	count = woal_le16_to_cpu(wpa_ie->pairwise_cipher.count);
321 	for (i = 0; i < count; i++) {
322 		switch (wpa_ie->pairwise_cipher.list[i].type) {
323 		case WPA_CIPHER_TKIP:
324 			sys_config->wpa_cfg.pairwise_cipher_wpa |= CIPHER_TKIP;
325 			break;
326 		case WPA_CIPHER_AES_CCM:
327 			sys_config->wpa_cfg.pairwise_cipher_wpa |=
328 				CIPHER_AES_CCMP;
329 			break;
330 		default:
331 			break;
332 		}
333 	}
334 	left -= sizeof(IEEEtypes_Wpa_t) + (count - 1) * sizeof(wpa_suite);
335 	if (left < (int)sizeof(wpa_suite_auth_key_mgmt_t))
336 		return MFALSE;
337 	key_mgmt =
338 		(wpa_suite_auth_key_mgmt_t *)((u8 *)wpa_ie +
339 					      sizeof(IEEEtypes_Wpa_t) +
340 					      (count - 1) * sizeof(wpa_suite));
341 	count = woal_le16_to_cpu(key_mgmt->count);
342 	if (left < (int)(sizeof(wpa_suite_auth_key_mgmt_t) +
343 			 (count - 1) * sizeof(wpa_suite)))
344 		return MFALSE;
345 	for (i = 0; i < count; i++) {
346 		switch (key_mgmt->list[i].type) {
347 		case RSN_AKM_8021X:
348 			sys_config->key_mgmt = KEY_MGMT_EAP;
349 			break;
350 		case RSN_AKM_PSK:
351 			sys_config->key_mgmt = KEY_MGMT_PSK;
352 			break;
353 		}
354 	}
355 	return MTRUE;
356 }
357 
358 /**
359  * @brief Find RSN/WPA IES
360  *
361  * @param ie              Pointer IE buffer
362  * @param sys_config      Pointer to mlan_uap_bss_param structure
363  *
364  * @return                MTRUE/MFALSE
365  */
woal_find_wpa_ies(const t_u8 * ie,int len,mlan_uap_bss_param * sys_config)366 static t_u8 woal_find_wpa_ies(const t_u8 *ie, int len,
367 			      mlan_uap_bss_param *sys_config)
368 {
369 	int bytes_left = len;
370 	const t_u8 *pcurrent_ptr = ie;
371 	t_u16 total_ie_len;
372 	t_u8 element_len;
373 	t_u8 wpa2 = 0;
374 	t_u8 wpa = 0;
375 	t_u8 ret = MFALSE;
376 	IEEEtypes_ElementId_e element_id;
377 	IEEEtypes_VendorSpecific_t *pvendor_ie;
378 	const t_u8 wpa_oui[4] = {0x00, 0x50, 0xf2, 0x01};
379 
380 	while (bytes_left >= 2) {
381 		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
382 		element_len = *((t_u8 *)pcurrent_ptr + 1);
383 		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
384 		if (bytes_left < total_ie_len) {
385 			PRINTM(MERROR,
386 			       "InterpretIE: Error in processing IE, bytes left < IE length\n");
387 			bytes_left = 0;
388 			continue;
389 		}
390 		switch (element_id) {
391 		case RSN_IE:
392 			wpa2 = woal_check_rsn_ie(
393 				(IEEEtypes_Rsn_t *)pcurrent_ptr, sys_config);
394 			break;
395 		case VENDOR_SPECIFIC_221:
396 			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
397 			if (!memcmp(pvendor_ie->vend_hdr.oui, wpa_oui,
398 				    sizeof(pvendor_ie->vend_hdr.oui)) &&
399 			    (pvendor_ie->vend_hdr.oui_type == wpa_oui[3])) {
400 				wpa = woal_check_wpa_ie(
401 					(IEEEtypes_Wpa_t *)pcurrent_ptr,
402 					sys_config);
403 			}
404 			break;
405 		default:
406 			break;
407 		}
408 		pcurrent_ptr += element_len + 2;
409 		/* Need to account for IE ID and IE Len */
410 		bytes_left -= (element_len + 2);
411 	}
412 	if (wpa && wpa2) {
413 		sys_config->protocol = PROTOCOL_WPA | PROTOCOL_WPA2;
414 		ret = MTRUE;
415 	} else if (wpa2) {
416 		sys_config->protocol = PROTOCOL_WPA2;
417 		ret = MTRUE;
418 	} else if (wpa) {
419 		sys_config->protocol = PROTOCOL_WPA;
420 		ret = MTRUE;
421 	}
422 	return ret;
423 }
424 
425 /**
426  * @brief Find and set WMM IES
427  *
428  * @param priv            Pointer to moal_private
429  * @param ie              Pointer IE buffer
430  * @param sys_config      Pointer to mlan_uap_bss_param structure
431  *
432  * @return                N/A
433  */
woal_set_wmm_ies(moal_private * priv,const t_u8 * ie,int len,mlan_uap_bss_param * sys_config)434 static t_void woal_set_wmm_ies(moal_private *priv, const t_u8 *ie, int len,
435 			       mlan_uap_bss_param *sys_config)
436 {
437 	int bytes_left = len;
438 	const t_u8 *pcurrent_ptr = ie;
439 	t_u16 total_ie_len;
440 	t_u8 element_len;
441 	IEEEtypes_VendorSpecific_t *pvendor_ie;
442 	IEEEtypes_ElementId_e element_id;
443 	const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
444 
445 	while (bytes_left >= 2) {
446 		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
447 		element_len = *((t_u8 *)pcurrent_ptr + 1);
448 		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
449 		if (bytes_left < total_ie_len) {
450 			PRINTM(MERROR,
451 			       "InterpretIE: Error in processing IE, bytes left < IE length\n");
452 			bytes_left = 0;
453 			continue;
454 		}
455 		switch (element_id) {
456 		case VENDOR_SPECIFIC_221:
457 			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
458 			if (!memcmp(pvendor_ie->vend_hdr.oui, wmm_oui,
459 				    sizeof(pvendor_ie->vend_hdr.oui)) &&
460 			    pvendor_ie->vend_hdr.oui_type == wmm_oui[3]) {
461 				if (total_ie_len ==
462 				    sizeof(IEEEtypes_WmmParameter_t)) {
463 					/*
464 					 * Only accept and copy the WMM IE if
465 					 * it matches the size expected for the
466 					 * WMM Parameter IE.
467 					 */
468 					moal_memcpy_ext(
469 						priv->phandle,
470 						&sys_config->wmm_para,
471 						pcurrent_ptr +
472 							sizeof(IEEEtypes_Header_t),
473 						element_len,
474 						sizeof(sys_config->wmm_para));
475 					/** set uap_host_based_config to true */
476 					sys_config->uap_host_based_config =
477 						MTRUE;
478 				}
479 			}
480 
481 			break;
482 		default:
483 			break;
484 		}
485 		pcurrent_ptr += element_len + 2;
486 		/* Need to account for IE ID and IE Len */
487 		bytes_left -= (element_len + 2);
488 	}
489 }
490 
491 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
492 /**
493  * @brief initialize AP or GO bss config
494  * @param priv            A pointer to moal private structure
495  * @param band		  BAND_2GHZ/BAND_5GHZ
496  * @param params          A pointer to cfg80211_ap_settings structure
497  * @return                0 -- success, otherwise fail
498  */
woal_check_11ac_capability(moal_private * priv,t_u8 band,struct cfg80211_ap_settings * params)499 static t_u8 woal_check_11ac_capability(moal_private *priv, t_u8 band,
500 				       struct cfg80211_ap_settings *params)
501 #else
502 /**
503  * @brief initialize AP or GO bss config
504  * @param band		  BAND_2GHZ/BAND_5GHZ
505  * @param priv            A pointer to moal private structure
506  * @return                0 -- success, otherwise fail
507  */
508 static t_u8 woal_check_11ac_capability(moal_private *priv, t_u8 band)
509 #endif
510 {
511 	mlan_fw_info fw_info;
512 	t_u8 enable_11ac = MFALSE;
513 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
514 	const u8 *vht_ie = NULL;
515 #endif
516 	ENTER();
517 	memset(&fw_info, 0, sizeof(mlan_fw_info));
518 	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
519 	if ((band == BAND_5GHZ) && !(fw_info.fw_bands & BAND_AAC)) {
520 		PRINTM(MCMND, "FW don't support 5G AC");
521 		LEAVE();
522 		return enable_11ac;
523 	}
524 	if ((band == BAND_2GHZ) && !(fw_info.fw_bands & BAND_GAC)) {
525 		PRINTM(MCMND, "FW don't support 2G AC");
526 		LEAVE();
527 		return enable_11ac;
528 	}
529 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
530 	vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail,
531 				  params->beacon.tail_len);
532 	if (vht_ie)
533 		enable_11ac = MTRUE;
534 	else
535 		enable_11ac = MFALSE;
536 #else
537 	enable_11ac = MTRUE;
538 #endif
539 	LEAVE();
540 	return enable_11ac;
541 }
542 
543 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
544 /**
545  * @brief initialize AP or GO bss config
546  * @param priv            A pointer to moal private structure
547  * @param band            BAND_5G/BAND_2GHZ
548  * @param params          A pointer to cfg80211_ap_settings structure
549  * @return                0 -- success, otherwise fail
550  */
woal_check_11ax_capability(moal_private * priv,t_u8 band,struct cfg80211_ap_settings * params)551 static t_u8 woal_check_11ax_capability(moal_private *priv, t_u8 band,
552 				       struct cfg80211_ap_settings *params)
553 {
554 	mlan_fw_info fw_info;
555 	t_u8 enable_11ax = MFALSE;
556 #if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 20, 0)
557 	mlan_ds_11ax_he_cfg he_cfg;
558 	t_u8 he_txrx_mcs_support[4] = {0xff, 0xff, 0xff, 0xff};
559 #endif
560 	ENTER();
561 	memset(&fw_info, 0, sizeof(mlan_fw_info));
562 	woal_request_get_fw_info(priv, MOAL_IOCTL_WAIT, &fw_info);
563 	if ((band == BAND_5GHZ) && !(fw_info.fw_bands & BAND_AAX)) {
564 		PRINTM(MCMND, "FW don't support 5G AX\n");
565 		LEAVE();
566 		return enable_11ax;
567 	}
568 	if ((band == BAND_2GHZ) && !(fw_info.fw_bands & BAND_GAX)) {
569 		PRINTM(MCMND, "FW don't support 2G AX");
570 		LEAVE();
571 		return enable_11ax;
572 	}
573 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
574 	if (params->he_cap)
575 		enable_11ax = MTRUE;
576 	else
577 		enable_11ax = MFALSE;
578 #else
579 	memset(&he_cfg, 0, sizeof(he_cfg));
580 	if (band == BAND_5GHZ)
581 		he_cfg.band = MBIT(1);
582 	else if (band == BAND_2GHZ)
583 		he_cfg.band = MBIT(0);
584 	if (0 == woal_11ax_cfg(priv, MLAN_ACT_GET, &he_cfg)) {
585 		if (he_cfg.he_cap.len &&
586 		    (he_cfg.he_cap.ext_id == HE_CAPABILITY)) {
587 			if (memcmp(he_cfg.he_cap.he_txrx_mcs_support,
588 				   he_txrx_mcs_support,
589 				   sizeof(he_txrx_mcs_support)))
590 				enable_11ax = MTRUE;
591 		}
592 	}
593 #endif
594 	PRINTM(MCMND, "enable_11ax=%d\n", enable_11ax);
595 	LEAVE();
596 	return enable_11ax;
597 }
598 #endif
599 
600 /**
601  * @brief get ht_cap from beacon ie
602  *
603  * @param ie              Pointer to IEs
604  * @param len             Total length of ie
605  *
606  * @return                ht_cap
607  */
woal_get_htcap_info(const t_u8 * ie,int len)608 static t_u16 woal_get_htcap_info(const t_u8 *ie, int len)
609 {
610 	t_u16 ht_cap_info = 0;
611 	IEEEtypes_HTCap_t *htcap_ie = NULL;
612 	htcap_ie =
613 		(IEEEtypes_HTCap_t *)woal_parse_ie_tlv(ie, len, HT_CAPABILITY);
614 	if (htcap_ie) {
615 		/* hostap has converted ht_cap_info to little endian, here
616 		 * conver to host endian */
617 		ht_cap_info = woal_le16_to_cpu(htcap_ie->ht_cap.ht_cap_info);
618 		PRINTM(MINFO, "Get ht_cap from beacon ies: 0x%x\n",
619 		       ht_cap_info);
620 	}
621 	return ht_cap_info;
622 }
623 
624 /**
625  * @brief get vht_cap from beacon ie
626  *
627  * @param ie              Pointer to IEs
628  * @param len             Total length of ie
629  *
630  * @return                Pointer to vht_cap ie
631  */
woal_get_vhtcap_info(const t_u8 * ie,int len)632 static IEEEtypes_VHTCap_t *woal_get_vhtcap_info(const t_u8 *ie, int len)
633 {
634 	IEEEtypes_VHTCap_t *vhtcap_ie = NULL;
635 	vhtcap_ie = (IEEEtypes_VHTCap_t *)woal_parse_ie_tlv(ie, len,
636 							    VHT_CAPABILITY);
637 	if (vhtcap_ie)
638 		PRINTM(MMSG, "Get vht_cap from beacon ies: 0x%x\n",
639 		       vhtcap_ie->vht_cap.vht_cap_info);
640 	return vhtcap_ie;
641 }
642 
643 /**
644  * @brief get vht_oper from beacon ie
645  *
646  * @param ie              Pointer to IEs
647  * @param len             Total length of ie
648  *
649  * @return                Pointer to vht_opr ie
650  */
woal_get_vht_oprat_ie(const t_u8 * ie,int len)651 static IEEEtypes_VHTOprat_t *woal_get_vht_oprat_ie(const t_u8 *ie, int len)
652 {
653 	IEEEtypes_VHTOprat_t *vht_oprat_ie = NULL;
654 	vht_oprat_ie = (IEEEtypes_VHTOprat_t *)woal_parse_ie_tlv(ie, len,
655 								 VHT_OPERATION);
656 	if (vht_oprat_ie)
657 		PRINTM(MMSG,
658 		       "Get vht_oprat_ie from beacon ies: chan_width=%d\n",
659 		       vht_oprat_ie->chan_width);
660 	return vht_oprat_ie;
661 }
662 
663 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
664 /** Starting Frequency for 11A band */
665 #define START_FREQ_11A_BAND 5000 /* in MHz */
666 /**
667  * @brief convert cfg80211_chan_def to Band_Config
668  *
669  * @param priv            A pointer to moal private structure
670  * @param bandcfg         A pointer to (Band_Config_t structure
671  * @param chandef         A pointer to cfg80211_chan_def structure
672  *
673  * @return                N/A
674  */
woal_convert_chan_to_bandconfig(moal_private * priv,Band_Config_t * bandcfg,struct cfg80211_chan_def * chandef)675 static void woal_convert_chan_to_bandconfig(moal_private *priv,
676 					    Band_Config_t *bandcfg,
677 					    struct cfg80211_chan_def *chandef)
678 {
679 	ENTER();
680 	memset(bandcfg, 0, sizeof(Band_Config_t));
681 	switch (chandef->chan->band) {
682 	case NL80211_BAND_2GHZ:
683 		bandcfg->chanBand = BAND_2GHZ;
684 		break;
685 	case NL80211_BAND_5GHZ:
686 		bandcfg->chanBand = BAND_5GHZ;
687 		break;
688 	default:
689 		break;
690 	}
691 	switch (chandef->width) {
692 	case NL80211_CHAN_WIDTH_20_NOHT:
693 	case NL80211_CHAN_WIDTH_20:
694 		bandcfg->chanWidth = CHAN_BW_20MHZ;
695 		break;
696 	case NL80211_CHAN_WIDTH_40:
697 		bandcfg->chanWidth = CHAN_BW_40MHZ;
698 		if (chandef->center_freq1 > chandef->chan->center_freq)
699 			bandcfg->chan2Offset = SEC_CHAN_ABOVE;
700 		else
701 			bandcfg->chan2Offset = SEC_CHAN_BELOW;
702 		break;
703 	case NL80211_CHAN_WIDTH_80:
704 		bandcfg->chan2Offset = woal_get_second_channel_offset(
705 			priv, chandef->chan->hw_value);
706 		bandcfg->chanWidth = CHAN_BW_80MHZ;
707 		break;
708 	case NL80211_CHAN_WIDTH_80P80:
709 	case NL80211_CHAN_WIDTH_160:
710 	default:
711 		break;
712 	}
713 	PRINTM(MCMND,
714 	       "cfg80211 AP: channel=%d, chanBand=0x%x chanWidth=0x%x chan2Offset=0x%x\n",
715 	       chandef->chan->hw_value, bandcfg->chanBand, bandcfg->chanWidth,
716 	       bandcfg->chan2Offset);
717 	LEAVE();
718 	return;
719 }
720 #endif
721 
722 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
723 /**
724  * @brief Enable radar detect for DFS channel
725  *
726  * @param priv            A pointer to moal private structure
727  * @param chandef         A pointer to cfg80211_chan_def structure
728  * @return                N/A
729  */
woal_enable_dfs_support(moal_private * priv,struct cfg80211_chan_def * chandef)730 static void woal_enable_dfs_support(moal_private *priv,
731 				    struct cfg80211_chan_def *chandef)
732 {
733 	mlan_ioctl_req *req = NULL;
734 	mlan_ds_11h_chan_rep_req *pchan_rpt_req = NULL;
735 	mlan_ds_11h_cfg *p11h_cfg = NULL;
736 	mlan_status status = MLAN_STATUS_SUCCESS;
737 	ENTER();
738 	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) {
739 		PRINTM(MIOCTL, "No radar channel\n");
740 		LEAVE();
741 		return;
742 	}
743 	PRINTM(MIOCTL, "start Radar detect, chan %d , Bw %d \n",
744 	       chandef->chan->hw_value, chandef->width);
745 
746 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
747 	if (NULL == req) {
748 		PRINTM(MIOCTL, "No Memory to allocate ioctl buffer\n");
749 		LEAVE();
750 		return;
751 	}
752 	p11h_cfg = (mlan_ds_11h_cfg *)req->pbuf;
753 	pchan_rpt_req = &p11h_cfg->param.chan_rpt_req;
754 	pchan_rpt_req->startFreq = 5000;
755 	pchan_rpt_req->chanNum = (t_u8)chandef->chan->hw_value;
756 	woal_convert_chan_to_bandconfig(priv, &pchan_rpt_req->bandcfg, chandef);
757 	pchan_rpt_req->host_based = MTRUE;
758 	pchan_rpt_req->millisec_dwell_time = 0;
759 
760 	p11h_cfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
761 	req->req_id = MLAN_IOCTL_11H_CFG;
762 	req->action = MLAN_ACT_SET;
763 	/* Send Channel Check command and wait until the report is ready */
764 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
765 	if (status != MLAN_STATUS_PENDING)
766 		kfree(req);
767 	LEAVE();
768 	return;
769 }
770 #endif
771 
772 /**
773  * @brief Prase supported rates from beacon data, set bss cfg accordingly
774  *
775  * @param priv                  A pointer to moal_private
776  * @param bss_cfg            A pointer to bss configuration structure
777  * @param head_ie            A pointer to beacon head IE buffer
778  * @param head_len           head IE buffer length
779  * @param tail_ie            A pointer to beacon tail IE buffer
780  * @param tail_len           tail IE buffer length *
781  * @return                   N/A
782  */
woal_set_uap_rates(moal_private * priv,mlan_uap_bss_param * bss_cfg,const t_u8 * head_ie,int head_len,const t_u8 * tail_ie,int tail_len)783 static void woal_set_uap_rates(moal_private *priv, mlan_uap_bss_param *bss_cfg,
784 			       const t_u8 *head_ie, int head_len,
785 			       const t_u8 *tail_ie, int tail_len)
786 {
787 	pIEEEtypes_Header_t rate_ie;
788 	pIEEEtypes_Header_t ext_rate_ie;
789 	int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable);
790 	const u8 *var_pos = head_ie + var_offset;
791 	int len = head_len - var_offset;
792 	int rate_len = 0;
793 
794 	rate_ie = (void *)woal_parse_ie_tlv(var_pos, len, WLAN_EID_SUPP_RATES);
795 	if (rate_ie) {
796 		memset(bss_cfg->rates, 0, sizeof(bss_cfg->rates));
797 		moal_memcpy_ext(priv->phandle, bss_cfg->rates, rate_ie + 1,
798 				rate_ie->len, sizeof(bss_cfg->rates));
799 		rate_len = MIN(rate_ie->len, sizeof(bss_cfg->rates));
800 	}
801 	ext_rate_ie = (void *)woal_parse_ie_tlv(tail_ie, tail_len,
802 						WLAN_EID_EXT_SUPP_RATES);
803 	if (ext_rate_ie) {
804 		moal_memcpy_ext(priv->phandle, &bss_cfg->rates[rate_len],
805 				ext_rate_ie + 1, ext_rate_ie->len,
806 				sizeof(bss_cfg->rates) - rate_len);
807 		rate_len += MIN(ext_rate_ie->len,
808 				(sizeof(bss_cfg->rates) - rate_len));
809 	}
810 	DBG_HEXDUMP(MCMD_D, "rates", bss_cfg->rates, sizeof(bss_cfg->rates));
811 }
812 
813 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
814 /**
815  * @brief initialize AP or GO bss config
816  *
817  * @param priv            A pointer to moal private structure
818  * @param params          A pointer to cfg80211_ap_settings structure
819  * @return                0 -- success, otherwise fail
820  */
woal_cfg80211_beacon_config(moal_private * priv,struct cfg80211_ap_settings * params)821 static int woal_cfg80211_beacon_config(moal_private *priv,
822 				       struct cfg80211_ap_settings *params)
823 #else
824 /**
825  * @brief initialize AP or GO bss config
826  *
827  * @param priv            A pointer to moal private structure
828  * @param params          A pointer to beacon_parameters structure
829  * @return                0 -- success, otherwise fail
830  */
831 static int woal_cfg80211_beacon_config(moal_private *priv,
832 				       struct beacon_parameters *params)
833 #endif
834 {
835 	struct wiphy *wiphy = NULL;
836 	const t_u8 *ie = NULL;
837 	int ret = 0, ie_len;
838 	mlan_uap_bss_param *sys_config = NULL;
839 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
840 	int i = 0;
841 #else
842 	t_u8 wpa_ies;
843 	const t_u8 *ssid_ie = NULL;
844 	struct ieee80211_mgmt *head = NULL;
845 	t_u16 capab_info = 0;
846 #endif
847 	t_u8 rates_bg[13] = {0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18,
848 			     0x24, 0x30, 0x48, 0x60, 0x6c, 0x00};
849 	t_u8 rates_a[9] = {0x8c, 0x12, 0x98, 0x24, 0xb0,
850 			   0x48, 0x60, 0x6c, 0x00};
851 #ifdef WIFI_DIRECT_SUPPORT
852 	t_u8 rates_wfd[9] = {0x8c, 0x12, 0x18, 0x24, 0x30,
853 			     0x48, 0x60, 0x6c, 0x00};
854 #endif
855 	t_u8 chan2Offset = SEC_CHAN_NONE;
856 	t_u8 enable_11n = MTRUE;
857 	t_u16 ht_cap = 0;
858 	t_u8 enable_11ac = MFALSE;
859 	t_u8 vht20_40 = MFALSE;
860 	IEEEtypes_VHTCap_t *vhtcap_ie = NULL;
861 	IEEEtypes_VHTOprat_t *vhtopr_ie = NULL;
862 	IEEEtypes_HECap_t *hecap_ie = NULL;
863 	t_u8 enable_11ax = MFALSE;
864 	t_u8 *wapi_ie = NULL;
865 	int wapi_ie_len = 0;
866 #ifdef WIFI_DIRECT_SUPPORT
867 	int GoAgeoutTime = priv->phandle->params.GoAgeoutTime;
868 #endif
869 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
870 	Band_Config_t bandcfg;
871 #endif
872 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
873 	mlan_ds_11h_chan_nop_info chan_nop_info;
874 #endif
875 	ENTER();
876 
877 	if (!params) {
878 		ret = -EFAULT;
879 		goto done;
880 	}
881 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
882 	ie = ((struct cfg80211_ap_settings *)params)->beacon.tail;
883 	ie_len = ((struct cfg80211_ap_settings *)params)->beacon.tail_len;
884 #else
885 	ie = ((struct beacon_parameters *)params)->tail;
886 	ie_len = ((struct beacon_parameters *)params)->tail_len;
887 #endif
888 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
889 	wapi_ie = (t_u8 *)woal_parse_ie_tlv(params->beacon.tail,
890 					    params->beacon.tail_len, WAPI_IE);
891 #else
892 	wapi_ie = (t_u8 *)woal_parse_ie_tlv(params->tail, params->tail_len,
893 					    WAPI_IE);
894 #endif
895 	if (wapi_ie) {
896 		wapi_ie_len = *(wapi_ie + 1) + 2;
897 		if (MLAN_STATUS_FAILURE ==
898 		    woal_set_get_gen_ie(priv, MLAN_ACT_SET, wapi_ie,
899 					&wapi_ie_len, MOAL_IOCTL_WAIT)) {
900 			PRINTM(MERROR, "Failed to set wapi ie\n");
901 			ret = -EFAULT;
902 			goto done;
903 		}
904 	}
905 
906 	wiphy = priv->phandle->wiphy;
907 	if (priv->bss_type != MLAN_BSS_TYPE_UAP
908 #ifdef WIFI_DIRECT_SUPPORT
909 	    && priv->bss_type != MLAN_BSS_TYPE_WIFIDIRECT
910 #endif
911 	) {
912 		ret = -EFAULT;
913 		goto done;
914 	}
915 	sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
916 	if (!sys_config) {
917 		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
918 		ret = -EFAULT;
919 		goto done;
920 	}
921 
922 	/* Initialize the uap bss values which are uploaded from firmware */
923 	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
924 							   MOAL_IOCTL_WAIT,
925 							   sys_config)) {
926 		PRINTM(MERROR, "Error getting AP confiruration\n");
927 		ret = -EFAULT;
928 		goto done;
929 	}
930 
931 	if (priv->phandle->params.uap_max_sta)
932 		sys_config->max_sta_count = priv->phandle->params.uap_max_sta;
933 
934 	/* Setting the default values */
935 	sys_config->channel = 6;
936 	sys_config->preamble_type = 0;
937 	sys_config->mgmt_ie_passthru_mask = priv->mgmt_subtype_mask;
938 	moal_memcpy_ext(priv->phandle, sys_config->mac_addr, priv->current_addr,
939 			ETH_ALEN, sizeof(sys_config->mac_addr));
940 
941 #ifdef WIFI_DIRECT_SUPPORT
942 	if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT && GoAgeoutTime) {
943 		sys_config->sta_ageout_timer = GoAgeoutTime;
944 		sys_config->ps_sta_ageout_timer = GoAgeoutTime;
945 	}
946 #endif
947 	/* Set frag_threshold, rts_threshold, and retry limit */
948 	sys_config->frag_threshold = wiphy->frag_threshold;
949 	sys_config->rts_threshold = wiphy->rts_threshold;
950 	sys_config->retry_limit = wiphy->retry_long;
951 	if (sys_config->frag_threshold == (t_u16)MLAN_FRAG_RTS_DISABLED) {
952 		sys_config->frag_threshold = MLAN_FRAG_MAX_VALUE;
953 	}
954 	if (sys_config->rts_threshold == (t_u16)MLAN_FRAG_RTS_DISABLED) {
955 		sys_config->rts_threshold = MLAN_RTS_MAX_VALUE;
956 	}
957 
958 	if (priv->bss_type == MLAN_BSS_TYPE_UAP) {
959 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
960 		if (params->beacon_interval)
961 			sys_config->beacon_period = params->beacon_interval;
962 #else
963 		if (params->interval)
964 			sys_config->beacon_period = params->interval;
965 #endif
966 		if (params->dtim_period)
967 			sys_config->dtim_period = params->dtim_period;
968 	}
969 
970 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
971 	/** back up ap's channel */
972 	moal_memcpy_ext(priv->phandle, &priv->chan, &params->chandef,
973 			sizeof(struct cfg80211_chan_def), sizeof(priv->chan));
974 #endif
975 
976 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
977 	woal_convert_chan_to_bandconfig(priv, &bandcfg, &params->chandef);
978 #endif
979 
980 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
981 	if (priv->phandle->usr_nop_period_sec) {
982 		PRINTM(MCMND, "Checking if AP's channel %d is under NOP\n",
983 		       priv->channel);
984 		memset(&chan_nop_info, 0, sizeof(chan_nop_info));
985 		chan_nop_info.curr_chan = priv->channel;
986 		chan_nop_info.chan_width = bandcfg.chanWidth;
987 		if (params->chandef.width >= NL80211_CHAN_WIDTH_20)
988 			chan_nop_info.new_chan.is_11n_enabled = MTRUE;
989 		chan_nop_info.new_chan.bandcfg = bandcfg;
990 		chan_nop_info.check_new_chan = MTRUE;
991 		woal_uap_get_channel_nop_info(priv, MOAL_IOCTL_WAIT,
992 					      &chan_nop_info);
993 		if (chan_nop_info.chan_under_nop) {
994 			PRINTM(MCMND,
995 			       "cfg80211: Channel %d is under NOP, New channel=%d\n",
996 			       priv->channel, chan_nop_info.new_chan.channel);
997 			priv->chan_under_nop = chan_nop_info.chan_under_nop;
998 			priv->channel = chan_nop_info.new_chan.channel;
999 			woal_chandef_create(priv, &priv->chan,
1000 					    &chan_nop_info.new_chan);
1001 		}
1002 	}
1003 #endif
1004 
1005 	if (priv->channel) {
1006 		memset(sys_config->rates, 0, sizeof(sys_config->rates));
1007 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
1008 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1009 		switch (priv->chan.width) {
1010 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 11, 0)
1011 		case NL80211_CHAN_WIDTH_5:
1012 		case NL80211_CHAN_WIDTH_10:
1013 #endif
1014 		case NL80211_CHAN_WIDTH_20_NOHT:
1015 			enable_11n = MFALSE;
1016 			break;
1017 		case NL80211_CHAN_WIDTH_20:
1018 			break;
1019 		case NL80211_CHAN_WIDTH_40:
1020 			if (priv->chan.center_freq1 <
1021 			    priv->chan.chan->center_freq)
1022 				chan2Offset = SEC_CHAN_BELOW;
1023 			else
1024 				chan2Offset = SEC_CHAN_ABOVE;
1025 			break;
1026 		case NL80211_CHAN_WIDTH_80:
1027 		case NL80211_CHAN_WIDTH_80P80:
1028 		case NL80211_CHAN_WIDTH_160:
1029 			chan2Offset = woal_get_second_channel_offset(
1030 				priv, priv->channel);
1031 			break;
1032 		default:
1033 			PRINTM(MWARN, "Unknown channel width: %d\n",
1034 			       priv->chan.width);
1035 			break;
1036 		}
1037 #else
1038 		switch (params->channel_type) {
1039 		case NL80211_CHAN_NO_HT:
1040 			enable_11n = MFALSE;
1041 			break;
1042 		case NL80211_CHAN_HT20:
1043 			break;
1044 		case NL80211_CHAN_HT40PLUS:
1045 			chan2Offset = SEC_CHAN_ABOVE;
1046 			break;
1047 		case NL80211_CHAN_HT40MINUS:
1048 			chan2Offset = SEC_CHAN_BELOW;
1049 			break;
1050 		default:
1051 			PRINTM(MWARN, "Unknown channel type: %d\n",
1052 			       params->channel_type);
1053 			break;
1054 		}
1055 #endif
1056 #endif /* CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
1057 
1058 		sys_config->channel = priv->channel;
1059 		if (priv->channel <= MAX_BG_CHANNEL) {
1060 			sys_config->bandcfg.chanBand = BAND_2GHZ;
1061 #ifdef WIFI_DIRECT_SUPPORT
1062 			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
1063 				moal_memcpy_ext(priv->phandle,
1064 						sys_config->rates, rates_wfd,
1065 						sizeof(rates_wfd),
1066 						sizeof(sys_config->rates));
1067 			else
1068 #endif
1069 				moal_memcpy_ext(priv->phandle,
1070 						sys_config->rates, rates_bg,
1071 						sizeof(rates_bg),
1072 						sizeof(sys_config->rates));
1073 		} else {
1074 			sys_config->bandcfg.chanBand = BAND_5GHZ;
1075 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
1076 			chan2Offset = woal_get_second_channel_offset(
1077 				priv, priv->channel);
1078 #endif
1079 
1080 #ifdef WIFI_DIRECT_SUPPORT
1081 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
1082 			/* Force enable 40MHZ on WFD interface */
1083 			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
1084 				chan2Offset = woal_get_second_channel_offset(
1085 					priv, priv->channel);
1086 #endif
1087 #endif
1088 #ifdef WIFI_DIRECT_SUPPORT
1089 			if (priv->bss_type == MLAN_BSS_TYPE_WIFIDIRECT)
1090 				moal_memcpy_ext(priv->phandle,
1091 						sys_config->rates, rates_wfd,
1092 						sizeof(rates_wfd),
1093 						sizeof(sys_config->rates));
1094 			else
1095 #endif
1096 				moal_memcpy_ext(priv->phandle,
1097 						sys_config->rates, rates_a,
1098 						sizeof(rates_a),
1099 						sizeof(sys_config->rates));
1100 		}
1101 
1102 		/* Replaced with rate from userspace, if exist */
1103 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1104 		woal_set_uap_rates(priv, sys_config, params->beacon.head,
1105 				   params->beacon.head_len, params->beacon.tail,
1106 				   params->beacon.tail_len);
1107 #else
1108 		woal_set_uap_rates(priv, sys_config, params->head,
1109 				   params->head_len, params->tail,
1110 				   params->tail_len);
1111 #endif
1112 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
1113 		moal_memcpy_ext(priv->phandle, &sys_config->bandcfg, &bandcfg,
1114 				sizeof(bandcfg), sizeof(bandcfg));
1115 #endif
1116 
1117 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1118 		enable_11ac = woal_check_11ac_capability(
1119 			priv, sys_config->bandcfg.chanBand, params);
1120 		if (enable_11ac &&
1121 		    ((priv->chan.width == NL80211_CHAN_WIDTH_20) ||
1122 		     (priv->chan.width == NL80211_CHAN_WIDTH_40)))
1123 			vht20_40 = MTRUE;
1124 #else
1125 		enable_11ac = woal_check_11ac_capability(
1126 			priv, sys_config->bandcfg.chanBand);
1127 #endif
1128 
1129 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1130 		enable_11ax = woal_check_11ax_capability(
1131 			priv, sys_config->bandcfg.chanBand, params);
1132 #endif
1133 
1134 		/* Disable GreenField by default */
1135 		sys_config->ht_cap_info = 0x10c;
1136 		if (enable_11n)
1137 			sys_config->ht_cap_info |= 0x20;
1138 		if (chan2Offset) {
1139 			sys_config->bandcfg.chan2Offset = chan2Offset;
1140 			sys_config->ht_cap_info |= 0x1042;
1141 			sys_config->ampdu_param = 3;
1142 		} else {
1143 			sys_config->bandcfg.chan2Offset = 0;
1144 		}
1145 		ht_cap = woal_get_htcap_info(ie, ie_len);
1146 		if (ht_cap) {
1147 			if (sys_config->bandcfg.chanBand == BAND_2GHZ)
1148 				sys_config->ht_cap_info =
1149 					(ht_cap &
1150 					 (wiphy->bands[IEEE80211_BAND_2GHZ]
1151 						  ->ht_cap.cap &
1152 					  0x13ff)) |
1153 					0x0c;
1154 			else
1155 				sys_config->ht_cap_info =
1156 					(ht_cap &
1157 					 (wiphy->bands[IEEE80211_BAND_5GHZ]
1158 						  ->ht_cap.cap &
1159 					  0x13ff)) |
1160 					0x0c;
1161 		}
1162 		PRINTM(MCMND,
1163 		       "11n=%d, ht_cap=0x%x, channel=%d, bandcfg:chanBand=0x%x chanWidth=0x%x chan2Offset=0x%x scanMode=0x%x\n",
1164 		       enable_11n, sys_config->ht_cap_info, priv->channel,
1165 		       sys_config->bandcfg.chanBand,
1166 		       sys_config->bandcfg.chanWidth,
1167 		       sys_config->bandcfg.chan2Offset,
1168 		       sys_config->bandcfg.scanMode);
1169 	}
1170 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
1171 	if (!params->ssid || !params->ssid_len) {
1172 		ret = -EINVAL;
1173 		goto done;
1174 	}
1175 	moal_memcpy_ext(priv->phandle, sys_config->ssid.ssid, params->ssid,
1176 			MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len),
1177 			sizeof(sys_config->ssid.ssid));
1178 	sys_config->ssid.ssid_len = MIN(MLAN_MAX_SSID_LENGTH, params->ssid_len);
1179 	/**
1180 	 * hidden_ssid=0: broadcast SSID in beacons.
1181 	 * hidden_ssid=1: send empty SSID (length=0) in beacon.
1182 	 * hidden_ssid=2: clear SSID (ACSII 0), but keep the original length
1183 	 */
1184 	if (!params->hidden_ssid)
1185 		sys_config->bcast_ssid_ctl = 1;
1186 	else if (params->hidden_ssid == 1)
1187 		sys_config->bcast_ssid_ctl = 0;
1188 	else if (params->hidden_ssid == 2)
1189 		sys_config->bcast_ssid_ctl = 2;
1190 	switch (params->auth_type) {
1191 	case NL80211_AUTHTYPE_SHARED_KEY:
1192 		sys_config->auth_mode = MLAN_AUTH_MODE_SHARED;
1193 		break;
1194 	case NL80211_AUTHTYPE_AUTOMATIC:
1195 		sys_config->auth_mode = MLAN_AUTH_MODE_AUTO;
1196 		break;
1197 	case NL80211_AUTHTYPE_OPEN_SYSTEM:
1198 	default:
1199 		sys_config->auth_mode = MLAN_AUTH_MODE_OPEN;
1200 		break;
1201 	}
1202 
1203 	sys_config->protocol = PROTOCOL_NO_SECURITY;
1204 	if ((params->crypto.wpa_versions & NL80211_WPA_VERSION_1) &&
1205 	    (params->crypto.wpa_versions & NL80211_WPA_VERSION_2))
1206 		sys_config->protocol = PROTOCOL_WPA | PROTOCOL_WPA2;
1207 	else if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1208 		sys_config->protocol = PROTOCOL_WPA2;
1209 	else if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1210 		sys_config->protocol = PROTOCOL_WPA;
1211 	if (params->crypto.n_akm_suites ||
1212 	    (params->privacy && params->crypto.wpa_versions))
1213 		woal_find_wpa_ies(ie, ie_len, sys_config);
1214 	for (i = 0; i < params->crypto.n_akm_suites; i++) {
1215 		switch (params->crypto.akm_suites[i]) {
1216 		case WLAN_AKM_SUITE_8021X:
1217 			sys_config->key_mgmt |= KEY_MGMT_EAP;
1218 			break;
1219 		case WLAN_AKM_SUITE_PSK:
1220 			sys_config->key_mgmt |= KEY_MGMT_PSK;
1221 			break;
1222 		}
1223 	}
1224 	sys_config->wpa_cfg.pairwise_cipher_wpa = 0;
1225 	sys_config->wpa_cfg.pairwise_cipher_wpa2 = 0;
1226 	for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) {
1227 		switch (params->crypto.ciphers_pairwise[i]) {
1228 		case WLAN_CIPHER_SUITE_WEP40:
1229 		case WLAN_CIPHER_SUITE_WEP104:
1230 			break;
1231 		case WLAN_CIPHER_SUITE_TKIP:
1232 			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1233 				sys_config->wpa_cfg.pairwise_cipher_wpa |=
1234 					CIPHER_TKIP;
1235 			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1236 				sys_config->wpa_cfg.pairwise_cipher_wpa2 |=
1237 					CIPHER_TKIP;
1238 			break;
1239 		case WLAN_CIPHER_SUITE_CCMP:
1240 			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1)
1241 				sys_config->wpa_cfg.pairwise_cipher_wpa |=
1242 					CIPHER_AES_CCMP;
1243 			if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2)
1244 				sys_config->wpa_cfg.pairwise_cipher_wpa2 |=
1245 					CIPHER_AES_CCMP;
1246 			break;
1247 		case WLAN_CIPHER_SUITE_SMS4:
1248 			sys_config->protocol = PROTOCOL_WAPI;
1249 			break;
1250 		}
1251 	}
1252 	switch (params->crypto.cipher_group) {
1253 	case WLAN_CIPHER_SUITE_WEP40:
1254 	case WLAN_CIPHER_SUITE_WEP104:
1255 		if ((priv->cipher == WLAN_CIPHER_SUITE_WEP40) ||
1256 		    (priv->cipher == WLAN_CIPHER_SUITE_WEP104)) {
1257 			sys_config->protocol = PROTOCOL_STATIC_WEP;
1258 			sys_config->key_mgmt = KEY_MGMT_NONE;
1259 			sys_config->wpa_cfg.length = 0;
1260 			moal_memcpy_ext(priv->phandle,
1261 					&sys_config->wep_cfg.key0,
1262 					&priv->uap_wep_key[0], sizeof(wep_key),
1263 					sizeof(sys_config->wep_cfg.key0));
1264 			moal_memcpy_ext(priv->phandle,
1265 					&sys_config->wep_cfg.key1,
1266 					&priv->uap_wep_key[1], sizeof(wep_key),
1267 					sizeof(sys_config->wep_cfg.key1));
1268 			moal_memcpy_ext(priv->phandle,
1269 					&sys_config->wep_cfg.key2,
1270 					&priv->uap_wep_key[2], sizeof(wep_key),
1271 					sizeof(sys_config->wep_cfg.key2));
1272 			moal_memcpy_ext(priv->phandle,
1273 					&sys_config->wep_cfg.key3,
1274 					&priv->uap_wep_key[3], sizeof(wep_key),
1275 					sizeof(sys_config->wep_cfg.key3));
1276 		}
1277 		break;
1278 	case WLAN_CIPHER_SUITE_TKIP:
1279 		sys_config->wpa_cfg.group_cipher = CIPHER_TKIP;
1280 		break;
1281 	case WLAN_CIPHER_SUITE_CCMP:
1282 		sys_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP;
1283 		break;
1284 	case WLAN_CIPHER_SUITE_SMS4:
1285 		sys_config->protocol = PROTOCOL_WAPI;
1286 		break;
1287 	}
1288 #else
1289 /* Since in Android ICS 4.0.1's wpa_supplicant, there is no way to set ssid
1290  * when GO (AP) starts up, so get it from beacon head parameter
1291  * TODO: right now use hard code
1292  * 24 -- ieee80211 header lenth, 12 -- fixed element length for beacon
1293  */
1294 #define BEACON_IE_OFFSET 36
1295 	/* Find SSID in head
1296 	 * SSID IE id: 0, right now use hard code
1297 	 */
1298 	ssid_ie = woal_parse_ie_tlv(params->head + BEACON_IE_OFFSET,
1299 				    params->head_len - BEACON_IE_OFFSET, 0);
1300 
1301 	if (!ssid_ie) {
1302 		PRINTM(MERROR, "No ssid IE found.\n");
1303 		ret = -EFAULT;
1304 		goto done;
1305 	}
1306 	if (*(ssid_ie + 1) > 32) {
1307 		PRINTM(MERROR, "ssid len error: %d\n", *(ssid_ie + 1));
1308 		ret = -EFAULT;
1309 		goto done;
1310 	}
1311 	moal_memcpy_ext(priv->phandle, sys_config->ssid.ssid, ssid_ie + 2,
1312 			*(ssid_ie + 1), sizeof(sys_config->ssid.ssid));
1313 	sys_config->ssid.ssid_len = *(ssid_ie + 1);
1314 	head = (struct ieee80211_mgmt *)params->head;
1315 
1316 	capab_info = le16_to_cpu(head->u.beacon.capab_info);
1317 	PRINTM(MIOCTL, "capab_info=0x%x\n", head->u.beacon.capab_info);
1318 	sys_config->auth_mode = MLAN_AUTH_MODE_OPEN;
1319 	/** For ICS, we don't support OPEN mode */
1320 	if ((priv->cipher == WLAN_CIPHER_SUITE_WEP40) ||
1321 	    (priv->cipher == WLAN_CIPHER_SUITE_WEP104)) {
1322 		sys_config->protocol = PROTOCOL_STATIC_WEP;
1323 		sys_config->key_mgmt = KEY_MGMT_NONE;
1324 		sys_config->wpa_cfg.length = 0;
1325 		moal_memcpy_ext(priv->phandle, &sys_config->wep_cfg.key0,
1326 				&priv->uap_wep_key[0], sizeof(wep_key),
1327 				sizeof(sys_config->wep_cfg.key0));
1328 		moal_memcpy_ext(priv->phandle, &sys_config->wep_cfg.key1,
1329 				&priv->uap_wep_key[1], sizeof(wep_key),
1330 				sizeof(sys_config->wep_cfg.key1));
1331 		moal_memcpy_ext(priv->phandle, &sys_config->wep_cfg.key2,
1332 				&priv->uap_wep_key[2], sizeof(wep_key),
1333 				sizeof(sys_config->wep_cfg.key2));
1334 		moal_memcpy_ext(priv->phandle, &sys_config->wep_cfg.key3,
1335 				&priv->uap_wep_key[3], sizeof(wep_key),
1336 				sizeof(sys_config->wep_cfg.key3));
1337 	} else {
1338 		/** Get cipher and key_mgmt from RSN/WPA IE */
1339 		if (capab_info & WLAN_CAPABILITY_PRIVACY) {
1340 			wpa_ies = woal_find_wpa_ies(
1341 				params->tail, params->tail_len, sys_config);
1342 			if (wpa_ies == MFALSE) {
1343 				/* hard code setting to wpa2-psk */
1344 				sys_config->protocol = PROTOCOL_WPA2;
1345 				sys_config->key_mgmt = KEY_MGMT_PSK;
1346 				sys_config->wpa_cfg.pairwise_cipher_wpa2 =
1347 					CIPHER_AES_CCMP;
1348 				sys_config->wpa_cfg.group_cipher =
1349 					CIPHER_AES_CCMP;
1350 			}
1351 		}
1352 	}
1353 #endif
1354 
1355 	if (GET_BSS_ROLE(priv) == MLAN_BSS_ROLE_UAP) {
1356 		/*find and set wmm ie*/
1357 		woal_set_wmm_ies(priv, ie, ie_len, sys_config);
1358 	}
1359 	/* If the security mode is configured as WEP or WPA-PSK,
1360 	 * it will disable 11n automatically, and if configured as
1361 	 * open(off) or wpa2-psk, it will automatically enable 11n */
1362 	if ((sys_config->protocol == PROTOCOL_STATIC_WEP) ||
1363 	    (sys_config->protocol == PROTOCOL_WPA))
1364 		enable_11n = MFALSE;
1365 	if (!enable_11n) {
1366 		if (woal_set_uap_ht_tx_cfg(priv, sys_config->bandcfg, ht_cap,
1367 					   MFALSE)) {
1368 			PRINTM(MMSG, "woal_set_uap_ht_tx_cfg fail\n");
1369 			ret = -EFAULT;
1370 			goto done;
1371 		}
1372 		woal_uap_set_11n_status(priv, sys_config, MLAN_ACT_DISABLE);
1373 	} else {
1374 		if (woal_set_uap_ht_tx_cfg(priv, sys_config->bandcfg, ht_cap,
1375 					   MTRUE)) {
1376 			PRINTM(MMSG, "woal_set_uap_ht_tx_cfg fail\n");
1377 			ret = -EFAULT;
1378 			goto done;
1379 		}
1380 		woal_uap_set_11n_status(priv, sys_config, MLAN_ACT_ENABLE);
1381 		woal_set_get_tx_bf_cap(priv, MLAN_ACT_GET,
1382 				       &sys_config->tx_bf_cap);
1383 	}
1384 	if (enable_11ac && enable_11n) {
1385 		vhtcap_ie = woal_get_vhtcap_info(ie, ie_len);
1386 		vhtopr_ie = woal_get_vht_oprat_ie(ie, ie_len);
1387 		// Enable VHT80
1388 		if (vhtopr_ie && vhtopr_ie->chan_width)
1389 			vht20_40 = 0;
1390 		woal_uap_set_11ac_status(priv, MLAN_ACT_ENABLE, vht20_40,
1391 					 vhtcap_ie);
1392 	} else {
1393 		woal_uap_set_11ac_status(priv, MLAN_ACT_DISABLE, vht20_40,
1394 					 NULL);
1395 	}
1396 	if (enable_11ax && enable_11n) {
1397 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
1398 		hecap_ie = (IEEEtypes_HECap_t *)woal_parse_ext_ie_tlv(
1399 			ie, ie_len, HE_CAPABILITY);
1400 #endif
1401 		woal_uap_set_11ax_status(priv, MLAN_ACT_ENABLE,
1402 					 sys_config->bandcfg.chanBand,
1403 					 hecap_ie);
1404 	} else
1405 		woal_uap_set_11ax_status(priv, MLAN_ACT_DISABLE,
1406 					 sys_config->bandcfg.chanBand, NULL);
1407 
1408 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1409 	if (params->inactivity_timeout) {
1410 		sys_config->sta_ageout_timer = params->inactivity_timeout * 10;
1411 		sys_config->ps_sta_ageout_timer =
1412 			params->inactivity_timeout * 10;
1413 	}
1414 	PRINTM(MIOCTL, "inactivity_timeout=%d\n", params->inactivity_timeout);
1415 	PRINTM(MIOCTL, "sta_ageout_timer=%d ps_sta_ageout_timer=%d\n",
1416 	       sys_config->sta_ageout_timer, sys_config->ps_sta_ageout_timer);
1417 #endif
1418 
1419 	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_SET,
1420 							   MOAL_IOCTL_WAIT,
1421 							   sys_config)) {
1422 		ret = -EFAULT;
1423 		goto done;
1424 	}
1425 
1426 	/** Set wacp_mode for uAP/P2P-GO */
1427 	if (priv->phandle->params.wacp_mode) {
1428 		PRINTM(MIOCTL, "wacp_mode: %d\n",
1429 		       priv->phandle->params.wacp_mode);
1430 		if (MLAN_STATUS_SUCCESS !=
1431 		    woal_set_wacp_mode(priv, MOAL_IOCTL_WAIT)) {
1432 			PRINTM(MERROR, "Set wacp_mode failed\n");
1433 			ret = -EFAULT;
1434 			goto done;
1435 		}
1436 	}
1437 
1438 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
1439 	woal_enable_dfs_support(priv, &priv->chan);
1440 #endif
1441 done:
1442 	kfree(sys_config);
1443 	LEAVE();
1444 	return ret;
1445 }
1446 
1447 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1448 /**
1449  * @brief Request the driver to add a monitor interface
1450  *
1451  * @param wiphy             A pointer to wiphy structure
1452  * @param name              Virtual interface name
1453  * @param name_assign_type  Interface name assignment type
1454  * @param flags             Flags for the virtual interface
1455  * @param params            A pointer to vif_params structure
1456  * @param new_dev           Netdevice to be passed out
1457  *
1458  * @return                  0 -- success, otherwise fail
1459  */
woal_cfg80211_add_mon_if(struct wiphy * wiphy,const char * name,unsigned char name_assign_type,u32 * flags,struct vif_params * params,struct net_device ** new_dev)1460 static int woal_cfg80211_add_mon_if(struct wiphy *wiphy, const char *name,
1461 				    unsigned char name_assign_type, u32 *flags,
1462 				    struct vif_params *params,
1463 				    struct net_device **new_dev)
1464 #else
1465 /**
1466  * @brief Request the driver to add a monitor interface
1467  *
1468  * @param wiphy           A pointer to wiphy structure
1469  * @param name            Virtual interface name
1470  * @param flags           Flags for the virtual interface
1471  * @param params          A pointer to vif_params structure
1472  * @param new_dev         Netdevice to be passed out
1473  *
1474  * @return                0 -- success, otherwise fail
1475  */
1476 static int woal_cfg80211_add_mon_if(struct wiphy *wiphy,
1477 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
1478 				    const
1479 #endif
1480 				    char *name,
1481 				    u32 *flags, struct vif_params *params,
1482 				    struct net_device **new_dev)
1483 #endif
1484 {
1485 	int ret = 0;
1486 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
1487 	moal_private *priv =
1488 		(moal_private *)woal_get_priv(handle, MLAN_BSS_ROLE_STA);
1489 	monitor_iface *mon_if = NULL;
1490 	struct net_device *ndev = NULL;
1491 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1492 	chan_band_info chan_info;
1493 #endif
1494 	unsigned char name_assign_type_tmp = 0;
1495 
1496 	ENTER();
1497 
1498 	ASSERT_RTNL();
1499 
1500 	if (handle->mon_if) {
1501 		PRINTM(MERROR, "%s: monitor interface exist: %s basedev %s\n",
1502 		       __func__, handle->mon_if->mon_ndev->name,
1503 		       handle->mon_if->base_ndev->name);
1504 		ret = -EFAULT;
1505 		goto fail;
1506 	}
1507 	if (!priv) {
1508 		PRINTM(MERROR, "add_mon_if: priv is NULL\n");
1509 		ret = -EFAULT;
1510 		goto fail;
1511 	}
1512 
1513 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1514 	name_assign_type_tmp = name_assign_type;
1515 #endif
1516 	mon_if = woal_prepare_mon_if(priv, name, name_assign_type_tmp,
1517 				     CHANNEL_SPEC_SNIFFER_MODE);
1518 	if (!mon_if) {
1519 		PRINTM(MFATAL, "Prepare mon_if fail.\n");
1520 		goto fail;
1521 	}
1522 	ndev = mon_if->mon_ndev;
1523 	dev_net_set(ndev, wiphy_net(wiphy));
1524 
1525 	moal_memcpy_ext(priv->phandle, ndev->perm_addr, wiphy->perm_addr,
1526 			ETH_ALEN, sizeof(ndev->perm_addr));
1527 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0)
1528 	eth_hw_addr_set(ndev, ndev->perm_addr);
1529 #else
1530 	moal_memcpy_ext(priv->phandle, ndev->dev_addr, ndev->perm_addr,
1531 			ETH_ALEN, MAX_ADDR_LEN);
1532 #endif
1533 	SET_NETDEV_DEV(ndev, wiphy_dev(wiphy));
1534 	ndev->ieee80211_ptr = &mon_if->wdev;
1535 	mon_if->wdev.iftype = NL80211_IFTYPE_MONITOR;
1536 	mon_if->wdev.wiphy = wiphy;
1537 
1538 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
1539 	/* Set default band channel config */
1540 	mon_if->band_chan_cfg.band = BAND_B | BAND_G;
1541 	mon_if->band_chan_cfg.band |= BAND_GN;
1542 	mon_if->band_chan_cfg.channel = 1;
1543 	mon_if->band_chan_cfg.chan_bandwidth = CHANNEL_BW_20MHZ;
1544 	memset(&chan_info, 0x00, sizeof(chan_info));
1545 	chan_info.channel = 1;
1546 	chan_info.is_11n_enabled = MTRUE;
1547 	if (MLAN_STATUS_FAILURE ==
1548 	    woal_chandef_create(priv, &mon_if->chandef, &chan_info)) {
1549 		ret = -EFAULT;
1550 		goto fail;
1551 	}
1552 	if (MLAN_STATUS_SUCCESS !=
1553 	    woal_set_net_monitor(priv, MOAL_IOCTL_WAIT,
1554 				 CHANNEL_SPEC_SNIFFER_MODE, 0x7,
1555 				 &mon_if->band_chan_cfg)) {
1556 		PRINTM(MERROR, "%s: woal_set_net_monitor fail\n", __func__);
1557 		ret = -EFAULT;
1558 		goto fail;
1559 	}
1560 #endif
1561 
1562 	ret = register_netdevice(ndev);
1563 	if (ret) {
1564 		PRINTM(MFATAL, "register net_device failed, ret=%d\n", ret);
1565 		free_netdev(ndev);
1566 		goto fail;
1567 	}
1568 
1569 	handle->mon_if = mon_if;
1570 
1571 	if (new_dev)
1572 		*new_dev = ndev;
1573 
1574 fail:
1575 	LEAVE();
1576 	return ret;
1577 }
1578 
1579 #ifdef WIFI_DIRECT_SUPPORT
1580 #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
1581 /**
1582  * @brief Callback function for virtual interface
1583  *      setup
1584  *
1585  *  @param dev    A pointer to structure net_device
1586  *
1587  *  @return       N/A
1588  */
woal_virt_if_setup(struct net_device * dev)1589 static void woal_virt_if_setup(struct net_device *dev)
1590 {
1591 	ENTER();
1592 	ether_setup(dev);
1593 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 11, 9)
1594 	dev->needs_free_netdev = true;
1595 #else
1596 	dev->destructor = free_netdev;
1597 #endif
1598 	LEAVE();
1599 }
1600 
1601 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1602 /**
1603  * @brief This function adds a new interface. It will
1604  *        allocate, initialize and register the device.
1605  *
1606  *  @param handle           A pointer to moal_handle structure
1607  *  @param bss_index        BSS index number
1608  *  @param name_assign_type Interface name assignment type
1609  *  @param bss_type         BSS type
1610  *
1611  *  @return                 A pointer to the new priv structure
1612  */
woal_alloc_virt_interface(moal_handle * handle,t_u8 bss_index,unsigned char name_assign_type,t_u8 bss_type,const char * name)1613 static moal_private *woal_alloc_virt_interface(moal_handle *handle,
1614 					       t_u8 bss_index,
1615 					       unsigned char name_assign_type,
1616 					       t_u8 bss_type, const char *name)
1617 #else
1618 /**
1619  * @brief This function adds a new interface. It will
1620  *        allocate, initialize and register the device.
1621  *
1622  *  @param handle    A pointer to moal_handle structure
1623  *  @param bss_index BSS index number
1624  *  @param bss_type  BSS type
1625  *
1626  *  @return          A pointer to the new priv structure
1627  */
1628 moal_private *woal_alloc_virt_interface(moal_handle *handle, t_u8 bss_index,
1629 					t_u8 bss_type,
1630 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
1631 					const
1632 #endif
1633 					char *name)
1634 #endif
1635 {
1636 	struct net_device *dev = NULL;
1637 	moal_private *priv = NULL;
1638 	ENTER();
1639 
1640 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
1641 #ifndef MAX_WMM_QUEUE
1642 #define MAX_WMM_QUEUE 4
1643 #endif
1644 	/* Allocate an Ethernet device */
1645 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
1646 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1647 	dev = alloc_netdev_mq(sizeof(moal_private), name, name_assign_type,
1648 			      woal_virt_if_setup, MAX_WMM_QUEUE);
1649 #else
1650 	dev = alloc_netdev_mq(sizeof(moal_private), name, NET_NAME_UNKNOWN,
1651 			      woal_virt_if_setup, MAX_WMM_QUEUE);
1652 #endif
1653 #else
1654 	dev = alloc_netdev_mq(sizeof(moal_private), name, woal_virt_if_setup,
1655 			      MAX_WMM_QUEUE);
1656 #endif
1657 #else
1658 	dev = alloc_netdev(sizeof(moal_private), name, woal_virt_if_setup);
1659 #endif
1660 	if (!dev) {
1661 		PRINTM(MFATAL, "Init virtual ethernet device failed\n");
1662 		goto error;
1663 	}
1664 	/* Allocate device name */
1665 	if ((dev_alloc_name(dev, name) < 0)) {
1666 		PRINTM(MERROR, "Could not allocate device name\n");
1667 		goto error;
1668 	}
1669 
1670 	priv = (moal_private *)netdev_priv(dev);
1671 	/* Save the priv to handle */
1672 	handle->priv[bss_index] = priv;
1673 
1674 	/* Use the same handle structure */
1675 	priv->phandle = handle;
1676 	priv->netdev = dev;
1677 	priv->bss_index = bss_index;
1678 	priv->bss_type = bss_type;
1679 	priv->bss_role = MLAN_BSS_ROLE_STA;
1680 
1681 	INIT_LIST_HEAD(&priv->tcp_sess_queue);
1682 	spin_lock_init(&priv->tcp_sess_lock);
1683 
1684 	INIT_LIST_HEAD(&priv->tx_stat_queue);
1685 	spin_lock_init(&priv->tx_stat_lock);
1686 	INIT_LIST_HEAD(&priv->mcast_list);
1687 	spin_lock_init(&priv->mcast_lock);
1688 
1689 	spin_lock_init(&priv->connect_lock);
1690 
1691 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
1692 	SET_MODULE_OWNER(dev);
1693 #endif
1694 
1695 	PRINTM(MCMND, "Alloc virtual interface%s\n", dev->name);
1696 
1697 	LEAVE();
1698 	return priv;
1699 error:
1700 	if (dev)
1701 		free_netdev(dev);
1702 	LEAVE();
1703 	return NULL;
1704 }
1705 
1706 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1707 /**
1708  * @brief Request the driver to add a virtual interface
1709  *
1710  * @param wiphy             A pointer to wiphy structure
1711  * @param name              Virtual interface name
1712  * @param name_assign_type  Interface name assignment type
1713  * @param type              Virtual interface type
1714  * @param flags             Flags for the virtual interface
1715  * @param params            A pointer to vif_params structure
1716  * @param new_dev		    new net_device to return
1717  *
1718  * @return                  0 -- success, otherwise fail
1719  */
woal_cfg80211_add_virt_if(struct wiphy * wiphy,const char * name,unsigned char name_assign_type,enum nl80211_iftype type,u32 * flags,struct vif_params * params,struct net_device ** new_dev)1720 static int woal_cfg80211_add_virt_if(struct wiphy *wiphy, const char *name,
1721 				     unsigned char name_assign_type,
1722 				     enum nl80211_iftype type, u32 *flags,
1723 				     struct vif_params *params,
1724 				     struct net_device **new_dev)
1725 #else
1726 /**
1727  * @brief Request the driver to add a virtual interface
1728  *
1729  * @param wiphy           A pointer to wiphy structure
1730  * @param name            Virtual interface name
1731  * @param type            Virtual interface type
1732  * @param flags           Flags for the virtual interface
1733  * @param params          A pointer to vif_params structure
1734  * @param new_dev		  new net_device to return
1735  *
1736  * @return                0 -- success, otherwise fail
1737  */
1738 int woal_cfg80211_add_virt_if(struct wiphy *wiphy,
1739 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
1740 			      const
1741 #endif
1742 			      char *name,
1743 			      enum nl80211_iftype type, u32 *flags,
1744 			      struct vif_params *params,
1745 			      struct net_device **new_dev)
1746 #endif
1747 {
1748 	int ret = 0;
1749 	struct net_device *ndev = NULL;
1750 	moal_private *priv = NULL, *new_priv = NULL;
1751 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
1752 	struct wireless_dev *wdev = NULL;
1753 	moal_private *vir_priv;
1754 	int i = 0;
1755 
1756 	ENTER();
1757 	ASSERT_RTNL();
1758 	priv = woal_get_vir_priv_bss_type(handle, MLAN_BSS_TYPE_WIFIDIRECT);
1759 	if (priv && priv->bss_role == MLAN_BSS_ROLE_UAP &&
1760 	    priv->bss_started == MTRUE) {
1761 		if (handle->pref_mac)
1762 			handle = (moal_handle *)handle->pref_mac;
1763 	}
1764 	priv = (moal_private *)woal_get_priv_bss_type(handle,
1765 						      MLAN_BSS_TYPE_WIFIDIRECT);
1766 	if (!priv || !priv->phandle) {
1767 		PRINTM(MERROR, "priv or handle is NULL\n");
1768 		LEAVE();
1769 		return -EFAULT;
1770 	}
1771 	if (priv->phandle->drv_mode.intf_num == priv->phandle->priv_num) {
1772 		PRINTM(MERROR, "max virtual interface limit reached\n");
1773 		for (i = 0; i < priv->phandle->priv_num; i++) {
1774 			vir_priv = priv->phandle->priv[i];
1775 			if (vir_priv->bss_virtual) {
1776 				woal_cfg80211_del_virt_if(wiphy,
1777 							  vir_priv->netdev);
1778 				break;
1779 			}
1780 		}
1781 		if (priv->phandle->drv_mode.intf_num ==
1782 		    priv->phandle->priv_num) {
1783 			LEAVE();
1784 			return -ENOMEM;
1785 		}
1786 	}
1787 	PRINTM(MMSG, "Add virtual interface %s\n", name);
1788 	if ((type != NL80211_IFTYPE_P2P_CLIENT) &&
1789 	    (type != NL80211_IFTYPE_P2P_GO)) {
1790 		PRINTM(MERROR, "Invalid iftype: %d\n", type);
1791 		LEAVE();
1792 		return -EINVAL;
1793 	}
1794 
1795 	handle = priv->phandle;
1796 	/* Cancel previous scan req */
1797 	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
1798 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
1799 	new_priv = woal_alloc_virt_interface(handle, handle->priv_num,
1800 					     name_assign_type,
1801 					     MLAN_BSS_TYPE_WIFIDIRECT, name);
1802 #else
1803 	new_priv = woal_alloc_virt_interface(handle, handle->priv_num,
1804 					     MLAN_BSS_TYPE_WIFIDIRECT, name);
1805 #endif
1806 	if (!new_priv) {
1807 		PRINTM(MERROR, "Add virtual interface fail.");
1808 		LEAVE();
1809 		return -EFAULT;
1810 	}
1811 	handle->priv_num++;
1812 
1813 	wdev = (struct wireless_dev *)&new_priv->w_dev;
1814 	memset(wdev, 0, sizeof(struct wireless_dev));
1815 	ndev = new_priv->netdev;
1816 	SET_NETDEV_DEV(ndev, wiphy_dev(wiphy));
1817 	ndev->ieee80211_ptr = wdev;
1818 	wdev->iftype = type;
1819 	wdev->wiphy = wiphy;
1820 	new_priv->wdev = wdev;
1821 	new_priv->bss_virtual = MTRUE;
1822 	new_priv->pa_netdev = priv->netdev;
1823 
1824 	/* Create workqueue for main process */
1825 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)
1826 	new_priv->mclist_workqueue =
1827 		alloc_workqueue("MCLIST_WORK_QUEUE",
1828 				WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
1829 #else
1830 	new_priv->mclist_workqueue = create_workqueue("MCLIST_WORK_QUEUE");
1831 #endif
1832 	if (!new_priv->mclist_workqueue) {
1833 		PRINTM(MERROR, "cannot alloc mclist workqueue \n");
1834 		return -EFAULT;
1835 	}
1836 	MLAN_INIT_WORK(&new_priv->mclist_work, woal_mclist_work_queue);
1837 
1838 	woal_init_sta_dev(ndev, new_priv);
1839 
1840 	/* Initialize priv structure */
1841 	woal_init_priv(new_priv, MOAL_IOCTL_WAIT);
1842 	/** Init to GO/CLIENT mode */
1843 	if (type == NL80211_IFTYPE_P2P_CLIENT)
1844 		woal_cfg80211_init_p2p_client(new_priv);
1845 	else if (type == NL80211_IFTYPE_P2P_GO)
1846 		woal_cfg80211_init_p2p_go(new_priv);
1847 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
1848 	ret = cfg80211_register_netdevice(ndev);
1849 #else
1850 	ret = register_netdevice(ndev);
1851 #endif
1852 	if (ret) {
1853 		handle->priv[new_priv->bss_index] = NULL;
1854 		handle->priv_num--;
1855 		if (ndev->reg_state == NETREG_REGISTERED) {
1856 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
1857 			cfg80211_unregister_netdevice(ndev);
1858 #else
1859 			unregister_netdevice(ndev);
1860 #endif
1861 			free_netdev(ndev);
1862 			ndev = NULL;
1863 		}
1864 		PRINTM(MFATAL, "register net_device failed, ret=%d\n", ret);
1865 		goto done;
1866 	}
1867 	netif_carrier_off(ndev);
1868 	woal_stop_queue(ndev);
1869 	if (new_dev)
1870 		*new_dev = ndev;
1871 #ifdef CONFIG_PROC_FS
1872 	woal_create_proc_entry(new_priv);
1873 	woal_debug_entry(new_priv);
1874 #endif /* CONFIG_PROC_FS */
1875 done:
1876 	LEAVE();
1877 	return ret;
1878 }
1879 
1880 /**
1881  *  @brief Notify mlan BSS will be removed.
1882  *
1883  *  @param priv          A pointer to moal_private structure
1884  *
1885  *  @return              MLAN_STATUS_SUCCESS/MLAN_STATUS_PENDING -- success,
1886  * otherwise fail
1887  */
woal_bss_remove(moal_private * priv)1888 static mlan_status woal_bss_remove(moal_private *priv)
1889 {
1890 	mlan_ioctl_req *req = NULL;
1891 	mlan_ds_bss *bss = NULL;
1892 	mlan_status status;
1893 
1894 	ENTER();
1895 
1896 	/* Allocate an IOCTL request buffer */
1897 	req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_bss));
1898 	if (req == NULL) {
1899 		status = MLAN_STATUS_FAILURE;
1900 		goto done;
1901 	}
1902 
1903 	/* Fill request buffer */
1904 	bss = (mlan_ds_bss *)req->pbuf;
1905 	bss->sub_command = MLAN_OID_BSS_REMOVE;
1906 	req->req_id = MLAN_IOCTL_BSS;
1907 	req->action = MLAN_ACT_SET;
1908 	/* Send IOCTL request to MLAN */
1909 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
1910 
1911 done:
1912 	if (status != MLAN_STATUS_PENDING)
1913 		kfree(req);
1914 	LEAVE();
1915 	return status;
1916 }
1917 
1918 /**
1919  *  @brief This function removes an virtual interface.
1920  *
1921  *  @param wiphy    A pointer to the wiphy structure
1922  *  @param dev      A pointer to the net_device structure
1923  *
1924  *  @return         0 -- success, otherwise fail
1925  */
woal_cfg80211_del_virt_if(struct wiphy * wiphy,struct net_device * dev)1926 int woal_cfg80211_del_virt_if(struct wiphy *wiphy, struct net_device *dev)
1927 {
1928 	int ret = 0;
1929 	int i = 0;
1930 	moal_private *priv = NULL;
1931 	moal_private *vir_priv = NULL;
1932 	moal_private *remain_priv = NULL;
1933 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
1934 	t_u8 find_bss = MFALSE;
1935 
1936 	for (i = 0; i < handle->priv_num; i++) {
1937 		vir_priv = handle->priv[i];
1938 		if (vir_priv) {
1939 			if (vir_priv->netdev == dev) {
1940 				find_bss = MTRUE;
1941 				PRINTM(MMSG,
1942 				       "Del virtual interface %s, index=%d\n",
1943 				       dev->name, i);
1944 				break;
1945 			}
1946 		}
1947 	}
1948 	if (!find_bss) {
1949 		/* Switch to the other MAC */
1950 		if (handle->pref_mac)
1951 			handle = (moal_handle *)handle->pref_mac;
1952 		for (i = 0; i < handle->priv_num; i++) {
1953 			vir_priv = handle->priv[i];
1954 			if (vir_priv) {
1955 				if (vir_priv->netdev == dev) {
1956 					find_bss = MTRUE;
1957 					PRINTM(MMSG,
1958 					       "Del virtual interface %s, index=%d\n",
1959 					       dev->name, i);
1960 					break;
1961 				}
1962 			}
1963 		}
1964 	}
1965 
1966 	priv = (moal_private *)woal_get_priv_bss_type(handle,
1967 						      MLAN_BSS_TYPE_WIFIDIRECT);
1968 	if (!priv)
1969 		return ret;
1970 	if (vir_priv && vir_priv->netdev == dev) {
1971 		woal_stop_queue(dev);
1972 		netif_carrier_off(dev);
1973 		netif_device_detach(dev);
1974 		if (handle->is_remain_timer_set) {
1975 			woal_cancel_timer(&handle->remain_timer);
1976 			woal_remain_timer_func(handle);
1977 		}
1978 
1979 		/*** cancel pending scan */
1980 		woal_cancel_scan(vir_priv, MOAL_IOCTL_WAIT);
1981 
1982 		woal_flush_tx_stat_queue(vir_priv);
1983 		woal_flush_mcast_list(vir_priv);
1984 
1985 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
1986 		/* cancel previous remain on channel to avoid firmware hang */
1987 		if (priv->phandle->remain_on_channel) {
1988 			t_u8 channel_status;
1989 			remain_priv =
1990 				priv->phandle
1991 					->priv[priv->phandle->remain_bss_index];
1992 			if (remain_priv) {
1993 				if (woal_cfg80211_remain_on_channel_cfg(
1994 					    remain_priv, MOAL_IOCTL_WAIT, MTRUE,
1995 					    &channel_status, NULL, 0, 0))
1996 					PRINTM(MERROR,
1997 					       "del_virt_if: Fail to cancel remain on channel\n");
1998 
1999 				if (priv->phandle->cookie) {
2000 					cfg80211_remain_on_channel_expired(
2001 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
2002 						remain_priv->netdev,
2003 #else
2004 						remain_priv->wdev,
2005 #endif
2006 						priv->phandle->cookie,
2007 						&priv->phandle->chan,
2008 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
2009 						priv->phandle->channel_type,
2010 #endif
2011 						GFP_ATOMIC);
2012 					priv->phandle->cookie = 0;
2013 				}
2014 				priv->phandle->remain_on_channel = MFALSE;
2015 			}
2016 		}
2017 #endif
2018 		if (vir_priv->mclist_workqueue) {
2019 			flush_workqueue(vir_priv->mclist_workqueue);
2020 			destroy_workqueue(vir_priv->mclist_workqueue);
2021 			vir_priv->mclist_workqueue = NULL;
2022 		}
2023 		woal_clear_all_mgmt_ies(vir_priv, MOAL_IOCTL_WAIT);
2024 		woal_cfg80211_deinit_p2p(vir_priv);
2025 		woal_bss_remove(vir_priv);
2026 #ifdef CONFIG_PROC_FS
2027 		/* Remove proc debug */
2028 		woal_debug_remove(vir_priv);
2029 		woal_proc_remove(vir_priv);
2030 #endif /* CONFIG_PROC_FS */
2031 		/* Last reference is our one */
2032 #if CFG80211_VERSION_CODE < KERNEL_VERSION(2, 6, 37)
2033 		PRINTM(MINFO, "refcnt = %d\n", atomic_read(&dev->refcnt));
2034 #else
2035 		PRINTM(MINFO, "refcnt = %d\n", netdev_refcnt_read(dev));
2036 #endif
2037 		PRINTM(MINFO, "netdev_finish_unregister: %s\n", dev->name);
2038 		/* Clear the priv in handle */
2039 		vir_priv->phandle->priv[vir_priv->bss_index] = NULL;
2040 		priv->phandle->priv_num--;
2041 		if (dev->reg_state == NETREG_REGISTERED)
2042 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
2043 			cfg80211_unregister_netdevice(dev);
2044 #else
2045 			unregister_netdevice(dev);
2046 #endif
2047 	}
2048 	return ret;
2049 }
2050 #endif
2051 #endif
2052 
2053 /**
2054  *  @brief This function removes an virtual interface.
2055  *
2056  *  @param handle    A pointer to the moal_handle structure
2057  *
2058  *  @return        N/A
2059  */
woal_remove_virtual_interface(moal_handle * handle)2060 void woal_remove_virtual_interface(moal_handle *handle)
2061 {
2062 #ifdef WIFI_DIRECT_SUPPORT
2063 	moal_private *priv = NULL;
2064 	int vir_intf = 0;
2065 	int i = 0;
2066 #endif
2067 	ENTER();
2068 	rtnl_lock();
2069 #ifdef WIFI_DIRECT_SUPPORT
2070 	for (i = 0; i < handle->priv_num; i++) {
2071 		priv = handle->priv[i];
2072 		if (priv) {
2073 			if (priv->bss_virtual) {
2074 				PRINTM(MCMND, "Remove virtual interface %s\n",
2075 				       priv->netdev->name);
2076 #ifdef CONFIG_PROC_FS
2077 				/* Remove proc debug */
2078 				woal_debug_remove(priv);
2079 				woal_proc_remove(priv);
2080 #endif /* CONFIG_PROC_FS */
2081 				netif_device_detach(priv->netdev);
2082 				if (priv->netdev->reg_state ==
2083 				    NETREG_REGISTERED)
2084 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 12, 0)
2085 					cfg80211_unregister_netdevice(
2086 						priv->netdev);
2087 #else
2088 					unregister_netdevice(priv->netdev);
2089 #endif
2090 				handle->priv[i] = NULL;
2091 				vir_intf++;
2092 			}
2093 		}
2094 	}
2095 #endif
2096 	if (handle->mon_if) {
2097 		netif_device_detach(handle->mon_if->mon_ndev);
2098 		if (handle->mon_if->mon_ndev->reg_state == NETREG_REGISTERED)
2099 			unregister_netdevice(handle->mon_if->mon_ndev);
2100 		handle->mon_if = NULL;
2101 	}
2102 	rtnl_unlock();
2103 #ifdef WIFI_DIRECT_SUPPORT
2104 	handle->priv_num -= vir_intf;
2105 #endif
2106 	LEAVE();
2107 }
2108 
2109 /**
2110  *  @brief This function check if uap interface is ready
2111  *
2112  * @param wiphy           A pointer to wiphy structure
2113  * @param name            Virtual interface name
2114  *
2115  *  @return        MTRUE/MFALSE;
2116  */
woal_uap_interface_ready(struct wiphy * wiphy,char * name,struct net_device ** new_dev)2117 static t_u8 woal_uap_interface_ready(struct wiphy *wiphy, char *name,
2118 				     struct net_device **new_dev)
2119 {
2120 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
2121 	moal_private *priv = NULL;
2122 	int i;
2123 
2124 	for (i = 0; i < handle->priv_num; i++) {
2125 		priv = handle->priv[i];
2126 		if (priv && (priv->bss_type == MLAN_BSS_TYPE_UAP) &&
2127 		    !strcmp(priv->netdev->name, name)) {
2128 			priv->wdev->iftype = NL80211_IFTYPE_AP;
2129 			*new_dev = priv->netdev;
2130 			break;
2131 		}
2132 	}
2133 	if (priv && *new_dev)
2134 		return MTRUE;
2135 	else
2136 		return MFALSE;
2137 }
2138 
2139 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
2140 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
2141 /**
2142  * @brief Request the driver to add a virtual interface
2143  *
2144  * @param wiphy           A pointer to wiphy structure
2145  * @param name            Virtual interface name
2146  * @param type            Virtual interface type
2147  * @param flags           Flags for the virtual interface
2148  * @param params          A pointer to vif_params structure
2149  *
2150  * @return                A pointer to net_device -- success, otherwise null
2151  */
woal_cfg80211_add_virtual_intf(struct wiphy * wiphy,char * name,enum nl80211_iftype type,u32 * flags,struct vif_params * params)2152 struct net_device *woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
2153 						  char *name,
2154 						  enum nl80211_iftype type,
2155 						  u32 *flags,
2156 						  struct vif_params *params)
2157 #else
2158 /**
2159  * @brief Request the driver to add a virtual interface
2160  *
2161  * @param wiphy           A pointer to wiphy structure
2162  * @param name            Virtual interface name
2163  * @param type            Virtual interface type
2164  * @param flags           Flags for the virtual interface
2165  * @param params          A pointer to vif_params structure
2166  *
2167  * @return                0 -- success, otherwise fail
2168  */
2169 int woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, char *name,
2170 				   enum nl80211_iftype type, u32 *flags,
2171 				   struct vif_params *params)
2172 #endif
2173 #else
2174 #if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 1, 0)
2175 /**
2176  * @brief Request the driver to add a virtual interface
2177  *
2178  * @param wiphy           A pointer to wiphy structure
2179  * @param name            Virtual interface name
2180  * @param type            Virtual interface type
2181  * @param flags           Flags for the virtual interface
2182  * @param params          A pointer to vif_params structure
2183  *
2184  * @return                A pointer to wireless_dev -- success, otherwise null
2185  */
2186 struct wireless_dev *woal_cfg80211_add_virtual_intf(struct wiphy *wiphy,
2187 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 7, 0)
2188 						    const
2189 #endif
2190 						    char *name,
2191 						    enum nl80211_iftype type,
2192 						    u32 *flags,
2193 						    struct vif_params *params)
2194 #else
2195 /**
2196  * @brief Request the driver to add a virtual interface
2197  *
2198  * @param wiphy             A pointer to wiphy structure
2199  * @param name              Virtual interface name
2200  * @param name_assign_type  Interface name assignment type
2201  * @param type              Virtual interface type
2202  * @param flags             Flags for the virtual interface
2203  * @param params            A pointer to vif_params structure
2204  *
2205  * @return                  A pointer to wireless_dev -- success, otherwise null
2206  */
2207 struct wireless_dev *
2208 woal_cfg80211_add_virtual_intf(struct wiphy *wiphy, const char *name,
2209 			       unsigned char name_assign_type,
2210 			       enum nl80211_iftype type,
2211 #if CFG80211_VERSION_CODE < KERNEL_VERSION(4, 12, 0)
2212 			       u32 *flags,
2213 #endif
2214 			       struct vif_params *params)
2215 #endif
2216 #endif
2217 {
2218 	struct net_device *ndev = NULL;
2219 	int ret = 0;
2220 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2221 	u32 *flags = &params->flags;
2222 #endif
2223 
2224 	ENTER();
2225 	PRINTM(MIOCTL, "add virtual intf: %d name: %s\n", type, name);
2226 	switch (type) {
2227 	case NL80211_IFTYPE_MONITOR:
2228 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
2229 		ret = woal_cfg80211_add_mon_if(wiphy, name, name_assign_type,
2230 					       flags, params, &ndev);
2231 #else
2232 		ret = woal_cfg80211_add_mon_if(wiphy, name, flags, params,
2233 					       &ndev);
2234 #endif
2235 		break;
2236 #ifdef WIFI_DIRECT_SUPPORT
2237 #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
2238 	case NL80211_IFTYPE_P2P_CLIENT:
2239 	case NL80211_IFTYPE_P2P_GO:
2240 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
2241 		ret = woal_cfg80211_add_virt_if(wiphy, name, name_assign_type,
2242 						type, flags, params, &ndev);
2243 #else
2244 		ret = woal_cfg80211_add_virt_if(wiphy, name, type, flags,
2245 						params, &ndev);
2246 #endif
2247 		break;
2248 #endif
2249 #endif
2250 	case NL80211_IFTYPE_AP:
2251 		if (!woal_uap_interface_ready(wiphy, (char *)name, &ndev)) {
2252 			PRINTM(MMSG,
2253 			       "Not support dynamically create %s UAP interface\n",
2254 			       name);
2255 			ret = -EFAULT;
2256 		}
2257 		break;
2258 	default:
2259 		PRINTM(MWARN, "Not supported if type: %d\n", type);
2260 		ret = -EFAULT;
2261 		break;
2262 	}
2263 	LEAVE();
2264 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
2265 #if CFG80211_VERSION_CODE > KERNEL_VERSION(2, 6, 37)
2266 	if (ret)
2267 		return ERR_PTR(ret);
2268 	else
2269 		return ndev;
2270 #else
2271 	return ret;
2272 #endif
2273 #else
2274 	if (ret)
2275 		return ERR_PTR(ret);
2276 	else
2277 		return ndev->ieee80211_ptr;
2278 #endif
2279 }
2280 
2281 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
2282 /**
2283  * @brief Request the driver to del a virtual interface
2284  *
2285  * @param wiphy           A pointer to wiphy structure
2286  * @param dev             The pointer to net_device
2287  *
2288  * @return               0 -- success, otherwise fail
2289  */
woal_cfg80211_del_virtual_intf(struct wiphy * wiphy,struct net_device * dev)2290 int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy, struct net_device *dev)
2291 #else
2292 /**
2293  * @brief Request the driver to del a virtual interface
2294  *
2295  * @param wiphy           A pointer to wiphy structure
2296  * @param wdev            The pointer to wireless_dev
2297  *
2298  * @return               0 -- success, otherwise fail
2299  */
2300 int woal_cfg80211_del_virtual_intf(struct wiphy *wiphy,
2301 				   struct wireless_dev *wdev)
2302 #endif
2303 {
2304 	int ret = 0;
2305 
2306 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
2307 	int i;
2308 	moal_private *vir_priv = NULL;
2309 
2310 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
2311 	struct net_device *dev = wdev->netdev;
2312 #endif
2313 
2314 	ENTER();
2315 
2316 	PRINTM(MIOCTL, "del virtual intf %s\n", dev->name);
2317 	ASSERT_RTNL();
2318 	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_MONITOR) {
2319 		if ((handle->mon_if) && (handle->mon_if->mon_ndev == dev)) {
2320 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
2321 			if (MLAN_STATUS_SUCCESS !=
2322 			    woal_set_net_monitor(handle->mon_if->priv,
2323 						 MOAL_IOCTL_WAIT, MFALSE, 0,
2324 						 NULL)) {
2325 				PRINTM(MERROR,
2326 				       "%s: woal_set_net_monitor fail\n",
2327 				       __func__);
2328 				ret = -EFAULT;
2329 			}
2330 #endif
2331 			handle->mon_if = NULL;
2332 		}
2333 		unregister_netdevice(dev);
2334 		LEAVE();
2335 		return ret;
2336 	}
2337 
2338 	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
2339 		for (i = 0; i < handle->priv_num; i++) {
2340 			vir_priv = handle->priv[i];
2341 			if (vir_priv) {
2342 				if (vir_priv->netdev == dev) {
2343 					PRINTM(MMSG,
2344 					       "Del virtual interface %s, index=%d\n",
2345 					       dev->name, i);
2346 					break;
2347 				}
2348 			}
2349 		}
2350 		if (vir_priv && vir_priv->bss_type == MLAN_BSS_TYPE_UAP) {
2351 #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
2352 			if (woal_cfg80211_del_beacon(wiphy, dev, 0))
2353 #else
2354 			if (woal_cfg80211_del_beacon(wiphy, dev))
2355 #endif
2356 				PRINTM(MERROR, "%s: del_beacon failed\n",
2357 				       __func__);
2358 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
2359 #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
2360 			vir_priv->wdev->links[0].ap.beacon_interval = 0;
2361 #else
2362 			vir_priv->wdev->beacon_interval = 0;
2363 #endif
2364 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
2365 #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
2366 			memset(&vir_priv->wdev->links[0].ap.chandef, 0,
2367 			       sizeof(vir_priv->wdev->links[0].ap.chandef));
2368 #else
2369 			memset(&vir_priv->wdev->chandef, 0,
2370 			       sizeof(vir_priv->wdev->chandef));
2371 #endif
2372 #endif
2373 #endif
2374 #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
2375 			vir_priv->wdev->u.ap.ssid_len = 0;
2376 #else
2377 			vir_priv->wdev->ssid_len = 0;
2378 #endif
2379 			PRINTM(MMSG, "Skip del UAP virtual interface %s",
2380 			       dev->name);
2381 		}
2382 		LEAVE();
2383 		return ret;
2384 	}
2385 
2386 #ifdef WIFI_DIRECT_SUPPORT
2387 #if CFG80211_VERSION_CODE >= WIFI_DIRECT_KERNEL_VERSION
2388 	ret = woal_cfg80211_del_virt_if(wiphy, dev);
2389 #endif
2390 #endif
2391 	LEAVE();
2392 	return ret;
2393 }
2394 
2395 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2396 /**
2397  * @brief initialize AP or GO parameters
2398 
2399  *
2400  * @param wiphy           A pointer to wiphy structure
2401  * @param dev             A pointer to net_device structure
2402  * @param params          A pointer to cfg80211_ap_settings structure
2403  * @return                0 -- success, otherwise fail
2404  */
woal_cfg80211_add_beacon(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_ap_settings * params)2405 int woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
2406 			     struct cfg80211_ap_settings *params)
2407 #else
2408 /**
2409  * @brief initialize AP or GO parameters
2410 
2411  *
2412  * @param wiphy           A pointer to wiphy structure
2413  * @param dev             A pointer to net_device structure
2414  * @param params          A pointer to beacon_parameters structure
2415  * @return                0 -- success, otherwise fail
2416  */
2417 int woal_cfg80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
2418 			     struct beacon_parameters *params)
2419 #endif
2420 {
2421 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2422 	int ret = 0;
2423 
2424 	t_u8 wait_option = MOAL_IOCTL_WAIT_TIMEOUT;
2425 
2426 	ENTER();
2427 
2428 	PRINTM(MMSG, "wlan: Starting AP\n");
2429 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
2430 	/* cancel previous remain on channel to avoid firmware hang */
2431 	if (priv->phandle->remain_on_channel) {
2432 		t_u8 channel_status;
2433 		moal_private *remain_priv;
2434 		remain_priv =
2435 			priv->phandle->priv[priv->phandle->remain_bss_index];
2436 		if (remain_priv) {
2437 			PRINTM(MCMND,
2438 			       "Cancel Remain on Channel before Starting AP\n");
2439 			if (woal_cfg80211_remain_on_channel_cfg(
2440 				    remain_priv, MOAL_IOCTL_WAIT, MTRUE,
2441 				    &channel_status, NULL, 0, 0))
2442 				PRINTM(MERROR,
2443 				       "add beacon: Fail to cancel remain on channel\n");
2444 			if (priv->phandle->cookie) {
2445 				cfg80211_remain_on_channel_expired(
2446 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 6, 0)
2447 					remain_priv->netdev,
2448 #else
2449 					remain_priv->wdev,
2450 #endif
2451 					priv->phandle->cookie,
2452 					&priv->phandle->chan,
2453 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 8, 0)
2454 					priv->phandle->channel_type,
2455 #endif
2456 					GFP_ATOMIC);
2457 				priv->phandle->cookie = 0;
2458 			}
2459 			priv->phandle->remain_on_channel = MFALSE;
2460 		}
2461 	}
2462 #endif
2463 
2464 #ifdef STA_CFG80211
2465 	/*** cancel pending scan */
2466 	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
2467 #endif
2468 
2469 	if (!params) {
2470 		LEAVE();
2471 		return -EFAULT;
2472 	}
2473 
2474 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
2475 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
2476 	priv->channel = ieee80211_frequency_to_channel(
2477 		params->chandef.chan->center_freq);
2478 #else
2479 	priv->channel =
2480 		ieee80211_frequency_to_channel(params->channel->center_freq);
2481 #endif
2482 #endif
2483 	/* bss config */
2484 	if (MLAN_STATUS_SUCCESS != woal_cfg80211_beacon_config(priv, params)) {
2485 		ret = -EFAULT;
2486 		goto done;
2487 	}
2488 
2489 	/* set mgmt frame ies */
2490 	ret = woal_cfg80211_mgmt_frame_ie(priv,
2491 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
2492 					  params->tail, params->tail_len, NULL,
2493 					  0, NULL, 0, NULL, 0, MGMT_MASK_BEACON
2494 #else
2495 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2496 					  params->beacon.tail,
2497 					  params->beacon.tail_len,
2498 					  params->beacon.proberesp_ies,
2499 					  params->beacon.proberesp_ies_len,
2500 					  params->beacon.assocresp_ies,
2501 					  params->beacon.assocresp_ies_len,
2502 #else
2503 					  params->tail, params->tail_len,
2504 					  params->proberesp_ies,
2505 					  params->proberesp_ies_len,
2506 					  params->assocresp_ies,
2507 					  params->assocresp_ies_len,
2508 #endif
2509 					  NULL, 0,
2510 					  MGMT_MASK_BEACON |
2511 						  MGMT_MASK_PROBE_RESP |
2512 						  MGMT_MASK_ASSOC_RESP
2513 #endif
2514 					  ,
2515 					  MOAL_IOCTL_WAIT);
2516 	if (ret)
2517 		goto done;
2518 
2519 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
2520 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2521 	if (params->beacon.beacon_ies && params->beacon.beacon_ies_len) {
2522 		ret = woal_cfg80211_mgmt_frame_ie(
2523 			priv, params->beacon.beacon_ies,
2524 			params->beacon.beacon_ies_len, NULL, 0, NULL, 0, NULL,
2525 			0, MGMT_MASK_BEACON_WPS_P2P, MOAL_IOCTL_WAIT);
2526 		if (ret) {
2527 			PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n");
2528 			goto done;
2529 		}
2530 	}
2531 #else
2532 	if (params->beacon_ies && params->beacon_ies_len) {
2533 		ret = woal_cfg80211_mgmt_frame_ie(priv, params->beacon_ies,
2534 						  params->beacon_ies_len, NULL,
2535 						  0, NULL, 0, NULL, 0,
2536 						  MGMT_MASK_BEACON_WPS_P2P,
2537 						  MOAL_IOCTL_WAIT);
2538 		if (ret) {
2539 			PRINTM(MERROR, "Failed to set beacon wps/p2p ie\n");
2540 			goto done;
2541 		}
2542 	}
2543 #endif
2544 #endif
2545 	priv->uap_host_based = MTRUE;
2546 
2547 	/* if the bss is stopped, then start it */
2548 	if (priv->bss_started == MFALSE) {
2549 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2550 		if (moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
2551 			wait_option = MOAL_NO_WAIT;
2552 #endif
2553 		if (woal_uap_bss_ctrl(priv, wait_option, UAP_BSS_START)) {
2554 			PRINTM(MERROR, "%s: start uap failed \n", __func__);
2555 			priv->uap_host_based = MFALSE;
2556 			ret = -EFAULT;
2557 			goto done;
2558 		}
2559 	}
2560 	PRINTM(MMSG, "wlan: AP started\n");
2561 done:
2562 	LEAVE();
2563 	return ret;
2564 }
2565 
2566 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2567 /**
2568  * @brief set AP or GO parameter
2569  *
2570  * @param wiphy           A pointer to wiphy structure
2571  * @param dev             A pointer to net_device structure
2572  * @param params          A pointer to cfg80211_beacon_data structure
2573  * @return                0 -- success, otherwise fail
2574  */
woal_cfg80211_set_beacon(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_beacon_data * params)2575 int woal_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
2576 			     struct cfg80211_beacon_data *params)
2577 #else
2578 /**
2579  * @brief set AP or GO parameter
2580  *
2581  * @param wiphy           A pointer to wiphy structure
2582  * @param dev             A pointer to net_device structure
2583  * @param params          A pointer to beacon_parameters structure
2584  * @return                0 -- success, otherwise fail
2585  */
2586 int woal_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
2587 			     struct beacon_parameters *params)
2588 #endif
2589 {
2590 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2591 	int ret = 0;
2592 
2593 	ENTER();
2594 
2595 	PRINTM(MIOCTL, "set beacon\n");
2596 	if (params != NULL) {
2597 #if CFG80211_VERSION_CODE < KERNEL_VERSION(3, 2, 0)
2598 		if (params->tail && params->tail_len) {
2599 			ret = woal_cfg80211_mgmt_frame_ie(
2600 				priv, params->tail, params->tail_len, NULL, 0,
2601 				NULL, 0, NULL, 0, MGMT_MASK_BEACON,
2602 				MOAL_IOCTL_WAIT);
2603 			if (ret)
2604 				goto done;
2605 		}
2606 #else
2607 		t_u16 mask = 0;
2608 		if (params->tail && params->tail_len)
2609 			mask |= MGMT_MASK_BEACON;
2610 		if (params->proberesp_ies && params->proberesp_ies_len)
2611 			mask |= MGMT_MASK_PROBE_RESP;
2612 		if (params->assocresp_ies && params->assocresp_ies_len)
2613 			mask |= MGMT_MASK_ASSOC_RESP;
2614 		PRINTM(MIOCTL, "Set beacon: mask=0x%x\n", mask);
2615 		if (mask) {
2616 			ret = woal_cfg80211_mgmt_frame_ie(
2617 				priv, params->tail, params->tail_len,
2618 				params->proberesp_ies,
2619 				params->proberesp_ies_len,
2620 				params->assocresp_ies,
2621 				params->assocresp_ies_len, NULL, 0, mask,
2622 				MOAL_IOCTL_WAIT);
2623 			if (ret)
2624 				goto done;
2625 		}
2626 		if (params->beacon_ies && params->beacon_ies_len) {
2627 			ret = woal_cfg80211_mgmt_frame_ie(
2628 				priv, params->beacon_ies,
2629 				params->beacon_ies_len, NULL, 0, NULL, 0, NULL,
2630 				0, MGMT_MASK_BEACON_WPS_P2P, MOAL_IOCTL_WAIT);
2631 			if (ret) {
2632 				PRINTM(MERROR,
2633 				       "Failed to set beacon wps/p2p ie\n");
2634 				goto done;
2635 			}
2636 		}
2637 #endif
2638 	}
2639 
2640 done:
2641 	LEAVE();
2642 	return ret;
2643 }
2644 
2645 /**
2646  * @brief reset AP or GO parameters
2647  *
2648  * @param wiphy           A pointer to wiphy structure
2649  * @param dev             A pointer to net_device structure
2650  *
2651  * @return                0 -- success, otherwise fail
2652  */
2653 #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
woal_cfg80211_del_beacon(struct wiphy * wiphy,struct net_device * dev,unsigned int link_id)2654 int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev,
2655 			     unsigned int link_id)
2656 #else
2657 int woal_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
2658 #endif
2659 {
2660 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2661 	int ret = 0;
2662 #ifdef STA_SUPPORT
2663 	moal_private *pmpriv = NULL;
2664 #endif
2665 
2666 	ENTER();
2667 
2668 	if (priv->phandle->driver_status) {
2669 		PRINTM(MERROR,
2670 		       "Block  woal_cfg80211_del_beacon in abnormal driver state\n");
2671 		LEAVE();
2672 		return ret;
2673 	}
2674 	priv->uap_host_based = MFALSE;
2675 	PRINTM(MMSG, "wlan: Stoping AP\n");
2676 #ifdef STA_SUPPORT
2677 	woal_cancel_scan(priv, MOAL_IOCTL_WAIT);
2678 #endif
2679 	memset(priv->dscp_map, 0xFF, sizeof(priv->dscp_map));
2680 	woal_deauth_all_station(priv);
2681 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2682 	if (moal_extflg_isset(priv->phandle, EXT_DFS_OFFLOAD))
2683 		woal_cancel_cac_block(priv);
2684 #endif
2685 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
2686 	memset(&priv->chan, 0, sizeof(struct cfg80211_chan_def));
2687 	if (priv->phandle->is_cac_timer_set &&
2688 	    priv->bss_index == priv->phandle->cac_bss_index) {
2689 		woal_cancel_timer(&priv->phandle->cac_timer);
2690 		priv->phandle->is_cac_timer_set = MFALSE;
2691 		/* Make sure Chan Report is cancelled */
2692 		if (woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT))
2693 			PRINTM(MERROR, "%s: cancel chan report failed \n",
2694 			       __func__);
2695 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
2696 		cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel,
2697 				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
2698 #else
2699 		cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED,
2700 				   GFP_KERNEL);
2701 #endif
2702 		memset(&priv->phandle->dfs_channel, 0,
2703 		       sizeof(struct cfg80211_chan_def));
2704 		priv->phandle->cac_bss_index = 0xff;
2705 	}
2706 	if (priv->csa_workqueue)
2707 		flush_workqueue(priv->csa_workqueue);
2708 #endif
2709 	/* if the bss is still running, then stop it */
2710 	if (priv->bss_started == MTRUE) {
2711 		if (woal_uap_bss_ctrl(priv, MOAL_NO_WAIT, UAP_BSS_STOP)) {
2712 			PRINTM(MERROR, "%s: stop uap failed \n", __func__);
2713 			ret = -EFAULT;
2714 			goto done;
2715 		}
2716 		if (woal_uap_bss_ctrl(priv, MOAL_NO_WAIT, UAP_BSS_RESET)) {
2717 			PRINTM(MERROR, "%s: reset uap failed \n", __func__);
2718 			ret = -EFAULT;
2719 			goto done;
2720 		}
2721 		/* Set WLAN MAC addresses */
2722 		if (MLAN_STATUS_FAILURE ==
2723 		    woal_request_set_mac_address(priv, MOAL_NO_WAIT)) {
2724 			PRINTM(MERROR, "Set MAC address failed\n");
2725 			ret = -EFAULT;
2726 			goto done;
2727 		}
2728 	}
2729 	woal_clear_all_mgmt_ies(priv, MOAL_NO_WAIT);
2730 #ifdef STA_SUPPORT
2731 	if (!woal_is_any_interface_active(priv->phandle)) {
2732 		pmpriv = woal_get_priv((moal_handle *)priv->phandle,
2733 				       MLAN_BSS_ROLE_STA);
2734 		if (pmpriv)
2735 			woal_set_scan_time(pmpriv, ACTIVE_SCAN_CHAN_TIME,
2736 					   PASSIVE_SCAN_CHAN_TIME,
2737 					   SPECIFIC_SCAN_CHAN_TIME);
2738 	}
2739 #endif
2740 
2741 	priv->cipher = 0;
2742 	memset(priv->uap_wep_key, 0, sizeof(priv->uap_wep_key));
2743 	priv->channel = 0;
2744 	PRINTM(MMSG, "wlan: AP stopped\n");
2745 done:
2746 	LEAVE();
2747 	return ret;
2748 }
2749 
2750 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
2751 /**
2752  * @brief change BSS
2753  *
2754  * @param wiphy           A pointer to wiphy structure
2755  * @param dev             A pointer to net_device structure
2756  * @param params          A pointer to bss_parameters structure
2757  *
2758  * @return                0 -- success, otherwise fail
2759  */
woal_cfg80211_change_bss(struct wiphy * wiphy,struct net_device * dev,struct bss_parameters * params)2760 int woal_cfg80211_change_bss(struct wiphy *wiphy, struct net_device *dev,
2761 			     struct bss_parameters *params)
2762 {
2763 	int ret = 0;
2764 	t_u8 change = MFALSE;
2765 	mlan_uap_bss_param *sys_config = NULL;
2766 	u8 bss_started = MFALSE;
2767 	t_u8 pkt_forward_ctl;
2768 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2769 
2770 	ENTER();
2771 	PRINTM(MIOCTL, "isolate=%d\n", params->ap_isolate);
2772 
2773 	sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
2774 	if (!sys_config) {
2775 		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
2776 		LEAVE();
2777 		return -EFAULT;
2778 	}
2779 
2780 	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
2781 							   MOAL_IOCTL_WAIT,
2782 							   sys_config)) {
2783 		PRINTM(MERROR, "Error getting AP confiruration\n");
2784 		ret = -EFAULT;
2785 		goto done;
2786 	}
2787 
2788 	pkt_forward_ctl = sys_config->pkt_forward_ctl;
2789 	if (params->ap_isolate) {
2790 		/** disable packet forwarding */
2791 		sys_config->pkt_forward_ctl |= PKT_FWD_INTRA_BCAST;
2792 		sys_config->pkt_forward_ctl |= PKT_FWD_INTRA_UCAST;
2793 	} else {
2794 		sys_config->pkt_forward_ctl &= ~PKT_FWD_INTRA_BCAST;
2795 		sys_config->pkt_forward_ctl &= ~PKT_FWD_INTRA_UCAST;
2796 	}
2797 	if (pkt_forward_ctl != sys_config->pkt_forward_ctl) {
2798 		change = MTRUE;
2799 		PRINTM(MIOCTL, "ap_isolate=%xd\n", params->ap_isolate);
2800 	}
2801 	if (change) {
2802 		if (priv->bss_started == MTRUE) {
2803 			bss_started = MTRUE;
2804 			if (woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT,
2805 					      UAP_BSS_STOP))
2806 				PRINTM(MERROR, "%s: stop uap failed \n",
2807 				       __func__);
2808 		}
2809 		if (params->use_short_preamble == 1)
2810 			sys_config->preamble_type = 1;
2811 		else if (params->use_short_preamble == 0)
2812 			sys_config->preamble_type = 2;
2813 		else
2814 			sys_config->preamble_type = 0;
2815 		if (MLAN_STATUS_SUCCESS ==
2816 		    woal_set_get_sys_config(priv, MLAN_ACT_SET, MOAL_IOCTL_WAIT,
2817 					    sys_config))
2818 			ret = 0;
2819 		if (bss_started) {
2820 			if (woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT_TIMEOUT,
2821 					      UAP_BSS_START))
2822 				PRINTM(MERROR, "%s: start uap failed \n",
2823 				       __func__);
2824 		}
2825 	}
2826 done:
2827 	kfree(sys_config);
2828 	LEAVE();
2829 	return ret;
2830 }
2831 #endif
2832 
2833 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
2834 /**
2835  * @brief del station
2836  *
2837  * @param wiphy           A pointer to wiphy structure
2838  * @param dev             A pointer to net_device structure
2839  * @param param           A pointer tostation_del_parameters structure
2840  *
2841  * @return                0 -- success, otherwise fail
2842  */
2843 #else
2844 /**
2845  * @brief del station
2846  *
2847  * @param wiphy           A pointer to wiphy structure
2848  * @param dev             A pointer to net_device structure
2849  * @param mac_addr		  A pointer to station mac address
2850  *
2851  * @return                0 -- success, otherwise fail
2852  */
2853 #endif
woal_cfg80211_del_station(struct wiphy * wiphy,struct net_device * dev,struct station_del_parameters * param)2854 int woal_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
2855 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
2856 			      struct station_del_parameters *param)
2857 #else
2858 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
2859 			      const u8 *mac_addr)
2860 #else
2861 			      u8 *mac_addr)
2862 #endif
2863 #endif
2864 {
2865 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
2866 	const u8 *mac_addr = NULL;
2867 #endif
2868 	u16 reason_code = REASON_CODE_DEAUTH_LEAVING;
2869 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2870 	ENTER();
2871 
2872 #ifdef UAP_SUPPORT
2873 	if ((priv->bss_type == MLAN_BSS_TYPE_UAP) && !priv->bss_started) {
2874 		woal_cancel_cac(priv);
2875 		LEAVE();
2876 		return 0;
2877 	}
2878 #endif
2879 
2880 	if (priv->media_connected == MFALSE) {
2881 		PRINTM(MINFO, "cfg80211: Media not connected!\n");
2882 		LEAVE();
2883 		return 0;
2884 	}
2885 
2886 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)
2887 	if (param) {
2888 		mac_addr = param->mac;
2889 		reason_code = param->reason_code;
2890 	}
2891 #endif
2892 
2893 	/** we will not send deauth to p2p interface, it might cause WPS failure
2894 	 */
2895 	if (mac_addr
2896 #ifdef WIFI_DIRECT_SUPPORT
2897 	    && !priv->phandle->is_go_timer_set
2898 #endif
2899 	) {
2900 		if (woal_deauth_assoc_station(priv, (u8 *)mac_addr,
2901 					      reason_code))
2902 			PRINTM(MMSG, "wlan: deauth station " MACSTR " failed\n",
2903 			       MAC2STR(mac_addr));
2904 	} else {
2905 		PRINTM(MIOCTL, "del station\n");
2906 	}
2907 	LEAVE();
2908 	return 0;
2909 }
2910 
2911 /**
2912  * @brief Get station info
2913  *
2914  * @param wiphy           A pointer to wiphy structure
2915  * @param dev             A pointer to net_device structure
2916  * @param mac			  A pointer to station mac address
2917  * @param stainfo		  A pointer to station_info structure
2918  *
2919  * @return                0 -- success, otherwise fail
2920  */
woal_uap_cfg80211_get_station(struct wiphy * wiphy,struct net_device * dev,const u8 * mac,struct station_info * stainfo)2921 int woal_uap_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
2922 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
2923 				  const u8 *mac,
2924 #else
2925 				  u8 *mac,
2926 #endif
2927 				  struct station_info *stainfo)
2928 {
2929 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
2930 	int ret = -EFAULT;
2931 	int i = 0;
2932 	mlan_ds_get_info *info = NULL;
2933 	mlan_ioctl_req *ioctl_req = NULL;
2934 	mlan_status status = MLAN_STATUS_SUCCESS;
2935 	mlan_ds_get_stats stats;
2936 
2937 	ENTER();
2938 	if (priv->media_connected == MFALSE) {
2939 		PRINTM(MINFO, "cfg80211: Media not connected!\n");
2940 		LEAVE();
2941 		return -ENOENT;
2942 	}
2943 
2944 	/* Allocate an IOCTL request buffer */
2945 	ioctl_req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
2946 		sizeof(mlan_ds_get_info));
2947 	if (ioctl_req == NULL) {
2948 		ret = -ENOMEM;
2949 		goto done;
2950 	}
2951 
2952 	info = (mlan_ds_get_info *)ioctl_req->pbuf;
2953 	info->sub_command = MLAN_OID_UAP_STA_LIST;
2954 	ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
2955 	ioctl_req->action = MLAN_ACT_GET;
2956 
2957 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
2958 	if (status != MLAN_STATUS_SUCCESS)
2959 		goto done;
2960 	for (i = 0; i < info->param.sta_list.sta_count; i++) {
2961 		if (!memcmp(info->param.sta_list.info[i].mac_address, mac,
2962 			    ETH_ALEN)) {
2963 			PRINTM(MIOCTL, "Get station: " MACSTR " RSSI=%d\n",
2964 			       MAC2STR(mac),
2965 			       (int)info->param.sta_list.info[i].rssi);
2966 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
2967 			stainfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME) |
2968 					  BIT(NL80211_STA_INFO_RX_BYTES) |
2969 					  BIT(NL80211_STA_INFO_TX_BYTES) |
2970 					  BIT(NL80211_STA_INFO_RX_PACKETS) |
2971 					  BIT(NL80211_STA_INFO_TX_PACKETS) |
2972 					  BIT(NL80211_STA_INFO_SIGNAL);
2973 			stainfo->rx_bytes =
2974 				info->param.sta_list.info[i].stats.rx_bytes;
2975 			stainfo->tx_bytes =
2976 				info->param.sta_list.info[i].stats.tx_bytes;
2977 			stainfo->rx_packets =
2978 				info->param.sta_list.info[i].stats.rx_packets;
2979 			stainfo->tx_packets =
2980 				info->param.sta_list.info[i].stats.tx_packets;
2981 #else
2982 			stainfo->filled = STATION_INFO_INACTIVE_TIME |
2983 					  STATION_INFO_SIGNAL;
2984 #endif
2985 			stainfo->inactive_time = 0;
2986 			stainfo->signal = info->param.sta_list.info[i].rssi;
2987 			ret = 0;
2988 			break;
2989 		}
2990 	}
2991 	memset(&stats, 0, sizeof(mlan_ds_get_stats));
2992 	if (MLAN_STATUS_SUCCESS !=
2993 	    woal_get_stats_info(priv, MOAL_IOCTL_WAIT, &stats)) {
2994 		PRINTM(MERROR, "Error getting stats information\n");
2995 		ret = MLAN_STATUS_FAILURE;
2996 		goto done;
2997 	}
2998 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
2999 	stainfo->filled |= BIT(NL80211_STA_INFO_TX_RETRIES) |
3000 			   BIT(NL80211_STA_INFO_TX_FAILED) |
3001 			   BIT(NL80211_STA_INFO_RX_DROP_MISC);
3002 	stainfo->tx_failed = stats.failed;
3003 	stainfo->tx_retries = stats.retry;
3004 	stainfo->rx_dropped_misc = stats.fcs_error;
3005 #endif
3006 done:
3007 	if (status != MLAN_STATUS_PENDING)
3008 		kfree(ioctl_req);
3009 	LEAVE();
3010 	return ret;
3011 }
3012 
3013 /**
3014  * @brief Request the driver to dump the station information
3015  *
3016  * @param wiphy           A pointer to wiphy structure
3017  * @param dev             A pointer to net_device structure
3018  * @param idx             Station index
3019  * @param mac             MAC address of the station
3020  * @param sinfo           A pointer to station_info structure
3021  *
3022  * @return                0 -- success, otherwise fail
3023  */
woal_uap_cfg80211_dump_station(struct wiphy * wiphy,struct net_device * dev,int idx,t_u8 * mac,struct station_info * sinfo)3024 int woal_uap_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
3025 				   int idx, t_u8 *mac,
3026 				   struct station_info *sinfo)
3027 {
3028 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
3029 	int ret = -EFAULT;
3030 	mlan_ds_get_info *info = NULL;
3031 	mlan_ioctl_req *ioctl_req = NULL;
3032 	mlan_status status = MLAN_STATUS_SUCCESS;
3033 	t_u32 sec = 0, usec = 0;
3034 	t_u64 cur_msec = 0;
3035 
3036 	ENTER();
3037 	if (priv->media_connected == MFALSE) {
3038 		PRINTM(MINFO, "cfg80211: Media not connected!\n");
3039 		LEAVE();
3040 		return -ENOENT;
3041 	}
3042 
3043 	/* Allocate an IOCTL request buffer */
3044 	ioctl_req = (mlan_ioctl_req *)woal_alloc_mlan_ioctl_req(
3045 		sizeof(mlan_ds_get_info));
3046 	if (ioctl_req == NULL) {
3047 		ret = -ENOMEM;
3048 		goto done;
3049 	}
3050 
3051 	info = (mlan_ds_get_info *)ioctl_req->pbuf;
3052 	info->sub_command = MLAN_OID_UAP_STA_LIST;
3053 	ioctl_req->req_id = MLAN_IOCTL_GET_INFO;
3054 	ioctl_req->action = MLAN_ACT_GET;
3055 
3056 	status = woal_request_ioctl(priv, ioctl_req, MOAL_IOCTL_WAIT);
3057 	if (status != MLAN_STATUS_SUCCESS)
3058 		goto done;
3059 	if (idx >= info->param.sta_list.sta_count) {
3060 		ret = -EFAULT;
3061 		goto done;
3062 	}
3063 	ret = 0;
3064 	moal_memcpy_ext(priv->phandle, mac,
3065 			info->param.sta_list.info[idx].mac_address, ETH_ALEN,
3066 			ETH_ALEN);
3067 	PRINTM(MIOCTL, "Dump station: " MACSTR " RSSI=%d\n", MAC2STR(mac),
3068 	       (int)info->param.sta_list.info[idx].rssi);
3069 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)
3070 	sinfo->filled = BIT(NL80211_STA_INFO_INACTIVE_TIME) |
3071 			BIT(NL80211_STA_INFO_SIGNAL);
3072 #else
3073 	sinfo->filled = STATION_INFO_INACTIVE_TIME | STATION_INFO_SIGNAL;
3074 #endif
3075 	if (info->param.sta_list.info[idx].stats.last_rx_in_msec) {
3076 		moal_get_system_time(priv->phandle, &sec, &usec);
3077 		cur_msec = (t_u64)sec * 1000 + (t_u64)usec / 1000;
3078 		sinfo->inactive_time = (t_u32)(
3079 			cur_msec -
3080 			info->param.sta_list.info[idx].stats.last_rx_in_msec);
3081 		PRINTM(MIOCTL,
3082 		       "cur:%llu - [%d].last_rx:%llu = inactive_time:%d\n",
3083 		       cur_msec, idx,
3084 		       info->param.sta_list.info[idx].stats.last_rx_in_msec,
3085 		       sinfo->inactive_time);
3086 	} else
3087 		sinfo->inactive_time = 0;
3088 	sinfo->signal = info->param.sta_list.info[idx].rssi;
3089 done:
3090 	if (status != MLAN_STATUS_PENDING)
3091 		kfree(ioctl_req);
3092 	LEAVE();
3093 	return ret;
3094 }
3095 
3096 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
3097 /**
3098  * @brief set mac filter
3099  *
3100  * @param wiphy           A pointer to wiphy structure
3101  * @param dev             A pointer to net_device structure
3102  * @param params		  A pointer to cfg80211_acl_data structure
3103  *
3104  * @return                0 -- success, otherwise fail
3105  */
woal_cfg80211_set_mac_acl(struct wiphy * wiphy,struct net_device * dev,const struct cfg80211_acl_data * params)3106 int woal_cfg80211_set_mac_acl(struct wiphy *wiphy, struct net_device *dev,
3107 			      const struct cfg80211_acl_data *params)
3108 {
3109 	int ret = -EFAULT;
3110 	mlan_uap_bss_param *sys_config = NULL;
3111 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
3112 	u8 bss_started = MFALSE;
3113 	ENTER();
3114 
3115 	PRINTM(MIOCTL, "Set mac acl, entries=%d, policy=%d\n",
3116 	       params->n_acl_entries, params->acl_policy);
3117 	sys_config = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
3118 	if (!sys_config) {
3119 		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
3120 		LEAVE();
3121 		return -EFAULT;
3122 	}
3123 
3124 	/* Initialize the uap bss values which are uploaded from firmware */
3125 	if (MLAN_STATUS_SUCCESS != woal_set_get_sys_config(priv, MLAN_ACT_GET,
3126 							   MOAL_IOCTL_WAIT,
3127 							   sys_config)) {
3128 		PRINTM(MERROR, "Error getting AP confiruration\n");
3129 		ret = -EFAULT;
3130 		goto done;
3131 	}
3132 	memset(&sys_config->filter, 0, sizeof(mac_filter));
3133 	if (params->n_acl_entries <= MAX_MAC_FILTER_NUM)
3134 		sys_config->filter.mac_count = params->n_acl_entries;
3135 	else
3136 		sys_config->filter.mac_count = MAX_MAC_FILTER_NUM;
3137 
3138 	if (params->acl_policy == NL80211_ACL_POLICY_DENY_UNLESS_LISTED)
3139 		sys_config->filter.filter_mode = MAC_FILTER_MODE_ALLOW_MAC;
3140 	else if (params->acl_policy == NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED)
3141 		sys_config->filter.filter_mode = MAC_FILTER_MODE_BLOCK_MAC;
3142 	moal_memcpy_ext(
3143 		priv->phandle, sys_config->filter.mac_list, params->mac_addrs,
3144 		sys_config->filter.mac_count * sizeof(mlan_802_11_mac_addr),
3145 		sizeof(sys_config->filter.mac_list));
3146 	if (priv->bss_started == MTRUE) {
3147 		bss_started = MTRUE;
3148 		if (woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT, UAP_BSS_STOP))
3149 			PRINTM(MERROR, "%s: stop uap failed \n", __func__);
3150 	}
3151 	if (MLAN_STATUS_SUCCESS == woal_set_get_sys_config(priv, MLAN_ACT_SET,
3152 							   MOAL_IOCTL_WAIT,
3153 							   sys_config))
3154 		ret = 0;
3155 done:
3156 	kfree(sys_config);
3157 	if (bss_started) {
3158 		if (woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT_TIMEOUT,
3159 				      UAP_BSS_START))
3160 			PRINTM(MERROR, "%s: start uap failed \n", __func__);
3161 	}
3162 	LEAVE();
3163 	return ret;
3164 }
3165 #endif
3166 
3167 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 1, 0)
3168 /**
3169  * @brief Set txq parameters
3170 
3171  * @param wiphy           A pointer to wiphy structure
3172  * @param dev             A pointer to net_device structure
3173  * @param params		  A pointer to ieee80211_txq_params structure
3174  *
3175  * @return                0 -- success, otherwise fail
3176  */
woal_cfg80211_set_txq_params(struct wiphy * wiphy,struct net_device * dev,struct ieee80211_txq_params * params)3177 int woal_cfg80211_set_txq_params(struct wiphy *wiphy, struct net_device *dev,
3178 				 struct ieee80211_txq_params *params)
3179 {
3180 	int ret = 0;
3181 	u8 ac = 0;
3182 	wmm_parameter_t ap_wmm_para;
3183 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
3184 
3185 	ENTER();
3186 
3187 	/* AC_BE: 0, AC_BK:1, AC_VI: 2, AC_VO:3 */
3188 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 5, 0)
3189 	switch (params->ac) {
3190 	case NL80211_AC_VO:
3191 		ac = 3;
3192 		break;
3193 	case NL80211_AC_VI:
3194 		ac = 2;
3195 		break;
3196 	case NL80211_AC_BK:
3197 		ac = 1;
3198 		break;
3199 	case NL80211_AC_BE:
3200 		ac = 0;
3201 		break;
3202 	default:
3203 		break;
3204 	}
3205 #else
3206 	switch (params->queue) {
3207 	case NL80211_TXQ_Q_VO:
3208 		ac = 3;
3209 		break;
3210 	case NL80211_TXQ_Q_VI:
3211 		ac = 2;
3212 		break;
3213 	case NL80211_TXQ_Q_BK:
3214 		ac = 1;
3215 		break;
3216 	case NL80211_TXQ_Q_BE:
3217 		ac = 0;
3218 		break;
3219 	default:
3220 		break;
3221 	}
3222 #endif
3223 
3224 	PRINTM(MMSG, "Set AC=%d, txop=%d cwmin=%d, cwmax=%d aifs=%d\n", ac,
3225 	       params->txop, params->cwmin, params->cwmax, params->aifs);
3226 
3227 	memset(&ap_wmm_para, 0, sizeof(wmm_parameter_t));
3228 
3229 	if (MLAN_STATUS_SUCCESS !=
3230 	    woal_set_get_ap_wmm_para(priv, MLAN_ACT_GET, &ap_wmm_para)) {
3231 		PRINTM(MERROR, "wlan: We don't support AP WMM parameter\n");
3232 		LEAVE();
3233 		return ret;
3234 	}
3235 	ap_wmm_para.ac_params[ac].aci_aifsn.aifsn = params->aifs;
3236 	ap_wmm_para.ac_params[ac].ecw.ecw_max = ilog2(params->cwmax + 1);
3237 	ap_wmm_para.ac_params[ac].ecw.ecw_min = ilog2(params->cwmin + 1);
3238 	ap_wmm_para.ac_params[ac].tx_op_limit = params->txop;
3239 	if (MLAN_STATUS_SUCCESS !=
3240 	    woal_set_get_ap_wmm_para(priv, MLAN_ACT_SET, &ap_wmm_para)) {
3241 		PRINTM(MERROR, "wlan: Fail to set AP WMM parameter\n");
3242 		ret = -EFAULT;
3243 	}
3244 	LEAVE();
3245 	return ret;
3246 }
3247 #endif
3248 
3249 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 17, 0)
3250 /**
3251  * @brief start background radar detection
3252  *
3253  * @param wiphy           A pointer to wiphy structure
3254  * @param chandef         A pointer to cfg80211_chan_def structure
3255  * @return                0 -- success, otherwise fail
3256  */
woal_cfg80211_set_radar_background(struct wiphy * wiphy,struct cfg80211_chan_def * chandef)3257 int woal_cfg80211_set_radar_background(struct wiphy *wiphy,
3258 				       struct cfg80211_chan_def *chandef)
3259 {
3260 	u32 cac_time_ms = DEF_CAC_DWELL_TIME;
3261 	moal_handle *handle = (moal_handle *)woal_get_wiphy_priv(wiphy);
3262 	moal_private *priv = woal_get_priv_bss_type(handle, MLAN_BSS_TYPE_DFS);
3263 	mlan_ds_11h_chan_rep_req chan_rpt_req;
3264 	int ret = 0;
3265 	mlan_status status;
3266 	ENTER();
3267 	if (!priv) {
3268 		PRINTM(MERROR,
3269 		       "DFS interface not avalible in set_radar_background\n");
3270 		return -EFAULT;
3271 	}
3272 	if (!chandef) {
3273 		PRINTM(MMSG, "Stop radar background\n");
3274 		woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
3275 		priv->chan_rpt_pending = MFALSE;
3276 		priv->radar_background = MFALSE;
3277 		memset(&priv->chan_rpt_req, 0,
3278 		       sizeof(mlan_ds_11h_chan_rep_req));
3279 		LEAVE();
3280 		return ret;
3281 	}
3282 	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR)) {
3283 		PRINTM(MERROR, "Not radar channel in set_radar_background\n");
3284 		LEAVE();
3285 		return -EFAULT;
3286 	}
3287 	if ((woal_is_etsi_country(priv->phandle->country_code) == MTRUE)) {
3288 		if (chandef->chan->hw_value == 120 ||
3289 		    chandef->chan->hw_value == 124 ||
3290 		    chandef->chan->hw_value == 128) {
3291 			cac_time_ms = MAX_CAC_DWELL_TIME;
3292 		}
3293 		if (chandef->chan->hw_value == 116 &&
3294 		    ((chandef->width == NL80211_CHAN_WIDTH_40) ||
3295 		     (chandef->width == NL80211_CHAN_WIDTH_80))) {
3296 			cac_time_ms = MAX_CAC_DWELL_TIME;
3297 		}
3298 	}
3299 	if (priv->chan_rpt_req.chanNum &&
3300 	    (priv->chan_rpt_req.chanNum != (t_u8)chandef->chan->hw_value)) {
3301 		woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT);
3302 		priv->chan_rpt_pending = MFALSE;
3303 		memset(&priv->chan_rpt_req, 0,
3304 		       sizeof(mlan_ds_11h_chan_rep_req));
3305 	}
3306 	chan_rpt_req.startFreq = START_FREQ_11A_BAND;
3307 	chan_rpt_req.chanNum = (t_u8)chandef->chan->hw_value;
3308 	chan_rpt_req.bandcfg.chanBand = BAND_5GHZ;
3309 	switch (chandef->width) {
3310 	case NL80211_CHAN_WIDTH_40:
3311 		chan_rpt_req.bandcfg.chanWidth = CHAN_BW_40MHZ;
3312 		break;
3313 	case NL80211_CHAN_WIDTH_80:
3314 		chan_rpt_req.bandcfg.chanWidth = CHAN_BW_80MHZ;
3315 		break;
3316 	case NL80211_CHAN_WIDTH_20:
3317 	case NL80211_CHAN_WIDTH_20_NOHT:
3318 	default:
3319 		chan_rpt_req.bandcfg.chanWidth = CHAN_BW_20MHZ;
3320 		break;
3321 	}
3322 	chan_rpt_req.millisec_dwell_time = cac_time_ms;
3323 	chan_rpt_req.host_based = MTRUE;
3324 	moal_memcpy_ext(priv->phandle, &priv->chan_rpt_req, &chan_rpt_req,
3325 			sizeof(mlan_ds_11h_chan_rep_req),
3326 			sizeof(mlan_ds_11h_chan_rep_req));
3327 	PRINTM(MCMND,
3328 	       "DFS: Start Background Radar detect on channel=%d, bandwidth=%d, cac time=%d\n",
3329 	       chan_rpt_req.chanNum, (int)(chan_rpt_req.bandcfg.chanWidth),
3330 	       chan_rpt_req.millisec_dwell_time);
3331 	status = woal_do_dfs_cac(priv, &chan_rpt_req);
3332 	if (status != MLAN_STATUS_SUCCESS) {
3333 		ret = -EFAULT;
3334 	} else {
3335 		priv->chan_rpt_pending = MTRUE;
3336 		priv->radar_background = MTRUE;
3337 		moal_memcpy_ext(priv->phandle, &priv->radar_background_chan,
3338 				chandef, sizeof(struct cfg80211_chan_def),
3339 				sizeof(struct cfg80211_chan_def));
3340 	}
3341 	LEAVE();
3342 	return ret;
3343 }
3344 #endif
3345 
3346 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
3347 /**
3348  * @brief cac timer call back function.
3349  *
3350  * @param context   a pointer to moal_handle
3351  *
3352  * @return           N/A
3353  */
woal_cac_timer_func(void * context)3354 void woal_cac_timer_func(void *context)
3355 {
3356 	moal_handle *handle = (moal_handle *)context;
3357 	moal_private *priv = handle->priv[handle->cac_bss_index];
3358 
3359 	PRINTM(MEVENT, "cac_timer fired.\n");
3360 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3361 	cfg80211_cac_event(priv->netdev, &handle->dfs_channel,
3362 			   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
3363 #else
3364 	cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
3365 #endif
3366 	handle->is_cac_timer_set = MFALSE;
3367 	memset(&handle->dfs_channel, 0, sizeof(struct cfg80211_chan_def));
3368 	handle->cac_bss_index = 0xff;
3369 }
3370 
3371 /**
3372  * @brief This function switch AP's channel
3373  *        1. clear mgmt IEs  		2. stop uAP
3374  *   	  3. set beacon after		4. set new channel
3375  *   	  5. start uAP    		    6. notify cfg80211
3376  *
3377  * @param priv          a pointer to moal_private
3378  * @param wait_option   wait option
3379  *
3380  * @return           N/A
3381  */
woal_switch_uap_channel(moal_private * priv,t_u8 wait_option)3382 static void woal_switch_uap_channel(moal_private *priv, t_u8 wait_option)
3383 {
3384 	chan_band_info uap_channel;
3385 	t_u8 chan2Offset = SEC_CHAN_NONE;
3386 	ENTER();
3387 	woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
3388 	if (woal_uap_bss_ctrl(priv, wait_option, UAP_BSS_STOP)) {
3389 		PRINTM(MERROR, "%s: stop uap failed \n", __func__);
3390 		goto done;
3391 	}
3392 	if (woal_cfg80211_set_beacon(priv->wdev->wiphy, priv->netdev,
3393 				     &priv->beacon_after)) {
3394 		PRINTM(MERROR, "%s: set mgmt ies failed \n", __func__);
3395 		goto done;
3396 	}
3397 
3398 	uap_channel.channel = ieee80211_frequency_to_channel(
3399 		priv->csa_chan.chan->center_freq);
3400 	switch (priv->csa_chan.width) {
3401 	case NL80211_CHAN_WIDTH_5:
3402 	case NL80211_CHAN_WIDTH_10:
3403 	case NL80211_CHAN_WIDTH_20_NOHT:
3404 		uap_channel.bandcfg.chanWidth = CHAN_BW_20MHZ;
3405 		break;
3406 	case NL80211_CHAN_WIDTH_20:
3407 		uap_channel.bandcfg.chanWidth = CHAN_BW_20MHZ;
3408 		break;
3409 	case NL80211_CHAN_WIDTH_40:
3410 		if (priv->csa_chan.center_freq1 <
3411 		    priv->csa_chan.chan->center_freq)
3412 			chan2Offset = SEC_CHAN_BELOW;
3413 		else
3414 			chan2Offset = SEC_CHAN_ABOVE;
3415 		uap_channel.bandcfg.chanWidth = CHAN_BW_40MHZ;
3416 		break;
3417 	case NL80211_CHAN_WIDTH_80:
3418 	case NL80211_CHAN_WIDTH_80P80:
3419 	case NL80211_CHAN_WIDTH_160:
3420 		uap_channel.bandcfg.chanWidth = CHAN_BW_80MHZ;
3421 		chan2Offset = woal_get_second_channel_offset(
3422 			priv, uap_channel.channel);
3423 		break;
3424 	default:
3425 		PRINTM(MWARN, "Unknown channel width: %d\n",
3426 		       priv->csa_chan.width);
3427 		break;
3428 	}
3429 	uap_channel.bandcfg.chanBand =
3430 		woal_ieee_band_to_radio_type(priv->csa_chan.chan->band);
3431 	uap_channel.bandcfg.chan2Offset = chan2Offset;
3432 	if (MLAN_STATUS_SUCCESS != woal_set_get_ap_channel(priv, MLAN_ACT_SET,
3433 							   wait_option,
3434 							   &uap_channel)) {
3435 		PRINTM(MERROR, "Fail to set ap channel \n");
3436 		goto done;
3437 	}
3438 	if (woal_uap_bss_ctrl(priv, MOAL_IOCTL_WAIT_TIMEOUT, UAP_BSS_START)) {
3439 		PRINTM(MERROR, "%s: start uap failed \n", __func__);
3440 		goto done;
3441 	}
3442 	PRINTM(MMSG, "CSA: old chan %d => new chan %d \n", priv->channel,
3443 	       uap_channel.channel);
3444 	priv->channel = uap_channel.channel;
3445 	moal_memcpy_ext(priv->phandle, &priv->chan, &priv->csa_chan,
3446 			sizeof(struct cfg80211_chan_def), sizeof(priv->chan));
3447 #if ((CFG80211_VERSION_CODE >= KERNEL_VERSION(5, 19, 2)) || IMX_ANDROID_13)
3448 	cfg80211_ch_switch_notify(priv->netdev, &priv->chan, 0);
3449 #else
3450 	cfg80211_ch_switch_notify(priv->netdev, &priv->chan);
3451 #endif
3452 	if (priv->uap_tx_blocked) {
3453 		if (!netif_carrier_ok(priv->netdev))
3454 			netif_carrier_on(priv->netdev);
3455 		woal_start_queue(priv->netdev);
3456 		priv->uap_tx_blocked = MFALSE;
3457 	}
3458 done:
3459 	LEAVE();
3460 	return;
3461 }
3462 
3463 /**
3464  * @brief csa work handler
3465  *
3466  * @param work            a pointer to work_struct
3467  *
3468  * @return                0 -- success, otherwise fail
3469  */
woal_csa_work_queue(struct work_struct * work)3470 void woal_csa_work_queue(struct work_struct *work)
3471 {
3472 	struct delayed_work *delayed_work =
3473 		container_of(work, struct delayed_work, work);
3474 	moal_private *priv = container_of(delayed_work, moal_private, csa_work);
3475 	ENTER();
3476 	if (priv->bss_started == MTRUE)
3477 		woal_switch_uap_channel(priv, MOAL_IOCTL_WAIT);
3478 	LEAVE();
3479 }
3480 
3481 #if KERNEL_VERSION(3, 12, 0) <= CFG80211_VERSION_CODE
3482 /*
3483  * @brief  handle WOAL_EVENT_CANCEL_CHANRPT
3484  *
3485  * @param priv           A pointer moal_private structure
3486  *
3487  * @return          N/A
3488  */
woal_process_cancel_chanrpt_event(moal_private * priv)3489 void woal_process_cancel_chanrpt_event(moal_private *priv)
3490 {
3491 	if (priv->phandle->is_cac_timer_set &&
3492 	    priv->bss_index == priv->phandle->cac_bss_index) {
3493 		woal_cancel_timer(&priv->phandle->cac_timer);
3494 		priv->phandle->is_cac_timer_set = MFALSE;
3495 		/* Make sure Chan Report is cancelled */
3496 		if (woal_11h_cancel_chan_report_ioctl(priv, MOAL_IOCTL_WAIT))
3497 			PRINTM(MERROR, "%s: cancel chan report failed \n",
3498 			       __func__);
3499 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 14, 0)
3500 		cfg80211_cac_event(priv->netdev, &priv->phandle->dfs_channel,
3501 				   NL80211_RADAR_CAC_ABORTED, GFP_KERNEL);
3502 #else
3503 		cfg80211_cac_event(priv->netdev, NL80211_RADAR_CAC_ABORTED,
3504 				   GFP_KERNEL);
3505 #endif
3506 		memset(&priv->phandle->dfs_channel, 0,
3507 		       sizeof(struct cfg80211_chan_def));
3508 		priv->phandle->cac_bss_index = 0xff;
3509 	}
3510 }
3511 #endif
3512 
3513 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
3514 /**
3515  * @brief start radar detection
3516  *
3517  * @param wiphy           A pointer to wiphy structure
3518  * @param dev             A pointer to net_device structure
3519  * @param chandef         A pointer to cfg80211_chan_def structure
3520  * @param cac_time_ms     A cac dwell time
3521  * @return                0 -- success, otherwise fail
3522  */
woal_cfg80211_start_radar_detection(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_chan_def * chandef,u32 cac_time_ms)3523 int woal_cfg80211_start_radar_detection(struct wiphy *wiphy,
3524 					struct net_device *dev,
3525 					struct cfg80211_chan_def *chandef,
3526 					u32 cac_time_ms)
3527 #else
3528 /**
3529  * @brief start radar detection
3530  *
3531  * @param wiphy           A pointer to wiphy structure
3532  * @param dev             A pointer to net_device structure
3533  * @param chandef         A pointer to cfg80211_chan_def structure
3534  * @return                0 -- success, otherwise fail
3535  */
3536 
3537 int woal_cfg80211_start_radar_detection(struct wiphy *wiphy,
3538 					struct net_device *dev,
3539 					struct cfg80211_chan_def *chandef)
3540 #endif
3541 {
3542 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
3543 	moal_handle *handle = priv->phandle;
3544 	mlan_ioctl_req *req = NULL;
3545 	mlan_ds_11h_chan_rep_req *pchan_rpt_req = NULL;
3546 	mlan_ds_11h_cfg *p11h_cfg = NULL;
3547 	int ret = 0;
3548 	mlan_status status = MLAN_STATUS_SUCCESS;
3549 
3550 	ENTER();
3551 
3552 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
3553 	PRINTM(MIOCTL, "start Radar detect, chan %d , Bw %d , Time %d \n",
3554 	       chandef->chan->hw_value, chandef->width, cac_time_ms);
3555 #else
3556 	PRINTM(MIOCTL, "start Radar detect, chan %d , Bw %d \n",
3557 	       chandef->chan->hw_value, chandef->width);
3558 #endif
3559 
3560 	if (priv->bss_started == MTRUE) {
3561 		PRINTM(MERROR, "recv CAC request when bss already started \n");
3562 		ret = -EFAULT;
3563 		goto done;
3564 	}
3565 	if (priv->phandle->cac_period || handle->is_cac_timer_set) {
3566 		PRINTM(MERROR,
3567 		       "Maybe other interface is doing CAC, please defer your oper\n");
3568 		ret = -EBUSY;
3569 		goto done;
3570 	}
3571 	req = woal_alloc_mlan_ioctl_req(sizeof(mlan_ds_11h_cfg));
3572 	if (NULL == req) {
3573 		ret = -ENOMEM;
3574 		goto done;
3575 	}
3576 
3577 	p11h_cfg = (mlan_ds_11h_cfg *)req->pbuf;
3578 	pchan_rpt_req = &p11h_cfg->param.chan_rpt_req;
3579 	pchan_rpt_req->startFreq = START_FREQ_11A_BAND;
3580 	pchan_rpt_req->chanNum = (t_u8)chandef->chan->hw_value;
3581 	woal_convert_chan_to_bandconfig(priv, &pchan_rpt_req->bandcfg, chandef);
3582 	pchan_rpt_req->host_based = MTRUE;
3583 
3584 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
3585 	pchan_rpt_req->millisec_dwell_time = cac_time_ms;
3586 #else
3587 	pchan_rpt_req->millisec_dwell_time = IEEE80211_DFS_MIN_CAC_TIME_MS;
3588 #endif
3589 	/* Since kernel doesn't support 600sec cac_timer for channels 120, 124,
3590 	 * and 128 (weather channels) in ETSI region, overwrite kernel's
3591 	 * cac_timer.
3592 	 */
3593 	if ((woal_is_etsi_country(priv->phandle->country_code) == MTRUE)) {
3594 		if (chandef->chan->hw_value == 120 ||
3595 		    chandef->chan->hw_value == 124 ||
3596 		    chandef->chan->hw_value == 128) {
3597 			pchan_rpt_req->millisec_dwell_time =
3598 				IEEE80211_DFS_MIN_CAC_TIME_MS * 10;
3599 		}
3600 		if (chandef->chan->hw_value == 116 &&
3601 		    ((chandef->width == NL80211_CHAN_WIDTH_40) ||
3602 		     (chandef->width == NL80211_CHAN_WIDTH_80))) {
3603 			pchan_rpt_req->millisec_dwell_time =
3604 				IEEE80211_DFS_MIN_CAC_TIME_MS * 10;
3605 		}
3606 	}
3607 	if (priv->user_cac_period_msec) {
3608 		pchan_rpt_req->millisec_dwell_time = priv->user_cac_period_msec;
3609 		PRINTM(MCMD_D,
3610 		       "cfg80211 dfstesting: User CAC Period=%d (msec) \n",
3611 		       pchan_rpt_req->millisec_dwell_time);
3612 	}
3613 
3614 	p11h_cfg->sub_command = MLAN_OID_11H_CHANNEL_CHECK;
3615 	req->req_id = MLAN_IOCTL_11H_CFG;
3616 	req->action = MLAN_ACT_SET;
3617 
3618 	/* Send Channel Check command and wait until the report is ready */
3619 	status = woal_request_ioctl(priv, req, MOAL_IOCTL_WAIT);
3620 	if (status != MLAN_STATUS_SUCCESS) {
3621 		PRINTM(MERROR, "Fail to start radar detection\n");
3622 		ret = -EFAULT;
3623 	} else {
3624 		moal_memcpy_ext(priv->phandle, &handle->dfs_channel, chandef,
3625 				sizeof(struct cfg80211_chan_def),
3626 				sizeof(handle->dfs_channel));
3627 		handle->cac_bss_index = priv->bss_index;
3628 		handle->is_cac_timer_set = MTRUE;
3629 		/* avoid EVENT_CHANNEL_RAPORT_READY missing, add 1s gap */
3630 		woal_mod_timer(&handle->cac_timer,
3631 			       pchan_rpt_req->millisec_dwell_time + 1000);
3632 	}
3633 done:
3634 	if (status != MLAN_STATUS_PENDING)
3635 		kfree(req);
3636 	LEAVE();
3637 	return ret;
3638 }
3639 
3640 /**
3641  * @brief channel switch
3642 
3643  * @param wiphy           A pointer to wiphy structure
3644  * @param dev             A pointer to net_device structure
3645  * @param params		  A pointer to cfg80211_csa_settings structure
3646  *
3647  * @return                0 -- success, otherwise fail
3648  */
woal_cfg80211_channel_switch(struct wiphy * wiphy,struct net_device * dev,struct cfg80211_csa_settings * params)3649 int woal_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
3650 				 struct cfg80211_csa_settings *params)
3651 {
3652 	int ret = 0;
3653 	moal_private *priv = (moal_private *)woal_get_netdev_priv(dev);
3654 	t_u32 chsw_msec;
3655 	mlan_uap_bss_param *bss_cfg = NULL;
3656 
3657 	ENTER();
3658 
3659 	if (!params) {
3660 		ret = -EINVAL;
3661 		goto done;
3662 	}
3663 	if (params->radar_required) {
3664 		PRINTM(MMSG, "switch to DFS channel\n");
3665 #if CFG80211_VERSION_CODE >= KERNEL_VERSION(3, 12, 0)
3666 		woal_enable_dfs_support(priv, &params->chandef);
3667 #endif
3668 	}
3669 	/* actually hostapd would always choose one diff channel*/
3670 	if (cfg80211_chandef_identical(&params->chandef, &priv->chan)) {
3671 		PRINTM(MMSG,
3672 		       "csa channel is same with current channel, invaild\n");
3673 		ret = -EINVAL;
3674 		goto done;
3675 	}
3676 	bss_cfg = kzalloc(sizeof(mlan_uap_bss_param), GFP_ATOMIC);
3677 	if (!bss_cfg) {
3678 		PRINTM(MERROR, "Fail to alloc memory for mlan_uap_bss_param\n");
3679 		ret = -EFAULT;
3680 		goto done;
3681 	}
3682 
3683 	if (params->block_tx) {
3684 		if (netif_carrier_ok(dev))
3685 			netif_carrier_off(dev);
3686 		woal_stop_queue(dev);
3687 		priv->uap_tx_blocked = MTRUE;
3688 	}
3689 
3690 	woal_clear_all_mgmt_ies(priv, MOAL_IOCTL_WAIT);
3691 	if (woal_cfg80211_set_beacon(wiphy, dev, &params->beacon_csa)) {
3692 		PRINTM(MERROR, "%s: setting csa mgmt ies failed\n", __func__);
3693 		goto done;
3694 	}
3695 
3696 	moal_memcpy_ext(priv->phandle, &priv->csa_chan, &params->chandef,
3697 			sizeof(struct cfg80211_chan_def),
3698 			sizeof(priv->csa_chan));
3699 	moal_memcpy_ext(priv->phandle, &priv->beacon_after,
3700 			&params->beacon_after,
3701 			sizeof(struct cfg80211_beacon_data),
3702 			sizeof(priv->beacon_after));
3703 
3704 	if (!priv->phandle->fw_ecsa_enable) {
3705 		if (MLAN_STATUS_SUCCESS !=
3706 		    woal_set_get_sys_config(priv, MLAN_ACT_GET, MOAL_IOCTL_WAIT,
3707 					    bss_cfg)) {
3708 			PRINTM(MERROR, "%s: get uap config failed\n", __func__);
3709 			ret = -EFAULT;
3710 			goto done;
3711 		}
3712 		chsw_msec = params->count * bss_cfg->beacon_period;
3713 		queue_delayed_work(priv->csa_workqueue, &priv->csa_work,
3714 				   msecs_to_jiffies(chsw_msec));
3715 	}
3716 done:
3717 	kfree(bss_cfg);
3718 	LEAVE();
3719 	return ret;
3720 }
3721 #endif
3722 
3723 /**
3724  * @brief Register the device with cfg80211
3725  *
3726  * @param dev       A pointer to net_device structure
3727  * @param bss_type  BSS type
3728  *
3729  * @return          MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3730  */
woal_register_uap_cfg80211(struct net_device * dev,t_u8 bss_type)3731 mlan_status woal_register_uap_cfg80211(struct net_device *dev, t_u8 bss_type)
3732 {
3733 	mlan_status ret = MLAN_STATUS_SUCCESS;
3734 	moal_private *priv = (moal_private *)netdev_priv(dev);
3735 	struct wireless_dev *wdev = NULL;
3736 
3737 	ENTER();
3738 
3739 	wdev = (struct wireless_dev *)&priv->w_dev;
3740 	memset(wdev, 0, sizeof(struct wireless_dev));
3741 
3742 	wdev->wiphy = priv->phandle->wiphy;
3743 	if (!wdev->wiphy) {
3744 		LEAVE();
3745 		return MLAN_STATUS_FAILURE;
3746 	}
3747 
3748 	if (bss_type == MLAN_BSS_TYPE_UAP)
3749 		wdev->iftype = NL80211_IFTYPE_AP;
3750 
3751 	dev_net_set(dev, wiphy_net(wdev->wiphy));
3752 	dev->ieee80211_ptr = wdev;
3753 	SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
3754 	priv->wdev = wdev;
3755 
3756 	LEAVE();
3757 	return ret;
3758 }
3759