1 /* 2 * RxXfer.c 3 * 4 * Copyright(c) 1998 - 2009 Texas Instruments. All rights reserved. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name Texas Instruments nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 35 /**************************************************************************** 36 * 37 * MODULE: rxXfer.c 38 * 39 * PURPOSE: Rx Xfer module implementation.Responsible for reading Rx from the FW 40 * and forward it to the upper layers. 41 * 42 ****************************************************************************/ 43 44 #define __FILE_ID__ FILE_ID_106 45 #include "tidef.h" 46 #include "osApi.h" 47 #include "report.h" 48 #include "rxXfer_api.h" 49 #include "FwEvent_api.h" 50 #include "TWDriverInternal.h" 51 #include "RxQueue_api.h" 52 #include "TwIf.h" 53 #include "public_host_int.h" 54 #include "bmtrace_api.h" 55 56 #define RX_DRIVER_COUNTER_ADDRESS 0x300538 57 #define PLCP_HEADER_LENGTH 8 58 #define WORD_SIZE 4 59 #define UNALIGNED_PAYLOAD 0x1 60 #define RX_DESCRIPTOR_SIZE (sizeof(RxIfDescriptor_t)) 61 #define MAX_PACKETS_NUMBER 8 62 #define MAX_CONSECUTIVE_READ_TXN 16 63 #define MAX_PACKET_SIZE 8192 /* Max Txn size */ 64 65 #ifdef PLATFORM_SYMBIAN /* UMAC is using only one buffer and therefore we can't use consecutive reads */ 66 #define MAX_CONSECUTIVE_READS 1 67 #else 68 #define MAX_CONSECUTIVE_READS 8 69 #endif 70 71 #define SLV_MEM_CP_VALUE(desc, offset) (((RX_DESC_GET_MEM_BLK(desc) << 8) + offset)) 72 #define ALIGNMENT_SIZE(desc) ((RX_DESC_GET_UNALIGNED(desc) & UNALIGNED_PAYLOAD) ? 2 : 0) 73 74 #if (NUM_RX_PKT_DESC & (NUM_RX_PKT_DESC - 1)) 75 #error NUM_RX_PKT_DESC is not a power of 2 which may degrade performance when we calculate modulo!! 76 #endif 77 78 79 #ifdef TI_DBG 80 typedef struct 81 { 82 TI_UINT32 uCountFwEvents; 83 TI_UINT32 uCountPktsForward; 84 TI_UINT32 uCountBufPend; 85 TI_UINT32 uCountBufNoMem; 86 TI_UINT32 uCountPktAggreg[MAX_XFER_BUFS]; 87 88 } TRxXferDbgStat; 89 #endif 90 91 typedef struct 92 { 93 TTxnStruct tTxnStruct; 94 TI_UINT32 uRegData; 95 TI_UINT32 uRegAdata; 96 97 } TRegTxn; 98 99 typedef struct 100 { 101 TTxnStruct tTxnStruct; 102 TI_UINT32 uCounter; 103 104 } TCounterTxn; 105 106 typedef struct 107 { 108 TI_HANDLE hOs; 109 TI_HANDLE hReport; 110 TI_HANDLE hTwIf; 111 TI_HANDLE hFwEvent; 112 TI_HANDLE hRxQueue; 113 114 TI_UINT32 aRxPktsDesc[NUM_RX_PKT_DESC]; /* Save Rx packets short descriptors from FwStatus */ 115 TI_UINT32 uFwRxCntr; /* Save last FW packets counter from FwStatus */ 116 TI_UINT32 uDrvRxCntr; /* The current driver processed packets counter */ 117 TI_UINT32 uPacketMemoryPoolStart; /* The FW mem-blocks area base address */ 118 TI_UINT32 uMaxAggregLen; /* The max length in bytes of aggregated packets transaction */ 119 TI_UINT32 uMaxAggregPkts; /* The max number of packets that may be aggregated in one transaction */ 120 TRequestForBufferCb RequestForBufferCB; /* Upper layer CB for allocating buffers for packets */ 121 TI_HANDLE RequestForBufferCB_handle; /* The upper later CB handle */ 122 TI_BOOL bPendingBuffer; /* If TRUE, we exited the Rx handler upon pending-buffer */ 123 124 TI_UINT32 uCurrTxnIndex; /* The current Txn structures index to use */ 125 TI_UINT32 uAvailableTxn; /* Number of Txn structures currently available */ 126 TRegTxn aSlaveRegTxn[MAX_CONSECUTIVE_READ_TXN]; /* Txn structures for writing mem-block address reg */ 127 TTxnStruct aTxnStruct[MAX_CONSECUTIVE_READ_TXN]; /* Txn structures for reading the Rx packets */ 128 TCounterTxn aCounterTxn[MAX_CONSECUTIVE_READ_TXN]; /* Txn structures for writing the driver counter workaround */ 129 130 TI_UINT8 aTempBuffer[MAX_PACKET_SIZE]; /* Dummy buffer to use if we couldn't get a buffer for the packet (so drop the packet) */ 131 TI_BOOL bChipIs1273Pg10; /* If TRUE the chip is PG1.0 and not 2.0 */ 132 TFailureEventCb fErrCb; /* The upper layer CB function for error handling */ 133 TI_HANDLE hErrCb; /* The CB function handle */ 134 135 #ifdef TI_DBG 136 TRxXferDbgStat tDbgStat; 137 #endif 138 139 } TRxXfer; 140 141 142 /************************ static function declaration *****************************/ 143 static TI_STATUS rxXfer_Handle(TI_HANDLE hRxXfer); 144 static void rxXfer_TxnDoneCb (TI_HANDLE hRxXfer, TTxnStruct* pTxn); 145 static void rxXfer_PktDropTxnDoneCb (TI_HANDLE hRxXfer, TTxnStruct *pTxn); 146 static ETxnStatus rxXfer_IssueTxn (TI_HANDLE hRxXfer, TI_UINT32 uFirstMemBlkAddr); 147 static void rxXfer_ForwardPacket (TRxXfer* pRxXfer, TTxnStruct* pTxn); 148 149 150 /**************************************************************************** 151 * RxXfer_Create() 152 **************************************************************************** 153 * DESCRIPTION: Create the RxXfer module object 154 * 155 * INPUTS: None 156 * 157 * OUTPUT: None 158 * 159 * RETURNS: The Created object 160 ****************************************************************************/ 161 TI_HANDLE rxXfer_Create (TI_HANDLE hOs) 162 { 163 TRxXfer *pRxXfer; 164 165 pRxXfer = os_memoryAlloc (hOs, sizeof(TRxXfer)); 166 if (pRxXfer == NULL) 167 return NULL; 168 169 /* For all the counters */ 170 os_memoryZero (hOs, pRxXfer, sizeof(TRxXfer)); 171 172 pRxXfer->hOs = hOs; 173 174 return (TI_HANDLE)pRxXfer; 175 } 176 177 178 /**************************************************************************** 179 * RxXfer_Destroy() 180 **************************************************************************** 181 * DESCRIPTION: Destroy the RxXfer module object 182 * 183 * INPUTS: hRxXfer - The object to free 184 * 185 * OUTPUT: None 186 * 187 * RETURNS: 188 ****************************************************************************/ 189 void rxXfer_Destroy (TI_HANDLE hRxXfer) 190 { 191 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 192 193 if (pRxXfer) 194 { 195 os_memoryFree (pRxXfer->hOs, pRxXfer, sizeof(TRxXfer)); 196 } 197 } 198 199 200 /**************************************************************************** 201 * rxXfer_init() 202 **************************************************************************** 203 * DESCRIPTION: Init the module object 204 * 205 * INPUTS: hRxXfer - module handle; 206 * other modules handles. 207 * 208 * OUTPUT: None 209 * 210 * RETURNS: None 211 ****************************************************************************/ 212 void rxXfer_Init(TI_HANDLE hRxXfer, 213 TI_HANDLE hFwEvent, 214 TI_HANDLE hReport, 215 TI_HANDLE hTwIf, 216 TI_HANDLE hRxQueue) 217 { 218 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 219 pRxXfer->hFwEvent = hFwEvent; 220 pRxXfer->hReport = hReport; 221 pRxXfer->hTwIf = hTwIf; 222 pRxXfer->hRxQueue = hRxQueue; 223 224 RxXfer_ReStart (hRxXfer, TI_TRUE); 225 226 #ifdef TI_DBG 227 rxXfer_ClearStats (pRxXfer); 228 #endif 229 } 230 231 232 /**************************************************************************** 233 * rxXfer_SetDefaults() 234 **************************************************************************** 235 * DESCRIPTION: Set module parameters default setting 236 * 237 * INPUTS: hRxXfer - module handle; 238 * 239 * OUTPUT: None 240 * 241 * RETURNS: None 242 ****************************************************************************/ 243 void rxXfer_SetDefaults (TI_HANDLE hRxXfer, TTwdInitParams *pInitParams) 244 { 245 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 246 247 pRxXfer->uMaxAggregPkts = pInitParams->tGeneral.uRxAggregPktsLimit; 248 } 249 250 251 /**************************************************************************** 252 * rxXfer_Register_CB() 253 **************************************************************************** 254 * DESCRIPTION: Register the function to be called for request for buffer. 255 * 256 * INPUTS: hRxXfer - RxXfer handle; 257 * 258 * OUTPUT: None 259 * 260 * RETURNS: None 261 ****************************************************************************/ 262 void rxXfer_Register_CB (TI_HANDLE hRxXfer, TI_UINT32 CallBackID, void *CBFunc, TI_HANDLE CBObj) 263 { 264 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 265 266 TRACE1(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , "rxXfer_Register_CB (Value = 0x%x)\n", CallBackID); 267 268 switch(CallBackID) 269 { 270 case TWD_INT_REQUEST_FOR_BUFFER: 271 pRxXfer->RequestForBufferCB = (TRequestForBufferCb)CBFunc; 272 pRxXfer->RequestForBufferCB_handle = CBObj; 273 break; 274 275 default: 276 TRACE0(pRxXfer->hReport, REPORT_SEVERITY_ERROR, "rxXfer_Register_CB - Illegal value\n"); 277 return; 278 } 279 } 280 281 282 /**************************************************************************** 283 * rxXfer_ForwardPacket() 284 **************************************************************************** 285 * DESCRIPTION: Forward received packet(s) to the upper layers. 286 * 287 * INPUTS: 288 * 289 * OUTPUT: 290 * 291 * RETURNS: 292 ****************************************************************************/ 293 static void rxXfer_ForwardPacket (TRxXfer *pRxXfer, TTxnStruct *pTxn) 294 { 295 TI_UINT32 uBufNum; 296 #ifdef TI_DBG /* for packet sanity check */ 297 RxIfDescriptor_t *pRxInfo = (RxIfDescriptor_t*)(pTxn->aBuf[0]); 298 TI_UINT16 uLenFromRxInfo; 299 #endif 300 301 /* Go over all occupied Txn buffers and forward their Rx packets upward */ 302 for (uBufNum = 0; uBufNum < MAX_XFER_BUFS; uBufNum++) 303 { 304 /* If no more buffers, exit the loop */ 305 if (pTxn->aLen[uBufNum] == 0) 306 { 307 break; 308 } 309 310 #ifdef TI_DBG /* Packet sanity check */ 311 /* Get length from RxInfo, handle endianess and convert to length in bytes */ 312 pRxInfo = (RxIfDescriptor_t*)(pTxn->aBuf[uBufNum]); 313 uLenFromRxInfo = ENDIAN_HANDLE_WORD(pRxInfo->length) << 2; 314 315 /* If the length in the RxInfo is different than in the short descriptor, set error status */ 316 if (pTxn->aLen[uBufNum] != uLenFromRxInfo) 317 { 318 TRACE3(pRxXfer->hReport, REPORT_SEVERITY_ERROR , "rxXfer_ForwardPacket: Bad Length!! RxInfoLength=%d, ShortDescLen=%d, RxInfoStatus=0x%x\n", uLenFromRxInfo, pTxn->aLen[uBufNum], pRxInfo->status); 319 320 pRxInfo->status &= ~RX_DESC_STATUS_MASK; 321 pRxInfo->status |= RX_DESC_STATUS_DRIVER_RX_Q_FAIL; 322 pRxInfo->length = ENDIAN_HANDLE_WORD(pTxn->aLen[uBufNum] >> 2); 323 324 /* If error CB available, trigger recovery !! */ 325 if (pRxXfer->fErrCb) 326 { 327 pRxXfer->fErrCb (pRxXfer->hErrCb, RX_XFER_FAILURE); 328 } 329 } 330 pRxXfer->tDbgStat.uCountPktsForward++; 331 #endif 332 333 /* Forward received packet to the upper layers */ 334 RxQueue_ReceivePacket (pRxXfer->hRxQueue, (const void *)pTxn->aBuf[uBufNum]); 335 } 336 337 /* reset the aBuf field for clean on recovery purpose */ 338 pTxn->aBuf[0] = 0; 339 } 340 341 342 /**************************************************************************** 343 * rxXfer_RxEvent() 344 **************************************************************************** 345 * DESCRIPTION: Called upon Rx event from the FW.calls the SM 346 * 347 * INPUTS: hRxXfer - RxXfer handle; 348 * 349 * OUTPUT: None 350 * 351 * RETURNS: TWIF_OK in case of Synch mode, or TWIF_PENDING in case of Asynch mode 352 * (when returning TWIF_PENDING, FwEvent module expects the FwEvent_EventComplete() 353 * function call to finish the Rx Client handling 354 * 355 ****************************************************************************/ 356 TI_STATUS rxXfer_RxEvent (TI_HANDLE hRxXfer, FwStatus_t *pFwStatus) 357 { 358 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 359 TI_UINT32 uTempCounters; 360 FwStatCntrs_t *pFwStatusCounters; 361 TI_UINT32 i; 362 TI_STATUS rc; 363 CL_TRACE_START_L2(); 364 365 uTempCounters = ENDIAN_HANDLE_LONG (pFwStatus->counters); 366 pFwStatusCounters = (FwStatCntrs_t*)(&uTempCounters); 367 368 TRACE2(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , "rxXfer_RxEvent: NewFwCntr=%d, OldFwCntr=%d\n", pFwStatusCounters->fwRxCntr, pRxXfer->uFwRxCntr); 369 370 /* If no new Rx packets - exit */ 371 if ((pFwStatusCounters->fwRxCntr % NUM_RX_PKT_DESC) == (pRxXfer->uFwRxCntr % NUM_RX_PKT_DESC)) 372 { 373 CL_TRACE_END_L2("tiwlan_drv.ko", "CONTEXT", "RX", ""); 374 return TI_OK; 375 } 376 377 #ifdef TI_DBG 378 pRxXfer->tDbgStat.uCountFwEvents++; 379 #endif 380 381 /* Save current FW counter and Rx packets short descriptors for processing */ 382 pRxXfer->uFwRxCntr = pFwStatusCounters->fwRxCntr; 383 for (i = 0; i < NUM_RX_PKT_DESC; i++) 384 { 385 pRxXfer->aRxPktsDesc[i] = ENDIAN_HANDLE_LONG (pFwStatus->rxPktsDesc[i]); 386 } 387 388 /* Handle all new Rx packets */ 389 rc = rxXfer_Handle (pRxXfer); 390 391 CL_TRACE_END_L2("tiwlan_drv.ko", "CONTEXT", "RX", ""); 392 return rc; 393 } 394 395 396 /**************************************************************************** 397 * rxXfer_Handle() 398 **************************************************************************** 399 * DESCRIPTION: 400 * 401 * INPUTS: hRxXfer - RxXfer handle; 402 * 403 * OUTPUT: 404 * 405 * RETURNS: 406 ****************************************************************************/ 407 static TI_STATUS rxXfer_Handle(TI_HANDLE hRxXfer) 408 { 409 #ifndef _VLCT_ 410 TRxXfer * pRxXfer = (TRxXfer *)hRxXfer; 411 TI_BOOL bIssueTxn = TI_FALSE; /* If TRUE transact current aggregated packets */ 412 TI_BOOL bDropLastPkt = TI_FALSE; /* If TRUE, need to drop last packet (RX_BUF_ALLOC_OUT_OF_MEM) */ 413 TI_BOOL bExit = TI_FALSE; /* If TRUE, can't process further packets so exit (after serving the other flags) */ 414 TI_UINT32 uAggregPktsNum = 0; /* Number of aggregated packets */ 415 TI_UINT32 uFirstMemBlkAddr = 0; 416 TI_UINT32 uRxDesc = 0; 417 TI_UINT32 uBuffSize = 0; 418 TI_UINT32 uTotalAggregLen = 0; 419 TI_UINT32 uDrvIndex; 420 TI_UINT32 uFwIndex; 421 TI_UINT8 * pHostBuf; 422 TTxnStruct * pTxn = NULL; 423 ETxnStatus eTxnStatus; 424 ERxBufferStatus eBufStatus; 425 PacketClassTag_e eRxPacketType; 426 CL_TRACE_START_L2(); 427 428 429 /* If no Txn structures available exit!! (fatal error - not expected to happen) */ 430 if (pRxXfer->uAvailableTxn == 0 ) 431 { 432 TRACE0(pRxXfer->hReport, REPORT_SEVERITY_ERROR, "rxXfer_Handle: No available Txn structures left!\n"); 433 CL_TRACE_END_L2("tiwlan_drv.ko", "CONTEXT", "RX", ""); 434 return TI_NOK; 435 } 436 437 uFwIndex = pRxXfer->uFwRxCntr % NUM_RX_PKT_DESC; 438 439 /* Loop while Rx packets can be transfered from the FW */ 440 while (1) 441 { 442 uDrvIndex = pRxXfer->uDrvRxCntr % NUM_RX_PKT_DESC; 443 444 /* If there are unprocessed Rx packets */ 445 if (uDrvIndex != uFwIndex) 446 { 447 /* Get next packte info */ 448 uRxDesc = pRxXfer->aRxPktsDesc[uDrvIndex]; 449 uBuffSize = RX_DESC_GET_LENGTH(uRxDesc) << 2; 450 eRxPacketType = (PacketClassTag_e)RX_DESC_GET_PACKET_CLASS_TAG (uRxDesc); 451 452 /* If new packet exceeds max aggregation length, set flag to send previous packets (postpone it to next loop) */ 453 if ((uTotalAggregLen + uBuffSize) > pRxXfer->uMaxAggregLen) 454 { 455 bIssueTxn = TI_TRUE; 456 } 457 458 /* No length limit so try to aggregate new packet */ 459 else 460 { 461 /* Allocate host read buffer */ 462 /* The RxBufAlloc() add an extra word for MAC header alignment in case of QoS MSDU */ 463 eBufStatus = pRxXfer->RequestForBufferCB(pRxXfer->RequestForBufferCB_handle, 464 (void**)&pHostBuf, 465 uBuffSize, 466 (TI_UINT32)NULL, 467 eRxPacketType); 468 469 TRACE6(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , "rxXfer_Handle: Index=%d, RxDesc=0x%x, DrvCntr=%d, FwCntr=%d, BufStatus=%d, BuffSize=%d\n", uDrvIndex, uRxDesc, pRxXfer->uDrvRxCntr, pRxXfer->uFwRxCntr, eBufStatus, uBuffSize); 470 471 /* If buffer allocated, add it to current Txn (up to 4 packets aggregation) */ 472 if (eBufStatus == RX_BUF_ALLOC_COMPLETE) 473 { 474 /* If first aggregated packet prepare the next Txn struct */ 475 if (uAggregPktsNum == 0) 476 { 477 pTxn = (TTxnStruct*)&(pRxXfer->aTxnStruct[pRxXfer->uCurrTxnIndex]); 478 pTxn->uHwAddr = SLV_MEM_DATA; 479 480 /* Save first mem-block of first aggregated packet! */ 481 uFirstMemBlkAddr = SLV_MEM_CP_VALUE(uRxDesc, pRxXfer->uPacketMemoryPoolStart); 482 } 483 pTxn->aBuf[uAggregPktsNum] = pHostBuf + ALIGNMENT_SIZE(uRxDesc); 484 pTxn->aLen[uAggregPktsNum] = uBuffSize; 485 uAggregPktsNum++; 486 uTotalAggregLen += uBuffSize; 487 if (uAggregPktsNum >= pRxXfer->uMaxAggregPkts) 488 { 489 bIssueTxn = TI_TRUE; 490 } 491 pRxXfer->uDrvRxCntr++; 492 } 493 494 /* If buffer pending until freeing previous buffer, set Exit flag and if needed set IssueTxn flag. */ 495 else if (eBufStatus == RX_BUF_ALLOC_PENDING) 496 { 497 bExit = TI_TRUE; 498 pRxXfer->bPendingBuffer = TI_TRUE; 499 if (uAggregPktsNum > 0) 500 { 501 bIssueTxn = TI_TRUE; 502 } 503 #ifdef TI_DBG 504 pRxXfer->tDbgStat.uCountBufPend++; 505 #endif 506 } 507 508 /* If no buffer due to out-of-memory, set DropLastPkt flag and if needed set IssueTxn flag. */ 509 else 510 { 511 bDropLastPkt = TI_TRUE; 512 if (uAggregPktsNum > 0) 513 { 514 bIssueTxn = TI_TRUE; 515 } 516 #ifdef TI_DBG 517 pRxXfer->tDbgStat.uCountBufNoMem++; 518 #endif 519 } 520 } 521 } 522 523 /* If no more packets, set Exit flag and if needed set IssueTxn flag. */ 524 else 525 { 526 bExit = TI_TRUE; 527 if (uAggregPktsNum > 0) 528 { 529 bIssueTxn = TI_TRUE; 530 } 531 } 532 533 534 /* If required to send Rx packet(s) transaction */ 535 if (bIssueTxn) 536 { 537 /* If not all 4 Txn buffers are used, reset first unused buffer length for indication */ 538 if (uAggregPktsNum < MAX_XFER_BUFS) 539 { 540 pTxn->aLen[uAggregPktsNum] = 0; 541 } 542 543 eTxnStatus = rxXfer_IssueTxn (pRxXfer, uFirstMemBlkAddr); 544 545 if (eTxnStatus == TXN_STATUS_COMPLETE) 546 { 547 /* Forward received packet to the upper layers */ 548 rxXfer_ForwardPacket (pRxXfer, pTxn); 549 } 550 else if (eTxnStatus == TXN_STATUS_PENDING) 551 { 552 /* Decrease the number of available txn structures */ 553 pRxXfer->uAvailableTxn--; 554 } 555 else 556 { 557 TRACE3(pRxXfer->hReport, REPORT_SEVERITY_ERROR , "rxXfer_Handle: Status=%d, DrvCntr=%d, RxDesc=0x%x\n", eTxnStatus, pRxXfer->uDrvRxCntr, uRxDesc); 558 } 559 560 #ifdef TI_DBG 561 pRxXfer->tDbgStat.uCountPktAggreg[uAggregPktsNum - 1]++; 562 #endif 563 564 uAggregPktsNum = 0; 565 uTotalAggregLen = 0; 566 bIssueTxn = TI_FALSE; 567 pRxXfer->uCurrTxnIndex = (pRxXfer->uCurrTxnIndex + 1) % MAX_CONSECUTIVE_READ_TXN; 568 } 569 570 /* If last packet should be dropped (no memory for host buffer) */ 571 if (bDropLastPkt) 572 { 573 /* Increment driver packets counter before calling rxXfer_IssueTxn() */ 574 pRxXfer->uDrvRxCntr++; 575 576 /* Read packet to dummy buffer and ignore it (no callback needed) */ 577 uFirstMemBlkAddr = SLV_MEM_CP_VALUE(uRxDesc, pRxXfer->uPacketMemoryPoolStart); 578 pTxn = (TTxnStruct*)&pRxXfer->aTxnStruct[pRxXfer->uCurrTxnIndex]; 579 BUILD_TTxnStruct(pTxn, SLV_MEM_DATA, pRxXfer->aTempBuffer, uBuffSize, (TTxnDoneCb)rxXfer_PktDropTxnDoneCb, hRxXfer) 580 eTxnStatus = rxXfer_IssueTxn (pRxXfer, uFirstMemBlkAddr); 581 if (eTxnStatus == TXN_STATUS_PENDING) 582 { 583 pRxXfer->uAvailableTxn--; 584 } 585 pRxXfer->uCurrTxnIndex = (pRxXfer->uCurrTxnIndex + 1) % MAX_CONSECUTIVE_READ_TXN; 586 bDropLastPkt = TI_FALSE; 587 } 588 589 /* Can't process more packets so exit */ 590 if (bExit) 591 { 592 CL_TRACE_END_L2("tiwlan_drv.ko", "CONTEXT", "RX", ""); 593 return TI_OK; 594 } 595 596 } /* End of while(1) */ 597 598 /* Unreachable code */ 599 600 #endif 601 } 602 603 604 /**************************************************************************** 605 * rxXfer_IssueTxn() 606 **************************************************************************** 607 * DESCRIPTION: 608 * 609 * INPUTS: 610 * 611 * OUTPUT: 612 * 613 * RETURNS: 614 ****************************************************************************/ 615 static ETxnStatus rxXfer_IssueTxn (TI_HANDLE hRxXfer, TI_UINT32 uFirstMemBlkAddr) 616 { 617 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 618 TI_UINT32 uIndex = pRxXfer->uCurrTxnIndex; 619 TTxnStruct *pTxn; 620 ETxnStatus eStatus; 621 622 /* Write the next mem block that we want to read */ 623 pTxn = &pRxXfer->aSlaveRegTxn[uIndex].tTxnStruct; 624 pTxn->uHwAddr = SLV_REG_DATA; 625 pRxXfer->aSlaveRegTxn[uIndex].uRegData = ENDIAN_HANDLE_LONG(uFirstMemBlkAddr); 626 pRxXfer->aSlaveRegTxn[uIndex].uRegAdata = ENDIAN_HANDLE_LONG(uFirstMemBlkAddr + 4); 627 twIf_Transact(pRxXfer->hTwIf, pTxn); 628 629 /* Issue the packet(s) read transaction (prepared in rxXfer_Handle) */ 630 pTxn = &pRxXfer->aTxnStruct[uIndex]; 631 eStatus = twIf_Transact(pRxXfer->hTwIf, pTxn); 632 633 /* Write driver packets counter to FW. This write automatically generates interrupt to FW */ 634 /* Note: Workaround for WL6-PG1.0 is still needed for PG2.0 ==> if (pRxXfer->bChipIs1273Pg10) */ 635 pTxn = &pRxXfer->aCounterTxn[uIndex].tTxnStruct; 636 pTxn->uHwAddr = RX_DRIVER_COUNTER_ADDRESS; 637 pRxXfer->aCounterTxn[uIndex].uCounter = ENDIAN_HANDLE_LONG(pRxXfer->uDrvRxCntr); 638 twIf_Transact(pRxXfer->hTwIf, pTxn); 639 640 TRACE5(pRxXfer->hReport, REPORT_SEVERITY_INFORMATION , "rxXfer_IssueTxn: Counter-Txn: HwAddr=0x%x, Len0=%d, Data0=%d, DrvCount=%d, TxnParams=0x%x\n", pTxn->uHwAddr, pTxn->aLen[0], *(TI_UINT32 *)(pTxn->aBuf[0]), pRxXfer->uDrvRxCntr, pTxn->uTxnParams); 641 642 /* Return the status of the packet(s) transaction - COMPLETE, PENDING or ERROR */ 643 return eStatus; 644 } 645 646 647 /**************************************************************************** 648 * rxXfer_SetRxDirectAccessParams() 649 **************************************************************************** 650 * DESCRIPTION: 651 * 652 * INPUTS: 653 * 654 * OUTPUT: 655 * 656 * RETURNS: 657 ****************************************************************************/ 658 void rxXfer_SetRxDirectAccessParams (TI_HANDLE hRxXfer, TDmaParams *pDmaParams) 659 { 660 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 661 662 pRxXfer->uPacketMemoryPoolStart = pDmaParams->PacketMemoryPoolStart; 663 } 664 665 666 /**************************************************************************** 667 * rxXfer_TxnDoneCb() 668 **************************************************************************** 669 * DESCRIPTION: Forward the packet to the registered CB 670 * 671 * INPUTS: 672 * 673 * OUTPUT: 674 * 675 * RETURNS: 676 ****************************************************************************/ 677 static void rxXfer_TxnDoneCb (TI_HANDLE hRxXfer, TTxnStruct *pTxn) 678 { 679 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 680 CL_TRACE_START_L2(); 681 682 /* Increase the number of available txn structures */ 683 pRxXfer->uAvailableTxn++; 684 685 /* Forward received packet to the upper layers */ 686 rxXfer_ForwardPacket (pRxXfer, pTxn); 687 688 /* If we exited the handler upon pending-buffer, call it again to handle further packets if any */ 689 if (pRxXfer->bPendingBuffer) 690 { 691 pRxXfer->bPendingBuffer = TI_FALSE; 692 rxXfer_Handle (hRxXfer); 693 } 694 695 CL_TRACE_END_L2("tiwlan_drv.ko", "INHERIT", "RX", ""); 696 } 697 698 699 /**************************************************************************** 700 * rxXfer_PktDropTxnDoneCb() 701 **************************************************************************** 702 * DESCRIPTION: Dummy CB for case of dropping a packet due to out-of-memory. 703 * 704 * INPUTS: 705 * 706 * OUTPUT: 707 * 708 * RETURNS: 709 ****************************************************************************/ 710 static void rxXfer_PktDropTxnDoneCb (TI_HANDLE hRxXfer, TTxnStruct *pTxn) 711 { 712 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 713 714 /* Increase the number of available txn structures */ 715 pRxXfer->uAvailableTxn++; 716 717 /* Restore the regular TxnDone callback to the used structure */ 718 pTxn->fTxnDoneCb = (TTxnDoneCb)rxXfer_TxnDoneCb; 719 pTxn->hCbHandle = hRxXfer; 720 } 721 722 723 /**************************************************************************** 724 * RxXfer_ReStart() 725 **************************************************************************** 726 * DESCRIPTION: RxXfer_ReStart the RxXfer module object (called by the recovery) 727 * 728 * INPUTS: hRxXfer - The object to free 729 * 730 * OUTPUT: None 731 * 732 * RETURNS: NONE 733 ****************************************************************************/ 734 void RxXfer_ReStart(TI_HANDLE hRxXfer, TI_BOOL bChipIs1273Pg10) 735 { 736 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 737 TTxnStruct* pTxn; 738 TI_UINT8 i; 739 740 /* remove the chipID check when WL6-PG1.0 becomes obsolete */ 741 pRxXfer->bChipIs1273Pg10 = bChipIs1273Pg10; 742 743 744 pRxXfer->uFwRxCntr = 0; 745 pRxXfer->uDrvRxCntr = 0; 746 pRxXfer->uCurrTxnIndex = 0; 747 pRxXfer->uMaxAggregLen = MAX_PACKET_SIZE; 748 pRxXfer->uAvailableTxn = MAX_CONSECUTIVE_READ_TXN - 1; 749 750 /* Scan all transaction array and release only pending transaction */ 751 for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++) 752 { 753 pTxn = &(pRxXfer->aTxnStruct[i]); 754 755 /* Check if buffer allocated and not the dummy one (has a different callback) */ 756 if ((pTxn->aBuf[0] != 0) && (pTxn->fTxnDoneCb == (TTxnDoneCb)rxXfer_TxnDoneCb)) 757 { 758 TI_UINT32 uBufNum; 759 RxIfDescriptor_t *pRxParams; 760 761 /* Go over the Txn occupied buffers and mark them as TAG_CLASS_UNKNOWN to be freed */ 762 for (uBufNum = 0; uBufNum < MAX_XFER_BUFS; uBufNum++) 763 { 764 /* If no more buffers, exit the loop */ 765 if (pTxn->aLen[uBufNum] == 0) 766 { 767 break; 768 } 769 770 pRxParams = (RxIfDescriptor_t *)(pTxn->aBuf[uBufNum]); 771 pRxParams->packet_class_tag = TAG_CLASS_UNKNOWN; 772 } 773 774 /* Call upper layer only to release the allocated buffer */ 775 rxXfer_ForwardPacket (pRxXfer, pTxn); 776 } 777 } 778 779 /* Fill the transaction structures fields that have constant values */ 780 for (i = 0; i < MAX_CONSECUTIVE_READ_TXN; i++) 781 { 782 /* First mem-block address (two consecutive registers) */ 783 pTxn = &(pRxXfer->aSlaveRegTxn[i].tTxnStruct); 784 TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) 785 BUILD_TTxnStruct(pTxn, SLV_REG_DATA, &pRxXfer->aSlaveRegTxn[i].uRegData, REGISTER_SIZE*2, NULL, NULL) 786 787 /* The packet(s) read transaction */ 788 pTxn = &(pRxXfer->aTxnStruct[i]); 789 TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_READ, TXN_FIXED_ADDR) 790 pTxn->fTxnDoneCb = (TTxnDoneCb)rxXfer_TxnDoneCb; 791 pTxn->hCbHandle = hRxXfer; 792 793 /* The driver packets counter */ 794 pTxn = &(pRxXfer->aCounterTxn[i].tTxnStruct); 795 TXN_PARAM_SET(pTxn, TXN_LOW_PRIORITY, TXN_FUNC_ID_WLAN, TXN_DIRECTION_WRITE, TXN_INC_ADDR) 796 BUILD_TTxnStruct(pTxn, RX_DRIVER_COUNTER_ADDRESS, &pRxXfer->aCounterTxn[i].uCounter, REGISTER_SIZE, NULL, NULL) 797 } 798 799 } 800 801 802 /**************************************************************************** 803 * rxXfer_RegisterErrCb() 804 **************************************************************************** 805 * DESCRIPTION: Register Error CB 806 * 807 * INPUTS: 808 * hRxXfer - The object 809 * ErrCb - The upper layer CB function for error handling 810 * hErrCb - The CB function handle 811 * 812 * OUTPUT: None 813 * 814 * RETURNS: void 815 ****************************************************************************/ 816 void rxXfer_RegisterErrCb (TI_HANDLE hRxXfer, void *fErrCb, TI_HANDLE hErrCb) 817 { 818 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 819 820 /* Save upper layer (health monitor) CB for recovery from fatal error */ 821 pRxXfer->fErrCb = (TFailureEventCb)fErrCb; 822 pRxXfer->hErrCb = hErrCb; 823 } 824 825 826 #ifdef TI_DBG 827 /**************************************************************************** 828 * rxXfer_ClearStats() 829 **************************************************************************** 830 * DESCRIPTION: 831 * 832 * INPUTS: 833 * pRxXfer The object 834 * 835 * OUTPUT: None 836 * 837 * RETURNS: TI_OK. 838 ****************************************************************************/ 839 void rxXfer_ClearStats (TI_HANDLE hRxXfer) 840 { 841 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 842 843 os_memoryZero (pRxXfer->hOs, &pRxXfer->tDbgStat, sizeof(TRxXferDbgStat)); 844 } 845 846 847 /**************************************************************************** 848 * rxXfer_PrintStats() 849 **************************************************************************** 850 * DESCRIPTION: . 851 * 852 * INPUTS: 853 * pRxXfer The object 854 * 855 * OUTPUT: None 856 * 857 * RETURNS: TI_OK. 858 ****************************************************************************/ 859 void rxXfer_PrintStats (TI_HANDLE hRxXfer) 860 { 861 #ifdef REPORT_LOG 862 TRxXfer *pRxXfer = (TRxXfer *)hRxXfer; 863 864 WLAN_OS_REPORT(("Print RX Xfer module info\n")); 865 WLAN_OS_REPORT(("=========================\n")); 866 WLAN_OS_REPORT(("uMaxAggregPkts = %d\n", pRxXfer->uMaxAggregPkts)); 867 WLAN_OS_REPORT(("uMaxAggregLen = %d\n", pRxXfer->uMaxAggregLen)); 868 WLAN_OS_REPORT(("FW counter = %d\n", pRxXfer->uFwRxCntr)); 869 WLAN_OS_REPORT(("Drv counter = %d\n", pRxXfer->uDrvRxCntr)); 870 WLAN_OS_REPORT(("AvailableTxn = %d\n", pRxXfer->uAvailableTxn)); 871 WLAN_OS_REPORT(("uCountFwEvents = %d\n", pRxXfer->tDbgStat.uCountFwEvents)); 872 WLAN_OS_REPORT(("uCountPktsForward = %d\n", pRxXfer->tDbgStat.uCountPktsForward)); 873 WLAN_OS_REPORT(("uCountBufPend = %d\n", pRxXfer->tDbgStat.uCountBufPend)); 874 WLAN_OS_REPORT(("uCountBufNoMem = %d\n", pRxXfer->tDbgStat.uCountBufNoMem)); 875 WLAN_OS_REPORT(("uCountPktAggreg-1 = %d\n", pRxXfer->tDbgStat.uCountPktAggreg[0])); 876 WLAN_OS_REPORT(("uCountPktAggreg-2 = %d\n", pRxXfer->tDbgStat.uCountPktAggreg[1])); 877 WLAN_OS_REPORT(("uCountPktAggreg-3 = %d\n", pRxXfer->tDbgStat.uCountPktAggreg[2])); 878 WLAN_OS_REPORT(("uCountPktAggreg-4 = %d\n", pRxXfer->tDbgStat.uCountPktAggreg[3])); 879 #endif 880 } 881 #endif 882