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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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 ****************************************************************************/ 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