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: envList.c */ 39 /* PURPOSE: Envelope list implementation */ 40 /* */ 41 /***************************************************************************/ 42 43 #include "MsduList.h" 44 #include "osTIType.h" 45 #include "paramIn.h" 46 #include "osApi.h" 47 48 /************************************************************************* 49 * msduList_CreateNewMsduList * 50 ************************************************************************* 51 DESCRIPTION: This function creates new Msdu list. 52 53 INPUT: maxNumOfElements : The maximum number of elements allowd 54 pOs : Pointer to os abstraction layer 55 56 OUTPUT: 57 58 RETURN: MsduList_T 59 *************************************************************************/ 60 MsduList_t* msduList_CreateNewMsduList( TI_HANDLE hOs ) 61 { 62 63 MsduList_t* msduList = (MsduList_t*) os_memoryAlloc(hOs,sizeof(MsduList_t)); 64 if( msduList == NULL ) 65 return NULL; 66 67 if(( msduList->hCriticalSectionProtect = os_protectCreate(hOs)) == NULL) 68 { 69 WLAN_OS_REPORT(("FATAL ERROR: Could not Create Critical Section Protection for Msdu List - Aborting\n")); 70 71 /* free Msdu List Control Block */ 72 os_memoryFree(hOs, msduList, sizeof(MsduList_t)); 73 74 return NULL; 75 } 76 77 msduList->hOs = hOs; 78 79 msduList->first = NULL; 80 msduList->last = NULL; 81 msduList->maxNumOfMsdu = 0; 82 msduList->CurrNumOfMsdu = 0; 83 msduList->ovFlowPolicy = DROP_NEW_PACKET; 84 msduList->numOfOverFlow = 0; 85 msduList->maxCurrOfMsdu =0; 86 87 return msduList; 88 } 89 90 /************************************************************************* 91 * msduList_ConfigMsduList * 92 ************************************************************************* 93 DESCRIPTION: This function configure the Msdu list. 94 95 INPUT: *this : A pointer to the list to configure 96 msduListConfig : Pointer to the Msdu list configuration 97 structure. 98 99 OUTPUT: 100 101 RETURN: TI_STATUS: OK/NOK 102 *************************************************************************/ 103 TI_STATUS msduList_ConfigMsduList( MsduList_t* this, TI_HANDLE hMemMgr, 104 TI_HANDLE hReport, TI_HANDLE hOs,INT16 maxNumOfElements) 105 { 106 if( hOs == NULL || hReport == NULL || 107 this == NULL || hMemMgr == NULL) 108 return NOK; 109 110 this->hReport = hReport; 111 this->hMemMgr = hMemMgr; 112 this->hOs = hOs; 113 this->maxNumOfMsdu = maxNumOfElements; 114 115 this->useAdmissionAlgo = FALSE; 116 this->credit = 0; 117 this->enableTransmissionTime = 0; 118 this->lastTimeStamp = 0; 119 this->mediumTime = 0; 120 this->totalUsedTime = 0; 121 122 this->highMediumUsageThreshold = 0; 123 this->lowMediumUsageThreshold = 0; 124 125 126 return OK; 127 128 } 129 130 /************************************************************************* 131 * msduList_SetMsduListNumOfElements * 132 ************************************************************************* 133 DESCRIPTION: This function configure the Msdu list max num of elements. 134 135 INPUT: *this : A pointer to the list to configure 136 maxNumOfElements: max num of elements. 137 OUTPUT: 138 139 RETURN: TI_STATUS: OK/NOK 140 *************************************************************************/ 141 142 TI_STATUS msduList_SetMsduListNumOfElements( MsduList_t* this, UINT16 maxNumOfElements) 143 { 144 if(this == NULL) 145 return NOK; 146 147 this->maxNumOfMsdu = maxNumOfElements; 148 149 return OK; 150 151 } 152 153 /************************************************************************* 154 * msduList_SetMsduListOverFlowPolicy * 155 ************************************************************************* 156 DESCRIPTION: This function configure the Msdu list policy in case of over flow . 157 158 INPUT: *this : A pointer to the list to configure 159 QueueOvFlowPolicy: over flow polict - new packet drop or old packet drop. 160 OUTPUT: 161 162 RETURN: TI_STATUS: OK/NOK 163 *************************************************************************/ 164 165 TI_STATUS msduList_SetMsduListOverFlowPolicy( MsduList_t* this, qOvFlowPolicy_e QueueOvFlowPolicy) 166 { 167 if(this == NULL) 168 return NOK; 169 170 this->ovFlowPolicy = QueueOvFlowPolicy; 171 172 return OK; 173 174 } 175 176 177 /************************************************************************* 178 * msduList_FreeMsduList * 179 ************************************************************************* 180 DESCRIPTION: This function free the Msdu list. 181 182 INPUT: *this : A pointer to the list to free 183 pOs : Pointer to os abstraction layer 184 185 OUTPUT: 186 187 RETURN: TI_STATUS: OK/NOK 188 *************************************************************************/ 189 TI_STATUS msduList_FreeMsduList( MsduList_t* this) 190 { 191 if( this->CurrNumOfMsdu != 0 ) 192 { 193 if( msduList_EmptyMsduList( this ) != OK ) 194 { 195 WLAN_REPORT_ERROR(this->hReport, TX_DATA_MODULE_LOG, 196 (" msduList_FreeMsduList() : failed \n")); 197 return NOK; 198 } 199 } 200 201 /* free protection */ 202 os_protectDestroy(this->hOs,this->hCriticalSectionProtect); 203 204 /* free msdu control block */ 205 os_memoryFree(this->hOs, this, sizeof(MsduList_t)); 206 207 return OK; 208 209 } 210 211 /************************************************************************* 212 * msduList_EmptyMsduList * 213 ************************************************************************* 214 DESCRIPTION: This function free all the MSDUs from the Msdu list. 215 216 INPUT: *this : A pointer to the list to empty 217 pOs : Pointer to os abstraction layer 218 219 OUTPUT: 220 221 RETURN: TI_STATUS: OK/NOK 222 *************************************************************************/ 223 TI_STATUS msduList_EmptyMsduList( MsduList_t* this) 224 { 225 UINT32 count; 226 mem_MSDU_T* pTempMsdu; 227 228 os_protectLock(this->hOs, this->hCriticalSectionProtect); /* START OF CRITICAL SECTION */ 229 if( this->CurrNumOfMsdu == 0 ) 230 { 231 WLAN_REPORT_INFORMATION(this->hReport, TX_DATA_MODULE_LOG, 232 (" msduList_EmptyMsduList() : List is empty \n")); 233 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 234 return OK; 235 } 236 237 /* update Tx status to NOK for all msdu in list */ 238 pTempMsdu = this->first; 239 for(count = 0 ; count < this->CurrNumOfMsdu ; count++) 240 { 241 memMgr_MsduFreeArg2Get(pTempMsdu) = NOK; 242 pTempMsdu = pTempMsdu->nextMSDUinList; 243 } 244 245 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); 246 /* free all msdu back to the memMngr */ 247 if ((wlan_memMngrFreeListOfMSDU(this->hMemMgr, memMgr_MsduHandle( this->first))) != OK) 248 { 249 WLAN_REPORT_ERROR(this->hReport, TX_DATA_MODULE_LOG, 250 (" msduList_EmptyMsduList() : Msdu free failed \n")); 251 } 252 253 os_protectLock(this->hOs, this->hCriticalSectionProtect); /* START OF CRITICAL SECTION */ 254 this->first = NULL; 255 this->last = NULL; 256 this->CurrNumOfMsdu = 0; 257 this->numOfOverFlow = 0; 258 this->maxCurrOfMsdu = 0; 259 260 this->useAdmissionAlgo = FALSE; 261 this->credit = 0; 262 this->enableTransmissionTime = 0; 263 this->lastTimeStamp = 0; 264 this->mediumTime = 0; 265 this->totalUsedTime = 0; 266 267 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 268 269 return OK; 270 } 271 272 /************************************************************************* 273 * msduList_MsduListIns * 274 ************************************************************************* 275 DESCRIPTION: This function insert MSDU to the list pointed by this. 276 277 INPUT: *this : A pointer to the list to insert. 278 *pMsdu : Pointer to the MSDU to insert, the MSDU 279 is inserted to be the last in the list. If the 280 list is full the first MSDU will be taken 281 out and will be returned in this pointer. 282 283 OUTPUT: *pMsdu : In case the list is full,this poiter will hold 284 the dropt MSDU's. 285 286 RETURN: OK : The MSDU has been inserted, there was enough 287 place in the list. 288 NOK: The list was full, the first MSDU is dropt, and 289 returned by *pMsdu. 290 ************************************************************************/ 291 TI_STATUS msduList_Insert( MsduList_t* this , mem_MSDU_T **pMsdu ) 292 { 293 294 os_protectLock(this->hOs, this->hCriticalSectionProtect); /* START OF CRITICAL SECTION */ 295 296 if( this->CurrNumOfMsdu == 0 ) 297 { 298 this->last = *pMsdu; 299 this->first = *pMsdu; 300 (*pMsdu)->nextMSDUinList = NULL; 301 (*pMsdu)->prevMSDUinList = NULL; 302 this->CurrNumOfMsdu++; 303 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 304 305 /* for debug */ 306 if( this->CurrNumOfMsdu > this->maxCurrOfMsdu ) 307 this->maxCurrOfMsdu = this->CurrNumOfMsdu; 308 309 return OK; 310 } 311 else 312 { 313 if( this->CurrNumOfMsdu == this->maxNumOfMsdu ) 314 { 315 this->numOfOverFlow++; 316 317 if(this->ovFlowPolicy == DROP_NEW_PACKET) 318 { 319 /* The list is full, remove the new coming msdu*/ 320 WLAN_REPORT_INFORMATION(this->hReport, TX_DATA_MODULE_LOG, 321 (" msduList_MsduListIns() : New Msdu has to be removed \n")); 322 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 323 324 /* for debug */ 325 if( this->CurrNumOfMsdu > this->maxCurrOfMsdu ) 326 this->maxCurrOfMsdu = this->CurrNumOfMsdu; 327 328 return NOK; 329 330 }else 331 { 332 /* The list is full, insert the new msdu and remove the first msdu*/ 333 this->last->nextMSDUinList = *pMsdu; 334 (*pMsdu)->prevMSDUinList = this->last; 335 (*pMsdu)->nextMSDUinList = NULL; 336 this->last = *pMsdu; 337 338 /* remove the first msdu from list */ 339 (*pMsdu) = this->first; 340 this->first = this->first->nextMSDUinList; 341 this->first->prevMSDUinList = NULL; 342 (*pMsdu)->nextMSDUinList = NULL; 343 344 WLAN_REPORT_INFORMATION(this->hReport, TX_DATA_MODULE_LOG, 345 (" msduList_MsduListIns() : First Msdu was removed \n")); 346 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 347 /* indicate that the first msdu has removed */ 348 349 /* for debug */ 350 if( this->CurrNumOfMsdu > this->maxCurrOfMsdu ) 351 this->maxCurrOfMsdu = this->CurrNumOfMsdu; 352 353 return NOK; 354 355 } 356 } 357 else 358 { /* insert the MSDU to be the last. */ 359 this->last->nextMSDUinList = *pMsdu; 360 (*pMsdu)->prevMSDUinList = this->last; 361 (*pMsdu)->nextMSDUinList = NULL; 362 this->last = *pMsdu; 363 } 364 365 this->CurrNumOfMsdu++; 366 367 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 368 369 /* for debug */ 370 if( this->CurrNumOfMsdu > this->maxCurrOfMsdu ) 371 this->maxCurrOfMsdu = this->CurrNumOfMsdu; 372 373 return OK; 374 } 375 } 376 377 378 /************************************************************************* 379 * msduList_MsduListGetFirst * 380 ************************************************************************* 381 DESCRIPTION: This function get MSDU to the list pointed by this. 382 383 INPUT: *this : A pointer to the list to get. 384 385 OUTPUT: *pMsdu : A pointer to the first MSDU in the list. 386 387 RETURN: OK : There was an MSDU in the list, and it is assigned 388 to the *pMsdu. 389 NOK: The list was empty, *pMsdu is trush. 390 ************************************************************************/ 391 TI_STATUS msduList_GetFirst( MsduList_t *this, mem_MSDU_T **pMsdu) 392 { 393 394 os_protectLock(this->hOs, this->hCriticalSectionProtect); /* START OF CRITICAL SECTION */ 395 396 if( this->CurrNumOfMsdu == 0 ) 397 { 398 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 399 return NOK; 400 } 401 402 *pMsdu = this->first; 403 this->first = this->first->nextMSDUinList; 404 if (this->first != NULL) 405 this->first->prevMSDUinList = NULL; 406 this->CurrNumOfMsdu--; 407 (*pMsdu)->nextMSDUinList = NULL; 408 409 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 410 411 return OK; 412 } 413 414 /************************************************************************* 415 * msduList_MsduListWatchFirst * 416 ************************************************************************* 417 DESCRIPTION: This function watch at the first SDU in the list. The 418 MSDU is not removed yet from the list. 419 420 INPUT: *this : A pointer to the list to watch. 421 422 OUTPUT: *pMsdu : A pointer to the first MSDU in the list. 423 424 RETURN: OK : There was an MSDU in the list, and it is assigned 425 to the *pMsdu. 426 NOK: The list was empty, *pMsdu is trush. 427 ************************************************************************/ 428 TI_STATUS msduList_WatchFirst( MsduList_t *this, mem_MSDU_T **pMsdu) 429 { 430 os_protectLock(this->hOs, this->hCriticalSectionProtect); /* START OF CRITICAL SECTION */ 431 432 if( this->CurrNumOfMsdu == 0 ) 433 { 434 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 435 return NOK; 436 } 437 438 *pMsdu = this->first; 439 440 os_protectUnlock(this->hOs, this->hCriticalSectionProtect); /* END OF CRITICAL SECTION */ 441 442 return OK; 443 } 444 445 UINT32 msduList_getCurrNumOfMsdu(MsduList_t *this) 446 { 447 return this->CurrNumOfMsdu; 448 } 449 450 451 /* Debug functions */ 452 /*-----------------*/ 453 void printMsduList(MsduList_t *this) 454 { 455 WLAN_OS_REPORT(("Msdu List : \n")); 456 457 WLAN_OS_REPORT(("first = %X\n", this->first)); 458 WLAN_OS_REPORT(("last = %X\n", this->last)); 459 WLAN_OS_REPORT(("maxNumOfMsdu = %d\n", this->maxNumOfMsdu)); 460 WLAN_OS_REPORT(("CurrNumOfMsdu = %d\n", this->CurrNumOfMsdu)); 461 WLAN_OS_REPORT(("numOfOverFlow = %d\n", this->numOfOverFlow)); 462 WLAN_OS_REPORT(("maxCurrOfMsdu = %d\n", this->maxCurrOfMsdu)); 463 464 WLAN_OS_REPORT(("useAdmissionAlgo = %d\n", this->useAdmissionAlgo)); 465 WLAN_OS_REPORT(("credit = %d\n", this->credit)); 466 WLAN_OS_REPORT(("enableTransmissionTime = %d\n", this->enableTransmissionTime)); 467 WLAN_OS_REPORT(("lastTimeStamp = %d\n", this->lastTimeStamp)); 468 WLAN_OS_REPORT(("mediumTime = %d\n", this->mediumTime)); 469 WLAN_OS_REPORT(("totalUsedTime = %d\n", this->totalUsedTime)); 470 471 } 472 473 void printFullMsduList(MsduList_t *this) 474 { 475 mem_MSDU_T* tmpMSDU; 476 UINT32 i=0; 477 478 printMsduList(this); 479 480 tmpMSDU = this->first; 481 while (++i, tmpMSDU != NULL) 482 { 483 WLAN_OS_REPORT(("tmpMSDU %d = %X handle=%d tmpMSDU->nextMSDU=%X\n", i, tmpMSDU, tmpMSDU->handle, tmpMSDU->nextMSDUinList)); 484 tmpMSDU = tmpMSDU->nextMSDUinList; 485 } 486 487 } 488