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;
}
Beispiel #2
0
/*----------------------------------------------------------------------------

  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 */