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