GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / rtl8192u / ieee80211 / rtl819x_BAProc.c
blob6cf5266c1354c606eac7cf60fde289757da75f3c
1 /********************************************************************************************************************************
2 * This file is created to process BA Action Frame. According to 802.11 spec, there are 3 BA action types at all. And as BA is
3 * related to TS, this part need some struture defined in QOS side code. Also TX RX is going to be resturctured, so how to send
4 * ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
5 * WB 2008-05-27
6 * *****************************************************************************************************************************/
7 #include "ieee80211.h"
8 #include "rtl819x_BA.h"
10 /********************************************************************************************************************
11 *function: Activate BA entry. And if Time is nozero, start timer.
12 * input: PBA_RECORD pBA //BA entry to be enabled
13 * u16 Time //indicate time delay.
14 * output: none
15 ********************************************************************************************************************/
16 void ActivateBAEntry(struct ieee80211_device* ieee, PBA_RECORD pBA, u16 Time)
18 pBA->bValid = true;
19 if(Time != 0)
20 mod_timer(&pBA->Timer, jiffies + MSECS(Time));
23 /********************************************************************************************************************
24 *function: deactivate BA entry, including its timer.
25 * input: PBA_RECORD pBA //BA entry to be disabled
26 * output: none
27 ********************************************************************************************************************/
28 void DeActivateBAEntry( struct ieee80211_device* ieee, PBA_RECORD pBA)
30 pBA->bValid = false;
31 del_timer_sync(&pBA->Timer);
33 u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD pTxTs)
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;
39 // Delete pending BA
40 if(pPendingBa->bValid)
42 DeActivateBAEntry(ieee, pPendingBa);
43 bSendDELBA = true;
46 // Delete admitted BA
47 if(pAdmittedBa->bValid)
49 DeActivateBAEntry(ieee, pAdmittedBa);
50 bSendDELBA = true;
53 return bSendDELBA;
56 u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD pRxTs)
58 PBA_RECORD pBa = &pRxTs->RxAdmittedBARecord;
59 u8 bSendDELBA = false;
61 if(pBa->bValid)
63 DeActivateBAEntry(ieee, pBa);
64 bSendDELBA = true;
67 return bSendDELBA;
70 /********************************************************************************************************************
71 *function: reset BA entry
72 * input:
73 * PBA_RECORD pBA //entry to be reset
74 * output: none
75 ********************************************************************************************************************/
76 void ResetBaEntry( PBA_RECORD pBA)
78 pBA->bValid = false;
79 pBA->BaParamSet.shortData = 0;
80 pBA->BaTimeoutValue = 0;
81 pBA->DialogToken = 0;
82 pBA->BaStartSeqCtrl.ShortData = 0;
84 //These functions need porting here or not?
85 /*******************************************************************************************************************************
86 *function: construct ADDBAREQ and ADDBARSP frame here together.
87 * input: u8* Dst //ADDBA frame's destination
88 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA.
89 * u16 StatusCode //status code in RSP and I will use it to indicate whether it's RSP or REQ(will I?)
90 * u8 type //indicate whether it's RSP(ACT_ADDBARSP) ow REQ(ACT_ADDBAREQ)
91 * output: none
92 * return: sk_buff* skb //return constructed skb to xmit
93 *******************************************************************************************************************************/
94 static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
96 struct sk_buff *skb = NULL;
97 struct ieee80211_hdr_3addr* BAReq = NULL;
98 u8* tag = NULL;
99 u16 tmp = 0;
100 u16 len = ieee->tx_headroom + 9;
101 //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) + BA Timeout Value(2) + BA Start SeqCtrl(2)(or StatusCode(2))
102 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
103 if (pBA == NULL||ieee == NULL)
105 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
106 return NULL;
108 skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr));
109 if (skb == NULL)
111 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
112 return NULL;
115 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.
116 skb_reserve(skb, ieee->tx_headroom);
118 BAReq = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
120 memcpy(BAReq->addr1, Dst, ETH_ALEN);
121 memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
123 memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
125 BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
127 //tag += sizeof( struct ieee80211_hdr_3addr); //move to action field
128 tag = (u8*)skb_put(skb, 9);
129 *tag ++= ACT_CAT_BA;
130 *tag ++= type;
131 // Dialog Token
132 *tag ++= pBA->DialogToken;
134 if (ACT_ADDBARSP == type)
136 // Status Code
137 printk("=====>to send ADDBARSP\n");
138 tmp = cpu_to_le16(StatusCode);
139 memcpy(tag, (u8*)&tmp, 2);
140 tag += 2;
142 // BA Parameter Set
143 tmp = cpu_to_le16(pBA->BaParamSet.shortData);
144 memcpy(tag, (u8*)&tmp, 2);
145 tag += 2;
146 // BA Timeout Value
147 tmp = cpu_to_le16(pBA->BaTimeoutValue);
148 memcpy(tag, (u8*)&tmp, 2);
149 tag += 2;
151 if (ACT_ADDBAREQ == type)
153 // BA Start SeqCtrl
154 memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2);
155 tag += 2;
158 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
159 return skb;
160 //return NULL;
164 /********************************************************************************************************************
165 *function: construct DELBA frame
166 * input: u8* dst //DELBA frame's destination
167 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
168 * TR_SELECT TxRxSelect //TX RX direction
169 * u16 ReasonCode //status code.
170 * output: none
171 * return: sk_buff* skb //return constructed skb to xmit
172 ********************************************************************************************************************/
173 static struct sk_buff* ieee80211_DELBA(
174 struct ieee80211_device* ieee,
175 u8* dst,
176 PBA_RECORD pBA,
177 TR_SELECT TxRxSelect,
178 u16 ReasonCode
181 DELBA_PARAM_SET DelbaParamSet;
182 struct sk_buff *skb = NULL;
183 struct ieee80211_hdr_3addr* Delba = NULL;
184 u8* tag = NULL;
185 u16 tmp = 0;
186 //len = head len + DELBA Parameter Set(2) + Reason Code(2)
187 u16 len = 6 + ieee->tx_headroom;
189 if (net_ratelimit())
190 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
192 memset(&DelbaParamSet, 0, 2);
194 DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0;
195 DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
197 skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr));
198 if (skb == NULL)
200 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
201 return NULL;
203 // memset(skb->data, 0, len+sizeof( struct ieee80211_hdr_3addr));
204 skb_reserve(skb, ieee->tx_headroom);
206 Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
208 memcpy(Delba->addr1, dst, ETH_ALEN);
209 memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
210 memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
211 Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
213 tag = (u8*)skb_put(skb, 6);
215 *tag ++= ACT_CAT_BA;
216 *tag ++= ACT_DELBA;
218 // DELBA Parameter Set
219 tmp = cpu_to_le16(DelbaParamSet.shortData);
220 memcpy(tag, (u8*)&tmp, 2);
221 tag += 2;
222 // Reason Code
223 tmp = cpu_to_le16(ReasonCode);
224 memcpy(tag, (u8*)&tmp, 2);
225 tag += 2;
227 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
228 if (net_ratelimit())
229 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __FUNCTION__);
230 return skb;
233 /********************************************************************************************************************
234 *function: send ADDBAReq frame out
235 * input: u8* dst //ADDBAReq frame's destination
236 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
237 * output: none
238 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
239 ********************************************************************************************************************/
240 void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA)
242 struct sk_buff *skb = NULL;
243 skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
245 if (skb)
247 softmac_mgmt_xmit(skb, ieee);
248 //add statistic needed here.
249 //and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
250 //WB
252 else
254 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
256 return;
259 /********************************************************************************************************************
260 *function: send ADDBARSP frame out
261 * input: u8* dst //DELBA frame's destination
262 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
263 * u16 StatusCode //RSP StatusCode
264 * output: none
265 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
266 ********************************************************************************************************************/
267 void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
269 struct sk_buff *skb = NULL;
270 skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
271 if (skb)
273 softmac_mgmt_xmit(skb, ieee);
274 //same above
276 else
278 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
281 return;
284 /********************************************************************************************************************
285 *function: send ADDBARSP frame out
286 * input: u8* dst //DELBA frame's destination
287 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
288 * TR_SELECT TxRxSelect //TX or RX
289 * u16 ReasonCode //DEL ReasonCode
290 * output: none
291 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
292 ********************************************************************************************************************/
294 void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
296 struct sk_buff *skb = NULL;
297 skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
298 if (skb)
300 softmac_mgmt_xmit(skb, ieee);
301 //same above
303 else
305 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
307 return ;
310 /********************************************************************************************************************
311 *function: RX ADDBAReq
312 * input: struct sk_buff * skb //incoming ADDBAReq skb.
313 * return: 0(pass), other(fail)
314 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
315 ********************************************************************************************************************/
316 int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
318 struct ieee80211_hdr_3addr* req = NULL;
319 u16 rc = 0;
320 u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL;
321 PBA_RECORD pBA = NULL;
322 PBA_PARAM_SET pBaParamSet = NULL;
323 u16* pBaTimeoutVal = NULL;
324 PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
325 PRX_TS_RECORD pTS = NULL;
327 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
329 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BAREQ(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
330 return -1;
333 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
335 req = ( struct ieee80211_hdr_3addr*) skb->data;
336 tag = (u8*)req;
337 dst = (u8*)(&req->addr2[0]);
338 tag += sizeof( struct ieee80211_hdr_3addr);
339 pDialogToken = tag + 2; //category+action
340 pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken
341 pBaTimeoutVal = (u16*)(tag + 5);
342 pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
344 printk("====================>rx ADDBAREQ from :%pM\n", dst);
345 //some other capability is not ready now.
346 if( (ieee->current_network.qos_data.active == 0) ||
347 (ieee->pHTInfo->bCurrentHTSupport == false)) //||
348 // (ieee->pStaQos->bEnableRxImmBA == false) )
350 rc = ADDBA_STATUS_REFUSED;
351 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);
352 goto OnADDBAReq_Fail;
354 // Search for related traffic stream.
355 // If there is no matched TS, reject the ADDBA request.
356 if( !GetTs(
357 ieee,
358 (PTS_COMMON_INFO*)(&pTS),
359 dst,
360 (u8)(pBaParamSet->field.TID),
361 RX_DIR,
362 true) )
364 rc = ADDBA_STATUS_REFUSED;
365 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
366 goto OnADDBAReq_Fail;
368 pBA = &pTS->RxAdmittedBARecord;
369 // To Determine the ADDBA Req content
370 // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
371 // I want to check StartSeqCtrl to make sure when we start aggregation!!!
373 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
375 rc = ADDBA_STATUS_INVALID_PARAM;
376 IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__);
377 goto OnADDBAReq_Fail;
379 // Admit the ADDBA Request
381 DeActivateBAEntry(ieee, pBA);
382 pBA->DialogToken = *pDialogToken;
383 pBA->BaParamSet = *pBaParamSet;
384 pBA->BaTimeoutValue = *pBaTimeoutVal;
385 pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
386 //for half N mode we only aggregate 1 frame
387 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
388 pBA->BaParamSet.field.BufferSize = 1;
389 else
390 pBA->BaParamSet.field.BufferSize = 32;
391 ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue);
392 ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
394 // End of procedure.
395 return 0;
397 OnADDBAReq_Fail:
399 BA_RECORD BA;
400 BA.BaParamSet = *pBaParamSet;
401 BA.BaTimeoutValue = *pBaTimeoutVal;
402 BA.DialogToken = *pDialogToken;
403 BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
404 ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
405 return 0; //we send RSP out.
410 /********************************************************************************************************************
411 *function: RX ADDBARSP
412 * input: struct sk_buff * skb //incoming ADDBAReq skb.
413 * return: 0(pass), other(fail)
414 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
415 ********************************************************************************************************************/
416 int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
418 struct ieee80211_hdr_3addr* rsp = NULL;
419 PBA_RECORD pPendingBA, pAdmittedBA;
420 PTX_TS_RECORD pTS = NULL;
421 u8* dst = NULL, *pDialogToken = NULL, *tag = NULL;
422 u16* pStatusCode = NULL, *pBaTimeoutVal = NULL;
423 PBA_PARAM_SET pBaParamSet = NULL;
424 u16 ReasonCode;
426 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
428 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in BARSP(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 9));
429 return -1;
431 rsp = ( struct ieee80211_hdr_3addr*)skb->data;
432 tag = (u8*)rsp;
433 dst = (u8*)(&rsp->addr2[0]);
434 tag += sizeof( struct ieee80211_hdr_3addr);
435 pDialogToken = tag + 2;
436 pStatusCode = (u16*)(tag + 3);
437 pBaParamSet = (PBA_PARAM_SET)(tag + 5);
438 pBaTimeoutVal = (u16*)(tag + 7);
440 // Check the capability
441 // Since we can always receive A-MPDU, we just check if it is under HT mode.
442 if( ieee->current_network.qos_data.active == 0 ||
443 ieee->pHTInfo->bCurrentHTSupport == false ||
444 ieee->pHTInfo->bCurrentAMPDUEnable == false )
446 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);
447 ReasonCode = DELBA_REASON_UNKNOWN_BA;
448 goto OnADDBARsp_Reject;
453 // Search for related TS.
454 // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
456 if (!GetTs(
457 ieee,
458 (PTS_COMMON_INFO*)(&pTS),
459 dst,
460 (u8)(pBaParamSet->field.TID),
461 TX_DIR,
462 false) )
464 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
465 ReasonCode = DELBA_REASON_UNKNOWN_BA;
466 goto OnADDBARsp_Reject;
469 pTS->bAddBaReqInProgress = false;
470 pPendingBA = &pTS->TxPendingBARecord;
471 pAdmittedBA = &pTS->TxAdmittedBARecord;
475 // Check if related BA is waiting for setup.
476 // If not, reject by sending DELBA frame.
478 if((pAdmittedBA->bValid==true))
480 // Since BA is already setup, we ignore all other ADDBA Response.
481 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
482 return -1;
484 else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
486 IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
487 ReasonCode = DELBA_REASON_UNKNOWN_BA;
488 goto OnADDBARsp_Reject;
490 else
492 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
493 DeActivateBAEntry(ieee, pPendingBA);
497 if(*pStatusCode == ADDBA_STATUS_SUCCESS)
500 // Determine ADDBA Rsp content here.
501 // We can compare the value of BA parameter set that Peer returned and Self sent.
502 // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
504 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
506 // Since this is a kind of ADDBA failed, we delay next ADDBA process.
507 pTS->bAddBaReqDelayed = true;
508 DeActivateBAEntry(ieee, pAdmittedBA);
509 ReasonCode = DELBA_REASON_END_BA;
510 goto OnADDBARsp_Reject;
515 // Admitted condition
517 pAdmittedBA->DialogToken = *pDialogToken;
518 pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
519 pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
520 pAdmittedBA->BaParamSet = *pBaParamSet;
521 DeActivateBAEntry(ieee, pAdmittedBA);
522 ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
524 else
526 // Delay next ADDBA process.
527 pTS->bAddBaReqDelayed = true;
530 // End of procedure
531 return 0;
533 OnADDBARsp_Reject:
535 BA_RECORD BA;
536 BA.BaParamSet = *pBaParamSet;
537 ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
538 return 0;
543 /********************************************************************************************************************
544 *function: RX DELBA
545 * input: struct sk_buff * skb //incoming ADDBAReq skb.
546 * return: 0(pass), other(fail)
547 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
548 ********************************************************************************************************************/
549 int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
551 struct ieee80211_hdr_3addr* delba = NULL;
552 PDELBA_PARAM_SET pDelBaParamSet = NULL;
553 u16* pReasonCode = NULL;
554 u8* dst = NULL;
556 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
558 IEEE80211_DEBUG(IEEE80211_DL_ERR, " Invalid skb len in DELBA(%d / %zu)\n", skb->len, (sizeof( struct ieee80211_hdr_3addr) + 6));
559 return -1;
562 if(ieee->current_network.qos_data.active == 0 ||
563 ieee->pHTInfo->bCurrentHTSupport == false )
565 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);
566 return -1;
569 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
570 delba = ( struct ieee80211_hdr_3addr*)skb->data;
571 dst = (u8*)(&delba->addr2[0]);
572 delba += sizeof( struct ieee80211_hdr_3addr);
573 pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
574 pReasonCode = (u16*)(delba+4);
576 if(pDelBaParamSet->field.Initiator == 1)
578 PRX_TS_RECORD pRxTs;
580 if( !GetTs(
581 ieee,
582 (PTS_COMMON_INFO*)&pRxTs,
583 dst,
584 (u8)pDelBaParamSet->field.TID,
585 RX_DIR,
586 false) )
588 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for RXTS in %s()\n", __FUNCTION__);
589 return -1;
592 RxTsDeleteBA(ieee, pRxTs);
594 else
596 PTX_TS_RECORD pTxTs;
598 if(!GetTs(
599 ieee,
600 (PTS_COMMON_INFO*)&pTxTs,
601 dst,
602 (u8)pDelBaParamSet->field.TID,
603 TX_DIR,
604 false) )
606 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for TXTS in %s()\n", __FUNCTION__);
607 return -1;
610 pTxTs->bUsingBa = false;
611 pTxTs->bAddBaReqInProgress = false;
612 pTxTs->bAddBaReqDelayed = false;
613 del_timer_sync(&pTxTs->TsAddBaTimer);
614 //PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
615 TxTsDeleteBA(ieee, pTxTs);
617 return 0;
621 // ADDBA initiate. This can only be called by TX side.
623 void
624 TsInitAddBA(
625 struct ieee80211_device* ieee,
626 PTX_TS_RECORD pTS,
627 u8 Policy,
628 u8 bOverwritePending
631 PBA_RECORD pBA = &pTS->TxPendingBARecord;
633 if(pBA->bValid==true && bOverwritePending==false)
634 return;
636 // Set parameters to "Pending" variable set
637 DeActivateBAEntry(ieee, pBA);
639 pBA->DialogToken++; // DialogToken: Only keep the latest dialog token
640 pBA->BaParamSet.field.AMSDU_Support = 0; // Do not support A-MSDU with A-MPDU now!!
641 pBA->BaParamSet.field.BAPolicy = Policy; // Policy: Delayed or Immediate
642 pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID; // TID
643 // BufferSize: This need to be set according to A-MPDU vector
644 pBA->BaParamSet.field.BufferSize = 32; // BufferSize: This need to be set according to A-MPDU vector
645 pBA->BaTimeoutValue = 0; // Timeout value: Set 0 to disable Timer
646 pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; // Block Ack will start after 3 packets later.
648 ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
650 ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
653 void
654 TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
657 if(TxRxSelect == TX_DIR)
659 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
661 if(TxTsDeleteBA(ieee, pTxTs))
662 ieee80211_send_DELBA(
663 ieee,
664 pTsCommonInfo->Addr,
665 (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
666 TxRxSelect,
667 DELBA_REASON_END_BA);
669 else if(TxRxSelect == RX_DIR)
671 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
672 if(RxTsDeleteBA(ieee, pRxTs))
673 ieee80211_send_DELBA(
674 ieee,
675 pTsCommonInfo->Addr,
676 &pRxTs->RxAdmittedBARecord,
677 TxRxSelect,
678 DELBA_REASON_END_BA );
681 /********************************************************************************************************************
682 *function: BA setup timer
683 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
684 * return: NULL
685 * notice:
686 ********************************************************************************************************************/
687 void BaSetupTimeOut(unsigned long data)
689 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
691 pTxTs->bAddBaReqInProgress = false;
692 pTxTs->bAddBaReqDelayed = true;
693 pTxTs->TxPendingBARecord.bValid = false;
696 void TxBaInactTimeout(unsigned long data)
698 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
699 struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
700 TxTsDeleteBA(ieee, pTxTs);
701 ieee80211_send_DELBA(
702 ieee,
703 pTxTs->TsCommonInfo.Addr,
704 &pTxTs->TxAdmittedBARecord,
705 TX_DIR,
706 DELBA_REASON_TIMEOUT);
709 void RxBaInactTimeout(unsigned long data)
711 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data;
712 struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
714 RxTsDeleteBA(ieee, pRxTs);
715 ieee80211_send_DELBA(
716 ieee,
717 pRxTs->TsCommonInfo.Addr,
718 &pRxTs->RxAdmittedBARecord,
719 RX_DIR,
720 DELBA_REASON_TIMEOUT);
721 return ;