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