1 /**************************************************************************** 2 **+-----------------------------------------------------------------------+** 3 **| |** 4 **| Copyright(c) 1998 - 2008 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 * 38 * MODULE: txResult.c 39 * 40 * PURPOSE: Handle packets Tx results upon Tx-complete from the FW. 41 * 42 * DESCRIPTION: 43 * ============ 44 * This module is called upon Tx-complete from FW. 45 * It retrieves the transmitted packets results from the FW TxResult table and 46 * calls the upper layer callback function for each packet with its results. 47 * 48 ****************************************************************************/ 49 50 #include "osTIType.h" 51 #include "whalCommon.h" 52 #include "TNETWIF.h" 53 #include "whalHwDefs.h" 54 #include "txResult_api.h" 55 #include "TNETW_Driver_types.h" 56 #include "FwEvent_api.h" 57 #include "txResult.h" /* Local definitions */ 58 59 /****************** static function decleration *****************************************/ 60 static void txResult_handleNewEntries(txResultObj_t *pTxResult); 61 static void txResult_StateMachine(TI_HANDLE hTxResult,UINT8 module_id ,TI_STATUS status); 62 static TI_STATUS txResult_writeNewEntries(txResultObj_t *pTxResult,UINT8 currBuffer); 63 64 65 /**************************************************************************** 66 * txResult_Create() 67 **************************************************************************** 68 * DESCRIPTION: Create the Tx-Result object 69 * 70 * INPUTS: hOs 71 * 72 * OUTPUT: None 73 * 74 * RETURNS: The Created object 75 ****************************************************************************/ 76 TI_HANDLE txResult_Create(TI_HANDLE hOs) 77 { 78 txResultObj_t *pTxResult; 79 80 pTxResult = os_memoryAlloc(hOs, sizeof(txResultObj_t)); 81 if (pTxResult == NULL) 82 return NULL; 83 84 os_memoryZero(hOs, pTxResult, sizeof(txResultObj_t)); 85 86 pTxResult->hOs = hOs; 87 88 return( (TI_HANDLE)pTxResult ); 89 } 90 91 92 /**************************************************************************** 93 * txResult_Destroy() 94 **************************************************************************** 95 * DESCRIPTION: Destroy the Tx-Result object 96 * 97 * INPUTS: hTxResult - The object to free 98 * 99 * OUTPUT: None 100 * 101 * RETURNS: OK or NOK 102 ****************************************************************************/ 103 TI_STATUS txResult_Destroy(TI_HANDLE hTxResult) 104 { 105 txResultObj_t *pTxResult = (txResultObj_t *)hTxResult; 106 107 if (pTxResult) 108 os_memoryFree(pTxResult->hOs, pTxResult, sizeof(txResultObj_t)); 109 110 return OK; 111 } 112 113 114 /**************************************************************************** 115 * txResult_init() 116 **************************************************************************** 117 DESCRIPTION: 118 ============ 119 Initialize the txResult module. 120 ****************************************************************************/ 121 TI_STATUS txResult_init(TI_HANDLE hTxResult, TI_HANDLE hReport, TI_HANDLE hTNETWIF, TI_HANDLE hFwEvent) 122 { 123 txResultObj_t *pTxResult = (txResultObj_t *)hTxResult; 124 125 pTxResult->hReport = hReport; 126 pTxResult->hTNETWIF = hTNETWIF; 127 pTxResult->hFwEvent = hFwEvent; 128 129 txResult_restart(pTxResult); 130 131 #ifdef TI_DBG 132 os_memoryZero( pTxResult->hOs, &(pTxResult->txCompleteDepthHistogram), sizeof(UINT32) * FW_TX_CMPLT_BLOCK_SIZE ); 133 #endif 134 135 FwEvent_Enable(pTxResult->hFwEvent, ACX_INTR_TX_RESULT); 136 137 return OK; 138 } 139 140 141 /**************************************************************************** 142 * txResult_restart() 143 **************************************************************************** 144 DESCRIPTION: 145 ============ 146 Restarts the Tx-Result module. 147 Should be called upon init and recovery!! 148 Shouldn't be called upon disconnect, since the FW provides Tx-Complete 149 for all pending packets in FW!! 150 ****************************************************************************/ 151 TI_STATUS txResult_restart(TI_HANDLE hTxResult) 152 { 153 txResultObj_t *pTxResult = (txResultObj_t *)hTxResult; 154 155 pTxResult->TxCmpltStartPointIterator = 0; 156 157 return OK; 158 } 159 160 161 /**************************************************************************** 162 * txResult_setHwInfo() 163 **************************************************************************** 164 * DESCRIPTION: 165 * Called after the HW configuration upon init or recovery. 166 * Store the Tx-result table HW address. 167 * 168 * INPUTS: 169 * hTxXfer The object 170 * pDataPathParams Pointer to the HW Addresses 171 * 172 * OUTPUT: None 173 * 174 * RETURNS: None 175 ****************************************************************************/ 176 void txResult_setHwInfo(TI_HANDLE hTxResult, ACXDataPathParamsResp_t *pDataPathParams) 177 { 178 txResultObj_t *pTxResult = (txResultObj_t *)hTxResult; 179 180 pTxResult->txResultTableAddr = pDataPathParams->txCompleteAddr; 181 182 /* Print of the Tx Result Table address */ 183 WLAN_REPORT_INFORMATION(pTxResult->hReport, TX_RESULT_MODULE_LOG, 184 ("Get Tx-Result-Table HW-Addr: 0x%x\n", pTxResult->txResultTableAddr)); 185 } 186 187 188 /**************************************************************************** 189 * txResult_TxCmpltIntrCB() 190 **************************************************************************** 191 * DESCRIPTION: 192 * ============ 193 * Called upon Tx-complete interrupt from the FW. 194 * 195 * INPUTS: TI_HANDLE hTxResult - the txResult object handle. 196 * 197 * OUTPUT: None 198 * 199 * RETURNS: TNETWIF_OK in Synch mode or TNETWIF_PENDING on Asynch mode. 200 ***************************************************************************/ 201 202 #if FW_TX_CMPLT_BLOCK_SIZE & (FW_TX_CMPLT_BLOCK_SIZE - 1) 203 #error "FW_TX_CMPLT_BLOCK_SIZE must be power of 2" 204 #endif 205 206 TI_STATUS txResult_TxCmpltIntrCB (TI_HANDLE hTxResult) 207 { 208 txResultObj_t *pTxResult = (txResultObj_t *)hTxResult; 209 210 if (TX_RESULT_STATE_IDLE != pTxResult->state) 211 { 212 WLAN_REPORT_ERROR(pTxResult->hReport,TX_RESULT_MODULE_LOG, 213 ("rxXfer_RxEvent called in state %d !!!\n",pTxResult->state)); 214 return TNETWIF_ERROR; 215 } 216 217 /* assume that we are in synch bus until otherwise is proven */ 218 pTxResult->bSync = TRUE; 219 220 /* 0,OK has no meaning */ 221 txResult_StateMachine(hTxResult,0,OK); 222 223 return pTxResult->returnValue; 224 } 225 226 227 /**************************************************************************** 228 * txResult_StateMachine() 229 **************************************************************************** 230 * DESCRIPTION: main SM of the module.called in IDLE state by txResult_TxCmpltIntrCB() on 231 * Tx Complete interrupt from the FW. 232 * Reads all Tx-Result cyclic table from the FW. 233 * Goes over the valid entries (containing unread Tx-results) and calls the 234 * upper layer callback function for each packet with its results. 235 * At the end - writes all new results back to the FW 236 * The flow of the SM is by that order: 237 * IDLE -> READING -> WRITING1 -> WRITING2 -> EXIT 238 * On synch mode - each state is called in the same context in the while loop. 239 * On Asynch mode - each state returns TNETWIF_PENDING and exits the SM.The CB of 240 * each Asynch is the SM, that will continue the handling. 241 * 242 * 243 * 244 * INPUTS: module_id - not used (for prototype only). 245 * status - not used (for prototype only). 246 * 247 * OUTPUT: returnValue - This parameter is used to indicate the FwEvent mosule about the status of 248 * the client.if (returnValue == TNETWIF_OK) than client finished working (synch mode) 249 * if (returnValue == TNETWIF_PENDING) than FwEvent module is waiting to be notified 250 * that client finished the handling (Asynch mode) 251 * 252 * RETURNS: None 253 ****************************************************************************/ 254 static void txResult_StateMachine(TI_HANDLE hTxResult,UINT8 module_id ,TI_STATUS status) 255 { 256 txResultObj_t *pTxResult = (txResultObj_t *)hTxResult; 257 258 pTxResult->returnValue = OK; 259 260 /* this while loop will continue till the exit or when waiting for the CB due to 261 memory transfer operation pending for DMA to complete */ 262 while (TNETWIF_PENDING != pTxResult->returnValue) 263 { 264 WLAN_REPORT_INFORMATION(pTxResult->hReport,TX_RESULT_MODULE_LOG, 265 ("txResult SM: state = %d, rc = %d, Buffers = %d\n", 266 pTxResult->state,pTxResult->returnValue,pTxResult->numOfBuffers)); 267 268 switch(pTxResult->state) 269 { 270 case TX_RESULT_STATE_IDLE: 271 /* Read all Tx-Result table from the FW (Synch or Asynch) */ 272 pTxResult->returnValue = TNETWIF_ReadMemOpt (pTxResult->hTNETWIF, 273 pTxResult->txResultTableAddr, 274 PADREAD (pTxResult->TxCmpltAttr), 275 FW_TX_CMPLT_BLOCK_SIZE * sizeof(TxResultDescriptor_t), 276 FW_EVENT_MODULE_ID, 277 txResult_StateMachine,hTxResult); 278 279 pTxResult->state = TX_RESULT_STATE_READING; 280 break; 281 282 case TX_RESULT_STATE_READING: 283 /* process the new table and call the upper layers to handle results. 284 Also update numOfBuffers & entry (from, to) */ 285 txResult_handleNewEntries(pTxResult); 286 287 if (TX_RESULT_NO_BUFFER == pTxResult->numOfBuffers) 288 { /* no need to write to FW - exit SM */ 289 pTxResult->state = TX_RESULT_STATE_EXIT; 290 } 291 else 292 { 293 pTxResult->state = TX_RESULT_STATE_WRITING1; 294 } 295 break; 296 case TX_RESULT_STATE_WRITING1: 297 298 pTxResult->returnValue = txResult_writeNewEntries(pTxResult,0); 299 if (TX_RESULT_ONE_BUFFER == pTxResult->numOfBuffers) 300 { /* only one write was needed - exit SM */ 301 pTxResult->state = TX_RESULT_STATE_EXIT; 302 } 303 else 304 { 305 pTxResult->state = TX_RESULT_STATE_WRITING2; 306 } 307 break; 308 309 case TX_RESULT_STATE_WRITING2: 310 311 pTxResult->returnValue = txResult_writeNewEntries(pTxResult,1); 312 313 pTxResult->state = TX_RESULT_STATE_EXIT; 314 break; 315 316 case TX_RESULT_STATE_EXIT: 317 318 if (FALSE == pTxResult->bSync) 319 { /* Async bus - call FwEvent for notifying the completion */ 320 FwEvent_EventComplete(pTxResult->hFwEvent, TNETWIF_OK); 321 } 322 else /* This is the synch case - we should return TNETWIF_OK */ 323 { 324 pTxResult->returnValue = TNETWIF_OK; 325 } 326 pTxResult->state = TX_RESULT_STATE_IDLE; 327 328 return; 329 330 default: 331 WLAN_REPORT_ERROR(pTxResult->hReport,HAL_TX_MODULE_LOG,("rxXfer_StateMachine Unknown state = %d\n", 332 pTxResult->state)); 333 } 334 } 335 336 /* if we are here - we got TNETWIF_PENDING, so we are in Async mode */ 337 pTxResult->bSync = FALSE; 338 339 if (TNETWIF_ERROR == pTxResult->returnValue) 340 { 341 WLAN_REPORT_ERROR(pTxResult->hReport,TX_RESULT_MODULE_LOG, 342 ("txResult_StateMachine returning TNETWIF_ERROR in state %d !!!\n",pTxResult->state)); 343 } 344 } 345 346 347 /**************************************************************************** 348 * txResult_handleNewEntries() 349 **************************************************************************** 350 * DESCRIPTION: 351 * ============ 352 * Goes over the valid entries (containing unread Tx-results) and calls the 353 * upper layer callback function for each packet with its results. 354 * 355 * INPUTS: TI_HANDLE hTxResult - the txResult object handle. 356 * 357 * OUTPUT: 1) number of buffers to write on . (The case of 2 buffers can happen 358 * in case of wrap around - and we need 2 different writes to FW) 359 * 360 * 2) start-end address of the buffers to be written 361 * 362 * RETURNS: 363 ***************************************************************************/ 364 static void txResult_handleNewEntries(txResultObj_t *pTxResult) 365 { 366 TxResultDescriptor_t *pCurrentEntry; /* Points to the current table entry */ 367 UINT32 uIndex; /* The current table entry */ 368 UINT32 uNumOfTxComplete; /* Counts contiguous valid entries (i.e. waiting for host read) */ 369 UINT32 uLoopCount; /* Used only to prevent endless loop */ 370 371 uIndex = pTxResult->TxCmpltStartPointIterator; 372 uNumOfTxComplete = 0; 373 374 /* Begin the loop only from the point where the last Tx Complete was received before */ 375 for (uLoopCount = uNumOfTxComplete = 0; uLoopCount < FW_TX_CMPLT_BLOCK_SIZE; uLoopCount ++) 376 { 377 /* 378 * Update current entry. 379 * Take into account that uIndex may be 16, so make & 0xf 380 */ 381 pCurrentEntry = &pTxResult->TxCmpltAttr[uIndex & (FW_TX_CMPLT_BLOCK_SIZE - 1)]; 382 383 WLAN_REPORT_INFORMATION(pTxResult->hReport, TX_RESULT_MODULE_LOG, 384 ("Tx Result Entry %d: Done1/2=%d/%d, DescID=%d, Status=%d, Rate=%d, Duration=%d, Retries=%d, HandleTime=%d, SecurNum=%d\n", 385 uIndex, pCurrentEntry->done1, pCurrentEntry->done2, pCurrentEntry->descID, pCurrentEntry->status, 386 pCurrentEntry->actualRate, pCurrentEntry->mediumUsage, pCurrentEntry->ackFailures, 387 pCurrentEntry->fwHandlingTime, pCurrentEntry->lsbSecuritySequenceNumber)); 388 389 /* If the current entry contains fresh Tx-result information */ 390 if (pCurrentEntry->done1 == 1 && pCurrentEntry->done2 == 1) 391 { 392 /* Call GWSI Tx-complete callback with current entry pointer. */ 393 /* It is assumed that the entry is only accessed in this context and only for reading. */ 394 pTxResult->sendPacketCompleteCB (pTxResult->sendPacketCompleteHandle, pCurrentEntry); 395 396 /* Clear entry */ 397 pCurrentEntry->done1 = 0; 398 pCurrentEntry->done2 = 0; 399 400 /* Increment the index to point to next entry (wrap around is handled below) */ 401 if (uIndex >= FW_TX_CMPLT_BLOCK_SIZE) 402 uIndex = 1; 403 else 404 uIndex ++; 405 406 uNumOfTxComplete ++; 407 } 408 else 409 break; 410 } 411 412 #ifdef TI_DBG 413 /* Update the TX result depth histogram */ 414 pTxResult->txCompleteDepthHistogram [uNumOfTxComplete] ++; 415 #endif 416 417 /* Copy the handled entries back to FW to clear them */ 418 if (uNumOfTxComplete) 419 { 420 /* No wrap. Make only 1 write */ 421 if (uIndex > pTxResult->TxCmpltStartPointIterator) 422 { 423 pTxResult->entry[0].from = pTxResult->TxCmpltStartPointIterator; 424 pTxResult->entry[0].to = uIndex; 425 pTxResult->numOfBuffers = TX_RESULT_ONE_BUFFER; 426 } 427 /* Wrap. Make 2 writes */ 428 else if (uIndex < pTxResult->TxCmpltStartPointIterator) 429 { 430 pTxResult->entry[0].from = pTxResult->TxCmpltStartPointIterator; 431 pTxResult->entry[0].to = FW_TX_CMPLT_BLOCK_SIZE; 432 pTxResult->entry[1].from = 0; 433 pTxResult->entry[1].to = uIndex; 434 pTxResult->numOfBuffers = TX_RESULT_TWO_BUFFERS; 435 } 436 /* Wrap, all 16 descriptors are filled. Make 1 write from index 0 */ 437 else 438 { 439 pTxResult->entry[0].from = 0; 440 pTxResult->entry[0].to = FW_TX_CMPLT_BLOCK_SIZE; 441 pTxResult->numOfBuffers = TX_RESULT_ONE_BUFFER; 442 } 443 444 } 445 else /* no new entry - no need to write buffers */ 446 { 447 pTxResult->numOfBuffers = TX_RESULT_NO_BUFFER; 448 } 449 /* 450 * Update start point iterator. 451 * Take into account that uIndex may be 16, so make & 0xf 452 */ 453 pTxResult->TxCmpltStartPointIterator = uIndex & (FW_TX_CMPLT_BLOCK_SIZE - 1); 454 } 455 456 457 /**************************************************************************** 458 * txResult_writeNewEntries() 459 **************************************************************************** 460 * DESCRIPTION: 461 * ============ 462 * Clears the read entries in the FW. 463 * 464 * 465 * INPUTS: pTxResult - the txResult object handle. 466 * currBuffer - number of buffer to write on (0 or 1) 467 * 468 * OUTPUT: None 469 * 470 * RETURNS: TNETWIF_OK in case of Synch call, TNETWIF_PENDING in case of Asynch call 471 * 472 * NOTE: please note that we are running over the last WORD before the first entry 473 * since we need to save this place for the bus handling 474 ***************************************************************************/ 475 static TI_STATUS txResult_writeNewEntries(txResultObj_t *pTxResult,UINT8 currBuffer) 476 { 477 /* 478 * Write to firmware - NOTE: that we are running over the last WORD before the first entry 479 * since we need to save this place for the bus handling 480 */ 481 return TNETWIF_WriteMemOpt (pTxResult->hTNETWIF, 482 pTxResult->txResultTableAddr + pTxResult->entry[currBuffer].from * sizeof(TxResultDescriptor_t), 483 PADWRITE (&pTxResult->TxCmpltAttr[pTxResult->entry[currBuffer].from]), 484 (pTxResult->entry[currBuffer].to - pTxResult->entry[currBuffer].from) * sizeof(TxResultDescriptor_t), 485 FW_EVENT_MODULE_ID, 486 txResult_StateMachine, 487 (TI_HANDLE)pTxResult); 488 489 } 490 491 /**************************************************************************** 492 * txResult_RegisterCB() 493 **************************************************************************** 494 * DESCRIPTION: Register the upper driver Tx-Result callback functions. 495 ****************************************************************************/ 496 void txResult_RegisterCB(TI_HANDLE hTxResult, tiUINT32 CallBackID, void *CBFunc, TI_HANDLE CBObj) 497 { 498 txResultObj_t* pTxResult = (txResultObj_t*)hTxResult; 499 500 switch(CallBackID) 501 { 502 /* Set Tx-Complete callback */ 503 case TX_RESULT_SEND_PKT_COMPLETE: 504 pTxResult->sendPacketCompleteCB = (SendPacketCompleteCB_t)CBFunc; 505 pTxResult->sendPacketCompleteHandle = CBObj; 506 break; 507 508 default: 509 WLAN_REPORT_ERROR(pTxResult->hReport, TX_RESULT_MODULE_LOG, ("txResult_RegisterCB - Illegal value\n")); 510 return; 511 } 512 } 513 514 515 /**************************************************************************** 516 * txResult_RegisterCB() 517 **************************************************************************** 518 * DESCRIPTION: Prints TX result debig information. 519 ****************************************************************************/ 520 void txResult_printInfo(TI_HANDLE hTxResult) 521 { 522 #ifdef TI_DBG 523 txResultObj_t* pTxResult = (txResultObj_t*)hTxResult; 524 525 WLAN_OS_REPORT(("Tx-Result Module Information:\n")); 526 WLAN_OS_REPORT(("=============================\n\n")); 527 528 WLAN_OS_REPORT((" FW result array depth histogram:\n")); 529 WLAN_OS_REPORT((" --------------------------------\n\n")); 530 WLAN_OS_REPORT((" depth: %8d %8d %8d %8d %8d %8d\n", 0, 1, 2, 3, 4, 5)); 531 WLAN_OS_REPORT((" INTR: %8d %8d %8d %8d %8d %8d\n\n", 532 pTxResult->txCompleteDepthHistogram[ 0 ], 533 pTxResult->txCompleteDepthHistogram[ 1 ], 534 pTxResult->txCompleteDepthHistogram[ 2 ], 535 pTxResult->txCompleteDepthHistogram[ 3 ], 536 pTxResult->txCompleteDepthHistogram[ 4 ], 537 pTxResult->txCompleteDepthHistogram[ 5 ])); 538 WLAN_OS_REPORT((" depth: %8d %8d %8d %8d %8d %8d\n", 6, 7, 8, 9, 10, 11)); 539 WLAN_OS_REPORT((" INTR: %8d %8d %8d %8d %8d %8d\n\n", 540 pTxResult->txCompleteDepthHistogram[ 6 ], 541 pTxResult->txCompleteDepthHistogram[ 7 ], 542 pTxResult->txCompleteDepthHistogram[ 8 ], 543 pTxResult->txCompleteDepthHistogram[ 9 ], 544 pTxResult->txCompleteDepthHistogram[ 10 ], 545 pTxResult->txCompleteDepthHistogram[ 11 ])); 546 WLAN_OS_REPORT((" depth: %8d %8d %8d %8d %8d\n", 12, 13, 14, 15, 16)); 547 WLAN_OS_REPORT((" INTR: %8d %8d %8d %8d %8d\n\n", 548 pTxResult->txCompleteDepthHistogram[ 12 ], 549 pTxResult->txCompleteDepthHistogram[ 13 ], 550 pTxResult->txCompleteDepthHistogram[ 14 ], 551 pTxResult->txCompleteDepthHistogram[ 15 ], 552 pTxResult->txCompleteDepthHistogram[ 16 ])); 553 #endif 554 } 555 556 /**************************************************************************** 557 * txResult_RegisterCB() 558 **************************************************************************** 559 * DESCRIPTION: Prints TX result debig information. 560 ****************************************************************************/ 561 void txResult_clearInfo(TI_HANDLE hTxResult) 562 { 563 #ifdef TI_DBG 564 txResultObj_t* pTxResult = (txResultObj_t*)hTxResult; 565 566 os_memoryZero( pTxResult->hOs, pTxResult->txCompleteDepthHistogram, sizeof(UINT32) * FW_TX_CMPLT_BLOCK_SIZE ); 567 #endif 568 } 569 570