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
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.
27 ********************************************************************************************************************/
28 void ActivateBAEntry(struct ieee80211_device
* ieee
, PBA_RECORD pBA
, u16 Time
)
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
39 ********************************************************************************************************************/
40 void DeActivateBAEntry( struct ieee80211_device
* ieee
, PBA_RECORD pBA
)
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;
52 if(pPendingBa
->bValid
)
54 DeActivateBAEntry(ieee
, pPendingBa
);
59 if(pAdmittedBa
->bValid
)
61 DeActivateBAEntry(ieee
, pAdmittedBa
);
68 u8
RxTsDeleteBA( struct ieee80211_device
* ieee
, PRX_TS_RECORD pRxTs
)
70 PBA_RECORD pBa
= &pRxTs
->RxAdmittedBARecord
;
71 u8 bSendDELBA
= false;
75 DeActivateBAEntry(ieee
, pBa
);
82 /********************************************************************************************************************
83 *function: reset BA entry
85 * PBA_RECORD pBA //entry to be reset
87 ********************************************************************************************************************/
88 void ResetBaEntry( PBA_RECORD pBA
)
91 pBA
->BaParamSet
.shortData
= 0;
92 pBA
->BaTimeoutValue
= 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)
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
;
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
);
119 skb
= dev_alloc_skb(len
+ sizeof( struct ieee80211_hdr_3addr
));
122 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "can't alloc skb for ADDBA_REQ\n");
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);
142 *tag
++= pBA
->DialogToken
;
144 if (ACT_ADDBARSP
== type
)
147 printk("=====>to send ADDBARSP\n");
148 tmp
= cpu_to_le16(StatusCode
);
149 memcpy(tag
, (u8
*)&tmp
, 2);
153 tmp
= cpu_to_le16(pBA
->BaParamSet
.shortData
);
154 memcpy(tag
, (u8
*)&tmp
, 2);
157 tmp
= cpu_to_le16(pBA
->BaTimeoutValue
);
158 memcpy(tag
, (u8
*)&tmp
, 2);
161 if (ACT_ADDBAREQ
== type
)
164 memcpy(tag
,(u8
*)&(pBA
->BaStartSeqCtrl
), 2);
168 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA
|IEEE80211_DL_BA
, skb
->data
, skb
->len
);
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.
179 * return: sk_buff* skb //return constructed skb to xmit
180 ********************************************************************************************************************/
181 static struct sk_buff
* ieee80211_DELBA(
182 struct ieee80211_device
* ieee
,
185 TR_SELECT TxRxSelect
,
189 DELBA_PARAM_SET DelbaParamSet
;
190 struct sk_buff
*skb
= NULL
;
191 struct ieee80211_hdr_3addr
* Delba
= NULL
;
194 u16 len
= 6 + ieee
->tx_headroom
;
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
));
207 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "can't alloc skb for ADDBA_REQ\n");
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);
224 // DELBA Parameter Set
225 tmp
= cpu_to_le16(DelbaParamSet
.shortData
);
226 memcpy(tag
, (u8
*)&tmp
, 2);
229 tmp
= cpu_to_le16(ReasonCode
);
230 memcpy(tag
, (u8
*)&tmp
, 2);
233 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA
|IEEE80211_DL_BA
, skb
->data
, skb
->len
);
235 IEEE80211_DEBUG(IEEE80211_DL_TRACE
| IEEE80211_DL_BA
, "<=====%s()\n", __FUNCTION__
);
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
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.
253 softmac_mgmt_xmit(skb
, ieee
);
257 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "alloc skb error in function %s()\n", __FUNCTION__
);
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
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
276 softmac_mgmt_xmit(skb
, ieee
);
280 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "alloc skb error in function %s()\n", __FUNCTION__
);
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
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
302 softmac_mgmt_xmit(skb
, ieee
);
306 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "alloc skb error in function %s()\n", __FUNCTION__
);
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
;
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",
333 sizeof(struct ieee80211_hdr_3addr
) + 9);
337 IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA
|IEEE80211_DL_BA
, skb
->data
, skb
->len
);
339 req
= ( struct ieee80211_hdr_3addr
*) skb
->data
;
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.
362 (PTS_COMMON_INFO
*)(&pTS
),
364 (u8
)(pBaParamSet
->field
.TID
),
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;
394 pBA
->BaParamSet
.field
.BufferSize
= 32;
395 ActivateBAEntry(ieee
, pBA
, 0);
396 ieee80211_send_ADDBARsp(ieee
, dst
, pBA
, ADDBA_STATUS_SUCCESS
);
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
;
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",
434 sizeof(struct ieee80211_hdr_3addr
) + 9);
437 rsp
= ( struct ieee80211_hdr_3addr
*)skb
->data
;
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.
464 (PTS_COMMON_INFO
*)(&pTS
),
466 (u8
)(pBaParamSet
->field
.TID
),
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");
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
;
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
);
530 pTS
->bAddBaReqDelayed
= true;
531 pTS
->bDisable_AddBa
= true;
532 ReasonCode
= DELBA_REASON_END_BA
;
533 goto OnADDBARsp_Reject
;
542 BA
.BaParamSet
= *pBaParamSet
;
543 ieee80211_send_DELBA(ieee
, dst
, &BA
, TX_DIR
, ReasonCode
);
549 /********************************************************************************************************************
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
;
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",
567 sizeof(struct ieee80211_hdr_3addr
) + 6);
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
);
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)
591 (PTS_COMMON_INFO
*)&pRxTs
,
593 (u8
)pDelBaParamSet
->field
.TID
,
597 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "can't get TS for RXTS in %s()\n", __FUNCTION__
);
601 RxTsDeleteBA(ieee
, pRxTs
);
609 (PTS_COMMON_INFO
*)&pTxTs
,
611 (u8
)pDelBaParamSet
->field
.TID
,
615 IEEE80211_DEBUG(IEEE80211_DL_ERR
, "can't get TS for TXTS in %s()\n", __FUNCTION__
);
619 pTxTs
->bUsingBa
= false;
620 pTxTs
->bAddBaReqInProgress
= false;
621 pTxTs
->bAddBaReqDelayed
= false;
622 del_timer_sync(&pTxTs
->TsAddBaTimer
);
623 TxTsDeleteBA(ieee
, pTxTs
);
629 // ADDBA initiate. This can only be called by TX side.
633 struct ieee80211_device
* ieee
,
639 PBA_RECORD pBA
= &pTS
->TxPendingBARecord
;
641 if(pBA
->bValid
==true && bOverwritePending
==false)
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
);
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(
673 (pTxTs
->TxAdmittedBARecord
.bValid
)?(&pTxTs
->TxAdmittedBARecord
):(&pTxTs
->TxPendingBARecord
),
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(
684 &pRxTs
->RxAdmittedBARecord
,
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
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(
711 pTxTs
->TsCommonInfo
.Addr
,
712 &pTxTs
->TxAdmittedBARecord
,
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(
725 pRxTs
->TsCommonInfo
.Addr
,
726 &pRxTs
->RxAdmittedBARecord
,
728 DELBA_REASON_TIMEOUT
);