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