1764 lines
49 KiB
C
1764 lines
49 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright(c) 2019 - 2020 Realtek Corporation.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of version 2 of the GNU General Public License as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
*****************************************************************************/
|
|
#include "phl_headers.h"
|
|
|
|
void __reset_snd_grp(struct phl_snd_grp *grp)
|
|
{
|
|
u8 i = 0;
|
|
|
|
grp->snd_type = PHL_SND_TYPE_INVALID;
|
|
grp->band = 0;
|
|
grp->num_sta = 0;
|
|
grp->wrole_idx = 0;
|
|
grp->grp_tier = PHL_SND_GRP_TIER_1;
|
|
grp->snd_sts = PHL_SND_STS_PENDING;
|
|
for (i = 0; i < MAX_NUM_STA_SND_GRP; i++) {
|
|
grp->sta[i].valid = false;
|
|
grp->sta[i].macid = 0;
|
|
grp->sta[i].bw = CHANNEL_WIDTH_20;
|
|
grp->sta[i].snd_fb_t = PHL_SND_FB_TYPE_SU;
|
|
grp->sta[i].npda_sta_info = 0;
|
|
grp->sta[i].bf_entry = NULL;
|
|
grp->sta[i].snd_sts = PHL_SND_STS_PENDING;
|
|
}
|
|
}
|
|
|
|
enum rtw_phl_status _phl_snd_init_snd_grp(
|
|
struct phl_info_t *phl_info)
|
|
{
|
|
enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct phl_sound_param *param = &snd->snd_param;
|
|
u8 i = 0;
|
|
do {
|
|
if (param->snd_grp == NULL) {
|
|
status = RTW_PHL_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
for (i = 0; i < MAX_SND_GRP_NUM; i++) {
|
|
__reset_snd_grp(¶m->snd_grp[i]);
|
|
param->snd_grp[i].gidx = i;
|
|
}
|
|
} while (0);
|
|
|
|
return status;
|
|
}
|
|
#ifdef CONFIG_FSM
|
|
/* For EXTERNAL application to create Sound object */
|
|
/* @fsm: FSM main structure which created by phl_snd_new_fsm()
|
|
* @phl_info: private data structure to invoke hal/phl function
|
|
*
|
|
* return
|
|
*/
|
|
enum rtw_phl_status phl_snd_new_obj(
|
|
struct fsm_main *fsm,
|
|
struct phl_info_t *phl_info)
|
|
{
|
|
enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
|
|
struct phl_sound_obj *snd_obj = NULL;
|
|
struct fsm_obj *obj = NULL;
|
|
void *drv_priv = phl_to_drvpriv(phl_info);
|
|
FUNCIN();
|
|
|
|
do {
|
|
snd_obj = phl_fsm_new_obj(
|
|
fsm, (void **)&obj, sizeof(*snd_obj));
|
|
|
|
if (snd_obj == NULL) {
|
|
status = RTW_PHL_STATUS_RESOURCE;
|
|
break;
|
|
}
|
|
phl_info->snd_obj = snd_obj;
|
|
|
|
snd_obj->fsm = fsm;
|
|
snd_obj->fsm_obj = obj;
|
|
snd_obj->phl_info = phl_info;
|
|
|
|
/*Init the snd group static resources here*/
|
|
status = _phl_snd_init_snd_grp(phl_info);
|
|
|
|
/* init obj local use variable */
|
|
PHL_INFO("snd_fsm_func_init_st_hdl : PHL SND FSM Module Start Work\n");
|
|
_os_spinlock_init(drv_priv, &snd_obj->snd_lock);
|
|
_os_spinlock_init(drv_priv, &snd_obj->cmd_lock);
|
|
phl_snd_func_snd_init(snd_obj->phl_info);
|
|
|
|
} while (0);
|
|
|
|
if (RTW_PHL_STATUS_SUCCESS != status) {
|
|
PHL_ERR("phl_snd_init_obj FAIL\n");
|
|
/* phl fsm module will handle to free the phl fsm related object*/
|
|
/* phl_snd_deinit_obj(phl_info); */
|
|
}
|
|
|
|
FUNCOUT();
|
|
return status;
|
|
}
|
|
#endif
|
|
|
|
/* PHL SOUND EXTERNAL APIs */
|
|
/* get sounding in progress */
|
|
u8 rtw_phl_snd_chk_in_progress(void *phl)
|
|
{
|
|
u8 ret = 0;
|
|
struct phl_info_t *phl_info = (struct phl_info_t *)phl;
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
void *d = phl_to_drvpriv(phl_info);
|
|
|
|
_os_spinlock(d, &snd->snd_lock, _bh, NULL);
|
|
ret = snd->snd_in_progress;
|
|
_os_spinunlock(d, &snd->snd_lock, _bh, NULL);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* rtw_phl_sound_start
|
|
* @phl:(struct phl_info_t *)
|
|
* @st_dlg_tkn: start dialog token value, if 0, it will use previous sounding dialog token;
|
|
* @period: sounding process period (group--> next group)
|
|
* @test_flag: test mode flags
|
|
**/
|
|
enum rtw_phl_status
|
|
rtw_phl_sound_start(void *phl, u8 wrole_idx, u8 st_dlg_tkn, u8 period, u8 test_flag)
|
|
{
|
|
#ifdef CONFIG_FSM
|
|
struct phl_info_t *phl_info = (struct phl_info_t *)phl;
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct phl_snd_start_req snd_req;
|
|
|
|
snd_req.wrole = (void *)rtw_phl_get_wrole_by_ridx(phl_info->phl_com, wrole_idx);
|
|
|
|
snd_req.dialog_token = (st_dlg_tkn == 0) ?
|
|
snd->snd_param.snd_dialog_token : st_dlg_tkn;
|
|
snd_req.proc_timeout_ms = SND_PROC_DEFAULT_TIMEOUT; /* Default Value */
|
|
snd_req.proc_period = (period > SND_PROC_DEFAULT_PERIOD) ?
|
|
SND_PROC_DEFAULT_PERIOD : period; /*MAX = Default Value */
|
|
snd_req.test_flag = test_flag;
|
|
if (test_flag&PHL_SND_TEST_F_PASS_STS_CHK)
|
|
snd_req.bypass_sts_chk = true;
|
|
else
|
|
snd_req.bypass_sts_chk = false; /* Default False */
|
|
|
|
return phl_snd_fsm_ev_start_func(phl, &snd_req);
|
|
#else
|
|
return RTW_PHL_STATUS_FAILURE;
|
|
#endif
|
|
}
|
|
|
|
enum rtw_phl_status
|
|
rtw_phl_sound_down_ev(void *phl)
|
|
{
|
|
enum rtw_phl_status status = RTW_PHL_STATUS_SUCCESS;
|
|
|
|
#ifdef CONFIG_FSM
|
|
status = phl_snd_fsm_ev_c2h_snd_down(phl);
|
|
#else
|
|
status = RTW_PHL_STATUS_FAILURE;
|
|
#endif
|
|
return status;
|
|
}
|
|
|
|
|
|
enum rtw_phl_status
|
|
rtw_phl_sound_abort(void *phl)
|
|
{
|
|
#ifdef CONFIG_FSM
|
|
return phl_snd_fsm_ev_abort(phl);
|
|
#else
|
|
return RTW_PHL_STATUS_FAILURE;
|
|
#endif
|
|
}
|
|
|
|
/* set fixed mode parameters APIs*/
|
|
void rtw_phl_snd_dump_fix_para(struct phl_info_t *phl_info)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct phl_snd_fix_param *para = NULL;
|
|
u8 i = 0;
|
|
|
|
para = &snd->snd_param.fix_param;
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "===> rtw_phl_snd_fix_dump_para \n");
|
|
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "test_flag = 0x%x \n", snd->snd_param.test_flag);
|
|
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "en_fix_gidx = %d \n", para->en_fix_gidx ? 1 : 0);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "en_fix_fb_type = %d \n", para->en_fix_fb_type ? 1 : 0);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "en_fix_sta = %d \n", para->en_fix_sta ? 1 : 0);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "en_fix_snd_bw = %d \n", para->en_fix_snd_bw ? 1 : 0);
|
|
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "grp_idx = %d \n", para->grp_idx);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "snd_fb_type = %d \n", para->snd_fb_type);
|
|
|
|
for (i = 0; i < MAX_NUM_STA_SND_GRP; i++) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "sta_macid[i] = 0x%x \n", para->sta_macid[i]);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "bw[i] = %d \n",para->bw[i]);
|
|
}
|
|
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "<=== rtw_phl_snd_fix_dump_para \n");
|
|
}
|
|
/* fixed group idx */
|
|
void rtw_phl_snd_fix_gidx(struct phl_info_t *phl_info, bool en, u8 gidx)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "rtw_phl_snd_fix_gidx() set sounding gidx = 0x%x\n", gidx);
|
|
if (en) {
|
|
snd->snd_param.fix_param.en_fix_gidx = 1;
|
|
snd->snd_param.fix_param.grp_idx = gidx;
|
|
} else {
|
|
snd->snd_param.fix_param.en_fix_gidx = 0;
|
|
}
|
|
}
|
|
/* fixed snd feedback type */
|
|
void rtw_phl_snd_fix_snd_fb_type(struct phl_info_t *phl_info,
|
|
bool en, enum snd_fb_type fb_type)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "rtw_phl_snd_fix_gidx() set sounding fb_type = 0x%x\n",
|
|
fb_type);
|
|
if (en) {
|
|
snd->snd_param.fix_param.en_fix_fb_type = 1;
|
|
snd->snd_param.fix_param.snd_fb_type = fb_type;
|
|
} else {
|
|
snd->snd_param.fix_param.en_fix_fb_type = 0;
|
|
}
|
|
}
|
|
|
|
/* fixed sounding sta macids */
|
|
void rtw_phl_snd_fix_set_sta(struct phl_info_t *phl_info,
|
|
bool en, u8 sidx, u16 macid)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "rtw_phl_snd_fix_set_sta() set sta[%d] macid = 0x%x\n",
|
|
sidx, macid);
|
|
if (en) {
|
|
snd->snd_param.fix_param.en_fix_sta = 1;
|
|
if (sidx < MAX_NUM_STA_SND_GRP)
|
|
snd->snd_param.fix_param.sta_macid[sidx] = macid;
|
|
else
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "ERROR, sidx >= 4\n");
|
|
} else {
|
|
snd->snd_param.fix_param.en_fix_sta = 0;
|
|
}
|
|
}
|
|
|
|
/* fixed sounding sta bw */
|
|
void rtw_phl_snd_fix_set_bw(struct phl_info_t *phl_info,
|
|
bool en, u8 sidx, enum channel_width bw)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "rtw_phl_snd_fix_set_bw() set sta[%d] bw = 0x%x\n", sidx, bw);
|
|
if (en) {
|
|
snd->snd_param.fix_param.en_fix_snd_bw = 1;
|
|
if (sidx < MAX_NUM_STA_SND_GRP)
|
|
snd->snd_param.fix_param.bw[sidx] = bw;
|
|
else
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "ERROR, sidx >= 4\n");
|
|
} else {
|
|
snd->snd_param.fix_param.en_fix_snd_bw = 0;
|
|
}
|
|
}
|
|
|
|
/* set forced fw tx mu-mimo (forced fw tx decision) */
|
|
void rtw_phl_snd_fix_tx_he_mu(struct phl_info_t *phl_info, u8 gid, bool en)
|
|
{
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "rtw_phl_snd_fix_tx_mu_para()\n");
|
|
|
|
rtw_hal_bf_set_txmu_para(phl_info->hal, gid, en,
|
|
HAL_PROT_NO_PROETCT, HAL_ACK_N_USER_BA);
|
|
|
|
rtw_hal_bf_set_fix_mode(phl_info->hal, gid, en);
|
|
}
|
|
|
|
|
|
/* PHL SOUND INTERNAL APIs */
|
|
/* SND FUNC */
|
|
enum rtw_phl_status
|
|
phl_snd_func_snd_init(struct phl_info_t *phl_info)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
void *d = phl_to_drvpriv(phl_info);
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
u8 f_ru_tbl_80m[MAX_SND_HE_BFRP_USER_NUM][MAX_SND_HE_BFRP_USER_NUM] = {
|
|
{RTW_HE_RU996_1, RTW_HE_RU996_1, RTW_HE_RU996_1 ,RTW_HE_RU996_1},
|
|
{RTW_HE_RU484_1, RTW_HE_RU484_2, RTW_HE_RU996_1 ,RTW_HE_RU996_1},
|
|
{RTW_HE_RU484_1, RTW_HE_RU242_3, RTW_HE_RU242_4 ,RTW_HE_RU996_1},
|
|
{RTW_HE_RU242_1, RTW_HE_RU242_2, RTW_HE_RU242_3 ,RTW_HE_RU242_4}
|
|
};
|
|
|
|
u8 f_ru_tbl_20m[MAX_SND_HE_BFRP_USER_NUM][MAX_SND_HE_BFRP_USER_NUM] = {
|
|
{RTW_HE_RU242_1, RTW_HE_RU242_1, RTW_HE_RU242_1, RTW_HE_RU242_1},
|
|
{RTW_HE_RU106_1, RTW_HE_RU106_1, RTW_HE_RU242_1, RTW_HE_RU242_1},
|
|
{RTW_HE_RU106_1, RTW_HE_RU52_3, RTW_HE_RU52_4, RTW_HE_RU242_1},
|
|
{RTW_HE_RU52_1, RTW_HE_RU52_2, RTW_HE_RU52_3, RTW_HE_RU52_4}
|
|
};
|
|
|
|
/* Add Other Sounding FUNC/PRCO Initialization Here */
|
|
snd->snd_param.snd_proc_timeout_ms = SND_PROC_DEFAULT_TIMEOUT;/* ms */
|
|
snd->snd_param.cur_proc_grp_idx = 0;
|
|
snd->snd_param.pre_proc_grp_idx = 0;
|
|
snd->snd_param.snd_dialog_token = 1;
|
|
snd->snd_param.snd_func_grp_num = 0;
|
|
snd->snd_param.grp_used_map = 0;
|
|
snd->snd_param.snd_proc_period = SND_PROC_DEFAULT_PERIOD;
|
|
snd->snd_param.snd_fail_counter = 0;
|
|
|
|
/*fixed_ru_tbl*/
|
|
_os_mem_cpy(d, snd->snd_param.fix_param.f_ru_tbl_20, f_ru_tbl_20m,
|
|
MAX_SND_HE_BFRP_USER_NUM * MAX_SND_HE_BFRP_USER_NUM);
|
|
_os_mem_cpy(d, snd->snd_param.fix_param.f_ru_tbl_80, f_ru_tbl_80m,
|
|
MAX_SND_HE_BFRP_USER_NUM * MAX_SND_HE_BFRP_USER_NUM);
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
enum rtw_phl_status
|
|
phl_snd_func_pre_config(struct phl_info_t *phl_info)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct phl_sound_param *snd_param = &snd->snd_param;
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
void *d = phl_to_drvpriv(phl_info);
|
|
|
|
snd_param->proc_start_time = _os_get_cur_time_ms();
|
|
snd_param->cur_proc_grp_idx = 0; /* default start from group idx 0 */
|
|
snd_param->pre_proc_grp_idx = 0;
|
|
_os_spinlock(d, &snd->snd_lock, _bh, NULL);
|
|
snd->is_terminated = 0;
|
|
snd->snd_in_progress = 1;
|
|
_os_spinunlock(d, &snd->snd_lock, _bh, NULL);
|
|
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "PHL SND FUNC Start with SND Dialog Token = 0x%x\n",
|
|
snd_param->snd_dialog_token);
|
|
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
|
|
/* SND_FUNC : GROUP related */
|
|
/**
|
|
* phl_snd_proc_get_grp()
|
|
* get the grp(struct phl_sound_grp *) with group index.
|
|
* input:
|
|
* @gidx: group idx.
|
|
* return:
|
|
* @grp: (struct phl_snd_grp *grp), NULL = FAIL;
|
|
*/
|
|
struct phl_snd_grp *
|
|
phl_snd_get_grp_byidx(struct phl_info_t *phl_info, u8 gidx)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct phl_sound_param *snd_param = &snd->snd_param;
|
|
struct phl_snd_grp *grp = NULL;
|
|
|
|
do {
|
|
if (gidx >= MAX_SND_GRP_NUM)
|
|
break;
|
|
|
|
if (!(snd_param->grp_used_map & BIT(gidx)))
|
|
break;
|
|
|
|
if (0 == snd_param->snd_grp[gidx].num_sta)
|
|
break;
|
|
|
|
if (PHL_SND_TYPE_INVALID == snd_param->snd_grp[gidx].snd_type)
|
|
break;
|
|
|
|
grp = &snd_param->snd_grp[gidx];
|
|
|
|
} while (0);
|
|
|
|
return grp;
|
|
}
|
|
|
|
/**
|
|
* phl_snd_func_remove_grp()
|
|
* remove the target sounding grp from sound process;
|
|
* input:
|
|
* @grp: (struct phl_snd_grp *) target sounding grp,
|
|
*/
|
|
enum rtw_phl_status
|
|
phl_snd_func_remove_grp(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct phl_sound_param *snd_param = &snd->snd_param;
|
|
|
|
if (grp == NULL) {
|
|
return pstatus;
|
|
}
|
|
if (snd_param->grp_used_map & BIT(grp->gidx)) {
|
|
|
|
/* Check and Release all the BF resource */
|
|
pstatus = phl_snd_proc_release_res(phl_info, grp);
|
|
if (pstatus != RTW_PHL_STATUS_SUCCESS) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "PHL SND Remove Grp : release BF resouce fail\n");
|
|
}
|
|
|
|
/* Reset group content to default value */
|
|
__reset_snd_grp(grp);
|
|
|
|
/* Clear Group BIT */
|
|
snd_param->grp_used_map &= ~BIT(grp->gidx);
|
|
snd_param->snd_func_grp_num--;
|
|
|
|
} else {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "PHL SND Remove Grp : Group is not in used!!!\n");
|
|
}
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
/**
|
|
* phl_snd_func_remove_grp_all()
|
|
* remove the all of the sounding grp from sound process;
|
|
*/
|
|
void
|
|
phl_snd_func_remove_grp_all(struct phl_info_t *phl_info)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
struct phl_snd_grp *grp = NULL;
|
|
u8 idx = 0;
|
|
|
|
for(idx = 0; idx < MAX_SND_GRP_NUM; idx++) {
|
|
grp = phl_snd_get_grp_byidx(phl_info, idx);
|
|
if (grp != NULL) {
|
|
pstatus = phl_snd_func_remove_grp(phl_info, grp);
|
|
if (pstatus != RTW_PHL_STATUS_SUCCESS) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "Remove SND GRP[%d] Fail\n", idx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* _phl_snd_get_available_gidx()
|
|
* Get available group resource.
|
|
* return:
|
|
* @gidx: u8, the group idx in snd_param->grp[n]
|
|
*/
|
|
u8 _phl_snd_get_available_gidx(struct phl_sound_obj *snd)
|
|
{
|
|
struct phl_sound_param *param = &snd->snd_param;
|
|
u8 gidx = MAX_SND_GRP_NUM;
|
|
|
|
for (gidx = 0; gidx < MAX_SND_GRP_NUM; gidx++) {
|
|
if (!(param->grp_used_map & BIT(gidx))) {
|
|
param->grp_used_map |= BIT(gidx);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return gidx;
|
|
}
|
|
|
|
/**
|
|
* _phl_snd_func_grp_add_sta()
|
|
* Add the STA into sounding group.
|
|
* input:
|
|
* @sta: (struct rtw_phl_stainfo_t *) the target sta to be added.
|
|
* the function will use the macid / bw information in sta_info;
|
|
* @gidx: the group idx to add
|
|
*/
|
|
enum rtw_phl_status
|
|
_phl_snd_func_grp_add_sta(
|
|
struct phl_info_t *phl_info, struct rtw_phl_stainfo_t *sta, u8 gidx)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct phl_sound_param *snd_param = &snd->snd_param;
|
|
struct phl_snd_grp *grp = NULL;
|
|
u8 i = 0;
|
|
bool chk = false;
|
|
|
|
do {
|
|
|
|
if (NULL == sta) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "STA == NULL !!!!\n");
|
|
break;
|
|
}
|
|
|
|
if (gidx >= MAX_SND_GRP_NUM) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "Get SND Grp Resource Fail : gidx >= MAX_SND_GRP_NUM\n");
|
|
break;
|
|
}
|
|
|
|
grp = &snd_param->snd_grp[gidx];
|
|
|
|
/* check grp->sta[i].macid with sta->macid, skip it if same.*/
|
|
for (i = 0; i < grp->num_sta; i++) {
|
|
if(grp->sta[i].macid == sta->macid) {
|
|
chk = true;
|
|
break;
|
|
}
|
|
}
|
|
if (true == chk)
|
|
break;
|
|
|
|
if (grp->num_sta >= MAX_NUM_STA_SND_GRP) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "The SND Grp is already has 4 STAs\n");
|
|
break;
|
|
}
|
|
|
|
grp->sta[grp->num_sta].macid = sta->macid;
|
|
grp->sta[grp->num_sta].snd_sts = PHL_SND_STS_PENDING;
|
|
grp->sta[grp->num_sta].bw = sta->chandef.bw;
|
|
grp->sta[grp->num_sta].valid = true;
|
|
grp->num_sta++;
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "sta bw = %d\n", sta->chandef.bw);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "grp->num_sta = %d\n", grp->num_sta);
|
|
|
|
pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
} while (0);
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
/**
|
|
* phl_snd_func_add_snd_grp :
|
|
* Add a Sounding Group with Primary STA for FW Sounding
|
|
* @phl_info: struct phl_info_t *
|
|
* @he_snd: 1 = HE , 0 =VHT
|
|
* @gidx: return value, snd group idxx in group list
|
|
* @psta: (struct rtw_phl_stainfo_t *)Primary Sounding STA,
|
|
* if pSTA is unavailable , SND PROC for this group will be terminated.
|
|
**/
|
|
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)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct phl_sound_param *snd_param = &snd->snd_param;
|
|
struct phl_snd_grp *grp = NULL;
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
|
|
|
|
do {
|
|
/* Check Primary STA Available*/
|
|
if (psta == NULL) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "psta == NULL\n");
|
|
break;
|
|
}
|
|
|
|
/* Get available sounding group resource */
|
|
*gidx = _phl_snd_get_available_gidx(snd);
|
|
if (*gidx >= MAX_SND_GRP_NUM) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "Get SND Grp Resource Fail : gidx >= MAX_SND_GRP_NUM\n");
|
|
break;
|
|
}
|
|
|
|
grp = &(snd_param->snd_grp[*gidx]);
|
|
grp->band = psta->wrole->hw_band;
|
|
grp->snd_type = he_snd ? PHL_SND_TYPE_HE_SW :
|
|
PHL_SND_TYPE_VHT_SW;
|
|
grp->wrole_idx = wrole_idx;
|
|
grp->snd_sts = PHL_SND_STS_PENDING;
|
|
grp->num_sta = 0;
|
|
|
|
/* Primary STA use idx-0 */
|
|
_phl_snd_func_grp_add_sta(phl_info, psta, *gidx);
|
|
|
|
snd_param->snd_func_grp_num++;
|
|
|
|
pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "phl_snd_func_add_snd_grp : Add group[%d] Success\n",
|
|
*gidx);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "phl_snd_func_add_snd_grp : grp->snd_type 0x%x\n",
|
|
grp->snd_type);
|
|
|
|
} while (0);
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
/**
|
|
* _phl_snd_func_set_grp_fb_mu()
|
|
* Set the whole sounding grp's feedback type = MU
|
|
* input:
|
|
* @grp: (struct phl_snd_grp *) the target group.
|
|
*/
|
|
void _phl_snd_func_set_grp_fb_mu(struct phl_snd_grp *grp)
|
|
{
|
|
u8 i = 0;
|
|
if (grp == NULL)
|
|
return;
|
|
for (i = 0; i < grp->num_sta; i++) {
|
|
grp->sta[i].snd_fb_t = PHL_SND_FB_TYPE_MU;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* phl_snd_func_grouping()
|
|
* function for soundind fsm state : SND_FUNC_READY
|
|
* input:
|
|
* @wroleidx: the index of wrole which the sounding proc run under with.
|
|
*/
|
|
enum rtw_phl_status
|
|
phl_snd_func_grouping(struct phl_info_t *phl_info, u8 wroleidx)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct phl_sound_param *snd_param = &snd->snd_param;
|
|
struct phl_snd_fix_param *fix_para = &snd->snd_param.fix_param;
|
|
struct rtw_wifi_role_t *wrole = NULL;
|
|
struct rtw_phl_stainfo_t *self = NULL, *sta;
|
|
struct phl_snd_grp *grp = NULL;
|
|
void *drv = phl_to_drvpriv(phl_info);
|
|
struct phl_queue *sta_queue;
|
|
u8 gidx = 0;
|
|
u8 cnt = 0;
|
|
|
|
wrole = rtw_phl_get_wrole_by_ridx(phl_info->phl_com, wroleidx);
|
|
|
|
/* if wrole(STA) is linked, seft = AP */
|
|
/* if wrole is AP, self = ???? */
|
|
self = rtw_phl_get_stainfo_self(phl_info, wrole);
|
|
if (self == NULL) {
|
|
PHL_ERR("Cannot get self's phl_sta\n");
|
|
return pstatus;
|
|
}
|
|
sta_queue = &wrole->assoc_sta_queue;
|
|
if (PHL_RTYPE_STATION == wrole->type) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, " PHL_RTYPE_STATION == wrole->type \n");
|
|
/* STA Mode : Only SU TxBF with AP */
|
|
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "self->macid = 0x%x \n", self->macid);
|
|
debug_dump_mac_address(self->mac_addr);
|
|
|
|
pstatus = phl_snd_func_add_snd_grp(
|
|
phl_info,
|
|
(self->wmode & WLAN_MD_11AX) ? true :
|
|
false,
|
|
wrole->id, self, &gidx);
|
|
grp = &snd_param->snd_grp[gidx];
|
|
grp->grp_tier = PHL_SND_GRP_TIER_0;
|
|
grp->sta[0].snd_fb_t = PHL_SND_FB_TYPE_SU;
|
|
grp->snd_type = (self->wmode & WLAN_MD_11AX) ?
|
|
PHL_SND_TYPE_HE_HW : PHL_SND_TYPE_VHT_HW;
|
|
} else {
|
|
#if 1
|
|
/* Test Code: Group-1 :Forced MU Sounding with first 1~4 STAs */
|
|
/* the mu sounding list shall get from mu grouping module */
|
|
cnt = 0;
|
|
_os_spinlock(drv, &sta_queue->lock, _bh, NULL);
|
|
phl_list_for_loop(sta, struct rtw_phl_stainfo_t,
|
|
&wrole->assoc_sta_queue.queue, list) {
|
|
if (is_broadcast_mac_addr(sta->mac_addr))
|
|
continue;
|
|
if (sta == self)
|
|
continue;
|
|
/* First STA */
|
|
if (cnt == 0) {
|
|
pstatus = phl_snd_func_add_snd_grp(
|
|
phl_info,
|
|
(sta->wmode & WLAN_MD_11AX) ?
|
|
true : false,
|
|
wrole->id, sta, &gidx);
|
|
if (pstatus != RTW_PHL_STATUS_SUCCESS)
|
|
break;
|
|
} else {
|
|
/* get next associated sta and add to group */
|
|
_phl_snd_func_grp_add_sta(phl_info, sta, gidx);
|
|
}
|
|
cnt++;
|
|
if (cnt >= 4)
|
|
break;
|
|
}
|
|
_os_spinunlock(drv, &sta_queue->lock, _bh, NULL);
|
|
if(pstatus != RTW_PHL_STATUS_SUCCESS)
|
|
return RTW_PHL_STATUS_FAILURE;
|
|
grp = &snd_param->snd_grp[gidx];
|
|
grp->grp_tier = PHL_SND_GRP_TIER_0;
|
|
/* Test : forced MU */
|
|
_phl_snd_func_set_grp_fb_mu(&snd_param->snd_grp[gidx]);
|
|
#endif
|
|
}
|
|
|
|
/*TODO: fixed paramters gidx when multi-group */
|
|
if (snd_param->test_flag&PHL_SND_TEST_F_GRP_SND_PARA) {
|
|
/*Test Mode force set the group fb type = MU */
|
|
if (fix_para->en_fix_fb_type) {
|
|
if (PHL_SND_FB_TYPE_MU == fix_para->snd_fb_type) {
|
|
_phl_snd_func_set_grp_fb_mu(
|
|
&snd_param->snd_grp[gidx]);
|
|
}
|
|
/**
|
|
* Note : 8852A only support two CSI Buffer for SU,
|
|
* take care that num of STA in SU sounding of a group shall < 2.
|
|
**/
|
|
}
|
|
|
|
if(fix_para->en_fix_snd_bw) {
|
|
grp = &snd_param->snd_grp[gidx];
|
|
for (cnt = 0; cnt < MAX_NUM_STA_SND_GRP; cnt++) {
|
|
if (grp->sta[cnt].valid)
|
|
grp->sta[cnt].bw = fix_para->bw[cnt];
|
|
}
|
|
}
|
|
} else {
|
|
grp = &snd_param->snd_grp[gidx];
|
|
if (grp->num_sta > 2) {
|
|
/* forced using MU feedback because of SU CSI buffer number */
|
|
_phl_snd_func_set_grp_fb_mu(&snd_param->snd_grp[gidx]);
|
|
}
|
|
}
|
|
|
|
if (snd_param->test_flag & PHL_SND_TEST_F_GRP_EN_BF_FIX) {
|
|
snd_param->snd_grp[gidx].en_fix_mode = 1; /* post confg forced mode setting */
|
|
}
|
|
return pstatus;
|
|
|
|
}
|
|
|
|
/* SND PROC */
|
|
|
|
/* Free BF/CQI resource */
|
|
enum rtw_phl_status
|
|
_phl_snd_proc_release_res_cqi(
|
|
struct phl_info_t *phl_info, struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
|
|
/*CQI Fb doesn't query any resource*/
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
enum rtw_phl_status
|
|
_phl_snd_proc_release_res_bf(
|
|
struct phl_info_t *phl_info, struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
|
|
struct phl_snd_sta *snd_sta;
|
|
struct rtw_phl_stainfo_t *sta = NULL;
|
|
u8 idx = 0;
|
|
|
|
for (idx = 0; idx < grp->num_sta; idx++) {
|
|
snd_sta = &grp->sta[idx];
|
|
if(0 == snd_sta->valid)
|
|
continue;
|
|
|
|
sta = rtw_phl_get_stainfo_by_macid(
|
|
phl_info, snd_sta->macid);
|
|
if (NULL == sta) {
|
|
PHL_ERR("_phl_snd_proc_release_res_bf: Cannot find STA macid 0x%x in PHL STA Info List \n",
|
|
snd_sta->macid);
|
|
continue;
|
|
}
|
|
if (NULL == sta->hal_sta->bf_entry)
|
|
continue;
|
|
|
|
hstatus = rtw_hal_snd_release_proc_sta_res(phl_info->hal, sta);
|
|
if(hstatus != RTW_HAL_STATUS_SUCCESS) {
|
|
PHL_ERR("_phl_snd_proc_release_res_bf: macid 0x%x Free Sounding Resource FAIL \n",
|
|
snd_sta->macid);
|
|
continue;
|
|
}
|
|
/* un link the bf entry to STA info */
|
|
sta->hal_sta->bf_entry = NULL;
|
|
}
|
|
return pstatus;
|
|
}
|
|
/**
|
|
* phl_snd_proc_release_res:
|
|
* Release the sounding resource for the group
|
|
* @phl_info: phl_info_t
|
|
* @grp: (struct phl_snd_grp *) sounding gorup for release resource
|
|
**/
|
|
enum rtw_phl_status
|
|
phl_snd_proc_release_res(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
struct phl_snd_sta *snd_sta;
|
|
snd_sta = &grp->sta[0];
|
|
if (snd_sta->snd_fb_t == PHL_SND_FB_TYPE_CQI)
|
|
pstatus = _phl_snd_proc_release_res_cqi(phl_info, grp);
|
|
else
|
|
pstatus = _phl_snd_proc_release_res_bf(phl_info, grp);
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
/**
|
|
* _phl_snd_proc_get_bf_res_cqi_fb:
|
|
* CQI Sounding doesn't need BF Reresource
|
|
* @phl_info: phl_info_t
|
|
* @grp: (struct phl_sound_grp *) sounding gorup
|
|
* @nsta: return value : how many sta query resource success
|
|
**/
|
|
enum rtw_phl_status
|
|
_phl_snd_proc_get_res_cqi_fb(
|
|
struct phl_info_t *phl_info, struct phl_snd_grp *grp, u8 *nsta)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
struct phl_snd_sta *snd_sta;
|
|
u8 idx = 0;
|
|
struct rtw_phl_stainfo_t *sta = NULL;
|
|
|
|
*nsta = 0;
|
|
|
|
for (idx = 0; idx < grp->num_sta; idx++) {
|
|
snd_sta = &grp->sta[idx];
|
|
sta = rtw_phl_get_stainfo_by_macid(phl_info, snd_sta->macid);
|
|
if (NULL == sta) {
|
|
PHL_ERR("phl_snd_proc_get_bf_res: Cannot find STA macid 0x%x in PHL STA Info List \n",
|
|
snd_sta->macid);
|
|
continue;
|
|
}
|
|
|
|
rtw_hal_snd_ndpa_sta_info_he(
|
|
sta,
|
|
&snd_sta->npda_sta_info,
|
|
snd_sta->bw,
|
|
PHL_SND_FB_TYPE_CQI);
|
|
|
|
(*nsta)++;
|
|
}
|
|
if (*nsta == 0) {
|
|
grp->snd_sts = PHL_SND_STS_FAILURE;
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
}
|
|
if (*nsta != grp->num_sta) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, " Sounding STAs is fewer than group sta because of resource!");
|
|
}
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
/**
|
|
* _phl_snd_proc_get_res_bf:
|
|
* Get BF Resource for SU/MU Sounding
|
|
* @phl_info: phl_info_t
|
|
* @grp: (struct phl_sound_grp *) sounding gorup
|
|
* @nsta: return value : how many sta query bf resource success
|
|
**/
|
|
enum rtw_phl_status
|
|
_phl_snd_proc_get_res_bf(
|
|
struct phl_info_t *phl_info, struct phl_snd_grp *grp, u8 *nsta)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
|
|
struct phl_snd_sta *snd_sta;
|
|
u8 idx = 0;
|
|
struct rtw_phl_stainfo_t *sta = NULL;
|
|
bool mu, qry_bf;
|
|
|
|
*nsta = 0;
|
|
|
|
for (idx = 0; idx < grp->num_sta; idx++) {
|
|
snd_sta = &grp->sta[idx];
|
|
sta = rtw_phl_get_stainfo_by_macid(phl_info, snd_sta->macid);
|
|
if (NULL == sta) {
|
|
PHL_ERR("phl_snd_proc_get_bf_res: Cannot find STA macid 0x%x in PHL STA Info List \n",
|
|
snd_sta->macid);
|
|
continue;
|
|
}
|
|
|
|
mu = (snd_sta->snd_fb_t == PHL_SND_FB_TYPE_MU) ? true:false;
|
|
qry_bf = false;
|
|
if (sta->hal_sta->bf_entry != NULL) {
|
|
/* The sta already have BF reource */
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, " sta->bf_entry != NULL\n");
|
|
/* Check the BF resource */
|
|
hstatus = rtw_hal_snd_chk_bf_res(phl_info->hal,
|
|
sta, mu, sta->chandef.bw);
|
|
if (RTW_HAL_STATUS_FAILURE == hstatus) {
|
|
rtw_hal_snd_release_proc_sta_res(phl_info->hal,
|
|
sta);
|
|
qry_bf = true;
|
|
|
|
} else {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "Use Original BF Resource \n");
|
|
qry_bf = false;
|
|
}
|
|
} else {
|
|
qry_bf = true;
|
|
}
|
|
|
|
if (true == qry_bf) {
|
|
hstatus = rtw_hal_snd_query_proc_sta_res(
|
|
phl_info->hal, sta, mu, sta->chandef.bw,
|
|
grp->en_swap_mode);
|
|
if (hstatus != RTW_HAL_STATUS_SUCCESS) {
|
|
PHL_ERR("phl_snd_proc_get_bf_res: macid 0x%x query sounding resource FAIL \n",
|
|
snd_sta->macid);
|
|
if (grp->en_swap_mode) {
|
|
break;/* break in swap mode if one of sta query bf res fail */
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
if (grp->snd_type >= PHL_SND_TYPE_HE_HW) {
|
|
rtw_hal_snd_ndpa_sta_info_he(
|
|
sta,
|
|
&snd_sta->npda_sta_info,
|
|
snd_sta->bw,
|
|
snd_sta->snd_fb_t);
|
|
} else {
|
|
rtw_hal_snd_ndpa_sta_info_vht(sta,
|
|
&snd_sta->npda_sta_info, mu);
|
|
}
|
|
|
|
/* Link STA information to Group Information */
|
|
snd_sta->bf_entry = sta->hal_sta->bf_entry;
|
|
|
|
(*nsta)++;
|
|
}
|
|
|
|
if (*nsta == 0) {
|
|
grp->snd_sts = PHL_SND_STS_FAILURE;
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
}
|
|
if (*nsta != grp->num_sta) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "FAIL : Sounding STAs is fewer than group sta because of resource!\n");
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
}
|
|
|
|
return pstatus;
|
|
}
|
|
/* snd proc get BF/CSI resource */
|
|
enum rtw_phl_status
|
|
phl_snd_proc_get_res(
|
|
struct phl_info_t *phl_info, struct phl_snd_grp *grp, u8 *nsta)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
struct phl_snd_sta *snd_sta;
|
|
FUNCIN_WSTS(pstatus);
|
|
|
|
snd_sta = &grp->sta[0];
|
|
/* CQI Fb cannot mixed with SU/MU feedback type*/
|
|
if(snd_sta->snd_fb_t == PHL_SND_FB_TYPE_CQI)
|
|
pstatus = _phl_snd_proc_get_res_cqi_fb(phl_info, grp, nsta);
|
|
else
|
|
pstatus = _phl_snd_proc_get_res_bf(phl_info, grp, nsta);
|
|
|
|
if(pstatus != RTW_PHL_STATUS_SUCCESS)
|
|
grp->snd_sts = PHL_SND_STS_FAILURE;
|
|
|
|
FUNCOUT_WSTS(pstatus);
|
|
return pstatus;
|
|
}
|
|
|
|
/* 2. SND Preconfiguration */
|
|
|
|
/**
|
|
* _get_mu_mimo_gid_2sta()
|
|
* hard code for 8852A, gid relattion-ship
|
|
**/
|
|
static u8 _get_mu_mimo_gid_2sta(u8 primary, u8 secondary)
|
|
{
|
|
u8 gid_tbl[6][6] = { {0xFF, 1, 2, 3, 4, 5},
|
|
{16, 0xFF, 6, 7, 8, 9},
|
|
{17, 21, 0xFF, 10, 11, 12},
|
|
{18, 22, 25, 0xFF, 13, 14},
|
|
{19, 23, 26, 28, 0xFF, 15},
|
|
{20, 24, 27, 29, 30, 0xFF} };
|
|
u8 ret = 0xFF;
|
|
|
|
if ((primary < 6) && (secondary < 6))
|
|
ret = gid_tbl[primary][secondary];
|
|
|
|
return ret;
|
|
}
|
|
/* pre calculate mu-gid */
|
|
enum rtw_phl_status
|
|
phl_snd_cal_mu_grp_bitmap(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
struct rtw_phl_stainfo_t *psta_info = NULL;
|
|
struct rtw_phl_stainfo_t *tmp_psta_info = NULL;
|
|
struct phl_snd_sta *sta = NULL;
|
|
struct phl_snd_sta *tmp_sta = NULL;
|
|
u8 bfmu_idx , bfmu_idx_tmp;
|
|
u8 i = 0, j = 0;
|
|
|
|
for (i = 0; i < MAX_NUM_STA_SND_GRP; i++) {
|
|
sta = &grp->sta[i];
|
|
if (false == sta->valid)
|
|
continue;
|
|
/* primary STA */
|
|
psta_info = rtw_phl_get_stainfo_by_macid(
|
|
phl_info, sta->macid);
|
|
|
|
if (NULL == sta->bf_entry)
|
|
continue;
|
|
if (false == rtw_hal_bf_chk_bf_type(phl_info->hal,
|
|
psta_info, true)) {
|
|
continue; /*BF SU Entry*/
|
|
}
|
|
/* primary STA MU Entry Idx */
|
|
bfmu_idx = rtw_hal_bf_get_sumu_idx(phl_info->hal,
|
|
sta->bf_entry);
|
|
|
|
psta_info->hal_sta->mugrp_bmp = 0; /* clear first */
|
|
|
|
for (j = 0; j < MAX_NUM_STA_SND_GRP; j++) {
|
|
if (j == i) /* self */
|
|
continue;
|
|
/* secondary sta */
|
|
tmp_sta = &grp->sta[j];
|
|
|
|
if (NULL == tmp_sta->bf_entry)
|
|
continue;
|
|
|
|
tmp_psta_info = rtw_phl_get_stainfo_by_macid(
|
|
phl_info, tmp_sta->macid);
|
|
|
|
if (false == rtw_hal_bf_chk_bf_type(phl_info->hal,
|
|
tmp_psta_info, true)) {
|
|
continue; /* BF SU Entry */
|
|
}
|
|
|
|
/* secondary sta MU Entry Idx */
|
|
bfmu_idx_tmp = rtw_hal_bf_get_sumu_idx(phl_info->hal,
|
|
tmp_sta->bf_entry);
|
|
|
|
/* Default set group bit enable = 1 */
|
|
/* grp bitmap doesn't include self */
|
|
/** BIT 0 1 2 3 4
|
|
* MU_0 : MU_1 MU_2 MU_3 MU_4 MU_5
|
|
* MU_1 : MU_0 MU_2 MU_3 MU_4 MU_5
|
|
* MU_2 : MU_0 MU_1 MU_3 MU_4 MU_5
|
|
* ...
|
|
* MU_5 : MU_0 MU_1 MU_2 MU_3 MU_4
|
|
**/
|
|
|
|
if (bfmu_idx_tmp > bfmu_idx) {
|
|
psta_info->hal_sta->mugrp_bmp |=
|
|
BIT(bfmu_idx_tmp - 1);
|
|
} else {
|
|
psta_info->hal_sta->mugrp_bmp |=
|
|
BIT(bfmu_idx_tmp);
|
|
}
|
|
}
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "sta(macid = 0x%x) mugrp_bmp = 0x%x \n",
|
|
psta_info->macid, psta_info->hal_sta->mugrp_bmp);
|
|
}
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
/* Preconfiguration before souding */
|
|
enum rtw_phl_status
|
|
phl_snd_proc_precfg(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
|
|
struct phl_snd_sta *sta = NULL;
|
|
u8 idx = 0;
|
|
struct rtw_phl_stainfo_t *psta_info = NULL;
|
|
FUNCIN_WSTS(pstatus);
|
|
do {
|
|
if (grp == NULL) {
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
if (PHL_SND_TYPE_INVALID == grp->snd_type) {
|
|
/* both SW/HW mode need to set call halmac api to set bf entry */
|
|
break;
|
|
}
|
|
for (idx = 0; idx < MAX_NUM_STA_SND_GRP; idx++) {
|
|
sta = &grp->sta[idx];
|
|
if (false == sta->valid)
|
|
continue;
|
|
psta_info = rtw_phl_get_stainfo_by_macid(
|
|
phl_info, sta->macid);
|
|
|
|
/*check bf entry available and snd_fb_type = SU/MU */
|
|
if ((NULL != psta_info->hal_sta->bf_entry) &&
|
|
(PHL_SND_FB_TYPE_CQI != sta->snd_fb_t)) {
|
|
|
|
hstatus = rtw_hal_snd_proc_pre_cfg_sta(
|
|
phl_info->hal, psta_info);
|
|
|
|
if (hstatus != RTW_HAL_STATUS_SUCCESS) {
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
/* Prepare Group bitmap for Tx MU-MIMO */
|
|
if (PHL_SND_FB_TYPE_MU == grp->sta[0].snd_fb_t)
|
|
pstatus = phl_snd_cal_mu_grp_bitmap(phl_info, grp);
|
|
|
|
} while (0);
|
|
|
|
|
|
if(pstatus != RTW_PHL_STATUS_SUCCESS)
|
|
grp->snd_sts = PHL_SND_STS_FAILURE;
|
|
FUNCOUT_WSTS(pstatus);
|
|
return pstatus;
|
|
}
|
|
/* 3. Send Sounding Command to HAL/FW */
|
|
/*TODO: RU Allocation is now hard code value */
|
|
/* HE TB Sounding : 2 sta in a grp */
|
|
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)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct rtw_phl_stainfo_t *sta_info = NULL;
|
|
u8 *f_ru_tbl = NULL;
|
|
|
|
if (grp->num_sta != 2)
|
|
return;
|
|
/* get first sta */
|
|
sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[0].macid);
|
|
|
|
if (bfrp_num == 1) {
|
|
if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[1][0];/* Fixed 20MHz RU Table of 2 STA */
|
|
else
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[1][0];/* Fixed 80MHz RU Table of 2 STA */
|
|
} else {
|
|
if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[0][0];/* Fixed 20MHz RU Table of 1 STA */
|
|
else
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[0][0];/* Fixed 80MHz RU Table of 1 STA */
|
|
}
|
|
|
|
/* fill commmand */
|
|
rtw_hal_snd_ax_fwcmd_tb_pri(phl_info->hal, cmd, grp->sta[0].bw,
|
|
sta_info, grp->num_sta, 0);
|
|
/* Always use BFRP#0 for primary user */
|
|
rtw_hal_snd_ax_fwcmd_tb_add_sta(
|
|
phl_info->hal, cmd,
|
|
&grp->sta[0].npda_sta_info,
|
|
sta_info,
|
|
f_ru_tbl[0],
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
/*get second sta*/
|
|
sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[1].macid);
|
|
|
|
rtw_hal_snd_ax_fwcmd_tb_add_sta(
|
|
phl_info->hal, cmd,
|
|
&grp->sta[1].npda_sta_info,
|
|
sta_info,
|
|
f_ru_tbl[1],
|
|
1,
|
|
(bfrp_num == 1) ? 0 : 1,
|
|
(bfrp_num == 1) ? 1 : 0);
|
|
|
|
}
|
|
|
|
/* HE TB Sounding : 3 sta in a grp */
|
|
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)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct rtw_phl_stainfo_t *sta_info = NULL;
|
|
u8 *f_ru_tbl = NULL;
|
|
|
|
if(grp->num_sta != 3)
|
|
return;
|
|
/* get first sta */
|
|
sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[0].macid);
|
|
|
|
if (bfrp_num == 1) {
|
|
if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[2][0];/* Fixed 20MHz RU Table of 3 STA */
|
|
else
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[2][0];/* Fixed 80MHz RU Table of 3 STA */
|
|
} else {
|
|
if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[1][0];/* Fixed 20MHz RU Table of 2 STA */
|
|
else
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[1][0];/* Fixed 80MHz RU Table of 2 STA */
|
|
}
|
|
|
|
/* fill commmand */
|
|
rtw_hal_snd_ax_fwcmd_tb_pri(phl_info->hal, cmd, grp->sta[0].bw,
|
|
sta_info, grp->num_sta, 0);
|
|
/* Always use BFRP#0 for primary user */
|
|
rtw_hal_snd_ax_fwcmd_tb_add_sta(
|
|
phl_info->hal, cmd,
|
|
&grp->sta[0].npda_sta_info,
|
|
sta_info,
|
|
f_ru_tbl[0],
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
/*get second sta*/
|
|
sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[1].macid);
|
|
|
|
rtw_hal_snd_ax_fwcmd_tb_add_sta(
|
|
phl_info->hal, cmd,
|
|
&grp->sta[1].npda_sta_info,
|
|
sta_info,
|
|
f_ru_tbl[1],
|
|
1,
|
|
0,
|
|
1);
|
|
/*get third sta*/
|
|
sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[2].macid);
|
|
|
|
rtw_hal_snd_ax_fwcmd_tb_add_sta(
|
|
phl_info->hal, cmd,
|
|
&grp->sta[2].npda_sta_info,
|
|
sta_info,
|
|
f_ru_tbl[2],
|
|
2,
|
|
(bfrp_num == 1) ? 0 : 1,
|
|
(bfrp_num == 1) ? 2 : 0);
|
|
|
|
}
|
|
|
|
/* HE TB Sounding : 4 sta in a grp */
|
|
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)
|
|
{
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct rtw_phl_stainfo_t *sta_info = NULL;
|
|
u8 *f_ru_tbl = NULL;
|
|
|
|
if(grp->num_sta != 4)
|
|
return;
|
|
/* get first sta */
|
|
sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[0].macid);
|
|
|
|
if (bfrp_num == 1) {
|
|
if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[3][0];/* Fixed 20MHz RU Table of 4 STA */
|
|
else
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[3][0];/* Fixed 80MHz RU Table of 4 STA */
|
|
} else {
|
|
if (CHANNEL_WIDTH_20 == grp->sta[0].bw)
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_20[1][0];/* Fixed 20MHz RU Table of 2 STA */
|
|
else
|
|
f_ru_tbl = &snd->snd_param.fix_param.f_ru_tbl_80[1][0];/* Fixed 80MHz RU Table of 2 STA */
|
|
}
|
|
|
|
/* fill commmand */
|
|
rtw_hal_snd_ax_fwcmd_tb_pri(phl_info->hal, cmd, grp->sta[0].bw,
|
|
sta_info, grp->num_sta, 0);
|
|
/* Always use BFRP#0 for primary user */
|
|
rtw_hal_snd_ax_fwcmd_tb_add_sta(
|
|
phl_info->hal, cmd,
|
|
&grp->sta[0].npda_sta_info,
|
|
sta_info,
|
|
f_ru_tbl[0],
|
|
0,
|
|
0,
|
|
0);
|
|
|
|
/*get second sta*/
|
|
sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[1].macid);
|
|
|
|
rtw_hal_snd_ax_fwcmd_tb_add_sta(
|
|
phl_info->hal, cmd,
|
|
&grp->sta[1].npda_sta_info,
|
|
sta_info,
|
|
f_ru_tbl[1],
|
|
1,
|
|
(bfrp_num == 1) ? 0 : 0,
|
|
(bfrp_num == 1) ? 1 : 1);
|
|
/*get third sta*/
|
|
sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[2].macid);
|
|
|
|
rtw_hal_snd_ax_fwcmd_tb_add_sta(
|
|
phl_info->hal, cmd,
|
|
&grp->sta[2].npda_sta_info,
|
|
sta_info,
|
|
f_ru_tbl[2],
|
|
2,
|
|
(bfrp_num == 1) ? 0 : 1,
|
|
(bfrp_num == 1) ? 2 : 0);
|
|
|
|
/*get 4th sta*/
|
|
sta_info = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[3].macid);
|
|
|
|
rtw_hal_snd_ax_fwcmd_tb_add_sta(
|
|
phl_info->hal, cmd,
|
|
&grp->sta[3].npda_sta_info,
|
|
sta_info,
|
|
f_ru_tbl[3],
|
|
3,
|
|
(bfrp_num == 1) ? 0 : 1,
|
|
(bfrp_num == 1) ? 3 : 1);
|
|
|
|
}
|
|
|
|
|
|
enum rtw_phl_status
|
|
phl_snd_proc_start_sounding_fw(struct phl_info_t *phl_info,
|
|
struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
|
|
enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct phl_sound_param *snd_param = &snd->snd_param;
|
|
struct rtw_phl_stainfo_t *sta_info = NULL;
|
|
u8 *cmd = NULL;
|
|
u8 i = 0;
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "==> phl_snd_proc_start_sounding_fw \n");
|
|
do {
|
|
if (NULL == grp)
|
|
break;
|
|
if(grp->sta[0].valid == 0)
|
|
break;
|
|
|
|
/*get first sta*/
|
|
sta_info = rtw_phl_get_stainfo_by_macid(
|
|
phl_info, grp->sta[0].macid);
|
|
|
|
switch (grp->snd_type) {
|
|
case PHL_SND_TYPE_VHT_SW:
|
|
{
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "--> PHL_SND_TYPE_VHT_SW\n");
|
|
cmd = rtw_hal_snd_prepare_snd_cmd(phl_info->hal);
|
|
if (cmd == NULL)
|
|
break;
|
|
if (grp->num_sta == 1) {
|
|
rtw_hal_snd_vht_fwcmd_su(
|
|
phl_info->hal, cmd,
|
|
grp->sta[0].bw,
|
|
sta_info,
|
|
&grp->sta[0].npda_sta_info);
|
|
|
|
} else {
|
|
rtw_hal_snd_vht_fwcmd_mu_pri(
|
|
phl_info->hal, cmd,
|
|
grp->sta[0].bw,
|
|
sta_info,
|
|
grp->num_sta,
|
|
&grp->sta[0].npda_sta_info);
|
|
|
|
for (i = 1; i < grp->num_sta; i++) {
|
|
if(grp->sta[i].valid == 0)
|
|
break;
|
|
sta_info = rtw_phl_get_stainfo_by_macid(
|
|
phl_info, grp->sta[i].macid);
|
|
|
|
rtw_hal_snd_vht_fwcmd_mu_add_sta(
|
|
phl_info->hal, cmd,
|
|
&grp->sta[i].npda_sta_info,
|
|
sta_info,
|
|
i,
|
|
(i==(grp->num_sta-1)) ? 1 : 0
|
|
);
|
|
}
|
|
}
|
|
rtw_hal_snd_set_fw_cmd_dialogtkn(
|
|
phl_info->hal, cmd,
|
|
0,
|
|
snd_param->snd_dialog_token);
|
|
hstatus = rtw_hal_snd_send_fw_cmd(phl_info->hal, cmd);
|
|
if (hstatus != RTW_HAL_STATUS_SUCCESS) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
|
|
"ERROR: rtw_hal_snd_send_fw_cmd Fail!!!!\n");
|
|
}
|
|
/* free cmd buf at last !!! */
|
|
hstatus = rtw_hal_snd_release_snd_cmd(phl_info->hal, cmd);
|
|
}
|
|
break;
|
|
case PHL_SND_TYPE_HE_SW:
|
|
{
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "--> PHL_SND_TYPE_HE_SW\n");
|
|
cmd = rtw_hal_snd_prepare_snd_cmd(phl_info->hal);
|
|
if (cmd == NULL)
|
|
break;
|
|
if (grp->num_sta == 1) {
|
|
rtw_hal_snd_ax_fwcmd_nontb(
|
|
phl_info->hal, cmd,
|
|
grp->sta[0].bw,
|
|
sta_info,
|
|
&grp->sta[0].npda_sta_info);
|
|
} else {
|
|
/* Default use only 1 BFRP */
|
|
/* TODO: Fixed mode or when to use 2 BFRP */
|
|
if (grp->num_sta == 4)
|
|
_phl_snd_proc_fw_cmd_he_tb_4sta(
|
|
phl_info, grp, cmd, 1);
|
|
else if (grp->num_sta == 3)
|
|
_phl_snd_proc_fw_cmd_he_tb_3sta(
|
|
phl_info, grp, cmd, 1);
|
|
else if (grp->num_sta == 2)
|
|
_phl_snd_proc_fw_cmd_he_tb_2sta(
|
|
phl_info, grp, cmd, 1);
|
|
else
|
|
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");
|
|
}
|
|
rtw_hal_snd_set_fw_cmd_dialogtkn(
|
|
phl_info->hal, cmd,
|
|
1,
|
|
snd_param->snd_dialog_token);
|
|
|
|
hstatus = rtw_hal_snd_send_fw_cmd(phl_info->hal, cmd);
|
|
if (hstatus != RTW_HAL_STATUS_SUCCESS) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
|
|
"ERROR: rtw_hal_snd_send_fw_cmd Fail!!!!\n");
|
|
}
|
|
/* free cmd buf at last !!! */
|
|
hstatus = rtw_hal_snd_release_snd_cmd(phl_info->hal, cmd);
|
|
}
|
|
break;
|
|
case PHL_SND_TYPE_VHT_HW:
|
|
{
|
|
u8 dialog_tkn = (snd->snd_param.snd_dialog_token << 2);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
|
|
"PHL_SND_TYPE_VHT_HW:\n");
|
|
if(NULL == snd->ops.snd_send_ndpa)
|
|
break;
|
|
rtw_hal_snd_mac_ctrl(phl_info->hal, sta_info->wrole->hw_band, 0);
|
|
pstatus = snd->ops.snd_send_ndpa(
|
|
phl_to_drvpriv(phl_info),
|
|
sta_info->wrole,
|
|
&dialog_tkn,
|
|
&grp->sta[0].npda_sta_info,
|
|
grp->sta[0].bw);
|
|
}
|
|
break;
|
|
case PHL_SND_TYPE_HE_HW:
|
|
{
|
|
u8 dialog_tkn = (snd->snd_param.snd_dialog_token << 2) | BIT(1);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
|
|
"PHL_SND_TYPE_HE_HW:\n");
|
|
if(NULL == snd->ops.snd_send_ndpa)
|
|
break;
|
|
rtw_hal_snd_mac_ctrl(phl_info->hal, sta_info->wrole->hw_band, 0);
|
|
pstatus = snd->ops.snd_send_ndpa(
|
|
phl_to_drvpriv(phl_info),
|
|
sta_info->wrole,
|
|
&dialog_tkn,
|
|
&grp->sta[0].npda_sta_info,
|
|
grp->sta[0].bw);
|
|
}
|
|
break;
|
|
case PHL_SND_TYPE_INVALID:
|
|
default:
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "ERROR: grp->snd_type invalid\n");
|
|
break;
|
|
}
|
|
pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
} while (0);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "<== phl_snd_proc_start_sounding_fw \n");
|
|
return pstatus;
|
|
}
|
|
|
|
/* 4. Post Configruation */
|
|
|
|
/* BY MU_GID if MU Sounding */
|
|
enum rtw_phl_status
|
|
_phl_snd_proc_postcfg_mu_gid(struct phl_info_t *phl_info,
|
|
struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
|
|
struct rtw_phl_stainfo_t *psta_info = NULL;
|
|
struct phl_snd_sta *sta = NULL;
|
|
struct rtw_hal_muba_info ba_info;
|
|
u8 i = 0, j = 0;
|
|
u8 bfmu_idx;
|
|
u8 mugrp_bmp = 0;
|
|
u8 gid = 0xFF;
|
|
|
|
|
|
for (i = 0; i < MAX_NUM_STA_SND_GRP; i++) {
|
|
sta = &grp->sta[i];
|
|
if((false == sta->valid) || (NULL == sta->bf_entry))
|
|
continue;
|
|
|
|
bfmu_idx = rtw_hal_bf_get_sumu_idx(phl_info->hal,
|
|
sta->bf_entry);
|
|
|
|
psta_info = rtw_phl_get_stainfo_by_macid(
|
|
phl_info, sta->macid);
|
|
|
|
mugrp_bmp = psta_info->hal_sta->mugrp_bmp;
|
|
|
|
/* GID(X + Y)'s setting is same as GID(Y + X)*/
|
|
for (j = bfmu_idx; j < 5; j++) {
|
|
if (mugrp_bmp & BIT(j)) {
|
|
gid = _get_mu_mimo_gid_2sta(bfmu_idx, j + 1);
|
|
/*Prepare MU BAR Info*/
|
|
rtw_hal_bf_preset_mu_ba_info(phl_info->hal,
|
|
psta_info, &ba_info);
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "snd_post_cfg : gid = 0x%x \n", gid);
|
|
hstatus = rtw_hal_snd_proc_post_cfg_gid(
|
|
phl_info->hal,
|
|
gid,
|
|
(void *)&ba_info);
|
|
|
|
if (RTW_HAL_STATUS_SUCCESS != hstatus) {
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return pstatus;
|
|
}
|
|
/* Per STA setting */
|
|
enum rtw_phl_status
|
|
_phl_snd_proc_postcfg_sta(struct phl_info_t *phl_info,
|
|
struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct rtw_phl_stainfo_t *psta_info = NULL;
|
|
struct phl_snd_sta *sta = NULL;
|
|
u8 idx = 0;
|
|
bool mu = false;
|
|
|
|
/*post config for a single sta*/
|
|
for (idx = 0; idx < MAX_NUM_STA_SND_GRP; idx++) {
|
|
sta = &grp->sta[idx];
|
|
mu = (sta->snd_fb_t == PHL_SND_FB_TYPE_MU) ? true : false;
|
|
if (false == sta->valid)
|
|
continue;
|
|
|
|
psta_info = rtw_phl_get_stainfo_by_macid(phl_info, sta->macid);
|
|
if (NULL == psta_info)
|
|
continue;
|
|
|
|
rtw_hal_snd_polling_snd_sts(phl_info->hal, psta_info);
|
|
if (RTW_HAL_STATUS_SUCCESS ==
|
|
rtw_hal_bf_get_entry_snd_sts(psta_info->hal_sta->bf_entry)) {
|
|
sta->snd_sts = PHL_SND_STS_SUCCESS;
|
|
} else {
|
|
sta->snd_sts = PHL_SND_STS_FAILURE;
|
|
}
|
|
|
|
if ((PHL_SND_STS_SUCCESS != sta->snd_sts) &&
|
|
(false == snd->snd_param.bypass_snd_sts_chk)) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "SKIP STA Post Config because of sounding fail\n");
|
|
continue; /*Sounding Fail, Next STA */
|
|
}
|
|
|
|
hstatus = rtw_hal_snd_proc_post_cfg_sta(phl_info->hal,
|
|
psta_info, mu);
|
|
|
|
if (hstatus != RTW_HAL_STATUS_SUCCESS) {
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
}
|
|
}
|
|
|
|
return pstatus;
|
|
}
|
|
/* SND PROC Post Config API for FSM */
|
|
enum rtw_phl_status
|
|
phl_snd_proc_postcfg(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
|
|
bool mu = false, he = true;
|
|
|
|
FUNCIN();
|
|
|
|
do {
|
|
if (grp == NULL) {
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
break;
|
|
}
|
|
he = (grp->snd_type >= PHL_SND_TYPE_HE_HW) ? true : false;
|
|
mu = (grp->sta[0].snd_fb_t == PHL_SND_FB_TYPE_MU) ? true :
|
|
false;
|
|
|
|
/* 1. post config for whole sounding group */
|
|
if (grp->skip_post_cfg & BIT(1)) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "SKIP SND PROC POST CFG - Group \n");
|
|
} else {
|
|
hstatus = rtw_hal_snd_proc_post_cfg(
|
|
phl_info->hal,
|
|
he,
|
|
mu,
|
|
grp->en_fix_mode);
|
|
if (hstatus != RTW_HAL_STATUS_SUCCESS) {
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
}
|
|
}
|
|
|
|
/* 2. post config for gid (STA + STA) */
|
|
if (grp->skip_post_cfg & BIT(2)) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "SKIP SND PROC POST CFG - GID \n");
|
|
} else {
|
|
if (true == mu) {
|
|
/* only mu sounding has gid related config */
|
|
_phl_snd_proc_postcfg_mu_gid(phl_info, grp);
|
|
}
|
|
}
|
|
|
|
/* 3. (Shall always at last) post config for each STA in group */
|
|
if (grp->skip_post_cfg & BIT(3)) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "SKIP SND PROC POST CFG - STA \n");
|
|
} else {
|
|
_phl_snd_proc_postcfg_sta(phl_info, grp);
|
|
}
|
|
|
|
} while (0);
|
|
|
|
FUNCOUT();
|
|
return pstatus;
|
|
}
|
|
|
|
/* SND_PROC_DOWN --> Next Sounding : Check sounding module status */
|
|
enum rtw_phl_status
|
|
phl_snd_proc_chk_condition(struct phl_info_t *phl_info, struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
|
|
struct phl_sound_obj *snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
struct rtw_wifi_role_t *role =
|
|
(struct rtw_wifi_role_t *)snd->snd_param.m_wrole;
|
|
struct phl_snd_sta *sta = NULL;
|
|
struct rtw_phl_stainfo_t *psta = NULL;
|
|
struct phl_sound_param *para = &snd->snd_param;
|
|
u8 i = 0;
|
|
u8 terminate = 0;
|
|
/* TODO: Add any conditions to stop the sounding fsm here */
|
|
do {
|
|
if (true == snd->is_terminated)
|
|
break;
|
|
|
|
if (NULL != role) {
|
|
if (PHL_RTYPE_STATION == role->type) {
|
|
if (MLME_NO_LINK == role->mstate)
|
|
break;
|
|
psta = rtw_phl_get_stainfo_self(phl_info, role);
|
|
if (rtw_hal_bf_get_entry_snd_sts(
|
|
psta->hal_sta->bf_entry)) {
|
|
para->snd_fail_counter++;
|
|
if (para->snd_fail_counter > 10) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_ ,
|
|
"Sounding Fail Count > 10, break sounding !!!!\n");
|
|
break;
|
|
}
|
|
} else {
|
|
para->snd_fail_counter = 0;
|
|
}
|
|
} else if (PHL_RTYPE_AP == role->type) {
|
|
if (false == role->active)
|
|
break;
|
|
if (grp->sta[0].bw > role->chandef.bw)
|
|
break;
|
|
if (0 == grp->num_sta)
|
|
break;
|
|
for (i = 0; i < grp->num_sta; i++) {
|
|
sta = &grp->sta[i];
|
|
psta = rtw_phl_get_stainfo_by_macid(phl_info, sta->macid);
|
|
if (NULL == psta) {
|
|
terminate = 1;
|
|
break;
|
|
}
|
|
if (false == psta->active) {
|
|
terminate = 1;
|
|
break;
|
|
}
|
|
if (sta->bw != psta->chandef.bw) {
|
|
terminate = 1;
|
|
break;
|
|
}
|
|
}
|
|
if(terminate)
|
|
break;
|
|
}
|
|
}
|
|
|
|
pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
} while (0);
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Check the previous sounding group sounding status and free the resource.
|
|
* if grp is TIER0 grp, skip release BF/CQI resource.
|
|
**/
|
|
void
|
|
phl_snd_proc_chk_prev_grp(struct phl_info_t *phl_info,
|
|
struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
bool free_res = false;
|
|
|
|
if (PHL_SND_STS_FAILURE == grp->snd_sts) {
|
|
/* Sounding Fail */
|
|
free_res = true;
|
|
} else if ((PHL_SND_GRP_TIER_1 == grp->grp_tier) && (PHL_SND_STS_PENDING != grp->snd_sts)) {
|
|
/* Sounding Success and Group is TIER_1 */
|
|
free_res = true;
|
|
}
|
|
|
|
if (free_res) {
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_, "Free Previous SND Group's Resource\n");
|
|
pstatus = phl_snd_proc_release_res(phl_info, grp);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
enum rtw_phl_status
|
|
phl_snd_polling_pri_sta_sts(struct phl_info_t *phl_info,
|
|
struct phl_snd_grp *grp)
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
struct rtw_phl_stainfo_t *sta = NULL;
|
|
|
|
PHL_TRACE(COMP_PHL_SOUND, _PHL_INFO_,
|
|
"phl_snd_polling_stutus : polling primay sta sounding status\n");
|
|
sta = rtw_phl_get_stainfo_by_macid(phl_info, grp->sta[0].macid);
|
|
if (sta != NULL) {
|
|
if (sta->active == true)
|
|
rtw_hal_snd_polling_snd_sts(phl_info->hal, sta);
|
|
else
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
} else {
|
|
pstatus = RTW_PHL_STATUS_FAILURE;
|
|
}
|
|
|
|
return pstatus;
|
|
}
|
|
|
|
void
|
|
phl_snd_mac_ctrl(struct phl_info_t *phl_info,
|
|
struct rtw_wifi_role_t *wrole, u8 ctrl)
|
|
{
|
|
enum rtw_hal_status hstatus = RTW_HAL_STATUS_SUCCESS;
|
|
hstatus = rtw_hal_snd_mac_ctrl(phl_info->hal, wrole->hw_band, ctrl);
|
|
}
|
|
|
|
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))
|
|
{
|
|
enum rtw_phl_status pstatus = RTW_PHL_STATUS_FAILURE;
|
|
struct phl_info_t *phl_info = (struct phl_info_t *)phl;
|
|
struct phl_sound_obj *snd = NULL;
|
|
if((phl_info != NULL) && (snd_send_ndpa != NULL)) {
|
|
if (phl_info->snd_obj != NULL) {
|
|
snd = (struct phl_sound_obj *)phl_info->snd_obj;
|
|
snd->ops.snd_send_ndpa = snd_send_ndpa;
|
|
pstatus = RTW_PHL_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
return pstatus;
|
|
} |