xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8852bs/phl/phl_sound.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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(&param->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 }