void WDI_DS_PrepareBDHeader (wpt_packet* palPacket, wpt_uint8 ucDisableHWFrmXtl, wpt_uint8 alignment) { void* pvBDHeader; wpt_uint8 ucHeaderOffset; wpt_uint8 ucHeaderLen; wpt_uint8 ucQosEnabled; wpt_uint8 ucWDSEnabled; wpt_uint32 ucMpduLen; wpt_uint32 ucPktLen; WDI_DS_TxMetaInfoType *pTxMetadata; pvBDHeader = WPAL_PACKET_GET_BD_POINTER(palPacket); pTxMetadata = WDI_DS_ExtractTxMetaData(palPacket); ucQosEnabled = pTxMetadata->qosEnabled; ucWDSEnabled = pTxMetadata->fenableWDS; WPAL_PACKET_SET_BD_LENGTH(palPacket, WDI_TX_BD_HEADER_SIZE); if ( ucDisableHWFrmXtl ) { ucHeaderOffset = WDI_TX_BD_HEADER_SIZE; ucHeaderLen = WDI_802_11_HEADER_LEN; if ( 0 != ucQosEnabled ) { ucHeaderLen += WDI_802_11_HEADER_QOS_CTL; } if ( 0 != ucWDSEnabled) { ucHeaderLen += WDI_802_11_HEADER_ADDR4_LEN; } } else { ucHeaderOffset = WDI_TX_BD_HEADER_SIZE+WDI_802_11_MAX_HEADER_LEN; ucHeaderLen = WDI_802_3_HEADER_LEN; } WDI_TX_BD_SET_MPDU_HEADER_LEN( pvBDHeader, ucHeaderLen); WDI_TX_BD_SET_MPDU_HEADER_OFFSET( pvBDHeader, ucHeaderOffset); WDI_TX_BD_SET_MPDU_DATA_OFFSET( pvBDHeader, ucHeaderOffset + ucHeaderLen + alignment); ucPktLen = wpalPacketGetLength( palPacket ); ucMpduLen = ucPktLen - WPAL_PACKET_GET_BD_LENGTH( palPacket ); WDI_TX_BD_SET_MPDU_LEN( pvBDHeader, ucMpduLen ); DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WLAN DTI: VALUES ARE HLen=%x Hoff=%x doff=%x len=%x ex=%d", ucHeaderLen, ucHeaderOffset, (ucHeaderOffset + ucHeaderLen + alignment), pTxMetadata->fPktlen, alignment); }
void *WDI_DS_MemPoolAlloc(WDI_DS_BdMemPoolType *memPool, void **pPhysAddress, WDI_ResPoolType wdiResPool) { wpt_uint32 index; void *pVirtAddress; wpt_uint32 maxNumPool; switch(wdiResPool) { case WDI_MGMT_POOL_ID: maxNumPool = WDI_DS_HI_PRI_RES_NUM; break; case WDI_DATA_POOL_ID: maxNumPool = WDI_DS_LO_PRI_RES_NUM; break; default: return NULL; } if(maxNumPool == memPool->numChunks) { return NULL; } //Find the leading 0 in the allocation bitmap if((index = find_leading_zero_and_setbit(memPool->AllocationBitmap, maxNumPool)) == -EPERM) { //DbgBreakPoint(); DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WDI_DS_MemPoolAlloc: index:%d(NULL), numChunks:%d", index, memPool->numChunks ); return NULL; } memPool->numChunks++; // The first 8 bytes are reserved for internal use for control bits and hash. pVirtAddress = (wpt_uint8 *)memPool->pVirtBaseAddress + (memPool->chunkSize * index) + 8; *pPhysAddress = (wpt_uint8 *)memPool->pPhysBaseAddress + (memPool->chunkSize * index) + 8; DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WDI_DS_MemPoolAlloc: index:%d, numChunks:%d", index, memPool->numChunks ); return pVirtAddress; }
void *WDI_DS_MemPoolAlloc(WDI_DS_BdMemPoolType *memPool, void **pPhysAddress, WDI_ResPoolType wdiResPool) { wpt_uint32 index; void *pVirtAddress; wpt_uint32 maxNumPool; switch(wdiResPool) { case WDI_MGMT_POOL_ID: maxNumPool = WDI_DS_HI_PRI_RES_NUM; break; case WDI_DATA_POOL_ID: maxNumPool = WDI_DS_LO_PRI_RES_NUM; break; default: return NULL; } if(maxNumPool == memPool->numChunks) { return NULL; } if((index = find_leading_zero_and_setbit(memPool->AllocationBitmap, maxNumPool)) == -EPERM) { DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WDI_DS_MemPoolAlloc: index:%d(NULL), numChunks:%d", index, memPool->numChunks ); return NULL; } memPool->numChunks++; pVirtAddress = (wpt_uint8 *)memPool->pVirtBaseAddress + (memPool->chunkSize * index) + 8; *pPhysAddress = (wpt_uint8 *)memPool->pPhysBaseAddress + (memPool->chunkSize * index) + 8; DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WDI_DS_MemPoolAlloc: index:%d, numChunks:%d", index, memPool->numChunks ); return pVirtAddress; }
/* DTS open function. * On open the transport device should initialize itself. * Parameters: * pContext:Cookie that should be passed back to the caller along * with the callback. * * Return Value: SUCCESS Completed successfully. * FAILURE_XXX Request was rejected due XXX Reason. * */ wpt_status WDTS_openTransport( void *pContext) { void *pDTDriverContext; WDI_DS_ClientDataType *pClientData; WDI_Status sWdiStatus = WDI_STATUS_SUCCESS; WDTS_ClientCallbacks WDTSCb; pClientData = (WDI_DS_ClientDataType*) wpalMemoryAllocate(sizeof(WDI_DS_ClientDataType)); if (!pClientData){ return eWLAN_PAL_STATUS_E_NOMEM; } pClientData->suspend = 0; WDI_DS_AssignDatapathContext(pContext, (void*)pClientData); pDTDriverContext = gTransportDriver.open(); if( NULL == pDTDriverContext ) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, " %s fail from transport open", __func__); return eWLAN_PAL_STATUS_E_FAILURE; } WDT_AssignTransportDriverContext(pContext, pDTDriverContext); WDTSCb.rxFrameReadyCB = WDTS_RxPacket; WDTSCb.txCompleteCB = WDTS_TxPacketComplete; WDTSCb.lowResourceCB = WDTS_OOResourceNotification; WDTSCb.receiveMbMsgCB = WDTS_MbReceiveMsg; WDTSCb.receiveLogCompleteCB = WDTS_LogRxDone; gTransportDriver.register_client(pDTDriverContext, WDTSCb, (void*)pClientData); /* Create a memory pool for Mgmt BDheaders.*/ sWdiStatus = WDI_DS_MemPoolCreate(&pClientData->mgmtMemPool, WDI_DS_MAX_CHUNK_SIZE, WDI_DS_HI_PRI_RES_NUM); if (WDI_STATUS_SUCCESS != sWdiStatus){ return eWLAN_PAL_STATUS_E_NOMEM; } /* Create a memory pool for Data BDheaders.*/ sWdiStatus = WDI_DS_MemPoolCreate(&pClientData->dataMemPool, WDI_DS_MAX_CHUNK_SIZE, WDI_DS_LO_PRI_RES_NUM); if (WDI_STATUS_SUCCESS != sWdiStatus){ return eWLAN_PAL_STATUS_E_NOMEM; } wpalMemoryZero(&gDsTrafficStats, sizeof(gDsTrafficStats)); WDI_DS_LoggingMbCreate(&pClientData->loggingMbContext, sizeof(tLoggingMailBox)); if (WDI_STATUS_SUCCESS != sWdiStatus) return eWLAN_PAL_STATUS_E_NOMEM; return eWLAN_PAL_STATUS_SUCCESS; }
/* API to fill Rate Info based on the mac efficiency passed to it * macEff si used to caclulate mac throughput based on each rate index/PHY rate. * This is eventually used by MAS to calculate RX stats periodically sent to FW * The start and end Rate Index are the other arguments to this API - the new mac * efficiency passed to this API (Arg1) is only applied between startRateIndex (arg2) and endRateIndex (arg3). */ void WDTS_FillRateInfo(wpt_uint8 macEff, wpt_int16 startRateIndex, wpt_int16 endRateIndex) { int i; DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "Change only 11ac rates\n"); for (i=startRateIndex; i<=endRateIndex; i++) { // tputRate --> unit in Mega bits per sec X 10 gRateInfo[i].tputRate = ((gRateInfo[i].phyRate * macEff)/100); // tputBmps --> unit in Bytes per msec = (tputRateX1024x1024)/(8x10X1000) ~= (tputRate*13) gRateInfo[i].tputBpms = gRateInfo[i].tputRate * MB_PER_SEC_TO_BYTES_PER_MSEC; // tputBpus --> unit in Bytes per usec: (+ 500) to round off to integral value gRateInfo[i].tputBpus = ((gRateInfo[i].tputBpms + 500) / 1000); if (gRateInfo[i].tputBpus == 0) gRateInfo[i].tputBpus = 1; DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "%4u, %4u, %5u, %2u", gRateInfo[i].phyRate, gRateInfo[i].tputRate, gRateInfo[i].tputBpms, gRateInfo[i].tputBpus ); } }
/** @brief Decrease reserved TX resource count by specific STA @param pMemPool: pointer to the BD memory pool @param staId STA ID @see @return Result of the function call */ void WDI_DS_MemPoolDecreaseReserveCount(WDI_DS_BdMemPoolType *memPool, wpt_uint8 staId) { if(0 == memPool->numChunkSTA[staId].numChunkReservedBySTA) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, "SAT %d reserved resource count cannot be smaller than 0", staId ); return; } if((memPool->numChunkSTA[staId].validIdx) && (staId < WDI_DS_MAX_STA_ID)) { memPool->numChunkSTA[staId].numChunkReservedBySTA--; } return; }
/* DTS open function. * On open the transport device should initialize itself. * Parameters: * pContext:Cookie that should be passed back to the caller along * with the callback. * * Return Value: SUCCESS Completed successfully. * FAILURE_XXX Request was rejected due XXX Reason. * */ wpt_status WDTS_openTransport( void *pContext) { void *pDTDriverContext; WDI_DS_ClientDataType *pClientData; WDI_Status sWdiStatus = WDI_STATUS_SUCCESS; pClientData = (WDI_DS_ClientDataType*) wpalMemoryAllocate(sizeof(WDI_DS_ClientDataType)); if (!pClientData){ return eWLAN_PAL_STATUS_E_NOMEM; } pClientData->suspend = 0; WDI_DS_AssignDatapathContext(pContext, (void*)pClientData); pDTDriverContext = gTransportDriver.open(); if( NULL == pDTDriverContext ) { DTI_TRACE( DTI_TRACE_LEVEL_ERROR, " %s fail from transport open", __FUNCTION__); return eWLAN_PAL_STATUS_E_FAILURE; } WDT_AssignTransportDriverContext(pContext, pDTDriverContext); gTransportDriver.register_client(pDTDriverContext, WDTS_RxPacket, WDTS_TxPacketComplete, WDTS_OOResourceNotification, (void*)pClientData); /* Create a memory pool for Mgmt BDheaders.*/ sWdiStatus = WDI_DS_MemPoolCreate(&pClientData->mgmtMemPool, WDI_DS_MAX_CHUNK_SIZE, WDI_DS_HI_PRI_RES_NUM); if (WDI_STATUS_SUCCESS != sWdiStatus){ return eWLAN_PAL_STATUS_E_NOMEM; } /* Create a memory pool for Data BDheaders.*/ sWdiStatus = WDI_DS_MemPoolCreate(&pClientData->dataMemPool, WDI_DS_MAX_CHUNK_SIZE, WDI_DS_LO_PRI_RES_NUM); if (WDI_STATUS_SUCCESS != sWdiStatus){ return eWLAN_PAL_STATUS_E_NOMEM; } 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); /* 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; }
/*========================================================================== * FUNCTION WDI_DS_PrepareBDHeader DESCRIPTION function for preparing BD header before HAL processing. PARAMETERS IN palPacket: PAL packet pointer RETURN VALUE No return. SIDE EFFECTS ============================================================================*/ void WDI_DS_PrepareBDHeader (wpt_packet* palPacket, wpt_uint8 ucDisableHWFrmXtl, wpt_uint8 alignment) { void* pvBDHeader; wpt_uint8 ucHeaderOffset; wpt_uint8 ucHeaderLen; wpt_uint8 ucQosEnabled; wpt_uint8 ucWDSEnabled; wpt_uint32 ucMpduLen; wpt_uint32 ucPktLen; WDI_DS_TxMetaInfoType *pTxMetadata; /* Extract reuqired information from Metadata */ pvBDHeader = WPAL_PACKET_GET_BD_POINTER(palPacket); pTxMetadata = WDI_DS_ExtractTxMetaData(palPacket); ucQosEnabled = pTxMetadata->qosEnabled; ucWDSEnabled = pTxMetadata->fenableWDS; WPAL_PACKET_SET_BD_LENGTH(palPacket, WDI_TX_BD_HEADER_SIZE); /*--------------------------------------------------------------------- Fill MPDU info fields: - MPDU data start offset - MPDU header start offset - MPDU header length - MPDU length - this is a 16b field - needs swapping --------------------------------------------------------------------*/ if ( ucDisableHWFrmXtl ) { ucHeaderOffset = WDI_TX_BD_HEADER_SIZE; ucHeaderLen = WDI_802_11_HEADER_LEN; if ( 0 != ucQosEnabled ) { ucHeaderLen += WDI_802_11_HEADER_QOS_CTL; } if ( 0 != ucWDSEnabled) { ucHeaderLen += WDI_802_11_HEADER_ADDR4_LEN; } } else { ucHeaderOffset = WDI_TX_BD_HEADER_SIZE+WDI_802_11_MAX_HEADER_LEN; ucHeaderLen = WDI_802_3_HEADER_LEN; } WDI_TX_BD_SET_MPDU_HEADER_LEN( pvBDHeader, ucHeaderLen); WDI_TX_BD_SET_MPDU_HEADER_OFFSET( pvBDHeader, ucHeaderOffset); WDI_TX_BD_SET_MPDU_DATA_OFFSET( pvBDHeader, ucHeaderOffset + ucHeaderLen + alignment); // pkt length from PAL API. Need to change in case of HW FT used ucPktLen = wpalPacketGetLength( palPacket ); // This includes BD length /** This is the length (in number of bytes) of the entire MPDU (header and data). Note that the length INCLUDES FCS field. */ ucMpduLen = ucPktLen - WPAL_PACKET_GET_BD_LENGTH( palPacket ); WDI_TX_BD_SET_MPDU_LEN( pvBDHeader, ucMpduLen ); DTI_TRACE( DTI_TRACE_LEVEL_INFO, "WLAN DTI: VALUES ARE HLen=%x Hoff=%x doff=%x len=%x ex=%d", ucHeaderLen, ucHeaderOffset, (ucHeaderOffset + ucHeaderLen + alignment), pTxMetadata->fPktlen, alignment); }/* WDI_DS_PrepareBDHeader */
/* 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; }