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