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, ¶m->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