2019-10-22 18:04:18 +08:00
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/* Copyright(c) 2018-2019 Realtek Corporation.
*/
# include "main.h"
# include "reg.h"
# include "bf.h"
# include "debug.h"
void rtw_bf_disassoc ( struct rtw_dev * rtwdev , struct ieee80211_vif * vif ,
struct ieee80211_bss_conf * bss_conf )
{
struct rtw_vif * rtwvif = ( struct rtw_vif * ) vif - > drv_priv ;
struct rtw_bfee * bfee = & rtwvif - > bfee ;
struct rtw_bf_info * bfinfo = & rtwdev - > bf_info ;
if ( bfee - > role = = RTW_BFEE_NONE )
return ;
if ( bfee - > role = = RTW_BFEE_MU )
bfinfo - > bfer_mu_cnt - - ;
else if ( bfee - > role = = RTW_BFEE_SU )
bfinfo - > bfer_su_cnt - - ;
2020-04-20 13:50:48 +08:00
rtw_chip_config_bfee ( rtwdev , rtwvif , bfee , false ) ;
2019-10-22 18:04:18 +08:00
bfee - > role = RTW_BFEE_NONE ;
}
void rtw_bf_assoc ( struct rtw_dev * rtwdev , struct ieee80211_vif * vif ,
struct ieee80211_bss_conf * bss_conf )
{
struct ieee80211_hw * hw = rtwdev - > hw ;
struct rtw_vif * rtwvif = ( struct rtw_vif * ) vif - > drv_priv ;
struct rtw_bfee * bfee = & rtwvif - > bfee ;
struct rtw_bf_info * bfinfo = & rtwdev - > bf_info ;
struct rtw_chip_info * chip = rtwdev - > chip ;
struct ieee80211_sta * sta ;
struct ieee80211_sta_vht_cap * vht_cap ;
struct ieee80211_sta_vht_cap * ic_vht_cap ;
const u8 * bssid = bss_conf - > bssid ;
u32 sound_dim ;
u8 i ;
if ( ! ( chip - > band & RTW_BAND_5G ) )
return ;
rcu_read_lock ( ) ;
sta = ieee80211_find_sta ( vif , bssid ) ;
if ( ! sta ) {
rtw_warn ( rtwdev , " failed to find station entry for bss %pM \n " ,
bssid ) ;
goto out_unlock ;
}
ic_vht_cap = & hw - > wiphy - > bands [ NL80211_BAND_5GHZ ] - > vht_cap ;
vht_cap = & sta - > vht_cap ;
if ( ( ic_vht_cap - > cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE ) & &
( vht_cap - > cap & IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE ) ) {
if ( bfinfo - > bfer_mu_cnt > = chip - > bfer_mu_max_num ) {
rtw_dbg ( rtwdev , RTW_DBG_BF , " mu bfer number over limit \n " ) ;
goto out_unlock ;
}
ether_addr_copy ( bfee - > mac_addr , bssid ) ;
2020-02-07 16:47:29 +08:00
bfee - > role = RTW_BFEE_MU ;
2019-10-22 18:04:18 +08:00
bfee - > p_aid = ( bssid [ 5 ] < < 1 ) | ( bssid [ 4 ] > > 7 ) ;
bfee - > aid = bss_conf - > aid ;
bfinfo - > bfer_mu_cnt + + ;
2020-04-20 13:50:48 +08:00
rtw_chip_config_bfee ( rtwdev , rtwvif , bfee , true ) ;
2019-10-22 18:04:18 +08:00
} else if ( ( ic_vht_cap - > cap & IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE ) & &
( vht_cap - > cap & IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE ) ) {
if ( bfinfo - > bfer_su_cnt > = chip - > bfer_su_max_num ) {
rtw_dbg ( rtwdev , RTW_DBG_BF , " su bfer number over limit \n " ) ;
goto out_unlock ;
}
sound_dim = vht_cap - > cap &
IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK ;
sound_dim > > = IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT ;
ether_addr_copy ( bfee - > mac_addr , bssid ) ;
2020-02-07 16:47:29 +08:00
bfee - > role = RTW_BFEE_SU ;
2019-10-22 18:04:18 +08:00
bfee - > sound_dim = ( u8 ) sound_dim ;
bfee - > g_id = 0 ;
bfee - > p_aid = ( bssid [ 5 ] < < 1 ) | ( bssid [ 4 ] > > 7 ) ;
bfinfo - > bfer_su_cnt + + ;
for ( i = 0 ; i < chip - > bfer_su_max_num ; i + + ) {
if ( ! test_bit ( i , bfinfo - > bfer_su_reg_maping ) ) {
set_bit ( i , bfinfo - > bfer_su_reg_maping ) ;
bfee - > su_reg_index = i ;
break ;
}
}
2020-04-20 13:50:48 +08:00
rtw_chip_config_bfee ( rtwdev , rtwvif , bfee , true ) ;
2019-10-22 18:04:18 +08:00
}
out_unlock :
rcu_read_unlock ( ) ;
}
void rtw_bf_init_bfer_entry_mu ( struct rtw_dev * rtwdev ,
struct mu_bfer_init_para * param )
{
u16 mu_bf_ctl = 0 ;
u8 * addr = param - > bfer_address ;
int i ;
for ( i = 0 ; i < ETH_ALEN ; i + + )
rtw_write8 ( rtwdev , REG_ASSOCIATED_BFMER0_INFO + i , addr [ i ] ) ;
rtw_write16 ( rtwdev , REG_ASSOCIATED_BFMER0_INFO + 6 , param - > paid ) ;
rtw_write16 ( rtwdev , REG_TX_CSI_RPT_PARAM_BW20 , param - > csi_para ) ;
mu_bf_ctl = rtw_read16 ( rtwdev , REG_WMAC_MU_BF_CTL ) & 0xC000 ;
mu_bf_ctl | = param - > my_aid | ( param - > csi_length_sel < < 12 ) ;
rtw_write16 ( rtwdev , REG_WMAC_MU_BF_CTL , mu_bf_ctl ) ;
}
void rtw_bf_cfg_sounding ( struct rtw_dev * rtwdev , struct rtw_vif * vif ,
enum rtw_trx_desc_rate rate )
{
u32 psf_ctl = 0 ;
u8 csi_rsc = 0x1 ;
psf_ctl = rtw_read32 ( rtwdev , REG_BBPSF_CTRL ) |
BIT_WMAC_USE_NDPARATE |
( csi_rsc < < 13 ) ;
rtw_write8 ( rtwdev , REG_SND_PTCL_CTRL , RTW_SND_CTRL_SOUNDING ) ;
rtw_write8 ( rtwdev , REG_SND_PTCL_CTRL + 3 , 0x26 ) ;
rtw_write8_clr ( rtwdev , REG_RXFLTMAP1 , BIT_RXFLTMAP1_BF_REPORT_POLL ) ;
rtw_write8_clr ( rtwdev , REG_RXFLTMAP4 , BIT_RXFLTMAP4_BF_REPORT_POLL ) ;
if ( vif - > net_type = = RTW_NET_AP_MODE )
rtw_write32 ( rtwdev , REG_BBPSF_CTRL , psf_ctl | BIT ( 12 ) ) ;
else
rtw_write32 ( rtwdev , REG_BBPSF_CTRL , psf_ctl & ~ BIT ( 12 ) ) ;
}
void rtw_bf_cfg_mu_bfee ( struct rtw_dev * rtwdev , struct cfg_mumimo_para * param )
{
u8 mu_tbl_sel ;
u8 mu_valid ;
mu_valid = rtw_read8 ( rtwdev , REG_MU_TX_CTL ) &
~ BIT_MASK_R_MU_TABLE_VALID ;
rtw_write8 ( rtwdev , REG_MU_TX_CTL ,
( mu_valid | BIT ( 0 ) | BIT ( 1 ) ) & ~ ( BIT ( 7 ) ) ) ;
mu_tbl_sel = rtw_read8 ( rtwdev , REG_MU_TX_CTL + 1 ) & 0xF8 ;
rtw_write8 ( rtwdev , REG_MU_TX_CTL + 1 , mu_tbl_sel ) ;
rtw_write32 ( rtwdev , REG_MU_STA_GID_VLD , param - > given_gid_tab [ 0 ] ) ;
rtw_write32 ( rtwdev , REG_MU_STA_USER_POS_INFO , param - > given_user_pos [ 0 ] ) ;
rtw_write32 ( rtwdev , REG_MU_STA_USER_POS_INFO + 4 ,
param - > given_user_pos [ 1 ] ) ;
rtw_write8 ( rtwdev , REG_MU_TX_CTL + 1 , mu_tbl_sel | 1 ) ;
rtw_write32 ( rtwdev , REG_MU_STA_GID_VLD , param - > given_gid_tab [ 1 ] ) ;
rtw_write32 ( rtwdev , REG_MU_STA_USER_POS_INFO , param - > given_user_pos [ 2 ] ) ;
rtw_write32 ( rtwdev , REG_MU_STA_USER_POS_INFO + 4 ,
param - > given_user_pos [ 3 ] ) ;
}
void rtw_bf_del_bfer_entry_mu ( struct rtw_dev * rtwdev )
{
rtw_write32 ( rtwdev , REG_ASSOCIATED_BFMER0_INFO , 0 ) ;
rtw_write32 ( rtwdev , REG_ASSOCIATED_BFMER0_INFO + 4 , 0 ) ;
rtw_write16 ( rtwdev , REG_WMAC_MU_BF_CTL , 0 ) ;
rtw_write8 ( rtwdev , REG_MU_TX_CTL , 0 ) ;
}
void rtw_bf_del_sounding ( struct rtw_dev * rtwdev )
{
rtw_write8 ( rtwdev , REG_SND_PTCL_CTRL , 0 ) ;
}
void rtw_bf_enable_bfee_su ( struct rtw_dev * rtwdev , struct rtw_vif * vif ,
struct rtw_bfee * bfee )
{
2020-06-03 17:42:16 +08:00
u8 nc_index = hweight8 ( rtwdev - > hal . antenna_rx ) - 1 ;
2019-10-22 18:04:18 +08:00
u8 nr_index = bfee - > sound_dim ;
u8 grouping = 0 , codebookinfo = 1 , coefficientsize = 3 ;
u32 addr_bfer_info , addr_csi_rpt , csi_param ;
u8 i ;
rtw_dbg ( rtwdev , RTW_DBG_BF , " config as an su bfee \n " ) ;
switch ( bfee - > su_reg_index ) {
case 1 :
addr_bfer_info = REG_ASSOCIATED_BFMER1_INFO ;
addr_csi_rpt = REG_TX_CSI_RPT_PARAM_BW20 + 2 ;
break ;
case 0 :
default :
addr_bfer_info = REG_ASSOCIATED_BFMER0_INFO ;
addr_csi_rpt = REG_TX_CSI_RPT_PARAM_BW20 ;
break ;
}
/* Sounding protocol control */
rtw_write8 ( rtwdev , REG_SND_PTCL_CTRL , RTW_SND_CTRL_SOUNDING ) ;
/* MAC address/Partial AID of Beamformer */
for ( i = 0 ; i < ETH_ALEN ; i + + )
rtw_write8 ( rtwdev , addr_bfer_info + i , bfee - > mac_addr [ i ] ) ;
csi_param = ( u16 ) ( ( coefficientsize < < 10 ) |
( codebookinfo < < 8 ) |
( grouping < < 6 ) |
( nr_index < < 3 ) |
nc_index ) ;
rtw_write16 ( rtwdev , addr_csi_rpt , csi_param ) ;
/* ndp rx standby timer */
rtw_write8 ( rtwdev , REG_SND_PTCL_CTRL + 3 , RTW_NDP_RX_STANDBY_TIME ) ;
}
2020-05-15 13:23:21 +08:00
EXPORT_SYMBOL ( rtw_bf_enable_bfee_su ) ;
2019-10-22 18:04:18 +08:00
/* nc index: 1 2T2R 0 1T1R
* nr index : 1 use Nsts 0 use reg setting
* codebookinfo : 1 802.11 ac 3 802.11 n
*/
void rtw_bf_enable_bfee_mu ( struct rtw_dev * rtwdev , struct rtw_vif * vif ,
struct rtw_bfee * bfee )
{
struct rtw_bf_info * bf_info = & rtwdev - > bf_info ;
struct mu_bfer_init_para param ;
2020-06-03 17:42:16 +08:00
u8 nc_index = hweight8 ( rtwdev - > hal . antenna_rx ) - 1 ;
u8 nr_index = 1 ;
2019-10-22 18:04:18 +08:00
u8 grouping = 0 , codebookinfo = 1 , coefficientsize = 0 ;
u32 csi_param ;
rtw_dbg ( rtwdev , RTW_DBG_BF , " config as an mu bfee \n " ) ;
csi_param = ( u16 ) ( ( coefficientsize < < 10 ) |
( codebookinfo < < 8 ) |
( grouping < < 6 ) |
( nr_index < < 3 ) |
nc_index ) ;
rtw_dbg ( rtwdev , RTW_DBG_BF , " nc=%d nr=%d group=%d codebookinfo=%d coefficientsize=%d \n " ,
nc_index , nr_index , grouping , codebookinfo ,
coefficientsize ) ;
param . paid = bfee - > p_aid ;
param . csi_para = csi_param ;
param . my_aid = bfee - > aid & 0xfff ;
param . csi_length_sel = HAL_CSI_SEG_4K ;
ether_addr_copy ( param . bfer_address , bfee - > mac_addr ) ;
rtw_bf_init_bfer_entry_mu ( rtwdev , & param ) ;
bf_info - > cur_csi_rpt_rate = DESC_RATE6M ;
rtw_bf_cfg_sounding ( rtwdev , vif , DESC_RATE6M ) ;
/* accept action_no_ack */
rtw_write16_set ( rtwdev , REG_RXFLTMAP0 , BIT_RXFLTMAP0_ACTIONNOACK ) ;
/* accept NDPA and BF report poll */
rtw_write16_set ( rtwdev , REG_RXFLTMAP1 , BIT_RXFLTMAP1_BF ) ;
}
2020-05-15 13:23:21 +08:00
EXPORT_SYMBOL ( rtw_bf_enable_bfee_mu ) ;
2019-10-22 18:04:18 +08:00
void rtw_bf_remove_bfee_su ( struct rtw_dev * rtwdev ,
struct rtw_bfee * bfee )
{
struct rtw_bf_info * bfinfo = & rtwdev - > bf_info ;
rtw_dbg ( rtwdev , RTW_DBG_BF , " remove as a su bfee \n " ) ;
rtw_write8 ( rtwdev , REG_SND_PTCL_CTRL , RTW_SND_CTRL_REMOVE ) ;
switch ( bfee - > su_reg_index ) {
case 0 :
rtw_write32 ( rtwdev , REG_ASSOCIATED_BFMER0_INFO , 0 ) ;
rtw_write16 ( rtwdev , REG_ASSOCIATED_BFMER0_INFO + 4 , 0 ) ;
rtw_write16 ( rtwdev , REG_TX_CSI_RPT_PARAM_BW20 , 0 ) ;
break ;
case 1 :
rtw_write32 ( rtwdev , REG_ASSOCIATED_BFMER1_INFO , 0 ) ;
rtw_write16 ( rtwdev , REG_ASSOCIATED_BFMER1_INFO + 4 , 0 ) ;
rtw_write16 ( rtwdev , REG_TX_CSI_RPT_PARAM_BW20 + 2 , 0 ) ;
break ;
}
clear_bit ( bfee - > su_reg_index , bfinfo - > bfer_su_reg_maping ) ;
bfee - > su_reg_index = 0xFF ;
}
2020-05-15 13:23:21 +08:00
EXPORT_SYMBOL ( rtw_bf_remove_bfee_su ) ;
2019-10-22 18:04:18 +08:00
void rtw_bf_remove_bfee_mu ( struct rtw_dev * rtwdev ,
struct rtw_bfee * bfee )
{
struct rtw_bf_info * bfinfo = & rtwdev - > bf_info ;
rtw_write8 ( rtwdev , REG_SND_PTCL_CTRL , RTW_SND_CTRL_REMOVE ) ;
rtw_bf_del_bfer_entry_mu ( rtwdev ) ;
if ( bfinfo - > bfer_su_cnt = = 0 & & bfinfo - > bfer_mu_cnt = = 0 )
rtw_bf_del_sounding ( rtwdev ) ;
}
2020-05-15 13:23:21 +08:00
EXPORT_SYMBOL ( rtw_bf_remove_bfee_mu ) ;
2019-10-22 18:04:18 +08:00
void rtw_bf_set_gid_table ( struct rtw_dev * rtwdev , struct ieee80211_vif * vif ,
struct ieee80211_bss_conf * conf )
{
struct rtw_vif * rtwvif = ( struct rtw_vif * ) vif - > drv_priv ;
struct rtw_bfee * bfee = & rtwvif - > bfee ;
struct cfg_mumimo_para param ;
if ( bfee - > role ! = RTW_BFEE_MU ) {
rtw_dbg ( rtwdev , RTW_DBG_BF , " this vif is not mu bfee \n " ) ;
return ;
}
param . grouping_bitmap = 0 ;
param . mu_tx_en = 0 ;
memset ( param . sounding_sts , 0 , 6 ) ;
memcpy ( param . given_gid_tab , conf - > mu_group . membership , 8 ) ;
memcpy ( param . given_user_pos , conf - > mu_group . position , 16 ) ;
rtw_dbg ( rtwdev , RTW_DBG_BF , " STA0: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x \n " ,
param . given_gid_tab [ 0 ] , param . given_user_pos [ 0 ] ,
param . given_user_pos [ 1 ] ) ;
rtw_dbg ( rtwdev , RTW_DBG_BF , " STA1: gid_valid=0x%x, user_position_l=0x%x, user_position_h=0x%x \n " ,
param . given_gid_tab [ 1 ] , param . given_user_pos [ 2 ] ,
param . given_user_pos [ 3 ] ) ;
rtw_bf_cfg_mu_bfee ( rtwdev , & param ) ;
}
2020-05-15 13:23:21 +08:00
EXPORT_SYMBOL ( rtw_bf_set_gid_table ) ;
2019-10-22 18:04:18 +08:00
void rtw_bf_phy_init ( struct rtw_dev * rtwdev )
{
u8 tmp8 ;
u32 tmp32 ;
u8 retry_limit = 0xA ;
u8 ndpa_rate = 0x10 ;
u8 ack_policy = 3 ;
tmp32 = rtw_read32 ( rtwdev , REG_MU_TX_CTL ) ;
/* Enable P1 aggr new packet according to P0 transfer time */
tmp32 | = BIT_MU_P1_WAIT_STATE_EN ;
/* MU Retry Limit */
tmp32 & = ~ BIT_MASK_R_MU_RL ;
tmp32 | = ( retry_limit < < BIT_SHIFT_R_MU_RL ) & BIT_MASK_R_MU_RL ;
/* Disable Tx MU-MIMO until sounding done */
tmp32 & = ~ BIT_EN_MU_MIMO ;
/* Clear validity of MU STAs */
tmp32 & = ~ BIT_MASK_R_MU_TABLE_VALID ;
rtw_write32 ( rtwdev , REG_MU_TX_CTL , tmp32 ) ;
/* MU-MIMO Option as default value */
tmp8 = ack_policy < < BIT_SHIFT_WMAC_TXMU_ACKPOLICY ;
tmp8 | = BIT_WMAC_TXMU_ACKPOLICY_EN ;
rtw_write8 ( rtwdev , REG_WMAC_MU_BF_OPTION , tmp8 ) ;
/* MU-MIMO Control as default value */
rtw_write16 ( rtwdev , REG_WMAC_MU_BF_CTL , 0 ) ;
/* Set MU NDPA rate & BW source */
rtw_write32_set ( rtwdev , REG_TXBF_CTRL , BIT_USE_NDPA_PARAMETER ) ;
/* Set NDPA Rate */
rtw_write8 ( rtwdev , REG_NDPA_OPT_CTRL , ndpa_rate ) ;
rtw_write32_mask ( rtwdev , REG_BBPSF_CTRL , BIT_MASK_CSI_RATE ,
DESC_RATE6M ) ;
}
2020-05-15 13:23:21 +08:00
EXPORT_SYMBOL ( rtw_bf_phy_init ) ;
2019-10-22 18:04:18 +08:00
void rtw_bf_cfg_csi_rate ( struct rtw_dev * rtwdev , u8 rssi , u8 cur_rate ,
u8 fixrate_en , u8 * new_rate )
{
u32 csi_cfg ;
u16 cur_rrsr ;
csi_cfg = rtw_read32 ( rtwdev , REG_BBPSF_CTRL ) & ~ BIT_MASK_CSI_RATE ;
cur_rrsr = rtw_read16 ( rtwdev , REG_RRSR ) ;
if ( rssi > = 40 ) {
if ( cur_rate ! = DESC_RATE54M ) {
cur_rrsr | = BIT ( DESC_RATE54M ) ;
csi_cfg | = ( DESC_RATE54M & BIT_MASK_CSI_RATE_VAL ) < <
BIT_SHIFT_CSI_RATE ;
rtw_write16 ( rtwdev , REG_RRSR , cur_rrsr ) ;
rtw_write32 ( rtwdev , REG_BBPSF_CTRL , csi_cfg ) ;
}
* new_rate = DESC_RATE54M ;
} else {
if ( cur_rate ! = DESC_RATE24M ) {
cur_rrsr & = ~ BIT ( DESC_RATE54M ) ;
csi_cfg | = ( DESC_RATE54M & BIT_MASK_CSI_RATE_VAL ) < <
BIT_SHIFT_CSI_RATE ;
rtw_write16 ( rtwdev , REG_RRSR , cur_rrsr ) ;
rtw_write32 ( rtwdev , REG_BBPSF_CTRL , csi_cfg ) ;
}
* new_rate = DESC_RATE24M ;
}
}
2020-05-15 13:23:21 +08:00
EXPORT_SYMBOL ( rtw_bf_cfg_csi_rate ) ;