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