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