VOS_STATUS WDA_DS_TxFrames ( v_PVOID_t pvosGCtx ) { VOS_STATUS vosStatus; vos_pkt_t *pTxMgmtChain = NULL; vos_pkt_t *pTxDataChain = NULL; vos_pkt_t *pTxPacket = NULL; v_BOOL_t bUrgent; wpt_uint32 ucTxResReq; WDI_Status wdiStatus; tWDA_CbContext *wdaContext = NULL; v_U32_t uMgmtAvailRes; v_U32_t uDataAvailRes; WLANTL_TxCompCBType pfnTxComp = NULL; v_U32_t uTxFailCount = 0; wdaContext = (tWDA_CbContext *)vos_get_context(VOS_MODULE_ID_WDA, pvosGCtx); if ( NULL == wdaContext ) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "WDA:Invalid wda context pointer from pvosGCtx on WDA_DS_TxFrames" ); return VOS_STATUS_E_FAULT; } /*------------------------------------------------------------------------- Need to fetch separatelly for Mgmt and Data frames because TL is not aware of separate resource management at the lower levels -------------------------------------------------------------------------*/ /*Mgmt tx*/ uMgmtAvailRes = WDI_GetAvailableResCount(wdaContext->pWdiContext, WDI_MGMT_POOL_ID); ucTxResReq = WLANTL_GetFrames( pvosGCtx, &pTxMgmtChain, uMgmtAvailRes, (wdaContext->uTxFlowMask & WDA_HI_FLOW_MASK), &bUrgent ); // We need to initialize vsoStatus in case we don't enter the "while" // loop. If we don't enter the loop, it means that there are no packets, // available, and that is considered success. If we enter the loop, // vosStatus will be set appropriately inside the loop vosStatus = VOS_STATUS_SUCCESS; while ( NULL != pTxMgmtChain ) { /* Walk the chain and unchain the packet */ pTxPacket = pTxMgmtChain; vosStatus = vos_pkt_walk_packet_chain( pTxMgmtChain, &pTxMgmtChain, VOS_TRUE ); if( (VOS_STATUS_SUCCESS != vosStatus) && (VOS_STATUS_E_EMPTY != vosStatus) ) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "WDA Walking packet chain returned status : %d", vosStatus ); VOS_ASSERT( 0 ); vosStatus = VOS_STATUS_E_FAILURE; break; } if ( VOS_STATUS_E_EMPTY == vosStatus ) { vosStatus = VOS_STATUS_SUCCESS; } wdiStatus = WDI_DS_TxPacket( wdaContext->pWdiContext, (wpt_packet*)pTxPacket, 0 /* more */ ); if ( WDI_STATUS_SUCCESS != wdiStatus ) { VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, "WDA : Pushing a packet to WDI failed." ); if ( WDI_STATUS_E_NOT_ALLOWED != wdiStatus ) { uTxFailCount++; } VOS_ASSERT( wdiStatus == WDI_STATUS_E_NOT_ALLOWED ); //We need to free the packet here vos_pkt_get_user_data_ptr(pTxPacket, VOS_PKT_USER_DATA_ID_TL, (void **)&pfnTxComp); if(pfnTxComp) { pfnTxComp(pvosGCtx, pTxPacket, VOS_STATUS_E_FAILURE); } } }; if ( uTxFailCount ) { VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WDA : Tx fail count for mgmt pkts: %d.", uTxFailCount); uTxFailCount = 0; } /*Data tx*/ uDataAvailRes = WDI_GetAvailableResCount(wdaContext->pWdiContext, WDI_DATA_POOL_ID); ucTxResReq = WLANTL_GetFrames( pvosGCtx, &pTxDataChain, /*WDA_DS_DXE_RES_COUNT*/ uDataAvailRes, (wdaContext->uTxFlowMask & WDA_LO_FLOW_MASK), &bUrgent ); // We need to initialize vsoStatus in case we don't enter the "while" // loop. If we don't enter the loop, it means that there are no packets, // available, and that is considered success. If we enter the loop, // vosStatus will be set appropriately inside the loop vosStatus = VOS_STATUS_SUCCESS; while ( NULL != pTxDataChain ) { /* Walk the chain and unchain the packet */ pTxPacket = pTxDataChain; vosStatus = vos_pkt_walk_packet_chain( pTxDataChain, &pTxDataChain, VOS_TRUE ); if( (VOS_STATUS_SUCCESS != vosStatus) && (VOS_STATUS_E_EMPTY != vosStatus) ) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "WDA Walking packet chain returned status : %d", vosStatus ); VOS_ASSERT( 0 ); vosStatus = VOS_STATUS_E_FAILURE; break; } if ( VOS_STATUS_E_EMPTY == vosStatus ) { vosStatus = VOS_STATUS_SUCCESS; } wdiStatus = WDI_DS_TxPacket( wdaContext->pWdiContext, (wpt_packet*)pTxPacket, 0 /* more */ ); if ( WDI_STATUS_SUCCESS != wdiStatus ) { VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, "WDA : Pushing a packet to WDI failed." ); if ( WDI_STATUS_E_NOT_ALLOWED != wdiStatus ) { uTxFailCount++; } VOS_ASSERT( wdiStatus == WDI_STATUS_E_NOT_ALLOWED ); //We need to free the packet here vos_pkt_get_user_data_ptr(pTxPacket, VOS_PKT_USER_DATA_ID_TL, (void **)&pfnTxComp); if(pfnTxComp) { pfnTxComp(pvosGCtx, pTxPacket, VOS_STATUS_E_FAILURE); } } }; if ( uTxFailCount ) { VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WDA : Tx fail count for data pkts: %d.", uTxFailCount); } WDI_DS_TxComplete(wdaContext->pWdiContext, ucTxResReq); return vosStatus; }
/*---------------------------------------------------------------------------- FUNCTION WLANBAP_TxCompCB DESCRIPTION The tx complete callback registered with TL. TL will call this to notify the client when a transmission for a packet has ended. PARAMETERS IN pvosGCtx: pointer to the global vos context; a handle to TL/HAL/PE/BAP/HDD control block can be extracted from its context vosDataBuff: pointer to the VOSS data buffer that was transmitted wTxSTAtus: status of the transmission RETURN VALUE The result code associated with performing the operation ----------------------------------------------------------------------------*/ VOS_STATUS WLANBAP_TxCompCB ( v_PVOID_t pvosGCtx, vos_pkt_t* vosDataBuff, VOS_STATUS wTxSTAtus ) { VOS_STATUS vosStatus; ptBtampHandle bapHdl; /* holds ptBtampHandle value returned */ ptBtampContext bapContext; /* Holds the btampContext value returned */ v_PVOID_t pHddHdl; /* Handle to return BSL context in */ v_PVOID_t pvlogLinkHandle = NULL; v_U32_t value; WLANBAP_HCIACLHeaderType hciACLHeader; /* retrieve the BSL and BAP contexts */ /* I don't really know how to do this - in the general case. */ /* So, for now, I will just use something that works. */ /* (In general, I will have to keep a list of the outstanding transmit */ /* buffers, in order to determine which assoc they are with.) */ //vosStatus = WLANBAP_GetCtxFromStaId ( // ucSTAId, /* The StaId (used by TL, PE, and HAL) */ // &bapHdl, /* "handle" to return ptBtampHandle value in */ // &bapContext, /* "handle" to return ptBtampContext value in */ // &pHddHdl); /* "handle" to return BSL context in */ /* Temporarily we do the following*/ //bapHdl = &btampCtx; bapHdl = (v_PVOID_t)gpBtampCtx; /* Typecast the handle into a context. Works as we have only one link*/ bapContext = ((ptBtampContext) bapHdl); /*------------------------------------------------------------------------ Sanity check params ------------------------------------------------------------------------*/ if ( NULL == vosDataBuff) { VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Invalid vosDataBuff value in %s", __FUNCTION__); return VOS_STATUS_E_FAULT; } if ( NULL == bapContext) { VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Invalid bapContext value in %s", __FUNCTION__); vos_pkt_return_packet( vosDataBuff ); return VOS_STATUS_E_FAULT; } pHddHdl = bapContext->pHddHdl; vosStatus = VOS_STATUS_SUCCESS; if ( VOS_STATUS_SUCCESS != vosStatus ) { VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, "Unable to retrieve BSL or BAP context from STA Id in WLANBAP_TxCompCB"); vos_pkt_return_packet( vosDataBuff ); return VOS_STATUS_E_FAULT; } /*Get the logical link handle from the vos user data*/ vos_pkt_get_user_data_ptr( vosDataBuff, VOS_PKT_USER_DATA_ID_BAP, &pvlogLinkHandle); value = (v_U32_t)pvlogLinkHandle; hciACLHeader.logLinkHandle = value; #ifdef BAP_DEBUG /* Trace the bapContext referenced. */ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "WLAN BAP Context Monitor: bapContext value = %p in %s:%d. vosDataBuff=%p", bapContext, __FUNCTION__, __LINE__, vosDataBuff ); #endif //BAP_DEBUG // Sanity check the log_link_handle value // JEZ100722: Temporary changes. if (BTAMP_VALID_LOG_LINK( hciACLHeader.logLinkHandle)) { vos_atomic_increment_U32( &bapContext->btampLogLinkCtx[hciACLHeader.logLinkHandle].uTxPktCompleted); // &bapContext->btampLogLinkCtx[0].uTxPktCompleted); // vos_atomic_increment_U32( // &bapContext->btampLogLinkCtx[1].uTxPktCompleted); } else { VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "In %s:%d: Invalid logical link handle: %d", __FUNCTION__, __LINE__, hciACLHeader.logLinkHandle); } /* Invoke the callback that BSL registered with me */ vosStatus = (*bapContext->pfnBtampTxCompCB)( pHddHdl, vosDataBuff, wTxSTAtus); return vosStatus; } /* WLANBAP_TxCompCB */