xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852be/phl/phl_mcc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright(c) 2019 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 #define _PHL_MCC_C_
16 #include "phl_headers.h"
17 
18 #ifdef CONFIG_MCC_SUPPORT
19 #include "phl_mcc.h"
_mcc_dump_state(enum rtw_phl_mcc_state * state)20 void _mcc_dump_state(enum rtw_phl_mcc_state *state)
21 {
22 	if (MCC_NONE == *state) {
23 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_state(): MCC_NONE\n");
24 	} else if (MCC_CFG_EN_INFO == *state) {
25 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_state(): MCC_CFG_EN_INFO\n");
26 	} else if (MCC_TRIGGER_FW_EN == *state) {
27 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_state(): MCC_TRIGGER_FW_EN\n");
28 	} else if (MCC_FW_EN_FAIL == *state) {
29 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_state(): MCC_FW_EN_FAIL\n");
30 	} else if (MCC_RUNING == *state) {
31 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_state(): MCC_RUNING\n");
32 	} else if (MCC_TRIGGER_FW_DIS == *state) {
33 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_state(): MCC_TRIGGER_FW_DIS\n");
34 	} else if (MCC_FW_DIS_FAIL == *state) {
35 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_state(): MCC_FW_DIS_FAIL\n");
36 	} else if (MCC_STOP == *state) {
37 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_state(): MCC_STOP\n");
38 	} else {
39 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_dump_state(): Undefined state(%d)\n",
40 			*state);
41 	}
42 }
43 
_mcc_dump_mode(enum rtw_phl_tdmra_wmode * mode)44 void _mcc_dump_mode(enum rtw_phl_tdmra_wmode *mode)
45 {
46 	if (RTW_PHL_TDMRA_AP_CLIENT_WMODE == *mode) {
47 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_mode(): RTW_PHL_TDMRA_AP_CLIENT_WMODE\n");
48 	} else if (RTW_PHL_TDMRA_2CLIENTS_WMODE == *mode) {
49 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_mode(): RTW_PHL_TDMRA_2CLIENTS_WMODE\n");
50 	} else if (RTW_PHL_TDMRA_AP_WMODE == *mode) {
51 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_mode(): RTW_PHL_TDMRA_AP_WMODE\n");
52 	} else {
53 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_dump_mode(): Undefined mode(%d)\n",
54 			*mode);
55 	}
56 }
57 
_mcc_dump_sync_tsf_info(struct rtw_phl_mcc_sync_tsf_info * info)58 void _mcc_dump_sync_tsf_info(struct rtw_phl_mcc_sync_tsf_info *info)
59 {
60 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_sync_tsf_info(): sync_en(%d), source macid(%d), target macid(%d), offset(%d)\n",
61 		info->sync_en, info->source, info->target, info->offset);
62 }
63 
_mcc_dump_dur_info(struct rtw_phl_mcc_dur_info * dur_i)64 void _mcc_dump_dur_info(struct rtw_phl_mcc_dur_info *dur_i)
65 {
66 	struct rtw_phl_mcc_dur_lim_info *dur_l = NULL;
67 
68 	dur_l = &dur_i->dur_limit;
69 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_dump_role_info(): dur(%d), dur lim info: enable(%d), tag(%d), max_dur(%d)\n",
70 		dur_i->dur, dur_l->enable, dur_l->tag, dur_l->max_dur);
71 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "<<< _mcc_dump_role_info(): max_toa(%d), max_tob(%d)\n",
72 		dur_l->max_toa, dur_l->max_tob);
73 }
74 
_mcc_dump_role_info(struct rtw_phl_mcc_role * mrole)75 void _mcc_dump_role_info(struct rtw_phl_mcc_role *mrole)
76 {
77 	struct rtw_phl_mcc_policy_info *policy = &mrole->policy;
78 	u8 i = 0;
79 
80 	policy = &mrole->policy;
81 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_dump_role_info(): wrole id(%d), type(%d), macid(%d), bcn_intvl(%d)\n",
82 		mrole->wrole->id, mrole->wrole->type, mrole->macid,
83 		mrole->bcn_intvl);
84 	for (i = 0; i < PHL_MACID_MAX_ARRAY_NUM; i++) {
85 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_role_info(): macid_map[%d]= 0x%08X\n",
86 			i, mrole->used_macid.bitmap[i]);
87 	}
88 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_role_info(): chan(%d), center_ch(%d), bw(%d), offset(%d)\n",
89 		mrole->chandef->chan, mrole->chandef->center_ch,
90 		mrole->chandef->bw, mrole->chandef->offset);
91 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_role_info(): group(%d), c2h_rpt(%d), tx_null_early(%d)\n",
92 		mrole->group, policy->c2h_rpt, policy->tx_null_early);
93 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_role_info(): dis_tx_null(%d), in_curr_ch(%d), dis_sw_retry(%d)\n",
94 		policy->dis_tx_null, policy->in_curr_ch, policy->dis_sw_retry);
95 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_role_info(): sw_retry_count(%d), rfk_chk(%d)\n",
96 		policy->sw_retry_count, policy->rfk_chk);
97 	_mcc_dump_dur_info(&policy->dur_info);
98 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "<<< _mcc_dump_role_info(): courtesy_en(%d), courtesy_num(%d), courtesy_target(0x%x)\n",
99 		policy->courtesy_en, policy->courtesy_num,
100 		policy->courtesy_target);
101 }
102 
_mcc_dump_pattern(struct rtw_phl_mcc_pattern * m_pattern)103 void _mcc_dump_pattern(struct rtw_phl_mcc_pattern *m_pattern)
104 {
105 	struct rtw_phl_mcc_courtesy *courtesy_i = &m_pattern->courtesy_i;
106 
107 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_dump_pattern(): tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d), bcns_offset(%d), calc_fail(%d), d_r_d_a_spacing_max(%d), c_en(%d)\n",
108 		m_pattern->tob_r, m_pattern->toa_r, m_pattern->tob_a,
109 		m_pattern->toa_a, m_pattern->bcns_offset, m_pattern->calc_fail,
110 		m_pattern->d_r_d_a_spacing_max, courtesy_i->c_en);
111 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_pattern(): slot_num(%d), bt_slot_num(%d)\n",
112 		m_pattern->slot_num, m_pattern->bt_slot_num);
113 	if (courtesy_i->c_en) {
114 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "<<< _mcc_dump_pattern(): c_en(%d), c_num(%d), src_role->macid(0x%x), tgt_role->macid(0x%x)\n",
115 			courtesy_i->c_en, courtesy_i->c_num,
116 			courtesy_i->src_role->macid,
117 			courtesy_i->tgt_role->macid);
118 	}
119 }
120 
_mcc_dump_ref_role_info(struct rtw_phl_mcc_en_info * info)121 void _mcc_dump_ref_role_info(struct rtw_phl_mcc_en_info *info)
122 {
123 	struct rtw_phl_mcc_role *ref_role = NULL;
124 
125 	ref_role = get_ref_role(info);
126 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_ref_role_info(): mrole idx(%d), wrole id(%d), macid(%d) chan(%d), bw(%d), offset(%d)\n",
127 		info->ref_role_idx, ref_role->wrole->id, ref_role->macid,
128 		ref_role->chandef->chan, ref_role->chandef->bw,
129 		ref_role->chandef->offset);
130 }
131 
_mcc_dump_en_info(struct rtw_phl_mcc_en_info * info)132 void _mcc_dump_en_info(struct rtw_phl_mcc_en_info *info)
133 {
134 	struct rtw_phl_mcc_role *m_role = NULL;
135 	u8 midx = 0;
136 
137 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_en_info(): mrole_map(0x%x), role_num(%d), mcc_intvl(%d), Start tsf(0x%08X %08X)\n",
138 		info->mrole_map, info->mrole_num, info->mcc_intvl,
139 		info->tsf_high, info->tsf_low);
140 	_mcc_dump_ref_role_info(info);
141 	_mcc_dump_sync_tsf_info(&info->sync_tsf_info);
142 	_mcc_dump_pattern(&info->m_pattern);
143 	for (midx = 0; midx < MCC_ROLE_NUM; midx++) {
144 		if (!(info->mrole_map & BIT(midx)))
145 			continue;
146 		m_role = &info->mcc_role[midx];
147 		_mcc_dump_role_info(m_role);
148 	}
149 }
150 
_mcc_dump_bt_ino(struct rtw_phl_mcc_bt_info * bt_info)151 void _mcc_dump_bt_ino(struct rtw_phl_mcc_bt_info *bt_info)
152 {
153 	u8 seg_num = BT_SEG_NUM;
154 
155 	if (bt_info->bt_seg_num > seg_num)
156 		return;
157 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_dump_bt_ino(): bt_dur(%d), bt_seg_num(%d), bt_seg[0](%d), bt_seg[1](%d), add_bt_role(%d)\n",
158 		bt_info->bt_dur, bt_info->bt_seg_num, bt_info->bt_seg[0],
159 		bt_info->bt_seg[1], bt_info->add_bt_role);
160 }
161 
_mcc_dump_mcc_info(struct phl_mcc_info * minfo)162 void _mcc_dump_mcc_info(struct phl_mcc_info *minfo)
163 {
164 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_dump_mcc_info():\n");
165 	_mcc_dump_mode(&minfo->mcc_mode);
166 	_mcc_dump_state(&minfo->state);
167 	_mcc_dump_bt_ino(&minfo->bt_info);
168 	_mcc_dump_en_info(&minfo->en_info);
169 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "<<< _mcc_dump_mcc_info():\n");
170 }
171 
_mcc_set_state(struct phl_mcc_info * minfo,enum rtw_phl_mcc_state state)172 void _mcc_set_state(struct phl_mcc_info *minfo, enum rtw_phl_mcc_state state)
173 {
174 	PHL_TRACE(COMP_PHL_MCC, _PHL_ALWAYS_, "_mcc_set_state(): Set from (%d) to (%d)\n",
175 		minfo->state, state);
176 	minfo->state = state;
177 	_mcc_dump_state(&minfo->state);
178 }
179 
_mcc_is_ap_category(struct rtw_wifi_role_t * wrole)180 bool _mcc_is_ap_category(struct rtw_wifi_role_t *wrole)
181 {
182 	bool ret = false;
183 
184 	if (wrole->type == PHL_RTYPE_AP || wrole->type == PHL_RTYPE_P2P_GO)
185 		ret = true;
186 	return ret;
187 }
188 
_mcc_is_client_category(struct rtw_wifi_role_t * wrole)189 bool _mcc_is_client_category(struct rtw_wifi_role_t *wrole)
190 {
191 	bool ret = false;
192 
193 	if (wrole->type == PHL_RTYPE_STATION || wrole->type == PHL_RTYPE_P2P_GC || wrole->type == PHL_RTYPE_TDLS)
194 		ret = true;
195 	return ret;
196 }
197 
198 struct rtw_phl_mcc_role *
_mcc_get_mrole_by_wrole(struct phl_mcc_info * minfo,struct rtw_wifi_role_t * wrole)199 _mcc_get_mrole_by_wrole(struct phl_mcc_info *minfo,
200 				struct rtw_wifi_role_t *wrole)
201 {
202 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
203 	struct rtw_phl_mcc_role *m_role = NULL;
204 	u8 midx = 0;
205 
206 	for (midx = 0; midx < MCC_ROLE_NUM; midx++) {
207 		if (!(en_info->mrole_map & BIT(midx)))
208 			continue;
209 		m_role = &en_info->mcc_role[midx];
210 		if (m_role->wrole == wrole) {
211 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_get_mrole_by_wrole(): Get mrole in mrole_idx(%d), wrole->type(%d), wrole->id(%d)\n",
212 				midx, wrole->type, wrole->id);
213 			return m_role;
214 		}
215 	}
216 	return NULL;
217 }
218 
219 u8
_mcc_get_mrole_idx_by_wrole(struct phl_mcc_info * minfo,struct rtw_wifi_role_t * wrole,u8 * idx)220 _mcc_get_mrole_idx_by_wrole(struct phl_mcc_info *minfo,
221 				struct rtw_wifi_role_t *wrole, u8 *idx)
222 {
223 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
224 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
225 	struct rtw_phl_mcc_role *m_role = NULL;
226 	u8 midx = 0;
227 
228 	for (midx = 0; midx < MCC_ROLE_NUM; midx++) {
229 		if (!(en_info->mrole_map & BIT(midx)))
230 			continue;
231 		m_role = &en_info->mcc_role[midx];
232 		if (m_role->wrole == wrole) {
233 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_get_mrole_idx_by_wrole(): Get mrole in mrole_idx(%d)\n",
234 				midx);
235 			*idx = midx;
236 			status = RTW_PHL_STATUS_SUCCESS;
237 			break;
238 		}
239 	}
240 	return status;
241 }
242 
243 struct rtw_phl_mcc_role *
_mcc_get_mrole_by_category(struct rtw_phl_mcc_en_info * en_info,enum _mcc_role_cat category)244 _mcc_get_mrole_by_category(struct rtw_phl_mcc_en_info *en_info,
245 			enum _mcc_role_cat category)
246 {
247 	struct rtw_phl_mcc_role *m_role = NULL;
248 	u8 midx = 0;
249 
250 	for (midx = 0; midx < MCC_ROLE_NUM; midx++) {
251 		if (!(en_info->mrole_map & BIT(midx)))
252 			continue;
253 		m_role = &en_info->mcc_role[midx];
254 		if (MCC_ROLE_AP_CAT == category) {
255 			if (_mcc_is_ap_category(m_role->wrole))
256 				return m_role;
257 		} else if (MCC_ROLE_CLIENT_CAT == category) {
258 			if (_mcc_is_client_category(m_role->wrole))
259 				return m_role;
260 		} else {
261 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_get_mrole_by_category(): Undefined category(%d)\n",
262 				category);
263 			break;
264 		}
265 	}
266 	return NULL;
267 }
268 
_mcc_transfer_mode(struct phl_info_t * phl,struct phl_mcc_info * minfo,u8 role_map)269 enum rtw_phl_status _mcc_transfer_mode(struct phl_info_t *phl,
270 				struct phl_mcc_info *minfo, u8 role_map)
271 {
272 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
273 	struct rtw_wifi_role_t *wrole = NULL;
274 	u8 ridx = 0, ap_num = 0, client_num = 0;
275 
276 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
277 		if (!(role_map & BIT(ridx)))
278 			continue;
279 		wrole = rtw_phl_get_wrole_by_ridx(phl->phl_com, ridx);
280 		if (wrole == NULL) {
281 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_transfer_mode(): get wrole fail, role_idx(%d)\n",
282 				ridx);
283 			goto exit;
284 		}
285 		if (_mcc_is_client_category(wrole)) {
286 			client_num++;
287 		} else if (_mcc_is_ap_category(wrole)) {
288 			ap_num++;
289 		} else {
290 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_transfer_mode(): undefined category, role->type(%d), ridx(%d), shall check code flow\n",
291 				wrole->type, ridx);
292 			goto exit;
293 		}
294 	}
295 	if ((client_num + ap_num > MAX_MCC_GROUP_ROLE)){
296 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_transfer_mode(): client_num(%d) + ap_num(%d) is illegal num, please check code flow\n",
297 			client_num, ap_num);
298 		goto exit;
299 	}
300 	if (ap_num == 1 && client_num == 1) {
301 		minfo->mcc_mode = RTW_PHL_TDMRA_AP_CLIENT_WMODE;
302 	} else if (ap_num == 0 && client_num == 2) {
303 		minfo->mcc_mode = RTW_PHL_TDMRA_2CLIENTS_WMODE;
304 	} else if (ap_num == 1 && client_num == 0) {
305 		minfo->mcc_mode = RTW_PHL_TDMRA_AP_WMODE;
306 	} else {
307 		minfo->mcc_mode = RTW_PHL_TDMRA_UNKNOWN_WMODE;
308 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_transfer_mode(): Undefined mode, please check code flow\n");
309 		goto exit;
310 	}
311 	_mcc_dump_mode(&minfo->mcc_mode);
312 	status = RTW_PHL_STATUS_SUCCESS;
313 exit:
314 	return status;
315 }
316 
_mcc_get_role_map(struct phl_info_t * phl,struct hw_band_ctl_t * band_ctrl,u8 * role_map)317 enum rtw_phl_status _mcc_get_role_map(struct phl_info_t *phl,
318 				struct hw_band_ctl_t *band_ctrl, u8 *role_map)
319 {
320 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
321 	void *drv = phl_to_drvpriv(phl);
322 	struct rtw_chan_ctx *chanctx = NULL;
323 	_os_list *chan_ctx_list = &band_ctrl->chan_ctx_queue.queue;
324 
325 	*role_map = 0;
326 	_os_spinlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
327 	phl_list_for_loop(chanctx, struct rtw_chan_ctx, chan_ctx_list, list) {
328 		*role_map |= chanctx->role_map;
329 	}
330 	_os_spinunlock(drv, &band_ctrl->chan_ctx_queue.lock, _ps, NULL);
331 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_get_role_map(): role_map(%d)\n",
332 		*role_map);
333 	status = RTW_PHL_STATUS_SUCCESS;
334 	return status;
335 }
336 
_mcc_set_fw_log_info(struct phl_info_t * phl,u8 hw_band,bool en_fw_mcc_log,u8 fw_mcc_log_lv)337 void _mcc_set_fw_log_info(struct phl_info_t *phl, u8 hw_band,
338 			bool en_fw_mcc_log, u8 fw_mcc_log_lv)
339 {
340 	struct phl_mcc_info *minfo = get_mcc_info(phl, hw_band);
341 
342 	if (minfo->fw_log_i.en_fw_mcc_log != en_fw_mcc_log) {
343 		minfo->fw_log_i.en_fw_mcc_log = en_fw_mcc_log;
344 		minfo->fw_log_i.update = true;
345 	}
346 	if (minfo->fw_log_i.fw_mcc_log_lv != fw_mcc_log_lv) {
347 		minfo->fw_log_i.fw_mcc_log_lv = fw_mcc_log_lv;
348 		minfo->fw_log_i.update = true;
349 	}
350 }
351 
_mcc_up_fw_log_setting(struct phl_info_t * phl,struct phl_mcc_info * minfo)352 void _mcc_up_fw_log_setting(struct phl_info_t *phl, struct phl_mcc_info *minfo)
353 {
354 	struct phl_mcc_fw_log_info *fw_log_i = &minfo->fw_log_i;
355 
356 	if (fw_log_i->update) {
357 		rtw_hal_cfg_fw_mcc_log(phl->hal, fw_log_i->en_fw_mcc_log);
358 		fw_log_i->update = false;
359 	}
360 }
361 
_mcc_set_unspecific_dur(struct phl_mcc_info * minfo)362 void _mcc_set_unspecific_dur(struct phl_mcc_info *minfo)
363 {
364 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
365 	struct rtw_phl_mcc_role *m_role = NULL;
366 	u8 midx = 0;
367 
368 	for (midx = 0; midx < MCC_ROLE_NUM; midx++) {
369 		if (!(en_info->mrole_map & BIT(midx)))
370 			continue;
371 		m_role = &en_info->mcc_role[midx];
372 		m_role->policy.dur_info.dur = MCC_DUR_NONSPECIFIC;
373 	}
374 }
375 
_mcc_fill_dur_lim_info(struct phl_info_t * phl,struct rtw_phl_mcc_role * mrole,struct phl_mcc_dur_lim_req_info * dur_req)376 void _mcc_fill_dur_lim_info(struct phl_info_t *phl,
377 				struct rtw_phl_mcc_role *mrole,
378 				struct phl_mcc_dur_lim_req_info *dur_req)
379 {
380 	struct rtw_phl_mcc_dur_info *dur_i = &mrole->policy.dur_info;
381 	struct rtw_phl_mcc_dur_lim_info *dur_lim = &dur_i->dur_limit;
382 	u64 tsf_lim = 0;
383 	u32 max_toa = 0, max_tob = 0, max_dur = 0;
384 	u32 bcn_intvl = mrole->bcn_intvl * TU;
385 
386 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_dur_lim_info(): dur_req: tag(%d), enable(%d), start_t_h(0x%08x), start_t_l(0x%08x), dur(%d), intvl(%d)\n",
387 		dur_req->tag, dur_req->enable, dur_req->start_t_h,
388 		dur_req->start_t_l, dur_req->dur, dur_req->intvl);
389 	dur_lim->enable = false;
390 	if (!dur_req->enable) {
391 		goto exit;
392 	}
393 	if (bcn_intvl != dur_req->intvl) {
394 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_dur_lim_info(): not support bcn_intvl(%d) != dur_req.intvl(%d), please check code\n",
395 			bcn_intvl, dur_req->intvl);
396 		goto exit;
397 	}
398 	/*Assume bcn allocat in TSF % BcnInvtal = 0*/
399 	tsf_lim = dur_req->start_t_h;
400 	tsf_lim = tsf_lim << 32;
401 	tsf_lim |= dur_req->start_t_l;
402 	max_toa = (u16)_os_modular64(tsf_lim, mrole->bcn_intvl * TU);
403 	if (max_toa >= (mrole->bcn_intvl * TU - dur_req->dur) ||
404 		max_toa == 0) {
405 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_dur_lim_info(): not support bcn allocate in limited slot, please check code\n");
406 		goto exit;
407 	}
408 	max_dur = dur_req->intvl - dur_req->dur;
409 	max_toa = max_toa / TU;
410 	max_dur = max_dur / TU;
411 	max_tob = max_dur - max_toa;
412 
413 	dur_lim->max_toa = (u16)max_toa;
414 	dur_lim->max_tob = (u16)max_tob;
415 	dur_lim->max_dur = (u16)max_dur;
416 	dur_lim->tag = dur_req->tag;
417 	dur_lim->enable = true;
418 exit:
419 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_dur_lim_info(): dur_lim_info: enable(%d), tag(%d), max_toa(%d), max_tob(%d), max_dur(%d)\n",
420 			dur_lim->enable, dur_lim->tag, dur_lim->max_toa,
421 			dur_lim->max_tob, dur_lim->max_dur);
422 	return;
423 }
424 
_mcc_fill_default_policy(struct phl_info_t * phl,struct rtw_phl_mcc_role * mrole)425 void _mcc_fill_default_policy(struct phl_info_t *phl,
426 				struct rtw_phl_mcc_role *mrole)
427 {
428 	struct rtw_phl_mcc_policy_info *policy = &mrole->policy;
429 	struct phl_mcc_dur_lim_req_info dur_req = {0};
430 
431 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_default_policy(): set mcc policy by default setting\n");
432 	policy->c2h_rpt = RTW_MCC_RPT_ALL;
433 	policy->tx_null_early = 3;
434 	policy->dis_tx_null = _mcc_is_client_category(mrole->wrole) ? 0 : 1;
435 	policy->in_curr_ch = 0;
436 	policy->dis_sw_retry = 1;
437 	policy->sw_retry_count = 0;
438 	policy->dur_info.dur = _mcc_is_client_category(mrole->wrole) ?
439 					DEFAULT_CLIENT_DUR : DEFAULT_AP_DUR;
440 	phl_mr_mcc_query_role_time_slot_lim(phl, mrole->wrole, &dur_req);
441 	_mcc_fill_dur_lim_info(phl, mrole, &dur_req);
442 	policy->rfk_chk = rtw_hal_check_ch_rfk(phl->hal, &mrole->wrole->chandef);
443 	if (false == policy->rfk_chk) {
444 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_fill_default_policy(): No rfk, it will degrade perormance, please check code\n");
445 	}
446 }
447 
_mcc_fill_mcc_role_policy_info(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole,struct rtw_phl_mcc_role * mrole)448 void _mcc_fill_mcc_role_policy_info(struct phl_info_t *phl,
449 		struct rtw_wifi_role_t *wrole, struct rtw_phl_mcc_role *mrole)
450 {
451 	struct phl_com_mcc_info *com_info = phl_to_com_mcc_info(phl);
452 	struct rtw_phl_mcc_policy_info *policy = &mrole->policy;
453 	struct rtw_phl_mcc_setting_info param = {0};
454 	struct phl_mcc_info *minfo = get_mcc_info(phl, wrole->hw_band);
455 
456 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, ">>> _mcc_fill_mcc_role_policy_info()\n");
457 	_mcc_fill_default_policy(phl, mrole);
458 	if (NULL == com_info->ops.mcc_get_setting)
459 		goto exit;
460 	param.wrole = wrole;
461 	param.role_map = minfo->role_map;
462 	param.tx_null_early = NONSPECIFIC_SETTING;
463 	param.dur = NONSPECIFIC_SETTING;
464 	if (!com_info->ops.mcc_get_setting(com_info->ops.priv, &param)) {
465 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_fill_mcc_role_policy_info(): mcc_get_setting from core layer fail\n");
466 		goto exit;
467 	}
468 	if (NONSPECIFIC_SETTING != param.tx_null_early) {
469 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_fill_mcc_role_policy_info(): Core layer change tx_null_early from %d to %d\n",
470 			policy->tx_null_early, param.tx_null_early);
471 		policy->tx_null_early = param.tx_null_early;
472 	}
473 	if (NONSPECIFIC_SETTING != param.dur) {
474 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_fill_mcc_role_policy_info(): Core layer change dur from %d to %d\n",
475 			policy->dur_info.dur, param.dur);
476 		policy->dur_info.dur = param.dur;
477 	}
478 	_mcc_set_fw_log_info(phl, wrole->hw_band, param.en_fw_mcc_log,
479 				param.fw_mcc_log_lv);
480 exit:
481 	return;
482 }
483 
_mcc_fill_macid_bitmap_by_role(struct phl_info_t * phl,struct rtw_phl_mcc_role * mrole)484 void _mcc_fill_macid_bitmap_by_role(struct phl_info_t *phl,
485 					struct rtw_phl_mcc_role *mrole)
486 {
487 	struct macid_ctl_t *mc = phl_to_mac_ctrl(phl);
488 	struct rtw_phl_mcc_macid_bitmap *used_macid = &mrole->used_macid;
489 	u8 i = 0, max_map_idx = 0;
490 
491 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_fill_macid_bitmap_by_role()\n");
492 	for (i = 0; i < PHL_MACID_MAX_ARRAY_NUM; i++) {
493 		if ((mc->wifi_role_usedmap[mrole->wrole->id][i] != 0) &&
494 							(max_map_idx <= i)) {
495 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_macid_bitmap_by_role(): macid_map[%d]=0x%08x\n",
496 				i, mc->wifi_role_usedmap[mrole->wrole->id][i]);
497 			max_map_idx = i;
498 		}
499 	}
500 	used_macid->bitmap = &mc->wifi_role_usedmap[mrole->wrole->id][0];
501 	used_macid->len = (max_map_idx + 1) * sizeof(u32);
502 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_macid_bitmap_by_role(): bitmap->len(%d), max_map_idx(%d)\n",
503 		used_macid->len, max_map_idx);
504 }
505 
_mcc_fill_mcc_role_basic_info(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole,struct rtw_phl_mcc_role * mrole)506 enum rtw_phl_status _mcc_fill_mcc_role_basic_info(struct phl_info_t *phl,
507 		struct rtw_wifi_role_t *wrole, struct rtw_phl_mcc_role *mrole)
508 {
509 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
510 	struct rtw_phl_stainfo_t *sta = rtw_phl_get_stainfo_self(phl, wrole);
511 
512 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_fill_mcc_role_basic_info()\n");
513 	if (sta == NULL) {
514 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_mcc_role_basic_info(): transfer mcc mode failed\n");
515 		goto exit;
516 	}
517 	mrole->wrole = wrole;
518 	mrole->macid = sta->macid;
519 #ifdef RTW_PHL_BCN
520 	if (_mcc_is_ap_category(wrole))
521 		mrole->bcn_intvl = (u16)wrole->bcn_cmn.bcn_interval;
522 	else
523 #endif
524 		mrole->bcn_intvl = sta->asoc_cap.bcn_interval;
525 	if (mrole->bcn_intvl == 0) {
526 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_mcc_role_basic_info(): mrole->bcn_intvl ==0, please check code of core layer.\n");
527 		goto exit;
528 	}
529 	mrole->chandef = &wrole->chandef;
530 	_mcc_fill_macid_bitmap_by_role(phl, mrole);
531 	status = RTW_PHL_STATUS_SUCCESS;
532 exit:
533 	return status;
534 }
535 
_mcc_fill_ref_role_info(struct phl_info_t * phl,struct rtw_phl_mcc_en_info * en_info,struct rtw_wifi_role_t * wrole)536 enum rtw_phl_status _mcc_fill_ref_role_info(struct phl_info_t *phl,
537 			struct rtw_phl_mcc_en_info *en_info,
538 			struct rtw_wifi_role_t *wrole)
539 {
540 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
541 	struct rtw_phl_mcc_role *mrole = NULL;
542 
543 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_fill_ref_role_info()\n");
544 	mrole = &en_info->mcc_role[REF_ROLE_IDX];
545 	status = _mcc_fill_mcc_role_basic_info(phl, wrole, mrole);
546 	if (RTW_PHL_STATUS_SUCCESS != status) {
547 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_ref_role_info(): set basic info failed\n");
548 		goto exit;
549 	}
550 	_mcc_fill_mcc_role_policy_info(phl, wrole, mrole);
551 	en_info->mrole_map |= BIT(REF_ROLE_IDX);
552 	en_info->mrole_num++;
553 	status = RTW_PHL_STATUS_SUCCESS;
554 exit:
555 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_ref_role_info(): status(%d), wrole id(%d), wrole->type(%d), Fill mrole(%d) Info\n",
556 			status, wrole->id, wrole->type, REF_ROLE_IDX);
557 	return status;
558 }
559 
_mcc_fill_role_info(struct phl_info_t * phl,struct rtw_phl_mcc_en_info * en_info,u8 role_map,struct rtw_wifi_role_t * cur_role)560 enum rtw_phl_status _mcc_fill_role_info(struct phl_info_t *phl,
561 			struct rtw_phl_mcc_en_info *en_info, u8 role_map,
562 			struct rtw_wifi_role_t *cur_role)
563 {
564 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
565 	struct rtw_wifi_role_t *wrole = NULL;
566 	struct rtw_phl_mcc_role *mrole = NULL;
567 	u8 ridx = 0, mcc_idx = 0;
568 
569 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_fill_role_info()\n");
570 	if (RTW_PHL_STATUS_SUCCESS != _mcc_fill_ref_role_info(phl, en_info,
571 								cur_role)) {
572 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_role_info(): set ref role info failed\n");
573 		goto exit;
574 	}
575 	mcc_idx = en_info->mrole_num;
576 	role_map &= ~(BIT(cur_role->id));
577 	for (ridx = 0; ridx < MAX_WIFI_ROLE_NUMBER; ridx++) {
578 		if (!(role_map & BIT(ridx)))
579 			continue;
580 		wrole = rtw_phl_get_wrole_by_ridx(phl->phl_com, ridx);
581 		if (wrole == NULL) {
582 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_role_info(): get wrole fail, role_idx(%d)\n",
583 				ridx);
584 			goto exit;
585 		}
586 		if (mcc_idx >= MCC_ROLE_NUM) {
587 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_role_info(): mcc_idx(%d) >= MCC_ROLE_NUM(%d)\n",
588 				mcc_idx, MCC_ROLE_NUM);
589 			goto exit;
590 		}
591 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_role_info(): wrole(%d), wrole->type(%d), Fill mrole(%d) Info\n",
592 			ridx, wrole->type, mcc_idx);
593 		mrole = &en_info->mcc_role[mcc_idx];
594 		status = _mcc_fill_mcc_role_basic_info(phl, wrole, mrole);
595 		if (RTW_PHL_STATUS_SUCCESS != status) {
596 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_role_info(): set basic info failed\n");
597 			goto exit;
598 		}
599 		_mcc_fill_mcc_role_policy_info(phl, wrole, mrole);
600 		en_info->mrole_map |= BIT(mcc_idx);
601 		en_info->mrole_num++;
602 		mcc_idx ++;
603 	}
604 	status = RTW_PHL_STATUS_SUCCESS;
605 exit:
606 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "<<< _mcc_fill_role_info(): status(%d), role_map(0x%x), mcc_role_map(0x%x)\n",
607 		status, role_map, en_info->mrole_map);
608 	return status;
609 }
610 
_mcc_fill_coex_mode(struct phl_info_t * phl,struct phl_mcc_info * minfo)611 void _mcc_fill_coex_mode(struct phl_info_t *phl, struct phl_mcc_info *minfo)
612 {
613 	/* if get from core or ....
614 	else*/
615 	minfo->coex_mode = RTW_PHL_MCC_COEX_MODE_BT_MASTER;
616 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_coex_mode(): Set default mode(%d)\n",
617 		minfo->coex_mode);
618 }
619 
_mcc_fill_bt_dur(struct phl_info_t * phl,struct phl_mcc_info * minfo)620 void _mcc_fill_bt_dur(struct phl_info_t *phl, struct phl_mcc_info *minfo)
621 {
622 	minfo->bt_info.bt_dur = (u16)rtw_hal_get_btc_req_slot(phl->hal);
623 	minfo->bt_info.bt_seg_num = 1;
624 	minfo->bt_info.bt_seg[0] = minfo->bt_info.bt_dur;
625 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_bt_dur(): minfo->bt_info.bt_dur(%d)\n",
626 		minfo->bt_info.bt_dur);
627 
628 }
629 
630 /*
631  * fill slot info
632  * @m_pattern: pattern info
633  * @bt_role: True: BT Role; False: Wifi Role
634  * @dur: time slot
635  * @mrole: mcc role info
636  */
_mcc_fill_slot_info(struct rtw_phl_mcc_pattern * m_pattern,bool bt_role,u16 dur,struct rtw_phl_mcc_role * mrole)637 void _mcc_fill_slot_info(struct rtw_phl_mcc_pattern *m_pattern, bool bt_role,
638 				u16 dur, struct rtw_phl_mcc_role *mrole)
639 {
640 	if (m_pattern->slot_num >= SLOT_NUM) {
641 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_slot_info(): Fail, m_pattern->slot_num(%d) >= SLOT_NUM(%d)\n",
642 		m_pattern->slot_num, SLOT_NUM);
643 		return;
644 	}
645 	if (bt_role) {
646 		m_pattern->slot_order[m_pattern->slot_num].bt_role = true;
647 		m_pattern->slot_order[m_pattern->slot_num].slot = dur;
648 		m_pattern->slot_order[m_pattern->slot_num].mrole = NULL;
649 		m_pattern->bt_slot_num++;
650 	} else {
651 		m_pattern->slot_order[m_pattern->slot_num].bt_role = false;
652 		m_pattern->slot_order[m_pattern->slot_num].slot = dur;
653 		m_pattern->slot_order[m_pattern->slot_num].mrole = mrole;
654 	}
655 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "m_pattern->slot_num(): Fill slot, Idx(%d), dur(%d), is BT slot(%d)\n",
656 		m_pattern->slot_num, dur, bt_role);
657 	m_pattern->slot_num++;
658 }
659 
_mcc_reset_minfo(struct phl_info_t * phl,struct phl_mcc_info * minfo,enum _mcc_minfo_reset_type reset_type)660 void _mcc_reset_minfo(struct phl_info_t *phl, struct phl_mcc_info *minfo,
661 				enum _mcc_minfo_reset_type reset_type)
662 {
663 	void *priv = phl_to_drvpriv(phl);
664 
665 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_reset_minfo\n");
666 	if (reset_type == MINFO_RESET_ALL) {
667 		_os_mem_set(priv, minfo, 0, sizeof(struct phl_mcc_info));
668 		return;
669 	}
670 	if (reset_type & MINFO_RESET_EN_INFO)
671 		_os_mem_set(priv, &minfo->en_info, 0,
672 				sizeof(struct rtw_phl_mcc_en_info));
673 	if (reset_type & MINFO_RESET_MODE)
674 		_os_mem_set(priv, &minfo->mcc_mode, 0,
675 				sizeof(enum rtw_phl_tdmra_wmode));
676 	if (reset_type & MINFO_RESET_ROLE_MAP)
677 		_os_mem_set(priv, &minfo->role_map, 0,
678 				sizeof(minfo->role_map));
679 	if (reset_type & MINFO_RESET_STATE)
680 		_os_mem_set(priv, &minfo->state, 0,
681 				sizeof(enum rtw_phl_mcc_state));
682 	if (reset_type & MINFO_RESET_COEX_MODE)
683 		_os_mem_set(priv, &minfo->coex_mode, 0,
684 				sizeof(enum rtw_phl_mcc_coex_mode));
685 	if (reset_type & MINFO_RESET_BT_INFO)
686 		_os_mem_set(priv, &minfo->bt_info, 0,
687 				sizeof(struct rtw_phl_mcc_bt_info));
688 	if (reset_type & MINFO_RESET_PATTERN_INFO)
689 		_os_mem_set(priv, &minfo->en_info.m_pattern, 0,
690 				sizeof(struct rtw_phl_mcc_pattern));
691 }
692 
_mcc_clean_noa(struct phl_info_t * phl,struct rtw_phl_mcc_en_info * en_info)693 void _mcc_clean_noa(struct phl_info_t *phl, struct rtw_phl_mcc_en_info *en_info)
694 {
695 	struct phl_com_mcc_info *com_info = phl_to_com_mcc_info(phl);
696 	struct rtw_phl_mcc_noa param = {0};
697 
698 	if (com_info == NULL) {
699 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_clean_noa(): Get mcc common info failed\n");
700 	} else if (com_info->ops.mcc_update_noa) {
701 		struct rtw_phl_mcc_role *ap_role = NULL;
702 		ap_role = _mcc_get_mrole_by_category(en_info, MCC_ROLE_AP_CAT);
703 		if (NULL == ap_role) {
704 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_clean_noa(): Get AP role fail\n");
705 			goto exit;
706 		}
707 		param.wrole = ap_role->wrole;
708 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_clean_noa()\n");
709 		com_info->ops.mcc_update_noa(com_info->ops.priv, &param);
710 	}
711 exit:
712 	return;
713 }
714 
_tdmra_calc_noa_2wrole(struct phl_info_t * phl,struct phl_mcc_info * minfo,struct rtw_phl_mcc_noa * param)715 bool _tdmra_calc_noa_2wrole(struct phl_info_t *phl, struct phl_mcc_info *minfo,
716 				struct rtw_phl_mcc_noa *param)
717 {
718 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
719 	struct rtw_phl_mcc_bt_info *bt = &minfo->bt_info;
720 	struct rtw_phl_mcc_role *role_ref = get_ref_role(en_info);
721 	struct rtw_phl_mcc_role *role_ano = (role_ref == &en_info->mcc_role[0])
722 				? &en_info->mcc_role[1] : &en_info->mcc_role[0];
723 	u16 d_r = role_ref->policy.dur_info.dur;
724 	u16 d_a = role_ano->policy.dur_info.dur;
725 	u64 mcc_start = 0, noa_start = 0;
726 	bool ret = false;
727 
728 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, ">>> _tdmra_calc_noa_2wrole()\n");
729 	mcc_start = en_info->tsf_high;
730 	mcc_start = mcc_start << 32;
731 	mcc_start |= en_info->tsf_low;
732 	if (_mcc_is_ap_category(role_ref->wrole)){
733 		/*calculate end time of GO*/
734 		noa_start = mcc_start + (d_r * TU);
735 		param->dur = en_info->mcc_intvl - d_r;
736 		param->wrole = role_ref->wrole;
737 	} else {
738 		u32 tsf_ref_h = 0, tsf_ref_l = 0, tsf_ano_h = 0, tsf_ano_l = 0;
739 		u64 tsf_ref = 0, tsf_ano = 0;
740 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_tdmra_calc_noa_2wrole(): AP Role isn't ref role, we need to get 2 port tsf\n");
741 		_mcc_dump_bt_ino(bt);
742 		if (RTW_HAL_STATUS_SUCCESS != rtw_hal_mcc_get_2ports_tsf(
743 				phl->hal, role_ref->group, role_ref->macid,
744 				role_ano->macid, &tsf_ref_h, &tsf_ref_l,
745 				&tsf_ano_h, &tsf_ano_l)) {
746 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_tdmra_calc_noa_2wrole(): Get 2 port tsf failed\n");
747 			goto exit;
748 		}
749 		tsf_ref = tsf_ref_h;
750 		tsf_ref = tsf_ref << 32;
751 		tsf_ref |= tsf_ref_l;
752 		tsf_ano = tsf_ano_h;
753 		tsf_ano = tsf_ano << 32;
754 		tsf_ano |= tsf_ano_l;
755 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_tdmra_calc_noa_2wrole(): tsf_ref: 0x%08X %08x, tsf_ano: 0x%08x %08x\n",
756 			(u32)(tsf_ref >> 32), (u32)tsf_ref,
757 			(u32)(tsf_ano >> 32), (u32)tsf_ano);
758 		/*calculate end time of GO*/
759 		noa_start = mcc_start + (en_info->mcc_intvl * TU);
760 		if (bt->add_bt_role) {
761 			if(bt->bt_seg_num == 1) {
762 				noa_start -= (bt->bt_seg[0] * TU);
763 			} else if (bt->bt_seg_num == 2) {
764 				noa_start -= (bt->bt_seg[1] * TU);
765 			} else {
766 				PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_tdmra_calc_noa_2wrole(): error bt_seg_num(%d), please check code flow\n",
767 					bt->bt_seg_num);
768 				goto exit;
769 			}
770 		}
771 		noa_start = noa_start - tsf_ref + tsf_ano;
772 		param->dur = en_info->mcc_intvl - d_a;
773 		param->wrole = role_ano->wrole;
774 	}
775 	param->start_t_h = noa_start >> 32;
776 	param->start_t_l = (u32)noa_start;
777 	param->cnt = 255;
778 	param->interval = en_info->mcc_intvl;
779 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_tdmra_calc_noa_2wrole(): IsGORef(%d), mcc_start(0x%08x %08x)\n",
780 		_mcc_is_ap_category(role_ref->wrole),
781 		(u32)(mcc_start >> 32), (u32)mcc_start);
782 	ret = true;
783 exit:
784 	return ret;
785 }
786 
_tdmra_calc_noa_1wrole(struct phl_info_t * phl,struct phl_mcc_info * minfo,struct rtw_phl_mcc_noa * param)787 bool _tdmra_calc_noa_1wrole(struct phl_info_t *phl, struct phl_mcc_info *minfo,
788 				struct rtw_phl_mcc_noa *param)
789 {
790 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
791 	struct rtw_phl_mcc_role *role_ref = get_ref_role(en_info);
792 	u16 d_r = role_ref->policy.dur_info.dur;
793 	u64 mcc_start = 0, noa_start = 0;
794 	bool ret = false;
795 
796 	mcc_start = en_info->tsf_high;
797 	mcc_start = mcc_start << 32;
798 	mcc_start |= en_info->tsf_low;
799 	/*calculate end time of GO*/
800 	noa_start = mcc_start + (d_r * TU);
801 	param->dur = en_info->mcc_intvl - d_r;
802 	param->wrole = role_ref->wrole;
803 	param->start_t_h = noa_start >> 32;
804 	param->start_t_l = (u32)noa_start;
805 	param->cnt = 255;
806 	param->interval = en_info->mcc_intvl;
807 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_tdmra_calc_noa_1wrole(): IsGORef(%d), mcc_start(0x%08x %08x)\n",
808 		_mcc_is_ap_category(role_ref->wrole),
809 		(u32)(mcc_start >> 32), (u32)mcc_start);
810 	ret = true;
811 	return ret;
812 }
813 
814 
_mcc_up_noa(struct phl_info_t * phl,struct phl_mcc_info * minfo)815 void _mcc_up_noa(struct phl_info_t *phl, struct phl_mcc_info *minfo)
816 
817 {
818 	struct phl_com_mcc_info *com_info = phl_to_com_mcc_info(phl);
819 	struct rtw_phl_mcc_noa param = {0};
820 
821 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, ">>> _mcc_up_noa()\n");
822 	if (com_info == NULL) {
823 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_up_noa(): Get mcc common info failed\n");
824 		goto exit;
825 	}
826 	if (!com_info->ops.mcc_update_noa)
827 		goto exit;
828 	if (RTW_PHL_TDMRA_AP_CLIENT_WMODE == minfo->mcc_mode) {
829 		if (false == _tdmra_calc_noa_2wrole(phl, minfo, &param))
830 			goto exit;
831 	} else if (RTW_PHL_TDMRA_AP_WMODE == minfo->mcc_mode) {
832 		if (false == _tdmra_calc_noa_1wrole(phl, minfo, &param))
833 			goto exit;
834 	} else {
835 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_up_noa(): error wmode\n");
836 		_mcc_dump_mode(&minfo->mcc_mode);
837 		goto exit;
838 	}
839 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_up_noa(): NOA_start(0x%08x %08x), dur(%d), cnt(%d), interval(%d)\n",
840 		param.start_t_h, param.start_t_l, param.dur, param.cnt,
841 		param.interval);
842 	com_info->ops.mcc_update_noa(com_info->ops.priv, &param);
843 exit:
844 	return;
845 }
846 
_mcc_adjust_dur_for_2g_mcc_2role_bt(struct phl_mcc_info * minfo)847 bool _mcc_adjust_dur_for_2g_mcc_2role_bt(struct phl_mcc_info *minfo)
848 {
849 	struct rtw_phl_mcc_bt_info *bt_info = &minfo->bt_info;
850 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
851 	struct rtw_phl_mcc_role *m_role1 = &en_info->mcc_role[0];
852 	struct rtw_phl_mcc_role *m_role2 = &en_info->mcc_role[1];
853 	u16 d1 = m_role1->policy.dur_info.dur;
854 	u16 d2 = m_role2->policy.dur_info.dur;
855 	u16 d1_max = (m_role1->policy.dur_info.dur_limit.enable) ?
856 		m_role1->policy.dur_info.dur_limit.max_dur : en_info->mcc_intvl;
857 	u16 d2_max = (m_role2->policy.dur_info.dur_limit.enable) ?
858 		m_role2->policy.dur_info.dur_limit.max_dur : en_info->mcc_intvl;
859 	u16 d1_min = _mcc_is_ap_category(m_role1->wrole) ?
860 					MIN_AP_DUR : MIN_CLIENT_DUR;
861 	u16 d2_min = _mcc_is_ap_category(m_role2->wrole) ?
862 					MIN_AP_DUR : MIN_CLIENT_DUR;
863 	u16 wifi_dur = 0, bt_dur = bt_info->bt_dur;
864 	u16 i = 0;
865 	bool adjust_ok = false;
866 
867 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_adjust_dur_for_2g_mcc_2role_bt(): mcc_intvl(%d), bt_dur(%d), d1(%d), d2(%d), d1_min(%d), d1_max(%d), d2_min(%d), d2_max(%d)\n",
868 		en_info->mcc_intvl, bt_dur, d1, d2, d1_min, d1_max, d2_min, d2_max);
869 	for (i = 0; i < en_info->mcc_intvl; i++) {
870 		wifi_dur = en_info->mcc_intvl - bt_dur;
871 		d1 = ((d1 * 100 / (d1 + d2)) * wifi_dur) / 100;
872 		if (d1 < d1_min) {
873 			d1 = d1_min;
874 		} else if (d1 > d1_max) {
875 			d1 = d1_max;
876 		}
877 		d2 = wifi_dur - d1;
878 		if (d2 < d2_min) {
879 			d2 = d2_min;
880 			d1 = wifi_dur - d2;
881 		} else if (d2 > d2_max) {
882 			d2 = d2_max;
883 			d1 = wifi_dur - d2;
884 		}
885 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_adjust_dur_for_2g_mcc_2role_bt(): Loop bt_dur(%d), d1(%d), d2(%d)\n",
886 				bt_dur, d1, d2);
887 		if ((d1 >= d1_min) && (d1 <= d1_max) &&
888 			(d2 >= d2_min) && (d2 <= d2_max)) {
889 			m_role1->policy.dur_info.dur = d1;
890 			m_role2->policy.dur_info.dur = d2;
891 			bt_info->bt_dur = bt_dur;
892 			en_info->m_pattern.d_r_d_a_spacing_max = bt_info->bt_dur;
893 			adjust_ok = true;
894 			break;
895 		}
896 		bt_dur--;
897 	}
898 	if (adjust_ok == false){
899 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_adjust_dur_for_2g_mcc_2role_bt(): Adjust fail\n");
900 	} else {
901 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_adjust_dur_for_2g_mcc_2role_bt(): Adjust ok, d1(%d), d2(%d), bt dur(%d), d_r_d_a_spacing_max(%d)\n",
902 			m_role1->policy.dur_info.dur,
903 			m_role2->policy.dur_info.dur,
904 			bt_info->bt_dur, en_info->m_pattern.d_r_d_a_spacing_max);
905 	}
906 	return adjust_ok;
907 }
908 
_mcc_adjust_dur_for_2_band_mcc_2role_bt(struct phl_mcc_info * minfo,struct rtw_phl_mcc_role * role_2g,struct rtw_phl_mcc_role * role_non_2g)909 void _mcc_adjust_dur_for_2_band_mcc_2role_bt(struct phl_mcc_info *minfo,
910 	struct rtw_phl_mcc_role *role_2g, struct rtw_phl_mcc_role *role_non_2g)
911 {
912 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
913 	enum rtw_phl_mcc_coex_mode *coex_mode = &minfo->coex_mode;
914 	struct rtw_phl_mcc_policy_info *plcy_2g = &role_2g->policy;
915 	struct rtw_phl_mcc_policy_info *plcy_non2g = &role_non_2g->policy;
916 	u16 *bt_dur = &minfo->bt_info.bt_dur;
917 	u16 dur_2g = 0, dur_non2g = 0;
918 
919 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_adjust_dur_for_2_band_mcc_2role_bt(): coex_mode(%d) 2G_Dur(%d), 5G_Dur(%d), BT_Dur(%d)\n",
920 		*coex_mode, plcy_2g->dur_info.dur, plcy_non2g->dur_info.dur,
921 		*bt_dur);
922 	if (plcy_non2g->dur_info.dur >= *bt_dur) {
923 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_adjust_dur_for_2_band_mcc_2role_bt(): 5G_Dur(%d) >= BT_Dur(%d), no need to adjust 5G duration for BT\n",
924 			plcy_non2g->dur_info.dur, *bt_dur);
925 		goto exit;
926 	}
927 	if (plcy_non2g->dur_info.dur_limit.enable &&
928 		plcy_non2g->dur_info.dur_limit.max_dur < *bt_dur) {
929 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_adjust_dur_for_2_band_mcc_2role_bt(): dur_limit.max_dur(%d) < bt_dur(%d), We can't adjust 5G duration(%d) for BT\n",
930 			plcy_non2g->dur_info.dur_limit.max_dur,
931 			*bt_dur, plcy_non2g->dur_info.dur);
932 		goto exit;
933 	}
934 	if (*coex_mode == RTW_PHL_MCC_COEX_MODE_BT_MASTER) {
935 		dur_non2g = *bt_dur;
936 		dur_2g = en_info->mcc_intvl - dur_non2g;
937 		if (plcy_2g->dur_info.dur_limit.enable &&
938 			plcy_2g->dur_info.dur_limit.max_dur < dur_2g) {
939 			dur_2g = plcy_2g->dur_info.dur_limit.max_dur;
940 			dur_non2g = en_info->mcc_intvl - dur_2g;
941 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_adjust_dur_for_2_band_mcc_2role_bt(): plcy_2g->max_dur(%d) < dur_2g(%d), We can adjust some 5G duration for BT\n",
942 				plcy_2g->dur_info.dur_limit.max_dur, dur_2g);
943 		}
944 		plcy_non2g->dur_info.dur = dur_non2g;
945 		plcy_2g->dur_info.dur = dur_2g;
946 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_adjust_dur_for_2_band_mcc_2role_bt(): coex_mode == RTW_PHL_MCC_COEX_MODE_BT_MASTER, we adjust 5G duration for BT\n");
947 	} else if (*coex_mode == RTW_PHL_MCC_COEX_MODE_WIFI_MASTER) {
948 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_adjust_dur_for_2_band_mcc_2role_bt(): coex_mode == RTW_PHL_MCC_COEX_MODE_WIFI_MASTER, we don't adjust 5G duration for BT\n");
949 		goto exit;
950 	} else {
951 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_adjust_dur_for_2_band_mcc_2role_bt(): coex_mode(%d), Undefined mode, ignore bt duration\n",
952 			*coex_mode);
953 		goto exit;
954 	}
955 	PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_adjust_dur_for_2_band_mcc_2role_bt(): After adjust, 2G_Dur(%d), 5G_Dur(%d), BT_Dur(%d)\n",
956 		plcy_2g->dur_info.dur, plcy_non2g->dur_info.dur,
957 		*bt_dur);
958 exit:
959 	return;
960 }
961 
_mcc_need_to_seg_bt_dur(struct phl_mcc_info * minfo)962 bool _mcc_need_to_seg_bt_dur(struct phl_mcc_info *minfo)
963 {
964 /* Not ready for implementation*/
965 	return false;
966 #if 0
967 	bool seg = false;
968 	struct rtw_phl_mcc_en_info *info = &minfo->en_info;
969 	struct rtw_phl_mcc_dur_lim_info *limit_i = NULL;
970 	u8 i = 0;
971 
972 	if (minfo->mcc_mode != RTW_PHL_TDMRA_2CLIENTS_WMODE)
973 		goto exit;
974 	if (minfo->bt_info.bt_dur < BT_DUR_SEG_TH || BT_SEG_NUM < 2)
975 		goto exit;
976 	for (i = 0; i < MCC_ROLE_NUM; i++) {
977 		limit_i = &minfo->en_info.mcc_role[i].policy.dur_info.dur_limit;
978 		if (limit_i->enable) {
979 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_need_to_seg_bt_dur(): Can't seg bt slot when wifi slot with limitation\n");
980 			goto exit;
981 		}
982 	}
983 	seg = true;
984 exit:
985 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_need_to_seg_bt_dur(): seg(%d)\n",
986 		seg);
987 	return seg;
988 #endif
989 }
990 
991 /*
992  * 2 wifi slot req + bt slot req
993  */
_mcc_discision_dur_for_2g_mcc_2role_bt(struct phl_mcc_info * minfo)994 void _mcc_discision_dur_for_2g_mcc_2role_bt(struct phl_mcc_info *minfo)
995 {
996 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
997 	struct rtw_phl_mcc_role *m_role1 = &en_info->mcc_role[0];
998 	struct rtw_phl_mcc_role *m_role2 = &en_info->mcc_role[1];
999 	u16 d1 = 0, d2 = 0;
1000 
1001 	/* Segment bt slot, don't support in current code*/
1002 	if (_mcc_need_to_seg_bt_dur(minfo)) {
1003 		/*2 wifi slot + 2bt slot*/
1004 		d1 = m_role1->policy.dur_info.dur;
1005 		d2 = m_role2->policy.dur_info.dur;
1006 		en_info->mcc_intvl = WORSECASE_INTVL;
1007 		_mcc_adjust_dur_for_2g_mcc_2role_bt(minfo);
1008 		minfo->bt_info.bt_seg_num = 2;
1009 		minfo->bt_info.bt_seg[0] = minfo->bt_info.bt_dur / 2;
1010 		minfo->bt_info.bt_seg[1] = minfo->bt_info.bt_dur -
1011 						minfo->bt_info.bt_seg[0];
1012 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_discision_dur_for_2g_mcc_2role_bt(): Change D1(%d), D2(%d) to D1(%d), D2(%d), bt_seg[0](%d), bt_seg[1](%d)\n",
1013 			d1, d2, m_role1->policy.dur_info.dur,
1014 			m_role2->policy.dur_info.dur,
1015 			minfo->bt_info.bt_seg[0], minfo->bt_info.bt_seg[1]);
1016 	} else {
1017 	/*2 wifi slot + 1bt slot*/
1018 		if (minfo->bt_info.bt_dur > BT_DUR_MAX_2WS) {
1019 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_discision_dur_for_2g_mcc_2role_bt(): bt req slot(%d) > BT_DUR_MAX_2WS(%d)\n",
1020 				minfo->bt_info.bt_dur, BT_DUR_MAX_2WS);
1021 			minfo->bt_info.bt_dur = BT_DUR_MAX_2WS;
1022 			minfo->bt_info.bt_seg[0] = BT_DUR_MAX_2WS;
1023 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_discision_dur_for_2g_mcc_2role_bt(): set bt rq slot to (%d)\n",
1024 				minfo->bt_info.bt_dur);
1025 		}
1026 		_mcc_adjust_dur_for_2g_mcc_2role_bt(minfo);
1027 	}
1028 }
1029 
_mcc_discision_duration_for_2role_bt_v2(struct phl_mcc_info * minfo)1030 bool _mcc_discision_duration_for_2role_bt_v2(struct phl_mcc_info *minfo)
1031 {
1032 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
1033 	struct rtw_phl_mcc_bt_info *bt_info = &minfo->bt_info;
1034 	struct rtw_phl_mcc_role *m_role1 = &en_info->mcc_role[0];
1035 	struct rtw_phl_mcc_role *m_role2 = &en_info->mcc_role[1];
1036 	bool add_extra_bt_role = false;
1037 
1038 	if (bt_info->bt_dur == 0)
1039 		goto exit;
1040 	if (m_role1->chandef->band == BAND_ON_24G &&
1041 		m_role2->chandef->band == BAND_ON_24G) {
1042 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_discision_duration_for_2role_bt_v2(): Not support , We will ignore Bt slot\n");
1043 #if 0
1044 		if (_mcc_adjust_dur_for_2g_mcc_2role_bt(minfo)) {
1045 			add_extra_bt_role = true;
1046 		} else {
1047 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_discision_duration_for_2role_bt(): Adjust dur fail, We will ignore Bt slot\n");
1048 		}
1049 #endif
1050 		goto exit;
1051 	}
1052 	if (m_role1->chandef->band != BAND_ON_24G &&
1053 		m_role2->chandef->band != BAND_ON_24G) {
1054 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_discision_duration_for_2role_bt_v2(): All 5G, Don't care BT duration\n");
1055 		goto exit;
1056 	}
1057 	if (m_role1->chandef->band == BAND_ON_24G)
1058 		_mcc_adjust_dur_for_2_band_mcc_2role_bt(minfo, m_role1, m_role2);
1059 	else
1060 		_mcc_adjust_dur_for_2_band_mcc_2role_bt(minfo, m_role2, m_role1);
1061 exit:
1062 	return add_extra_bt_role;
1063 }
1064 
_mcc_discision_duration_for_2role_bt(struct phl_mcc_info * minfo)1065 bool _mcc_discision_duration_for_2role_bt(struct phl_mcc_info *minfo)
1066 {
1067 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
1068 	struct rtw_phl_mcc_role *m_role1 = &en_info->mcc_role[0];
1069 	struct rtw_phl_mcc_role *m_role2 = &en_info->mcc_role[1];
1070 	bool add_extra_bt_role = false;
1071 
1072 	if (minfo->bt_info.bt_dur == 0)
1073 		goto exit;
1074 	if (m_role1->chandef->band == BAND_ON_24G &&
1075 		m_role2->chandef->band == BAND_ON_24G) {
1076 		_mcc_discision_dur_for_2g_mcc_2role_bt(minfo);
1077 		add_extra_bt_role = true;
1078 		goto exit;
1079 	}
1080 	if (m_role1->chandef->band != BAND_ON_24G &&
1081 		m_role2->chandef->band != BAND_ON_24G) {
1082 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_discision_duration_for_2role_bt(): All 5G, Don't care BT duration\n");
1083 		goto exit;
1084 	}
1085 	if (m_role1->chandef->band == BAND_ON_24G)
1086 		_mcc_adjust_dur_for_2_band_mcc_2role_bt(minfo, m_role1, m_role2);
1087 	else
1088 		_mcc_adjust_dur_for_2_band_mcc_2role_bt(minfo, m_role2, m_role1);
1089 
1090 exit:
1091 	return add_extra_bt_role;
1092 }
1093 
_mcc_calculate_start_tsf(struct phl_info_t * phl,struct rtw_phl_mcc_en_info * en_info)1094 enum rtw_phl_status _mcc_calculate_start_tsf(struct phl_info_t *phl,
1095 					struct rtw_phl_mcc_en_info *en_info
1096 )
1097 {
1098 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
1099 	struct rtw_phl_mcc_role *ref_role = get_ref_role(en_info);
1100 	u32 tsf_h = 0, tsf_l = 0;
1101 	u64 tsf = 0, start_tsf = 0;
1102 	u8 i = 0, max_loop = 10, calc_done = 0;
1103 	u16 offset = 0;
1104 
1105 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_get_tsf(phl->hal,
1106 				ref_role->wrole->hw_port, &tsf_h, &tsf_l)) {
1107 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_start_tsf(): Get tsf fail\n");
1108 		goto exit;
1109 	}
1110 	tsf = tsf_h;
1111 	tsf = tsf << 32;
1112 	tsf |= tsf_l;
1113 	/*calculate the value between current TSF and TBTT*/
1114 	phl_calc_offset_from_tbtt(phl, ref_role->wrole, tsf, &offset);
1115 	start_tsf = tsf - ((offset + en_info->m_pattern.tob_r) * TU);
1116 	for (i = 0; i < max_loop; i++) {
1117 		if (start_tsf < (tsf + (MIN_TRIGGER_MCC_TIME * TU))) {
1118 			start_tsf += (ref_role->bcn_intvl * TU);
1119 		} else {
1120 			calc_done = 1;
1121 			break;
1122 		}
1123 	}
1124 	if (!calc_done) {
1125 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calculate_start_tsf(): Calcculate start tsf fail, please check code flow\n");
1126 		goto exit;
1127 	}
1128 	en_info->tsf_high = start_tsf >> 32;
1129 	en_info->tsf_low = (u32)start_tsf;
1130 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_start_tsf(): start_tsf(0x%08x %08x), cur_tsf(0x%08x %08x), ref_role->bcn_intvl(%d), ref_role->duration(%d)\n",
1131 		(u32)(start_tsf >> 32), (u32)start_tsf, (u32)(tsf >> 32),
1132 		(u32)tsf, ref_role->bcn_intvl, ref_role->policy.dur_info.dur);
1133 	status = RTW_PHL_STATUS_SUCCESS;
1134 exit:
1135 	return status;
1136 }
1137 
_mcc_set_2_clients_worsecase_default_pattern(struct rtw_phl_mcc_pattern * m_pattern,u16 dur_ref)1138 void _mcc_set_2_clients_worsecase_default_pattern(struct rtw_phl_mcc_pattern *m_pattern,
1139 					u16 dur_ref)
1140 {
1141 	m_pattern->toa_r = CLIENTS_WORSECASE_REF_TOA;
1142 	m_pattern->tob_r = dur_ref - m_pattern->toa_r;
1143 	_mcc_fill_slot_info(m_pattern, false,
1144 				m_pattern->role_ref->policy.dur_info.dur,
1145 				m_pattern->role_ref);
1146 	_mcc_fill_slot_info(m_pattern, false,
1147 				m_pattern->role_ano->policy.dur_info.dur,
1148 				m_pattern->role_ano);
1149 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_set_2_clients_worsecase_default_pattern(): tob_r(%d), toa_r(%d)\n",
1150 		m_pattern->tob_r, m_pattern->toa_r);
1151 }
1152 
1153 /*
1154  * get bcn offset for 2 wifi slot and 1 bt slot for pattern1
1155  * Pattern:
1156  * |      Dur_r     |     Dur_a      | Bt slot |
1157  *          bcn                bcn
1158  * | tob_r | toa_r|tob_a | toa_a| Bt slot |
1159  */
_mcc_get_offset_for_2_wslot_1_btslot_p1(s16 dur_r,s16 tob_r,s16 tob_a)1160 s16 _mcc_get_offset_for_2_wslot_1_btslot_p1(s16 dur_r,
1161 				s16 tob_r, s16 tob_a)
1162 {
1163 	return dur_r - tob_r + tob_a;
1164 }
1165 
1166 /*
1167  * get bcn offset for 2 wifi slot and 1 bt slot for pattern2
1168  * Pattern:
1169  * |      Dur_r     | Bt slot |     Dur_a      |
1170  *          bcn                            bcn
1171  * | tob_r | toa_r| Bt slot |tob_a | toa_a|
1172  */
_mcc_get_offset_for_2_wslot_1_btslot_p2(s16 dur_r,s16 bt_dur,s16 tob_r,s16 tob_a)1173 s16 _mcc_get_offset_for_2_wslot_1_btslot_p2(s16 dur_r, s16 bt_dur,
1174 				s16 tob_r, s16 tob_a)
1175 {
1176 	return dur_r - tob_r + bt_dur + tob_a;
1177 }
1178 
_mcc_get_offset_range_for_2wslot_1btslot_p1(s16 ref_dur,s16 ano_dur,s16 * bcn_min,s16 * bcn_max)1179 void _mcc_get_offset_range_for_2wslot_1btslot_p1(s16 ref_dur, s16 ano_dur,
1180 				s16 *bcn_min, s16 *bcn_max)
1181 {
1182 	s16 min1 = 0, max1 = 0;
1183 
1184 	*bcn_min = _mcc_get_offset_for_2_wslot_1_btslot_p1(ref_dur, EARLY_RX_BCN_T,
1185 							EARLY_RX_BCN_T);
1186 	*bcn_max = _mcc_get_offset_for_2_wslot_1_btslot_p1(ref_dur, EARLY_RX_BCN_T,
1187 							ano_dur - MIN_RX_BCN_T);
1188 	min1 = _mcc_get_offset_for_2_wslot_1_btslot_p1(ref_dur,
1189 					ref_dur - MIN_RX_BCN_T, EARLY_RX_BCN_T);
1190 	max1 = _mcc_get_offset_for_2_wslot_1_btslot_p1(ref_dur,
1191 				ref_dur - MIN_RX_BCN_T, ano_dur - MIN_RX_BCN_T);
1192 	if (min1 < *bcn_min)
1193 		*bcn_min = min1;
1194 	if (max1 > *bcn_max)
1195 		*bcn_max = max1;
1196 	PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_get_offset_range_for_2wslot_1btslot_p1(): min(%d), max(%d)\n",
1197 		*bcn_min, *bcn_max);
1198 }
1199 
_mcc_get_offset_range_for_2wslot_1btslot_p2(s16 ref_dur,s16 ano_dur,s16 bt_dur,s16 * bcn_min,s16 * bcn_max)1200 void _mcc_get_offset_range_for_2wslot_1btslot_p2(s16 ref_dur, s16 ano_dur,
1201 				s16 bt_dur, s16 *bcn_min, s16 *bcn_max)
1202 {
1203 	s16 min1 = 0, max1 = 0;
1204 
1205 	*bcn_min = _mcc_get_offset_for_2_wslot_1_btslot_p2(ref_dur, bt_dur,
1206 						EARLY_RX_BCN_T, EARLY_RX_BCN_T);
1207 	*bcn_max = _mcc_get_offset_for_2_wslot_1_btslot_p2(ref_dur, bt_dur,
1208 					EARLY_RX_BCN_T, ano_dur - MIN_RX_BCN_T);
1209 	min1 = _mcc_get_offset_for_2_wslot_1_btslot_p2(ref_dur, bt_dur,
1210 					ref_dur - MIN_RX_BCN_T, EARLY_RX_BCN_T);
1211 
1212 	min1 = _mcc_get_offset_for_2_wslot_1_btslot_p2(ref_dur, bt_dur,
1213 				ref_dur - MIN_RX_BCN_T, ano_dur - MIN_RX_BCN_T);
1214 	if (min1 < *bcn_min)
1215 		*bcn_min = min1;
1216 	if (max1 > *bcn_max)
1217 		*bcn_max = max1;
1218 	PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_get_offset_range_for_2wslot_1btslot_p2(): min(%d), max(%d)\n",
1219 		*bcn_min, *bcn_max);
1220 }
1221 
_mcc_get_offset_for_2_clients_worsecase(s16 ref_dur,s16 ano_dur,u16 ref_bcn_intvl,s16 toa_ref,s16 tob_ano)1222 s16 _mcc_get_offset_for_2_clients_worsecase(s16 ref_dur, s16 ano_dur,
1223 				u16 ref_bcn_intvl, s16 toa_ref, s16 tob_ano)
1224 {
1225 	return toa_ref + tob_ano + ref_dur + ano_dur - (2 * ref_bcn_intvl);
1226 }
1227 
_mcc_get_offset_range_for_2_clients_worsecase(s16 ref_dur,s16 ano_dur,u16 ref_bcn_intvl,s16 * bcn_min,s16 * bcn_max)1228 void _mcc_get_offset_range_for_2_clients_worsecase(s16 ref_dur, s16 ano_dur,
1229 				u16 ref_bcn_intvl, s16 *bcn_min, s16 *bcn_max)
1230 {
1231 	s16 min1 = 0, min2 = 0, max1 = 0, max2 = 0;
1232 	min1 = _mcc_get_offset_for_2_clients_worsecase(ref_dur, ano_dur,
1233 				ref_bcn_intvl, MIN_RX_BCN_T, EARLY_RX_BCN_T);
1234 	max1 = _mcc_get_offset_for_2_clients_worsecase(ref_dur, ano_dur,
1235 				ref_bcn_intvl, MIN_RX_BCN_T, ano_dur -
1236 				MIN_RX_BCN_T);
1237 	min2 = _mcc_get_offset_for_2_clients_worsecase(ref_dur, ano_dur,
1238 				ref_bcn_intvl, ref_dur - EARLY_RX_BCN_T,
1239 				EARLY_RX_BCN_T);
1240 	max2 = _mcc_get_offset_for_2_clients_worsecase(ref_dur, ano_dur,
1241 				ref_bcn_intvl, ref_dur -EARLY_RX_BCN_T,
1242 				ano_dur - MIN_RX_BCN_T);
1243 	if (min1 < min2)
1244 		*bcn_min = min1;
1245 	else
1246 		*bcn_min = min2;
1247 	if (max1 > max2)
1248 		*bcn_max = max1;
1249 	else
1250 		*bcn_max = max2;
1251 }
1252 
1253 /*
1254  * copy from _mcc_calc_2wslot_1btslot_nego_p1
1255  * | Wifi slot1 | Bt slot | Wifi slot2 |
1256  */
_mcc_calc_2wslot_1btslot_nego_p2(struct rtw_phl_mcc_dur_info * ref_dur,struct rtw_phl_mcc_dur_info * ano_dur,s16 bt_dur,s16 offset,struct rtw_phl_mcc_pattern * m_pattern)1257 bool _mcc_calc_2wslot_1btslot_nego_p2(struct rtw_phl_mcc_dur_info *ref_dur,
1258 			struct rtw_phl_mcc_dur_info *ano_dur, s16 bt_dur,
1259 			s16 offset, struct rtw_phl_mcc_pattern *m_pattern)
1260 {
1261 	bool cal_ok = false;
1262 	s16 tob_r = 0, toa_r = 0, tob_a = 0, toa_a = 0;
1263 
1264 	if ((ref_dur->dur_limit.enable) && (ano_dur->dur_limit.enable)) {
1265 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2wslot_1btslot_nego_p2(): not support, both enable slot limitation\n");
1266 		/*todo*/
1267 		goto exit;
1268 	}
1269 	if (ref_dur->dur_limit.enable) {
1270 		tob_r = ref_dur->dur / 2;
1271 		toa_r = ref_dur->dur - tob_r;
1272 		if (tob_r > ref_dur->dur_limit.max_tob) {
1273 			tob_r = ref_dur->dur_limit.max_tob;
1274 			toa_r = ref_dur->dur - tob_r;
1275 		}
1276 		if (toa_r > ref_dur->dur_limit.max_toa) {
1277 			toa_r = ref_dur->dur_limit.max_toa;
1278 			tob_r = ref_dur->dur - toa_r;
1279 		}
1280 		if ((tob_r > ref_dur->dur_limit.max_tob) ||
1281 			(toa_r > ref_dur->dur_limit.max_toa)) {
1282 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2wslot_1btslot_nego_p2(): After adjust tob_r(%d) > max_tob(%d) or toa_r(%d) > max_toa(%d)\n",
1283 				tob_r, ref_dur->dur_limit.max_tob,
1284 				toa_r, ref_dur->dur_limit.max_toa);
1285 			goto exit;
1286 		}
1287 		tob_a = offset - toa_r - bt_dur;
1288 		toa_a = ano_dur->dur - tob_a;
1289 		if (tob_a <= 0 || toa_a <= 0) {
1290 			m_pattern->courtesy_i.c_en= true;
1291 			m_pattern->courtesy_i.c_num = 3;
1292 			m_pattern->courtesy_i.src_role = m_pattern->role_ref;
1293 			m_pattern->courtesy_i.tgt_role = m_pattern->role_ano;
1294 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calc_2wslot_1btslot_nego_p2(): Limi by ref dur, courtesy_info: c_en(%d), c_num(%d), src_role->macid(0x%x), tgt_role->macid(0x%x)\n",
1295 				m_pattern->courtesy_i.c_en,
1296 				m_pattern->courtesy_i.c_num,
1297 				m_pattern->courtesy_i.src_role->macid,
1298 				m_pattern->courtesy_i.tgt_role->macid);
1299 		}
1300 		goto fill_pattern;
1301 	} else if (ano_dur->dur_limit.enable) {
1302 		tob_a = ano_dur->dur / 2;
1303 		toa_a = ano_dur->dur - tob_a;
1304 		if (tob_a > ano_dur->dur_limit.max_tob) {
1305 			tob_a = ano_dur->dur_limit.max_tob;
1306 			toa_a = ano_dur->dur - tob_a;
1307 		}
1308 		if (toa_a > ano_dur->dur_limit.max_toa) {
1309 			toa_a = ano_dur->dur_limit.max_toa;
1310 			tob_a = ano_dur->dur - toa_a;
1311 		}
1312 		if ((tob_a > ano_dur->dur_limit.max_tob) ||
1313 			(toa_a > ano_dur->dur_limit.max_toa)) {
1314 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2wslot_1btslot_nego_p2(): After adjust tob_r(%d) > max_tob(%d) or toa_r(%d) > max_toa(%d)\n",
1315 				tob_a, ano_dur->dur_limit.max_tob,
1316 				toa_a, ano_dur->dur_limit.max_toa);
1317 			goto exit;
1318 		}
1319 		toa_r = offset - tob_a - bt_dur;
1320 		tob_r = ref_dur->dur - toa_r;
1321 		if (toa_r <= 0 || tob_r <= 0) {
1322 			m_pattern->courtesy_i.c_en= true;
1323 			m_pattern->courtesy_i.c_num = 3;
1324 			m_pattern->courtesy_i.src_role = m_pattern->role_ano;
1325 			m_pattern->courtesy_i.tgt_role = m_pattern->role_ref;
1326 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calc_2wslot_1btslot_nego_p2(): Limi by ano dur, courtesy_info: c_en(%d), c_num(%d), src_role->macid(0x%x), tgt_role->macid(0x%x)\n",
1327 				m_pattern->courtesy_i.c_en,
1328 				m_pattern->courtesy_i.c_num,
1329 				m_pattern->courtesy_i.src_role->macid,
1330 				m_pattern->courtesy_i.tgt_role->macid);
1331 		}
1332 		goto fill_pattern;
1333 	} else {
1334 		tob_r = ref_dur->dur / 2;
1335 		toa_r = ref_dur->dur - tob_r;
1336 		tob_a = offset - toa_r - bt_dur;
1337 		toa_a = ano_dur->dur - tob_a;
1338 		if (tob_a <= 0 || toa_a <= 0) {
1339 			m_pattern->courtesy_i.c_en= true;
1340 			m_pattern->courtesy_i.c_num = 3;
1341 			m_pattern->courtesy_i.src_role = m_pattern->role_ref;
1342 			m_pattern->courtesy_i.tgt_role = m_pattern->role_ano;
1343 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calc_2wslot_1btslot_nego_p2(): Limi by ref dur, courtesy_info: c_en(%d), c_num(%d), src_role->macid(0x%x), tgt_role->macid(0x%x)\n",
1344 				m_pattern->courtesy_i.c_en,
1345 				m_pattern->courtesy_i.c_num,
1346 				m_pattern->courtesy_i.src_role->macid,
1347 				m_pattern->courtesy_i.tgt_role->macid);
1348 		}
1349 		goto fill_pattern;
1350 	}
1351 fill_pattern:
1352 	cal_ok = true;
1353 	m_pattern->tob_r = tob_r;
1354 	m_pattern->toa_r = toa_r;
1355 	m_pattern->tob_a = tob_a;
1356 	m_pattern->toa_a = toa_a;
1357 	_mcc_fill_slot_info(m_pattern, false, ref_dur->dur, m_pattern->role_ref);
1358 	_mcc_fill_slot_info(m_pattern, true, bt_dur, NULL);
1359 	_mcc_fill_slot_info(m_pattern, false, ano_dur->dur, m_pattern->role_ano);
1360 exit:
1361 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2wslot_1btslot_nego_p2(): calc nego patter ok(%d)\n",
1362 		cal_ok);
1363 	return cal_ok;
1364 }
1365 
1366 /*
1367  * copy from _mcc_calc_2_wrole_nego_pattern
1368  * |   Wifi slot1   |   Wifi slot2   | Bt slot |
1369  * |      Dur_r     |     Dur_a      | Bt slot |
1370  *          bcn                bcn
1371  * | tob_r | toa_r|tob_a | toa_a| Bt slot |
1372  */
_mcc_calc_2wslot_1btslot_nego_p1(struct rtw_phl_mcc_dur_info * ref_dur,struct rtw_phl_mcc_dur_info * ano_dur,s16 offset,s16 bt_dur,struct rtw_phl_mcc_pattern * m_pattern)1373 bool _mcc_calc_2wslot_1btslot_nego_p1(struct rtw_phl_mcc_dur_info *ref_dur,
1374 			struct rtw_phl_mcc_dur_info *ano_dur, s16 offset,
1375 			s16 bt_dur, struct rtw_phl_mcc_pattern *m_pattern)
1376 {
1377 	bool cal_ok = false;
1378 	s16 tob_r = 0, toa_r = 0, tob_a = 0, toa_a = 0;
1379 
1380 	if ((ref_dur->dur_limit.enable) && (ano_dur->dur_limit.enable)) {
1381 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2wslot_1btslot_nego_p1(): not support, both enable slot limitation\n");
1382 		/*todo*/
1383 		goto exit;
1384 	}
1385 	if (ref_dur->dur_limit.enable) {
1386 		tob_r = ref_dur->dur / 2;
1387 		toa_r = ref_dur->dur - tob_r;
1388 		if (tob_r > ref_dur->dur_limit.max_tob) {
1389 			tob_r = ref_dur->dur_limit.max_tob;
1390 			toa_r = ref_dur->dur - tob_r;
1391 		}
1392 		if (toa_r > ref_dur->dur_limit.max_toa) {
1393 			toa_r = ref_dur->dur_limit.max_toa;
1394 			tob_r = ref_dur->dur - toa_r;
1395 		}
1396 		if ((tob_r > ref_dur->dur_limit.max_tob) ||
1397 			(toa_r > ref_dur->dur_limit.max_toa)) {
1398 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2wslot_1btslot_nego_p1(): After adjust tob_r(%d) > max_tob(%d) or toa_r(%d) > max_toa(%d)\n",
1399 				tob_r, ref_dur->dur_limit.max_tob,
1400 				toa_r, ref_dur->dur_limit.max_toa);
1401 			goto exit;
1402 		}
1403 		tob_a = offset - toa_r;
1404 		toa_a = ano_dur->dur - tob_a;
1405 		if (tob_a <= 0 || toa_a <= 0) {
1406 			m_pattern->courtesy_i.c_en= true;
1407 			m_pattern->courtesy_i.c_num = 3;
1408 			m_pattern->courtesy_i.src_role = m_pattern->role_ref;
1409 			m_pattern->courtesy_i.tgt_role = m_pattern->role_ano;
1410 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calc_2wslot_1btslot_nego_p1(): Limi by ref dur, courtesy_info: c_en(%d), c_num(%d), src_role->macid(0x%x), tgt_role->macid(0x%x)\n",
1411 				m_pattern->courtesy_i.c_en,
1412 				m_pattern->courtesy_i.c_num,
1413 				m_pattern->courtesy_i.src_role->macid,
1414 				m_pattern->courtesy_i.tgt_role->macid);
1415 		}
1416 		goto fill_pattern;
1417 	} else if (ano_dur->dur_limit.enable) {
1418 		tob_a = ano_dur->dur / 2;
1419 		toa_a = ano_dur->dur - tob_a;
1420 		if (tob_a > ano_dur->dur_limit.max_tob) {
1421 			tob_a = ano_dur->dur_limit.max_tob;
1422 			toa_a = ano_dur->dur - tob_a;
1423 		}
1424 		if (toa_a > ano_dur->dur_limit.max_toa) {
1425 			toa_a = ano_dur->dur_limit.max_toa;
1426 			tob_a = ano_dur->dur - toa_a;
1427 		}
1428 		if ((tob_a > ano_dur->dur_limit.max_tob) ||
1429 			(toa_a > ano_dur->dur_limit.max_toa)) {
1430 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2wslot_1btslot_nego_p1(): After adjust tob_r(%d) > max_tob(%d) or toa_r(%d) > max_toa(%d)\n",
1431 				tob_a, ano_dur->dur_limit.max_tob,
1432 				toa_a, ano_dur->dur_limit.max_toa);
1433 			goto exit;
1434 		}
1435 		toa_r = offset - tob_a;
1436 		tob_r = ref_dur->dur - toa_r;
1437 		if (toa_r <= 0 || tob_r <= 0) {
1438 			m_pattern->courtesy_i.c_en= true;
1439 			m_pattern->courtesy_i.c_num = 3;
1440 			m_pattern->courtesy_i.src_role = m_pattern->role_ano;
1441 			m_pattern->courtesy_i.tgt_role = m_pattern->role_ref;
1442 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calc_2wslot_1btslot_nego_p1(): Limi by ano dur, courtesy_info: c_en(%d), c_num(%d), src_role->macid(0x%x), tgt_role->macid(0x%x)\n",
1443 				m_pattern->courtesy_i.c_en,
1444 				m_pattern->courtesy_i.c_num,
1445 				m_pattern->courtesy_i.src_role->macid,
1446 				m_pattern->courtesy_i.tgt_role->macid);
1447 		}
1448 		goto fill_pattern;
1449 	} else {
1450 		tob_r = ref_dur->dur / 2;
1451 		toa_r = ref_dur->dur - tob_r;
1452 		tob_a = offset - toa_r;
1453 		toa_a = ano_dur->dur - tob_a;
1454 		if (tob_a <= 0 || toa_a <= 0) {
1455 			m_pattern->courtesy_i.c_en= true;
1456 			m_pattern->courtesy_i.c_num = 3;
1457 			m_pattern->courtesy_i.src_role = m_pattern->role_ref;
1458 			m_pattern->courtesy_i.tgt_role = m_pattern->role_ano;
1459 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calc_2wslot_1btslot_nego_p1(): courtesy_info: c_en(%d), c_num(%d), src_role->macid(0x%x), tgt_role->macid(0x%x)\n",
1460 				m_pattern->courtesy_i.c_en,
1461 				m_pattern->courtesy_i.c_num,
1462 				m_pattern->courtesy_i.src_role->macid,
1463 				m_pattern->courtesy_i.tgt_role->macid);
1464 		}
1465 		goto fill_pattern;
1466 	}
1467 fill_pattern:
1468 	cal_ok = true;
1469 	m_pattern->tob_r = tob_r;
1470 	m_pattern->toa_r = toa_r;
1471 	m_pattern->tob_a = tob_a;
1472 	m_pattern->toa_a = toa_a;
1473 	_mcc_fill_slot_info(m_pattern, false, ref_dur->dur, m_pattern->role_ref);
1474 	_mcc_fill_slot_info(m_pattern, false, ano_dur->dur, m_pattern->role_ano);
1475 	_mcc_fill_slot_info(m_pattern, true, bt_dur, NULL);
1476 exit:
1477 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2wslot_1btslot_nego_p1(): calc nego patter ok(%d)\n",
1478 		cal_ok);
1479 	return cal_ok;
1480 }
1481 
1482 /*
1483  * copy from _mcc_calculate_2_clients_pattern
1484  * Calculate pattern2 for 2 wifi slot and 1 bt slot
1485  * Pattern:
1486  * |   Wifi slot1   | Bt slot |   Wifi slot2   |
1487  * |      Dur_r     | Bt slot |     Dur_a      |
1488  *          bcn                            bcn
1489  * | tob_r | toa_r| Bt slot |tob_a | toa_a|
1490  * @offset: The offset of Bcns
1491  * @m_pattern: pattern info
1492  */
_mcc_calculate_2wslot_1btslot_pattern2(struct rtw_phl_mcc_dur_info * ref_dur,struct rtw_phl_mcc_dur_info * ano_dur,u16 offset,s16 bt_dur,struct rtw_phl_mcc_pattern * m_pattern)1493 enum rtw_phl_status _mcc_calculate_2wslot_1btslot_pattern2(
1494 				struct rtw_phl_mcc_dur_info *ref_dur,
1495 				struct rtw_phl_mcc_dur_info *ano_dur,
1496 				u16 offset, s16 bt_dur,
1497 				struct rtw_phl_mcc_pattern *m_pattern)
1498 {
1499 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
1500 	u16 mcc_intvl = ref_dur->dur + ano_dur->dur;
1501 	s16 tob_r = 0, toa_r = 0, tob_a = 0, toa_a = 0, tob_r_cand = 0;
1502 	s16 d_r = ref_dur->dur, d_a = ano_dur->dur, bcns_offset = offset;
1503 	s16 sum = 0, sum_last = 0;
1504 	s16 tob_r_l = ref_dur->dur_limit.max_tob;
1505 	s16 toa_r_l = ref_dur->dur_limit.max_toa;
1506 	s16 tob_a_l = ano_dur->dur_limit.max_tob;
1507 	s16 toa_a_l = ano_dur->dur_limit.max_toa;
1508 
1509 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern2(): ref_dur(%d), ano_dur(%d), bt_dur(%d), bcns offset(%d)\n",
1510 		d_r, d_a, bt_dur, bcns_offset);
1511 	for (tob_r = EARLY_RX_BCN_T; tob_r < mcc_intvl; tob_r++) {
1512 		toa_r = d_r - tob_r;
1513 		if (toa_r < MIN_RX_BCN_T) {
1514 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern2(): break loop, by toa_r(%d) < MIN_RX_BCN_T(%d)\n",
1515 				toa_r, MIN_RX_BCN_T);
1516 			break;
1517 		}
1518 		if (ref_dur->dur_limit.enable) {
1519 			if (tob_r > tob_r_l) {
1520 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern2(): tob_r(%d) > tob_r_l(%d), Break loop\n",
1521 					tob_r, tob_r_l);
1522 				break;
1523 			} else if (toa_r > toa_r_l) {
1524 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern2(): toa_r(%d) > toa_r_l(%d), continue next loop\n",
1525 					toa_r, toa_r_l);
1526 				continue;
1527 			}
1528 		}
1529 		tob_a = bcns_offset - toa_r - bt_dur;
1530 		if (tob_a < EARLY_RX_BCN_T)
1531 			continue;
1532 		toa_a = d_a - tob_a;
1533 		if (toa_a < MIN_RX_BCN_T){
1534 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern2(): break loop, by toa_a(%d) < MIN_RX_BCN_T(%d)\n",
1535 				toa_a, MIN_RX_BCN_T);
1536 			break;
1537 		}
1538 		if (ano_dur->dur_limit.enable) {
1539 			if (tob_a > tob_a_l || toa_a > toa_a_l) {
1540 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern2(): tob_a(%d) > tob_a_l(%d) || toa_a(%d) > toa_a_l(%d), continue next loop\n",
1541 					tob_a, tob_a_l, toa_a, toa_a_l);
1542 				continue;
1543 			}
1544 		}
1545 		sum = ((tob_r - toa_r) * (tob_r - toa_r)) +
1546 			((tob_r - tob_a) * (tob_r - tob_a)) +
1547 			((tob_r - toa_a) * (tob_r - toa_a)) +
1548 			((toa_r - tob_a) * (toa_r - tob_a)) +
1549 			((toa_r - toa_a) * (toa_r - toa_a)) +
1550 			((tob_a - toa_a) * (tob_a - toa_a));
1551 		tob_r_cand = tob_r;
1552 		if (sum_last !=0 && sum > sum_last) {
1553 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern2(): Find the optimal pattern, by get minSum\n");
1554 			break;
1555 		}
1556 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern2(): tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d), sum_last(%d), sum(%d)\n",
1557 			tob_r, toa_r, tob_a, toa_a, sum_last, sum);
1558 		sum_last = sum;
1559 	}
1560 	if (0 == tob_r_cand) {
1561 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2wslot_1btslot_pattern2(): Can't found suitable pattern, goto calc_nego_pattern\n");
1562 		goto exit;
1563 	}
1564 	tob_r = tob_r_cand;
1565 	toa_r = d_r - tob_r;
1566 	tob_a = bcns_offset - toa_r;
1567 	toa_a = d_a - tob_a;
1568 	m_pattern->tob_r = tob_r;
1569 	m_pattern->toa_r = toa_r;
1570 	m_pattern->tob_a = tob_a;
1571 	m_pattern->toa_a = toa_a;
1572 	/*Update slot order*/
1573 	_mcc_fill_slot_info(m_pattern, false, ref_dur->dur, m_pattern->role_ref);
1574 	_mcc_fill_slot_info(m_pattern, true, bt_dur, NULL);
1575 	_mcc_fill_slot_info(m_pattern, false, ano_dur->dur, m_pattern->role_ano);
1576 	status = RTW_PHL_STATUS_SUCCESS;
1577 exit:
1578 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern2(): status(%d), tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d)\n",
1579 		status, m_pattern->tob_r, m_pattern->toa_r, m_pattern->tob_a,
1580 		m_pattern->toa_a);
1581 	return status;
1582 }
1583 
1584 /*
1585  * copy from _mcc_calculate_2_clients_pattern
1586  * Calculate pattern1 for 2 wifi slot and 1 bt slot
1587  * Pattern:
1588  * |   Wifi slot1   |   Wifi slot2   | Bt slot |
1589  * |      Dur_r     |     Dur_a      | Bt slot |
1590  *          bcn                bcn
1591  * | tob_r | toa_r|tob_a | toa_a| Bt slot |
1592  * @offset: The offset of Bcns
1593  * @m_pattern: pattern info
1594  */
_mcc_calculate_2wslot_1btslot_pattern1(struct rtw_phl_mcc_dur_info * ref_dur,struct rtw_phl_mcc_dur_info * ano_dur,u16 offset,s16 bt_dur,struct rtw_phl_mcc_pattern * m_pattern)1595 enum rtw_phl_status _mcc_calculate_2wslot_1btslot_pattern1(
1596 			struct rtw_phl_mcc_dur_info *ref_dur,
1597 			struct rtw_phl_mcc_dur_info *ano_dur,
1598 			u16 offset, s16 bt_dur,
1599 			struct rtw_phl_mcc_pattern *m_pattern)
1600 {
1601 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
1602 	u16 mcc_intvl = ref_dur->dur + ano_dur->dur;
1603 	s16 tob_r = 0, toa_r = 0, tob_a = 0, toa_a = 0, tob_r_cand = 0;
1604 	s16 d_r = ref_dur->dur, d_a = ano_dur->dur, bcns_offset = offset;
1605 	s16 sum = 0, sum_last = 0;
1606 	s16 tob_r_l = ref_dur->dur_limit.max_tob;
1607 	s16 toa_r_l = ref_dur->dur_limit.max_toa;
1608 	s16 tob_a_l = ano_dur->dur_limit.max_tob;
1609 	s16 toa_a_l = ano_dur->dur_limit.max_toa;
1610 
1611 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern1(): ref_dur(%d), ano_dur(%d), bcns offset(%d)\n",
1612 		d_r, d_a, bcns_offset);
1613 	for (tob_r = EARLY_RX_BCN_T; tob_r < mcc_intvl; tob_r++) {
1614 		toa_r = d_r - tob_r;
1615 		if (toa_r < MIN_RX_BCN_T) {
1616 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern1(): break loop, by toa_r(%d) < MIN_RX_BCN_T(%d)\n",
1617 				toa_r, MIN_RX_BCN_T);
1618 			break;
1619 		}
1620 		if (ref_dur->dur_limit.enable) {
1621 			if (tob_r > tob_r_l) {
1622 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern1(): tob_r(%d) > tob_r_l(%d), Break loop\n",
1623 					tob_r, tob_r_l);
1624 				break;
1625 			} else if (toa_r > toa_r_l) {
1626 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern1(): toa_r(%d) > toa_r_l(%d), continue next loop\n",
1627 					toa_r, toa_r_l);
1628 				continue;
1629 			}
1630 		}
1631 		tob_a = bcns_offset - toa_r;
1632 		if (tob_a < EARLY_RX_BCN_T)
1633 			continue;
1634 		toa_a = d_a - tob_a;
1635 		if (toa_a < MIN_RX_BCN_T){
1636 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern1(): break loop, by toa_a(%d) < MIN_RX_BCN_T(%d)\n",
1637 				toa_a, MIN_RX_BCN_T);
1638 			break;
1639 		}
1640 		if (ano_dur->dur_limit.enable) {
1641 			if (tob_a > tob_a_l || toa_a > toa_a_l) {
1642 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern1(): tob_a(%d) > tob_a_l(%d) || toa_a(%d) > toa_a_l(%d), continue next loop\n",
1643 					tob_a, tob_a_l, toa_a, toa_a_l);
1644 				continue;
1645 			}
1646 		}
1647 		sum = ((tob_r - toa_r) * (tob_r - toa_r)) +
1648 			((tob_r - tob_a) * (tob_r - tob_a)) +
1649 			((tob_r - toa_a) * (tob_r - toa_a)) +
1650 			((toa_r - tob_a) * (toa_r - tob_a)) +
1651 			((toa_r - toa_a) * (toa_r - toa_a)) +
1652 			((tob_a - toa_a) * (tob_a - toa_a));
1653 		tob_r_cand = tob_r;
1654 		if (sum_last !=0 && sum > sum_last) {
1655 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern1(): Find the optimal pattern, by get minSum\n");
1656 			break;
1657 		}
1658 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern1(): tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d), sum_last(%d), sum(%d)\n",
1659 			tob_r, toa_r, tob_a, toa_a, sum_last, sum);
1660 		sum_last = sum;
1661 	}
1662 	if (0 == tob_r_cand) {
1663 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2wslot_1btslot_pattern1(): Can't found suitable pattern, goto calc_nego_pattern\n");
1664 		goto exit;
1665 	}
1666 	tob_r = tob_r_cand;
1667 	toa_r = d_r - tob_r;
1668 	tob_a = bcns_offset - toa_r;
1669 	toa_a = d_a - tob_a;
1670 	m_pattern->tob_r = tob_r;
1671 	m_pattern->toa_r = toa_r;
1672 	m_pattern->tob_a = tob_a;
1673 	m_pattern->toa_a = toa_a;
1674 	_mcc_fill_slot_info(m_pattern, false, ref_dur->dur, m_pattern->role_ref);
1675 	_mcc_fill_slot_info(m_pattern, false, ano_dur->dur, m_pattern->role_ano);
1676 	_mcc_fill_slot_info(m_pattern, true, bt_dur, NULL);
1677 	status = RTW_PHL_STATUS_SUCCESS;
1678 exit:
1679 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2wslot_1btslot_pattern1(): status(%d), tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d)\n",
1680 		status, m_pattern->tob_r, m_pattern->toa_r, m_pattern->tob_a,
1681 		m_pattern->toa_a);
1682 	return status;
1683 }
1684 
1685 /*
1686  * Calculate pattern for 2 wifi slot and 1 bt slot
1687  */
_mcc_calculate_2wslot_1btslot_pattern(struct rtw_phl_mcc_dur_info * ref_dur,struct rtw_phl_mcc_dur_info * ano_dur,s16 bt_dur,struct rtw_phl_mcc_pattern * m_pattern)1688 enum rtw_phl_status _mcc_calculate_2wslot_1btslot_pattern(
1689 			struct rtw_phl_mcc_dur_info *ref_dur,
1690 			struct rtw_phl_mcc_dur_info *ano_dur,
1691 			s16 bt_dur, struct rtw_phl_mcc_pattern *m_pattern)
1692 {
1693 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
1694 	s16 offset_min = 0, offset_max = 0;
1695 	u16 offset = m_pattern->bcns_offset;
1696 
1697 	_mcc_get_offset_range_for_2wslot_1btslot_p1(ref_dur->dur, ano_dur->dur,
1698 						&offset_min, &offset_max);
1699 	if (offset >= offset_min && offset <= offset_max) {
1700 		if (RTW_PHL_STATUS_SUCCESS !=
1701 			_mcc_calculate_2wslot_1btslot_pattern1(ref_dur, ano_dur,
1702 						offset, bt_dur, m_pattern)) {
1703 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2wslot_1btslot_pattern(): Pattern1, Can't found suitable pattern, goto calc_nego_pattern\n");
1704 			goto calc_nego_pattern;
1705 		} else {
1706 			status = RTW_PHL_STATUS_SUCCESS;
1707 			goto exit;
1708 		}
1709 	}
1710 	_mcc_get_offset_range_for_2wslot_1btslot_p2(ref_dur->dur, ano_dur->dur,
1711 					bt_dur, &offset_min, &offset_max);
1712 	if (offset >= offset_min && offset <= offset_max) {
1713 		if (RTW_PHL_STATUS_SUCCESS !=
1714 			_mcc_calculate_2wslot_1btslot_pattern2(ref_dur, ano_dur,
1715 						offset, bt_dur, m_pattern)) {
1716 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2wslot_1btslot_pattern(): Pattern2, Can't found suitable pattern, goto calc_nego_pattern\n");
1717 			goto calc_nego_pattern;
1718 		} else {
1719 			status = RTW_PHL_STATUS_SUCCESS;
1720 			goto exit;
1721 		}
1722 	} else {
1723 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2wslot_1btslot_pattern(): worsecase, goto calc_nego_pattern\n");
1724 		goto calc_nego_pattern;
1725 	}
1726 calc_nego_pattern:
1727 	if (_mcc_calc_2wslot_1btslot_nego_p1(ref_dur,
1728 					ano_dur, offset, bt_dur, m_pattern)) {
1729 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2wslot_1btslot_pattern(): calc_nego_pattern1 ok\n");
1730 	} else if (_mcc_calc_2wslot_1btslot_nego_p2(ref_dur,
1731 					ano_dur, offset, bt_dur, m_pattern)) {
1732 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2wslot_1btslot_pattern(): calc_nego_pattern2 ok\n");
1733 	} else {
1734 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calculate_2wslot_1btslot_pattern(): calc_nego_pattern fail\n");
1735 		goto exit;
1736 	}
1737 	status = RTW_PHL_STATUS_SUCCESS;
1738 exit:
1739 	return status;
1740 }
1741 
1742 /*
1743  * |Wifi1 slot| Wifi2 slot|
1744  * <              150TU               ><              150TU               >
1745  * |      Dur_r     |     Dur_a      |      Dur_r     |     Dur_a      |
1746  *          bcn_r                                                     bcn_a
1747  * | tob_r | toa_r|                                        |tob_a | toa_a|
1748  */
_mcc_calc_2_clients_worsecase_pattern(u16 ref_dur,u16 ano_dur,u16 offset,u16 ref_bcn_intvl,struct rtw_phl_mcc_pattern * m_pattern)1749 enum rtw_phl_status _mcc_calc_2_clients_worsecase_pattern(u16 ref_dur,
1750 				u16 ano_dur, u16 offset, u16 ref_bcn_intvl,
1751 				struct rtw_phl_mcc_pattern *m_pattern)
1752 {
1753 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
1754 	u16 mcc_intvl = ref_dur + ano_dur;
1755 	s16 tob_r = 0, toa_r = 0, tob_a = 0, toa_a = 0;
1756 	s16 d_r = ref_dur, d_a = ano_dur, bcns_offset = offset;
1757 	s16 sum = 0, sum_last = 0, offset_min = 0, offset_max = 0;
1758 
1759 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_worsecase_pattern(): ref_dur(%d), ano_dur(%d), bcns offset(%d), ref_bcn_intvl(%d)\n",
1760 		ref_dur, ano_dur, offset, ref_bcn_intvl);
1761 	if (ref_bcn_intvl != HANDLE_BCN_INTVL) {
1762 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2_clients_worsecase_pattern(): ref_bcn_intvl(%d) != HANDLE_BCN_INTVL(%d), now, we can't calculate the pattern\n",
1763 			ref_bcn_intvl, HANDLE_BCN_INTVL);
1764 		goto exit;
1765 	}
1766 	_mcc_get_offset_range_for_2_clients_worsecase(d_r, d_a, ref_bcn_intvl,
1767 						&offset_min, &offset_max);
1768 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_worsecase_pattern(): we can calculate the range of bcn offset is %d~%d\n",
1769 			offset_min, offset_max);
1770 	if ((bcns_offset >= offset_min) && (bcns_offset <= offset_max))
1771 		goto calc;
1772 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_worsecase_pattern(): transform bcn offset from %d to %d\n",
1773 			bcns_offset, ref_bcn_intvl - bcns_offset);
1774 	/*bcn offfset = 85, we can transform to -15*/
1775 	bcns_offset = ref_bcn_intvl - bcns_offset;
1776 	if (bcns_offset >= offset_min && offset_min <=offset_max) {
1777 		goto calc;
1778 	} else {
1779 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calculate_2_clients_worsecase_pattern(): bcn offset out of range, we can't calculate it\n");
1780 		goto exit;
1781 	}
1782 calc:
1783 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_worsecase_pattern(): Start calculate\n");
1784 	for (tob_r = EARLY_RX_BCN_T; tob_r < mcc_intvl; tob_r++) {
1785 		toa_r = d_r - tob_r;
1786 		if (toa_r < MIN_RX_BCN_T) {
1787 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_worsecase_pattern(): Find the optimal pattern, by toa_r(%d) < MIN_RX_BCN_T(%d)\n",
1788 				toa_r, MIN_RX_BCN_T);
1789 			break;
1790 		}
1791 		tob_a = bcns_offset + 2 * ref_bcn_intvl - toa_r - mcc_intvl;
1792 		if (tob_a < EARLY_RX_BCN_T)
1793 			continue;
1794 		toa_a = d_a - tob_a;
1795 		if (toa_a < MIN_RX_BCN_T){
1796 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_worsecase_pattern(): Find the optimal pattern, by toa_a(%d) < MIN_RX_BCN_T(%d)\n",
1797 				toa_a, MIN_RX_BCN_T);
1798 			break;
1799 		}
1800 		sum = ((tob_r - toa_r) * (tob_r - toa_r)) +
1801 			((tob_r - tob_a) * (tob_r - tob_a)) +
1802 			((tob_r - toa_a) * (tob_r - toa_a)) +
1803 			((toa_r - tob_a) * (toa_r - tob_a)) +
1804 			((toa_r - toa_a) * (toa_r - toa_a)) +
1805 			((tob_a - toa_a) * (tob_a - toa_a));
1806 		if (sum_last !=0 && sum > sum_last) {
1807 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_worsecase_pattern(): Find the optimal pattern, by get minSum\n");
1808 			break;
1809 		}
1810 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_worsecase_pattern(): tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d), sum_last(%d), sum(%d)\n",
1811 			tob_r, toa_r, tob_a, toa_a, sum_last, sum);
1812 		sum_last = sum;
1813 
1814 	}
1815 	tob_r = tob_r - 1;
1816 	toa_r = d_r - tob_r;
1817 	tob_a = bcns_offset + 2 * ref_bcn_intvl - toa_r - mcc_intvl;
1818 	toa_a = d_a - tob_a;
1819 	m_pattern->tob_r = (u8)tob_r;
1820 	m_pattern->toa_r = (u8)toa_r;
1821 	m_pattern->tob_a = (u8)tob_a;
1822 	m_pattern->toa_a = (u8)toa_a;
1823 	_mcc_fill_slot_info(m_pattern, false, ref_dur, m_pattern->role_ref);
1824 	_mcc_fill_slot_info(m_pattern, false, ano_dur, m_pattern->role_ano);
1825 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_worsecase_pattern(): Result, tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d)\n",
1826 			tob_r, toa_r, tob_a, toa_a);
1827 	status = RTW_PHL_STATUS_SUCCESS;
1828 exit:
1829 	if (status != RTW_PHL_STATUS_SUCCESS)
1830 		m_pattern->calc_fail = true;
1831 	return status;
1832 }
1833 
1834 #if 0
1835 void _mcc_fill_bt_slot(struct phl_mcc_info *minfo,
1836 				struct rtw_phl_mcc_dur_info *ref_dur,
1837 				struct rtw_phl_mcc_dur_info *ano_dur)
1838 {
1839 	struct rtw_phl_mcc_bt_info *bt_info = &minfo->bt_info;
1840 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
1841 	struct rtw_phl_mcc_pattern *m_pattern = &en_info->m_pattern;
1842 	u8 i = 0;
1843 	s16 spacing = 0;
1844 
1845 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_fill_bt_slot()\n");
1846 	if (false == bt_info->add_bt_role)
1847 		goto exit;
1848 	spacing = m_pattern->bcns_offset - m_pattern->toa_r - m_pattern->tob_a;
1849 	if (0 < spacing) {
1850 		if (bt_info->bt_dur < spacing) {
1851 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_bt_slot(): bt_info->bt_dur(%d) < spacing(%d), adjust BT dur to (%d), please check code\n",
1852 				bt_info->bt_dur, spacing, spacing);
1853 			bt_info->bt_dur = spacing;
1854 			bt_info->bt_seg[0] = bt_info->bt_dur;
1855 			bt_info->bt_seg_num = 1;
1856 			goto exit;
1857 		}
1858 		bt_info->bt_seg[0] = spacing;
1859 		bt_info->bt_seg[1] = bt_info->bt_dur - bt_info->bt_seg[0];
1860 		bt_info->bt_seg_num = 2;
1861 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_bt_slot(): Segment Bt dur to Seg1(%d), Seg2(%d)\n",
1862 			bt_info->bt_seg[0], bt_info->bt_seg[1]);
1863 	} else if (0 == spacing){
1864 		bt_info->bt_seg[0] = bt_info->bt_dur;
1865 		bt_info->bt_seg_num = 1;
1866 	} else {
1867 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_bt_slot(): spacing(%d) < 0, please check code,\n",
1868 			spacing);
1869 	}
1870 exit:
1871 	_mcc_dump_bt_ino(bt_info);
1872 	return;
1873 }
1874 #endif
1875 
1876 /*
1877  * |Wifi1 slot|Wifi2 slot|
1878  */
_mcc_calc_2_wrole_nego_pattern(struct rtw_phl_mcc_dur_info * ref_dur,struct rtw_phl_mcc_dur_info * ano_dur,s16 offset,struct rtw_phl_mcc_pattern * m_pattern)1879 bool _mcc_calc_2_wrole_nego_pattern(struct rtw_phl_mcc_dur_info *ref_dur,
1880 				struct rtw_phl_mcc_dur_info *ano_dur, s16 offset,
1881 				struct rtw_phl_mcc_pattern *m_pattern)
1882 {
1883 	bool cal_ok = false;
1884 	s16 tob_r = 0, toa_r = 0, tob_a = 0, toa_a = 0;
1885 
1886 	if ((!ref_dur->dur_limit.enable) && (!ano_dur->dur_limit.enable)) {
1887 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2_wrole_nego_pattern(): not support, both not enable slot limitation\n");
1888 		/*todo*/
1889 		goto exit;
1890 	}
1891 	if ((ref_dur->dur_limit.enable) && (ano_dur->dur_limit.enable)) {
1892 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2_wrole_nego_pattern(): not support, both enable slot limitation\n");
1893 		/*todo*/
1894 		goto exit;
1895 	}
1896 	if ((ref_dur->dur_limit.enable) && (!ano_dur->dur_limit.enable)) {
1897 		tob_r = ref_dur->dur / 2;
1898 		toa_r = ref_dur->dur - tob_r;
1899 		if (tob_r > ref_dur->dur_limit.max_tob) {
1900 			tob_r = ref_dur->dur_limit.max_tob;
1901 			toa_r = ref_dur->dur - tob_r;
1902 		}
1903 		if (toa_r > ref_dur->dur_limit.max_toa) {
1904 			toa_r = ref_dur->dur_limit.max_toa;
1905 			tob_r = ref_dur->dur - toa_r;
1906 		}
1907 		if ((tob_r > ref_dur->dur_limit.max_tob) ||
1908 			(toa_r > ref_dur->dur_limit.max_toa)) {
1909 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2_wrole_nego_pattern(): After adjust tob_r(%d) > max_tob(%d) or toa_r(%d) > max_toa(%d)\n",
1910 				tob_r, ref_dur->dur_limit.max_tob,
1911 				toa_r, ref_dur->dur_limit.max_toa);
1912 			goto exit;
1913 		}
1914 		tob_a = offset - toa_r;
1915 		toa_a = ano_dur->dur - tob_a;
1916 		if (tob_a <= 0 || toa_a <= 0) {
1917 			m_pattern->courtesy_i.c_en= true;
1918 			m_pattern->courtesy_i.c_num = 3;
1919 			m_pattern->courtesy_i.src_role = m_pattern->role_ref;
1920 			m_pattern->courtesy_i.tgt_role = m_pattern->role_ano;
1921 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calc_2_wrole_nego_pattern(): Limi by ref dur, courtesy_info: c_en(%d), c_num(%d), src_role->macid(0x%x), tgt_role->macid(0x%x)\n",
1922 				m_pattern->courtesy_i.c_en,
1923 				m_pattern->courtesy_i.c_num,
1924 				m_pattern->courtesy_i.src_role->macid,
1925 				m_pattern->courtesy_i.tgt_role->macid);
1926 		}
1927 		goto fill_pattern;
1928 	}
1929 	if ((!ref_dur->dur_limit.enable) && (ano_dur->dur_limit.enable)) {
1930 		tob_a = ano_dur->dur / 2;
1931 		toa_a = ano_dur->dur - tob_a;
1932 		if (tob_a > ano_dur->dur_limit.max_tob) {
1933 			tob_a = ano_dur->dur_limit.max_tob;
1934 			toa_a = ano_dur->dur - tob_a;
1935 		}
1936 		if (toa_a > ano_dur->dur_limit.max_toa) {
1937 			toa_a = ano_dur->dur_limit.max_toa;
1938 			tob_a = ano_dur->dur - toa_a;
1939 		}
1940 		if ((tob_a > ano_dur->dur_limit.max_tob) ||
1941 			(toa_a > ano_dur->dur_limit.max_toa)) {
1942 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2_wrole_nego_pattern(): After adjust tob_r(%d) > max_tob(%d) or toa_r(%d) > max_toa(%d)\n",
1943 				tob_a, ano_dur->dur_limit.max_tob,
1944 				toa_a, ano_dur->dur_limit.max_toa);
1945 			goto exit;
1946 		}
1947 		toa_r = offset - tob_a;
1948 		tob_r = ref_dur->dur - toa_r;
1949 		if (toa_r <= 0 || tob_r <= 0) {
1950 			m_pattern->courtesy_i.c_en= true;
1951 			m_pattern->courtesy_i.c_num = 3;
1952 			m_pattern->courtesy_i.src_role = m_pattern->role_ano;
1953 			m_pattern->courtesy_i.tgt_role = m_pattern->role_ref;
1954 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calc_2_wrole_nego_pattern(): Limi by ano dur, courtesy_info: c_en(%d), c_num(%d), src_role->macid(0x%x), tgt_role->macid(0x%x)\n",
1955 				m_pattern->courtesy_i.c_en,
1956 				m_pattern->courtesy_i.c_num,
1957 				m_pattern->courtesy_i.src_role->macid,
1958 				m_pattern->courtesy_i.tgt_role->macid);
1959 		}
1960 		goto fill_pattern;
1961 	}
1962 fill_pattern:
1963 	cal_ok = true;
1964 	m_pattern->tob_r = tob_r;
1965 	m_pattern->toa_r = toa_r;
1966 	m_pattern->tob_a = tob_a;
1967 	m_pattern->toa_a = toa_a;
1968 	_mcc_fill_slot_info(m_pattern, false, ref_dur->dur, m_pattern->role_ref);
1969 	_mcc_fill_slot_info(m_pattern, false, ano_dur->dur, m_pattern->role_ano);
1970 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wrole_nego_pattern(): calc nego patter\n");
1971 exit:
1972 	return cal_ok;
1973 }
1974 
1975 #if 0
1976 /**
1977  * Calculate the optimal pattern for 2wrole MCC with limitation of time slot v2
1978  * @ref_dur: Duration info of reference ch
1979  * @ano_dur: Duration info of another ch
1980  * @offset: The offset between beacon of ref_role and beacon of ano_role
1981  * @m_pattern: mcc pattern.
1982  **/
1983 enum rtw_phl_status _mcc_calculate_2_wrole_pattern_v2(
1984 				struct rtw_phl_mcc_dur_info *ref_dur,
1985 				struct rtw_phl_mcc_dur_info *ano_dur,
1986 				u16 offset,
1987 				struct rtw_phl_mcc_pattern *m_pattern)
1988 {
1989 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
1990 	s16 tob_r = 0, toa_r = 0, tob_a = 0, toa_a = 0;
1991 	s16 tob_r_cand = 0, toa_r_cand = 0, tob_a_cand = 0, toa_a_cand = 0;
1992 	s16 d_r = ref_dur->dur, d_a = ano_dur->dur, bcns_offset = offset;
1993 	s16 sum = 0, sum_last = 0;
1994 	s16 tob_r_min = _mcc_is_ap_category(m_pattern->role_ref->wrole) ?
1995 			EARLY_TX_BCN_T : EARLY_RX_BCN_T;
1996 	s16 toa_r_min = _mcc_is_ap_category(m_pattern->role_ref->wrole) ?
1997 			MIN_TX_BCN_T : MIN_RX_BCN_T;
1998 	s16 tob_a_min = _mcc_is_ap_category(m_pattern->role_ano->wrole) ?
1999 			EARLY_TX_BCN_T : EARLY_RX_BCN_T;
2000 	s16 toa_a_min = _mcc_is_ap_category(m_pattern->role_ano->wrole) ?
2001 			MIN_TX_BCN_T : MIN_RX_BCN_T;
2002 	s16 min_bcns_offset = toa_r_min + tob_a_min;
2003 	s16 i = 0, cnt = 0;
2004 	bool bdry_r = false, bdry_a = false; /*reach boundary edge*/
2005 
2006 	if ((bcns_offset > (m_pattern->role_ref->bcn_intvl - min_bcns_offset))
2007 		|| (bcns_offset < min_bcns_offset)) {
2008 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2_wrole_pattern_v2(): bcns_offset(%d) > max_offset(%d) || bcns_offset < min_offset(%d), goto calc_nego_pattern\n",
2009 			bcns_offset,
2010 			(m_pattern->role_ref->bcn_intvl - min_bcns_offset),
2011 			min_bcns_offset);
2012 		goto calc_nego_pattern;
2013 	}
2014 	cnt = bcns_offset - toa_r_min - tob_a_min;
2015 	toa_r = toa_r_min;
2016 	tob_a = tob_a_min;
2017 	for (i = 0; i < cnt; i++) {
2018 		if ((true == bdry_r) && (true == bdry_a)) {
2019 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2_wrole_pattern_v2(): braek loop by (true == bdry_r) && (true == bdry_a)\n");
2020 			break;
2021 		}
2022 		if (true == bdry_r)
2023 			goto calc_ano;
2024 		if (i > 0)
2025 			toa_r++;
2026 		tob_r = d_r - toa_r;
2027 		if (tob_r < tob_r_min) {
2028 			bdry_r = true;
2029 			goto calc_ano;
2030 		}
2031 		if (!ref_dur->dur_limit.enable)
2032 			goto check_conflict1;
2033 		if ((tob_r > ref_dur->dur_limit.max_tob) ||
2034 			(toa_r > ref_dur->dur_limit.max_toa)) {
2035 			goto calc_ano;
2036 		}
2037 check_conflict1:
2038 		if ((toa_r + tob_a_cand) > bcns_offset) {
2039 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2_wrole_pattern_v2(): braek loop by conflict(toa_r(%d) + tob_a_cand(%d)) > bcns_offset(%d)\n",
2040 				toa_r, tob_a_cand, bcns_offset);
2041 			break;
2042 		}
2043 		toa_r_cand = toa_r;
2044 calc_ano:
2045 		if (true == bdry_a)
2046 			continue;
2047 		if (i > 0)
2048 			tob_a++;
2049 		toa_a = d_a - tob_a;
2050 		if (toa_a < toa_a_min) {
2051 			bdry_a = true;
2052 			continue;
2053 		}
2054 		if (!ano_dur->dur_limit.enable)
2055 			goto check_conflict2;
2056 		if ((tob_a > ano_dur->dur_limit.max_tob) ||
2057 			(toa_a > ano_dur->dur_limit.max_toa)) {
2058 			continue;
2059 		}
2060 check_conflict2:
2061 		if ((bcns_offset - (tob_a + toa_r_cand)) >
2062 			(m_pattern->d_r_d_a_spacing_max)) {
2063 			continue;
2064 		}
2065 		if ((tob_a + toa_r_cand) > bcns_offset) {
2066 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2_wrole_pattern_v2(): braek loop by conflict(tob_a(%d) + toa_r_cand(%d)) > bcns_offset(%d)\n",
2067 				tob_a, toa_r_cand, bcns_offset);
2068 			break;
2069 		}
2070 		tob_a_cand = tob_a;
2071 /*calculate candidate result*/
2072 		tob_r_cand = d_r - toa_r_cand;
2073 		toa_a_cand = d_a - tob_a_cand;
2074 		sum = ((tob_r_cand - toa_r_cand) * (tob_r_cand - toa_r_cand)) +
2075 		      ((tob_r_cand - tob_a_cand) * (tob_r_cand - tob_a_cand)) +
2076 		      ((tob_r_cand - toa_a_cand) * (tob_r_cand - toa_a_cand)) +
2077 		      ((toa_r_cand - tob_a_cand) * (toa_r_cand - tob_a_cand)) +
2078 		      ((toa_r_cand - toa_a_cand) * (toa_r_cand - toa_a_cand)) +
2079 		      ((tob_a_cand - toa_a_cand) * (tob_a_cand - toa_a_cand));
2080 		if (sum_last !=0 && sum > sum_last) {
2081 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_wrole_pattern_v2(): Find the optimal pattern, by get minSum\n");
2082 			break;
2083 		}
2084 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_wrole_pattern_v2(): tob_r_cand(%d), toa_r_cand(%d), tob_a_cand(%d), toa_a_cand(%d), sum_last(%d), sum(%d)\n",
2085 			tob_r_cand, toa_r_cand, tob_a_cand, toa_a_cand,
2086 			sum_last, sum);
2087 		sum_last = sum;
2088 	}
2089 	if ((0 == toa_r_cand) || (0 == tob_a_cand)) {
2090 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2_wrole_pattern_v2(): Can't found suitable pattern, goto calc_nego_pattern\n");
2091 		goto calc_nego_pattern;
2092 	}
2093 	m_pattern->tob_r = tob_r_cand;
2094 	m_pattern->toa_r = toa_r_cand;
2095 	m_pattern->tob_a = tob_a_cand;
2096 	m_pattern->toa_a = toa_a_cand;
2097 	_mcc_fill_slot_info(m_pattern, false, ref_dur->dur, m_pattern->role_ref);
2098 	_mcc_fill_slot_info(m_pattern, false, ano_dur->dur, m_pattern->role_ano);
2099 	status = RTW_PHL_STATUS_SUCCESS;
2100 	goto exit;
2101 calc_nego_pattern:
2102 	if (_mcc_calc_2_wrole_nego_pattern(ref_dur, ano_dur, bcns_offset,
2103 						m_pattern)) {
2104 		status = RTW_PHL_STATUS_SUCCESS;
2105 	}
2106 exit:
2107 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_wrole_pattern_v2(): m_pattern: tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d)\n",
2108 		m_pattern->tob_r, m_pattern->toa_r, m_pattern->tob_a,
2109 		m_pattern->toa_a);
2110 	return status;
2111 }
2112 #endif
2113 
2114 #if 0
2115 /**
2116  * Copy from _mcc_calc_2_clients_worsecase_pattern and add limitation of time slot
2117  * worsecase: TDMA interval is 150 TU
2118  * Calculate the optimal pattern for 2wifi slot with limitation of time slot for worsecase
2119  * @ref_dur: Duration info of reference slot
2120  * @ano_dur: Duration info of another slot
2121  * @offset: The offset between beacon of ref_role and beacon of ano_role
2122  * @ref_bcn_intvl: Bcn interval of reference role
2123  * @m_pattern: mcc pattern.
2124  **/
2125 enum rtw_phl_status _mcc_calc_2_wifi_slot_worsecase_pattern(
2126 			struct rtw_phl_mcc_dur_info *ref_dur,
2127 			struct rtw_phl_mcc_dur_info *ano_dur, u16 offset,
2128 			u16 ref_bcn_intvl, struct rtw_phl_mcc_pattern *m_pattern)
2129 {
2130 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2131 	u16 mcc_intvl = ref_dur->dur + ano_dur->dur;
2132 	s16 tob_r = 0, toa_r = 0, tob_a = 0, toa_a = 0, tob_r_cand = 0;
2133 
2134 	s16 d_r = ref_dur->dur, d_a = ano_dur->dur, bcns_offset = offset;
2135 	s16 sum = 0, sum_last = 0, offset_min = 0, offset_max = 0;
2136 	s16 tob_r_l = ref_dur->dur_limit.max_tob;
2137 	s16 toa_r_l = ref_dur->dur_limit.max_toa;
2138 	s16 tob_a_l = ano_dur->dur_limit.max_tob;
2139 	s16 toa_a_l = ano_dur->dur_limit.max_toa;
2140 
2141 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): ref_dur(%d), ano_dur(%d), bcns offset(%d), ref_bcn_intvl(%d)\n",
2142 		d_r, d_a, offset, ref_bcn_intvl);
2143 	if (ref_bcn_intvl != HANDLE_BCN_INTVL) {
2144 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): ref_bcn_intvl(%d) != HANDLE_BCN_INTVL(%d), now, we can't calculate the pattern\n",
2145 			ref_bcn_intvl, HANDLE_BCN_INTVL);
2146 		goto exit;
2147 	}
2148 	_mcc_get_offset_range_for_2_clients_worsecase(d_r, d_a, ref_bcn_intvl,
2149 						&offset_min, &offset_max);
2150 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): we can calculate the range of bcn offset is %d~%d\n",
2151 			offset_min, offset_max);
2152 	if ((bcns_offset >= offset_min) && (bcns_offset <= offset_max))
2153 		goto calc;
2154 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): transform bcn offset from %d to %d\n",
2155 			bcns_offset, ref_bcn_intvl - bcns_offset);
2156 	/*bcn offfset = 85, we can transform to -15*/
2157 	bcns_offset = ref_bcn_intvl - bcns_offset;
2158 	if (bcns_offset >= offset_min && offset_min <=offset_max) {
2159 		goto calc;
2160 	} else {
2161 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): bcn offset out of range, we can't calculate it\n");
2162 		goto exit;
2163 	}
2164 calc:
2165 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): Start calculate\n");
2166 	for (tob_r = EARLY_RX_BCN_T; tob_r < mcc_intvl; tob_r++) {
2167 		toa_r = d_r - tob_r;
2168 		if (toa_r < MIN_RX_BCN_T) {
2169 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): Break loop, by toa_r(%d) < MIN_RX_BCN_T(%d)\n",
2170 				toa_r, MIN_RX_BCN_T);
2171 			break;
2172 		}
2173 		if (ref_dur->dur_limit.enable) {
2174 			if (toa_r > toa_r_l) {
2175 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): toa_r(%d) > toa_r_l(%d), continue next loop\n",
2176 					toa_r, toa_r_l);
2177 				continue;
2178 			}
2179 			if (tob_r > tob_r_l) {
2180 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): Break loop, tob_r(%d) > tob_r_l(%d)\n",
2181 					tob_r, tob_r_l);
2182 				break;
2183 			}
2184 		}
2185 		tob_a = bcns_offset + 2 * ref_bcn_intvl - toa_r - mcc_intvl;
2186 		if (tob_a < EARLY_RX_BCN_T)
2187 			continue;
2188 		toa_a = d_a - tob_a;
2189 		if (toa_a < MIN_RX_BCN_T){
2190 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): Break loop, by toa_a(%d) < MIN_RX_BCN_T(%d)\n",
2191 				toa_a, MIN_RX_BCN_T);
2192 			break;
2193 		}
2194 		if (ano_dur->dur_limit.enable) {
2195 			if (tob_a > tob_a_l || toa_a > toa_a_l) {
2196 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): tob_a(%d) > tob_a_l(%d) || toa_a(%d) > toa_a_l(%d), continue next loop\n",
2197 					tob_a, tob_a_l, toa_a, toa_a_l);
2198 				continue;
2199 			}
2200 		}
2201 		sum = ((tob_r - toa_r) * (tob_r - toa_r)) +
2202 			((tob_r - tob_a) * (tob_r - tob_a)) +
2203 			((tob_r - toa_a) * (tob_r - toa_a)) +
2204 			((toa_r - tob_a) * (toa_r - tob_a)) +
2205 			((toa_r - toa_a) * (toa_r - toa_a)) +
2206 			((tob_a - toa_a) * (tob_a - toa_a));
2207 		tob_r_cand = tob_r;
2208 		if (sum_last !=0 && sum > sum_last) {
2209 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): Find the optimal pattern, by get minSum\n");
2210 			break;
2211 		}
2212 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d), sum_last(%d), sum(%d)\n",
2213 			tob_r, toa_r, tob_a, toa_a, sum_last, sum);
2214 		sum_last = sum;
2215 
2216 	}
2217 	if (0 == tob_r_cand) {
2218 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): Can't found suitable pattern, goto calc_nego_pattern\n");
2219 		goto calc_nego_pattern;
2220 	}
2221 	tob_r = tob_r_cand;
2222 	toa_r = d_r - tob_r;
2223 	tob_a = bcns_offset + 2 * ref_bcn_intvl - toa_r - mcc_intvl;
2224 	toa_a = d_a - tob_a;
2225 	m_pattern->tob_r = tob_r;
2226 	m_pattern->toa_r = toa_r;
2227 	m_pattern->tob_a = tob_a;
2228 	m_pattern->toa_a = toa_a;
2229 	_mcc_fill_slot_info(m_pattern, false, ref_dur->dur, m_pattern->role_ref);
2230 	_mcc_fill_slot_info(m_pattern, false, ano_dur->dur, m_pattern->role_ano);
2231 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): Result, tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d)\n",
2232 			tob_r, toa_r, tob_a, toa_a);
2233 	status = RTW_PHL_STATUS_SUCCESS;
2234 	goto exit;
2235 calc_nego_pattern:
2236 	if (_mcc_calc_2_wrole_nego_pattern(ref_dur, ano_dur, bcns_offset,
2237 					m_pattern))
2238 		status = RTW_PHL_STATUS_SUCCESS;
2239 exit:
2240 	if (status != RTW_PHL_STATUS_SUCCESS)
2241 		m_pattern->calc_fail = true;
2242 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calc_2_wifi_slot_worsecase_pattern(): status(%d)\n",
2243 		status);
2244 	return status;
2245 }
2246 #endif
2247 
2248 /*
2249  * Calculate the optimal pattern for 2wrole MCC with limitation of time slot
2250  * @ref_dur: Duration of reference ch
2251  * @ano_dur: Duration of another ch
2252  * @offset: The offset between beacon of client1 and beacon of client2
2253  * @m_pattern: mcc pattern.
2254  * |          Wifi1 slot        |            Wifi2 slot        |          Wifi1 slot        |             Wifi2 slot        |
2255  * <tob_r> Bcn_r <toa_r>                                   <tob_r> Bcn_r <toa_r>
2256  *                                  <tob_a> Bcn_a <toa_a>                                  <tob_a> Bcn_a <toa_a>
2257  *	         <       bcns_offset       >
2258  */
_mcc_calculate_2_wrole_pattern(struct rtw_phl_mcc_dur_info * ref_dur,struct rtw_phl_mcc_dur_info * ano_dur,u16 offset,struct rtw_phl_mcc_pattern * m_pattern)2259 enum rtw_phl_status _mcc_calculate_2_wrole_pattern(
2260 				struct rtw_phl_mcc_dur_info *ref_dur,
2261 				struct rtw_phl_mcc_dur_info *ano_dur,
2262 				u16 offset,
2263 				struct rtw_phl_mcc_pattern *m_pattern)
2264 {
2265 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2266 	u16 mcc_intvl = ref_dur->dur + ano_dur->dur;
2267 	s16 tob_r = 0, toa_r = 0, tob_a = 0, toa_a = 0, tob_r_cand = 0;
2268 	s16 d_r = ref_dur->dur, d_a = ano_dur->dur, bcns_offset = offset;
2269 	s16 sum = 0, sum_last = 0;
2270 	s16 tob_r_l = ref_dur->dur_limit.max_tob;
2271 	s16 toa_r_l = ref_dur->dur_limit.max_toa;
2272 	s16 tob_a_l = ano_dur->dur_limit.max_tob;
2273 	s16 toa_a_l = ano_dur->dur_limit.max_toa;
2274 
2275 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_wrole_pattern(): ref_dur(%d), ano_dur(%d), bcns offset(%d)\n",
2276 		d_r, d_a, bcns_offset);
2277 	for (tob_r = EARLY_RX_BCN_T; tob_r < mcc_intvl; tob_r++) {
2278 		toa_r = d_r - tob_r;
2279 		if (toa_r < MIN_RX_BCN_T) {
2280 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_wrole_pattern(): break loop, by toa_r(%d) < MIN_RX_BCN_T(%d)\n",
2281 				toa_r, MIN_RX_BCN_T);
2282 			break;
2283 		}
2284 		if (ref_dur->dur_limit.enable) {
2285 			if (tob_r > tob_r_l || toa_r > toa_r_l) {
2286 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_wrole_pattern(): tob_r(%d) > tob_r_l(%d) || toa_r(%d) > toa_r_l(%d), continue next loop\n",
2287 					tob_r, tob_r_l, toa_r, toa_r_l);
2288 				continue;
2289 			}
2290 		}
2291 		tob_a = bcns_offset - toa_r;
2292 		if (tob_a < EARLY_RX_BCN_T)
2293 			continue;
2294 		toa_a = d_a - tob_a;
2295 		if (toa_a < MIN_RX_BCN_T){
2296 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_wrole_pattern(): break loop, by toa_a(%d) < MIN_RX_BCN_T(%d)\n",
2297 				toa_a, MIN_RX_BCN_T);
2298 			break;
2299 		}
2300 		if (ano_dur->dur_limit.enable) {
2301 			if (tob_a > tob_a_l || toa_a > toa_a_l) {
2302 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_wrole_pattern(): tob_a(%d) > tob_a_l(%d) || toa_a(%d) > toa_a_l(%d), continue next loop\n",
2303 					tob_a, tob_a_l, toa_a, toa_a_l);
2304 				continue;
2305 			}
2306 		}
2307 		sum = ((tob_r - toa_r) * (tob_r - toa_r)) +
2308 			((tob_r - tob_a) * (tob_r - tob_a)) +
2309 			((tob_r - toa_a) * (tob_r - toa_a)) +
2310 			((toa_r - tob_a) * (toa_r - tob_a)) +
2311 			((toa_r - toa_a) * (toa_r - toa_a)) +
2312 			((tob_a - toa_a) * (tob_a - toa_a));
2313 		tob_r_cand = tob_r;
2314 		if (sum_last !=0 && sum > sum_last) {
2315 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_wrole_pattern(): Find the optimal pattern, by get minSum\n");
2316 			break;
2317 		}
2318 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_wrole_pattern(): tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d), sum_last(%d), sum(%d)\n",
2319 			tob_r, toa_r, tob_a, toa_a, sum_last, sum);
2320 		sum_last = sum;
2321 	}
2322 	if (0 == tob_r_cand) {
2323 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_calculate_2_wrole_pattern(): Can't found suitable pattern, goto calc_nego_pattern\n");
2324 		goto calc_nego_pattern;
2325 	}
2326 	tob_r = tob_r_cand;
2327 	toa_r = d_r - tob_r;
2328 	tob_a = bcns_offset - toa_r;
2329 	toa_a = d_a - tob_a;
2330 	m_pattern->tob_r = tob_r;
2331 	m_pattern->toa_r = toa_r;
2332 	m_pattern->tob_a = tob_a;
2333 	m_pattern->toa_a = toa_a;
2334 	_mcc_fill_slot_info(m_pattern, false, ref_dur->dur, m_pattern->role_ref);
2335 	_mcc_fill_slot_info(m_pattern, false, ano_dur->dur, m_pattern->role_ano);
2336 	status = RTW_PHL_STATUS_SUCCESS;
2337 	goto exit;
2338 calc_nego_pattern:
2339 	if (_mcc_calc_2_wrole_nego_pattern(ref_dur, ano_dur, bcns_offset,
2340 					m_pattern))
2341 		status = RTW_PHL_STATUS_SUCCESS;
2342 exit:
2343 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_pattern(): tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d)\n",
2344 			m_pattern->tob_r, m_pattern->toa_r, m_pattern->tob_a,
2345 			m_pattern->toa_a);
2346 	return status;
2347 }
2348 
2349 /*
2350  * Calculate the optimal pattern for client+client MCC
2351  * @ref_dur: Duration of reference ch
2352  * @ano_dur: Duration of another ch
2353  * @offset: The offset between beacon of client1 and beacon of client2
2354  * @m_pattern: mcc pattern.
2355  * |          Wifi1 slot        |            Wifi2 slot        |          Wifi1 slot        |             Wifi2 slot        |
2356  * <tob_r> Bcn_r <toa_r>                                   <tob_r> Bcn_r <toa_r>
2357  *                                  <tob_a> Bcn_a <toa_a>                                  <tob_a> Bcn_a <toa_a>
2358  *	         <       bcns_offset       >
2359  */
_mcc_calculate_2_clients_pattern(u16 ref_dur,u16 ano_dur,u16 offset,struct rtw_phl_mcc_pattern * m_pattern)2360 void _mcc_calculate_2_clients_pattern(u16 ref_dur, u16 ano_dur, u16 offset,
2361 					struct rtw_phl_mcc_pattern *m_pattern)
2362 {
2363 	u16 mcc_intvl = ref_dur + ano_dur;
2364 	s16 tob_r = 0, toa_r = 0, tob_a = 0, toa_a = 0;
2365 	s16 d_r = ref_dur, d_a = ano_dur, bcns_offset = offset;
2366 	s16 sum = 0, sum_last = 0;
2367 
2368 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_pattern(): ref_dur(%d), ano_dur(%d), bcns offset(%d)\n",
2369 		ref_dur, ano_dur, offset);
2370 	for (tob_r = EARLY_RX_BCN_T; tob_r < mcc_intvl; tob_r++) {
2371 		toa_r = d_r - tob_r;
2372 		if (toa_r < MIN_RX_BCN_T) {
2373 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_pattern(): Find the optimal pattern, by toa_r(%d) < MIN_RX_BCN_T(%d)\n",
2374 				toa_r, MIN_RX_BCN_T);
2375 			break;
2376 		}
2377 		tob_a = bcns_offset - toa_r;
2378 		if (tob_a < EARLY_RX_BCN_T)
2379 			continue;
2380 		toa_a = d_a - tob_a;
2381 		if (toa_a < MIN_RX_BCN_T){
2382 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_pattern(): Find the optimal pattern, by toa_a(%d) < MIN_RX_BCN_T(%d)\n",
2383 				toa_a, MIN_RX_BCN_T);
2384 			break;
2385 		}
2386 		sum = ((tob_r - toa_r) * (tob_r - toa_r)) +
2387 			((tob_r - tob_a) * (tob_r - tob_a)) +
2388 			((tob_r - toa_a) * (tob_r - toa_a)) +
2389 			((toa_r - tob_a) * (toa_r - tob_a)) +
2390 			((toa_r - toa_a) * (toa_r - toa_a)) +
2391 			((tob_a - toa_a) * (tob_a - toa_a));
2392 		if (sum_last !=0 && sum > sum_last) {
2393 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_pattern(): Find the optimal pattern, by get minSum\n");
2394 			break;
2395 		}
2396 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_pattern(): tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d), sum_last(%d), sum(%d)\n",
2397 			tob_r, toa_r, tob_a, toa_a, sum_last, sum);
2398 		sum_last = sum;
2399 	}
2400 	tob_r = tob_r - 1;
2401 	toa_r = d_r - tob_r;
2402 	tob_a = bcns_offset - toa_r;
2403 	toa_a = d_a - tob_a;
2404 	m_pattern->tob_r = (u8)tob_r;
2405 	m_pattern->toa_r = (u8)toa_r;
2406 	m_pattern->tob_a = (u8)tob_a;
2407 	m_pattern->toa_a = (u8)toa_a;
2408 	_mcc_fill_slot_info(m_pattern, false, ref_dur, m_pattern->role_ref);
2409 	_mcc_fill_slot_info(m_pattern, false, ano_dur, m_pattern->role_ano);
2410 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_calculate_2_clients_pattern(): tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d)\n",
2411 			tob_r, toa_r, tob_a, toa_a);
2412 }
2413 
2414 /*
2415  * Fill patten info for 2wifi slot req + bt slot req
2416  * @minfo: enable mcc info
2417  * @role_ref: reference wifi slot req
2418  * @role_ano: another wifi slot req
2419  */
_mcc_fill_2_wrole_bt_pattern(struct phl_mcc_info * minfo,struct rtw_phl_mcc_role * role_ref,struct rtw_phl_mcc_role * role_ano)2420 void _mcc_fill_2_wrole_bt_pattern(struct phl_mcc_info *minfo,
2421 	struct rtw_phl_mcc_role *role_ref, struct rtw_phl_mcc_role *role_ano)
2422 {
2423 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
2424 	struct rtw_phl_mcc_pattern *m_pattern = &en_info->m_pattern;
2425 	struct rtw_phl_mcc_dur_info dur_ref = role_ref->policy.dur_info;
2426 	struct rtw_phl_mcc_dur_info dur_ano = role_ano->policy.dur_info;
2427 #if 0
2428 	u16 dr_max = (dur_ref.dur_limit.enable) ?
2429 			dur_ref.dur_limit.max_dur : en_info->mcc_intvl;
2430 	u16 da_max = (dur_ano.dur_limit.enable) ?
2431 			dur_ano.dur_limit.max_dur : en_info->mcc_intvl;
2432 
2433 
2434 	if (minfo->bt_info.bt_seg_num == 2) {
2435 		/*temporary disable this case, we can't handle it in GC(NOA)+STA*/
2436 		minfo->bt_info.add_bt_role = true;
2437 		if (((dur_ref.dur + minfo->bt_info.bt_seg[0]) <= dr_max) &&
2438 			((dur_ano.dur + minfo->bt_info.bt_seg[1]) <= da_max)) {
2439 			dur_ref.dur += minfo->bt_info.bt_seg[0];
2440 			dur_ano.dur += minfo->bt_info.bt_seg[1];
2441 		} else if ((dur_ref.dur + minfo->bt_info.bt_dur) <= dr_max) {
2442 			dur_ref.dur += minfo->bt_info.bt_dur;
2443 		} else if ((dur_ano.dur + minfo->bt_info.bt_dur) <= da_max) {
2444 			dur_ano.dur += minfo->bt_info.bt_dur;
2445 		} else {
2446 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_2_wrole_bt_pattern(): Fail to combine wifi slot and bt slot to single slot, we use default worsecase pattern \n");
2447 			_mcc_set_2_clients_worsecase_default_pattern(m_pattern, dur_ref.dur);
2448 			goto exit;
2449 		}
2450 		if (RTW_PHL_STATUS_SUCCESS !=
2451 				_mcc_calc_2_wifi_slot_worsecase_pattern(
2452 						&dur_ref, &dur_ano,
2453 						m_pattern->bcns_offset,
2454 						role_ref->bcn_intvl,
2455 						m_pattern)) {
2456 			_mcc_set_2_clients_worsecase_default_pattern(m_pattern, dur_ref.dur);
2457 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_fill_2_wrole_bt_pattern(): _mcc_calc_2_wifi_slot_worsecase_pattern fail, we use default worsecase pattern\n");
2458 		}
2459 		dur_ref = role_ref->policy.dur_info;
2460 		dur_ano = role_ano->policy.dur_info;
2461 		if (m_pattern->tob_r > (dur_ref.dur - MIN_RX_BCN_T)) {
2462 			role_ref->policy.protect_bcn = true;
2463 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_fill_2_wrole_bt_pattern(): bcn will in bt dur, we set protect_bcn = true for role_ref\n");
2464 		}
2465 		if (m_pattern->tob_a > (dur_ano.dur - MIN_RX_BCN_T)) {
2466 			role_ano->policy.protect_bcn = true;
2467 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_fill_2_wrole_bt_pattern(): bcn will in bt dur, we set protect_bcn = true for role_ano\n");
2468 		}
2469 	} else
2470 #endif
2471 	if (minfo->bt_info.bt_seg_num == 1) {
2472 		minfo->bt_info.add_bt_role = true;
2473 		if (RTW_PHL_STATUS_SUCCESS !=
2474 			_mcc_calculate_2wslot_1btslot_pattern(&dur_ref,
2475 				&dur_ano, minfo->bt_info.bt_dur, m_pattern)) {
2476 			PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_fill_2_wrole_bt_pattern(): _mcc_calculate_2wslot_1btslot_pattern fail, we use default worsecase pattern\n");
2477 			_mcc_set_2_clients_worsecase_default_pattern(m_pattern, dur_ref.dur);
2478 		}
2479 	} else {
2480 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_2_wrole_bt_pattern(): error bt_seg_num(%d)\n",
2481 			minfo->bt_info.bt_seg_num);
2482 	}
2483 #if 0
2484 exit:
2485 #endif
2486 	return;
2487 }
2488 
_mcc_fill_2wrole_pattern_with_limitation(struct phl_mcc_info * minfo,struct rtw_phl_mcc_role * role_ref,struct rtw_phl_mcc_role * role_ano)2489 bool _mcc_fill_2wrole_pattern_with_limitation(struct phl_mcc_info *minfo,
2490 	struct rtw_phl_mcc_role *role_ref, struct rtw_phl_mcc_role *role_ano)
2491 {
2492 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
2493 	struct rtw_phl_mcc_dur_info *dur_i_r = &role_ref->policy.dur_info;
2494 	struct rtw_phl_mcc_dur_info *dur_i_a = &role_ano->policy.dur_info;
2495 	struct rtw_phl_mcc_policy_info *policy_i = NULL;
2496 	struct rtw_phl_mcc_courtesy *courtesy_i = &en_info->m_pattern.courtesy_i;
2497 	bool ret = false;
2498 
2499 	if (!(dur_i_r->dur_limit.enable || dur_i_a->dur_limit.enable))
2500 		goto exit;
2501 	if (dur_i_r->dur_limit.enable && dur_i_a->dur_limit.enable) {
2502 		/*implement in phase????*/
2503 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_2wrole_pattern_with_limitation(): Not support for all enable limitation, tag_r(%d), tag_a(%d)\n",
2504 			dur_i_r->dur_limit.tag, dur_i_a->dur_limit.tag);
2505 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_2wrole_pattern_with_limitation(): we ignore the limitation of time slot, it will degrade performance\n");
2506 		goto exit;
2507 	}
2508 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_fill_2wrole_pattern_with_limitation\n");
2509 	if (_mcc_discision_duration_for_2role_bt(minfo)) {
2510 		_mcc_fill_2_wrole_bt_pattern(minfo, role_ref,  role_ano);
2511 	} else if (RTW_PHL_STATUS_SUCCESS != _mcc_calculate_2_wrole_pattern(
2512 					dur_i_r, dur_i_a,
2513 					en_info->m_pattern.bcns_offset,
2514 					&en_info->m_pattern)) {
2515 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_2wrole_pattern_with_limitation(): Calc pattern fail with limitation of time slot, we ignore the limitation of time slot, it will degrade performance\n");
2516 		goto exit;
2517 	}
2518 	/*_mcc_fill_bt_slot(minfo, dur_i_r, dur_i_a);*/
2519 	if (true == courtesy_i->c_en) {
2520 		policy_i = &courtesy_i->src_role->policy;
2521 		policy_i->courtesy_en = true;
2522 		policy_i->courtesy_num = courtesy_i->c_num;
2523 		policy_i->courtesy_target = (u8)courtesy_i->tgt_role->macid;
2524 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_2wrole_pattern_with_limitation(): Enable courtesy function, time slot of macid:0x%x replace by time slot of macid:0x%x, courtesy_num(%d)\n",
2525 			courtesy_i->src_role->macid, policy_i->courtesy_target,
2526 			policy_i->courtesy_num);
2527 	}
2528 	ret =true;
2529 exit:
2530 	return ret;
2531 }
2532 
_mcc_fill_2_clients_pattern(struct phl_mcc_info * minfo,u8 worsecase,struct rtw_phl_mcc_role * role_ref,struct rtw_phl_mcc_role * role_ano)2533 void _mcc_fill_2_clients_pattern(struct phl_mcc_info *minfo, u8 worsecase,
2534 	struct rtw_phl_mcc_role *role_ref, struct rtw_phl_mcc_role *role_ano)
2535 {
2536 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
2537 
2538 	if (!worsecase) {
2539 		_mcc_calculate_2_clients_pattern(role_ref->policy.dur_info.dur,
2540 						role_ano->policy.dur_info.dur,
2541 						en_info->m_pattern.bcns_offset,
2542 						&en_info->m_pattern);
2543 		goto exit;
2544 	}
2545 	if (RTW_PHL_STATUS_SUCCESS != _mcc_calc_2_clients_worsecase_pattern(
2546 					role_ref->policy.dur_info.dur,
2547 					role_ano->policy.dur_info.dur,
2548 					en_info->m_pattern.bcns_offset,
2549 					role_ref->bcn_intvl,
2550 					&en_info->m_pattern)) {
2551 		_mcc_set_2_clients_worsecase_default_pattern(&en_info->m_pattern,
2552 						role_ref->policy.dur_info.dur);
2553 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_fill_info_for_2_clients_mode(): _mcc_calc_2_clients_worsecase_pattern fail, we use default worsecase pattern\n");
2554 	}
2555 exit:
2556 	return;
2557 }
2558 
_mcc_get_2_clients_bcn_offset(struct phl_info_t * phl,u16 * offset,struct rtw_phl_mcc_role * role_ref,struct rtw_phl_mcc_role * role_ano)2559 enum rtw_phl_status _mcc_get_2_clients_bcn_offset(struct phl_info_t *phl,
2560 			u16 *offset, struct rtw_phl_mcc_role *role_ref,
2561 			struct rtw_phl_mcc_role *role_ano)
2562 {
2563 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2564 	u32 tsf_ref_h = 0, tsf_ref_l = 0, tsf_ano_h = 0, tsf_ano_l = 0;
2565 	u64 tsf_ref = 0, tsf_ano = 0;
2566 	u16 ofst_r = 0, ofst_a = 0;
2567 
2568 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_mcc_get_2ports_tsf(phl->hal,
2569 			role_ref->group, role_ref->macid, role_ano->macid,
2570 			&tsf_ref_h, &tsf_ref_l, &tsf_ano_h, &tsf_ano_l)) {
2571 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_get_2_clients_bcn_offset(): Get tsf failed\n");
2572 		goto exit;
2573 	}
2574 	tsf_ref = tsf_ref_h;
2575 	tsf_ref = tsf_ref << 32;
2576 	tsf_ref |= tsf_ref_l;
2577 	tsf_ano = tsf_ano_h;
2578 	tsf_ano = tsf_ano << 32;
2579 	tsf_ano |= tsf_ano_l;
2580 	/*calculate the value between current TSF and TBTT*/
2581 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_get_2_clients_bcn_offset(): role_ref calc_offset_from_tbtt\n");
2582 	phl_calc_offset_from_tbtt(phl, role_ref->wrole, tsf_ref, &ofst_r);
2583 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_get_2_clients_bcn_offset(): role_ano calc_offset_from_tbtt\n");
2584 	phl_calc_offset_from_tbtt(phl, role_ano->wrole, tsf_ano, &ofst_a);
2585 	if (ofst_r < ofst_a)
2586 		ofst_r += role_ref->bcn_intvl;
2587 	*offset = ofst_r - ofst_a;
2588 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_get_2_clients_bcn_offset(): bcn offset(%d)\n",
2589 		*offset);
2590 	status = RTW_PHL_STATUS_SUCCESS;
2591 exit:
2592 	return status;
2593 }
2594 
2595 /**
2596 * set defalut pattern for ap slot+sta slot
2597  * |       Wifi1 slot           |          Wifi2 slot         |       Wifi1 slot           |          Wifi2 slot         |
2598  * <tob_r> Bcn_r <toa_r>                                  <tob_r> Bcn_r <toa_r>
2599  *                                  <tob_a> Bcn_a <toa_a>                                 <tob_a> Bcn_a <toa_a>
2600  *               <         bcns_offset         >
2601  **/
2602 
_mcc_set_ap_client_default_pattern(struct phl_mcc_info * minfo,u16 * bcns_offet)2603 void _mcc_set_ap_client_default_pattern(struct phl_mcc_info *minfo,
2604 					u16 *bcns_offet)
2605 {
2606 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
2607 	struct rtw_phl_mcc_pattern *m_pattern = &en_info->m_pattern;
2608 	struct rtw_phl_mcc_role *role_ref = get_ref_role(en_info);
2609 	struct rtw_phl_mcc_role *role_ano = (role_ref == &en_info->mcc_role[0])
2610 				? &en_info->mcc_role[1] : &en_info->mcc_role[0];
2611 
2612 	*bcns_offet = (u8)(en_info->mcc_intvl / 2);
2613 	m_pattern->toa_r= role_ref->policy.dur_info.dur / 2;
2614 	m_pattern->tob_r = role_ref->policy.dur_info.dur - m_pattern->toa_r;
2615 	m_pattern->tob_a = (u8)(*bcns_offet - m_pattern->toa_r);
2616 	m_pattern->toa_a = role_ano->policy.dur_info.dur - m_pattern->tob_a;
2617 	_mcc_fill_slot_info(m_pattern, false, role_ref->policy.dur_info.dur, role_ref);
2618 	_mcc_fill_slot_info(m_pattern, false, role_ano->policy.dur_info.dur, role_ano);
2619 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_set_ap_client_default_pattern(): tob_r(%d), toa_r(%d), tob_a(%d), toa_a(%d)\n",
2620 		m_pattern->tob_r, m_pattern->toa_r, m_pattern->tob_a, m_pattern->toa_a);
2621 }
2622 
_mcc_set_worsecase_dur_for_2_clients_mode(struct rtw_phl_mcc_dur_info * dur_i_1,struct rtw_phl_mcc_dur_info * dur_i_2,u16 * mcc_intvl)2623 void _mcc_set_worsecase_dur_for_2_clients_mode(
2624 				struct rtw_phl_mcc_dur_info *dur_i_1,
2625 				struct rtw_phl_mcc_dur_info *dur_i_2,
2626 				u16 *mcc_intvl)
2627 {
2628 	/*need to get from core layer for worsecase??*/
2629 	if (dur_i_1->dur > dur_i_2->dur) {
2630 		*mcc_intvl = WORSECASE_INTVL;
2631 		dur_i_1->dur = CLIENTS_WORSECASE_LARGE_DUR;
2632 		dur_i_2->dur = (*mcc_intvl - dur_i_1->dur);
2633 	} else {
2634 		*mcc_intvl = WORSECASE_INTVL;
2635 		dur_i_2->dur = CLIENTS_WORSECASE_LARGE_DUR;
2636 		dur_i_1->dur = (*mcc_intvl - dur_i_2->dur);
2637 	}
2638 }
2639 
_mcc_set_dur_for_2_clients_mode(struct rtw_phl_mcc_dur_info * dur_i_1,struct rtw_phl_mcc_dur_info * dur_i_2,u16 * mcc_intvl)2640 void _mcc_set_dur_for_2_clients_mode(
2641 				struct rtw_phl_mcc_dur_info *dur_i_1,
2642 				struct rtw_phl_mcc_dur_info *dur_i_2,
2643 				u16 *mcc_intvl)
2644 {
2645 	u16 *dur1 = &dur_i_1->dur, *dur2 = &dur_i_2->dur;
2646 
2647 	if (*dur1 == MCC_DUR_NONSPECIFIC) {
2648 		*dur1 = (*mcc_intvl - (*dur2));
2649 	} else {
2650 		*dur2 = (*mcc_intvl - (*dur1));
2651 	}
2652 	PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_set_dur_for_2_clients_mode(): Original dur1(%d), dur2(%d)\n",
2653 		*dur1, *dur2);
2654 	if (*dur1 < MIN_CLIENT_DUR) {
2655 		*dur1 = MIN_CLIENT_DUR;
2656 		*dur2 = (*mcc_intvl - (*dur1));
2657 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_set_dur_for_2_clients_mode(): Core specific unsuitable duration, we adjust dur to dur1(%d) and dur2(%d)\n",
2658 			*dur1, *dur2);
2659 	} else if (*dur2 < MIN_CLIENT_DUR) {
2660 		*dur2 = MIN_CLIENT_DUR;
2661 		*dur1 = (*mcc_intvl - (*dur2));
2662 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_set_dur_for_2_clients_mode(): Core specific unsuitable duration, we adjust dur to dur1(%d) and dur2(%d)\n",
2663 			*dur1, *dur2);
2664 	}
2665 	if ((dur_i_1->dur_limit.enable) && (dur_i_1->dur_limit.max_dur != 0) &&
2666 		(*dur1 > dur_i_1->dur_limit.max_dur)) {
2667 		*dur1 = dur_i_1->dur_limit.max_dur;
2668 		*dur2 = (*mcc_intvl - (*dur1));
2669 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_set_dur_for_2_clients_mode(): dur1 > max_dur(%d), we adjust dur to dur1(%d) and dur2(%d)\n",
2670 			dur_i_1->dur_limit.max_dur, *dur1, *dur2);
2671 	}
2672 	if ((dur_i_2->dur_limit.enable) && (dur_i_2->dur_limit.max_dur != 0) &&
2673 		(*dur2 > dur_i_2->dur_limit.max_dur)) {
2674 		*dur2 = dur_i_2->dur_limit.max_dur;
2675 		*dur1 = (*mcc_intvl - (*dur2));
2676 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_set_dur_for_2_clients_mode(): dur2 > max_dur(%d), we adjust dur to dur1(%d) and dur2(%d)\n",
2677 			dur_i_2->dur_limit.max_dur, *dur1, *dur2);
2678 	}
2679 }
2680 
_mcc_fill_info_for_2_clients_mode(struct phl_info_t * phl,struct phl_mcc_info * minfo)2681 enum rtw_phl_status _mcc_fill_info_for_2_clients_mode(struct phl_info_t *phl,
2682 						struct phl_mcc_info *minfo)
2683 {
2684 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2685 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
2686 	struct rtw_phl_mcc_role *role_ref = get_ref_role(en_info);
2687 	struct rtw_phl_mcc_role *role_ano = (role_ref == &en_info->mcc_role[0])
2688 				? &en_info->mcc_role[1] : &en_info->mcc_role[0];
2689 	u16 bcns_offset = 0;
2690 	bool worsecase = false;
2691 
2692 	en_info->mcc_intvl = role_ref->bcn_intvl;
2693 	if (RTW_PHL_STATUS_SUCCESS != _mcc_get_2_clients_bcn_offset(phl,
2694 					&bcns_offset, role_ref, role_ano)) {
2695 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_info_for_2_clients_mode(): Get bcn offset fail\n");
2696 		goto exit;
2697 	}
2698 	en_info->m_pattern.role_ref = role_ref;
2699 	en_info->m_pattern.role_ano = role_ano;
2700 	en_info->m_pattern.bcns_offset = bcns_offset;
2701 	if ((bcns_offset < MIN_BCNS_OFFSET) ||
2702 		(bcns_offset > (role_ref->bcn_intvl - MIN_BCNS_OFFSET))) {
2703 		worsecase = true;
2704 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_fill_info_for_2_clients_mode(): worsecase, bcns_offset(%d) < %d or bcns_offset > %d\n",
2705 			bcns_offset, MIN_BCNS_OFFSET,
2706 			(role_ref->bcn_intvl - MIN_BCNS_OFFSET));
2707 	}
2708 	_mcc_set_dur_for_2_clients_mode(&role_ref->policy.dur_info,
2709 					&role_ano->policy.dur_info,
2710 					&en_info->mcc_intvl);
2711 	if (_mcc_fill_2wrole_pattern_with_limitation(minfo, role_ref, role_ano)) {
2712 		/*wifi slot, bt slot, and only 1 wifi slot with limitation*/
2713 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_info_for_2_clients_mode(): _mcc_fill_2wrole_pattern_with_limitation\n");
2714 	} else if (_mcc_discision_duration_for_2role_bt(minfo)) {
2715 		_mcc_fill_2_wrole_bt_pattern(minfo, role_ref, role_ano);
2716 	} else {
2717 	/*We only adjust dur for all wifi slot in worsecase*/
2718 		if (worsecase) {
2719 			_mcc_set_worsecase_dur_for_2_clients_mode(
2720 				&role_ref->policy.dur_info,
2721 				&role_ano->policy.dur_info, &en_info->mcc_intvl);
2722 		}
2723 		_mcc_fill_2_clients_pattern(minfo, worsecase, role_ref, role_ano);
2724 	}
2725 	if (RTW_PHL_STATUS_SUCCESS != _mcc_calculate_start_tsf(phl, en_info)) {
2726 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_info_for_2_clients_mode(): calculate start tsf fail\n");
2727 		goto exit;
2728 	}
2729 	status = RTW_PHL_STATUS_SUCCESS;
2730 exit:
2731 	return status;
2732 }
2733 
_mcc_set_dur_for_ap_client_mode(u16 * ap_dur,u16 * client_dur,u16 mcc_intvl)2734 void _mcc_set_dur_for_ap_client_mode(u16 *ap_dur, u16 *client_dur, u16 mcc_intvl)
2735 {
2736 	if (*ap_dur == MCC_DUR_NONSPECIFIC)
2737 		*ap_dur = mcc_intvl - *client_dur;
2738 	if (*ap_dur < MIN_AP_DUR) {
2739 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_set_dur_for_ap_client_mode(): ap_dur(%d) < MIN_AP_DUR(%d), set ap_dur = MIN_AP_DUR\n",
2740 			*ap_dur, MIN_AP_DUR);
2741 		*ap_dur = MIN_AP_DUR;
2742 	} else if (*ap_dur > (mcc_intvl - MIN_CLIENT_DUR)) {
2743 		PHL_TRACE(COMP_PHL_MCC, _PHL_WARNING_, "_mcc_set_dur_for_ap_client_mode(): ap_dur(%d) < MAX_AP_DUR(%d), set ap_dur = MAX_AP_DUR\n",
2744 			*ap_dur, (mcc_intvl - MIN_CLIENT_DUR));
2745 		*ap_dur = mcc_intvl - MIN_CLIENT_DUR;
2746 	}
2747 	*client_dur = mcc_intvl - *ap_dur;
2748 }
2749 
_mcc_fill_info_for_ap_client_mode(struct phl_info_t * phl,struct phl_mcc_info * minfo)2750 enum rtw_phl_status _mcc_fill_info_for_ap_client_mode(
2751 			struct phl_info_t *phl, struct phl_mcc_info *minfo)
2752 {
2753 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2754 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
2755 	struct rtw_phl_mcc_sync_tsf_info *sync_info = &en_info->sync_tsf_info;
2756 	struct rtw_phl_mcc_role *ap_role = NULL;
2757 	struct rtw_phl_mcc_role *client_role = NULL;
2758 	struct rtw_phl_mcc_role *role_ref = get_ref_role(en_info);
2759 	struct rtw_phl_mcc_role *role_ano = (role_ref == &en_info->mcc_role[0])
2760 				? &en_info->mcc_role[1] : &en_info->mcc_role[0];
2761 
2762 	ap_role = _mcc_get_mrole_by_category(en_info, MCC_ROLE_AP_CAT);
2763 	client_role = _mcc_get_mrole_by_category(en_info, MCC_ROLE_CLIENT_CAT);
2764 	if (ap_role == NULL || client_role == NULL) {
2765 		_mcc_dump_en_info(en_info);
2766 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_info_for_ap_client_mode(): (ap_role == NULL || client_role == NULL)\n");
2767 		goto exit;
2768 	}
2769 	en_info->m_pattern.role_ref = role_ref;
2770 	en_info->m_pattern.role_ano = role_ano;
2771 	en_info->mcc_intvl = ap_role->bcn_intvl;
2772 	_mcc_set_dur_for_ap_client_mode(&ap_role->policy.dur_info.dur,
2773 					&client_role->policy.dur_info.dur,
2774 					en_info->mcc_intvl);
2775 	if (_mcc_discision_duration_for_2role_bt(minfo)) {
2776 		en_info->m_pattern.bcns_offset = AP_CLIENT_OFFSET;
2777 		_mcc_fill_2_wrole_bt_pattern(minfo, role_ref, role_ano);
2778 	} else {
2779 		_mcc_set_ap_client_default_pattern(minfo,
2780 					&en_info->m_pattern.bcns_offset);
2781 	}
2782 	if (RTW_PHL_STATUS_SUCCESS != rtw_phl_tbtt_sync(phl,
2783 					client_role->wrole, ap_role->wrole,
2784 					en_info->m_pattern.bcns_offset, true,
2785 					&sync_info->offset)) {
2786 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_info_for_ap_client_mode(): Sync tsf fail\n");
2787 		goto exit;
2788 	}
2789 	sync_info->source = client_role->macid;
2790 	sync_info->target = ap_role->macid;
2791 	sync_info->sync_en = true;
2792 	if (RTW_PHL_STATUS_SUCCESS != _mcc_calculate_start_tsf(phl, en_info)) {
2793 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_info_for_ap_client_mode(): calculate start tsf fail\n");
2794 		goto exit;
2795 	}
2796 	status = RTW_PHL_STATUS_SUCCESS;
2797 exit:
2798 	return status;
2799 }
2800 
2801 /*
2802  * |         Wifi slot          |          BT slot         |
2803  * <tob_r> Bcn_r <toa_r>
2804 **/
_mcc_fill_info_for_ap_bt_mode(struct phl_info_t * phl,struct phl_mcc_info * minfo)2805 enum rtw_phl_status _mcc_fill_info_for_ap_bt_mode(
2806 			struct phl_info_t *phl, struct phl_mcc_info *minfo)
2807 {
2808 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2809 	struct rtw_phl_mcc_en_info *en_info = &minfo->en_info;
2810 	struct rtw_phl_mcc_role *role_ref = get_ref_role(en_info);
2811 	struct rtw_phl_mcc_pattern *m_pattern = &en_info->m_pattern;
2812 
2813 	minfo->bt_info.add_bt_role = true;
2814 	en_info->mcc_intvl = role_ref->bcn_intvl;
2815 	role_ref->policy.dur_info.dur = (u8)(en_info->mcc_intvl -
2816 							minfo->bt_info.bt_dur);
2817 	m_pattern->role_ref = role_ref;
2818 	m_pattern->toa_r= role_ref->policy.dur_info.dur / 2;
2819 	m_pattern->tob_r = role_ref->policy.dur_info.dur - m_pattern->toa_r;
2820 	_mcc_fill_slot_info(m_pattern, false, role_ref->policy.dur_info.dur, role_ref);
2821 	_mcc_fill_slot_info(m_pattern, true, minfo->bt_info.bt_dur, NULL);
2822 	if (RTW_PHL_STATUS_SUCCESS != _mcc_calculate_start_tsf(phl, en_info)) {
2823 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_fill_info_for_ap_bt_mode(): calculate start tsf fail\n");
2824 		goto exit;
2825 	}
2826 	status = RTW_PHL_STATUS_SUCCESS;
2827 exit:
2828 	return status;
2829 }
2830 
_mcc_pkt_offload_for_client(struct phl_info_t * phl,u8 macid)2831 enum rtw_phl_status _mcc_pkt_offload_for_client(struct phl_info_t *phl, u8 macid)
2832 {
2833 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2834 	struct rtw_phl_stainfo_t *phl_sta = NULL;
2835 	struct rtw_pkt_ofld_null_info null_info = {0};
2836 	void *d = phl_to_drvpriv(phl);
2837 	u32 null_token = 0;
2838 
2839 	phl_sta = rtw_phl_get_stainfo_by_macid(phl, macid);
2840 	if (phl_sta == NULL) {
2841 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_pkt_offload_for_client(): get sta fail, macid(%d)\n",
2842 			macid);
2843 		goto exit;
2844 	}
2845 	if (NOT_USED != phl_pkt_ofld_get_id(phl, macid,
2846 						PKT_TYPE_NULL_DATA)) {
2847 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_pkt_offload_for_client(): macid(%d), we had already offload NULL Pkt\n",
2848 			macid);
2849 		status = RTW_PHL_STATUS_SUCCESS;
2850 		goto exit;
2851 	}
2852 	_os_mem_cpy(d, &(null_info.a1[0]), &(phl_sta->mac_addr[0]),
2853 		MAC_ADDRESS_LENGTH);
2854 	_os_mem_cpy(d,&(null_info.a2[0]), &(phl_sta->wrole->mac_addr[0]),
2855 		MAC_ADDRESS_LENGTH);
2856 	_os_mem_cpy(d, &(null_info.a3[0]), &(phl_sta->mac_addr[0]),
2857 		MAC_ADDRESS_LENGTH);
2858 	if (RTW_PHL_STATUS_SUCCESS != phl_pkt_ofld_request(phl, macid,
2859 						PKT_TYPE_NULL_DATA, &null_token,
2860 						__func__, &null_info)) {
2861 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_pkt_offload_for_client(): Pkt offload fail, macid(%d)\n",
2862 			macid);
2863 		goto exit;
2864 	}
2865 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_pkt_offload_for_client(): offload ok, macid(%d), null_token(%d)\n",
2866 		macid, null_token);
2867 	status = RTW_PHL_STATUS_SUCCESS;
2868 exit:
2869 	return status;
2870 }
2871 
2872 
_mcc_pkt_offload(struct phl_info_t * phl,struct rtw_phl_mcc_en_info * info)2873 enum rtw_phl_status _mcc_pkt_offload(struct phl_info_t *phl,
2874 					struct rtw_phl_mcc_en_info *info)
2875 {
2876 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2877 	struct rtw_phl_mcc_role *mcc_role = NULL;
2878 	u8 midx = 0;
2879 
2880 	for (midx = 0; midx < MCC_ROLE_NUM; midx++) {
2881 		if (!(info->mrole_map & BIT(midx)))
2882 			continue;
2883 		mcc_role = &info->mcc_role[midx];
2884 		if (_mcc_is_client_category(mcc_role->wrole)) {
2885 			if (RTW_PHL_STATUS_SUCCESS !=
2886 				_mcc_pkt_offload_for_client(phl,
2887 							(u8)mcc_role->macid)) {
2888 				PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_pkt_offload_for_client(): mcc_role index(%d)\n",
2889 					midx);
2890 				goto exit;
2891 			}
2892 		}
2893 	}
2894 	status = RTW_PHL_STATUS_SUCCESS;
2895 exit:
2896 	return status;
2897 }
2898 
_mcc_update_2_clients_pattern(struct phl_info_t * phl,struct phl_mcc_info * ori_minfo,struct phl_mcc_info * new_minfo)2899 enum rtw_phl_status _mcc_update_2_clients_pattern(struct phl_info_t *phl,
2900 				struct phl_mcc_info *ori_minfo,
2901 				struct phl_mcc_info *new_minfo)
2902 {
2903 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2904 
2905 	if (RTW_PHL_STATUS_SUCCESS != _mcc_fill_info_for_2_clients_mode(phl,
2906 								new_minfo)) {
2907 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_update_2_clients_pattern(): fill info fail for 2clients mode\n");
2908 		goto error;
2909 	}
2910 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_mcc_change_pattern(phl->hal,
2911 					&ori_minfo->en_info, &new_minfo->en_info,
2912 					&new_minfo->bt_info)) {
2913 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_update_2_clients_pattern(): set duration fail\n");
2914 		goto error;
2915 	}
2916 	status = RTW_PHL_STATUS_SUCCESS;
2917 	goto exit;
2918 error:
2919 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_update_2_clients_pattern(): Update fail\n");
2920 exit:
2921 	return status;
2922 }
2923 
_mcc_update_ap_client_pattern(struct phl_info_t * phl,struct phl_mcc_info * ori_minfo,struct phl_mcc_info * new_minfo)2924 enum rtw_phl_status _mcc_update_ap_client_pattern(struct phl_info_t *phl,
2925 		struct phl_mcc_info *ori_minfo, struct phl_mcc_info *new_minfo)
2926 {
2927 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2928 
2929 	if (RTW_PHL_STATUS_SUCCESS != _mcc_fill_info_for_ap_client_mode(phl,
2930 								new_minfo)) {
2931 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_update_ap_client_pattern(): fill info fail for ap client mode\n");
2932 		goto error;
2933 	}
2934 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_mcc_change_pattern(phl->hal,
2935 					&ori_minfo->en_info, &new_minfo->en_info,
2936 					&new_minfo->bt_info)) {
2937 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_update_ap_client_pattern(): set duration fail\n");
2938 		goto error;
2939 	}
2940 	if ((new_minfo->en_info.sync_tsf_info.sync_en) &&
2941 		(new_minfo->en_info.sync_tsf_info.offset !=
2942 		ori_minfo->en_info.sync_tsf_info.offset)) {
2943 		if (RTW_HAL_STATUS_SUCCESS != rtw_hal_mcc_sync_enable(phl->hal,
2944 							&new_minfo->en_info)) {
2945 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_update_ap_client_pattern(): set tsf sync fail\n");
2946 			goto error;
2947 		}
2948 	}
2949 	_mcc_up_noa(phl, new_minfo);
2950 	status = RTW_PHL_STATUS_SUCCESS;
2951 	goto exit;
2952 error:
2953 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_update_ap_client_pattern(): Update fail\n");
2954 exit:
2955 	return status;
2956 }
2957 
_mcc_update_ap_bt_pattern(struct phl_info_t * phl,struct phl_mcc_info * ori_minfo,struct phl_mcc_info * new_minfo)2958 enum rtw_phl_status _mcc_update_ap_bt_pattern(struct phl_info_t *phl,
2959 		struct phl_mcc_info *ori_minfo, struct phl_mcc_info *new_minfo)
2960 {
2961 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2962 
2963 	if (RTW_PHL_STATUS_SUCCESS != _mcc_fill_info_for_ap_bt_mode(phl,
2964 								new_minfo)) {
2965 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_update_ap_bt_pattern(): fill info fail for ap_bt\n");
2966 		goto error;
2967 	}
2968 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_mcc_change_pattern(phl->hal,
2969 					&ori_minfo->en_info, &new_minfo->en_info,
2970 					&new_minfo->bt_info)) {
2971 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_update_ap_bt_pattern(): set duration fail\n");
2972 		goto error;
2973 	}
2974 	_mcc_up_noa(phl, new_minfo);
2975 	status = RTW_PHL_STATUS_SUCCESS;
2976 	goto exit;
2977 error:
2978 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_update_ap_bt_pattern(): Update fail\n");
2979 exit:
2980 	return status;
2981 }
2982 
_mcc_duration_change(struct phl_info_t * phl,struct phl_mcc_info * minfo,struct phl_mcc_info * new_minfo)2983 enum rtw_phl_status _mcc_duration_change(struct phl_info_t *phl,
2984 		struct phl_mcc_info *minfo, struct phl_mcc_info *new_minfo)
2985 {
2986 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
2987 
2988 	if (RTW_PHL_TDMRA_AP_CLIENT_WMODE == minfo->mcc_mode) {
2989 		if (RTW_PHL_STATUS_SUCCESS != _mcc_update_ap_client_pattern(
2990 					phl, minfo, new_minfo)) {
2991 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_duration_change(): update ap_client fail\n");
2992 			goto exit;
2993 		}
2994 	} else if (RTW_PHL_TDMRA_2CLIENTS_WMODE == minfo->mcc_mode) {
2995 		if (RTW_PHL_STATUS_SUCCESS != _mcc_update_2_clients_pattern(
2996 							phl, minfo, new_minfo)) {
2997 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_duration_change(): update ap_client fail\n");
2998 			goto exit;
2999 		}
3000 	} else if (RTW_PHL_TDMRA_AP_WMODE == minfo->mcc_mode) {
3001 		if (RTW_PHL_STATUS_SUCCESS != _mcc_update_ap_bt_pattern(
3002 							phl, minfo, new_minfo)) {
3003 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_duration_change(): update ap_bt fail\n");
3004 			goto exit;
3005 		}
3006 	} else {
3007 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_duration_change(): Undefined mcc_mode(%d)\n",
3008 			minfo->mcc_mode);
3009 		goto exit;
3010 	}
3011 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_duration_change(): Update success\n");
3012 	_os_mem_cpy(phl_to_drvpriv(phl), minfo, new_minfo,
3013 			sizeof(struct phl_mcc_info));
3014 	status = RTW_PHL_STATUS_SUCCESS;
3015 exit:
3016 	return status;
3017 }
3018 
_mcc_2_clients_tracking(struct phl_info_t * phl,struct phl_mcc_info * minfo)3019 void _mcc_2_clients_tracking(struct phl_info_t *phl,
3020 				struct phl_mcc_info *minfo
3021 )
3022 {
3023 	struct rtw_phl_mcc_en_info *en_info = NULL;
3024 	struct rtw_phl_mcc_pattern *m_pattern = NULL;
3025 	struct rtw_phl_mcc_role *role_ref = NULL;
3026 	struct rtw_phl_mcc_role *role_ano = NULL;
3027 	struct phl_mcc_info new_minfo = {0};
3028 	u16 bcns_offset = 0, diff = 0, tol = 0;/*tolerance*/
3029 	bool negative_sign = false;
3030 
3031 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> _mcc_2_clients_tracking\n");
3032 	_os_mem_cpy(phl_to_drvpriv(phl), &new_minfo, minfo,
3033 			sizeof(struct phl_mcc_info));
3034 	en_info = &new_minfo.en_info;
3035 	m_pattern = &en_info->m_pattern;
3036 	role_ref = get_ref_role(en_info);
3037 	role_ano = (role_ref == &en_info->mcc_role[0]) ? &en_info->mcc_role[1] :
3038 							&en_info->mcc_role[0];
3039 	if (RTW_PHL_STATUS_SUCCESS != _mcc_get_2_clients_bcn_offset(phl,
3040 					&bcns_offset, role_ref, role_ano)) {
3041 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_2_clients_tracking(): Get bcn offset fail\n");
3042 		goto exit;
3043 	}
3044 	if (bcns_offset > m_pattern->bcns_offset) {
3045 		diff = bcns_offset - m_pattern->bcns_offset;
3046 	} else {
3047 		diff = m_pattern->bcns_offset - bcns_offset;
3048 		negative_sign = true;
3049 	}
3050 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_2_clients_tracking(): old bcns_offset(%d), new bcns_offset(%d)\n",
3051 		m_pattern->bcns_offset, bcns_offset);
3052 	_mcc_dump_pattern(m_pattern);
3053 	_mcc_dump_ref_role_info(en_info);
3054 	if (en_info->m_pattern.courtesy_i.c_en) {
3055 		tol = CLIENTS_TRACKING_COURTESY_TH;
3056 		goto decision;
3057 	}
3058 	if (en_info->mcc_intvl == WORSECASE_INTVL) {
3059 		tol = CLIENTS_TRACKING_WORSECASE_TH;
3060 		goto decision;
3061 	}
3062 	if (negative_sign) {
3063 		if (m_pattern->tob_a <= EARLY_RX_BCN_T) {
3064 			tol = CLIENTS_TRACKING_CRITICAL_POINT_TH;
3065 		} else if (m_pattern->tob_a >= (2 * EARLY_RX_BCN_T)){
3066 			tol = m_pattern->tob_a - ((3 * EARLY_RX_BCN_T) / 2);
3067 		} else {
3068 			tol = CLIENTS_TRACKING_TH;
3069 		}
3070 	} else {
3071 		if (m_pattern->toa_a <= MIN_RX_BCN_T) {
3072 			tol = CLIENTS_TRACKING_CRITICAL_POINT_TH;
3073 		} else if (m_pattern->toa_a >= (2 * MIN_RX_BCN_T)){
3074 			tol = m_pattern->toa_a - ((3 * MIN_RX_BCN_T) / 2);
3075 		} else {
3076 			tol = CLIENTS_TRACKING_TH;
3077 		}
3078 	}
3079 decision:
3080 	if (diff < tol)
3081 		goto exit;
3082 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_2_clients_tracking(): Need to update new 2clients pattern, negative_sign(%d), diff(%d), tolerance(%d), mcc_intvl(%d)\n",
3083 		negative_sign, diff, tol, en_info->mcc_intvl);
3084 	_mcc_reset_minfo(phl, &new_minfo, MINFO_RESET_BT_INFO |
3085 						MINFO_RESET_PATTERN_INFO);
3086 	/*fill original bt slot*/
3087 	_mcc_fill_bt_dur(phl, &new_minfo);
3088 	/*get original wifi time slot*/
3089 	_mcc_fill_mcc_role_policy_info(phl, role_ref->wrole, role_ref);
3090 	_mcc_fill_mcc_role_policy_info(phl, role_ano->wrole, role_ano);
3091 	if (RTW_PHL_STATUS_SUCCESS != _mcc_update_2_clients_pattern(phl,
3092 							minfo, &new_minfo)) {
3093 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_2_clients_tracking(): update 2clients fail\n");
3094 		goto exit;
3095 	}
3096 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_2_clients_tracking(): update new pattern ok\n");
3097 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_2_clients_tracking(): old pattern:\n");
3098 	_mcc_dump_pattern(&en_info->m_pattern);
3099 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "_mcc_2_clients_tracking(): new pattern:\n");
3100 	_mcc_dump_pattern(&new_minfo.en_info.m_pattern);
3101 	_os_mem_cpy(phl_to_drvpriv(phl), minfo, &new_minfo,
3102 			sizeof(struct phl_mcc_info));
3103 exit:
3104 	return;
3105 }
3106 
rtw_phl_mcc_ap_bt_coex_enable(struct phl_info_t * phl,struct rtw_wifi_role_t * cur_role)3107 enum rtw_phl_status rtw_phl_mcc_ap_bt_coex_enable(struct phl_info_t *phl,
3108 				struct rtw_wifi_role_t *cur_role)
3109 {
3110 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3111 	struct phl_mcc_info *minfo = NULL;
3112 	struct rtw_phl_mcc_en_info *en_info = NULL;
3113 	struct hw_band_ctl_t *band_ctrl = get_band_ctrl(phl, cur_role->hw_band);
3114 
3115 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_mcc_ap_bt_coex_enable(): cur_role->type(%d)\n",
3116 		cur_role->type);
3117 	if (!is_mcc_init(phl)) {
3118 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_ap_bt_coex_enable(): mcc is not init, please check code\n");
3119 		goto exit;
3120 	}
3121 	minfo = get_mcc_info(phl, cur_role->hw_band);
3122 	en_info = &minfo->en_info;
3123 	if (MCC_NONE != minfo->state && MCC_STOP != minfo->state) {
3124 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_ap_bt_coex_enable(): (MCC_NONE != minfo->state || MCC_STOP != minfo->state(%d)), please check code flow\n",
3125 			minfo->state);
3126 		_mcc_dump_state(&minfo->state);
3127 		goto exit;
3128 	}
3129 	_mcc_set_state(minfo, MCC_CFG_EN_INFO);
3130 	_mcc_reset_minfo(phl, minfo, (MINFO_RESET_EN_INFO | MINFO_RESET_MODE |
3131 				MINFO_RESET_ROLE_MAP | MINFO_RESET_COEX_MODE |
3132 				MINFO_RESET_BT_INFO));
3133 	if (RTW_PHL_STATUS_SUCCESS != _mcc_get_role_map(phl, band_ctrl,
3134 							&minfo->role_map)) {
3135 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_ap_bt_coex_enable(): Get role map failed\n");
3136 		goto _cfg_info_fail;
3137 	}
3138 	if (RTW_PHL_STATUS_SUCCESS != _mcc_transfer_mode(phl, minfo,
3139 							minfo->role_map)) {
3140 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_ap_bt_coex_enable(): transfer mcc mode failed\n");
3141 		goto _cfg_info_fail;
3142 	}
3143 	if (RTW_PHL_TDMRA_AP_WMODE != minfo->mcc_mode) {
3144 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_ap_bt_coex_enable(): error  wmode\n");
3145 		_mcc_dump_mode(&minfo->mcc_mode);
3146 		goto _cfg_info_fail;
3147 	}
3148 	if (RTW_PHL_STATUS_SUCCESS != _mcc_fill_role_info(phl, en_info,
3149 						minfo->role_map, cur_role)) {
3150 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_ap_bt_coex_enable(): fill role info failed\n");
3151 		goto _cfg_info_fail;
3152 	}
3153 	_mcc_fill_coex_mode(phl, minfo);
3154 	_mcc_fill_bt_dur(phl, minfo);
3155 	if (RTW_PHL_STATUS_SUCCESS != _mcc_get_mrole_idx_by_wrole(minfo,
3156 					cur_role, &en_info->ref_role_idx)) {
3157 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_ap_bt_coex_enable(): fill ref_role idx failed\n");
3158 		goto _cfg_info_fail;
3159 	}
3160 	if (RTW_PHL_STATUS_SUCCESS != _mcc_fill_info_for_ap_bt_mode(phl, minfo)) {
3161 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_ap_bt_coex_enable(): fill ref_role idx failed\n");
3162 		goto _cfg_info_fail;
3163 	}
3164 	_mcc_set_state(minfo, MCC_TRIGGER_FW_EN);
3165 	if (rtw_hal_mcc_enable(phl->hal, en_info, &minfo->bt_info,
3166 				minfo->mcc_mode) != RTW_HAL_STATUS_SUCCESS) {
3167 		_mcc_set_state(minfo, MCC_FW_EN_FAIL);
3168 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_ap_bt_coex_enable(): Enable FW mcc Fail\n");
3169 		goto exit;
3170 	}
3171 	_mcc_set_state(minfo, MCC_RUNING);
3172 	PHL_TRACE(COMP_PHL_MCC, _PHL_ALWAYS_, "rtw_phl_mcc_ap_bt_coex_enable(): Enable FW mcc ok\n");
3173 	_mcc_up_noa(phl, minfo);
3174 	_mcc_dump_mcc_info(minfo);
3175 	_mcc_up_fw_log_setting(phl, minfo);
3176 	status = RTW_PHL_STATUS_SUCCESS;
3177 	goto exit;
3178 _cfg_info_fail:
3179 	_mcc_set_state(minfo, MCC_NONE);
3180 exit:
3181 	PHL_TRACE(COMP_PHL_MCC, _PHL_ALWAYS_, "<<< rtw_phl_mcc_ap_bt_coex_enable():status(%d)\n",
3182 		status);
3183 	return status;
3184 }
3185 
rtw_phl_mcc_go_bt_coex_disable(struct phl_info_t * phl,struct rtw_wifi_role_t * spec_role)3186 enum rtw_phl_status rtw_phl_mcc_go_bt_coex_disable(struct phl_info_t *phl,
3187 				struct rtw_wifi_role_t *spec_role)
3188 {
3189 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3190 	struct phl_mcc_info *minfo = NULL;
3191 	struct rtw_phl_mcc_en_info *en_info = NULL;
3192 	struct rtw_phl_mcc_role *m_role = NULL;
3193 
3194 	if (!is_mcc_init(phl)) {
3195 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_go_bt_coex_disable(): mcc is not init, please check code\n");
3196 		goto exit;
3197 	}
3198 	minfo = get_mcc_info(phl, spec_role->hw_band);
3199 	en_info = &minfo->en_info;
3200 	if (MCC_RUNING != minfo->state) {
3201 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_go_bt_coex_disable(): MCC_RUNING != m_info->state, please check code flow\n");
3202 		_mcc_dump_state(&minfo->state);
3203 		goto exit;
3204 	}
3205 	if (NULL == (m_role = _mcc_get_mrole_by_wrole(minfo, spec_role))) {
3206 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_go_bt_coex_disable(): Can't get mrole, wrole id(%d), please check code flow\n",
3207 			spec_role->id);
3208 		goto exit;
3209 	}
3210 	_mcc_set_state(minfo, MCC_TRIGGER_FW_DIS);
3211 	if (rtw_hal_mcc_disable(phl->hal, m_role->group, m_role->macid,
3212 				minfo->mcc_mode) != RTW_HAL_STATUS_SUCCESS) {
3213 		status = RTW_PHL_STATUS_FAILURE;
3214 		_mcc_set_state(minfo, MCC_FW_DIS_FAIL);
3215 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_,"rtw_phl_mcc_go_bt_coex_disable(): Disable FW mcc Fail\n");
3216 		goto exit;
3217 	}
3218 	rtw_hal_sync_cur_ch(phl->hal, spec_role->hw_band, spec_role->chandef);
3219 	_mcc_set_state(minfo, MCC_STOP);
3220 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_go_bt_coex_disable(): Disable FW mcc ok\n");
3221 	_mcc_clean_noa(phl, en_info);
3222 	status = RTW_PHL_STATUS_SUCCESS;
3223 exit:
3224 	PHL_TRACE(COMP_PHL_MCC, _PHL_ALWAYS_, "<<< rtw_phl_mcc_go_bt_coex_disable(): status(%d)\n",
3225 		status);
3226 	return status;
3227 }
3228 
rtw_phl_mcc_watchdog(struct phl_info_t * phl,u8 band_idx)3229 void rtw_phl_mcc_watchdog(struct phl_info_t *phl, u8 band_idx)
3230 {
3231 	struct phl_mcc_info *minfo = NULL;
3232 
3233 	if (!is_mcc_init(phl)) {
3234 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_watchdog(): mcc is not init, please check code\n");
3235 		goto exit;
3236 	}
3237 	minfo = get_mcc_info(phl, band_idx);
3238 	if (MCC_RUNING != minfo->state)
3239 		goto exit;
3240 
3241 	if (RTW_PHL_TDMRA_2CLIENTS_WMODE == minfo->mcc_mode)
3242 		_mcc_2_clients_tracking(phl, minfo);
3243 
3244 exit:
3245 	return;
3246 }
3247 
rtw_phl_mcc_duration_change(struct phl_info_t * phl,struct phl_tdmra_dur_change_info * info)3248 enum rtw_phl_status rtw_phl_mcc_duration_change(struct phl_info_t *phl,
3249 			struct phl_tdmra_dur_change_info *info)
3250 {
3251 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3252 	struct phl_mcc_info *minfo = get_mcc_info(phl, info->hw_band);
3253 	struct phl_mcc_info new_minfo = {0};
3254 	struct rtw_phl_mcc_role *spec_mrole = NULL;
3255 
3256 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_mcc_duration_change\n");
3257 	_os_mem_cpy(phl_to_drvpriv(phl), &new_minfo, minfo,
3258 			sizeof(struct phl_mcc_info));
3259 	_mcc_set_unspecific_dur(&new_minfo);
3260 	spec_mrole = _mcc_get_mrole_by_wrole(&new_minfo, info->role);
3261 	if (NULL == spec_mrole) {
3262 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_duration_change(): Can't get mrole by wrole(%d), please check code flow\n",
3263 			info->role->id);
3264 		goto exit;
3265 	}
3266 	spec_mrole->policy.dur_info.dur = info->dur;
3267 	if (RTW_PHL_STATUS_SUCCESS != _mcc_duration_change(phl, minfo,
3268 								&new_minfo)) {
3269 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_duration_change(): Change fail\n");
3270 		goto exit;
3271 	}
3272 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_duration_change(): Change success\n");
3273 	status = RTW_PHL_STATUS_SUCCESS;
3274 	_mcc_dump_mcc_info(&new_minfo);
3275 exit:
3276 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "<<< rtw_phl_mcc_duration_change\n");
3277 	return status;
3278 }
3279 
rtw_phl_mcc_bt_duration_change(struct phl_info_t * phl,struct phl_tdmra_dur_change_info * info)3280 enum rtw_phl_status rtw_phl_mcc_bt_duration_change(struct phl_info_t *phl,
3281 				struct phl_tdmra_dur_change_info *info)
3282 {
3283 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3284 	struct phl_mcc_info *minfo = get_mcc_info(phl, info->hw_band);
3285 	struct phl_mcc_info new_minfo = {0};
3286 	struct rtw_phl_mcc_en_info *en_info = NULL;
3287 	struct rtw_phl_mcc_role *mrole = NULL;
3288 	u8 midx = 0;
3289 	bool exist_2g = false;
3290 
3291 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_mcc_bt_duration_change(): dur(%d)\n",
3292 		info->dur);
3293 	if (info->dur == minfo->bt_info.bt_dur) {
3294 		status = RTW_PHL_STATUS_SUCCESS;
3295 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "rtw_phl_mcc_bt_duration_change(): no change of bt slot(%d), skip it\n",
3296 			info->dur);
3297 		goto exit;
3298 	}
3299 	_os_mem_cpy(phl_to_drvpriv(phl), &new_minfo, minfo,
3300 			sizeof(struct phl_mcc_info));
3301 	en_info = &new_minfo.en_info;
3302 	_mcc_reset_minfo(phl, &new_minfo, MINFO_RESET_BT_INFO |
3303 						MINFO_RESET_PATTERN_INFO);
3304 	_mcc_fill_bt_dur(phl, &new_minfo);
3305 	/*fill original wifi time slot*/
3306 	for (midx = 0; midx < en_info->mrole_num; midx++) {
3307 		if (!(en_info->mrole_map & BIT(midx)))
3308 			continue;
3309 		mrole = &en_info->mcc_role[midx];
3310 		_mcc_fill_mcc_role_policy_info(phl, mrole->wrole, mrole);
3311 		if (mrole->chandef->band == BAND_ON_24G)
3312 			exist_2g = true;
3313 	}
3314 	if (false == exist_2g) {
3315 		status = RTW_PHL_STATUS_SUCCESS;
3316 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "rtw_phl_mcc_bt_duration_change(): All 5G, Don't care BT duration\n");
3317 		goto exit;
3318 	}
3319 	if (RTW_PHL_STATUS_SUCCESS != _mcc_duration_change(phl, minfo,
3320 								&new_minfo)) {
3321 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_bt_duration_change(): Change fail\n");
3322 		goto exit;
3323 	}
3324 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_bt_duration_change(): Change success\n");
3325 	status = RTW_PHL_STATUS_SUCCESS;
3326 	_mcc_dump_mcc_info(&new_minfo);
3327 exit:
3328 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "<<< rtw_phl_mcc_bt_duration_change(): status(%d)\n",
3329 		status);
3330 	return status;
3331 }
3332 
rtw_phl_mcc_dur_lim_change(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole,struct phl_mcc_dur_lim_req_info * lim_req)3333 enum rtw_phl_status rtw_phl_mcc_dur_lim_change(struct phl_info_t *phl,
3334 				struct rtw_wifi_role_t *wrole,
3335 				struct phl_mcc_dur_lim_req_info *lim_req)
3336 {
3337 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3338 	struct phl_mcc_info *minfo = NULL;
3339 	struct phl_mcc_info new_minfo = {0};
3340 	struct rtw_phl_mcc_en_info *en_info = NULL;
3341 	struct rtw_phl_mcc_role *spec_mrole = NULL;
3342 	struct rtw_phl_mcc_role *mrole = NULL;
3343 	u8 midx = 0;
3344 
3345 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_mcc_dur_lim_change()\n");
3346 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "_mcc_fill_dur_lim_info(): dur_req: tag(%d), enable(%d), start_t_h(0x%08x), start_t_l(0x%08x), dur(%d), intvl(%d)\n",
3347 		lim_req->tag, lim_req->enable, lim_req->start_t_h,
3348 		lim_req->start_t_l, lim_req->dur, lim_req->intvl);
3349 
3350 	if (!is_mcc_init(phl)) {
3351 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_dur_lim_change(): mcc is not init, please check code\n");
3352 		goto exit;
3353 	}
3354 	minfo = get_mcc_info(phl, wrole->hw_band);
3355 	if (MCC_RUNING != minfo->state) {
3356 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_dur_lim_change(): MCC_RUNING != minfo->state, , please check code flow\n");
3357 		_mcc_dump_state(&minfo->state);
3358 		goto exit;
3359 	}
3360 	_os_mem_cpy(phl_to_drvpriv(phl), &new_minfo, minfo,
3361 			sizeof(struct phl_mcc_info));
3362 	spec_mrole = _mcc_get_mrole_by_wrole(&new_minfo, wrole);
3363 	if (NULL == spec_mrole) {
3364 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_dur_lim_change(): Can't get mrole by wrole(%d), please check code flow\n",
3365 			wrole->id);
3366 		goto exit;
3367 	}
3368 	en_info = &new_minfo.en_info;
3369 	/*fill original bt slot*/
3370 	_mcc_reset_minfo(phl, &new_minfo, MINFO_RESET_BT_INFO |
3371 						MINFO_RESET_PATTERN_INFO);
3372 	_mcc_fill_bt_dur(phl, &new_minfo);
3373 	/*fill original wifi time slot*/
3374 	for (midx = 0; midx < en_info->mrole_num; midx++) {
3375 		if (!(en_info->mrole_map & BIT(midx)))
3376 			continue;
3377 		mrole = &en_info->mcc_role[midx];
3378 		_mcc_fill_mcc_role_policy_info(phl, mrole->wrole, mrole);
3379 	}
3380 	_mcc_fill_dur_lim_info(phl, spec_mrole, lim_req);
3381 	if (RTW_PHL_STATUS_SUCCESS != _mcc_duration_change(phl, minfo,
3382 								&new_minfo)) {
3383 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_dur_lim_change(): Change fail\n");
3384 		goto exit;
3385 	}
3386 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_dur_lim_change(): Change success\n");
3387 	status = RTW_PHL_STATUS_SUCCESS;
3388 exit:
3389 	return status;
3390 }
3391 
rtw_phl_mcc_sta_entry_change(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole)3392 void rtw_phl_mcc_sta_entry_change(struct phl_info_t *phl,
3393 					struct rtw_wifi_role_t *wrole)
3394 {
3395 	struct phl_mcc_info *minfo = NULL;
3396 	struct rtw_phl_mcc_role *mrole = NULL;
3397 
3398 	if (!is_mcc_init(phl)) {
3399 		goto exit;
3400 	}
3401 	minfo = get_mcc_info(phl, wrole->hw_band);
3402 	if (MCC_RUNING != minfo->state) {
3403 		goto exit;
3404 	}
3405 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, ">>> rtw_phl_mcc_sta_entry_change\n");
3406 	minfo = get_mcc_info(phl, wrole->hw_band);
3407 	if (NULL == (mrole = _mcc_get_mrole_by_wrole(minfo, wrole))) {
3408 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_sta_entry_change(): Can't get mrole, wrole id(%d), please check code flow\n",
3409 			wrole->id);
3410 		goto exit;
3411 	}
3412 	_mcc_fill_macid_bitmap_by_role(phl, mrole);
3413 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_mcc_update_macid_bitmap(
3414 					phl->hal, mrole->group,
3415 					mrole->macid, &mrole->used_macid)) {
3416 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_sta_entry_change(): Update macid map fail\n");
3417 		goto exit;
3418 	}
3419 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_notify_mcc_macid(phl->hal,
3420 	                                                       mrole,
3421 	                                                       minfo->mcc_mode)) {
3422 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_sta_entry_change(): Notify macid map fail\n");
3423 	}
3424 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_sta_entry_change(): Update macid map ok\n");
3425 	_mcc_dump_mcc_info(minfo);
3426 exit:
3427 	return;
3428 }
3429 
phl_mcc_client_link_notify_for_ap(struct phl_info_t * phl,struct rtw_wifi_role_t * wrole,enum role_state state)3430 void phl_mcc_client_link_notify_for_ap(struct phl_info_t *phl,
3431 			struct rtw_wifi_role_t *wrole, enum role_state state)
3432 {
3433 	struct phl_mcc_info *minfo = NULL;
3434 	struct rtw_phl_mcc_role *mrole = NULL;
3435 
3436 	if (state != PHL_ROLE_MSTS_STA_CONN_START &&
3437 		state != PHL_ROLE_MSTS_STA_DIS_CONN)
3438 		goto exit;
3439 	if (!is_mcc_init(phl)) {
3440 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s(): mcc is not init, please check code\n",
3441 			__func__);
3442 		goto exit;
3443 	}
3444 	minfo = get_mcc_info(phl, wrole->hw_band);
3445 	if (MCC_RUNING != minfo->state) {
3446 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s(): MCC_RUNING != minfo->state\n",
3447 			__func__);
3448 		_mcc_dump_state(&minfo->state);
3449 		goto exit;
3450 	}
3451 	if (NULL == (mrole = _mcc_get_mrole_by_wrole(minfo, wrole))) {
3452 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s(): Can't get mrole, wrole id(%d), please check code flow\n",
3453 			__func__, wrole->id);
3454 		goto exit;
3455 	}
3456 	_mcc_fill_macid_bitmap_by_role(phl, mrole);
3457 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_mcc_update_macid_bitmap(
3458 					phl->hal, mrole->group,
3459 					mrole->macid, &mrole->used_macid)) {
3460 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s(): Update macid map fail\n",
3461 			__func__);
3462 		goto exit;
3463 	}
3464 	if (RTW_HAL_STATUS_SUCCESS != rtw_hal_notify_mcc_macid(phl->hal,
3465 	                                                       mrole,
3466 	                                                       minfo->mcc_mode)) {
3467 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_client_link_notify_for_ap(): Notify macid map fail\n");
3468 	}
3469 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s(): Update macid map ok\n",
3470 		__func__);
3471 	_mcc_dump_mcc_info(minfo);
3472 exit:
3473 	return;
3474 }
3475 
rtw_phl_mcc_inprogress(struct phl_info_t * phl,u8 band_idx)3476 bool rtw_phl_mcc_inprogress(struct phl_info_t *phl, u8 band_idx)
3477 {
3478 	bool ret = false;
3479 	struct phl_mcc_info *minfo = NULL;
3480 
3481 	if (!is_mcc_init(phl)) {
3482 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_inprogress(): mcc is not init, please check code\n");
3483 		goto exit;
3484 	}
3485 	minfo = get_mcc_info(phl, band_idx);
3486 	if (MCC_TRIGGER_FW_EN == minfo->state || MCC_RUNING == minfo->state ||
3487 		MCC_TRIGGER_FW_DIS == minfo->state ||
3488 		MCC_FW_DIS_FAIL == minfo->state) {
3489 		ret = true;
3490 	}
3491 exit:
3492 	return ret;
3493 }
3494 
_is_mcc_sts_err(struct phl_info_t * phl,u8 band_idx)3495 static bool _is_mcc_sts_err(struct phl_info_t *phl, u8 band_idx)
3496 {
3497 	bool ret = false;
3498 	struct phl_mcc_info *minfo = NULL;
3499 
3500 	if (!is_mcc_init(phl)) {
3501 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_,
3502 			"%s(): mcc is not init, please check code\n",
3503 			__func__);
3504 		goto exit;
3505 	}
3506 	minfo = get_mcc_info(phl, band_idx);
3507 	if (MCC_FW_DIS_FAIL == minfo->state ||
3508 		MCC_FW_EN_FAIL == minfo->state) {
3509 		ret = true;
3510 	}
3511 exit:
3512 	return ret;
3513 }
3514 
rtw_phl_mcc_reset(struct phl_info_t * phl,u8 band_idx)3515 enum rtw_phl_status rtw_phl_mcc_reset(struct phl_info_t *phl,
3516 					u8 band_idx)
3517 {
3518 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3519 	struct rtw_phl_mcc_en_info *en_info = NULL;
3520 	struct phl_mcc_info *minfo = NULL;
3521 
3522 	FUNCIN();
3523 	if (!is_mcc_init(phl)) {
3524 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_,
3525 			"%s(): mcc is not init, please check code\n",
3526 			__func__);
3527 		goto exit;
3528 	}
3529 	minfo = get_mcc_info(phl, band_idx);
3530 	en_info = &minfo->en_info;
3531 
3532 	/* Reset mcc */
3533 	rtw_hal_mcc_reset(phl->hal, en_info->group, minfo->mcc_mode);
3534 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_,
3535 		"%s(): reset mcc group(%d) complete\n",
3536 		__func__, en_info->group);
3537 	/* Reset state */
3538 	_mcc_set_state(minfo, MCC_NONE);
3539 
3540 	if (minfo->mcc_mode == RTW_PHL_TDMRA_AP_CLIENT_WMODE ||
3541 		minfo->mcc_mode == RTW_PHL_TDMRA_AP_WMODE)
3542 		_mcc_clean_noa(phl, en_info);
3543 	status = RTW_PHL_STATUS_SUCCESS;
3544 exit:
3545 	return status;
3546 }
3547 
rtw_phl_mcc_recovery(struct phl_info_t * phl,u8 band_idx)3548 enum rtw_phl_status rtw_phl_mcc_recovery(struct phl_info_t *phl,
3549 					u8 band_idx)
3550 {
3551 	enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
3552 
3553 	if (_is_mcc_sts_err(phl, band_idx)) {
3554 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_,
3555 			"%s: err status detected, try to reset mcc.\n",
3556 			__func__);
3557 		rtw_phl_mcc_reset(phl, band_idx);
3558 	}
3559 
3560 	return status;
3561 }
3562 
3563 /* Enable Fw MCC
3564  * @cur_role: the role in the current ch.
3565  */
rtw_phl_mcc_enable(struct phl_info_t * phl,struct rtw_wifi_role_t * cur_role)3566 enum rtw_phl_status rtw_phl_mcc_enable(struct phl_info_t *phl,
3567 					struct rtw_wifi_role_t *cur_role)
3568 {
3569 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3570 	struct phl_mcc_info *minfo = NULL;
3571 	struct rtw_phl_mcc_en_info *en_info = NULL;
3572 	struct hw_band_ctl_t *band_ctrl = get_band_ctrl(phl, cur_role->hw_band);
3573 	u8 role_map = 0;
3574 
3575 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_mcc_enable(): cur_role->type(%d)\n",
3576 		cur_role->type);
3577 	if (!is_mcc_init(phl)) {
3578 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): mcc is not init, please check code\n");
3579 		goto exit;
3580 	}
3581 	minfo = get_mcc_info(phl, cur_role->hw_band);
3582 	en_info = &minfo->en_info;
3583 	if (MCC_NONE != minfo->state && MCC_STOP != minfo->state) {
3584 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): (MCC_NONE != minfo->state || MCC_STOP != minfo->state(%d)), please check code flow\n",
3585 			minfo->state);
3586 		_mcc_dump_state(&minfo->state);
3587 		goto exit;
3588 	}
3589 	_mcc_set_state(minfo, MCC_CFG_EN_INFO);
3590 	if (RTW_PHL_STATUS_SUCCESS != _mcc_get_role_map(phl, band_ctrl,
3591 							&role_map)) {
3592 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): Get role map failed\n");
3593 		goto _cfg_info_fail;
3594 	}
3595 	_mcc_reset_minfo(phl, minfo, (MINFO_RESET_EN_INFO | MINFO_RESET_MODE |
3596 				MINFO_RESET_ROLE_MAP | MINFO_RESET_COEX_MODE |
3597 				MINFO_RESET_BT_INFO));
3598 	minfo->role_map = role_map;
3599 	if (RTW_PHL_STATUS_SUCCESS != _mcc_transfer_mode(phl, minfo,
3600 							role_map)) {
3601 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): transfer mcc mode failed\n");
3602 		goto _cfg_info_fail;
3603 	}
3604 	if (RTW_PHL_STATUS_SUCCESS != _mcc_fill_role_info(phl, en_info,
3605 							role_map, cur_role)) {
3606 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): fill role info failed\n");
3607 		goto _cfg_info_fail;
3608 	}
3609 	_mcc_fill_coex_mode(phl, minfo);
3610 	_mcc_fill_bt_dur(phl, minfo);
3611 	if (RTW_PHL_STATUS_SUCCESS != _mcc_get_mrole_idx_by_wrole(minfo,
3612 					cur_role, &en_info->ref_role_idx)) {
3613 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): fill ref_role idx failed\n");
3614 		goto _cfg_info_fail;
3615 	}
3616 	if (minfo->mcc_mode == RTW_PHL_TDMRA_AP_CLIENT_WMODE) {
3617 		if (RTW_PHL_STATUS_SUCCESS !=
3618 			_mcc_fill_info_for_ap_client_mode(phl, minfo)) {
3619 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): fill info failed for ap_client mode\n");
3620 			goto _cfg_info_fail;
3621 		}
3622 	} else if (minfo->mcc_mode == RTW_PHL_TDMRA_2CLIENTS_WMODE){
3623 		if (RTW_PHL_STATUS_SUCCESS !=
3624 			_mcc_fill_info_for_2_clients_mode(phl, minfo)) {
3625 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): fill info failed for 2clients mode\n");
3626 			goto _cfg_info_fail;
3627 		}
3628 	} else {
3629 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): Undefined mcc_mode(%d)\n",
3630 			minfo->mcc_mode);
3631 		goto _cfg_info_fail;
3632 	}
3633 	_mcc_dump_mcc_info(minfo);
3634 	if (RTW_PHL_STATUS_SUCCESS != _mcc_pkt_offload(phl, en_info)) {
3635 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): pkt offload Fail\n");
3636 		goto _cfg_info_fail;
3637 	}
3638 	_mcc_set_state(minfo, MCC_TRIGGER_FW_EN);
3639 	if (rtw_hal_mcc_enable(phl->hal, en_info, &minfo->bt_info,
3640 				minfo->mcc_mode) != RTW_HAL_STATUS_SUCCESS) {
3641 		_mcc_set_state(minfo, MCC_FW_EN_FAIL);
3642 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_enable(): Enable FW mcc Fail\n");
3643 		goto exit;
3644 	}
3645 	_mcc_set_state(minfo, MCC_RUNING);
3646 	PHL_TRACE(COMP_PHL_MCC, _PHL_ALWAYS_, "rtw_phl_mcc_enable(): Enable FW mcc ok\n");
3647 	if (minfo->mcc_mode == RTW_PHL_TDMRA_AP_CLIENT_WMODE)
3648 		_mcc_up_noa(phl, minfo);
3649 	_mcc_dump_mcc_info(minfo);
3650 	_mcc_up_fw_log_setting(phl, minfo);
3651 	status = RTW_PHL_STATUS_SUCCESS;
3652 	goto exit;
3653 _cfg_info_fail:
3654 	_mcc_set_state(minfo, MCC_NONE);
3655 exit:
3656 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "<<< rtw_phl_mcc_enable():status(%d)\n",
3657 		status);
3658 	return status;
3659 }
3660 
3661 /*
3662  * Stop fw mcc
3663  * @ spec_role: You want to fw switch ch to the specific ch of the role when fw stop mcc
3664  */
rtw_phl_mcc_disable(struct phl_info_t * phl,struct rtw_wifi_role_t * spec_role)3665 enum rtw_phl_status rtw_phl_mcc_disable(struct phl_info_t *phl,
3666 					struct rtw_wifi_role_t *spec_role)
3667 {
3668 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3669 	struct phl_mcc_info *minfo = NULL;
3670 	struct rtw_phl_mcc_en_info *en_info = NULL;
3671 	struct rtw_phl_mcc_role *m_role = NULL;
3672 
3673 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_mcc_disable()\n");
3674 	if (!is_mcc_init(phl)) {
3675 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_disable(): mcc is not init, please check code\n");
3676 		goto exit;
3677 	}
3678 	minfo = get_mcc_info(phl, spec_role->hw_band);
3679 	en_info = &minfo->en_info;
3680 	if (MCC_RUNING != minfo->state) {
3681 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_disable(): MCC_RUNING != m_info->state, please check code flow\n");
3682 		_mcc_dump_state(&minfo->state);
3683 		goto exit;
3684 	}
3685 	if (NULL == (m_role = _mcc_get_mrole_by_wrole(minfo, spec_role))) {
3686 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_disable(): Can't get mrole, wrole id(%d), please check code flow\n",
3687 			spec_role->id);
3688 		goto exit;
3689 	}
3690 	_mcc_set_state(minfo, MCC_TRIGGER_FW_DIS);
3691 	if (rtw_hal_mcc_disable(phl->hal, m_role->group, m_role->macid,
3692 				minfo->mcc_mode) != RTW_HAL_STATUS_SUCCESS) {
3693 		status = RTW_PHL_STATUS_FAILURE;
3694 		_mcc_set_state(minfo, MCC_FW_DIS_FAIL);
3695 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_,"rtw_phl_mcc_disable(): Disable FW mcc Fail\n");
3696 		goto exit;
3697 	}
3698 	rtw_hal_sync_cur_ch(phl->hal, spec_role->hw_band, spec_role->chandef);
3699 	_mcc_set_state(minfo, MCC_STOP);
3700 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_disable(): Disable FW mcc ok\n");
3701 	if (minfo->mcc_mode == RTW_PHL_TDMRA_AP_CLIENT_WMODE)
3702 		_mcc_clean_noa(phl, en_info);
3703 	status = RTW_PHL_STATUS_SUCCESS;
3704 exit:
3705 	return status;
3706 }
3707 
3708 
rtw_phl_tdmra_duration_change(struct phl_info_t * phl,struct phl_tdmra_dur_change_info * info)3709 enum rtw_phl_status rtw_phl_tdmra_duration_change(struct phl_info_t *phl,
3710 			struct phl_tdmra_dur_change_info *info)
3711 {
3712 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3713 	struct phl_mcc_info *minfo = NULL;
3714 	struct rtw_phl_mcc_en_info *en_info = NULL;
3715 
3716 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_tdmra_duration_change()\n");
3717 	if (!is_mcc_init(phl)) {
3718 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_tdmra_duration_change(): mcc is not init, please check code\n");
3719 		goto exit;
3720 	}
3721 	minfo = get_mcc_info(phl, info->hw_band);
3722 	en_info = &minfo->en_info;
3723 	if (MCC_RUNING != minfo->state) {
3724 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_tdmra_duration_change(): MCC_RUNING != m_info->state, please check code flow\n");
3725 		_mcc_dump_state(&minfo->state);
3726 		goto exit;
3727 	}
3728 	if (true == info->bt_role) {
3729 		status = rtw_phl_mcc_bt_duration_change(phl, info);
3730 	} else {
3731 		status = rtw_phl_mcc_duration_change(phl, info);
3732 	}
3733 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "<<< rtw_phl_tdmra_duration_change(): status(%d)\n",
3734 		status);
3735 exit:
3736 	return status;
3737 }
3738 
rtw_phl_tdmra_enable(struct phl_info_t * phl,struct rtw_wifi_role_t * cur_role)3739 enum rtw_phl_status rtw_phl_tdmra_enable(struct phl_info_t *phl,
3740 				struct rtw_wifi_role_t *cur_role)
3741 {
3742 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3743 	struct hw_band_ctl_t *band_ctrl = get_band_ctrl(phl, cur_role->hw_band);
3744 	struct mr_info *cur_info = &band_ctrl->cur_info;
3745 	u8 chanctx_num = 0;
3746 
3747 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_tdmra_enable\n");
3748 	chanctx_num = (u8)phl_mr_get_chanctx_num(phl, band_ctrl);
3749 	if (2 == chanctx_num) {
3750 		status = rtw_phl_mcc_enable(phl, cur_role);
3751 	} else if (1 == chanctx_num) {
3752 		if ((1 == cur_info->ap_num || 1 == cur_info->p2p_go_num) &&
3753 		   (cur_info->ld_sta_num == 0 || cur_info->lg_sta_num == 0)) {
3754 			status = rtw_phl_mcc_ap_bt_coex_enable(phl, cur_role);
3755 		} else {
3756 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_tdmra_enable(): Not support this type\n");
3757 			PHL_DUMP_MR_EX(phl);
3758 		}
3759 	} else {
3760 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_tdmra_enable(): Not support for chanctx_num(%d)\n",
3761 			chanctx_num);
3762 	}
3763 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "<<< rtw_phl_tdmra_enable(): status(%d)\n",
3764 		status);
3765 	return status;
3766 }
3767 
3768 /*
3769  * Stop tdmra
3770  * @ spec_role: You want to fw switch ch to the specific ch of the role when fw stop tdma
3771  */
rtw_phl_tdmra_disable(struct phl_info_t * phl,struct rtw_wifi_role_t * spec_role)3772 enum rtw_phl_status rtw_phl_tdmra_disable(struct phl_info_t *phl,
3773 				struct rtw_wifi_role_t *spec_role)
3774 {
3775 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3776 	struct phl_mcc_info *minfo = NULL;
3777 	struct rtw_phl_mcc_en_info *en_info = NULL;
3778 	struct rtw_phl_mcc_role *m_role = NULL;
3779 
3780 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_tdmra_disable()\n");
3781 	if (!is_mcc_init(phl)) {
3782 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_tdmra_disable(): mcc is not init, please check code\n");
3783 		goto exit;
3784 	}
3785 	minfo = get_mcc_info(phl, spec_role->hw_band);
3786 	en_info = &minfo->en_info;
3787 	if (MCC_RUNING != minfo->state) {
3788 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_tdmra_disable(): MCC_RUNING != m_info->state, please check code flow\n");
3789 		_mcc_dump_state(&minfo->state);
3790 		goto exit;
3791 	}
3792 	if (NULL == (m_role = _mcc_get_mrole_by_wrole(minfo, spec_role))) {
3793 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_tdmra_disable(): Can't get mrole, wrole id(%d), please check code flow\n",
3794 			spec_role->id);
3795 		#ifdef RTW_WKARD_TDMRA_AUTO_GET_STAY_ROLE
3796 		m_role = get_ref_role(en_info);
3797 		if (m_role == NULL) {
3798 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s(): Can't get mrole from ref_mrole, please check code flow\n",
3799 				__func__);
3800 			goto exit;
3801 		} else {
3802 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "%s(): Workaround get mrore from ref_mrole\n",
3803 				__func__);
3804 		}
3805 		#else
3806 		goto exit;
3807 		#endif /* RTW_WKARD_TDMRA_AUTO_GET_STAY_ROLE */
3808 	}
3809 	_mcc_set_state(minfo, MCC_TRIGGER_FW_DIS);
3810 	if (rtw_hal_mcc_disable(phl->hal, m_role->group, m_role->macid,
3811 				minfo->mcc_mode) != RTW_HAL_STATUS_SUCCESS) {
3812 		status = RTW_PHL_STATUS_FAILURE;
3813 		_mcc_set_state(minfo, MCC_FW_DIS_FAIL);
3814 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_,"rtw_phl_tdmra_disable(): Disable FW mcc Fail\n");
3815 		goto exit;
3816 	}
3817 	rtw_hal_sync_cur_ch(phl->hal, m_role->wrole->hw_band, *m_role->chandef);
3818 	_mcc_set_state(minfo, MCC_STOP);
3819 	PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_tdmra_disable(): Disable FW mcc ok\n");
3820 	if (minfo->mcc_mode == RTW_PHL_TDMRA_AP_CLIENT_WMODE ||
3821 		minfo->mcc_mode == RTW_PHL_TDMRA_AP_WMODE)
3822 		_mcc_clean_noa(phl, en_info);
3823 	status = RTW_PHL_STATUS_SUCCESS;
3824 exit:
3825 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "<<< rtw_phl_tdmra_disable(): status(%d)\n",
3826 		status);
3827 	return status;
3828 }
3829 
rtw_phl_mcc_init_ops(struct phl_info_t * phl,struct rtw_phl_mcc_ops * ops)3830 enum rtw_phl_status rtw_phl_mcc_init_ops(struct phl_info_t *phl, struct rtw_phl_mcc_ops *ops)
3831 {
3832 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3833 	struct phl_com_mcc_info *com_info = NULL;
3834 
3835 	if (!is_mcc_init(phl)) {
3836 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_init_ops(): mcc is not init, please check code\n");
3837 		goto exit;
3838 	}
3839 	com_info = phl_to_com_mcc_info(phl);
3840 	com_info->ops.priv = ops->priv;
3841 	com_info->ops.mcc_update_noa = ops->mcc_update_noa;
3842 	com_info->ops.mcc_get_setting = ops->mcc_get_setting;
3843 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "rtw_phl_mcc_init_ops(): init ok\n");
3844 	status = RTW_PHL_STATUS_SUCCESS;
3845 exit:
3846 	return status;
3847 }
3848 
rtw_phl_mcc_init(struct phl_info_t * phl)3849 enum rtw_phl_status rtw_phl_mcc_init(struct phl_info_t *phl)
3850 {
3851 	enum rtw_phl_status status = RTW_PHL_STATUS_FAILURE;
3852 	struct rtw_phl_com_t *phl_com = phl->phl_com;
3853 	void *drv = phl_to_drvpriv(phl);
3854 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
3855 	struct hw_band_ctl_t *band_ctrl = NULL;
3856 	u8 band_idx = 0;
3857 
3858 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_mcc_init()\n");
3859 	set_mcc_init_state(phl, false);
3860 	if (mr_ctl->com_mcc == NULL) {
3861 		mr_ctl->com_mcc = _os_mem_alloc(drv, sizeof(struct phl_com_mcc_info));
3862 		if (mr_ctl->com_mcc != NULL) {
3863 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "rtw_phl_mcc_init(): Allocate phl_com_mcc_info\n");
3864 		} else {
3865 			PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_init(): Allocate phl_com_mcc_info Fail\n");
3866 			goto deinit;
3867 		}
3868 	}
3869 	for (band_idx = 0; band_idx < MAX_BAND_NUM; band_idx++) {
3870 		band_ctrl = &mr_ctl->band_ctrl[band_idx];
3871 		if (band_ctrl->mcc_info == NULL) {
3872 			band_ctrl->mcc_info = _os_mem_alloc(drv,
3873 						sizeof(struct phl_mcc_info));
3874 			if (band_ctrl->mcc_info != NULL) {
3875 				PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "rtw_phl_mcc_init(): Allocate mcc_info for HW Band(%d)\n",
3876 					band_idx);
3877 			} else {
3878 				PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_init(): Allocate mcc_info fail for HW Band(%d)\n",
3879 					band_idx);
3880 				goto deinit;
3881 			}
3882 		}
3883 	}
3884 	set_mcc_init_state(phl, true);
3885 	status = RTW_PHL_STATUS_SUCCESS;
3886 	goto exit;
3887 deinit:
3888 	rtw_phl_mcc_deinit(phl);
3889 exit:
3890 	return status;
3891 }
3892 
rtw_phl_mcc_deinit(struct phl_info_t * phl)3893 void rtw_phl_mcc_deinit(struct phl_info_t *phl)
3894 {
3895 	struct rtw_phl_com_t *phl_com = phl->phl_com;
3896 	void *drv = phl_to_drvpriv(phl);
3897 	struct phl_com_mcc_info *com_info = phl_to_com_mcc_info(phl);
3898 	struct mr_ctl_t *mr_ctl = phlcom_to_mr_ctrl(phl_com);
3899 	struct hw_band_ctl_t *band_ctrl = NULL;
3900 	u8 band_idx = 0;
3901 
3902 	PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, ">>> rtw_phl_mcc_deinit()\n");
3903 	if (com_info != NULL) {
3904 		_os_mem_free(drv, com_info, sizeof(struct phl_com_mcc_info));
3905 		PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "rtw_phl_mcc_deinit(): Free phl_com_mcc_info\n");
3906 	}
3907 	for (band_idx = 0; band_idx < MAX_BAND_NUM; band_idx++) {
3908 		band_ctrl = &mr_ctl->band_ctrl[band_idx];
3909 		if (band_ctrl->mcc_info != NULL) {
3910 			_os_mem_free(drv, band_ctrl->mcc_info,
3911 						sizeof(struct phl_mcc_info));
3912 			PHL_TRACE(COMP_PHL_MCC, _PHL_INFO_, "rtw_phl_mcc_deinit(): Free phl_mcc_info, HwBand(%d)\n",
3913 				band_idx);
3914 		}
3915 	}
3916 	set_mcc_init_state(phl, false);
3917 }
3918 
rtw_phl_mcc_get_dbg_info(struct phl_info_t * phl,u8 band_idx,enum rtw_phl_mcc_dbg_type type,void * info)3919 bool rtw_phl_mcc_get_dbg_info(struct phl_info_t *phl, u8 band_idx,
3920 				enum rtw_phl_mcc_dbg_type type, void *info)
3921 {
3922 	bool get_ok = false;
3923 	struct phl_mcc_info *minfo = NULL;
3924 	struct rtw_phl_mcc_en_info *en_info = NULL;
3925 
3926 	if (!is_mcc_init(phl)) {
3927 		PHL_TRACE(COMP_PHL_MCC, _PHL_ERR_, "rtw_phl_mcc_get_dbg_info(): mcc is not init, please check code\n");
3928 		goto exit;
3929 	}
3930 	minfo = get_mcc_info(phl, band_idx);
3931 	en_info = &minfo->en_info;
3932 
3933 	if (MCC_DBG_STATE == type) {
3934 		*(enum rtw_phl_mcc_state *)info = minfo->state;
3935 	} else if (MCC_DBG_OP_MODE == type) {
3936 		*(enum rtw_phl_tdmra_wmode *)info = minfo->mcc_mode;
3937 	} else if (MCC_DBG_COEX_MODE == type) {
3938 		*(enum rtw_phl_mcc_coex_mode *)info = minfo->coex_mode;
3939 	} else if (MCC_DBG_BT_INFO == type) {
3940 		_os_mem_cpy(phl_to_drvpriv(phl), info, &minfo->bt_info,
3941 				sizeof(struct rtw_phl_mcc_bt_info));
3942 	} else if (MCC_DBG_EN_INFO == type) {
3943 		_os_mem_cpy(phl_to_drvpriv(phl), info, en_info,
3944 				sizeof(struct rtw_phl_mcc_en_info));
3945 	} else {
3946 		goto exit;
3947 	}
3948 	get_ok = true;
3949 
3950 exit:
3951 	return get_ok;
3952 }
3953 
3954 
3955 #endif /* CONFIG_MCC_SUPPORT */
3956