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