M7350/wlan/8192es/DriverSrcPkg/Driver/rtl8192cd_92es/Beamforming.c
2024-09-09 08:59:52 +00:00

2211 lines
60 KiB
C
Executable File
Raw Blame History

#include "8192cd.h"
#include "8192cd_cfg.h"
#include "8192cd_util.h"
#include "8192cd_headers.h"
#include "Beamforming.h"
#include "8812_reg.h"
#include "8812_vht_gen.h"
#ifdef BEAMFORMING_SUPPORT
VOID
Beamforming_SetBeamFormLeave(
struct rtl8192cd_priv *priv,
u1Byte Idx
)
{
#ifdef CONFIG_RTL_8812_SUPPORT
if(GET_CHIP_VER(priv) == VERSION_8812E)
SetBeamformLeave8812(priv, Idx);
#endif
#ifdef CONFIG_WLAN_HAL_8192EE
if(GET_CHIP_VER(priv) == VERSION_8192E)
SetBeamformLeave92E(priv,Idx);
#endif
#ifdef CONFIG_WLAN_HAL_8814AE
if(GET_CHIP_VER(priv) == VERSION_8814A)
SetBeamformLeave8814A(priv,Idx);
#endif
}
VOID
Beamforming_SetBeamFormStatus(
struct rtl8192cd_priv *priv,
u1Byte Idx
)
{
#ifdef CONFIG_WLAN_HAL_8192EE
if(GET_CHIP_VER(priv)== VERSION_8192E)
SetBeamformStatus92E(priv, Idx);
#endif
#ifdef CONFIG_RTL_8812_SUPPORT
if(GET_CHIP_VER(priv)== VERSION_8812E)
SetBeamformStatus8812(priv, Idx);
#endif
#ifdef CONFIG_WLAN_HAL_8814AE
if(GET_CHIP_VER(priv) == VERSION_8814A)
SetBeamformStatus8814A(priv,Idx);
#endif
}
VOID
Beamforming_SetBeamFormEnter(
struct rtl8192cd_priv *priv,
u1Byte Idx
)
{
#ifdef CONFIG_WLAN_HAL_8192EE
if (GET_CHIP_VER(priv)== VERSION_8192E)
SetBeamformEnter92E(priv, Idx);
#endif
#ifdef CONFIG_RTL_8812_SUPPORT
if (GET_CHIP_VER(priv)== VERSION_8812E)
SetBeamformEnter8812(priv, Idx);
#endif
#ifdef CONFIG_WLAN_HAL_8814AE
if(GET_CHIP_VER(priv) == VERSION_8814A)
SetBeamformEnter8814A(priv,Idx);
#endif
}
VOID
Beamforming_NDPARate(
struct rtl8192cd_priv *priv,
BOOLEAN Mode,
u1Byte BW,
u1Byte Rate
)
{
#ifdef CONFIG_WLAN_HAL_8192EE
if(GET_CHIP_VER(priv)== VERSION_8192E){
Beamforming_NDPARate_92E(priv, Mode, BW, Rate);
}
#endif
#ifdef CONFIG_RTL_8812_SUPPORT
if(GET_CHIP_VER(priv)== VERSION_8812E) {
Beamforming_NDPARate_8812(priv, Mode, BW, Rate); //
}
#endif
#ifdef CONFIG_WLAN_HAL_8814AE
if(GET_CHIP_VER(priv)== VERSION_8814A){
Beamforming_NDPARate_8814A(priv, Mode, BW, Rate);
}
#endif
}
VOID
Beamforming_SetHWTimer(
struct rtl8192cd_priv *priv,
u2Byte t
)
{
#ifdef CONFIG_WLAN_HAL_8192EE
if(GET_CHIP_VER(priv)== VERSION_8192E)
{
HW_VAR_HW_REG_TIMER_STOP_92E(priv);
HW_VAR_HW_REG_TIMER_INIT_92E(priv, t);
HW_VAR_HW_REG_TIMER_START_92E(priv);
}
#endif
#ifdef CONFIG_RTL_8812_SUPPORT
if(GET_CHIP_VER(priv)== VERSION_8812E)
{
HW_VAR_HW_REG_TIMER_STOP_8812(priv);
HW_VAR_HW_REG_TIMER_INIT_8812(priv, t);
HW_VAR_HW_REG_TIMER_START_8812(priv);
}
#endif
#ifdef CONFIG_WLAN_HAL_8814AE
if(GET_CHIP_VER(priv)== VERSION_8814A)
{
HW_VAR_HW_REG_TIMER_STOP_8814A(priv);
HW_VAR_HW_REG_TIMER_INIT_8814A(priv, t);
HW_VAR_HW_REG_TIMER_START_8814A(priv);
}
#endif
}
VOID
Beamforming_StopHWTimer(
struct rtl8192cd_priv *priv
)
{
#ifdef CONFIG_WLAN_HAL_8192EE
if(GET_CHIP_VER(priv)== VERSION_8192E)
{
HW_VAR_HW_REG_TIMER_STOP_92E(priv);
}
#endif
#ifdef CONFIG_RTL_8812_SUPPORT
if(GET_CHIP_VER(priv)== VERSION_8812E)
{
HW_VAR_HW_REG_TIMER_STOP_8812(priv);
}
#endif
#ifdef CONFIG_WLAN_HAL_8814AE
if(GET_CHIP_VER(priv)== VERSION_8814A)
{
HW_VAR_HW_REG_TIMER_STOP_8814A(priv);
}
#endif
}
u1Byte
Beamforming_GetHTNDPTxRate(
struct rtl8192cd_priv *priv,
u1Byte CompSteeringNumofBFer
)
{
u1Byte Nr_index = 0;
u1Byte NDPTxRate;
#ifdef CONFIG_WLAN_HAL_8814AE
if(GET_CHIP_VER(priv)== VERSION_8814A)
Nr_index = TxBF_Nr(halTxbf8814A_GetNtx(priv), CompSteeringNumofBFer); /*find Nr*/
else
#endif
Nr_index = TxBF_Nr(1, CompSteeringNumofBFer); /*find Nr*/
switch(Nr_index)
{
case 1:
NDPTxRate = _MCS8_RATE_;
break;
case 2:
NDPTxRate = _MCS16_RATE_;
break;
case 3:
NDPTxRate = _MCS24_RATE_;
break;
default:
NDPTxRate = _MCS8_RATE_;
break;
}
return NDPTxRate;
}
u1Byte
Beamforming_GetVHTNDPTxRate(
struct rtl8192cd_priv *priv,
u1Byte CompSteeringNumofBFer
)
{
u1Byte Nr_index = 0;
u1Byte NDPTxRate;
#ifdef CONFIG_WLAN_HAL_8814AE
if(GET_CHIP_VER(priv)== VERSION_8814A)
Nr_index = TxBF_Nr(halTxbf8814A_GetNtx(priv), CompSteeringNumofBFer); /*find Nr*/
else
#endif
Nr_index = TxBF_Nr(1, CompSteeringNumofBFer); /*find Nr*/
switch(Nr_index)
{
case 1:
NDPTxRate = _NSS2_MCS0_RATE_;
break;
case 2:
NDPTxRate = _NSS3_MCS0_RATE_;
break;
case 3:
NDPTxRate = _NSS4_MCS0_RATE_;
break;
default:
NDPTxRate = _NSS2_MCS0_RATE_;
break;
}
return NDPTxRate;
}
VOID
PacketAppendData(
IN POCTET_STRING packet,
IN OCTET_STRING data
)
{
pu1Byte buf = packet->Octet + packet->Length;
memcpy( buf, data.Octet, data.Length);
packet->Length = packet->Length + data.Length;
}
VOID
Beamforming_GidPAid(
struct rtl8192cd_priv *priv,
struct stat_info *pstat)
{
if (OPMODE & WIFI_AP_STATE)
{
u2Byte AID = (u2Byte) ((pstat->aid) & 0x1ff); //AID[0:8]
u2Byte bssid = 0;
pstat->g_id = 63;
bssid = ((BSSID[5] & 0xf0) >> 4) ^ (BSSID[5] & 0xf); // BSSID[44:47] xor BSSID[40:43]
pstat->p_aid = (AID + bssid * 32) & 0x1ff; // (dec(A) + dec(B)*32) mod 512
}
else if (OPMODE & WIFI_ADHOC_STATE)
{
pstat->p_aid = REMAP_AID(pstat);
pstat->g_id = 63;
}
else if (OPMODE & WIFI_STATION_STATE)
{
pstat->g_id = 0;
pstat->p_aid = ((int)(pstat->hwaddr[5])<<1) | (pstat->hwaddr[4]>>7);
}
}
BEAMFORMING_CAP
Beamforming_GetEntryBeamCapByMacId(
struct rtl8192cd_priv *priv,
IN u1Byte MacId
)
{
u1Byte i = 0;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
BEAMFORMING_CAP BeamformEntryCap = BEAMFORMING_CAP_NONE;
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
{
if(pBeamformingInfo->BeamformeeEntry[i].bUsed &&
(MacId == pBeamformingInfo->BeamformeeEntry[i].MacId))
{
BeamformEntryCap = pBeamformingInfo->BeamformeeEntry[i].BeamformEntryCap;
i = BEAMFORMEE_ENTRY_NUM;
}
}
return BeamformEntryCap;
}
PRT_BEAMFORMING_ENTRY
Beamforming_GetBFeeEntryByAddr(
struct rtl8192cd_priv *priv,
IN pu1Byte RA,
OUT pu1Byte Idx
)
{
u1Byte i = 0;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
{
if((pBeamformingInfo->BeamformeeEntry[i].bUsed) &&
((memcmp(RA, pBeamformingInfo->BeamformeeEntry[i].MacAddr, MACADDRLEN)) == 0))
{
*Idx = i;
return &(pBeamformingInfo->BeamformeeEntry[i]);
}
}
return NULL;
}
PRT_BEAMFORMER_ENTRY
Beamforming_GetBFerEntryByAddr(
struct rtl8192cd_priv *priv,
IN pu1Byte RA,
OUT pu1Byte Idx
)
{
u1Byte i = 0;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++)
{
if((pBeamformingInfo->BeamformerEntry[i].bUsed) &&
((memcmp(RA, pBeamformingInfo->BeamformerEntry[i].MacAddr, MACADDRLEN)) == 0))
{
*Idx = i;
return &(pBeamformingInfo->BeamformerEntry[i]);
}
}
return NULL;
}
PRT_BEAMFORMING_ENTRY
Beamforming_GetEntryByMacId(
struct rtl8192cd_priv *priv,
u1Byte MacId,
pu1Byte Idx
)
{
u1Byte i = 0;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
{
if(pBeamformingInfo->BeamformeeEntry[i].bUsed &&
(MacId == pBeamformingInfo->BeamformeeEntry[i].MacId))
{
*Idx = i;
return &(pBeamformingInfo->BeamformeeEntry[i]);
}
}
return NULL;
}
PRT_BEAMFORMING_ENTRY
Beamforming_GetFreeBFeeEntry(
struct rtl8192cd_priv *priv,
OUT pu1Byte Idx,
pu1Byte RA
)
{
u1Byte i = 0;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s Start!\n", __FUNCTION__));
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s, RA= 0x %x%x%x%x%x%x\n",
__FUNCTION__,
RA[0],RA[1],RA[2],RA[3],RA[4],RA[5]));
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s, BFeeEntry_Idx0= 0x %x%x%x%x%x%x\n",
__FUNCTION__,
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[0],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[1],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[2],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[3],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[4],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[5]));
if( !(memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0, MACADDRLEN)) ){
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, (memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0, MACADDRLEN)) == 1, return NULL!!\n", __FUNCTION__));
return NULL;
}
else if(!(memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1, MACADDRLEN))){
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, (memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1, MACADDRLEN)) == 1, return NULL!!\n", __FUNCTION__));
return NULL;
}
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
{
if(pBeamformingInfo->BeamformeeEntry[i].bUsed == FALSE)
{
*Idx = i;
return &(pBeamformingInfo->BeamformeeEntry[i]);
}
}
return NULL;
}
PRT_BEAMFORMER_ENTRY
Beamforming_GetFreeBFerEntry(
struct rtl8192cd_priv *priv,
OUT pu1Byte Idx,
pu1Byte RA
)
{
u1Byte i = 0;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s Start!\n", __FUNCTION__));
if(!(memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx0, MACADDRLEN))){
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, (memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx0, MACADDRLEN)) == 1, return NULL!!\n", __FUNCTION__));
return NULL;
}
else if(!(memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx1, MACADDRLEN))){
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, (memcmp(RA, pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx1, MACADDRLEN)) == 1, return NULL!!\n", __FUNCTION__));
return NULL;
}
for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++)
{
if(pBeamformingInfo->BeamformerEntry[i].bUsed == FALSE)
{
*Idx = i;
return &(pBeamformingInfo->BeamformerEntry[i]);
}
}
return NULL;
}
PRT_BEAMFORMING_ENTRY
Beamforming_AddBFeeEntry(
struct rtl8192cd_priv *priv,
struct stat_info *pSTA,
pu1Byte RA,
u2Byte AID,
u2Byte MacID,
u1Byte BW,
BEAMFORMING_CAP BeamformCap,
pu1Byte Idx,
u2Byte CompSteeringNumofBFer
)
{
PRT_BEAMFORMING_ENTRY pEntry;
pEntry = Beamforming_GetFreeBFeeEntry(priv, Idx,RA);
// Check if this MAC address is in DelEntryList
if(pEntry != NULL)
{
pEntry->bUsed = TRUE;
pEntry->AID = AID;
pEntry->MacId = MacID;
pEntry->BW = BW;
// AID -> P_AID
if (OPMODE & WIFI_AP_STATE)
{
u2Byte bssid = ((GET_MY_HWADDR[5]>> 4) & 0x0f ) ^
(GET_MY_HWADDR[5] & 0xf); // BSSID[44:47] xor BSSID[40:43]
pEntry->P_AID = (AID + (bssid <<5)) & 0x1ff; // (dec(A) + dec(B)*32) mod 512
}
else if (OPMODE & WIFI_ADHOC_STATE)
{
// pEntry->P_AID = AID;
pEntry->P_AID = 0;
}
else if (OPMODE & WIFI_STATION_STATE) {
pEntry->P_AID = RA[5]; // BSSID[39:47]
pEntry->P_AID = (pEntry->P_AID << 1) | (RA[4] >> 7 );
}
//
memcpy(pEntry->MacAddr, RA, MACADDRLEN);
pEntry->bTxBF = FALSE;
pEntry->bSound = FALSE;
pEntry->BeamformEntryCap = BeamformCap;
pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
pEntry->LogStatusFailCnt = 0;
pEntry->CompSteeringNumofBFer = CompSteeringNumofBFer;
pEntry->pSTA = pSTA;
#ifdef MBSSID
if(GET_CHIP_VER(priv) == VERSION_8812E)
if (GET_MIB(GET_ROOT(priv))->miscEntry.vap_enable)
rtl8192cd_set_mbssid(priv, RA, *Idx);
#endif
return pEntry;
}
else
return NULL;
}
PRT_BEAMFORMER_ENTRY
Beamforming_AddBFerEntry(
struct rtl8192cd_priv *priv,
pu1Byte RA,
u2Byte AID,
BEAMFORMING_CAP BeamformCap,
pu1Byte Idx,
u2Byte NumofSoundingDim
)
{
PRT_BEAMFORMER_ENTRY pEntry;
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s Start!\n", __FUNCTION__));
pEntry = Beamforming_GetFreeBFerEntry(priv, Idx, RA);
if(pEntry != NULL)
{
pEntry->bUsed = TRUE;
// AID -> P_AID
if (OPMODE & WIFI_AP_STATE)
{
u2Byte bssid = ((GET_MY_HWADDR[5]>> 4) & 0x0f ) ^ (GET_MY_HWADDR[5] & 0xf); // BSSID[44:47] xor BSSID[40:43]
pEntry->P_AID = (AID + (bssid <<5)) & 0x1ff; // (dec(A) + dec(B)*32) mod 512
}
else if (OPMODE & WIFI_ADHOC_STATE)
{
pEntry->P_AID = 0;
}
else if (OPMODE & WIFI_STATION_STATE) {
pEntry->P_AID = RA[5]; // BSSID[39:47]
pEntry->P_AID = (pEntry->P_AID << 1) | (RA[4] >> 7 );
}
memcpy(pEntry->MacAddr, RA, MACADDRLEN);
pEntry->BeamformEntryCap = BeamformCap;
pEntry->NumofSoundingDim = NumofSoundingDim;
pEntry->ClockResetTimes = 0;
pEntry->NDPAPreLogSeq = 0;
pEntry->NDPALogSeq = 0;
pEntry->NDPALogRetryCnt = 0;
pEntry->NDPALogSuccess = 0;
// pEntry->LogStatusFailCnt = 0;
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, BFer Entry!=NULL\n", __FUNCTION__));
return pEntry;
}
else
return NULL;
}
BOOLEAN
Beamforming_RemoveEntry(
struct rtl8192cd_priv *priv,
IN pu1Byte RA,
OUT pu1Byte Idx
)
{
PRT_BEAMFORMER_ENTRY pBFerEntry = Beamforming_GetBFerEntryByAddr(priv, RA, Idx);
PRT_BEAMFORMING_ENTRY pBFeeEntry = Beamforming_GetBFeeEntryByAddr(priv, RA, Idx);
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
u1Byte i;
// CurDelBFerBFeeEntrySel had been decided by the function who calls Beamforming_DeInitEntry
DEL_ENTRY_TYPE_SEL CurDelBFerBFeeEntrySel=pBeamformingInfo->CurDelBFerBFeeEntrySel;
BOOLEAN ret = FALSE;
// if( (CurDelBFerBFeeEntrySel== BFerEntry)||(CurDelBFerBFeeEntrySel == BFerBFeeEntry) )
/*
if( CurDelBFerBFeeEntrySel == BFerEntry)
{
if (pBFerEntry != NULL)
{
pBFerEntry->bUsed = FALSE;
pBFerEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;
if(*Idx==0)
memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx0[0], RA, 6);
else
memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx1[0], RA, 6);
ret = TRUE;
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, Remove BFerEntry idx=%d\n", __FUNCTION__, *Idx));
}
}
*/
if (pBFerEntry != NULL)
{
pBFerEntry->bUsed = FALSE;
pBFerEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;
if(CurDelBFerBFeeEntrySel == BFerEntry)
{
if(*Idx==0)
memcpy(pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx0, RA, 6);
else
memcpy(pBeamformingInfo->DelEntryListByMACAddr.BFerEntry_Idx1, RA, 6);
}
ret = TRUE;
}
if (pBFeeEntry != NULL)
{
pBFeeEntry->bUsed = FALSE;
pBFeeEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;
if(CurDelBFerBFeeEntrySel == BFeeEntry)
{
if(*Idx==0)
memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[0], RA, 6);
else
memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[0], RA, 6);
}
ret = TRUE;
}
/*
if( (CurDelBFerBFeeEntrySel == BFeeEntry)||(CurDelBFerBFeeEntrySel == BFerBFeeEntry) )
{
if (pBFeeEntry != NULL)
{
pBFeeEntry->bUsed = FALSE;
pBFeeEntry->BeamformEntryCap = BEAMFORMING_CAP_NONE;
if(*Idx==0)
memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[0], RA, 6);
else
memcpy(&pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[0], RA, 6);
ret = TRUE;
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, Remove BFeeEntry idx=%d\n", __FUNCTION__, *Idx));
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, RA=0x%x%x%x%x%x%x\n",
__FUNCTION__,
RA[0],RA[1],RA[2],RA[3],RA[4],RA[5]));
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, BFeeEntry_Idx0=0x%x%x%x%x%x%x, BFeeEntry_Idx1=0x%x%x%x%x%x%x\n",
__FUNCTION__,
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[0],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[1],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[2],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[3],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[4],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx0[5],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[0],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[1],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[2],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[3],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[4],
pBeamformingInfo->DelEntryListByMACAddr.BFeeEntry_Idx1[5]
));
}
}
*/
return ret;
}
BOOLEAN
Beamforming_InitEntry(
struct rtl8192cd_priv *priv,
struct stat_info *pSTA,
pu1Byte BFerBFeeIdx
)
{
PRT_BEAMFORMING_ENTRY pBeamformEntry = NULL;
PRT_BEAMFORMER_ENTRY pBeamformerEntry = NULL;
pu1Byte RA;
u2Byte AID, MacID;
u1Byte WirelessMode;
u1Byte BW = HT_CHANNEL_WIDTH_20;
BEAMFORMING_CAP BeamformCap = BEAMFORMING_CAP_NONE;
u1Byte BFerIdx = 0xF, BFeeIdx = 0xF;
u2Byte CompSteeringNumofBFer = 0, NumofSoundingDim = 0;
// The current setting does not support Beaforming
if (priv->pmib->dot11RFEntry.txbf == 0)
{
return FALSE;
}
// IBSS, AP mode
if(pSTA != NULL)
{
AID = pSTA->aid;
RA = pSTA->hwaddr;
MacID = pSTA->aid;
WirelessMode = pSTA->WirelessMode;
BW = pSTA->tx_bw;
}
else // Client mode
{
return FALSE;
}
if( WirelessMode < WIRELESS_MODE_N_24G)
return FALSE;
else
{
// BIT 4 implies capable of sending NDPA (BFER),
// BIT 3 implies capable of receiving NDPA (BFEE),
if(pSTA->ht_cap_len && (cpu_to_le32(pSTA->ht_cap_buf.txbf_cap) & 0x8)&& (priv->pmib->dot11RFEntry.txbfer == 1)) //bfer
{
BeamformCap |=BEAMFORMER_CAP_HT_EXPLICIT;
CompSteeringNumofBFer = (u1Byte)((cpu_to_le32(pSTA->ht_cap_buf.txbf_cap) & (BIT(23)|BIT(24)))>>23);
// panic_printk("[%d] BeamformCap = BEAMFORMER_CAP_HT_EXPLICIT \n",__LINE__);
}
if (pSTA->ht_cap_len && (cpu_to_le32(pSTA->ht_cap_buf.txbf_cap) & 0x10)&& (priv->pmib->dot11RFEntry.txbfee == 1)) //bfee
{
BeamformCap |=BEAMFORMEE_CAP_HT_EXPLICIT;
NumofSoundingDim = (u1Byte)((cpu_to_le32(pSTA->ht_cap_buf.txbf_cap) & (BIT(27)|BIT(28)))>>27);
// panic_printk("[%d] BeamformCap = BEAMFORMEE_CAP_HT_EXPLICIT \n",__LINE__);
}
#ifdef RTK_AC_SUPPORT
if(WirelessMode == WIRELESS_MODE_AC_5G)
{
if(pSTA->vht_cap_len && (cpu_to_le32(pSTA->vht_cap_buf.vht_cap_info) & BIT(SU_BFEE_S)) && (priv->pmib->dot11RFEntry.txbfer == 1)) // AC<41>٨S<D9A8>̾<EFBFBD>bfer or bfee<65><65>
{
BeamformCap |=BEAMFORMER_CAP_VHT_SU;
CompSteeringNumofBFer = (u1Byte)((cpu_to_le32(pSTA->vht_cap_buf.vht_cap_info) & (BIT(MAX_ANT_SUPP_S)|BIT(MAX_ANT_SUPP_S+1)|BIT(MAX_ANT_SUPP_E)))>>MAX_ANT_SUPP_S);
}
if(pSTA->vht_cap_len && (cpu_to_le32(pSTA->vht_cap_buf.vht_cap_info) & BIT(SU_BFER_S)) && (priv->pmib->dot11RFEntry.txbfee == 1))
{
BeamformCap |=BEAMFORMEE_CAP_VHT_SU;
NumofSoundingDim = (u1Byte)((cpu_to_le32(pSTA->vht_cap_buf.vht_cap_info) & (BIT(SOUNDING_DIMENSIONS_S)|BIT(SOUNDING_DIMENSIONS_S+1)|BIT(SOUNDING_DIMENSIONS_E)))>>SOUNDING_DIMENSIONS_S);
}
}
#endif
}
if(BeamformCap == BEAMFORMING_CAP_NONE)
return FALSE;
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, CompSteeringNumofBFer = %d, NumofSoundingDim = %d\n", __FUNCTION__, CompSteeringNumofBFer, NumofSoundingDim));
// bfme
if((BeamformCap & BEAMFORMEE_CAP_HT_EXPLICIT) || (BeamformCap & BEAMFORMEE_CAP_VHT_SU))
{
pBeamformerEntry = Beamforming_GetBFerEntryByAddr(priv, RA, &BFerIdx);
if(pBeamformerEntry == NULL)
{
pBeamformerEntry = Beamforming_AddBFerEntry(priv, RA, AID, BeamformCap, &BFerIdx, NumofSoundingDim);
if(pBeamformerEntry == NULL)
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, Not enough BFer entry!\n", __FUNCTION__));
}
}
// bfer
if((BeamformCap & BEAMFORMER_CAP_HT_EXPLICIT) || (BeamformCap & BEAMFORMER_CAP_VHT_SU))
{
pBeamformEntry = Beamforming_GetBFeeEntryByAddr(priv, RA, &BFeeIdx);
if(pBeamformEntry == NULL)
{
pBeamformEntry = Beamforming_AddBFeeEntry(priv, pSTA, RA, AID, MacID, BW, BeamformCap, &BFeeIdx, CompSteeringNumofBFer);
if(pBeamformEntry == NULL)
{
return FALSE;
}
else
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
}
else
{
// Entry has been created. If entry is initialing or progressing then errors occur.
if( pBeamformEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED &&
pBeamformEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED)
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, Error State of Beamforming\n", __FUNCTION__));
return FALSE;
}
else
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZEING;
}
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
Beamforming_AutoTest(priv, BFeeIdx, pBeamformEntry);
}
*BFerBFeeIdx = (BFerIdx<<4) | BFeeIdx;
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, BFerIdx=%d, BFeeIdx=%d, BFerBFeeIdx=%d \n", __FUNCTION__, BFerIdx, BFeeIdx, *BFerBFeeIdx));
return TRUE;
}
BOOLEAN
Beamforming_DeInitEntry(
struct rtl8192cd_priv *priv,
pu1Byte RA
)
{
u1Byte Idx = 0;
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]%s Start!!!\n", __FUNCTION__));
if(Beamforming_RemoveEntry(priv, RA, &Idx) == TRUE)
{
Beamforming_SetBeamFormLeave(priv, Idx);
#ifdef CONFIG_RTL_8812_SUPPORT // 8812 only??
#ifdef MBSSID
if (GET_MIB(GET_ROOT(priv))->miscEntry.vap_enable)
rtl8192cd_clear_mbssid(priv, Idx);
#endif
#endif
return TRUE;
}
else
{
// For AP debug, because when STA disconnect AP, release_stainfo will be triggered many times
return FALSE;
}
}
VOID
BeamformingReset(
struct rtl8192cd_priv *priv
)
{
u1Byte Idx = 0;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++)
{
if(pBeamformingInfo->BeamformeeEntry[Idx].bUsed == TRUE)
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, Reset entry idx=%d\n", __FUNCTION__, Idx));
pBeamformingInfo->BeamformeeEntry[Idx].bUsed = FALSE;
pBeamformingInfo->BeamformeeEntry[Idx].BeamformEntryCap = BEAMFORMING_CAP_NONE;
//pBeamformingInfo->BeamformeeEntry[Idx].BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
pBeamformingInfo->BeamformeeEntry[Idx].bBeamformingInProgress = FALSE;
Beamforming_SetBeamFormLeave(priv, Idx);
}
}
for(Idx = 0; Idx < BEAMFORMER_ENTRY_NUM; Idx++)
{
pBeamformingInfo->BeamformerEntry[Idx].bUsed = FALSE;
}
}
#define FillOctetString(_os,_octet,_len) \
(_os).Octet=(pu1Byte)(_octet); \
(_os).Length=(_len);
VOID
ConstructHTNDPAPacket(
struct rtl8192cd_priv *priv,
pu1Byte RA,
pu1Byte Buffer,
pu4Byte pLength,
u1Byte BW
)
{
u2Byte Duration= 0;
OCTET_STRING pNDPAFrame, ActionContent;
u1Byte ActionHdr[4] = {ACT_CAT_VENDOR, 0x00, 0xe0, 0x4c};
int aSifsTime = ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && (priv->pshare->ht_sta_num)) ? 0x10 : 10;
SET_80211_HDR_FRAME_CONTROL(Buffer,0);
SET_80211_HDR_ORDER(Buffer, 1);
SET_80211_HDR_TYPE_AND_SUBTYPE(Buffer,Type_Action_No_Ack);
memcpy((void *)GetAddr1Ptr(Buffer), RA, MACADDRLEN);
memcpy((void *)GetAddr2Ptr(Buffer), GET_MY_HWADDR, MACADDRLEN);
memcpy((void *)GetAddr3Ptr(Buffer), BSSID, MACADDRLEN);
Duration = 2*aSifsTime + 40;
if(BW== HT_CHANNEL_WIDTH_20_40)
Duration+= 87;
else
Duration+= 180;
SET_80211_HDR_DURATION(Buffer, Duration);
//HT control field
SET_HT_CTRL_CSI_STEERING(Buffer+sMacHdrLng, 3);
SET_HT_CTRL_NDP_ANNOUNCEMENT(Buffer+sMacHdrLng, 1);
FillOctetString(pNDPAFrame, Buffer, sMacHdrLng+sHTCLng);
FillOctetString(ActionContent, ActionHdr, 4);
PacketAppendData(&pNDPAFrame, ActionContent);
*pLength = 32;
}
BOOLEAN
SendHTNDPAPacket(
struct rtl8192cd_priv *priv,
pu1Byte RA,
u1Byte BW,
u1Byte NDPTxRate
)
{
BOOLEAN ret = TRUE;
unsigned char *pbuf = get_wlanllchdr_from_poll(priv);
u4Byte PacketLength;
DECLARE_TXINSN(txinsn);
if(pbuf)
{
memset(pbuf, 0, sizeof(struct wlan_hdr));
ConstructHTNDPAPacket(
priv,
RA,
pbuf,
&PacketLength,
BW
);
txinsn.q_num = MGNT_QUEUE;
txinsn.fr_type = _PRE_ALLOCLLCHDR_;
txinsn.phdr = pbuf;
txinsn.hdr_len = PacketLength;
txinsn.fr_len = 0;
txinsn.lowest_tx_rate = txinsn.tx_rate = NDPTxRate; //_MCS8_RATE_;, According to Nr
txinsn.fixed_rate = 1;
txinsn.ndpa = 1;
if (rtl8192cd_wlantx(priv, &txinsn) == CONGESTED) {
netif_stop_queue(priv->dev);
priv->ext_stats.tx_drops++;
// panic_printk("TX DROP: Congested!\n");
if (txinsn.phdr)
release_wlanhdr_to_poll(priv, txinsn.phdr);
if (txinsn.pframe)
release_mgtbuf_to_poll(priv, txinsn.pframe);
return 0;
}
}
else
ret = FALSE;
return ret;
}
VOID
ConstructVHTNDPAPacket(
struct rtl8192cd_priv *priv,
pu1Byte RA,
u2Byte AID,
pu1Byte Buffer,
pu4Byte pLength,
u1Byte BW
)
{
u2Byte Duration= 0;
u1Byte Sequence = 0;
pu1Byte pNDPAFrame = Buffer;
u2Byte tmp16;
RT_NDPA_STA_INFO STAInfo;
int aSifsTime = ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N) && (priv->pshare->ht_sta_num)) ? 0x10 : 10;
// Frame control.
SET_80211_HDR_FRAME_CONTROL(pNDPAFrame, 0);
SET_80211_HDR_TYPE_AND_SUBTYPE(pNDPAFrame, Type_NDPA);
memcpy((void *)GetAddr1Ptr(pNDPAFrame), RA, MACADDRLEN);
memcpy((void *)GetAddr2Ptr(pNDPAFrame), GET_MY_HWADDR, MACADDRLEN);
Duration = 2*aSifsTime + 44;
if(BW == HT_CHANNEL_WIDTH_80)
Duration += 40;
else if(BW == HT_CHANNEL_WIDTH_20_40)
Duration+= 87;
else
Duration+= 180;
SetDuration(pNDPAFrame, Duration);
Sequence = GET_HW(priv)->sounding_seq<<2;
GET_HW(priv)->sounding_seq = (GET_HW(priv)->sounding_seq+1) & 0xfff;
memcpy(pNDPAFrame+16, &Sequence,1);
if (OPMODE & WIFI_ADHOC_STATE)
AID = 0;
STAInfo.AID = AID;
STAInfo.FeedbackType = 0;
STAInfo.NcIndex = 0;
memcpy(&tmp16, (pu1Byte)&STAInfo, 2);
tmp16 = cpu_to_le16(tmp16);
memcpy(pNDPAFrame+17, &tmp16, 2);
*pLength = 19;
}
BOOLEAN
SendVHTNDPAPacket(
struct rtl8192cd_priv *priv,
IN pu1Byte RA,
IN u2Byte AID,
u1Byte BW,
u1Byte NDPTxRate
)
{
BOOLEAN ret = TRUE;
u4Byte PacketLength;
unsigned char *pbuf = get_wlanllchdr_from_poll(priv);
DECLARE_TXINSN(txinsn);
if(pbuf)
{
memset(pbuf, 0, sizeof(struct wlan_hdr));
ConstructVHTNDPAPacket (
priv,
RA,
AID,
pbuf,
&PacketLength,
BW
);
txinsn.q_num = MANAGE_QUE_NUM;
txinsn.fr_type = _PRE_ALLOCLLCHDR_;
txinsn.phdr = pbuf;
txinsn.hdr_len = PacketLength;
txinsn.fr_len = 0;
txinsn.fixed_rate = 1;
txinsn.lowest_tx_rate = txinsn.tx_rate = NDPTxRate; // According to Nr
txinsn.ndpa = 1;
if (rtl8192cd_wlantx(priv, &txinsn) == CONGESTED) {
netif_stop_queue(priv->dev);
priv->ext_stats.tx_drops++;
// panic_printk("TX DROP: Congested!\n");
if (txinsn.phdr)
release_wlanhdr_to_poll(priv, txinsn.phdr);
if (txinsn.pframe)
release_mgtbuf_to_poll(priv, txinsn.pframe);
return 0;
}
}
else
ret = FALSE;
return ret;
}
u1Byte
beamforming_SoundingIdx(
PRT_BEAMFORMING_INFO pBeamInfo
)
{
u1Byte Idx = 0;
PRT_BEAMFORMING_PERIOD_INFO pBeamPeriodInfo = &(pBeamInfo->BeamformingPeriodInfo);
if( pBeamPeriodInfo->Mode == SOUNDING_SW_VHT_TIMER ||pBeamPeriodInfo->Mode == SOUNDING_SW_HT_TIMER ||
pBeamPeriodInfo->Mode == SOUNDING_HW_VHT_TIMER ||pBeamPeriodInfo->Mode == SOUNDING_HW_HT_TIMER)
Idx = pBeamPeriodInfo->Idx;
else
Idx = 0;
return Idx;
}
BEAMFORMING_NOTIFY_STATE
beamfomring_bSounding(
PRT_BEAMFORMING_INFO pBeamInfo,
pu1Byte Idx
)
{
BEAMFORMING_NOTIFY_STATE bSounding = BEAMFORMING_NOTIFY_NONE;
//RT_BEAMFORMING_ENTRY Entry = pBeamInfo->BeamformeeEntry[*Idx];
RT_BEAMFORMING_PERIOD_INFO BeamPeriodInfo = pBeamInfo->BeamformingPeriodInfo;
if(BeamPeriodInfo.Mode == SOUNDING_STOP_All_TIMER)
bSounding = BEAMFORMING_NOTIFY_RESET;
// else if(BeamPeriodInfo.Mode == SOUNDING_STOP_OID_TIMER && Entry.bTxBF == FALSE)
// bSounding = BEAMFORMING_NOTIFY_RESET;
else
{
u1Byte i;
for(i=0;i<BEAMFORMEE_ENTRY_NUM;i++)
{
//panic_printk("[David]@%s: BFee Entry %d bUsed=%d, bSound=%d \n", __FUNCTION__, i, pBeamInfo->BeamformeeEntry[i].bUsed, pBeamInfo->BeamformeeEntry[i].bSound);
if(pBeamInfo->BeamformeeEntry[i].bUsed && (!pBeamInfo->BeamformeeEntry[i].bSound))
{
*Idx = i;
bSounding = BEAMFORMING_NOTIFY_ADD;
}
if((!pBeamInfo->BeamformeeEntry[i].bUsed) && pBeamInfo->BeamformeeEntry[i].bSound)
{
*Idx = i;
bSounding = BEAMFORMING_NOTIFY_DELETE;
}
}
}
return bSounding;
}
SOUNDING_MODE
beamforming_SoundingMode(
PRT_BEAMFORMING_INFO pBeamInfo,
u1Byte Idx
)
{
RT_BEAMFORMING_PERIOD_INFO BeamPeriodInfo = pBeamInfo->BeamformingPeriodInfo;
SOUNDING_MODE Mode = BeamPeriodInfo.Mode;
RT_BEAMFORMING_ENTRY Entry = pBeamInfo->BeamformeeEntry[Idx];
if( BeamPeriodInfo.Mode == SOUNDING_SW_VHT_TIMER || BeamPeriodInfo.Mode == SOUNDING_SW_HT_TIMER ||
BeamPeriodInfo.Mode == SOUNDING_HW_VHT_TIMER || BeamPeriodInfo.Mode == SOUNDING_HW_HT_TIMER )
Mode = BeamPeriodInfo.Mode;
else if(Entry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU)
Mode = SOUNDING_AUTO_VHT_TIMER;
else if(Entry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT)
Mode = SOUNDING_AUTO_HT_TIMER;
return Mode;
}
u2Byte
beamforming_SoundingTime(
PRT_BEAMFORMING_INFO pBeamInfo,
SOUNDING_MODE Mode
)
{
u2Byte SoundingTime = 0xffff;
RT_BEAMFORMING_PERIOD_INFO BeamPeriodInfo = pBeamInfo->BeamformingPeriodInfo;
if(Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_HW_VHT_TIMER)
SoundingTime = BeamPeriodInfo.BeamPeriod * 32;
else if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_SW_VHT_TIMER)
SoundingTime = BeamPeriodInfo.BeamPeriod ;
else
SoundingTime = 20*32;
return SoundingTime;
}
u1Byte
beamforming_SoundingBW(
PRT_BEAMFORMING_INFO pBeamInfo,
SOUNDING_MODE Mode,
u1Byte Idx
)
{
u1Byte SoundingBW = HT_CHANNEL_WIDTH_20;
RT_BEAMFORMING_ENTRY Entry = pBeamInfo->BeamformeeEntry[Idx];
RT_BEAMFORMING_PERIOD_INFO BeamPeriodInfo = pBeamInfo->BeamformingPeriodInfo;
if(Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_HW_VHT_TIMER)
SoundingBW = BeamPeriodInfo.BW;
else if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_SW_VHT_TIMER)
SoundingBW = BeamPeriodInfo.BW;
else
SoundingBW = Entry.BW;
return SoundingBW;
}
VOID
beamforming_StartPeriod(
struct rtl8192cd_priv *priv,
u1Byte Idx
)
{
PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo);
PRT_BEAMFORMING_TIMER_INFO pBeamTimerInfo = &(pBeamInfo->BeamformingTimerInfo[Idx]);
// pBeamTimerInfo->Idx = Idx;
pBeamTimerInfo->Mode = beamforming_SoundingMode(pBeamInfo, Idx);
pBeamTimerInfo->BW = beamforming_SoundingBW(pBeamInfo, pBeamTimerInfo->Mode, Idx);
pBeamTimerInfo->BeamPeriod = beamforming_SoundingTime(pBeamInfo, pBeamTimerInfo->Mode);
if(pBeamTimerInfo->Mode == SOUNDING_SW_VHT_TIMER || pBeamTimerInfo->Mode == SOUNDING_SW_HT_TIMER)
{
ODM_SetTimer(ODMPTR, &pBeamInfo->BeamformingTimer, pBeamTimerInfo->BeamPeriod);
}
else
{
Beamforming_SetHWTimer(priv, pBeamTimerInfo->BeamPeriod);
}
// panic_printk ("%s Idx %d Mode %d BW %d Period %d\n", __FUNCTION__,
// Idx, pBeamTimerInfo->Mode, pBeamTimerInfo->BW, pBeamTimerInfo->BeamPeriod);
}
VOID
beamforming_EndPeriod_SW(
struct rtl8192cd_priv *priv,
u1Byte Idx
)
{
// u1Byte Idx = 0;
PRT_BEAMFORMING_ENTRY pBeamformEntry;
PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo);
PRT_BEAMFORMING_TIMER_INFO pBeamTimerInfo = &(pBeamInfo->BeamformingTimerInfo[Idx]);
if(pBeamTimerInfo->Mode == SOUNDING_SW_VHT_TIMER || pBeamTimerInfo->Mode == SOUNDING_SW_HT_TIMER)
{
ODM_CancelTimer(ODMPTR, &pBeamInfo->BeamformingTimer);
}
else
{
Beamforming_StopHWTimer(priv);
}
}
VOID
beamforming_EndPeriod_FW(
struct rtl8192cd_priv *priv,
u1Byte Idx
)
{
return;
}
VOID
beamforming_ClearEntry_SW(
struct rtl8192cd_priv *priv,
BOOLEAN IsDelete,
u1Byte DeleteIdx
)
{
u1Byte Idx = 0;
PRT_BEAMFORMING_ENTRY pBeamformEntry;
PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo);
if(IsDelete)
{
if(DeleteIdx<BEAMFORMEE_ENTRY_NUM)
{
pBeamformEntry = pBeamInfo->BeamformeeEntry + DeleteIdx;
if(!((!pBeamformEntry->bUsed) && pBeamformEntry->bSound))
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, SW DeleteIdx is wrong!\n", __FUNCTION__));
return;
}
if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSING)
{
pBeamformEntry->bBeamformingInProgress = FALSE;
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
}
else if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED)
{
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_UNINITIALIZE;
Beamforming_SetBeamFormStatus(priv, DeleteIdx);
}
pBeamformEntry->bSound=FALSE;
}
}
else
{
for(Idx = 0; Idx < BEAMFORMEE_ENTRY_NUM; Idx++)
{
pBeamformEntry = pBeamInfo->BeamformeeEntry+Idx;
if(pBeamformEntry->bSound)
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, SW Reset entry %d\n", __FUNCTION__, Idx));
/*
* If End procedure is
* 1. Between (Send NDPA, C2H packet return), reset state to initialized.
* After C2H packet return , status bit will be set to zero.
*r
* 2. After C2H packet, then reset state to initialized and clear status bit.
*/
if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSING)
{
Beamforming_End(priv, 0);
}
else if(pBeamformEntry->BeamformEntryState == BEAMFORMING_ENTRY_STATE_PROGRESSED)
{
pBeamformEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
Beamforming_SetBeamFormStatus(priv, Idx);
}
pBeamformEntry->bSound=FALSE;
}
}
}
}
VOID
beamforming_ClearEntry_FW(
struct rtl8192cd_priv *priv,
BOOLEAN IsDelete,
u1Byte DeleteIdx
)
{
return;
}
struct rtl8192cd_priv*
getBeamEntryDev(struct rtl8192cd_priv *priv, PRT_BEAMFORMING_ENTRY pEntry)
{
struct stat_info *pstat;
struct rtl8192cd_priv *vxd_priv;
int j;
pstat = get_stainfo(priv, pEntry->MacAddr);
if(pstat)
return priv;
#ifdef MBSSID
if ((OPMODE & WIFI_AP_STATE) && priv->pmib->miscEntry.vap_enable)
{
for (j=0; j<RTL8192CD_NUM_VWLAN; j++)
{
if ((priv->pvap_priv[j]->assoc_num > 0) && IS_DRV_OPEN(priv->pvap_priv[j]))
{
pstat = get_stainfo(priv->pvap_priv[j], pEntry->MacAddr);
if(pstat)
return priv->pvap_priv[j];
}
}
}
#endif
#ifdef UNIVERSAL_REPEATER
vxd_priv = GET_VXD_PRIV(priv);
if((OPMODE & WIFI_STATION_STATE) && (vxd_priv->assoc_num > 0) && IS_DRV_OPEN(vxd_priv) )
{
pstat = get_stainfo(vxd_priv, pEntry->MacAddr);
if(pstat)
return vxd_priv;
}
#endif
return NULL;
}
BOOLEAN
BeamformingStart_V2(
struct rtl8192cd_priv *priv,
u1Byte Idx,
u1Byte Mode,
u1Byte BW
)
{
pu1Byte RA = NULL;
PRT_BEAMFORMING_ENTRY pEntry;
BOOLEAN ret = TRUE;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
u1Byte NDPTxRate;
pEntry = &(pBeamformingInfo->BeamformeeEntry[Idx]);
priv = getBeamEntryDev(priv, pEntry);
if( !priv)
return FALSE;
if(pEntry->bUsed == FALSE)
{
pEntry->bBeamformingInProgress = FALSE;
return FALSE;
}
else
{
if(pEntry->bBeamformingInProgress)
return FALSE;
pEntry->bBeamformingInProgress = TRUE;
RA = pEntry->MacAddr;
if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER)
{
if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT))
{
// pBeamformingInfo->bBeamformingInProgress = FALSE;
pEntry->bBeamformingInProgress = FALSE;
return FALSE;
}
}
else if(Mode == SOUNDING_SW_VHT_TIMER || Mode == SOUNDING_HW_VHT_TIMER || Mode == SOUNDING_AUTO_VHT_TIMER)
{
if(!(pEntry->BeamformEntryCap & BEAMFORMER_CAP_VHT_SU))
{
// pBeamformingInfo->bBeamformingInProgress = FALSE;
pEntry->bBeamformingInProgress = FALSE;
return FALSE;
}
}
if(pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_INITIALIZED && pEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSED)
{
// pBeamformingInfo->bBeamformingInProgress = FALSE;
pEntry->bBeamformingInProgress = FALSE;
return FALSE;
}
else
{
pEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSING;
pEntry->bSound = TRUE;
}
}
pEntry->BW = BW;
pBeamformingInfo->BeamformeeCurIdx = Idx;
Beamforming_SetBeamFormStatus(priv, (pBeamformingInfo->BeamformeeCurIdx));
Beamforming_NDPARate(priv, Mode, BW, 0); // soundingpreiod only for debug, use 0 for all case
// debug
if(!priv->pshare->rf_ft_var.soundingEnable)
return TRUE;
#ifdef CONFIG_WLAN_HAL_8192EE
if ((OPMODE & WIFI_AP_STATE) && (priv->pshare->soundingLock))
return TRUE;
#endif
//
if(Mode == SOUNDING_SW_HT_TIMER || Mode == SOUNDING_HW_HT_TIMER || Mode == SOUNDING_AUTO_HT_TIMER)
{
NDPTxRate = Beamforming_GetHTNDPTxRate(priv, pEntry->CompSteeringNumofBFer);
ret = SendHTNDPAPacket(priv,RA, BW, NDPTxRate);
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, HT NDP Rate = %d\n", __FUNCTION__, NDPTxRate));
}
else
{
NDPTxRate = Beamforming_GetVHTNDPTxRate(priv, pEntry->CompSteeringNumofBFer);
#ifdef CONFIG_WLAN_HAL_8814AE
if(((pEntry->pSTA->current_tx_rate >=_NSS3_MCS7_RATE_) && (pEntry->pSTA->current_tx_rate <=_NSS3_MCS9_RATE_)) &&
priv->pshare->rf_ft_var.Nsnding3SS &&(GET_CHIP_VER(priv)== VERSION_8814A) )
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, VHT3SS 7,8,9, not sounding!!\n", __FUNCTION__));
}
else
#endif
#ifdef CONFIG_RTL_8812_SUPPORT
if(((pEntry->pSTA->current_tx_rate >=_NSS2_MCS0_RATE_) && (pEntry->pSTA->current_tx_rate <=_NSS2_MCS9_RATE_)) &&
priv->pshare->rf_ft_var.Nsnding3SS && (GET_CHIP_VER(priv)== VERSION_8812E) )
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, VHT2SS 0-9 Not sounding!!\n", __FUNCTION__));
}
else
#endif
/*
#ifdef CONFIG_WLAN_HAL_8192EE
if(((pEntry->pSTA->current_tx_rate >=_MCS8_RATE_) && (pEntry->pSTA->current_tx_rate <=_MCS15_RATE_)) &&
priv->pshare->rf_ft_var.Nsnding3SS && (GET_CHIP_VER(priv)== VERSION_8192E) )
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, HT MCS 8-15 Not sounding!!\n", __FUNCTION__));
}
else
#endif
*/
{
if(priv->pshare->rf_ft_var.ndpaaid != 0xff)
ret = SendVHTNDPAPacket(priv,RA, priv->pshare->rf_ft_var.ndpaaid, BW, NDPTxRate);
else
ret = SendVHTNDPAPacket(priv,RA, pEntry->AID, BW, NDPTxRate);
}
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, VHT NDP Rate = %d\n", __FUNCTION__, NDPTxRate));
}
if(ret == FALSE)
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, Beamforming_RemoveEntry because of failure sending NDPA for addr =\n", __FUNCTION__));
// Beamforming_RemoveEntry(priv, RA, &Idx);
Beamforming_Leave(priv, RA);
// pBeamformingInfo->bBeamformingInProgress = FALSE;
pEntry->bBeamformingInProgress = FALSE;
return FALSE;
}
return TRUE;
}
VOID
Beamforming_Notify(
struct rtl8192cd_priv *priv
)
{
u1Byte Idx=BEAMFORMEE_ENTRY_NUM;
BEAMFORMING_NOTIFY_STATE bSounding = BEAMFORMING_NOTIFY_NONE;
PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo);
PRT_BEAMFORMING_TIMER_INFO pBeamTimerInfo = NULL;
bSounding = beamfomring_bSounding(pBeamInfo, &Idx);
if(Idx<BEAMFORMEE_ENTRY_NUM)
pBeamTimerInfo = &(pBeamInfo->BeamformingTimerInfo[Idx]);
else if(bSounding == BEAMFORMING_NOTIFY_RESET)
pBeamTimerInfo = &(pBeamInfo->BeamformingTimerInfo[0]);
if(pBeamInfo->BeamformState == BEAMFORMING_STATE_END)
{
if(bSounding==BEAMFORMING_NOTIFY_ADD)
{
beamforming_StartPeriod(priv, Idx);
pBeamInfo->BeamformState = BEAMFORMING_STATE_START_1BFee;
}
}
else if(pBeamInfo->BeamformState == BEAMFORMING_STATE_START_1BFee)
{
if(bSounding==BEAMFORMING_NOTIFY_ADD)
{
beamforming_StartPeriod(priv, Idx);
pBeamInfo->BeamformState = BEAMFORMING_STATE_START_2BFee;
}
else if(bSounding == BEAMFORMING_NOTIFY_DELETE)
{
if(pBeamTimerInfo->Mode == SOUNDING_FW_HT_TIMER || pBeamTimerInfo->Mode == SOUNDING_FW_VHT_TIMER)
{
beamforming_EndPeriod_FW(priv, Idx);
beamforming_ClearEntry_FW(priv, TRUE, Idx);
}
else
{
beamforming_EndPeriod_SW(priv, Idx);
beamforming_ClearEntry_SW(priv, TRUE, Idx);
}
pBeamInfo->BeamformState = BEAMFORMING_STATE_END;
}
else if(bSounding == BEAMFORMING_NOTIFY_RESET)
{
if(pBeamTimerInfo->Mode == SOUNDING_FW_HT_TIMER || pBeamTimerInfo->Mode == SOUNDING_FW_VHT_TIMER)
{
beamforming_EndPeriod_FW(priv, Idx);
beamforming_ClearEntry_FW(priv, FALSE, Idx);
}
else
{
beamforming_EndPeriod_SW(priv, Idx);
beamforming_ClearEntry_SW(priv, FALSE, Idx);
}
pBeamInfo->BeamformState = BEAMFORMING_STATE_END;
}
}
else if(pBeamInfo->BeamformState == BEAMFORMING_STATE_START_2BFee)
{
if(bSounding == BEAMFORMING_NOTIFY_ADD)
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, should be block\n", __FUNCTION__));
}
else if(bSounding == BEAMFORMING_NOTIFY_DELETE)
{
if(pBeamTimerInfo->Mode == SOUNDING_FW_HT_TIMER || pBeamTimerInfo->Mode == SOUNDING_FW_VHT_TIMER)
{
beamforming_EndPeriod_FW(priv, Idx);
beamforming_ClearEntry_FW(priv, TRUE, Idx);
}
else
{
// For 2->1 entry, we should not cancel SW timer
beamforming_ClearEntry_SW(priv, TRUE, Idx);
}
pBeamInfo->BeamformState = BEAMFORMING_STATE_START_1BFee;
}
else if(bSounding == BEAMFORMING_NOTIFY_RESET)
{
if(pBeamTimerInfo->Mode == SOUNDING_FW_HT_TIMER || pBeamTimerInfo->Mode == SOUNDING_FW_VHT_TIMER)
{
beamforming_EndPeriod_FW(priv, Idx);
beamforming_ClearEntry_FW(priv, FALSE, Idx);
}
else
{
beamforming_EndPeriod_SW(priv, Idx);
beamforming_ClearEntry_SW(priv, FALSE, Idx);
}
pBeamInfo->BeamformState = BEAMFORMING_STATE_END;
}
}
}
VOID
Beamforming_AutoTest(
struct rtl8192cd_priv *priv,
u1Byte Idx,
PRT_BEAMFORMING_ENTRY pBeamformEntry
)
{
SOUNDING_MODE Mode;
BEAMFORMING_CAP BeamformCap = pBeamformEntry->BeamformEntryCap;
PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo);
PRT_BEAMFORMING_PERIOD_INFO pBeamPeriodInfo = &(pBeamInfo->BeamformingPeriodInfo);
if(BeamformCap & BEAMFORMER_CAP_VHT_SU)
Mode = SOUNDING_SW_VHT_TIMER;
else if(BeamformCap & BEAMFORMER_CAP_HT_EXPLICIT)
{
Mode = SOUNDING_SW_HT_TIMER; // use sw timer for all IC
/*#ifdef CONFIG_WLAN_HAL_8192EE
if(GET_CHIP_VER(priv)== VERSION_8192E)
Mode = SOUNDING_SW_HT_TIMER;
#endif
#ifdef CONFIG_RTL_8812_SUPPORT
if(GET_CHIP_VER(priv)== VERSION_8812E)
Mode = SOUNDING_HW_HT_TIMER;
#endif
#ifdef CONFIG_WLAN_HAL_8814AE
if(GET_CHIP_VER(priv)== VERSION_8814A)
Mode = SOUNDING_HW_HT_TIMER;
#endif*/
}
else
return;
pBeamPeriodInfo->Idx = Idx;
pBeamPeriodInfo->Mode = Mode;
pBeamPeriodInfo->BW = pBeamformEntry->BW;
pBeamPeriodInfo->BeamPeriod = priv->pshare->rf_ft_var.soundingPeriod;
}
VOID
Beamforming_End(
struct rtl8192cd_priv *priv,
BOOLEAN Status
)
{
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
PRT_BEAMFORMING_ENTRY pBFeeEntry = &(pBeamformingInfo->BeamformeeEntry[pBeamformingInfo->BeamformeeCurIdx]);
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, BeamformEntryState=%d, pBFeeEntry->bUsed=%d\n",
__FUNCTION__,
pBFeeEntry->BeamformEntryState,
pBFeeEntry->bUsed
));
if((pBFeeEntry->BeamformEntryState != BEAMFORMING_ENTRY_STATE_PROGRESSING)||(pBFeeEntry->bUsed==0))
{
return;
}
// Because in this case 8814A STOP sounding @BeamformingStart_V2 , so NOT apply V-matrix here.
if(((pBFeeEntry->pSTA->current_tx_rate >=_NSS3_MCS7_RATE_) && (pBFeeEntry->pSTA->current_tx_rate <=_NSS3_MCS9_RATE_)) &&
priv->pshare->rf_ft_var.Nsnding3SS)
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, VHT3SS 7,8,9, do not apply V matrix.\n", __FUNCTION__));
pBFeeEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
Beamforming_SetBeamFormStatus(priv, (pBeamformingInfo->BeamformeeCurIdx));
}
else if(Status == 1) // Receive CSI successful
{
pBFeeEntry->LogStatusFailCnt = 0;
pBFeeEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_PROGRESSED;
Beamforming_SetBeamFormStatus(priv, (pBeamformingInfo->BeamformeeCurIdx));
}
else // Receive CSI failure
{
pBFeeEntry->BeamformEntryState = BEAMFORMING_ENTRY_STATE_INITIALIZED;
pBFeeEntry->LogStatusFailCnt++;
}
pBFeeEntry->bBeamformingInProgress = FALSE;
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, pEntry->LogStatusFailCnt : %d\n", __FUNCTION__, pBFeeEntry->LogStatusFailCnt));
// Receive CSI failure
if(pBFeeEntry->LogStatusFailCnt > 50)
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s, LogStatusFailCnt > 50\n", __FUNCTION__));
pBeamformingInfo->CurDelBFerBFeeEntrySel = BFeeEntry;
if(Beamforming_DeInitEntry(priv, pBFeeEntry->MacAddr))
Beamforming_Notify(priv);
}
}
int shortenSoundingPeriod(struct rtl8192cd_priv *priv)
{
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
PRT_BEAMFORMING_ENTRY pEntry = &(pBeamformingInfo->BeamformeeEntry[0]);
struct stat_info *pstat;
struct rtl8192cd_priv *vxd_priv;
u4Byte idx, j, ret=0;
pBeamformingInfo->BeamformingPeriodState = 0; //
for(idx=0 ; idx<BEAMFORMEE_ENTRY_NUM; idx++)
{
pEntry = &(pBeamformingInfo->BeamformeeEntry[idx]);
if( pEntry->bUsed)
{
pstat = get_stainfo(priv, pEntry->MacAddr);
if(pstat)
{
if(pstat->tx_avarage > (1<<16))//0.5Mbps
{
++ret;
if(idx == 0) //
pBeamformingInfo->BeamformingPeriodState+=1; // entry 0 only = 1
else // entry 1 only = 2
pBeamformingInfo->BeamformingPeriodState+=2; // entry 0 and 1 = 3
}
}
#ifdef MBSSID
if ((OPMODE & WIFI_AP_STATE) && priv->pmib->miscEntry.vap_enable)
{
for (j=0; j<RTL8192CD_NUM_VWLAN; j++)
{
if ((priv->pvap_priv[j]->assoc_num > 0) && IS_DRV_OPEN(priv->pvap_priv[j]))
{
pstat = get_stainfo(priv->pvap_priv[j], pEntry->MacAddr);
if(pstat)
{
if(pstat->tx_avarage > (1<<16)) // 0.5Mbps
++ret;
}
}
}
}
#endif
#ifdef UNIVERSAL_REPEATER
vxd_priv = GET_VXD_PRIV(priv);
if((OPMODE & WIFI_STATION_STATE) && (vxd_priv->assoc_num > 0) && IS_DRV_OPEN(vxd_priv) )
{
pstat = get_stainfo(vxd_priv, pEntry->MacAddr);
if(pstat)
{
if(pstat->tx_avarage > (1<<16)) // 0.5Mbps
++ret;
}
}
#endif
}
}
//panic_printk("BeamformPeriodState = %d\n", pBeamformingInfo->BeamformingPeriodState);
return ret;
}
u1Byte
getBFeeStaNum(
struct rtl8192cd_priv *priv
)
{
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
int idx;
u1Byte BFee_STA_Num = 0;
for(idx=0 ; idx<BEAMFORMEE_ENTRY_NUM; idx++)
{
if(pBeamformingInfo->BeamformeeEntry[idx].bUsed)
BFee_STA_Num++;
}
return BFee_STA_Num;
}
VOID
Beamforming_TimerCallback(
struct rtl8192cd_priv *priv
)
{
BOOLEAN ret = FALSE;//, timer_set=FALSE;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
int idx = pBeamformingInfo->BeamformeeCurIdx;
PRT_BEAMFORMING_ENTRY pEntry = &(pBeamformingInfo->BeamformeeEntry[idx]);
PRT_BEAMFORMING_TIMER_INFO pBeamformingTimerInfo = &(pBeamformingInfo->BeamformingTimerInfo[idx]);
u1Byte BFee_STA_Num = 0;
u1Byte index = 0;
BFee_STA_Num = getBFeeStaNum(priv);
if (!(priv->drv_state & DRV_STATE_OPEN))
return;
#if 0
for(idx=0 ; idx<BEAMFORMEE_ENTRY_NUM; idx++)
{
#else
{
if(BFee_STA_Num == 2)
{
if(pBeamformingInfo->BeamformingPeriodState == 0 || pBeamformingInfo->BeamformingPeriodState == 3)
{
if(pBeamformingInfo->BeamformeeEntry[idx^1].bUsed)
idx ^=1;
}
else if(pBeamformingInfo->BeamformingPeriodState == 2)
{
idx = 1;
}
else
idx = 0;
}
else
{
if(pBeamformingInfo->BeamformeeEntry[0].bUsed)
idx = 0;
else if(pBeamformingInfo->BeamformeeEntry[1].bUsed)
idx = 1;
}
pBeamformingInfo->BeamformeeCurIdx = idx;
#endif
pEntry = &(pBeamformingInfo->BeamformeeEntry[idx]);
pBeamformingTimerInfo = &(pBeamformingInfo->BeamformingTimerInfo[idx]);
if(pEntry->bBeamformingInProgress)
{
Beamforming_End(priv, 0);
}
if( pEntry->bUsed)
{
ret = BeamformingStart_V2( priv, idx, pBeamformingTimerInfo->Mode, pEntry->BW);
}
// if(ret && !timer_set)
// if(ret)
if(pBeamformingInfo->BeamformeeEntry[0].bUsed || pBeamformingInfo->BeamformeeEntry[1].bUsed)
{
if(pBeamformingInfo->BeamformState >= BEAMFORMING_STATE_START_1BFee)
{
if(pBeamformingTimerInfo->Mode == SOUNDING_SW_VHT_TIMER || pBeamformingTimerInfo->Mode == SOUNDING_SW_HT_TIMER)
{
if(shortenSoundingPeriod(priv)){
if(pBeamformingInfo->BeamformingPeriodState == 1 || pBeamformingInfo->BeamformingPeriodState == 2)
{
ODM_SetTimer(ODMPTR, &pBeamformingInfo->BeamformingTimer, pBeamformingTimerInfo->BeamPeriod/100);
}
else // pBeamformingInfo->BeamformingPeriodState == 3
{
ODM_SetTimer(ODMPTR, &pBeamformingInfo->BeamformingTimer, pBeamformingTimerInfo->BeamPeriod/200);
}
}
else
{
ODM_SetTimer(ODMPTR, &pBeamformingInfo->BeamformingTimer, pBeamformingTimerInfo->BeamPeriod);
}
}
else
{
int BeamPeriod = priv->pshare->rf_ft_var.soundingPeriod;
if(pBeamformingTimerInfo->Mode == SOUNDING_HW_VHT_TIMER || pBeamformingTimerInfo->Mode == SOUNDING_HW_HT_TIMER)
BeamPeriod *=32; //HW timer, clock = 32K
if(shortenSoundingPeriod(priv))
{
if(pBeamformingInfo->BeamformingPeriodState == 1 || pBeamformingInfo->BeamformingPeriodState == 2) //only one entry is in used
BeamPeriod /= 100;
else //two entries are in used
BeamPeriod /= 200;
}
if(pBeamformingTimerInfo->BeamPeriod != BeamPeriod)
{
pBeamformingTimerInfo->BeamPeriod = BeamPeriod;
}
Beamforming_SetHWTimer(priv, pBeamformingTimerInfo->BeamPeriod);
}
// timer_set = 1;
}
}
}
}
VOID Beamforming_SWTimerCallback(unsigned long task_priv)
{
struct rtl8192cd_priv *priv = (struct rtl8192cd_priv *)task_priv;
Beamforming_TimerCallback(priv);
// mod_timer(&priv->txbf_swtimer, jiffies + priv->pshare->rf_ft_var.soundingPeriod);
}
VOID
Beamforming_Init(
struct rtl8192cd_priv *priv
)
{
PRT_BEAMFORMING_INFO pBeamInfo = &(priv->pshare->BeamformingInfo);
PRT_BEAMFORMING_PERIOD_INFO pBeamPeriodInfo = &(pBeamInfo->BeamformingPeriodInfo);
pBeamInfo->BeamformingPeriodState = 0;
pBeamPeriodInfo->Mode = SOUNDING_STOP_OID_TIMER;
init_timer(&pBeamInfo->BeamformingTimer);
pBeamInfo->BeamformingTimer.function = Beamforming_SWTimerCallback;
pBeamInfo->BeamformingTimer.data = (unsigned long)priv;
}
VOID
Beamforming_Release(
struct rtl8192cd_priv *priv
)
{
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
ODM_CancelTimer(ODMPTR, &pBeamformingInfo->BeamformingTimer);
}
VOID
Beamforming_Enter(
struct rtl8192cd_priv *priv,
struct stat_info *pstat
)
{
u1Byte BFerBFeeIdx = 0xff;
if(Beamforming_InitEntry(priv, pstat, &BFerBFeeIdx))
{
Beamforming_SetBeamFormEnter(priv, BFerBFeeIdx);
}
}
VOID
Beamforming_Leave(
struct rtl8192cd_priv *priv,
pu1Byte RA
)
{
u1Byte Idx = 0;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
Beamforming_GetBFeeEntryByAddr(priv, RA, &Idx);
if(RA == NULL)
{
BeamformingReset(priv);
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, Reset entry\n", __FUNCTION__));
}
else
{
pBeamformingInfo->CurDelBFerBFeeEntrySel = BFerBFeeEntry;
Beamforming_DeInitEntry(priv, RA);
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("%s, DeInit entry %d\n", __FUNCTION__, Idx));
}
Beamforming_Notify(priv);
}
VOID
Beamforming_SetTxBFen(
struct rtl8192cd_priv *priv,
u1Byte MacId,
BOOLEAN bTxBF
)
{
u1Byte Idx = 0;
// PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
PRT_BEAMFORMING_ENTRY pEntry;
pEntry = Beamforming_GetEntryByMacId(priv, MacId, &Idx);
if(pEntry == NULL)
return;
else
pEntry->bTxBF = bTxBF;
Beamforming_Notify(priv);
}
BEAMFORMING_CAP
Beamforming_GetBeamCap(
IN PRT_BEAMFORMING_INFO pBeamInfo
)
{
u1Byte i;
BOOLEAN bSelfBeamformer = FALSE;
BOOLEAN bSelfBeamformee = FALSE;
RT_BEAMFORMING_ENTRY BeamformeeEntry;
RT_BEAMFORMER_ENTRY BeamformerEntry;
BEAMFORMING_CAP BeamformCap = BEAMFORMING_CAP_NONE;
/*
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
{
BeamformEntry = pBeamInfo->BeamformeeEntry[i];
if(BeamformEntry.bUsed)
{
if( (BeamformEntry.BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU) ||
(BeamformEntry.BeamformEntryCap & BEAMFORMEE_CAP_HT_EXPLICIT))
bSelfBeamformee = TRUE;
if( (BeamformEntry.BeamformEntryCap & BEAMFORMER_CAP_VHT_SU) ||
(BeamformEntry.BeamformEntryCap & BEAMFORMER_CAP_HT_EXPLICIT))
bSelfBeamformer = TRUE;
}
if(bSelfBeamformer && bSelfBeamformee)
i = BEAMFORMEE_ENTRY_NUM;
}
*/
for(i = 0; i < BEAMFORMEE_ENTRY_NUM; i++)
{
BeamformeeEntry = pBeamInfo->BeamformeeEntry[i];
if(BeamformeeEntry.bUsed)
{
bSelfBeamformer = TRUE;
//panic_printk("[Beamform]%s, BFee entry %d bUsed=TRUE\n", __FUNCTION__, i);
}
}
for(i = 0; i < BEAMFORMER_ENTRY_NUM; i++)
{
BeamformerEntry = pBeamInfo->BeamformerEntry[i];
if(BeamformerEntry.bUsed)
{
bSelfBeamformee = TRUE;
//panic_printk"[Beamform]%s, BFer entry %d bUsed=TRUE\n", __FUNCTION__, i);
}
}
if(bSelfBeamformer)
BeamformCap |= BEAMFORMER_CAP;
if(bSelfBeamformee)
BeamformCap |= BEAMFORMEE_CAP;
return BeamformCap;
}
VOID
Beamforming_GetNDPAFrame(
struct rtl8192cd_priv *priv,
pu1Byte pNDPAFrame
)
{
pu1Byte TA ;
u1Byte Idx, Sequence;
PRT_BEAMFORMER_ENTRY pBeamformerEntry = NULL;
PRT_BEAMFORMING_INFO pBeamformingInfo = &(priv->pshare->BeamformingInfo);
if (GET_CHIP_VER(priv) != VERSION_8812E)
return;
if(IsCtrlNDPA(pNDPAFrame) == FALSE)
return;
TA = GetAddr2Ptr(pNDPAFrame);
// Remove signaling TA.
TA[0] = TA[0] & 0xFE;
pBeamformerEntry = Beamforming_GetBFerEntryByAddr(priv, TA, &Idx);
if(pBeamformerEntry == NULL)
return;
else if(!(pBeamformerEntry->BeamformEntryCap & BEAMFORMEE_CAP_VHT_SU))
return;
// NDPALogSuccess: 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( pBeamformerEntry->NDPALogSuccess==1 )
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s ,ClockResetTimes=%d, NDPALogSuccess=%d, clock reset is no longer needed!!\n",
__FUNCTION__,
pBeamformerEntry->ClockResetTimes,
pBeamformerEntry->NDPALogSuccess));
return;
}
else if( pBeamformerEntry->ClockResetTimes==3 )
{
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s ,ClockResetTimes=%d, NDPALogSuccess=%d, DeInit BFer Entry !!\n",
__FUNCTION__,
pBeamformerEntry->ClockResetTimes,
pBeamformerEntry->NDPALogSuccess));
pBeamformingInfo->CurDelBFerBFeeEntrySel = BFerEntry ;
Beamforming_DeInitEntry(priv, pBeamformerEntry->MacAddr);
return;
}
Sequence = (pNDPAFrame[16]) >> 2;
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s Start, Sequence=%d, NDPALogSeq=%d, NDPAPreLogSeq=%d, NDPALogRetryCnt=%d, ClockResetTimes=%d, NDPALogSuccess=%d\n",
__FUNCTION__,
Sequence,
pBeamformerEntry->NDPALogSeq,
pBeamformerEntry->NDPAPreLogSeq,
pBeamformerEntry->NDPALogRetryCnt,
pBeamformerEntry->ClockResetTimes,
pBeamformerEntry->NDPALogSuccess));
if ((pBeamformerEntry->NDPALogSeq != 0) && (pBeamformerEntry->NDPAPreLogSeq != 0))
{
//2 Success Condition
if( (pBeamformerEntry->NDPALogSeq!=Sequence)&&(pBeamformerEntry->NDPALogSeq!=pBeamformerEntry->NDPAPreLogSeq) )
{
/* break option for clcok reset, 2015-03-30, Jeffery */
pBeamformerEntry->NDPALogRetryCnt = 0;
/*As long as 8812A receive NDPA and feedback CSI succeed once, clock reset is no longer needed.*/
/*That is, NDPALogSuccess is NOT needed to be reset to zero, 2015-04-13, Jeffery*/
pBeamformerEntry->NDPALogSuccess=1;
}
//2 Fail Condition
else
{
if (pBeamformerEntry->NDPALogRetryCnt == 5)
{
pBeamformerEntry->ClockResetTimes++;
pBeamformerEntry->NDPALogRetryCnt = 0;
watchdog_kick();
ODM_RT_TRACE(ODMPTR, BEAMFORMING_DEBUG, ODM_DBG_LOUD, ("[Beamforming]@%s ,Clock Reset!!! ClockResetTimes=%d\n",
__FUNCTION__,
pBeamformerEntry->ClockResetTimes));
#ifdef CONFIG_RTL_8812_SUPPORT
_Beamforming_CLK(priv);
#endif
}
else
pBeamformerEntry->NDPALogRetryCnt++;
}
}
pBeamformerEntry->NDPAPreLogSeq = pBeamformerEntry->NDPALogSeq;
pBeamformerEntry->NDPALogSeq = Sequence;
}
#endif