Home | History | Annotate | Download | only in FW_Transfer
      1 /*
      2  * txResult.c
      3  *
      4  * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  *
     11  *  * Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *  * Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in
     15  *    the documentation and/or other materials provided with the
     16  *    distribution.
     17  *  * Neither the name Texas Instruments nor the names of its
     18  *    contributors may be used to endorse or promote products derived
     19  *    from this software without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     24  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     25  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     26  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     27  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     32  */
     33 
     34 
     35 /****************************************************************************
     36  *
     37  *   MODULE:  txResult.c
     38  *
     39  *   PURPOSE:  Handle packets Tx results upon Tx-complete from the FW.
     40  *
     41  *   DESCRIPTION:
     42  *   ============
     43  *      This module is called upon Tx-complete from FW.
     44  *      It retrieves the transmitted packets results from the FW TxResult table and
     45  *        calls the upper layer callback function for each packet with its results.
     46  *
     47  ****************************************************************************/
     48 
     49 #define __FILE_ID__  FILE_ID_107
     50 #include "tidef.h"
     51 #include "osApi.h"
     52 #include "report.h"
     53 #include "TwIf.h"
     54 #include "txCtrlBlk_api.h"
     55 #include "txResult_api.h"
     56 #include "TWDriver.h"
     57 #include "FwEvent_api.h"
     58 
     59 
     60 
     61 #define TX_RESULT_QUEUE_DEPTH_MASK  (TRQ_DEPTH - 1)
     62 
     63 #if (TX_RESULT_QUEUE_DEPTH_MASK & TRQ_DEPTH)
     64     #error  TRQ_DEPTH should be a power of 2 !!
     65 #endif
     66 
     67 
     68 /* Callback function definition for Tx sendPacketComplete */
     69 typedef void (* TSendPacketCompleteCb)(TI_HANDLE hCbObj, TxResultDescriptor_t *pTxResultInfo);
     70 
     71 /* Tx-Result SM states */
     72 typedef enum
     73 {
     74     TX_RESULT_STATE_IDLE,
     75     TX_RESULT_STATE_READING
     76 } ETxResultState;
     77 
     78 /* The host Tx-results counter write transaction structure. */
     79 typedef struct
     80 {
     81     TTxnStruct tTxnStruct;
     82     TI_UINT32  uCounter;
     83 } THostCounterWriteTxn;
     84 
     85 /* The Tx-results counters and table read transaction structure. */
     86 typedef struct
     87 {
     88     TTxnStruct          tTxnStruct;
     89     TxResultInterface_t tTxResultInfo;
     90 } TResultsInfoReadTxn;
     91 
     92 /* The TxResult module object. */
     93 typedef struct
     94 {
     95     TI_HANDLE               hOs;
     96     TI_HANDLE               hReport;
     97     TI_HANDLE               hTwIf;
     98 
     99     TI_UINT32               uTxResultInfoAddr;       /* The HW Tx-Result Table address */
    100     TI_UINT32               uTxResultHostCounterAddr;/* The Tx-Result host counter address in SRAM */
    101     TI_UINT32               uHostResultsCounter;     /* Number of results read by host from queue since FW-init (updated to FW) */
    102     ETxResultState          eState;                  /* Current eState of SM */
    103     TSendPacketCompleteCb   fSendPacketCompleteCb;   /* Tx-Complete callback function */
    104     TI_HANDLE               hSendPacketCompleteHndl; /* Tx-Complete callback function handle */
    105     THostCounterWriteTxn    tHostCounterWriteTxn;    /* The structure used for writing host results counter to FW */
    106     TResultsInfoReadTxn     tResultsInfoReadTxn;     /* The structure used for reading Tx-results counters and table from  FW */
    107 #ifdef TI_DBG
    108     TI_UINT32               uInterruptsCounter;         /* Count number of Tx-results */
    109 #endif
    110 
    111 } TTxResultObj;
    112 
    113 
    114 static void txResult_Restart (TTxResultObj *pTxResult);
    115 static void txResult_HandleNewResults (TTxResultObj *pTxResult);
    116 static void txResult_StateMachine (TI_HANDLE hTxResult);
    117 
    118 
    119 
    120 /****************************************************************************
    121  *                      txResult_Create()
    122  ****************************************************************************
    123  * DESCRIPTION: Create the Tx-Result object
    124  *
    125  * INPUTS:  hOs
    126  *
    127  * OUTPUT:  None
    128  *
    129  * RETURNS: The Created object
    130  ****************************************************************************/
    131 TI_HANDLE txResult_Create(TI_HANDLE hOs)
    132 {
    133     TTxResultObj *pTxResult;
    134 
    135     pTxResult = os_memoryAlloc(hOs, sizeof(TTxResultObj));
    136     if (pTxResult == NULL)
    137         return NULL;
    138 
    139     os_memoryZero(hOs, pTxResult, sizeof(TTxResultObj));
    140 
    141     pTxResult->hOs = hOs;
    142 
    143     return( (TI_HANDLE)pTxResult );
    144 }
    145 
    146 
    147 /****************************************************************************
    148  *                      txResult_Destroy()
    149  ****************************************************************************
    150  * DESCRIPTION: Destroy the Tx-Result object
    151  *
    152  * INPUTS:  hTxResult - The object to free
    153  *
    154  * OUTPUT:  None
    155  *
    156  * RETURNS: TI_OK or TI_NOK
    157  ****************************************************************************/
    158 TI_STATUS txResult_Destroy(TI_HANDLE hTxResult)
    159 {
    160     TTxResultObj *pTxResult = (TTxResultObj *)hTxResult;
    161 
    162     if (pTxResult)
    163         os_memoryFree(pTxResult->hOs, pTxResult, sizeof(TTxResultObj));
    164 
    165     return TI_OK;
    166 }
    167 
    168 
    169 /****************************************************************************
    170  *               txResult_Init()
    171  ****************************************************************************
    172    DESCRIPTION:
    173    ============
    174      Initialize the txResult module.
    175  ****************************************************************************/
    176 TI_STATUS txResult_Init(TI_HANDLE hTxResult, TI_HANDLE hReport, TI_HANDLE hTwIf)
    177 {
    178     TTxResultObj *pTxResult = (TTxResultObj *)hTxResult;
    179     TTxnStruct   *pTxn;
    180 
    181     pTxResult->hReport    = hReport;
    182     pTxResult->hTwIf      = hTwIf;
    183 
    184     /* Prepare Host-Results-Counter write transaction (HwAddr is filled before each transaction) */
    185     pTxn = &pTxResult->tHostCounterWriteTxn.tTxnStruct;
    186     TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
    187     BUILD_TTxnStruct(pTxn, 0, &pTxResult->tHostCounterWriteTxn.uCounter, REGISTER_SIZE, NULL, NULL)
    188 
    189     /* Prepare Tx-Result counter and table read transaction (HwAddr is filled before each transaction) */
    190     pTxn = &pTxResult->tResultsInfoReadTxn.tTxnStruct;
    191     TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_INC_ADDR)
    192     BUILD_TTxnStruct(pTxn,
    193                      0,
    194                      &pTxResult->tResultsInfoReadTxn.tTxResultInfo,
    195                      sizeof(TxResultInterface_t),
    196                      (TTxnDoneCb)txResult_StateMachine,
    197                      hTxResult)
    198 
    199     txResult_Restart (pTxResult);
    200 
    201     return TI_OK;
    202 }
    203 
    204 
    205 /****************************************************************************
    206  *               txResult_Restart()
    207  ****************************************************************************
    208    DESCRIPTION:
    209    ============
    210      Restarts the Tx-Result module.
    211      Called upon init and recovery.
    212      Shouldn't be called upon disconnect, since the FW provides Tx-Complete
    213        for all pending packets in FW!!
    214  ****************************************************************************/
    215 static void txResult_Restart (TTxResultObj *pTxResult)
    216 {
    217 	pTxResult->uHostResultsCounter = 0;
    218     pTxResult->eState = TX_RESULT_STATE_IDLE;
    219 }
    220 
    221 
    222 /****************************************************************************
    223  *                      txResult_setHwInfo()
    224  ****************************************************************************
    225  * DESCRIPTION:
    226  *      Called after the HW configuration upon init or recovery.
    227  *      Store the Tx-result table HW address.
    228  ****************************************************************************/
    229 void  txResult_setHwInfo(TI_HANDLE hTxResult, TDmaParams *pDmaParams)
    230 {
    231     TTxResultObj *pTxResult = (TTxResultObj *)hTxResult;
    232 
    233     pTxResult->uTxResultInfoAddr = (TI_UINT32)(pDmaParams->fwTxResultInterface);
    234 	pTxResult->uTxResultHostCounterAddr = pTxResult->uTxResultInfoAddr +
    235 		TI_FIELD_OFFSET(TxResultControl_t, TxResultHostCounter);
    236 
    237     txResult_Restart (pTxResult);
    238 }
    239 
    240 
    241 /****************************************************************************
    242  *                      txResult_TxCmpltIntrCb()
    243  ****************************************************************************
    244  * DESCRIPTION:
    245  * ============
    246  *  Called upon DATA interrupt from the FW.
    247  *  If new Tx results are available, start handling them.
    248  *
    249  * INPUTS:  hTxResult - the txResult object handle.
    250  *          pFwStatus - The FW status registers read by the FwEvent
    251  *
    252  * OUTPUT:  None
    253  *
    254  * RETURNS: void
    255  ***************************************************************************/
    256 void txResult_TxCmpltIntrCb (TI_HANDLE hTxResult, FwStatus_t *pFwStatus)
    257 {
    258     TTxResultObj   *pTxResult = (TTxResultObj *)hTxResult;
    259     TI_UINT32      uTempCounters;
    260     FwStatCntrs_t  *pFwStatusCounters;
    261 
    262 #ifdef TI_DBG
    263     pTxResult->uInterruptsCounter++;
    264 
    265     if (pTxResult->eState != TX_RESULT_STATE_IDLE)
    266     {
    267         TRACE1(pTxResult->hReport, REPORT_SEVERITY_INFORMATION, ": called in eState %d, so exit\n", pTxResult->eState);
    268         return;
    269     }
    270 #endif
    271 
    272     /* If no new results - exit (may happen since Data interrupt is common to all Tx&Rx events) */
    273     uTempCounters = ENDIAN_HANDLE_LONG(pFwStatus->counters);
    274     pFwStatusCounters = (FwStatCntrs_t *)&uTempCounters;
    275     if (pFwStatusCounters->txResultsCntr == (TI_UINT8)pTxResult->uHostResultsCounter)
    276     {
    277         TRACE0(pTxResult->hReport, REPORT_SEVERITY_INFORMATION, ": No new Tx results\n");
    278         return;
    279     }
    280 
    281     /* Call the SM to handle the new Tx results */
    282     txResult_StateMachine (hTxResult);
    283 }
    284 
    285 
    286 /****************************************************************************
    287  *                      txResult_StateMachine()
    288  ****************************************************************************
    289  * DESCRIPTION:
    290  *
    291  *  The main SM of the module. Called in IDLE eState by txResult_TxCmpltIntrCb() on
    292  *      Data interrupt from the FW.
    293  *  If no new results - exit (may happen since Data interrupt is common to all Tx&Rx events)
    294  *  Read all Tx-Result cyclic table.
    295  *  Go over the new Tx-results and call the upper layer callback function for each packet result.
    296  *  At the end - write the new host counter to the FW.
    297  *
    298  * INPUTS:
    299  *
    300  * OUTPUT:
    301  *
    302  * RETURNS: None
    303  ****************************************************************************/
    304 static void txResult_StateMachine (TI_HANDLE hTxResult)
    305 {
    306     TTxResultObj *pTxResult  = (TTxResultObj *)hTxResult;
    307 	ETxnStatus   eTwifStatus = TXN_STATUS_COMPLETE;  /* Last bus operation status: Complete (Sync) or Pending (Async). */
    308     TTxnStruct   *pTxn       = &(pTxResult->tResultsInfoReadTxn.tTxnStruct);
    309 
    310     /* Loop while processing is completed in current context (sync), or until fully completed */
    311     while (eTwifStatus == TXN_STATUS_COMPLETE)
    312     {
    313         TRACE2(pTxResult->hReport, REPORT_SEVERITY_INFORMATION, ": eState = %d, eTwifStatus = %d\n", pTxResult->eState, eTwifStatus);
    314 
    315         switch(pTxResult->eState)
    316         {
    317         case TX_RESULT_STATE_IDLE:
    318             /* Read Tx-Result queue and counters. */
    319             pTxn->uHwAddr = pTxResult->uTxResultInfoAddr;
    320             eTwifStatus = twIf_Transact (pTxResult->hTwIf, pTxn);
    321 
    322             pTxResult->eState = TX_RESULT_STATE_READING;
    323             break;
    324 
    325         case TX_RESULT_STATE_READING:
    326             /* Process new Tx results, call upper layers to handle them and update host-index in the FW. */
    327             txResult_HandleNewResults (pTxResult);
    328             pTxResult->eState = TX_RESULT_STATE_IDLE;
    329             return;  /*********  Exit after all processing is finished  **********/
    330 
    331         default:
    332             TRACE1(pTxResult->hReport, REPORT_SEVERITY_ERROR, ": Unknown eState = %d\n", pTxResult->eState);
    333             return;
    334         }
    335     }
    336 
    337     if (eTwifStatus == TXN_STATUS_ERROR)
    338     {
    339         TRACE2(pTxResult->hReport, REPORT_SEVERITY_ERROR, ": returning ERROR in eState %d, eTwifStatus=%d !!!\n", pTxResult->eState, eTwifStatus);
    340     }
    341 }
    342 
    343 
    344 /****************************************************************************
    345  *                      txResult_HandleNewResults()
    346  ****************************************************************************
    347  * DESCRIPTION:
    348  * ============
    349  *	We now have the Tx Result table info from the FW so do as follows:
    350  *	1.	Find the number of new results (FW counter minus host counter), and if 0 exit.
    351  *  2.	Call the upper layers callback per Tx result.
    352  *	3.	Update Host-Counter to be equal to the FW-Counter, and write it to the FW.
    353  ***************************************************************************/
    354 static void txResult_HandleNewResults (TTxResultObj *pTxResult)
    355 {
    356 	TI_UINT32 uNumNewResults;    /* The number of new Tx-Result entries to be processed. */
    357 	TI_UINT32 uFwResultsCounter; /* The FW current results counter (accumulated). */
    358 	TI_UINT32 uTableIndex;
    359 	TI_UINT32 i;
    360 	TxResultDescriptor_t *pCurrentResult;
    361     TTxnStruct *pTxn = &(pTxResult->tHostCounterWriteTxn.tTxnStruct);
    362 
    363 	/* The uFwResultsCounter is the accumulated number of Tx-Results provided by the FW, and the
    364 	 *   uHostResultsCounter is the accumulated number of Tx-Results processed by the host.
    365 	 * The delta is the number of new Tx-results in the queue, waiting for host processing.
    366 	 * Since the difference is always a small positive number, a simple subtraction is good
    367 	 *   also for wrap around case.
    368 	 */
    369 	uFwResultsCounter = ENDIAN_HANDLE_LONG(pTxResult->tResultsInfoReadTxn.tTxResultInfo.TxResultControl.TxResultFwCounter);
    370 	uNumNewResults = uFwResultsCounter - pTxResult->uHostResultsCounter;
    371 
    372 #ifdef TI_DBG
    373 	/* Verify there are new entries (was already checked in txResult_TxCmpltIntrCb) */
    374 	if (uNumNewResults == 0)
    375 	{
    376 TRACE2(pTxResult->hReport, REPORT_SEVERITY_WARNING, ": No New Results although indicated by FwStatus!!  HostCount=%d, FwCount=%d\n", pTxResult->uHostResultsCounter, uFwResultsCounter);
    377 		return;
    378 	}
    379 #endif
    380 
    381 	/* Update host results-counter in FW to be equal to the FW counter (all new results were processed). */
    382 	pTxResult->tHostCounterWriteTxn.uCounter = ENDIAN_HANDLE_LONG(uFwResultsCounter);
    383     pTxn->uHwAddr = pTxResult->uTxResultHostCounterAddr;
    384     twIf_Transact(pTxResult->hTwIf, pTxn);
    385 
    386     TRACE3(pTxResult->hReport, REPORT_SEVERITY_INFORMATION, ": NumResults=%d, OriginalHostCount=%d, FwCount=%d\n", uNumNewResults, pTxResult->uHostResultsCounter, uFwResultsCounter);
    387 
    388 	/* Loop over all new Tx-results and call Tx-complete callback with current entry pointer. */
    389     /* NOTE: THIS SHOULD COME LAST because it may lead to driver-stop process!! */
    390 	for (i = 0; i < uNumNewResults; i++)
    391 	{
    392 		uTableIndex = pTxResult->uHostResultsCounter & TX_RESULT_QUEUE_DEPTH_MASK;
    393 		pCurrentResult = &(pTxResult->tResultsInfoReadTxn.tTxResultInfo.TxResultQueue[uTableIndex]);
    394         pTxResult->uHostResultsCounter++;
    395 
    396         TRACE1(pTxResult->hReport, REPORT_SEVERITY_INFORMATION , ": call upper layer CB, Status = %d\n", pCurrentResult->status);
    397 
    398 		pTxResult->fSendPacketCompleteCb (pTxResult->hSendPacketCompleteHndl, pCurrentResult);
    399 	}
    400 }
    401 
    402 
    403 /****************************************************************************
    404  *                      txResult_RegisterCb()
    405  ****************************************************************************
    406  * DESCRIPTION:  Register the upper driver Tx-Result callback functions.
    407  ****************************************************************************/
    408 void txResult_RegisterCb (TI_HANDLE hTxResult, TI_UINT32 uCallBackId, void *CBFunc, TI_HANDLE hCbObj)
    409 {
    410     TTxResultObj* pTxResult = (TTxResultObj*)hTxResult;
    411 
    412     switch (uCallBackId)
    413     {
    414         /* Set Tx-Complete callback */
    415         case TWD_INT_SEND_PACKET_COMPLETE:
    416             pTxResult->fSendPacketCompleteCb   = (TSendPacketCompleteCb)CBFunc;
    417             pTxResult->hSendPacketCompleteHndl = hCbObj;
    418             break;
    419 
    420         default:
    421             TRACE0(pTxResult->hReport, REPORT_SEVERITY_ERROR, ": Illegal value\n");
    422             return;
    423     }
    424 }
    425 
    426 
    427 #ifdef TI_DBG      /*  Debug Functions   */
    428 
    429 /****************************************************************************
    430  *                      txResult_PrintInfo()
    431  ****************************************************************************
    432  * DESCRIPTION:  Prints TX result debug information.
    433  ****************************************************************************/
    434 void txResult_PrintInfo (TI_HANDLE hTxResult)
    435 {
    436 #ifdef REPORT_LOG
    437     TTxResultObj* pTxResult = (TTxResultObj*)hTxResult;
    438 
    439     WLAN_OS_REPORT(("Tx-Result Module Information:\n"));
    440     WLAN_OS_REPORT(("=============================\n"));
    441     WLAN_OS_REPORT(("uInterruptsCounter:     %d\n", pTxResult->uInterruptsCounter));
    442     WLAN_OS_REPORT(("uHostResultsCounter:    %d\n", pTxResult->uHostResultsCounter));
    443     WLAN_OS_REPORT(("=============================\n"));
    444 #endif
    445 }
    446 
    447 
    448 /****************************************************************************
    449  *                      txResult_ClearInfo()
    450  ****************************************************************************
    451  * DESCRIPTION:  Clears TX result debug information.
    452  ****************************************************************************/
    453 void txResult_ClearInfo (TI_HANDLE hTxResult)
    454 {
    455     TTxResultObj* pTxResult = (TTxResultObj*)hTxResult;
    456 
    457     pTxResult->uInterruptsCounter = 0;
    458 }
    459 
    460 #endif  /* TI_DBG */
    461 
    462 
    463