• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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) */