2025-05-10 21:58:58 +08:00

830 lines
23 KiB
C

/******************************************************************************
*
* Copyright(c) 2019 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.
*
*****************************************************************************/
#define _HAL_STA_C_
#include "hal_headers.h"
void
_hal_sta_rssi_init(struct rtw_phl_stainfo_t *sta)
{
sta->hal_sta->rssi_stat.assoc_rssi = 0;
sta->hal_sta->rssi_stat.ma_rssi = 0;
}
static enum rtw_hal_status
_hal_bfee_init(struct hal_info_t *hal_info,
struct rtw_phl_stainfo_t *sta)
{
enum rtw_hal_status hstatus = RTW_HAL_STATUS_FAILURE;
struct rtw_wifi_role_t *wrole = NULL;
bool enable_bfee = false;
do {
if(NULL == sta)
break;
wrole = sta->wrole;
if(NULL == wrole)
break;
/*only init BFee when wrole cap's bfee and sta cap 's bfer matched */
if ((wrole->proto_role_cap.he_su_bfme ||
wrole->proto_role_cap.he_mu_bfme) &&
(sta->asoc_cap.he_su_bfmr || sta->asoc_cap.he_mu_bfmr)) {
enable_bfee = true;
}
if ((wrole->proto_role_cap.vht_su_bfme ||
wrole->proto_role_cap.vht_mu_bfme) &&
(sta->asoc_cap.vht_su_bfmr || sta->asoc_cap.vht_mu_bfmr)) {
enable_bfee = true;
}
if (wrole->proto_role_cap.ht_su_bfme &&
sta->asoc_cap.ht_su_bfmr)
enable_bfee = true;
if (true == enable_bfee) {
/* BFee Functions */
if (RTW_HAL_STATUS_SUCCESS !=
hal_bf_hw_mac_init_bfee(hal_info,
sta->wrole->hw_band)) {
PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
"%s : Init HW MAC BFee Fail\n",
__func__);
break;
}
/* BFee CSI parameters*/
hal_info->hal_com->csi_para_ctrl_sel = false;
if (RTW_HAL_STATUS_SUCCESS !=
hal_bf_set_bfee_csi_para(hal_info,
hal_info->hal_com->csi_para_ctrl_sel,
sta)) {
PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
"%s : Set BFee CSI Para Fail\n",
__func__);
break;
}
#ifdef RTW_WKARD_DYNAMIC_BFEE_CAP
/* BB Workaround */
rtw_hal_bb_dcr_en(hal_info, true);
#endif
PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_,
"%s : Enable HW BFee Function Success\n",
__func__);
}
hstatus = RTW_HAL_STATUS_SUCCESS;
} while (0);
return hstatus;
}
static enum rtw_hal_status
_hal_set_default_cctrl_tbl(struct hal_info_t *hal_info,
struct rtw_phl_stainfo_t *sta)
{
enum rtw_hal_status sts = RTW_HAL_STATUS_FAILURE;
struct rtw_hal_mac_ax_cctl_info cctrl, cctl_info_mask;
#ifdef RTW_WKARD_DEF_CMACTBL_CFG
u16 cfg;
enum rf_path path = (hal_info->hal_com->rfpath_tx_num == 1)?RF_PATH_B:RF_PATH_AB;
#endif
_os_mem_set(hal_to_drvpriv(hal_info), &cctrl, 0, sizeof(struct rtw_hal_mac_ax_cctl_info));
_os_mem_set(hal_to_drvpriv(hal_info), &cctl_info_mask, 0, sizeof(struct rtw_hal_mac_ax_cctl_info));
if (NULL == sta)
goto out;
cctrl.txpwr_mode = 0;
cctl_info_mask.txpwr_mode = 0x7;
#ifdef RTW_WKARD_DEF_CMACTBL_CFG
cfg = rtw_hal_bb_cfg_cmac_tx_ant(hal_info, path);
cctrl.ntx_path_en = cfg & 0x0f;
cctl_info_mask.ntx_path_en = 0xF;
cctrl.path_map_a = ((cfg>>4) & 0x03);
cctl_info_mask.path_map_a = 0x3;
cctrl.path_map_b = ((cfg>>6) & 0x03);
cctl_info_mask.path_map_b = 0x3;
cctrl.path_map_c = ((cfg>>8) & 0x03);
cctl_info_mask.path_map_c = 0x3;
cctrl.path_map_d = ((cfg>>10) & 0x03);
cctl_info_mask.path_map_d = 0x3;
#else
cctrl.ntx_path_en = 0x3;
cctl_info_mask.ntx_path_en = 0xF;
cctrl.path_map_a = 0x0;
cctl_info_mask.path_map_a = 0x3;
cctrl.path_map_b = 0x1;
cctl_info_mask.path_map_b = 0x3;
cctrl.path_map_c = 0x2;
cctl_info_mask.path_map_c = 0x3;
cctrl.path_map_d = 0x3;
cctl_info_mask.path_map_d = 0x3;
#endif
cctrl.antsel_a = 0x0;
cctl_info_mask.antsel_a = 0x1;
cctrl.antsel_b = 0x0;
cctl_info_mask.antsel_b = 0x1;
cctrl.antsel_c = 0x0;
cctl_info_mask.antsel_c = 0x1;
cctrl.antsel_d = 0x0;
cctl_info_mask.antsel_d = 0x1;
cctrl.doppler_ctrl = 0;
cctl_info_mask.doppler_ctrl = 0x3;
cctrl.txpwr_tolerence = 0;
cctl_info_mask.txpwr_tolerence = 0xF;
#ifdef CONFIG_PHL_DEFAULT_MGNT_Q_RPT_EN
cctrl.mgq_rpt_en = 1;
cctl_info_mask.mgq_rpt_en = 1;
#endif
sts = rtw_hal_cmc_tbl_cfg(hal_info, &cctrl ,&cctl_info_mask, sta->macid);
out:
return sts;
}
static enum rtw_hal_status
_hal_update_cctrl_tbl(struct hal_info_t *hal_info,
struct rtw_phl_stainfo_t *sta)
{
struct rtw_wifi_role_t *wrole = sta->wrole;
enum rtw_hal_status sts = RTW_HAL_STATUS_FAILURE;
struct rtw_hal_mac_ax_cctl_info cctrl, cctl_info_mask;
_os_mem_set(hal_to_drvpriv(hal_info), &cctrl, 0, sizeof(struct rtw_hal_mac_ax_cctl_info));
_os_mem_set(hal_to_drvpriv(hal_info), &cctl_info_mask, 0, sizeof(struct rtw_hal_mac_ax_cctl_info));
if (NULL == sta)
goto out;
/*TODO - update cctrl tab from stainfo*/
cctrl.disrtsfb = 1;
cctl_info_mask.disrtsfb = 1;
cctrl.disdatafb = 1;
cctl_info_mask.disdatafb = 1;
/*
if (!cctrl.disdatafb)
cctrl.arfr_ctrl = rtw_hal_bb_get_arfr_idx(hal_info, sta);
*/
if (wrole->cap.rty_lmt_rts == 0xFF) {
cctrl.rts_txcnt_lmt_sel = 0;
} else {
cctrl.rts_txcnt_lmt_sel = 1;
cctrl.rts_txcnt_lmt = wrole->cap.rty_lmt_rts & 0xF;
cctl_info_mask.rts_txcnt_lmt = 0xF;
}
cctl_info_mask.rts_txcnt_lmt_sel = 1;
cctrl.rts_rty_lowest_rate = (sta->chandef.band == BAND_ON_24G) ? (RTW_DATA_RATE_CCK1) : (RTW_DATA_RATE_OFDM6);
cctl_info_mask.rts_rty_lowest_rate = 0xF;
if (wrole->cap.rty_lmt == 0xFF) {
cctrl.data_txcnt_lmt_sel = 0;
} else {
cctrl.data_txcnt_lmt_sel = 1;
cctrl.data_tx_cnt_lmt = wrole->cap.rty_lmt & 0x3F;
cctl_info_mask.data_tx_cnt_lmt = 0x3F;
}
cctl_info_mask.data_txcnt_lmt_sel = 1;
/* hana_todo: follow wd agg_num settings before updating cmac tbl while addba handshake is ready */
/* cctrl.max_agg_num_sel = 1;
cctl_info_mask.max_agg_num_sel = 1;
cctrl.max_agg_num = sta->asoc_cap.num_ampdu - 1;
cctl_info_mask.max_agg_num = 0xFF;
*/
if (cctrl.max_agg_num > 0x3F) {
cctrl.ba_bmap = 1;
cctl_info_mask.ba_bmap = 0x3;
}
if (sta->wrole->type == PHL_RTYPE_STATION || sta->wrole->type == PHL_RTYPE_TDLS) {
cctrl.uldl = 1;
cctl_info_mask.uldl = 1;
} else {
cctrl.uldl = 0;
cctl_info_mask.uldl = 1;
}
cctrl.multi_port_id = sta->wrole->hw_port;
cctl_info_mask.multi_port_id = 0x7;
if (sta->wrole->type == PHL_RTYPE_AP) {
cctrl.data_dcm = 0; /*(sta->asoc_cap.dcm_max_const_rx > 0)*/
cctl_info_mask.data_dcm = 1;
}
if (sta->asoc_cap.pkt_padding == 3) {
/* follow PPE threshold */
u8 ppe16 = 0, ppe8 = 0;
u8 nss = sta->asoc_cap.nss_rx;
/* bw = 20MHz */
ppe16 = (sta->asoc_cap.ppe_thr[nss - 1][CHANNEL_WIDTH_20] & 0x7);
ppe8 = (sta->asoc_cap.ppe_thr[nss - 1][CHANNEL_WIDTH_20]>>3) & 0x7;
if ((ppe16 != 7) && (ppe8 == 7)) {
cctrl.nominal_pkt_padding = 2;
cctl_info_mask.nominal_pkt_padding = 0x3;
} else if (ppe8 != 7) {
cctrl.nominal_pkt_padding = 1;
cctl_info_mask.nominal_pkt_padding = 0x3;
} else {
cctrl.nominal_pkt_padding = 0;
cctl_info_mask.nominal_pkt_padding = 0x3;
}
/* bw = 40MHz */
ppe16 = (sta->asoc_cap.ppe_thr[nss - 1][CHANNEL_WIDTH_40] & 0x7);
ppe8 = (sta->asoc_cap.ppe_thr[nss - 1][CHANNEL_WIDTH_40]>>3) & 0x7;
if ((ppe16 != 7) && (ppe8 == 7)) {
cctrl.nominal_pkt_padding40 = 2;
cctl_info_mask.nominal_pkt_padding40 = 0x3;
} else if (ppe8 != 7) {
cctrl.nominal_pkt_padding40 = 1;
cctl_info_mask.nominal_pkt_padding40 = 0x3;
} else {
cctrl.nominal_pkt_padding40 = 0;
cctl_info_mask.nominal_pkt_padding40 = 0x3;
}
/* bw = 80MHz */
ppe16 = (sta->asoc_cap.ppe_thr[nss - 1][CHANNEL_WIDTH_80] & 0x7);
ppe8 = (sta->asoc_cap.ppe_thr[nss - 1][CHANNEL_WIDTH_80]>>3) & 0x7;
if ((ppe16 != 7) && (ppe8 == 7)) {
cctrl.nominal_pkt_padding80 = 2;
cctl_info_mask.nominal_pkt_padding80 = 0x3;
} else if (ppe8 != 7) {
cctrl.nominal_pkt_padding80 = 1;
cctl_info_mask.nominal_pkt_padding80 = 0x3;
} else {
cctrl.nominal_pkt_padding80 = 0;
cctl_info_mask.nominal_pkt_padding80 = 0x3;
}
} else {
cctrl.nominal_pkt_padding = sta->asoc_cap.pkt_padding;
cctrl.nominal_pkt_padding40 = sta->asoc_cap.pkt_padding;
cctrl.nominal_pkt_padding80 = sta->asoc_cap.pkt_padding;
cctl_info_mask.nominal_pkt_padding = 0x3;
cctl_info_mask.nominal_pkt_padding40 = 0x3;
cctl_info_mask.nominal_pkt_padding80 = 0x3;
}
if (sta->wmode&WLAN_MD_11AX) {
/**
* bsr_queue_size_format:
* 1: buffer status unit is 802.11, HE mode
* 0: buffer status unit is 802.11, legacy mode
**/
cctrl.bsr_queue_size_format = 1;
cctl_info_mask.bsr_queue_size_format = 1;
}
sts = rtw_hal_cmc_tbl_cfg(hal_info, &cctrl, &cctl_info_mask, sta->macid);
out:
return sts;
}
static enum rtw_hal_status
_hal_update_dctrl_tbl(struct hal_info_t *hal_info,
struct rtw_phl_stainfo_t *sta)
{
enum rtw_hal_status sts = RTW_HAL_STATUS_FAILURE;
struct mac_ax_dctl_info dctrl, dctl_info_mask;
if (NULL == sta)
goto out;
_os_mem_set(hal_to_drvpriv(hal_info), &dctrl, 0, sizeof(struct mac_ax_dctl_info));
_os_mem_set(hal_to_drvpriv(hal_info), &dctl_info_mask, 0, sizeof(struct mac_ax_dctl_info));
#ifdef CONFIG_PHL_CSUM_OFFLOAD_RX
dctrl.chksum_offload_en = 1;
dctl_info_mask.chksum_offload_en = 1;
dctrl.with_llc = 1;
dctl_info_mask.with_llc = 1;
#endif /*CONFIG_PHL_CSUM_OFFLOAD_RX*/
sts = rtw_hal_dmc_tbl_cfg(hal_info, &dctrl, &dctl_info_mask, sta->macid);
out:
return sts;
}
enum rtw_hal_status
_hal_update_ba_cam(struct hal_info_t *hal_info, u8 valid, u16 macid,
u8 dialog_token, u16 timeout, u16 start_seq_num,
u16 ba_policy, u16 tid, u16 buf_size, u8 camid)
{
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
void *drv = hal_to_drvpriv(hal_info);
struct mac_ax_bacam_info ba_cam = {0};
FUNCIN();
_os_mem_set(drv, &ba_cam, 0, sizeof(ba_cam));
ba_cam.valid = valid;
ba_cam.init_req = 1;
ba_cam.entry_idx = camid;
ba_cam.tid = tid;
ba_cam.macid = (u8)macid;
if (buf_size > 64)
ba_cam.bmap_size = 4;
else
ba_cam.bmap_size = 0;
ba_cam.ssn = start_seq_num;
PHL_INFO("[BACAM] ba_cam.valid = %d, ba_cam.init_req = %d, ba_cam.entry_idx = %d\n",
ba_cam.valid,
ba_cam.init_req,
ba_cam.entry_idx);
PHL_INFO("[BACAM] ba_cam.tid = %d, ba_cam.macid = %d, ba_cam.bmap_size = %d\n",
ba_cam.tid,
ba_cam.macid,
ba_cam.bmap_size);
PHL_INFO("[BACAM] ba_cam.ssn = 0x%X\n",
ba_cam.ssn);
hal_status = rtw_hal_bacam_cfg(hal_info, &ba_cam);
if (RTW_HAL_STATUS_FAILURE == hal_status) {
PHL_WARN("rtw_hal_bacam_cfg fail 0x%08X\n", hal_status);
}
FUNCOUT();
return hal_status;
}
enum rtw_hal_status
rtw_hal_start_ba_session(void *hal, struct rtw_phl_stainfo_t *sta,
u8 dialog_token, u16 timeout, u16 start_seq_num,
u16 ba_policy, u16 tid, u16 buf_size)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
u8 idx = 0;
if (sta->hal_sta->ba_ctl.count == MAX_BAENTRY) {
PHL_INFO("No avail standard entry found\n");
if (tid != 0)
goto out;
else {
for (idx = 0; idx < MAX_BAENTRY; idx++) {
if (sta->hal_sta->ba_ctl.tid[idx] != 0) {
PHL_INFO("Remove old entry(%d) tid(%d)\n",
idx, sta->hal_sta->ba_ctl.tid[idx]);
hal_status = _hal_update_ba_cam(hal_info, 0, sta->macid, 0,
0, 0, 0, 0, 0, idx);
if (hal_status == RTW_HAL_STATUS_SUCCESS) {
sta->hal_sta->ba_ctl.used_map[idx] = false;
sta->hal_sta->ba_ctl.count--;
break;
}
} else {
PHL_INFO("Use existing entry(%d)\n", idx);
sta->hal_sta->ba_ctl.used_map[idx] = false;
sta->hal_sta->ba_ctl.count--;
break;
}
}
}
}
for (idx = 0; idx < MAX_BAENTRY; idx++) {
if (!sta->hal_sta->ba_ctl.used_map[idx])
break;
}
if (idx == MAX_BAENTRY) {
PHL_WARN("No avail standard entry found but count is(%d)\n",
sta->hal_sta->ba_ctl.count);
goto out;
}
hal_status = _hal_update_ba_cam(hal_info, 1, sta->macid, dialog_token,
timeout, start_seq_num, ba_policy, tid,
buf_size, idx);
if (RTW_HAL_STATUS_SUCCESS != hal_status)
goto out;
sta->hal_sta->ba_ctl.used_map[idx] = 1;
sta->hal_sta->ba_ctl.tid[idx] = (u8)tid;
sta->hal_sta->ba_ctl.count++;
out:
return hal_status;
}
enum rtw_hal_status
rtw_hal_stop_ba_session(void *hal, struct rtw_phl_stainfo_t *sta, u16 tid)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
u8 i;
for (i = 0; i < MAX_BAENTRY; i++) {
if (sta->hal_sta->ba_ctl.used_map[i] &&
((u8)tid == sta->hal_sta->ba_ctl.tid[i])) {
hal_status = _hal_update_ba_cam(hal_info, 0, sta->macid, 0,
0, 0, 0, 0, 0, i);
break;
}
}
if (RTW_HAL_STATUS_SUCCESS != hal_status)
goto out;
sta->hal_sta->ba_ctl.used_map[i] = 0;
sta->hal_sta->ba_ctl.tid[i] = 0xff;
sta->hal_sta->ba_ctl.count--;
out:
return hal_status;
}
enum rtw_hal_status
rtw_hal_stainfo_init(void *hal, struct rtw_phl_stainfo_t *sta)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
void *drv = hal_to_drvpriv(hal_info);
sta->hal_sta = _os_mem_alloc(drv, sizeof(struct rtw_hal_stainfo_t));
if (sta->hal_sta == NULL) {
PHL_ERR("alloc hal_sta failed\n");
goto error_exit;
}
/* alloc trx_stats */
sta->hal_sta->trx_stat.wp_rpt_stats =_os_mem_alloc(drv,
sizeof(struct rtw_wp_rpt_stats) * PHL_AC_QUEUE_TOTAL);
if (sta->hal_sta->trx_stat.wp_rpt_stats == NULL) {
PHL_ERR("alloc wp_rpt_stats failed\n");
goto error_rpt_stats;
}
sta->hal_sta->hw_cfg_tab =
_os_mem_alloc(drv, sizeof(struct rtw_hw_cfg_tab));
if (sta->hal_sta->hw_cfg_tab == NULL) {
PHL_ERR("alloc hw_cfg_tab failed\n");
goto error_hsta_mem;
}
hal_status = rtw_hal_bb_stainfo_init(hal_info, sta);
if (hal_status != RTW_HAL_STATUS_SUCCESS) {
PHL_ERR("alloc bb_stainfo failed\n");
goto error_hw_cfg_tab;
}
/* Init lock for tx statistics */
_os_spinlock_init(drv, &sta->hal_sta->trx_stat.tx_sts_lock);
/* Init STA RSSI Statistics */
_hal_sta_rssi_init(sta);
return hal_status;
error_hw_cfg_tab :
if (sta->hal_sta->hw_cfg_tab) {
_os_mem_free(drv, sta->hal_sta->hw_cfg_tab,
sizeof(struct rtw_hw_cfg_tab));
sta->hal_sta->hw_cfg_tab = NULL;
}
error_hsta_mem :
if (sta->hal_sta->trx_stat.wp_rpt_stats) {
_os_mem_free(drv, sta->hal_sta->trx_stat.wp_rpt_stats,
sizeof(struct rtw_wp_rpt_stats) * PHL_AC_QUEUE_TOTAL);
sta->hal_sta->trx_stat.wp_rpt_stats = NULL;
}
error_rpt_stats :
if (sta->hal_sta) {
_os_mem_free(drv, sta->hal_sta,
sizeof(struct rtw_hal_stainfo_t));
sta->hal_sta = NULL;
}
error_exit :
return hal_status;
}
enum rtw_hal_status
rtw_hal_stainfo_deinit(void *hal, struct rtw_phl_stainfo_t *sta)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
void *drv = hal_to_drvpriv(hal_info);
if (sta->hal_sta) {
/* Free lock for tx statistics */
_os_spinlock_free(drv, &sta->hal_sta->trx_stat.tx_sts_lock);
if (sta->hal_sta->trx_stat.wp_rpt_stats) {
_os_mem_free(drv, sta->hal_sta->trx_stat.wp_rpt_stats,
sizeof(struct rtw_wp_rpt_stats) * PHL_AC_QUEUE_TOTAL);
sta->hal_sta->trx_stat.wp_rpt_stats = NULL;
}
hal_status = rtw_hal_bb_stainfo_deinit(hal_info, sta);
if (hal_status != RTW_HAL_STATUS_SUCCESS)
PHL_ERR("bb_stainfo deinit failed\n");
if (sta->hal_sta->hw_cfg_tab) {
_os_mem_free(drv, sta->hal_sta->hw_cfg_tab,
sizeof(struct rtw_hw_cfg_tab));
sta->hal_sta->hw_cfg_tab = NULL;
}
_os_mem_free(drv, sta->hal_sta,
sizeof(struct rtw_hal_stainfo_t));
sta->hal_sta = NULL;
}
return hal_status;
}
static void _hal_sta_set_default_value(struct hal_info_t *hal_info,
struct rtw_phl_stainfo_t *sta)
{
u8 i;
sta->hal_sta->ra_info.ra_registered = false;
sta->hal_sta->ba_ctl.count = 0;
for (i = 0; i<MAX_BAENTRY; i++) {
sta->hal_sta->ba_ctl.tid[i] = 0xff;
sta->hal_sta->ba_ctl.used_map[i] = 0;
}
}
enum rtw_hal_status
rtw_hal_add_sta_entry(void *hal, struct rtw_phl_stainfo_t *sta)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
_hal_sta_set_default_value(hal_info, sta);
/*add mac address-cam*/
if (rtw_hal_mac_addr_cam_add_entry(hal_info, sta) !=
RTW_HAL_STATUS_SUCCESS) {
PHL_ERR("rtw_hal_mac_addr_cam_add_entry failed\n");
goto _exit;
}
/*update default cmac table*/
if (_hal_set_default_cctrl_tbl(hal_info, sta) !=
RTW_HAL_STATUS_SUCCESS) {
PHL_WARN("_hal_set_default_cctrl_tbl failed\n");
/* goto _exit; */ /* shall be unmark after header FW is ready */
}
if (_hal_update_dctrl_tbl(hal_info, sta) !=
RTW_HAL_STATUS_SUCCESS) {
PHL_WARN("_hal_set_default_dctrl_tbl failed\n");
/* goto _exit; */
}
/*add bb stainfo*/
if (rtw_hal_bb_stainfo_add(hal_info, sta) !=
RTW_HAL_STATUS_SUCCESS) {
PHL_ERR("rtw_hal_bb_stainfo_add failed\n");
goto _err_bbsta_add;
}
return RTW_HAL_STATUS_SUCCESS;
_err_bbsta_add:
rtw_hal_mac_addr_cam_del_entry(hal_info, sta);
_exit:
return RTW_HAL_STATUS_FAILURE;
}
enum rtw_hal_status
rtw_hal_update_sta_entry(void *hal, struct rtw_phl_stainfo_t *sta,
bool is_connect)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
enum phl_upd_mode mode = PHL_UPD_STA_CON_DISCONN;
/*update cmac table*/
if (RTW_HAL_STATUS_SUCCESS != _hal_update_cctrl_tbl(hal_info, sta))
PHL_WARN("_hal_update_cctrl_tbl failed\n");
/*update dmac table*/
if (RTW_HAL_STATUS_SUCCESS != _hal_update_dctrl_tbl(hal_info, sta))
PHL_WARN("_hal_update_dctrl_tbl failed\n");
/*change mac address-cam & mac_h2c_join_info*/
hal_status = rtw_hal_mac_addr_cam_change_entry(hal_info, sta, mode, is_connect);
if (hal_status != RTW_HAL_STATUS_SUCCESS) {
PHL_ERR("rtw_hal_mac_addr_cam_change_entry failed\n");
}
if (is_connect) {
if (RTW_HAL_STATUS_SUCCESS != _hal_bfee_init(hal_info, sta)) {
PHL_ERR("_hal_bfee_init Fail!\n");
}
if (sta->hal_sta->rssi_stat.assoc_rssi == 0
#ifdef CONFIG_PHL_TDLS
/* There is no association frame for TDLS connection */
&& sta->wrole->type != PHL_RTYPE_TDLS
#endif
) {
PHL_ERR("%s macid:%d assoc_rssi == 0\n", __func__, sta->macid);
_os_warn_on(1);
}
hal_status = rtw_hal_bb_upt_ramask(hal_info, sta);
if (hal_status != RTW_HAL_STATUS_SUCCESS)
PHL_ERR("rtw_hal_bb_upt_ramask failed\n");
hal_status = rtw_hal_bb_ra_register(hal_info, sta);
if (hal_status != RTW_HAL_STATUS_SUCCESS)
PHL_ERR("rtw_hal_bb_ra_register failed\n");
hal_info->hal_com->assoc_sta_cnt++;
if (sta->wmode & WLAN_MD_11AX) {
rtw_hal_bb_set_sta_id(hal_info, sta->aid, sta->wrole->hw_band);
rtw_hal_bb_set_bss_color(hal_info, sta->asoc_cap.bsscolor,
sta->wrole->hw_band);
rtw_hal_bb_set_tb_pwr_ofst(hal_info, 0, sta->wrole->hw_band);
}
/* reset rssi stat value */
sta->hal_sta->rssi_stat.ma_rssi_mgnt = 0;
}
else {
hal_status = rtw_hal_bb_ra_deregister(hal_info, sta);
if (hal_status != RTW_HAL_STATUS_SUCCESS)
PHL_ERR("rtw_hal_bb_ra_deregister failed\n");
hal_info->hal_com->assoc_sta_cnt--;
/* reset drv rssi_stat */
_hal_sta_rssi_init(sta);
_hal_sta_set_default_value(hal_info, sta);
}
/* reset bb rssi_stat */
rtw_hal_bb_media_status_update(hal_info, sta, is_connect);
return hal_status;
}
enum rtw_hal_status
rtw_hal_change_sta_entry(void *hal, struct rtw_phl_stainfo_t *sta,
enum phl_upd_mode mode)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
bool is_connect = false;
PHL_TRACE(COMP_PHL_DBG, _PHL_INFO_, "%s: sta->macid(0x%X), mode(%d)\n",
__FUNCTION__, sta->macid , mode);
/*update cmac table*/
if (RTW_HAL_STATUS_SUCCESS != _hal_update_cctrl_tbl(hal_info, sta))
PHL_WARN("_hal_update_cctrl_tbl failed\n");
/*update dmac table*/
if (RTW_HAL_STATUS_SUCCESS != _hal_update_dctrl_tbl(hal_info, sta))
PHL_WARN("_hal_update_dctrl_tbl failed\n");
/*change mac address-cam & mac_h2c_join_info */
is_connect = (sta->wrole->mstate == MLME_LINKED) ? true : false;
hal_status = rtw_hal_mac_addr_cam_change_entry(hal_info, sta, mode, is_connect);
if (hal_status != RTW_HAL_STATUS_SUCCESS)
PHL_ERR("rtw_hal_mac_addr_cam_change_entry failed\n");
hal_status = rtw_hal_bb_ra_update(hal_info, sta);
if (hal_status != RTW_HAL_STATUS_SUCCESS)
PHL_ERR("rtw_hal_bb_ra_update failed\n");
return hal_status;
}
enum rtw_hal_status
rtw_hal_del_sta_entry(void *hal, struct rtw_phl_stainfo_t *sta)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
enum rtw_hal_status hal_status = RTW_HAL_STATUS_FAILURE;
_hal_sta_set_default_value(hal_info, sta);
hal_status = rtw_hal_mac_addr_cam_del_entry(hal_info, sta);
if (hal_status != RTW_HAL_STATUS_SUCCESS)
PHL_ERR("mac_addr_cam_del_entry failed\n");
hal_status = rtw_hal_bb_stainfo_delete(hal_info, sta);
if (hal_status != RTW_HAL_STATUS_SUCCESS)
PHL_ERR("bb_stainfo deinit failed\n");
return hal_status;
}
u8 rtw_hal_get_sta_rssi(struct rtw_phl_stainfo_t *sta)
{
u8 rssi = (sta->hal_sta->rssi_stat.rssi >> 1);
return rssi;
}
u8 rtw_hal_get_sta_rssi_bcn(struct rtw_phl_stainfo_t *sta)
{
u8 rssi = (sta->hal_sta->rssi_stat.rssi_bcn >> 1);
return rssi;
}
bool rtw_hal_is_sta_linked(void *hal, struct rtw_phl_stainfo_t *sta)
{
return (sta->hal_sta->ra_info.ra_registered == true) ? true : false;
}
enum rtw_hal_status
rtw_hal_set_edca(void *hal, struct rtw_wifi_role_t *wrole, u8 ac, u32 edca)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
enum rtw_hal_status hal_status;
hal_status = rtw_hal_mac_set_edca(hal_info->hal_com, wrole->hw_band,
wrole->hw_wmm, ac, edca);
return hal_status;
}
enum rtw_hal_status
rtw_hal_cfg_tx_ampdu(void *hal, struct rtw_phl_stainfo_t *sta)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
enum rtw_hal_status hsts = RTW_HAL_STATUS_FAILURE;
/* update ampdu configuration */
if (64 == sta->asoc_cap.num_ampdu)
hsts = rtw_hal_mac_set_hw_ampdu_cfg(hal_info, 0, 0x3F, 0xA5);
else if (128 == sta->asoc_cap.num_ampdu)
hsts = rtw_hal_mac_set_hw_ampdu_cfg(hal_info, 0, 0x7F, 0xAB);
if (RTW_HAL_STATUS_SUCCESS != hsts)
goto out;
/* todo: update cmac table */
out:
return hsts;
}
enum rtw_hal_status
rtw_hal_set_sta_rx_sts(struct rtw_phl_stainfo_t *sta, u8 rst,
struct rtw_r_meta_data *meta)
{
if (rst) {
sta->hal_sta->trx_stat.rx_ok_cnt = 0;
sta->hal_sta->trx_stat.rx_err_cnt = 0;
} else {
if (meta->crc32 || meta->icverr)
sta->hal_sta->trx_stat.rx_err_cnt++;
else
sta->hal_sta->trx_stat.rx_ok_cnt++;
sta->hal_sta->trx_stat.rx_bw = meta->bw;
sta->hal_sta->trx_stat.rx_rate = meta->rx_rate;
sta->hal_sta->trx_stat.rx_gi_ltf = meta->rx_gi_ltf;
}
/* TODO: rx_rate_plurality */
return RTW_HAL_STATUS_SUCCESS;
}
enum rtw_hal_status
rtw_hal_query_rainfo(void *hal, struct rtw_hal_stainfo_t *hal_sta,
struct rtw_phl_rainfo *phl_rainfo)
{
enum rtw_hal_status hal_sts = RTW_HAL_STATUS_FAILURE;
hal_sts = rtw_hal_bb_query_rainfo(hal, hal_sta, phl_rainfo);
return hal_sts;
}
/**
* rtw_hal_query_txsts_rpt() - get txok and tx retry info
* @hal: struct hal_info_t *
* @macid: indicate the first macid that you want to query.
* Return rtw_hal_bb_query_txsts_rpt's return value in enum rtw_hal_status type.
*/
enum rtw_hal_status
rtw_hal_query_txsts_rpt(void *hal, u16 macid)
{
struct hal_info_t *hal_info = (struct hal_info_t *)hal;
/*get tx ok and tx retry statistics*/
if (RTW_HAL_STATUS_SUCCESS != rtw_hal_bb_query_txsts_rpt(hal_info, macid, 0xFFFF))
return RTW_HAL_STATUS_FAILURE;
else
return RTW_HAL_STATUS_SUCCESS;
}