summaryrefslogtreecommitdiff
path: root/network/wlan/WDI/COMMON/BAGen.c
diff options
context:
space:
mode:
authorDaiqian Hu <[email protected]>2016-11-21 08:54:24 +0800
committerDaiqian Hu <[email protected]>2016-11-21 08:54:24 +0800
commita95eaad088f61aa55da9d73015cf1ed86e64a67e (patch)
tree15b498a08a4aee4b7f8b1627d39c965b3aa3ba98 /network/wlan/WDI/COMMON/BAGen.c
parent1aa0338ec5418345ea0c383e92b4fa19f7c98425 (diff)
Re-submit for WDI sample driver to GitHub
Submit WDI sample driver to GitHub for RS1.
Diffstat (limited to 'network/wlan/WDI/COMMON/BAGen.c')
-rw-r--r--network/wlan/WDI/COMMON/BAGen.c943
1 files changed, 943 insertions, 0 deletions
diff --git a/network/wlan/WDI/COMMON/BAGen.c b/network/wlan/WDI/COMMON/BAGen.c
new file mode 100644
index 00000000..6d789c04
--- /dev/null
+++ b/network/wlan/WDI/COMMON/BAGen.c
@@ -0,0 +1,943 @@
+#include "Mp_Precomp.h"
+
+#if WPP_SOFTWARE_TRACE
+#include "BAGen.tmh"
+#endif
+
+VOID
+ActivateBAEntry(
+ PADAPTER Adapter,
+ PBA_RECORD pBA,
+ u2Byte Time
+ )
+{
+ RT_TRACE(COMP_HT, DBG_LOUD, ("pBA->bValid = TRUE\r\n"));
+ pBA->bValid = TRUE;
+ if(Time != 0)
+ PlatformSetTimer(Adapter, &pBA->Timer, Time);
+}
+
+VOID
+DeActivateBAEntry(
+ PADAPTER Adapter,
+ PBA_RECORD pBA
+)
+{
+ RT_TRACE(COMP_HT, DBG_LOUD, ("pBA->bValid = FALSE\r\n"));
+ pBA->bValid = FALSE;
+ PlatformCancelTimer(Adapter, &pBA->Timer);
+}
+
+VOID
+ExtendBAEntry(
+ PADAPTER Adapter,
+ PBA_RECORD pBA
+ )
+{
+// if(pBA->bValid && pBA->LifeTime!=0)
+// {
+// PlatformCancelTimer(Adapter, &pBA->Timer);
+// PlatformSetTimer(Adapter, &pBA->Timer, pBA->LifeTime);
+// }
+}
+
+BOOLEAN
+TxTsDeleteBA(
+ PADAPTER Adapter,
+ PTX_TS_RECORD pTxTs
+ )
+{
+ PBA_RECORD pAdmittedBa = &pTxTs->TxAdmittedBARecord;
+ PBA_RECORD pPendingBa = &pTxTs->TxPendingBARecord;
+ BOOLEAN bSendDELBA = FALSE;
+
+ // Delete pending BA
+ if(pPendingBa->bValid)
+ {
+ DeActivateBAEntry(Adapter, pPendingBa);
+ bSendDELBA = TRUE;
+ }
+
+ // Delete admitted BA
+ if(pAdmittedBa->bValid)
+ {
+ DeActivateBAEntry(Adapter, pAdmittedBa);
+ bSendDELBA = TRUE;
+ }
+
+ return bSendDELBA;
+}
+
+BOOLEAN
+RxTsDeleteBA(
+ PADAPTER Adapter,
+ PRX_TS_RECORD pRxTs
+ )
+{
+ PBA_RECORD pBa = &pRxTs->RxAdmittedBARecord;
+ BOOLEAN bSendDELBA = FALSE;
+
+ if(pBa->bValid)
+ {
+ DeActivateBAEntry(Adapter, pBa);
+ bSendDELBA = TRUE;
+ }
+
+ return bSendDELBA;
+}
+
+
+VOID
+ResetBaEntry(
+ PBA_RECORD pBA
+ )
+{
+ pBA->bValid = FALSE;
+ pBA->BaParamSet = 0;
+ pBA->BaTimeoutValue = 0;
+ pBA->DialogToken = 0;
+ pBA->BaStartSeqCtrl = 0;
+}
+
+VOID
+ConstructADDBAReq(
+ IN PADAPTER Adapter,
+ IN pu1Byte Addr,
+ IN PBA_RECORD pBA,
+ OUT pu1Byte Buffer,
+ OUT pu4Byte pLength
+ )
+{
+ OCTET_STRING osADDBAFrame, tmp;
+
+ FillOctetString(osADDBAFrame, Buffer, 0);
+ *pLength = 0;
+
+ ConstructMaFrameHdr(
+ Adapter,
+ Addr,
+ ACT_CAT_BA,
+ ACT_ADDBAREQ,
+ &osADDBAFrame );
+
+ // Dialog Token
+ FillOctetString(tmp, &pBA->DialogToken, 1);
+ PacketAppendData(&osADDBAFrame, tmp);
+
+ // BA Parameter Set
+ FillOctetString(tmp, &pBA->BaParamSet, 2);
+ PacketAppendData(&osADDBAFrame, tmp);
+
+ // BA Timeout Value
+ FillOctetString(tmp, &pBA->BaTimeoutValue, 2);
+ PacketAppendData(&osADDBAFrame, tmp);
+
+ // BA Start SeqCtrl
+ FillOctetString(tmp, &pBA->BaStartSeqCtrl, 2);
+ PacketAppendData(&osADDBAFrame, tmp);
+
+ *pLength = osADDBAFrame.Length;
+}
+
+VOID
+ConstructADDBARsp(
+ IN PADAPTER Adapter,
+ IN pu1Byte Addr,
+ IN PBA_RECORD pBA,
+ IN u2Byte StatusCode,
+ OUT pu1Byte Buffer,
+ OUT pu4Byte pLength
+ )
+{
+ OCTET_STRING osADDBAFrame, tmp;
+
+ FillOctetString(osADDBAFrame, Buffer, 0);
+ *pLength = 0;
+
+ ConstructMaFrameHdr(
+ Adapter,
+ Addr,
+ ACT_CAT_BA,
+ ACT_ADDBARSP,
+ &osADDBAFrame );
+
+ // Dialog Token
+ FillOctetString(tmp, &pBA->DialogToken, 1);
+ PacketAppendData(&osADDBAFrame, tmp);
+
+ // Status Code
+ FillOctetString(tmp, &StatusCode, 2);
+ PacketAppendData(&osADDBAFrame, tmp);
+
+ // BA Parameter Set
+ FillOctetString(tmp, &pBA->BaParamSet, 2);
+ PacketAppendData(&osADDBAFrame, tmp);
+
+ // BA Timeout Value
+ FillOctetString(tmp, &pBA->BaTimeoutValue, 2);
+ PacketAppendData(&osADDBAFrame, tmp);
+
+ *pLength = osADDBAFrame.Length;
+}
+
+VOID
+ConstructDELBA(
+ IN PADAPTER Adapter,
+ IN pu1Byte Addr,
+ IN PBA_RECORD pBA,
+ IN TR_SELECT TxRxSelect,
+ IN u2Byte ReasonCode,
+ OUT pu1Byte Buffer,
+ OUT pu4Byte pLength
+ )
+{
+ OCTET_STRING osDELBAFrame, tmp;
+ u2Byte DelbaParamSet=0;
+
+ SET_DELBA_PARAM_SET_FIELD_INITIATOR(&DelbaParamSet, (TxRxSelect==TX_DIR)?1:0 );
+ SET_DELBA_PARAM_SET_FIELD_TID(&DelbaParamSet, GET_BA_PARAM_SET_FIELD_TID(&(pBA->BaParamSet))) ;
+
+ FillOctetString(osDELBAFrame, Buffer, 0);
+ *pLength = 0;
+
+ ConstructMaFrameHdr(
+ Adapter,
+ Addr,
+ ACT_CAT_BA,
+ ACT_DELBA,
+ &osDELBAFrame );
+
+ // DELBA Parameter Set
+ FillOctetString(tmp, &DelbaParamSet, 2);
+ PacketAppendData(&osDELBAFrame, tmp);
+
+ // Reason Code
+ FillOctetString(tmp, &ReasonCode, 2);
+ PacketAppendData(&osDELBAFrame, tmp);
+
+ *pLength = osDELBAFrame.Length;
+}
+
+VOID
+SendADDBAReq(
+ IN PADAPTER Adapter,
+ IN pu1Byte Addr,
+ IN PBA_RECORD pBA
+ )
+{
+ PRT_TCB pTcb;
+ PRT_TX_LOCAL_BUFFER pBuf;
+ u1Byte DataRate = MgntQuery_MgntFrameTxRate(Adapter, Addr);
+
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====>SendADDBAReq()\n"));
+
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
+
+ if(MgntGetBuffer(Adapter, &pTcb, &pBuf))
+ {
+ ConstructADDBAReq(Adapter, Addr, pBA, pBuf->Buffer.VirtualAddress, &pTcb->PacketLength);
+
+ if(pTcb->PacketLength != 0)
+ {
+ if(ACTING_AS_AP(Adapter))
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, BE_QUEUE, DataRate);
+ else
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, DataRate);
+ }
+ }
+
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
+}
+
+VOID
+SendADDBARsp(
+ IN PADAPTER Adapter,
+ IN pu1Byte Addr,
+ IN PBA_RECORD pBA,
+ IN u2Byte StatusCode
+ )
+{
+ PRT_TCB pTcb;
+ PRT_TX_LOCAL_BUFFER pBuf;
+ u1Byte DataRate = MgntQuery_MgntFrameTxRate(Adapter, Addr);
+
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====>SendADDBARsp()\n"));
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
+
+ if(MgntGetBuffer(Adapter, &pTcb, &pBuf))
+ {
+ ConstructADDBARsp(
+ Adapter,
+ Addr,
+ pBA,
+ StatusCode,
+ pBuf->Buffer.VirtualAddress,
+ &pTcb->PacketLength );
+
+ if(pTcb->PacketLength != 0)
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, DataRate);
+ }
+
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
+}
+
+VOID
+SendDELBA(
+ IN PADAPTER Adapter,
+ IN pu1Byte Addr,
+ IN PBA_RECORD pBA,
+ IN TR_SELECT TxRxSelect,
+ IN u2Byte ReasonCode
+ )
+{
+ PRT_TCB pTcb;
+ PRT_TX_LOCAL_BUFFER pBuf;
+ u1Byte DataRate = MgntQuery_MgntFrameTxRate(Adapter, Addr);
+
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====>SendDELBA()\n"));
+ PlatformAcquireSpinLock(Adapter, RT_TX_SPINLOCK);
+
+ if(MgntGetBuffer(Adapter, &pTcb, &pBuf))
+ {
+ ConstructDELBA(
+ Adapter,
+ Addr,
+ pBA,
+ TxRxSelect,
+ ReasonCode,
+ pBuf->Buffer.VirtualAddress,
+ &pTcb->PacketLength );
+
+ if(pTcb->PacketLength != 0)
+ MgntSendPacket(Adapter, pTcb, pBuf, pTcb->PacketLength, NORMAL_QUEUE, DataRate);
+ }
+
+ PlatformReleaseSpinLock(Adapter, RT_TX_SPINLOCK);
+}
+
+
+RT_STATUS
+OnADDBAReq(
+ IN PADAPTER Adapter,
+ IN PRT_RFD pRfd,
+ IN POCTET_STRING mmpdu
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PBA_RECORD pBA;
+ PRX_TS_RECORD pTS;
+ pu1Byte Addr = Frame_Addr2(*mmpdu);
+ u2Byte StatusCode;
+ RT_TRACE(COMP_QOS, DBG_TRACE, ("=====>OnADDBAReq()\n"));
+ // CategoryCode(1) + ActionCode(1) + DialogToken(1) + ParameterSet(2) + TimeoutValue(2) + StartSequence(2)
+ if(mmpdu->Length < sMacHdrLng + 9)
+ {
+ RT_TRACE(COMP_QOS, DBG_SERIOUS, ("OnADDBAReq(): Invalid length(%d) of frame\n", mmpdu->Length));
+ return RT_STATUS_MALFORMED_PKT;
+ }
+ //
+ // Check Block Ack support.
+ // Reject if there is no support of Block Ack.
+ //
+ if( (pMgntInfo->pStaQos->CurrentQosMode == QOS_DISABLE) ||
+ (pMgntInfo->pHTInfo->bCurrentHTSupport == FALSE) ||
+ (pMgntInfo->pHTInfo->bAcceptAddbaReq == FALSE) ||
+ (pMgntInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ) )
+ {
+ StatusCode = ADDBA_STATUS_REFUSED;
+ goto OnADDBAReq_Fail;
+ }
+
+ // Add by hpfan: reject addba when 4-way is not finished
+ if(pMgntInfo->bWiFiConfg &&
+ pMgntInfo->SecurityInfo.SecLvl > RT_SEC_LVL_NONE && !SecIsTxKeyInstalled(Adapter, pMgntInfo->Bssid))
+ {
+ StatusCode = ADDBA_STATUS_REFUSED;
+ goto OnADDBAReq_Fail;
+ }
+
+ //
+ // Search for related traffic stream.
+ // If there is no matched TS, reject the ADDBA request.
+ //
+ if( !GetTs(
+ Adapter,
+ (PTS_COMMON_INFO*)(&pTS),
+ Addr,
+ GET_BA_FRAME_PARAM_SET_TID(mmpdu->Octet),
+ RX_DIR,
+ TRUE) )
+ {
+ StatusCode = ADDBA_STATUS_REFUSED;
+ goto OnADDBAReq_Fail;
+ }
+ pBA = &pTS->RxAdmittedBARecord;
+
+
+ //
+ // To Determine the ADDBA Req content
+ // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
+ // I want to check StartSeqCtrl to make sure when we start aggregation!!!
+ //
+ if(GET_BA_FRAME_PARAM_SET_BA_POLICY(mmpdu->Octet) == BA_POLICY_DELAYED)
+ {
+ StatusCode = ADDBA_STATUS_INVALID_PARAM;
+ goto OnADDBAReq_Fail;
+ }
+
+ //
+ // Clear all packets queued in driver for RxReorder and prepare to receive packet from new
+ // new sequence start!!
+ // This fix the protocol IOT issue with Netgear WRT3500.
+ //
+
+ FlushRxTsPendingPkts(Adapter, pTS);
+
+ //
+ // Admit the ADDBA Request
+ //
+ DeActivateBAEntry(Adapter, pBA);
+ PlatformMoveMemory(&(pBA->DialogToken) , GET_BA_FRAME_DIALOG_TOKEN(mmpdu->Octet), 1);
+ PlatformMoveMemory(&(pBA->BaParamSet) , GET_BA_FRAME_PARAM_SET(mmpdu->Octet), 2);
+ PlatformMoveMemory(&(pBA->BaTimeoutValue), GET_BA_FRAME_TIMEOUT_VALUE(mmpdu->Octet), 2);
+ PlatformMoveMemory(&(pBA->BaStartSeqCtrl), GET_BAREQ_FRAME_START_SQECTRL(mmpdu->Octet), 2);
+
+ {
+ SET_BA_PARAM_SET_FIELD_BUF_SIZE( &(pBA->BaParamSet), 64); // At least, forced by SPEC
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("OnADDBAReq(): SET_FIELD_BUF_SIZE = 64\n"));
+ }
+
+ ActivateBAEntry(Adapter, pBA, 0);
+ SendADDBARsp(Adapter, Addr, pBA, ADDBA_STATUS_SUCCESS);
+
+ // End of procedure.
+ return RT_STATUS_SUCCESS;
+
+OnADDBAReq_Fail:
+ {
+ BA_RECORD BA;
+ PlatformMoveMemory(&(BA.BaParamSet), GET_BA_FRAME_PARAM_SET(mmpdu->Octet), 2);
+ PlatformMoveMemory(&(BA.BaTimeoutValue), GET_BA_FRAME_TIMEOUT_VALUE(mmpdu->Octet), 2);
+ PlatformMoveMemory(&(BA.DialogToken), GET_BA_FRAME_DIALOG_TOKEN(mmpdu->Octet), 1);
+ SET_BA_PARAM_SET_FIELD_BA_POLICY(&(BA.BaParamSet), BA_POLICY_IMMEDIATE);
+ SendADDBARsp(Adapter, Addr, &BA, StatusCode);
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("OnADDBAReq(): OnADDBAReq_Fail\n"));
+ }
+ return RT_STATUS_SUCCESS;
+}
+
+RT_STATUS
+OnADDBARsp(
+ IN PADAPTER Adapter,
+ IN PRT_RFD pRfd,
+ IN POCTET_STRING mmpdu
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PBA_RECORD pPendingBA, pAdmittedBA;
+ PTX_TS_RECORD pTS;
+ pu1Byte Addr = Frame_Addr2(*mmpdu);
+ pu1Byte pDialogToken = GET_BA_FRAME_DIALOG_TOKEN(mmpdu->Octet);
+ pu1Byte pStatusCode = GET_BA_FRAME_STATUS_CODE(mmpdu->Octet);
+ u2Byte ReasonCode = ADDBA_STATUS_INVALID_PARAM;
+
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====>OnADDBARsp()\n"));
+ // CategoryCode(1) + ActionCode(1) + DialogToken(1) + StatusCode(2) + ParameterSet(2) + TimeoutValue(2)
+ if(mmpdu->Length < sMacHdrLng + 9)
+ {
+ RT_TRACE(COMP_QOS, DBG_SERIOUS, ("OnADDBARsp(): Invalid length(%d) of frame\n", mmpdu->Length));
+ return RT_STATUS_MALFORMED_PKT;
+ }
+
+ //
+ // Check the capability
+ // Since we can always receive A-MPDU, we just check if it is under HT mode.
+ //
+ if(pMgntInfo->pStaQos->CurrentQosMode == QOS_DISABLE ||
+ pMgntInfo->pHTInfo->bCurrentHTSupport == FALSE ||
+ pMgntInfo->pHTInfo->bCurrentAMPDUEnable == FALSE )
+ {
+ ReasonCode = DELBA_REASON_UNKNOWN_BA;
+ goto OnADDBARsp_Reject;
+ }
+
+ //
+ // Search for related TS.
+ // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
+ //
+ if (!GetTs(
+ Adapter,
+ (PTS_COMMON_INFO*)(&pTS),
+ Addr,
+ GET_BA_FRAME_PARAM_SET_TID(mmpdu->Octet),
+ TX_DIR,
+ FALSE) )
+ {
+ ReasonCode = DELBA_REASON_UNKNOWN_BA;
+ goto OnADDBARsp_Reject;
+ }
+ pTS->bAddBaReqInProgress = FALSE;
+ pPendingBA = &pTS->TxPendingBARecord;
+ pAdmittedBA = &pTS->TxAdmittedBARecord;
+
+
+ //
+ // Check if related BA is waiting for setup.
+ // If not, reject by sending DELBA frame.
+ //
+ if((pAdmittedBA->bValid==TRUE))
+ {
+ // Since BA is already setup, we ignore all other ADDBA Response.
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n"));
+ return RT_STATUS_PKT_DROP;
+ }
+ else if((pPendingBA->bValid == FALSE) ||(*pDialogToken != pPendingBA->DialogToken))
+ {
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n"));
+ ReasonCode = DELBA_REASON_UNKNOWN_BA;
+ goto OnADDBARsp_Reject;
+ }
+ else
+ {
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", (*pStatusCode) ));
+ DeActivateBAEntry(Adapter, pPendingBA);
+ }
+
+
+ if((*pStatusCode) == ADDBA_STATUS_SUCCESS)
+ {
+ //
+ // Determine ADDBA Rsp content here.
+ // We can compare the value of BA parameter set that Peer returned and Self sent.
+ // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
+ //
+ if(GET_BA_FRAME_PARAM_SET_BA_POLICY(mmpdu->Octet) == BA_POLICY_DELAYED)
+ {
+ // Since this is a kind of ADDBA failed, we delay next ADDBA process.
+ pTS->bAddBaReqDelayed = TRUE;
+
+ DeActivateBAEntry(Adapter, pAdmittedBA);
+ ReasonCode = DELBA_REASON_END_BA;
+ goto OnADDBARsp_Reject;
+ }
+
+
+ //
+ // Admitted condition
+ //
+ PlatformMoveMemory(&(pAdmittedBA->DialogToken) , GET_BA_FRAME_DIALOG_TOKEN(mmpdu->Octet), 1);
+ PlatformMoveMemory(&(pAdmittedBA->BaTimeoutValue), GET_BA_FRAME_TIMEOUT_VALUE(mmpdu->Octet), 2);
+ PlatformMoveMemory(&(pAdmittedBA->BaStartSeqCtrl), &(pPendingBA->BaStartSeqCtrl), 2);
+ PlatformMoveMemory(&(pAdmittedBA->BaParamSet) , GET_BA_FRAME_PARAM_SET(mmpdu->Octet), 2);
+ pAdmittedBA->BufferSize = GET_BA_FRAME_PARAM_SET_BUF_SIZE(mmpdu->Octet);
+
+ if(0 == pAdmittedBA->BufferSize)
+ {
+ RT_PRINT_ADDR(COMP_HT, DBG_WARNING, "[WARNING]OnADDBARsp(): Incorrect BufferSize (0) in AddBaRsp, skip this BlockAck process for Addr = ", Addr);
+ ReasonCode = ADDBA_STATUS_INVALID_PARAM;
+ goto OnADDBARsp_Reject;
+ }
+ DeActivateBAEntry(Adapter, pAdmittedBA);
+ ActivateBAEntry(Adapter, pAdmittedBA, 0 );
+ }
+ else
+ {
+ // Delay next ADDBA process.
+ pTS->bAddBaReqDelayed = TRUE;
+ }
+
+ // End of procedure
+ if(Adapter->TDLSSupport)
+ {
+ TDLS_OnAddBaRsp(Adapter, mmpdu);
+ }
+
+ return RT_STATUS_SUCCESS;
+
+OnADDBARsp_Reject:
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("OnADDBARsp(): Rejected!!!!!!!!ReasonCode=%d\n", ReasonCode));
+ {
+ BA_RECORD BA;
+ PlatformMoveMemory(&(BA.BaParamSet), GET_BA_FRAME_PARAM_SET(mmpdu->Octet), 2);
+ SendDELBA(Adapter, Addr, &BA, TX_DIR, ReasonCode);
+ }
+ return RT_STATUS_SUCCESS;
+}
+
+
+RT_STATUS
+OnDELBA(
+ IN PADAPTER Adapter,
+ IN PRT_RFD pRfd,
+ IN POCTET_STRING mmpdu
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ pu1Byte Addr = Frame_Addr2(*mmpdu);
+ BA_RECORD BA;
+
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====>OnDELBA()\n"));
+ if(pMgntInfo->pStaQos->CurrentQosMode == QOS_DISABLE ||
+ pMgntInfo->pHTInfo->bCurrentHTSupport == FALSE )
+ return RT_STATUS_SUCCESS;
+
+ // CategoryCode(1) + ActionCode(1) + ParameterSet(2) + ReasonCode(2)
+ if(mmpdu->Length < sMacHdrLng + 6)
+ {
+ RT_TRACE(COMP_QOS, DBG_SERIOUS, ("OnDELBA(): Invalid length(%d) of frame\n", mmpdu->Length));
+ return RT_STATUS_MALFORMED_PKT;
+ }
+
+ if(GET_DELBA_FRAME_PARAM_SET_INITIATOR(mmpdu->Octet) == 1)
+ {
+ PRX_TS_RECORD pRxTs;
+
+ if( !GetTs(
+ Adapter,
+ (PTS_COMMON_INFO*)&pRxTs,
+ Addr,
+ GET_DELBA_FRAME_PARAM_SET_TID(mmpdu->Octet),
+ RX_DIR,
+ FALSE) )
+ {
+ return RT_STATUS_FAILURE;
+ }
+
+ //BA Process Error when link with Netgear3500 v1
+ //Fix do S3/S4 long run error
+ //by sherry 20101124
+ if(pMgntInfo->IOTPeer == HT_IOT_PEER_MARVELL)
+ {
+ PlatformMoveMemory(&(BA.BaParamSet), GET_BA_FRAME_PARAM_SET(mmpdu->Octet), 2);
+ SendDELBA(Adapter, Addr, &BA, RX_DIR, 1);
+ }
+
+ RxTsDeleteBA(Adapter, pRxTs);
+ }
+ else
+ {
+ PTX_TS_RECORD pTxTs;
+
+ if(!GetTs(
+ Adapter,
+ (PTS_COMMON_INFO*)&pTxTs,
+ Addr,
+ GET_DELBA_FRAME_PARAM_SET_TID(mmpdu->Octet),
+ TX_DIR,
+ FALSE) )
+ {
+ return RT_STATUS_FAILURE;
+ }
+
+ pTxTs->bUsingBa = FALSE;
+ pTxTs->bAddBaReqInProgress = FALSE;
+ pTxTs->bAddBaReqDelayed = FALSE;
+ PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
+ TxTsDeleteBA(Adapter, pTxTs);
+ }
+
+ return RT_STATUS_SUCCESS;
+}
+
+//
+// ADDBA initiate. This can only be called by TX side.
+//
+VOID
+TsInitAddBA(
+ PADAPTER Adapter,
+ PTX_TS_RECORD pTS,
+ u1Byte Policy,
+ BOOLEAN bOverwritePending
+ )
+{
+ PBA_RECORD pBA = &pTS->TxPendingBARecord;
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ PRT_HIGH_THROUGHPUT pHTInfo = GET_HT_INFO(pMgntInfo);
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====>TsInitAddBA()\n"));
+
+ if(pBA->bValid==TRUE && bOverwritePending==FALSE)
+ return;
+
+ // Set parameters to "Pending" variable set
+ DeActivateBAEntry(Adapter, pBA);
+
+ pBA->DialogToken++; // DialogToken: Only keep the latest dialog token
+ SET_BA_PARAM_SET_FIELD_AMSDU_SUPPORT(&(pBA->BaParamSet), 0); // Do not support A-MSDU with A-MPDU now!!
+ SET_BA_PARAM_SET_FIELD_BA_POLICY(&(pBA->BaParamSet), Policy); // Policy: Delayed or Immediate
+ SET_BA_PARAM_SET_FIELD_TID(&(pBA->BaParamSet), GET_TSPEC_BODY_TSINFO_TSID(pTS->TsCommonInfo.TSpec)); // TID
+ // BufferSize: This need to be set according to A-MPDU vector
+
+ {
+ SET_BA_PARAM_SET_FIELD_BUF_SIZE(&(pBA->BaParamSet), 64); // BufferSize: This need to be set according to A-MPDU vector
+ }
+
+ // TODO: Enable AMSDU may not be aware of AMPDU
+ if(HT_AMSDU_WITHIN_AMPDU == pHTInfo->ForcedAMSDUMode)
+ {
+ SET_BA_PARAM_SET_FIELD_AMSDU_SUPPORT(&(pBA->BaParamSet), 1);
+ }
+
+ pBA->BaTimeoutValue = 0; // Timeout value: Set 0 to disable Timer
+ SET_BA_START_SQECTRL_FIELD_SEQ_NUM(&(pBA->BaStartSeqCtrl), ((pTS->TxCurSeq) % 4096));
+
+ ActivateBAEntry(Adapter, pBA, BA_SETUP_TIMEOUT);
+
+ SendADDBAReq(Adapter, pTS->TsCommonInfo.Addr, pBA);
+
+ if(!ACTING_AS_AP(Adapter))
+ {
+ // Negoitate with current SeqNum, but active this BA after 3 packets Txed
+ SET_BA_START_SQECTRL_FIELD_SEQ_NUM(&(pBA->BaStartSeqCtrl), ((pTS->TxCurSeq + 3) % 4096));
+ }
+}
+
+VOID
+TsInitDelBA(
+ PADAPTER Adapter,
+ PTS_COMMON_INFO pTsCommonInfo,
+ TR_SELECT TxRxSelect
+ )
+{
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====>TsInitDelBA()\n"));
+
+ if(TxRxSelect == TX_DIR)
+ {
+ PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
+
+ if(TxTsDeleteBA(Adapter, pTxTs))
+ SendDELBA(
+ Adapter,
+ pTsCommonInfo->Addr,
+ (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
+ TxRxSelect,
+ DELBA_REASON_END_BA );
+ }
+ else if(TxRxSelect == RX_DIR)
+ {
+ PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
+ if(RxTsDeleteBA(Adapter, pRxTs))
+ SendDELBA(
+ Adapter,
+ pTsCommonInfo->Addr,
+ &pRxTs->RxAdmittedBARecord,
+ TxRxSelect,
+ DELBA_REASON_END_BA );
+ }
+}
+
+VOID
+BaSetupTimeOut(
+ PRT_TIMER pTimer
+ )
+{
+ PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTimer->Context;
+
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====>BaSetupTimeOut()\n"));
+ pTxTs->bAddBaReqInProgress = FALSE;
+ pTxTs->bAddBaReqDelayed = TRUE;
+ pTxTs->TxPendingBARecord.bValid = FALSE;
+}
+
+VOID
+TxBaInactTimeout(
+ PRT_TIMER pTimer
+ )
+{
+ PADAPTER Adapter = (PADAPTER)pTimer->Adapter;
+ PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTimer->Context;
+
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====>TxBaInactTimeout()\n"));
+ TxTsDeleteBA(Adapter, pTxTs);
+ SendDELBA(
+ Adapter,
+ pTxTs->TsCommonInfo.Addr,
+ &pTxTs->TxAdmittedBARecord,
+ TX_DIR,
+ DELBA_REASON_TIMEOUT );
+}
+
+VOID
+RxBaInactTimeout(
+ PRT_TIMER pTimer
+ )
+{
+ PADAPTER Adapter = (PADAPTER)pTimer->Adapter;
+ PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTimer->Context;
+
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====>RxBaInactTimeout()\n"));
+ if(ACTING_AS_AP(Adapter))
+ return;
+
+ RxTsDeleteBA(Adapter, pRxTs);
+ SendDELBA(
+ Adapter,
+ pRxTs->TsCommonInfo.Addr,
+ &pRxTs->RxAdmittedBARecord,
+ RX_DIR,
+ DELBA_REASON_TIMEOUT );
+}
+
+VOID
+RxBACheck(
+ PADAPTER Adapter,
+ PRT_RFD pRfd,
+ POCTET_STRING pFrame
+ )
+{
+
+}
+
+//
+// Description: Parse BlockAckReq frame
+//
+// 2015.08.19. Added by tynli.
+//
+RT_STATUS
+OnBAReq(
+ IN PADAPTER Adapter,
+ IN PRT_RFD pRfd,
+ IN OCTET_STRING ospdu
+ )
+{
+ PMGNT_INFO pMgntInfo = &(Adapter->MgntInfo);
+ pu1Byte pBARFrame = ospdu.Octet;
+ u1Byte BARAckPolicy, MultiTID, CompressedBitmap, GCR, TIDInfo = 0;
+ u2Byte StartSeqNum, LatestSeqNum;
+ PRX_TS_RECORD pTS = NULL;
+ pu1Byte Addr = Frame_Addr2(ospdu);
+ BAR_TYPE BARType = BAR_TYPE_BASIC_BAR;
+
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("=====> OnBAReq()\n"));
+
+ // Header (16) + BAR control (2)
+ if(ospdu.Length < 16 + 2)
+ {
+ RT_TRACE(COMP_QOS, DBG_SERIOUS, ("OnBAReq(): Invalid length(%d) of frame\n", ospdu.Length));
+ return RT_STATUS_MALFORMED_PKT;
+ }
+
+ //
+ // Check Block Ack Req support.
+ // Reject if there is no support of Block Ack Req.
+ //
+ if((pMgntInfo->pStaQos->CurrentQosMode == QOS_DISABLE) ||
+ (pMgntInfo->pHTInfo->bCurrentHTSupport == FALSE))
+ {
+ //StatusCode = ADDBA_STATUS_REFUSED;
+ return RT_STATUS_FAILURE;
+ }
+
+ // Get the BAR control field offset
+ pBARFrame += 16;
+ BARAckPolicy = GET_BAR_PARAM_CTRL_FIELD_BAR_ACK_POLICY(pBARFrame);
+ if(BARAckPolicy == BAR_NORMAL_ACK)
+ {
+ // Normal Ack
+ MultiTID = GET_BAR_PARAM_CTRL_FIELD_MULTI_TID(pBARFrame);
+ CompressedBitmap = GET_BAR_PARAM_CTRL_FIELD_COMPRESSED_BITMAP(pBARFrame);
+ GCR = GET_BAR_PARAM_CTRL_FIELD_GCR(pBARFrame);
+ TIDInfo = GET_BAR_PARAM_CTRL_FIELD_TID_INFO(pBARFrame);
+
+ if(MultiTID == 0 && CompressedBitmap == 0 && GCR == 0)
+ {
+ // Basic BlockAckReq
+ BARType = BAR_TYPE_BASIC_BAR;
+ }
+ else if(MultiTID == 0 && CompressedBitmap == 1 && GCR == 0)
+ {
+ // Compressed BlockAckReq
+ BARType = BAR_TYPE_COMPRESSED_BAR;
+ }
+ else if(MultiTID == 1 && CompressedBitmap == 0 && GCR == 0)
+ {
+ // Extended Compressed BlockAckReq
+ BARType = BAR_TYPE_EXT_COMPRESSED_BAR;
+ }
+ else if(MultiTID == 1 && CompressedBitmap == 1 && GCR == 0)
+ {
+ // Multi-TID BlockAckReq
+ BARType = BAR_TYPE_MULTI_TID_BAR;
+ }
+ else if(MultiTID == 0 && CompressedBitmap == 1 && GCR == 1)
+ {
+ // GCR BlockAckReq
+ BARType = BAR_TYPE_GCR_BAR;
+ }
+ else
+ {
+ // Reserved
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("OnBAReq(): BAR type is reserved.\n"));
+
+ }
+ }
+ else
+ {
+ // No Ack
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("OnBAReq(): BAR ACK policy is No ACK. Not handle now!!\n"));
+ }
+
+
+ //
+ // Search for related traffic stream.
+ //
+ if(!GetTs(
+ Adapter,
+ (PTS_COMMON_INFO*)(&pTS),
+ Addr,
+ TIDInfo,
+ RX_DIR,
+ TRUE))
+ {
+ return RT_STATUS_FAILURE;
+ }
+
+ if(BARType == BAR_TYPE_BASIC_BAR || BARType == BAR_TYPE_COMPRESSED_BAR ||
+ BARType == BAR_TYPE_EXT_COMPRESSED_BAR || BARType == BAR_TYPE_GCR_BAR)
+ {
+ PRT_LIST_ENTRY pList = &pTS->RxPendingPktList;
+
+ // Get BAR Info
+ pBARFrame += 2;
+ StartSeqNum = GET_BAR_PARAM_INFO_FIELD_STARTING_SEQ_NUM(pBARFrame);
+
+ // Check the last received sequence number
+ if(!RTIsListEmpty(pList))
+ {
+ LatestSeqNum = ((PRX_REORDER_ENTRY)pList->Blink)->SeqNum;
+ }
+ else
+ {
+ // Pending list is empty!
+ LatestSeqNum = pTS->RxIndicateSeq;
+ }
+
+ // Update Rx indicate seq num for TS.
+ if(!(SN_LESS(StartSeqNum, LatestSeqNum) || SN_EQUAL(StartSeqNum, LatestSeqNum)))
+ {
+ //
+ // Indicate packets queued in driver for RxReorder and prepare to receive packet from new
+ // new sequence start!!
+ //
+ if(pTS->RxIndicateState==RXTS_INDICATE_BATCH)
+ IndicateRxReorderList(Adapter, pTS, FALSE);
+ else if(pTS->RxIndicateState==RXTS_INDICATE_REORDER)
+ IndicateRxReorderList(Adapter, pTS, TRUE);
+
+ if(!(SN_LESS(StartSeqNum, pTS->RxIndicateSeq) || SN_EQUAL(StartSeqNum, pTS->RxIndicateSeq)))
+ {
+ pTS->RxIndicateSeq = StartSeqNum;
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("OnBAReq(): Update Rx indcate starting sequence (%#X)!!\n", StartSeqNum));
+ }
+ }
+ //RT_TRACE(COMP_QOS, DBG_LOUD, ("OnBAReq(): BARAckPolicy=%d, MultiTID=%d, CompressedBitmap=%#X, GCR=%d, TIDInfo=%d, StartSeqNum=%#X\n",
+ // BARAckPolicy, MultiTID, CompressedBitmap, GCR, TIDInfo, StartSeqNum));
+ }
+ else if(BARType == BAR_TYPE_MULTI_TID_BAR)
+ {
+ RT_TRACE(COMP_QOS, DBG_LOUD, ("OnBAReq(): Multi-TID BAR is not supported now!!\n"));
+ }
+
+ //RT_PRINT_DATA(COMP_QOS, DBG_LOUD, "OnBAReq() Frame:\n", ospdu.Octet, ospdu.Length);
+
+ return RT_STATUS_SUCCESS;
+}