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