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