blob: d1275e887f0cdcd198903db17bd0c22b4c4f7ef2 [file] [log] [blame]
Jerry Chuang8fc85982009-11-03 07:17:11 -02001#include "ieee80211.h"
2#include <linux/etherdevice.h>
3#include "rtl819x_TS.h"
4
Jerry Chuang8fc85982009-11-03 07:17:11 -02005void 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********************************************************************************************************************/
Jerry Chuang8fc85982009-11-03 07:17:11 -020024void 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}
Jerry Chuang8fc85982009-11-03 07:17:11 -020097
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){
Joe Perches0ee9f672009-12-06 11:34:52 -0800293 // 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);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200294 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 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200360 if (ieee->current_network.qos_data.supported == 0)
361 UP = 0;
362 else
363 {
Jerry Chuang8fc85982009-11-03 07:17:11 -0200364 // 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
Joe Perches0ee9f672009-12-06 11:34:52 -0800448 IEEE80211_DEBUG(IEEE80211_DL_TS, "to init current TS, UP:%d, Dir:%d, addr:%pM\n", UP, Dir, Addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200449 // 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
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200496 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);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200501 pRxReorderEntry = (PRX_REORDER_ENTRY)list_entry(pRxTS->RxPendingPktList.prev,RX_REORDER_ENTRY,List);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200502 list_del_init(&pRxReorderEntry->List);
503 {
504 int i = 0;
505 struct ieee80211_rxb * prxb = pRxReorderEntry->prxb;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200506 if (unlikely(!prxb))
507 {
508 spin_unlock_irqrestore(&(ieee->reorder_spinlock), flags);
509 return;
510 }
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200511 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 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200521
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;
Joe Perches0ee9f672009-12-06 11:34:52 -0800534 printk("===========>RemovePeerTS,%pM\n", Addr);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200535 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 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200575}
576
577void RemoveAllTS(struct ieee80211_device* ieee)
578{
579 PTS_COMMON_INFO pTS, pTmpTS;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200580 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 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200607}
608
609void TsStartAddBaProcess(struct ieee80211_device* ieee, PTX_TS_RECORD pTxTS)
610{
611 if(pTxTS->bAddBaReqInProgress == false)
612 {
613 pTxTS->bAddBaReqInProgress = true;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200614 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 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200624 }
625 else
626 IEEE80211_DEBUG(IEEE80211_DL_ERR, "%s()==>BA timer is already added\n", __FUNCTION__);
627}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200628EXPORT_SYMBOL(RemovePeerTS);