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 / rtl8192su / ieee80211 / rtl819x_BAProc.c
blob619e98d5b2c6e1faab76bb36e3d6a4e16162ec8e
1 /******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
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.
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
13 * The full GNU General Public License is included in this distribution in the
14 * file called LICENSE.
16 * Contact Information:
17 * wlanfae <wlanfae@realtek.com>
18 ******************************************************************************/
19 #include "ieee80211.h"
20 #include "rtl819x_BA.h"
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)
30 pBA->bValid = true;
31 if(Time != 0)
32 mod_timer(&pBA->Timer, jiffies + MSECS(Time));
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)
42 pBA->bValid = false;
43 del_timer_sync(&pBA->Timer);
45 u8 TxTsDeleteBA( struct ieee80211_device* ieee, PTX_TS_RECORD pTxTs)
47 PBA_RECORD pAdmittedBa = &pTxTs->TxAdmittedBARecord; //These two BA entries must exist in TS structure
48 PBA_RECORD pPendingBa = &pTxTs->TxPendingBARecord;
49 u8 bSendDELBA = false;
51 // Delete pending BA
52 if(pPendingBa->bValid)
54 DeActivateBAEntry(ieee, pPendingBa);
55 bSendDELBA = true;
58 // Delete admitted BA
59 if(pAdmittedBa->bValid)
61 DeActivateBAEntry(ieee, pAdmittedBa);
62 bSendDELBA = true;
65 return bSendDELBA;
68 u8 RxTsDeleteBA( struct ieee80211_device* ieee, PRX_TS_RECORD pRxTs)
70 PBA_RECORD pBa = &pRxTs->RxAdmittedBARecord;
71 u8 bSendDELBA = false;
73 if(pBa->bValid)
75 DeActivateBAEntry(ieee, pBa);
76 bSendDELBA = true;
79 return bSendDELBA;
82 /********************************************************************************************************************
83 *function: reset BA entry
84 * input:
85 * PBA_RECORD pBA //entry to be reset
86 * output: none
87 ********************************************************************************************************************/
88 void ResetBaEntry( PBA_RECORD pBA)
90 pBA->bValid = false;
91 pBA->BaParamSet.shortData = 0;
92 pBA->BaTimeoutValue = 0;
93 pBA->DialogToken = 0;
94 pBA->BaStartSeqCtrl.ShortData = 0;
96 //These functions need porting here or not?
97 /*******************************************************************************************************************************
98 *function: construct ADDBAREQ and ADDBARSP frame here together.
99 * input: u8* Dst //ADDBA frame's destination
100 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA.
101 * u16 StatusCode //status code in RSP and I will use it to indicate whether it's RSP or REQ(will I?)
102 * u8 type //indicate whether it's RSP(ACT_ADDBARSP) ow REQ(ACT_ADDBAREQ)
103 * output: none
104 * return: sk_buff* skb //return constructed skb to xmit
105 *******************************************************************************************************************************/
106 static struct sk_buff* ieee80211_ADDBA(struct ieee80211_device* ieee, u8* Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
108 struct sk_buff *skb = NULL;
109 struct ieee80211_hdr_3addr* BAReq = NULL;
110 u8* tag = NULL;
111 u16 tmp = 0;
112 u16 len = ieee->tx_headroom + 9;
113 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __FUNCTION__, type, Dst, ieee->dev);
114 if (pBA == NULL||ieee == NULL)
116 IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA(%p) is NULL or ieee(%p) is NULL\n", pBA, ieee);
117 return NULL;
119 skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr));
120 if (skb == NULL)
122 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
123 return NULL;
126 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.
127 skb_reserve(skb, ieee->tx_headroom);
129 BAReq = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
131 memcpy(BAReq->addr1, Dst, ETH_ALEN);
132 memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
134 memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
136 BAReq->frame_control = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
138 tag = (u8*)skb_put(skb, 9);
139 *tag ++= ACT_CAT_BA;
140 *tag ++= type;
141 // Dialog Token
142 *tag ++= pBA->DialogToken;
144 if (ACT_ADDBARSP == type)
146 // Status Code
147 printk("=====>to send ADDBARSP\n");
148 tmp = cpu_to_le16(StatusCode);
149 memcpy(tag, (u8*)&tmp, 2);
150 tag += 2;
152 // BA Parameter Set
153 tmp = cpu_to_le16(pBA->BaParamSet.shortData);
154 memcpy(tag, (u8*)&tmp, 2);
155 tag += 2;
156 // BA Timeout Value
157 tmp = cpu_to_le16(pBA->BaTimeoutValue);
158 memcpy(tag, (u8*)&tmp, 2);
159 tag += 2;
161 if (ACT_ADDBAREQ == type)
163 // BA Start SeqCtrl
164 memcpy(tag,(u8*)&(pBA->BaStartSeqCtrl), 2);
165 tag += 2;
168 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
169 return skb;
172 /********************************************************************************************************************
173 *function: construct DELBA frame
174 * input: u8* dst //DELBA frame's destination
175 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
176 * TR_SELECT TxRxSelect //TX RX direction
177 * u16 ReasonCode //status code.
178 * output: none
179 * return: sk_buff* skb //return constructed skb to xmit
180 ********************************************************************************************************************/
181 static struct sk_buff* ieee80211_DELBA(
182 struct ieee80211_device* ieee,
183 u8* dst,
184 PBA_RECORD pBA,
185 TR_SELECT TxRxSelect,
186 u16 ReasonCode
189 DELBA_PARAM_SET DelbaParamSet;
190 struct sk_buff *skb = NULL;
191 struct ieee80211_hdr_3addr* Delba = NULL;
192 u8* tag = NULL;
193 u16 tmp = 0;
194 u16 len = 6 + ieee->tx_headroom;
196 if (net_ratelimit())
197 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), ReasonCode(%d) sentd to:%pM\n", __FUNCTION__, ReasonCode, dst);
199 memset(&DelbaParamSet, 0, 2);
201 DelbaParamSet.field.Initiator = (TxRxSelect==TX_DIR)?1:0;
202 DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
204 skb = dev_alloc_skb(len + sizeof( struct ieee80211_hdr_3addr));
205 if (skb == NULL)
207 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
208 return NULL;
210 skb_reserve(skb, ieee->tx_headroom);
212 Delba = ( struct ieee80211_hdr_3addr *) skb_put(skb,sizeof( struct ieee80211_hdr_3addr));
214 memcpy(Delba->addr1, dst, ETH_ALEN);
215 memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
216 memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
217 Delba->frame_control = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
219 tag = (u8*)skb_put(skb, 6);
221 *tag ++= ACT_CAT_BA;
222 *tag ++= ACT_DELBA;
224 // DELBA Parameter Set
225 tmp = cpu_to_le16(DelbaParamSet.shortData);
226 memcpy(tag, (u8*)&tmp, 2);
227 tag += 2;
228 // Reason Code
229 tmp = cpu_to_le16(ReasonCode);
230 memcpy(tag, (u8*)&tmp, 2);
231 tag += 2;
233 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
234 if (net_ratelimit())
235 IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "<=====%s()\n", __FUNCTION__);
236 return skb;
239 /********************************************************************************************************************
240 *function: send ADDBAReq frame out
241 * input: u8* dst //ADDBAReq frame's destination
242 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
243 * output: none
244 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
245 ********************************************************************************************************************/
246 void ieee80211_send_ADDBAReq(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA)
248 struct sk_buff *skb = NULL;
249 skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
251 if (skb)
253 softmac_mgmt_xmit(skb, ieee);
255 else
257 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
259 return;
262 /********************************************************************************************************************
263 *function: send ADDBARSP frame out
264 * input: u8* dst //DELBA frame's destination
265 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
266 * u16 StatusCode //RSP StatusCode
267 * output: none
268 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
269 ********************************************************************************************************************/
270 void ieee80211_send_ADDBARsp(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, u16 StatusCode)
272 struct sk_buff *skb = NULL;
273 skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
274 if (skb)
276 softmac_mgmt_xmit(skb, ieee);
278 else
280 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
283 return;
286 /********************************************************************************************************************
287 *function: send ADDBARSP frame out
288 * input: u8* dst //DELBA frame's destination
289 * PBA_RECORD pBA //BA_RECORD entry which stores the necessary information for BA
290 * TR_SELECT TxRxSelect //TX or RX
291 * u16 ReasonCode //DEL ReasonCode
292 * output: none
293 * notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
294 ********************************************************************************************************************/
296 void ieee80211_send_DELBA(struct ieee80211_device* ieee, u8* dst, PBA_RECORD pBA, TR_SELECT TxRxSelect, u16 ReasonCode)
298 struct sk_buff *skb = NULL;
299 skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
300 if (skb)
302 softmac_mgmt_xmit(skb, ieee);
304 else
306 IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __FUNCTION__);
308 return ;
311 /********************************************************************************************************************
312 *function: RX ADDBAReq
313 * input: struct sk_buff * skb //incoming ADDBAReq skb.
314 * return: 0(pass), other(fail)
315 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
316 ********************************************************************************************************************/
317 int ieee80211_rx_ADDBAReq( struct ieee80211_device* ieee, struct sk_buff *skb)
319 struct ieee80211_hdr_3addr* req = NULL;
320 u16 rc = 0;
321 u8 * dst = NULL, *pDialogToken = NULL, *tag = NULL;
322 PBA_RECORD pBA = NULL;
323 PBA_PARAM_SET pBaParamSet = NULL;
324 u16* pBaTimeoutVal = NULL;
325 PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
326 PRX_TS_RECORD pTS = NULL;
328 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
330 IEEE80211_DEBUG(IEEE80211_DL_ERR,
331 " Invalid skb len in BAREQ(%d / %zd)\n",
332 skb->len,
333 sizeof(struct ieee80211_hdr_3addr) + 9);
334 return -1;
337 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
339 req = ( struct ieee80211_hdr_3addr*) skb->data;
340 tag = (u8*)req;
341 dst = (u8*)(&req->addr2[0]);
342 tag += sizeof( struct ieee80211_hdr_3addr);
343 pDialogToken = tag + 2; //category+action
344 pBaParamSet = (PBA_PARAM_SET)(tag + 3); //+DialogToken
345 pBaTimeoutVal = (u16*)(tag + 5);
346 pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
348 printk("====================>rx ADDBAREQ from :%pM\n", dst);
349 //some other capability is not ready now.
350 if( (ieee->current_network.qos_data.active == 0) ||
351 (ieee->pHTInfo->bCurrentHTSupport == false) ||
352 (ieee->pHTInfo->IOTAction & HT_IOT_ACT_REJECT_ADDBA_REQ))
354 rc = ADDBA_STATUS_REFUSED;
355 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);
356 goto OnADDBAReq_Fail;
358 // Search for related traffic stream.
359 // If there is no matched TS, reject the ADDBA request.
360 if( !GetTs(
361 ieee,
362 (PTS_COMMON_INFO*)(&pTS),
363 dst,
364 (u8)(pBaParamSet->field.TID),
365 RX_DIR,
366 true) )
368 rc = ADDBA_STATUS_REFUSED;
369 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
370 goto OnADDBAReq_Fail;
372 pBA = &pTS->RxAdmittedBARecord;
373 // To Determine the ADDBA Req content
374 // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
375 // I want to check StartSeqCtrl to make sure when we start aggregation!!!
377 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
379 rc = ADDBA_STATUS_INVALID_PARAM;
380 IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __FUNCTION__);
381 goto OnADDBAReq_Fail;
383 // Admit the ADDBA Request
384 DeActivateBAEntry(ieee, pBA);
385 pBA->DialogToken = *pDialogToken;
386 pBA->BaParamSet = *pBaParamSet;
387 pBA->BaTimeoutValue = *pBaTimeoutVal;
388 pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
389 //for half N mode we only aggregate 1 frame
390 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)||
391 (ieee->pHTInfo->IOTAction & HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT))
392 pBA->BaParamSet.field.BufferSize = 1;
393 else
394 pBA->BaParamSet.field.BufferSize = 32;
395 ActivateBAEntry(ieee, pBA, 0);
396 ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
398 return 0;
400 OnADDBAReq_Fail:
402 BA_RECORD BA;
403 BA.BaParamSet = *pBaParamSet;
404 BA.BaTimeoutValue = *pBaTimeoutVal;
405 BA.DialogToken = *pDialogToken;
406 BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
407 ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
408 return 0; //we send RSP out.
413 /********************************************************************************************************************
414 *function: RX ADDBARSP
415 * input: struct sk_buff * skb //incoming ADDBAReq skb.
416 * return: 0(pass), other(fail)
417 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
418 ********************************************************************************************************************/
419 int ieee80211_rx_ADDBARsp( struct ieee80211_device* ieee, struct sk_buff *skb)
421 struct ieee80211_hdr_3addr* rsp = NULL;
422 PBA_RECORD pPendingBA, pAdmittedBA;
423 PTX_TS_RECORD pTS = NULL;
424 u8* dst = NULL, *pDialogToken = NULL, *tag = NULL;
425 u16* pStatusCode = NULL, *pBaTimeoutVal = NULL;
426 PBA_PARAM_SET pBaParamSet = NULL;
427 u16 ReasonCode;
429 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 9)
431 IEEE80211_DEBUG(IEEE80211_DL_ERR,
432 " Invalid skb len in BARSP(%d / %zd)\n",
433 skb->len,
434 sizeof(struct ieee80211_hdr_3addr) + 9);
435 return -1;
437 rsp = ( struct ieee80211_hdr_3addr*)skb->data;
438 tag = (u8*)rsp;
439 dst = (u8*)(&rsp->addr2[0]);
440 tag += sizeof( struct ieee80211_hdr_3addr);
441 pDialogToken = tag + 2;
442 pStatusCode = (u16*)(tag + 3);
443 pBaParamSet = (PBA_PARAM_SET)(tag + 5);
444 pBaTimeoutVal = (u16*)(tag + 7);
446 // Check the capability
447 // Since we can always receive A-MPDU, we just check if it is under HT mode.
448 if( ieee->current_network.qos_data.active == 0 ||
449 ieee->pHTInfo->bCurrentHTSupport == false ||
450 ieee->pHTInfo->bCurrentAMPDUEnable == false )
452 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);
453 ReasonCode = DELBA_REASON_UNKNOWN_BA;
454 goto OnADDBARsp_Reject;
459 // Search for related TS.
460 // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
462 if (!GetTs(
463 ieee,
464 (PTS_COMMON_INFO*)(&pTS),
465 dst,
466 (u8)(pBaParamSet->field.TID),
467 TX_DIR,
468 false) )
470 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __FUNCTION__);
471 ReasonCode = DELBA_REASON_UNKNOWN_BA;
472 goto OnADDBARsp_Reject;
475 pTS->bAddBaReqInProgress = false;
476 pPendingBA = &pTS->TxPendingBARecord;
477 pAdmittedBA = &pTS->TxAdmittedBARecord;
481 // Check if related BA is waiting for setup.
482 // If not, reject by sending DELBA frame.
484 if((pAdmittedBA->bValid==true))
486 // Since BA is already setup, we ignore all other ADDBA Response.
487 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
488 return -1;
490 else if((pPendingBA->bValid == false) ||(*pDialogToken != pPendingBA->DialogToken))
492 IEEE80211_DEBUG(IEEE80211_DL_ERR, "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
493 ReasonCode = DELBA_REASON_UNKNOWN_BA;
494 goto OnADDBARsp_Reject;
496 else
498 IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
499 DeActivateBAEntry(ieee, pPendingBA);
503 if(*pStatusCode == ADDBA_STATUS_SUCCESS)
506 // Determine ADDBA Rsp content here.
507 // We can compare the value of BA parameter set that Peer returned and Self sent.
508 // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
510 if(pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED)
512 // Since this is a kind of ADDBA failed, we delay next ADDBA process.
513 pTS->bAddBaReqDelayed = true;
514 DeActivateBAEntry(ieee, pAdmittedBA);
515 ReasonCode = DELBA_REASON_END_BA;
516 goto OnADDBARsp_Reject;
521 // Admitted condition
523 pAdmittedBA->DialogToken = *pDialogToken;
524 pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
525 pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
526 pAdmittedBA->BaParamSet = *pBaParamSet;
527 DeActivateBAEntry(ieee, pAdmittedBA);
528 ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
529 } else {
530 pTS->bAddBaReqDelayed = true;
531 pTS->bDisable_AddBa = true;
532 ReasonCode = DELBA_REASON_END_BA;
533 goto OnADDBARsp_Reject;
536 // End of procedure
537 return 0;
539 OnADDBARsp_Reject:
541 BA_RECORD BA;
542 BA.BaParamSet = *pBaParamSet;
543 ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
544 return 0;
549 /********************************************************************************************************************
550 *function: RX DELBA
551 * input: struct sk_buff * skb //incoming ADDBAReq skb.
552 * return: 0(pass), other(fail)
553 * notice: As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
554 ********************************************************************************************************************/
555 int ieee80211_rx_DELBA(struct ieee80211_device* ieee,struct sk_buff *skb)
557 struct ieee80211_hdr_3addr* delba = NULL;
558 PDELBA_PARAM_SET pDelBaParamSet = NULL;
559 u16* pReasonCode = NULL;
560 u8* dst = NULL;
562 if (skb->len < sizeof( struct ieee80211_hdr_3addr) + 6)
564 IEEE80211_DEBUG(IEEE80211_DL_ERR,
565 " Invalid skb len in DELBA(%d / %zd)\n",
566 skb->len,
567 sizeof(struct ieee80211_hdr_3addr) + 6);
568 return -1;
571 if(ieee->current_network.qos_data.active == 0 ||
572 ieee->pHTInfo->bCurrentHTSupport == false )
574 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);
575 return -1;
578 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
579 delba = ( struct ieee80211_hdr_3addr*)skb->data;
580 dst = (u8*)(&delba->addr2[0]);
581 delba += sizeof( struct ieee80211_hdr_3addr);
582 pDelBaParamSet = (PDELBA_PARAM_SET)(delba+2);
583 pReasonCode = (u16*)(delba+4);
585 if(pDelBaParamSet->field.Initiator == 1)
587 PRX_TS_RECORD pRxTs;
589 if( !GetTs(
590 ieee,
591 (PTS_COMMON_INFO*)&pRxTs,
592 dst,
593 (u8)pDelBaParamSet->field.TID,
594 RX_DIR,
595 false) )
597 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for RXTS in %s()\n", __FUNCTION__);
598 return -1;
601 RxTsDeleteBA(ieee, pRxTs);
603 else
605 PTX_TS_RECORD pTxTs;
607 if(!GetTs(
608 ieee,
609 (PTS_COMMON_INFO*)&pTxTs,
610 dst,
611 (u8)pDelBaParamSet->field.TID,
612 TX_DIR,
613 false) )
615 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS for TXTS in %s()\n", __FUNCTION__);
616 return -1;
619 pTxTs->bUsingBa = false;
620 pTxTs->bAddBaReqInProgress = false;
621 pTxTs->bAddBaReqDelayed = false;
622 del_timer_sync(&pTxTs->TsAddBaTimer);
623 TxTsDeleteBA(ieee, pTxTs);
625 return 0;
629 // ADDBA initiate. This can only be called by TX side.
631 void
632 TsInitAddBA(
633 struct ieee80211_device* ieee,
634 PTX_TS_RECORD pTS,
635 u8 Policy,
636 u8 bOverwritePending
639 PBA_RECORD pBA = &pTS->TxPendingBARecord;
641 if(pBA->bValid==true && bOverwritePending==false)
642 return;
644 // Set parameters to "Pending" variable set
645 DeActivateBAEntry(ieee, pBA);
647 pBA->DialogToken++; // DialogToken: Only keep the latest dialog token
648 pBA->BaParamSet.field.AMSDU_Support = 0; // Do not support A-MSDU with A-MPDU now!!
649 pBA->BaParamSet.field.BAPolicy = Policy; // Policy: Delayed or Immediate
650 pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID; // TID
651 // BufferSize: This need to be set according to A-MPDU vector
652 pBA->BaParamSet.field.BufferSize = 32; // BufferSize: This need to be set according to A-MPDU vector
653 pBA->BaTimeoutValue = 0; // Timeout value: Set 0 to disable Timer
654 pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096; // Block Ack will start after 3 packets later.
656 ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
658 ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
661 void
662 TsInitDelBA( struct ieee80211_device* ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
665 if(TxRxSelect == TX_DIR)
667 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
669 if(TxTsDeleteBA(ieee, pTxTs))
670 ieee80211_send_DELBA(
671 ieee,
672 pTsCommonInfo->Addr,
673 (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
674 TxRxSelect,
675 DELBA_REASON_END_BA);
677 else if(TxRxSelect == RX_DIR)
679 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
680 if(RxTsDeleteBA(ieee, pRxTs))
681 ieee80211_send_DELBA(
682 ieee,
683 pTsCommonInfo->Addr,
684 &pRxTs->RxAdmittedBARecord,
685 TxRxSelect,
686 DELBA_REASON_END_BA );
689 /********************************************************************************************************************
690 *function: BA setup timer
691 * input: unsigned long data //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
692 * return: NULL
693 * notice:
694 ********************************************************************************************************************/
695 void BaSetupTimeOut(unsigned long data)
697 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
699 pTxTs->bAddBaReqInProgress = false;
700 pTxTs->bAddBaReqDelayed = true;
701 pTxTs->TxPendingBARecord.bValid = false;
704 void TxBaInactTimeout(unsigned long data)
706 PTX_TS_RECORD pTxTs = (PTX_TS_RECORD)data;
707 struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
708 TxTsDeleteBA(ieee, pTxTs);
709 ieee80211_send_DELBA(
710 ieee,
711 pTxTs->TsCommonInfo.Addr,
712 &pTxTs->TxAdmittedBARecord,
713 TX_DIR,
714 DELBA_REASON_TIMEOUT);
717 void RxBaInactTimeout(unsigned long data)
719 PRX_TS_RECORD pRxTs = (PRX_TS_RECORD)data;
720 struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
722 RxTsDeleteBA(ieee, pRxTs);
723 ieee80211_send_DELBA(
724 ieee,
725 pRxTs->TsCommonInfo.Addr,
726 &pRxTs->RxAdmittedBARecord,
727 RX_DIR,
728 DELBA_REASON_TIMEOUT);
729 return ;