2017-04-07 11:39:45 +00:00
/******************************************************************************
*
* Copyright ( c ) 2007 - 2016 Realtek Corporation . All rights reserved .
*
* 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 .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . ,
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 , USA
*
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define _RTW_BEAMFORMING_C_
# include <drv_types.h>
# include <hal_data.h>
# ifdef CONFIG_BEAMFORMING
# if (BEAMFORMING_SUPPORT == 0) /*for diver defined beamforming*/
# ifdef RTW_BEAMFORMING_VERSION_2
/*
* For phydm
*/
BEAMFORMING_CAP beamforming_get_entry_beam_cap_by_mac_id ( void * mlme , u8 mac_id )
{
PADAPTER adapter ;
struct beamforming_info * pBeamInfo ;
struct beamformee_entry * bfee ;
BEAMFORMING_CAP cap = BEAMFORMING_CAP_NONE ;
u8 i = 0 ;
adapter = mlme_to_adapter ( ( struct mlme_priv * ) mlme ) ;
pBeamInfo = GET_BEAMFORM_INFO ( adapter ) ;
for ( i = 0 ; i < MAX_BEAMFORMER_ENTRY_NUM ; i + + ) {
bfee = & pBeamInfo - > bfee_entry [ i ] ;
if ( ( bfee - > used = = _TRUE )
& & ( bfee - > mac_id = = mac_id ) ) {
cap = bfee - > cap ;
break ;
}
}
return cap ;
}
struct beamformer_entry * beamforming_get_bfer_entry_by_addr ( PADAPTER adapter , u8 * ra )
{
u8 i = 0 ;
struct beamforming_info * bf_info ;
struct beamformer_entry * entry ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
for ( i = 0 ; i < MAX_BEAMFORMER_ENTRY_NUM ; i + + ) {
entry = & bf_info - > bfer_entry [ i ] ;
if ( entry - > used = = _FALSE )
continue ;
if ( _rtw_memcmp ( ra , entry - > mac_addr , ETH_ALEN ) = = _TRUE ) {
return entry ;
}
}
return NULL ;
}
struct beamformee_entry * beamforming_get_bfee_entry_by_addr ( PADAPTER adapter , u8 * ra )
{
u8 i = 0 ;
struct beamforming_info * bf_info ;
struct beamformee_entry * entry ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
for ( i = 0 ; i < MAX_BEAMFORMEE_ENTRY_NUM ; i + + ) {
entry = & bf_info - > bfee_entry [ i ] ;
if ( entry - > used = = _FALSE )
continue ;
if ( _rtw_memcmp ( ra , entry - > mac_addr , ETH_ALEN ) = = _TRUE )
return entry ;
}
return NULL ;
}
static struct beamformer_entry * _get_bfer_free_entry ( PADAPTER adapter )
{
u8 i = 0 ;
struct beamforming_info * bf_info ;
struct beamformer_entry * entry ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
for ( i = 0 ; i < MAX_BEAMFORMER_ENTRY_NUM ; i + + ) {
entry = & bf_info - > bfer_entry [ i ] ;
if ( entry - > used = = _FALSE )
return entry ;
}
return NULL ;
}
static struct beamformee_entry * _get_bfee_free_entry ( PADAPTER adapter )
{
u8 i = 0 ;
struct beamforming_info * bf_info ;
struct beamformee_entry * entry ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
for ( i = 0 ; i < MAX_BEAMFORMEE_ENTRY_NUM ; i + + ) {
entry = & bf_info - > bfee_entry [ i ] ;
if ( entry - > used = = _FALSE )
return entry ;
}
return NULL ;
}
/*
* Description :
* Get the first entry index of MU Beamformee .
*
* Return Value :
* Index of the first MU sta .
*
* 2015.05 .25 . Created by tynli .
*
*/
static u8 _get_first_mu_bfee_entry_idx ( PADAPTER adapter , struct beamformee_entry * ignore )
{
struct beamforming_info * bf_info ;
struct beamformee_entry * entry ;
u8 idx = 0xFF ;
u8 bFound = _FALSE ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
for ( idx = 0 ; idx < MAX_BEAMFORMEE_ENTRY_NUM ; idx + + ) {
entry = & bf_info - > bfee_entry [ idx ] ;
if ( ignore & & ( entry = = ignore ) )
continue ;
if ( ( entry - > used = = _TRUE ) & &
TEST_FLAG ( entry - > cap , BEAMFORMEE_CAP_VHT_MU ) ) {
bFound = _TRUE ;
break ;
}
}
if ( bFound = = _FALSE )
idx = 0xFF ;
return idx ;
}
static void _update_min_sounding_period ( PADAPTER adapter , u16 period , u8 leave )
{
struct beamforming_info * bf_info ;
struct beamformee_entry * entry ;
u8 i = 0 ;
u16 min_val = 0xFFFF ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
if ( _TRUE = = leave ) {
/*
* When a BFee left ,
* we need to find the latest min sounding period
* from the remaining BFees
*/
for ( i = 0 ; i < MAX_BEAMFORMEE_ENTRY_NUM ; i + + ) {
entry = & bf_info - > bfee_entry [ i ] ;
if ( ( entry - > used = = _TRUE )
& & ( entry - > sound_period < min_val ) )
min_val = entry - > sound_period ;
}
if ( min_val = = 0xFFFF )
bf_info - > sounding_info . min_sounding_period = 0 ;
else
bf_info - > sounding_info . min_sounding_period = min_val ;
} else {
if ( ( bf_info - > sounding_info . min_sounding_period = = 0 )
| | ( period < bf_info - > sounding_info . min_sounding_period ) )
bf_info - > sounding_info . min_sounding_period = period ;
}
}
static struct beamformer_entry * _add_bfer_entry ( PADAPTER adapter ,
struct sta_info * sta , u8 bf_cap , u8 sounding_dim , u8 comp_steering )
{
struct mlme_priv * mlme ;
struct beamforming_info * bf_info ;
struct beamformer_entry * entry ;
u8 * bssid ;
u16 val16 ;
u8 i ;
mlme = & adapter - > mlmepriv ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
entry = beamforming_get_bfer_entry_by_addr ( adapter , sta - > hwaddr ) ;
if ( ! entry ) {
entry = _get_bfer_free_entry ( adapter ) ;
if ( ! entry )
return NULL ;
}
entry - > used = _TRUE ;
if ( check_fwstate ( mlme , WIFI_AP_STATE ) ) {
bssid = adapter_mac_addr ( adapter ) ;
/* BSSID[44:47] xor BSSID[40:43] */
val16 = ( ( bssid [ 5 ] & 0xF0 ) > > 4 ) ^ ( bssid [ 5 ] & 0xF ) ;
/* (dec(A) + dec(B)*32) mod 512 */
entry - > p_aid = ( sta - > aid + val16 * 32 ) & 0x1FF ;
entry - > g_id = 63 ;
} else if ( ( check_fwstate ( mlme , WIFI_ADHOC_STATE ) = = _TRUE )
| | ( check_fwstate ( mlme , WIFI_ADHOC_MASTER_STATE ) = = _TRUE ) ) {
entry - > p_aid = 0 ;
entry - > g_id = 63 ;
} else {
bssid = sta - > hwaddr ;
/* BSSID[39:47] */
entry - > p_aid = ( bssid [ 5 ] < < 1 ) | ( bssid [ 4 ] > > 7 ) ;
entry - > g_id = 0 ;
}
RTW_INFO ( " %s: p_aid=0x%04x g_id=0x%04x aid=0x%x \n " ,
__FUNCTION__ , entry - > p_aid , entry - > g_id , sta - > aid ) ;
_rtw_memcpy ( entry - > mac_addr , sta - > hwaddr , ETH_ALEN ) ;
entry - > cap = bf_cap ;
entry - > state = BEAMFORM_ENTRY_HW_STATE_ADD_INIT ;
entry - > NumofSoundingDim = sounding_dim ;
if ( TEST_FLAG ( bf_cap , BEAMFORMER_CAP_VHT_MU ) ) {
bf_info - > beamformer_mu_cnt + = 1 ;
entry - > aid = sta - > aid ;
} else if ( TEST_FLAG ( bf_cap , BEAMFORMER_CAP_VHT_SU | BEAMFORMER_CAP_HT_EXPLICIT ) ) {
bf_info - > beamformer_su_cnt + = 1 ;
/* Record HW idx info */
for ( i = 0 ; i < MAX_NUM_BEAMFORMER_SU ; i + + ) {
if ( ( bf_info - > beamformer_su_reg_maping & BIT ( i ) ) = = 0 ) {
bf_info - > beamformer_su_reg_maping | = BIT ( i ) ;
entry - > su_reg_index = i ;
break ;
}
}
RTW_INFO ( " %s: Add BFer entry beamformer_su_reg_maping=%#X, su_reg_index=%d \n " ,
__FUNCTION__ , bf_info - > beamformer_su_reg_maping , entry - > su_reg_index ) ;
}
return entry ;
}
static struct beamformee_entry * _add_bfee_entry ( PADAPTER adapter ,
struct sta_info * sta , u8 bf_cap , u8 sounding_dim , u8 comp_steering )
{
struct mlme_priv * mlme ;
struct beamforming_info * bf_info ;
struct beamformee_entry * entry ;
u8 * bssid ;
u16 val16 ;
u8 i ;
mlme = & adapter - > mlmepriv ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
entry = beamforming_get_bfee_entry_by_addr ( adapter , sta - > hwaddr ) ;
if ( ! entry ) {
entry = _get_bfee_free_entry ( adapter ) ;
if ( ! entry )
return NULL ;
}
entry - > used = _TRUE ;
entry - > aid = sta - > aid ;
entry - > mac_id = sta - > mac_id ;
entry - > sound_bw = sta - > bw_mode ;
if ( check_fwstate ( mlme , WIFI_AP_STATE ) ) {
bssid = adapter_mac_addr ( adapter ) ;
/* BSSID[44:47] xor BSSID[40:43] */
val16 = ( ( bssid [ 5 ] & 0xF0 ) > > 4 ) ^ ( bssid [ 5 ] & 0xF ) ;
/* (dec(A) + dec(B)*32) mod 512 */
entry - > p_aid = ( sta - > aid + val16 * 32 ) & 0x1FF ;
entry - > g_id = 63 ;
} else if ( check_fwstate ( mlme , WIFI_ADHOC_STATE ) | | check_fwstate ( mlme , WIFI_ADHOC_MASTER_STATE ) ) {
entry - > p_aid = 0 ;
entry - > g_id = 63 ;
} else {
bssid = sta - > hwaddr ;
/* BSSID[39:47] */
entry - > p_aid = ( bssid [ 5 ] < < 1 ) | ( bssid [ 4 ] > > 7 ) ;
entry - > g_id = 0 ;
}
_rtw_memcpy ( entry - > mac_addr , sta - > hwaddr , ETH_ALEN ) ;
entry - > txbf = _FALSE ;
entry - > sounding = _FALSE ;
entry - > sound_period = 40 ;
entry - > cap = bf_cap ;
_update_min_sounding_period ( adapter , entry - > sound_period , _FALSE ) ;
entry - > SoundCnt = GetInitSoundCnt ( entry - > sound_period , bf_info - > sounding_info . min_sounding_period ) ;
entry - > LogStatusFailCnt = 0 ;
entry - > NumofSoundingDim = sounding_dim ;
entry - > CompSteeringNumofBFer = comp_steering ;
entry - > state = BEAMFORM_ENTRY_HW_STATE_ADD_INIT ;
if ( TEST_FLAG ( bf_cap , BEAMFORMEE_CAP_VHT_MU ) ) {
bf_info - > beamformee_mu_cnt + = 1 ;
bf_info - > first_mu_bfee_index = _get_first_mu_bfee_entry_idx ( adapter , NULL ) ;
/* Record HW idx info */
for ( i = 0 ; i < MAX_NUM_BEAMFORMEE_MU ; i + + ) {
if ( ( bf_info - > beamformee_mu_reg_maping & BIT ( i ) ) = = 0 ) {
bf_info - > beamformee_mu_reg_maping | = BIT ( i ) ;
entry - > mu_reg_index = i ;
break ;
}
}
RTW_INFO ( " %s: Add BFee entry beamformee_mu_reg_maping=%#X, mu_reg_index=%d \n " ,
__FUNCTION__ , bf_info - > beamformee_mu_reg_maping , entry - > mu_reg_index ) ;
} else if ( TEST_FLAG ( bf_cap , BEAMFORMEE_CAP_VHT_SU | BEAMFORMEE_CAP_HT_EXPLICIT ) ) {
bf_info - > beamformee_su_cnt + = 1 ;
/* Record HW idx info */
for ( i = 0 ; i < MAX_NUM_BEAMFORMEE_SU ; i + + ) {
if ( ( bf_info - > beamformee_su_reg_maping & BIT ( i ) ) = = 0 ) {
bf_info - > beamformee_su_reg_maping | = BIT ( i ) ;
entry - > su_reg_index = i ;
break ;
}
}
RTW_INFO ( " %s: Add BFee entry beamformee_su_reg_maping=%#X, su_reg_index=%d \n " ,
__FUNCTION__ , bf_info - > beamformee_su_reg_maping , entry - > su_reg_index ) ;
}
return entry ;
}
static void _remove_bfer_entry ( PADAPTER adapter , struct beamformer_entry * entry )
{
struct beamforming_info * bf_info ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
entry - > state = BEAMFORM_ENTRY_HW_STATE_DELETE_INIT ;
if ( TEST_FLAG ( entry - > cap , BEAMFORMER_CAP_VHT_MU ) ) {
bf_info - > beamformer_mu_cnt - = 1 ;
_rtw_memset ( entry - > gid_valid , 0 , 8 ) ;
_rtw_memset ( entry - > user_position , 0 , 16 ) ;
} else if ( TEST_FLAG ( entry - > cap , BEAMFORMER_CAP_VHT_SU | BEAMFORMER_CAP_HT_EXPLICIT ) ) {
bf_info - > beamformer_su_cnt - = 1 ;
}
if ( bf_info - > beamformer_mu_cnt = = 0 )
bf_info - > beamforming_cap & = ~ BEAMFORMEE_CAP_VHT_MU ;
if ( bf_info - > beamformer_su_cnt = = 0 )
bf_info - > beamforming_cap & = ~ ( BEAMFORMEE_CAP_VHT_SU | BEAMFORMEE_CAP_HT_EXPLICIT ) ;
}
static void _remove_bfee_entry ( PADAPTER adapter , struct beamformee_entry * entry )
{
struct beamforming_info * bf_info ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
entry - > state = BEAMFORM_ENTRY_HW_STATE_DELETE_INIT ;
if ( TEST_FLAG ( entry - > cap , BEAMFORMEE_CAP_VHT_MU ) ) {
bf_info - > beamformee_mu_cnt - = 1 ;
bf_info - > first_mu_bfee_index = _get_first_mu_bfee_entry_idx ( adapter , entry ) ;
} else if ( TEST_FLAG ( entry - > cap , BEAMFORMEE_CAP_VHT_SU | BEAMFORMEE_CAP_HT_EXPLICIT ) ) {
bf_info - > beamformee_su_cnt - = 1 ;
}
if ( bf_info - > beamformee_mu_cnt = = 0 )
bf_info - > beamforming_cap & = ~ BEAMFORMER_CAP_VHT_MU ;
if ( bf_info - > beamformee_su_cnt = = 0 )
bf_info - > beamforming_cap & = ~ ( BEAMFORMER_CAP_VHT_SU | BEAMFORMER_CAP_HT_EXPLICIT ) ;
_update_min_sounding_period ( adapter , 0 , _TRUE ) ;
}
/*
* Parameters
* adapter struct _adapter *
* sta struct sta_info *
* sta_bf_cap beamforming capabe of sta
* sounding_dim Number of Sounding Dimensions
* comp_steering Compressed Steering Number of Beamformer Antennas Supported
*/
static void _get_sta_beamform_cap ( PADAPTER adapter , struct sta_info * sta ,
u8 * sta_bf_cap , u8 * sounding_dim , u8 * comp_steering )
{
struct ht_priv * ht ;
# ifdef CONFIG_80211AC_VHT
struct vht_priv * vht ;
# endif /* CONFIG_80211AC_VHT */
u16 bf_cap ;
* sta_bf_cap = 0 ;
* sounding_dim = 0 ;
* comp_steering = 0 ;
ht = & adapter - > mlmepriv . htpriv ;
# ifdef CONFIG_80211AC_VHT
vht = & adapter - > mlmepriv . vhtpriv ;
# endif /* CONFIG_80211AC_VHT */
if ( IsSupportedHT ( sta - > wireless_mode ) = = _TRUE ) {
/* HT */
bf_cap = ht - > beamform_cap ;
if ( TEST_FLAG ( bf_cap , BEAMFORMING_HT_BEAMFORMEE_ENABLE ) ) {
* sta_bf_cap | = BEAMFORMER_CAP_HT_EXPLICIT ;
* sounding_dim = ( bf_cap & BEAMFORMING_HT_BEAMFORMEE_CHNL_EST_CAP ) > > 6 ;
}
if ( TEST_FLAG ( bf_cap , BEAMFORMING_HT_BEAMFORMER_ENABLE ) ) {
* sta_bf_cap | = BEAMFORMEE_CAP_HT_EXPLICIT ;
* comp_steering = ( bf_cap & BEAMFORMING_HT_BEAMFORMER_STEER_NUM ) > > 4 ;
}
}
# ifdef CONFIG_80211AC_VHT
if ( IsSupportedVHT ( sta - > wireless_mode ) = = _TRUE ) {
/* VHT */
bf_cap = vht - > beamform_cap ;
/* We are SU Beamformee because the STA is SU Beamformer */
if ( TEST_FLAG ( bf_cap , BEAMFORMING_VHT_BEAMFORMEE_ENABLE ) ) {
* sta_bf_cap | = BEAMFORMER_CAP_VHT_SU ;
/* We are MU Beamformee because the STA is MU Beamformer */
if ( TEST_FLAG ( bf_cap , BEAMFORMING_VHT_MU_MIMO_STA_ENABLE ) )
* sta_bf_cap | = BEAMFORMER_CAP_VHT_MU ;
* sounding_dim = ( bf_cap & BEAMFORMING_VHT_BEAMFORMEE_SOUND_DIM ) > > 12 ;
}
/* We are SU Beamformer because the STA is SU Beamformee */
if ( TEST_FLAG ( bf_cap , BEAMFORMING_VHT_BEAMFORMER_ENABLE ) ) {
* sta_bf_cap | = BEAMFORMEE_CAP_VHT_SU ;
/* We are MU Beamformer because the STA is MU Beamformee */
if ( TEST_FLAG ( bf_cap , BEAMFORMING_VHT_MU_MIMO_AP_ENABLE ) )
* sta_bf_cap | = BEAMFORMEE_CAP_VHT_MU ;
* comp_steering = ( bf_cap & BEAMFORMING_VHT_BEAMFORMER_STS_CAP ) > > 8 ;
}
}
# endif /* CONFIG_80211AC_VHT */
}
/*
* Return :
* _TRUE success
* _FALSE fail
*/
static u8 _init_entry ( PADAPTER adapter , struct sta_info * sta )
{
struct mlme_priv * mlme ;
struct ht_priv * htpriv ;
# ifdef CONFIG_80211AC_VHT
struct vht_priv * vhtpriv ;
# endif
struct mlme_ext_priv * mlme_ext ;
struct sta_info * sta_real ;
struct beamformer_entry * bfer = NULL ;
struct beamformee_entry * bfee = NULL ;
u8 * ra ;
u8 wireless_mode ;
u8 sta_bf_cap ;
u8 sounding_dim = 0 ; /* number of sounding dimensions */
u8 comp_steering_num = 0 ; /* compressed steering number */
mlme = & adapter - > mlmepriv ;
htpriv = & mlme - > htpriv ;
# ifdef CONFIG_80211AC_VHT
vhtpriv = & mlme - > vhtpriv ;
# endif
mlme_ext = & adapter - > mlmeextpriv ;
ra = sta - > hwaddr ;
wireless_mode = sta - > wireless_mode ;
sta_real = rtw_get_stainfo ( & adapter - > stapriv , ra ) ;
/* The current setting does not support Beaforming */
if ( ( IsSupportedHT ( wireless_mode ) = = _FALSE )
& & ( IsSupportedVHT ( wireless_mode ) = = _FALSE ) )
return _FALSE ;
if ( ( 0 = = htpriv - > beamform_cap )
# ifdef CONFIG_80211AC_VHT
& & ( 0 = = vhtpriv - > beamform_cap )
# endif
) {
RTW_INFO ( " The configuration disabled Beamforming! Skip... \n " ) ;
return _FALSE ;
}
_get_sta_beamform_cap ( adapter , sta ,
& sta_bf_cap , & sounding_dim , & comp_steering_num ) ;
RTW_INFO ( " STA Beamforming Capability=0x%02X \n " , sta_bf_cap ) ;
if ( sta_bf_cap = = BEAMFORMING_CAP_NONE )
return _FALSE ;
if ( ( sta_bf_cap & BEAMFORMEE_CAP_HT_EXPLICIT )
| | ( sta_bf_cap & BEAMFORMEE_CAP_VHT_SU )
| | ( sta_bf_cap & BEAMFORMEE_CAP_VHT_MU ) )
sta_bf_cap | = BEAMFORMEE_CAP ;
else
sta_bf_cap | = BEAMFORMER_CAP ;
if ( sta_bf_cap & BEAMFORMER_CAP ) {
/* The other side is beamformer */
bfer = _add_bfer_entry ( adapter , sta , sta_bf_cap , sounding_dim , comp_steering_num ) ;
if ( bfer = = NULL ) {
RTW_ERR ( " %s: Fail to allocate bfer entry! \n " , __FUNCTION__ ) ;
return _FALSE ;
}
sta_real - > txbf_paid = bfer - > p_aid ;
sta_real - > txbf_gid = bfer - > g_id ;
} else {
/* The other side is beamformee */
bfee = _add_bfee_entry ( adapter , sta , sta_bf_cap , sounding_dim , comp_steering_num ) ;
if ( bfee = = NULL ) {
RTW_ERR ( " %s: Fail to allocate bfee entry! \n " , __FUNCTION__ ) ;
return _FALSE ;
}
sta_real - > txbf_paid = bfee - > p_aid ;
sta_real - > txbf_gid = bfee - > g_id ;
}
return _TRUE ;
}
static void _deinit_entry ( PADAPTER adapter , u8 * ra )
{
struct beamforming_info * bf_info ;
struct beamformer_entry * bfer = NULL ;
struct beamformee_entry * bfee = NULL ;
u8 bHwStateAddInit = _FALSE ;
RTW_INFO ( " +%s \n " , __FUNCTION__ ) ;
bf_info = GET_BEAMFORM_INFO ( adapter ) ;
bfer = beamforming_get_bfer_entry_by_addr ( adapter , ra ) ;
bfee = beamforming_get_bfee_entry_by_addr ( adapter , ra ) ;
if ( ! bfer & & ! bfee ) {
RTW_WARN ( " %s: " MAC_FMT " is neither beamforming ee or er!! \n " ,
__FUNCTION__ , MAC_ARG ( ra ) ) ;
return ;
}
if ( bfer & & bfee )
RTW_ERR ( " %s: " MAC_FMT " is both beamforming ee & er!! \n " ,
__FUNCTION__ , MAC_ARG ( ra ) ) ;
if ( bfer )
_remove_bfer_entry ( adapter , bfer ) ;
if ( bfee )
_remove_bfee_entry ( adapter , bfee ) ;
rtw_hal_set_hwreg ( adapter , HW_VAR_SOUNDING_LEAVE , ra ) ;
RTW_DBG ( " -%s \n " , __FUNCTION__ ) ;
}
void _beamforming_reset ( PADAPTER adapter )
{
RTW_ERR ( " %s: Not ready!! \n " , __FUNCTION__ ) ;
}
void beamforming_enter ( PADAPTER adapter , void * sta )
{
u8 ret ;
ret = _init_entry ( adapter , ( struct sta_info * ) sta ) ;
if ( ret = = _FALSE )
return ;
rtw_hal_set_hwreg ( adapter , HW_VAR_SOUNDING_ENTER , sta ) ;
}
void beamforming_leave ( PADAPTER adapter , u8 * ra )
{
if ( ra = = NULL )
_beamforming_reset ( adapter ) ;
else
_deinit_entry ( adapter , ra ) ;
}
void beamforming_sounding_fail ( PADAPTER adapter )
{
RTW_ERR ( " +%s: not implemented yet! \n " , __FUNCTION__ ) ;
}
u8 beamforming_send_vht_gid_mgnt_packet ( PADAPTER adapter , struct beamformee_entry * entry )
{
struct xmit_priv * xmitpriv ;
struct mlme_priv * mlmepriv ;
struct xmit_frame * pmgntframe ;
struct pkt_attrib * attrib ;
struct rtw_ieee80211_hdr * wlanhdr ;
u8 * pframe ;
xmitpriv = & adapter - > xmitpriv ;
mlmepriv = & adapter - > mlmepriv ;
pmgntframe = alloc_mgtxmitframe ( xmitpriv ) ;
if ( ! pmgntframe )
return _FALSE ;
/* update attribute */
attrib = & pmgntframe - > attrib ;
update_mgntframe_attrib ( adapter , attrib ) ;
attrib - > rate = MGN_6M ;
attrib - > bwmode = CHANNEL_WIDTH_20 ;
attrib - > subtype = WIFI_ACTION ;
_rtw_memset ( pmgntframe - > buf_addr , 0 , WLANHDR_OFFSET + TXDESC_OFFSET ) ;
pframe = ( u8 * ) pmgntframe - > buf_addr + TXDESC_OFFSET ;
wlanhdr = ( struct rtw_ieee80211_hdr * ) pframe ;
wlanhdr - > frame_ctl = 0 ;
SetFrameSubType ( pframe , attrib - > subtype ) ;
SetDuration ( pframe , 0 ) ;
SetFragNum ( pframe , 0 ) ;
SetSeqNum ( pframe , 0 ) ;
_rtw_memcpy ( wlanhdr - > addr1 , entry - > mac_addr , ETH_ALEN ) ;
_rtw_memcpy ( wlanhdr - > addr2 , adapter_mac_addr ( adapter ) , ETH_ALEN ) ;
_rtw_memcpy ( wlanhdr - > addr3 , get_bssid ( mlmepriv ) , ETH_ALEN ) ;
pframe [ 24 ] = RTW_WLAN_CATEGORY_VHT ;
pframe [ 25 ] = RTW_WLAN_ACTION_VHT_GROUPID_MANAGEMENT ;
_rtw_memcpy ( & pframe [ 26 ] , entry - > gid_valid , 8 ) ;
_rtw_memcpy ( & pframe [ 34 ] , entry - > user_position , 16 ) ;
attrib - > pktlen = 54 ;
attrib - > last_txcmdsz = attrib - > pktlen ;
dump_mgntframe ( adapter , pmgntframe ) ;
return _TRUE ;
}
void beamforming_watchdog ( PADAPTER adapter )
{
}
# else /* !RTW_BEAMFORMING_VERSION_2 */
struct beamforming_entry * beamforming_get_entry_by_addr ( struct mlme_priv * pmlmepriv , u8 * ra , u8 * idx )
{
u8 i = 0 ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( pmlmepriv ) ;
for ( i = 0 ; i < BEAMFORMING_ENTRY_NUM ; i + + ) {
if ( pBeamInfo - > beamforming_entry [ i ] . bUsed & &
( _rtw_memcmp ( ra , pBeamInfo - > beamforming_entry [ i ] . mac_addr , ETH_ALEN ) ) ) {
* idx = i ;
return & ( pBeamInfo - > beamforming_entry [ i ] ) ;
}
}
return NULL ;
}
BEAMFORMING_CAP beamforming_get_entry_beam_cap_by_mac_id ( PVOID pmlmepriv , u8 mac_id )
{
u8 i = 0 ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( ( struct mlme_priv * ) pmlmepriv ) ;
BEAMFORMING_CAP BeamformEntryCap = BEAMFORMING_CAP_NONE ;
for ( i = 0 ; i < BEAMFORMING_ENTRY_NUM ; i + + ) {
if ( pBeamInfo - > beamforming_entry [ i ] . bUsed & &
( mac_id = = pBeamInfo - > beamforming_entry [ i ] . mac_id ) ) {
BeamformEntryCap = pBeamInfo - > beamforming_entry [ i ] . beamforming_entry_cap ;
i = BEAMFORMING_ENTRY_NUM ;
}
}
return BeamformEntryCap ;
}
struct beamforming_entry * beamforming_get_free_entry ( struct mlme_priv * pmlmepriv , u8 * idx )
{
u8 i = 0 ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( pmlmepriv ) ;
for ( i = 0 ; i < BEAMFORMING_ENTRY_NUM ; i + + ) {
if ( pBeamInfo - > beamforming_entry [ i ] . bUsed = = _FALSE ) {
* idx = i ;
return & ( pBeamInfo - > beamforming_entry [ i ] ) ;
}
}
return NULL ;
}
struct beamforming_entry * beamforming_add_entry ( PADAPTER adapter , u8 * ra , u16 aid ,
u16 mac_id , CHANNEL_WIDTH bw , BEAMFORMING_CAP beamfrom_cap , u8 * idx )
{
struct mlme_priv * pmlmepriv = & ( adapter - > mlmepriv ) ;
struct beamforming_entry * pEntry = beamforming_get_free_entry ( pmlmepriv , idx ) ;
if ( pEntry ! = NULL ) {
pEntry - > bUsed = _TRUE ;
pEntry - > aid = aid ;
pEntry - > mac_id = mac_id ;
pEntry - > sound_bw = bw ;
if ( check_fwstate ( pmlmepriv , WIFI_AP_STATE ) ) {
u16 BSSID = ( ( * ( adapter_mac_addr ( adapter ) + 5 ) & 0xf0 ) > > 4 ) ^
( * ( adapter_mac_addr ( adapter ) + 5 ) & 0xf ) ; /* BSSID[44:47] xor BSSID[40:43] */
pEntry - > p_aid = ( aid + BSSID * 32 ) & 0x1ff ; /* (dec(A) + dec(B)*32) mod 512 */
pEntry - > g_id = 63 ;
} else if ( check_fwstate ( pmlmepriv , WIFI_ADHOC_STATE ) | | check_fwstate ( pmlmepriv , WIFI_ADHOC_MASTER_STATE ) ) {
pEntry - > p_aid = 0 ;
pEntry - > g_id = 63 ;
} else {
pEntry - > p_aid = ra [ 5 ] ; /* BSSID[39:47] */
pEntry - > p_aid = ( pEntry - > p_aid < < 1 ) | ( ra [ 4 ] > > 7 ) ;
pEntry - > g_id = 0 ;
}
_rtw_memcpy ( pEntry - > mac_addr , ra , ETH_ALEN ) ;
pEntry - > bSound = _FALSE ;
/* 3 TODO SW/FW sound period */
pEntry - > sound_period = 200 ;
pEntry - > beamforming_entry_cap = beamfrom_cap ;
pEntry - > beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE ;
pEntry - > PreLogSeq = 0 ; /*Modified by Jeffery @2015-04-13*/
pEntry - > LogSeq = 0 ; /*Modified by Jeffery @2014-10-29*/
pEntry - > LogRetryCnt = 0 ; /*Modified by Jeffery @2014-10-29*/
pEntry - > LogSuccess = 0 ; /*LogSuccess is NOT needed to be accumulated, so LogSuccessCnt->LogSuccess, 2015-04-13, Jeffery*/
pEntry - > ClockResetTimes = 0 ; /*Modified by Jeffery @2015-04-13*/
pEntry - > LogStatusFailCnt = 0 ;
return pEntry ;
} else
return NULL ;
}
BOOLEAN beamforming_remove_entry ( struct mlme_priv * pmlmepriv , u8 * ra , u8 * idx )
{
struct beamforming_entry * pEntry = beamforming_get_entry_by_addr ( pmlmepriv , ra , idx ) ;
if ( pEntry ! = NULL ) {
pEntry - > bUsed = _FALSE ;
pEntry - > beamforming_entry_cap = BEAMFORMING_CAP_NONE ;
pEntry - > beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE ;
return _TRUE ;
} else
return _FALSE ;
}
/* Used for BeamformingStart_V1 */
void beamforming_dym_ndpa_rate ( PADAPTER adapter )
{
u16 NDPARate = MGN_6M ;
PHAL_DATA_TYPE pHalData = GET_HAL_DATA ( adapter ) ;
if ( pHalData - > MinUndecoratedPWDBForDM > 30 ) /* link RSSI > 30% */
NDPARate = MGN_24M ;
else
NDPARate = MGN_6M ;
/* BW = CHANNEL_WIDTH_20; */
NDPARate = NDPARate < < 8 ;
rtw_hal_set_hwreg ( adapter , HW_VAR_SOUNDING_RATE , ( u8 * ) & NDPARate ) ;
}
void beamforming_dym_period ( PADAPTER Adapter )
{
u8 Idx ;
BOOLEAN bChangePeriod = _FALSE ;
u16 SoundPeriod_SW , SoundPeriod_FW ;
PHAL_DATA_TYPE pHalData = GET_HAL_DATA ( Adapter ) ;
struct dvobj_priv * pdvobjpriv = adapter_to_dvobj ( Adapter ) ;
struct beamforming_entry * pBeamformEntry ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( ( & Adapter - > mlmepriv ) ) ;
struct sounding_info * pSoundInfo = & ( pBeamInfo - > sounding_info ) ;
/* 3 TODO per-client throughput caculation. */
if ( pdvobjpriv - > traffic_stat . cur_tx_tp + pdvobjpriv - > traffic_stat . cur_rx_tp > 2 ) {
SoundPeriod_SW = 32 * 20 ;
SoundPeriod_FW = 2 ;
} else {
SoundPeriod_SW = 32 * 2000 ;
SoundPeriod_FW = 200 ;
}
for ( Idx = 0 ; Idx < BEAMFORMING_ENTRY_NUM ; Idx + + ) {
pBeamformEntry = pBeamInfo - > beamforming_entry + Idx ;
if ( pBeamformEntry - > bDefaultCSI ) {
SoundPeriod_SW = 32 * 2000 ;
SoundPeriod_FW = 200 ;
}
if ( pBeamformEntry - > beamforming_entry_cap & ( BEAMFORMER_CAP_HT_EXPLICIT | BEAMFORMER_CAP_VHT_SU ) ) {
if ( pSoundInfo - > sound_mode = = SOUNDING_FW_VHT_TIMER | | pSoundInfo - > sound_mode = = SOUNDING_FW_HT_TIMER ) {
if ( pBeamformEntry - > sound_period ! = SoundPeriod_FW ) {
pBeamformEntry - > sound_period = SoundPeriod_FW ;
bChangePeriod = _TRUE ; /* Only FW sounding need to send H2C packet to change sound period. */
}
} else if ( pBeamformEntry - > sound_period ! = SoundPeriod_SW )
pBeamformEntry - > sound_period = SoundPeriod_SW ;
}
}
if ( bChangePeriod )
rtw_hal_set_hwreg ( Adapter , HW_VAR_SOUNDING_FW_NDPA , ( u8 * ) & Idx ) ;
}
BOOLEAN issue_ht_sw_ndpa_packet ( PADAPTER Adapter , u8 * ra , CHANNEL_WIDTH bw , u8 qidx )
{
struct xmit_frame * pmgntframe ;
struct pkt_attrib * pattrib ;
struct rtw_ieee80211_hdr * pwlanhdr ;
struct xmit_priv * pxmitpriv = & ( Adapter - > xmitpriv ) ;
struct mlme_ext_priv * pmlmeext = & Adapter - > mlmeextpriv ;
struct mlme_ext_info * pmlmeinfo = & ( pmlmeext - > mlmext_info ) ;
u8 ActionHdr [ 4 ] = { ACT_CAT_VENDOR , 0x00 , 0xe0 , 0x4c } ;
u8 * pframe ;
u16 * fctrl ;
u16 duration = 0 ;
u8 aSifsTime = 0 ;
u8 NDPTxRate = 0 ;
RTW_INFO ( " %s: issue_ht_sw_ndpa_packet! \n " , __func__ ) ;
NDPTxRate = MGN_MCS8 ;
RTW_INFO ( " %s: NDPTxRate =%d \n " , __func__ , NDPTxRate ) ;
pmgntframe = alloc_mgtxmitframe ( pxmitpriv ) ;
if ( pmgntframe = = NULL )
return _FALSE ;
/*update attribute*/
pattrib = & pmgntframe - > attrib ;
update_mgntframe_attrib ( Adapter , pattrib ) ;
pattrib - > qsel = QSLT_MGNT ;
pattrib - > rate = NDPTxRate ;
pattrib - > bwmode = bw ;
pattrib - > order = 1 ;
pattrib - > subtype = WIFI_ACTION_NOACK ;
_rtw_memset ( pmgntframe - > buf_addr , 0 , WLANHDR_OFFSET + TXDESC_OFFSET ) ;
pframe = ( u8 * ) ( pmgntframe - > buf_addr ) + TXDESC_OFFSET ;
pwlanhdr = ( struct rtw_ieee80211_hdr * ) pframe ;
fctrl = & pwlanhdr - > frame_ctl ;
* ( fctrl ) = 0 ;
SetOrderBit ( pframe ) ;
SetFrameSubType ( pframe , WIFI_ACTION_NOACK ) ;
_rtw_memcpy ( pwlanhdr - > addr1 , ra , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr2 , adapter_mac_addr ( Adapter ) , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr3 , get_my_bssid ( & ( pmlmeinfo - > network ) ) , ETH_ALEN ) ;
if ( pmlmeext - > cur_wireless_mode = = WIRELESS_11B )
aSifsTime = 10 ;
else
aSifsTime = 16 ;
duration = 2 * aSifsTime + 40 ;
if ( bw = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
SetDuration ( pframe , duration ) ;
/*HT control field*/
SET_HT_CTRL_CSI_STEERING ( pframe + 24 , 3 ) ;
SET_HT_CTRL_NDP_ANNOUNCEMENT ( pframe + 24 , 1 ) ;
_rtw_memcpy ( pframe + 28 , ActionHdr , 4 ) ;
pattrib - > pktlen = 32 ;
pattrib - > last_txcmdsz = pattrib - > pktlen ;
dump_mgntframe ( Adapter , pmgntframe ) ;
return _TRUE ;
}
BOOLEAN issue_ht_ndpa_packet ( PADAPTER Adapter , u8 * ra , CHANNEL_WIDTH bw , u8 qidx )
{
struct xmit_frame * pmgntframe ;
struct pkt_attrib * pattrib ;
struct rtw_ieee80211_hdr * pwlanhdr ;
struct xmit_priv * pxmitpriv = & ( Adapter - > xmitpriv ) ;
struct mlme_ext_priv * pmlmeext = & Adapter - > mlmeextpriv ;
struct mlme_ext_info * pmlmeinfo = & ( pmlmeext - > mlmext_info ) ;
u8 ActionHdr [ 4 ] = { ACT_CAT_VENDOR , 0x00 , 0xe0 , 0x4c } ;
u8 * pframe ;
u16 * fctrl ;
u16 duration = 0 ;
u8 aSifsTime = 0 ;
pmgntframe = alloc_mgtxmitframe ( pxmitpriv ) ;
if ( pmgntframe = = NULL )
return _FALSE ;
/*update attribute*/
pattrib = & pmgntframe - > attrib ;
update_mgntframe_attrib ( Adapter , pattrib ) ;
if ( qidx = = BCN_QUEUE_INX )
pattrib - > qsel = QSLT_BEACON ;
pattrib - > rate = MGN_MCS8 ;
pattrib - > bwmode = bw ;
pattrib - > order = 1 ;
pattrib - > subtype = WIFI_ACTION_NOACK ;
_rtw_memset ( pmgntframe - > buf_addr , 0 , WLANHDR_OFFSET + TXDESC_OFFSET ) ;
pframe = ( u8 * ) ( pmgntframe - > buf_addr ) + TXDESC_OFFSET ;
pwlanhdr = ( struct rtw_ieee80211_hdr * ) pframe ;
fctrl = & pwlanhdr - > frame_ctl ;
* ( fctrl ) = 0 ;
SetOrderBit ( pframe ) ;
SetFrameSubType ( pframe , WIFI_ACTION_NOACK ) ;
_rtw_memcpy ( pwlanhdr - > addr1 , ra , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr2 , adapter_mac_addr ( Adapter ) , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr3 , get_my_bssid ( & ( pmlmeinfo - > network ) ) , ETH_ALEN ) ;
if ( pmlmeext - > cur_wireless_mode = = WIRELESS_11B )
aSifsTime = 10 ;
else
aSifsTime = 16 ;
duration = 2 * aSifsTime + 40 ;
if ( bw = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
SetDuration ( pframe , duration ) ;
/* HT control field */
SET_HT_CTRL_CSI_STEERING ( pframe + 24 , 3 ) ;
SET_HT_CTRL_NDP_ANNOUNCEMENT ( pframe + 24 , 1 ) ;
_rtw_memcpy ( pframe + 28 , ActionHdr , 4 ) ;
pattrib - > pktlen = 32 ;
pattrib - > last_txcmdsz = pattrib - > pktlen ;
dump_mgntframe ( Adapter , pmgntframe ) ;
return _TRUE ;
}
BOOLEAN beamforming_send_ht_ndpa_packet ( PADAPTER Adapter , u8 * ra , CHANNEL_WIDTH bw , u8 qidx )
{
return issue_ht_ndpa_packet ( Adapter , ra , bw , qidx ) ;
}
BOOLEAN issue_vht_sw_ndpa_packet ( PADAPTER Adapter , u8 * ra , u16 aid , CHANNEL_WIDTH bw , u8 qidx )
{
struct xmit_frame * pmgntframe ;
struct pkt_attrib * pattrib ;
struct rtw_ieee80211_hdr * pwlanhdr ;
struct xmit_priv * pxmitpriv = & ( Adapter - > xmitpriv ) ;
struct mlme_ext_priv * pmlmeext = & Adapter - > mlmeextpriv ;
struct mlme_ext_info * pmlmeinfo = & ( pmlmeext - > mlmext_info ) ;
struct mlme_priv * pmlmepriv = & ( Adapter - > mlmepriv ) ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( pmlmepriv ) ;
struct rtw_ndpa_sta_info sta_info ;
u8 NDPTxRate = 0 ;
u8 * pframe ;
u16 * fctrl ;
u16 duration = 0 ;
u8 sequence = 0 , aSifsTime = 0 ;
RTW_INFO ( " %s: issue_vht_sw_ndpa_packet! \n " , __func__ ) ;
NDPTxRate = MGN_VHT2SS_MCS0 ;
RTW_INFO ( " %s: NDPTxRate =%d \n " , __func__ , NDPTxRate ) ;
pmgntframe = alloc_mgtxmitframe ( pxmitpriv ) ;
if ( pmgntframe = = NULL ) {
RTW_INFO ( " %s, alloc mgnt frame fail \n " , __func__ ) ;
return _FALSE ;
}
/*update attribute*/
pattrib = & pmgntframe - > attrib ;
update_mgntframe_attrib ( Adapter , pattrib ) ;
pattrib - > qsel = QSLT_MGNT ;
pattrib - > rate = NDPTxRate ;
pattrib - > bwmode = bw ;
pattrib - > subtype = WIFI_NDPA ;
_rtw_memset ( pmgntframe - > buf_addr , 0 , WLANHDR_OFFSET + TXDESC_OFFSET ) ;
pframe = ( u8 * ) ( pmgntframe - > buf_addr ) + TXDESC_OFFSET ;
pwlanhdr = ( struct rtw_ieee80211_hdr * ) pframe ;
fctrl = & pwlanhdr - > frame_ctl ;
* ( fctrl ) = 0 ;
SetFrameSubType ( pframe , WIFI_NDPA ) ;
_rtw_memcpy ( pwlanhdr - > addr1 , ra , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr2 , adapter_mac_addr ( Adapter ) , ETH_ALEN ) ;
if ( IsSupported5G ( pmlmeext - > cur_wireless_mode ) | | IsSupportedHT ( pmlmeext - > cur_wireless_mode ) )
aSifsTime = 16 ;
else
aSifsTime = 10 ;
duration = 2 * aSifsTime + 44 ;
if ( bw = = CHANNEL_WIDTH_80 )
duration + = 40 ;
else if ( bw = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
SetDuration ( pframe , duration ) ;
sequence = pBeamInfo - > sounding_sequence < < 2 ;
if ( pBeamInfo - > sounding_sequence > = 0x3f )
pBeamInfo - > sounding_sequence = 0 ;
else
pBeamInfo - > sounding_sequence + + ;
_rtw_memcpy ( pframe + 16 , & sequence , 1 ) ;
if ( ( ( pmlmeinfo - > state & 0x03 ) = = WIFI_FW_ADHOC_STATE ) | | ( ( pmlmeinfo - > state & 0x03 ) = = WIFI_FW_AP_STATE ) )
aid = 0 ;
sta_info . aid = aid ;
sta_info . feedback_type = 0 ;
sta_info . nc_index = 0 ;
_rtw_memcpy ( pframe + 17 , ( u8 * ) & sta_info , 2 ) ;
pattrib - > pktlen = 19 ;
pattrib - > last_txcmdsz = pattrib - > pktlen ;
dump_mgntframe ( Adapter , pmgntframe ) ;
return _TRUE ;
}
BOOLEAN issue_vht_ndpa_packet ( PADAPTER Adapter , u8 * ra , u16 aid , CHANNEL_WIDTH bw , u8 qidx )
{
struct xmit_frame * pmgntframe ;
struct pkt_attrib * pattrib ;
struct rtw_ieee80211_hdr * pwlanhdr ;
struct xmit_priv * pxmitpriv = & ( Adapter - > xmitpriv ) ;
struct mlme_ext_priv * pmlmeext = & Adapter - > mlmeextpriv ;
struct mlme_ext_info * pmlmeinfo = & ( pmlmeext - > mlmext_info ) ;
struct mlme_priv * pmlmepriv = & ( Adapter - > mlmepriv ) ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( pmlmepriv ) ;
struct rtw_ndpa_sta_info sta_info ;
u8 * pframe ;
u16 * fctrl ;
u16 duration = 0 ;
u8 sequence = 0 , aSifsTime = 0 ;
pmgntframe = alloc_mgtxmitframe ( pxmitpriv ) ;
if ( pmgntframe = = NULL )
return _FALSE ;
/*update attribute*/
pattrib = & pmgntframe - > attrib ;
update_mgntframe_attrib ( Adapter , pattrib ) ;
if ( qidx = = BCN_QUEUE_INX )
pattrib - > qsel = QSLT_BEACON ;
pattrib - > rate = MGN_VHT2SS_MCS0 ;
pattrib - > bwmode = bw ;
pattrib - > subtype = WIFI_NDPA ;
_rtw_memset ( pmgntframe - > buf_addr , 0 , WLANHDR_OFFSET + TXDESC_OFFSET ) ;
pframe = ( u8 * ) ( pmgntframe - > buf_addr ) + TXDESC_OFFSET ;
pwlanhdr = ( struct rtw_ieee80211_hdr * ) pframe ;
fctrl = & pwlanhdr - > frame_ctl ;
* ( fctrl ) = 0 ;
SetFrameSubType ( pframe , WIFI_NDPA ) ;
_rtw_memcpy ( pwlanhdr - > addr1 , ra , ETH_ALEN ) ;
_rtw_memcpy ( pwlanhdr - > addr2 , adapter_mac_addr ( Adapter ) , ETH_ALEN ) ;
if ( IsSupported5G ( pmlmeext - > cur_wireless_mode ) | | IsSupportedHT ( pmlmeext - > cur_wireless_mode ) )
aSifsTime = 16 ;
else
aSifsTime = 10 ;
duration = 2 * aSifsTime + 44 ;
if ( bw = = CHANNEL_WIDTH_80 )
duration + = 40 ;
else if ( bw = = CHANNEL_WIDTH_40 )
duration + = 87 ;
else
duration + = 180 ;
SetDuration ( pframe , duration ) ;
sequence = pBeamInfo - > sounding_sequence < < 2 ;
if ( pBeamInfo - > sounding_sequence > = 0x3f )
pBeamInfo - > sounding_sequence = 0 ;
else
pBeamInfo - > sounding_sequence + + ;
_rtw_memcpy ( pframe + 16 , & sequence , 1 ) ;
if ( ( ( pmlmeinfo - > state & 0x03 ) = = WIFI_FW_ADHOC_STATE ) | | ( ( pmlmeinfo - > state & 0x03 ) = = WIFI_FW_AP_STATE ) )
aid = 0 ;
sta_info . aid = aid ;
sta_info . feedback_type = 0 ;
sta_info . nc_index = 0 ;
_rtw_memcpy ( pframe + 17 , ( u8 * ) & sta_info , 2 ) ;
pattrib - > pktlen = 19 ;
pattrib - > last_txcmdsz = pattrib - > pktlen ;
dump_mgntframe ( Adapter , pmgntframe ) ;
return _TRUE ;
}
BOOLEAN beamforming_send_vht_ndpa_packet ( PADAPTER Adapter , u8 * ra , u16 aid , CHANNEL_WIDTH bw , u8 qidx )
{
return issue_vht_ndpa_packet ( Adapter , ra , aid , bw , qidx ) ;
}
BOOLEAN beamfomring_bSounding ( struct beamforming_info * pBeamInfo )
{
BOOLEAN bSounding = _FALSE ;
if ( ( beamforming_get_beamform_cap ( pBeamInfo ) & BEAMFORMER_CAP ) = = 0 )
bSounding = _FALSE ;
else
bSounding = _TRUE ;
return bSounding ;
}
u8 beamforming_sounding_idx ( struct beamforming_info * pBeamInfo )
{
u8 idx = 0 ;
u8 i ;
for ( i = 0 ; i < BEAMFORMING_ENTRY_NUM ; i + + ) {
if ( pBeamInfo - > beamforming_entry [ i ] . bUsed & &
( _FALSE = = pBeamInfo - > beamforming_entry [ i ] . bSound ) ) {
idx = i ;
break ;
}
}
return idx ;
}
SOUNDING_MODE beamforming_sounding_mode ( struct beamforming_info * pBeamInfo , u8 idx )
{
struct beamforming_entry BeamEntry = pBeamInfo - > beamforming_entry [ idx ] ;
SOUNDING_MODE mode ;
if ( BeamEntry . beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU )
mode = SOUNDING_FW_VHT_TIMER ;
else if ( BeamEntry . beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT )
mode = SOUNDING_FW_HT_TIMER ;
else
mode = SOUNDING_STOP_All_TIMER ;
return mode ;
}
u16 beamforming_sounding_time ( struct beamforming_info * pBeamInfo , SOUNDING_MODE mode , u8 idx )
{
u16 sounding_time = 0xffff ;
struct beamforming_entry BeamEntry = pBeamInfo - > beamforming_entry [ idx ] ;
sounding_time = BeamEntry . sound_period ;
return sounding_time ;
}
CHANNEL_WIDTH beamforming_sounding_bw ( struct beamforming_info * pBeamInfo , SOUNDING_MODE mode , u8 idx )
{
CHANNEL_WIDTH sounding_bw = CHANNEL_WIDTH_20 ;
struct beamforming_entry BeamEntry = pBeamInfo - > beamforming_entry [ idx ] ;
sounding_bw = BeamEntry . sound_bw ;
return sounding_bw ;
}
BOOLEAN beamforming_select_beam_entry ( struct beamforming_info * pBeamInfo )
{
struct sounding_info * pSoundInfo = & ( pBeamInfo - > sounding_info ) ;
pSoundInfo - > sound_idx = beamforming_sounding_idx ( pBeamInfo ) ;
if ( pSoundInfo - > sound_idx < BEAMFORMING_ENTRY_NUM )
pSoundInfo - > sound_mode = beamforming_sounding_mode ( pBeamInfo , pSoundInfo - > sound_idx ) ;
else
pSoundInfo - > sound_mode = SOUNDING_STOP_All_TIMER ;
if ( SOUNDING_STOP_All_TIMER = = pSoundInfo - > sound_mode )
return _FALSE ;
else {
pSoundInfo - > sound_bw = beamforming_sounding_bw ( pBeamInfo , pSoundInfo - > sound_mode , pSoundInfo - > sound_idx ) ;
pSoundInfo - > sound_period = beamforming_sounding_time ( pBeamInfo , pSoundInfo - > sound_mode , pSoundInfo - > sound_idx ) ;
return _TRUE ;
}
}
BOOLEAN beamforming_start_fw ( PADAPTER adapter , u8 idx )
{
u8 * RA = NULL ;
struct beamforming_entry * pEntry ;
BOOLEAN ret = _TRUE ;
struct mlme_priv * pmlmepriv = & ( adapter - > mlmepriv ) ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( pmlmepriv ) ;
pEntry = & ( pBeamInfo - > beamforming_entry [ idx ] ) ;
if ( pEntry - > bUsed = = _FALSE ) {
RTW_INFO ( " Skip Beamforming, no entry for Idx =%d \n " , idx ) ;
return _FALSE ;
}
pEntry - > beamforming_entry_state = BEAMFORMING_ENTRY_STATE_PROGRESSING ;
pEntry - > bSound = _TRUE ;
rtw_hal_set_hwreg ( adapter , HW_VAR_SOUNDING_FW_NDPA , ( u8 * ) & idx ) ;
return _TRUE ;
}
void beamforming_end_fw ( PADAPTER adapter )
{
u8 idx = 0 ;
rtw_hal_set_hwreg ( adapter , HW_VAR_SOUNDING_FW_NDPA , ( u8 * ) & idx ) ;
RTW_INFO ( " %s \n " , __FUNCTION__ ) ;
}
BOOLEAN beamforming_start_period ( PADAPTER adapter )
{
BOOLEAN ret = _TRUE ;
struct mlme_priv * pmlmepriv = & ( adapter - > mlmepriv ) ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( pmlmepriv ) ;
struct sounding_info * pSoundInfo = & ( pBeamInfo - > sounding_info ) ;
beamforming_dym_ndpa_rate ( adapter ) ;
beamforming_select_beam_entry ( pBeamInfo ) ;
if ( pSoundInfo - > sound_mode = = SOUNDING_FW_VHT_TIMER | | pSoundInfo - > sound_mode = = SOUNDING_FW_HT_TIMER )
ret = beamforming_start_fw ( adapter , pSoundInfo - > sound_idx ) ;
else
ret = _FALSE ;
RTW_INFO ( " %s Idx %d Mode %d BW %d Period %d \n " , __FUNCTION__ ,
pSoundInfo - > sound_idx , pSoundInfo - > sound_mode , pSoundInfo - > sound_bw , pSoundInfo - > sound_period ) ;
return ret ;
}
void beamforming_end_period ( PADAPTER adapter )
{
u8 idx = 0 ;
struct beamforming_entry * pBeamformEntry ;
struct mlme_priv * pmlmepriv = & ( adapter - > mlmepriv ) ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( pmlmepriv ) ;
struct sounding_info * pSoundInfo = & ( pBeamInfo - > sounding_info ) ;
if ( pSoundInfo - > sound_mode = = SOUNDING_FW_VHT_TIMER | | pSoundInfo - > sound_mode = = SOUNDING_FW_HT_TIMER )
beamforming_end_fw ( adapter ) ;
}
void beamforming_notify ( PADAPTER adapter )
{
BOOLEAN bSounding = _FALSE ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( & ( adapter - > mlmepriv ) ) ;
bSounding = beamfomring_bSounding ( pBeamInfo ) ;
if ( pBeamInfo - > beamforming_state = = BEAMFORMING_STATE_IDLE ) {
if ( bSounding ) {
if ( beamforming_start_period ( adapter ) = = _TRUE )
pBeamInfo - > beamforming_state = BEAMFORMING_STATE_START ;
}
} else if ( pBeamInfo - > beamforming_state = = BEAMFORMING_STATE_START ) {
if ( bSounding ) {
if ( beamforming_start_period ( adapter ) = = _FALSE )
pBeamInfo - > beamforming_state = BEAMFORMING_STATE_END ;
} else {
beamforming_end_period ( adapter ) ;
pBeamInfo - > beamforming_state = BEAMFORMING_STATE_END ;
}
} else if ( pBeamInfo - > beamforming_state = = BEAMFORMING_STATE_END ) {
if ( bSounding ) {
if ( beamforming_start_period ( adapter ) = = _TRUE )
pBeamInfo - > beamforming_state = BEAMFORMING_STATE_START ;
}
} else
RTW_INFO ( " %s BeamformState %d \n " , __FUNCTION__ , pBeamInfo - > beamforming_state ) ;
RTW_INFO ( " %s BeamformState %d bSounding %d \n " , __FUNCTION__ , pBeamInfo - > beamforming_state , bSounding ) ;
}
BOOLEAN beamforming_init_entry ( PADAPTER adapter , struct sta_info * psta , u8 * idx )
{
struct mlme_priv * pmlmepriv = & ( adapter - > mlmepriv ) ;
struct ht_priv * phtpriv = & ( pmlmepriv - > htpriv ) ;
# ifdef CONFIG_80211AC_VHT
struct vht_priv * pvhtpriv = & ( pmlmepriv - > vhtpriv ) ;
# endif
struct mlme_ext_priv * pmlmeext = & ( adapter - > mlmeextpriv ) ;
struct mlme_ext_info * pmlmeinfo = & ( pmlmeext - > mlmext_info ) ;
struct beamforming_entry * pBeamformEntry = NULL ;
u8 * ra ;
u16 aid , mac_id ;
u8 wireless_mode ;
CHANNEL_WIDTH bw = CHANNEL_WIDTH_20 ;
BEAMFORMING_CAP beamform_cap = BEAMFORMING_CAP_NONE ;
/* The current setting does not support Beaforming */
if ( 0 = = phtpriv - > beamform_cap
# ifdef CONFIG_80211AC_VHT
& & 0 = = pvhtpriv - > beamform_cap
# endif
) {
RTW_INFO ( " The configuration disabled Beamforming! Skip... \n " ) ;
return _FALSE ;
}
aid = psta - > aid ;
ra = psta - > hwaddr ;
mac_id = psta - > mac_id ;
wireless_mode = psta - > wireless_mode ;
bw = psta - > bw_mode ;
if ( IsSupportedHT ( wireless_mode ) | | IsSupportedVHT ( wireless_mode ) ) {
/* 3 */ /* HT */
u8 cur_beamform ;
cur_beamform = psta - > htpriv . beamform_cap ;
/* We are Beamformee because the STA is Beamformer */
if ( TEST_FLAG ( cur_beamform , BEAMFORMING_HT_BEAMFORMER_ENABLE ) )
beamform_cap = ( BEAMFORMING_CAP ) ( beamform_cap | BEAMFORMEE_CAP_HT_EXPLICIT ) ;
/* We are Beamformer because the STA is Beamformee */
if ( TEST_FLAG ( cur_beamform , BEAMFORMING_HT_BEAMFORMEE_ENABLE ) )
beamform_cap = ( BEAMFORMING_CAP ) ( beamform_cap | BEAMFORMER_CAP_HT_EXPLICIT ) ;
# ifdef CONFIG_80211AC_VHT
if ( IsSupportedVHT ( wireless_mode ) ) {
/* 3 */ /* VHT */
cur_beamform = psta - > vhtpriv . beamform_cap ;
/* We are Beamformee because the STA is Beamformer */
if ( TEST_FLAG ( cur_beamform , BEAMFORMING_VHT_BEAMFORMER_ENABLE ) )
beamform_cap = ( BEAMFORMING_CAP ) ( beamform_cap | BEAMFORMEE_CAP_VHT_SU ) ;
/* We are Beamformer because the STA is Beamformee */
if ( TEST_FLAG ( cur_beamform , BEAMFORMING_VHT_BEAMFORMEE_ENABLE ) )
beamform_cap = ( BEAMFORMING_CAP ) ( beamform_cap | BEAMFORMER_CAP_VHT_SU ) ;
}
# endif /* CONFIG_80211AC_VHT */
if ( beamform_cap = = BEAMFORMING_CAP_NONE )
return _FALSE ;
RTW_INFO ( " Beamforming Config Capability = 0x%02X \n " , beamform_cap ) ;
pBeamformEntry = beamforming_get_entry_by_addr ( pmlmepriv , ra , idx ) ;
if ( pBeamformEntry = = NULL ) {
pBeamformEntry = beamforming_add_entry ( adapter , ra , aid , mac_id , bw , beamform_cap , idx ) ;
if ( pBeamformEntry = = NULL )
return _FALSE ;
else
pBeamformEntry - > beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZEING ;
} else {
/* Entry has been created. If entry is initialing or progressing then errors occur. */
if ( pBeamformEntry - > beamforming_entry_state ! = BEAMFORMING_ENTRY_STATE_INITIALIZED & &
pBeamformEntry - > beamforming_entry_state ! = BEAMFORMING_ENTRY_STATE_PROGRESSED ) {
RTW_INFO ( " Error State of Beamforming " ) ;
return _FALSE ;
} else
pBeamformEntry - > beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZEING ;
}
pBeamformEntry - > beamforming_entry_state = BEAMFORMING_ENTRY_STATE_INITIALIZED ;
psta - > txbf_paid = pBeamformEntry - > p_aid ;
psta - > txbf_gid = pBeamformEntry - > g_id ;
RTW_INFO ( " %s Idx %d \n " , __FUNCTION__ , * idx ) ;
} else
return _FALSE ;
return _SUCCESS ;
}
void beamforming_deinit_entry ( PADAPTER adapter , u8 * ra )
{
u8 idx = 0 ;
struct mlme_priv * pmlmepriv = & ( adapter - > mlmepriv ) ;
if ( beamforming_remove_entry ( pmlmepriv , ra , & idx ) = = _TRUE )
rtw_hal_set_hwreg ( adapter , HW_VAR_SOUNDING_LEAVE , ( u8 * ) & idx ) ;
RTW_INFO ( " %s Idx %d \n " , __FUNCTION__ , idx ) ;
}
void beamforming_reset ( PADAPTER adapter )
{
u8 idx = 0 ;
struct mlme_priv * pmlmepriv = & ( adapter - > mlmepriv ) ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( pmlmepriv ) ;
for ( idx = 0 ; idx < BEAMFORMING_ENTRY_NUM ; idx + + ) {
if ( pBeamInfo - > beamforming_entry [ idx ] . bUsed = = _TRUE ) {
pBeamInfo - > beamforming_entry [ idx ] . bUsed = _FALSE ;
pBeamInfo - > beamforming_entry [ idx ] . beamforming_entry_cap = BEAMFORMING_CAP_NONE ;
pBeamInfo - > beamforming_entry [ idx ] . beamforming_entry_state = BEAMFORMING_ENTRY_STATE_UNINITIALIZE ;
rtw_hal_set_hwreg ( adapter , HW_VAR_SOUNDING_LEAVE , ( u8 * ) & idx ) ;
}
}
RTW_INFO ( " %s \n " , __FUNCTION__ ) ;
}
void beamforming_sounding_fail ( PADAPTER Adapter )
{
struct mlme_priv * pmlmepriv = & ( Adapter - > mlmepriv ) ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( pmlmepriv ) ;
struct beamforming_entry * pEntry = & ( pBeamInfo - > beamforming_entry [ pBeamInfo - > beamforming_cur_idx ] ) ;
pEntry - > bSound = _FALSE ;
rtw_hal_set_hwreg ( Adapter , HW_VAR_SOUNDING_FW_NDPA , ( u8 * ) & pBeamInfo - > beamforming_cur_idx ) ;
beamforming_deinit_entry ( Adapter , pEntry - > mac_addr ) ;
}
void beamforming_check_sounding_success ( PADAPTER Adapter , BOOLEAN status )
{
struct mlme_priv * pmlmepriv = & ( Adapter - > mlmepriv ) ;
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( pmlmepriv ) ;
struct beamforming_entry * pEntry = & ( pBeamInfo - > beamforming_entry [ pBeamInfo - > beamforming_cur_idx ] ) ;
if ( status = = 1 )
pEntry - > LogStatusFailCnt = 0 ;
else {
pEntry - > LogStatusFailCnt + + ;
RTW_INFO ( " %s LogStatusFailCnt %d \n " , __FUNCTION__ , pEntry - > LogStatusFailCnt ) ;
}
if ( pEntry - > LogStatusFailCnt > 20 ) {
RTW_INFO ( " %s LogStatusFailCnt > 20, Stop SOUNDING \n " , __FUNCTION__ ) ;
/* pEntry->bSound = _FALSE; */
/* rtw_hal_set_hwreg(Adapter, HW_VAR_SOUNDING_FW_NDPA, (u8 *)&pBeamInfo->beamforming_cur_idx); */
/* beamforming_deinit_entry(Adapter, pEntry->mac_addr); */
beamforming_wk_cmd ( Adapter , BEAMFORMING_CTRL_SOUNDING_FAIL , NULL , 0 , 1 ) ;
}
}
void beamforming_enter ( PADAPTER adapter , PVOID psta )
{
u8 idx = 0xff ;
if ( beamforming_init_entry ( adapter , ( struct sta_info * ) psta , & idx ) )
rtw_hal_set_hwreg ( adapter , HW_VAR_SOUNDING_ENTER , ( u8 * ) & idx ) ;
/* RTW_INFO("%s Idx %d\n", __FUNCTION__, idx); */
}
void beamforming_leave ( PADAPTER adapter , u8 * ra )
{
if ( ra = = NULL )
beamforming_reset ( adapter ) ;
else
beamforming_deinit_entry ( adapter , ra ) ;
beamforming_notify ( adapter ) ;
}
BEAMFORMING_CAP beamforming_get_beamform_cap ( struct beamforming_info * pBeamInfo )
{
u8 i ;
BOOLEAN bSelfBeamformer = _FALSE ;
BOOLEAN bSelfBeamformee = _FALSE ;
struct beamforming_entry beamforming_entry ;
BEAMFORMING_CAP beamform_cap = BEAMFORMING_CAP_NONE ;
for ( i = 0 ; i < BEAMFORMING_ENTRY_NUM ; i + + ) {
beamforming_entry = pBeamInfo - > beamforming_entry [ i ] ;
if ( beamforming_entry . bUsed ) {
if ( ( beamforming_entry . beamforming_entry_cap & BEAMFORMEE_CAP_VHT_SU ) | |
( beamforming_entry . beamforming_entry_cap & BEAMFORMEE_CAP_HT_EXPLICIT ) )
bSelfBeamformee = _TRUE ;
if ( ( beamforming_entry . beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU ) | |
( beamforming_entry . beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT ) )
bSelfBeamformer = _TRUE ;
}
if ( bSelfBeamformer & & bSelfBeamformee )
i = BEAMFORMING_ENTRY_NUM ;
}
if ( bSelfBeamformer )
beamform_cap | = BEAMFORMER_CAP ;
if ( bSelfBeamformee )
beamform_cap | = BEAMFORMEE_CAP ;
return beamform_cap ;
}
void beamforming_watchdog ( PADAPTER Adapter )
{
struct beamforming_info * pBeamInfo = GET_BEAMFORM_INFO ( ( & ( Adapter - > mlmepriv ) ) ) ;
if ( pBeamInfo - > beamforming_state ! = BEAMFORMING_STATE_START )
return ;
beamforming_dym_period ( Adapter ) ;
beamforming_dym_ndpa_rate ( Adapter ) ;
}
# endif /* !RTW_BEAMFORMING_VERSION_2 */
# endif /* #if (BEAMFORMING_SUPPORT ==0) - for diver defined beamforming*/
u32 beamforming_get_report_frame ( PADAPTER Adapter , union recv_frame * precv_frame )
{
u32 ret = _SUCCESS ;
# if (BEAMFORMING_SUPPORT == 1)
PHAL_DATA_TYPE pHalData = GET_HAL_DATA ( Adapter ) ;
PDM_ODM_T pDM_Odm = & ( pHalData - > odmpriv ) ;
ret = Beamforming_GetReportFrame ( pDM_Odm , precv_frame ) ;
# else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
# ifdef RTW_BEAMFORMING_VERSION_2
struct beamformee_entry * pBeamformEntry = NULL ;
struct mlme_priv * pmlmepriv = & Adapter - > mlmepriv ;
u8 * pframe = precv_frame - > u . hdr . rx_data ;
u32 frame_len = precv_frame - > u . hdr . len ;
u8 * ta ;
u8 * frame_body ;
u8 category , action ;
u8 * pMIMOCtrlField , * pCSIMatrix ;
u8 Nc = 0 , Nr = 0 , CH_W = 0 ;
u16 CSIMatrixLen = 0 ;
RTW_DBG ( " +%s \n " , __FUNCTION__ ) ;
/* Memory comparison to see if CSI report is the same with previous one */
ta = GetAddr2Ptr ( pframe ) ;
pBeamformEntry = beamforming_get_bfee_entry_by_addr ( Adapter , ta ) ;
if ( ! pBeamformEntry )
return _FAIL ;
frame_body = pframe + sizeof ( struct rtw_ieee80211_hdr_3addr ) ;
category = frame_body [ 0 ] ;
action = frame_body [ 1 ] ;
if ( ( category = = RTW_WLAN_CATEGORY_VHT )
& & ( action = = RTW_WLAN_ACTION_VHT_COMPRESSED_BEAMFORMING ) ) {
pMIMOCtrlField = pframe + 26 ;
Nc = ( ( * pMIMOCtrlField ) & 0x7 ) + 1 ;
Nr = ( ( ( * pMIMOCtrlField ) & 0x38 ) > > 3 ) + 1 ;
CH_W = ( ( ( * pMIMOCtrlField ) & 0xC0 ) > > 6 ) ;
/*
* 24 + ( 1 + 1 + 3 ) + 2
* = = > MAC header + ( Category + ActionCode + MIMOControlField ) + SNR ( Nc = 2 )
*/
pCSIMatrix = pMIMOCtrlField + 3 + Nc ;
CSIMatrixLen = frame_len - 26 - 3 - Nc ;
} else if ( ( category = = RTW_WLAN_CATEGORY_HT )
& & ( action = = RTW_WLAN_ACTION_HT_COMPRESS_BEAMFORMING ) ) {
pMIMOCtrlField = pframe + 26 ;
Nc = ( ( * pMIMOCtrlField ) & 0x3 ) + 1 ;
Nr = ( ( ( * pMIMOCtrlField ) & 0xC ) > > 2 ) + 1 ;
CH_W = ( ( * pMIMOCtrlField ) & 0x10 ) > > 4 ;
/*
* 24 + ( 1 + 1 + 6 ) + 2
* = = > MAC header + ( Category + ActionCode + MIMOControlField ) + SNR ( Nc = 2 )
*/
pCSIMatrix = pMIMOCtrlField + 6 + Nr ;
CSIMatrixLen = frame_len - 26 - 6 - Nr ;
}
RTW_INFO ( " %s: pkt type=%d-%d, Nc=%d, Nr=%d, CH_W=%d \n " ,
__FUNCTION__ , category , action , Nc , Nr , CH_W ) ;
# else /* !RTW_BEAMFORMING_VERSION_2 */
struct beamforming_entry * pBeamformEntry = NULL ;
struct mlme_priv * pmlmepriv = & ( Adapter - > mlmepriv ) ;
u8 * pframe = precv_frame - > u . hdr . rx_data ;
u32 frame_len = precv_frame - > u . hdr . len ;
u8 * ta ;
u8 idx , offset ;
/*RTW_INFO("beamforming_get_report_frame\n");*/
/*Memory comparison to see if CSI report is the same with previous one*/
ta = GetAddr2Ptr ( pframe ) ;
pBeamformEntry = beamforming_get_entry_by_addr ( pmlmepriv , ta , & idx ) ;
if ( pBeamformEntry - > beamforming_entry_cap & BEAMFORMER_CAP_VHT_SU )
offset = 31 ; /*24+(1+1+3)+2 MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/
else if ( pBeamformEntry - > beamforming_entry_cap & BEAMFORMER_CAP_HT_EXPLICIT )
offset = 34 ; /*24+(1+1+6)+2 MAC header+(Category+ActionCode+MIMOControlField)+SNR(Nc=2)*/
else
return ret ;
/*RTW_INFO("%s MacId %d offset=%d\n", __FUNCTION__, pBeamformEntry->mac_id, offset);*/
if ( _rtw_memcmp ( pBeamformEntry - > PreCsiReport + offset , pframe + offset , frame_len - offset ) = = _FALSE )
pBeamformEntry - > DefaultCsiCnt = 0 ;
else
pBeamformEntry - > DefaultCsiCnt + + ;
_rtw_memcpy ( & pBeamformEntry - > PreCsiReport , pframe , frame_len ) ;
pBeamformEntry - > bDefaultCSI = _FALSE ;
if ( pBeamformEntry - > DefaultCsiCnt > 20 )
pBeamformEntry - > bDefaultCSI = _TRUE ;
else
pBeamformEntry - > bDefaultCSI = _FALSE ;
# endif /* !RTW_BEAMFORMING_VERSION_2 */
# endif
return ret ;
}
void beamforming_get_ndpa_frame ( PADAPTER Adapter , union recv_frame * precv_frame )
{
# if (BEAMFORMING_SUPPORT == 1)
PHAL_DATA_TYPE pHalData = GET_HAL_DATA ( Adapter ) ;
PDM_ODM_T pDM_Odm = & ( pHalData - > odmpriv ) ;
Beamforming_GetNDPAFrame ( pDM_Odm , precv_frame ) ;
# else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
# ifdef RTW_BEAMFORMING_VERSION_2
RTW_DBG ( " +%s \n " , __FUNCTION__ ) ;
# else /* !RTW_BEAMFORMING_VERSION_2 */
u8 * ta ;
u8 idx , Sequence ;
u8 * pframe = precv_frame - > u . hdr . rx_data ;
struct mlme_priv * pmlmepriv = & ( Adapter - > mlmepriv ) ;
struct beamforming_entry * pBeamformEntry = NULL ;
/*RTW_INFO("beamforming_get_ndpa_frame\n");*/
if ( IS_HARDWARE_TYPE_8812 ( Adapter ) = = _FALSE )
return ;
else if ( GetFrameSubType ( pframe ) ! = WIFI_NDPA )
return ;
ta = GetAddr2Ptr ( pframe ) ;
/*Remove signaling TA. */
ta [ 0 ] = ta [ 0 ] & 0xFE ;
pBeamformEntry = beamforming_get_entry_by_addr ( pmlmepriv , ta , & idx ) ;
if ( pBeamformEntry = = NULL )
return ;
else if ( ! ( pBeamformEntry - > beamforming_entry_cap & BEAMFORMEE_CAP_VHT_SU ) )
return ;
/*LogSuccess: As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is NO LONGER needed !2015-04-10, Jeffery*/
/*ClockResetTimes: While BFer entry always doesn't receive our CSI, clock will reset again and again.So ClockResetTimes is limited to 5 times.2015-04-13, Jeffery*/
else if ( ( pBeamformEntry - > LogSuccess = = 1 ) | | ( pBeamformEntry - > ClockResetTimes = = 5 ) ) {
RTW_INFO ( " [%s] LogSeq=%d, PreLogSeq=%d \n " , __func__ , pBeamformEntry - > LogSeq , pBeamformEntry - > PreLogSeq ) ;
return ;
}
Sequence = ( pframe [ 16 ] ) > > 2 ;
RTW_INFO ( " [%s] Start, Sequence=%d, LogSeq=%d, PreLogSeq=%d, LogRetryCnt=%d, ClockResetTimes=%d, LogSuccess=%d \n " ,
__func__ , Sequence , pBeamformEntry - > LogSeq , pBeamformEntry - > PreLogSeq , pBeamformEntry - > LogRetryCnt , pBeamformEntry - > ClockResetTimes , pBeamformEntry - > LogSuccess ) ;
if ( ( pBeamformEntry - > LogSeq ! = 0 ) & & ( pBeamformEntry - > PreLogSeq ! = 0 ) ) {
/*Success condition*/
if ( ( pBeamformEntry - > LogSeq ! = Sequence ) & & ( pBeamformEntry - > PreLogSeq ! = pBeamformEntry - > LogSeq ) ) {
/* break option for clcok reset, 2015-03-30, Jeffery */
pBeamformEntry - > LogRetryCnt = 0 ;
/*As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is no longer needed.*/
/*That is, LogSuccess is NOT needed to be reset to zero, 2015-04-13, Jeffery*/
pBeamformEntry - > LogSuccess = 1 ;
} else { /*Fail condition*/
if ( pBeamformEntry - > LogRetryCnt = = 5 ) {
pBeamformEntry - > ClockResetTimes + + ;
pBeamformEntry - > LogRetryCnt = 0 ;
RTW_INFO ( " [%s] Clock Reset!!! ClockResetTimes=%d \n " , __func__ , pBeamformEntry - > ClockResetTimes ) ;
beamforming_wk_cmd ( Adapter , BEAMFORMING_CTRL_SOUNDING_CLK , NULL , 0 , 1 ) ;
} else
pBeamformEntry - > LogRetryCnt + + ;
}
}
/*Update LogSeq & PreLogSeq*/
pBeamformEntry - > PreLogSeq = pBeamformEntry - > LogSeq ;
pBeamformEntry - > LogSeq = Sequence ;
# endif /* !RTW_BEAMFORMING_VERSION_2 */
# endif
}
/* octets in data header, no WEP */
# define sMacHdrLng 24
/* VHT Group ID (GID) Management Frame */
# define FRAME_OFFSET_VHT_GID_MGNT_MEMBERSHIP_STATUS_ARRAY (sMacHdrLng + 2)
# define FRAME_OFFSET_VHT_GID_MGNT_USER_POSITION_ARRAY (sMacHdrLng + 10)
/* VHT GID Management Frame Info */
# define GET_VHT_GID_MGNT_INFO_MEMBERSHIP_STATUS(_pStart) LE_BITS_TO_1BYTE((_pStart), 0, 8)
# define GET_VHT_GID_MGNT_INFO_USER_POSITION(_pStart) LE_BITS_TO_1BYTE((_pStart), 0, 8)
/*
* Description :
* On VHT GID management frame by an MU beamformee .
*
* 2015.05 .20 . Created by tynli .
*/
u32 beamforming_get_vht_gid_mgnt_frame ( PADAPTER adapter , union recv_frame * precv_frame )
{
# ifdef RTW_BEAMFORMING_VERSION_2
u8 * ta ;
u8 idx ;
u8 * pframe ;
u8 * pBuffer = NULL ;
struct beamformer_entry * bfer = NULL ;
RTW_DBG ( " +%s \n " , __FUNCTION__ ) ;
pframe = precv_frame - > u . hdr . rx_data ;
/* Get BFer entry by Addr2 */
ta = GetAddr2Ptr ( pframe ) ;
/* Remove signaling TA */
ta [ 0 ] & = 0xFE ;
bfer = beamforming_get_bfer_entry_by_addr ( adapter , ta ) ;
if ( ! bfer ) {
RTW_INFO ( " %s: Cannot find BFer entry!! \n " , __FUNCTION__ ) ;
return _FAIL ;
}
/* Parsing Membership Status Array */
pBuffer = pframe + FRAME_OFFSET_VHT_GID_MGNT_MEMBERSHIP_STATUS_ARRAY ;
for ( idx = 0 ; idx < 8 ; idx + + )
bfer - > gid_valid [ idx ] = GET_VHT_GID_MGNT_INFO_MEMBERSHIP_STATUS ( pBuffer + idx ) ;
/* Parsing User Position Array */
pBuffer = pframe + FRAME_OFFSET_VHT_GID_MGNT_USER_POSITION_ARRAY ;
for ( idx = 0 ; idx < 16 ; idx + + )
bfer - > user_position [ idx ] = GET_VHT_GID_MGNT_INFO_USER_POSITION ( pBuffer + idx ) ;
/* Config HW GID table */
beamforming_wk_cmd ( adapter , BEAMFORMING_CTRL_SET_GID_TABLE , ( u8 * ) & bfer , sizeof ( struct beamformer_entry * ) , 1 ) ;
return _SUCCESS ;
# else /* !RTW_BEAMFORMING_VERSION_2 */
return _FAIL ;
# endif /* !RTW_BEAMFORMING_VERSION_2 */
}
void beamforming_wk_hdl ( _adapter * padapter , u8 type , u8 * pbuf )
{
PHAL_DATA_TYPE pHalData = GET_HAL_DATA ( padapter ) ;
PDM_ODM_T pDM_Odm = & ( pHalData - > odmpriv ) ;
# if (BEAMFORMING_SUPPORT == 1) /*(BEAMFORMING_SUPPORT == 1)- for PHYDM beamfoming*/
switch ( type ) {
case BEAMFORMING_CTRL_ENTER : {
struct sta_info * psta = ( PVOID ) pbuf ;
u16 staIdx = psta - > mac_id ;
Beamforming_Enter ( pDM_Odm , staIdx ) ;
break ;
}
case BEAMFORMING_CTRL_LEAVE :
Beamforming_Leave ( pDM_Odm , pbuf ) ;
break ;
default :
break ;
}
# else /*(BEAMFORMING_SUPPORT == 0)- for drv beamfoming*/
switch ( type ) {
case BEAMFORMING_CTRL_ENTER :
beamforming_enter ( padapter , ( PVOID ) pbuf ) ;
break ;
case BEAMFORMING_CTRL_LEAVE :
beamforming_leave ( padapter , pbuf ) ;
break ;
case BEAMFORMING_CTRL_SOUNDING_FAIL :
beamforming_sounding_fail ( padapter ) ;
break ;
case BEAMFORMING_CTRL_SOUNDING_CLK :
rtw_hal_set_hwreg ( padapter , HW_VAR_SOUNDING_CLK , NULL ) ;
break ;
case BEAMFORMING_CTRL_SET_GID_TABLE :
rtw_hal_set_hwreg ( padapter , HW_VAR_SOUNDING_SET_GID_TABLE , * ( void * * ) pbuf ) ;
break ;
default :
break ;
}
# endif
}
u8 beamforming_wk_cmd ( _adapter * padapter , s32 type , u8 * pbuf , s32 size , u8 enqueue )
{
struct cmd_obj * ph2c ;
struct drvextra_cmd_parm * pdrvextra_cmd_parm ;
struct cmd_priv * pcmdpriv = & padapter - > cmdpriv ;
u8 res = _SUCCESS ;
if ( enqueue ) {
u8 * wk_buf ;
ph2c = ( struct cmd_obj * ) rtw_zmalloc ( sizeof ( struct cmd_obj ) ) ;
if ( ph2c = = NULL ) {
res = _FAIL ;
goto exit ;
}
pdrvextra_cmd_parm = ( struct drvextra_cmd_parm * ) rtw_zmalloc ( sizeof ( struct drvextra_cmd_parm ) ) ;
if ( pdrvextra_cmd_parm = = NULL ) {
rtw_mfree ( ( unsigned char * ) ph2c , sizeof ( struct cmd_obj ) ) ;
res = _FAIL ;
goto exit ;
}
if ( pbuf ! = NULL ) {
wk_buf = rtw_zmalloc ( size ) ;
if ( wk_buf = = NULL ) {
rtw_mfree ( ( u8 * ) ph2c , sizeof ( struct cmd_obj ) ) ;
rtw_mfree ( ( u8 * ) pdrvextra_cmd_parm , sizeof ( struct drvextra_cmd_parm ) ) ;
res = _FAIL ;
goto exit ;
}
_rtw_memcpy ( wk_buf , pbuf , size ) ;
} else {
wk_buf = NULL ;
size = 0 ;
}
pdrvextra_cmd_parm - > ec_id = BEAMFORMING_WK_CID ;
pdrvextra_cmd_parm - > type = type ;
pdrvextra_cmd_parm - > size = size ;
pdrvextra_cmd_parm - > pbuf = wk_buf ;
init_h2fwcmd_w_parm_no_rsp ( ph2c , pdrvextra_cmd_parm , GEN_CMD_CODE ( _Set_Drv_Extra ) ) ;
res = rtw_enqueue_cmd ( pcmdpriv , ph2c ) ;
} else
beamforming_wk_hdl ( padapter , type , pbuf ) ;
exit :
return res ;
}
void update_attrib_txbf_info ( _adapter * padapter , struct pkt_attrib * pattrib , struct sta_info * psta )
{
if ( psta ) {
pattrib - > txbf_g_id = psta - > txbf_gid ;
pattrib - > txbf_p_aid = psta - > txbf_paid ;
}
}
# endif