1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 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
16 #include <drv_types.h>
17
18 #ifdef CONFIG_IOCTL_CFG80211
rtw_roch_stay_in_cur_chan(_adapter * padapter)19 u8 rtw_roch_stay_in_cur_chan(_adapter *padapter)
20 {
21 int i;
22 _adapter *iface;
23 struct mlme_priv *pmlmepriv;
24 struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
25 u8 rst = _FALSE;
26
27 for (i = 0; i < dvobj->iface_nums; i++) {
28 iface = dvobj->padapters[i];
29 if (iface) {
30 pmlmepriv = &iface->mlmepriv;
31
32 if (check_fwstate(pmlmepriv, WIFI_UNDER_LINKING | WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE) == _TRUE) {
33 RTW_INFO(ADPT_FMT"- WIFI_UNDER_LINKING |WIFI_UNDER_WPS | WIFI_UNDER_KEY_HANDSHAKE (mlme state:0x%x)\n",
34 ADPT_ARG(iface), get_fwstate(&iface->mlmepriv));
35 rst = _TRUE;
36 break;
37 }
38 #ifdef CONFIG_AP_MODE
39 if (MLME_IS_AP(iface) || MLME_IS_MESH(iface)) {
40 if (rtw_ap_sta_states_check(iface) == _TRUE) {
41 rst = _TRUE;
42 break;
43 }
44 }
45 #endif
46 }
47 }
48
49 return rst;
50 }
51
rtw_ro_ch_handler(_adapter * adapter,u8 * buf)52 static int rtw_ro_ch_handler(_adapter *adapter, u8 *buf)
53 {
54 int ret = H2C_SUCCESS;
55 struct rtw_roch_parm *roch_parm = (struct rtw_roch_parm *)buf;
56 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
57 struct roch_info *prochinfo = &adapter->rochinfo;
58 #ifdef CONFIG_CONCURRENT_MODE
59 struct mlme_ext_priv *pmlmeext = &adapter->mlmeextpriv;
60 #endif
61 u8 ready_on_channel = _FALSE;
62 u8 remain_ch;
63 unsigned int duration;
64
65 _enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
66
67 if (rtw_cfg80211_get_is_roch(adapter) != _TRUE)
68 goto exit;
69
70 remain_ch = (u8)ieee80211_frequency_to_channel(roch_parm->ch.center_freq);
71 duration = roch_parm->duration;
72
73 RTW_INFO(FUNC_ADPT_FMT" ch:%u duration:%d, cookie:0x%llx\n"
74 , FUNC_ADPT_ARG(adapter), remain_ch, roch_parm->duration, roch_parm->cookie);
75
76 if (roch_parm->wdev && roch_parm->cookie) {
77 if (prochinfo->ro_ch_wdev != roch_parm->wdev) {
78 RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"
79 , FUNC_ADPT_ARG(adapter), prochinfo->ro_ch_wdev, roch_parm->wdev);
80 rtw_warn_on(1);
81 }
82
83 if (prochinfo->remain_on_ch_cookie != roch_parm->cookie) {
84 RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"
85 , FUNC_ADPT_ARG(adapter), prochinfo->remain_on_ch_cookie, roch_parm->cookie);
86 rtw_warn_on(1);
87 }
88 }
89
90 if (rtw_roch_stay_in_cur_chan(adapter) == _TRUE) {
91 remain_ch = rtw_mi_get_union_chan(adapter);
92 RTW_INFO(FUNC_ADPT_FMT" stay in union ch:%d\n", FUNC_ADPT_ARG(adapter), remain_ch);
93 }
94
95 #ifdef CONFIG_CONCURRENT_MODE
96 if (rtw_mi_check_status(adapter, MI_LINKED) && (0 != rtw_mi_get_union_chan(adapter))) {
97 if ((remain_ch != rtw_mi_get_union_chan(adapter)) && !check_fwstate(&adapter->mlmepriv, WIFI_ASOC_STATE)) {
98 if (remain_ch != pmlmeext->cur_channel
99 #ifdef RTW_ROCH_BACK_OP
100 || ATOMIC_READ(&pwdev_priv->switch_ch_to) == 1
101 #endif
102 ) {
103 rtw_leave_opch(adapter);
104
105 #ifdef RTW_ROCH_BACK_OP
106 RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, prochinfo->max_away_dur);
107 ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);
108 /* remain_ch is not same as union channel. duration is max_away_dur to
109 * back to AP's channel.
110 */
111 _set_timer(&prochinfo->ap_roch_ch_switch_timer, prochinfo->max_away_dur);
112 #endif
113 }
114 }
115 ready_on_channel = _TRUE;
116 } else
117 #endif /* CONFIG_CONCURRENT_MODE */
118 {
119 if (remain_ch != rtw_get_oper_ch(adapter))
120 ready_on_channel = _TRUE;
121 }
122
123 if (ready_on_channel == _TRUE) {
124 #ifndef RTW_SINGLE_WIPHY
125 if (!check_fwstate(&adapter->mlmepriv, WIFI_ASOC_STATE))
126 #endif
127 {
128 #ifdef CONFIG_CONCURRENT_MODE
129 if (rtw_get_oper_ch(adapter) != remain_ch)
130 #endif
131 {
132 /* if (!padapter->mlmepriv.LinkDetectInfo.bBusyTraffic) */
133 set_channel_bwmode(adapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
134 }
135 }
136 }
137
138 #ifdef CONFIG_BT_COEXIST
139 rtw_btcoex_ScanNotify(adapter, _TRUE);
140 #endif
141
142 RTW_INFO("%s, set ro ch timer, duration=%d\n", __func__, duration);
143 _set_timer(&prochinfo->remain_on_ch_timer, duration);
144
145 exit:
146 _exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
147
148 return ret;
149 }
150
rtw_cancel_ro_ch_handler(_adapter * padapter,u8 * buf)151 static int rtw_cancel_ro_ch_handler(_adapter *padapter, u8 *buf)
152 {
153 int ret = H2C_SUCCESS;
154 struct rtw_roch_parm *roch_parm = (struct rtw_roch_parm *)buf;
155 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
156 struct roch_info *prochinfo = &padapter->rochinfo;
157 struct wireless_dev *wdev;
158 #ifdef CONFIG_P2P
159 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
160 #endif
161 u8 ch, bw, offset;
162
163 _enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
164
165 if (rtw_cfg80211_get_is_roch(padapter) != _TRUE)
166 goto exit;
167
168 if (roch_parm->wdev && roch_parm->cookie) {
169 if (prochinfo->ro_ch_wdev != roch_parm->wdev) {
170 RTW_WARN(FUNC_ADPT_FMT" ongoing wdev:%p, wdev:%p\n"
171 , FUNC_ADPT_ARG(padapter), prochinfo->ro_ch_wdev, roch_parm->wdev);
172 rtw_warn_on(1);
173 }
174
175 if (prochinfo->remain_on_ch_cookie != roch_parm->cookie) {
176 RTW_WARN(FUNC_ADPT_FMT" ongoing cookie:0x%llx, cookie:0x%llx\n"
177 , FUNC_ADPT_ARG(padapter), prochinfo->remain_on_ch_cookie, roch_parm->cookie);
178 rtw_warn_on(1);
179 }
180 }
181
182 #if defined(RTW_ROCH_BACK_OP) && defined(CONFIG_CONCURRENT_MODE)
183 _cancel_timer_ex(&prochinfo->ap_roch_ch_switch_timer);
184 ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
185 #endif
186
187 if (rtw_mi_get_ch_setting_union(padapter, &ch, &bw, &offset) != 0) {
188 if (0)
189 RTW_INFO(FUNC_ADPT_FMT" back to linked/linking union - ch:%u, bw:%u, offset:%u\n",
190 FUNC_ADPT_ARG(padapter), ch, bw, offset);
191 #ifdef CONFIG_P2P
192 } else if (adapter_wdev_data(padapter)->p2p_enabled && pwdinfo->listen_channel) {
193 ch = pwdinfo->listen_channel;
194 bw = CHANNEL_WIDTH_20;
195 offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
196 if (0)
197 RTW_INFO(FUNC_ADPT_FMT" back to listen ch - ch:%u, bw:%u, offset:%u\n",
198 FUNC_ADPT_ARG(padapter), ch, bw, offset);
199 #endif
200 } else {
201 ch = prochinfo->restore_channel;
202 bw = CHANNEL_WIDTH_20;
203 offset = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
204 if (0)
205 RTW_INFO(FUNC_ADPT_FMT" back to restore ch - ch:%u, bw:%u, offset:%u\n",
206 FUNC_ADPT_ARG(padapter), ch, bw, offset);
207 }
208
209 set_channel_bwmode(padapter, ch, offset, bw);
210 rtw_back_opch(padapter);
211 #ifdef CONFIG_P2P
212 rtw_p2p_set_state(pwdinfo, rtw_p2p_pre_state(pwdinfo));
213 #ifdef CONFIG_DEBUG_CFG80211
214 RTW_INFO("%s, role=%d, p2p_state=%d\n", __func__, rtw_p2p_role(pwdinfo), rtw_p2p_state(pwdinfo));
215 #endif
216 #endif
217
218 wdev = prochinfo->ro_ch_wdev;
219
220 rtw_cfg80211_set_is_roch(padapter, _FALSE);
221 prochinfo->ro_ch_wdev = NULL;
222 rtw_cfg80211_set_last_ro_ch_time(padapter);
223
224 rtw_cfg80211_remain_on_channel_expired(wdev
225 , prochinfo->remain_on_ch_cookie
226 , &prochinfo->remain_on_ch_channel
227 , prochinfo->remain_on_ch_type, GFP_KERNEL);
228
229 RTW_INFO("cfg80211_remain_on_channel_expired cookie:0x%llx\n"
230 , prochinfo->remain_on_ch_cookie);
231
232 #ifdef CONFIG_BT_COEXIST
233 rtw_btcoex_ScanNotify(padapter, _FALSE);
234 #endif
235
236 exit:
237 _exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
238
239 return ret;
240 }
241
rtw_ro_ch_timer_process(void * FunctionContext)242 static void rtw_ro_ch_timer_process(void *FunctionContext)
243 {
244 _adapter *adapter = (_adapter *)FunctionContext;
245
246 rtw_cancel_roch_cmd(adapter, 0, NULL, 0);
247 }
248 #endif /* CONFIG_IOCTL_CFG80211 */
249
250 #if (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211)
rtw_roch_wk_hdl(_adapter * padapter,int intCmdType,u8 * buf)251 s32 rtw_roch_wk_hdl(_adapter *padapter, int intCmdType, u8 *buf)
252 {
253 int ret = H2C_SUCCESS;
254
255 switch (intCmdType) {
256
257 #ifdef CONFIG_IOCTL_CFG80211
258 case ROCH_RO_CH_WK:
259 ret = rtw_ro_ch_handler(padapter, buf);
260 break;
261 case ROCH_CANCEL_RO_CH_WK:
262 ret = rtw_cancel_ro_ch_handler(padapter, buf);
263 break;
264 #endif
265
266 #ifdef CONFIG_CONCURRENT_MODE
267 case ROCH_AP_ROCH_CH_SWITCH_PROCESS_WK:
268 rtw_concurrent_handler(padapter);
269 break;
270 #endif
271
272 default:
273 rtw_warn_on(1);
274 break;
275 }
276
277 return ret;
278 }
279
get_roch_parm_size(struct rtw_roch_parm * roch_parm)280 static int get_roch_parm_size(struct rtw_roch_parm *roch_parm)
281 {
282 #ifdef CONFIG_IOCTL_CFG80211
283 return (roch_parm ? sizeof(*roch_parm) : 0);
284 #else
285 rtw_warn_on(roch_parm);
286 return 0;
287 #endif
288 }
289
rtw_roch_wk_cmd(_adapter * padapter,int intCmdType,struct rtw_roch_parm * roch_parm,u8 flags)290 u8 rtw_roch_wk_cmd(_adapter *padapter, int intCmdType, struct rtw_roch_parm *roch_parm, u8 flags)
291 {
292 struct cmd_obj *ph2c = NULL;
293 struct drvextra_cmd_parm *pdrvextra_cmd_parm = NULL;
294 struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
295 struct submit_ctx sctx;
296 u8 res = _SUCCESS;
297
298 if (flags & RTW_CMDF_DIRECTLY) {
299 /* no need to enqueue, do the cmd hdl directly and free cmd parameter */
300 if (H2C_SUCCESS != rtw_roch_wk_hdl(padapter, intCmdType, (u8 *)roch_parm))
301 res = _FAIL;
302 goto free_parm;
303 } else {
304 ph2c = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
305 if (!ph2c) {
306 res = _FAIL;
307 goto free_parm;
308 }
309
310 pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
311 if (!pdrvextra_cmd_parm) {
312 res = _FAIL;
313 goto free_parm;
314 }
315
316 pdrvextra_cmd_parm->ec_id = ROCH_WK_CID;
317 pdrvextra_cmd_parm->type = intCmdType;
318 pdrvextra_cmd_parm->size = get_roch_parm_size(roch_parm);
319 pdrvextra_cmd_parm->pbuf = (u8 *)roch_parm;
320
321 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvextra_cmd_parm, CMD_SET_DRV_EXTRA);
322
323 if (flags & RTW_CMDF_WAIT_ACK) {
324 ph2c->sctx = &sctx;
325 rtw_sctx_init(&sctx, 10 * 1000);
326 }
327
328 res = rtw_enqueue_cmd(pcmdpriv, ph2c);
329
330 if (res == _SUCCESS && (flags & RTW_CMDF_WAIT_ACK)) {
331 rtw_sctx_wait(&sctx, __func__);
332 _enter_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
333 if (sctx.status == RTW_SCTX_SUBMITTED)
334 ph2c->sctx = NULL;
335 _exit_critical_mutex(&pcmdpriv->sctx_mutex, NULL);
336 if (sctx.status != RTW_SCTX_DONE_SUCCESS)
337 res = _FAIL;
338 }
339 }
340
341 return res;
342
343 free_parm:
344 if (roch_parm)
345 rtw_mfree((u8 *)roch_parm, get_roch_parm_size(roch_parm));
346 if (ph2c)
347 rtw_mfree((u8 *)ph2c, sizeof(*ph2c));
348
349 return res;
350 }
351
352 #ifdef CONFIG_CONCURRENT_MODE
rtw_ap_roch_ch_switch_timer_process(void * ctx)353 void rtw_ap_roch_ch_switch_timer_process(void *ctx)
354 {
355 _adapter *adapter = (_adapter *)ctx;
356 #ifdef CONFIG_IOCTL_CFG80211
357 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(adapter);
358 #endif
359
360 #ifdef CONFIG_IOCTL_CFG80211
361 ATOMIC_SET(&pwdev_priv->switch_ch_to, 1);
362 #endif
363
364 rtw_roch_wk_cmd(adapter, ROCH_AP_ROCH_CH_SWITCH_PROCESS_WK, NULL, 0);
365 }
366
chk_need_stay_in_cur_chan(_adapter * padapter)367 static bool chk_need_stay_in_cur_chan(_adapter *padapter)
368 {
369 #ifdef CONFIG_P2P
370 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
371
372 /* When CONFIG_FULL_CH_IN_P2P_HANDSHAKE is defined and the
373 * interface is in the P2P_STATE_GONEGO_OK state, do not let the
374 * interface switch to the listen channel, because the interface will
375 * switch to the OP channel after the GO negotiation is successful.
376 */
377 if (padapter->registrypriv.full_ch_in_p2p_handshake == 1 && rtw_p2p_chk_state(pwdinfo , P2P_STATE_GONEGO_OK)) {
378 RTW_INFO("%s, No linked interface now, but go nego ok, do not back to listen channel\n", __func__);
379 return _TRUE;
380 }
381 #endif
382
383 return _FALSE;
384 }
385
chk_driver_interface(_adapter * padapter,u8 driver_interface)386 static bool chk_driver_interface(_adapter *padapter, u8 driver_interface)
387 {
388 #ifdef CONFIG_P2P
389 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
390
391 if (pwdinfo->driver_interface == driver_interface)
392 return _TRUE;
393 #elif defined(CONFIG_IOCTL_CFG80211)
394 if (driver_interface == DRIVER_CFG80211)
395 return _TRUE;
396 #endif
397
398 return _FALSE;
399 }
400
get_remain_ch(_adapter * padapter)401 static u8 get_remain_ch(_adapter *padapter)
402 {
403 struct roch_info *prochinfo = &padapter->rochinfo;
404 #ifdef CONFIG_P2P
405 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
406 #endif
407 u8 remain_ch;
408
409 #ifdef CONFIG_P2P
410 remain_ch = pwdinfo->listen_channel;
411 #elif defined(CONFIG_IOCTL_CFG80211)
412 if (chk_driver_interface(padapter, DRIVER_CFG80211))
413 remain_ch = ieee80211_frequency_to_channel(prochinfo->remain_on_ch_channel.center_freq);
414 else
415 rtw_warn_on(1);
416 #endif
417
418 return remain_ch;
419 }
420
rtw_concurrent_handler(_adapter * padapter)421 void rtw_concurrent_handler(_adapter *padapter)
422 {
423 #ifdef CONFIG_IOCTL_CFG80211
424 struct rtw_wdev_priv *pwdev_priv = adapter_wdev_data(padapter);
425 #endif
426 struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
427 struct roch_info *prochinfo = &padapter->rochinfo;
428 #ifdef CONFIG_P2P
429 struct wifidirect_info *pwdinfo = &padapter->wdinfo;
430 u8 val8;
431 #endif
432 u8 remain_ch = get_remain_ch(padapter);
433
434 #ifdef CONFIG_IOCTL_CFG80211
435 if (chk_driver_interface(padapter, DRIVER_CFG80211)
436 && !rtw_cfg80211_get_is_roch(padapter))
437 return;
438 #endif
439
440 if (rtw_mi_check_status(padapter, MI_LINKED)) {
441 u8 union_ch = rtw_mi_get_union_chan(padapter);
442 u8 union_bw = rtw_mi_get_union_bw(padapter);
443 u8 union_offset = rtw_mi_get_union_offset(padapter);
444 unsigned int duration;
445
446 #ifdef CONFIG_P2P
447 pwdinfo->operating_channel = union_ch;
448 #endif
449
450 if (chk_driver_interface(padapter, DRIVER_CFG80211)) {
451 #ifdef CONFIG_IOCTL_CFG80211
452 _enter_critical_mutex(&pwdev_priv->roch_mutex, NULL);
453
454 if (rtw_get_oper_ch(padapter) != union_ch) {
455 /* Current channel is not AP's channel - switching to AP's channel */
456 RTW_INFO("%s, switch ch back to union=%u,%u, %u\n"
457 , __func__, union_ch, union_bw, union_offset);
458 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
459 rtw_back_opch(padapter);
460
461 /* Now, the driver stays on AP's channel. We should stay on AP's
462 * channel for min_home_dur (duration) and next switch channel is
463 * listen channel.
464 */
465 duration = prochinfo->min_home_dur;
466 } else {
467 /* Current channel is AP's channel - switching to listen channel */
468 RTW_INFO("%s, switch ch to roch=%u\n"
469 , __func__, remain_ch);
470 rtw_leave_opch(padapter);
471 set_channel_bwmode(padapter,
472 remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
473
474 /* Now, the driver stays on listen channel. We should stay on listen
475 * channel for max_away_dur (duration) and next switch channel is AP's
476 * channel.
477 */
478 duration = prochinfo->max_away_dur;
479 }
480
481 /* set channel switch timer */
482 ATOMIC_SET(&pwdev_priv->switch_ch_to, 0);
483 _set_timer(&prochinfo->ap_roch_ch_switch_timer, duration);
484 RTW_INFO("%s, set switch ch timer, duration=%d\n", __func__, duration);
485
486 _exit_critical_mutex(&pwdev_priv->roch_mutex, NULL);
487 #endif
488 }
489 #ifdef CONFIG_P2P
490 else if (chk_driver_interface(padapter, DRIVER_WEXT)) {
491 if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_IDLE)) {
492 /* Now, the driver stays on the AP's channel. */
493 /* If the pwdinfo->ext_listen_period = 0, that means the P2P listen state is not available on listen channel. */
494 if (pwdinfo->ext_listen_period > 0) {
495 RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_period = %d\n", __FUNCTION__, pwdinfo->ext_listen_period);
496
497 if (union_ch != pwdinfo->listen_channel) {
498 rtw_leave_opch(padapter);
499 set_channel_bwmode(padapter, pwdinfo->listen_channel, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
500 }
501
502 rtw_p2p_set_state(pwdinfo, P2P_STATE_LISTEN);
503
504 if (!rtw_mi_check_mlmeinfo_state(padapter, WIFI_FW_AP_STATE)) {
505 val8 = 1;
506 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
507 }
508 /* Todo: To check the value of pwdinfo->ext_listen_period is equal to 0 or not. */
509 _set_timer(&prochinfo->ap_roch_ch_switch_timer, pwdinfo->ext_listen_period);
510 }
511
512 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_LISTEN) ||
513 rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_FAIL) ||
514 (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _FALSE) ||
515 rtw_p2p_chk_state(pwdinfo, P2P_STATE_RX_PROVISION_DIS_REQ)) {
516 /* Now, the driver is in the listen state of P2P mode. */
517 RTW_INFO("[%s] P2P_STATE_IDLE, ext_listen_interval = %d\n", __FUNCTION__, pwdinfo->ext_listen_interval);
518
519 /* Commented by Albert 2012/11/01 */
520 /* If the AP's channel is the same as the listen channel, we should still be in the listen state */
521 /* Other P2P device is still able to find this device out even this device is in the AP's channel. */
522 /* So, configure this device to be able to receive the probe request frame and set it to listen state. */
523 if (union_ch != pwdinfo->listen_channel) {
524
525 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
526 if (!rtw_mi_check_status(padapter, MI_AP_MODE)) {
527 val8 = 0;
528 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
529 }
530 rtw_p2p_set_state(pwdinfo, P2P_STATE_IDLE);
531 rtw_back_opch(padapter);
532 }
533
534 /* Todo: To check the value of pwdinfo->ext_listen_interval is equal to 0 or not. */
535 _set_timer(&prochinfo->ap_roch_ch_switch_timer, pwdinfo->ext_listen_interval);
536
537 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_OK)) {
538 /* The driver had finished the P2P handshake successfully. */
539 val8 = 0;
540 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
541 set_channel_bwmode(padapter, union_ch, union_offset, union_bw);
542 rtw_back_opch(padapter);
543
544 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_PROVISION_DIS_REQ)) {
545 val8 = 1;
546 set_channel_bwmode(padapter, pwdinfo->tx_prov_disc_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
547 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
548 issue_probereq_p2p(padapter, NULL);
549 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
550 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_GONEGO_ING) && pwdinfo->nego_req_info.benable == _TRUE) {
551 val8 = 1;
552 set_channel_bwmode(padapter, pwdinfo->nego_req_info.peer_channel_num[0], HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
553 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
554 issue_probereq_p2p(padapter, NULL);
555 _set_timer(&pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT);
556 } else if (rtw_p2p_chk_state(pwdinfo, P2P_STATE_TX_INVITE_REQ) && pwdinfo->invitereq_info.benable == _TRUE) {
557 /*
558 val8 = 1;
559 set_channel_bwmode(padapter, , HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
560 rtw_hal_set_hwreg(padapter, HW_VAR_MLME_SITESURVEY, (u8 *)(&val8));
561 issue_probereq_p2p(padapter, NULL);
562 _set_timer( &pwdinfo->pre_tx_scan_timer, P2P_TX_PRESCAN_TIMEOUT );
563 */
564 }
565 }
566 #endif /* CONFIG_P2P */
567 } else if (!chk_need_stay_in_cur_chan(padapter)) {
568 set_channel_bwmode(padapter, remain_ch, HAL_PRIME_CHNL_OFFSET_DONT_CARE, CHANNEL_WIDTH_20);
569 }
570 }
571 #endif /* CONFIG_CONCURRENT_MODE */
572
rtw_init_roch_info(_adapter * padapter)573 void rtw_init_roch_info(_adapter *padapter)
574 {
575 struct roch_info *prochinfo = &padapter->rochinfo;
576
577 _rtw_memset(prochinfo, 0x00, sizeof(struct roch_info));
578
579 #ifdef CONFIG_CONCURRENT_MODE
580 rtw_init_timer(&prochinfo->ap_roch_ch_switch_timer, padapter, rtw_ap_roch_ch_switch_timer_process, padapter);
581 #ifdef CONFIG_IOCTL_CFG80211
582 prochinfo->min_home_dur = 1500; /* min duration for traffic, home_time */
583 prochinfo->max_away_dur = 250; /* max acceptable away duration, home_away_time */
584 #endif
585 #endif
586
587 #ifdef CONFIG_IOCTL_CFG80211
588 rtw_init_timer(&prochinfo->remain_on_ch_timer, padapter, rtw_ro_ch_timer_process, padapter);
589 #endif
590 }
591 #endif /* (defined(CONFIG_P2P) && defined(CONFIG_CONCURRENT_MODE)) || defined(CONFIG_IOCTL_CFG80211) */