Fix common misspellings
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / rtl8192e / ieee80211 / rtl819x_BAProc.c
CommitLineData
c8881632
MM
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 */
ecdfa446
GKH
8#include "ieee80211.h"
9#include "rtl819x_BA.h"
10
c8881632
MM
11/*
12 * Activate BA entry. And if Time is nozero, start timer.
13 */
ecdfa446
GKH
14void 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
c8881632
MM
21/*
22 * deactivate BA entry, including its timer.
23 */
ecdfa446
GKH
24void DeActivateBAEntry( struct ieee80211_device* ieee, PBA_RECORD pBA)
25{
26 pBA->bValid = false;
27 del_timer_sync(&pBA->Timer);
28}
c8881632
MM
29
30/*
31 * deactivete BA entry in Tx Ts, and send DELBA.
32 */
ecdfa446
GKH
33u8 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
c8881632
MM
56/*
57 * deactivete BA entry in Tx Ts, and send DELBA.
58 */
ecdfa446
GKH
59u8 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
c8881632
MM
73/*
74 * reset BA entry
75 */
ecdfa446
GKH
76void 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}
c8881632
MM
84
85/*
86 * construct ADDBAREQ and ADDBARSP frame here together.
87 * return constructed skb to xmit
88 */
ecdfa446
GKH
89static 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))
0ee9f67c 97 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
ecdfa446
GKH
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
c8881632
MM
158/*
159 * construct DELBA frame
160 */
ecdfa446
GKH
161static 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())
0ee9f67c 178 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
ecdfa446
GKH
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
c8881632
MM
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 */
ecdfa446
GKH
226void 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 }
ecdfa446
GKH
242}
243
c8881632
MM
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 */
ecdfa446
GKH
249void 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 }
ecdfa446 262}
ecdfa446 263
c8881632
MM
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 */
ecdfa446
GKH
269void 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
ecdfa446
GKH
285int 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 {
3d8affc0 298 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
ecdfa446
GKH
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
0ee9f67c 313 printk("====================>rx ADDBAREQ from :%pM\n", dst);
ecdfa446
GKH
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
1e04ca7a 356 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee))
ecdfa446
GKH
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
366OnADDBAReq_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
ecdfa446
GKH
379int 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 {
3d8affc0 391 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
ecdfa446
GKH
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
496OnADDBARsp_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
ecdfa446
GKH
506int 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 {
3d8affc0 515 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6));
ecdfa446
GKH
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
c8881632 577/* ADDBA initiate. This can only be called by TX side. */
ecdfa446
GKH
578void
579TsInitAddBA(
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
608void
609TsInitDelBA( 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}
c8881632
MM
636
637/*
638 * BA setup timer
639 * acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
640 */
ecdfa446
GKH
641void 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
650void 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
663void 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);
ecdfa446
GKH
675}
676