• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  ****************************************************************************/
rxXfer_Create(TI_HANDLE hOs)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  ****************************************************************************/
rxXfer_Destroy(TI_HANDLE hRxXfer)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  ****************************************************************************/
rxXfer_Init(TI_HANDLE hRxXfer,TI_HANDLE hFwEvent,TI_HANDLE hReport,TI_HANDLE hTwIf,TI_HANDLE hRxQueue)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  ****************************************************************************/
rxXfer_SetDefaults(TI_HANDLE hRxXfer,TTwdInitParams * pInitParams)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  ****************************************************************************/
rxXfer_SetBusParams(TI_HANDLE hRxXfer,TI_UINT32 uDmaBufLen)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  ****************************************************************************/
rxXfer_Register_CB(TI_HANDLE hRxXfer,TI_UINT32 CallBackID,void * CBFunc,TI_HANDLE CBObj)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  ****************************************************************************/
rxXfer_ForwardPacket(TRxXfer * pRxXfer,TTxnStruct * pTxn)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  ****************************************************************************/
rxXfer_RxEvent(TI_HANDLE hRxXfer,FwStatus_t * pFwStatus)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  ****************************************************************************/
rxXfer_Handle(TI_HANDLE hRxXfer)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  ****************************************************************************/
rxXfer_IssueTxn(TI_HANDLE hRxXfer,TI_UINT32 uFirstMemBlkAddr)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  ****************************************************************************/
rxXfer_SetRxDirectAccessParams(TI_HANDLE hRxXfer,TDmaParams * pDmaParams)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  ****************************************************************************/
rxXfer_TxnDoneCb(TI_HANDLE hRxXfer,TTxnStruct * pTxn)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  ****************************************************************************/
rxXfer_PktDropTxnDoneCb(TI_HANDLE hRxXfer,TTxnStruct * pTxn)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  ****************************************************************************/
rxXfer_Restart(TI_HANDLE hRxXfer)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  ****************************************************************************/
rxXfer_RegisterErrCb(TI_HANDLE hRxXfer,void * fErrCb,TI_HANDLE hErrCb)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  ****************************************************************************/
rxXfer_ClearStats(TI_HANDLE hRxXfer)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  ****************************************************************************/
rxXfer_PrintStats(TI_HANDLE hRxXfer)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