830 lines
23 KiB
C
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;
|
|
}
|
|
|