rtl819x_TSProc.c revision 0ee9f67c4028500a4348e8bc87ee7ec1139b8259
1#include "ieee80211.h" 2#include <linux/etherdevice.h> 3#include "rtl819x_TS.h" 4 5void TsSetupTimeOut(unsigned long data) 6{ 7 // Not implement yet 8 // This is used for WMMSA and ACM , that would send ADDTSReq frame. 9} 10 11void TsInactTimeout(unsigned long data) 12{ 13 // Not implement yet 14 // This is used for WMMSA and ACM. 15 // This function would be call when TS is no Tx/Rx for some period of time. 16} 17 18/******************************************************************************************************************** 19 *function: I still not understand this function, so wait for further implementation 20 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer 21 * return: NULL 22 * notice: 23********************************************************************************************************************/ 24void RxPktPendingTimeout(unsigned long data) 25{ 26 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data; 27 struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]); 28 29 PRX_REORDER_ENTRY pReorderEntry = NULL; 30 31 //u32 flags = 0; 32 unsigned long flags = 0; 33 struct ieee80211_rxb *stats_IndicateArray[REORDER_WIN_SIZE]; 34 u8 index = 0; 35 bool bPktInBuf = false; 36 37 38 spin_lock_irqsave(&(ieee->reorder_spinlock), flags); 39 //PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK); 40 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"==================>%s()\n",__FUNCTION__); 41 if(pRxTs->RxTimeoutIndicateSeq != 0xffff) 42 { 43 // Indicate the pending packets sequentially according to SeqNum until meet the gap. 44 while(!list_empty(&pRxTs->RxPendingPktList)) 45 { 46 pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->RxPendingPktList.prev,RX_REORDER_ENTRY,List); 47 if(index == 0) 48 pRxTs->RxIndicateSeq = pReorderEntry->SeqNum; 49 50 if( SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) || 51 SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) ) 52 { 53 list_del_init(&pReorderEntry->List); 54 55 if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq)) 56 pRxTs->RxIndicateSeq = (pRxTs->RxIndicateSeq + 1) % 4096; 57 58 IEEE80211_DEBUG(IEEE80211_DL_REORDER,"RxPktPendingTimeout(): IndicateSeq: %d\n", pReorderEntry->SeqNum); 59 stats_IndicateArray[index] = pReorderEntry->prxb; 60 index++; 61 62 list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List); 63 } 64 else 65 { 66 bPktInBuf = true; 67 break; 68 } 69 } 70 } 71 72 if(index>0) 73 { 74 // Set RxTimeoutIndicateSeq to 0xffff to indicate no pending packets in buffer now. 75 pRxTs->RxTimeoutIndicateSeq = 0xffff; 76 77 // Indicate packets 78 if(index > REORDER_WIN_SIZE){ 79 IEEE80211_DEBUG(IEEE80211_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n"); 80 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); 81 return; 82 } 83 ieee80211_indicate_packets(ieee, stats_IndicateArray, index); 84 } 85 86 if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff)) 87 { 88 pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq; 89 if(timer_pending(&pRxTs->RxPktPendingTimer)) 90 del_timer_sync(&pRxTs->RxPktPendingTimer); 91 pRxTs->RxPktPendingTimer.expires = jiffies + ieee->pHTInfo->RxReorderPendingTime; 92 add_timer(&pRxTs->RxPktPendingTimer); 93 } 94 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); 95 //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK); 96} 97 98/******************************************************************************************************************** 99 *function: Add BA timer function 100 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer 101 * return: NULL 102 * notice: 103********************************************************************************************************************/ 104void TsAddBaProcess(unsigned long data) 105{ 106 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data; 107 u8 num = pTxTs->num; 108 struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[num]); 109 110 TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false); 111 IEEE80211_DEBUG(IEEE80211_DL_BA, "TsAddBaProcess(): ADDBA Req is started!! \n"); 112} 113 114 115void ResetTsCommonInfo(PTS_COMMON_INFO pTsCommonInfo) 116{ 117 memset(pTsCommonInfo->Addr, 0, 6); 118 memset(&pTsCommonInfo->TSpec, 0, sizeof(TSPEC_BODY)); 119 memset(&pTsCommonInfo->TClass, 0, sizeof(QOS_TCLAS)*TCLAS_NUM); 120 pTsCommonInfo->TClasProc = 0; 121 pTsCommonInfo->TClasNum = 0; 122} 123 124void ResetTxTsEntry(PTX_TS_RECORD pTS) 125{ 126 ResetTsCommonInfo(&pTS->TsCommonInfo); 127 pTS->TxCurSeq = 0; 128 pTS->bAddBaReqInProgress = false; 129 pTS->bAddBaReqDelayed = false; 130 pTS->bUsingBa = false; 131 ResetBaEntry(&pTS->TxAdmittedBARecord); //For BA Originator 132 ResetBaEntry(&pTS->TxPendingBARecord); 133} 134 135void ResetRxTsEntry(PRX_TS_RECORD pTS) 136{ 137 ResetTsCommonInfo(&pTS->TsCommonInfo); 138 pTS->RxIndicateSeq = 0xffff; // This indicate the RxIndicateSeq is not used now!! 139 pTS->RxTimeoutIndicateSeq = 0xffff; // This indicate the RxTimeoutIndicateSeq is not used now!! 140 ResetBaEntry(&pTS->RxAdmittedBARecord); // For BA Recepient 141} 142 143void TSInitialize(struct ieee80211_device *ieee) 144{ 145 PTX_TS_RECORD pTxTS = ieee->TxTsRecord; 146 PRX_TS_RECORD pRxTS = ieee->RxTsRecord; 147 PRX_REORDER_ENTRY pRxReorderEntry = ieee->RxReorderEntry; 148 u8 count = 0; 149 IEEE80211_DEBUG(IEEE80211_DL_TS, "==========>%s()\n", __FUNCTION__); 150 // Initialize Tx TS related info. 151 INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List); 152 INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List); 153 INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List); 154 155 for(count = 0; count < TOTAL_TS_NUM; count++) 156 { 157 // 158 pTxTS->num = count; 159 // The timers for the operation of Traffic Stream and Block Ack. 160 // DLS related timer will be add here in the future!! 161 init_timer(&pTxTS->TsCommonInfo.SetupTimer); 162 pTxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pTxTS; 163 pTxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut; 164 165 init_timer(&pTxTS->TsCommonInfo.InactTimer); 166 pTxTS->TsCommonInfo.InactTimer.data = (unsigned long)pTxTS; 167 pTxTS->TsCommonInfo.InactTimer.function = TsInactTimeout; 168 169 init_timer(&pTxTS->TsAddBaTimer); 170 pTxTS->TsAddBaTimer.data = (unsigned long)pTxTS; 171 pTxTS->TsAddBaTimer.function = TsAddBaProcess; 172 173 init_timer(&pTxTS->TxPendingBARecord.Timer); 174 pTxTS->TxPendingBARecord.Timer.data = (unsigned long)pTxTS; 175 pTxTS->TxPendingBARecord.Timer.function = BaSetupTimeOut; 176 177 init_timer(&pTxTS->TxAdmittedBARecord.Timer); 178 pTxTS->TxAdmittedBARecord.Timer.data = (unsigned long)pTxTS; 179 pTxTS->TxAdmittedBARecord.Timer.function = TxBaInactTimeout; 180 181 ResetTxTsEntry(pTxTS); 182 list_add_tail(&pTxTS->TsCommonInfo.List, &ieee->Tx_TS_Unused_List); 183 pTxTS++; 184 } 185 186 // Initialize Rx TS related info. 187 INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List); 188 INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List); 189 INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List); 190 for(count = 0; count < TOTAL_TS_NUM; count++) 191 { 192 pRxTS->num = count; 193 INIT_LIST_HEAD(&pRxTS->RxPendingPktList); 194 195 init_timer(&pRxTS->TsCommonInfo.SetupTimer); 196 pRxTS->TsCommonInfo.SetupTimer.data = (unsigned long)pRxTS; 197 pRxTS->TsCommonInfo.SetupTimer.function = TsSetupTimeOut; 198 199 init_timer(&pRxTS->TsCommonInfo.InactTimer); 200 pRxTS->TsCommonInfo.InactTimer.data = (unsigned long)pRxTS; 201 pRxTS->TsCommonInfo.InactTimer.function = TsInactTimeout; 202 203 init_timer(&pRxTS->RxAdmittedBARecord.Timer); 204 pRxTS->RxAdmittedBARecord.Timer.data = (unsigned long)pRxTS; 205 pRxTS->RxAdmittedBARecord.Timer.function = RxBaInactTimeout; 206 207 init_timer(&pRxTS->RxPktPendingTimer); 208 pRxTS->RxPktPendingTimer.data = (unsigned long)pRxTS; 209 pRxTS->RxPktPendingTimer.function = RxPktPendingTimeout; 210 211 ResetRxTsEntry(pRxTS); 212 list_add_tail(&pRxTS->TsCommonInfo.List, &ieee->Rx_TS_Unused_List); 213 pRxTS++; 214 } 215 // Initialize unused Rx Reorder List. 216 INIT_LIST_HEAD(&ieee->RxReorder_Unused_List); 217//#ifdef TO_DO_LIST 218 for(count = 0; count < REORDER_ENTRY_NUM; count++) 219 { 220 list_add_tail( &pRxReorderEntry->List,&ieee->RxReorder_Unused_List); 221 if(count == (REORDER_ENTRY_NUM-1)) 222 break; 223 pRxReorderEntry = &ieee->RxReorderEntry[count+1]; 224 } 225//#endif 226 227} 228 229void AdmitTS(struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, u32 InactTime) 230{ 231 del_timer_sync(&pTsCommonInfo->SetupTimer); 232 del_timer_sync(&pTsCommonInfo->InactTimer); 233 234 if(InactTime!=0) 235 mod_timer(&pTsCommonInfo->InactTimer, jiffies + MSECS(InactTime)); 236} 237 238 239PTS_COMMON_INFO SearchAdmitTRStream(struct ieee80211_device *ieee, u8* Addr, u8 TID, TR_SELECT TxRxSelect) 240{ 241 //DIRECTION_VALUE dir; 242 u8 dir; 243 bool search_dir[4] = {0, 0, 0, 0}; 244 struct list_head* psearch_list; //FIXME 245 PTS_COMMON_INFO pRet = NULL; 246 if(ieee->iw_mode == IW_MODE_MASTER) //ap mode 247 { 248 if(TxRxSelect == TX_DIR) 249 { 250 search_dir[DIR_DOWN] = true; 251 search_dir[DIR_BI_DIR]= true; 252 } 253 else 254 { 255 search_dir[DIR_UP] = true; 256 search_dir[DIR_BI_DIR]= true; 257 } 258 } 259 else if(ieee->iw_mode == IW_MODE_ADHOC) 260 { 261 if(TxRxSelect == TX_DIR) 262 search_dir[DIR_UP] = true; 263 else 264 search_dir[DIR_DOWN] = true; 265 } 266 else 267 { 268 if(TxRxSelect == TX_DIR) 269 { 270 search_dir[DIR_UP] = true; 271 search_dir[DIR_BI_DIR]= true; 272 search_dir[DIR_DIRECT]= true; 273 } 274 else 275 { 276 search_dir[DIR_DOWN] = true; 277 search_dir[DIR_BI_DIR]= true; 278 search_dir[DIR_DIRECT]= true; 279 } 280 } 281 282 if(TxRxSelect == TX_DIR) 283 psearch_list = &ieee->Tx_TS_Admit_List; 284 else 285 psearch_list = &ieee->Rx_TS_Admit_List; 286 287 //for(dir = DIR_UP; dir <= DIR_BI_DIR; dir++) 288 for(dir = 0; dir <= DIR_BI_DIR; dir++) 289 { 290 if(search_dir[dir] ==false ) 291 continue; 292 list_for_each_entry(pRet, psearch_list, List){ 293 // IEEE80211_DEBUG(IEEE80211_DL_TS, "ADD:%pM, TID:%d, dir:%d\n", pRet->Addr, pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection); 294 if (memcmp(pRet->Addr, Addr, 6) == 0) 295 if (pRet->TSpec.f.TSInfo.field.ucTSID == TID) 296 if(pRet->TSpec.f.TSInfo.field.ucDirection == dir) 297 { 298 // printk("Bingo! got it\n"); 299 break; 300 } 301 302 } 303 if(&pRet->List != psearch_list) 304 break; 305 } 306 307 if(&pRet->List != psearch_list){ 308 return pRet ; 309 } 310 else 311 return NULL; 312} 313 314void MakeTSEntry( 315 PTS_COMMON_INFO pTsCommonInfo, 316 u8* Addr, 317 PTSPEC_BODY pTSPEC, 318 PQOS_TCLAS pTCLAS, 319 u8 TCLAS_Num, 320 u8 TCLAS_Proc 321 ) 322{ 323 u8 count; 324 325 if(pTsCommonInfo == NULL) 326 return; 327 328 memcpy(pTsCommonInfo->Addr, Addr, 6); 329 330 if(pTSPEC != NULL) 331 memcpy((u8*)(&(pTsCommonInfo->TSpec)), (u8*)pTSPEC, sizeof(TSPEC_BODY)); 332 333 for(count = 0; count < TCLAS_Num; count++) 334 memcpy((u8*)(&(pTsCommonInfo->TClass[count])), (u8*)pTCLAS, sizeof(QOS_TCLAS)); 335 336 pTsCommonInfo->TClasProc = TCLAS_Proc; 337 pTsCommonInfo->TClasNum = TCLAS_Num; 338} 339 340 341bool GetTs( 342 struct ieee80211_device* ieee, 343 PTS_COMMON_INFO *ppTS, 344 u8* Addr, 345 u8 TID, 346 TR_SELECT TxRxSelect, //Rx:1, Tx:0 347 bool bAddNewTs 348 ) 349{ 350 u8 UP = 0; 351 // 352 // We do not build any TS for Broadcast or Multicast stream. 353 // So reject these kinds of search here. 354 // 355 if(is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr)) 356 { 357 IEEE80211_DEBUG(IEEE80211_DL_ERR, "get TS for Broadcast or Multicast\n"); 358 return false; 359 } 360 if (ieee->current_network.qos_data.supported == 0) 361 UP = 0; 362 else 363 { 364 // In WMM case: we use 4 TID only 365 if (!IsACValid(TID)) 366 { 367 IEEE80211_DEBUG(IEEE80211_DL_ERR, " in %s(), TID(%d) is not valid\n", __FUNCTION__, TID); 368 return false; 369 } 370 371 switch(TID) 372 { 373 case 0: 374 case 3: 375 UP = 0; 376 break; 377 378 case 1: 379 case 2: 380 UP = 2; 381 break; 382 383 case 4: 384 case 5: 385 UP = 5; 386 break; 387 388 case 6: 389 case 7: 390 UP = 7; 391 break; 392 } 393 } 394 395 *ppTS = SearchAdmitTRStream( 396 ieee, 397 Addr, 398 UP, 399 TxRxSelect); 400 if(*ppTS != NULL) 401 { 402 return true; 403 } 404 else 405 { 406 if(bAddNewTs == false) 407 { 408 IEEE80211_DEBUG(IEEE80211_DL_TS, "add new TS failed(tid:%d)\n", UP); 409 return false; 410 } 411 else 412 { 413 // 414 // Create a new Traffic stream for current Tx/Rx 415 // This is for EDCA and WMM to add a new TS. 416 // For HCCA or WMMSA, TS cannot be addmit without negotiation. 417 // 418 TSPEC_BODY TSpec; 419 PQOS_TSINFO pTSInfo = &TSpec.f.TSInfo; 420 struct list_head* pUnusedList = 421 (TxRxSelect == TX_DIR)? 422 (&ieee->Tx_TS_Unused_List): 423 (&ieee->Rx_TS_Unused_List); 424 425 struct list_head* pAddmitList = 426 (TxRxSelect == TX_DIR)? 427 (&ieee->Tx_TS_Admit_List): 428 (&ieee->Rx_TS_Admit_List); 429 430 DIRECTION_VALUE Dir = (ieee->iw_mode == IW_MODE_MASTER)? 431 ((TxRxSelect==TX_DIR)?DIR_DOWN:DIR_UP): 432 ((TxRxSelect==TX_DIR)?DIR_UP:DIR_DOWN); 433 IEEE80211_DEBUG(IEEE80211_DL_TS, "to add Ts\n"); 434 if(!list_empty(pUnusedList)) 435 { 436 (*ppTS) = list_entry(pUnusedList->next, TS_COMMON_INFO, List); 437 list_del_init(&(*ppTS)->List); 438 if(TxRxSelect==TX_DIR) 439 { 440 PTX_TS_RECORD tmp = container_of(*ppTS, TX_TS_RECORD, TsCommonInfo); 441 ResetTxTsEntry(tmp); 442 } 443 else{ 444 PRX_TS_RECORD tmp = container_of(*ppTS, RX_TS_RECORD, TsCommonInfo); 445 ResetRxTsEntry(tmp); 446 } 447 448 IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr); 449 // Prepare TS Info releated field 450 pTSInfo->field.ucTrafficType = 0; // Traffic type: WMM is reserved in this field 451 pTSInfo->field.ucTSID = UP; // TSID 452 pTSInfo->field.ucDirection = Dir; // Direction: if there is DirectLink, this need additional consideration. 453 pTSInfo->field.ucAccessPolicy = 1; // Access policy 454 pTSInfo->field.ucAggregation = 0; // Aggregation 455 pTSInfo->field.ucPSB = 0; // Aggregation 456 pTSInfo->field.ucUP = UP; // User priority 457 pTSInfo->field.ucTSInfoAckPolicy = 0; // Ack policy 458 pTSInfo->field.ucSchedule = 0; // Schedule 459 460 MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0); 461 AdmitTS(ieee, *ppTS, 0); 462 list_add_tail(&((*ppTS)->List), pAddmitList); 463 // if there is DirectLink, we need to do additional operation here!! 464 465 return true; 466 } 467 else 468 { 469 IEEE80211_DEBUG(IEEE80211_DL_ERR, "in function %s() There is not enough TS record to be used!!", __FUNCTION__); 470 return false; 471 } 472 } 473 } 474} 475 476void RemoveTsEntry( 477 struct ieee80211_device* ieee, 478 PTS_COMMON_INFO pTs, 479 TR_SELECT TxRxSelect 480 ) 481{ 482 //u32 flags = 0; 483 unsigned long flags = 0; 484 del_timer_sync(&pTs->SetupTimer); 485 del_timer_sync(&pTs->InactTimer); 486 TsInitDelBA(ieee, pTs, TxRxSelect); 487 488 if(TxRxSelect == RX_DIR) 489 { 490//#ifdef TO_DO_LIST 491 PRX_REORDER_ENTRY pRxReorderEntry; 492 PRX_TS_RECORD pRxTS = (PRX_TS_RECORD)pTs; 493 if(timer_pending(&pRxTS->RxPktPendingTimer)) 494 del_timer_sync(&pRxTS->RxPktPendingTimer); 495 496 while(!list_empty(&pRxTS->RxPendingPktList)) 497 { 498 // PlatformAcquireSpinLock(Adapter, RT_RX_SPINLOCK); 499 spin_lock_irqsave(&(ieee->reorder_spinlock), flags); 500 //pRxReorderEntry = list_entry(&pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List); 501 pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List); 502 list_del_init(&pRxReorderEntry->List); 503 { 504 int i = 0; 505 struct ieee80211_rxb * prxb = pRxReorderEntry->prxb; 506 if (unlikely(!prxb)) 507 { 508 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); 509 return; 510 } 511 for(i =0; i < prxb->nr_subframes; i++) { 512 dev_kfree_skb(prxb->subframes[i]); 513 } 514 kfree(prxb); 515 prxb = NULL; 516 } 517 list_add_tail(&pRxReorderEntry->List,&ieee->RxReorder_Unused_List); 518 //PlatformReleaseSpinLock(Adapter, RT_RX_SPINLOCK); 519 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags); 520 } 521 522//#endif 523 } 524 else 525 { 526 PTX_TS_RECORD pTxTS = (PTX_TS_RECORD)pTs; 527 del_timer_sync(&pTxTS->TsAddBaTimer); 528 } 529} 530 531void RemovePeerTS(struct ieee80211_device* ieee, u8* Addr) 532{ 533 PTS_COMMON_INFO pTS, pTmpTS; 534 printk("===========>RemovePeerTS,%pM\n", Addr); 535 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) 536 { 537 if (memcmp(pTS->Addr, Addr, 6) == 0) 538 { 539 RemoveTsEntry(ieee, pTS, TX_DIR); 540 list_del_init(&pTS->List); 541 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); 542 } 543 } 544 545 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) 546 { 547 if (memcmp(pTS->Addr, Addr, 6) == 0) 548 { 549 printk("====>remove Tx_TS_admin_list\n"); 550 RemoveTsEntry(ieee, pTS, TX_DIR); 551 list_del_init(&pTS->List); 552 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); 553 } 554 } 555 556 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) 557 { 558 if (memcmp(pTS->Addr, Addr, 6) == 0) 559 { 560 RemoveTsEntry(ieee, pTS, RX_DIR); 561 list_del_init(&pTS->List); 562 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); 563 } 564 } 565 566 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) 567 { 568 if (memcmp(pTS->Addr, Addr, 6) == 0) 569 { 570 RemoveTsEntry(ieee, pTS, RX_DIR); 571 list_del_init(&pTS->List); 572 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); 573 } 574 } 575} 576 577void RemoveAllTS(struct ieee80211_device* ieee) 578{ 579 PTS_COMMON_INFO pTS, pTmpTS; 580 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List) 581 { 582 RemoveTsEntry(ieee, pTS, TX_DIR); 583 list_del_init(&pTS->List); 584 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); 585 } 586 587 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List) 588 { 589 RemoveTsEntry(ieee, pTS, TX_DIR); 590 list_del_init(&pTS->List); 591 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List); 592 } 593 594 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List) 595 { 596 RemoveTsEntry(ieee, pTS, RX_DIR); 597 list_del_init(&pTS->List); 598 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); 599 } 600 601 list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List) 602 { 603 RemoveTsEntry(ieee, pTS, RX_DIR); 604 list_del_init(&pTS->List); 605 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List); 606 } 607} 608 609void TsStartAddBaProcess(struct ieee80211_device* ieee, PTX_TS_RECORD pTxTS) 610{ 611 if(pTxTS->bAddBaReqInProgress == false) 612 { 613 pTxTS->bAddBaReqInProgress = true; 614 if(pTxTS->bAddBaReqDelayed) 615 { 616 IEEE80211_DEBUG(IEEE80211_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n"); 617 mod_timer(&pTxTS->TsAddBaTimer, jiffies + MSECS(TS_ADDBA_DELAY)); 618 } 619 else 620 { 621 IEEE80211_DEBUG(IEEE80211_DL_BA,"TsStartAddBaProcess(): Immediately Start ADDBA now!!\n"); 622 mod_timer(&pTxTS->TsAddBaTimer, jiffies+10); //set 10 ticks 623 } 624 } 625 else 626 IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __FUNCTION__); 627} 628EXPORT_SYMBOL(RemovePeerTS); 629