/****************************************************************************** * * 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; ihal_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; }