xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/core/rtw_scan.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 - 2020 Realtek Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of version 2 of the GNU General Public License as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  *****************************************************************************/
15 #include <drv_types.h>
16 
17 /*rtw_mlme.c*/
rtw_init_sitesurvey_parm(_adapter * padapter,struct sitesurvey_parm * pparm)18 void rtw_init_sitesurvey_parm(_adapter *padapter, struct sitesurvey_parm *pparm)
19 {
20 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
21 
22 	_rtw_memset(pparm, 0, sizeof(struct sitesurvey_parm));
23 	pparm->scan_mode = pmlmepriv->scan_mode;
24 }
25 
26 #ifdef CONFIG_SET_SCAN_DENY_TIMER
rtw_is_scan_deny(_adapter * adapter)27 inline bool rtw_is_scan_deny(_adapter *adapter)
28 {
29 	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
30 	return (ATOMIC_READ(&mlmepriv->set_scan_deny) != 0) ? _TRUE : _FALSE;
31 }
rtw_clear_scan_deny(_adapter * adapter)32 inline void rtw_clear_scan_deny(_adapter *adapter)
33 {
34 	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
35 	ATOMIC_SET(&mlmepriv->set_scan_deny, 0);
36 	if (0)
37 		RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
38 }
39 
rtw_set_scan_deny_timer_hdl(void * ctx)40 void rtw_set_scan_deny_timer_hdl(void *ctx)
41 {
42 	_adapter *adapter = (_adapter *)ctx;
43 
44 	rtw_clear_scan_deny(adapter);
45 }
rtw_set_scan_deny(_adapter * adapter,u32 ms)46 void rtw_set_scan_deny(_adapter *adapter, u32 ms)
47 {
48 	struct mlme_priv *mlmepriv = &adapter->mlmepriv;
49 	if (0)
50 		RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
51 	ATOMIC_SET(&mlmepriv->set_scan_deny, 1);
52 	_set_timer(&mlmepriv->set_scan_deny_timer, ms);
53 }
54 #endif
55 
rtw_drv_scan_by_self(_adapter * padapter,u8 reason)56 void rtw_drv_scan_by_self(_adapter *padapter, u8 reason)
57 {
58 	struct sitesurvey_parm parm;
59 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
60 	int i;
61 #if 1
62 	u8 ssc_chk;
63 
64 	ssc_chk = rtw_sitesurvey_condition_check(padapter, _FALSE);
65 	if( ssc_chk == SS_DENY_BUSY_TRAFFIC) {
66 		#ifdef CONFIG_LAYER2_ROAMING
67 		if (rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE) && pmlmepriv->need_to_roam == _TRUE) {
68 			RTW_INFO(FUNC_ADPT_FMT" need to roam, don't care BusyTraffic\n", FUNC_ADPT_ARG(padapter));
69 		 } else
70 		#endif
71 		{
72 			RTW_INFO(FUNC_ADPT_FMT" exit BusyTraffic\n", FUNC_ADPT_ARG(padapter));
73 			goto exit;
74 		}
75 	} else if (ssc_chk != SS_ALLOW) {
76 		goto exit;
77 	}
78 
79 	if (!rtw_is_adapter_up(padapter))
80 		goto exit;
81 #else
82 	if (rtw_is_scan_deny(padapter))
83 		goto exit;
84 
85 	if (!rtw_is_adapter_up(padapter))
86 		goto exit;
87 
88 	if (rtw_mi_busy_traffic_check(padapter)) {
89 #ifdef CONFIG_LAYER2_ROAMING
90 		if (rtw_chk_roam_flags(padapter, RTW_ROAM_ACTIVE) && pmlmepriv->need_to_roam == _TRUE) {
91 			RTW_INFO("need to roam, don't care BusyTraffic\n");
92 		} else
93 #endif
94 		{
95 			RTW_INFO(FUNC_ADPT_FMT" exit BusyTraffic\n", FUNC_ADPT_ARG(padapter));
96 			goto exit;
97 		}
98 	}
99 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE) && check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
100 		RTW_INFO(FUNC_ADPT_FMT" WIFI_AP_STATE && WIFI_UNDER_WPS\n", FUNC_ADPT_ARG(padapter));
101 		goto exit;
102 	}
103 	if (check_fwstate(pmlmepriv, (WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING)) == _TRUE) {
104 		RTW_INFO(FUNC_ADPT_FMT" WIFI_UNDER_SURVEY|WIFI_UNDER_LINKING\n", FUNC_ADPT_ARG(padapter));
105 		goto exit;
106 	}
107 
108 #ifdef CONFIG_CONCURRENT_MODE
109 	if (rtw_mi_buddy_check_fwstate(padapter, (WIFI_UNDER_SURVEY | WIFI_UNDER_LINKING | WIFI_UNDER_WPS))) {
110 		RTW_INFO(FUNC_ADPT_FMT", but buddy_intf is under scanning or linking or wps_phase\n", FUNC_ADPT_ARG(padapter));
111 		goto exit;
112 	}
113 #endif
114 #endif
115 
116 	RTW_INFO(FUNC_ADPT_FMT" reason:0x%02x\n", FUNC_ADPT_ARG(padapter), reason);
117 
118 	/* only for 20/40 BSS */
119 	if (reason == RTW_AUTO_SCAN_REASON_2040_BSS) {
120 		rtw_init_sitesurvey_parm(padapter, &parm);
121 		for (i=0;i<14;i++) {
122 			parm.ch[i].hw_value = i + 1;
123 			parm.ch[i].flags = RTW_IEEE80211_CHAN_PASSIVE_SCAN;
124 		}
125 		parm.ch_num = 14;
126 		rtw_sitesurvey_cmd(padapter, &parm);
127 		goto exit;
128 	}
129 
130 #ifdef CONFIG_RTW_MBO
131 #if defined(CONFIG_RTW_WNM) || defined(CONFIG_RTW_80211K)
132 	if ((reason == RTW_AUTO_SCAN_REASON_ROAM)
133 		&& (rtw_roam_nb_scan_list_set(padapter, &parm)))
134 		goto exit;
135 #endif
136 #endif
137 
138 	rtw_sitesurvey_cmd(padapter, NULL);
139 exit:
140 	return;
141 }
142 
143 #ifdef CONFIG_RTW_ACS
rtw_set_acs_sitesurvey(_adapter * adapter)144 u8 rtw_set_acs_sitesurvey(_adapter *adapter)
145 {
146 	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
147 	struct sitesurvey_parm parm;
148 	u8 uch;
149 	u8 ch_num = 0;
150 	int i;
151 	enum band_type band;
152 	u8 (*center_chs_num)(u8) = NULL;
153 	u8 (*center_chs)(u8, u8) = NULL;
154 	u8 ret = _FAIL;
155 
156 	if (!rtw_mi_get_ch_setting_union(adapter, &uch, NULL, NULL))
157 		goto exit;
158 
159 	_rtw_memset(&parm, 0, sizeof(struct sitesurvey_parm));
160 	parm.scan_mode = RTW_PHL_SCAN_PASSIVE;
161 	parm.bw = CHANNEL_WIDTH_20;
162 	parm.acs = 1;
163 
164 	for (band = BAND_ON_24G; band < BAND_MAX; band++) {
165 		if (band == BAND_ON_24G) {
166 			center_chs_num = center_chs_2g_num;
167 			center_chs = center_chs_2g;
168 		} else
169 		#if CONFIG_IEEE80211_BAND_5GHZ
170 		if (band == BAND_ON_5G) {
171 			center_chs_num = center_chs_5g_num;
172 			center_chs = center_chs_5g;
173 		} else
174 		#endif
175 		{
176 			center_chs_num = NULL;
177 			center_chs = NULL;
178 		}
179 
180 		if (!center_chs_num || !center_chs)
181 			continue;
182 
183 		if (rfctl->ch_sel_within_same_band) {
184 			if (rtw_is_2g_ch(uch) && band != BAND_ON_24G)
185 				continue;
186 			#if CONFIG_IEEE80211_BAND_5GHZ
187 			if (rtw_is_5g_ch(uch) && band != BAND_ON_5G)
188 				continue;
189 			#endif
190 		}
191 
192 		ch_num = center_chs_num(CHANNEL_WIDTH_20);
193 		for (i = 0; i < ch_num && parm.ch_num < RTW_CHANNEL_SCAN_AMOUNT; i++) {
194 			parm.ch[parm.ch_num].hw_value = center_chs(CHANNEL_WIDTH_20, i);
195 			parm.ch[parm.ch_num].flags = RTW_IEEE80211_CHAN_PASSIVE_SCAN;
196 			parm.ch_num++;
197 		}
198 	}
199 
200 	ret = rtw_sitesurvey_cmd(adapter, &parm);
201 
202 exit:
203 	return ret;
204 }
205 #endif /* CONFIG_RTW_ACS */
206 
_rtw_wait_scan_done(_adapter * adapter,u32 timeout_ms)207 static u32 _rtw_wait_scan_done(_adapter *adapter, u32 timeout_ms)
208 {
209 	systime start;
210 	u32 pass_ms;
211 	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
212 	struct mlme_ext_priv *pmlmeext = &(adapter->mlmeextpriv);
213 	u8 abort_timeout = false;
214 
215 	start = rtw_get_current_time();
216 
217 	while ((rtw_cfg80211_get_is_roch(adapter) == _TRUE || check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY))
218 	       && rtw_get_passing_time_ms(start) <= timeout_ms) {
219 
220 		if (RTW_CANNOT_RUN(adapter_to_dvobj(adapter)))
221 			break;
222 
223 		RTW_INFO(FUNC_NDEV_FMT"fw_state=WIFI_UNDER_SURVEY!\n", FUNC_NDEV_ARG(adapter->pnetdev));
224 		rtw_msleep_os(20);
225 		abort_timeout = true;
226 	}
227 
228 	if (_TRUE == abort_timeout && check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY)) {
229 		if (!RTW_CANNOT_RUN(adapter_to_dvobj(adapter)))
230 			RTW_ERR(FUNC_NDEV_FMT"waiting for scan_abort time out!\n",
231 					FUNC_NDEV_ARG(adapter->pnetdev));
232 		pmlmeext->scan_abort_to = _TRUE;
233 		#ifdef CONFIG_PLATFORM_MSTAR
234 		/*_clr_fwstate_(pmlmepriv, WIFI_UNDER_SURVEY);*/
235 		/*set_survey_timer(pmlmeext, 0);*/
236 		mlme_set_scan_to_timer(pmlmepriv, 50);
237 		#endif
238 		rtw_indicate_scan_done(adapter, _TRUE);
239 	}
240 
241 	pmlmeext->scan_abort = _FALSE;
242 	RTW_INFO(FUNC_ADPT_FMT "- %s....scan_abort:%d\n",
243 		FUNC_ADPT_ARG(adapter), __func__, pmlmeext->scan_abort);
244 	pass_ms = rtw_get_passing_time_ms(start);
245 
246 	RTW_INFO("%s scan timeout value:%d ms, total take:%d ms\n",
247 				__func__, timeout_ms, pass_ms);
248 	return pass_ms;
249 }
250 
251 /*
252 * timeout_ms > 0:rtw_scan_abort_timeout , = 0:rtw_scan_wait_completed
253 */
rtw_scan_abort(_adapter * adapter,u32 timeout_ms)254 u32 rtw_scan_abort(_adapter *adapter, u32 timeout_ms)
255 {
256 	struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
257 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
258 	enum rtw_phl_status psts = RTW_PHL_STATUS_FAILURE;
259 	u32 pass_ms = 0;
260 
261 	if (rtw_cfg80211_get_is_roch(adapter) == _TRUE || check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY)) {
262 		pmlmeext->scan_abort = _TRUE;
263 		RTW_INFO(FUNC_ADPT_FMT "- %s....scan_abort:%d\n",
264 			FUNC_ADPT_ARG(adapter), __func__, pmlmeext->scan_abort);
265 		rtw_sctx_init(&pmlmeext->sitesurvey_res.sctx, timeout_ms);
266 
267 		#ifdef CONFIG_CMD_SCAN
268 		if (pmlmeext->sitesurvey_res.scan_param)
269 			psts = rtw_phl_cmd_scan_cancel(adapter_to_dvobj(adapter)->phl,
270 					pmlmeext->sitesurvey_res.scan_param);
271 		#else
272 		psts = rtw_phl_scan_cancel(adapter_to_dvobj(adapter)->phl);
273 		#endif
274 
275 		if (psts == RTW_PHL_STATUS_SUCCESS)
276 			rtw_sctx_wait(&pmlmeext->sitesurvey_res.sctx, __func__);
277 		pass_ms = _rtw_wait_scan_done(adapter, timeout_ms);
278 	}
279 	return pass_ms;
280 }
281 
rtw_scan_abort_no_wait(_adapter * adapter)282 void rtw_scan_abort_no_wait(_adapter *adapter)
283 {
284 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
285 
286 	#ifdef CONFIG_CMD_SCAN
287 	if (pmlmeext->sitesurvey_res.scan_param)
288 		rtw_phl_cmd_scan_cancel(adapter_to_dvobj(adapter)->phl,
289 			pmlmeext->sitesurvey_res.scan_param);
290 	#else
291 	rtw_phl_scan_cancel(adapter_to_dvobj(adapter)->phl);
292 	#endif
293 }
294 
295 /*
296 * rtw_scan_timeout_handler - Timeout/Faliure handler for CMD SiteSurvey
297 * @adapter: pointer to _adapter structure
298 */
rtw_scan_timeout_handler(void * ctx)299 void rtw_scan_timeout_handler(void *ctx)
300 {
301 	_adapter *adapter = (_adapter *)ctx;
302 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
303 	RTW_INFO(FUNC_ADPT_FMT" fw_state=%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
304 
305 	rtw_scan_abort_no_wait(adapter);
306 #if 0
307 	_rtw_spinlock_bh(&pmlmepriv->lock);
308 	_clr_fwstate_(pmlmepriv, WIFI_UNDER_SURVEY);
309 	_rtw_spinunlock_bh(&pmlmepriv->lock);
310 
311 	#ifdef CONFIG_IOCTL_CFG80211
312 	rtw_cfg80211_surveydone_event_callback(adapter);
313 	#endif /* CONFIG_IOCTL_CFG80211 */
314 	rtw_indicate_scan_done(adapter, _TRUE);
315 #endif
316 }
317 
_rtw_scan_abort_check(_adapter * adapter,const char * caller)318 static inline bool _rtw_scan_abort_check(_adapter *adapter, const char *caller)
319 {
320 	struct	mlme_priv *pmlmepriv = &adapter->mlmepriv;
321 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
322 	struct submit_ctx *sctx = &pmlmeext->sitesurvey_res.sctx;
323 
324 	RTW_INFO(FUNC_ADPT_FMT "- %s....scan_abort:%d\n",
325 			FUNC_ADPT_ARG(adapter), __func__, pmlmeext->scan_abort);
326 
327 	if (pmlmeext->scan_abort == _FALSE)
328 		return _FALSE;
329 
330 	if (pmlmeext->scan_abort_to) {
331 		RTW_ERR("%s scan abort timeout\n", caller);
332 		rtw_warn_on(1);
333 	}
334 	_cancel_timer_ex(&pmlmepriv->scan_to_timer);
335 	pmlmeext->scan_abort = _FALSE;
336 	pmlmeext->scan_abort_to = _FALSE;
337 	if (sctx) {
338 		RTW_INFO("%s scan abort .....(%d ms)\n", caller, rtw_get_passing_time_ms(sctx->submit_time));
339 		rtw_sctx_done(&sctx);
340 	}
341 	return _TRUE;
342 }
alloc_network(struct mlme_priv * pmlmepriv)343 static struct wlan_network *alloc_network(struct	mlme_priv *pmlmepriv) /* (_queue	*free_queue) */
344 {
345 	struct	wlan_network	*pnetwork;
346 	pnetwork = _rtw_alloc_network(pmlmepriv);
347 	return pnetwork;
348 }
349 
update_current_network(_adapter * adapter,WLAN_BSSID_EX * pnetwork)350 static void update_current_network(_adapter *adapter, WLAN_BSSID_EX *pnetwork)
351 {
352 	struct	mlme_priv *pmlmepriv = &(adapter->mlmepriv);
353 
354 	if ((check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE) && (is_same_network(&(pmlmepriv->cur_network.network), pnetwork))) {
355 
356 		/* if(pmlmepriv->cur_network.network.IELength<= pnetwork->IELength) */
357 		{
358 			rtw_update_network(&(pmlmepriv->cur_network.network), pnetwork, adapter, _TRUE);
359 			rtw_update_protection(adapter, (pmlmepriv->cur_network.network.IEs) + sizeof(NDIS_802_11_FIXED_IEs),
360 				      pmlmepriv->cur_network.network.IELength);
361 		}
362 	}
363 }
364 
365 /*Caller must hold pmlmepriv->lock first.*/
update_scanned_network(_adapter * adapter,WLAN_BSSID_EX * target)366 static bool update_scanned_network(_adapter *adapter, WLAN_BSSID_EX *target)
367 {
368 	_list	*plist, *phead;
369 	u32	bssid_ex_sz;
370 	struct mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
371 #ifdef CONFIG_P2P
372 	struct wifidirect_info *pwdinfo = &(adapter->wdinfo);
373 #endif /* CONFIG_P2P */
374 	_queue	*queue	= &(pmlmepriv->scanned_queue);
375 	struct wlan_network	*pnetwork = NULL;
376 	struct wlan_network	*choice = NULL;
377 	int target_find = 0;
378 	bool update_ie = _FALSE;
379 
380 	_rtw_spinlock_bh(&queue->lock);
381 	phead = get_list_head(queue);
382 	plist = get_next(phead);
383 
384 #if 0
385 	RTW_INFO("%s => ssid:%s , rssi:%ld , ss:%d\n",
386 		__func__, target->Ssid.Ssid, target->PhyInfo.rssi, target->PhyInfo.SignalStrength);
387 #endif
388 
389 	while (1) {
390 		if (rtw_end_of_queue_search(phead, plist) == _TRUE)
391 			break;
392 
393 		pnetwork = LIST_CONTAINOR(plist, struct wlan_network, list);
394 
395 #ifdef CONFIG_P2P
396 		if (_rtw_memcmp(pnetwork->network.MacAddress, target->MacAddress, ETH_ALEN) &&
397 		    _rtw_memcmp(pnetwork->network.Ssid.Ssid, "DIRECT-", 7) &&
398 		    rtw_get_p2p_ie(pnetwork->network.IEs + _FIXED_IE_LENGTH_,
399 				   pnetwork->network.IELength - _FIXED_IE_LENGTH_,
400 				   NULL, NULL)) {
401 			target_find = 1;
402 			break;
403 		}
404 #endif
405 
406 		if (is_same_network(&(pnetwork->network), target)) {
407 			target_find = 1;
408 			break;
409 		}
410 
411 		if (rtw_roam_flags(adapter)) {
412 			/* TODO: don't  select netowrk in the same ess as choice if it's new enough*/
413 		}
414 		if (pnetwork->fixed) {
415 			plist = get_next(plist);
416 			continue;
417 		}
418 
419 #ifdef CONFIG_RSSI_PRIORITY
420 		if ((choice == NULL) || (pnetwork->network.PhyInfo.SignalStrength < choice->network.PhyInfo.SignalStrength))
421 			#ifdef CONFIG_RTW_MESH
422 			if (!MLME_IS_MESH(adapter) || !MLME_IS_ASOC(adapter)
423 				|| !rtw_bss_is_same_mbss(&pmlmepriv->cur_network.network, &pnetwork->network))
424 			#endif
425 				choice = pnetwork;
426 #else
427 		if (choice == NULL || rtw_time_after(choice->last_scanned, pnetwork->last_scanned))
428 			#ifdef CONFIG_RTW_MESH
429 			if (!MLME_IS_MESH(adapter) || !MLME_IS_ASOC(adapter)
430 				|| !rtw_bss_is_same_mbss(&pmlmepriv->cur_network.network, &pnetwork->network))
431 			#endif
432 				choice = pnetwork;
433 #endif
434 		plist = get_next(plist);
435 
436 	}
437 
438 
439 	/* If we didn't find a match, then get a new network slot to initialize
440 	 * with this beacon's information */
441 	/* if (rtw_end_of_queue_search(phead,plist)== _TRUE) { */
442 	if (!target_find) {
443 		if (_rtw_queue_empty(&(pmlmepriv->free_bss_pool)) == _TRUE) {
444 			/* If there are no more slots, expire the choice */
445 			/* list_del_init(&choice->list); */
446 			pnetwork = choice;
447 			if (pnetwork == NULL)
448 				goto unlock_scan_queue;
449 
450 #ifdef CONFIG_RSSI_PRIORITY
451 			RTW_DBG("%s => ssid:%s ,bssid:"MAC_FMT"  will be deleted from scanned_queue (rssi:%d , ss:%d)\n",
452 			__func__, pnetwork->network.Ssid.Ssid, MAC_ARG(pnetwork->network.MacAddress),
453 			pnetwork->network.PhyInfo.rssi, pnetwork->network.PhyInfo.SignalStrength);
454 #else
455 			RTW_DBG("%s => ssid:%s ,bssid:"MAC_FMT" will be deleted from scanned_queue\n",
456 			__func__, pnetwork->network.Ssid.Ssid, MAC_ARG(pnetwork->network.MacAddress));
457 #endif
458 
459 			_rtw_memcpy(&(pnetwork->network), target,  get_WLAN_BSSID_EX_sz(target));
460 			pnetwork->bcn_keys_valid = 0;
461 			if (target->Reserved[0] == BSS_TYPE_BCN || target->Reserved[0] == BSS_TYPE_PROB_RSP)
462 				rtw_update_bcn_keys_of_network(pnetwork);
463 			/* variable initialize */
464 			pnetwork->fixed = _FALSE;
465 			pnetwork->last_scanned = rtw_get_current_time();
466 			pnetwork->last_non_hidden_ssid_ap = pnetwork->last_scanned;
467 			#if defined(CONFIG_RTW_MESH) && CONFIG_RTW_MESH_ACNODE_PREVENT
468 			pnetwork->acnode_stime = 0;
469 			pnetwork->acnode_notify_etime = 0;
470 			#endif
471 
472 			pnetwork->network_type = 0;
473 			pnetwork->aid = 0;
474 			pnetwork->join_res = 0;
475 
476 			/* bss info not receving from the right channel */
477 			if (pnetwork->network.PhyInfo.SignalQuality == 101)
478 				pnetwork->network.PhyInfo.SignalQuality = 0;
479 		} else {
480 			/* Otherwise just pull from the free list */
481 
482 			pnetwork = alloc_network(pmlmepriv); /* will update scan_time */
483 			if (pnetwork == NULL)
484 				goto unlock_scan_queue;
485 
486 			bssid_ex_sz = get_WLAN_BSSID_EX_sz(target);
487 			target->Length = bssid_ex_sz;
488 
489 			_rtw_memcpy(&(pnetwork->network), target, bssid_ex_sz);
490 			pnetwork->bcn_keys_valid = 0;
491 			if (target->Reserved[0] == BSS_TYPE_BCN || target->Reserved[0] == BSS_TYPE_PROB_RSP)
492 				rtw_update_bcn_keys_of_network(pnetwork);
493 
494 			/* bss info not receving from the right channel */
495 			if (pnetwork->network.PhyInfo.SignalQuality == 101)
496 				pnetwork->network.PhyInfo.SignalQuality = 0;
497 
498 			rtw_list_insert_tail(&(pnetwork->list), &(queue->queue));
499 
500 		}
501 	} else {
502 		/* we have an entry and we are going to update it. But this entry may
503 		 * be already expired. In this case we do the same as we found a new
504 		 * net and call the new_net handler
505 		 */
506 		#if defined(CONFIG_RTW_MESH) && CONFIG_RTW_MESH_ACNODE_PREVENT
507 		systime last_scanned = pnetwork->last_scanned;
508 		#endif
509 		struct beacon_keys bcn_keys;
510 		bool bcn_keys_valid = 0;
511 		bool is_hidden_ssid_ap = 0;
512 
513 		pnetwork->last_scanned = rtw_get_current_time();
514 
515 		if (target->Reserved[0] == BSS_TYPE_BCN || target->Reserved[0] == BSS_TYPE_PROB_RSP) {
516 			if (target->InfrastructureMode == Ndis802_11Infrastructure) {
517 				is_hidden_ssid_ap = hidden_ssid_ap(target);
518 				if (!is_hidden_ssid_ap) /* update last time it's non hidden ssid AP */
519 					pnetwork->last_non_hidden_ssid_ap = rtw_get_current_time();
520 			}
521 			bcn_keys_valid = rtw_get_bcn_keys_from_bss(target, &bcn_keys);
522 		}
523 
524 		if (target->InfrastructureMode == Ndis802_11_mesh
525 			|| target->Reserved[0] >= pnetwork->network.Reserved[0])
526 			update_ie = _TRUE;
527 		else if (target->InfrastructureMode == Ndis802_11Infrastructure && !pnetwork->fixed
528 			&& rtw_get_passing_time_ms(pnetwork->last_non_hidden_ssid_ap) > SCANQUEUE_LIFETIME)
529 			update_ie = _TRUE;
530 		else if (bcn_keys_valid) {
531 			if (is_hidden_ssid(bcn_keys.ssid, bcn_keys.ssid_len)) {
532 				/* hidden ssid, replace with current beacon ssid directly */
533 				_rtw_memcpy(bcn_keys.ssid, pnetwork->bcn_keys.ssid, pnetwork->bcn_keys.ssid_len);
534 				bcn_keys.ssid_len = pnetwork->bcn_keys.ssid_len;
535 			}
536 			if (rtw_bcn_key_compare(&pnetwork->bcn_keys, &bcn_keys) == _FALSE)
537 				update_ie = _TRUE;
538 		}
539 
540 		#if defined(CONFIG_RTW_MESH) && CONFIG_RTW_MESH_ACNODE_PREVENT
541 		if (!MLME_IS_MESH(adapter) || !MLME_IS_ASOC(adapter)
542 			|| pnetwork->network.Configuration.DSConfig != target->Configuration.DSConfig
543 			|| rtw_get_passing_time_ms(last_scanned) > adapter->mesh_cfg.peer_sel_policy.scanr_exp_ms
544 			|| !rtw_bss_is_same_mbss(&pnetwork->network, target)
545 		) {
546 			pnetwork->acnode_stime = 0;
547 			pnetwork->acnode_notify_etime = 0;
548 		}
549 		#endif
550 
551 		if (bcn_keys_valid) {
552 			_rtw_memcpy(&pnetwork->bcn_keys, &bcn_keys, sizeof(bcn_keys));
553 			pnetwork->bcn_keys_valid = 1;
554 		} else if (update_ie)
555 			pnetwork->bcn_keys_valid = 0;
556 
557 		rtw_update_network(&(pnetwork->network), target, adapter, update_ie);
558 	}
559 
560 	#if defined(CONFIG_RTW_MESH) && CONFIG_RTW_MESH_ACNODE_PREVENT
561 	if (MLME_IS_MESH(adapter) && MLME_IS_ASOC(adapter))
562 		rtw_mesh_update_scanned_acnode_status(adapter, pnetwork);
563 	#endif
564 
565 unlock_scan_queue:
566 	_rtw_spinunlock_bh(&queue->lock);
567 
568 #ifdef CONFIG_RTW_MESH
569 	if (pnetwork && MLME_IS_MESH(adapter)
570 		&& check_fwstate(pmlmepriv, WIFI_ASOC_STATE)
571 		&& !check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY)
572 	)
573 		rtw_chk_candidate_peer_notify(adapter, pnetwork);
574 #endif
575 
576 	return update_ie;
577 }
578 
add_network(_adapter * adapter,WLAN_BSSID_EX * pnetwork)579 static void add_network(_adapter *adapter, WLAN_BSSID_EX *pnetwork)
580 {
581 	bool update_ie;
582 	/* _queue *queue = &(pmlmepriv->scanned_queue); */
583 	/* _rtw_spinlock_bh(&queue->lock); */
584 
585 #if defined(CONFIG_P2P) && defined(CONFIG_P2P_REMOVE_GROUP_INFO)
586 	if (adapter->registrypriv.wifi_spec == 0)
587 		rtw_bss_ex_del_p2p_attr(pnetwork, P2P_ATTR_GROUP_INFO);
588 #endif
589 
590 #ifdef CONFIG_IGNORE_GO_AND_LOW_RSSI_IN_SCAN_LIST
591 	if (adapter->registrypriv.ignore_go_in_scan) {
592 		if(rtw_chk_p2p_wildcard_ssid(pnetwork) == _SUCCESS ||
593 			rtw_chk_p2p_ie(pnetwork) == _SUCCESS)
594 			return;
595 	}
596 	/*100 was follow n & ac IC setting SignalStrength rang was 0~100*/
597 	if(adapter->registrypriv->ignore_low_rssi_in_scan != 0xff &&
598 		pnetwork->PhyInfo.rssi < (adapter->registrypriv->ignore_low_rssi_in_scan - 100))
599 		return;
600 #endif /*CONFIG_IGNORE_GO_AND_LOW_RSSI_IN_SCAN_LIST*/
601 
602 	if (!rtw_hw_chk_wl_func(adapter_to_dvobj(adapter), WL_FUNC_MIRACAST))
603 		rtw_bss_ex_del_wfd_ie(pnetwork);
604 
605 	/* Wi-Fi driver will update the current network if the scan result of the connected AP be updated by scan. */
606 	update_ie = update_scanned_network(adapter, pnetwork);
607 
608 	if (update_ie)
609 		update_current_network(adapter, pnetwork);
610 
611 	/* _rtw_spinunlock_bh(&queue->lock); */
612 
613 }
614 
615 #ifdef CONFIG_STA_MULTIPLE_BSSID
rtw_gen_new_bssid(const u8 * bssid,u8 max_bssid_ind,u8 mbssid_index,u8 * new_bssid)616 static inline void rtw_gen_new_bssid(const u8 *bssid, u8 max_bssid_ind,
617 					  u8 mbssid_index, u8 *new_bssid)
618 {
619 	u8 i = 0;
620 	u8 max_num = 1;
621 	u8 B;
622 	u8 new_a5;
623 
624 	for (i = 0; i < max_bssid_ind; i++)
625 		max_num = max_num * 2;
626 	/*RTW_INFO("%s, max_num=%d\n", __func__, max_num);*/
627 	/*RTW_INFO("%s, %02x,%02x,%02x,%02x,%02x,%02x \n", __func__, bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);*/
628 
629 	B = bssid[5] % max_num;
630 
631 	new_a5 = bssid[5] - B + ((B + mbssid_index) % max_num);
632 
633 	new_bssid[0] = bssid[0];
634 	new_bssid[1] = bssid[1];
635 	new_bssid[2] = bssid[2];
636 	new_bssid[3] = bssid[3];
637 	new_bssid[4] = bssid[4];
638 	new_bssid[5] = new_a5;
639 
640 	/*RTW_INFO("%s, %02x,%02x,%02x,%02x,%02x,%02x \n", __func__, new_bssid[0], new_bssid[1], new_bssid[2], new_bssid[3], new_bssid[4], new_bssid[5]);*/
641 }
642 
add_mbssid_network(_adapter * padapter,WLAN_BSSID_EX * ref_bss)643 void add_mbssid_network(_adapter *padapter, WLAN_BSSID_EX *ref_bss)
644 {
645 	WLAN_BSSID_EX *pbss;
646 	u32 sub_ies_len;
647 	u8 *mbssid_ie_ptr = NULL;
648 	PNDIS_802_11_VARIABLE_IEs pIE, sub_pie;
649 	u8 max_bssid_indicator;
650 	int i,j;
651 	u8* mbssid_ie;
652 	sint mbssid_len;
653 	u8 mbssid_index;
654 	u8 copy_ie_offset;
655 	u32 copy_ie_len = 0;
656 
657 	mbssid_ie = rtw_get_ie(ref_bss->IEs + _BEACON_IE_OFFSET_
658 		                              , WLAN_EID_MULTIPLE_BSSID
659 		                              , &mbssid_len
660 		                              , (ref_bss->IELength- _BEACON_IE_OFFSET_));
661 	if (!mbssid_ie)
662 		return;
663 #if 0
664 	else
665 		RTW_PRINT_DUMP("mbssid_ie: ", (const u8 *)mbssid_ie, mbssid_len);
666 #endif
667 
668 	mbssid_ie_ptr = mbssid_ie;
669 	max_bssid_indicator = GET_MBSSID_MAX_BSSID_INDOCATOR(mbssid_ie_ptr);
670 	/*RTW_INFO("%s, max_bssid_indicator=%d\n", __func__, max_bssid_indicator);*/
671 	mbssid_ie_ptr = mbssid_ie_ptr + MBSSID_MAX_BSSID_INDICATOR_OFFSET;
672 
673 	for (i = 0; i + 1 < mbssid_len;) {
674 		pIE = (PNDIS_802_11_VARIABLE_IEs)(mbssid_ie_ptr + i);
675 
676 		switch (pIE->ElementID) {
677 		case MBSSID_NONTRANSMITTED_BSSID_PROFILE_ID:
678 			sub_ies_len = pIE->Length;
679 			pbss = (WLAN_BSSID_EX *)rtw_zmalloc(sizeof(WLAN_BSSID_EX));
680 			if (pbss) {
681 				_rtw_memcpy(pbss, ref_bss, sizeof(WLAN_BSSID_EX));
682 				_rtw_memset(pbss->IEs, 0, MAX_IE_SZ);
683 				copy_ie_len =  _TIMESTAMP_ + _BEACON_ITERVAL_;
684 				_rtw_memcpy(pbss->IEs, ref_bss->IEs, copy_ie_len);
685 			} else {
686 				return;
687 			}
688 
689 			for (j = 0; j + 1 < sub_ies_len;) {
690 				sub_pie = (PNDIS_802_11_VARIABLE_IEs)(pIE->data + j);
691 				switch (sub_pie->ElementID) {
692 				case WLAN_EID_NON_TX_BSSID_CAP:
693 					/*RTW_INFO("%s, sub_pie->Length=%d\n", __func__, sub_pie->Length);*/
694 					/*RTW_PRINT_DUMP("WLAN_EID_NON_TX_BSSID_CAP: ", (const u8 *)sub_pie->data, sub_pie->Length);*/
695 					copy_ie_offset =  _TIMESTAMP_ + _BEACON_ITERVAL_;
696 					_rtw_memcpy(pbss->IEs + copy_ie_offset, sub_pie->data, sub_pie->Length);
697 					break;
698 				case WLAN_EID_SSID:
699 					/*RTW_PRINT_DUMP("WLAN_EID_SSID: ", (const u8 *)sub_pie->data, sub_pie->Length);*/
700 					/*RTW_INFO("%s, ref_bss->IELength=%d\n", __func__, ref_bss->IELength);*/
701 					/*RTW_PRINT_DUMP("A ref_bss->IEs: ", (const u8 *)ref_bss->IEs, ref_bss->IELength);*/
702 					copy_ie_offset =  _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_;
703 					copy_ie_len =  WLAN_IE_ID_LEN + WLAN_IE_LEN_LEN;
704 					_rtw_memcpy(pbss->IEs + copy_ie_offset, sub_pie, copy_ie_len);
705 
706 					copy_ie_offset = copy_ie_offset + WLAN_IE_ID_LEN + WLAN_IE_LEN_LEN;
707 					_rtw_memcpy(pbss->IEs + copy_ie_offset, sub_pie->data, sub_pie->Length);
708 					_rtw_memcpy(pbss->IEs + copy_ie_offset + sub_pie->Length
709 						                , ref_bss->IEs + copy_ie_offset + ref_bss->Ssid.SsidLength
710 						                , ref_bss->IELength - (copy_ie_offset + ref_bss->Ssid.SsidLength));
711 
712 					pbss->IELength = ref_bss->IELength + (sub_pie->Length - ref_bss->Ssid.SsidLength);
713 					/*RTW_INFO("%s, ref_bss->Ssid.SsidLength=%d\n", __func__, ref_bss->Ssid.SsidLength);*/
714 					/*RTW_INFO("%s, sub_pie->Length=%d\n", __func__, sub_pie->Length);*/
715 					/*RTW_INFO("%s, pbss->IELength=%d\n", __func__, pbss->IELength);*/
716 					/*RTW_PRINT_DUMP("B pbss->IEs: ", (const u8 *)pbss->IEs, pbss->IELength);*/
717 
718 					_rtw_memset(pbss->Ssid.Ssid, 0, pbss->Ssid.SsidLength);
719 					_rtw_memcpy(pbss->Ssid.Ssid, sub_pie->data, sub_pie->Length);
720 					pbss->Ssid.SsidLength = sub_pie->Length;
721 					break;
722 				case WLAN_EID_MULTI_BSSID_IDX:
723 					/*RTW_INFO("%s, sub_pie->Length=%d\n", __func__, sub_pie->Length);*/
724 					/*RTW_PRINT_DUMP("WLAN_EID_MULTI_BSSID_IDX: ", (const u8 *)sub_pie->data, sub_pie->Length);*/
725 					_rtw_memcpy(&mbssid_index, sub_pie->data, sub_pie->Length);
726 					/*RTW_INFO("%s,mbssid_index=%d\n", __func__, mbssid_index);*/
727 					rtw_gen_new_bssid(ref_bss->MacAddress, max_bssid_indicator
728 						                          , mbssid_index, pbss->MacAddress);
729 					pbss->mbssid_index = mbssid_index;
730 					break;
731 				default:
732 					break;
733 				}
734 
735 				j += (sub_pie->Length + WLAN_IE_ID_LEN + WLAN_IE_LEN_LEN);
736 				/*RTW_INFO("%s, j=%d\n", __func__, j);*/
737 			}
738 			pbss->is_mbssid = _TRUE;
739 			add_network(padapter, pbss);
740 			rtw_mfree((u8 *)pbss, sizeof(WLAN_BSSID_EX));
741 			break;
742 		case MBSSID_VENDOR_SPECIFIC_ID:
743 			break;
744 		default:
745 			break;
746 		}
747 
748 		i += (pIE->Length + WLAN_IE_ID_LEN + WLAN_IE_LEN_LEN);
749 		/*RTW_INFO("%s, i=%d\n", __func__, i);*/
750 	}
751 }
752 #endif
753 
rtw_survey_event_callback(_adapter * adapter,u8 * pbuf)754 void rtw_survey_event_callback(_adapter	*adapter, u8 *pbuf)
755 {
756 	u32 len;
757 	u8 val8;
758 	WLAN_BSSID_EX *pnetwork;
759 	struct	mlme_priv	*pmlmepriv = &(adapter->mlmepriv);
760 
761 	pnetwork = (WLAN_BSSID_EX *)pbuf;
762 
763 	len = get_WLAN_BSSID_EX_sz(pnetwork);
764 	if (len > (sizeof(WLAN_BSSID_EX))) {
765 		return;
766 	}
767 
768 #ifdef CONFIG_RTW_80211K
769     	val8 = 0;
770 	rtw_hal_get_hwreg(adapter, HW_VAR_FREECNT, &val8);
771 
772 	/* use TSF if no free run counter */
773 	if (val8==0)
774 		pnetwork->PhyInfo.free_cnt = (u32)rtw_hal_get_tsftr_by_port(
775 			adapter, rtw_hal_get_port(adapter));
776 #endif
777 
778 	if (pnetwork->InfrastructureMode == Ndis802_11Infrastructure) {
779 		if (MLME_IS_SCAN(adapter)) {
780 			adapter->mlmeextpriv.sitesurvey_res.activate_ch_cnt
781 				+= rtw_process_beacon_hint(adapter, pnetwork);
782 		}
783 	}
784 
785 	_rtw_spinlock_bh(&pmlmepriv->lock);
786 
787 	/* update IBSS_network 's timestamp */
788 	if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) == _TRUE) {
789 		if (_rtw_memcmp(&(pmlmepriv->cur_network.network.MacAddress), pnetwork->MacAddress, ETH_ALEN)) {
790 			struct wlan_network *ibss_wlan = NULL;
791 
792 			_rtw_memcpy(pmlmepriv->cur_network.network.IEs, pnetwork->IEs, 8);
793 			_rtw_spinlock_bh(&(pmlmepriv->scanned_queue.lock));
794 			ibss_wlan = _rtw_find_network(&pmlmepriv->scanned_queue,  pnetwork->MacAddress);
795 			if (ibss_wlan) {
796 				_rtw_memcpy(ibss_wlan->network.IEs , pnetwork->IEs, 8);
797 				_rtw_spinunlock_bh(&(pmlmepriv->scanned_queue.lock));
798 				goto exit;
799 			}
800 			_rtw_spinunlock_bh(&(pmlmepriv->scanned_queue.lock));
801 		}
802 	}
803 
804 	/* lock pmlmepriv->lock when you accessing network_q */
805 	if ((check_fwstate(pmlmepriv, WIFI_UNDER_LINKING)) == _FALSE) {
806 		if (pnetwork->Ssid.Ssid[0] == 0)
807 			pnetwork->Ssid.SsidLength = 0;
808 		add_network(adapter, pnetwork);
809 #ifdef CONFIG_STA_MULTIPLE_BSSID
810 		add_mbssid_network(adapter, pnetwork);
811 #endif
812 	}
813 
814 exit:
815 	_rtw_spinunlock_bh(&pmlmepriv->lock);
816 
817 
818 	return;
819 }
820 
rtw_surveydone_event_callback(_adapter * adapter,u8 * pbuf)821 void rtw_surveydone_event_callback(_adapter *adapter, u8 *pbuf)
822 {
823 	struct surveydone_event *parm = (struct surveydone_event *)pbuf;
824 	struct	mlme_priv	*pmlmepriv = &adapter->mlmepriv;
825 	struct mlme_ext_priv	*pmlmeext = &adapter->mlmeextpriv;
826 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
827 
828 	_rtw_spinlock_bh(&pmlmepriv->lock);
829 	if (pmlmepriv->wps_probe_req_ie) {
830 		u32 free_len = pmlmepriv->wps_probe_req_ie_len;
831 		pmlmepriv->wps_probe_req_ie_len = 0;
832 		rtw_mfree(pmlmepriv->wps_probe_req_ie, free_len);
833 		pmlmepriv->wps_probe_req_ie = NULL;
834 	}
835 
836 	if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY) == _FALSE) {
837 		RTW_INFO(FUNC_ADPT_FMT" fw_state:0x%x\n", FUNC_ADPT_ARG(adapter), get_fwstate(pmlmepriv));
838 		/* rtw_warn_on(1); */
839 	}
840 
841 	_clr_fwstate_(pmlmepriv, WIFI_UNDER_SURVEY);
842 	_rtw_spinunlock_bh(&pmlmepriv->lock);
843 
844 	_cancel_timer_ex(&pmlmepriv->scan_to_timer);
845 
846 	_rtw_spinlock_bh(&pmlmepriv->lock);
847 	#ifdef CONFIG_SIGNAL_STAT_PROCESS
848 	rtw_set_signal_stat_timer(&adapter->recvinfo);
849 	#endif
850 	if (pmlmepriv->to_join == _TRUE) {
851 		if ((check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == _TRUE)) {
852 			if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _FALSE) {
853 				set_fwstate(pmlmepriv, WIFI_UNDER_LINKING);
854 
855 				if (rtw_select_and_join_from_scanned_queue(pmlmepriv) == _SUCCESS) {
856 					/*_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);*/
857 					set_assoc_timer(pmlmepriv, MAX_JOIN_TIMEOUT);
858 				}
859 				else {
860 					WLAN_BSSID_EX    *pdev_network = &(adapter->registrypriv.dev_network);
861 					u8 *pibss = adapter->registrypriv.dev_network.MacAddress;
862 
863 					/* pmlmepriv->fw_state ^= WIFI_UNDER_SURVEY; */ /* because don't set assoc_timer */
864 					_clr_fwstate_(pmlmepriv, WIFI_UNDER_SURVEY);
865 
866 
867 					_rtw_memset(&pdev_network->Ssid, 0, sizeof(NDIS_802_11_SSID));
868 					_rtw_memcpy(&pdev_network->Ssid, &pmlmepriv->assoc_ssid, sizeof(NDIS_802_11_SSID));
869 
870 					rtw_update_registrypriv_dev_network(adapter);
871 					rtw_generate_random_ibss(pibss);
872 
873 					/*pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;*/
874 					init_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
875 
876 					if (rtw_create_ibss_cmd(adapter, 0) != _SUCCESS)
877 						RTW_ERR("rtw_create_ibss_cmd FAIL\n");
878 
879 					pmlmepriv->to_join = _FALSE;
880 				}
881 			}
882 		} else {
883 			int s_ret;
884 			set_fwstate(pmlmepriv, WIFI_UNDER_LINKING);
885 			pmlmepriv->to_join = _FALSE;
886 			s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
887 			if (_SUCCESS == s_ret) {
888 				/*_set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);*/
889 				set_assoc_timer(pmlmepriv, MAX_JOIN_TIMEOUT);
890 			} else if (s_ret == 2) { /* there is no need to wait for join */
891 				_clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
892 				rtw_indicate_connect(adapter);
893 			} else {
894 				RTW_INFO("try_to_join, but select scanning queue fail, to_roam:%d\n", rtw_to_roam(adapter));
895 
896 				if (rtw_to_roam(adapter) != 0) {
897 					struct sitesurvey_parm scan_parm;
898 					u8 ssc_chk = rtw_sitesurvey_condition_check(adapter, _FALSE);
899 
900 					rtw_init_sitesurvey_parm(adapter, &scan_parm);
901 					_rtw_memcpy(&scan_parm.ssid[0], &pmlmepriv->assoc_ssid, sizeof(NDIS_802_11_SSID));
902 					scan_parm.ssid_num = 1;
903 
904 					if (rtw_dec_to_roam(adapter) == 0
905 						|| (ssc_chk != SS_ALLOW && ssc_chk != SS_DENY_BUSY_TRAFFIC)
906 						|| _SUCCESS != rtw_sitesurvey_cmd(adapter, &scan_parm)
907 					   ) {
908 						rtw_set_to_roam(adapter, 0);
909 						if (MLME_IS_ASOC(adapter) == _TRUE)
910 							rtw_free_assoc_resources(adapter, _TRUE);
911 						rtw_indicate_disconnect(adapter, 0, _FALSE);
912 					} else
913 						pmlmepriv->to_join = _TRUE;
914 				} else
915 					rtw_indicate_disconnect(adapter, 0, _FALSE);
916 				_clr_fwstate_(pmlmepriv, WIFI_UNDER_LINKING);
917 			}
918 		}
919 	} else {
920 		if (rtw_chk_roam_flags(adapter, RTW_ROAM_ACTIVE)
921                 #if (defined(CONFIG_RTW_WNM) && defined(CONFIG_RTW_80211R))
922                         || rtw_wnm_btm_roam_triggered(adapter)
923                 #endif
924 		) {
925 			if (MLME_IS_STA(adapter)
926 			    && check_fwstate(pmlmepriv, WIFI_ASOC_STATE)) {
927 				if (rtw_select_roaming_candidate(pmlmepriv) == _SUCCESS) {
928 #ifdef CONFIG_RTW_80211R
929 					rtw_ft_start_roam(adapter,
930 						(u8 *)pmlmepriv->roam_network->network.MacAddress);
931 #else
932 					receive_disconnect(adapter, pmlmepriv->cur_network.network.MacAddress
933 						, WLAN_REASON_ACTIVE_ROAM, _FALSE);
934 					pmlmeinfo->disconnect_occurred_time = rtw_systime_to_ms(rtw_get_current_time());
935 					pmlmeinfo->disconnect_code = DISCONNECTION_BY_DRIVER_DUE_TO_ROAMING;
936 					pmlmeinfo->wifi_reason_code = WLAN_REASON_UNSPECIFIED;
937 #endif
938 				}
939 			}
940 		}
941 	}
942 
943 	RTW_INFO("scan complete in %dms\n",rtw_get_passing_time_ms(pmlmepriv->scan_start_time));
944 
945 	_rtw_spinunlock_bh(&pmlmepriv->lock);
946 
947 #ifdef CONFIG_P2P_PS
948 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
949 		p2p_ps_wk_cmd(adapter, P2P_PS_SCAN_DONE, 0);
950 #endif /* CONFIG_P2P_PS */
951 
952 	rtw_mi_os_xmit_schedule(adapter);
953 #ifdef CONFIG_DRVEXT_MODULE_WSC
954 	drvext_surveydone_callback(&adapter->drvextpriv);
955 #endif
956 
957 #ifdef DBG_CONFIG_ERROR_DETECT
958 	{
959 		struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
960 		if (pmlmeext->sitesurvey_res.bss_cnt == 0) {
961 			/* rtw_hal_sreset_reset(adapter); */
962 		}
963 	}
964 #endif
965 
966 #ifdef CONFIG_IOCTL_CFG80211
967 	rtw_cfg80211_surveydone_event_callback(adapter);
968 #endif /* CONFIG_IOCTL_CFG80211 */
969 
970 	rtw_indicate_scan_done(adapter, pmlmeext->scan_abort);
971 
972 #if defined(CONFIG_CONCURRENT_MODE) && defined(CONFIG_IOCTL_CFG80211)
973 	rtw_cfg80211_indicate_scan_done_for_buddy(adapter, _FALSE);
974 #endif
975 
976 	if (parm->activate_ch_cnt) {
977 		#ifdef CONFIG_IOCTL_CFG80211
978 		struct get_chplan_resp *chplan;
979 
980 		if (rtw_get_chplan_cmd(adapter, RTW_CMDF_DIRECTLY, &chplan) != _SUCCESS
981 			|| rtw_regd_change_complete_async(adapter_to_wiphy(adapter), chplan) != _SUCCESS)
982 			rtw_warn_on(1);
983 		#endif
984 
985 		op_class_pref_apply_regulatory(adapter, REG_BEACON_HINT);
986 		rtw_nlrtw_reg_beacon_hint_event(adapter);
987 	}
988 
989 #ifdef CONFIG_RTW_MESH
990 	#if CONFIG_RTW_MESH_OFFCH_CAND
991 	if (rtw_mesh_offch_candidate_accepted(adapter)) {
992 		u8 ch;
993 
994 		ch = rtw_mesh_select_operating_ch(adapter);
995 		if (ch && pmlmepriv->cur_network.network.Configuration.DSConfig != ch) {
996 			u8 ifbmp = rtw_mi_get_ap_mesh_ifbmp(adapter);
997 
998 			if (ifbmp) {
999 				/* switch to selected channel */
1000 				rtw_change_bss_chbw_cmd(adapter, RTW_CMDF_DIRECTLY, ifbmp, 0, ch, REQ_BW_ORI, REQ_OFFSET_NONE);
1001 				issue_probereq_ex(adapter, &pmlmepriv->cur_network.network.mesh_id, NULL, 0, 0, 0, 0);
1002 			} else
1003 				rtw_warn_on(1);
1004 		}
1005 	}
1006 	#endif
1007 #endif /* CONFIG_RTW_MESH */
1008 
1009 #ifdef CONFIG_RTW_ACS
1010 	if (parm->acs) {
1011 		u8 ifbmp = rtw_mi_get_ap_mesh_ifbmp(adapter);
1012 
1013 		if (ifbmp)
1014 			rtw_change_bss_chbw_cmd(adapter, RTW_CMDF_DIRECTLY, ifbmp, 0, REQ_CH_INT_INFO, REQ_BW_ORI, REQ_OFFSET_NONE);
1015 	}
1016 #endif
1017 }
1018 
_rtw_sitesurvey_condition_check(const char * caller,_adapter * adapter,bool check_sc_interval)1019 u8 _rtw_sitesurvey_condition_check(const char *caller, _adapter *adapter, bool check_sc_interval)
1020 {
1021 	u8 ss_condition = SS_ALLOW;
1022 	struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1023 	struct registry_priv *registry_par = &adapter->registrypriv;
1024 
1025 
1026 #ifdef CONFIG_MP_INCLUDED
1027 	if (rtw_mp_mode_check(adapter)) {
1028 		RTW_INFO("%s ("ADPT_FMT") MP mode block Scan request\n", caller, ADPT_ARG(adapter));
1029 		ss_condition = SS_DENY_MP_MODE;
1030 		goto _exit;
1031 	}
1032 #endif
1033 
1034 #ifdef DBG_LA_MODE
1035 	if(registry_par->la_mode_en == 1 && MLME_IS_ASOC(adapter)) {
1036 		RTW_INFO("%s ("ADPT_FMT") LA debug mode block Scan request\n", caller, ADPT_ARG(adapter));
1037 		ss_condition = SS_DENY_LA_MODE;
1038 		goto _exit;
1039 	}
1040 #endif
1041 
1042 #ifdef CONFIG_IOCTL_CFG80211
1043 	if (adapter_wdev_data(adapter)->block_scan == _TRUE) {
1044 		RTW_INFO("%s ("ADPT_FMT") wdev_priv.block_scan is set\n", caller, ADPT_ARG(adapter));
1045 		ss_condition = SS_DENY_BLOCK_SCAN;
1046 		goto _exit;
1047 	}
1048 #endif
1049 
1050 	if (adapter_to_dvobj(adapter)->scan_deny == _TRUE) {
1051 		RTW_INFO("%s ("ADPT_FMT") tpt mode, scan deny!\n", caller, ADPT_ARG(adapter));
1052 		ss_condition = SS_DENY_BLOCK_SCAN;
1053 		goto _exit;
1054 	}
1055 
1056 	if (rtw_is_scan_deny(adapter)) {
1057 		RTW_INFO("%s ("ADPT_FMT") : scan deny\n", caller, ADPT_ARG(adapter));
1058 		ss_condition = SS_DENY_BY_DRV;
1059 		goto _exit;
1060 	}
1061 
1062 	#if 0 /*GEORGIA_TODO_FIXIT*/
1063 	if (adapter_to_rfctl(adapter)->adaptivity_en
1064 	    && rtw_hal_get_phy_edcca_flag(adapter)
1065 	    && rtw_is_2g_ch(GET_PHL_COM(adapter_to_dvobj(adapter))->current_channel)) {
1066 		RTW_WARN(FUNC_ADPT_FMT": Adaptivity block scan! (ch=%u)\n",
1067 			 FUNC_ADPT_ARG(adapter),
1068 			 GET_PHL_COM(adapter_to_dvobj(adapter))->current_channel);
1069 		ss_condition = SS_DENY_ADAPTIVITY;
1070 		goto _exit;
1071 	}
1072 	#endif
1073 	if (check_fwstate(pmlmepriv, WIFI_AP_STATE)){
1074 		if(check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
1075 			RTW_INFO("%s ("ADPT_FMT") : scan abort!! AP mode process WPS\n", caller, ADPT_ARG(adapter));
1076 			ss_condition = SS_DENY_SELF_AP_UNDER_WPS;
1077 			goto _exit;
1078 		} else if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING) == _TRUE) {
1079 			RTW_INFO("%s ("ADPT_FMT") : scan abort!!AP mode under linking (fwstate=0x%x)\n",
1080 				caller, ADPT_ARG(adapter), pmlmepriv->fw_state);
1081 			ss_condition = SS_DENY_SELF_AP_UNDER_LINKING;
1082 			goto _exit;
1083 		} else if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY) == _TRUE) {
1084 			RTW_INFO("%s ("ADPT_FMT") : scan abort!!AP mode under survey (fwstate=0x%x)\n",
1085 				caller, ADPT_ARG(adapter), pmlmepriv->fw_state);
1086 			ss_condition = SS_DENY_SELF_AP_UNDER_SURVEY;
1087 			goto _exit;
1088 		}
1089 	} else {
1090 		if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING) == _TRUE) {
1091 			RTW_INFO("%s ("ADPT_FMT") : scan abort!!STA mode under linking (fwstate=0x%x)\n",
1092 				caller, ADPT_ARG(adapter), pmlmepriv->fw_state);
1093 			ss_condition = SS_DENY_SELF_STA_UNDER_LINKING;
1094 			goto _exit;
1095 		} else if (check_fwstate(pmlmepriv, WIFI_UNDER_SURVEY) == _TRUE) {
1096 			RTW_INFO("%s ("ADPT_FMT") : scan abort!!STA mode under survey (fwstate=0x%x)\n",
1097 				caller, ADPT_ARG(adapter), pmlmepriv->fw_state);
1098 			ss_condition = SS_DENY_SELF_STA_UNDER_SURVEY;
1099 			goto _exit;
1100 		}
1101 	}
1102 
1103 #ifdef CONFIG_CONCURRENT_MODE
1104 	if (rtw_mi_buddy_check_fwstate(adapter, WIFI_UNDER_LINKING | WIFI_UNDER_WPS)) {
1105 		RTW_INFO("%s ("ADPT_FMT") : scan abort!! buddy_intf under linking or wps\n", caller, ADPT_ARG(adapter));
1106 		ss_condition = SS_DENY_BUDDY_UNDER_LINK_WPS;
1107 		goto _exit;
1108 
1109 	} else if (rtw_mi_buddy_check_fwstate(adapter, WIFI_UNDER_SURVEY)) {
1110 		RTW_INFO("%s ("ADPT_FMT") : scan abort!! buddy_intf under survey\n", caller, ADPT_ARG(adapter));
1111 		ss_condition = SS_DENY_BUDDY_UNDER_SURVEY;
1112 		goto _exit;
1113 	}
1114 #endif /* CONFIG_CONCURRENT_MODE */
1115 
1116 #ifdef RTW_BUSY_DENY_SCAN
1117 	/*
1118 	 * busy traffic check
1119 	 * Rules:
1120 	 * 1. If (scan interval <= BUSY_TRAFFIC_SCAN_DENY_PERIOD) always allow
1121 	 *    scan, otherwise goto rule 2.
1122 	 * 2. Deny scan if any interface is busy, otherwise allow scan.
1123 	 */
1124 	if (pmlmepriv->lastscantime
1125 	    && (rtw_get_passing_time_ms(pmlmepriv->lastscantime) >
1126 		registry_par->scan_interval_thr)
1127 	    && rtw_mi_busy_traffic_check(adapter)) {
1128 		RTW_WARN("%s ("ADPT_FMT") : scan abort!! BusyTraffic\n",
1129 			 caller, ADPT_ARG(adapter));
1130 		ss_condition = SS_DENY_BUSY_TRAFFIC;
1131 		goto _exit;
1132 	}
1133 #endif /* RTW_BUSY_DENY_SCAN */
1134 
1135 _exit:
1136 	return ss_condition;
1137 }
1138 
1139 
1140 /*rtw_mlme_ext.c*/
sitesurvey_set_offch_state(_adapter * adapter,u8 scan_state)1141 void sitesurvey_set_offch_state(_adapter *adapter, u8 scan_state)
1142 {
1143 	struct rf_ctl_t *rfctl = adapter_to_rfctl(adapter);
1144 
1145 	_rtw_mutex_lock_interruptible(&rfctl->offch_mutex);
1146 
1147 	switch (scan_state) {
1148 	case SCAN_DISABLE:
1149 	case SCAN_BACK_OP:
1150 		rfctl->offch_state = OFFCHS_NONE;
1151 		break;
1152 	case SCAN_START:
1153 	case SCAN_LEAVING_OP:
1154 		rfctl->offch_state = OFFCHS_LEAVING_OP;
1155 		break;
1156 	case SCAN_ENTER:
1157 	case SCAN_LEAVE_OP:
1158 		rfctl->offch_state = OFFCHS_LEAVE_OP;
1159 		break;
1160 	case SCAN_COMPLETE:
1161 	case SCAN_BACKING_OP:
1162 		rfctl->offch_state = OFFCHS_BACKING_OP;
1163 		break;
1164 	default:
1165 		break;
1166 	}
1167 
1168 	_rtw_mutex_unlock(&rfctl->offch_mutex);
1169 }
rtw_scan_sparse(_adapter * adapter,struct rtw_ieee80211_channel * ch,u8 ch_num)1170 static u8 rtw_scan_sparse(_adapter *adapter, struct rtw_ieee80211_channel *ch, u8 ch_num)
1171 {
1172 	/* interval larger than this is treated as backgroud scan */
1173 #ifndef RTW_SCAN_SPARSE_BG_INTERVAL_MS
1174 #define RTW_SCAN_SPARSE_BG_INTERVAL_MS 12000
1175 #endif
1176 
1177 #ifndef RTW_SCAN_SPARSE_CH_NUM_MIRACAST
1178 #define RTW_SCAN_SPARSE_CH_NUM_MIRACAST 1
1179 #endif
1180 #ifndef RTW_SCAN_SPARSE_CH_NUM_BG
1181 #define RTW_SCAN_SPARSE_CH_NUM_BG 4
1182 #endif
1183 
1184 #define SCAN_SPARSE_CH_NUM_INVALID 255
1185 
1186 	static u8 token = 255;
1187 	u32 interval;
1188 	bool busy_traffic = _FALSE;
1189 	bool miracast_enabled = _FALSE;
1190 	bool bg_scan = _FALSE;
1191 	u8 max_allow_ch = SCAN_SPARSE_CH_NUM_INVALID;
1192 	u8 scan_division_num;
1193 	u8 ret_num = ch_num;
1194 	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
1195 
1196 	if (mlmeext->last_scan_time == 0)
1197 		mlmeext->last_scan_time = rtw_get_current_time();
1198 
1199 	interval = rtw_get_passing_time_ms(mlmeext->last_scan_time);
1200 
1201 
1202 	if (rtw_mi_busy_traffic_check(adapter))
1203 		busy_traffic = _TRUE;
1204 
1205 	if (rtw_mi_check_miracast_enabled(adapter))
1206 		miracast_enabled = _TRUE;
1207 
1208 	if (interval > RTW_SCAN_SPARSE_BG_INTERVAL_MS)
1209 		bg_scan = _TRUE;
1210 
1211 	/* max_allow_ch by conditions*/
1212 
1213 #if RTW_SCAN_SPARSE_MIRACAST
1214 	if (miracast_enabled == _TRUE && busy_traffic == _TRUE)
1215 		max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_MIRACAST);
1216 #endif
1217 
1218 #if RTW_SCAN_SPARSE_BG
1219 	if (bg_scan == _TRUE)
1220 		max_allow_ch = rtw_min(max_allow_ch, RTW_SCAN_SPARSE_CH_NUM_BG);
1221 #endif
1222 
1223 
1224 	if (max_allow_ch != SCAN_SPARSE_CH_NUM_INVALID) {
1225 		int i;
1226 		int k = 0;
1227 
1228 		scan_division_num = (ch_num / max_allow_ch) + ((ch_num % max_allow_ch) ? 1 : 0);
1229 		token = (token + 1) % scan_division_num;
1230 
1231 		if (0)
1232 			RTW_INFO("scan_division_num:%u, token:%u\n", scan_division_num, token);
1233 
1234 		for (i = 0; i < ch_num; i++) {
1235 			if (ch[i].hw_value && (i % scan_division_num) == token
1236 			   ) {
1237 				if (i != k)
1238 					_rtw_memcpy(&ch[k], &ch[i], sizeof(struct rtw_ieee80211_channel));
1239 				k++;
1240 			}
1241 		}
1242 
1243 		_rtw_memset(&ch[k], 0, sizeof(struct rtw_ieee80211_channel));
1244 
1245 		ret_num = k;
1246 		mlmeext->last_scan_time = rtw_get_current_time();
1247 	}
1248 
1249 	return ret_num;
1250 }
1251 
rtw_scan_ch_decision(_adapter * padapter,struct rtw_ieee80211_channel * out,u32 out_num,struct rtw_ieee80211_channel * in,u32 in_num,bool no_sparse)1252 static int rtw_scan_ch_decision(_adapter *padapter, struct rtw_ieee80211_channel *out,
1253 		u32 out_num, struct rtw_ieee80211_channel *in, u32 in_num, bool no_sparse)
1254 {
1255 	int i, j;
1256 	int set_idx;
1257 	u8 chan;
1258 	struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
1259 	struct registry_priv *regsty = dvobj_to_regsty(adapter_to_dvobj(padapter));
1260 
1261 	/* clear first */
1262 	_rtw_memset(out, 0, sizeof(struct rtw_ieee80211_channel) * out_num);
1263 
1264 	/* acquire channels from in */
1265 	j = 0;
1266 	for (i = 0; i < in_num; i++) {
1267 
1268 		if (0)
1269 			RTW_INFO(FUNC_ADPT_FMT" "CHAN_FMT"\n", FUNC_ADPT_ARG(padapter), CHAN_ARG(&in[i]));
1270 
1271 		if (!in[i].hw_value || (in[i].flags & RTW_IEEE80211_CHAN_DISABLED))
1272 			continue;
1273 		if (rtw_mlme_band_check(padapter, in[i].hw_value) == _FALSE)
1274 			continue;
1275 
1276 		set_idx = rtw_chset_search_ch(rfctl->channel_set, in[i].hw_value);
1277 		if (set_idx >= 0) {
1278 			if (j >= out_num) {
1279 				RTW_PRINT(FUNC_ADPT_FMT" out_num:%u not enough\n",
1280 					  FUNC_ADPT_ARG(padapter), out_num);
1281 				break;
1282 			}
1283 
1284 			_rtw_memcpy(&out[j], &in[i], sizeof(struct rtw_ieee80211_channel));
1285 
1286 			if (rfctl->channel_set[set_idx].flags & (RTW_CHF_NO_IR | RTW_CHF_DFS))
1287 				out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
1288 
1289 			j++;
1290 		}
1291 		if (j >= out_num)
1292 			break;
1293 	}
1294 
1295 	/* if out is empty, use channel_set as default */
1296 	if (j == 0) {
1297 		for (i = 0; i < rfctl->max_chan_nums; i++) {
1298 			chan = rfctl->channel_set[i].ChannelNum;
1299 			if (rtw_mlme_band_check(padapter, chan) == _TRUE) {
1300 				if (rtw_mlme_ignore_chan(padapter, chan) == _TRUE)
1301 					continue;
1302 
1303 				if (0)
1304 					RTW_INFO(FUNC_ADPT_FMT" ch:%u\n", FUNC_ADPT_ARG(padapter), chan);
1305 
1306 				if (j >= out_num) {
1307 					RTW_PRINT(FUNC_ADPT_FMT" out_num:%u not enough\n",
1308 						FUNC_ADPT_ARG(padapter), out_num);
1309 					break;
1310 				}
1311 
1312 				out[j].hw_value = chan;
1313 
1314 				if (rfctl->channel_set[i].flags & (RTW_CHF_NO_IR | RTW_CHF_DFS))
1315 					out[j].flags |= RTW_IEEE80211_CHAN_PASSIVE_SCAN;
1316 
1317 				j++;
1318 			}
1319 		}
1320 	}
1321 
1322 	if (!no_sparse
1323 		&& !regsty->wifi_spec
1324 		&& j > 6 /* assume ch_num > 6 is normal scan */
1325 	) {
1326 		/* scan_sparse */
1327 		j = rtw_scan_sparse(padapter, out, j);
1328 	}
1329 
1330 	return j;
1331 }
1332 #ifdef CONFIG_SCAN_BACKOP
rtw_scan_backop_decision(_adapter * adapter)1333 u8 rtw_scan_backop_decision(_adapter *adapter)
1334 {
1335 	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
1336 	struct mi_state mstate;
1337 	u8 backop_flags = 0;
1338 
1339 	rtw_mi_status(adapter, &mstate);
1340 
1341 	if ((MSTATE_STA_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_sta(mlmeext, SS_BACKOP_EN))
1342 		|| (MSTATE_STA_NUM(&mstate) && mlmeext_chk_scan_backop_flags_sta(mlmeext, SS_BACKOP_EN_NL)))
1343 		backop_flags |= mlmeext_scan_backop_flags_sta(mlmeext);
1344 
1345 #ifdef CONFIG_AP_MODE
1346 	if ((MSTATE_AP_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_ap(mlmeext, SS_BACKOP_EN))
1347 		|| (MSTATE_AP_NUM(&mstate) && mlmeext_chk_scan_backop_flags_ap(mlmeext, SS_BACKOP_EN_NL)))
1348 		backop_flags |= mlmeext_scan_backop_flags_ap(mlmeext);
1349 #endif
1350 
1351 #ifdef CONFIG_RTW_MESH
1352 	if ((MSTATE_MESH_LD_NUM(&mstate) && mlmeext_chk_scan_backop_flags_mesh(mlmeext, SS_BACKOP_EN))
1353 		|| (MSTATE_MESH_NUM(&mstate) && mlmeext_chk_scan_backop_flags_mesh(mlmeext, SS_BACKOP_EN_NL)))
1354 		backop_flags |= mlmeext_scan_backop_flags_mesh(mlmeext);
1355 #endif
1356 
1357 	return backop_flags;
1358 }
1359 #endif
1360 
1361 #if 0 /*#ifndef CONFIG_PHL_ARCH*/
1362 void survey_timer_hdl(void *ctx)
1363 {
1364 	_adapter *padapter = (_adapter *)ctx;
1365 	struct cmd_obj *cmd;
1366 	struct sitesurvey_parm *psurveyPara;
1367 	struct cmd_priv *pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
1368 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1369 
1370 	if (mlmeext_scan_state(pmlmeext) > SCAN_DISABLE) {
1371 		cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
1372 		if (cmd == NULL) {
1373 			rtw_warn_on(1);
1374 			goto exit;
1375 		}
1376 		cmd->padapter = padapter;
1377 
1378 		psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
1379 		if (psurveyPara == NULL) {
1380 			rtw_warn_on(1);
1381 			rtw_mfree((unsigned char *)cmd, sizeof(struct cmd_obj));
1382 			goto exit;
1383 		}
1384 
1385 		init_h2fwcmd_w_parm_no_rsp(cmd, psurveyPara, CMD_SITE_SURVEY);
1386 		rtw_enqueue_cmd(pcmdpriv, cmd);
1387 	}
1388 
1389 exit:
1390 	return;
1391 }
1392 
1393 static const char *const _scan_state_str[] = {
1394 	"SCAN_DISABLE",
1395 	"SCAN_START",
1396 	"SCAN_PS_ANNC_WAIT",
1397 	"SCAN_ENTER",
1398 	"SCAN_PROCESS",
1399 	"SCAN_BACKING_OP",
1400 	"SCAN_BACK_OP",
1401 	"SCAN_LEAVING_OP",
1402 	"SCAN_LEAVE_OP",
1403 	"SCAN_SW_ANTDIV_BL",
1404 	"SCAN_TO_P2P_LISTEN",
1405 	"SCAN_P2P_LISTEN",
1406 	"SCAN_COMPLETE",
1407 	"SCAN_STATE_MAX",
1408 };
1409 
1410 void rtw_survey_cmd_callback(_adapter *padapter ,  struct cmd_obj *pcmd)
1411 {
1412 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
1413 
1414 
1415 	if (pcmd->res == H2C_DROPPED) {
1416 		/* TODO: cancel timer and do timeout handler directly... */
1417 		/* need to make timeout handlerOS independent */
1418 		mlme_set_scan_to_timer(pmlmepriv, 1);
1419 	} else if (pcmd->res != H2C_SUCCESS) {
1420 		mlme_set_scan_to_timer(pmlmepriv, 1);
1421 	}
1422 
1423 	/* free cmd */
1424 	rtw_free_cmd_obj(pcmd);
1425 
1426 }
1427 
1428 const char *scan_state_str(u8 state)
1429 {
1430 	state = (state >= SCAN_STATE_MAX) ? SCAN_STATE_MAX : state;
1431 	return _scan_state_str[state];
1432 }
1433 
1434 static bool scan_abort_hdl(_adapter *adapter)
1435 {
1436 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
1437 	struct ss_res *ss = &pmlmeext->sitesurvey_res;
1438 #ifdef CONFIG_P2P
1439 	struct wifidirect_info *pwdinfo = &adapter->wdinfo;
1440 #endif
1441 	bool ret = _FALSE;
1442 
1443 	if (pmlmeext->scan_abort == _TRUE) {
1444 #ifdef CONFIG_P2P
1445 		if (!rtw_p2p_chk_state(&adapter->wdinfo, P2P_STATE_NONE)) {
1446 			rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_MAX);
1447 			ss->channel_idx = 3;
1448 			RTW_INFO("%s idx:%d, cnt:%u\n", __FUNCTION__
1449 				 , ss->channel_idx
1450 				 , pwdinfo->find_phase_state_exchange_cnt
1451 				);
1452 		} else
1453 #endif
1454 		{
1455 			ss->channel_idx = ss->ch_num;
1456 			RTW_INFO("%s idx:%d\n", __FUNCTION__
1457 				 , ss->channel_idx
1458 				);
1459 		}
1460 		pmlmeext->scan_abort = _FALSE;
1461 		ret = _TRUE;
1462 	}
1463 
1464 	return ret;
1465 }
1466 
1467 static void sitesurvey_res_reset(_adapter *adapter, struct sitesurvey_parm *parm)
1468 {
1469 	struct ss_res *ss = &adapter->mlmeextpriv.sitesurvey_res;
1470 	RT_CHANNEL_INFO *chset = adapter_to_chset(adapter);
1471 	int i;
1472 
1473 	ss->bss_cnt = 0;
1474 	ss->activate_ch_cnt = 0;
1475 	ss->channel_idx = 0;
1476 	ss->force_ssid_scan = 0;
1477 	ss->igi_scan = 0;
1478 	ss->igi_before_scan = 0;
1479 #ifdef CONFIG_SCAN_BACKOP
1480 	ss->scan_cnt = 0;
1481 #endif
1482 #if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
1483 	ss->is_sw_antdiv_bl_scan = 0;
1484 #endif
1485 	ss->ssid_num = 0;
1486 	for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
1487 		if (parm->ssid[i].SsidLength) {
1488 			_rtw_memcpy(ss->ssid[i].Ssid, parm->ssid[i].Ssid, IW_ESSID_MAX_SIZE);
1489 			ss->ssid[i].SsidLength = parm->ssid[i].SsidLength;
1490 			ss->ssid_num++;
1491 		} else
1492 			ss->ssid[i].SsidLength = 0;
1493 	}
1494 
1495 	ss->ch_num = rtw_scan_ch_decision(adapter
1496 					, ss->ch, RTW_CHANNEL_SCAN_AMOUNT
1497 					, parm->ch, parm->ch_num
1498 					, parm->acs
1499 				);
1500 
1501 	for (i = 0; i < MAX_CHANNEL_NUM; i++)
1502 		chset[i].hidden_bss_cnt = 0;
1503 
1504 	ss->bw = parm->bw;
1505 	ss->igi = parm->igi;
1506 	ss->token = parm->token;
1507 	ss->duration = parm->duration;
1508 	ss->scan_mode = parm->scan_mode;
1509 	ss->token = parm->token;
1510 	ss->acs = parm->acs;
1511 }
1512 
1513 static u8 sitesurvey_pick_ch_behavior(_adapter *padapter, u8 *ch,
1514 					enum rtw_phl_scan_type *type)
1515 {
1516 	u8 next_state;
1517 	u8 scan_ch = 0;
1518 	enum rtw_phl_scan_type stype = RTW_PHL_SCAN_PASSIVE;
1519 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1520 	struct ss_res *ss = &pmlmeext->sitesurvey_res;
1521 	struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
1522 	int ch_set_idx;
1523 #ifdef CONFIG_P2P
1524 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1525 #endif
1526 #ifdef CONFIG_SCAN_BACKOP
1527 	u8 backop_flags = 0;
1528 #endif
1529 
1530 	/* handle scan abort request */
1531 	scan_abort_hdl(padapter);
1532 
1533 #ifdef CONFIG_P2P
1534 	if (pwdinfo->rx_invitereq_info.scan_op_ch_only || pwdinfo->p2p_info.scan_op_ch_only) {
1535 		if (pwdinfo->rx_invitereq_info.scan_op_ch_only)
1536 			scan_ch = pwdinfo->rx_invitereq_info.operation_ch[ss->channel_idx];
1537 		else
1538 			scan_ch = pwdinfo->p2p_info.operation_ch[ss->channel_idx];
1539 		stype = RTW_PHL_SCAN_ACTIVE;
1540 	} else if (rtw_p2p_findphase_ex_is_social(pwdinfo)) {
1541 		/*
1542 		* Commented by Albert 2011/06/03
1543 		* The driver is in the find phase, it should go through the social channel.
1544 		*/
1545 		scan_ch = pwdinfo->social_chan[ss->channel_idx];
1546 		ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, scan_ch);
1547 		if (ch_set_idx >= 0)
1548 			stype = rfctl->channel_set[ch_set_idx].flags & RTW_CHF_NO_IR ? RTW_PHL_SCAN_PASSIVE : RTW_PHL_SCAN_ACTIVE;
1549 		else
1550 			stype = RTW_PHL_SCAN_ACTIVE;
1551 	} else
1552 #endif /* CONFIG_P2P */
1553 	{
1554 		struct rtw_ieee80211_channel *ch;
1555 
1556 		#ifdef CONFIG_SCAN_BACKOP
1557 		backop_flags = rtw_scan_backop_decision(padapter);
1558 		#endif
1559 
1560 		#ifdef CONFIG_SCAN_BACKOP
1561 		if (!(backop_flags && ss->scan_cnt >= ss->scan_cnt_max))
1562 		#endif
1563 		{
1564 			#ifdef CONFIG_RTW_WIFI_HAL
1565 			if (adapter_to_dvobj(padapter)->nodfs) {
1566 				while (ss->channel_idx < ss->ch_num && rtw_chset_is_dfs_ch(rfctl->channel_set, ss->ch[ss->channel_idx].hw_value))
1567 					ss->channel_idx++;
1568 			} else
1569 			#endif
1570 			if (ss->channel_idx != 0 && ss->force_ssid_scan == 0
1571 				&& pmlmeext->sitesurvey_res.ssid_num
1572 				&& (ss->ch[ss->channel_idx - 1].flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN)
1573 			) {
1574 				ch_set_idx = rtw_chset_search_ch(rfctl->channel_set, ss->ch[ss->channel_idx - 1].hw_value);
1575 				if (ch_set_idx != -1 && rfctl->channel_set[ch_set_idx].hidden_bss_cnt
1576 					&& (!IS_DFS_SLAVE_WITH_RD(rfctl)
1577 						|| rtw_rfctl_dfs_domain_unknown(rfctl)
1578 						|| !CH_IS_NON_OCP(&rfctl->channel_set[ch_set_idx]))
1579 				) {
1580 					ss->channel_idx--;
1581 					ss->force_ssid_scan = 1;
1582 				}
1583 			} else
1584 				ss->force_ssid_scan = 0;
1585 		}
1586 
1587 		if (ss->channel_idx < ss->ch_num) {
1588 			ch = &ss->ch[ss->channel_idx];
1589 			scan_ch = ch->hw_value;
1590 
1591 			#if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)
1592 			if (IS_ACS_ENABLE(padapter) && rtw_is_acs_passiv_scan(padapter))
1593 				stype = RTW_PHL_SCAN_PASSIVE;
1594 			else
1595 			#endif /*CONFIG_RTW_ACS*/
1596 				stype = (ch->flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) ? RTW_PHL_SCAN_PASSIVE : RTW_PHL_SCAN_ACTIVE;
1597 		}
1598 	}
1599 
1600 	if (scan_ch != 0) {
1601 		next_state = SCAN_PROCESS;
1602 
1603 		#ifdef CONFIG_SCAN_BACKOP
1604 		if (backop_flags) {
1605 			if (ss->scan_cnt < ss->scan_cnt_max)
1606 				ss->scan_cnt++;
1607 			else {
1608 				mlmeext_assign_scan_backop_flags(pmlmeext, backop_flags);
1609 				next_state = SCAN_BACKING_OP;
1610 			}
1611 		}
1612 		#endif
1613 
1614 	} else if (rtw_p2p_findphase_ex_is_needed(pwdinfo)) {
1615 		/* go p2p listen */
1616 		next_state = SCAN_TO_P2P_LISTEN;
1617 
1618 #ifdef CONFIG_ANTENNA_DIVERSITY
1619 	} else if (rtw_hal_antdiv_before_linked(padapter)) {
1620 		/* go sw antdiv before link */
1621 		next_state = SCAN_SW_ANTDIV_BL;
1622 #endif
1623 	} else {
1624 		next_state = SCAN_COMPLETE;
1625 
1626 #if defined(DBG_SCAN_SW_ANTDIV_BL)
1627 		{
1628 			/* for SCAN_SW_ANTDIV_BL state testing */
1629 			struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1630 			int i;
1631 			bool is_linked = _FALSE;
1632 
1633 			for (i = 0; i < dvobj->iface_nums; i++) {
1634 				if (rtw_linked_check(dvobj->padapters[i]))
1635 					is_linked = _TRUE;
1636 			}
1637 
1638 			if (!is_linked) {
1639 				static bool fake_sw_antdiv_bl_state = 0;
1640 
1641 				if (fake_sw_antdiv_bl_state == 0) {
1642 					next_state = SCAN_SW_ANTDIV_BL;
1643 					fake_sw_antdiv_bl_state = 1;
1644 				} else
1645 					fake_sw_antdiv_bl_state = 0;
1646 			}
1647 		}
1648 #endif /* defined(DBG_SCAN_SW_ANTDIV_BL) */
1649 	}
1650 
1651 #ifdef CONFIG_SCAN_BACKOP
1652 	if (next_state != SCAN_PROCESS)
1653 		ss->scan_cnt = 0;
1654 #endif
1655 
1656 
1657 #ifdef DBG_FIXED_CHAN
1658 	if (pmlmeext->fixed_chan != 0xff && next_state == SCAN_PROCESS)
1659 		scan_ch = pmlmeext->fixed_chan;
1660 #endif
1661 
1662 	if (ch)
1663 		*ch = scan_ch;
1664 	if (type)
1665 		*type = stype;
1666 
1667 	return next_state;
1668 }
1669 
1670 void site_survey(_adapter *padapter, u8 survey_channel,
1671 	enum rtw_phl_scan_type ScanType)
1672 {
1673 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1674 	struct ss_res *ss = &pmlmeext->sitesurvey_res;
1675 	u8 ssid_scan = 0;
1676 
1677 #ifdef CONFIG_P2P
1678 #ifndef CONFIG_IOCTL_CFG80211
1679 	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
1680 #endif
1681 #endif
1682 
1683 	if (survey_channel != 0) {
1684 		set_channel_bwmode(padapter,
1685 				survey_channel,
1686 				CHAN_OFFSET_NO_EXT,
1687 				CHANNEL_WIDTH_20,
1688 				_FALSE);
1689 
1690 		if (ScanType == RTW_PHL_SCAN_PASSIVE && ss->force_ssid_scan)
1691 			ssid_scan = 1;
1692 		else if (ScanType == RTW_PHL_SCAN_ACTIVE) {
1693 #ifdef CONFIG_P2P
1694 			#ifdef CONFIG_IOCTL_CFG80211
1695 			if (rtw_cfg80211_is_p2p_scan(padapter))
1696 			#else
1697 			if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)
1698 				|| rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH))
1699 			#endif
1700 			{
1701 				issue_probereq_p2p(padapter, NULL);
1702 				issue_probereq_p2p(padapter, NULL);
1703 				issue_probereq_p2p(padapter, NULL);
1704 			} else
1705 #endif /* CONFIG_P2P */
1706 			{
1707 				if (pmlmeext->sitesurvey_res.scan_mode == RTW_PHL_SCAN_ACTIVE) {
1708 					/* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
1709 					if (padapter->registrypriv.wifi_spec)
1710 						issue_probereq(padapter, NULL, NULL);
1711 					else
1712 						issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
1713 					issue_probereq(padapter, NULL, NULL);
1714 				}
1715 
1716 				ssid_scan = 1;
1717 			}
1718 		}
1719 
1720 		if (ssid_scan) {
1721 			int i;
1722 
1723 			for (i = 0; i < RTW_SSID_SCAN_AMOUNT; i++) {
1724 				if (pmlmeext->sitesurvey_res.ssid[i].SsidLength) {
1725 					/* IOT issue, When wifi_spec is not set, send one probe req without WPS IE. */
1726 					if (padapter->registrypriv.wifi_spec)
1727 						issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
1728 					else
1729 						issue_probereq_ex(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL, 0, 0, 0, 0);
1730 					issue_probereq(padapter, &(pmlmeext->sitesurvey_res.ssid[i]), NULL);
1731 				}
1732 			}
1733 		}
1734 	} else {
1735 		/* channel number is 0 or this channel is not valid. */
1736 		rtw_warn_on(1);
1737 	}
1738 
1739 	return;
1740 }
1741 
1742 void survey_done_set_ch_bw(_adapter *padapter)
1743 {
1744 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1745 	u8 cur_channel = 0;
1746 	u8 cur_bwmode;
1747 	u8 cur_ch_offset;
1748 
1749 	if (rtw_mi_get_ch_setting_union(padapter, &cur_channel, &cur_bwmode, &cur_ch_offset) != 0) {
1750 		if (0)
1751 			RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
1752 				FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
1753 	} else {
1754 #ifdef CONFIG_P2P
1755 		struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1756 		_adapter *iface;
1757 		int i;
1758 
1759 		for (i = 0; i < dvobj->iface_nums; i++) {
1760 			iface = dvobj->padapters[i];
1761 			if (!iface)
1762 				continue;
1763 
1764 #ifdef CONFIG_IOCTL_CFG80211
1765 			if (iface->wdinfo.driver_interface == DRIVER_CFG80211 && !adapter_wdev_data(iface)->p2p_enabled)
1766 				continue;
1767 #endif
1768 
1769 			if (rtw_p2p_chk_state(&iface->wdinfo, P2P_STATE_LISTEN)) {
1770 				cur_channel = iface->wdinfo.listen_channel;
1771 				cur_bwmode = CHANNEL_WIDTH_20;
1772 				cur_ch_offset = CHAN_OFFSET_NO_EXT;
1773 				if (0)
1774 					RTW_INFO(FUNC_ADPT_FMT" back to "ADPT_FMT"'s listen ch - ch:%u, bw:%u, offset:%u\n",
1775 						FUNC_ADPT_ARG(padapter), ADPT_ARG(iface), cur_channel, cur_bwmode, cur_ch_offset);
1776 				break;
1777 			}
1778 		}
1779 #endif /* CONFIG_P2P */
1780 
1781 		if (cur_channel == 0) {
1782 			cur_channel = pmlmeext->chandef.chan;
1783 			cur_bwmode = pmlmeext->chandef.bw;
1784 			cur_ch_offset = pmlmeext->chandef.offset;
1785 			if (0)
1786 				RTW_INFO(FUNC_ADPT_FMT" back to ch:%u, bw:%u, offset:%u\n",
1787 					FUNC_ADPT_ARG(padapter), cur_channel, cur_bwmode, cur_ch_offset);
1788 		}
1789 	}
1790 	set_channel_bwmode(padapter, cur_channel, cur_ch_offset, cur_bwmode, _FALSE);
1791 }
1792 
1793 void sitesurvey_set_igi(_adapter *adapter)
1794 {
1795 	struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
1796 	struct ss_res *ss = &mlmeext->sitesurvey_res;
1797 	u8 igi;
1798 #ifdef CONFIG_P2P
1799 	struct wifidirect_info *pwdinfo = &adapter->wdinfo;
1800 #endif
1801 
1802 	switch (mlmeext_scan_state(mlmeext)) {
1803 	case SCAN_ENTER:
1804 		#ifdef CONFIG_P2P
1805 		#ifdef CONFIG_IOCTL_CFG80211
1806 		if (pwdinfo->driver_interface == DRIVER_CFG80211 && rtw_cfg80211_is_p2p_scan(adapter))
1807 			igi = 0x30;
1808 		else
1809 		#endif /* CONFIG_IOCTL_CFG80211 */
1810 		if (!rtw_p2p_chk_state(pwdinfo, P2P_STATE_NONE))
1811 			igi = 0x28;
1812 		else
1813 		#endif /* CONFIG_P2P */
1814 
1815 		if (ss->igi)
1816 			igi = ss->igi;
1817 		else
1818 		#if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)
1819 		if (IS_ACS_ENABLE(adapter) && rtw_is_acs_igi_valid(adapter))
1820 			igi = rtw_acs_get_adv_igi(adapter);
1821 		else
1822 		#endif /*CONFIG_RTW_ACS*/
1823 			igi = 0x1e;
1824 
1825 		/* record IGI status */
1826 		ss->igi_scan = igi;
1827 		rtw_hal_get_phydm_var(adapter, HAL_PHYDM_IGI, &ss->igi_before_scan, NULL);
1828 
1829 		/* disable DIG and set IGI for scan */
1830 		rtw_hal_set_phydm_var(adapter, HAL_PHYDM_IGI, &igi, _FALSE);
1831 		break;
1832 	case SCAN_COMPLETE:
1833 	case SCAN_TO_P2P_LISTEN:
1834 		/* enable DIG and restore IGI */
1835 		igi = 0xff;
1836 		rtw_hal_set_phydm_var(adapter, HAL_PHYDM_IGI, &igi, _FALSE);
1837 		break;
1838 #ifdef CONFIG_SCAN_BACKOP
1839 	case SCAN_BACKING_OP:
1840 		/* write IGI for op channel when DIG is not enabled */
1841 		rtw_hal_set_phydm_var(adapter, HAL_PHYDM_IGI_W, &ss->igi_before_scan, _FALSE);
1842 		break;
1843 	case SCAN_LEAVE_OP:
1844 		/* write IGI for scan when DIG is not enabled */
1845 		rtw_hal_set_phydm_var(adapter, HAL_PHYDM_IGI_W, &ss->igi_scan, _FALSE);
1846 		break;
1847 #endif /* CONFIG_SCAN_BACKOP */
1848 	default:
1849 		rtw_warn_on(1);
1850 		break;
1851 	}
1852 }
1853 void sitesurvey_set_msr(_adapter *adapter, bool enter)
1854 {
1855 	u8 network_type;
1856 	struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
1857 	struct mlme_ext_info *pmlmeinfo = &(pmlmeext->mlmext_info);
1858 
1859 	if (enter) {
1860 		/* set MSR to no link state */
1861 		network_type = _HW_STATE_NOLINK_;
1862 	} else {
1863 		network_type = pmlmeinfo->state & 0x3;
1864 	}
1865 }
1866 
1867 u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf)
1868 {
1869 	struct sitesurvey_parm	*pparm = (struct sitesurvey_parm *)pbuf;
1870 #ifdef DBG_CHECK_FW_PS_STATE
1871 	struct dvobj_priv *dvobj = padapter->dvobj;
1872 	struct debug_priv *pdbgpriv = &dvobj->drv_dbg;
1873 #endif
1874 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1875 	struct ss_res *ss = &pmlmeext->sitesurvey_res;
1876 #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
1877 	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
1878 #endif
1879 	u8 val8;
1880 
1881 #ifdef CONFIG_P2P
1882 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
1883 #endif
1884 
1885 #ifdef DBG_CHECK_FW_PS_STATE
1886 	if (rtw_fw_ps_state(padapter) == _FAIL) {
1887 		RTW_INFO("scan without leave 32k\n");
1888 		pdbgpriv->dbg_scan_pwr_state_cnt++;
1889 	}
1890 #endif /* DBG_CHECK_FW_PS_STATE */
1891 
1892 	/* increase channel idx */
1893 	if (mlmeext_chk_scan_state(pmlmeext, SCAN_PROCESS))
1894 		ss->channel_idx++;
1895 
1896 	/* update scan state to next state (assigned by previous cmd hdl) */
1897 	if (mlmeext_scan_state(pmlmeext) != mlmeext_scan_next_state(pmlmeext))
1898 		mlmeext_set_scan_state(pmlmeext, mlmeext_scan_next_state(pmlmeext));
1899 
1900 operation_by_state:
1901 	switch (mlmeext_scan_state(pmlmeext)) {
1902 
1903 	case SCAN_DISABLE:
1904 		/*
1905 		* SW parameter initialization
1906 		*/
1907 
1908 		sitesurvey_res_reset(padapter, pparm);
1909 		mlmeext_set_scan_state(pmlmeext, SCAN_START);
1910 		goto operation_by_state;
1911 
1912 	case SCAN_START:
1913 #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
1914 		if ((pwdev_priv->pno_mac_addr[0] != 0xFF)
1915 			    && (MLME_IS_STA(padapter))
1916 	    	    && (check_fwstate(&padapter->mlmepriv, WIFI_ASOC_STATE) == _FALSE)) {
1917 			u16 seq_num;
1918 
1919 			rtw_hal_pno_random_gen_mac_addr(padapter);
1920 			rtw_hal_set_hw_mac_addr(padapter, pwdev_priv->pno_mac_addr);
1921 			get_random_bytes(&seq_num, 2);
1922 			pwdev_priv->pno_scan_seq_num = seq_num & 0xFFF;
1923 			RTW_INFO("%s pno_scan_seq_num %d\n", __func__,
1924 				 pwdev_priv->pno_scan_seq_num);
1925 		}
1926 #endif
1927 
1928 		/*
1929 		* prepare to leave operating channel
1930 		*/
1931 
1932 		/* apply rx ampdu setting */
1933 		if (ss->rx_ampdu_accept != RX_AMPDU_ACCEPT_INVALID
1934 			|| ss->rx_ampdu_size != RX_AMPDU_SIZE_INVALID)
1935 			rtw_rx_ampdu_apply(padapter);
1936 
1937 		/* clear HW TX queue before scan */
1938 		rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
1939 
1940 		rtw_hal_macid_sleep_all_used(padapter);
1941 
1942 		/* power save state announcement */
1943 		if (rtw_ps_annc(padapter, 1)) {
1944 			mlmeext_set_scan_state(pmlmeext, SCAN_PS_ANNC_WAIT);
1945 			mlmeext_set_scan_next_state(pmlmeext, SCAN_ENTER);
1946 			set_survey_timer(pmlmeext, 50); /* delay 50ms to protect nulldata(1) */
1947 		} else {
1948 			mlmeext_set_scan_state(pmlmeext, SCAN_ENTER);
1949 			goto operation_by_state;
1950 		}
1951 
1952 		break;
1953 
1954 	case SCAN_ENTER:
1955 		/*
1956 		* HW register and DM setting for enter scan
1957 		*/
1958 
1959 		rtw_phydm_ability_backup(padapter);
1960 
1961 		sitesurvey_set_igi(padapter);
1962 
1963 		/* config dynamic functions for off channel */
1964 		rtw_phydm_func_for_offchannel(padapter);
1965 		/* set network type to no link state */
1966 		sitesurvey_set_msr(padapter, _TRUE);
1967 
1968 		val8 = 1; /* under site survey */
1969 		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
1970 
1971 		mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);
1972 		goto operation_by_state;
1973 
1974 	case SCAN_PROCESS: {
1975 		u8 scan_ch;
1976 		enum rtw_phl_scan_type stype;
1977 		u8 next_state;
1978 		u32 scan_ms;
1979 
1980 #ifdef CONFIG_RTW_ACS
1981 		if (IS_ACS_ENABLE(padapter))
1982 			rtw_acs_get_rst(padapter);
1983 #endif
1984 
1985 		next_state = sitesurvey_pick_ch_behavior(padapter, &scan_ch, &stype);
1986 
1987 		if (next_state != SCAN_PROCESS) {
1988 			mlmeext_set_scan_state(pmlmeext, next_state);
1989 			goto operation_by_state;
1990 		}
1991 
1992 		/* still SCAN_PROCESS state */
1993 		#ifdef DBG_SITESURVEY
1994 			#ifdef CONFIG_P2P
1995 			RTW_INFO(FUNC_ADPT_FMT" %s ch:%u (cnt:%u,idx:%d) at %dms, %c%c%c%c\n"
1996 				, FUNC_ADPT_ARG(padapter)
1997 				, mlmeext_scan_state_str(pmlmeext)
1998 				, scan_ch
1999 				, pwdinfo->find_phase_state_exchange_cnt, ss->channel_idx
2000 				, rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
2001 				, stype ? 'A' : 'P', ss->scan_mode ? 'A' : 'P'
2002 				, ss->ssid[0].SsidLength ? 'S' : ' '
2003 				, ss->force_ssid_scan ? 'F' : ' '
2004 			);
2005 			#else
2006 			RTW_INFO(FUNC_ADPT_FMT" %s ch:%u (idx:%d) at %dms, %c%c%c%c\n"
2007 				, FUNC_ADPT_ARG(padapter)
2008 				, mlmeext_scan_state_str(pmlmeext)
2009 				, scan_ch
2010 				, ss->channel_idx
2011 				, rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
2012 				, stype ? 'A' : 'P', ss->scan_mode ? 'A' : 'P'
2013 				, ss->ssid[0].SsidLength ? 'S' : ' '
2014 				, ss->force_ssid_scan ? 'F' : ' '
2015 			);
2016 			#endif /* CONFIG_P2P */
2017 		#endif /*DBG_SITESURVEY*/
2018 #ifdef DBG_FIXED_CHAN
2019 		if (pmlmeext->fixed_chan != 0xff)
2020 			RTW_INFO(FUNC_ADPT_FMT" fixed_chan:%u\n", pmlmeext->fixed_chan);
2021 #endif
2022 
2023 		site_survey(padapter, scan_ch, stype);
2024 
2025 #if defined(CONFIG_ATMEL_RC_PATCH)
2026 		if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
2027 			scan_ms = 20;
2028 		else
2029 			scan_ms = 40;
2030 #else
2031 		#if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)
2032 		if (IS_ACS_ENABLE(padapter) && rtw_is_acs_st_valid(padapter))
2033 			scan_ms = rtw_acs_get_adv_st(padapter);
2034 		else
2035 		#endif /*CONFIG_RTW_ACS*/
2036 			scan_ms = ss->scan_ch_ms;
2037 #endif
2038 
2039 #if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
2040 		if (ss->is_sw_antdiv_bl_scan)
2041 			scan_ms = scan_ms / 2;
2042 #endif
2043 
2044 #ifdef CONFIG_RTW_ACS
2045 		if (IS_ACS_ENABLE(padapter)) {
2046 			if (pparm->token)
2047 				rtw_acs_trigger(padapter, scan_ms, scan_ch, NHM_PID_IEEE_11K_HIGH);
2048 			else
2049 				rtw_acs_trigger(padapter, scan_ms, scan_ch, NHM_PID_ACS);
2050 		}
2051 #endif
2052 
2053 		set_survey_timer(pmlmeext, scan_ms);
2054 		break;
2055 	}
2056 
2057 #ifdef CONFIG_SCAN_BACKOP
2058 	case SCAN_BACKING_OP: {
2059 		u8 back_ch, back_bw, back_ch_offset;
2060 		u8 need_ch_setting_union = _TRUE;
2061 
2062 		if (need_ch_setting_union) {
2063 			if (rtw_mi_get_ch_setting_union(padapter, &back_ch, &back_bw, &back_ch_offset) == 0) {
2064 				rtw_warn_on(1);
2065 				back_ch = pmlmeext->chandef.chan;
2066 				back_bw = pmlmeext->chandef.bw;
2067 				back_ch_offset = pmlmeext->chandef.offset;
2068 			}
2069 		}
2070 
2071 		#ifdef DBG_SITESURVEY
2072 			RTW_INFO(FUNC_ADPT_FMT" %s ch:%u, bw:%u, offset:%u at %dms\n"
2073 				 , FUNC_ADPT_ARG(padapter)
2074 				 , mlmeext_scan_state_str(pmlmeext)
2075 				 , back_ch, back_bw, back_ch_offset
2076 				, rtw_get_passing_time_ms(padapter->mlmepriv.scan_start_time)
2077 				);
2078 		#endif /*DBG_SITESURVEY*/
2079 		set_channel_bwmode(padapter, back_ch, back_ch_offset, back_bw, _FALSE);
2080 
2081 		sitesurvey_set_msr(padapter, _FALSE);
2082 
2083 		val8 = 0; /* survey done */
2084 		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
2085 
2086 		if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)) {
2087 			sitesurvey_set_igi(padapter);
2088 			rtw_hal_macid_wakeup_all_used(padapter);
2089 			rtw_ps_annc(padapter, 0);
2090 		}
2091 
2092 		mlmeext_set_scan_state(pmlmeext, SCAN_BACK_OP);
2093 		ss->backop_time = rtw_get_current_time();
2094 
2095 		if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_TX_RESUME))
2096 			rtw_mi_os_xmit_schedule(padapter);
2097 
2098 		goto operation_by_state;
2099 	}
2100 
2101 	case SCAN_BACK_OP:
2102 		if (rtw_get_passing_time_ms(ss->backop_time) >= ss->backop_ms
2103 		    || pmlmeext->scan_abort
2104 		   ) {
2105 			mlmeext_set_scan_state(pmlmeext, SCAN_LEAVING_OP);
2106 			goto operation_by_state;
2107 		}
2108 		set_survey_timer(pmlmeext, 50);
2109 		break;
2110 
2111 	case SCAN_LEAVING_OP:
2112 		/*
2113 		 * prepare to leave operating channel
2114 		 */
2115 
2116 		/* clear HW TX queue before scan */
2117 		rtw_hal_set_hwreg(padapter, HW_VAR_CHECK_TXBUF, 0);
2118 
2119 		rtw_hal_macid_sleep_all_used(padapter);
2120 		if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC)
2121 			&& rtw_ps_annc(padapter, 1)
2122 		) {
2123 			mlmeext_set_scan_state(pmlmeext, SCAN_PS_ANNC_WAIT);
2124 			mlmeext_set_scan_next_state(pmlmeext, SCAN_LEAVE_OP);
2125 			set_survey_timer(pmlmeext, 50); /* delay 50ms to protect nulldata(1) */
2126 		} else {
2127 			mlmeext_set_scan_state(pmlmeext, SCAN_LEAVE_OP);
2128 			goto operation_by_state;
2129 		}
2130 
2131 		break;
2132 
2133 	case SCAN_LEAVE_OP:
2134 		/*
2135 		* HW register and DM setting for enter scan
2136 		*/
2137 
2138 		if (mlmeext_chk_scan_backop_flags(pmlmeext, SS_BACKOP_PS_ANNC))
2139 			sitesurvey_set_igi(padapter);
2140 
2141 		sitesurvey_set_msr(padapter, _TRUE);
2142 
2143 		val8 = 1; /* under site survey */
2144 		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
2145 
2146 		mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);
2147 		goto operation_by_state;
2148 
2149 #endif /* CONFIG_SCAN_BACKOP */
2150 
2151 #if defined(CONFIG_ANTENNA_DIVERSITY) || defined(DBG_SCAN_SW_ANTDIV_BL)
2152 	case SCAN_SW_ANTDIV_BL:
2153 		/*
2154 		* 20100721
2155 		* For SW antenna diversity before link, it needs to switch to another antenna and scan again.
2156 		* It compares the scan result and select better one to do connection.
2157 		*/
2158 		ss->bss_cnt = 0;
2159 		ss->channel_idx = 0;
2160 		ss->is_sw_antdiv_bl_scan = 1;
2161 
2162 		mlmeext_set_scan_next_state(pmlmeext, SCAN_PROCESS);
2163 		set_survey_timer(pmlmeext, ss->scan_ch_ms);
2164 		break;
2165 #endif
2166 
2167 #ifdef CONFIG_P2P
2168 	case SCAN_TO_P2P_LISTEN:
2169 		/*
2170 		* Set the P2P State to the listen state of find phase
2171 		* and set the current channel to the listen channel
2172 		*/
2173 		set_channel_bwmode(padapter,
2174 				pwdinfo->listen_channel,
2175 				CHAN_OFFSET_NO_EXT,
2176 				CHANNEL_WIDTH_20,
2177 				_FALSE);
2178 		rtw_p2p_set_state(pwdinfo, P2P_STATE_FIND_PHASE_LISTEN);
2179 
2180 		/* turn on phy-dynamic functions */
2181 		rtw_phydm_ability_restore(padapter);
2182 
2183 		sitesurvey_set_igi(padapter);
2184 
2185 		mlmeext_set_scan_state(pmlmeext, SCAN_P2P_LISTEN);
2186 		_set_timer(&pwdinfo->find_phase_timer, (u32)((u32)pwdinfo->listen_dwell * 100));
2187 		break;
2188 
2189 	case SCAN_P2P_LISTEN:
2190 		mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);
2191 		ss->channel_idx = 0;
2192 		goto operation_by_state;
2193 #endif /* CONFIG_P2P */
2194 
2195 	case SCAN_COMPLETE:
2196 #ifdef CONFIG_RTW_CFGVENDOR_RANDOM_MAC_OUI
2197 		rtw_hal_set_hw_mac_addr(padapter, adapter_mac_addr(padapter));
2198 #endif
2199 #ifdef CONFIG_P2P
2200 		if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_SCAN)
2201 		    || rtw_p2p_chk_state(pwdinfo, P2P_STATE_FIND_PHASE_SEARCH)
2202 		   ) {
2203 #ifdef CONFIG_CONCURRENT_MODE
2204 			if (pwdinfo->driver_interface == DRIVER_WEXT) {
2205 				if (rtw_mi_check_status(padapter, MI_LINKED))
2206 					_set_timer(&pwdinfo->ap_p2p_switch_timer, 500);
2207 			}
2208 #endif
2209 
2210 			rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
2211 		}
2212 		rtw_p2p_findphase_ex_set(pwdinfo, P2P_FINDPHASE_EX_NONE);
2213 #endif /* CONFIG_P2P */
2214 
2215 		/* switch channel */
2216 		survey_done_set_ch_bw(padapter);
2217 
2218 		sitesurvey_set_msr(padapter, _FALSE);
2219 
2220 		val8 = 0; /* survey done */
2221 		rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
2222 
2223 		/* turn on phy-dynamic functions */
2224 		rtw_phydm_ability_restore(padapter);
2225 
2226 		sitesurvey_set_igi(padapter);
2227 		rtw_hal_macid_wakeup_all_used(padapter);
2228 		rtw_ps_annc(padapter, 0);
2229 
2230 		/* apply rx ampdu setting */
2231 		rtw_rx_ampdu_apply(padapter);
2232 
2233 		mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE);
2234 
2235 		report_surveydone_event(padapter, ss->acs);
2236 #ifdef CONFIG_RTW_ACS
2237 		if (IS_ACS_ENABLE(padapter))
2238 			rtw_acs_select_best_chan(padapter);
2239 #endif
2240 
2241 		issue_action_BSSCoexistPacket(padapter);
2242 		issue_action_BSSCoexistPacket(padapter);
2243 		issue_action_BSSCoexistPacket(padapter);
2244 
2245 #ifdef CONFIG_RTW_80211K
2246 		if (ss->token)
2247 			rm_post_event(padapter, ss->token, RM_EV_survey_done);
2248 #endif /* CONFIG_RTW_80211K */
2249 
2250 		break;
2251 	}
2252 
2253 	return H2C_SUCCESS;
2254 }
2255 #else
sitesurvey_cmd_hdl(_adapter * padapter,u8 * pbuf)2256 u8 sitesurvey_cmd_hdl(_adapter *padapter, u8 *pbuf)
2257 {
2258 	RTW_ERR("%s executed??\n", __func__);
2259 	rtw_warn_on(1);
2260 	return 0;
2261 }
rtw_survey_cmd_callback(_adapter * padapter,struct cmd_obj * pcmd)2262 void rtw_survey_cmd_callback(_adapter  *padapter, struct cmd_obj *pcmd)
2263 {
2264 	RTW_ERR("%s executed??\n", __func__);
2265 	rtw_warn_on(1);
2266 }
2267 
2268 /* remain on channel priv */
2269 #define ROCH_CH_READY	0x1
2270 
2271 struct scan_priv {
2272 	_adapter *padapter;
2273 
2274 	/* for remain on channel callback */
2275 	struct wireless_dev *wdev;
2276 	struct ieee80211_channel channel;
2277 	u8 channel_type;
2278 	unsigned int duration;
2279 	u64 cookie;
2280 
2281 	u8 restore_ch;
2282 
2283 	u8 roch_step;
2284 #ifdef CONFIG_RTW_80211K
2285 	u32 rrm_token;	/* 80211k use it to identify caller */
2286 #endif
2287 };
2288 
2289 #ifdef CONFIG_CMD_SCAN
_alloc_phl_param(_adapter * adapter,u8 scan_ch_num)2290 static struct rtw_phl_scan_param *_alloc_phl_param(_adapter *adapter, u8 scan_ch_num)
2291 {
2292 	struct rtw_phl_scan_param *phl_param = NULL;
2293 	struct scan_priv *scan_priv = NULL;
2294 
2295 	if (scan_ch_num == 0) {
2296 		RTW_ERR("%s scan_ch_num = 0\n", __func__);
2297 		goto _err_exit;
2298 	}
2299 	/*create mem of PHL Scan parameter*/
2300 	phl_param = rtw_zmalloc(sizeof(*phl_param));
2301 	if (phl_param == NULL) {
2302 		RTW_ERR("%s alloc phl_param fail\n", __func__);
2303 		goto _err_exit;
2304 	}
2305 
2306 	scan_priv = rtw_zmalloc(sizeof(*scan_priv));
2307 	if (scan_priv == NULL) {
2308 		RTW_ERR("%s alloc scan_priv fail\n", __func__);
2309 		goto _err_scanpriv;
2310 	}
2311 	scan_priv->padapter = adapter;
2312 	phl_param->priv = scan_priv;
2313 	phl_param->wifi_role = adapter->phl_role;
2314 	phl_param->back_op_mode = SCAN_BKOP_NONE;
2315 
2316 	phl_param->ch_sz = sizeof(struct phl_scan_channel) * (scan_ch_num + 1);
2317 	phl_param->ch = rtw_zmalloc(phl_param->ch_sz);
2318 	if (phl_param->ch == NULL) {
2319 		RTW_ERR("%s: alloc phl scan ch fail\n", __func__);
2320 		goto _err_param_ch;
2321 	}
2322 
2323 	return phl_param;
2324 
2325 _err_param_ch:
2326 	if (scan_priv)
2327 		rtw_mfree(scan_priv, sizeof(*scan_priv));
2328 _err_scanpriv:
2329 	if (phl_param)
2330 		rtw_mfree(phl_param, sizeof(*phl_param));
2331 _err_exit:
2332 	rtw_warn_on(1);
2333 	return phl_param;
2334 }
2335 
_free_phl_param(_adapter * adapter,struct rtw_phl_scan_param * phl_param)2336 static u8 _free_phl_param(_adapter *adapter, struct rtw_phl_scan_param *phl_param)
2337 {
2338 	u8 res = _FAIL;
2339 
2340 	if (!phl_param)
2341 		return res;
2342 
2343 	if (phl_param->ch)
2344 		rtw_mfree(phl_param->ch, phl_param->ch_sz);
2345 	if (phl_param->priv)
2346 		rtw_mfree(phl_param->priv, sizeof(struct scan_priv));
2347 	rtw_mfree(phl_param, sizeof(struct rtw_phl_scan_param));
2348 
2349 	res = _SUCCESS;
2350 	return res;
2351 }
2352 #endif /*CONFIG_CMD_SCAN*/
scan_issue_pbreq_cb(void * priv,struct rtw_phl_scan_param * param)2353 static int scan_issue_pbreq_cb(void *priv, struct rtw_phl_scan_param *param)
2354 {
2355 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
2356 	_adapter *padapter = scan_priv->padapter;
2357 	NDIS_802_11_SSID ssid;
2358 	int i;
2359 
2360 
2361 	/* active scan behavior */
2362 	if (padapter->registrypriv.wifi_spec)
2363 		issue_probereq(padapter, NULL, NULL);
2364 	else
2365 		issue_probereq_ex(padapter, NULL, NULL, 0, 0, 0, 0);
2366 
2367 	issue_probereq(padapter, NULL, NULL);
2368 
2369 	for (i = 0; i < param->ssid_num; i++) {
2370 		if (param->ssid[i].ssid_len == 0)
2371 			continue;
2372 
2373 		ssid.SsidLength = param->ssid[i].ssid_len;
2374 		_rtw_memcpy(ssid.Ssid, &param->ssid[i].ssid, ssid.SsidLength);
2375 		/* IOT issue,
2376 		 * Send one probe req without WPS IE,
2377 		 * when not wifi_spec
2378 		 */
2379 		if (padapter->registrypriv.wifi_spec)
2380 			issue_probereq(padapter, &ssid, NULL);
2381 		else
2382 			issue_probereq_ex(padapter, &ssid, NULL, 0, 0, 0, 0);
2383 
2384 		issue_probereq(padapter, &ssid, NULL);
2385 	}
2386 	return 0;
2387 }
2388 
scan_complete_cb(void * priv,struct rtw_phl_scan_param * param)2389 static int scan_complete_cb(void *priv, struct rtw_phl_scan_param *param)
2390 {
2391 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
2392 	_adapter *padapter = scan_priv->padapter;
2393 	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
2394 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2395 	bool acs = _FALSE;
2396 	int ret = _FAIL;
2397 
2398 	if (!rtw_is_adapter_up(padapter))
2399 		goto _exit;
2400 
2401 	mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE);
2402 
2403 	report_surveydone_event(padapter, acs, RTW_CMDF_DIRECTLY);
2404 	ret = _SUCCESS;
2405 
2406 _exit:
2407 	RTW_INFO(FUNC_ADPT_FMT" takes %d ms to scan %d/%d channels\n",
2408 			FUNC_ADPT_ARG(padapter), param->total_scan_time,
2409 			#ifdef CONFIG_CMD_SCAN
2410 			param->ch_idx,
2411 			#else
2412 			param->ch_idx + 1,
2413 			#endif
2414 			param->ch_num);
2415 	_rtw_scan_abort_check(padapter, __func__);
2416 
2417 #ifdef CONFIG_CMD_SCAN
2418 	_free_phl_param(padapter, param);
2419 	pmlmeext->sitesurvey_res.scan_param = NULL;
2420 #else
2421 	rtw_mfree(scan_priv, sizeof(*scan_priv));
2422 #endif
2423 
2424 	return ret;
2425 }
2426 
scan_start_cb(void * priv,struct rtw_phl_scan_param * param)2427 static int scan_start_cb(void *priv, struct rtw_phl_scan_param *param)
2428 {
2429 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
2430 	_adapter *padapter = scan_priv->padapter;
2431 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2432 
2433 	pmlmeext->sitesurvey_res.bss_cnt = 0;
2434 	pmlmeext->sitesurvey_res.activate_ch_cnt = 0;
2435 	//TODO remove
2436 	mlmeext_set_scan_state(pmlmeext, SCAN_PROCESS);
2437 	#ifdef CONFIG_CMD_SCAN
2438 	pmlmeext->sitesurvey_res.scan_param = param;
2439 	#endif
2440 	return 0;
2441 }
2442 
2443 #ifdef CONFIG_P2P
scan_issue_p2p_pbreq_cb(void * priv,struct rtw_phl_scan_param * param)2444 static int scan_issue_p2p_pbreq_cb(void *priv, struct rtw_phl_scan_param *param)
2445 {
2446 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
2447 	_adapter *padapter = scan_priv->padapter;
2448 
2449 	issue_probereq_p2p(padapter, NULL);
2450 	issue_probereq_p2p(padapter, NULL);
2451 	issue_probereq_p2p(padapter, NULL);
2452 	return 0;
2453 }
2454 #endif
2455 
scan_ch_ready_cb(void * priv,struct rtw_phl_scan_param * param)2456 static int scan_ch_ready_cb(void *priv, struct rtw_phl_scan_param *param)
2457 {
2458 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
2459 	_adapter *padapter = scan_priv->padapter;
2460 
2461 	RTW_INFO("%s ch:%d\n", __func__, param->scan_ch->channel);
2462 	return 0;
2463 }
2464 
_ps_announce(_adapter * adapter,bool ps)2465 static inline void _ps_announce(_adapter *adapter, bool ps)
2466 {
2467 	RTW_INFO(FUNC_ADPT_FMT" issue_null(%d)\n", FUNC_ADPT_ARG(adapter), ps);
2468 	if (MLME_IS_STA(adapter)) {
2469 		if (is_client_associated_to_ap(adapter) == _TRUE) {
2470 			/*issue_nulldata(adapter, NULL, ps, 3, 500);*/
2471 			issue_nulldata(adapter, NULL, ps, 1, 0);
2472 		}
2473 	}
2474 	#ifdef CONFIG_RTW_MESH
2475 	else if (MLME_IS_MESH(adapter)) {
2476 		rtw_mesh_ps_annc(adapter, ps);
2477 	}
2478 	#endif
2479 }
2480 
scan_issu_null_data_cb(void * priv,u8 ridx,bool ps)2481 u8 scan_issu_null_data_cb(void *priv, u8 ridx, bool ps)
2482 {
2483 	#ifdef CONFIG_CMD_SCAN
2484 	struct dvobj_priv *obj = (struct dvobj_priv *)priv;
2485 	#else
2486 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
2487 	_adapter *padapter = scan_priv->padapter;
2488 	struct dvobj_priv *obj = adapter_to_dvobj(padapter);
2489 	#endif
2490 	_adapter *iface = NULL;
2491 
2492 	if (ridx >= CONFIG_IFACE_NUMBER) {
2493 		RTW_ERR("%s ridx:%d invalid\n", __func__, ridx);
2494 		rtw_warn_on(1);
2495 		goto _error;
2496 	}
2497 
2498 	iface = obj->padapters[ridx];
2499 	if (!rtw_is_adapter_up(iface))
2500 		goto _error;
2501 
2502 	_ps_announce(iface, ps);
2503 
2504 	return _SUCCESS;
2505 _error:
2506 	return _FAIL;
2507 }
2508 
2509 static struct rtw_phl_scan_ops scan_ops_cb = {
2510 	.scan_start = scan_start_cb,
2511 	.scan_ch_ready = scan_ch_ready_cb,
2512 	.scan_complete = scan_complete_cb,
2513 	.scan_issue_pbreq = scan_issue_pbreq_cb,
2514 	.scan_issue_null_data = scan_issu_null_data_cb
2515 };
2516 
2517 #ifdef CONFIG_P2P
2518 static struct rtw_phl_scan_ops scan_ops_p2p_cb = {
2519 	.scan_start = scan_start_cb,
2520 	.scan_ch_ready = scan_ch_ready_cb,
2521 	.scan_complete = scan_complete_cb,
2522 	.scan_issue_pbreq = scan_issue_p2p_pbreq_cb,
2523 	.scan_issue_null_data = scan_issu_null_data_cb
2524 };
2525 #endif
2526 
2527 #ifdef CONFIG_RTW_80211K
scan_complete_rrm_cb(void * priv,struct rtw_phl_scan_param * param)2528 static int scan_complete_rrm_cb(void *priv, struct rtw_phl_scan_param *param)
2529 {
2530 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
2531 	_adapter *padapter = scan_priv->padapter;
2532 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2533 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2534 	int ret = _FAIL;
2535 
2536 	if (!rtw_is_adapter_up(padapter))
2537 		goto _exit;
2538 
2539 	mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE);
2540 	_rtw_spinlock_bh(&pmlmepriv->lock);
2541 	_clr_fwstate_(pmlmepriv, WIFI_UNDER_SURVEY);
2542 	_rtw_spinunlock_bh(&pmlmepriv->lock);
2543 
2544 	/* inform RRM scan complete */
2545 	rm_post_event(padapter, scan_priv->rrm_token, RM_EV_survey_done);
2546 	ret = _SUCCESS;
2547 
2548 _exit:
2549 	RTW_INFO(FUNC_ADPT_FMT" takes %d ms to scan %d/%d channels\n",
2550 		FUNC_ADPT_ARG(padapter), param->total_scan_time,
2551 		param->ch_idx + 1, param->ch_num);
2552 	_rtw_scan_abort_check(padapter, __func__);
2553 
2554 #ifdef CONFIG_CMD_SCAN
2555 	_free_phl_param(padapter, param);
2556 	pmlmeext->sitesurvey_res.scan_param = NULL;
2557 #else
2558 	rtw_mfree(scan_priv, sizeof(*scan_priv));
2559 #endif
2560 	return ret;
2561 }
2562 
2563 static struct rtw_phl_scan_ops scan_ops_rrm_cb = {
2564 	.scan_start = scan_start_cb,
2565 	.scan_ch_ready = scan_ch_ready_cb,
2566 	.scan_complete = scan_complete_rrm_cb,
2567 	.scan_issue_pbreq = scan_issue_pbreq_cb,
2568 	.scan_issue_null_data = scan_issu_null_data_cb
2569 };
2570 #endif /* CONFIG_RTW_80211K */
2571 
2572 #ifndef SCAN_PER_CH_EX_TIME
2573 #define SCAN_PER_CH_EX_TIME	40 /*8852bs sw ch ov*/
2574 #endif /*SCAN_PER_CH_EX_TIME*/
rtw_scan_timeout_decision(_adapter * padapter)2575 static u32 rtw_scan_timeout_decision(_adapter *padapter)
2576 {
2577 	u8 max_chan_num;
2578 	u8 issue_null_time;
2579 	u16 scan_ms;
2580 	u16 p_ch_ex_time;
2581 	u32 non_op_buf;
2582 	u32 back_op_times = 0;
2583 
2584 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2585 	struct ss_res *ss = &pmlmeext->sitesurvey_res;
2586 	#ifdef CONFIG_SCAN_BACKOP
2587 	u8 backop_cout = 0;
2588 	#endif /*CONFIG_SCAN_BACKOP*/
2589 
2590 	if (padapter->registrypriv.scan_pch_ex_time != 0)
2591 		p_ch_ex_time = padapter->registrypriv.scan_pch_ex_time;
2592 	else
2593 		p_ch_ex_time = SCAN_PER_CH_EX_TIME;
2594 
2595 	/*issue null time,null(0)+null(1),undefine flag phl sleep 50ms*/
2596 	issue_null_time = 10;
2597 	#ifndef RTW_WKARD_TX_NULL_WD_RP
2598 	issue_null_time += 50;
2599 	#endif /*RTW_WKARD_TX_NULL_WD_RP*/
2600 
2601 	if (is_supported_5g(padapter->registrypriv.band_type)
2602 		&& is_supported_24g(padapter->registrypriv.band_type))
2603 		max_chan_num = MAX_CHANNEL_NUM_2G_5G;/* dual band */
2604 	else
2605 		max_chan_num = MAX_CHANNEL_NUM_2G;/*single band*/
2606 
2607 	#ifdef CONFIG_SCAN_BACKOP
2608 	backop_cout = max_chan_num / ss->scan_cnt_max;
2609 	/* delay 50ms to protect nulldata(1) */
2610 	if (rtw_scan_backop_decision(padapter))
2611 		back_op_times = backop_cout * (ss->backop_ms + p_ch_ex_time + issue_null_time);
2612 	#endif
2613 
2614 	if (ss->duration)
2615 		scan_ms = ss->duration;
2616 	else
2617 	#if defined(CONFIG_RTW_ACS) && defined(CONFIG_RTW_ACS_DBG)
2618 	if (IS_ACS_ENABLE(padapter) && rtw_is_acs_st_valid(padapter))
2619 		scan_ms = rtw_acs_get_adv_st(padapter);
2620 	else
2621 	#endif /*CONFIG_RTW_ACS*/
2622 		scan_ms = ss->scan_ch_ms;
2623 
2624 	/*non op channel buffer time + scan start/done issue null*/
2625 	non_op_buf = max_chan_num * p_ch_ex_time + issue_null_time;
2626 
2627 	ss->scan_timeout_ms = (scan_ms * max_chan_num) + back_op_times + non_op_buf;
2628 	#ifdef DBG_SITESURVEY
2629 	RTW_INFO("%s, max_chan_num(%d), p_ch_ex_time(%d), \
2630 		 ss->scan_cnt_max=%d issue_null_time=%d\n" \
2631 		 , __func__, max_chan_num, p_ch_ex_time,
2632 		 ss->scan_cnt_max, issue_null_time);
2633 	RTW_INFO("%s , scan_timeout_ms = %d (ms), scan_ms=%d (ms), \
2634 		back_op_times=%d (ms), ss->duration=%d (ms)\n" \
2635 		, __func__, ss->scan_timeout_ms, scan_ms, back_op_times, ss->duration);
2636 	#endif /*DBG_SITESURVEY*/
2637 
2638 	return ss->scan_timeout_ms;
2639 }
2640 
2641 /*
2642 rtw_sitesurvey_cmd(~)
2643 	### NOTE:#### (!!!!)
2644 	MUST TAKE CARE THAT BEFORE CALLING THIS FUNC, YOU SHOULD HAVE LOCKED pmlmepriv->lock
2645 */
2646 #ifdef CONFIG_CMD_SCAN
scan_channel_list_filled(_adapter * padapter,struct rtw_phl_scan_param * phl_param,struct sitesurvey_parm * param)2647 static void scan_channel_list_filled(_adapter *padapter,
2648 	struct rtw_phl_scan_param *phl_param, struct sitesurvey_parm *param)
2649 {
2650 	struct phl_scan_channel *phl_ch = phl_param->ch;
2651 	u8 i = 0;
2652 
2653 	for (i = 0; i < param->ch_num; i++) {
2654 		phl_ch[i].channel = param->ch[i].hw_value;
2655 		phl_ch[i].scan_mode = NORMAL_SCAN_MODE;
2656 		phl_ch[i].bw = param->bw;
2657 		phl_ch[i].duration = param->duration;
2658 
2659 		if (param->ch[i].flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN)
2660 			phl_ch[i].type = RTW_PHL_SCAN_PASSIVE;
2661 		else
2662 			phl_ch[i].type = RTW_PHL_SCAN_ACTIVE;
2663 	}
2664 	phl_param->ch_num = param->ch_num;
2665 }
2666 
2667 #ifdef RTW_WKARD_CMD_SCAN_EXTEND_ACTIVE_SCAN
2668 /*
2669  * Count extended active scan time(ms) and add time to
2670  * struct mlme_ext_priv.sitesurvey_res.scan_timeout_ms.
2671  *
2672  * Return extended active scan time which unit is ms.
2673  */
_scan_ext_act_time_count(struct _ADAPTER * a,struct rtw_phl_scan_param * scan)2674 static u32 _scan_ext_act_time_count(struct _ADAPTER *a,
2675 				    struct rtw_phl_scan_param *scan)
2676 {
2677 	struct ss_res *ss = &a->mlmeextpriv.sitesurvey_res;
2678 	u16 ext_time = 0;
2679 	int i;
2680 
2681 
2682 	for (i = 0; i < scan->ch_num; i++) {
2683 		if (scan->ch[i].ext_act_scan == EXT_ACT_SCAN_ENABLE)
2684 			ext_time += scan->ext_act_scan_period;
2685 	}
2686 #ifdef DBG_SITESURVEY
2687 	RTW_PRINT(FUNC_ADPT_FMT ": Add extend active scan time %u ms to total "
2688 		  "scan time (from %u to %u)\n",
2689 		  FUNC_ADPT_ARG(a), ext_time, ss->scan_timeout_ms,
2690 		  ext_time + ss->scan_timeout_ms);
2691 #endif /* DBG_SITESURVEY */
2692 	ss->scan_timeout_ms += ext_time;
2693 
2694 	return ext_time;
2695 }
2696 #endif /* RTW_WKARD_CMD_SCAN_EXTEND_ACTIVE_SCAN */
2697 
rtw_sitesurvey_cmd(_adapter * padapter,struct sitesurvey_parm * pparm)2698 u8 rtw_sitesurvey_cmd(_adapter *padapter, struct sitesurvey_parm *pparm)
2699 {
2700 	u8 res = _FAIL;
2701 	u8 i;
2702 	u32 scan_timeout_ms;
2703 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
2704 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
2705 	struct rtw_phl_scan_param *phl_param = NULL;
2706 	struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT] = {0};
2707 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2708 	struct sitesurvey_parm *tmp_parm = NULL;
2709 	struct mlme_ext_priv *mlmeext = &padapter->mlmeextpriv;
2710 	struct ss_res *ss = &mlmeext->sitesurvey_res;
2711 	struct rf_ctl_t *rfctl = adapter_to_rfctl(padapter);
2712 #ifdef CONFIG_RTW_80211K
2713 	struct scan_priv *scan_priv = NULL;
2714 #endif
2715 
2716 	if (pparm == NULL) {
2717 		tmp_parm = rtw_zmalloc(sizeof(struct sitesurvey_parm));
2718 		if (tmp_parm == NULL) {
2719 			RTW_ERR("%s alloc tmp_parm fail\n", __func__);
2720 			goto _err_exit;
2721 		}
2722 		rtw_init_sitesurvey_parm(padapter, tmp_parm);
2723 		pparm = tmp_parm;
2724 	}
2725 
2726 	/* backup original ch list */
2727 	_rtw_memcpy(ch, pparm->ch,
2728 		sizeof(struct rtw_ieee80211_channel) * pparm->ch_num);
2729 
2730 	/* modify ch list according to chanel plan */
2731 	pparm->ch_num = rtw_scan_ch_decision(padapter,
2732 					pparm->ch, RTW_CHANNEL_SCAN_AMOUNT,
2733 					ch, pparm->ch_num, pparm->acs);
2734 
2735 	if (pparm->duration == 0)
2736 		pparm->duration = ss->scan_ch_ms; /* ms */
2737 
2738 	/*create mem of PHL Scan parameter*/
2739 	phl_param = _alloc_phl_param(padapter, pparm->ch_num);
2740 	if (phl_param == NULL) {
2741 		RTW_ERR("%s alloc phl_param fail\n", __func__);
2742 		goto _err_param;
2743 	}
2744 
2745 	/* STEP_1 transfer to rtw channel list to phl channel list */
2746 	scan_channel_list_filled(padapter, phl_param, pparm);
2747 
2748 	/* STEP_2 copy the ssid info to phl param */
2749 	phl_param->ssid_num = rtw_min(pparm->ssid_num, SCAN_SSID_AMOUNT);
2750 	for (i = 0; i < phl_param->ssid_num; ++i) {
2751 		phl_param->ssid[i].ssid_len = pparm->ssid[i].SsidLength;
2752 		_rtw_memcpy(&phl_param->ssid[i].ssid, &pparm->ssid[i].Ssid, phl_param->ssid[i].ssid_len);
2753 	}
2754 #ifdef RTW_WKARD_CMD_SCAN_EXTEND_ACTIVE_SCAN
2755 	/* STEP_2.1 set EXT_ACT_SCAN_ENABLE for hidden AP scan */
2756 	if (phl_param->ssid[0].ssid_len) {
2757 		phl_param->ext_act_scan_period = RTW_EXTEND_ACTIVE_SCAN_PERIOD;
2758 		for (i = 0; i < phl_param->ch_num; i++) {
2759 			int chset_idx;
2760 			chset_idx = rtw_chset_search_ch(rfctl->channel_set,
2761 							phl_param->ch[i].channel);
2762 			if (chset_idx < 0) {
2763 				RTW_ERR(FUNC_ADPT_FMT ": cann't find ch %u in chset!\n",
2764 					FUNC_ADPT_ARG(padapter), phl_param->ch[i].channel);
2765 				continue;
2766 			}
2767 
2768 			if ((phl_param->ch[i].type == RTW_PHL_SCAN_PASSIVE)
2769 			    && (!IS_DFS_SLAVE_WITH_RD(rfctl)
2770 				|| rtw_rfctl_dfs_domain_unknown(rfctl)
2771 				|| !CH_IS_NON_OCP(&rfctl->channel_set[chset_idx])))
2772 				phl_param->ch[i].ext_act_scan = EXT_ACT_SCAN_ENABLE;
2773 		}
2774 	}
2775 #endif /* RTW_WKARD_CMD_SCAN_EXTEND_ACTIVE_SCAN */
2776 
2777 	/* STEP_3 set ops according to scan_type */
2778 	switch (pparm->scan_type) {
2779 	#ifdef CONFIG_P2P
2780 	case RTW_SCAN_P2P:
2781 		phl_param->ops = &scan_ops_p2p_cb;
2782 	break;
2783 	#endif
2784 
2785 	#ifdef CONFIG_RTW_80211K
2786 	case RTW_SCAN_RRM:
2787 		phl_param->ops = &scan_ops_rrm_cb;
2788 		scan_priv = (struct scan_priv *)phl_param->priv;
2789 		scan_priv->rrm_token = pparm->rrm_token;
2790 		ss->token = pparm->rrm_token;
2791 	break;
2792 	#endif
2793 
2794 	case RTW_SCAN_NORMAL:
2795 	default:
2796 		phl_param->ops = &scan_ops_cb;
2797 #ifdef CONFIG_SCAN_BACKOP
2798 		if (rtw_scan_backop_decision(padapter)) {
2799 			phl_param->back_op_ch_dur_ms = ss->backop_ms;
2800 			phl_param->back_op_mode = SCAN_BKOP_CNT;
2801 			phl_param->back_op_ch_cnt = ss->scan_cnt_max;
2802 		} else {
2803 			phl_param->back_op_mode = SCAN_BKOP_NONE;
2804 		}
2805 #else
2806 		phl_param->back_op_mode = SCAN_BKOP_NONE;
2807 #endif /* CONFIG_SCAN_BACKOP */
2808 	break;
2809 	}
2810 
2811 	/* STEP_4 reset variables for each scan */
2812 	for (i = 0; i < MAX_CHANNEL_NUM; i++)
2813 		rfctl->channel_set[i].hidden_bss_cnt = 0;
2814 
2815 	set_fwstate(pmlmepriv, WIFI_UNDER_SURVEY);
2816 
2817 	if(rtw_phl_cmd_scan_request(dvobj->phl, phl_param, true) != RTW_PHL_STATUS_SUCCESS) {
2818 		RTW_ERR("%s request scam_cmd failed\n", __func__);
2819 		_clr_fwstate_(pmlmepriv, WIFI_UNDER_SURVEY);
2820 		goto _err_req_param;
2821 	}
2822 
2823 	pmlmeext->sitesurvey_res.scan_param = phl_param;
2824 	rtw_free_network_queue(padapter, _FALSE);
2825 
2826 	pmlmepriv->scan_start_time = rtw_get_current_time();
2827 	scan_timeout_ms = rtw_scan_timeout_decision(padapter);
2828 #ifdef RTW_WKARD_CMD_SCAN_EXTEND_ACTIVE_SCAN
2829 	scan_timeout_ms += _scan_ext_act_time_count(padapter, phl_param);
2830 #endif /* RTW_WKARD_CMD_SCAN_EXTEND_ACTIVE_SCAN */
2831 	mlme_set_scan_to_timer(pmlmepriv,scan_timeout_ms);
2832 
2833 	rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
2834 	if (tmp_parm)
2835 		rtw_mfree(tmp_parm, sizeof(*tmp_parm));
2836 	res = _SUCCESS;
2837 	return res;
2838 
2839 _err_req_param:
2840 	_free_phl_param(padapter, phl_param);
2841 _err_param:
2842 	if (tmp_parm)
2843 		rtw_mfree(tmp_parm, sizeof(*tmp_parm));
2844 _err_exit:
2845 	rtw_warn_on(1);
2846 	return res;
2847 }
2848 
2849 #else /*!CONFIG_CMD_SCAN*/
2850 
2851 /**
2852  * prepare phl_channel list according to SCAN type
2853  *
2854  */
scan_channel_list_preparation(_adapter * padapter,struct rtw_phl_scan_param * dst,struct sitesurvey_parm * src)2855 static int scan_channel_list_preparation(_adapter *padapter,
2856 	struct rtw_phl_scan_param *dst, struct sitesurvey_parm *src)
2857 {
2858 	struct phl_scan_channel *phl_ch = NULL;
2859 	int phl_ch_sz = 0;
2860 	int i;
2861 
2862 	phl_ch_sz = sizeof(struct phl_scan_channel) * (src->ch_num + 1);
2863 
2864 	phl_ch = rtw_malloc(phl_ch_sz);
2865 	if (phl_ch == NULL) {
2866 		RTW_ERR("scan: alloc phl scan ch fail\n");
2867 		return -1;
2868 	}
2869 	_rtw_memset(phl_ch, 0, phl_ch_sz);
2870 
2871 	i = 0;
2872 	while (i < src->ch_num) {
2873 
2874 		phl_ch[i].channel = src->ch[i].hw_value;
2875 		phl_ch[i].scan_mode = NORMAL_SCAN_MODE;
2876 		phl_ch[i].bw = src->bw;
2877 		phl_ch[i].duration = src->duration;
2878 
2879 		if (src->ch[i].flags & RTW_IEEE80211_CHAN_PASSIVE_SCAN) {
2880 			phl_ch[i].type = RTW_PHL_SCAN_PASSIVE;
2881 
2882 		} else {
2883 			phl_ch[i].type = RTW_PHL_SCAN_ACTIVE;
2884 
2885 			/* reduce scan time in active channel */
2886 			if (src->scan_type == RTW_SCAN_NORMAL)
2887 				phl_ch[i].duration = src->duration >> 1;
2888 		}
2889 		i++;
2890 	}
2891 
2892 	dst->ch = phl_ch;
2893 	dst->ch_sz = phl_ch_sz;
2894 	dst->ch_num = src->ch_num;
2895 
2896 	return 0;
2897 }
2898 
rtw_site_survey_fsm(_adapter * padapter,struct cmd_obj * pcmd)2899 u32 rtw_site_survey_fsm(_adapter *padapter, struct cmd_obj *pcmd)
2900 {
2901 	u32 res = RTW_PHL_STATUS_FAILURE;
2902 	struct scan_priv *scan_priv;
2903 	struct rtw_phl_scan_param *phl_param;
2904 	struct sitesurvey_parm *rtw_param;
2905 	struct rtw_ieee80211_channel ch[RTW_CHANNEL_SCAN_AMOUNT];
2906 	u8 i;
2907 
2908 	scan_priv = rtw_malloc(sizeof(*scan_priv));
2909 	if (scan_priv == NULL) {
2910 		RTW_ERR("scan: %s alloc scan_priv fail\n", __func__);
2911 		return RTW_PHL_STATUS_FAILURE;
2912 	}
2913 	_rtw_memset(scan_priv, 0, sizeof(*scan_priv));
2914 	scan_priv->padapter = padapter;
2915 	rtw_param = (struct sitesurvey_parm *)pcmd->parmbuf;
2916 
2917 	if (rtw_param->duration == 0)
2918 		rtw_param->duration = SURVEY_TO; /* ms */
2919 
2920 	/* backup original ch list */
2921 	_rtw_memcpy(ch, rtw_param->ch,
2922 		sizeof(struct rtw_ieee80211_channel) *
2923 		rtw_param->ch_num);
2924 
2925 	/* modify ch list according to chanel plan */
2926 	rtw_param->ch_num = rtw_scan_ch_decision(padapter,
2927 				rtw_param->ch, RTW_CHANNEL_SCAN_AMOUNT,
2928 				ch, rtw_param->ch_num, rtw_param->acs);
2929 
2930 	phl_param = rtw_malloc(sizeof(*phl_param));
2931 	if (phl_param == NULL) {
2932 		RTW_ERR("scan: %s alloc param fail\n", __func__);
2933 		if (scan_priv)
2934 			rtw_mfree(scan_priv, sizeof(*scan_priv));
2935 			return RTW_PHL_STATUS_FAILURE;
2936 		}
2937 	_rtw_memset(phl_param, 0, sizeof(*phl_param));
2938 
2939 	/* transfer to rtw channel list to phl channel list */
2940 	scan_channel_list_preparation(padapter, phl_param, rtw_param);
2941 
2942 	/* copy the ssid info to phl param */
2943 	phl_param->ssid_num = rtw_min(rtw_param->ssid_num, SCAN_SSID_AMOUNT);
2944 	for (i = 0; i < phl_param->ssid_num; ++i) {
2945 		phl_param->ssid[i].ssid_len = rtw_param->ssid[i].SsidLength;
2946 		_rtw_memcpy(&phl_param->ssid[i].ssid, &rtw_param->ssid[i].Ssid, phl_param->ssid[i].ssid_len);
2947 	}
2948 
2949 	switch (rtw_param->scan_type) {
2950 #ifdef CONFIG_P2P
2951 	case RTW_SCAN_P2P:
2952 		phl_param->ops = &scan_ops_p2p_cb;
2953 	break;
2954 #endif
2955 #ifdef CONFIG_RTW_80211K
2956 	case RTW_SCAN_RRM:
2957 		phl_param->ops = &scan_ops_rrm_cb;
2958 		if (rtw_param->ch_num > 13) {
2959 			phl_param->back_op_mode = SCAN_BKOP_CNT;
2960 			phl_param->back_op_ch_cnt = 3;
2961 		}
2962 	break;
2963 #endif
2964 	case RTW_SCAN_NORMAL:
2965 	default:
2966 		phl_param->ops = &scan_ops_cb;
2967 		phl_param->back_op_mode = SCAN_BKOP_CNT;
2968 		phl_param->back_op_ch_cnt = 3;
2969 		break;
2970 	}
2971 	phl_param->priv = scan_priv;
2972 	phl_param->wifi_role = padapter->phl_role;
2973 
2974 	res = rtw_phl_scan_request(adapter_to_dvobj(padapter)->phl, phl_param, TO_TAIL);
2975 	rtw_mfree(phl_param->ch, phl_param->ch_sz);
2976 	rtw_mfree(phl_param, sizeof(*phl_param));
2977 
2978 	return res;
2979 }
2980 
rtw_sitesurvey_cmd(_adapter * padapter,struct sitesurvey_parm * pparm)2981 u8 rtw_sitesurvey_cmd(_adapter *padapter, struct sitesurvey_parm *pparm)
2982 {
2983 	u8 res = _FAIL;
2984 	struct cmd_obj *cmd;
2985 	struct sitesurvey_parm	*psurveyPara;
2986 	struct cmd_priv	*pcmdpriv = &adapter_to_dvobj(padapter)->cmdpriv;
2987 	struct mlme_priv	*pmlmepriv = &padapter->mlmepriv;
2988 
2989 #ifdef CONFIG_LPS
2990 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
2991 		rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_SCAN, 0);
2992 #endif
2993 
2994 #ifdef CONFIG_P2P_PS
2995 	if (check_fwstate(pmlmepriv, WIFI_ASOC_STATE) == _TRUE)
2996 		p2p_ps_wk_cmd(padapter, P2P_PS_SCAN, 1);
2997 #endif /* CONFIG_P2P_PS */
2998 
2999 	cmd = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3000 	if (cmd == NULL)
3001 		return _FAIL;
3002 	cmd->padapter = padapter;
3003 
3004 	psurveyPara = (struct sitesurvey_parm *)rtw_zmalloc(sizeof(struct sitesurvey_parm));
3005 	if (psurveyPara == NULL) {
3006 		rtw_mfree((unsigned char *) cmd, sizeof(struct cmd_obj));
3007 		return _FAIL;
3008 	}
3009 
3010 	if (pparm)
3011 		_rtw_memcpy(psurveyPara, pparm, sizeof(struct sitesurvey_parm));
3012 	else
3013 		psurveyPara->scan_mode = pmlmepriv->scan_mode;
3014 
3015 	rtw_free_network_queue(padapter, _FALSE);
3016 
3017 	init_h2fwcmd_w_parm_no_rsp(cmd, psurveyPara, CMD_SITE_SURVEY);
3018 
3019 	set_fwstate(pmlmepriv, WIFI_UNDER_SURVEY);
3020 
3021 
3022 	res = rtw_enqueue_cmd(pcmdpriv, cmd);
3023 
3024 	if (res == _SUCCESS) {
3025 		u32 scan_timeout_ms;
3026 
3027 		pmlmepriv->scan_start_time = rtw_get_current_time();
3028 		scan_timeout_ms = rtw_scan_timeout_decision(padapter);
3029 		mlme_set_scan_to_timer(pmlmepriv,scan_timeout_ms);
3030 
3031 		rtw_led_control(padapter, LED_CTL_SITE_SURVEY);
3032 	} else {
3033 		_clr_fwstate_(pmlmepriv, WIFI_UNDER_SURVEY);
3034 	}
3035 
3036 
3037 	return res;
3038 }
3039 #endif/*CONFIG_CMD_SCAN*/
3040 
3041 
3042 /* inform caller phl_scan are ready on remain channel */
roch_ready_cb(void * priv,struct rtw_phl_scan_param * param)3043 static int roch_ready_cb(void *priv, struct rtw_phl_scan_param *param)
3044 {
3045 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
3046 	_adapter *padapter = scan_priv->padapter;
3047 	struct cfg80211_roch_info *pcfg80211_rochinfo =
3048 		&padapter->cfg80211_rochinfo;
3049 
3050 	RTW_INFO("%s cookie:0x%llx\n", __func__,
3051 		pcfg80211_rochinfo->remain_on_ch_cookie);
3052 
3053 	if ((scan_priv->roch_step & ROCH_CH_READY))
3054 		return 0;
3055 
3056 	scan_priv->roch_step |= ROCH_CH_READY;
3057 
3058 	rtw_cfg80211_ready_on_channel(
3059 		scan_priv->wdev,
3060 		scan_priv->cookie,
3061 		&scan_priv->channel,
3062 		scan_priv->channel_type,
3063 		scan_priv->duration,
3064 		GFP_KERNEL);
3065 	return 0;
3066 }
3067 
roch_off_ch_tx_cb(void * priv,struct rtw_phl_scan_param * param,void * data)3068 static int roch_off_ch_tx_cb(void *priv,
3069 	struct rtw_phl_scan_param *param, void *data)
3070 {
3071 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
3072 	struct dvobj_priv *dvobj = adapter_to_dvobj(scan_priv->padapter);
3073 
3074 #ifdef CONFIG_CMD_SCAN
3075 	RTW_ERR("CMD_SCAN call %s\n", __func__);
3076 	rtw_warn_on(1);
3077 #else
3078 	phl_cmd_complete_job(dvobj->phl, (struct phl_cmd_job *)data);
3079 #endif
3080 	return 0;
3081 }
3082 
3083 #ifdef CONFIG_P2P
p2p_roch_complete_cb(void * priv,struct rtw_phl_scan_param * param)3084 static int p2p_roch_complete_cb(void *priv, struct rtw_phl_scan_param *param)
3085 {
3086 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
3087 	_adapter *padapter = scan_priv->padapter;
3088 	int ret = _FAIL;
3089 	struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
3090 	struct cfg80211_roch_info *pcfg80211_rochinfo =
3091 		&padapter->cfg80211_rochinfo;
3092 	struct wifidirect_info *pwdinfo = &padapter->wdinfo;
3093 
3094 	if (!rtw_is_adapter_up(padapter))
3095 		goto _exit;
3096 
3097 	mlmeext_set_scan_state(&padapter->mlmeextpriv, SCAN_DISABLE);
3098 
3099 	/* roch_ready() and roch_complete() MUST be a PAIR
3100 	 * otherwise will caurse wpa_supplicant hang!!!
3101 	 * This case may happen when someone cancel remain on ch
3102 	 * before it really start. (called roch_ready()).
3103 	 */
3104 	if (!(scan_priv->roch_step & ROCH_CH_READY))
3105 		roch_ready_cb(priv, param);
3106 
3107 #ifndef CONFIG_CMD_SCAN
3108 	rtw_back_opch(padapter);
3109 #endif
3110 #ifdef CONFIG_DEBUG_CFG80211
3111 	RTW_INFO("%s, role=%d\n", __func__, rtw_p2p_role(pwdinfo));
3112 #endif
3113 
3114 	rtw_cfg80211_set_is_roch(padapter, _FALSE);
3115 	pcfg80211_rochinfo->ro_ch_wdev = NULL;
3116 	rtw_cfg80211_set_last_ro_ch_time(padapter);
3117 
3118 	ret = _SUCCESS;
3119 _exit:
3120 	/* callback to cfg80211 */
3121 	rtw_cfg80211_remain_on_channel_expired(scan_priv->wdev
3122 		, scan_priv->cookie
3123 		, &scan_priv->channel
3124 		, scan_priv->channel_type, GFP_KERNEL);
3125 
3126 	RTW_INFO("cfg80211_remain_on_channel_expired cookie:0x%llx\n"
3127 		, pcfg80211_rochinfo->remain_on_ch_cookie);
3128 
3129 	RTW_INFO(FUNC_ADPT_FMT" takes %d ms to scan %d/%d channels\n",
3130 			FUNC_ADPT_ARG(padapter), param->total_scan_time,
3131 			#ifdef CONFIG_CMD_SCAN
3132 			param->ch_idx,
3133 			#else
3134 			param->ch_idx + 1,
3135 			#endif
3136 			param->ch_num);
3137 	_rtw_scan_abort_check(padapter, __func__);
3138 
3139 #ifdef CONFIG_CMD_SCAN
3140 	_free_phl_param(padapter, param);
3141 	padapter->mlmeextpriv.sitesurvey_res.scan_param = NULL;
3142 #else
3143 	rtw_mfree(scan_priv, sizeof(*scan_priv));
3144 #endif
3145 	return ret;
3146 }
3147 
p2p_roch_start_cb(void * priv,struct rtw_phl_scan_param * param)3148 static int p2p_roch_start_cb(void *priv, struct rtw_phl_scan_param *param)
3149 {
3150 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
3151 	_adapter *padapter = scan_priv->padapter;
3152 	struct cfg80211_roch_info *pcfg80211_rochinfo;
3153 
3154 	pcfg80211_rochinfo = &padapter->cfg80211_rochinfo;
3155 
3156 	//TODO remove
3157 	mlmeext_set_scan_state(&padapter->mlmeextpriv, SCAN_PROCESS);
3158 
3159 	rtw_cfg80211_set_is_roch(padapter, _TRUE);
3160 	pcfg80211_rochinfo->ro_ch_wdev = scan_priv->wdev;
3161 	pcfg80211_rochinfo->remain_on_ch_cookie = scan_priv->cookie;
3162 	pcfg80211_rochinfo->duration = scan_priv->duration;
3163 	rtw_cfg80211_set_last_ro_ch_time(padapter);
3164 	_rtw_memcpy(&pcfg80211_rochinfo->remain_on_ch_channel,
3165 		&scan_priv->channel, sizeof(struct ieee80211_channel));
3166 	#if (KERNEL_VERSION(3, 8, 0) > LINUX_VERSION_CODE)
3167 	pcfg80211_rochinfo->remain_on_ch_type = scan_priv->channel_type;
3168 	#endif
3169 	pcfg80211_rochinfo->restore_channel = scan_priv->restore_ch;
3170 
3171 	#ifdef CONFIG_CMD_SCAN
3172 	padapter->mlmeextpriv.sitesurvey_res.scan_param = param;
3173 	#endif
3174 
3175 	return 0;
3176 }
3177 #endif
3178 
roch_start_cb(void * priv,struct rtw_phl_scan_param * param)3179 static int roch_start_cb(void *priv, struct rtw_phl_scan_param *param)
3180 {
3181 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
3182 	_adapter *padapter = scan_priv->padapter;
3183 
3184 	mlmeext_set_scan_state(&padapter->mlmeextpriv, SCAN_PROCESS);
3185 	rtw_cfg80211_set_is_roch(padapter, _TRUE);
3186 	#ifdef CONFIG_CMD_SCAN
3187 	padapter->mlmeextpriv.sitesurvey_res.scan_param = param;
3188 	#endif
3189 
3190 	return 0;
3191 }
3192 
roch_complete_cb(void * priv,struct rtw_phl_scan_param * param)3193 static int roch_complete_cb(void *priv, struct rtw_phl_scan_param *param)
3194 {
3195 	struct scan_priv *scan_priv = (struct scan_priv *)priv;
3196 	_adapter *padapter = scan_priv->padapter;
3197 	struct cfg80211_roch_info *pcfg80211_rochinfo =
3198 		&padapter->cfg80211_rochinfo;
3199 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3200 	int ret = _FAIL;
3201 
3202 	if (!rtw_is_adapter_up(padapter))
3203 		goto _exit;
3204 
3205 	mlmeext_set_scan_state(pmlmeext, SCAN_DISABLE);
3206 
3207 	/* roch_ready() and roch_complete() MUST be a PAIR
3208 	 * otherwise will caurse wpa_supplicant hang!!!
3209 	 * This case may happen when someone cancel remain on ch
3210 	 * before it really start. (called roch_ready()).
3211 	 */
3212 	if (!(scan_priv->roch_step & ROCH_CH_READY))
3213 		roch_ready_cb(priv, param);
3214 
3215 	rtw_cfg80211_set_is_roch(padapter, _FALSE);
3216 
3217 	ret = _SUCCESS;
3218 
3219 _exit:
3220 	/* callback to cfg80211 */
3221 	rtw_cfg80211_remain_on_channel_expired(scan_priv->wdev
3222 		, scan_priv->cookie
3223 		, &scan_priv->channel
3224 		, scan_priv->channel_type, GFP_KERNEL);
3225 
3226 	RTW_INFO("cfg80211_remain_on_channel_expired cookie:0x%llx\n"
3227 		, pcfg80211_rochinfo->remain_on_ch_cookie);
3228 
3229 	RTW_INFO(FUNC_ADPT_FMT" takes %d ms to scan %d/%d channels\n",
3230 			FUNC_ADPT_ARG(padapter), param->total_scan_time,
3231 			#ifdef CONFIG_CMD_SCAN
3232 			param->ch_idx,
3233 			#else
3234 			param->ch_idx + 1,
3235 			#endif
3236 			param->ch_num);
3237 	_rtw_scan_abort_check(padapter, __func__);
3238 
3239 #ifdef CONFIG_CMD_SCAN
3240 	_free_phl_param(padapter, param);
3241 	pmlmeext->sitesurvey_res.scan_param = NULL;
3242 #else
3243 	rtw_mfree(scan_priv, sizeof(*scan_priv));
3244 #endif
3245 	return ret;
3246 }
3247 
3248 #ifdef CONFIG_P2P
3249 /* p2p remain on channel */
3250 static struct rtw_phl_scan_ops p2p_remain_ops_cb = {
3251 	.scan_start = p2p_roch_start_cb,
3252 	.scan_ch_ready = roch_ready_cb,
3253 	.scan_off_ch_tx = roch_off_ch_tx_cb,
3254 	.scan_complete = p2p_roch_complete_cb,
3255 	.scan_issue_null_data = scan_issu_null_data_cb
3256 };
3257 #endif
3258 
3259 /* normal remain on channel */
3260 static struct rtw_phl_scan_ops remain_ops_cb = {
3261 	.scan_start = roch_start_cb,
3262 	.scan_ch_ready = roch_ready_cb,
3263 	.scan_off_ch_tx = roch_off_ch_tx_cb,
3264 	.scan_complete = roch_complete_cb,
3265 	.scan_issue_null_data = scan_issu_null_data_cb
3266 };
3267 
3268 #ifdef CONFIG_IOCTL_CFG80211
roch_stay_in_cur_chan(_adapter * padapter)3269 static u8 roch_stay_in_cur_chan(_adapter *padapter)
3270 {
3271 	int i;
3272 	_adapter *iface;
3273 	struct mlme_priv *pmlmepriv;
3274 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3275 	u8 rst = _FALSE;
3276 
3277 	for (i = 0; i < dvobj->iface_nums; i++) {
3278 		iface = dvobj->padapters[i];
3279 		if (iface) {
3280 			pmlmepriv = &iface->mlmepriv;
3281 
3282 			if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE) == _TRUE) {
3283 				RTW_INFO(ADPT_FMT"- WIFI_UNDER_LINKING |WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE (mlme state:0x%x)\n",
3284 						ADPT_ARG(iface), get_fwstate(&iface->mlmepriv));
3285 				rst = _TRUE;
3286 				break;
3287 			}
3288 			#ifdef CONFIG_AP_MODE
3289 			if (MLME_IS_AP(iface) || MLME_IS_MESH(iface)) {
3290 				if (rtw_ap_sta_states_check(iface) == _TRUE) {
3291 					rst = _TRUE;
3292 					break;
3293 				}
3294 			}
3295 			#endif
3296 		}
3297 	}
3298 
3299 	return rst;
3300 }
3301 
3302 #ifdef CONFIG_CMD_SCAN
rtw_phl_remain_on_ch_cmd(_adapter * padapter,u64 cookie,struct wireless_dev * wdev,struct ieee80211_channel * ch,u8 ch_type,unsigned int duration,struct back_op_param * bkop_parm,u8 is_p2p)3303 u8 rtw_phl_remain_on_ch_cmd(_adapter *padapter,
3304 	u64 cookie, struct wireless_dev *wdev,
3305 	struct ieee80211_channel *ch, u8 ch_type,
3306 	unsigned int duration, struct back_op_param *bkop_parm,
3307 	u8 is_p2p)
3308 {
3309 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3310 	struct rtw_phl_scan_param *phl_param = NULL;
3311 	struct scan_priv *scan_priv = NULL;
3312 	u16 remain_ch;
3313 	u8 chan_num;
3314 	u8 res = _FAIL;
3315 
3316 	/* prepare remain channel - check channel */
3317 	remain_ch = (u16)ieee80211_frequency_to_channel(ch->center_freq);
3318 	if (roch_stay_in_cur_chan(padapter) == _TRUE) { /*???*/
3319 		remain_ch = rtw_mi_get_union_chan(padapter);
3320 		RTW_INFO(FUNC_ADPT_FMT" stay in union ch:%d\n",
3321 			FUNC_ADPT_ARG(padapter), remain_ch);
3322 	}
3323 	chan_num = 1;
3324 
3325 	phl_param = _alloc_phl_param(padapter, chan_num);
3326 	if (phl_param == NULL) {
3327 		RTW_ERR("%s alloc phl_param fail\n", __func__);
3328 		goto _err_exit;
3329 	}
3330 
3331 	/*** fill phl parameter - scan_priv ***/
3332 	scan_priv = (struct scan_priv *)phl_param->priv;
3333 	scan_priv->padapter = padapter;
3334 	scan_priv->wdev = wdev;
3335 	_rtw_memcpy(&scan_priv->channel, ch, sizeof(*ch));
3336 	scan_priv->channel_type = ch_type;
3337 	scan_priv->cookie = cookie;
3338 	scan_priv->duration = duration;
3339 	scan_priv->restore_ch = rtw_get_oper_ch(padapter);
3340 
3341 	/* fill phl param - chan */
3342 	phl_param->ch->channel = remain_ch;
3343 	phl_param->ch->duration = duration;
3344 	phl_param->ch->scan_mode = P2P_LISTEN_MODE;
3345 	phl_param->ch->bw = CHANNEL_WIDTH_20;
3346 	phl_param->ch_num = chan_num;
3347 
3348 	/* fill back op param */
3349 	phl_param->back_op_mode = SCAN_BKOP_TIMER;
3350 	phl_param->back_op_ch_cnt = 1;
3351 	phl_param->back_op_ch_dur_ms = bkop_parm->on_ch_dur;/*op_ch time*/
3352 	phl_param->back_op_off_ch_dur_ms = bkop_parm->off_ch_dur;/*ro_ch time*/
3353 	phl_param->back_op_off_ch_ext_dur_ms = bkop_parm->off_ch_ext_dur;
3354 
3355 #ifdef CONFIG_P2P
3356 	/* set ops according to is_p2p */
3357 	if (is_p2p)
3358 		phl_param->ops = &p2p_remain_ops_cb;
3359 	else
3360 #endif
3361 		phl_param->ops = &remain_ops_cb;
3362 
3363 	if(rtw_phl_cmd_scan_request(dvobj->phl, phl_param, true) == RTW_PHL_STATUS_FAILURE) {
3364 		RTW_ERR("%s request scam_cmd failed\n", __func__);
3365 		goto _err_req_param;
3366 	}
3367 
3368 
3369 	RTW_INFO(FUNC_ADPT_FMT" ch:%u duration:%d, cookie:0x%llx\n"
3370 			, FUNC_ADPT_ARG(padapter), remain_ch,	duration, cookie);
3371 	res = _SUCCESS;
3372 	return res;
3373 
3374 _err_req_param:
3375 	_free_phl_param(padapter, phl_param);
3376 _err_exit:
3377 	rtw_warn_on(1);
3378 	return res;
3379 }
3380 
3381 #else
rtw_phl_remain_on_ch_cmd(_adapter * padapter,u64 cookie,struct wireless_dev * wdev,struct ieee80211_channel * ch,u8 ch_type,unsigned int duration,struct back_op_param * bkop_parm,u8 is_p2p)3382 u8 rtw_phl_remain_on_ch_cmd(_adapter *padapter,
3383 	u64 cookie, struct wireless_dev *wdev,
3384 	struct ieee80211_channel *ch, u8 ch_type,
3385 	unsigned int duration, struct back_op_param *bkop_parm,
3386 	u8 is_p2p)
3387 {
3388 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3389 	struct rtw_phl_scan_param phl_param;
3390 	struct scan_priv *scan_priv;
3391 	struct phl_scan_channel phl_ch;
3392 	int phl_ch_sz = 0;
3393 	u16 remain_ch;
3394 	u8 res = _FAIL;
3395 
3396 	_rtw_memset(&phl_param, 0, sizeof(phl_param));
3397 
3398 	scan_priv = rtw_malloc(sizeof(*scan_priv));
3399 	if (scan_priv == NULL) {
3400 		RTW_ERR("scan: %s alloc scan_priv fail\n", __func__);
3401 		return res;
3402 	}
3403 	_rtw_memset(scan_priv, 0, sizeof(*scan_priv));
3404 
3405 	scan_priv->padapter = padapter;
3406 	scan_priv->wdev = wdev;
3407 	_rtw_memcpy(&scan_priv->channel, ch, sizeof(*ch));
3408 	scan_priv->channel_type = ch_type;
3409 
3410 	scan_priv->cookie = cookie;
3411 	scan_priv->duration = duration;
3412 	scan_priv->restore_ch = rtw_get_oper_ch(padapter);
3413 
3414 	phl_param.priv = scan_priv;
3415 
3416 	/* check channel */
3417 	remain_ch = (u16)ieee80211_frequency_to_channel(ch->center_freq);
3418 
3419 	if (roch_stay_in_cur_chan(padapter) == _TRUE) {
3420 		remain_ch = rtw_mi_get_union_chan(padapter);
3421 		RTW_INFO(FUNC_ADPT_FMT" stay in union ch:%d\n",
3422 			FUNC_ADPT_ARG(padapter), remain_ch);
3423 	}
3424 
3425 	/* prepare remain channel */
3426 	phl_ch_sz = sizeof(struct phl_scan_channel);
3427 	_rtw_memset(&phl_ch, 0, phl_ch_sz);
3428 
3429 	phl_ch.channel = remain_ch;
3430 	phl_ch.duration = scan_priv->duration;
3431 	phl_ch.scan_mode = NORMAL_SCAN_MODE;
3432 	phl_ch.bw = CHANNEL_WIDTH_20;
3433 
3434 	phl_param.ch = &phl_ch;
3435 	phl_param.ch_sz = phl_ch_sz;
3436 	phl_param.ch_num = 1;
3437 	phl_param.wifi_role = padapter->phl_role;
3438 
3439 	phl_param.back_op_mode = SCAN_BKOP_TIMER;
3440 	phl_param.back_op_ch_dur_ms = bkop_parm->on_ch_dur;
3441 	phl_param.back_op_off_ch_dur_ms = bkop_parm->off_ch_dur;
3442 	phl_param.back_op_off_ch_ext_dur_ms = bkop_parm->off_ch_ext_dur;
3443 
3444 #ifdef CONFIG_P2P
3445 	if (is_p2p)
3446 		phl_param.ops = &p2p_remain_ops_cb;
3447 	else
3448 #endif
3449 		phl_param.ops = &remain_ops_cb;
3450 
3451 	RTW_INFO(FUNC_ADPT_FMT" ch:%u duration:%d, cookie:0x%llx\n"
3452 		, FUNC_ADPT_ARG(padapter), phl_ch.channel,
3453 		scan_priv->duration, cookie);
3454 
3455 	/* sent message to request phl scan
3456 	 * IMMEDIATE imply cancelling previous scan request if has
3457 	 */
3458 	rtw_phl_scan_request(dvobj->phl, &phl_param, IMMEDIATE);
3459 
3460 	/* scan_priv will be cancelled in roch_complete_cb */
3461 	res = _SUCCESS;
3462 	return res;
3463 }
3464 #endif
3465 #endif /*CONFIG_IOCTL_CFG80211*/
3466 
3467 #endif /*CONFIG_PHL_ARCH*/
3468