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, ¶ms->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, ¶ms->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 = ¶ms->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, ¶ms->chandef);
3667 #endif
3668 }
3669 /* actually hostapd would always choose one diff channel*/
3670 if (cfg80211_chandef_identical(¶ms->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, ¶ms->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, ¶ms->chandef,
3697 sizeof(struct cfg80211_chan_def),
3698 sizeof(priv->csa_chan));
3699 moal_memcpy_ext(priv->phandle, &priv->beacon_after,
3700 ¶ms->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