staging: rtl8192e: Pass ieee80211_device to callbacks
[pandora-kernel.git] / drivers / staging / rtl8192e / ieee80211 / rtl819x_BAProc.c
1 /*
2  * This file is created to process BA Action Frame. According to 802.11 spec,
3  * there are 3 BA action types at all. And as BA is related to TS, this part
4  * need some struture defined in QOS side code. Also TX RX is going to be
5  * resturctured, so how to send ADDBAREQ ADDBARSP and DELBA packet is still
6  * on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
7  */
8 #include "ieee80211.h"
9 #include "rtl819x_BA.h"
10
11 /*
12  * Activate BA entry. And if Time is nozero, start timer.
13  */
14 void ActivateBAEntry(struct ieee80211_device* ieee, PBA_RECORD pBA, u16 Time)
15 {
16         pBA->bValid = true;
17         if(Time != 0)
18                 mod_timer(&pBA->Timer, jiffies + MSECS(Time));
19 }
20
21 /*
22  * deactivate BA entry, including its timer.
23  */
24 void DeActivateBAEntry( struct ieee80211_device* ieee, PBA_RECORD pBA)
25 {
26         pBA->bValid = false;
27         del_timer_sync(&pBA->Timer);
28 }
29
30 /*
31  * deactivete BA entry in Tx Ts, and send DELBA.
32  */
33 u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD   pTxTs)
34 {
35         PBA_RECORD              pAdmittedBa = &pTxTs->TxAdmittedBARecord;  //These two BA entries must exist in TS structure
36         PBA_RECORD              pPendingBa = &pTxTs->TxPendingBARecord;
37         u8                      bSendDELBA = false;
38
39         // Delete pending BA
40         if(pPendingBa->bValid)
41         {
42                 DeActivateBAEntry(ieee, pPendingBa);
43                 bSendDELBA = true;
44         }
45
46         // Delete admitted BA
47         if(pAdmittedBa->bValid)
48         {
49                 DeActivateBAEntry(ieee, pAdmittedBa);
50                 bSendDELBA = true;
51         }
52
53         return bSendDELBA;
54 }
55
56 /*
57  * deactivete BA entry in Tx Ts, and send DELBA.
58  */
59 u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD   pRxTs)
60 {
61         PBA_RECORD              pBa = &pRxTs->RxAdmittedBARecord;
62         u8                      bSendDELBA = false;
63
64         if(pBa->bValid)
65         {
66                 DeActivateBAEntry(ieee, pBa);
67                 bSendDELBA = true;
68         }
69
70         return bSendDELBA;
71 }
72
73 /*
74  * reset BA entry
75  */
76 void ResetBaEntry( PBA_RECORD pBA)
77 {
78         pBA->bValid                     = false;
79         pBA->BaParamSet.shortData       = 0;
80         pBA->BaTimeoutValue             = 0;
81         pBA->DialogToken                = 0;
82         pBA->BaStartSeqCtrl.ShortData   = 0;
83 }
84
85 /*
86  * construct ADDBAREQ and ADDBARSP frame here together.
87  * return constructed skb to xmit
88  */
89 static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
90 {
91         struct sk_buff *skb = NULL;
92          struct ieee80211_hdr_3addr* BAReq = NULL;
93         u8* tag = NULL;
94         u16 tmp = 0;
95         u16 len = ieee->tx_headroom + 9;
96         //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) +  BA Timeout Value(2) +  BA Start SeqCtrl(2)(or StatusCode(2))
97         IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
98         if (pBA == NULL||ieee == NULL)
99         {
100                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
101                 return NULL;
102         }
103         skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME
104         if (skb == NULL)
105         {
106                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
107                 return NULL;
108         }
109
110         memset(skb->data, 0, sizeof( struct ieee80211_hdr_3addr));      //I wonder whether it's necessary. Apparently kernel will not do it when alloc a skb.
111         skb_reserve(skb, ieee->tx_headroom);
112
113         BAReq = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
114
115         memcpy(BAReq->addr1, Dst, ETH_ALEN);
116         memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
117
118         memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
119
120         BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
121
122         //tag += sizeof( struct ieee80211_hdr_3addr); //move to action field
123         tag = (u8*)skb_put(skb, 9);
124         *tag ++= ACT_CAT_BA;
125         *tag ++= type;
126         // Dialog Token
127         *tag ++= pBA->DialogToken;
128
129         if (ACT_ADDBARSP == type)
130         {
131                 // Status Code
132                 printk("=====>to send ADDBARSP\n");
133                 tmp = cpu_to_le16(StatusCode);
134                 memcpy(tag, (u8*)&tmp, 2);
135                 tag += 2;
136         }
137         // BA Parameter Set
138         tmp = cpu_to_le16(pBA->BaParamSet.shortData);
139         memcpy(tag, (u8*)&tmp, 2);
140         tag += 2;
141         // BA Timeout Value
142         tmp = cpu_to_le16(pBA->BaTimeoutValue);
143         memcpy(tag, (u8*)&tmp, 2);
144         tag += 2;
145
146         if (ACT_ADDBAREQ == type)
147         {
148         // BA Start SeqCtrl
149                 memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2);
150                 tag += 2;
151         }
152
153         IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
154         return skb;
155         //return NULL;
156 }
157
158 /*
159  * construct DELBA frame
160  */
161 static struct sk_buff* ieee80211_DELBA(
162         struct ieee80211_device* ieee,
163         u8*                      dst,
164         PBA_RECORD               pBA,
165         TR_SELECT                TxRxSelect,
166         u16                      ReasonCode
167         )
168 {
169         DELBA_PARAM_SET DelbaParamSet;
170         struct sk_buff *skb = NULL;
171          struct ieee80211_hdr_3addr* Delba = NULL;
172         u8* tag = NULL;
173         u16 tmp = 0;
174         //len = head len + DELBA Parameter Set(2) + Reason Code(2)
175         u16 len = 6 + ieee->tx_headroom;
176
177         if (net_ratelimit())
178         IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
179
180         memset(&DelbaParamSet, 0, 2);
181
182         DelbaParamSet.field.Initiator   = (TxRxSelect==TX_DIR)?1:0;
183         DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
184
185         skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr)); //need to add something others? FIXME
186         if (skb == NULL)
187         {
188                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
189                 return NULL;
190         }
191 //      memset(skb->data, 0, len+sizeof( struct ieee80211_hdr_3addr));
192         skb_reserve(skb, ieee->tx_headroom);
193
194         Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
195
196         memcpy(Delba->addr1, dst, ETH_ALEN);
197         memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
198         memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
199         Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
200
201         tag = (u8*)skb_put(skb, 6);
202
203         *tag ++= ACT_CAT_BA;
204         *tag ++= ACT_DELBA;
205
206         // DELBA Parameter Set
207         tmp = cpu_to_le16(DelbaParamSet.shortData);
208         memcpy(tag, (u8*)&tmp, 2);
209         tag += 2;
210         // Reason Code
211         tmp = cpu_to_le16(ReasonCode);
212         memcpy(tag, (u8*)&tmp, 2);
213         tag += 2;
214
215         IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
216         if (net_ratelimit())
217         IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __FUNCTION__);
218         return skb;
219 }
220
221 /*
222  * send ADDBAReq frame out
223  * If any possible, please hide pBA in ieee.
224  * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
225  */
226 void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA)
227 {
228         struct sk_buff *skb = NULL;
229         skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
230
231         if (skb)
232         {
233                 softmac_mgmt_xmit(skb, ieee);
234                 //add statistic needed here.
235                 //and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
236                 //WB
237         }
238         else
239         {
240                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
241         }
242 }
243
244 /*
245  * send ADDBARSP frame out
246  *  If any possible, please hide pBA in ieee.
247  * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
248  */
249 void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
250 {
251         struct sk_buff *skb = NULL;
252         skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
253         if (skb)
254         {
255                 softmac_mgmt_xmit(skb, ieee);
256                 //same above
257         }
258         else
259         {
260                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
261         }
262 }
263
264 /*
265  * send ADDBARSP frame out
266  * If any possible, please hide pBA in ieee.
267  * And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
268  */
269 void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
270 {
271         struct sk_buff *skb = NULL;
272         skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
273         if (skb)
274         {
275                 softmac_mgmt_xmit(skb, ieee);
276                 //same above
277         }
278         else
279         {
280                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
281         }
282         return ;
283 }
284
285 int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
286 {
287          struct ieee80211_hdr_3addr* req = NULL;
288         u16 rc = 0;
289         u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL;
290         PBA_RECORD pBA = NULL;
291         PBA_PARAM_SET   pBaParamSet = NULL;
292         u16* pBaTimeoutVal = NULL;
293         PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
294         PRX_TS_RECORD   pTS = NULL;
295
296         if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
297         {
298                 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 9));
299                 return -1;
300         }
301
302         IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
303
304         req = ( struct ieee80211_hdr_3addr*) skb->data;
305         tag = (u8*)req;
306         dst = (u8*)(&req->addr2[0]);
307         tag += sizeof( struct ieee80211_hdr_3addr);
308         pDialogToken = tag + 2;  //category+action
309         pBaParamSet = (PBA_PARAM_SET)(tag + 3);   //+DialogToken
310         pBaTimeoutVal = (u16*)(tag + 5);
311         pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
312
313         printk("====================>rx ADDBAREQ from :%pM\n", dst);
314 //some other capability is not ready now.
315         if(     (ieee->current_network.qos_data.active == 0) ||
316                 (ieee->pHTInfo->bCurrentHTSupport == false)) //||
317         //      (ieee->pStaQos->bEnableRxImmBA == false)        )
318         {
319                 rc = ADDBA_STATUS_REFUSED;
320                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n", ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
321                 goto OnADDBAReq_Fail;
322         }
323         // Search for related traffic stream.
324         // If there is no matched TS, reject the ADDBA request.
325         if(     !GetTs(
326                         ieee,
327                         (PTS_COMMON_INFO*)(&pTS),
328                         dst,
329                         (u8)(pBaParamSet->field.TID),
330                         RX_DIR,
331                         true)   )
332         {
333                 rc = ADDBA_STATUS_REFUSED;
334                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
335                 goto OnADDBAReq_Fail;
336         }
337         pBA = &pTS->RxAdmittedBARecord;
338         // To Determine the ADDBA Req content
339         // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
340         // I want to check StartSeqCtrl to make sure when we start aggregation!!!
341         //
342         if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
343         {
344                 rc = ADDBA_STATUS_INVALID_PARAM;
345                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__);
346                 goto OnADDBAReq_Fail;
347         }
348                 // Admit the ADDBA Request
349         //
350         DeActivateBAEntry(ieee, pBA);
351         pBA->DialogToken = *pDialogToken;
352         pBA->BaParamSet = *pBaParamSet;
353         pBA->BaTimeoutValue = *pBaTimeoutVal;
354         pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
355         //for half N mode we only aggregate 1 frame
356         if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
357         pBA->BaParamSet.field.BufferSize = 1;
358         else
359         pBA->BaParamSet.field.BufferSize = 32;
360         ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue);
361         ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
362
363         // End of procedure.
364         return 0;
365
366 OnADDBAReq_Fail:
367         {
368                 BA_RECORD       BA;
369                 BA.BaParamSet = *pBaParamSet;
370                 BA.BaTimeoutValue = *pBaTimeoutVal;
371                 BA.DialogToken = *pDialogToken;
372                 BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
373                 ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
374                 return 0; //we send RSP out.
375         }
376
377 }
378
379 int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
380 {
381          struct ieee80211_hdr_3addr* rsp = NULL;
382         PBA_RECORD              pPendingBA, pAdmittedBA;
383         PTX_TS_RECORD           pTS = NULL;
384         u8* dst = NULL, *pDialogToken = NULL, *tag = NULL;
385         u16* pStatusCode = NULL, *pBaTimeoutVal = NULL;
386         PBA_PARAM_SET           pBaParamSet = NULL;
387         u16                     ReasonCode;
388
389         if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
390         {
391                 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 9));
392                 return -1;
393         }
394         rsp = ( struct ieee80211_hdr_3addr*)skb->data;
395         tag = (u8*)rsp;
396         dst = (u8*)(&rsp->addr2[0]);
397         tag += sizeof( struct ieee80211_hdr_3addr);
398         pDialogToken = tag + 2;
399         pStatusCode = (u16*)(tag + 3);
400         pBaParamSet = (PBA_PARAM_SET)(tag + 5);
401         pBaTimeoutVal = (u16*)(tag + 7);
402
403         // Check the capability
404         // Since we can always receive A-MPDU, we just check if it is under HT mode.
405         if(     ieee->current_network.qos_data.active == 0  ||
406                 ieee->pHTInfo->bCurrentHTSupport == false ||
407                 ieee->pHTInfo->bCurrentAMPDUEnable == false )
408         {
409                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bCurrentAMPDUEnable);
410                 ReasonCode = DELBA_REASON_UNKNOWN_BA;
411                 goto OnADDBARsp_Reject;
412         }
413
414
415         //
416         // Search for related TS.
417         // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
418         //
419         if (!GetTs(
420                         ieee,
421                         (PTS_COMMON_INFO*)(&pTS),
422                         dst,
423                         (u8)(pBaParamSet->field.TID),
424                         TX_DIR,
425                         false)  )
426         {
427                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
428                 ReasonCode = DELBA_REASON_UNKNOWN_BA;
429                 goto OnADDBARsp_Reject;
430         }
431
432         pTS->bAddBaReqInProgress = false;
433         pPendingBA = &pTS->TxPendingBARecord;
434         pAdmittedBA = &pTS->TxAdmittedBARecord;
435
436
437         //
438         // Check if related BA is waiting for setup.
439         // If not, reject by sending DELBA frame.
440         //
441         if((pAdmittedBA->bValid==true))
442         {
443                 // Since BA is already setup, we ignore all other ADDBA Response.
444                 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
445                 return -1;
446         }
447         else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
448         {
449                 IEEE80211_DEBUG(IEEE80211_DL_ERR,  "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
450                 ReasonCode = DELBA_REASON_UNKNOWN_BA;
451                 goto OnADDBARsp_Reject;
452         }
453         else
454         {
455                 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
456                 DeActivateBAEntry(ieee, pPendingBA);
457         }
458
459
460         if(*pStatusCode == ADDBA_STATUS_SUCCESS)
461         {
462                 //
463                 // Determine ADDBA Rsp content here.
464                 // We can compare the value of BA parameter set that Peer returned and Self sent.
465                 // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
466                 //
467                 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
468                 {
469                         // Since this is a kind of ADDBA failed, we delay next ADDBA process.
470                         pTS->bAddBaReqDelayed = true;
471                         DeActivateBAEntry(ieee, pAdmittedBA);
472                         ReasonCode = DELBA_REASON_END_BA;
473                         goto OnADDBARsp_Reject;
474                 }
475
476
477                 //
478                 // Admitted condition
479                 //
480                 pAdmittedBA->DialogToken = *pDialogToken;
481                 pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
482                 pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
483                 pAdmittedBA->BaParamSet = *pBaParamSet;
484                 DeActivateBAEntry(ieee, pAdmittedBA);
485                 ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
486         }
487         else
488         {
489                 // Delay next ADDBA process.
490                 pTS->bAddBaReqDelayed = true;
491         }
492
493         // End of procedure
494         return 0;
495
496 OnADDBARsp_Reject:
497         {
498                 BA_RECORD       BA;
499                 BA.BaParamSet = *pBaParamSet;
500                 ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
501                 return 0;
502         }
503
504 }
505
506 int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
507 {
508          struct ieee80211_hdr_3addr* delba = NULL;
509         PDELBA_PARAM_SET        pDelBaParamSet = NULL;
510         u16*                    pReasonCode = NULL;
511         u8*                     dst = NULL;
512
513         if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
514         {
515                 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len,    (sizeof( struct ieee80211_hdr_3addr) + 6));
516                 return -1;
517         }
518
519         if(ieee->current_network.qos_data.active == 0 ||
520                 ieee->pHTInfo->bCurrentHTSupport == false )
521         {
522                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "received DELBA while QOS or HT is not supported(%d, %d)\n",ieee->current_network.qos_data.active, ieee->pHTInfo->bCurrentHTSupport);
523                 return -1;
524         }
525
526         IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
527         delba = ( struct ieee80211_hdr_3addr*)skb->data;
528         dst = (u8*)(&delba->addr2[0]);
529         delba += sizeof( struct ieee80211_hdr_3addr);
530         pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
531         pReasonCode = (u16*)(delba+4);
532
533         if(pDelBaParamSet->field.Initiator == 1)
534         {
535                 PRX_TS_RECORD   pRxTs;
536
537                 if( !GetTs(
538                                 ieee,
539                                 (PTS_COMMON_INFO*)&pRxTs,
540                                 dst,
541                                 (u8)pDelBaParamSet->field.TID,
542                                 RX_DIR,
543                                 false)  )
544                 {
545                         IEEE80211_DEBUG(IEEE80211_DL_ERR,  "can't get TS for RXTS in %s()\n", __FUNCTION__);
546                         return -1;
547                 }
548
549                 RxTsDeleteBA(ieee, pRxTs);
550         }
551         else
552         {
553                 PTX_TS_RECORD   pTxTs;
554
555                 if(!GetTs(
556                         ieee,
557                         (PTS_COMMON_INFO*)&pTxTs,
558                         dst,
559                         (u8)pDelBaParamSet->field.TID,
560                         TX_DIR,
561                         false)  )
562                 {
563                         IEEE80211_DEBUG(IEEE80211_DL_ERR,  "can't get TS for TXTS in %s()\n", __FUNCTION__);
564                         return -1;
565                 }
566
567                 pTxTs->bUsingBa = false;
568                 pTxTs->bAddBaReqInProgress = false;
569                 pTxTs->bAddBaReqDelayed = false;
570                 del_timer_sync(&pTxTs->TsAddBaTimer);
571                 //PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
572                 TxTsDeleteBA(ieee, pTxTs);
573         }
574         return 0;
575 }
576
577 /* ADDBA initiate. This can only be called by TX side. */
578 void
579 TsInitAddBA(
580         struct ieee80211_device* ieee,
581         PTX_TS_RECORD   pTS,
582         u8              Policy,
583         u8              bOverwritePending
584         )
585 {
586         PBA_RECORD                      pBA = &pTS->TxPendingBARecord;
587
588         if(pBA->bValid==true && bOverwritePending==false)
589                 return;
590
591         // Set parameters to "Pending" variable set
592         DeActivateBAEntry(ieee, pBA);
593
594         pBA->DialogToken++;                                             // DialogToken: Only keep the latest dialog token
595         pBA->BaParamSet.field.AMSDU_Support = 0;        // Do not support A-MSDU with A-MPDU now!!
596         pBA->BaParamSet.field.BAPolicy = Policy;        // Policy: Delayed or Immediate
597         pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID;      // TID
598         // BufferSize: This need to be set according to A-MPDU vector
599         pBA->BaParamSet.field.BufferSize = 32;          // BufferSize: This need to be set according to A-MPDU vector
600         pBA->BaTimeoutValue = 0;                                        // Timeout value: Set 0 to disable Timer
601         pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096;  // Block Ack will start after 3 packets later.
602
603         ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
604
605         ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
606 }
607
608 void
609 TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
610 {
611
612         if(TxRxSelect == TX_DIR)
613         {
614                 PTX_TS_RECORD   pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
615
616                 if(TxTsDeleteBA(ieee, pTxTs))
617                         ieee80211_send_DELBA(
618                                 ieee,
619                                 pTsCommonInfo->Addr,
620                                 (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
621                                 TxRxSelect,
622                                 DELBA_REASON_END_BA);
623         }
624         else if(TxRxSelect == RX_DIR)
625         {
626                 PRX_TS_RECORD   pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
627                 if(RxTsDeleteBA(ieee, pRxTs))
628                         ieee80211_send_DELBA(
629                                 ieee,
630                                 pTsCommonInfo->Addr,
631                                 &pRxTs->RxAdmittedBARecord,
632                                 TxRxSelect,
633                                 DELBA_REASON_END_BA     );
634         }
635 }
636
637 /*
638  *  BA setup timer
639  *  acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
640  */
641 void BaSetupTimeOut(unsigned long data)
642 {
643         PTX_TS_RECORD   pTxTs = (PTX_TS_RECORD)data;
644
645         pTxTs->bAddBaReqInProgress = false;
646         pTxTs->bAddBaReqDelayed = true;
647         pTxTs->TxPendingBARecord.bValid = false;
648 }
649
650 void TxBaInactTimeout(unsigned long data)
651 {
652         PTX_TS_RECORD   pTxTs = (PTX_TS_RECORD)data;
653         struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
654         TxTsDeleteBA(ieee, pTxTs);
655         ieee80211_send_DELBA(
656                 ieee,
657                 pTxTs->TsCommonInfo.Addr,
658                 &pTxTs->TxAdmittedBARecord,
659                 TX_DIR,
660                 DELBA_REASON_TIMEOUT);
661 }
662
663 void RxBaInactTimeout(unsigned long data)
664 {
665         PRX_TS_RECORD   pRxTs = (PRX_TS_RECORD)data;
666         struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
667
668         RxTsDeleteBA(ieee, pRxTs);
669         ieee80211_send_DELBA(
670                 ieee,
671                 pRxTs->TsCommonInfo.Addr,
672                 &pRxTs->RxAdmittedBARecord,
673                 RX_DIR,
674                 DELBA_REASON_TIMEOUT);
675 }
676