1 /******************************************************************************
2 *
3 * Copyright(c) 2019 - 2020 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 #include "phl_headers.h"
16
__reset_snd_grp(struct phl_snd_grp * grp)17 void __reset_snd_grp(struct phl_snd_grp *grp)
18 {
19 u8 i = 0;
20
21 grp->snd_type = PHL_SND_TYPE_INVALID;
22 grp->band = 0;
23 grp->num_sta = 0;
24 grp->wrole_idx = 0;
25 grp->grp_tier = PHL_SND_GRP_TIER_1;
26 grp->snd_sts = PHL_SND_STS_PENDING;
27 for (i = 0; i < MAX_NUM_STA_SND_GRP; i++) {
28 grp->sta[i].valid = false;
29 grp->sta[i].macid = 0;
30 grp->sta[i].bw = CHANNEL_WIDTH_20;
31 grp->sta[i].snd_fb_t = PHL_SND_FB_TYPE_SU;
32 grp->sta[i].npda_sta_info = 0;
33 grp->sta[i].bf_entry = NULL;
34 grp->sta[i].snd_sts = PHL_SND_STS_PENDING;
35 }
36 }
37
_phl_snd_init_snd_grp(struct phl_info_t * phl_info)38 enum rtw_phl_status _phl_snd_init_snd_grp(
39 struct phl_info_t *phl_info)
40 {
41 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
42 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
43 struct phl_sound_param *param = &snd->snd_param;
44 u8 i = 0;
45 do {
46 if (param->snd_grp == NULL) {
47 status = RTW_PHL_STATUS_FAILURE;
48 break;
49 }
50 for (i = 0; i < MAX_SND_GRP_NUM; i++) {
51 __reset_snd_grp(¶m->snd_grp[i]);
52 param->snd_grp[i].gidx = i;
53 }
54 } while (0);
55
56 return status;
57 }
58 #ifdef CONFIG_FSM
59 /* For EXTERNAL application to create Sound object */
60 /* @fsm: FSM main structure which created by phl_snd_new_fsm()
61 * @phl_info: private data structure to invoke hal/phl function
62 *
63 * return
64 */
phl_snd_new_obj(struct fsm_main * fsm,struct phl_info_t * phl_info)65 enum rtw_phl_status phl_snd_new_obj(
66 struct fsm_main *fsm,
67 struct phl_info_t *phl_info)
68 {
69 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
70 struct phl_sound_obj *snd_obj = NULL;
71 struct fsm_obj *obj = NULL;
72 void *drv_priv = phl_to_drvpriv(phl_info);
73 FUNCIN();
74
75 do {
76 snd_obj = phl_fsm_new_obj(
77 fsm, (void **)&obj, sizeof(*snd_obj));
78
79 if (snd_obj == NULL) {
80 status = RTW_PHL_STATUS_RESOURCE;
81 break;
82 }
83 phl_info->snd_obj = snd_obj;
84
85 snd_obj->fsm = fsm;
86 snd_obj->fsm_obj = obj;
87 snd_obj->phl_info = phl_info;
88
89 /*Init the snd group static resources here*/
90 status = _phl_snd_init_snd_grp(phl_info);
91
92 /* init obj local use variable */
93 PHL_INFO("snd_fsm_func_init_st_hdl : PHL SND FSM Module Start Work\n");
94 _os_spinlock_init(drv_priv, &snd_obj->snd_lock);
95 _os_spinlock_init(drv_priv, &snd_obj->cmd_lock);
96 phl_snd_func_snd_init(snd_obj->phl_info);
97
98 } while (0);
99
100 if (RTW_PHL_STATUS_SUCCESS != status) {
101 PHL_ERR("phl_snd_init_obj FAIL\n");
102 /* phl fsm module will handle to free the phl fsm related object*/
103 /* phl_snd_deinit_obj(phl_info); */
104 }
105
106 FUNCOUT();
107 return status;
108 }
109 #endif
110
111 /* PHL SOUND EXTERNAL APIs */
112 /* get sounding in progress */
rtw_phl_snd_chk_in_progress(void * phl)113 u8 rtw_phl_snd_chk_in_progress(void *phl)
114 {
115 u8 ret = 0;
116 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
117 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
118 void *d = phl_to_drvpriv(phl_info);
119
120 _os_spinlock(d, &snd->snd_lock, _bh, NULL);
121 ret = snd->snd_in_progress;
122 _os_spinunlock(d, &snd->snd_lock, _bh, NULL);
123
124 return ret;
125 }
126
127 /**
128 * rtw_phl_sound_start
129 * @phl:(struct phl_info_t *)
130 * @st_dlg_tkn: start dialog token value, if 0, it will use previous sounding dialog token;
131 * @period: sounding process period (group--> next group)
132 * @test_flag: test mode flags
133 **/
134 enum rtw_phl_status
rtw_phl_sound_start(void * phl,u8 wrole_idx,u8 st_dlg_tkn,u8 period,u8 test_flag)135 rtw_phl_sound_start(void *phl, u8 wrole_idx, u8 st_dlg_tkn, u8 period, u8 test_flag)
136 {
137 #ifdef CONFIG_FSM
138 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
139 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
140 struct phl_snd_start_req snd_req;
141
142 snd_req.wrole = (void *)rtw_phl_get_wrole_by_ridx(phl_info->phl_com, wrole_idx);
143
144 snd_req.dialog_token = (st_dlg_tkn == 0) ?
145 snd->snd_param.snd_dialog_token : st_dlg_tkn;
146 snd_req.proc_timeout_ms = SND_PROC_DEFAULT_TIMEOUT; /* Default Value */
147 snd_req.proc_period = (period > SND_PROC_DEFAULT_PERIOD) ?
148 SND_PROC_DEFAULT_PERIOD : period; /*MAX = Default Value */
149 snd_req.test_flag = test_flag;
150 if (test_flag&PHL_SND_TEST_F_PASS_STS_CHK)
151 snd_req.bypass_sts_chk = true;
152 else
153 snd_req.bypass_sts_chk = false; /* Default False */
154
155 return phl_snd_fsm_ev_start_func(phl, &snd_req);
156 #else
157 return RTW_PHL_STATUS_FAILURE;
158 #endif
159 }
160
161 enum rtw_phl_status
rtw_phl_sound_down_ev(void * phl)162 rtw_phl_sound_down_ev(void *phl)
163 {
164 enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
165
166 #ifdef CONFIG_FSM
167 status = phl_snd_fsm_ev_c2h_snd_down(phl);
168 #else
169 status = RTW_PHL_STATUS_FAILURE;
170 #endif
171 return status;
172 }
173
174
175 enum rtw_phl_status
rtw_phl_sound_abort(void * phl)176 rtw_phl_sound_abort(void *phl)
177 {
178 #ifdef CONFIG_FSM
179 return phl_snd_fsm_ev_abort(phl);
180 #else
181 return RTW_PHL_STATUS_FAILURE;
182 #endif
183 }
184
185 /* set fixed mode parameters APIs*/
rtw_phl_snd_dump_fix_para(struct phl_info_t * phl_info)186 void rtw_phl_snd_dump_fix_para(struct phl_info_t *phl_info)
187 {
188 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
189 struct phl_snd_fix_param *para = NULL;
190 u8 i = 0;
191
192 para = &snd->snd_param.fix_param;
193 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "===> rtw_phl_snd_fix_dump_para \n");
194
195 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "test_flag = 0x%x \n", snd->snd_param.test_flag);
196
197 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "en_fix_gidx = %d \n", para->en_fix_gidx ? 1 : 0);
198 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "en_fix_fb_type = %d \n", para->en_fix_fb_type ? 1 : 0);
199 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "en_fix_sta = %d \n", para->en_fix_sta ? 1 : 0);
200 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "en_fix_snd_bw = %d \n", para->en_fix_snd_bw ? 1 : 0);
201
202 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "grp_idx = %d \n", para->grp_idx);
203 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "snd_fb_type = %d \n", para->snd_fb_type);
204
205 for (i = 0; i < MAX_NUM_STA_SND_GRP; i++) {
206 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "sta_macid[i] = 0x%x \n", para->sta_macid[i]);
207 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "bw[i] = %d \n",para->bw[i]);
208 }
209
210 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "<=== rtw_phl_snd_fix_dump_para \n");
211 }
212 /* fixed group idx */
rtw_phl_snd_fix_gidx(struct phl_info_t * phl_info,bool en,u8 gidx)213 void rtw_phl_snd_fix_gidx(struct phl_info_t *phl_info, bool en, u8 gidx)
214 {
215 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
216 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "rtw_phl_snd_fix_gidx() set sounding gidx = 0x%x\n", gidx);
217 if (en) {
218 snd->snd_param.fix_param.en_fix_gidx = 1;
219 snd->snd_param.fix_param.grp_idx = gidx;
220 } else {
221 snd->snd_param.fix_param.en_fix_gidx = 0;
222 }
223 }
224 /* fixed snd feedback type */
rtw_phl_snd_fix_snd_fb_type(struct phl_info_t * phl_info,bool en,enum snd_fb_type fb_type)225 void rtw_phl_snd_fix_snd_fb_type(struct phl_info_t *phl_info,
226 bool en, enum snd_fb_type fb_type)
227 {
228 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
229 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "rtw_phl_snd_fix_gidx() set sounding fb_type = 0x%x\n",
230 fb_type);
231 if (en) {
232 snd->snd_param.fix_param.en_fix_fb_type = 1;
233 snd->snd_param.fix_param.snd_fb_type = fb_type;
234 } else {
235 snd->snd_param.fix_param.en_fix_fb_type = 0;
236 }
237 }
238
239 /* fixed sounding sta macids */
rtw_phl_snd_fix_set_sta(struct phl_info_t * phl_info,bool en,u8 sidx,u16 macid)240 void rtw_phl_snd_fix_set_sta(struct phl_info_t *phl_info,
241 bool en, u8 sidx, u16 macid)
242 {
243 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
244 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "rtw_phl_snd_fix_set_sta() set sta[%d] macid = 0x%x\n",
245 sidx, macid);
246 if (en) {
247 snd->snd_param.fix_param.en_fix_sta = 1;
248 if (sidx < MAX_NUM_STA_SND_GRP)
249 snd->snd_param.fix_param.sta_macid[sidx] = macid;
250 else
251 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "ERROR, sidx >= 4\n");
252 } else {
253 snd->snd_param.fix_param.en_fix_sta = 0;
254 }
255 }
256
257 /* fixed sounding sta bw */
rtw_phl_snd_fix_set_bw(struct phl_info_t * phl_info,bool en,u8 sidx,enum channel_width bw)258 void rtw_phl_snd_fix_set_bw(struct phl_info_t *phl_info,
259 bool en, u8 sidx, enum channel_width bw)
260 {
261 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
262 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "rtw_phl_snd_fix_set_bw() set sta[%d] bw = 0x%x\n", sidx, bw);
263 if (en) {
264 snd->snd_param.fix_param.en_fix_snd_bw = 1;
265 if (sidx < MAX_NUM_STA_SND_GRP)
266 snd->snd_param.fix_param.bw[sidx] = bw;
267 else
268 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "ERROR, sidx >= 4\n");
269 } else {
270 snd->snd_param.fix_param.en_fix_snd_bw = 0;
271 }
272 }
273
274 /* set forced fw tx mu-mimo (forced fw tx decision) */
rtw_phl_snd_fix_tx_he_mu(struct phl_info_t * phl_info,u8 gid,bool en)275 void rtw_phl_snd_fix_tx_he_mu(struct phl_info_t *phl_info, u8 gid, bool en)
276 {
277 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "rtw_phl_snd_fix_tx_mu_para()\n");
278
279 rtw_hal_bf_set_txmu_para(phl_info->hal, gid, en,
280 HAL_PROT_NO_PROETCT, HAL_ACK_N_USER_BA);
281
282 rtw_hal_bf_set_fix_mode(phl_info->hal, gid, en);
283 }
284
285
286 /* PHL SOUND INTERNAL APIs */
287 /* SND FUNC */
288 enum rtw_phl_status
phl_snd_func_snd_init(struct phl_info_t * phl_info)289 phl_snd_func_snd_init(struct phl_info_t *phl_info)
290 {
291 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
292 void *d = phl_to_drvpriv(phl_info);
293 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
294 u8 f_ru_tbl_80m[MAX_SND_HE_BFRP_USER_NUM][MAX_SND_HE_BFRP_USER_NUM] = {
295 {RTW_HE_RU996_1, RTW_HE_RU996_1, RTW_HE_RU996_1 ,RTW_HE_RU996_1},
296 {RTW_HE_RU484_1, RTW_HE_RU484_2, RTW_HE_RU996_1 ,RTW_HE_RU996_1},
297 {RTW_HE_RU484_1, RTW_HE_RU242_3, RTW_HE_RU242_4 ,RTW_HE_RU996_1},
298 {RTW_HE_RU242_1, RTW_HE_RU242_2, RTW_HE_RU242_3 ,RTW_HE_RU242_4}
299 };
300
301 u8 f_ru_tbl_20m[MAX_SND_HE_BFRP_USER_NUM][MAX_SND_HE_BFRP_USER_NUM] = {
302 {RTW_HE_RU242_1, RTW_HE_RU242_1, RTW_HE_RU242_1, RTW_HE_RU242_1},
303 {RTW_HE_RU106_1, RTW_HE_RU106_1, RTW_HE_RU242_1, RTW_HE_RU242_1},
304 {RTW_HE_RU106_1, RTW_HE_RU52_3, RTW_HE_RU52_4, RTW_HE_RU242_1},
305 {RTW_HE_RU52_1, RTW_HE_RU52_2, RTW_HE_RU52_3, RTW_HE_RU52_4}
306 };
307
308 /* Add Other Sounding FUNC/PRCO Initialization Here */
309 snd->snd_param.snd_proc_timeout_ms = SND_PROC_DEFAULT_TIMEOUT;/* ms */
310 snd->snd_param.cur_proc_grp_idx = 0;
311 snd->snd_param.pre_proc_grp_idx = 0;
312 snd->snd_param.snd_dialog_token = 1;
313 snd->snd_param.snd_func_grp_num = 0;
314 snd->snd_param.grp_used_map = 0;
315 snd->snd_param.snd_proc_period = SND_PROC_DEFAULT_PERIOD;
316 snd->snd_param.snd_fail_counter = 0;
317
318 /*fixed_ru_tbl*/
319 _os_mem_cpy(d, snd->snd_param.fix_param.f_ru_tbl_20, f_ru_tbl_20m,
320 MAX_SND_HE_BFRP_USER_NUM * MAX_SND_HE_BFRP_USER_NUM);
321 _os_mem_cpy(d, snd->snd_param.fix_param.f_ru_tbl_80, f_ru_tbl_80m,
322 MAX_SND_HE_BFRP_USER_NUM * MAX_SND_HE_BFRP_USER_NUM);
323
324 return pstatus;
325 }
326
327 enum rtw_phl_status
phl_snd_func_pre_config(struct phl_info_t * phl_info)328 phl_snd_func_pre_config(struct phl_info_t *phl_info)
329 {
330 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
331 struct phl_sound_param *snd_param = &snd->snd_param;
332 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
333 void *d = phl_to_drvpriv(phl_info);
334
335 snd_param->proc_start_time = _os_get_cur_time_ms();
336 snd_param->cur_proc_grp_idx = 0; /* default start from group idx 0 */
337 snd_param->pre_proc_grp_idx = 0;
338 _os_spinlock(d, &snd->snd_lock, _bh, NULL);
339 snd->is_terminated = 0;
340 snd->snd_in_progress = 1;
341 _os_spinunlock(d, &snd->snd_lock, _bh, NULL);
342
343 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "PHL SND FUNC Start with SND Dialog Token = 0x%x\n",
344 snd_param->snd_dialog_token);
345
346
347 return pstatus;
348 }
349
350
351 /* SND_FUNC : GROUP related */
352 /**
353 * phl_snd_proc_get_grp()
354 * get the grp(struct phl_sound_grp *) with group index.
355 * input:
356 * @gidx: group idx.
357 * return:
358 * @grp: (struct phl_snd_grp *grp), NULL = FAIL;
359 */
360 struct phl_snd_grp *
phl_snd_get_grp_byidx(struct phl_info_t * phl_info,u8 gidx)361 phl_snd_get_grp_byidx(struct phl_info_t *phl_info, u8 gidx)
362 {
363 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
364 struct phl_sound_param *snd_param = &snd->snd_param;
365 struct phl_snd_grp *grp = NULL;
366
367 do {
368 if (gidx >= MAX_SND_GRP_NUM)
369 break;
370
371 if (!(snd_param->grp_used_map & BIT(gidx)))
372 break;
373
374 if (0 == snd_param->snd_grp[gidx].num_sta)
375 break;
376
377 if (PHL_SND_TYPE_INVALID == snd_param->snd_grp[gidx].snd_type)
378 break;
379
380 grp = &snd_param->snd_grp[gidx];
381
382 } while (0);
383
384 return grp;
385 }
386
387 /**
388 * phl_snd_func_remove_grp()
389 * remove the target sounding grp from sound process;
390 * input:
391 * @grp: (struct phl_snd_grp *) target sounding grp,
392 */
393 enum rtw_phl_status
phl_snd_func_remove_grp(struct phl_info_t * phl_info,struct phl_snd_grp * grp)394 phl_snd_func_remove_grp(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
395 {
396 enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
397 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
398 struct phl_sound_param *snd_param = &snd->snd_param;
399
400 if (grp == NULL) {
401 return pstatus;
402 }
403 if (snd_param->grp_used_map & BIT(grp->gidx)) {
404
405 /* Check and Release all the BF resource */
406 pstatus = phl_snd_proc_release_res(phl_info, grp);
407 if (pstatus != RTW_PHL_STATUS_SUCCESS) {
408 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "PHL SND Remove Grp : release BF resouce fail\n");
409 }
410
411 /* Reset group content to default value */
412 __reset_snd_grp(grp);
413
414 /* Clear Group BIT */
415 snd_param->grp_used_map &= ~BIT(grp->gidx);
416 snd_param->snd_func_grp_num--;
417
418 } else {
419 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "PHL SND Remove Grp : Group is not in used!!!\n");
420 }
421
422 return pstatus;
423 }
424
425 /**
426 * phl_snd_func_remove_grp_all()
427 * remove the all of the sounding grp from sound process;
428 */
429 void
phl_snd_func_remove_grp_all(struct phl_info_t * phl_info)430 phl_snd_func_remove_grp_all(struct phl_info_t *phl_info)
431 {
432 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
433 struct phl_snd_grp *grp = NULL;
434 u8 idx = 0;
435
436 for(idx = 0; idx < MAX_SND_GRP_NUM; idx++) {
437 grp = phl_snd_get_grp_byidx(phl_info, idx);
438 if (grp != NULL) {
439 pstatus = phl_snd_func_remove_grp(phl_info, grp);
440 if (pstatus != RTW_PHL_STATUS_SUCCESS) {
441 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "Remove SND GRP[%d] Fail\n", idx);
442 }
443 }
444 }
445 }
446
447 /**
448 * _phl_snd_get_available_gidx()
449 * Get available group resource.
450 * return:
451 * @gidx: u8, the group idx in snd_param->grp[n]
452 */
_phl_snd_get_available_gidx(struct phl_sound_obj * snd)453 u8 _phl_snd_get_available_gidx(struct phl_sound_obj *snd)
454 {
455 struct phl_sound_param *param = &snd->snd_param;
456 u8 gidx = MAX_SND_GRP_NUM;
457
458 for (gidx = 0; gidx < MAX_SND_GRP_NUM; gidx++) {
459 if (!(param->grp_used_map & BIT(gidx))) {
460 param->grp_used_map |= BIT(gidx);
461 break;
462 }
463 }
464
465 return gidx;
466 }
467
468 /**
469 * _phl_snd_func_grp_add_sta()
470 * Add the STA into sounding group.
471 * input:
472 * @sta: (struct rtw_phl_stainfo_t *) the target sta to be added.
473 * the function will use the macid / bw information in sta_info;
474 * @gidx: the group idx to add
475 */
476 enum rtw_phl_status
_phl_snd_func_grp_add_sta(struct phl_info_t * phl_info,struct rtw_phl_stainfo_t * sta,u8 gidx)477 _phl_snd_func_grp_add_sta(
478 struct phl_info_t *phl_info, struct rtw_phl_stainfo_t *sta, u8 gidx)
479 {
480 enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
481 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
482 struct phl_sound_param *snd_param = &snd->snd_param;
483 struct phl_snd_grp *grp = NULL;
484 u8 i = 0;
485 bool chk = false;
486
487 do {
488
489 if (NULL == sta) {
490 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "STA == NULL !!!!\n");
491 break;
492 }
493
494 if (gidx >= MAX_SND_GRP_NUM) {
495 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "Get SND Grp Resource Fail : gidx >= MAX_SND_GRP_NUM\n");
496 break;
497 }
498
499 grp = &snd_param->snd_grp[gidx];
500
501 /* check grp->sta[i].macid with sta->macid, skip it if same.*/
502 for (i = 0; i < grp->num_sta; i++) {
503 if(grp->sta[i].macid == sta->macid) {
504 chk = true;
505 break;
506 }
507 }
508 if (true == chk)
509 break;
510
511 if (grp->num_sta >= MAX_NUM_STA_SND_GRP) {
512 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "The SND Grp is already has 4 STAs\n");
513 break;
514 }
515
516 grp->sta[grp->num_sta].macid = sta->macid;
517 grp->sta[grp->num_sta].snd_sts = PHL_SND_STS_PENDING;
518 grp->sta[grp->num_sta].bw = sta->chandef.bw;
519 grp->sta[grp->num_sta].valid = true;
520 grp->num_sta++;
521 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "sta bw = %d\n", sta->chandef.bw);
522 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "grp->num_sta = %d\n", grp->num_sta);
523
524 pstatus = RTW_PHL_STATUS_SUCCESS;
525 } while (0);
526
527 return pstatus;
528 }
529
530 /**
531 * phl_snd_func_add_snd_grp :
532 * Add a Sounding Group with Primary STA for FW Sounding
533 * @phl_info: struct phl_info_t *
534 * @he_snd: 1 = HE , 0 =VHT
535 * @gidx: return value, snd group idxx in group list
536 * @psta: (struct rtw_phl_stainfo_t *)Primary Sounding STA,
537 * if pSTA is unavailable , SND PROC for this group will be terminated.
538 **/
539 enum rtw_phl_status
phl_snd_func_add_snd_grp(struct phl_info_t * phl_info,bool he_snd,u8 wrole_idx,struct rtw_phl_stainfo_t * psta,u8 * gidx)540 phl_snd_func_add_snd_grp(
541 struct phl_info_t *phl_info, bool he_snd,
542 u8 wrole_idx, struct rtw_phl_stainfo_t *psta, u8 *gidx)
543 {
544 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
545 struct phl_sound_param *snd_param = &snd->snd_param;
546 struct phl_snd_grp *grp = NULL;
547 enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
548
549 do {
550 /* Check Primary STA Available*/
551 if (psta == NULL) {
552 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "psta == NULL\n");
553 break;
554 }
555
556 /* Get available sounding group resource */
557 *gidx = _phl_snd_get_available_gidx(snd);
558 if (*gidx >= MAX_SND_GRP_NUM) {
559 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "Get SND Grp Resource Fail : gidx >= MAX_SND_GRP_NUM\n");
560 break;
561 }
562
563 grp = &(snd_param->snd_grp[*gidx]);
564 grp->band = psta->wrole->hw_band;
565 grp->snd_type = he_snd ? PHL_SND_TYPE_HE_SW :
566 PHL_SND_TYPE_VHT_SW;
567 grp->wrole_idx = wrole_idx;
568 grp->snd_sts = PHL_SND_STS_PENDING;
569 grp->num_sta = 0;
570
571 /* Primary STA use idx-0 */
572 _phl_snd_func_grp_add_sta(phl_info, psta, *gidx);
573
574 snd_param->snd_func_grp_num++;
575
576 pstatus = RTW_PHL_STATUS_SUCCESS;
577
578 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "phl_snd_func_add_snd_grp : Add group[%d] Success\n",
579 *gidx);
580 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "phl_snd_func_add_snd_grp : grp->snd_type 0x%x\n",
581 grp->snd_type);
582
583 } while (0);
584
585 return pstatus;
586 }
587
588 /**
589 * _phl_snd_func_set_grp_fb_mu()
590 * Set the whole sounding grp's feedback type = MU
591 * input:
592 * @grp: (struct phl_snd_grp *) the target group.
593 */
_phl_snd_func_set_grp_fb_mu(struct phl_snd_grp * grp)594 void _phl_snd_func_set_grp_fb_mu(struct phl_snd_grp *grp)
595 {
596 u8 i = 0;
597 if (grp == NULL)
598 return;
599 for (i = 0; i < grp->num_sta; i++) {
600 grp->sta[i].snd_fb_t = PHL_SND_FB_TYPE_MU;
601 }
602 }
603
604 /**
605 * phl_snd_func_grouping()
606 * function for soundind fsm state : SND_FUNC_READY
607 * input:
608 * @wroleidx: the index of wrole which the sounding proc run under with.
609 */
610 enum rtw_phl_status
phl_snd_func_grouping(struct phl_info_t * phl_info,u8 wroleidx)611 phl_snd_func_grouping(struct phl_info_t *phl_info, u8 wroleidx)
612 {
613 enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
614 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
615 struct phl_sound_param *snd_param = &snd->snd_param;
616 struct phl_snd_fix_param *fix_para = &snd->snd_param.fix_param;
617 struct rtw_wifi_role_t *wrole = NULL;
618 struct rtw_phl_stainfo_t *self = NULL, *sta;
619 struct phl_snd_grp *grp = NULL;
620 void *drv = phl_to_drvpriv(phl_info);
621 struct phl_queue *sta_queue;
622 u8 gidx = 0;
623 u8 cnt = 0;
624
625 wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, wroleidx);
626
627 /* if wrole(STA) is linked, seft = AP */
628 /* if wrole is AP, self = ???? */
629 self = rtw_phl_get_stainfo_self(phl_info, wrole);
630 if (self == NULL) {
631 PHL_ERR("Cannot get self's phl_sta\n");
632 return pstatus;
633 }
634 sta_queue = &wrole->assoc_sta_queue;
635 if (PHL_RTYPE_STATION == wrole->type) {
636 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, " PHL_RTYPE_STATION == wrole->type \n");
637 /* STA Mode : Only SU TxBF with AP */
638
639 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "self->macid = 0x%x \n", self->macid);
640 debug_dump_mac_address(self->mac_addr);
641
642 pstatus = phl_snd_func_add_snd_grp(
643 phl_info,
644 (self->wmode & WLAN_MD_11AX) ? true :
645 false,
646 wrole->id, self, &gidx);
647 grp = &snd_param->snd_grp[gidx];
648 grp->grp_tier = PHL_SND_GRP_TIER_0;
649 grp->sta[0].snd_fb_t = PHL_SND_FB_TYPE_SU;
650 grp->snd_type = (self->wmode & WLAN_MD_11AX) ?
651 PHL_SND_TYPE_HE_HW : PHL_SND_TYPE_VHT_HW;
652 } else {
653 #if 1
654 /* Test Code: Group-1 :Forced MU Sounding with first 1~4 STAs */
655 /* the mu sounding list shall get from mu grouping module */
656 cnt = 0;
657 _os_spinlock(drv, &sta_queue->lock, _bh, NULL);
658 phl_list_for_loop(sta, struct rtw_phl_stainfo_t,
659 &wrole->assoc_sta_queue.queue, list) {
660 if (is_broadcast_mac_addr(sta->mac_addr))
661 continue;
662 if (sta == self)
663 continue;
664 /* First STA */
665 if (cnt == 0) {
666 pstatus = phl_snd_func_add_snd_grp(
667 phl_info,
668 (sta->wmode & WLAN_MD_11AX) ?
669 true : false,
670 wrole->id, sta, &gidx);
671 if (pstatus != RTW_PHL_STATUS_SUCCESS)
672 break;
673 } else {
674 /* get next associated sta and add to group */
675 _phl_snd_func_grp_add_sta(phl_info, sta, gidx);
676 }
677 cnt++;
678 if (cnt >= 4)
679 break;
680 }
681 _os_spinunlock(drv, &sta_queue->lock, _bh, NULL);
682 if(pstatus != RTW_PHL_STATUS_SUCCESS)
683 return RTW_PHL_STATUS_FAILURE;
684 grp = &snd_param->snd_grp[gidx];
685 grp->grp_tier = PHL_SND_GRP_TIER_0;
686 /* Test : forced MU */
687 _phl_snd_func_set_grp_fb_mu(&snd_param->snd_grp[gidx]);
688 #endif
689 }
690
691 /*TODO: fixed paramters gidx when multi-group */
692 if (snd_param->test_flag&PHL_SND_TEST_F_GRP_SND_PARA) {
693 /*Test Mode force set the group fb type = MU */
694 if (fix_para->en_fix_fb_type) {
695 if (PHL_SND_FB_TYPE_MU == fix_para->snd_fb_type) {
696 _phl_snd_func_set_grp_fb_mu(
697 &snd_param->snd_grp[gidx]);
698 }
699 /**
700 * Note : 8852A only support two CSI Buffer for SU,
701 * take care that num of STA in SU sounding of a group shall < 2.
702 **/
703 }
704
705 if(fix_para->en_fix_snd_bw) {
706 grp = &snd_param->snd_grp[gidx];
707 for (cnt = 0; cnt < MAX_NUM_STA_SND_GRP; cnt++) {
708 if (grp->sta[cnt].valid)
709 grp->sta[cnt].bw = fix_para->bw[cnt];
710 }
711 }
712 } else {
713 grp = &snd_param->snd_grp[gidx];
714 if (grp->num_sta > 2) {
715 /* forced using MU feedback because of SU CSI buffer number */
716 _phl_snd_func_set_grp_fb_mu(&snd_param->snd_grp[gidx]);
717 }
718 }
719
720 if (snd_param->test_flag & PHL_SND_TEST_F_GRP_EN_BF_FIX) {
721 snd_param->snd_grp[gidx].en_fix_mode = 1; /* post confg forced mode setting */
722 }
723 return pstatus;
724
725 }
726
727 /* SND PROC */
728
729 /* Free BF/CQI resource */
730 enum rtw_phl_status
_phl_snd_proc_release_res_cqi(struct phl_info_t * phl_info,struct phl_snd_grp * grp)731 _phl_snd_proc_release_res_cqi(
732 struct phl_info_t *phl_info, struct phl_snd_grp *grp)
733 {
734 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
735
736 /*CQI Fb doesn't query any resource*/
737
738 return pstatus;
739 }
740
741 enum rtw_phl_status
_phl_snd_proc_release_res_bf(struct phl_info_t * phl_info,struct phl_snd_grp * grp)742 _phl_snd_proc_release_res_bf(
743 struct phl_info_t *phl_info, struct phl_snd_grp *grp)
744 {
745 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
746 enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
747 struct phl_snd_sta *snd_sta;
748 struct rtw_phl_stainfo_t *sta = NULL;
749 u8 idx = 0;
750
751 for (idx = 0; idx < grp->num_sta; idx++) {
752 snd_sta = &grp->sta[idx];
753 if(0 == snd_sta->valid)
754 continue;
755
756 sta = rtw_phl_get_stainfo_by_macid(
757 phl_info, snd_sta->macid);
758 if (NULL == sta) {
759 PHL_ERR("_phl_snd_proc_release_res_bf: Cannot find STA macid 0x%x in PHL STA Info List \n",
760 snd_sta->macid);
761 continue;
762 }
763 if (NULL == sta->hal_sta->bf_entry)
764 continue;
765
766 hstatus = rtw_hal_snd_release_proc_sta_res(phl_info->hal, sta);
767 if(hstatus != RTW_HAL_STATUS_SUCCESS) {
768 PHL_ERR("_phl_snd_proc_release_res_bf: macid 0x%x Free Sounding Resource FAIL \n",
769 snd_sta->macid);
770 continue;
771 }
772 /* un link the bf entry to STA info */
773 sta->hal_sta->bf_entry = NULL;
774 }
775 return pstatus;
776 }
777 /**
778 * phl_snd_proc_release_res:
779 * Release the sounding resource for the group
780 * @phl_info: phl_info_t
781 * @grp: (struct phl_snd_grp *) sounding gorup for release resource
782 **/
783 enum rtw_phl_status
phl_snd_proc_release_res(struct phl_info_t * phl_info,struct phl_snd_grp * grp)784 phl_snd_proc_release_res(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
785 {
786 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
787 struct phl_snd_sta *snd_sta;
788 snd_sta = &grp->sta[0];
789 if (snd_sta->snd_fb_t == PHL_SND_FB_TYPE_CQI)
790 pstatus = _phl_snd_proc_release_res_cqi(phl_info, grp);
791 else
792 pstatus = _phl_snd_proc_release_res_bf(phl_info, grp);
793
794 return pstatus;
795 }
796
797 /**
798 * _phl_snd_proc_get_bf_res_cqi_fb:
799 * CQI Sounding doesn't need BF Reresource
800 * @phl_info: phl_info_t
801 * @grp: (struct phl_sound_grp *) sounding gorup
802 * @nsta: return value : how many sta query resource success
803 **/
804 enum rtw_phl_status
_phl_snd_proc_get_res_cqi_fb(struct phl_info_t * phl_info,struct phl_snd_grp * grp,u8 * nsta)805 _phl_snd_proc_get_res_cqi_fb(
806 struct phl_info_t *phl_info, struct phl_snd_grp *grp, u8 *nsta)
807 {
808 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
809 struct phl_snd_sta *snd_sta;
810 u8 idx = 0;
811 struct rtw_phl_stainfo_t *sta = NULL;
812
813 *nsta = 0;
814
815 for (idx = 0; idx < grp->num_sta; idx++) {
816 snd_sta = &grp->sta[idx];
817 sta = rtw_phl_get_stainfo_by_macid(phl_info, snd_sta->macid);
818 if (NULL == sta) {
819 PHL_ERR("phl_snd_proc_get_bf_res: Cannot find STA macid 0x%x in PHL STA Info List \n",
820 snd_sta->macid);
821 continue;
822 }
823
824 rtw_hal_snd_ndpa_sta_info_he(
825 sta,
826 &snd_sta->npda_sta_info,
827 snd_sta->bw,
828 PHL_SND_FB_TYPE_CQI);
829
830 (*nsta)++;
831 }
832 if (*nsta == 0) {
833 grp->snd_sts = PHL_SND_STS_FAILURE;
834 pstatus = RTW_PHL_STATUS_FAILURE;
835 }
836 if (*nsta != grp->num_sta) {
837 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, " Sounding STAs is fewer than group sta because of resource!");
838 }
839
840 return pstatus;
841 }
842
843 /**
844 * _phl_snd_proc_get_res_bf:
845 * Get BF Resource for SU/MU Sounding
846 * @phl_info: phl_info_t
847 * @grp: (struct phl_sound_grp *) sounding gorup
848 * @nsta: return value : how many sta query bf resource success
849 **/
850 enum rtw_phl_status
_phl_snd_proc_get_res_bf(struct phl_info_t * phl_info,struct phl_snd_grp * grp,u8 * nsta)851 _phl_snd_proc_get_res_bf(
852 struct phl_info_t *phl_info, struct phl_snd_grp *grp, u8 *nsta)
853 {
854 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
855 enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
856 struct phl_snd_sta *snd_sta;
857 u8 idx = 0;
858 struct rtw_phl_stainfo_t *sta = NULL;
859 bool mu, qry_bf;
860
861 *nsta = 0;
862
863 for (idx = 0; idx < grp->num_sta; idx++) {
864 snd_sta = &grp->sta[idx];
865 sta = rtw_phl_get_stainfo_by_macid(phl_info, snd_sta->macid);
866 if (NULL == sta) {
867 PHL_ERR("phl_snd_proc_get_bf_res: Cannot find STA macid 0x%x in PHL STA Info List \n",
868 snd_sta->macid);
869 continue;
870 }
871
872 mu = (snd_sta->snd_fb_t == PHL_SND_FB_TYPE_MU) ? true:false;
873 qry_bf = false;
874 if (sta->hal_sta->bf_entry != NULL) {
875 /* The sta already have BF reource */
876 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, " sta->bf_entry != NULL\n");
877 /* Check the BF resource */
878 hstatus = rtw_hal_snd_chk_bf_res(phl_info->hal,
879 sta, mu, sta->chandef.bw);
880 if (RTW_HAL_STATUS_FAILURE == hstatus) {
881 rtw_hal_snd_release_proc_sta_res(phl_info->hal,
882 sta);
883 qry_bf = true;
884
885 } else {
886 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "Use Original BF Resource \n");
887 qry_bf = false;
888 }
889 } else {
890 qry_bf = true;
891 }
892
893 if (true == qry_bf) {
894 hstatus = rtw_hal_snd_query_proc_sta_res(
895 phl_info->hal, sta, mu, sta->chandef.bw,
896 grp->en_swap_mode);
897 if (hstatus != RTW_HAL_STATUS_SUCCESS) {
898 PHL_ERR("phl_snd_proc_get_bf_res: macid 0x%x query sounding resource FAIL \n",
899 snd_sta->macid);
900 if (grp->en_swap_mode) {
901 break;/* break in swap mode if one of sta query bf res fail */
902 }
903 continue;
904 }
905 }
906 if (grp->snd_type >= PHL_SND_TYPE_HE_HW) {
907 rtw_hal_snd_ndpa_sta_info_he(
908 sta,
909 &snd_sta->npda_sta_info,
910 snd_sta->bw,
911 snd_sta->snd_fb_t);
912 } else {
913 rtw_hal_snd_ndpa_sta_info_vht(sta,
914 &snd_sta->npda_sta_info, mu);
915 }
916
917 /* Link STA information to Group Information */
918 snd_sta->bf_entry = sta->hal_sta->bf_entry;
919
920 (*nsta)++;
921 }
922
923 if (*nsta == 0) {
924 grp->snd_sts = PHL_SND_STS_FAILURE;
925 pstatus = RTW_PHL_STATUS_FAILURE;
926 }
927 if (*nsta != grp->num_sta) {
928 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "FAIL : Sounding STAs is fewer than group sta because of resource!\n");
929 pstatus = RTW_PHL_STATUS_FAILURE;
930 }
931
932 return pstatus;
933 }
934 /* snd proc get BF/CSI resource */
935 enum rtw_phl_status
phl_snd_proc_get_res(struct phl_info_t * phl_info,struct phl_snd_grp * grp,u8 * nsta)936 phl_snd_proc_get_res(
937 struct phl_info_t *phl_info, struct phl_snd_grp *grp, u8 *nsta)
938 {
939 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
940 struct phl_snd_sta *snd_sta;
941 FUNCIN_WSTS(pstatus);
942
943 snd_sta = &grp->sta[0];
944 /* CQI Fb cannot mixed with SU/MU feedback type*/
945 if(snd_sta->snd_fb_t == PHL_SND_FB_TYPE_CQI)
946 pstatus = _phl_snd_proc_get_res_cqi_fb(phl_info, grp, nsta);
947 else
948 pstatus = _phl_snd_proc_get_res_bf(phl_info, grp, nsta);
949
950 if(pstatus != RTW_PHL_STATUS_SUCCESS)
951 grp->snd_sts = PHL_SND_STS_FAILURE;
952
953 FUNCOUT_WSTS(pstatus);
954 return pstatus;
955 }
956
957 /* 2. SND Preconfiguration */
958
959 /**
960 * _get_mu_mimo_gid_2sta()
961 * hard code for 8852A, gid relattion-ship
962 **/
_get_mu_mimo_gid_2sta(u8 primary,u8 secondary)963 static u8 _get_mu_mimo_gid_2sta(u8 primary, u8 secondary)
964 {
965 u8 gid_tbl[6][6] = { {0xFF, 1, 2, 3, 4, 5},
966 {16, 0xFF, 6, 7, 8, 9},
967 {17, 21, 0xFF, 10, 11, 12},
968 {18, 22, 25, 0xFF, 13, 14},
969 {19, 23, 26, 28, 0xFF, 15},
970 {20, 24, 27, 29, 30, 0xFF} };
971 u8 ret = 0xFF;
972
973 if ((primary < 6) && (secondary < 6))
974 ret = gid_tbl[primary][secondary];
975
976 return ret;
977 }
978 /* pre calculate mu-gid */
979 enum rtw_phl_status
phl_snd_cal_mu_grp_bitmap(struct phl_info_t * phl_info,struct phl_snd_grp * grp)980 phl_snd_cal_mu_grp_bitmap(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
981 {
982 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
983 struct rtw_phl_stainfo_t *psta_info = NULL;
984 struct rtw_phl_stainfo_t *tmp_psta_info = NULL;
985 struct phl_snd_sta *sta = NULL;
986 struct phl_snd_sta *tmp_sta = NULL;
987 u8 bfmu_idx , bfmu_idx_tmp;
988 u8 i = 0, j = 0;
989
990 for (i = 0; i < MAX_NUM_STA_SND_GRP; i++) {
991 sta = &grp->sta[i];
992 if (false == sta->valid)
993 continue;
994 /* primary STA */
995 psta_info = rtw_phl_get_stainfo_by_macid(
996 phl_info, sta->macid);
997
998 if (NULL == sta->bf_entry)
999 continue;
1000 if (false == rtw_hal_bf_chk_bf_type(phl_info->hal,
1001 psta_info, true)) {
1002 continue; /*BF SU Entry*/
1003 }
1004 /* primary STA MU Entry Idx */
1005 bfmu_idx = rtw_hal_bf_get_sumu_idx(phl_info->hal,
1006 sta->bf_entry);
1007
1008 psta_info->hal_sta->mugrp_bmp = 0; /* clear first */
1009
1010 for (j = 0; j < MAX_NUM_STA_SND_GRP; j++) {
1011 if (j == i) /* self */
1012 continue;
1013 /* secondary sta */
1014 tmp_sta = &grp->sta[j];
1015
1016 if (NULL == tmp_sta->bf_entry)
1017 continue;
1018
1019 tmp_psta_info = rtw_phl_get_stainfo_by_macid(
1020 phl_info, tmp_sta->macid);
1021
1022 if (false == rtw_hal_bf_chk_bf_type(phl_info->hal,
1023 tmp_psta_info, true)) {
1024 continue; /* BF SU Entry */
1025 }
1026
1027 /* secondary sta MU Entry Idx */
1028 bfmu_idx_tmp = rtw_hal_bf_get_sumu_idx(phl_info->hal,
1029 tmp_sta->bf_entry);
1030
1031 /* Default set group bit enable = 1 */
1032 /* grp bitmap doesn't include self */
1033 /** BIT 0 1 2 3 4
1034 * MU_0 : MU_1 MU_2 MU_3 MU_4 MU_5
1035 * MU_1 : MU_0 MU_2 MU_3 MU_4 MU_5
1036 * MU_2 : MU_0 MU_1 MU_3 MU_4 MU_5
1037 * ...
1038 * MU_5 : MU_0 MU_1 MU_2 MU_3 MU_4
1039 **/
1040
1041 if (bfmu_idx_tmp > bfmu_idx) {
1042 psta_info->hal_sta->mugrp_bmp |=
1043 BIT(bfmu_idx_tmp - 1);
1044 } else {
1045 psta_info->hal_sta->mugrp_bmp |=
1046 BIT(bfmu_idx_tmp);
1047 }
1048 }
1049 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "sta(macid = 0x%x) mugrp_bmp = 0x%x \n",
1050 psta_info->macid, psta_info->hal_sta->mugrp_bmp);
1051 }
1052
1053 return pstatus;
1054 }
1055
1056 /* Preconfiguration before souding */
1057 enum rtw_phl_status
phl_snd_proc_precfg(struct phl_info_t * phl_info,struct phl_snd_grp * grp)1058 phl_snd_proc_precfg(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
1059 {
1060 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1061 enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1062 struct phl_snd_sta *sta = NULL;
1063 u8 idx = 0;
1064 struct rtw_phl_stainfo_t *psta_info = NULL;
1065 FUNCIN_WSTS(pstatus);
1066 do {
1067 if (grp == NULL) {
1068 pstatus = RTW_PHL_STATUS_FAILURE;
1069 break;
1070 }
1071 if (PHL_SND_TYPE_INVALID == grp->snd_type) {
1072 /* both SW/HW mode need to set call halmac api to set bf entry */
1073 break;
1074 }
1075 for (idx = 0; idx < MAX_NUM_STA_SND_GRP; idx++) {
1076 sta = &grp->sta[idx];
1077 if (false == sta->valid)
1078 continue;
1079 psta_info = rtw_phl_get_stainfo_by_macid(
1080 phl_info, sta->macid);
1081
1082 /*check bf entry available and snd_fb_type = SU/MU */
1083 if ((NULL != psta_info->hal_sta->bf_entry) &&
1084 (PHL_SND_FB_TYPE_CQI != sta->snd_fb_t)) {
1085
1086 hstatus = rtw_hal_snd_proc_pre_cfg_sta(
1087 phl_info->hal, psta_info);
1088
1089 if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1090 pstatus = RTW_PHL_STATUS_FAILURE;
1091 }
1092 }
1093 }
1094 /* Prepare Group bitmap for Tx MU-MIMO */
1095 if (PHL_SND_FB_TYPE_MU == grp->sta[0].snd_fb_t)
1096 pstatus = phl_snd_cal_mu_grp_bitmap(phl_info, grp);
1097
1098 } while (0);
1099
1100
1101 if(pstatus != RTW_PHL_STATUS_SUCCESS)
1102 grp->snd_sts = PHL_SND_STS_FAILURE;
1103 FUNCOUT_WSTS(pstatus);
1104 return pstatus;
1105 }
1106 /* 3. Send Sounding Command to HAL/FW */
1107 /*TODO: RU Allocation is now hard code value */
1108 /* HE TB Sounding : 2 sta in a grp */
1109 void
_phl_snd_proc_fw_cmd_he_tb_2sta(struct phl_info_t * phl_info,struct phl_snd_grp * grp,u8 * cmd,u8 bfrp_num)1110 _phl_snd_proc_fw_cmd_he_tb_2sta(struct phl_info_t *phl_info,
1111 struct phl_snd_grp *grp,
1112 u8 *cmd, u8 bfrp_num)
1113 {
1114 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
1115 struct rtw_phl_stainfo_t *sta_info = NULL;
1116 u8 *f_ru_tbl = NULL;
1117
1118 if (grp->num_sta != 2)
1119 return;
1120 /* get first sta */
1121 sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[0].macid);
1122
1123 if (bfrp_num == 1) {
1124 if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
1125 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[1][0];/* Fixed 20MHz RU Table of 2 STA */
1126 else
1127 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[1][0];/* Fixed 80MHz RU Table of 2 STA */
1128 } else {
1129 if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
1130 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[0][0];/* Fixed 20MHz RU Table of 1 STA */
1131 else
1132 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[0][0];/* Fixed 80MHz RU Table of 1 STA */
1133 }
1134
1135 /* fill commmand */
1136 rtw_hal_snd_ax_fwcmd_tb_pri(phl_info->hal, cmd, grp->sta[0].bw,
1137 sta_info, grp->num_sta, 0);
1138 /* Always use BFRP#0 for primary user */
1139 rtw_hal_snd_ax_fwcmd_tb_add_sta(
1140 phl_info->hal, cmd,
1141 &grp->sta[0].npda_sta_info,
1142 sta_info,
1143 f_ru_tbl[0],
1144 0,
1145 0,
1146 0);
1147
1148 /*get second sta*/
1149 sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[1].macid);
1150
1151 rtw_hal_snd_ax_fwcmd_tb_add_sta(
1152 phl_info->hal, cmd,
1153 &grp->sta[1].npda_sta_info,
1154 sta_info,
1155 f_ru_tbl[1],
1156 1,
1157 (bfrp_num == 1) ? 0 : 1,
1158 (bfrp_num == 1) ? 1 : 0);
1159
1160 }
1161
1162 /* HE TB Sounding : 3 sta in a grp */
1163 void
_phl_snd_proc_fw_cmd_he_tb_3sta(struct phl_info_t * phl_info,struct phl_snd_grp * grp,u8 * cmd,u8 bfrp_num)1164 _phl_snd_proc_fw_cmd_he_tb_3sta(struct phl_info_t *phl_info,
1165 struct phl_snd_grp *grp,
1166 u8 *cmd, u8 bfrp_num)
1167 {
1168 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
1169 struct rtw_phl_stainfo_t *sta_info = NULL;
1170 u8 *f_ru_tbl = NULL;
1171
1172 if(grp->num_sta != 3)
1173 return;
1174 /* get first sta */
1175 sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[0].macid);
1176
1177 if (bfrp_num == 1) {
1178 if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
1179 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[2][0];/* Fixed 20MHz RU Table of 3 STA */
1180 else
1181 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[2][0];/* Fixed 80MHz RU Table of 3 STA */
1182 } else {
1183 if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
1184 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[1][0];/* Fixed 20MHz RU Table of 2 STA */
1185 else
1186 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[1][0];/* Fixed 80MHz RU Table of 2 STA */
1187 }
1188
1189 /* fill commmand */
1190 rtw_hal_snd_ax_fwcmd_tb_pri(phl_info->hal, cmd, grp->sta[0].bw,
1191 sta_info, grp->num_sta, 0);
1192 /* Always use BFRP#0 for primary user */
1193 rtw_hal_snd_ax_fwcmd_tb_add_sta(
1194 phl_info->hal, cmd,
1195 &grp->sta[0].npda_sta_info,
1196 sta_info,
1197 f_ru_tbl[0],
1198 0,
1199 0,
1200 0);
1201
1202 /*get second sta*/
1203 sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[1].macid);
1204
1205 rtw_hal_snd_ax_fwcmd_tb_add_sta(
1206 phl_info->hal, cmd,
1207 &grp->sta[1].npda_sta_info,
1208 sta_info,
1209 f_ru_tbl[1],
1210 1,
1211 0,
1212 1);
1213 /*get third sta*/
1214 sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[2].macid);
1215
1216 rtw_hal_snd_ax_fwcmd_tb_add_sta(
1217 phl_info->hal, cmd,
1218 &grp->sta[2].npda_sta_info,
1219 sta_info,
1220 f_ru_tbl[2],
1221 2,
1222 (bfrp_num == 1) ? 0 : 1,
1223 (bfrp_num == 1) ? 2 : 0);
1224
1225 }
1226
1227 /* HE TB Sounding : 4 sta in a grp */
1228 void
_phl_snd_proc_fw_cmd_he_tb_4sta(struct phl_info_t * phl_info,struct phl_snd_grp * grp,u8 * cmd,u8 bfrp_num)1229 _phl_snd_proc_fw_cmd_he_tb_4sta(struct phl_info_t *phl_info,
1230 struct phl_snd_grp *grp,
1231 u8 *cmd, u8 bfrp_num)
1232 {
1233 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
1234 struct rtw_phl_stainfo_t *sta_info = NULL;
1235 u8 *f_ru_tbl = NULL;
1236
1237 if(grp->num_sta != 4)
1238 return;
1239 /* get first sta */
1240 sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[0].macid);
1241
1242 if (bfrp_num == 1) {
1243 if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
1244 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[3][0];/* Fixed 20MHz RU Table of 4 STA */
1245 else
1246 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[3][0];/* Fixed 80MHz RU Table of 4 STA */
1247 } else {
1248 if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
1249 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[1][0];/* Fixed 20MHz RU Table of 2 STA */
1250 else
1251 f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[1][0];/* Fixed 80MHz RU Table of 2 STA */
1252 }
1253
1254 /* fill commmand */
1255 rtw_hal_snd_ax_fwcmd_tb_pri(phl_info->hal, cmd, grp->sta[0].bw,
1256 sta_info, grp->num_sta, 0);
1257 /* Always use BFRP#0 for primary user */
1258 rtw_hal_snd_ax_fwcmd_tb_add_sta(
1259 phl_info->hal, cmd,
1260 &grp->sta[0].npda_sta_info,
1261 sta_info,
1262 f_ru_tbl[0],
1263 0,
1264 0,
1265 0);
1266
1267 /*get second sta*/
1268 sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[1].macid);
1269
1270 rtw_hal_snd_ax_fwcmd_tb_add_sta(
1271 phl_info->hal, cmd,
1272 &grp->sta[1].npda_sta_info,
1273 sta_info,
1274 f_ru_tbl[1],
1275 1,
1276 (bfrp_num == 1) ? 0 : 0,
1277 (bfrp_num == 1) ? 1 : 1);
1278 /*get third sta*/
1279 sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[2].macid);
1280
1281 rtw_hal_snd_ax_fwcmd_tb_add_sta(
1282 phl_info->hal, cmd,
1283 &grp->sta[2].npda_sta_info,
1284 sta_info,
1285 f_ru_tbl[2],
1286 2,
1287 (bfrp_num == 1) ? 0 : 1,
1288 (bfrp_num == 1) ? 2 : 0);
1289
1290 /*get 4th sta*/
1291 sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[3].macid);
1292
1293 rtw_hal_snd_ax_fwcmd_tb_add_sta(
1294 phl_info->hal, cmd,
1295 &grp->sta[3].npda_sta_info,
1296 sta_info,
1297 f_ru_tbl[3],
1298 3,
1299 (bfrp_num == 1) ? 0 : 1,
1300 (bfrp_num == 1) ? 3 : 1);
1301
1302 }
1303
1304
1305 enum rtw_phl_status
phl_snd_proc_start_sounding_fw(struct phl_info_t * phl_info,struct phl_snd_grp * grp)1306 phl_snd_proc_start_sounding_fw(struct phl_info_t *phl_info,
1307 struct phl_snd_grp *grp)
1308 {
1309 enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1310 enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
1311 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
1312 struct phl_sound_param *snd_param = &snd->snd_param;
1313 struct rtw_phl_stainfo_t *sta_info = NULL;
1314 u8 *cmd = NULL;
1315 u8 i = 0;
1316 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "==> phl_snd_proc_start_sounding_fw \n");
1317 do {
1318 if (NULL == grp)
1319 break;
1320 if(grp->sta[0].valid == 0)
1321 break;
1322
1323 /*get first sta*/
1324 sta_info = rtw_phl_get_stainfo_by_macid(
1325 phl_info, grp->sta[0].macid);
1326
1327 switch (grp->snd_type) {
1328 case PHL_SND_TYPE_VHT_SW:
1329 {
1330 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "--> PHL_SND_TYPE_VHT_SW\n");
1331 cmd = rtw_hal_snd_prepare_snd_cmd(phl_info->hal);
1332 if (cmd == NULL)
1333 break;
1334 if (grp->num_sta == 1) {
1335 rtw_hal_snd_vht_fwcmd_su(
1336 phl_info->hal, cmd,
1337 grp->sta[0].bw,
1338 sta_info,
1339 &grp->sta[0].npda_sta_info);
1340
1341 } else {
1342 rtw_hal_snd_vht_fwcmd_mu_pri(
1343 phl_info->hal, cmd,
1344 grp->sta[0].bw,
1345 sta_info,
1346 grp->num_sta,
1347 &grp->sta[0].npda_sta_info);
1348
1349 for (i = 1; i < grp->num_sta; i++) {
1350 if(grp->sta[i].valid == 0)
1351 break;
1352 sta_info = rtw_phl_get_stainfo_by_macid(
1353 phl_info, grp->sta[i].macid);
1354
1355 rtw_hal_snd_vht_fwcmd_mu_add_sta(
1356 phl_info->hal, cmd,
1357 &grp->sta[i].npda_sta_info,
1358 sta_info,
1359 i,
1360 (i==(grp->num_sta-1)) ? 1 : 0
1361 );
1362 }
1363 }
1364 rtw_hal_snd_set_fw_cmd_dialogtkn(
1365 phl_info->hal, cmd,
1366 0,
1367 snd_param->snd_dialog_token);
1368 hstatus = rtw_hal_snd_send_fw_cmd(phl_info->hal, cmd);
1369 if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1370 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
1371 "ERROR: rtw_hal_snd_send_fw_cmd Fail!!!!\n");
1372 }
1373 /* free cmd buf at last !!! */
1374 hstatus = rtw_hal_snd_release_snd_cmd(phl_info->hal, cmd);
1375 }
1376 break;
1377 case PHL_SND_TYPE_HE_SW:
1378 {
1379 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "--> PHL_SND_TYPE_HE_SW\n");
1380 cmd = rtw_hal_snd_prepare_snd_cmd(phl_info->hal);
1381 if (cmd == NULL)
1382 break;
1383 if (grp->num_sta == 1) {
1384 rtw_hal_snd_ax_fwcmd_nontb(
1385 phl_info->hal, cmd,
1386 grp->sta[0].bw,
1387 sta_info,
1388 &grp->sta[0].npda_sta_info);
1389 } else {
1390 /* Default use only 1 BFRP */
1391 /* TODO: Fixed mode or when to use 2 BFRP */
1392 if (grp->num_sta == 4)
1393 _phl_snd_proc_fw_cmd_he_tb_4sta(
1394 phl_info, grp, cmd, 1);
1395 else if (grp->num_sta == 3)
1396 _phl_snd_proc_fw_cmd_he_tb_3sta(
1397 phl_info, grp, cmd, 1);
1398 else if (grp->num_sta == 2)
1399 _phl_snd_proc_fw_cmd_he_tb_2sta(
1400 phl_info, grp, cmd, 1);
1401 else
1402 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "phl sounding : 1 sta with HE-TB case is NOT Ready ; need add fake sta into NDPA\n");
1403 }
1404 rtw_hal_snd_set_fw_cmd_dialogtkn(
1405 phl_info->hal, cmd,
1406 1,
1407 snd_param->snd_dialog_token);
1408
1409 hstatus = rtw_hal_snd_send_fw_cmd(phl_info->hal, cmd);
1410 if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1411 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
1412 "ERROR: rtw_hal_snd_send_fw_cmd Fail!!!!\n");
1413 }
1414 /* free cmd buf at last !!! */
1415 hstatus = rtw_hal_snd_release_snd_cmd(phl_info->hal, cmd);
1416 }
1417 break;
1418 case PHL_SND_TYPE_VHT_HW:
1419 {
1420 u8 dialog_tkn = (snd->snd_param.snd_dialog_token << 2);
1421 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
1422 "PHL_SND_TYPE_VHT_HW:\n");
1423 if(NULL == snd->ops.snd_send_ndpa)
1424 break;
1425 rtw_hal_snd_mac_ctrl(phl_info->hal, sta_info->wrole->hw_band, 0);
1426 pstatus = snd->ops.snd_send_ndpa(
1427 phl_to_drvpriv(phl_info),
1428 sta_info->wrole,
1429 &dialog_tkn,
1430 &grp->sta[0].npda_sta_info,
1431 grp->sta[0].bw);
1432 }
1433 break;
1434 case PHL_SND_TYPE_HE_HW:
1435 {
1436 u8 dialog_tkn = (snd->snd_param.snd_dialog_token << 2) | BIT(1);
1437 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
1438 "PHL_SND_TYPE_HE_HW:\n");
1439 if(NULL == snd->ops.snd_send_ndpa)
1440 break;
1441 rtw_hal_snd_mac_ctrl(phl_info->hal, sta_info->wrole->hw_band, 0);
1442 pstatus = snd->ops.snd_send_ndpa(
1443 phl_to_drvpriv(phl_info),
1444 sta_info->wrole,
1445 &dialog_tkn,
1446 &grp->sta[0].npda_sta_info,
1447 grp->sta[0].bw);
1448 }
1449 break;
1450 case PHL_SND_TYPE_INVALID:
1451 default:
1452 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "ERROR: grp->snd_type invalid\n");
1453 break;
1454 }
1455 pstatus = RTW_PHL_STATUS_SUCCESS;
1456 } while (0);
1457 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "<== phl_snd_proc_start_sounding_fw \n");
1458 return pstatus;
1459 }
1460
1461 /* 4. Post Configruation */
1462
1463 /* BY MU_GID if MU Sounding */
1464 enum rtw_phl_status
_phl_snd_proc_postcfg_mu_gid(struct phl_info_t * phl_info,struct phl_snd_grp * grp)1465 _phl_snd_proc_postcfg_mu_gid(struct phl_info_t *phl_info,
1466 struct phl_snd_grp *grp)
1467 {
1468 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1469 enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1470 struct rtw_phl_stainfo_t *psta_info = NULL;
1471 struct phl_snd_sta *sta = NULL;
1472 struct rtw_hal_muba_info ba_info;
1473 u8 i = 0, j = 0;
1474 u8 bfmu_idx;
1475 u8 mugrp_bmp = 0;
1476 u8 gid = 0xFF;
1477
1478
1479 for (i = 0; i < MAX_NUM_STA_SND_GRP; i++) {
1480 sta = &grp->sta[i];
1481 if((false == sta->valid) || (NULL == sta->bf_entry))
1482 continue;
1483
1484 bfmu_idx = rtw_hal_bf_get_sumu_idx(phl_info->hal,
1485 sta->bf_entry);
1486
1487 psta_info = rtw_phl_get_stainfo_by_macid(
1488 phl_info, sta->macid);
1489
1490 mugrp_bmp = psta_info->hal_sta->mugrp_bmp;
1491
1492 /* GID(X + Y)'s setting is same as GID(Y + X)*/
1493 for (j = bfmu_idx; j < 5; j++) {
1494 if (mugrp_bmp & BIT(j)) {
1495 gid = _get_mu_mimo_gid_2sta(bfmu_idx, j + 1);
1496 /*Prepare MU BAR Info*/
1497 rtw_hal_bf_preset_mu_ba_info(phl_info->hal,
1498 psta_info, &ba_info);
1499 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "snd_post_cfg : gid = 0x%x \n", gid);
1500 hstatus = rtw_hal_snd_proc_post_cfg_gid(
1501 phl_info->hal,
1502 gid,
1503 (void *)&ba_info);
1504
1505 if (RTW_HAL_STATUS_SUCCESS != hstatus) {
1506 pstatus = RTW_PHL_STATUS_FAILURE;
1507 }
1508 }
1509 }
1510 }
1511
1512 return pstatus;
1513 }
1514 /* Per STA setting */
1515 enum rtw_phl_status
_phl_snd_proc_postcfg_sta(struct phl_info_t * phl_info,struct phl_snd_grp * grp)1516 _phl_snd_proc_postcfg_sta(struct phl_info_t *phl_info,
1517 struct phl_snd_grp *grp)
1518 {
1519 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1520 enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1521 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
1522 struct rtw_phl_stainfo_t *psta_info = NULL;
1523 struct phl_snd_sta *sta = NULL;
1524 u8 idx = 0;
1525 bool mu = false;
1526
1527 /*post config for a single sta*/
1528 for (idx = 0; idx < MAX_NUM_STA_SND_GRP; idx++) {
1529 sta = &grp->sta[idx];
1530 mu = (sta->snd_fb_t == PHL_SND_FB_TYPE_MU) ? true : false;
1531 if (false == sta->valid)
1532 continue;
1533
1534 psta_info = rtw_phl_get_stainfo_by_macid(phl_info, sta->macid);
1535 if (NULL == psta_info)
1536 continue;
1537
1538 rtw_hal_snd_polling_snd_sts(phl_info->hal, psta_info);
1539 if (RTW_HAL_STATUS_SUCCESS ==
1540 rtw_hal_bf_get_entry_snd_sts(psta_info->hal_sta->bf_entry)) {
1541 sta->snd_sts = PHL_SND_STS_SUCCESS;
1542 } else {
1543 sta->snd_sts = PHL_SND_STS_FAILURE;
1544 }
1545
1546 if ((PHL_SND_STS_SUCCESS != sta->snd_sts) &&
1547 (false == snd->snd_param.bypass_snd_sts_chk)) {
1548 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "SKIP STA Post Config because of sounding fail\n");
1549 continue; /*Sounding Fail, Next STA */
1550 }
1551
1552 hstatus = rtw_hal_snd_proc_post_cfg_sta(phl_info->hal,
1553 psta_info, mu);
1554
1555 if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1556 pstatus = RTW_PHL_STATUS_FAILURE;
1557 }
1558 }
1559
1560 return pstatus;
1561 }
1562 /* SND PROC Post Config API for FSM */
1563 enum rtw_phl_status
phl_snd_proc_postcfg(struct phl_info_t * phl_info,struct phl_snd_grp * grp)1564 phl_snd_proc_postcfg(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
1565 {
1566 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1567 enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1568 bool mu = false, he = true;
1569
1570 FUNCIN();
1571
1572 do {
1573 if (grp == NULL) {
1574 pstatus = RTW_PHL_STATUS_FAILURE;
1575 break;
1576 }
1577 he = (grp->snd_type >= PHL_SND_TYPE_HE_HW) ? true : false;
1578 mu = (grp->sta[0].snd_fb_t == PHL_SND_FB_TYPE_MU) ? true :
1579 false;
1580
1581 /* 1. post config for whole sounding group */
1582 if (grp->skip_post_cfg & BIT(1)) {
1583 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "SKIP SND PROC POST CFG - Group \n");
1584 } else {
1585 hstatus = rtw_hal_snd_proc_post_cfg(
1586 phl_info->hal,
1587 he,
1588 mu,
1589 grp->en_fix_mode);
1590 if (hstatus != RTW_HAL_STATUS_SUCCESS) {
1591 pstatus = RTW_PHL_STATUS_FAILURE;
1592 }
1593 }
1594
1595 /* 2. post config for gid (STA + STA) */
1596 if (grp->skip_post_cfg & BIT(2)) {
1597 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "SKIP SND PROC POST CFG - GID \n");
1598 } else {
1599 if (true == mu) {
1600 /* only mu sounding has gid related config */
1601 _phl_snd_proc_postcfg_mu_gid(phl_info, grp);
1602 }
1603 }
1604
1605 /* 3. (Shall always at last) post config for each STA in group */
1606 if (grp->skip_post_cfg & BIT(3)) {
1607 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "SKIP SND PROC POST CFG - STA \n");
1608 } else {
1609 _phl_snd_proc_postcfg_sta(phl_info, grp);
1610 }
1611
1612 } while (0);
1613
1614 FUNCOUT();
1615 return pstatus;
1616 }
1617
1618 /* SND_PROC_DOWN --> Next Sounding : Check sounding module status */
1619 enum rtw_phl_status
phl_snd_proc_chk_condition(struct phl_info_t * phl_info,struct phl_snd_grp * grp)1620 phl_snd_proc_chk_condition(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
1621 {
1622 enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1623 struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
1624 struct rtw_wifi_role_t *role =
1625 (struct rtw_wifi_role_t *)snd->snd_param.m_wrole;
1626 struct phl_snd_sta *sta = NULL;
1627 struct rtw_phl_stainfo_t *psta = NULL;
1628 struct phl_sound_param *para = &snd->snd_param;
1629 u8 i = 0;
1630 u8 terminate = 0;
1631 /* TODO: Add any conditions to stop the sounding fsm here */
1632 do {
1633 if (true == snd->is_terminated)
1634 break;
1635
1636 if (NULL != role) {
1637 if (PHL_RTYPE_STATION == role->type) {
1638 if (MLME_NO_LINK == role->mstate)
1639 break;
1640 psta = rtw_phl_get_stainfo_self(phl_info, role);
1641 if (rtw_hal_bf_get_entry_snd_sts(
1642 psta->hal_sta->bf_entry)) {
1643 para->snd_fail_counter++;
1644 if (para->snd_fail_counter > 10) {
1645 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_ ,
1646 "Sounding Fail Count > 10, break sounding !!!!\n");
1647 break;
1648 }
1649 } else {
1650 para->snd_fail_counter = 0;
1651 }
1652 } else if (PHL_RTYPE_AP == role->type) {
1653 if (false == role->active)
1654 break;
1655 if (grp->sta[0].bw > role->chandef.bw)
1656 break;
1657 if (0 == grp->num_sta)
1658 break;
1659 for (i = 0; i < grp->num_sta; i++) {
1660 sta = &grp->sta[i];
1661 psta = rtw_phl_get_stainfo_by_macid(phl_info, sta->macid);
1662 if (NULL == psta) {
1663 terminate = 1;
1664 break;
1665 }
1666 if (false == psta->active) {
1667 terminate = 1;
1668 break;
1669 }
1670 if (sta->bw != psta->chandef.bw) {
1671 terminate = 1;
1672 break;
1673 }
1674 }
1675 if(terminate)
1676 break;
1677 }
1678 }
1679
1680 pstatus = RTW_PHL_STATUS_SUCCESS;
1681 } while (0);
1682
1683 return pstatus;
1684 }
1685
1686
1687
1688 /**
1689 * Check the previous sounding group sounding status and free the resource.
1690 * if grp is TIER0 grp, skip release BF/CQI resource.
1691 **/
1692 void
phl_snd_proc_chk_prev_grp(struct phl_info_t * phl_info,struct phl_snd_grp * grp)1693 phl_snd_proc_chk_prev_grp(struct phl_info_t *phl_info,
1694 struct phl_snd_grp *grp)
1695 {
1696 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1697 bool free_res = false;
1698
1699 if (PHL_SND_STS_FAILURE == grp->snd_sts) {
1700 /* Sounding Fail */
1701 free_res = true;
1702 } else if ((PHL_SND_GRP_TIER_1 == grp->grp_tier) && (PHL_SND_STS_PENDING != grp->snd_sts)) {
1703 /* Sounding Success and Group is TIER_1 */
1704 free_res = true;
1705 }
1706
1707 if (free_res) {
1708 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "Free Previous SND Group's Resource\n");
1709 pstatus = phl_snd_proc_release_res(phl_info, grp);
1710 }
1711
1712 return;
1713 }
1714
1715 enum rtw_phl_status
phl_snd_polling_pri_sta_sts(struct phl_info_t * phl_info,struct phl_snd_grp * grp)1716 phl_snd_polling_pri_sta_sts(struct phl_info_t *phl_info,
1717 struct phl_snd_grp *grp)
1718 {
1719 enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
1720 struct rtw_phl_stainfo_t *sta = NULL;
1721
1722 PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
1723 "phl_snd_polling_stutus : polling primay sta sounding status\n");
1724 sta = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[0].macid);
1725 if (sta != NULL) {
1726 if (sta->active == true)
1727 rtw_hal_snd_polling_snd_sts(phl_info->hal, sta);
1728 else
1729 pstatus = RTW_PHL_STATUS_FAILURE;
1730 } else {
1731 pstatus = RTW_PHL_STATUS_FAILURE;
1732 }
1733
1734 return pstatus;
1735 }
1736
1737 void
phl_snd_mac_ctrl(struct phl_info_t * phl_info,struct rtw_wifi_role_t * wrole,u8 ctrl)1738 phl_snd_mac_ctrl(struct phl_info_t *phl_info,
1739 struct rtw_wifi_role_t *wrole, u8 ctrl)
1740 {
1741 enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
1742 hstatus = rtw_hal_snd_mac_ctrl(phl_info->hal, wrole->hw_band, ctrl);
1743 }
1744
1745 enum rtw_phl_status
rtw_phl_snd_init_ops_send_ndpa(void * phl,enum rtw_phl_status (* snd_send_ndpa)(void *,struct rtw_wifi_role_t *,u8 *,u32 *,enum channel_width))1746 rtw_phl_snd_init_ops_send_ndpa(void *phl,
1747 enum rtw_phl_status (*snd_send_ndpa)(void *,
1748 struct rtw_wifi_role_t *,
1749 u8 *,
1750 u32 *,
1751 enum channel_width))
1752 {
1753 enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
1754 struct phl_info_t *phl_info = (struct phl_info_t *)phl;
1755 struct phl_sound_obj *snd = NULL;
1756 if((phl_info != NULL) && (snd_send_ndpa != NULL)) {
1757 if (phl_info->snd_obj != NULL) {
1758 snd = (struct phl_sound_obj *)phl_info->snd_obj;
1759 snd->ops.snd_send_ndpa = snd_send_ndpa;
1760 pstatus = RTW_PHL_STATUS_SUCCESS;
1761 }
1762 }
1763 return pstatus;
1764 }