/* DTS Rx packet function. * This function should be invoked by the transport device to indicate * reception of a frame. * Parameters: * pContext:Cookie that should be passed back to the caller * pFrame:Refernce to PAL frame. * Return Value: SUCCESS Completed successfully. * FAILURE_XXX Request was rejected due XXX Reason. * */ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType channel) { WDI_DS_ClientDataType *pClientData = (WDI_DS_ClientDataType*)(pContext); wpt_boolean bASF, bFSF, bLSF, bAEF; wpt_uint8 ucMPDUHOffset, ucMPDUHLen, ucTid; wpt_uint8 *pBDHeader; wpt_uint16 usMPDUDOffset, usMPDULen; WDI_DS_RxMetaInfoType *pRxMetadata; wpt_uint8 isFcBd = 0; tpSirMacFrameCtl pMacFrameCtl; // Do Sanity checks if(NULL == pContext || NULL == pFrame){ return eWLAN_PAL_STATUS_E_FAILURE; } /*------------------------------------------------------------------------ Extract BD header and check if valid ------------------------------------------------------------------------*/ pBDHeader = (wpt_uint8*)wpalPacketGetRawBuf(pFrame); if(NULL == pBDHeader) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "WLAN TL:BD header received NULL - dropping packet"); wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_E_FAILURE; } WDI_SwapRxBd(pBDHeader); ucMPDUHOffset = (wpt_uint8)WDI_RX_BD_GET_MPDU_H_OFFSET(pBDHeader); usMPDUDOffset = (wpt_uint16)WDI_RX_BD_GET_MPDU_D_OFFSET(pBDHeader); usMPDULen = (wpt_uint16)WDI_RX_BD_GET_MPDU_LEN(pBDHeader); ucMPDUHLen = (wpt_uint8)WDI_RX_BD_GET_MPDU_H_LEN(pBDHeader); ucTid = (wpt_uint8)WDI_RX_BD_GET_TID(pBDHeader); /* If RX thread drain small size of frame from HW too fast * Sometimes HW cannot handle interrupt fast enough * And system crash might happen * To avoid system crash, input 1usec delay each frame draining * within host side, if frame size is smaller that threshold. * This is SW work around, to fix HW problem * Throughput and SnS test done successfully */ if (usMPDULen < DTS_RX_DELAY_FRAMESIZE_THRESHOLD) { wpalBusyWait(1); } /*------------------------------------------------------------------------ Gather AMSDU information ------------------------------------------------------------------------*/ bASF = WDI_RX_BD_GET_ASF(pBDHeader); bAEF = WDI_RX_BD_GET_AEF(pBDHeader); bFSF = WDI_RX_BD_GET_ESF(pBDHeader); bLSF = WDI_RX_BD_GET_LSF(pBDHeader); isFcBd = WDI_RX_FC_BD_GET_FC(pBDHeader); DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WLAN TL:BD header processing data: HO %d DO %d Len %d HLen %d" " Tid %d BD %d", ucMPDUHOffset, usMPDUDOffset, usMPDULen, ucMPDUHLen, ucTid, WDI_RX_BD_HEADER_SIZE); if(!isFcBd) { if(usMPDUDOffset <= ucMPDUHOffset || usMPDULen < ucMPDUHLen) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "WLAN TL:BD header corrupted - dropping packet"); /* Drop packet ???? */ wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } if((ucMPDUHOffset < WDI_RX_BD_HEADER_SIZE) && (!(bASF && !bFSF))){ /* AMSDU case, ucMPDUHOffset = 0 it should be hancdled seperatly */ /* Drop packet ???? */ wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } /* AMSDU frame, but not first sub-frame * No MPDU header, MPDU header offset is 0 * Total frame size is actual frame size + MPDU data offset */ if((ucMPDUHOffset < WDI_RX_BD_HEADER_SIZE) && (bASF && !bFSF)){ ucMPDUHOffset = usMPDUDOffset; } if(VPKT_SIZE_BUFFER < (usMPDULen+ucMPDUHOffset)){ DTI_TRACE( DTI_TRACE_LEVEL_FATAL, "Invalid Frame size, might memory corrupted"); /* Size of the packet tranferred by the DMA engine is * greater than the the memory allocated for the skb */ WPAL_BUG(0); wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } if(eWLAN_PAL_STATUS_SUCCESS != wpalPacketSetRxLength(pFrame, usMPDULen+ucMPDUHOffset)) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "Invalid Frame Length, Frame dropped.."); wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } if(eWLAN_PAL_STATUS_SUCCESS != wpalPacketRawTrimHead(pFrame, ucMPDUHOffset)) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "Failed to trim Raw Packet Head, Frame dropped.."); wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } pRxMetadata = WDI_DS_ExtractRxMetaData(pFrame); pRxMetadata->fc = isFcBd; pRxMetadata->staId = WDI_RX_BD_GET_STA_ID(pBDHeader); pRxMetadata->addr3Idx = WDI_RX_BD_GET_ADDR3_IDX(pBDHeader); pRxMetadata->rxChannel = WDI_RX_BD_GET_RX_CHANNEL(pBDHeader); pRxMetadata->rfBand = WDI_RX_BD_GET_RFBAND(pBDHeader); pRxMetadata->rtsf = WDI_RX_BD_GET_RTSF(pBDHeader); pRxMetadata->bsf = WDI_RX_BD_GET_BSF(pBDHeader); pRxMetadata->scan = WDI_RX_BD_GET_SCAN(pBDHeader); pRxMetadata->dpuSig = WDI_RX_BD_GET_DPU_SIG(pBDHeader); pRxMetadata->ft = WDI_RX_BD_GET_FT(pBDHeader); pRxMetadata->ne = WDI_RX_BD_GET_NE(pBDHeader); pRxMetadata->llcr = WDI_RX_BD_GET_LLCR(pBDHeader); pRxMetadata->bcast = WDI_RX_BD_GET_UB(pBDHeader); pRxMetadata->tid = ucTid; pRxMetadata->dpuFeedback = WDI_RX_BD_GET_DPU_FEEDBACK(pBDHeader); pRxMetadata->rateIndex = WDI_RX_BD_GET_RATEINDEX(pBDHeader); pRxMetadata->rxpFlags = WDI_RX_BD_GET_RXPFLAGS(pBDHeader); pRxMetadata->mclkRxTimestamp = WDI_RX_BD_GET_TIMESTAMP(pBDHeader); #ifdef WLAN_FEATURE_11W pRxMetadata->rmf = WDI_RX_BD_GET_RMF(pBDHeader); #endif #ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD pRxMetadata->offloadScanLearn = WDI_RX_BD_GET_OFFLOADSCANLEARN(pBDHeader); pRxMetadata->roamCandidateInd = WDI_RX_BD_GET_ROAMCANDIDATEIND(pBDHeader); #endif /* typeSubtype in BD doesn't look like correct. Fill from frame ctrl TL does it for Volans but TL does not know BD for Prima. WDI should do it */ if ( 0 == WDI_RX_BD_GET_FT(pBDHeader) ) { if ( bASF ) { pRxMetadata->subtype = WDI_MAC_DATA_QOS_DATA; pRxMetadata->type = WDI_MAC_DATA_FRAME; } else { pMacFrameCtl = (tpSirMacFrameCtl)(((wpt_uint8*)pBDHeader) + ucMPDUHOffset); pRxMetadata->subtype = pMacFrameCtl->subType; pRxMetadata->type = pMacFrameCtl->type; } } else { pMacFrameCtl = (tpSirMacFrameCtl)(((wpt_uint8*)pBDHeader) + WDI_RX_BD_HEADER_SIZE); pRxMetadata->subtype = pMacFrameCtl->subType; pRxMetadata->type = pMacFrameCtl->type; } pRxMetadata->mpduHeaderPtr = pBDHeader + ucMPDUHOffset; pRxMetadata->mpduDataPtr = pBDHeader + usMPDUDOffset; pRxMetadata->mpduLength = usMPDULen; pRxMetadata->mpduHeaderLength = ucMPDUHLen; /*------------------------------------------------------------------------ Gather AMPDU information ------------------------------------------------------------------------*/ pRxMetadata->ampdu_reorderOpcode = (wpt_uint8)WDI_RX_BD_GET_BA_OPCODE(pBDHeader); pRxMetadata->ampdu_reorderSlotIdx = (wpt_uint8)WDI_RX_BD_GET_BA_SI(pBDHeader); pRxMetadata->ampdu_reorderFwdIdx = (wpt_uint8)WDI_RX_BD_GET_BA_FI(pBDHeader); pRxMetadata->currentPktSeqNo = (wpt_uint16)WDI_RX_BD_GET_BA_CSN(pBDHeader); /*------------------------------------------------------------------------ Gather AMSDU information ------------------------------------------------------------------------*/ pRxMetadata->amsdu_asf = bASF; pRxMetadata->amsdu_aef = bAEF; pRxMetadata->amsdu_esf = bFSF; pRxMetadata->amsdu_lsf = bLSF; pRxMetadata->amsdu_size = WDI_RX_BD_GET_AMSDU_SIZE(pBDHeader); pRxMetadata->rssi0 = WDI_RX_BD_GET_RSSI0(pBDHeader); pRxMetadata->rssi1 = WDI_RX_BD_GET_RSSI1(pBDHeader); /* Missing: wpt_uint32 fcSTATxQStatus:8; wpt_uint32 fcSTAThreshIndMask:8; wpt_uint32 fcSTAPwrSaveStateMask:8; wpt_uint32 fcSTAValidMask:8; wpt_uint8 fcSTATxQLen[8]; // one byte per STA. wpt_uint8 fcSTACurTxRate[8]; // current Tx rate for each sta. unknownUcastPkt */ pRxMetadata->replayCount = WDTS_GetReplayCounterFromRxBD(pBDHeader); pRxMetadata->snr = WDI_RX_BD_GET_SNR(pBDHeader); /* * PAL BD pointer information needs to be populated */ WPAL_PACKET_SET_BD_POINTER(pFrame, pBDHeader); WPAL_PACKET_SET_BD_LENGTH(pFrame, sizeof(WDI_RxBdType)); // Invoke Rx complete callback pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame); } else { wpalPacketSetRxLength(pFrame, usMPDULen+ucMPDUHOffset); wpalPacketRawTrimHead(pFrame, ucMPDUHOffset); pRxMetadata = WDI_DS_ExtractRxMetaData(pFrame); //flow control related pRxMetadata->fc = isFcBd; pRxMetadata->mclkRxTimestamp = WDI_RX_BD_GET_TIMESTAMP(pBDHeader); pRxMetadata->fcStaTxDisabledBitmap = WDI_RX_FC_BD_GET_STA_TX_DISABLED_BITMAP(pBDHeader); pRxMetadata->fcSTAValidMask = WDI_RX_FC_BD_GET_STA_VALID_MASK(pBDHeader); // Invoke Rx complete callback pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame); } //Log the RX Stats if(gDsTrafficStats.running && pRxMetadata->staId < HAL_NUM_STA) { if(pRxMetadata->rateIndex < WDTS_MAX_RATE_NUM) { if(pRxMetadata->type == WDI_MAC_DATA_FRAME) { gDsTrafficStats.rxStats[pRxMetadata->staId][pRxMetadata->rateIndex].rxBytesRcvd += pRxMetadata->mpduLength; gDsTrafficStats.rxStats[pRxMetadata->staId][pRxMetadata->rateIndex].rxPacketsRcvd++; } } } return eWLAN_PAL_STATUS_SUCCESS; }
/* DTS Rx packet function. * This function should be invoked by the transport device to indicate * reception of a frame. * Parameters: * pContext:Cookie that should be passed back to the caller * pFrame:Refernce to PAL frame. * Return Value: SUCCESS Completed successfully. * FAILURE_XXX Request was rejected due XXX Reason. * */ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType channel) { WDI_DS_ClientDataType *pClientData = (WDI_DS_ClientDataType*)(pContext); wpt_boolean bASF, bFSF, bLSF, bAEF; wpt_uint8 ucMPDUHOffset, ucMPDUHLen, ucTid; wpt_uint8 *pBDHeader; wpt_uint16 usMPDUDOffset, usMPDULen; WDI_DS_RxMetaInfoType *pRxMetadata; wpt_uint8 isFcBd = 0; tpSirMacFrameCtl pMacFrameCtl; // Do Sanity checks if(NULL == pContext || NULL == pFrame){ return eWLAN_PAL_STATUS_E_FAILURE; } /*------------------------------------------------------------------------ Extract BD header and check if valid ------------------------------------------------------------------------*/ pBDHeader = (wpt_uint8*)wpalPacketGetRawBuf(pFrame); if(NULL == pBDHeader) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "WLAN TL:BD header received NULL - dropping packet"); wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_E_FAILURE; } WDI_SwapRxBd(pBDHeader); ucMPDUHOffset = (wpt_uint8)WDI_RX_BD_GET_MPDU_H_OFFSET(pBDHeader); usMPDUDOffset = (wpt_uint16)WDI_RX_BD_GET_MPDU_D_OFFSET(pBDHeader); usMPDULen = (wpt_uint16)WDI_RX_BD_GET_MPDU_LEN(pBDHeader); ucMPDUHLen = (wpt_uint8)WDI_RX_BD_GET_MPDU_H_LEN(pBDHeader); ucTid = (wpt_uint8)WDI_RX_BD_GET_TID(pBDHeader); /*------------------------------------------------------------------------ Gather AMSDU information ------------------------------------------------------------------------*/ bASF = WDI_RX_BD_GET_ASF(pBDHeader); bAEF = WDI_RX_BD_GET_AEF(pBDHeader); bFSF = WDI_RX_BD_GET_ESF(pBDHeader); bLSF = WDI_RX_BD_GET_LSF(pBDHeader); isFcBd = WDI_RX_FC_BD_GET_FC(pBDHeader); DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WLAN TL:BD header processing data: HO %d DO %d Len %d HLen %d" " Tid %d BD %d", ucMPDUHOffset, usMPDUDOffset, usMPDULen, ucMPDUHLen, ucTid, WDI_RX_BD_HEADER_SIZE); if(!isFcBd) { if(usMPDUDOffset <= ucMPDUHOffset || usMPDULen < ucMPDUHLen) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "WLAN TL:BD header corrupted - dropping packet"); /* Drop packet ???? */ wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } if((ucMPDUHOffset < WDI_RX_BD_HEADER_SIZE) && (!(bASF && !bFSF))){ /* AMSDU case, ucMPDUHOffset = 0 it should be hancdled seperatly */ /* Drop packet ???? */ wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } /* AMSDU frame, but not first sub-frame * No MPDU header, MPDU header offset is 0 * Total frame size is actual frame size + MPDU data offset */ if((ucMPDUHOffset < WDI_RX_BD_HEADER_SIZE) && (bASF && !bFSF)){ ucMPDUHOffset = usMPDUDOffset; } if(VPKT_SIZE_BUFFER < (usMPDULen+ucMPDUHOffset)){ DTI_TRACE( DTI_TRACE_LEVEL_FATAL, "Invalid Frame size, might memory corrupted"); wpalPacketFree(pFrame); return eWLAN_PAL_STATUS_SUCCESS; } wpalPacketSetRxLength(pFrame, usMPDULen+ucMPDUHOffset); wpalPacketRawTrimHead(pFrame, ucMPDUHOffset); pRxMetadata = WDI_DS_ExtractRxMetaData(pFrame); pRxMetadata->fc = isFcBd; pRxMetadata->staId = WDI_RX_BD_GET_STA_ID(pBDHeader); pRxMetadata->addr3Idx = WDI_RX_BD_GET_ADDR3_IDX(pBDHeader); pRxMetadata->rxChannel = WDI_RX_BD_GET_RX_CHANNEL(pBDHeader); pRxMetadata->rtsf = WDI_RX_BD_GET_RTSF(pBDHeader); pRxMetadata->bsf = WDI_RX_BD_GET_BSF(pBDHeader); pRxMetadata->scan = WDI_RX_BD_GET_SCAN(pBDHeader); pRxMetadata->dpuSig = WDI_RX_BD_GET_DPU_SIG(pBDHeader); pRxMetadata->ft = WDI_RX_BD_GET_FT(pBDHeader); pRxMetadata->ne = WDI_RX_BD_GET_NE(pBDHeader); pRxMetadata->llcr = WDI_RX_BD_GET_LLCR(pBDHeader); pRxMetadata->bcast = WDI_RX_BD_GET_UB(pBDHeader); pRxMetadata->tid = ucTid; pRxMetadata->dpuFeedback = WDI_RX_BD_GET_DPU_FEEDBACK(pBDHeader); pRxMetadata->rateIndex = WDI_RX_BD_GET_RATEINDEX(pBDHeader); pRxMetadata->rxpFlags = WDI_RX_BD_GET_RXPFLAGS(pBDHeader); pRxMetadata->mclkRxTimestamp = WDI_RX_BD_GET_TIMESTAMP(pBDHeader); /* typeSubtype in BD doesn't look like correct. Fill from frame ctrl TL does it for Volans but TL does not know BD for Prima. WDI should do it */ if ( 0 == WDI_RX_BD_GET_FT(pBDHeader) ) { if ( bASF ) { pRxMetadata->subtype = WDI_MAC_DATA_QOS_DATA; pRxMetadata->type = WDI_MAC_DATA_FRAME; } else { pMacFrameCtl = (tpSirMacFrameCtl)(((wpt_uint8*)pBDHeader) + ucMPDUHOffset); pRxMetadata->subtype = pMacFrameCtl->subType; pRxMetadata->type = pMacFrameCtl->type; } } else { pMacFrameCtl = (tpSirMacFrameCtl)(((wpt_uint8*)pBDHeader) + WDI_RX_BD_HEADER_SIZE); pRxMetadata->subtype = pMacFrameCtl->subType; pRxMetadata->type = pMacFrameCtl->type; } pRxMetadata->mpduHeaderPtr = pBDHeader + ucMPDUHOffset; pRxMetadata->mpduDataPtr = pBDHeader + usMPDUDOffset; pRxMetadata->mpduLength = usMPDULen; pRxMetadata->mpduHeaderLength = ucMPDUHLen; /*------------------------------------------------------------------------ Gather AMPDU information ------------------------------------------------------------------------*/ pRxMetadata->ampdu_reorderOpcode = (wpt_uint8)WDI_RX_BD_GET_BA_OPCODE(pBDHeader); pRxMetadata->ampdu_reorderSlotIdx = (wpt_uint8)WDI_RX_BD_GET_BA_SI(pBDHeader); pRxMetadata->ampdu_reorderFwdIdx = (wpt_uint8)WDI_RX_BD_GET_BA_FI(pBDHeader); pRxMetadata->currentPktSeqNo = (wpt_uint8)WDI_RX_BD_GET_BA_CSN(pBDHeader); /*------------------------------------------------------------------------ Gather AMSDU information ------------------------------------------------------------------------*/ pRxMetadata->amsdu_asf = bASF; pRxMetadata->amsdu_aef = bAEF; pRxMetadata->amsdu_esf = bFSF; pRxMetadata->amsdu_lsf = bLSF; pRxMetadata->amsdu_size = WDI_RX_BD_GET_AMSDU_SIZE(pBDHeader); pRxMetadata->rssi0 = WDI_RX_BD_GET_RSSI0(pBDHeader); pRxMetadata->rssi1 = WDI_RX_BD_GET_RSSI1(pBDHeader); /* Missing: wpt_uint32 fcSTATxQStatus:8; wpt_uint32 fcSTAThreshIndMask:8; wpt_uint32 fcSTAPwrSaveStateMask:8; wpt_uint32 fcSTAValidMask:8; wpt_uint8 fcSTATxQLen[8]; // one byte per STA. wpt_uint8 fcSTACurTxRate[8]; // current Tx rate for each sta. unknownUcastPkt */ pRxMetadata->replayCount = WDTS_GetReplayCounterFromRxBD(pBDHeader); pRxMetadata->snr = WDI_RX_BD_GET_SNR(pBDHeader); /* * PAL BD pointer information needs to be populated */ WPAL_PACKET_SET_BD_POINTER(pFrame, pBDHeader); WPAL_PACKET_SET_BD_LENGTH(pFrame, sizeof(WDI_RxBdType)); // Invoke Rx complete callback pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame); } else { wpalPacketSetRxLength(pFrame, usMPDULen+ucMPDUHOffset); wpalPacketRawTrimHead(pFrame, ucMPDUHOffset); pRxMetadata = WDI_DS_ExtractRxMetaData(pFrame); //flow control related pRxMetadata->fc = isFcBd; pRxMetadata->fcStaTxDisabledBitmap = WDI_RX_FC_BD_GET_STA_TX_DISABLED_BITMAP(pBDHeader); pRxMetadata->fcSTAValidMask = WDI_RX_FC_BD_GET_STA_VALID_MASK(pBDHeader); // Invoke Rx complete callback pClientData->receiveFrameCB(pClientData->pCallbackContext, pFrame); } return eWLAN_PAL_STATUS_SUCCESS; }