Home | History | Annotate | Download | only in FW_Transfer
      1 /*
      2  * RxXfer.c
      3  *
      4  * Copyright(c) 1998 - 2010 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:  rxXfer.c
     38  *
     39  *   PURPOSE: Rx Xfer module implementation.Responsible for reading Rx from the FW
     40  *              and forward it to the upper layers.
     41  *
     42  ****************************************************************************/
     43 
     44 #define __FILE_ID__  FILE_ID_106
     45 #include "tidef.h"
     46 #include "osApi.h"
     47 #include "report.h"
     48 #include "rxXfer_api.h"
     49 #include "FwEvent_api.h"
     50 #include "TWDriverInternal.h"
     51 #include "RxQueue_api.h"
     52 #include "TwIf.h"
     53 #include "public_host_int.h"
     54 #include "bmtrace_api.h"
     55 
     56 #define RX_DRIVER_COUNTER_ADDRESS 0x300538
     57 #define PLCP_HEADER_LENGTH 8
     58 #define WORD_SIZE   4
     59 #define UNALIGNED_PAYLOAD   0x1
     60 #define RX_DESCRIPTOR_SIZE          (sizeof(RxIfDescriptor_t))
     61 #define MAX_PACKETS_NUMBER          8
     62 #define MAX_CONSECUTIVE_READ_TXN    16
     63 #define MAX_PACKET_SIZE             8192    /* Max Txn size */
     64 
     65 #ifdef PLATFORM_SYMBIAN	/* UMAC is using only one buffer and therefore we can't use consecutive reads */
     66     #define MAX_CONSECUTIVE_READS   1
     67 #else
     68     #define MAX_CONSECUTIVE_READS   8
     69 #endif
     70 
     71 #define SLV_MEM_CP_VALUE(desc, offset)  (((RX_DESC_GET_MEM_BLK(desc) << 8) + offset))
     72 #define ALIGNMENT_SIZE(desc)            ((RX_DESC_GET_UNALIGNED(desc) & UNALIGNED_PAYLOAD) ? 2 : 0)
     73 
     74 #if (NUM_RX_PKT_DESC & (NUM_RX_PKT_DESC - 1))
     75     #error  NUM_RX_PKT_DESC is not a power of 2 which may degrade performance when we calculate modulo!!
     76 #endif
     77 
     78 
     79 #ifdef TI_DBG
     80 typedef struct
     81 {
     82     TI_UINT32           uCountFwEvents;
     83     TI_UINT32           uCountPktsForward;
     84     TI_UINT32           uCountBufPend;
     85     TI_UINT32           uCountBufNoMem;
     86     TI_UINT32           uCountPktAggreg[MAX_XFER_BUFS];
     87 
     88 } TRxXferDbgStat;
     89 #endif
     90 
     91 typedef struct
     92 {
     93     TTxnStruct          tTxnStruct;
     94     TI_UINT32           uRegData;
     95     TI_UINT32           uRegAdata;
     96 
     97 } TRegTxn;
     98 
     99 typedef struct
    100 {
    101     TTxnStruct          tTxnStruct;
    102     TI_UINT32           uCounter;
    103 
    104 } TCounterTxn;
    105 
    106 typedef struct
    107 {
    108     TI_HANDLE           hOs;
    109     TI_HANDLE           hReport;
    110     TI_HANDLE           hTwIf;
    111     TI_HANDLE           hFwEvent;
    112     TI_HANDLE           hRxQueue;
    113 
    114     TI_UINT32           aRxPktsDesc[NUM_RX_PKT_DESC];           /* Save Rx packets short descriptors from FwStatus */
    115     TI_UINT32           uFwRxCntr;                              /* Save last FW packets counter from FwStatus */
    116     TI_UINT32           uDrvRxCntr;                             /* The current driver processed packets counter */
    117     TI_UINT32           uPacketMemoryPoolStart;                 /* The FW mem-blocks area base address */
    118     TI_UINT32           uMaxAggregLen;                          /* The max length in bytes of aggregated packets transaction */
    119     TI_UINT32           uMaxAggregPkts;                         /* The max number of packets that may be aggregated in one transaction */
    120     TRequestForBufferCb RequestForBufferCB;                     /* Upper layer CB for allocating buffers for packets */
    121     TI_HANDLE           RequestForBufferCB_handle;              /* The upper later CB handle */
    122     TI_BOOL             bPendingBuffer;                         /* If TRUE, we exited the Rx handler upon pending-buffer */
    123 
    124     TI_UINT32           uCurrTxnIndex;                          /* The current Txn structures index to use */
    125     TI_UINT32           uAvailableTxn;                          /* Number of Txn structures currently available */
    126     TRegTxn             aSlaveRegTxn[MAX_CONSECUTIVE_READ_TXN]; /* Txn structures for writing mem-block address reg */
    127     TTxnStruct          aTxnStruct[MAX_CONSECUTIVE_READ_TXN];   /* Txn structures for reading the Rx packets */
    128     TCounterTxn         aCounterTxn[MAX_CONSECUTIVE_READ_TXN];  /* Txn structures for writing the driver counter workaround */
    129 
    130     TI_UINT8            aTempBuffer[MAX_PACKET_SIZE];           /* Dummy buffer to use if we couldn't get a buffer for the packet (so drop the packet) */
    131     TFailureEventCb     fErrCb;                                 /* The upper layer CB function for error handling */
    132     TI_HANDLE           hErrCb;                                 /* The CB function handle */
    133 
    134 #ifdef TI_DBG
    135     TRxXferDbgStat      tDbgStat;
    136 #endif
    137 
    138 } TRxXfer;
    139 
    140 
    141 /************************ static function declaration *****************************/
    142 static TI_STATUS rxXfer_Handle(TI_HANDLE hRxXfer);
    143 static void rxXfer_TxnDoneCb (TI_HANDLE hRxXfer, TTxnStruct* pTxn);
    144 static void         rxXfer_PktDropTxnDoneCb (TI_HANDLE hRxXfer, TTxnStruct *pTxn);
    145 static ETxnStatus   rxXfer_IssueTxn (TI_HANDLE hRxXfer, TI_UINT32 uFirstMemBlkAddr);
    146 static void         rxXfer_ForwardPacket (TRxXfer* pRxXfer, TTxnStruct* pTxn);
    147 
    148 
    149 /****************************************************************************
    150  *                      RxXfer_Create()
    151  ****************************************************************************
    152  * DESCRIPTION: Create the RxXfer module object
    153  *
    154  * INPUTS:  None
    155  *
    156  * OUTPUT:  None
    157  *
    158  * RETURNS: The Created object
    159  ****************************************************************************/
    160 TI_HANDLE rxXfer_Create (TI_HANDLE hOs)
    161 {
    162     TRxXfer *pRxXfer;
    163 
    164     pRxXfer = os_memoryAlloc (hOs, sizeof(TRxXfer));
    165     if (pRxXfer == NULL)
    166         return NULL;
    167 
    168     /* For all the counters */
    169     os_memoryZero (hOs, pRxXfer, sizeof(TRxXfer));
    170 
    171     pRxXfer->hOs = hOs;
    172 
    173     return (TI_HANDLE)pRxXfer;
    174 }
    175 
    176 
    177 /****************************************************************************
    178  *                      RxXfer_Destroy()
    179  ****************************************************************************
    180  * DESCRIPTION: Destroy the RxXfer module object
    181  *
    182  * INPUTS:  hRxXfer - The object to free
    183  *
    184  * OUTPUT:  None
    185  *
    186  * RETURNS:
    187  ****************************************************************************/
    188 void rxXfer_Destroy (TI_HANDLE hRxXfer)
    189 {
    190     TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    191 
    192     if (pRxXfer)
    193     {
    194         os_memoryFree (pRxXfer->hOs, pRxXfer, sizeof(TRxXfer));
    195     }
    196 }
    197 
    198 
    199 /****************************************************************************
    200  *                      rxXfer_init()
    201  ****************************************************************************
    202  * DESCRIPTION: Init the module object
    203  *
    204  * INPUTS:      hRxXfer - module handle;
    205  *              other modules handles.
    206  *
    207  * OUTPUT:  None
    208  *
    209  * RETURNS: None
    210  ****************************************************************************/
    211 void rxXfer_Init(TI_HANDLE hRxXfer,
    212                  TI_HANDLE hFwEvent,
    213                  TI_HANDLE hReport,
    214                  TI_HANDLE hTwIf,
    215                  TI_HANDLE hRxQueue)
    216 {
    217     TRxXfer *pRxXfer        = (TRxXfer *)hRxXfer;
    218     pRxXfer->hFwEvent       = hFwEvent;
    219     pRxXfer->hReport        = hReport;
    220     pRxXfer->hTwIf          = hTwIf;
    221     pRxXfer->hRxQueue       = hRxQueue;
    222 
    223     rxXfer_Restart (hRxXfer);
    224 
    225 #ifdef TI_DBG
    226     rxXfer_ClearStats (pRxXfer);
    227 #endif
    228 }
    229 
    230 
    231 /****************************************************************************
    232  *                      rxXfer_SetDefaults()
    233  ****************************************************************************
    234  * DESCRIPTION: Set module parameters default setting
    235  *
    236  * INPUTS:      hRxXfer - module handle;
    237  *
    238  * OUTPUT:  None
    239  *
    240  * RETURNS: None
    241  ****************************************************************************/
    242 void rxXfer_SetDefaults (TI_HANDLE hRxXfer, TTwdInitParams *pInitParams)
    243 {
    244     TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    245 
    246     pRxXfer->uMaxAggregPkts = pInitParams->tGeneral.uRxAggregPktsLimit;
    247 }
    248 
    249 
    250 /****************************************************************************
    251  *                      rxXfer_SetBusParams()
    252  ****************************************************************************
    253  * DESCRIPTION: Configure bus driver DMA-able buffer length to be used as a limit to the aggragation length.
    254  *
    255  * INPUTS:      hRxXfer    - module handle
    256  *              uDmaBufLen - The bus driver DMA-able buffer length
    257  *
    258  * OUTPUT:  None
    259  *
    260  * RETURNS: None
    261  ****************************************************************************/
    262 void rxXfer_SetBusParams (TI_HANDLE hRxXfer, TI_UINT32 uDmaBufLen)
    263 {
    264     TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    265 
    266     pRxXfer->uMaxAggregLen = uDmaBufLen;
    267 }
    268 
    269 
    270 /****************************************************************************
    271  *                      rxXfer_Register_CB()
    272  ****************************************************************************
    273  * DESCRIPTION: Register the function to be called for request for buffer.
    274  *
    275  * INPUTS:      hRxXfer       - RxXfer handle;
    276  *
    277  * OUTPUT:  None
    278  *
    279  * RETURNS: None
    280  ****************************************************************************/
    281 void rxXfer_Register_CB (TI_HANDLE hRxXfer, TI_UINT32 CallBackID, void *CBFunc, TI_HANDLE CBObj)
    282 {
    283     TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    284 
    285     TRACE1(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , "rxXfer_Register_CB (Value = 0x%x)\n", CallBackID);
    286 
    287     switch(CallBackID)
    288     {
    289     case TWD_INT_REQUEST_FOR_BUFFER:
    290         pRxXfer->RequestForBufferCB = (TRequestForBufferCb)CBFunc;
    291         pRxXfer->RequestForBufferCB_handle = CBObj;
    292         break;
    293 
    294     default:
    295         TRACE0(pRxXfer->hReport, REPORT_SEVERITY_ERROR, "rxXfer_Register_CB - Illegal value\n");
    296         return;
    297     }
    298 }
    299 
    300 
    301 /****************************************************************************
    302  *                      rxXfer_ForwardPacket()
    303  ****************************************************************************
    304  * DESCRIPTION:  Forward received packet(s) to the upper layers.
    305  *
    306  * INPUTS:
    307  *
    308  * OUTPUT:
    309  *
    310  * RETURNS:
    311  ****************************************************************************/
    312 static void rxXfer_ForwardPacket (TRxXfer *pRxXfer, TTxnStruct *pTxn)
    313 {
    314     TI_UINT32 uBufNum;
    315     RxIfDescriptor_t *pRxInfo  = (RxIfDescriptor_t*)(pTxn->aBuf[0]);
    316 #ifdef TI_DBG   /* for packet sanity check */
    317     TI_UINT16        uLenFromRxInfo;
    318 #endif
    319 
    320     /* Go over all occupied Txn buffers and forward their Rx packets upward */
    321     for (uBufNum = 0; uBufNum < MAX_XFER_BUFS; uBufNum++)
    322     {
    323         /* If no more buffers, exit the loop */
    324         if (pTxn->aLen[uBufNum] == 0)
    325         {
    326             break;
    327         }
    328 
    329 #ifdef TI_DBG   /* Packet sanity check */
    330         /* Get length from RxInfo, handle endianess and convert to length in bytes */
    331         pRxInfo = (RxIfDescriptor_t*)(pTxn->aBuf[uBufNum]);
    332         uLenFromRxInfo = ENDIAN_HANDLE_WORD(pRxInfo->length) << 2;
    333 
    334         /* If the length in the RxInfo is different than in the short descriptor, set error status */
    335         if (pTxn->aLen[uBufNum] != uLenFromRxInfo)
    336         {
    337             TRACE3(pRxXfer->hReport, REPORT_SEVERITY_ERROR , "rxXfer_ForwardPacket: Bad Length!! RxInfoLength=%d, ShortDescLen=%d, RxInfoStatus=0x%x\n", uLenFromRxInfo, pTxn->aLen[uBufNum], pRxInfo->status);
    338 
    339             pRxInfo->status &= ~RX_DESC_STATUS_MASK;
    340             pRxInfo->status |= RX_DESC_STATUS_DRIVER_RX_Q_FAIL;
    341             pRxInfo->length = ENDIAN_HANDLE_WORD(pTxn->aLen[uBufNum] >> 2);
    342 
    343             /* If error CB available, trigger recovery !! */
    344             if (pRxXfer->fErrCb)
    345             {
    346                 pRxXfer->fErrCb (pRxXfer->hErrCb, RX_XFER_FAILURE);
    347             }
    348         }
    349         else
    350         {
    351             TRACE2(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , "rxXfer_ForwardPacket: RxInfoLength=%d, RxInfoStatus=0x%x\n", uLenFromRxInfo, pRxInfo->status);
    352         }
    353         pRxXfer->tDbgStat.uCountPktsForward++;
    354 #endif
    355 
    356         /* This is the last packet in the Burst so mark its EndOfBurst flag */
    357         if (TXN_PARAM_GET_END_OF_BURST(pTxn) && (uBufNum == (MAX_XFER_BUFS - 1) || pTxn->aLen[uBufNum + 1] == 0))
    358         {
    359             TXN_PARAM_SET_END_OF_BURST(pTxn, 0);
    360             pRxInfo->driverFlags |= DRV_RX_FLAG_END_OF_BURST;
    361         }
    362         /* Forward received packet to the upper layers */
    363         RxQueue_ReceivePacket (pRxXfer->hRxQueue, (const void *)pTxn->aBuf[uBufNum]);
    364     }
    365 
    366     /* reset the aBuf field for clean on recovery purpose */
    367     pTxn->aBuf[0] = 0;
    368 }
    369 
    370 
    371 /****************************************************************************
    372  *                      rxXfer_RxEvent()
    373  ****************************************************************************
    374  * DESCRIPTION: Called upon Rx event from the FW.calls the SM
    375  *
    376  * INPUTS:      hRxXfer       - RxXfer handle;
    377  *
    378  * OUTPUT:  None
    379  *
    380  * RETURNS: TWIF_OK in case of Synch mode, or TWIF_PENDING in case of Asynch mode
    381  *          (when returning TWIF_PENDING, FwEvent module expects the FwEvent_EventComplete()
    382  *          function call to finish the Rx Client handling
    383  *
    384  ****************************************************************************/
    385 ETxnStatus rxXfer_RxEvent (TI_HANDLE hRxXfer, FwStatus_t *pFwStatus)
    386 {
    387     TRxXfer        *pRxXfer = (TRxXfer *)hRxXfer;
    388     TI_UINT32      uTempCounters;
    389     FwStatCntrs_t  *pFwStatusCounters;
    390     TI_UINT32       i;
    391     TI_STATUS   rc;
    392     CL_TRACE_START_L2();
    393 
    394     uTempCounters = ENDIAN_HANDLE_LONG (pFwStatus->counters);
    395     pFwStatusCounters = (FwStatCntrs_t*)(&uTempCounters);
    396 
    397     TRACE2(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , "rxXfer_RxEvent: NewFwCntr=%d, OldFwCntr=%d\n", pFwStatusCounters->fwRxCntr, pRxXfer->uFwRxCntr);
    398 
    399     /* If no new Rx packets - exit */
    400     if ((pFwStatusCounters->fwRxCntr % NUM_RX_PKT_DESC) == (pRxXfer->uFwRxCntr % NUM_RX_PKT_DESC))
    401     {
    402         CL_TRACE_END_L2("tiwlan_drv.ko", "CONTEXT", "RX", "");
    403         return TXN_STATUS_COMPLETE;
    404     }
    405 
    406 #ifdef TI_DBG
    407     pRxXfer->tDbgStat.uCountFwEvents++;
    408 #endif
    409 
    410     /* Save current FW counter and Rx packets short descriptors for processing */
    411     pRxXfer->uFwRxCntr = pFwStatusCounters->fwRxCntr;
    412     for (i = 0; i < NUM_RX_PKT_DESC; i++)
    413     {
    414         pRxXfer->aRxPktsDesc[i] = ENDIAN_HANDLE_LONG (pFwStatus->rxPktsDesc[i]);
    415     }
    416 
    417     /* Handle all new Rx packets */
    418     rc = rxXfer_Handle (pRxXfer);
    419 
    420     CL_TRACE_END_L2("tiwlan_drv.ko", "CONTEXT", "RX", "");
    421     return TXN_STATUS_COMPLETE;
    422 }
    423 
    424 
    425 /****************************************************************************
    426  *                      rxXfer_Handle()
    427  ****************************************************************************
    428  * DESCRIPTION:
    429  *
    430  * INPUTS:      hRxXfer       - RxXfer handle;
    431  *
    432  * OUTPUT:
    433  *
    434  * RETURNS:
    435  ****************************************************************************/
    436 static TI_STATUS rxXfer_Handle(TI_HANDLE hRxXfer)
    437 {
    438 #ifndef _VLCT_
    439     TRxXfer *        pRxXfer          = (TRxXfer *)hRxXfer;
    440     TI_BOOL          bIssueTxn        = TI_FALSE; /* If TRUE transact current aggregated packets */
    441     TI_BOOL          bDropLastPkt     = TI_FALSE; /* If TRUE, need to drop last packet (RX_BUF_ALLOC_OUT_OF_MEM) */
    442     TI_BOOL          bExit            = TI_FALSE; /* If TRUE, can't process further packets so exit (after serving the other flags) */
    443     TI_UINT32        uAggregPktsNum   = 0;        /* Number of aggregated packets */
    444     TI_UINT32        uFirstMemBlkAddr = 0;
    445     TI_UINT32        uRxDesc          = 0;
    446     TI_UINT32        uBuffSize        = 0;
    447     TI_UINT32        uTotalAggregLen  = 0;
    448     TI_UINT32        uDrvIndex;
    449     TI_UINT32        uFwIndex;
    450     TI_UINT8 *       pHostBuf;
    451     TTxnStruct *     pTxn = NULL;
    452     ETxnStatus       eTxnStatus;
    453     ERxBufferStatus  eBufStatus;
    454     PacketClassTag_e eRxPacketType;
    455     CL_TRACE_START_L2();
    456 
    457 
    458     /* If no Txn structures available exit!! (fatal error - not expected to happen) */
    459     if (pRxXfer->uAvailableTxn == 0 )
    460     {
    461         TRACE0(pRxXfer->hReport, REPORT_SEVERITY_ERROR, "rxXfer_Handle: No available Txn structures left!\n");
    462         CL_TRACE_END_L2("tiwlan_drv.ko", "CONTEXT", "RX", "");
    463         return TI_NOK;
    464     }
    465 
    466     uFwIndex = pRxXfer->uFwRxCntr % NUM_RX_PKT_DESC;
    467 
    468     /* Loop while Rx packets can be transfered from the FW */
    469     while (1)
    470     {
    471         uDrvIndex = pRxXfer->uDrvRxCntr % NUM_RX_PKT_DESC;
    472 
    473         /* If there are unprocessed Rx packets */
    474         if (uDrvIndex != uFwIndex)
    475         {
    476             /* Get next packte info */
    477             uRxDesc       = pRxXfer->aRxPktsDesc[uDrvIndex];
    478             uBuffSize     = RX_DESC_GET_LENGTH(uRxDesc) << 2;
    479             eRxPacketType = (PacketClassTag_e)RX_DESC_GET_PACKET_CLASS_TAG (uRxDesc);
    480 
    481             /* If new packet exceeds max aggregation length, set flag to send previous packets (postpone it to next loop) */
    482             if ((uTotalAggregLen + uBuffSize) > pRxXfer->uMaxAggregLen)
    483             {
    484                 bIssueTxn = TI_TRUE;
    485             }
    486 
    487             /* No length limit so try to aggregate new packet */
    488             else
    489             {
    490                 /* Allocate host read buffer */
    491                 /* The RxBufAlloc() add an extra word for MAC header alignment in case of QoS MSDU */
    492                 eBufStatus = pRxXfer->RequestForBufferCB(pRxXfer->RequestForBufferCB_handle,
    493                                                          (void**)&pHostBuf,
    494                                                          uBuffSize,
    495                                                          (TI_UINT32)NULL,
    496                                                          eRxPacketType);
    497 
    498                 TRACE6(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , "rxXfer_Handle: Index=%d, RxDesc=0x%x, DrvCntr=%d, FwCntr=%d, BufStatus=%d, BuffSize=%d\n", uDrvIndex, uRxDesc, pRxXfer->uDrvRxCntr, pRxXfer->uFwRxCntr, eBufStatus, uBuffSize);
    499 
    500                 /* If buffer allocated, add it to current Txn (up to 4 packets aggregation) */
    501                 if (eBufStatus == RX_BUF_ALLOC_COMPLETE)
    502                 {
    503                     /* If first aggregated packet prepare the next Txn struct */
    504                     if (uAggregPktsNum == 0)
    505                     {
    506                         pTxn = (TTxnStruct*)&(pRxXfer->aTxnStruct[pRxXfer->uCurrTxnIndex]);
    507                         pTxn->uHwAddr = SLV_MEM_DATA;
    508 
    509                         /* Save first mem-block of first aggregated packet! */
    510                         uFirstMemBlkAddr = SLV_MEM_CP_VALUE(uRxDesc, pRxXfer->uPacketMemoryPoolStart);
    511                     }
    512                     pTxn->aBuf[uAggregPktsNum] = pHostBuf + ALIGNMENT_SIZE(uRxDesc);
    513                     pTxn->aLen[uAggregPktsNum] = uBuffSize;
    514                     uAggregPktsNum++;
    515                     uTotalAggregLen += uBuffSize;
    516                     if (uAggregPktsNum >= pRxXfer->uMaxAggregPkts)
    517                     {
    518                         bIssueTxn = TI_TRUE;
    519                     }
    520                     pRxXfer->uDrvRxCntr++;
    521                 }
    522 
    523                 /* If buffer pending until freeing previous buffer, set Exit flag and if needed set IssueTxn flag. */
    524                 else if (eBufStatus == RX_BUF_ALLOC_PENDING)
    525                 {
    526                     bExit = TI_TRUE;
    527                     pRxXfer->bPendingBuffer = TI_TRUE;
    528                     if (uAggregPktsNum > 0)
    529                     {
    530                         bIssueTxn = TI_TRUE;
    531                     }
    532 #ifdef TI_DBG
    533                     pRxXfer->tDbgStat.uCountBufPend++;
    534 #endif
    535                 }
    536 
    537                 /* If no buffer due to out-of-memory, set DropLastPkt flag and if needed set IssueTxn flag. */
    538                 else
    539                 {
    540                     bDropLastPkt = TI_TRUE;
    541                     if (uAggregPktsNum > 0)
    542                     {
    543                         bIssueTxn = TI_TRUE;
    544                     }
    545 #ifdef TI_DBG
    546                     pRxXfer->tDbgStat.uCountBufNoMem++;
    547 #endif
    548                 }
    549             }
    550         }
    551 
    552         /* If no more packets, set Exit flag and if needed set IssueTxn flag. */
    553         else
    554         {
    555             bExit = TI_TRUE;
    556             if (uAggregPktsNum > 0)
    557             {
    558                 bIssueTxn = TI_TRUE;
    559             }
    560         }
    561 
    562 
    563         /* If required to send Rx packet(s) transaction */
    564         if (bIssueTxn)
    565         {
    566             if (bExit)
    567             {
    568                 TXN_PARAM_SET_END_OF_BURST(pTxn, 1);
    569             }
    570             /* If not all 4 Txn buffers are used, reset first unused buffer length for indication */
    571             if (uAggregPktsNum < MAX_XFER_BUFS)
    572             {
    573                 pTxn->aLen[uAggregPktsNum] = 0;
    574             }
    575 
    576             eTxnStatus = rxXfer_IssueTxn (pRxXfer, uFirstMemBlkAddr);
    577 
    578             if (eTxnStatus == TXN_STATUS_COMPLETE)
    579             {
    580                 /* Forward received packet to the upper layers */
    581                 rxXfer_ForwardPacket (pRxXfer, pTxn);
    582             }
    583             else if (eTxnStatus == TXN_STATUS_PENDING)
    584             {
    585                 /* Decrease the number of available txn structures */
    586                 pRxXfer->uAvailableTxn--;
    587             }
    588             else
    589             {
    590                 TRACE3(pRxXfer->hReport, REPORT_SEVERITY_ERROR , "rxXfer_Handle: Status=%d, DrvCntr=%d, RxDesc=0x%x\n", eTxnStatus, pRxXfer->uDrvRxCntr, uRxDesc);
    591             }
    592 
    593 #ifdef TI_DBG
    594             pRxXfer->tDbgStat.uCountPktAggreg[uAggregPktsNum - 1]++;
    595 #endif
    596 
    597             uAggregPktsNum  = 0;
    598             uTotalAggregLen = 0;
    599             bIssueTxn       = TI_FALSE;
    600             pRxXfer->uCurrTxnIndex = (pRxXfer->uCurrTxnIndex + 1) % MAX_CONSECUTIVE_READ_TXN;
    601         }
    602 
    603         /* If last packet should be dropped (no memory for host buffer) */
    604         if (bDropLastPkt)
    605         {
    606             /* Increment driver packets counter before calling rxXfer_IssueTxn() */
    607             pRxXfer->uDrvRxCntr++;
    608 
    609             /* Read packet to dummy buffer and ignore it (no callback needed) */
    610             uFirstMemBlkAddr = SLV_MEM_CP_VALUE(uRxDesc, pRxXfer->uPacketMemoryPoolStart);
    611             pTxn = (TTxnStruct*)&pRxXfer->aTxnStruct[pRxXfer->uCurrTxnIndex];
    612             BUILD_TTxnStruct(pTxn, SLV_MEM_DATA, pRxXfer->aTempBuffer, uBuffSize, (TTxnDoneCb)rxXfer_PktDropTxnDoneCb, hRxXfer)
    613             eTxnStatus = rxXfer_IssueTxn (pRxXfer, uFirstMemBlkAddr);
    614             if (eTxnStatus == TXN_STATUS_PENDING)
    615             {
    616                 pRxXfer->uAvailableTxn--;
    617             }
    618             pRxXfer->uCurrTxnIndex = (pRxXfer->uCurrTxnIndex + 1) % MAX_CONSECUTIVE_READ_TXN;
    619             bDropLastPkt = TI_FALSE;
    620         }
    621 
    622         /* Can't process more packets so exit */
    623         if (bExit)
    624         {
    625             CL_TRACE_END_L2("tiwlan_drv.ko", "CONTEXT", "RX", "");
    626             return TI_OK;
    627         }
    628 
    629     } /* End of while(1) */
    630 
    631     /* Unreachable code */
    632 
    633 #endif
    634 }
    635 
    636 
    637 /****************************************************************************
    638  *                      rxXfer_IssueTxn()
    639  ****************************************************************************
    640  * DESCRIPTION:
    641  *
    642  * INPUTS:
    643  *
    644  * OUTPUT:
    645  *
    646  * RETURNS:
    647  ****************************************************************************/
    648 static ETxnStatus rxXfer_IssueTxn (TI_HANDLE hRxXfer, TI_UINT32 uFirstMemBlkAddr)
    649 {
    650     TRxXfer    *pRxXfer = (TRxXfer *)hRxXfer;
    651     TI_UINT32   uIndex  = pRxXfer->uCurrTxnIndex;
    652     TTxnStruct *pTxn;
    653     ETxnStatus  eStatus;
    654 
    655     /* Write the next mem block that we want to read */
    656     pTxn = &pRxXfer->aSlaveRegTxn[uIndex].tTxnStruct;
    657     pTxn->uHwAddr = SLV_REG_DATA;
    658     pRxXfer->aSlaveRegTxn[uIndex].uRegData  = ENDIAN_HANDLE_LONG(uFirstMemBlkAddr);
    659     pRxXfer->aSlaveRegTxn[uIndex].uRegAdata = ENDIAN_HANDLE_LONG(uFirstMemBlkAddr + 4);
    660     twIf_Transact(pRxXfer->hTwIf, pTxn);
    661 
    662     /* Issue the packet(s) read transaction (prepared in rxXfer_Handle) */
    663     pTxn = &pRxXfer->aTxnStruct[uIndex];
    664     eStatus = twIf_Transact(pRxXfer->hTwIf, pTxn);
    665 
    666     /* Write driver packets counter to FW. This write automatically generates interrupt to FW */
    667     /* Note: Workaround for WL6-PG1.0 is still needed for PG2.0   ==>  if (pRxXfer->bChipIs1273Pg10)  */
    668     pTxn = &pRxXfer->aCounterTxn[uIndex].tTxnStruct;
    669     pTxn->uHwAddr = RX_DRIVER_COUNTER_ADDRESS;
    670     pRxXfer->aCounterTxn[uIndex].uCounter = ENDIAN_HANDLE_LONG(pRxXfer->uDrvRxCntr);
    671     twIf_Transact(pRxXfer->hTwIf, pTxn);
    672 
    673     TRACE5(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , "rxXfer_IssueTxn: Counter-Txn: HwAddr=0x%x, Len0=%d, Data0=%d, DrvCount=%d, TxnParams=0x%x\n", pTxn->uHwAddr, pTxn->aLen[0], *(TI_UINT32 *)(pTxn->aBuf[0]), pRxXfer->uDrvRxCntr, pTxn->uTxnParams);
    674 
    675     /* Return the status of the packet(s) transaction - COMPLETE, PENDING or ERROR */
    676     return eStatus;
    677 }
    678 
    679 
    680 /****************************************************************************
    681  *                      rxXfer_SetRxDirectAccessParams()
    682  ****************************************************************************
    683  * DESCRIPTION:
    684  *
    685  * INPUTS:
    686  *
    687  * OUTPUT:
    688  *
    689  * RETURNS:
    690  ****************************************************************************/
    691 void rxXfer_SetRxDirectAccessParams (TI_HANDLE hRxXfer, TDmaParams *pDmaParams)
    692 {
    693     TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    694 
    695     pRxXfer->uPacketMemoryPoolStart = pDmaParams->PacketMemoryPoolStart;
    696 }
    697 
    698 
    699 /****************************************************************************
    700  *                      rxXfer_TxnDoneCb()
    701  ****************************************************************************
    702  * DESCRIPTION: Forward the packet to the registered CB
    703  *
    704  * INPUTS:
    705  *
    706  * OUTPUT:
    707  *
    708  * RETURNS:
    709  ****************************************************************************/
    710 static void rxXfer_TxnDoneCb (TI_HANDLE hRxXfer, TTxnStruct *pTxn)
    711 {
    712     TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    713     CL_TRACE_START_L2();
    714 
    715     /* Increase the number of available txn structures */
    716     pRxXfer->uAvailableTxn++;
    717 
    718     /* Forward received packet to the upper layers */
    719     rxXfer_ForwardPacket (pRxXfer, pTxn);
    720 
    721     /* If we exited the handler upon pending-buffer, call it again to handle further packets if any */
    722     if (pRxXfer->bPendingBuffer)
    723     {
    724         pRxXfer->bPendingBuffer = TI_FALSE;
    725         rxXfer_Handle (hRxXfer);
    726     }
    727 
    728     CL_TRACE_END_L2("tiwlan_drv.ko", "INHERIT", "RX", "");
    729 }
    730 
    731 
    732 /****************************************************************************
    733  *                      rxXfer_PktDropTxnDoneCb()
    734  ****************************************************************************
    735  * DESCRIPTION: Dummy CB for case of dropping a packet due to out-of-memory.
    736  *
    737  * INPUTS:
    738  *
    739  * OUTPUT:
    740  *
    741  * RETURNS:
    742  ****************************************************************************/
    743 static void rxXfer_PktDropTxnDoneCb (TI_HANDLE hRxXfer, TTxnStruct *pTxn)
    744 {
    745     TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    746 
    747     /* Increase the number of available txn structures */
    748     pRxXfer->uAvailableTxn++;
    749 
    750     /* Restore the regular TxnDone callback to the used structure */
    751     pTxn->fTxnDoneCb = (TTxnDoneCb)rxXfer_TxnDoneCb;
    752     pTxn->hCbHandle  = hRxXfer;
    753 }
    754 
    755 
    756 /****************************************************************************
    757  *                      rxXfer_Restart()
    758  ****************************************************************************
    759  * DESCRIPTION:	rxXfer_Restart the RxXfer module object (called by the recovery)
    760  *
    761  * INPUTS:	hRxXfer - The object to free
    762  *
    763  * OUTPUT:	None
    764  *
    765  * RETURNS:	NONE
    766  ****************************************************************************/
    767 void rxXfer_Restart(TI_HANDLE hRxXfer)
    768 {
    769 	TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    770     TTxnStruct* pTxn;
    771     TI_UINT8    i;
    772 
    773     pRxXfer->uFwRxCntr     = 0;
    774     pRxXfer->uDrvRxCntr    = 0;
    775     pRxXfer->uCurrTxnIndex = 0;
    776     pRxXfer->uAvailableTxn = MAX_CONSECUTIVE_READ_TXN - 1;
    777 
    778     /* Scan all transaction array and release only pending transaction */
    779     for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++)
    780     {
    781         pTxn = &(pRxXfer->aTxnStruct[i]);
    782 
    783         /* Check if buffer allocated and not the dummy one (has a different callback) */
    784         if ((pTxn->aBuf[0] != 0) && (pTxn->fTxnDoneCb == (TTxnDoneCb)rxXfer_TxnDoneCb))
    785         {
    786             TI_UINT32 uBufNum;
    787             RxIfDescriptor_t *pRxParams;
    788 
    789             /* Go over the Txn occupied  buffers and mark them as TAG_CLASS_UNKNOWN to be freed */
    790             for (uBufNum = 0; uBufNum < MAX_XFER_BUFS; uBufNum++)
    791             {
    792                 /* If no more buffers, exit the loop */
    793                 if (pTxn->aLen[uBufNum] == 0)
    794                 {
    795                     break;
    796                 }
    797 
    798                 pRxParams = (RxIfDescriptor_t *)(pTxn->aBuf[uBufNum]);
    799                 pRxParams->packet_class_tag = TAG_CLASS_UNKNOWN;
    800             }
    801 
    802             /* Call upper layer only to release the allocated buffer */
    803             rxXfer_ForwardPacket (pRxXfer, pTxn);
    804         }
    805     }
    806 
    807     /* Fill the transaction structures fields that have constant values */
    808     for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++)
    809     {
    810         /* First mem-block address (two consecutive registers) */
    811         pTxn = &(pRxXfer->aSlaveRegTxn[i].tTxnStruct);
    812         TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
    813         BUILD_TTxnStruct(pTxn, SLV_REG_DATA, &pRxXfer->aSlaveRegTxn[i].uRegData, REGISTER_SIZE*2, NULL, NULL)
    814 
    815         /* The packet(s) read transaction */
    816         pTxn = &(pRxXfer->aTxnStruct[i]);
    817         TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_FIXED_ADDR)
    818         pTxn->fTxnDoneCb = (TTxnDoneCb)rxXfer_TxnDoneCb;
    819         pTxn->hCbHandle  = hRxXfer;
    820 
    821         /* The driver packets counter */
    822         pTxn = &(pRxXfer->aCounterTxn[i].tTxnStruct);
    823         TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR)
    824         BUILD_TTxnStruct(pTxn, RX_DRIVER_COUNTER_ADDRESS, &pRxXfer->aCounterTxn[i].uCounter, REGISTER_SIZE, NULL, NULL)
    825     }
    826 
    827 }
    828 
    829 
    830 /****************************************************************************
    831  *                      rxXfer_RegisterErrCb()
    832  ****************************************************************************
    833  * DESCRIPTION: Register Error CB
    834  *
    835  * INPUTS:
    836  *          hRxXfer - The object
    837  *          ErrCb   - The upper layer CB function for error handling
    838  *          hErrCb  - The CB function handle
    839  *
    840  * OUTPUT:  None
    841  *
    842  * RETURNS: void
    843  ****************************************************************************/
    844 void rxXfer_RegisterErrCb (TI_HANDLE hRxXfer, void *fErrCb, TI_HANDLE hErrCb)
    845 {
    846     TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    847 
    848     /* Save upper layer (health monitor) CB for recovery from fatal error */
    849     pRxXfer->fErrCb = (TFailureEventCb)fErrCb;
    850     pRxXfer->hErrCb = hErrCb;
    851 }
    852 
    853 
    854 #ifdef TI_DBG
    855 /****************************************************************************
    856  *                      rxXfer_ClearStats()
    857  ****************************************************************************
    858  * DESCRIPTION:
    859  *
    860  * INPUTS:
    861  *          pRxXfer The object
    862  *
    863  * OUTPUT:  None
    864  *
    865  * RETURNS: TI_OK.
    866  ****************************************************************************/
    867 void rxXfer_ClearStats (TI_HANDLE hRxXfer)
    868 {
    869     TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    870 
    871     os_memoryZero (pRxXfer->hOs, &pRxXfer->tDbgStat, sizeof(TRxXferDbgStat));
    872 }
    873 
    874 
    875 /****************************************************************************
    876  *                      rxXfer_PrintStats()
    877  ****************************************************************************
    878  * DESCRIPTION: .
    879  *
    880  * INPUTS:
    881  *          pRxXfer The object
    882  *
    883  * OUTPUT:  None
    884  *
    885  * RETURNS: TI_OK.
    886  ****************************************************************************/
    887 void rxXfer_PrintStats (TI_HANDLE hRxXfer)
    888 {
    889 #ifdef REPORT_LOG
    890     TRxXfer *pRxXfer = (TRxXfer *)hRxXfer;
    891 
    892     WLAN_OS_REPORT(("Print RX Xfer module info\n"));
    893     WLAN_OS_REPORT(("=========================\n"));
    894     WLAN_OS_REPORT(("uMaxAggregPkts     = %d\n", pRxXfer->uMaxAggregPkts));
    895     WLAN_OS_REPORT(("uMaxAggregLen      = %d\n", pRxXfer->uMaxAggregLen));
    896     WLAN_OS_REPORT(("FW counter         = %d\n", pRxXfer->uFwRxCntr));
    897     WLAN_OS_REPORT(("Drv counter        = %d\n", pRxXfer->uDrvRxCntr));
    898     WLAN_OS_REPORT(("AvailableTxn       = %d\n", pRxXfer->uAvailableTxn));
    899     WLAN_OS_REPORT(("uCountFwEvents     = %d\n", pRxXfer->tDbgStat.uCountFwEvents));
    900     WLAN_OS_REPORT(("uCountPktsForward  = %d\n", pRxXfer->tDbgStat.uCountPktsForward));
    901     WLAN_OS_REPORT(("uCountBufPend      = %d\n", pRxXfer->tDbgStat.uCountBufPend));
    902     WLAN_OS_REPORT(("uCountBufNoMem     = %d\n", pRxXfer->tDbgStat.uCountBufNoMem));
    903     WLAN_OS_REPORT(("uCountPktAggreg-1  = %d\n", pRxXfer->tDbgStat.uCountPktAggreg[0]));
    904     WLAN_OS_REPORT(("uCountPktAggreg-2  = %d\n", pRxXfer->tDbgStat.uCountPktAggreg[1]));
    905     WLAN_OS_REPORT(("uCountPktAggreg-3  = %d\n", pRxXfer->tDbgStat.uCountPktAggreg[2]));
    906     WLAN_OS_REPORT(("uCountPktAggreg-4  = %d\n", pRxXfer->tDbgStat.uCountPktAggreg[3]));
    907 #endif
    908 }
    909 #endif
    910