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, ¶m)) {
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, ¶m);
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, ¶m))
830 goto exit;
831 } else if (RTW_PHL_TDMRA_AP_WMODE == minfo->mcc_mode) {
832 if (false == _tdmra_calc_noa_1wrole(phl, minfo, ¶m))
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, ¶m);
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