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 * The full GNU General Public License is included in this distribution in the
10 * file called LICENSE.
12 * Contact Information:
13 * wlanfae <wlanfae@realtek.com>
14 ******************************************************************************/
15 #include <asm/byteorder.h>
16 #include <asm/unaligned.h>
17 #include <linux/etherdevice.h>
19 #include "rtl819x_BA.h"
21 static void ActivateBAEntry(struct rtllib_device
*ieee
, struct ba_record
*pBA
,
26 mod_timer(&pBA
->Timer
, jiffies
+ msecs_to_jiffies(Time
));
29 static void DeActivateBAEntry(struct rtllib_device
*ieee
, struct ba_record
*pBA
)
32 del_timer_sync(&pBA
->Timer
);
35 static u8
TxTsDeleteBA(struct rtllib_device
*ieee
, struct tx_ts_record
*pTxTs
)
37 struct ba_record
*pAdmittedBa
= &pTxTs
->TxAdmittedBARecord
;
38 struct ba_record
*pPendingBa
= &pTxTs
->TxPendingBARecord
;
39 u8 bSendDELBA
= false;
41 if (pPendingBa
->bValid
) {
42 DeActivateBAEntry(ieee
, pPendingBa
);
46 if (pAdmittedBa
->bValid
) {
47 DeActivateBAEntry(ieee
, pAdmittedBa
);
53 static u8
RxTsDeleteBA(struct rtllib_device
*ieee
, struct rx_ts_record
*pRxTs
)
55 struct ba_record
*pBa
= &pRxTs
->RxAdmittedBARecord
;
56 u8 bSendDELBA
= false;
59 DeActivateBAEntry(ieee
, pBa
);
66 void ResetBaEntry(struct ba_record
*pBA
)
69 pBA
->BaParamSet
.shortData
= 0;
70 pBA
->BaTimeoutValue
= 0;
72 pBA
->BaStartSeqCtrl
.ShortData
= 0;
74 static struct sk_buff
*rtllib_ADDBA(struct rtllib_device
*ieee
, u8
*Dst
,
75 struct ba_record
*pBA
,
76 u16 StatusCode
, u8 type
)
78 struct sk_buff
*skb
= NULL
;
79 struct rtllib_hdr_3addr
*BAReq
= NULL
;
81 u16 len
= ieee
->tx_headroom
+ 9;
83 netdev_dbg(ieee
->dev
, "%s(): frame(%d) sentd to: %pM, ieee->dev:%p\n",
84 __func__
, type
, Dst
, ieee
->dev
);
87 netdev_warn(ieee
->dev
, "pBA is NULL\n");
90 skb
= dev_alloc_skb(len
+ sizeof(struct rtllib_hdr_3addr
));
94 memset(skb
->data
, 0, sizeof(struct rtllib_hdr_3addr
));
96 skb_reserve(skb
, ieee
->tx_headroom
);
98 BAReq
= (struct rtllib_hdr_3addr
*)skb_put(skb
,
99 sizeof(struct rtllib_hdr_3addr
));
101 ether_addr_copy(BAReq
->addr1
, Dst
);
102 ether_addr_copy(BAReq
->addr2
, ieee
->dev
->dev_addr
);
104 ether_addr_copy(BAReq
->addr3
, ieee
->current_network
.bssid
);
105 BAReq
->frame_ctl
= cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT
);
107 tag
= (u8
*)skb_put(skb
, 9);
110 *tag
++ = pBA
->DialogToken
;
112 if (type
== ACT_ADDBARSP
) {
113 RT_TRACE(COMP_DBG
, "====>to send ADDBARSP\n");
115 put_unaligned_le16(StatusCode
, tag
);
119 put_unaligned_le16(pBA
->BaParamSet
.shortData
, tag
);
122 put_unaligned_le16(pBA
->BaTimeoutValue
, tag
);
125 if (type
== ACT_ADDBAREQ
) {
126 memcpy(tag
, (u8
*)&(pBA
->BaStartSeqCtrl
), 2);
131 print_hex_dump_bytes("rtllib_ADDBA(): ", DUMP_PREFIX_NONE
, skb
->data
,
137 static struct sk_buff
*rtllib_DELBA(struct rtllib_device
*ieee
, u8
*dst
,
138 struct ba_record
*pBA
,
139 enum tr_select TxRxSelect
, u16 ReasonCode
)
141 union delba_param_set DelbaParamSet
;
142 struct sk_buff
*skb
= NULL
;
143 struct rtllib_hdr_3addr
*Delba
= NULL
;
145 u16 len
= 6 + ieee
->tx_headroom
;
148 netdev_dbg(ieee
->dev
, "%s(): ReasonCode(%d) sentd to: %pM\n",
149 __func__
, ReasonCode
, dst
);
151 memset(&DelbaParamSet
, 0, 2);
153 DelbaParamSet
.field
.Initiator
= (TxRxSelect
== TX_DIR
) ? 1 : 0;
154 DelbaParamSet
.field
.TID
= pBA
->BaParamSet
.field
.TID
;
156 skb
= dev_alloc_skb(len
+ sizeof(struct rtllib_hdr_3addr
));
160 skb_reserve(skb
, ieee
->tx_headroom
);
162 Delba
= (struct rtllib_hdr_3addr
*) skb_put(skb
,
163 sizeof(struct rtllib_hdr_3addr
));
165 ether_addr_copy(Delba
->addr1
, dst
);
166 ether_addr_copy(Delba
->addr2
, ieee
->dev
->dev_addr
);
167 ether_addr_copy(Delba
->addr3
, ieee
->current_network
.bssid
);
168 Delba
->frame_ctl
= cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT
);
170 tag
= (u8
*)skb_put(skb
, 6);
176 put_unaligned_le16(DelbaParamSet
.shortData
, tag
);
179 put_unaligned_le16(ReasonCode
, tag
);
183 print_hex_dump_bytes("rtllib_DELBA(): ", DUMP_PREFIX_NONE
, skb
->data
,
189 static void rtllib_send_ADDBAReq(struct rtllib_device
*ieee
, u8
*dst
,
190 struct ba_record
*pBA
)
194 skb
= rtllib_ADDBA(ieee
, dst
, pBA
, 0, ACT_ADDBAREQ
);
197 RT_TRACE(COMP_DBG
, "====>to send ADDBAREQ!!!!!\n");
198 softmac_mgmt_xmit(skb
, ieee
);
200 netdev_dbg(ieee
->dev
, "Failed to generate ADDBAReq packet.\n");
204 static void rtllib_send_ADDBARsp(struct rtllib_device
*ieee
, u8
*dst
,
205 struct ba_record
*pBA
, u16 StatusCode
)
209 skb
= rtllib_ADDBA(ieee
, dst
, pBA
, StatusCode
, ACT_ADDBARSP
);
211 softmac_mgmt_xmit(skb
, ieee
);
213 netdev_dbg(ieee
->dev
, "Failed to generate ADDBARsp packet.\n");
216 static void rtllib_send_DELBA(struct rtllib_device
*ieee
, u8
*dst
,
217 struct ba_record
*pBA
, enum tr_select TxRxSelect
,
222 skb
= rtllib_DELBA(ieee
, dst
, pBA
, TxRxSelect
, ReasonCode
);
224 softmac_mgmt_xmit(skb
, ieee
);
226 netdev_dbg(ieee
->dev
, "Failed to generate DELBA packet.\n");
229 int rtllib_rx_ADDBAReq(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
231 struct rtllib_hdr_3addr
*req
= NULL
;
233 u8
*dst
= NULL
, *pDialogToken
= NULL
, *tag
= NULL
;
234 struct ba_record
*pBA
= NULL
;
235 union ba_param_set
*pBaParamSet
= NULL
;
236 u16
*pBaTimeoutVal
= NULL
;
237 union sequence_control
*pBaStartSeqCtrl
= NULL
;
238 struct rx_ts_record
*pTS
= NULL
;
240 if (skb
->len
< sizeof(struct rtllib_hdr_3addr
) + 9) {
241 netdev_warn(ieee
->dev
, "Invalid skb len in BAREQ(%d / %d)\n",
243 (int)(sizeof(struct rtllib_hdr_3addr
) + 9));
248 print_hex_dump_bytes("rtllib_rx_ADDBAReq(): ", DUMP_PREFIX_NONE
,
249 skb
->data
, skb
->len
);
252 req
= (struct rtllib_hdr_3addr
*) skb
->data
;
254 dst
= (u8
*)(&req
->addr2
[0]);
255 tag
+= sizeof(struct rtllib_hdr_3addr
);
256 pDialogToken
= tag
+ 2;
257 pBaParamSet
= (union ba_param_set
*)(tag
+ 3);
258 pBaTimeoutVal
= (u16
*)(tag
+ 5);
259 pBaStartSeqCtrl
= (union sequence_control
*)(req
+ 7);
261 RT_TRACE(COMP_DBG
, "====>rx ADDBAREQ from : %pM\n", dst
);
262 if (ieee
->current_network
.qos_data
.active
== 0 ||
263 (ieee
->pHTInfo
->bCurrentHTSupport
== false) ||
264 (ieee
->pHTInfo
->IOTAction
& HT_IOT_ACT_REJECT_ADDBA_REQ
)) {
265 rc
= ADDBA_STATUS_REFUSED
;
266 netdev_warn(ieee
->dev
,
267 "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n",
268 ieee
->current_network
.qos_data
.active
,
269 ieee
->pHTInfo
->bCurrentHTSupport
);
270 goto OnADDBAReq_Fail
;
272 if (!GetTs(ieee
, (struct ts_common_info
**)(&pTS
), dst
,
273 (u8
)(pBaParamSet
->field
.TID
), RX_DIR
, true)) {
274 rc
= ADDBA_STATUS_REFUSED
;
275 netdev_warn(ieee
->dev
, "%s(): can't get TS\n", __func__
);
276 goto OnADDBAReq_Fail
;
278 pBA
= &pTS
->RxAdmittedBARecord
;
280 if (pBaParamSet
->field
.BAPolicy
== BA_POLICY_DELAYED
) {
281 rc
= ADDBA_STATUS_INVALID_PARAM
;
282 netdev_warn(ieee
->dev
, "%s(): BA Policy is not correct\n",
284 goto OnADDBAReq_Fail
;
287 rtllib_FlushRxTsPendingPkts(ieee
, pTS
);
289 DeActivateBAEntry(ieee
, pBA
);
290 pBA
->DialogToken
= *pDialogToken
;
291 pBA
->BaParamSet
= *pBaParamSet
;
292 pBA
->BaTimeoutValue
= *pBaTimeoutVal
;
293 pBA
->BaStartSeqCtrl
= *pBaStartSeqCtrl
;
295 if (ieee
->GetHalfNmodeSupportByAPsHandler(ieee
->dev
) ||
296 (ieee
->pHTInfo
->IOTAction
& HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT
))
297 pBA
->BaParamSet
.field
.BufferSize
= 1;
299 pBA
->BaParamSet
.field
.BufferSize
= 32;
301 ActivateBAEntry(ieee
, pBA
, 0);
302 rtllib_send_ADDBARsp(ieee
, dst
, pBA
, ADDBA_STATUS_SUCCESS
);
310 BA
.BaParamSet
= *pBaParamSet
;
311 BA
.BaTimeoutValue
= *pBaTimeoutVal
;
312 BA
.DialogToken
= *pDialogToken
;
313 BA
.BaParamSet
.field
.BAPolicy
= BA_POLICY_IMMEDIATE
;
314 rtllib_send_ADDBARsp(ieee
, dst
, &BA
, rc
);
319 int rtllib_rx_ADDBARsp(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
321 struct rtllib_hdr_3addr
*rsp
= NULL
;
322 struct ba_record
*pPendingBA
, *pAdmittedBA
;
323 struct tx_ts_record
*pTS
= NULL
;
324 u8
*dst
= NULL
, *pDialogToken
= NULL
, *tag
= NULL
;
325 u16
*pStatusCode
= NULL
, *pBaTimeoutVal
= NULL
;
326 union ba_param_set
*pBaParamSet
= NULL
;
329 if (skb
->len
< sizeof(struct rtllib_hdr_3addr
) + 9) {
330 netdev_warn(ieee
->dev
, "Invalid skb len in BARSP(%d / %d)\n",
332 (int)(sizeof(struct rtllib_hdr_3addr
) + 9));
335 rsp
= (struct rtllib_hdr_3addr
*)skb
->data
;
337 dst
= (u8
*)(&rsp
->addr2
[0]);
338 tag
+= sizeof(struct rtllib_hdr_3addr
);
339 pDialogToken
= tag
+ 2;
340 pStatusCode
= (u16
*)(tag
+ 3);
341 pBaParamSet
= (union ba_param_set
*)(tag
+ 5);
342 pBaTimeoutVal
= (u16
*)(tag
+ 7);
344 RT_TRACE(COMP_DBG
, "====>rx ADDBARSP from : %pM\n", dst
);
345 if (ieee
->current_network
.qos_data
.active
== 0 ||
346 ieee
->pHTInfo
->bCurrentHTSupport
== false ||
347 ieee
->pHTInfo
->bCurrentAMPDUEnable
== false) {
348 netdev_warn(ieee
->dev
,
349 "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",
350 ieee
->current_network
.qos_data
.active
,
351 ieee
->pHTInfo
->bCurrentHTSupport
,
352 ieee
->pHTInfo
->bCurrentAMPDUEnable
);
353 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
354 goto OnADDBARsp_Reject
;
358 if (!GetTs(ieee
, (struct ts_common_info
**)(&pTS
), dst
,
359 (u8
)(pBaParamSet
->field
.TID
), TX_DIR
, false)) {
360 netdev_warn(ieee
->dev
, "%s(): can't get TS\n", __func__
);
361 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
362 goto OnADDBARsp_Reject
;
365 pTS
->bAddBaReqInProgress
= false;
366 pPendingBA
= &pTS
->TxPendingBARecord
;
367 pAdmittedBA
= &pTS
->TxAdmittedBARecord
;
370 if (pAdmittedBA
->bValid
== true) {
371 netdev_dbg(ieee
->dev
, "%s(): ADDBA response already admitted\n",
374 } else if ((pPendingBA
->bValid
== false) ||
375 (*pDialogToken
!= pPendingBA
->DialogToken
)) {
376 netdev_warn(ieee
->dev
,
377 "%s(): ADDBA Rsp. BA invalid, DELBA!\n",
379 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
380 goto OnADDBARsp_Reject
;
382 netdev_dbg(ieee
->dev
,
383 "%s(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n",
384 __func__
, *pStatusCode
);
385 DeActivateBAEntry(ieee
, pPendingBA
);
389 if (*pStatusCode
== ADDBA_STATUS_SUCCESS
) {
390 if (pBaParamSet
->field
.BAPolicy
== BA_POLICY_DELAYED
) {
391 pTS
->bAddBaReqDelayed
= true;
392 DeActivateBAEntry(ieee
, pAdmittedBA
);
393 ReasonCode
= DELBA_REASON_END_BA
;
394 goto OnADDBARsp_Reject
;
398 pAdmittedBA
->DialogToken
= *pDialogToken
;
399 pAdmittedBA
->BaTimeoutValue
= *pBaTimeoutVal
;
400 pAdmittedBA
->BaStartSeqCtrl
= pPendingBA
->BaStartSeqCtrl
;
401 pAdmittedBA
->BaParamSet
= *pBaParamSet
;
402 DeActivateBAEntry(ieee
, pAdmittedBA
);
403 ActivateBAEntry(ieee
, pAdmittedBA
, *pBaTimeoutVal
);
405 pTS
->bAddBaReqDelayed
= true;
406 pTS
->bDisable_AddBa
= true;
407 ReasonCode
= DELBA_REASON_END_BA
;
408 goto OnADDBARsp_Reject
;
417 BA
.BaParamSet
= *pBaParamSet
;
418 rtllib_send_DELBA(ieee
, dst
, &BA
, TX_DIR
, ReasonCode
);
423 int rtllib_rx_DELBA(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
425 struct rtllib_hdr_3addr
*delba
= NULL
;
426 union delba_param_set
*pDelBaParamSet
= NULL
;
429 if (skb
->len
< sizeof(struct rtllib_hdr_3addr
) + 6) {
430 netdev_warn(ieee
->dev
, "Invalid skb len in DELBA(%d / %d)\n",
432 (int)(sizeof(struct rtllib_hdr_3addr
) + 6));
436 if (ieee
->current_network
.qos_data
.active
== 0 ||
437 ieee
->pHTInfo
->bCurrentHTSupport
== false) {
438 netdev_warn(ieee
->dev
,
439 "received DELBA while QOS or HT is not supported(%d, %d)\n",
440 ieee
->current_network
. qos_data
.active
,
441 ieee
->pHTInfo
->bCurrentHTSupport
);
446 print_hex_dump_bytes("rtllib_rx_DELBA(): ", DUMP_PREFIX_NONE
, skb
->data
,
449 delba
= (struct rtllib_hdr_3addr
*)skb
->data
;
450 dst
= (u8
*)(&delba
->addr2
[0]);
451 pDelBaParamSet
= (union delba_param_set
*)&delba
->payload
[2];
453 if (pDelBaParamSet
->field
.Initiator
== 1) {
454 struct rx_ts_record
*pRxTs
;
456 if (!GetTs(ieee
, (struct ts_common_info
**)&pRxTs
, dst
,
457 (u8
)pDelBaParamSet
->field
.TID
, RX_DIR
, false)) {
458 netdev_warn(ieee
->dev
,
459 "%s(): can't get TS for RXTS. dst:%pM TID:%d\n",
461 (u8
)pDelBaParamSet
->field
.TID
);
465 RxTsDeleteBA(ieee
, pRxTs
);
467 struct tx_ts_record
*pTxTs
;
469 if (!GetTs(ieee
, (struct ts_common_info
**)&pTxTs
, dst
,
470 (u8
)pDelBaParamSet
->field
.TID
, TX_DIR
, false)) {
471 netdev_warn(ieee
->dev
, "%s(): can't get TS for TXTS\n",
476 pTxTs
->bUsingBa
= false;
477 pTxTs
->bAddBaReqInProgress
= false;
478 pTxTs
->bAddBaReqDelayed
= false;
479 del_timer_sync(&pTxTs
->TsAddBaTimer
);
480 TxTsDeleteBA(ieee
, pTxTs
);
485 void TsInitAddBA(struct rtllib_device
*ieee
, struct tx_ts_record
*pTS
,
486 u8 Policy
, u8 bOverwritePending
)
488 struct ba_record
*pBA
= &pTS
->TxPendingBARecord
;
490 if (pBA
->bValid
== true && bOverwritePending
== false)
493 DeActivateBAEntry(ieee
, pBA
);
496 pBA
->BaParamSet
.field
.AMSDU_Support
= 0;
497 pBA
->BaParamSet
.field
.BAPolicy
= Policy
;
498 pBA
->BaParamSet
.field
.TID
=
499 pTS
->TsCommonInfo
.TSpec
.f
.TSInfo
.field
.ucTSID
;
500 pBA
->BaParamSet
.field
.BufferSize
= 32;
501 pBA
->BaTimeoutValue
= 0;
502 pBA
->BaStartSeqCtrl
.field
.SeqNum
= (pTS
->TxCurSeq
+ 3) % 4096;
504 ActivateBAEntry(ieee
, pBA
, BA_SETUP_TIMEOUT
);
506 rtllib_send_ADDBAReq(ieee
, pTS
->TsCommonInfo
.Addr
, pBA
);
509 void TsInitDelBA(struct rtllib_device
*ieee
,
510 struct ts_common_info
*pTsCommonInfo
,
511 enum tr_select TxRxSelect
)
513 if (TxRxSelect
== TX_DIR
) {
514 struct tx_ts_record
*pTxTs
=
515 (struct tx_ts_record
*)pTsCommonInfo
;
517 if (TxTsDeleteBA(ieee
, pTxTs
))
518 rtllib_send_DELBA(ieee
, pTsCommonInfo
->Addr
,
519 (pTxTs
->TxAdmittedBARecord
.bValid
) ?
520 (&pTxTs
->TxAdmittedBARecord
) :
521 (&pTxTs
->TxPendingBARecord
),
522 TxRxSelect
, DELBA_REASON_END_BA
);
523 } else if (TxRxSelect
== RX_DIR
) {
524 struct rx_ts_record
*pRxTs
=
525 (struct rx_ts_record
*)pTsCommonInfo
;
526 if (RxTsDeleteBA(ieee
, pRxTs
))
527 rtllib_send_DELBA(ieee
, pTsCommonInfo
->Addr
,
528 &pRxTs
->RxAdmittedBARecord
,
529 TxRxSelect
, DELBA_REASON_END_BA
);
533 void BaSetupTimeOut(unsigned long data
)
535 struct tx_ts_record
*pTxTs
= (struct tx_ts_record
*)data
;
537 pTxTs
->bAddBaReqInProgress
= false;
538 pTxTs
->bAddBaReqDelayed
= true;
539 pTxTs
->TxPendingBARecord
.bValid
= false;
542 void TxBaInactTimeout(unsigned long data
)
544 struct tx_ts_record
*pTxTs
= (struct tx_ts_record
*)data
;
545 struct rtllib_device
*ieee
= container_of(pTxTs
, struct rtllib_device
,
546 TxTsRecord
[pTxTs
->num
]);
547 TxTsDeleteBA(ieee
, pTxTs
);
548 rtllib_send_DELBA(ieee
, pTxTs
->TsCommonInfo
.Addr
,
549 &pTxTs
->TxAdmittedBARecord
, TX_DIR
,
550 DELBA_REASON_TIMEOUT
);
553 void RxBaInactTimeout(unsigned long data
)
555 struct rx_ts_record
*pRxTs
= (struct rx_ts_record
*)data
;
556 struct rtllib_device
*ieee
= container_of(pRxTs
, struct rtllib_device
,
557 RxTsRecord
[pRxTs
->num
]);
559 RxTsDeleteBA(ieee
, pRxTs
);
560 rtllib_send_DELBA(ieee
, pRxTs
->TsCommonInfo
.Addr
,
561 &pRxTs
->RxAdmittedBARecord
, RX_DIR
,
562 DELBA_REASON_TIMEOUT
);