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