xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8188fu/hal/hal_mcc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /******************************************************************************
3  *
4  * Copyright(c) 2015 - 2017 Realtek Corporation.
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of version 2 of the GNU General Public License as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13  * more details.
14  *
15  *****************************************************************************/
16 #ifdef CONFIG_MCC_MODE
17 #define _HAL_MCC_C_
18 
19 #include <drv_types.h> /* PADAPTER */
20 #include <rtw_mcc.h> /* mcc structure */
21 #include <hal_data.h> /* HAL_DATA */
22 #include <rtw_pwrctrl.h> /* power control */
23 
24 /*  use for AP/GO + STA/GC case */
25 #define MCC_DURATION_IDX 0 /* druration for station side */
26 #define MCC_TSF_SYNC_OFFSET_IDX 1
27 #define MCC_START_TIME_OFFSET_IDX 2
28 #define MCC_INTERVAL_IDX 3
29 #define MCC_GUARD_OFFSET0_IDX 4
30 #define MCC_GUARD_OFFSET1_IDX 5
31 #define MCC_STOP_THRESHOLD 6
32 #define TU 1024 /* 1 TU equals 1024 microseconds */
33 /* druration, TSF sync offset, start time offset, interval (unit:TU (1024 microseconds))*/
34 u8 mcc_switch_channel_policy_table[][7]={
35 	{20, 50, 40, 100, 0, 0, 30},
36 	{80, 50, 10, 100, 0, 0, 30},
37 	{36, 50, 32, 100, 0, 0, 30},
38 	{30, 50, 35, 100, 0, 0, 30},
39 };
40 
41 const int mcc_max_policy_num = sizeof(mcc_switch_channel_policy_table) /sizeof(u8) /7;
42 
dump_iqk_val_table(PADAPTER padapter)43 static void dump_iqk_val_table(PADAPTER padapter)
44 {
45 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
46 	struct hal_iqk_reg_backup *iqk_reg_backup = pHalData->iqk_reg_backup;
47 	u8 total_rf_path = pHalData->NumTotalRFPath;
48 	u8 rf_path_idx = 0;
49 	u8 backup_chan_idx = 0;
50 	u8 backup_reg_idx = 0;
51 
52 #ifdef CONFIG_MCC_MODE_V2
53 #else
54 
55 	RTW_INFO("=============dump IQK backup table================\n");
56 	for (backup_chan_idx = 0; backup_chan_idx < MAX_IQK_INFO_BACKUP_CHNL_NUM; backup_chan_idx++) {
57 		for (rf_path_idx = 0; rf_path_idx < total_rf_path; rf_path_idx++) {
58 			for(backup_reg_idx = 0; backup_reg_idx < MAX_IQK_INFO_BACKUP_REG_NUM; backup_reg_idx++) {
59 				RTW_INFO("ch:%d. bw:%d. rf path:%d. reg[%d] = 0x%02x \n"
60 						, iqk_reg_backup[backup_chan_idx].central_chnl
61 						, iqk_reg_backup[backup_chan_idx].bw_mode
62 						, rf_path_idx
63 						, backup_reg_idx
64 						, iqk_reg_backup[backup_chan_idx].reg_backup[rf_path_idx][backup_reg_idx]
65 						);
66 			}
67 		}
68 	}
69 	RTW_INFO("=============================================\n");
70 
71 #endif
72 }
73 
rtw_hal_mcc_build_p2p_noa_attr(PADAPTER padapter,u8 * ie,u32 * ie_len)74 static void rtw_hal_mcc_build_p2p_noa_attr(PADAPTER padapter, u8 *ie, u32 *ie_len)
75 {
76 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
77 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
78 	struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
79 	u8 p2p_noa_attr_ie[MAX_P2P_IE_LEN] = {0x00};
80 	u32 p2p_noa_attr_len = 0;
81 	u8 noa_desc_num = 1;
82 	u8 opp_ps = 0; /* Disable OppPS */
83 	u8 noa_count = 255;
84 	u32 noa_duration;
85 	u32 noa_interval;
86 	u8 noa_index = 0;
87 	u8 mcc_policy_idx = 0;
88 
89 	mcc_policy_idx = pmccobjpriv->policy_index;
90 	noa_duration = mcc_switch_channel_policy_table[mcc_policy_idx][MCC_DURATION_IDX] * TU;
91 	noa_interval = mcc_switch_channel_policy_table[mcc_policy_idx][MCC_INTERVAL_IDX] * TU;
92 
93 	/* P2P OUI(4 bytes) */
94 	_rtw_memcpy(p2p_noa_attr_ie, P2P_OUI, 4);
95 	p2p_noa_attr_len = p2p_noa_attr_len + 4;
96 
97 	/* attrute ID(1 byte) */
98 	p2p_noa_attr_ie[p2p_noa_attr_len] = P2P_ATTR_NOA;
99 	p2p_noa_attr_len = p2p_noa_attr_len + 1;
100 
101 	/* attrute length(2 bytes) length = noa_desc_num*13 + 2 */
102 	RTW_PUT_LE16(p2p_noa_attr_ie + p2p_noa_attr_len, (noa_desc_num * 13 + 2));
103 	p2p_noa_attr_len = p2p_noa_attr_len + 2;
104 
105 	/* Index (1 byte) */
106 	p2p_noa_attr_ie[p2p_noa_attr_len] = noa_index;
107 	p2p_noa_attr_len = p2p_noa_attr_len + 1;
108 
109 	/* CTWindow and OppPS Parameters (1 byte) */
110 	p2p_noa_attr_ie[p2p_noa_attr_len] = opp_ps;
111 	p2p_noa_attr_len = p2p_noa_attr_len+ 1;
112 
113 	/* NoA Count (1 byte) */
114 	p2p_noa_attr_ie[p2p_noa_attr_len] = noa_count;
115 	p2p_noa_attr_len = p2p_noa_attr_len + 1;
116 
117 	/* NoA Duration (4 bytes) unit: microseconds */
118 	RTW_PUT_LE32(p2p_noa_attr_ie + p2p_noa_attr_len, noa_duration);
119 	p2p_noa_attr_len = p2p_noa_attr_len + 4;
120 
121 	/* NoA Interval (4 bytes) unit: microseconds */
122 	RTW_PUT_LE32(p2p_noa_attr_ie + p2p_noa_attr_len, noa_interval);
123 	p2p_noa_attr_len = p2p_noa_attr_len + 4;
124 
125 	/* NoA Start Time (4 bytes) unit: microseconds */
126 	RTW_PUT_LE32(p2p_noa_attr_ie + p2p_noa_attr_len, pmccadapriv->noa_start_time);
127 	if (0)
128 		RTW_INFO("indxe:%d, start_time=0x%02x:0x%02x:0x%02x:0x%02x\n"
129 		, noa_index
130 		, p2p_noa_attr_ie[p2p_noa_attr_len]
131 		, p2p_noa_attr_ie[p2p_noa_attr_len + 1]
132 		, p2p_noa_attr_ie[p2p_noa_attr_len + 2]
133 		, p2p_noa_attr_ie[p2p_noa_attr_len + 3]);
134 
135 	p2p_noa_attr_len = p2p_noa_attr_len + 4;
136 	rtw_set_ie(ie, _VENDOR_SPECIFIC_IE_, p2p_noa_attr_len, (u8 *)p2p_noa_attr_ie, ie_len);
137 }
138 
139 
140 /**
141  * rtw_hal_mcc_update_go_p2p_ie - update go p2p ie(add NoA attribute)
142  * @padapter: the adapter to be update go p2p ie
143  */
rtw_hal_mcc_update_go_p2p_ie(PADAPTER padapter)144 static void rtw_hal_mcc_update_go_p2p_ie(PADAPTER padapter)
145 {
146 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
147 	struct mcc_obj_priv *mccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
148 	u8 *pos = NULL;
149 
150 
151 	/* no noa attribute, build it */
152 	if (pmccadapriv->p2p_go_noa_ie_len == 0)
153 		rtw_hal_mcc_build_p2p_noa_attr(padapter, pmccadapriv->p2p_go_noa_ie, &pmccadapriv->p2p_go_noa_ie_len);
154 	else {
155 		/* has noa attribut, modify it */
156 		u32 noa_duration = 0;
157 
158 		/* update index */
159 		pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len - 15;
160 		/* 0~255 */
161 		(*pos) = ((*pos) + 1) % 256;
162 		if (0)
163 			RTW_INFO("indxe:%d\n", (*pos));
164 
165 
166 		/* update duration */
167 		noa_duration = mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_DURATION_IDX] * TU;
168 		pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len - 12;
169 		RTW_PUT_LE32(pos, noa_duration);
170 
171 		/* update start time */
172 		pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len - 4;
173 		RTW_PUT_LE32(pos, pmccadapriv->noa_start_time);
174 		if (0)
175 			RTW_INFO("start_time=0x%02x:0x%02x:0x%02x:0x%02x\n"
176 			, ((u8*)(pos))[0]
177 			, ((u8*)(pos))[1]
178 			, ((u8*)(pos))[2]
179 			, ((u8*)(pos))[3]);
180 
181 	}
182 
183 	if (0) {
184 		RTW_INFO("p2p_go_noa_ie_len:%d\n", pmccadapriv->p2p_go_noa_ie_len);
185 		RTW_INFO_DUMP("\n", pmccadapriv->p2p_go_noa_ie, pmccadapriv->p2p_go_noa_ie_len);
186 	}
187 	update_beacon(padapter, _VENDOR_SPECIFIC_IE_, P2P_OUI, _TRUE);
188 }
189 
190 /**
191  * rtw_hal_mcc_remove_go_p2p_ie - remove go p2p ie(add NoA attribute)
192  * @padapter: the adapter to be update go p2p ie
193  */
rtw_hal_mcc_remove_go_p2p_ie(PADAPTER padapter)194 static void rtw_hal_mcc_remove_go_p2p_ie(PADAPTER padapter)
195 {
196 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
197 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
198 
199 	/* chech has noa ie or not */
200 	if (pmccadapriv->p2p_go_noa_ie_len == 0)
201 		return;
202 
203 	pmccadapriv->p2p_go_noa_ie_len = 0;
204 	update_beacon(padapter, _VENDOR_SPECIFIC_IE_, P2P_OUI, _TRUE);
205 }
206 
207 /* restore IQK value for all interface */
rtw_hal_mcc_restore_iqk_val(PADAPTER padapter)208 void rtw_hal_mcc_restore_iqk_val(PADAPTER padapter)
209 {
210 	u8 take_care_iqk = _FALSE;
211 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
212 	_adapter *iface = NULL;
213 	struct mcc_adapter_priv *mccadapriv = NULL;
214 	u8 i = 0;
215 
216 	rtw_hal_get_hwreg(padapter, HW_VAR_CH_SW_NEED_TO_TAKE_CARE_IQK_INFO, &take_care_iqk);
217 	if (take_care_iqk == _TRUE && MCC_EN(padapter)) {
218 		for (i = 0; i < dvobj->iface_nums; i++) {
219 			iface = dvobj->padapters[i];
220 			if (iface == NULL)
221 				continue;
222 
223 			mccadapriv = &iface->mcc_adapterpriv;
224 			if (mccadapriv->role == MCC_ROLE_MAX)
225 				continue;
226 
227 			rtw_hal_ch_sw_iqk_info_restore(iface, CH_SW_USE_CASE_MCC);
228 		}
229 	}
230 
231 	if (0)
232 		dump_iqk_val_table(padapter);
233 }
234 
rtw_hal_check_mcc_status(PADAPTER padapter,u8 mcc_status)235 u8 rtw_hal_check_mcc_status(PADAPTER padapter, u8 mcc_status)
236 {
237 	struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
238 
239 	if (pmccobjpriv->mcc_status & (mcc_status))
240 		return _TRUE;
241 	else
242 		return _FALSE;
243 }
244 
rtw_hal_set_mcc_status(PADAPTER padapter,u8 mcc_status)245 void rtw_hal_set_mcc_status(PADAPTER padapter, u8 mcc_status)
246 {
247 	struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
248 
249 	pmccobjpriv->mcc_status |= (mcc_status);
250 }
251 
rtw_hal_clear_mcc_status(PADAPTER padapter,u8 mcc_status)252 void rtw_hal_clear_mcc_status(PADAPTER padapter, u8 mcc_status)
253 {
254 	struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
255 
256 	pmccobjpriv->mcc_status &= (~mcc_status);
257 }
258 
rtw_hal_mcc_update_policy_table(PADAPTER adapter)259 static void rtw_hal_mcc_update_policy_table(PADAPTER adapter)
260 {
261 	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
262 	struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
263 	u8 mcc_duration = mccobjpriv->duration;
264 	s8 mcc_policy_idx = mccobjpriv->policy_index;
265 	u8 interval = mcc_switch_channel_policy_table[mcc_policy_idx][MCC_INTERVAL_IDX];
266 	u8 new_mcc_duration_time = 0;
267 	u8 new_starttime_offset = 0;
268 
269 	/* convert % to ms */
270 	new_mcc_duration_time = mcc_duration * interval / 100;
271 
272 	/* start time offset = (interval - duration time)/2 */
273 	new_starttime_offset = (interval - new_mcc_duration_time) >> 1;
274 
275 	/* update modified parameters */
276 	mcc_switch_channel_policy_table[mcc_policy_idx][MCC_DURATION_IDX]
277 		= new_mcc_duration_time;
278 
279 	mcc_switch_channel_policy_table[mcc_policy_idx][MCC_START_TIME_OFFSET_IDX]
280 		= new_starttime_offset;
281 
282 
283 }
284 
rtw_hal_config_mcc_switch_channel_setting(PADAPTER padapter)285 static void rtw_hal_config_mcc_switch_channel_setting(PADAPTER padapter)
286 {
287 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
288 	struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
289 	struct registry_priv *registry_par = &padapter->registrypriv;
290 	u8 mcc_duration = 0;
291 	s8 mcc_policy_idx = 0;
292 
293 	mcc_policy_idx = registry_par->rtw_mcc_policy_table_idx;
294 	mcc_duration = mccobjpriv->duration;
295 
296 	if (mcc_policy_idx < 0 || mcc_policy_idx >= mcc_max_policy_num) {
297 		mccobjpriv->policy_index = 0;
298 		RTW_INFO("[MCC] can't find table(%d), use default policy(%d)\n",
299 			mcc_policy_idx, mccobjpriv->policy_index);
300 	} else
301 		mccobjpriv->policy_index = mcc_policy_idx;
302 
303 	/* convert % to time */
304 	if (mcc_duration != 0)
305 		rtw_hal_mcc_update_policy_table(padapter);
306 
307 	RTW_INFO("[MCC] policy(%d): %d,%d,%d,%d,%d,%d\n"
308 		, mccobjpriv->policy_index
309 		, mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_DURATION_IDX]
310 		, mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_TSF_SYNC_OFFSET_IDX]
311 		, mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_START_TIME_OFFSET_IDX]
312 		, mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_INTERVAL_IDX]
313 		, mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_GUARD_OFFSET0_IDX]
314 		, mcc_switch_channel_policy_table[mccobjpriv->policy_index][MCC_GUARD_OFFSET1_IDX]);
315 
316 }
317 
rtw_hal_mcc_assign_tx_threshold(PADAPTER padapter)318 static void rtw_hal_mcc_assign_tx_threshold(PADAPTER padapter)
319 {
320 	struct registry_priv *preg = &padapter->registrypriv;
321 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
322 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
323 
324 	switch (pmccadapriv->role) {
325 	case MCC_ROLE_STA:
326 	case MCC_ROLE_GC:
327 		switch (pmlmeext->cur_bwmode) {
328 		case CHANNEL_WIDTH_20:
329 			/*
330 			* target tx byte(bytes) = target tx tp(Mbits/sec) * 1024 * 1024 / 8 * (duration(ms) / 1024)
331 			*					= target tx tp(Mbits/sec) * 128 * duration(ms)
332 			* note:
333 			* target tx tp(Mbits/sec) * 1024 * 1024 / 8 ==> Mbits to bytes
334 			* duration(ms) / 1024 ==> msec to sec
335 			*/
336 			pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_sta_bw20_target_tx_tp * 128 * pmccadapriv->mcc_duration;
337 			break;
338 		case CHANNEL_WIDTH_40:
339 			pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_sta_bw40_target_tx_tp * 128 * pmccadapriv->mcc_duration;
340 			break;
341 		case CHANNEL_WIDTH_80:
342 			pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_sta_bw80_target_tx_tp * 128 * pmccadapriv->mcc_duration;
343 			break;
344 		case CHANNEL_WIDTH_160:
345 		case CHANNEL_WIDTH_80_80:
346 			RTW_INFO(FUNC_ADPT_FMT": not support bwmode = %d\n"
347 				, FUNC_ADPT_ARG(padapter), pmlmeext->cur_bwmode);
348 			break;
349 		}
350 		break;
351 	case MCC_ROLE_AP:
352 	case MCC_ROLE_GO:
353 		switch (pmlmeext->cur_bwmode) {
354 		case CHANNEL_WIDTH_20:
355 			pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_ap_bw20_target_tx_tp * 128 * pmccadapriv->mcc_duration;
356 			break;
357 		case CHANNEL_WIDTH_40:
358 			pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_ap_bw40_target_tx_tp * 128 * pmccadapriv->mcc_duration;
359 			break;
360 		case CHANNEL_WIDTH_80:
361 			pmccadapriv->mcc_target_tx_bytes_to_port = preg->rtw_mcc_ap_bw80_target_tx_tp * 128 * pmccadapriv->mcc_duration;
362 			break;
363 		case CHANNEL_WIDTH_160:
364 		case CHANNEL_WIDTH_80_80:
365 			RTW_INFO(FUNC_ADPT_FMT": not support bwmode = %d\n"
366 				, FUNC_ADPT_ARG(padapter), pmlmeext->cur_bwmode);
367 			break;
368 		}
369 		break;
370 	default:
371 		RTW_INFO(FUNC_ADPT_FMT": unknown role = %d\n"
372 			, FUNC_ADPT_ARG(padapter), pmccadapriv->role);
373 		break;
374 	}
375 }
376 
377 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
mcc_cfg_phdym_rf_ch(_adapter * adapter)378 static void mcc_cfg_phdym_rf_ch (_adapter *adapter)
379 {
380 		struct mcc_adapter_priv *mccadapriv = &adapter->mcc_adapterpriv;
381 		struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
382 		HAL_DATA_TYPE *hal = GET_HAL_DATA(adapter);
383 		struct dm_struct *dm = &hal->odmpriv;
384 		struct _phydm_mcc_dm_ *mcc_dm = &dm->mcc_dm;
385 		u8 order = 0;
386 
387 		set_channel_bwmode(adapter, mlmeext->cur_channel, mlmeext->cur_ch_offset, mlmeext->cur_bwmode);
388 		order = mccadapriv->order;
389 		mcc_dm->mcc_rf_channel[order] = phy_query_rf_reg(adapter, RF_PATH_A, 0x18, 0xffffffff);
390 }
391 
mcc_cfg_phdym_update_macid(_adapter * adapter,u8 add,u8 mac_id)392 static void mcc_cfg_phdym_update_macid (_adapter *adapter, u8 add, u8 mac_id)
393 {
394 		struct mcc_adapter_priv *mccadapriv = &adapter->mcc_adapterpriv;
395 		struct mlme_ext_priv *mlmeext = &adapter->mlmeextpriv;
396 		HAL_DATA_TYPE *hal = GET_HAL_DATA(adapter);
397 		struct dm_struct *dm = &hal->odmpriv;
398 		struct _phydm_mcc_dm_ *mcc_dm = &dm->mcc_dm;
399 		u8 order = 0, i = 0;
400 
401 		order = mccadapriv->order;
402 		if (add) {
403 			for (i = 0; i < NUM_STA; i++) {
404 				if (mcc_dm->sta_macid[order][i] == 0xff) {
405 					mcc_dm->sta_macid[order][i] = mac_id;
406 					break;
407 				}
408 			}
409 		} else {
410 			for (i = 0; i < NUM_STA; i++) {
411 				if (mcc_dm->sta_macid[order][i] == mac_id) {
412 					mcc_dm->sta_macid[order][i] = 0xff;
413 					break;
414 				}
415 			}
416 		}
417 
418 
419 }
420 
mcc_cfg_phdym_start(_adapter * adapter,u8 start)421 static void mcc_cfg_phdym_start(_adapter *adapter, u8 start)
422 {
423 	struct dvobj_priv *dvobj;
424 	struct mcc_obj_priv *mccobjpriv;
425 	HAL_DATA_TYPE *hal;
426 	struct dm_struct *dm;
427 	struct _phydm_mcc_dm_ *mcc_dm;
428 	u8 rfk_forbidden = _TRUE;
429 	u8 i = 0, j = 0;
430 
431 	dvobj = adapter_to_dvobj(adapter);
432 	mccobjpriv = adapter_to_mccobjpriv(adapter);
433 	hal = GET_HAL_DATA(adapter);
434 	dm = &hal->odmpriv;
435 	mcc_dm = &dm->mcc_dm;
436 
437 	if (start) {
438 		#ifdef CONFIG_MCC_PHYDM_OFFLOAD
439 		mcc_dm->mcc_status = mccobjpriv->mcc_phydm_offload;
440 		#endif
441 
442 		rfk_forbidden = _TRUE;
443 		halrf_cmn_info_set(dm, HALRF_CMNINFO_RFK_FORBIDDEN, rfk_forbidden);
444 	} else {
445 		rfk_forbidden = _FALSE;
446 		halrf_cmn_info_set(dm, HALRF_CMNINFO_RFK_FORBIDDEN, rfk_forbidden);
447 
448 		#ifdef CONFIG_MCC_PHYDM_OFFLOAD
449 		for(i = 0; i < MAX_MCC_NUM; i ++) {
450 			for(j = 0; j < NUM_STA; j ++) {
451 				if (mcc_dm->sta_macid[i][j] != 0xff)
452 					/* clear all used value for mcc stop */
453 					/* do nothing for mcc start due to phydm will init to 0xff */
454 					mcc_dm->sta_macid[i][j] = 0xff;
455 			}
456 			mcc_dm->mcc_rf_channel[i] = 0xff;
457 		}
458 		mcc_dm->mcc_status = 0;
459 		#endif
460 	}
461 }
462 
mcc_cfg_phdym_dump(_adapter * adapter,void * sel)463 static void mcc_cfg_phdym_dump(_adapter *adapter, void *sel)
464 {
465 	HAL_DATA_TYPE *hal;
466 	struct dm_struct *dm;
467 	struct _phydm_mcc_dm_ *mcc_dm;
468 	u8 rfk_forbidden = _TRUE;
469 	u8 i = 0, j = 0;
470 
471 
472 	hal = GET_HAL_DATA(adapter);
473 	dm = &hal->odmpriv;
474 	mcc_dm = &dm->mcc_dm;
475 
476 	rfk_forbidden = halrf_cmn_info_get(dm, HALRF_CMNINFO_RFK_FORBIDDEN);
477 	RTW_PRINT_SEL(sel, "dump mcc dm info\n");
478 	RTW_PRINT_SEL(sel, "mcc_status=%d\n", mcc_dm->mcc_status);
479 	RTW_PRINT_SEL(sel, "rfk_forbidden=%d\n", rfk_forbidden);
480 	for(i = 0; i < MAX_MCC_NUM; i ++) {
481 
482 		if (mcc_dm->mcc_rf_channel[i] != 0xff)
483 			RTW_PRINT_SEL(sel, "mcc_dm->mcc_rf_channel[%d] = 0x%02x\n", i, mcc_dm->mcc_rf_channel[i]);
484 
485 		for(j = 0; j < NUM_STA; j ++) {
486 			if (mcc_dm->sta_macid[i][j] != 0xff)
487 				RTW_PRINT_SEL(sel, "mcc_dm->sta_macid[%d][%d] = %d\n", i, j, mcc_dm->sta_macid[i][j]);
488 		}
489 	}
490 }
491 
mcc_cfg_phdym_offload(_adapter * adapter,u8 enable)492 static void mcc_cfg_phdym_offload(_adapter *adapter, u8 enable)
493 {
494 	struct mcc_obj_priv *mccobjpriv = adapter_to_mccobjpriv(adapter);
495 	_adapter *iface = NULL;
496 	struct mcc_adapter_priv *mccadapriv = NULL;
497 	HAL_DATA_TYPE *hal = NULL;
498 	struct dm_struct *dm = NULL;
499 	struct _phydm_mcc_dm_ *mcc_dm = NULL;
500 	struct sta_priv *stapriv = NULL;
501 	struct sta_info *sta = NULL;
502 	struct wlan_network *cur_network = NULL;
503 	_irqL irqL;
504 	_list	*head = NULL, *list = NULL;
505 	u8 i = 0;
506 
507 
508 	hal = GET_HAL_DATA(adapter);
509 	dm = &hal->odmpriv;
510 	mcc_dm = &dm->mcc_dm;
511 
512 	/* due to phydm will rst related date, driver must set related data */
513 	if (enable) {
514 		for (i = 0; i < MAX_MCC_NUM; i++) {
515 			iface = mccobjpriv->iface[i];
516 			if (!iface)
517 				continue;
518 			stapriv = &iface->stapriv;
519 			mccadapriv = &iface->mcc_adapterpriv;
520 			switch (mccadapriv->role) {
521 			case MCC_ROLE_STA:
522 			case MCC_ROLE_GC:
523 				cur_network = &iface->mlmepriv.cur_network;
524 				sta = rtw_get_stainfo(stapriv, cur_network->network.MacAddress);
525 				if (sta)
526 					mcc_cfg_phdym_update_macid(iface, _TRUE, sta->cmn.mac_id);
527 				break;
528 			case MCC_ROLE_AP:
529 			case MCC_ROLE_GO:
530 				_enter_critical_bh(&stapriv->asoc_list_lock, &irqL);
531 
532 				head = &stapriv->asoc_list;
533 				list = get_next(head);
534 
535 				while ((rtw_end_of_queue_search(head, list)) == _FALSE) {
536 					sta = LIST_CONTAINOR(list, struct sta_info, asoc_list);
537 					list = get_next(list);
538 					mcc_cfg_phdym_update_macid(iface, _TRUE, sta->cmn.mac_id);
539 				}
540 
541 				_exit_critical_bh(&stapriv->asoc_list_lock, &irqL);
542 				break;
543 			default:
544 				RTW_INFO("Unknown role\n");
545 				rtw_warn_on(1);
546 				break;
547 			}
548 
549 		}
550 	}
551 
552 	mcc_dm->mcc_status = enable;
553 }
554 
rtw_hal_mcc_cfg_phydm(_adapter * adapter,enum mcc_cfg_phydm_ops ops,void * data)555 static void rtw_hal_mcc_cfg_phydm (_adapter *adapter, enum mcc_cfg_phydm_ops ops, void *data)
556 {
557 	switch (ops) {
558 	case MCC_CFG_PHYDM_OFFLOAD:
559 		mcc_cfg_phdym_offload(adapter, *(u8 *)data);
560 		break;
561 	case MCC_CFG_PHYDM_RF_CH:
562 		mcc_cfg_phdym_rf_ch(adapter);
563 		break;
564 	case MCC_CFG_PHYDM_ADD_CLIENT:
565 		mcc_cfg_phdym_update_macid(adapter, _TRUE, *(u8 *)data);
566 		break;
567 	case MCC_CFG_PHYDM_REMOVE_CLIENT:
568 		mcc_cfg_phdym_update_macid(adapter, _FALSE, *(u8 *)data);
569 		break;
570 	case MCC_CFG_PHYDM_START:
571 		mcc_cfg_phdym_start(adapter, _TRUE);
572 		break;
573 	case MCC_CFG_PHYDM_STOP:
574 		mcc_cfg_phdym_start(adapter, _FALSE);
575 		break;
576 	case MCC_CFG_PHYDM_DUMP:
577 		mcc_cfg_phdym_dump(adapter, data);
578 		break;
579 	case MCC_CFG_PHYDM_MAX:
580 	default:
581 		RTW_ERR("[MCC] rtw_hal_mcc_cfg_phydm ops error (%d)\n", ops);
582 		break;
583 
584 	}
585 }
586 #endif
587 
rtw_hal_config_mcc_role_setting(PADAPTER padapter,u8 order)588 static void rtw_hal_config_mcc_role_setting(PADAPTER padapter, u8 order)
589 {
590 	struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(padapter);
591 	struct mcc_obj_priv *pmccobjpriv = &(pdvobjpriv->mcc_objpriv);
592 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
593 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
594 	struct wlan_network *cur_network = &(pmlmepriv->cur_network);
595 	struct sta_priv *pstapriv = &padapter->stapriv;
596 	struct sta_info *psta = NULL;
597 	struct registry_priv *preg = &padapter->registrypriv;
598 	_irqL irqL;
599 	_list	*phead =NULL, *plist = NULL;
600 	u8 policy_index = 0;
601 	u8 mcc_duration = 0;
602 	u8 mcc_interval = 0;
603 	u8 starting_ap_num = DEV_AP_STARTING_NUM(pdvobjpriv);
604 	u8 ap_num = DEV_AP_NUM(pdvobjpriv);
605 
606 	policy_index = pmccobjpriv->policy_index;
607 	mcc_duration = mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_DURATION_IDX]
608 		- mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_GUARD_OFFSET0_IDX]
609 			- mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_GUARD_OFFSET1_IDX];
610 	mcc_interval = mcc_switch_channel_policy_table[pmccobjpriv->policy_index][MCC_INTERVAL_IDX];
611 
612 	if (starting_ap_num == 0 && ap_num == 0) {
613 		pmccadapriv->order = order;
614 
615 		if (pmccadapriv->order == 0) {
616 			/* setting is smiliar to GO/AP */
617 			/* pmccadapriv->mcc_duration = mcc_interval - mcc_duration;*/
618 			pmccadapriv->mgmt_queue_macid = MCC_ROLE_SOFTAP_GO_MGMT_QUEUE_MACID;
619 		} else if (pmccadapriv->order == 1) {
620 			/* pmccadapriv->mcc_duration = mcc_duration; */
621 			pmccadapriv->mgmt_queue_macid = MCC_ROLE_STA_GC_MGMT_QUEUE_MACID;
622 		} else {
623 			RTW_INFO("[MCC] not support >= 3 interface\n");
624 			rtw_warn_on(1);
625 		}
626 
627 		rtw_hal_mcc_assign_tx_threshold(padapter);
628 
629 		psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
630 		if (psta) {
631 			/* combine AP/GO macid and mgmt queue macid to bitmap */
632 			pmccadapriv->mcc_macid_bitmap = BIT(psta->cmn.mac_id) | BIT(pmccadapriv->mgmt_queue_macid);
633 			#ifdef CONFIG_MCC_PHYDM_OFFLOAD
634 			rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_ADD_CLIENT, &psta->cmn.mac_id);
635 			#endif
636 		} else {
637 			RTW_INFO(FUNC_ADPT_FMT":AP/GO station info is NULL\n", FUNC_ADPT_ARG(padapter));
638 			rtw_warn_on(1);
639 		}
640 	} else {
641 		/* GO/AP is 1nd order  GC/STA is 2nd order */
642 		switch (pmccadapriv->role) {
643 		case MCC_ROLE_STA:
644 		case MCC_ROLE_GC:
645 			pmccadapriv->order = 1;
646 			pmccadapriv->mcc_duration = mcc_duration;
647 
648 			rtw_hal_mcc_assign_tx_threshold(padapter);
649 			/* assign used mac to avoid affecting RA */
650 			pmccadapriv->mgmt_queue_macid = MCC_ROLE_STA_GC_MGMT_QUEUE_MACID;
651 
652 			psta = rtw_get_stainfo(pstapriv, cur_network->network.MacAddress);
653 			if (psta) {
654 				/* combine AP/GO macid and mgmt queue macid to bitmap */
655 				pmccadapriv->mcc_macid_bitmap = BIT(psta->cmn.mac_id) | BIT(pmccadapriv->mgmt_queue_macid);
656 				#ifdef CONFIG_MCC_PHYDM_OFFLOAD
657 				rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_ADD_CLIENT, &psta->cmn.mac_id);
658 				#endif
659 			} else {
660 				RTW_INFO(FUNC_ADPT_FMT":AP/GO station info is NULL\n", FUNC_ADPT_ARG(padapter));
661 				rtw_warn_on(1);
662 			}
663 			break;
664 		case MCC_ROLE_AP:
665 		case MCC_ROLE_GO:
666 			pmccadapriv->order = 0;
667 			/* total druation value equals interval */
668 			pmccadapriv->mcc_duration = mcc_interval - mcc_duration;
669 			pmccadapriv->p2p_go_noa_ie_len = 0; /* not NoA attribute at init time */
670 
671 			rtw_hal_mcc_assign_tx_threshold(padapter);
672 
673 			_enter_critical_bh(&pstapriv->asoc_list_lock, &irqL);
674 
675 			phead = &pstapriv->asoc_list;
676 			plist = get_next(phead);
677 			pmccadapriv->mcc_macid_bitmap = 0;
678 
679 			while ((rtw_end_of_queue_search(phead, plist)) == _FALSE) {
680 				psta = LIST_CONTAINOR(plist, struct sta_info, asoc_list);
681 				plist = get_next(plist);
682 				pmccadapriv->mcc_macid_bitmap |= BIT(psta->cmn.mac_id);
683 				#ifdef CONFIG_MCC_PHYDM_OFFLOAD
684 				rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_ADD_CLIENT, &psta->cmn.mac_id);
685 				#endif
686 			}
687 
688 			_exit_critical_bh(&pstapriv->asoc_list_lock, &irqL);
689 
690 			psta = rtw_get_bcmc_stainfo(padapter);
691 
692 			if (psta != NULL)
693 				pmccadapriv->mgmt_queue_macid = psta->cmn.mac_id;
694 			else {
695 				pmccadapriv->mgmt_queue_macid = MCC_ROLE_SOFTAP_GO_MGMT_QUEUE_MACID;
696 				RTW_INFO(FUNC_ADPT_FMT":bcmc station is NULL, use macid %d\n"
697 					, FUNC_ADPT_ARG(padapter), pmccadapriv->mgmt_queue_macid);
698 			}
699 
700 			/* combine client macid and mgmt queue macid to bitmap */
701 			pmccadapriv->mcc_macid_bitmap |= BIT(pmccadapriv->mgmt_queue_macid);
702 			break;
703 		default:
704 			RTW_INFO("Unknown role\n");
705 			rtw_warn_on(1);
706 			break;
707 		}
708 
709 	}
710 
711 	/* setting Null data parameters */
712 	if (pmccadapriv->role == MCC_ROLE_STA) {
713 			pmccadapriv->null_early = 3;
714 			pmccadapriv->null_rty_num= 5;
715 	} else if (pmccadapriv->role == MCC_ROLE_GC) {
716 			pmccadapriv->null_early = 2;
717 			pmccadapriv->null_rty_num= 5;
718 	} else {
719 			pmccadapriv->null_early = 0;
720 			pmccadapriv->null_rty_num= 0;
721 	}
722 
723 	RTW_INFO("********* "FUNC_ADPT_FMT" *********\n", FUNC_ADPT_ARG(padapter));
724 	RTW_INFO("order:%d\n", pmccadapriv->order);
725 	RTW_INFO("role:%d\n", pmccadapriv->role);
726 	RTW_INFO("mcc duration:%d\n", pmccadapriv->mcc_duration);
727 	RTW_INFO("null_early:%d\n", pmccadapriv->null_early);
728 	RTW_INFO("null_rty_num:%d\n", pmccadapriv->null_rty_num);
729 	RTW_INFO("mgmt queue macid:%d\n", pmccadapriv->mgmt_queue_macid);
730 	RTW_INFO("bitmap:0x%02x\n", pmccadapriv->mcc_macid_bitmap);
731 	RTW_INFO("target tx bytes:%d\n", pmccadapriv->mcc_target_tx_bytes_to_port);
732 	RTW_INFO("**********************************\n");
733 
734 	pmccobjpriv->iface[pmccadapriv->order] = padapter;
735 	#ifdef CONFIG_MCC_PHYDM_OFFLOAD
736 	rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_RF_CH, NULL);
737 	#endif
738 
739 }
740 
rtw_hal_mcc_rqt_tsf(PADAPTER padapter,u64 * out_tsf)741 static void rtw_hal_mcc_rqt_tsf(PADAPTER padapter, u64 *out_tsf)
742 {
743 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
744 	struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
745 	PADAPTER order0_iface = NULL;
746 	PADAPTER order1_iface = NULL;
747 	struct submit_ctx *tsf_req_sctx = NULL;
748 	enum _hw_port tsfx = MAX_HW_PORT;
749 	enum _hw_port tsfy = MAX_HW_PORT;
750 	u8 cmd[H2C_MCC_RQT_TSF_LEN] = {0};
751 
752 	_enter_critical_mutex(&mccobjpriv->mcc_tsf_req_mutex, NULL);
753 
754 	order0_iface = mccobjpriv->iface[0];
755 	order1_iface = mccobjpriv->iface[1];
756 
757 	tsf_req_sctx = &mccobjpriv->mcc_tsf_req_sctx;
758 	rtw_sctx_init(tsf_req_sctx, MCC_EXPIRE_TIME);
759 	mccobjpriv->mcc_tsf_req_sctx_order = 0;
760 	tsfx = rtw_hal_get_port(order0_iface);
761 	tsfy = rtw_hal_get_port(order1_iface);
762 
763 	SET_H2CCMD_MCC_RQT_TSFX(cmd, tsfx);
764 	SET_H2CCMD_MCC_RQT_TSFY(cmd, tsfy);
765 
766 	rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_RQT_TSF, H2C_MCC_RQT_TSF_LEN, cmd);
767 
768 	if (!rtw_sctx_wait(tsf_req_sctx, __func__))
769 		RTW_INFO(FUNC_ADPT_FMT": wait for mcc tsf req C2H time out\n", FUNC_ADPT_ARG(padapter));
770 
771 	if (tsf_req_sctx->status  == RTW_SCTX_DONE_SUCCESS && out_tsf != NULL) {
772 		out_tsf[0] = order0_iface->mcc_adapterpriv.tsf;
773 		out_tsf[1] = order1_iface->mcc_adapterpriv.tsf;
774 	}
775 
776 
777 	_exit_critical_mutex(&mccobjpriv->mcc_tsf_req_mutex, NULL);
778 }
779 
rtw_hal_mcc_check_start_time_is_valid(PADAPTER padapter,u8 case_num,u32 tsfdiff,s8 * upper_bound_0,s8 * lower_bound_0,s8 * upper_bound_1,s8 * lower_bound_1)780 static u8 rtw_hal_mcc_check_start_time_is_valid(PADAPTER padapter, u8 case_num,
781 	u32 tsfdiff, s8 *upper_bound_0, s8 *lower_bound_0, s8 *upper_bound_1, s8 *lower_bound_1)
782 {
783 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
784 	struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
785 	u8 duration_0 = 0, duration_1 = 0;
786 	s8 final_upper_bound = 0, final_lower_bound = 0;
787 	u8 intersection =  _FALSE;
788 	u8 min_start_time = 5;
789 	u8 max_start_time = 95;
790 
791 	duration_0 = mccobjpriv->iface[0]->mcc_adapterpriv.mcc_duration;
792 	duration_1 = mccobjpriv->iface[1]->mcc_adapterpriv.mcc_duration;
793 
794 	switch(case_num) {
795 	case 1:
796 		*upper_bound_0 = tsfdiff;
797 		*lower_bound_0 = tsfdiff - duration_1;
798 		*upper_bound_1 = 150 - duration_1;
799 		*lower_bound_1= 0;
800 		break;
801 	case 2:
802 		*upper_bound_0 = tsfdiff + 100;
803 		*lower_bound_0 = tsfdiff + 100 - duration_1;
804 		*upper_bound_1 = 150 - duration_1;
805 		*lower_bound_1= 0;
806 		break;
807 	case 3:
808 		*upper_bound_0 = tsfdiff + 50;
809 		*lower_bound_0 = tsfdiff + 50 - duration_1;
810 		*upper_bound_1 = 150 - duration_1;
811 		*lower_bound_1= 0;
812 		break;
813 	case 4:
814 		*upper_bound_0 = tsfdiff;
815 		*lower_bound_0 = tsfdiff - duration_1;
816 		*upper_bound_1 = 150 - duration_1;
817 		*lower_bound_1= 0;
818 		break;
819 	case 5:
820 		*upper_bound_0 = 200 - tsfdiff;
821 		*lower_bound_0 = 200 - tsfdiff - duration_1;
822 		*upper_bound_1 = 150 - duration_1;
823 		*lower_bound_1= 0;
824 		break;
825 	case 6:
826 		*upper_bound_0 = tsfdiff - 50;
827 		*lower_bound_0 = tsfdiff - 50 - duration_1;
828 		*upper_bound_1 = 150 - duration_1;
829 		*lower_bound_1= 0;
830 		break;
831 	default:
832 		RTW_ERR("[MCC] %s: error case number(%d\n)", __func__, case_num);
833 	}
834 
835 
836 	/* check Intersection or not */
837 	if ((*lower_bound_1 >= *upper_bound_0) ||
838 		(*lower_bound_0 >= *upper_bound_1))
839 		intersection = _FALSE;
840 	else
841 		intersection = _TRUE;
842 
843 	if (intersection) {
844 		if (*upper_bound_0 > *upper_bound_1)
845 			final_upper_bound = *upper_bound_1;
846 		else
847 			final_upper_bound = *upper_bound_0;
848 
849 		if (*lower_bound_0 > *lower_bound_1)
850 			final_lower_bound = *lower_bound_0;
851 		else
852 			final_lower_bound = *lower_bound_1;
853 
854 		mccobjpriv->start_time = (final_lower_bound + final_upper_bound) / 2;
855 
856 		/* check start time less than 5ms, request by Pablo@SD1 */
857 		if (mccobjpriv->start_time <= min_start_time) {
858 			mccobjpriv->start_time = 6;
859 			if (mccobjpriv->start_time < final_lower_bound && mccobjpriv->start_time > final_upper_bound) {
860 				intersection = _FALSE;
861 				goto exit;
862 			}
863 		}
864 
865 		/* check start time less than 95ms */
866 		if (mccobjpriv->start_time >= max_start_time) {
867 			mccobjpriv->start_time = 90;
868 			if (mccobjpriv->start_time < final_lower_bound && mccobjpriv->start_time > final_upper_bound) {
869 				intersection = _FALSE;
870 				goto exit;
871 			}
872 		}
873 	}
874 
875 exit:
876 	return intersection;
877 }
878 
rtw_hal_mcc_decide_duration(PADAPTER padapter)879 static void rtw_hal_mcc_decide_duration(PADAPTER padapter)
880 {
881 	struct registry_priv *registry_par = &padapter->registrypriv;
882 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
883 	struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
884 	struct mcc_adapter_priv *mccadapriv = NULL, *mccadapriv_order0 = NULL, *mccadapriv_order1 = NULL;
885 	_adapter *iface = NULL, *iface_order0 = NULL,  *iface_order1 = NULL;
886 	u8 duration = 0, i = 0, duration_time;
887 	u8 mcc_interval = 150;
888 
889 	iface_order0 = mccobjpriv->iface[0];
890 	iface_order1 = mccobjpriv->iface[1];
891 	mccadapriv_order0 = &iface_order0->mcc_adapterpriv;
892 	mccadapriv_order1 = &iface_order1->mcc_adapterpriv;
893 
894 	if (mccobjpriv->duration == 0) {
895 		/* default */
896 		duration = 30;/*(%)*/
897 		RTW_INFO("%s: mccobjpriv->duration=0, use default value(%d)\n",
898 			__FUNCTION__, duration);
899 	} else {
900 		duration = mccobjpriv->duration;/*(%)*/
901 		RTW_INFO("%s: mccobjpriv->duration=%d\n",
902 			__FUNCTION__, duration);
903 	}
904 
905 	mccobjpriv->interval = mcc_interval;
906 	mccobjpriv->mcc_stop_threshold = 2000 * 4 / 300 - 6;
907 	/* convert % to ms, for primary adapter */
908 	duration_time = mccobjpriv->interval * duration / 100;
909 
910 	for (i = 0; i < dvobj->iface_nums; i++) {
911 		iface = dvobj->padapters[i];
912 
913 		if (!iface)
914 			continue;
915 
916 		mccadapriv = &iface->mcc_adapterpriv;
917 		if (mccadapriv->role == MCC_ROLE_MAX)
918 			continue;
919 
920 		if (is_primary_adapter(iface))
921 			mccadapriv->mcc_duration = duration_time;
922 		else
923 			mccadapriv->mcc_duration = mccobjpriv->interval - duration_time;
924 	}
925 
926 	RTW_INFO("[MCC]"  FUNC_ADPT_FMT " order 0 duration=%d\n", FUNC_ADPT_ARG(iface_order0), mccadapriv_order0->mcc_duration);
927 	RTW_INFO("[MCC]"  FUNC_ADPT_FMT " order 1 duration=%d\n", FUNC_ADPT_ARG(iface_order1), mccadapriv_order1->mcc_duration);
928 }
929 
rtw_hal_mcc_update_timing_parameters(PADAPTER padapter,u8 force_update)930 static u8 rtw_hal_mcc_update_timing_parameters(PADAPTER padapter, u8 force_update)
931 {
932 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
933 	u8 need_update = _FALSE;
934 	u8 starting_ap_num = DEV_AP_STARTING_NUM(dvobj);
935 	u8 ap_num = DEV_AP_NUM(dvobj);
936 
937 
938 	/* for STA+STA, modify policy table */
939 	if (starting_ap_num == 0 && ap_num == 0) {
940 		struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
941 		struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
942 		struct mcc_adapter_priv *pmccadapriv = NULL;
943 		_adapter *iface = NULL;
944 		u64 tsf[MAX_MCC_NUM] = {0};
945 		u64 tsf0 = 0, tsf1 = 0;
946 		u32 beaconperiod_0 = 0, beaconperiod_1 = 0, tsfdiff = 0;
947 		s8 upper_bound_0 = 0, lower_bound_0 = 0;
948 		s8 upper_bound_1 = 0, lower_bound_1 = 0;
949 		u8 valid = _FALSE;
950 		u8 case_num = 1;
951 		u8 i = 0;
952 
953 		/* query TSF */
954 		rtw_hal_mcc_rqt_tsf(padapter, tsf);
955 
956 		/* selecet policy table according TSF diff */
957 		tsf0 = tsf[0];
958 		beaconperiod_0 = pmccobjpriv->iface[0]->mlmepriv.cur_network.network.Configuration.BeaconPeriod;
959 		tsf0 = rtw_modular64(tsf0, (beaconperiod_0 * TU));
960 
961 		tsf1 = tsf[1];
962 		beaconperiod_1 = pmccobjpriv->iface[1]->mlmepriv.cur_network.network.Configuration.BeaconPeriod;
963 		tsf1 = rtw_modular64(tsf1, (beaconperiod_1 * TU));
964 
965 		if (tsf0 > tsf1)
966 			tsfdiff = tsf0- tsf1;
967 		else
968 			tsfdiff = (tsf0 +  beaconperiod_0 * TU) - tsf1;
969 
970 		/* convert to ms */
971 		tsfdiff = (tsfdiff / TU);
972 
973 		/* force update*/
974 		if (force_update) {
975 			RTW_INFO("orig TSF0:%lld, orig TSF1:%lld\n",
976 				pmccobjpriv->iface[0]->mcc_adapterpriv.tsf, pmccobjpriv->iface[1]->mcc_adapterpriv.tsf);
977 			RTW_INFO("tsf0:%lld, tsf1:%lld\n", tsf0, tsf1);
978 			RTW_INFO("%s: force=%d, last_tsfdiff=%d, tsfdiff=%d, THRESHOLD=%d\n",
979 				__func__, force_update, pmccobjpriv->last_tsfdiff, tsfdiff, MCC_UPDATE_PARAMETER_THRESHOLD);
980 			pmccobjpriv->last_tsfdiff = tsfdiff;
981 			need_update = _TRUE;
982 		} else {
983 			if (pmccobjpriv->last_tsfdiff > tsfdiff) {
984 				/* last tsfdiff - current tsfdiff > THRESHOLD, update parameters */
985 				if (pmccobjpriv->last_tsfdiff > (tsfdiff + MCC_UPDATE_PARAMETER_THRESHOLD)) {
986 					RTW_INFO("orig TSF0:%lld, orig TSF1:%lld\n",
987 						pmccobjpriv->iface[0]->mcc_adapterpriv.tsf, pmccobjpriv->iface[1]->mcc_adapterpriv.tsf);
988 					RTW_INFO("tsf0:%lld, tsf1:%lld\n", tsf0, tsf1);
989 					RTW_INFO("%s: force=%d, last_tsfdiff=%d, tsfdiff=%d, THRESHOLD=%d\n",
990 						__func__, force_update, pmccobjpriv->last_tsfdiff, tsfdiff, MCC_UPDATE_PARAMETER_THRESHOLD);
991 
992 					pmccobjpriv->last_tsfdiff = tsfdiff;
993 					need_update = _TRUE;
994 				} else {
995 					need_update = _FALSE;
996 				}
997 			} else if (tsfdiff > pmccobjpriv->last_tsfdiff){
998 				/* current tsfdiff - last tsfdiff > THRESHOLD, update parameters */
999 				if (tsfdiff > (pmccobjpriv->last_tsfdiff + MCC_UPDATE_PARAMETER_THRESHOLD)) {
1000 					RTW_INFO("orig TSF0:%lld, orig TSF1:%lld\n",
1001 						pmccobjpriv->iface[0]->mcc_adapterpriv.tsf, pmccobjpriv->iface[1]->mcc_adapterpriv.tsf);
1002 					RTW_INFO("tsf0:%lld, tsf1:%lld\n", tsf0, tsf1);
1003 					RTW_INFO("%s: force=%d, last_tsfdiff=%d, tsfdiff=%d, THRESHOLD=%d\n",
1004 						__func__, force_update, pmccobjpriv->last_tsfdiff, tsfdiff, MCC_UPDATE_PARAMETER_THRESHOLD);
1005 
1006 					pmccobjpriv->last_tsfdiff = tsfdiff;
1007 					need_update = _TRUE;
1008 				} else {
1009 					need_update = _FALSE;
1010 				}
1011 			} else {
1012 				need_update = _FALSE;
1013 			}
1014 		}
1015 
1016 		if (need_update == _FALSE)
1017 			goto exit;
1018 
1019 		rtw_hal_mcc_decide_duration(padapter);
1020 
1021 		if (tsfdiff <= 50) {
1022 
1023 			/* RX TBTT 0 */
1024 			case_num = 1;
1025 			valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1026 				&upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1027 
1028 			if (valid)
1029 				goto valid_result;
1030 
1031 			/* RX TBTT 1 */
1032 			case_num = 2;
1033 			valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1034 				&upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1035 
1036 			if (valid)
1037 				goto valid_result;
1038 
1039 			/* RX TBTT 2 */
1040 			case_num = 3;
1041 			valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1042 				&upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1043 
1044 			if (valid)
1045 				goto valid_result;
1046 
1047 			if (valid == _FALSE) {
1048 				RTW_INFO("[MCC] do not find fit start time\n");
1049 				RTW_INFO("[MCC] tsfdiff:%d, duration:%d(%c), interval:%d\n",
1050 					tsfdiff, pmccobjpriv->duration, 37, pmccobjpriv->interval);
1051 
1052 			}
1053 
1054 		} else {
1055 
1056 			/* RX TBTT 0 */
1057 			case_num = 4;
1058 			valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1059 				&upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1060 
1061 			if (valid)
1062 				goto valid_result;
1063 
1064 
1065 			/* RX TBTT 1 */
1066 			case_num = 5;
1067 			valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1068 				&upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1069 
1070 			if (valid)
1071 				goto valid_result;
1072 
1073 
1074 			/* RX TBTT 2 */
1075 			case_num = 6;
1076 			valid = rtw_hal_mcc_check_start_time_is_valid(padapter, case_num, tsfdiff,
1077 				&upper_bound_0, &lower_bound_0, &upper_bound_1, &lower_bound_1);
1078 
1079 			if (valid)
1080 				goto valid_result;
1081 
1082 			if (valid == _FALSE) {
1083 				RTW_INFO("[MCC] do not find fit start time\n");
1084 				RTW_INFO("[MCC] tsfdiff:%d, duration:%d(%c), interval:%d\n",
1085 					tsfdiff, pmccobjpriv->duration, 37, pmccobjpriv->interval);
1086 			}
1087 		}
1088 
1089 
1090 
1091 	valid_result:
1092 		RTW_INFO("********************\n");
1093 		RTW_INFO("%s: case_num:%d, start time:%d\n",
1094 				__func__, case_num, pmccobjpriv->start_time);
1095 		RTW_INFO("%s: upper_bound_0:%d, lower_bound_0:%d\n",
1096 				__func__, upper_bound_0, lower_bound_0);
1097 		RTW_INFO("%s: upper_bound_1:%d, lower_bound_1:%d\n",
1098 				__func__, upper_bound_1, lower_bound_1);
1099 
1100 		for (i = 0; i < dvobj->iface_nums; i++) {
1101 			iface = dvobj->padapters[i];
1102 			if (iface == NULL)
1103 				continue;
1104 
1105 			pmccadapriv = &iface->mcc_adapterpriv;
1106 			pmccadapriv = &iface->mcc_adapterpriv;
1107 			if (pmccadapriv->role == MCC_ROLE_MAX)
1108 				continue;
1109 #if 0
1110 			if (pmccadapriv->order == 0) {
1111 				pmccadapriv->mcc_duration = mcc_duration;
1112 			} else if (pmccadapriv->order == 1) {
1113 				pmccadapriv->mcc_duration = mcc_interval - mcc_duration;
1114 			} else {
1115 				RTW_INFO("[MCC] not support >= 3 interface\n");
1116 				rtw_warn_on(1);
1117 			}
1118 #endif
1119 			RTW_INFO("********************\n");
1120 			RTW_INFO(FUNC_ADPT_FMT": order:%d, role:%d\n",
1121 				FUNC_ADPT_ARG(iface), pmccadapriv->order, pmccadapriv->role);
1122 			RTW_INFO(FUNC_ADPT_FMT": mcc duration:%d, target tx bytes:%d\n",
1123 				FUNC_ADPT_ARG(iface), pmccadapriv->mcc_duration, pmccadapriv->mcc_target_tx_bytes_to_port);
1124 			RTW_INFO(FUNC_ADPT_FMT": mgmt queue macid:%d, bitmap:0x%02x\n",
1125 				FUNC_ADPT_ARG(iface), pmccadapriv->mgmt_queue_macid, pmccadapriv->mcc_macid_bitmap);
1126 			RTW_INFO("********************\n");
1127 		}
1128 
1129 	}
1130 exit:
1131 	return need_update;
1132 }
1133 
rtw_hal_decide_mcc_role(PADAPTER padapter)1134 static u8 rtw_hal_decide_mcc_role(PADAPTER padapter)
1135 {
1136 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1137 	_adapter *iface = NULL;
1138 	struct mcc_adapter_priv *pmccadapriv = NULL;
1139 	struct wifidirect_info *pwdinfo = NULL;
1140 	struct mlme_priv *pmlmepriv = NULL;
1141 	u8 ret = _SUCCESS, i = 0;
1142 	u8 order = 1;
1143 
1144 	for (i = 0; i < dvobj->iface_nums; i++) {
1145 		iface = dvobj->padapters[i];
1146 		if (iface == NULL)
1147 			continue;
1148 
1149 		pmccadapriv = &iface->mcc_adapterpriv;
1150 		pwdinfo = &iface->wdinfo;
1151 
1152 		if (MLME_IS_GO(iface))
1153 			pmccadapriv->role = MCC_ROLE_GO;
1154 		else if (MLME_IS_AP(iface))
1155 			pmccadapriv->role = MCC_ROLE_AP;
1156 		else if (MLME_IS_GC(iface))
1157 			pmccadapriv->role = MCC_ROLE_GC;
1158 		else if (MLME_IS_STA(iface)) {
1159 			if (MLME_IS_LINKING(iface) || MLME_IS_ASOC(iface))
1160 				pmccadapriv->role = MCC_ROLE_STA;
1161 			else {
1162 				/* bypass non-linked/non-linking interface */
1163 				RTW_INFO(FUNC_ADPT_FMT" mlme state:0x%2x\n",
1164 					FUNC_ADPT_ARG(iface), MLME_STATE(iface));
1165 				continue;
1166 			}
1167 		} else {
1168 			/* bypass non-linked/non-linking interface */
1169 			RTW_INFO(FUNC_ADPT_FMT" P2P Role:%d, mlme state:0x%2x\n",
1170 				FUNC_ADPT_ARG(iface), pwdinfo->role, MLME_STATE(iface));
1171 			continue;
1172 		}
1173 
1174 		if (padapter == iface) {
1175 			/* current adapter is order 0 */
1176 			rtw_hal_config_mcc_role_setting(iface, 0);
1177 		} else {
1178 			rtw_hal_config_mcc_role_setting(iface, order);
1179 			order ++;
1180 		}
1181 	}
1182 
1183 	rtw_hal_mcc_update_timing_parameters(padapter, _TRUE);
1184 exit:
1185 	return ret;
1186 }
1187 
rtw_hal_construct_CTS(PADAPTER padapter,u8 * pframe,u32 * pLength)1188 static void rtw_hal_construct_CTS(PADAPTER padapter, u8 *pframe, u32 *pLength)
1189 {
1190 	u8 broadcast_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1191 
1192 	/* frame type, length = 1*/
1193 	set_frame_sub_type(pframe, WIFI_RTS);
1194 
1195 	/* frame control flag, length = 1 */
1196 	*(pframe + 1) = 0;
1197 
1198 	/* frame duration, length = 2 */
1199 	*(pframe + 2) = 0x00;
1200 	*(pframe + 3) = 0x78;
1201 
1202 	/* frame recvaddr, length = 6 */
1203 	_rtw_memcpy((pframe + 4), broadcast_addr, ETH_ALEN);
1204 	_rtw_memcpy((pframe + 4 + ETH_ALEN), adapter_mac_addr(padapter), ETH_ALEN);
1205 	_rtw_memcpy((pframe + 4 + ETH_ALEN*2), adapter_mac_addr(padapter), ETH_ALEN);
1206 	*pLength = 22;
1207 }
1208 
1209 /* avoid wrong information for power limit */
rtw_hal_mcc_upadate_chnl_bw(_adapter * padapter,u8 ch,u8 ch_offset,u8 bw,u8 print)1210 void rtw_hal_mcc_upadate_chnl_bw(_adapter *padapter, u8 ch, u8 ch_offset, u8 bw, u8 print)
1211 {
1212 
1213 	u8 center_ch, chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1214 	struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
1215 	PHAL_DATA_TYPE	hal = GET_HAL_DATA(padapter);
1216 	u8 cch_160, cch_80, cch_40, cch_20;
1217 
1218 	center_ch = rtw_get_center_ch(ch, bw, ch_offset);
1219 
1220 	if (bw == CHANNEL_WIDTH_80) {
1221 		if (center_ch > ch)
1222 			chnl_offset80 = HAL_PRIME_CHNL_OFFSET_LOWER;
1223 		else if (center_ch < ch)
1224 			chnl_offset80 = HAL_PRIME_CHNL_OFFSET_UPPER;
1225 		else
1226 			chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1227 	}
1228 
1229 	/* set Channel */
1230 	/* saved channel/bw info */
1231 	rtw_set_oper_ch(padapter, ch);
1232 	rtw_set_oper_bw(padapter, bw);
1233 	rtw_set_oper_choffset(padapter, ch_offset);
1234 
1235 	cch_80 = bw == CHANNEL_WIDTH_80 ? center_ch : 0;
1236 	cch_40 = bw == CHANNEL_WIDTH_40 ? center_ch : 0;
1237 	cch_20 = bw == CHANNEL_WIDTH_20 ? center_ch : 0;
1238 
1239 	if (cch_80 != 0)
1240 		cch_40 = rtw_get_scch_by_cch_offset(cch_80, CHANNEL_WIDTH_80, chnl_offset80);
1241 	if (cch_40 != 0)
1242 		cch_20 = rtw_get_scch_by_cch_offset(cch_40, CHANNEL_WIDTH_40, ch_offset);
1243 
1244 
1245 	hal->cch_80 = cch_80;
1246 	hal->cch_40 = cch_40;
1247 	hal->cch_20 = cch_20;
1248 	hal->current_channel = center_ch;
1249 	hal->CurrentCenterFrequencyIndex1 = center_ch;
1250 	hal->current_channel_bw = bw;
1251 	hal->nCur40MhzPrimeSC = ch_offset;
1252 	hal->nCur80MhzPrimeSC = chnl_offset80;
1253 	hal->current_band_type = ch > 14 ? BAND_ON_5G:BAND_ON_2_4G;
1254 
1255 	if (print) {
1256 		RTW_INFO(FUNC_ADPT_FMT" cch:%u, %s, offset40:%u, offset80:%u (%u, %u, %u), band:%s\n"
1257 			, FUNC_ADPT_ARG(padapter), center_ch, ch_width_str(bw)
1258 			, ch_offset, chnl_offset80
1259 			, hal->cch_80, hal->cch_40, hal->cch_20
1260 			, band_str(hal->current_band_type));
1261 	}
1262 }
1263 
rtw_hal_dl_mcc_fw_rsvd_page(_adapter * adapter,u8 * pframe,u16 * index,u8 tx_desc,u32 page_size,u8 * total_page_num,RSVDPAGE_LOC * rsvd_page_loc,u8 * page_num)1264 u8 rtw_hal_dl_mcc_fw_rsvd_page(_adapter *adapter, u8 *pframe, u16 *index,
1265 	u8 tx_desc, u32 page_size, u8 *total_page_num, RSVDPAGE_LOC *rsvd_page_loc, u8 *page_num)
1266 {
1267 	u32 len = 0;
1268 	_adapter *iface = NULL;
1269 	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
1270 	struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
1271 	struct mlme_ext_info *pmlmeinfo = NULL;
1272 	struct mlme_ext_priv *pmlmeext = NULL;
1273 	struct hal_com_data *hal = GET_HAL_DATA(adapter);
1274 	struct mcc_adapter_priv *mccadapriv = NULL;
1275 	u8 ret = _SUCCESS, i = 0, j  =0, order = 0, CurtPktPageNum = 0;
1276 	u8 *start = NULL;
1277 	u8 path = RF_PATH_A;
1278 
1279 	if (page_num) {
1280 #ifdef CONFIG_MCC_MODE_V2
1281 		if (!hal->RegIQKFWOffload)
1282 			RTW_WARN("[MCC] must enable FW IQK for New IC\n");
1283 #endif /* CONFIG_MCC_MODE_V2 */
1284 		*total_page_num += (2 * MAX_MCC_NUM+ 1);
1285 		RTW_INFO("[MCC] allocate mcc rsvd page num = %d\n", *total_page_num);
1286 		goto exit;
1287 	}
1288 
1289 	/* check proccess mcc start setting */
1290 	if (!rtw_hal_check_mcc_status(adapter, MCC_STATUS_PROCESS_MCC_START_SETTING)) {
1291 		ret = _FAIL;
1292 		goto exit;
1293 	}
1294 
1295 	for (i = 0; i < dvobj->iface_nums; i++) {
1296 		iface = dvobj->padapters[i];
1297 		if (iface == NULL)
1298 			continue;
1299 
1300 		mccadapriv = &iface->mcc_adapterpriv;
1301 		if (mccadapriv->role == MCC_ROLE_MAX)
1302 			continue;
1303 
1304 		order = mccadapriv->order;
1305 		pmccobjpriv->mcc_loc_rsvd_paga[order] = *total_page_num;
1306 
1307 		switch (mccadapriv->role) {
1308 		case MCC_ROLE_STA:
1309 		case MCC_ROLE_GC:
1310 			/* Build NULL DATA */
1311 			RTW_INFO("LocNull(order:%d): %d\n"
1312 				, order, pmccobjpriv->mcc_loc_rsvd_paga[order]);
1313 			len = 0;
1314 
1315 			rtw_hal_construct_NullFunctionData(iface
1316 				, &pframe[*index], &len, _FALSE, 0, 0, _FALSE);
1317 			rtw_hal_fill_fake_txdesc(iface, &pframe[*index-tx_desc],
1318 				len, _FALSE, _FALSE, _FALSE);
1319 
1320 			CurtPktPageNum = (u8)PageNum(tx_desc + len, page_size);
1321 			*total_page_num += CurtPktPageNum;
1322 			*index += (CurtPktPageNum * page_size);
1323 			RSVD_PAGE_CFG("LocNull", CurtPktPageNum, *total_page_num, *index);
1324 			break;
1325 		case MCC_ROLE_AP:
1326 			/* Bulid CTS */
1327 			RTW_INFO("LocCTS(order:%d): %d\n"
1328 				, order, pmccobjpriv->mcc_loc_rsvd_paga[order]);
1329 
1330 			len = 0;
1331 			rtw_hal_construct_CTS(iface, &pframe[*index], &len);
1332 			rtw_hal_fill_fake_txdesc(iface, &pframe[*index-tx_desc],
1333 				len, _FALSE, _FALSE, _FALSE);
1334 
1335 			CurtPktPageNum = (u8)PageNum(tx_desc + len, page_size);
1336 			*total_page_num += CurtPktPageNum;
1337 			*index += (CurtPktPageNum * page_size);
1338 			RSVD_PAGE_CFG("LocCTS", CurtPktPageNum, *total_page_num, *index);
1339 			break;
1340 		case MCC_ROLE_GO:
1341 		/* To DO */
1342 			break;
1343 		default:
1344 			RTW_INFO(FUNC_ADPT_FMT": unknown role = %d\n"
1345 				, FUNC_ADPT_ARG(iface), mccadapriv->role);
1346 			break;
1347 		}
1348 	}
1349 
1350 	for (i = 0; i < MAX_MCC_NUM; i++) {
1351 		u8 center_ch = 0, ch = 0, bw = 0, bw_offset = 0;
1352 		u8 power_index = 0;
1353 		u8 rate_array_sz = 0;
1354 		u8 *rates = NULL;
1355 		u8 rate = 0;
1356 		u8 shift = 0;
1357 		u32 power_index_4bytes = 0;
1358 		u8 total_rate = 0;
1359 		u8 *total_rate_offset = NULL;
1360 
1361 		iface = pmccobjpriv->iface[i];
1362 		pmlmeext = &iface->mlmeextpriv;
1363 		ch = pmlmeext->cur_channel;
1364 		bw = pmlmeext->cur_bwmode;
1365 		bw_offset = pmlmeext->cur_ch_offset;
1366 		center_ch = rtw_get_center_ch(ch, bw, bw_offset);
1367 		rtw_hal_mcc_upadate_chnl_bw(iface, ch, bw_offset, bw, _TRUE);
1368 
1369 		start = &pframe[*index - tx_desc];
1370 		_rtw_memset(start, 0, page_size);
1371 		pmccobjpriv->mcc_pwr_idx_rsvd_page[i] = *total_page_num;
1372 		RTW_INFO(ADPT_FMT" order:%d, pwr_idx_rsvd_page location[%d]: %d\n",
1373 			ADPT_ARG(iface), mccadapriv->order,
1374 			i, pmccobjpriv->mcc_pwr_idx_rsvd_page[i]);
1375 
1376 		total_rate_offset = start;
1377 
1378 		for (path = RF_PATH_A; path < hal->NumTotalRFPath; ++path) {
1379 			total_rate = 0;
1380 			/* PATH A for 0~63 byte, PATH B for 64~127 byte*/
1381 			if (path == RF_PATH_A)
1382 				start = total_rate_offset + 1;
1383 			else if (path == RF_PATH_B)
1384 				start = total_rate_offset + 64;
1385 			else {
1386 				RTW_INFO("[MCC] %s: unknow RF PATH(%d)\n", __func__, path);
1387 				break;
1388 			}
1389 
1390 			/* CCK */
1391 			if (ch <= 14) {
1392 				rate_array_sz = rates_by_sections[CCK].rate_num;
1393 				rates = rates_by_sections[CCK].rates;
1394 				for (j = 0; j < rate_array_sz; ++j) {
1395 					power_index = rtw_hal_get_tx_power_index(iface, path, rates[j], bw, center_ch, NULL);
1396 					rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
1397 
1398 					shift = rate % 4;
1399 					if (shift == 0) {
1400 						*start = rate;
1401 						start++;
1402 						total_rate++;
1403 
1404 						#ifdef DBG_PWR_IDX_RSVD_PAGE
1405 						RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1406 							ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1407 							center_ch, MGN_RATE_STR(rates[j]), power_index);
1408 						#endif
1409 					}
1410 
1411 					*start = power_index;
1412 					start++;
1413 
1414 					#ifdef DBG_PWR_IDX_RSVD_PAGE
1415 					RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1416 						ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1417 						center_ch, MGN_RATE_STR(rates[j]), power_index);
1418 
1419 
1420 					shift = rate % 4;
1421 					power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1422 					if (shift == 3) {
1423 						rate = rate - 3;
1424 						RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1425 						power_index_4bytes = 0;
1426 						total_rate++;
1427 					}
1428 					#endif
1429 
1430 				}
1431 			}
1432 
1433 			/* OFDM */
1434 			rate_array_sz = rates_by_sections[OFDM].rate_num;
1435 			rates = rates_by_sections[OFDM].rates;
1436 			for (j = 0; j < rate_array_sz; ++j) {
1437 				power_index = rtw_hal_get_tx_power_index(iface, path, rates[j], bw, center_ch, NULL);
1438 				rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
1439 
1440 				shift = rate % 4;
1441 				if (shift == 0) {
1442 					*start = rate;
1443 					start++;
1444 					total_rate++;
1445 
1446 					#ifdef DBG_PWR_IDX_RSVD_PAGE
1447 					RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1448 						ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1449 						center_ch, MGN_RATE_STR(rates[j]), power_index);
1450 					#endif
1451 
1452 				}
1453 
1454 				*start = power_index;
1455 				start++;
1456 
1457 				#ifdef DBG_PWR_IDX_RSVD_PAGE
1458 				RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1459 					ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1460 					center_ch, MGN_RATE_STR(rates[j]), power_index);
1461 
1462 				shift = rate % 4;
1463 				power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1464 				if (shift == 3) {
1465 					rate = rate - 3;
1466 					RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1467 					power_index_4bytes = 0;
1468 					total_rate++;
1469 				}
1470 				#endif
1471 			}
1472 
1473 			/* HT_MCS0_MCS7 */
1474 			rate_array_sz = rates_by_sections[HT_MCS0_MCS7].rate_num;
1475 			rates = rates_by_sections[HT_MCS0_MCS7].rates;
1476 			for (j = 0; j < rate_array_sz; ++j) {
1477 				power_index = rtw_hal_get_tx_power_index(iface, path, rates[j], bw, center_ch, NULL);
1478 				rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
1479 
1480 				shift = rate % 4;
1481 				if (shift == 0) {
1482 					*start = rate;
1483 					start++;
1484 					total_rate++;
1485 
1486 					#ifdef DBG_PWR_IDX_RSVD_PAGE
1487 					RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1488 						ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1489 						center_ch, MGN_RATE_STR(rates[j]), power_index);
1490 					#endif
1491 
1492 				}
1493 
1494 				*start = power_index;
1495 				start++;
1496 
1497 				#ifdef DBG_PWR_IDX_RSVD_PAGE
1498 				RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1499 					ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1500 					center_ch, MGN_RATE_STR(rates[j]), power_index);
1501 
1502 				shift = rate % 4;
1503 				power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1504 				if (shift == 3) {
1505 					rate = rate - 3;
1506 					RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1507 					power_index_4bytes = 0;
1508 					total_rate++;
1509 				}
1510 				#endif
1511 			}
1512 
1513 			/* HT_MCS8_MCS15 */
1514 			rate_array_sz = rates_by_sections[HT_MCS8_MCS15].rate_num;
1515 			rates = rates_by_sections[HT_MCS8_MCS15].rates;
1516 			for (j = 0; j < rate_array_sz; ++j) {
1517 				power_index = rtw_hal_get_tx_power_index(iface, path, rates[j], bw, center_ch, NULL);
1518 				rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
1519 
1520 				shift = rate % 4;
1521 				if (shift == 0) {
1522 					*start = rate;
1523 					start++;
1524 					total_rate++;
1525 
1526 					#ifdef DBG_PWR_IDX_RSVD_PAGE
1527 					RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1528 						ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1529 						center_ch, MGN_RATE_STR(rates[j]), power_index);
1530 					#endif
1531 				}
1532 
1533 				*start = power_index;
1534 				start++;
1535 
1536 				#ifdef DBG_PWR_IDX_RSVD_PAGE
1537 				RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1538 					ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1539 					center_ch, MGN_RATE_STR(rates[j]), power_index);
1540 
1541 				shift = rate % 4;
1542 				power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1543 				if (shift == 3) {
1544 					rate = rate - 3;
1545 					RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1546 					power_index_4bytes = 0;
1547 					total_rate++;
1548 				}
1549 				#endif
1550 			}
1551 
1552 			/* VHT_1SSMCS0_1SSMCS9 */
1553 			rate_array_sz = rates_by_sections[VHT_1SSMCS0_1SSMCS9].rate_num;
1554 			rates = rates_by_sections[VHT_1SSMCS0_1SSMCS9].rates;
1555 			for (j = 0; j < rate_array_sz; ++j) {
1556 				power_index = rtw_hal_get_tx_power_index(iface, path, rates[j], bw, center_ch, NULL);
1557 				rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
1558 
1559 				shift = rate % 4;
1560 				if (shift == 0) {
1561 					*start = rate;
1562 					start++;
1563 					total_rate++;
1564 					#ifdef DBG_PWR_IDX_RSVD_PAGE
1565 					RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:0x%02x\n",
1566 						ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1567 						center_ch, MGN_RATE_STR(rates[j]), power_index);
1568 					#endif
1569 				}
1570 				*start = power_index;
1571 				start++;
1572 				#ifdef DBG_PWR_IDX_RSVD_PAGE
1573 				RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1574 					ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1575 					center_ch, MGN_RATE_STR(rates[j]), power_index);
1576 
1577 				shift = rate % 4;
1578 				power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1579 				if (shift == 3) {
1580 					rate = rate - 3;
1581 					RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1582 					power_index_4bytes = 0;
1583 					total_rate++;
1584 				}
1585 				#endif
1586 			}
1587 
1588 			/* VHT_2SSMCS0_2SSMCS9 */
1589 			rate_array_sz = rates_by_sections[VHT_2SSMCS0_2SSMCS9].rate_num;
1590 			rates = rates_by_sections[VHT_2SSMCS0_2SSMCS9].rates;
1591 			for (j = 0; j < rate_array_sz; ++j) {
1592 				power_index = rtw_hal_get_tx_power_index(iface, path, rates[j], bw, center_ch, NULL);
1593 				rate = PHY_GetRateIndexOfTxPowerByRate(rates[j]);
1594 
1595 				shift = rate % 4;
1596 				if (shift == 0) {
1597 					*start = rate;
1598 					start++;
1599 					total_rate++;
1600 					#ifdef DBG_PWR_IDX_RSVD_PAGE
1601 					RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1602 						ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1603 						center_ch, MGN_RATE_STR(rates[j]), power_index);
1604 					#endif
1605 				}
1606 				*start = power_index;
1607 				start++;
1608 				#ifdef DBG_PWR_IDX_RSVD_PAGE
1609 				RTW_INFO("TXPWR("ADPT_FMT"): [%c][%s]ch:%u, %s, pwr_idx:%u\n",
1610 					ADPT_ARG(iface), rf_path_char(path), ch_width_str(bw),
1611 					center_ch, MGN_RATE_STR(rates[j]), power_index);
1612 
1613 				shift = rate % 4;
1614 				power_index_4bytes |= ((power_index & 0xff) << (shift * 8));
1615 				if (shift == 3) {
1616 					rate = rate - 3;
1617 					RTW_INFO("(index:0x%02x, rfpath:%d, rate:0x%02x)\n", index, path, rate);
1618 					power_index_4bytes = 0;
1619 						total_rate++;
1620 				}
1621 				#endif
1622 			}
1623 
1624 		}
1625 		/*  total rate store in offset 0 */
1626 		*total_rate_offset = total_rate;
1627 
1628 #ifdef DBG_PWR_IDX_RSVD_PAGE
1629 			RTW_INFO("total_rate=%d\n", total_rate);
1630 			RTW_INFO(" ======================="ADPT_FMT"===========================\n", ADPT_ARG(iface));
1631 			RTW_INFO_DUMP("\n", total_rate_offset, 128);
1632 			RTW_INFO(" ==================================================\n");
1633 #endif
1634 
1635 			CurtPktPageNum = 1;
1636 			*total_page_num += CurtPktPageNum;
1637 			*index += (CurtPktPageNum * page_size);
1638 			RSVD_PAGE_CFG("mcc_pwr_idx_rsvd_page", CurtPktPageNum, *total_page_num, *index);
1639 		}
1640 
1641 exit:
1642 	return ret;
1643 }
1644 
1645 /*
1646 * 1. Download MCC rsvd page
1647 * 2. Re-Download beacon after download rsvd page
1648 */
rtw_hal_set_fw_mcc_rsvd_page(PADAPTER padapter)1649 static void rtw_hal_set_fw_mcc_rsvd_page(PADAPTER padapter)
1650 {
1651 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
1652 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
1653 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1654 	PADAPTER port0_iface = dvobj_get_port0_adapter(dvobj);
1655 	PADAPTER iface = NULL;
1656 	struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
1657 	u8 mstatus = RT_MEDIA_CONNECT, i = 0;
1658 
1659 	RTW_INFO(FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
1660 
1661 	rtw_hal_set_hwreg(port0_iface, HW_VAR_H2C_FW_JOINBSSRPT, (u8 *)(&mstatus));
1662 
1663 	/* Re-Download beacon */
1664 	for (i = 0; i < MAX_MCC_NUM; i++) {
1665 		iface = pmccobjpriv->iface[i];
1666 		if (iface == NULL)
1667 			continue;
1668 
1669 		pmccadapriv = &iface->mcc_adapterpriv;
1670 
1671 		if (pmccadapriv->role == MCC_ROLE_AP
1672 			|| pmccadapriv->role == MCC_ROLE_GO) {
1673 			tx_beacon_hdl(iface, NULL);
1674 		}
1675 	}
1676 }
1677 
rtw_hal_set_mcc_rsvdpage_cmd(_adapter * padapter)1678 static void rtw_hal_set_mcc_rsvdpage_cmd(_adapter *padapter)
1679 {
1680 	u8 cmd[H2C_MCC_LOCATION_LEN] = {0}, i = 0, order = 0;
1681 	_adapter *iface = NULL;
1682 	PHAL_DATA_TYPE hal = GET_HAL_DATA(padapter);
1683 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1684 	struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
1685 
1686 	SET_H2CCMD_MCC_PWRIDX_OFFLOAD_EN(cmd, _TRUE);
1687 	SET_H2CCMD_MCC_PWRIDX_OFFLOAD_RFNUM(cmd, hal->NumTotalRFPath);
1688 	for (order = 0; order < MAX_MCC_NUM; order++) {
1689 		iface = pmccobjpriv->iface[i];
1690 
1691 		SET_H2CCMD_MCC_RSVDPAGE_LOC((cmd + order), pmccobjpriv->mcc_loc_rsvd_paga[order]);
1692 		SET_H2CCMD_MCC_PWRIDX_RSVDPAGE_LOC ((cmd + order), pmccobjpriv->mcc_pwr_idx_rsvd_page[order]);
1693 	}
1694 
1695 #ifdef CONFIG_MCC_MODE_DEBUG
1696 	RTW_INFO("=========================\n");
1697 	RTW_INFO("MCC RSVD PAGE LOC:\n");
1698 	for (i = 0; i < H2C_MCC_LOCATION_LEN; i++)
1699 		pr_dbg("0x%x ", cmd[i]);
1700 	pr_dbg("\n");
1701 	RTW_INFO("=========================\n");
1702 #endif /* CONFIG_MCC_MODE_DEBUG */
1703 
1704 	rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_LOCATION, H2C_MCC_LOCATION_LEN, cmd);
1705 }
1706 
rtw_hal_set_mcc_time_setting_cmd(PADAPTER padapter)1707 static void rtw_hal_set_mcc_time_setting_cmd(PADAPTER padapter)
1708 {
1709 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
1710 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
1711 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1712 	struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
1713 	u8 cmd[H2C_MCC_TIME_SETTING_LEN] = {0};
1714 	u8 fw_eable = 1;
1715 	u8 swchannel_early_time = MCC_SWCH_FW_EARLY_TIME;
1716 	u8 starting_ap_num = DEV_AP_STARTING_NUM(dvobj);
1717 	u8 ap_num = DEV_AP_NUM(dvobj);
1718 
1719 	if (starting_ap_num == 0 && ap_num == 0)
1720 		/* For STA+GC/STA+STA, TSF of GC/STA does not need to sync from TSF of other STA/GC */
1721 		fw_eable = 0;
1722 	else
1723 		/* Only for STA+GO/STA+AP, TSF of AP/GO need to sync from TSF of STA */
1724 		fw_eable = 1;
1725 
1726 	if (fw_eable == 1) {
1727 		PADAPTER order0_iface = NULL;
1728 		PADAPTER order1_iface = NULL;
1729 		u8 policy_idx = mccobjpriv->policy_index;
1730 		u8 tsf_sync_offset = mcc_switch_channel_policy_table[policy_idx][MCC_TSF_SYNC_OFFSET_IDX];
1731 		u8 start_time_offset = mcc_switch_channel_policy_table[policy_idx][MCC_START_TIME_OFFSET_IDX];
1732 		u8 interval = mcc_switch_channel_policy_table[policy_idx][MCC_INTERVAL_IDX];
1733 		u8 guard_offset0 = mcc_switch_channel_policy_table[policy_idx][MCC_GUARD_OFFSET0_IDX];
1734 		u8 guard_offset1 = mcc_switch_channel_policy_table[policy_idx][MCC_GUARD_OFFSET1_IDX];
1735 		enum _hw_port tsf_bsae_port = MAX_HW_PORT;
1736 		enum _hw_port tsf_sync_port = MAX_HW_PORT;
1737 		order0_iface = mccobjpriv->iface[0];
1738 		order1_iface = mccobjpriv->iface[1];
1739 
1740 		tsf_bsae_port = rtw_hal_get_port(order1_iface);
1741 		tsf_sync_port = rtw_hal_get_port(order0_iface);
1742 
1743 		/* FW set enable */
1744 		SET_H2CCMD_MCC_TIME_SETTING_FW_EN(cmd, fw_eable);
1745 		/* TSF Sync offset */
1746 		SET_H2CCMD_MCC_TIME_SETTING_TSF_SYNC_OFFSET(cmd, tsf_sync_offset);
1747 		/* start time offset */
1748 		SET_H2CCMD_MCC_TIME_SETTING_START_TIME(cmd, (start_time_offset + guard_offset0));
1749 		/* interval */
1750 		SET_H2CCMD_MCC_TIME_SETTING_INTERVAL(cmd, interval);
1751 		/* Early time to inform driver by C2H before switch channel */
1752 		SET_H2CCMD_MCC_TIME_SETTING_EARLY_SWITCH_RPT(cmd, swchannel_early_time);
1753 		/* Port0 sync from Port1, not support multi-port */
1754 		SET_H2CCMD_MCC_TIME_SETTING_ORDER_BASE(cmd, tsf_bsae_port);
1755 		SET_H2CCMD_MCC_TIME_SETTING_ORDER_SYNC(cmd, tsf_sync_port);
1756 	} else {
1757 		/* start time offset */
1758 		SET_H2CCMD_MCC_TIME_SETTING_START_TIME(cmd, mccobjpriv->start_time);
1759 		/* interval */
1760 		SET_H2CCMD_MCC_TIME_SETTING_INTERVAL(cmd, mccobjpriv->interval);
1761 		/* Early time to inform driver by C2H before switch channel */
1762 		SET_H2CCMD_MCC_TIME_SETTING_EARLY_SWITCH_RPT(cmd, swchannel_early_time);
1763 	}
1764 
1765 #ifdef CONFIG_MCC_MODE_DEBUG
1766 	{
1767 		u8 i = 0;
1768 
1769 		RTW_INFO("=========================\n");
1770 		RTW_INFO("NoA:\n");
1771 		for (i = 0; i < H2C_MCC_TIME_SETTING_LEN; i++)
1772 			pr_dbg("0x%x ", cmd[i]);
1773 		pr_dbg("\n");
1774 		RTW_INFO("=========================\n");
1775 	}
1776 #endif /* CONFIG_MCC_MODE_DEBUG */
1777 
1778 	rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_TIME_SETTING, H2C_MCC_TIME_SETTING_LEN, cmd);
1779 }
1780 
rtw_hal_set_mcc_IQK_offload_cmd(PADAPTER padapter)1781 static void rtw_hal_set_mcc_IQK_offload_cmd(PADAPTER padapter)
1782 {
1783 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1784 	struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
1785 	struct mcc_adapter_priv *pmccadapriv = NULL;
1786 	_adapter *iface = NULL;
1787 	u8 cmd[H2C_MCC_IQK_PARAM_LEN] = {0}, bready = 0, i = 0, order = 0;
1788 	u16 TX_X = 0, TX_Y = 0, RX_X = 0, RX_Y = 0;
1789 	u8 total_rf_path = GET_HAL_DATA(padapter)->NumTotalRFPath;
1790 	u8 rf_path_idx = 0, last_order = MAX_MCC_NUM - 1, last_rf_path_index = total_rf_path - 1;
1791 
1792 	/* by order, last order & last_rf_path_index must set ready bit = 1 */
1793 	for (i = 0; i < MAX_MCC_NUM; i++) {
1794 		iface = pmccobjpriv->iface[i];
1795 		if (iface == NULL)
1796 			continue;
1797 
1798 		pmccadapriv = &iface->mcc_adapterpriv;
1799 		order = pmccadapriv->order;
1800 
1801 		for (rf_path_idx = 0; rf_path_idx < total_rf_path; rf_path_idx ++) {
1802 
1803 			_rtw_memset(cmd, 0, H2C_MCC_IQK_PARAM_LEN);
1804 			TX_X = pmccadapriv->mcc_iqk_arr[rf_path_idx].TX_X & 0x7ff;/* [10:0]  */
1805 			TX_Y = pmccadapriv->mcc_iqk_arr[rf_path_idx].TX_Y & 0x7ff;/* [10:0]  */
1806 			RX_X = pmccadapriv->mcc_iqk_arr[rf_path_idx].RX_X & 0x3ff;/* [9:0]  */
1807 			RX_Y = pmccadapriv->mcc_iqk_arr[rf_path_idx].RX_Y & 0x3ff;/* [9:0]  */
1808 
1809 			/* ready or not */
1810 			if (order == last_order && rf_path_idx == last_rf_path_index)
1811 				bready = 1;
1812 			else
1813 				bready = 0;
1814 
1815 			SET_H2CCMD_MCC_IQK_READY(cmd, bready);
1816 			SET_H2CCMD_MCC_IQK_ORDER(cmd, order);
1817 			SET_H2CCMD_MCC_IQK_PATH(cmd, rf_path_idx);
1818 
1819 			/* fill RX_X[7:0] to (cmd+1)[7:0] bitlen=8 */
1820 			SET_H2CCMD_MCC_IQK_RX_L(cmd, (u8)(RX_X & 0xff));
1821 			/* fill RX_X[9:8] to (cmd+2)[1:0] bitlen=2 */
1822 			SET_H2CCMD_MCC_IQK_RX_M1(cmd, (u8)((RX_X >> 8) & 0x03));
1823 			/* fill RX_Y[5:0] to (cmd+2)[7:2] bitlen=6 */
1824 			SET_H2CCMD_MCC_IQK_RX_M2(cmd, (u8)(RX_Y & 0x3f));
1825 			/* fill RX_Y[9:6] to (cmd+3)[3:0] bitlen=4 */
1826 			SET_H2CCMD_MCC_IQK_RX_H(cmd, (u8)((RX_Y >> 6) & 0x0f));
1827 
1828 
1829 			/* fill TX_X[7:0] to (cmd+4)[7:0] bitlen=8 */
1830 			SET_H2CCMD_MCC_IQK_TX_L(cmd, (u8)(TX_X & 0xff));
1831 			/* fill TX_X[10:8] to (cmd+5)[2:0] bitlen=3 */
1832 			SET_H2CCMD_MCC_IQK_TX_M1(cmd, (u8)((TX_X >> 8) & 0x07));
1833 			/* fill TX_Y[4:0] to (cmd+5)[7:3] bitlen=5 */
1834 			SET_H2CCMD_MCC_IQK_TX_M2(cmd, (u8)(TX_Y & 0x1f));
1835 			/* fill TX_Y[10:5] to (cmd+6)[5:0] bitlen=6 */
1836 			SET_H2CCMD_MCC_IQK_TX_H(cmd, (u8)((TX_Y >> 5) & 0x3f));
1837 
1838 #ifdef CONFIG_MCC_MODE_DEBUG
1839 			RTW_INFO("=========================\n");
1840 			RTW_INFO(FUNC_ADPT_FMT" IQK:\n", FUNC_ADPT_ARG(iface));
1841 			RTW_INFO("TX_X: 0x%02x\n", TX_X);
1842 			RTW_INFO("TX_Y: 0x%02x\n", TX_Y);
1843 			RTW_INFO("RX_X: 0x%02x\n", RX_X);
1844 			RTW_INFO("RX_Y: 0x%02x\n", RX_Y);
1845 			RTW_INFO("cmd[0]:0x%02x\n", cmd[0]);
1846 			RTW_INFO("cmd[1]:0x%02x\n", cmd[1]);
1847 			RTW_INFO("cmd[2]:0x%02x\n", cmd[2]);
1848 			RTW_INFO("cmd[3]:0x%02x\n", cmd[3]);
1849 			RTW_INFO("cmd[4]:0x%02x\n", cmd[4]);
1850 			RTW_INFO("cmd[5]:0x%02x\n", cmd[5]);
1851 			RTW_INFO("cmd[6]:0x%02x\n", cmd[6]);
1852 			RTW_INFO("=========================\n");
1853 #endif /* CONFIG_MCC_MODE_DEBUG */
1854 
1855 			rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_IQK_PARAM, H2C_MCC_IQK_PARAM_LEN, cmd);
1856 		}
1857 	}
1858 }
1859 
1860 
rtw_hal_set_mcc_macid_cmd(PADAPTER padapter)1861 static void rtw_hal_set_mcc_macid_cmd(PADAPTER padapter)
1862 {
1863 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1864 	struct mcc_adapter_priv *pmccadapriv = NULL;
1865 	_adapter *iface = NULL;
1866 	u8 cmd[H2C_MCC_MACID_BITMAP_LEN] = {0}, i = 0, order = 0;
1867 	u16 bitmap = 0;
1868 
1869 	for (i = 0; i < dvobj->iface_nums; i++) {
1870 		iface = dvobj->padapters[i];
1871 		if (iface == NULL)
1872 			continue;
1873 
1874 		pmccadapriv = &iface->mcc_adapterpriv;
1875 		if (pmccadapriv->role == MCC_ROLE_MAX)
1876 			continue;
1877 
1878 		order = pmccadapriv->order;
1879 		bitmap = pmccadapriv->mcc_macid_bitmap;
1880 
1881 		if (order >= (H2C_MCC_MACID_BITMAP_LEN/2)) {
1882 			RTW_INFO(FUNC_ADPT_FMT" only support 3 interface at most(%d)\n"
1883 				, FUNC_ADPT_ARG(padapter), order);
1884 			continue;
1885 		}
1886 		SET_H2CCMD_MCC_MACID_BITMAP_L((cmd + order * 2), (u8)(bitmap & 0xff));
1887 		SET_H2CCMD_MCC_MACID_BITMAP_H((cmd + order * 2), (u8)((bitmap >> 8) & 0xff));
1888 	}
1889 
1890 #ifdef CONFIG_MCC_MODE_DEBUG
1891 	RTW_INFO("=========================\n");
1892 	RTW_INFO("MACID BITMAP: ");
1893 	for (i = 0; i < H2C_MCC_MACID_BITMAP_LEN; i++)
1894 		printk("0x%x ", cmd[i]);
1895 	printk("\n");
1896 	RTW_INFO("=========================\n");
1897 #endif /* CONFIG_MCC_MODE_DEBUG */
1898 	rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_MACID_BITMAP, H2C_MCC_MACID_BITMAP_LEN, cmd);
1899 }
1900 
1901 #ifdef CONFIG_MCC_MODE_V2
get_pri_ch_idx_by_adapter(u8 center_ch,u8 channel,u8 bw,u8 ch_offset40)1902 static u8 get_pri_ch_idx_by_adapter(u8 center_ch, u8 channel, u8 bw, u8 ch_offset40)
1903 {
1904 	u8 pri_ch_idx = 0, chnl_offset80 = 0;
1905 
1906 	if (bw == CHANNEL_WIDTH_80) {
1907 		if (center_ch > channel)
1908 			chnl_offset80 = HAL_PRIME_CHNL_OFFSET_LOWER;
1909 		else if (center_ch < channel)
1910 			chnl_offset80 = HAL_PRIME_CHNL_OFFSET_UPPER;
1911 		else
1912 			chnl_offset80 = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
1913 	}
1914 
1915 	if (bw == CHANNEL_WIDTH_80) {
1916 		/* primary channel is at lower subband of 80MHz & 40MHz */
1917 		if ((ch_offset40 == HAL_PRIME_CHNL_OFFSET_LOWER) && (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_LOWER))
1918 			pri_ch_idx = VHT_DATA_SC_20_LOWEST_OF_80MHZ;
1919 		/* primary channel is at lower subband of 80MHz & upper subband of 40MHz */
1920 		else if ((ch_offset40 == HAL_PRIME_CHNL_OFFSET_UPPER) && (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_LOWER))
1921 			pri_ch_idx = VHT_DATA_SC_20_LOWER_OF_80MHZ;
1922 		/* primary channel is at upper subband of 80MHz & lower subband of 40MHz */
1923 		else if ((ch_offset40 == HAL_PRIME_CHNL_OFFSET_LOWER) && (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_UPPER))
1924 			pri_ch_idx = VHT_DATA_SC_20_UPPER_OF_80MHZ;
1925 		/* primary channel is at upper subband of 80MHz & upper subband of 40MHz */
1926 		else if ((ch_offset40 == HAL_PRIME_CHNL_OFFSET_UPPER) && (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_UPPER))
1927 			pri_ch_idx = VHT_DATA_SC_20_UPPERST_OF_80MHZ;
1928 		else {
1929 			if (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_LOWER)
1930 				pri_ch_idx = VHT_DATA_SC_40_LOWER_OF_80MHZ;
1931 			else if (chnl_offset80 == HAL_PRIME_CHNL_OFFSET_UPPER)
1932 				pri_ch_idx = VHT_DATA_SC_40_UPPER_OF_80MHZ;
1933 			else
1934 				RTW_INFO("SCMapping: DONOT CARE Mode Setting\n");
1935 		}
1936 	} else if (bw == CHANNEL_WIDTH_40) {
1937 		/* primary channel is at upper subband of 40MHz */
1938 		if (ch_offset40== HAL_PRIME_CHNL_OFFSET_UPPER)
1939 			pri_ch_idx = VHT_DATA_SC_20_UPPER_OF_80MHZ;
1940 		/* primary channel is at lower subband of 40MHz */
1941 		else if (ch_offset40 == HAL_PRIME_CHNL_OFFSET_LOWER)
1942 			pri_ch_idx = VHT_DATA_SC_20_LOWER_OF_80MHZ;
1943 		else
1944 			RTW_INFO("SCMapping: DONOT CARE Mode Setting\n");
1945 	}
1946 
1947 	return  pri_ch_idx;
1948 }
1949 
rtw_hal_set_mcc_ctrl_cmd_v2(PADAPTER padapter,u8 stop)1950 static void rtw_hal_set_mcc_ctrl_cmd_v2(PADAPTER padapter, u8 stop)
1951 {
1952 	u8 cmd[H2C_MCC_CTRL_LEN] = {0}, i = 0;
1953 	u8 order = 0, totalnum = 0;
1954 	u8 center_ch = 0, pri_ch_idx = 0, bw = 0;
1955 	u8 duration = 0, role = 0, incurch = 0, rfetype = 0, distxnull = 0, c2hrpt = 0;
1956 	u8 dis_sw_retry = 0, null_early_time=2, tsfx = 0, update_parm = 0;
1957 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
1958 	struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
1959 	struct mcc_adapter_priv *mccadapriv = NULL;
1960 	struct mlme_ext_priv *pmlmeext = NULL;
1961 	struct mlme_ext_info *pmlmeinfo = NULL;
1962 	_adapter *iface = NULL;
1963 
1964 	RTW_INFO(FUNC_ADPT_FMT": stop=%d\n", FUNC_ADPT_ARG(padapter), stop);
1965 
1966 	for (i = 0; i < MAX_MCC_NUM; i++) {
1967 		iface = pmccobjpriv->iface[i];
1968 		if (iface == NULL)
1969 			continue;
1970 
1971 		if (stop) {
1972 			if (iface != padapter)
1973 				continue;
1974 		}
1975 
1976 		mccadapriv = &iface->mcc_adapterpriv;
1977 		order = mccadapriv->order;
1978 
1979 		if (!stop)
1980 			totalnum = MAX_MCC_NUM;
1981 		else
1982 			totalnum = 0xff; /* 0xff means stop */
1983 
1984 		pmlmeext = &iface->mlmeextpriv;
1985 		center_ch = rtw_get_center_ch(pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
1986 		pri_ch_idx = get_pri_ch_idx_by_adapter(center_ch, pmlmeext->cur_channel, pmlmeext->cur_bwmode, pmlmeext->cur_ch_offset);
1987 		bw = pmlmeext->cur_bwmode;
1988 		duration = mccadapriv->mcc_duration;
1989 		role = mccadapriv->role;
1990 
1991 		incurch = _FALSE;
1992 		dis_sw_retry = _TRUE;
1993 
1994 		/* STA/GC TX NULL data to inform AP/GC for ps mode */
1995 		switch (role) {
1996 		case MCC_ROLE_GO:
1997 		case MCC_ROLE_AP:
1998 			distxnull = MCC_DISABLE_TX_NULL;
1999 			break;
2000 		case MCC_ROLE_GC:
2001 			set_channel_bwmode(iface, pmlmeext->cur_channel, pmlmeext->cur_ch_offset, pmlmeext->cur_bwmode);
2002 			distxnull = MCC_ENABLE_TX_NULL;
2003 			break;
2004 		case MCC_ROLE_STA:
2005 			distxnull = MCC_ENABLE_TX_NULL;
2006 			break;
2007 		}
2008 
2009 		null_early_time = mccadapriv->null_early;
2010 
2011 		c2hrpt = MCC_C2H_REPORT_ALL_STATUS;
2012 		tsfx = rtw_hal_get_port(iface);
2013 		update_parm = 0;
2014 
2015 		SET_H2CCMD_MCC_CTRL_V2_ORDER(cmd, order);
2016 		SET_H2CCMD_MCC_CTRL_V2_TOTALNUM(cmd, totalnum);
2017 		SET_H2CCMD_MCC_CTRL_V2_CENTRAL_CH(cmd, center_ch);
2018 		SET_H2CCMD_MCC_CTRL_V2_PRIMARY_CH(cmd, pri_ch_idx);
2019 		SET_H2CCMD_MCC_CTRL_V2_BW(cmd, bw);
2020 		SET_H2CCMD_MCC_CTRL_V2_DURATION(cmd, duration);
2021 		SET_H2CCMD_MCC_CTRL_V2_ROLE(cmd, role);
2022 		SET_H2CCMD_MCC_CTRL_V2_INCURCH(cmd, incurch);
2023 		SET_H2CCMD_MCC_CTRL_V2_DIS_SW_RETRY(cmd, dis_sw_retry);
2024 		SET_H2CCMD_MCC_CTRL_V2_DISTXNULL(cmd, distxnull);
2025 		SET_H2CCMD_MCC_CTRL_V2_C2HRPT(cmd, c2hrpt);
2026 		SET_H2CCMD_MCC_CTRL_V2_TSFX(cmd, tsfx);
2027 		SET_H2CCMD_MCC_CTRL_V2_NULL_EARLY(cmd, null_early_time);
2028 		SET_H2CCMD_MCC_CTRL_V2_UPDATE_PARM(cmd, update_parm);
2029 
2030 #ifdef CONFIG_MCC_MODE_DEBUG
2031 		RTW_INFO("=========================\n");
2032 		RTW_INFO(FUNC_ADPT_FMT" MCC INFO:\n", FUNC_ADPT_ARG(iface));
2033 		RTW_INFO("cmd[0]:0x%02x\n", cmd[0]);
2034 		RTW_INFO("cmd[1]:0x%02x\n", cmd[1]);
2035 		RTW_INFO("cmd[2]:0x%02x\n", cmd[2]);
2036 		RTW_INFO("cmd[3]:0x%02x\n", cmd[3]);
2037 		RTW_INFO("cmd[4]:0x%02x\n", cmd[4]);
2038 		RTW_INFO("cmd[5]:0x%02x\n", cmd[5]);
2039 		RTW_INFO("cmd[6]:0x%02x\n", cmd[6]);
2040 		RTW_INFO("=========================\n");
2041 #endif /* CONFIG_MCC_MODE_DEBUG */
2042 
2043 		rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_CTRL_V2, H2C_MCC_CTRL_LEN, cmd);
2044 	}
2045 }
2046 
2047 #else
rtw_hal_set_mcc_ctrl_cmd_v1(PADAPTER padapter,u8 stop)2048 static void rtw_hal_set_mcc_ctrl_cmd_v1(PADAPTER padapter, u8 stop)
2049 {
2050 	u8 cmd[H2C_MCC_CTRL_LEN] = {0}, i = 0;
2051 	u8 order = 0, totalnum = 0, chidx = 0, bw = 0, bw40sc = 0, bw80sc = 0;
2052 	u8 duration = 0, role = 0, incurch = 0, rfetype = 0, distxnull = 0, c2hrpt = 0, chscan = 0;
2053 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2054 	struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
2055 	struct mcc_adapter_priv *mccadapriv = NULL;
2056 	struct mlme_ext_priv *pmlmeext = NULL;
2057 	struct mlme_ext_info *pmlmeinfo = NULL;
2058 	HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
2059 	_adapter *iface = NULL;
2060 
2061 	RTW_INFO(FUNC_ADPT_FMT": stop=%d\n", FUNC_ADPT_ARG(padapter), stop);
2062 
2063 	for (i = 0; i < MAX_MCC_NUM; i++) {
2064 		iface = pmccobjpriv->iface[i];
2065 		if (iface == NULL)
2066 			continue;
2067 
2068 		if (stop) {
2069 			if (iface != padapter)
2070 				continue;
2071 		}
2072 
2073 		mccadapriv = &iface->mcc_adapterpriv;
2074 		order = mccadapriv->order;
2075 
2076 		if (!stop)
2077 			totalnum = MAX_MCC_NUM;
2078 		else
2079 			totalnum = 0xff; /* 0xff means stop */
2080 
2081 		pmlmeext = &iface->mlmeextpriv;
2082 		chidx = pmlmeext->cur_channel;
2083 		bw = pmlmeext->cur_bwmode;
2084 		bw40sc = pmlmeext->cur_ch_offset;
2085 
2086 		/* decide 80 band width offset */
2087 		if (bw == CHANNEL_WIDTH_80) {
2088 			u8 center_ch = rtw_get_center_ch(chidx, bw, bw40sc);
2089 
2090 			if (center_ch > chidx)
2091 				bw80sc = HAL_PRIME_CHNL_OFFSET_LOWER;
2092 			else if (center_ch < chidx)
2093 				bw80sc = HAL_PRIME_CHNL_OFFSET_UPPER;
2094 			else
2095 				bw80sc = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2096 		} else
2097 			bw80sc = HAL_PRIME_CHNL_OFFSET_DONT_CARE;
2098 
2099 		duration = mccadapriv->mcc_duration;
2100 		role = mccadapriv->role;
2101 
2102 		incurch = _FALSE;
2103 
2104 		if (IS_HARDWARE_TYPE_8812(padapter))
2105 			rfetype = pHalData->rfe_type; /* RFETYPE (only for 8812)*/
2106 		else
2107 			rfetype = 0;
2108 
2109 		/* STA/GC TX NULL data to inform AP/GC for ps mode */
2110 		switch (role) {
2111 		case MCC_ROLE_GO:
2112 		case MCC_ROLE_AP:
2113 			distxnull = MCC_DISABLE_TX_NULL;
2114 			break;
2115 		case MCC_ROLE_GC:
2116 		case MCC_ROLE_STA:
2117 			distxnull = MCC_ENABLE_TX_NULL;
2118 			break;
2119 		}
2120 
2121 		c2hrpt = MCC_C2H_REPORT_ALL_STATUS;
2122 		chscan = MCC_CHIDX;
2123 
2124 		SET_H2CCMD_MCC_CTRL_ORDER(cmd, order);
2125 		SET_H2CCMD_MCC_CTRL_TOTALNUM(cmd, totalnum);
2126 		SET_H2CCMD_MCC_CTRL_CHIDX(cmd, chidx);
2127 		SET_H2CCMD_MCC_CTRL_BW(cmd, bw);
2128 		SET_H2CCMD_MCC_CTRL_BW40SC(cmd, bw40sc);
2129 		SET_H2CCMD_MCC_CTRL_BW80SC(cmd, bw80sc);
2130 		SET_H2CCMD_MCC_CTRL_DURATION(cmd, duration);
2131 		SET_H2CCMD_MCC_CTRL_ROLE(cmd, role);
2132 		SET_H2CCMD_MCC_CTRL_INCURCH(cmd, incurch);
2133 		SET_H2CCMD_MCC_CTRL_RFETYPE(cmd, rfetype);
2134 		SET_H2CCMD_MCC_CTRL_DISTXNULL(cmd, distxnull);
2135 		SET_H2CCMD_MCC_CTRL_C2HRPT(cmd, c2hrpt);
2136 		SET_H2CCMD_MCC_CTRL_CHSCAN(cmd, chscan);
2137 
2138 #ifdef CONFIG_MCC_MODE_DEBUG
2139 		RTW_INFO("=========================\n");
2140 		RTW_INFO(FUNC_ADPT_FMT" MCC INFO:\n", FUNC_ADPT_ARG(iface));
2141 		RTW_INFO("cmd[0]:0x%02x\n", cmd[0]);
2142 		RTW_INFO("cmd[1]:0x%02x\n", cmd[1]);
2143 		RTW_INFO("cmd[2]:0x%02x\n", cmd[2]);
2144 		RTW_INFO("cmd[3]:0x%02x\n", cmd[3]);
2145 		RTW_INFO("cmd[4]:0x%02x\n", cmd[4]);
2146 		RTW_INFO("cmd[5]:0x%02x\n", cmd[5]);
2147 		RTW_INFO("cmd[6]:0x%02x\n", cmd[6]);
2148 		RTW_INFO("=========================\n");
2149 #endif /* CONFIG_MCC_MODE_DEBUG */
2150 
2151 		rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_CTRL, H2C_MCC_CTRL_LEN, cmd);
2152 	}
2153 }
2154 #endif
2155 
rtw_hal_set_mcc_ctrl_cmd(PADAPTER padapter,u8 stop)2156 static void rtw_hal_set_mcc_ctrl_cmd(PADAPTER padapter, u8 stop)
2157 {
2158 	#ifdef CONFIG_MCC_MODE_V2
2159 		/* new cmd 0x17 */
2160 		rtw_hal_set_mcc_ctrl_cmd_v2(padapter, stop);
2161 	#else
2162 		/* old cmd 0x18 */
2163 		rtw_hal_set_mcc_ctrl_cmd_v1(padapter, stop);
2164 	#endif
2165 }
2166 
check_mcc_support(PADAPTER adapter)2167 static u8 check_mcc_support(PADAPTER adapter)
2168 {
2169 	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
2170 	u8 sta_linked_num = DEV_STA_LD_NUM(dvobj);
2171 	u8 starting_ap_num = DEV_AP_STARTING_NUM(dvobj);
2172 	u8 ap_num = DEV_AP_NUM(dvobj);
2173 	u8 ret = _FAIL;
2174 
2175 	RTW_INFO("[MCC] sta_linked_num=%d, starting_ap_num=%d,ap_num=%d\n",
2176 		sta_linked_num, starting_ap_num, ap_num);
2177 
2178 	/* case for sta + sta case  */
2179 	if (sta_linked_num == MAX_MCC_NUM) {
2180 		ret = _SUCCESS;
2181 		goto exit;
2182 	}
2183 
2184 	/* case for starting AP + linked sta */
2185 	if ((starting_ap_num + sta_linked_num) == MAX_MCC_NUM) {
2186 		ret = _SUCCESS;
2187 		goto exit;
2188 	}
2189 
2190 	/* case for started AP + linked sta */
2191 	if ((ap_num + sta_linked_num) == MAX_MCC_NUM) {
2192 		ret = _SUCCESS;
2193 		goto exit;
2194 	}
2195 
2196 exit:
2197 		return ret;
2198 }
2199 
rtw_hal_mcc_start_prehdl(PADAPTER padapter)2200 static void rtw_hal_mcc_start_prehdl(PADAPTER padapter)
2201 {
2202 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2203 	_adapter *iface = NULL;
2204 	struct mcc_adapter_priv *mccadapriv = NULL;
2205 	u8 i = 1;
2206 
2207 	for (i = 0; i < dvobj->iface_nums; i++) {
2208 		iface = dvobj->padapters[i];
2209 		if (iface == NULL)
2210 			continue;
2211 
2212 		mccadapriv = &iface->mcc_adapterpriv;
2213 		mccadapriv->role = MCC_ROLE_MAX;
2214 	}
2215 }
2216 
rtw_hal_set_mcc_start_setting(PADAPTER padapter,u8 status)2217 static u8 rtw_hal_set_mcc_start_setting(PADAPTER padapter, u8 status)
2218 {
2219 	u8 ret = _SUCCESS, enable_tsf_auto_sync = _FALSE;
2220 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2221 	struct pwrctrl_priv *pwrpriv = dvobj_to_pwrctl(dvobj);
2222 
2223 	if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
2224 		rtw_warn_on(1);
2225 		RTW_INFO("PS mode is not active before start mcc, force exit ps mode\n");
2226 		LeaveAllPowerSaveModeDirect(padapter);
2227 	}
2228 
2229 	if (check_mcc_support(padapter) == _FAIL) {
2230 		ret = _FAIL;
2231 		goto exit;
2232 	}
2233 
2234 	rtw_hal_mcc_start_prehdl(padapter);
2235 
2236 	/* configure mcc switch channel setting */
2237 	rtw_hal_config_mcc_switch_channel_setting(padapter);
2238 
2239 	if (rtw_hal_decide_mcc_role(padapter) == _FAIL) {
2240 		ret = _FAIL;
2241 		goto exit;
2242 	}
2243 
2244 	/* set mcc status to indicate process mcc start setting */
2245 	rtw_hal_set_mcc_status(padapter, MCC_STATUS_PROCESS_MCC_START_SETTING);
2246 
2247 	/* only download rsvd page for connect */
2248 	if (status == MCC_SETCMD_STATUS_START_CONNECT) {
2249 		/* download mcc rsvd page */
2250 		rtw_hal_set_fw_mcc_rsvd_page(padapter);
2251 		rtw_hal_set_mcc_rsvdpage_cmd(padapter);
2252 	}
2253 
2254 	/* configure time setting */
2255 	rtw_hal_set_mcc_time_setting_cmd(padapter);
2256 
2257 #ifndef CONFIG_MCC_MODE_V2
2258 	/* IQK value offload */
2259 	rtw_hal_set_mcc_IQK_offload_cmd(padapter);
2260 #endif
2261 
2262 	/* set mac id to fw */
2263 	rtw_hal_set_mcc_macid_cmd(padapter);
2264 
2265 	if (dvobj->p0_tsf.sync_port != MAX_HW_PORT ) {
2266 		/* disable tsf auto sync */
2267 		RTW_INFO("[MCC] disable HW TSF sync\n");
2268 		rtw_hal_set_hwreg(padapter, HW_VAR_TSF_AUTO_SYNC, &enable_tsf_auto_sync);
2269 	} else {
2270 		RTW_INFO("[MCC] already disable HW TSF sync\n");
2271 	}
2272 
2273 	/* set mcc parameter  */
2274 	rtw_hal_set_mcc_ctrl_cmd(padapter, _FALSE);
2275 
2276 exit:
2277 	return ret;
2278 }
2279 
rtw_hal_set_mcc_stop_setting(PADAPTER padapter,u8 status)2280 static void rtw_hal_set_mcc_stop_setting(PADAPTER padapter, u8 status)
2281 {
2282 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2283 	struct mcc_obj_priv *mccobjpriv = &dvobj->mcc_objpriv;
2284 	_adapter *iface = NULL;
2285 	struct mcc_adapter_priv *mccadapriv = NULL;
2286 	u8 i = 0;
2287 	/*
2288 	 * when adapter disconnect, stop mcc mod
2289 	 * total=0xf means stop mcc mode
2290 	 */
2291 
2292 	switch (status) {
2293 	default:
2294 		/* let fw switch to other interface channel */
2295 		for (i = 0; i < MAX_MCC_NUM; i++) {
2296 			iface = mccobjpriv->iface[i];
2297 			if (iface == NULL)
2298 				continue;
2299 
2300 			mccadapriv = &iface->mcc_adapterpriv;
2301 
2302 			/* use other interface to set cmd */
2303 			if (iface != padapter) {
2304 				rtw_hal_set_mcc_ctrl_cmd(iface, _TRUE);
2305 				break;
2306 			}
2307 		}
2308 		break;
2309 	}
2310 }
2311 
rtw_hal_mcc_status_hdl(PADAPTER padapter,u8 status)2312 static void rtw_hal_mcc_status_hdl(PADAPTER padapter, u8 status)
2313 {
2314 	switch (status) {
2315 	case MCC_SETCMD_STATUS_STOP_DISCONNECT:
2316 		rtw_hal_clear_mcc_status(padapter, MCC_STATUS_NEED_MCC | MCC_STATUS_DOING_MCC);
2317 		break;
2318 	case MCC_SETCMD_STATUS_STOP_SCAN_START:
2319 		rtw_hal_set_mcc_status(padapter, MCC_STATUS_NEED_MCC);
2320 		rtw_hal_clear_mcc_status(padapter, MCC_STATUS_DOING_MCC);
2321 		break;
2322 
2323 	case MCC_SETCMD_STATUS_START_CONNECT:
2324 	case MCC_SETCMD_STATUS_START_SCAN_DONE:
2325 		rtw_hal_set_mcc_status(padapter, MCC_STATUS_NEED_MCC | MCC_STATUS_DOING_MCC);
2326 		break;
2327 	default:
2328 		RTW_INFO(FUNC_ADPT_FMT" error status(%d)\n", FUNC_ADPT_ARG(padapter), status);
2329 		break;
2330 	}
2331 }
2332 
rtw_hal_mcc_stop_posthdl(PADAPTER padapter)2333 static void rtw_hal_mcc_stop_posthdl(PADAPTER padapter)
2334 {
2335 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2336 	struct mcc_obj_priv *mccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
2337 	struct mcc_adapter_priv *mccadapriv = NULL;
2338 	_adapter *iface = NULL;
2339 	PHAL_DATA_TYPE hal;
2340 	u8 i = 0;
2341 	u8 enable_rx_bar = _FALSE;
2342 
2343 	hal = GET_HAL_DATA(padapter);
2344 
2345 	for (i = 0; i < MAX_MCC_NUM; i++) {
2346 		iface = mccobjpriv->iface[i];
2347 		if (iface == NULL)
2348 			continue;
2349 
2350 		/* release network queue */
2351 		rtw_netif_wake_queue(iface->pnetdev);
2352 		mccadapriv = &iface->mcc_adapterpriv;
2353 		mccadapriv->mcc_tx_bytes_from_kernel = 0;
2354 		mccadapriv->mcc_last_tx_bytes_from_kernel = 0;
2355 		mccadapriv->mcc_tx_bytes_to_port = 0;
2356 
2357 		if (mccadapriv->role == MCC_ROLE_GO)
2358 			rtw_hal_mcc_remove_go_p2p_ie(iface);
2359 
2360 #ifdef CONFIG_TDLS
2361 		if (MLME_IS_STA(iface)) {
2362 			if (mccadapriv->backup_tdls_en) {
2363 				rtw_enable_tdls_func(iface);
2364 				RTW_INFO("%s: Disable MCC, Enable TDLS\n", __func__);
2365 				mccadapriv->backup_tdls_en = _FALSE;
2366 			}
2367 		}
2368 #endif /* CONFIG_TDLS */
2369 
2370 		mccadapriv->role = MCC_ROLE_MAX;
2371 		mccobjpriv->iface[i] = NULL;
2372 	}
2373 
2374 	/* force switch channel */
2375 	hal->current_channel = 0;
2376 	hal->current_channel_bw = CHANNEL_WIDTH_MAX;
2377 	#ifdef CONFIG_MCC_PHYDM_OFFLOAD
2378 	rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_STOP, NULL);
2379 	#endif
2380 }
2381 
rtw_hal_mcc_start_posthdl(PADAPTER padapter)2382 static void rtw_hal_mcc_start_posthdl(PADAPTER padapter)
2383 {
2384 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2385 	struct mcc_obj_priv *mccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
2386 	struct mcc_adapter_priv *mccadapriv = NULL;
2387 	struct pwrctrl_priv	*pwrpriv = adapter_to_pwrctl(padapter);
2388 	_adapter *iface = NULL;
2389 	u8 i = 0, order = 0;
2390 	u8 enable_rx_bar = _TRUE;
2391 
2392 	for (i = 0; i < MAX_MCC_NUM; i++) {
2393 		iface = mccobjpriv->iface[i];
2394 		if (iface == NULL)
2395 			continue;
2396 
2397 		mccadapriv = &iface->mcc_adapterpriv;
2398 		if (mccadapriv->role == MCC_ROLE_MAX)
2399 			continue;
2400 
2401 		mccadapriv->mcc_tx_bytes_from_kernel = 0;
2402 		mccadapriv->mcc_last_tx_bytes_from_kernel = 0;
2403 		mccadapriv->mcc_tx_bytes_to_port = 0;
2404 
2405 #ifdef CONFIG_TDLS
2406 		if (MLME_IS_STA(iface)) {
2407 			if (rtw_is_tdls_enabled(iface)) {
2408 				mccadapriv->backup_tdls_en = _TRUE;
2409 				rtw_disable_tdls_func(iface, _TRUE);
2410 				RTW_INFO("%s: Enable MCC, Disable TDLS\n", __func__);
2411 			}
2412 		}
2413 #endif /* CONFIG_TDLS */
2414 	}
2415 	#ifdef CONFIG_MCC_PHYDM_OFFLOAD
2416 	rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_START, NULL);
2417 	#endif
2418 }
2419 
2420 /*
2421  * rtw_hal_set_mcc_setting - set mcc setting
2422  * @padapter: currnet padapter to stop/start MCC
2423  * @stop: stop mcc or not
2424  * @return val: 1 for SUCCESS, 0 for fail
2425  */
rtw_hal_set_mcc_setting(PADAPTER padapter,u8 status)2426 static u8 rtw_hal_set_mcc_setting(PADAPTER padapter, u8 status)
2427 {
2428 	u8 ret = _FAIL;
2429 	struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
2430 	u8 stop = (status < MCC_SETCMD_STATUS_START_CONNECT) ? _TRUE : _FALSE;
2431 	u32 start_time = rtw_get_current_time();
2432 
2433 	RTW_INFO("===> "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
2434 
2435 	rtw_sctx_init(&pmccobjpriv->mcc_sctx, MCC_EXPIRE_TIME);
2436 	pmccobjpriv->mcc_c2h_status = MCC_RPT_MAX;
2437 
2438 	if (stop == _FALSE) {
2439 		/* handle mcc start */
2440 		if (rtw_hal_set_mcc_start_setting(padapter, status) == _FAIL)
2441 			goto exit;
2442 
2443 		/* wait for C2H */
2444 		if (!rtw_sctx_wait(&pmccobjpriv->mcc_sctx, __func__))
2445 			RTW_INFO(FUNC_ADPT_FMT": wait for mcc start C2H time out\n", FUNC_ADPT_ARG(padapter));
2446 		else
2447 			ret = _SUCCESS;
2448 
2449 		if (ret == _SUCCESS) {
2450 			RTW_INFO(FUNC_ADPT_FMT": mcc start sucecssfully\n", FUNC_ADPT_ARG(padapter));
2451 			rtw_hal_mcc_status_hdl(padapter, status);
2452 			rtw_hal_mcc_start_posthdl(padapter);
2453 		}
2454 	} else {
2455 
2456 		/* set mcc status to indicate process mcc start setting */
2457 		rtw_hal_set_mcc_status(padapter, MCC_STATUS_PROCESS_MCC_STOP_SETTING);
2458 
2459 		/* handle mcc stop */
2460 		rtw_hal_set_mcc_stop_setting(padapter, status);
2461 
2462 		/* wait for C2H */
2463 		if (!rtw_sctx_wait(&pmccobjpriv->mcc_sctx, __func__))
2464 			RTW_INFO(FUNC_ADPT_FMT": wait for mcc stop C2H time out\n", FUNC_ADPT_ARG(padapter));
2465 		else {
2466 			ret = _SUCCESS;
2467 			rtw_hal_mcc_status_hdl(padapter, status);
2468 			rtw_hal_mcc_stop_posthdl(padapter);
2469 		}
2470 	}
2471 
2472 exit:
2473 	/* clear mcc status */
2474 	rtw_hal_clear_mcc_status(padapter
2475 		, MCC_STATUS_PROCESS_MCC_START_SETTING | MCC_STATUS_PROCESS_MCC_STOP_SETTING);
2476 
2477 	RTW_INFO(FUNC_ADPT_FMT" in %dms <===\n"
2478 		, FUNC_ADPT_ARG(padapter), rtw_get_passing_time_ms(start_time));
2479 	return ret;
2480 }
2481 
2482 /**
2483  * rtw_hal_mcc_check_case_not_limit_traffic - handler flow ctrl for special case
2484  * @cur_iface: fw stay channel setting of this iface
2485  * @next_iface: fw will swich channel setting of this iface
2486  */
rtw_hal_mcc_check_case_not_limit_traffic(PADAPTER cur_iface,PADAPTER next_iface)2487 static void rtw_hal_mcc_check_case_not_limit_traffic(PADAPTER cur_iface, PADAPTER next_iface)
2488 {
2489 	u8 cur_bw = cur_iface->mlmeextpriv.cur_bwmode;
2490 	u8 next_bw = next_iface->mlmeextpriv.cur_bwmode;
2491 
2492 	/* for both interface are VHT80, doesn't limit_traffic according to iperf results */
2493 	if (cur_bw == CHANNEL_WIDTH_80 && next_bw == CHANNEL_WIDTH_80) {
2494 		cur_iface->mcc_adapterpriv.mcc_tp_limit = _FALSE;
2495 		next_iface->mcc_adapterpriv.mcc_tp_limit = _FALSE;
2496 	}
2497 }
2498 
2499 
2500 /**
2501  * rtw_hal_mcc_sw_ch_fw_notify_hdl - handler flow ctrl
2502  */
rtw_hal_mcc_sw_ch_fw_notify_hdl(PADAPTER padapter)2503 static void rtw_hal_mcc_sw_ch_fw_notify_hdl(PADAPTER padapter)
2504 {
2505 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
2506 	struct mcc_obj_priv *pmccobjpriv = &(pdvobjpriv->mcc_objpriv);
2507 	struct mcc_adapter_priv *cur_mccadapriv = NULL, *next_mccadapriv = NULL;
2508 	_adapter *iface = NULL, *cur_iface = NULL, *next_iface = NULL;
2509 	struct registry_priv *preg = &padapter->registrypriv;
2510 	u8 cur_op_ch = pdvobjpriv->oper_channel;
2511 	u8 i = 0, iface_num = pdvobjpriv->iface_nums, cur_order = 0, next_order = 0;
2512 	static u8 cnt = 1;
2513 	u32 single_tx_cri = preg->rtw_mcc_single_tx_cri;
2514 
2515 	for (i = 0; i < iface_num; i++) {
2516 		iface = pdvobjpriv->padapters[i];
2517 		if (iface == NULL)
2518 			continue;
2519 
2520 		if (cur_op_ch == iface->mlmeextpriv.cur_channel) {
2521 			cur_iface = iface;
2522 			cur_mccadapriv = &cur_iface->mcc_adapterpriv;
2523 			cur_order = cur_mccadapriv->order;
2524 			next_order = (cur_order + 1) % iface_num;
2525 			next_iface = pmccobjpriv->iface[next_order];
2526 			next_mccadapriv = &next_iface->mcc_adapterpriv;
2527 			break;
2528 		}
2529 	}
2530 
2531 	if (cur_iface == NULL || next_iface == NULL) {
2532 		RTW_ERR("cur_iface=%p,next_iface=%p\n", cur_iface, next_iface);
2533 		rtw_warn_on(1);
2534 		return;
2535 	}
2536 
2537 	/* check other interface tx busy traffic or not under every 2 switch channel notify(Mbits/100ms) */
2538 	if (cnt == 2) {
2539 		cur_mccadapriv->mcc_tp = (cur_mccadapriv->mcc_tx_bytes_from_kernel
2540 			- cur_mccadapriv->mcc_last_tx_bytes_from_kernel) * 10 * 8 / 1024 / 1024;
2541 		cur_mccadapriv->mcc_last_tx_bytes_from_kernel = cur_mccadapriv->mcc_tx_bytes_from_kernel;
2542 
2543 		next_mccadapriv->mcc_tp = (next_mccadapriv->mcc_tx_bytes_from_kernel
2544 			- next_mccadapriv->mcc_last_tx_bytes_from_kernel) * 10 * 8 / 1024 / 1024;
2545 		next_mccadapriv->mcc_last_tx_bytes_from_kernel = next_mccadapriv->mcc_tx_bytes_from_kernel;
2546 
2547 		cnt = 1;
2548 	} else
2549 		cnt = 2;
2550 
2551 	/* check single TX or cuncurrnet TX */
2552 	if (next_mccadapriv->mcc_tp < single_tx_cri) {
2553 		/* single TX, does not stop */
2554 		cur_mccadapriv->mcc_tx_stop = _FALSE;
2555 		cur_mccadapriv->mcc_tp_limit = _FALSE;
2556 	} else {
2557 		/* concurrent TX, stop */
2558 		cur_mccadapriv->mcc_tx_stop = _TRUE;
2559 		cur_mccadapriv->mcc_tp_limit = _TRUE;
2560 	}
2561 
2562 	if (cur_mccadapriv->mcc_tp < single_tx_cri) {
2563 		next_mccadapriv->mcc_tx_stop  = _FALSE;
2564 		next_mccadapriv->mcc_tp_limit = _FALSE;
2565 	} else {
2566 		next_mccadapriv->mcc_tx_stop = _FALSE;
2567 		next_mccadapriv->mcc_tp_limit = _TRUE;
2568 		next_mccadapriv->mcc_tx_bytes_to_port = 0;
2569 	}
2570 
2571 	/* stop current iface kernel queue or not */
2572 	if (cur_mccadapriv->mcc_tx_stop)
2573 		rtw_netif_stop_queue(cur_iface->pnetdev);
2574 	else
2575 		rtw_netif_wake_queue(cur_iface->pnetdev);
2576 
2577 	/* stop next iface kernel queue or not */
2578 	if (next_mccadapriv->mcc_tx_stop)
2579 		rtw_netif_stop_queue(next_iface->pnetdev);
2580 	else
2581 		rtw_netif_wake_queue(next_iface->pnetdev);
2582 
2583 	/* start xmit tasklet */
2584 	rtw_os_xmit_schedule(next_iface);
2585 
2586 	rtw_hal_mcc_check_case_not_limit_traffic(cur_iface, next_iface);
2587 
2588 	if (0) {
2589 		RTW_INFO("order:%d, mcc_tx_stop:%d, mcc_tp:%d\n",
2590 			cur_mccadapriv->order, cur_mccadapriv->mcc_tx_stop, cur_mccadapriv->mcc_tp);
2591 		dump_os_queue(0, cur_iface);
2592 		RTW_INFO("order:%d, mcc_tx_stop:%d, mcc_tp:%d\n",
2593 			next_mccadapriv->order, next_mccadapriv->mcc_tx_stop, next_mccadapriv->mcc_tp);
2594 		dump_os_queue(0, next_iface);
2595 	}
2596 }
2597 
rtw_hal_mcc_update_noa_start_time_hdl(PADAPTER padapter,u8 buflen,u8 * tmpBuf)2598 static void rtw_hal_mcc_update_noa_start_time_hdl(PADAPTER padapter, u8 buflen, u8 *tmpBuf)
2599 {
2600 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
2601 	struct mcc_obj_priv *pmccobjpriv = &(pdvobjpriv->mcc_objpriv);
2602 	struct mcc_adapter_priv *pmccadapriv = NULL;
2603 	PADAPTER iface = NULL;
2604 	u8 i = 0;
2605 	u8 policy_idx = pmccobjpriv->policy_index;
2606 	u8 noa_tsf_sync_offset = mcc_switch_channel_policy_table[policy_idx][MCC_TSF_SYNC_OFFSET_IDX];
2607 	u8 noa_start_time_offset = mcc_switch_channel_policy_table[policy_idx][MCC_START_TIME_OFFSET_IDX];
2608 
2609 	for (i = 0; i < pdvobjpriv->iface_nums; i++) {
2610 		iface = pdvobjpriv->padapters[i];
2611 		if (iface == NULL)
2612 			continue;
2613 
2614 		pmccadapriv = &iface->mcc_adapterpriv;
2615 		if (pmccadapriv->role == MCC_ROLE_MAX)
2616 			continue;
2617 
2618 		/* GO & channel match */
2619 		if (pmccadapriv->role == MCC_ROLE_GO) {
2620 			/* convert GO TBTT from FW to noa_start_time(TU convert to mircosecond) */
2621 			pmccadapriv->noa_start_time = RTW_GET_LE32(tmpBuf + 2) + noa_start_time_offset * TU;
2622 
2623 			if (0) {
2624 				RTW_INFO("TBTT:0x%02x\n", RTW_GET_LE32(tmpBuf + 2));
2625 				RTW_INFO("noa_tsf_sync_offset:%d, noa_start_time_offset:%d\n", noa_tsf_sync_offset, noa_start_time_offset);
2626 				RTW_INFO(FUNC_ADPT_FMT"buf=0x%02x:0x%02x:0x%02x:0x%02x, noa_start_time=0x%02x\n"
2627 					, FUNC_ADPT_ARG(iface)
2628 					, tmpBuf[2]
2629 					, tmpBuf[3]
2630 					, tmpBuf[4]
2631 					, tmpBuf[5]
2632 					,pmccadapriv->noa_start_time);
2633 				}
2634 
2635 			rtw_hal_mcc_update_go_p2p_ie(iface);
2636 
2637 			break;
2638 		}
2639 	}
2640 
2641 }
2642 
mcc_get_reg_hdl(PADAPTER adapter,const u8 * val)2643 static u8 mcc_get_reg_hdl(PADAPTER adapter, const u8 *val)
2644 {
2645 	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
2646 	struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
2647 	struct hal_com_data *hal = GET_HAL_DATA(adapter);
2648 	_adapter *cur_iface = NULL;
2649 	u8 ret = _SUCCESS;
2650 	u8 cur_order = 0;
2651 
2652 	u16 dbg_reg[DBG_MCC_REG_NUM] = {0x4d4,0x522,0xc50,0xe50};
2653 	u16 dbg_rf_reg[DBG_MCC_RF_REG_NUM] = {0x18};
2654 	u8 i;
2655 	u32 reg_val;
2656 	u8 path = 0, path_nums = 0;
2657 
2658 	if (!rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC)) {
2659 		ret = _FAIL;
2660 		goto exit;
2661 	}
2662 
2663 	if (!val)
2664 		cur_order = 0xff;
2665 	else
2666 		cur_order = *val;
2667 
2668 	if (cur_order >= MAX_MCC_NUM && cur_order != 0xff) {
2669 		RTW_ERR("%s: cur_order=%d\n", __func__, cur_order);
2670 		ret = _FAIL;
2671 		goto exit;
2672 	}
2673 
2674 	path_nums = hal->NumTotalRFPath;
2675 	if (cur_order == 0xff)
2676 		cur_iface = adapter;
2677 	else
2678 		cur_iface = mccobjpriv->iface[cur_order];
2679 
2680 	if (!cur_iface) {
2681 		RTW_ERR("%s: cur_iface = NULL,  cur_order=%d\n", __func__, cur_order);
2682 		ret = _FAIL;
2683 		goto exit;
2684 	}
2685 
2686 	_enter_critical_mutex(&mccobjpriv->mcc_dbg_reg_mutex, NULL);
2687 	if (!RTW_CANNOT_IO(adapter)) {
2688 		/* RTW_INFO("=================================\n");
2689 		RTW_INFO(ADPT_FMT": cur_order:%d\n", ADPT_ARG(cur_iface), cur_order); */
2690 
2691 		for (i = 0; i < ARRAY_SIZE(dbg_reg); i++) {
2692 			reg_val = rtw_read32(adapter, dbg_reg[i]);
2693 			mccobjpriv->dbg_reg[i] = dbg_reg[i];
2694 			mccobjpriv->dbg_reg_val[i] = reg_val;
2695 			/* RTW_PRINT("REG_%X:0x%08x\n", dbg_reg[i], reg_val); */
2696 		}
2697 		for (i = 0; i < ARRAY_SIZE(dbg_rf_reg); i++) {
2698 			for (path = 0; path < path_nums; path++) {
2699 				reg_val = rtw_hal_read_rfreg(adapter, path, dbg_rf_reg[i], 0xffffffff);
2700 				/* RTW_PRINT("RF_PATH_%d_REG_%X:0x%08x\n",
2701 					path, dbg_rf_reg[i], reg_val); */
2702 				mccobjpriv->dbg_rf_reg[i] = dbg_rf_reg[i];
2703 				mccobjpriv->dbg_rf_reg_val[i][path] = reg_val;
2704 			}
2705 		}
2706 	}
2707 	_exit_critical_mutex(&mccobjpriv->mcc_dbg_reg_mutex, NULL);
2708 
2709 exit:
2710 	return ret;
2711 }
2712 
mcc_get_reg_cmd(_adapter * adapter,u8 cur_order)2713 static u8 mcc_get_reg_cmd(_adapter *adapter, u8 cur_order)
2714 {
2715 	struct cmd_obj *cmdobj;
2716 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
2717 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
2718 	u8 *mcc_cur_order = NULL;
2719 	u8 res = _SUCCESS;
2720 
2721 
2722 	cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
2723 	if (cmdobj == NULL) {
2724 		res = _FAIL;
2725 		goto exit;
2726 	}
2727 
2728 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
2729 	if (pdrvextra_cmd_parm == NULL) {
2730 		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2731 		res = _FAIL;
2732 		goto exit;
2733 	}
2734 
2735 	mcc_cur_order = rtw_zmalloc(sizeof(u8));
2736 	if (mcc_cur_order == NULL) {
2737 		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
2738 		rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
2739 		res = _FAIL;
2740 		goto exit;
2741 	}
2742 
2743 	pdrvextra_cmd_parm->ec_id = MCC_CMD_WK_CID;
2744 	pdrvextra_cmd_parm->type = MCC_GET_DBG_REG_WK_CID;
2745 	pdrvextra_cmd_parm->size = 1;
2746 	pdrvextra_cmd_parm->pbuf = mcc_cur_order;
2747 
2748 	_rtw_memcpy(mcc_cur_order, &cur_order, 1);
2749 
2750 	init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
2751 	res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
2752 
2753 exit:
2754 	return res;
2755 }
2756 
rtw_hal_mcc_rpt_tsf_hdl(PADAPTER padapter,u8 buflen,u8 * tmpBuf)2757 static void rtw_hal_mcc_rpt_tsf_hdl(PADAPTER padapter, u8 buflen, u8 *tmpBuf)
2758 {
2759 	struct dvobj_priv *dvobjpriv = adapter_to_dvobj(padapter);
2760 	struct mcc_obj_priv *mccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
2761 	struct submit_ctx *mcc_tsf_req_sctx = &mccobjpriv->mcc_tsf_req_sctx;
2762 	struct mcc_adapter_priv *mccadapriv = NULL;
2763 	_adapter *iface = NULL;
2764 	u8 order = 0;
2765 
2766 	order = mccobjpriv->mcc_tsf_req_sctx_order;
2767 	iface = mccobjpriv->iface[order];
2768 	mccadapriv = &iface->mcc_adapterpriv;
2769 	mccadapriv->tsf = RTW_GET_LE64(tmpBuf + 2);
2770 
2771 
2772 	if (0)
2773 		RTW_INFO(FUNC_ADPT_FMT" TSF(order:%d):0x%02llx\n", FUNC_ADPT_ARG(iface), mccadapriv->order, mccadapriv->tsf);
2774 
2775 	if (mccadapriv->order == (MAX_MCC_NUM - 1))
2776 		rtw_sctx_done(&mcc_tsf_req_sctx);
2777 	else
2778 		mccobjpriv->mcc_tsf_req_sctx_order ++;
2779 
2780 }
2781 
2782 /**
2783  * rtw_hal_mcc_c2h_handler - mcc c2h handler
2784  */
rtw_hal_mcc_c2h_handler(PADAPTER padapter,u8 buflen,u8 * tmpBuf)2785 void rtw_hal_mcc_c2h_handler(PADAPTER padapter, u8 buflen, u8 *tmpBuf)
2786 {
2787 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
2788 	struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
2789 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
2790 	struct submit_ctx *mcc_sctx = &pmccobjpriv->mcc_sctx;
2791 	_adapter *cur_adapter = NULL;
2792 	u8 cur_ch = 0, cur_bw = 0, cur_ch_offset = 0;
2793 	_irqL irqL;
2794 
2795 	/* RTW_INFO("[length]=%d, [C2H data]="MAC_FMT"\n", buflen, MAC_ARG(tmpBuf)); */
2796 	/* To avoid reg is set, but driver recive c2h to set wrong oper_channel */
2797 	if (MCC_RPT_STOPMCC == pmccobjpriv->mcc_c2h_status) {
2798 		RTW_INFO(FUNC_ADPT_FMT" MCC alread stops return\n", FUNC_ADPT_ARG(padapter));
2799 		return;
2800 	}
2801 
2802 	_enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2803 	pmccobjpriv->mcc_c2h_status = tmpBuf[0];
2804 	pmccobjpriv->current_order = tmpBuf[1];
2805 	cur_adapter = pmccobjpriv->iface[pmccobjpriv->current_order];
2806 	cur_ch = cur_adapter->mlmeextpriv.cur_channel;
2807 	cur_bw = cur_adapter->mlmeextpriv.cur_bwmode;
2808 	cur_ch_offset = cur_adapter->mlmeextpriv.cur_ch_offset;
2809 	rtw_set_oper_ch(cur_adapter, cur_ch);
2810 	rtw_set_oper_bw(cur_adapter, cur_bw);
2811 	rtw_set_oper_choffset(cur_adapter, cur_ch_offset);
2812 	_exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2813 
2814 	if (0)
2815 		RTW_INFO("%d,order:%d,TSF:0x%llx\n", tmpBuf[0], tmpBuf[1], RTW_GET_LE64(tmpBuf + 2));
2816 
2817 	switch (pmccobjpriv->mcc_c2h_status) {
2818 	case MCC_RPT_SUCCESS:
2819 		_enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2820 		pmccobjpriv->cur_mcc_success_cnt++;
2821 		rtw_hal_mcc_upadate_chnl_bw(cur_adapter, cur_ch, cur_ch_offset, cur_bw, _FALSE);
2822 		mcc_get_reg_cmd(padapter, pmccobjpriv->current_order);
2823 		_exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2824 		break;
2825 	case MCC_RPT_TXNULL_FAIL:
2826 		RTW_INFO("[MCC] TXNULL FAIL\n");
2827 		break;
2828 	case MCC_RPT_STOPMCC:
2829 		RTW_INFO("[MCC] MCC stop\n");
2830 		pmccobjpriv->mcc_c2h_status = MCC_RPT_STOPMCC;
2831 		rtw_hal_mcc_upadate_chnl_bw(cur_adapter, cur_ch, cur_ch_offset, cur_bw, _TRUE);
2832 		rtw_sctx_done(&mcc_sctx);
2833 		break;
2834 	case MCC_RPT_READY:
2835 		_enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2836 		/* initialize counter & time */
2837 		pmccobjpriv->mcc_launch_time = rtw_get_current_time();
2838 		pmccobjpriv->mcc_c2h_status = MCC_RPT_READY;
2839 		pmccobjpriv->cur_mcc_success_cnt = 0;
2840 		pmccobjpriv->prev_mcc_success_cnt = 0;
2841 		pmccobjpriv->mcc_tolerance_time = MCC_TOLERANCE_TIME;
2842 		_exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2843 
2844 		RTW_INFO("[MCC] MCC ready\n");
2845 		rtw_sctx_done(&mcc_sctx);
2846 		break;
2847 	case MCC_RPT_SWICH_CHANNEL_NOTIFY:
2848 		rtw_hal_mcc_sw_ch_fw_notify_hdl(padapter);
2849 		break;
2850 	case MCC_RPT_UPDATE_NOA_START_TIME:
2851 		rtw_hal_mcc_update_noa_start_time_hdl(padapter, buflen, tmpBuf);
2852 		break;
2853 	case MCC_RPT_TSF:
2854 		_enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2855 		rtw_hal_mcc_rpt_tsf_hdl(padapter, buflen, tmpBuf);
2856 		_exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
2857 		break;
2858 	default:
2859 		/* RTW_INFO("[MCC] Other MCC status(%d)\n", pmccobjpriv->mcc_c2h_status); */
2860 		break;
2861 	}
2862 }
2863 
rtw_hal_mcc_update_parameter(PADAPTER padapter,u8 force_update)2864 void rtw_hal_mcc_update_parameter(PADAPTER padapter, u8 force_update)
2865 {
2866 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2867 	struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
2868 	u8 cmd[H2C_MCC_TIME_SETTING_LEN] = {0};
2869 	u8 swchannel_early_time = MCC_SWCH_FW_EARLY_TIME;
2870 	u8 ap_num = DEV_AP_NUM(dvobj);
2871 
2872 	if (ap_num == 0) {
2873 		u8 need_update = _FALSE;
2874 		u8 start_time_offset = 0, interval = 0, duration = 0;
2875 
2876 		need_update = rtw_hal_mcc_update_timing_parameters(padapter, force_update);
2877 
2878 		if (need_update == _FALSE)
2879 			return;
2880 
2881 		start_time_offset = mccobjpriv->start_time;
2882 		interval = mccobjpriv->interval;
2883 		duration = mccobjpriv->iface[0]->mcc_adapterpriv.mcc_duration;
2884 
2885 		SET_H2CCMD_MCC_TIME_SETTING_START_TIME(cmd, start_time_offset);
2886 		SET_H2CCMD_MCC_TIME_SETTING_INTERVAL(cmd, interval);
2887 		SET_H2CCMD_MCC_TIME_SETTING_EARLY_SWITCH_RPT(cmd, swchannel_early_time);
2888 		SET_H2CCMD_MCC_TIME_SETTING_UPDATE(cmd, _TRUE);
2889 		SET_H2CCMD_MCC_TIME_SETTING_ORDER0_DURATION(cmd, duration);
2890 	} else {
2891 		PADAPTER order0_iface = NULL;
2892 		PADAPTER order1_iface = NULL;
2893 		u8 policy_idx = mccobjpriv->policy_index;
2894 		u8 duration = mcc_switch_channel_policy_table[policy_idx][MCC_DURATION_IDX];
2895 		u8 tsf_sync_offset = mcc_switch_channel_policy_table[policy_idx][MCC_TSF_SYNC_OFFSET_IDX];
2896 		u8 start_time_offset = mcc_switch_channel_policy_table[policy_idx][MCC_START_TIME_OFFSET_IDX];
2897 		u8 interval = mcc_switch_channel_policy_table[policy_idx][MCC_INTERVAL_IDX];
2898 		u8 guard_offset0 = mcc_switch_channel_policy_table[policy_idx][MCC_GUARD_OFFSET0_IDX];
2899 		u8 guard_offset1 = mcc_switch_channel_policy_table[policy_idx][MCC_GUARD_OFFSET1_IDX];
2900 		u8 order0_duration = 0;
2901 		u8 i = 0;
2902 		enum _hw_port tsf_bsae_port = MAX_HW_PORT;
2903 		enum _hw_port tsf_sync_port = MAX_HW_PORT;
2904 
2905 		RTW_INFO("%s: policy_idx=%d\n", __func__, policy_idx);
2906 
2907 		order0_iface = mccobjpriv->iface[0];
2908 		order1_iface = mccobjpriv->iface[1];
2909 
2910 		/* GO/AP is order 0, GC/STA is order 1 */
2911 		order0_duration = order0_iface->mcc_adapterpriv.mcc_duration = interval - duration;
2912 		order0_iface->mcc_adapterpriv.mcc_duration = duration;
2913 
2914 		tsf_bsae_port = rtw_hal_get_port(order1_iface);
2915 		tsf_sync_port = rtw_hal_get_port(order0_iface);
2916 
2917 		/* update IE */
2918 		for (i = 0; i < dvobj->iface_nums; i++) {
2919 			PADAPTER iface = NULL;
2920 			struct mcc_adapter_priv *mccadapriv = NULL;
2921 
2922 			iface = dvobj->padapters[i];
2923 			if (iface == NULL)
2924 				continue;
2925 
2926 			mccadapriv = &iface->mcc_adapterpriv;
2927 			if (mccadapriv->role == MCC_ROLE_MAX)
2928 				continue;
2929 
2930 			if (mccadapriv->role == MCC_ROLE_GO)
2931 				rtw_hal_mcc_update_go_p2p_ie(iface);
2932 		}
2933 
2934 		/* update H2C cmd */
2935 		/* FW set enable */
2936 		SET_H2CCMD_MCC_TIME_SETTING_FW_EN(cmd, _TRUE);
2937 		/* TSF Sync offset */
2938 		SET_H2CCMD_MCC_TIME_SETTING_TSF_SYNC_OFFSET(cmd, tsf_sync_offset);
2939 		/* start time offset */
2940 		SET_H2CCMD_MCC_TIME_SETTING_START_TIME(cmd, (start_time_offset + guard_offset0));
2941 		/* interval */
2942 		SET_H2CCMD_MCC_TIME_SETTING_INTERVAL(cmd, interval);
2943 		/* Early time to inform driver by C2H before switch channel */
2944 		SET_H2CCMD_MCC_TIME_SETTING_EARLY_SWITCH_RPT(cmd, swchannel_early_time);
2945 		/* Port0 sync from Port1, not support multi-port */
2946 		SET_H2CCMD_MCC_TIME_SETTING_ORDER_BASE(cmd, tsf_bsae_port);
2947 		SET_H2CCMD_MCC_TIME_SETTING_ORDER_SYNC(cmd, tsf_sync_port);
2948 		SET_H2CCMD_MCC_TIME_SETTING_UPDATE(cmd, _TRUE);
2949 		SET_H2CCMD_MCC_TIME_SETTING_ORDER0_DURATION(cmd, order0_duration);
2950 	}
2951 
2952 	rtw_hal_fill_h2c_cmd(padapter, H2C_MCC_TIME_SETTING, H2C_MCC_TIME_SETTING_LEN, cmd);
2953 }
2954 
2955 /**
2956  * rtw_hal_mcc_sw_status_check - check mcc swich channel status
2957  * @padapter: primary adapter
2958  */
rtw_hal_mcc_sw_status_check(PADAPTER padapter)2959 void rtw_hal_mcc_sw_status_check(PADAPTER padapter)
2960 {
2961 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
2962 	struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
2963 	struct pwrctrl_priv	*pwrpriv = dvobj_to_pwrctl(dvobj);
2964 	struct mcc_adapter_priv *mccadapriv = NULL;
2965 	_adapter *iface = NULL;
2966 	u8 cur_cnt = 0, prev_cnt = 0, diff_cnt = 0, check_ret = _FAIL, threshold = 0;
2967 	u8 policy_idx = pmccobjpriv->policy_index;
2968 	u8 noa_enable = _FALSE;
2969 	u8 i = 0;
2970 	_irqL irqL;
2971 	u8 ap_num = DEV_AP_NUM(dvobj);
2972 
2973 /* #define MCC_RESTART 1 */
2974 
2975 	if (!MCC_EN(padapter))
2976 		return;
2977 
2978 	_enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
2979 
2980 	if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
2981 
2982 		/* check noa enable or not */
2983 		for (i = 0; i < dvobj->iface_nums; i++) {
2984 			iface = dvobj->padapters[i];
2985 			if (iface == NULL)
2986 				continue;
2987 
2988 			mccadapriv = &iface->mcc_adapterpriv;
2989 			if (mccadapriv->role == MCC_ROLE_MAX)
2990 				continue;
2991 
2992 			if (iface->wdinfo.p2p_ps_mode == P2P_PS_NOA) {
2993 				noa_enable = _TRUE;
2994 				break;
2995 			}
2996 		}
2997 
2998 		if (!noa_enable && ap_num == 0)
2999 			rtw_hal_mcc_update_parameter(padapter, _FALSE);
3000 
3001 		threshold = pmccobjpriv->mcc_stop_threshold;
3002 
3003 		if (pwrpriv->pwr_mode != PS_MODE_ACTIVE) {
3004 			rtw_warn_on(1);
3005 			RTW_INFO("PS mode is not active under mcc, force exit ps mode\n");
3006 			LeaveAllPowerSaveModeDirect(padapter);
3007 		}
3008 
3009 		if (rtw_get_passing_time_ms(pmccobjpriv->mcc_launch_time) > 2000) {
3010 			_enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
3011 
3012 			cur_cnt = pmccobjpriv->cur_mcc_success_cnt;
3013 			prev_cnt = pmccobjpriv->prev_mcc_success_cnt;
3014 			if (cur_cnt < prev_cnt)
3015 				diff_cnt = (cur_cnt + 255) - prev_cnt;
3016 			else
3017 				diff_cnt = cur_cnt - prev_cnt;
3018 
3019 			if (diff_cnt < threshold) {
3020 				pmccobjpriv->mcc_tolerance_time--;
3021 				RTW_INFO("%s: diff_cnt:%d, tolerance_time:%d\n",
3022 					__func__, diff_cnt, pmccobjpriv->mcc_tolerance_time);
3023 			} else
3024 				pmccobjpriv->mcc_tolerance_time = MCC_TOLERANCE_TIME;
3025 
3026 			pmccobjpriv->prev_mcc_success_cnt = pmccobjpriv->cur_mcc_success_cnt;
3027 
3028 			if (pmccobjpriv->mcc_tolerance_time != 0)
3029 				check_ret = _SUCCESS;
3030 
3031 			_exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
3032 
3033 			if (check_ret != _SUCCESS) {
3034 				RTW_INFO("============ MCC swich channel check fail (%d)=============\n", diff_cnt);
3035 				/* restart MCC */
3036 				#ifdef MCC_RESTART
3037 					rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_STOP_DISCONNECT);
3038 					rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT);
3039 				#endif /* MCC_RESTART */
3040 			}
3041 		} else {
3042 			_enter_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
3043 			pmccobjpriv->prev_mcc_success_cnt = pmccobjpriv->cur_mcc_success_cnt;
3044 			_exit_critical_bh(&pmccobjpriv->mcc_lock, &irqL);
3045 		}
3046 
3047 	}
3048 	_exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3049 }
3050 
3051 /**
3052  * rtw_hal_mcc_change_scan_flag - change scan flag under mcc
3053  *
3054  * MCC mode under sitesurvey goto AP channel to tx bcn & data
3055  * MCC mode under sitesurvey doesn't support TX data for station mode (FW not support)
3056  *
3057  * @padapter: the adapter to be change scan flag
3058  * @ch: pointer to rerurn ch
3059  * @bw: pointer to rerurn bw
3060  * @offset: pointer to rerurn offset
3061  */
rtw_hal_mcc_change_scan_flag(PADAPTER padapter,u8 * ch,u8 * bw,u8 * offset)3062 u8 rtw_hal_mcc_change_scan_flag(PADAPTER padapter, u8 *ch, u8 *bw, u8 *offset)
3063 {
3064 	u8 need_ch_setting_union = _TRUE, i = 0, flags = 0, back_op = _FALSE;
3065 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3066 	struct mcc_adapter_priv *mccadapriv = NULL;
3067 	struct mlme_ext_priv *mlmeext = NULL;
3068 	_adapter *iface = NULL;
3069 
3070 	if (!MCC_EN(padapter))
3071 		goto exit;
3072 
3073 	if (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC))
3074 		goto exit;
3075 
3076 	/* disable PS_ANNC & TX_RESUME for all interface */
3077 	/* ToDo: TX_RESUME by interface in SCAN_BACKING_OP */
3078 	mlmeext = &padapter->mlmeextpriv;
3079 
3080 	flags = mlmeext_scan_backop_flags(mlmeext);
3081 	if (mlmeext_chk_scan_backop_flags(mlmeext, SS_BACKOP_PS_ANNC))
3082 		flags &= ~SS_BACKOP_PS_ANNC;
3083 
3084 	if (mlmeext_chk_scan_backop_flags(mlmeext, SS_BACKOP_TX_RESUME))
3085 		flags &= ~SS_BACKOP_TX_RESUME;
3086 
3087 	mlmeext_assign_scan_backop_flags(mlmeext, flags);
3088 
3089 	for (i = 0; i < dvobj->iface_nums; i++) {
3090 		iface = dvobj->padapters[i];
3091 		if (!iface)
3092 			continue;
3093 
3094 		mlmeext = &iface->mlmeextpriv;
3095 
3096 		if (MLME_IS_GO(iface) || MLME_IS_AP(iface))
3097 			back_op = _TRUE;
3098 		else if (MLME_IS_GC(iface) && (iface != padapter))
3099 			/* switch to another linked interface(GO) to receive beacon to avoid no beacon disconnect */
3100 			back_op = _TRUE;
3101 		else if (MLME_IS_STA(iface) && MLME_IS_ASOC(iface) && (iface != padapter))
3102 			/* switch to another linked interface(STA) to receive beacon to avoid no beacon disconnect  */
3103 			back_op = _TRUE;
3104 		else {
3105 			/* bypass non-linked/non-linking interface/scan interface */
3106 			continue;
3107 		}
3108 
3109 		if (back_op) {
3110 			*ch = mlmeext->cur_channel;
3111 			*bw = mlmeext->cur_bwmode;
3112 			*offset = mlmeext->cur_ch_offset;
3113 			need_ch_setting_union = _FALSE;
3114 		}
3115 	}
3116 exit:
3117 	return need_ch_setting_union;
3118 }
3119 
3120 /**
3121  * rtw_hal_mcc_calc_tx_bytes_from_kernel - calculte tx bytes from kernel to check concurrent tx or not
3122  * @padapter: the adapter to be record tx bytes
3123  * @len: data len
3124  */
rtw_hal_mcc_calc_tx_bytes_from_kernel(PADAPTER padapter,u32 len)3125 inline void rtw_hal_mcc_calc_tx_bytes_from_kernel(PADAPTER padapter, u32 len)
3126 {
3127 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
3128 
3129 	if (MCC_EN(padapter)) {
3130 		if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3131 			pmccadapriv->mcc_tx_bytes_from_kernel += len;
3132 			if (0)
3133 				RTW_INFO("%s(order:%d): mcc tx bytes from kernel:%lld\n"
3134 					, __func__, pmccadapriv->order, pmccadapriv->mcc_tx_bytes_from_kernel);
3135 		}
3136 	}
3137 }
3138 
3139 /**
3140  * rtw_hal_mcc_calc_tx_bytes_to_port - calculte tx bytes to write port in order to flow crtl
3141  * @padapter: the adapter to be record tx bytes
3142  * @len: data len
3143  */
rtw_hal_mcc_calc_tx_bytes_to_port(PADAPTER padapter,u32 len)3144 inline void rtw_hal_mcc_calc_tx_bytes_to_port(PADAPTER padapter, u32 len)
3145 {
3146 	if (MCC_EN(padapter)) {
3147 		struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3148 		struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
3149 
3150 		if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3151 			pmccadapriv->mcc_tx_bytes_to_port += len;
3152 			if (0)
3153 				RTW_INFO("%s(order:%d): mcc tx bytes to port:%d, mcc target tx bytes to port:%d\n"
3154 					, __func__, pmccadapriv->order, pmccadapriv->mcc_tx_bytes_to_port
3155 					, pmccadapriv->mcc_target_tx_bytes_to_port);
3156 		}
3157 	}
3158 }
3159 
3160 /**
3161  * rtw_hal_mcc_stop_tx_bytes_to_port - stop write port to hw or not
3162  * @padapter: the adapter to be stopped
3163  */
rtw_hal_mcc_stop_tx_bytes_to_port(PADAPTER padapter)3164 inline u8 rtw_hal_mcc_stop_tx_bytes_to_port(PADAPTER padapter)
3165 {
3166 	if (MCC_EN(padapter)) {
3167 		struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3168 		struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
3169 
3170 		if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3171 			if (pmccadapriv->mcc_tp_limit) {
3172 				if (pmccadapriv->mcc_tx_bytes_to_port >= pmccadapriv->mcc_target_tx_bytes_to_port) {
3173 					pmccadapriv->mcc_tx_stop = _TRUE;
3174 					rtw_netif_stop_queue(padapter->pnetdev);
3175 					return _TRUE;
3176 				}
3177 			}
3178 		}
3179 	}
3180 
3181 	return _FALSE;
3182 }
3183 
rtw_hal_mcc_assign_scan_flag(PADAPTER padapter,u8 scan_done)3184 static void rtw_hal_mcc_assign_scan_flag(PADAPTER padapter, u8 scan_done)
3185 {
3186 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3187 	struct mcc_adapter_priv *mccadapriv = NULL;
3188 	_adapter *iface = NULL;
3189 	struct mlme_ext_priv *pmlmeext = NULL;
3190 	u8 i = 0, flags;
3191 
3192 	if (!MCC_EN(padapter))
3193 		return;
3194 
3195 	for (i = 0; i < dvobj->iface_nums; i++) {
3196 		iface = dvobj->padapters[i];
3197 		if (iface == NULL)
3198 			continue;
3199 
3200 		mccadapriv = &iface->mcc_adapterpriv;
3201 		if (mccadapriv->role == MCC_ROLE_MAX)
3202 			continue;
3203 
3204 		pmlmeext = &iface->mlmeextpriv;
3205 		if (is_client_associated_to_ap(iface)) {
3206 			flags = mlmeext_scan_backop_flags_sta(pmlmeext);
3207 			if (scan_done) {
3208 				if (mlmeext_chk_scan_backop_flags_sta(pmlmeext, SS_BACKOP_EN)) {
3209 					flags &= ~SS_BACKOP_EN;
3210 					mlmeext_assign_scan_backop_flags_sta(pmlmeext, flags);
3211 				}
3212 			} else {
3213 				if (!mlmeext_chk_scan_backop_flags_sta(pmlmeext, SS_BACKOP_EN)) {
3214 					flags |= SS_BACKOP_EN;
3215 					mlmeext_assign_scan_backop_flags_sta(pmlmeext, flags);
3216 				}
3217 			}
3218 
3219 		}
3220 	}
3221 }
3222 
3223 /**
3224  * rtw_hal_set_mcc_setting_scan_start - setting mcc under scan start
3225  * @padapter: the adapter to be setted
3226  * @ch_setting_changed: softap channel setting to be changed or not
3227  */
rtw_hal_set_mcc_setting_scan_start(PADAPTER padapter)3228 u8 rtw_hal_set_mcc_setting_scan_start(PADAPTER padapter)
3229 {
3230 	u8 ret = _FAIL;
3231 
3232 	if (MCC_EN(padapter)) {
3233 		struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3234 
3235 		_enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3236 		if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) {
3237 			if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3238 				ret = rtw_hal_set_mcc_setting(padapter,  MCC_SETCMD_STATUS_STOP_SCAN_START);
3239 				rtw_hal_mcc_assign_scan_flag(padapter, 0);
3240 			}
3241 		}
3242 		_exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3243 	}
3244 
3245 	return ret;
3246 }
3247 
3248 /**
3249  * rtw_hal_set_mcc_setting_scan_complete - setting mcc after scan commplete
3250  * @padapter: the adapter to be setted
3251  * @ch_setting_changed: softap channel setting to be changed or not
3252  */
rtw_hal_set_mcc_setting_scan_complete(PADAPTER padapter)3253 u8 rtw_hal_set_mcc_setting_scan_complete(PADAPTER padapter)
3254 {
3255 	u8 ret = _FAIL;
3256 
3257 	if (MCC_EN(padapter)) {
3258 		struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3259 
3260 		_enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3261 
3262 		if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) {
3263 				rtw_hal_mcc_assign_scan_flag(padapter, 1);
3264 				ret = rtw_hal_set_mcc_setting(padapter,  MCC_SETCMD_STATUS_START_SCAN_DONE);
3265 		}
3266 		_exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3267 	}
3268 
3269 	return ret;
3270 }
3271 
3272 
3273 /**
3274  * rtw_hal_set_mcc_setting_start_bss_network - setting mcc under softap start
3275  * @padapter: the adapter to be setted
3276  * @chbw_grouped: channel bw offset can not be allowed or not
3277  */
rtw_hal_set_mcc_setting_start_bss_network(PADAPTER padapter,u8 chbw_allow)3278 u8 rtw_hal_set_mcc_setting_start_bss_network(PADAPTER padapter, u8 chbw_allow)
3279 {
3280 	u8 ret = _FAIL;
3281 
3282 	if (MCC_EN(padapter)) {
3283 		/* channel bw offset can not be allowed, start MCC */
3284 		if (chbw_allow == _FALSE) {
3285 				struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3286 
3287 				rtw_hal_mcc_restore_iqk_val(padapter);
3288 				_enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3289 				ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT);
3290 				_exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3291 			}
3292 		}
3293 
3294 	return ret;
3295 }
3296 
3297 /**
3298  * rtw_hal_set_mcc_setting_disconnect - setting mcc under mlme disconnect(stop softap/disconnect from AP)
3299  * @padapter: the adapter to be setted
3300  */
rtw_hal_set_mcc_setting_disconnect(PADAPTER padapter)3301 u8 rtw_hal_set_mcc_setting_disconnect(PADAPTER padapter)
3302 {
3303 	u8 ret = _FAIL;
3304 
3305 	if (MCC_EN(padapter)) {
3306 		struct mcc_obj_priv *pmccobjpriv = &(adapter_to_dvobj(padapter)->mcc_objpriv);
3307 
3308 		_enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3309 		if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) {
3310 			if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
3311 				ret = rtw_hal_set_mcc_setting(padapter,  MCC_SETCMD_STATUS_STOP_DISCONNECT);
3312 		}
3313 		_exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3314 	}
3315 
3316 	return ret;
3317 }
3318 
3319 /**
3320  * rtw_hal_set_mcc_setting_join_done_chk_ch - setting mcc under join done
3321  * @padapter: the adapter to be checked
3322  */
rtw_hal_set_mcc_setting_join_done_chk_ch(PADAPTER padapter)3323 u8 rtw_hal_set_mcc_setting_join_done_chk_ch(PADAPTER padapter)
3324 {
3325 	u8 ret = _FAIL;
3326 
3327 	if (MCC_EN(padapter)) {
3328 		struct mi_state mstate;
3329 
3330 		rtw_mi_status_no_self(padapter, &mstate);
3331 
3332 		if (MSTATE_STA_LD_NUM(&mstate) || MSTATE_STA_LG_NUM(&mstate) || MSTATE_AP_NUM(&mstate)) {
3333 			bool chbw_allow = _TRUE;
3334 			u8 u_ch, u_offset, u_bw;
3335 			struct mlme_ext_priv *cur_mlmeext = &padapter->mlmeextpriv;
3336 			struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3337 
3338 			if (rtw_mi_get_ch_setting_union_no_self(padapter, &u_ch, &u_bw, &u_offset) <= 0) {
3339 				dump_adapters_status(RTW_DBGDUMP , dvobj);
3340 				rtw_warn_on(1);
3341 			}
3342 
3343 			RTW_INFO(FUNC_ADPT_FMT" union no self: %u,%u,%u\n"
3344 				, FUNC_ADPT_ARG(padapter), u_ch, u_bw, u_offset);
3345 
3346 			/* chbw_allow? */
3347 			chbw_allow = rtw_is_chbw_grouped(cur_mlmeext->cur_channel
3348 				, cur_mlmeext->cur_bwmode, cur_mlmeext->cur_ch_offset
3349 					, u_ch, u_bw, u_offset);
3350 
3351 			RTW_INFO(FUNC_ADPT_FMT" chbw_allow:%d\n"
3352 				, FUNC_ADPT_ARG(padapter), chbw_allow);
3353 
3354 			/* if chbw_allow = false, start MCC setting */
3355 			if (chbw_allow == _FALSE) {
3356 				struct mcc_obj_priv *pmccobjpriv = &dvobj->mcc_objpriv;
3357 
3358 				rtw_hal_mcc_restore_iqk_val(padapter);
3359 				_enter_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3360 				ret = rtw_hal_set_mcc_setting(padapter, MCC_SETCMD_STATUS_START_CONNECT);
3361 				_exit_critical_mutex(&pmccobjpriv->mcc_mutex, NULL);
3362 		}
3363 	}
3364 	}
3365 
3366 	return ret;
3367 }
3368 
3369 /**
3370  * rtw_hal_set_mcc_setting_chk_start_clnt_join - check change channel under start clnt join
3371  * @padapter: the adapter to be checked
3372  * @ch: pointer to rerurn ch
3373  * @bw: pointer to rerurn bw
3374  * @offset: pointer to rerurn offset
3375  * @chbw_allow: allow to use adapter's channel setting
3376  */
rtw_hal_set_mcc_setting_chk_start_clnt_join(PADAPTER padapter,u8 * ch,u8 * bw,u8 * offset,u8 chbw_allow)3377 u8 rtw_hal_set_mcc_setting_chk_start_clnt_join(PADAPTER padapter, u8 *ch, u8 *bw, u8 *offset, u8 chbw_allow)
3378 {
3379 	u8 ret = _FAIL;
3380 
3381 	/* if chbw_allow = false under en_mcc = TRUE, we do not change channel related setting  */
3382 	if (MCC_EN(padapter)) {
3383 		/* restore union channel related setting to current channel related setting */
3384 		if (chbw_allow == _FALSE) {
3385 			struct mlme_ext_priv *pmlmeext = &padapter->mlmeextpriv;
3386 
3387 			/* issue null data to other interface connected to AP */
3388 			rtw_hal_mcc_issue_null_data(padapter, chbw_allow, _TRUE);
3389 
3390 			*ch = pmlmeext->cur_channel;
3391 			*bw = pmlmeext->cur_bwmode;
3392 			*offset = pmlmeext->cur_ch_offset;
3393 
3394 			RTW_INFO(FUNC_ADPT_FMT" en_mcc:%d(%d,%d,%d,)\n"
3395 				, FUNC_ADPT_ARG(padapter), MCC_EN(padapter)
3396 				, *ch, *bw, *offset);
3397 			ret = _SUCCESS;
3398 		}
3399 	}
3400 
3401 	return ret;
3402 }
3403 
rtw_hal_mcc_dump_noa_content(void * sel,PADAPTER padapter)3404 static void rtw_hal_mcc_dump_noa_content(void *sel, PADAPTER padapter)
3405 {
3406 	struct mcc_adapter_priv *pmccadapriv = NULL;
3407 	u8 *pos = NULL;
3408 	pmccadapriv = &padapter->mcc_adapterpriv;
3409 	/* last position for NoA attribute */
3410 	pos = pmccadapriv->p2p_go_noa_ie + pmccadapriv->p2p_go_noa_ie_len;
3411 
3412 
3413 	RTW_PRINT_SEL(sel, "\nStart to dump NoA Content\n");
3414 	RTW_PRINT_SEL(sel, "NoA Counts:%d\n", *(pos - 13));
3415 	RTW_PRINT_SEL(sel, "NoA Duration(TU):%d\n", (RTW_GET_LE32(pos - 12))/TU);
3416 	RTW_PRINT_SEL(sel, "NoA Interval(TU):%d\n", (RTW_GET_LE32(pos - 8))/TU);
3417 	RTW_PRINT_SEL(sel, "NoA Start time(microseconds):0x%02x\n", RTW_GET_LE32(pos - 4));
3418 	RTW_PRINT_SEL(sel, "End to dump NoA Content\n");
3419 }
3420 
mcc_dump_dbg_reg(void * sel,_adapter * adapter)3421 static void mcc_dump_dbg_reg(void *sel, _adapter *adapter)
3422 {
3423 	struct mcc_obj_priv *mccobjpriv = adapter_to_mccobjpriv(adapter);
3424 	HAL_DATA_TYPE *hal = GET_HAL_DATA(adapter);
3425 	u8 i,j;
3426 	_irqL irqL;
3427 
3428 	_enter_critical_bh(&mccobjpriv->mcc_lock, &irqL);
3429 	RTW_PRINT_SEL(sel, "current order=%d\n", mccobjpriv->current_order);
3430 	_exit_critical_bh(&mccobjpriv->mcc_lock, &irqL);
3431 
3432 	_enter_critical_mutex(&mccobjpriv->mcc_dbg_reg_mutex, NULL);
3433 	for (i = 0; i < ARRAY_SIZE(mccobjpriv->dbg_reg); i++)
3434 			RTW_PRINT_SEL(sel, "REG_0x%X:0x%08x\n", mccobjpriv->dbg_reg[i], mccobjpriv->dbg_reg_val[i]);
3435 
3436 	for (i = 0; i < ARRAY_SIZE(mccobjpriv->dbg_rf_reg); i++) {
3437 		for (j = 0; j < hal->NumTotalRFPath; j++)
3438 			RTW_PRINT_SEL(sel, "RF_PATH_%d_REG_0x%X:0x%08x\n",
3439 				j, mccobjpriv->dbg_rf_reg[i], mccobjpriv->dbg_rf_reg_val[i][j]);
3440 	}
3441 	_exit_critical_mutex(&mccobjpriv->mcc_dbg_reg_mutex, NULL);
3442 }
3443 
3444 
rtw_hal_dump_mcc_info(void * sel,struct dvobj_priv * dvobj)3445 void rtw_hal_dump_mcc_info(void *sel, struct dvobj_priv *dvobj)
3446 {
3447 	struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
3448 	struct mcc_adapter_priv *mccadapriv = NULL;
3449 	_adapter *iface = NULL, *pri_adapter = NULL;
3450 	struct registry_priv *regpriv = NULL;
3451 	HAL_DATA_TYPE *hal = NULL;
3452 	u8 i = 0, j = 0;
3453 	u64 tsf[MAX_MCC_NUM] = {0};
3454 
3455 	/* regpriv is common for all adapter */
3456 	pri_adapter = dvobj_get_primary_adapter(dvobj);
3457 	hal = GET_HAL_DATA(pri_adapter);
3458 
3459 	RTW_PRINT_SEL(sel, "**********************************************\n");
3460 	RTW_PRINT_SEL(sel, "en_mcc:%d\n", MCC_EN(pri_adapter));
3461 	RTW_PRINT_SEL(sel, "primary adapter("ADPT_FMT") duration:%d%c\n",
3462 		ADPT_ARG(dvobj_get_primary_adapter(dvobj)), mccobjpriv->duration, 37);
3463 	RTW_PRINT_SEL(sel, "runtime duration:%s\n", mccobjpriv->enable_runtime_duration ? "enable":"disable");
3464 	RTW_PRINT_SEL(sel, "phydm offload:%s\n", mccobjpriv->mcc_phydm_offload ? "enable":"disable");
3465 
3466 	if (rtw_hal_check_mcc_status(pri_adapter, MCC_STATUS_DOING_MCC)) {
3467 		rtw_hal_mcc_rqt_tsf(pri_adapter, tsf);
3468 
3469 		for (i = 0; i < MAX_MCC_NUM; i++) {
3470 			iface = mccobjpriv->iface[i];
3471 			if (!iface)
3472 				continue;
3473 
3474 			regpriv = &iface->registrypriv;
3475 			mccadapriv = &iface->mcc_adapterpriv;
3476 
3477 			if (mccadapriv) {
3478 				u8 p2p_ps_mode = iface->wdinfo.p2p_ps_mode;
3479 
3480 				RTW_PRINT_SEL(sel, "adapter mcc info:\n");
3481 				RTW_PRINT_SEL(sel, "ifname:%s\n", ADPT_ARG(iface));
3482 				RTW_PRINT_SEL(sel, "order:%d\n", mccadapriv->order);
3483 				RTW_PRINT_SEL(sel, "duration:%d\n", mccadapriv->mcc_duration);
3484 				RTW_PRINT_SEL(sel, "target tx bytes:%d\n", mccadapriv->mcc_target_tx_bytes_to_port);
3485 				RTW_PRINT_SEL(sel, "current TP:%d\n", mccadapriv->mcc_tp);
3486 				RTW_PRINT_SEL(sel, "mgmt queue macid:%d\n", mccadapriv->mgmt_queue_macid);
3487 				RTW_PRINT_SEL(sel, "macid bitmap:0x%02x\n", mccadapriv->mcc_macid_bitmap);
3488 				RTW_PRINT_SEL(sel, "P2P NoA:%s\n\n", p2p_ps_mode == P2P_PS_NOA ? "enable":"disable");
3489 				RTW_PRINT_SEL(sel, "registry data:\n");
3490 				RTW_PRINT_SEL(sel, "ap target tx TP(BW:20M):%d Mbps\n", regpriv->rtw_mcc_ap_bw20_target_tx_tp);
3491 				RTW_PRINT_SEL(sel, "ap target tx TP(BW:40M):%d Mbps\n", regpriv->rtw_mcc_ap_bw40_target_tx_tp);
3492 				RTW_PRINT_SEL(sel, "ap target tx TP(BW:80M):%d Mbps\n", regpriv->rtw_mcc_ap_bw80_target_tx_tp);
3493 				RTW_PRINT_SEL(sel, "sta target tx TP(BW:20M):%d Mbps\n", regpriv->rtw_mcc_sta_bw20_target_tx_tp);
3494 				RTW_PRINT_SEL(sel, "sta target tx TP(BW:40M ):%d Mbps\n", regpriv->rtw_mcc_sta_bw40_target_tx_tp);
3495 				RTW_PRINT_SEL(sel, "sta target tx TP(BW:80M):%d Mbps\n", regpriv->rtw_mcc_sta_bw80_target_tx_tp);
3496 				RTW_PRINT_SEL(sel, "single tx criteria:%d Mbps\n", regpriv->rtw_mcc_single_tx_cri);
3497 				RTW_PRINT_SEL(sel, "HW TSF=0x%llx\n", tsf[mccadapriv->order]);
3498 				if (MLME_IS_GO(iface))
3499 					rtw_hal_mcc_dump_noa_content(sel, iface);
3500 				RTW_PRINT_SEL(sel, "**********************************************\n");
3501 			}
3502 		}
3503 
3504 		mcc_dump_dbg_reg(sel, pri_adapter);
3505 	}
3506 
3507 	#ifdef CONFIG_MCC_PHYDM_OFFLOAD
3508 	RTW_PRINT_SEL(sel, "@@@@@@@@@@@@@@@@@@@@\n");
3509 	rtw_hal_mcc_cfg_phydm(pri_adapter, MCC_CFG_PHYDM_DUMP, sel);
3510 	RTW_PRINT_SEL(sel, "@@@@@@@@@@@@@@@@@@@@\n");
3511 	#endif
3512 
3513 	RTW_PRINT_SEL(sel, "------------------------------------------\n");
3514 	RTW_PRINT_SEL(sel, "policy index:%d\n", mccobjpriv->policy_index);
3515 	RTW_PRINT_SEL(sel, "------------------------------------------\n");
3516 	RTW_PRINT_SEL(sel, "define data:\n");
3517 	RTW_PRINT_SEL(sel, "ap target tx TP(BW:20M):%d Mbps\n", MCC_AP_BW20_TARGET_TX_TP);
3518 	RTW_PRINT_SEL(sel, "ap target tx TP(BW:40M):%d Mbps\n", MCC_AP_BW40_TARGET_TX_TP);
3519 	RTW_PRINT_SEL(sel, "ap target tx TP(BW:80M):%d Mbps\n", MCC_AP_BW80_TARGET_TX_TP);
3520 	RTW_PRINT_SEL(sel, "sta target tx TP(BW:20M):%d Mbps\n", MCC_STA_BW20_TARGET_TX_TP);
3521 	RTW_PRINT_SEL(sel, "sta target tx TP(BW:40M):%d Mbps\n", MCC_STA_BW40_TARGET_TX_TP);
3522 	RTW_PRINT_SEL(sel, "sta target tx TP(BW:80M):%d Mbps\n", MCC_STA_BW80_TARGET_TX_TP);
3523 	RTW_PRINT_SEL(sel, "single tx criteria:%d Mbps\n", MCC_SINGLE_TX_CRITERIA);
3524 	RTW_PRINT_SEL(sel, "------------------------------------------\n");
3525 }
3526 
update_mcc_mgntframe_attrib(_adapter * padapter,struct pkt_attrib * pattrib)3527 inline void update_mcc_mgntframe_attrib(_adapter *padapter, struct pkt_attrib *pattrib)
3528 {
3529 	if (MCC_EN(padapter)) {
3530 		if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC)) {
3531 			/* use QSLT_MGNT to check mgnt queue or bcn queue */
3532 			if (pattrib->qsel == QSLT_MGNT) {
3533 				pattrib->mac_id = padapter->mcc_adapterpriv.mgmt_queue_macid;
3534 				pattrib->qsel = QSLT_VO;
3535 			}
3536 		}
3537 	}
3538 }
3539 
rtw_hal_mcc_link_status_chk(_adapter * padapter,const char * msg)3540 inline u8 rtw_hal_mcc_link_status_chk(_adapter *padapter, const char *msg)
3541 {
3542 	u8 ret = _TRUE, i = 0;
3543 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3544 	_adapter *iface;
3545 	struct mlme_ext_priv *mlmeext;
3546 
3547 	if (MCC_EN(padapter)) {
3548 		if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_NEED_MCC)) {
3549 			for (i = 0; i < dvobj->iface_nums; i++) {
3550 				iface = dvobj->padapters[i];
3551 				mlmeext = &iface->mlmeextpriv;
3552 				if (mlmeext_scan_state(mlmeext) != SCAN_DISABLE) {
3553 					#ifdef DBG_EXPIRATION_CHK
3554 						RTW_INFO(FUNC_ADPT_FMT" don't enter %s under scan for MCC mode\n", FUNC_ADPT_ARG(padapter), msg);
3555 					#endif
3556 					ret = _FALSE;
3557 					goto exit;
3558 				}
3559 			}
3560 		}
3561 	}
3562 
3563 exit:
3564 	return ret;
3565 }
3566 
rtw_hal_mcc_issue_null_data(_adapter * padapter,u8 chbw_allow,u8 ps_mode)3567 void rtw_hal_mcc_issue_null_data(_adapter *padapter, u8 chbw_allow, u8 ps_mode)
3568 {
3569 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3570 	_adapter *iface = NULL;
3571 	systime start = rtw_get_current_time();
3572 	u8 i = 0;
3573 
3574 	if (!MCC_EN(padapter))
3575 		return;
3576 
3577 	if (rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
3578 		return;
3579 
3580 	if (chbw_allow == _TRUE)
3581 		return;
3582 
3583 	for (i = 0; i < dvobj->iface_nums; i++) {
3584 		iface = dvobj->padapters[i];
3585 		/* issue null data to inform ap station will leave */
3586 		if (is_client_associated_to_ap(iface)) {
3587 			struct mlme_ext_priv *mlmeext = &iface->mlmeextpriv;
3588 			struct mlme_ext_info *mlmeextinfo = &mlmeext->mlmext_info;
3589 			u8 ch = mlmeext->cur_channel;
3590 			u8 bw = mlmeext->cur_bwmode;
3591 			u8 offset = mlmeext->cur_ch_offset;
3592 			struct sta_info *sta = rtw_get_stainfo(&iface->stapriv, get_my_bssid(&(mlmeextinfo->network)));
3593 
3594 			if (!sta)
3595 				continue;
3596 
3597 			set_channel_bwmode(iface, ch, offset, bw);
3598 
3599 			if (ps_mode)
3600 				rtw_hal_macid_sleep(iface, sta->cmn.mac_id);
3601 			else
3602 				rtw_hal_macid_wakeup(iface, sta->cmn.mac_id);
3603 
3604 			issue_nulldata(iface, NULL, ps_mode, 3, 50);
3605 		}
3606 	}
3607 	RTW_INFO("%s(%d ms)\n", __func__, rtw_get_passing_time_ms(start));
3608 }
3609 
rtw_hal_mcc_append_go_p2p_ie(PADAPTER padapter,u8 * pframe,u32 * len)3610 u8 *rtw_hal_mcc_append_go_p2p_ie(PADAPTER padapter, u8 *pframe, u32 *len)
3611 {
3612 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
3613 
3614 	if (!MCC_EN(padapter))
3615 		return pframe;
3616 
3617 	if (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
3618 		return pframe;
3619 
3620 	if (pmccadapriv->p2p_go_noa_ie_len == 0)
3621 		return pframe;
3622 
3623 	_rtw_memcpy(pframe, pmccadapriv->p2p_go_noa_ie, pmccadapriv->p2p_go_noa_ie_len);
3624 	*len = *len + pmccadapriv->p2p_go_noa_ie_len;
3625 
3626 	return pframe + pmccadapriv->p2p_go_noa_ie_len;
3627 }
3628 
rtw_hal_dump_mcc_policy_table(void * sel)3629 void rtw_hal_dump_mcc_policy_table(void *sel)
3630 {
3631 	u8 idx = 0;
3632 	RTW_PRINT_SEL(sel, "duration\t,tsf sync offset\t,start time offset\t,interval\t,guard offset0\t,guard offset1\n");
3633 
3634 	for (idx = 0; idx < mcc_max_policy_num; idx ++) {
3635 		RTW_PRINT_SEL(sel, "%d\t\t,%d\t\t\t,%d\t\t\t,%d\t\t,%d\t\t,%d\n"
3636 			, mcc_switch_channel_policy_table[idx][MCC_DURATION_IDX]
3637 			, mcc_switch_channel_policy_table[idx][MCC_TSF_SYNC_OFFSET_IDX]
3638 			, mcc_switch_channel_policy_table[idx][MCC_START_TIME_OFFSET_IDX]
3639 			, mcc_switch_channel_policy_table[idx][MCC_INTERVAL_IDX]
3640 			, mcc_switch_channel_policy_table[idx][MCC_GUARD_OFFSET0_IDX]
3641 			, mcc_switch_channel_policy_table[idx][MCC_GUARD_OFFSET1_IDX]);
3642 	}
3643 }
3644 
rtw_hal_mcc_update_macid_bitmap(PADAPTER padapter,int mac_id,u8 add)3645 void rtw_hal_mcc_update_macid_bitmap(PADAPTER padapter, int mac_id, u8 add)
3646 {
3647 	struct mcc_adapter_priv *pmccadapriv = &padapter->mcc_adapterpriv;
3648 
3649 	if (!MCC_EN(padapter))
3650 		return;
3651 
3652 	if (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
3653 		return;
3654 
3655 	if (pmccadapriv->role == MCC_ROLE_GC || pmccadapriv->role == MCC_ROLE_STA)
3656 		return;
3657 
3658 	if (mac_id < 0) {
3659 		RTW_WARN("%s: mac_id < 0(%d)\n", __func__, mac_id);
3660 		return;
3661 	}
3662 
3663 	RTW_INFO(ADPT_FMT" %s macid=%d, ori mcc_macid_bitmap=0x%08x\n"
3664 		, ADPT_ARG(padapter), add ? "add" : "clear"
3665 		, mac_id, pmccadapriv->mcc_macid_bitmap);
3666 
3667 	if (add) {
3668 		#ifdef CONFIG_MCC_PHYDM_OFFLOAD
3669 		rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_ADD_CLIENT, &mac_id);
3670 		#endif
3671 		pmccadapriv->mcc_macid_bitmap |= BIT(mac_id);
3672 	} else {
3673 		#ifdef CONFIG_MCC_PHYDM_OFFLOAD
3674 		rtw_hal_mcc_cfg_phydm(padapter, MCC_CFG_PHYDM_REMOVE_CLIENT, &mac_id);
3675 		#endif
3676 		pmccadapriv->mcc_macid_bitmap &= ~(BIT(mac_id));
3677 	}
3678 	rtw_hal_set_mcc_macid_cmd(padapter);
3679 }
3680 
rtw_hal_mcc_process_noa(PADAPTER padapter)3681 void rtw_hal_mcc_process_noa(PADAPTER padapter)
3682 {
3683 	struct wifidirect_info *pwdinfo = &(padapter->wdinfo);
3684 	struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
3685 	struct mcc_obj_priv *pmccobjpriv = &(dvobj->mcc_objpriv);
3686 
3687 	if (!MCC_EN(padapter))
3688 		return;
3689 
3690 	if (!rtw_hal_check_mcc_status(padapter, MCC_STATUS_DOING_MCC))
3691 		return;
3692 
3693 	if (!MLME_IS_GC(padapter))
3694 		return;
3695 
3696 	switch(pwdinfo->p2p_ps_mode) {
3697 	case P2P_PS_NONE:
3698 		RTW_INFO("[MCC] Disable NoA under MCC\n");
3699 		rtw_hal_mcc_update_parameter(padapter, _TRUE);
3700 		break;
3701 	case P2P_PS_NOA:
3702 		RTW_INFO("[MCC] Enable NoA under MCC\n");
3703 		break;
3704 	default:
3705 		break;
3706 
3707 	}
3708 }
3709 
rtw_hal_mcc_parameter_init(PADAPTER padapter)3710 void rtw_hal_mcc_parameter_init(PADAPTER padapter)
3711 {
3712 	if (!padapter->registrypriv.en_mcc)
3713 		return;
3714 
3715 	if (is_primary_adapter(padapter)) {
3716 		SET_MCC_EN_FLAG(padapter, padapter->registrypriv.en_mcc);
3717 		SET_MCC_DURATION(padapter, padapter->registrypriv.rtw_mcc_duration);
3718 		SET_MCC_RUNTIME_DURATION(padapter, padapter->registrypriv.rtw_mcc_enable_runtime_duration);
3719 		SET_MCC_PHYDM_OFFLOAD(padapter, padapter->registrypriv.rtw_mcc_phydm_offload);
3720 	}
3721 }
3722 
3723 
set_mcc_duration_hdl(PADAPTER adapter,const u8 * val)3724 static u8 set_mcc_duration_hdl(PADAPTER adapter, const u8 *val)
3725 {
3726 	struct dvobj_priv *dvobj = adapter_to_dvobj(adapter);
3727 	struct mcc_obj_priv *mccobjpriv = &(dvobj->mcc_objpriv);
3728 	_adapter *iface = NULL;
3729 	u8 duration = 50;
3730 	u8 ret = _SUCCESS, noa_enable = _FALSE, i = 0;
3731 	enum mcc_duration_setting type;
3732 
3733 	if (!mccobjpriv->enable_runtime_duration)
3734 		goto exit;
3735 
3736 #ifdef CONFIG_P2P_PS
3737 	/* check noa enable or not */
3738 	for (i = 0; i < dvobj->iface_nums; i++) {
3739 		iface = dvobj->padapters[i];
3740 		if (iface->wdinfo.p2p_ps_mode == P2P_PS_NOA) {
3741 			noa_enable = _TRUE;
3742 			break;
3743 		}
3744 	}
3745 #endif /* CONFIG_P2P_PS */
3746 
3747 	type = val[0];
3748 	duration = val[1];
3749 
3750 	if (type == MCC_DURATION_MAPPING) {
3751 		switch (duration) {
3752 			/* 0 = fair scheduling */
3753 			case 0:
3754 				mccobjpriv->duration= 40;
3755 				mccobjpriv->policy_index = 2;
3756 				mccobjpriv->mchan_sched_mode = MCC_FAIR_SCHEDULE;
3757 				break;
3758 			/* 1 = favor STA */
3759 			case 1:
3760 				mccobjpriv->duration= 70;
3761 				mccobjpriv->policy_index = 1;
3762 				mccobjpriv->mchan_sched_mode = MCC_FAVOR_STA;
3763 				break;
3764 			/* 2 = favor P2P*/
3765 			case 2:
3766 			default:
3767 				mccobjpriv->duration= 30;
3768 				mccobjpriv->policy_index = 0;
3769 				mccobjpriv->mchan_sched_mode = MCC_FAVOR_P2P;
3770 				break;
3771 		}
3772 	} else {
3773 		mccobjpriv->duration = duration;
3774 		rtw_hal_mcc_update_policy_table(adapter);
3775 	}
3776 
3777 	/* only update sw parameter under MCC
3778 	    it will be force update during */
3779 	if (noa_enable)
3780 		goto exit;
3781 
3782 	if (rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC))
3783 		rtw_hal_mcc_update_parameter(adapter, _TRUE);
3784 exit:
3785 	return ret;
3786 }
3787 
rtw_set_mcc_duration_cmd(_adapter * adapter,u8 type,u8 val)3788 u8 rtw_set_mcc_duration_cmd(_adapter *adapter, u8 type, u8 val)
3789 {
3790 	struct cmd_obj *cmdobj;
3791 	struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3792 	struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3793 	u8 *buf = NULL;
3794 	u8 sz = 2;
3795 	u8 res = _SUCCESS;
3796 
3797 
3798 	cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3799 	if (cmdobj == NULL) {
3800 		res = _FAIL;
3801 		goto exit;
3802 	}
3803 
3804 	pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3805 	if (pdrvextra_cmd_parm == NULL) {
3806 		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
3807 		res = _FAIL;
3808 		goto exit;
3809 	}
3810 
3811 	buf = rtw_zmalloc(sizeof(u8) * sz);
3812 	if (buf == NULL) {
3813 		rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
3814 		rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
3815 		res = _FAIL;
3816 		goto exit;
3817 	}
3818 
3819 	pdrvextra_cmd_parm->ec_id = MCC_CMD_WK_CID;
3820 	pdrvextra_cmd_parm->type = MCC_SET_DURATION_WK_CID;
3821 	pdrvextra_cmd_parm->size = sz;
3822 	pdrvextra_cmd_parm->pbuf = buf;
3823 
3824 	_rtw_memcpy(buf, &type, 1);
3825 	_rtw_memcpy(buf + 1, &val, 1);
3826 
3827 	init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3828 	res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3829 
3830 exit:
3831 	return res;
3832 }
3833 
3834 #ifdef CONFIG_MCC_PHYDM_OFFLOAD
mcc_phydm_offload_enable_hdl(_adapter * adapter,const u8 * val)3835 static u8 mcc_phydm_offload_enable_hdl(_adapter *adapter, const u8 *val)
3836 {
3837 	struct mcc_obj_priv *mccobjpriv =  adapter_to_mccobjpriv(adapter);
3838 	u8 ret = _SUCCESS;
3839 	u8 enable = *val;
3840 
3841 	/*only modify driver parameter during non-mcc status */
3842 	if (!rtw_hal_check_mcc_status(adapter, MCC_STATUS_DOING_MCC)) {
3843 		mccobjpriv->mcc_phydm_offload = enable;
3844 	} else {
3845 		/*modify both driver & phydm parameter during mcc status */
3846 		mccobjpriv->mcc_phydm_offload = enable;
3847 		rtw_hal_mcc_cfg_phydm(adapter, MCC_CFG_PHYDM_OFFLOAD, &mccobjpriv->mcc_phydm_offload);
3848 	}
3849 
3850 	RTW_INFO("[MCC] phydm offload enable hdl(%d)\n", mccobjpriv->mcc_phydm_offload);
3851 
3852 	return ret;
3853 }
3854 
rtw_set_mcc_phydm_offload_enable_cmd(_adapter * adapter,u8 enable,u8 enqueue)3855 u8 rtw_set_mcc_phydm_offload_enable_cmd(_adapter *adapter, u8 enable, u8 enqueue)
3856 {
3857 	u8 res = _SUCCESS;
3858 
3859 	if (enqueue) {
3860 		struct cmd_obj *cmdobj;
3861 		struct drvextra_cmd_parm *pdrvextra_cmd_parm;
3862 		struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
3863 		u8 *mcc_phydm_offload_enable = NULL;
3864 
3865 
3866 		cmdobj = (struct cmd_obj *)rtw_zmalloc(sizeof(struct cmd_obj));
3867 		if (cmdobj == NULL) {
3868 			res = _FAIL;
3869 			goto exit;
3870 		}
3871 
3872 		pdrvextra_cmd_parm = (struct drvextra_cmd_parm *)rtw_zmalloc(sizeof(struct drvextra_cmd_parm));
3873 		if (pdrvextra_cmd_parm == NULL) {
3874 			rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
3875 			res = _FAIL;
3876 			goto exit;
3877 		}
3878 
3879 		mcc_phydm_offload_enable = rtw_zmalloc(sizeof(u8));
3880 		if (mcc_phydm_offload_enable == NULL) {
3881 			rtw_mfree((u8 *)cmdobj, sizeof(struct cmd_obj));
3882 			rtw_mfree((u8 *)pdrvextra_cmd_parm, sizeof(struct drvextra_cmd_parm));
3883 			res = _FAIL;
3884 			goto exit;
3885 		}
3886 
3887 		pdrvextra_cmd_parm->ec_id = MCC_CMD_WK_CID;
3888 		pdrvextra_cmd_parm->type = MCC_SET_PHYDM_OFFLOAD_WK_CID;
3889 		pdrvextra_cmd_parm->size = 1;
3890 		pdrvextra_cmd_parm->pbuf = mcc_phydm_offload_enable;
3891 
3892 		_rtw_memcpy(mcc_phydm_offload_enable, &enable, 1);
3893 		init_h2fwcmd_w_parm_no_rsp(cmdobj, pdrvextra_cmd_parm, GEN_CMD_CODE(_Set_Drv_Extra));
3894 		res = rtw_enqueue_cmd(pcmdpriv, cmdobj);
3895 	} else {
3896 		mcc_phydm_offload_enable_hdl(adapter, &enable);
3897 	}
3898 
3899 exit:
3900 	return res;
3901 }
3902 #endif
3903 
rtw_mcc_cmd_hdl(_adapter * adapter,u8 type,const u8 * val)3904 u8 rtw_mcc_cmd_hdl(_adapter *adapter, u8 type, const u8 *val)
3905 {
3906 	struct mcc_obj_priv *mccobjpriv =  adapter_to_mccobjpriv(adapter);
3907 	u8 ret = _SUCCESS;
3908 
3909 	switch (type) {
3910 	case MCC_SET_DURATION_WK_CID:
3911 		set_mcc_duration_hdl(adapter, val);
3912 		break;
3913 	case MCC_GET_DBG_REG_WK_CID:
3914 		mcc_get_reg_hdl(adapter, val);
3915 		break;
3916 	#ifdef CONFIG_MCC_PHYDM_OFFLOAD
3917 	case MCC_SET_PHYDM_OFFLOAD_WK_CID:
3918 		mcc_phydm_offload_enable_hdl(adapter, val);
3919 		break;
3920 	#endif
3921 	default:
3922 		RTW_ERR("[MCC] rtw_mcc_cmd_hdl fail(%d)\n", type);
3923 		break;
3924 	}
3925 
3926 
3927 
3928 	return ret;
3929 }
3930 
3931 #endif /* CONFIG_MCC_MODE */
3932