a3bfb92a8b2caff97df980fffca0f41ee809caca
[linux-flexiantxendom0-natty.git] / ubuntu / rtl8192se / rtllib / rtl819x_TSProc.c
1 /******************************************************************************
2  * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3  *
4  * This program is distributed in the hope that it will be useful, but WITHOUT
5  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
7  * more details.
8  *
9  * You should have received a copy of the GNU General Public License along with
10  * this program; if not, write to the Free Software Foundation, Inc.,
11  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
12  *
13  * The full GNU General Public License is included in this distribution in the
14  * file called LICENSE.
15  *
16  * Contact Information:
17  * wlanfae <wlanfae@realtek.com>
18 ******************************************************************************/
19 #include "rtllib.h"
20 #include <linux/etherdevice.h>
21 #include "rtl819x_TS.h"
22 extern void _setup_timer( struct timer_list*, void*, unsigned long);
23 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
24 #define list_for_each_entry_safe(pos, n, head, member) \
25         for (pos = list_entry((head)->next, typeof(*pos), member), \
26                 n = list_entry(pos->member.next, typeof(*pos), member); \
27                 &pos->member != (head); \
28                 pos = n, n = list_entry(n->member.next, typeof(*n), member))
29 #endif
30 void TsSetupTimeOut(unsigned long data)
31 {
32 }
33
34 void TsInactTimeout(unsigned long data)
35 {
36 }
37
38 #if 1
39 void RxPktPendingTimeout(unsigned long data)
40 {
41         PRX_TS_RECORD   pRxTs = (PRX_TS_RECORD)data;
42         struct rtllib_device *ieee = container_of(pRxTs, struct rtllib_device, RxTsRecord[pRxTs->num]);
43         
44         PRX_REORDER_ENTRY       pReorderEntry = NULL;
45
46         unsigned long flags = 0;
47         struct rtllib_rxb *stats_IndicateArray[REORDER_WIN_SIZE];
48         u8 index = 0;
49         bool bPktInBuf = false;
50
51
52         spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
53         RTLLIB_DEBUG(RTLLIB_DL_REORDER,"==================>%s()\n",__FUNCTION__);
54         if(pRxTs->RxTimeoutIndicateSeq != 0xffff)
55         {
56                 while(!list_empty(&pRxTs->RxPendingPktList))
57                 {
58                         pReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTs->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
59                         if(index == 0)
60                                 pRxTs->RxIndicateSeq = pReorderEntry->SeqNum;
61
62                         if( SN_LESS(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq) || 
63                                 SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq)   )
64                         {
65                                 list_del_init(&pReorderEntry->List);
66                         
67                                 if(SN_EQUAL(pReorderEntry->SeqNum, pRxTs->RxIndicateSeq))
68                                         pRxTs->RxIndicateSeq = (pRxTs->RxIndicateSeq + 1) % 4096;
69
70                                 RTLLIB_DEBUG(RTLLIB_DL_REORDER,"RxPktPendingTimeout(): IndicateSeq: %d\n", pReorderEntry->SeqNum);
71                                 stats_IndicateArray[index] = pReorderEntry->prxb;
72                                 index++;
73                                 
74                                 list_add_tail(&pReorderEntry->List, &ieee->RxReorder_Unused_List);
75                         }
76                         else
77                         {
78                                 bPktInBuf = true;
79                                 break;
80                         }
81                 }
82         }
83
84         if(index>0)
85         {
86                 pRxTs->RxTimeoutIndicateSeq = 0xffff;
87         
88                 if(index > REORDER_WIN_SIZE){
89                         RTLLIB_DEBUG(RTLLIB_DL_ERR, "RxReorderIndicatePacket(): Rx Reorer buffer full!! \n");
90                         spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
91                         return;
92                 }
93                 rtllib_indicate_packets(ieee, stats_IndicateArray, index);
94                  bPktInBuf = false;
95
96         }
97
98         if(bPktInBuf && (pRxTs->RxTimeoutIndicateSeq==0xffff))
99         {
100                 pRxTs->RxTimeoutIndicateSeq = pRxTs->RxIndicateSeq;
101 #if 0   
102                 if(timer_pending(&pTS->RxPktPendingTimer))
103                         del_timer_sync(&pTS->RxPktPendingTimer);
104                 pTS->RxPktPendingTimer.expires = jiffies + MSECS(pHTInfo->RxReorderPendingTime);
105                 add_timer(&pTS->RxPktPendingTimer);
106 #else
107                 mod_timer(&pRxTs->RxPktPendingTimer,  jiffies + MSECS(ieee->pHTInfo->RxReorderPendingTime));
108 #endif
109
110 #if 0           
111                 if(timer_pending(&pRxTs->RxPktPendingTimer))
112                         del_timer_sync(&pRxTs->RxPktPendingTimer);
113                 pRxTs->RxPktPendingTimer.expires = jiffies + ieee->pHTInfo->RxReorderPendingTime;
114                 add_timer(&pRxTs->RxPktPendingTimer);
115 #endif
116         }
117         spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
118 }
119 #endif
120
121 void TsAddBaProcess(unsigned long data)
122 {
123         PTX_TS_RECORD   pTxTs = (PTX_TS_RECORD)data;
124         u8 num = pTxTs->num;
125         struct rtllib_device *ieee = container_of(pTxTs, struct rtllib_device, TxTsRecord[num]);
126
127         TsInitAddBA(ieee, pTxTs, BA_POLICY_IMMEDIATE, false);
128         RTLLIB_DEBUG(RTLLIB_DL_BA, "TsAddBaProcess(): ADDBA Req is started!! \n");
129 }
130
131
132 void ResetTsCommonInfo(PTS_COMMON_INFO  pTsCommonInfo)
133 {
134         memset(pTsCommonInfo->Addr, 0, 6);
135         memset(&pTsCommonInfo->TSpec, 0, sizeof(TSPEC_BODY));
136         memset(&pTsCommonInfo->TClass, 0, sizeof(QOS_TCLAS)*TCLAS_NUM);
137         pTsCommonInfo->TClasProc = 0;
138         pTsCommonInfo->TClasNum = 0;
139 }
140
141 void ResetTxTsEntry(PTX_TS_RECORD pTS)
142 {
143         ResetTsCommonInfo(&pTS->TsCommonInfo);
144         pTS->TxCurSeq = 0;
145         pTS->bAddBaReqInProgress = false;
146         pTS->bAddBaReqDelayed = false;
147         pTS->bUsingBa = false;
148         pTS->bDisable_AddBa = false;
149         ResetBaEntry(&pTS->TxAdmittedBARecord); 
150         ResetBaEntry(&pTS->TxPendingBARecord);
151 }
152
153 void ResetRxTsEntry(PRX_TS_RECORD pTS)
154 {
155         ResetTsCommonInfo(&pTS->TsCommonInfo);
156         pTS->RxIndicateSeq = 0xffff; 
157         pTS->RxTimeoutIndicateSeq = 0xffff; 
158         ResetBaEntry(&pTS->RxAdmittedBARecord);   
159 }
160 #ifdef _RTL8192_EXT_PATCH_
161 void ResetAdmitTRStream(struct rtllib_device *ieee, u8 *Addr)
162 {
163         u8      dir;
164         bool                            search_dir[4] = {0, 0, 0, 0};
165         struct list_head*               psearch_list; 
166         PTS_COMMON_INFO pRet = NULL;
167         PRX_TS_RECORD pRxTS = NULL;
168         PTX_TS_RECORD pTxTS = NULL;
169
170         if(ieee->iw_mode != IW_MODE_MESH) 
171                 return;
172
173         search_dir[DIR_DOWN]    = true;
174         psearch_list = &ieee->Rx_TS_Admit_List;
175         for(dir = 0; dir <= DIR_BI_DIR; dir++)
176         {
177                 if(search_dir[dir] ==false )
178                         continue;
179                 list_for_each_entry(pRet, psearch_list, List){
180                         if ((memcmp(pRet->Addr, Addr, 6) == 0) && (pRet->TSpec.f.TSInfo.field.ucDirection == dir))
181                         {
182                                 pRxTS = (PRX_TS_RECORD)pRet;
183                                 pRxTS->RxIndicateSeq = 0xffff;
184                                 pRxTS->RxTimeoutIndicateSeq = 0xffff;
185                         }
186                                         
187                 }       
188         }
189         search_dir[DIR_UP]      = true;
190         psearch_list = &ieee->Tx_TS_Admit_List;
191         for(dir = 0; dir <= DIR_BI_DIR; dir++)
192         {
193                 if(search_dir[dir] ==false )
194                         continue;
195                 list_for_each_entry(pRet, psearch_list, List){
196                         if ((memcmp(pRet->Addr, Addr, 6) == 0) && (pRet->TSpec.f.TSInfo.field.ucDirection == dir))
197                         {
198                                 pTxTS = (PTX_TS_RECORD)pRet;
199                                 pTxTS->TxCurSeq = 0xffff;
200                         }
201                                         
202                 }       
203         }
204
205         return;
206 }
207 #endif
208
209 void TSInitialize(struct rtllib_device *ieee)
210 {
211         PTX_TS_RECORD           pTxTS  = ieee->TxTsRecord;
212         PRX_TS_RECORD           pRxTS  = ieee->RxTsRecord;
213         PRX_REORDER_ENTRY       pRxReorderEntry = ieee->RxReorderEntry;
214         u8                              count = 0;
215         RTLLIB_DEBUG(RTLLIB_DL_TS, "==========>%s()\n", __FUNCTION__);
216         INIT_LIST_HEAD(&ieee->Tx_TS_Admit_List);
217         INIT_LIST_HEAD(&ieee->Tx_TS_Pending_List);
218         INIT_LIST_HEAD(&ieee->Tx_TS_Unused_List);
219
220         for(count = 0; count < TOTAL_TS_NUM; count++)
221         {
222                 pTxTS->num = count;
223                 _setup_timer(&pTxTS->TsCommonInfo.SetupTimer,
224                             TsSetupTimeOut,
225                             (unsigned long) pTxTS);
226
227                 _setup_timer(&pTxTS->TsCommonInfo.InactTimer,
228                             TsInactTimeout,
229                             (unsigned long) pTxTS);
230
231                 _setup_timer(&pTxTS->TsAddBaTimer,
232                             TsAddBaProcess,
233                             (unsigned long) pTxTS);
234                 
235                 _setup_timer(&pTxTS->TxPendingBARecord.Timer,
236                             BaSetupTimeOut, 
237                             (unsigned long) pTxTS);
238                 _setup_timer(&pTxTS->TxAdmittedBARecord.Timer,
239                             TxBaInactTimeout,
240                             (unsigned long) pTxTS);
241                 
242                 ResetTxTsEntry(pTxTS);
243                 list_add_tail(&pTxTS->TsCommonInfo.List, 
244                                 &ieee->Tx_TS_Unused_List); 
245                 pTxTS++;
246         }
247
248         INIT_LIST_HEAD(&ieee->Rx_TS_Admit_List);
249         INIT_LIST_HEAD(&ieee->Rx_TS_Pending_List);
250         INIT_LIST_HEAD(&ieee->Rx_TS_Unused_List);
251         for(count = 0; count < TOTAL_TS_NUM; count++)
252         {
253                 pRxTS->num = count;
254                 INIT_LIST_HEAD(&pRxTS->RxPendingPktList);
255                 
256                 _setup_timer(&pRxTS->TsCommonInfo.SetupTimer,
257                             TsSetupTimeOut,
258                             (unsigned long) pRxTS);
259         
260                 _setup_timer(&pRxTS->TsCommonInfo.InactTimer,
261                             TsInactTimeout,
262                             (unsigned long) pRxTS);
263
264                 _setup_timer(&pRxTS->RxAdmittedBARecord.Timer,
265                             RxBaInactTimeout,
266                             (unsigned long) pRxTS);
267                 
268                 _setup_timer(&pRxTS->RxPktPendingTimer,
269                             RxPktPendingTimeout,
270                             (unsigned long) pRxTS);
271                 
272                 ResetRxTsEntry(pRxTS);
273                 list_add_tail(&pRxTS->TsCommonInfo.List, &ieee->Rx_TS_Unused_List);
274                 pRxTS++;
275         }
276         INIT_LIST_HEAD(&ieee->RxReorder_Unused_List);
277         for(count = 0; count < REORDER_ENTRY_NUM; count++)
278         {
279                 list_add_tail( &pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
280                 if(count == (REORDER_ENTRY_NUM-1))
281                         break;
282                 pRxReorderEntry = &ieee->RxReorderEntry[count+1];
283         }
284
285 }
286
287 void AdmitTS(struct rtllib_device *ieee, PTS_COMMON_INFO pTsCommonInfo, u32 InactTime)
288 {
289         del_timer_sync(&pTsCommonInfo->SetupTimer);
290         del_timer_sync(&pTsCommonInfo->InactTimer);
291
292         if(InactTime!=0)
293                 mod_timer(&pTsCommonInfo->InactTimer, jiffies + MSECS(InactTime));
294 }
295
296
297 PTS_COMMON_INFO SearchAdmitTRStream(struct rtllib_device *ieee, u8*     Addr, u8 TID, TR_SELECT TxRxSelect)
298 {
299         u8      dir;
300         bool                            search_dir[4] = {0, 0, 0, 0};
301         struct list_head*               psearch_list; 
302         PTS_COMMON_INFO pRet = NULL;
303         if(ieee->iw_mode == IW_MODE_MASTER) 
304         {
305                 if(TxRxSelect == TX_DIR)
306                 {
307                         search_dir[DIR_DOWN] = true;
308                         search_dir[DIR_BI_DIR]= true;
309                 }
310                 else
311                 {
312                         search_dir[DIR_UP]      = true;
313                         search_dir[DIR_BI_DIR]= true;
314                 }
315         }
316         else if(ieee->iw_mode == IW_MODE_ADHOC)
317         {
318                 if(TxRxSelect == TX_DIR)
319                         search_dir[DIR_UP]      = true;
320                 else
321                         search_dir[DIR_DOWN] = true;
322         }
323         else
324         {
325                 if(TxRxSelect == TX_DIR)
326                 {
327                         search_dir[DIR_UP]      = true;
328                         search_dir[DIR_BI_DIR]= true;
329                         search_dir[DIR_DIRECT]= true;
330                 }
331                 else
332                 {
333                         search_dir[DIR_DOWN] = true;
334                         search_dir[DIR_BI_DIR]= true;
335                         search_dir[DIR_DIRECT]= true;
336                 }
337         }
338
339         if(TxRxSelect == TX_DIR)
340                 psearch_list = &ieee->Tx_TS_Admit_List;
341         else
342                 psearch_list = &ieee->Rx_TS_Admit_List;
343         
344         for(dir = 0; dir <= DIR_BI_DIR; dir++)
345         {
346                 if(search_dir[dir] ==false )
347                         continue;
348                 list_for_each_entry(pRet, psearch_list, List){
349                         if (memcmp(pRet->Addr, Addr, 6) == 0)
350                                 if (pRet->TSpec.f.TSInfo.field.ucTSID == TID)
351                                         if(pRet->TSpec.f.TSInfo.field.ucDirection == dir)
352                                         {
353                                                 break;
354                                         }
355                                         
356                 }       
357                 if(&pRet->List  != psearch_list)
358                         break;
359         }
360
361         if(&pRet->List  != psearch_list){
362                 return pRet ;
363         }
364         else 
365                 return NULL;
366 }
367
368 void MakeTSEntry(
369                 PTS_COMMON_INFO pTsCommonInfo,
370                 u8*             Addr,
371                 PTSPEC_BODY     pTSPEC,
372                 PQOS_TCLAS      pTCLAS,
373                 u8              TCLAS_Num,
374                 u8              TCLAS_Proc
375         )
376 {
377         u8      count;
378
379         if(pTsCommonInfo == NULL)
380                 return;
381         
382         memcpy(pTsCommonInfo->Addr, Addr, 6);
383
384         if(pTSPEC != NULL)
385                 memcpy((u8*)(&(pTsCommonInfo->TSpec)), (u8*)pTSPEC, sizeof(TSPEC_BODY));
386
387         for(count = 0; count < TCLAS_Num; count++)
388                 memcpy((u8*)(&(pTsCommonInfo->TClass[count])), (u8*)pTCLAS, sizeof(QOS_TCLAS));
389
390         pTsCommonInfo->TClasProc = TCLAS_Proc;
391         pTsCommonInfo->TClasNum = TCLAS_Num;
392 }
393
394 #ifdef _RTL8192_EXT_PATCH_
395 void dump_ts_list(struct list_head * ts_list)
396 {
397         PTS_COMMON_INFO pRet = NULL;
398         u8 i=0;
399         list_for_each_entry(pRet, ts_list, List){
400                 printk("i=%d ADD:"MAC_FMT", TID:%d, dir:%d\n",i,MAC_ARG(pRet->Addr), pRet->TSpec.f.TSInfo.field.ucTSID, pRet->TSpec.f.TSInfo.field.ucDirection);
401                 i++;
402         }
403         
404 }
405 #endif
406
407 bool GetTs(
408         struct rtllib_device*   ieee,
409         PTS_COMMON_INFO                 *ppTS,
410         u8*                             Addr,
411         u8                              TID,
412         TR_SELECT                       TxRxSelect,  
413         bool                            bAddNewTs
414         )
415 {
416         u8      UP = 0;
417         if(is_broadcast_ether_addr(Addr) || is_multicast_ether_addr(Addr))
418         {
419                 RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! get TS for Broadcast or Multicast\n");
420                 return false;
421         }
422 #if 0
423         if(ieee->pStaQos->CurrentQosMode == QOS_DISABLE)
424         {       UP = 0; } 
425         else if(ieee->pStaQos->CurrentQosMode & QOS_WMM)
426         {
427 #else
428         if (ieee->current_network.qos_data.supported == 0)
429                 UP = 0;
430         else
431         {
432 #endif
433                 if (!IsACValid(TID))
434                 {
435                         RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR! in %s(), TID(%d) is not valid\n", __FUNCTION__, TID);
436                         return false;
437                 }
438
439                 switch(TID)
440                 {
441                 case 0:
442                 case 3:
443                         UP = 0;
444                         break;
445
446                 case 1:
447                 case 2:
448                         UP = 2;
449                         break;
450                         
451                 case 4:
452                 case 5:
453                         UP = 5;
454                         break;
455                         
456                 case 6:
457                 case 7:
458                         UP = 7;
459                         break;
460                 }
461         }
462
463         *ppTS = SearchAdmitTRStream(
464                         ieee, 
465                         Addr,
466                         UP, 
467                         TxRxSelect);
468         if(*ppTS != NULL)
469         {
470                 return true;
471         }
472         else
473         {
474                 if(bAddNewTs == false)
475                 {
476                         RTLLIB_DEBUG(RTLLIB_DL_TS, "add new TS failed(tid:%d)\n", UP);
477                         return false;
478                 }
479                 else
480                 {
481                         TSPEC_BODY      TSpec;
482                         PQOS_TSINFO             pTSInfo = &TSpec.f.TSInfo;
483                         struct list_head*       pUnusedList = 
484                                                                 (TxRxSelect == TX_DIR)?
485                                                                 (&ieee->Tx_TS_Unused_List):
486                                                                 (&ieee->Rx_TS_Unused_List);
487                                                                 
488                         struct list_head*       pAddmitList = 
489                                                                 (TxRxSelect == TX_DIR)?
490                                                                 (&ieee->Tx_TS_Admit_List):
491                                                                 (&ieee->Rx_TS_Admit_List);
492
493                         DIRECTION_VALUE         Dir =           (ieee->iw_mode == IW_MODE_MASTER)? 
494                                                                 ((TxRxSelect==TX_DIR)?DIR_DOWN:DIR_UP):
495                                                                 ((TxRxSelect==TX_DIR)?DIR_UP:DIR_DOWN);
496                         RTLLIB_DEBUG(RTLLIB_DL_TS, "to add Ts\n");
497                         if(!list_empty(pUnusedList))
498                         {
499                                 (*ppTS) = list_entry(pUnusedList->next, TS_COMMON_INFO, List);
500                                 list_del_init(&(*ppTS)->List);  
501                                 if(TxRxSelect==TX_DIR)
502                                 {
503                                         PTX_TS_RECORD tmp = container_of(*ppTS, TX_TS_RECORD, TsCommonInfo);
504                                         ResetTxTsEntry(tmp);
505                                 }
506                                 else{
507                                         PRX_TS_RECORD tmp = container_of(*ppTS, RX_TS_RECORD, TsCommonInfo);    
508                                         ResetRxTsEntry(tmp);
509                                 }
510                                 
511                                 RTLLIB_DEBUG(RTLLIB_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:"MAC_FMT"\n", UP, Dir, MAC_ARG(Addr));
512                                 pTSInfo->field.ucTrafficType = 0;                       
513                                 pTSInfo->field.ucTSID = UP;                     
514                                 pTSInfo->field.ucDirection = Dir;                       
515                                 pTSInfo->field.ucAccessPolicy = 1;              
516                                 pTSInfo->field.ucAggregation = 0;               
517                                 pTSInfo->field.ucPSB = 0;                               
518                                 pTSInfo->field.ucUP = UP;                               
519                                 pTSInfo->field.ucTSInfoAckPolicy = 0;           
520                                 pTSInfo->field.ucSchedule = 0;                  
521                                         
522                                 MakeTSEntry(*ppTS, Addr, &TSpec, NULL, 0, 0);
523                                 AdmitTS(ieee, *ppTS, 0);
524                                 list_add_tail(&((*ppTS)->List), pAddmitList);
525
526                                 return true;
527                         }
528                         else
529                         {
530                                 RTLLIB_DEBUG(RTLLIB_DL_ERR, "ERR!!in function %s() There is not enough dir=%d(0=up down=1) TS record to be used!!", __FUNCTION__,Dir);
531                                 return false;
532                         }               
533                 }               
534         }
535 }
536
537 void RemoveTsEntry(
538         struct rtllib_device*   ieee,
539         PTS_COMMON_INFO                 pTs,
540         TR_SELECT                       TxRxSelect
541         )
542 {
543         unsigned long flags = 0;
544         del_timer_sync(&pTs->SetupTimer);
545         del_timer_sync(&pTs->InactTimer);
546         TsInitDelBA(ieee, pTs, TxRxSelect);
547
548         if(TxRxSelect == RX_DIR)
549         {
550                 PRX_REORDER_ENTRY       pRxReorderEntry;
551                 PRX_TS_RECORD           pRxTS = (PRX_TS_RECORD)pTs;
552                 if(timer_pending(&pRxTS->RxPktPendingTimer))    
553                         del_timer_sync(&pRxTS->RxPktPendingTimer);
554
555                 while(!list_empty(&pRxTS->RxPendingPktList))
556                 {
557                         spin_lock_irqsave(&(ieee->reorder_spinlock), flags);
558                         pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
559                         list_del_init(&pRxReorderEntry->List);
560                         {
561                                 int i = 0;
562                                 struct rtllib_rxb * prxb = pRxReorderEntry->prxb;
563                                 if (unlikely(!prxb))
564                                 {
565                                         spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
566                                         return;
567                                 }
568                                 for(i =0; i < prxb->nr_subframes; i++) {
569                                         dev_kfree_skb(prxb->subframes[i]);
570                                 }
571                                 kfree(prxb);
572                                 prxb = NULL;
573                         }
574                         list_add_tail(&pRxReorderEntry->List,&ieee->RxReorder_Unused_List);
575                         spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
576                 }
577
578         }
579         else
580         {
581                 PTX_TS_RECORD pTxTS = (PTX_TS_RECORD)pTs;
582                 del_timer_sync(&pTxTS->TsAddBaTimer);
583         }
584 }
585
586 void RemovePeerTS(struct rtllib_device* ieee, u8* Addr)
587 {
588         PTS_COMMON_INFO pTS, pTmpTS;
589         printk("===========>RemovePeerTS,"MAC_FMT"\n", MAC_ARG(Addr));
590 #if 1
591         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
592         {
593                 if (memcmp(pTS->Addr, Addr, 6) == 0)
594                 {
595                         RemoveTsEntry(ieee, pTS, TX_DIR);
596                         list_del_init(&pTS->List);
597                         list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
598                 }
599         }
600         
601         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
602         {
603                 if (memcmp(pTS->Addr, Addr, 6) == 0)
604                 {
605                         printk("====>remove Tx_TS_admin_list\n");
606                         RemoveTsEntry(ieee, pTS, TX_DIR);
607                         list_del_init(&pTS->List);
608                         list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
609                 }
610         }
611         
612         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
613         {
614                 if (memcmp(pTS->Addr, Addr, 6) == 0)
615                 {
616                         RemoveTsEntry(ieee, pTS, RX_DIR);
617                         list_del_init(&pTS->List);
618                         list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
619                 }
620         }
621
622         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
623         {
624                 if (memcmp(pTS->Addr, Addr, 6) == 0)
625                 {
626                         RemoveTsEntry(ieee, pTS, RX_DIR);
627                         list_del_init(&pTS->List);
628                         list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
629                 }
630         }
631 #endif
632 }
633
634 void RemoveAllTS(struct rtllib_device* ieee)
635 {
636         PTS_COMMON_INFO pTS, pTmpTS;
637 #if 1   
638         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Pending_List, List)
639         {
640                 RemoveTsEntry(ieee, pTS, TX_DIR);
641                 list_del_init(&pTS->List);
642                 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);    
643         }
644
645         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Tx_TS_Admit_List, List)
646         {
647                 RemoveTsEntry(ieee, pTS, TX_DIR);
648                 list_del_init(&pTS->List);
649                 list_add_tail(&pTS->List, &ieee->Tx_TS_Unused_List);
650         }
651         
652         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Pending_List, List)
653         {
654                 RemoveTsEntry(ieee, pTS, RX_DIR);
655                 list_del_init(&pTS->List);
656                 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
657         }
658
659         list_for_each_entry_safe(pTS, pTmpTS, &ieee->Rx_TS_Admit_List, List)
660         {
661                 RemoveTsEntry(ieee, pTS, RX_DIR);
662                 list_del_init(&pTS->List);
663                 list_add_tail(&pTS->List, &ieee->Rx_TS_Unused_List);
664         }
665 #endif
666 }
667
668 void TsStartAddBaProcess(struct rtllib_device* ieee, PTX_TS_RECORD      pTxTS)
669 {
670         if(pTxTS->bAddBaReqInProgress == false)
671         {
672                 pTxTS->bAddBaReqInProgress = true;
673 #if 1
674                 if(pTxTS->bAddBaReqDelayed)
675                 {
676                         RTLLIB_DEBUG(RTLLIB_DL_BA, "TsStartAddBaProcess(): Delayed Start ADDBA after 60 sec!!\n");
677                         mod_timer(&pTxTS->TsAddBaTimer, jiffies + MSECS(TS_ADDBA_DELAY));
678                 }
679                 else
680                 {
681                         RTLLIB_DEBUG(RTLLIB_DL_BA,"TsStartAddBaProcess(): Immediately Start ADDBA now!!\n");
682                         mod_timer(&pTxTS->TsAddBaTimer, jiffies+10); 
683                 }
684 #endif
685         }
686         else
687                 RTLLIB_DEBUG(RTLLIB_DL_ERR, "%s()==>BA timer is already added\n", __FUNCTION__);
688 }
689
690 #ifndef BUILT_IN_RTLLIB
691 EXPORT_SYMBOL_RSL(RemovePeerTS);
692 #ifdef _RTL8192_EXT_PATCH_
693 EXPORT_SYMBOL_RSL(ResetAdmitTRStream);
694 #endif
695 #endif