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