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 <asm/byteorder.h>
20 #include <asm/unaligned.h>
21 #include <linux/etherdevice.h>
23 #include "rtl819x_BA.h"
25 static void ActivateBAEntry(struct rtllib_device
*ieee
, struct ba_record
*pBA
,
30 mod_timer(&pBA
->Timer
, jiffies
+ msecs_to_jiffies(Time
));
33 static void DeActivateBAEntry(struct rtllib_device
*ieee
, struct ba_record
*pBA
)
36 del_timer_sync(&pBA
->Timer
);
39 static u8
TxTsDeleteBA(struct rtllib_device
*ieee
, struct tx_ts_record
*pTxTs
)
41 struct ba_record
*pAdmittedBa
= &pTxTs
->TxAdmittedBARecord
;
42 struct ba_record
*pPendingBa
= &pTxTs
->TxPendingBARecord
;
43 u8 bSendDELBA
= false;
45 if (pPendingBa
->bValid
) {
46 DeActivateBAEntry(ieee
, pPendingBa
);
50 if (pAdmittedBa
->bValid
) {
51 DeActivateBAEntry(ieee
, pAdmittedBa
);
57 static u8
RxTsDeleteBA(struct rtllib_device
*ieee
, struct rx_ts_record
*pRxTs
)
59 struct ba_record
*pBa
= &pRxTs
->RxAdmittedBARecord
;
60 u8 bSendDELBA
= false;
63 DeActivateBAEntry(ieee
, pBa
);
70 void ResetBaEntry(struct ba_record
*pBA
)
73 pBA
->BaParamSet
.shortData
= 0;
74 pBA
->BaTimeoutValue
= 0;
76 pBA
->BaStartSeqCtrl
.ShortData
= 0;
78 static struct sk_buff
*rtllib_ADDBA(struct rtllib_device
*ieee
, u8
*Dst
,
79 struct ba_record
*pBA
,
80 u16 StatusCode
, u8 type
)
82 struct sk_buff
*skb
= NULL
;
83 struct rtllib_hdr_3addr
*BAReq
= NULL
;
85 u16 len
= ieee
->tx_headroom
+ 9;
87 netdev_dbg(ieee
->dev
, "%s(): frame(%d) sentd to: %pM, ieee->dev:%p\n",
88 __func__
, type
, Dst
, ieee
->dev
);
91 netdev_warn(ieee
->dev
, "pBA is NULL\n");
94 skb
= dev_alloc_skb(len
+ sizeof(struct rtllib_hdr_3addr
));
98 memset(skb
->data
, 0, sizeof(struct rtllib_hdr_3addr
));
100 skb_reserve(skb
, ieee
->tx_headroom
);
102 BAReq
= (struct rtllib_hdr_3addr
*)skb_put(skb
,
103 sizeof(struct rtllib_hdr_3addr
));
105 ether_addr_copy(BAReq
->addr1
, Dst
);
106 ether_addr_copy(BAReq
->addr2
, ieee
->dev
->dev_addr
);
108 ether_addr_copy(BAReq
->addr3
, ieee
->current_network
.bssid
);
109 BAReq
->frame_ctl
= cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT
);
111 tag
= (u8
*)skb_put(skb
, 9);
114 *tag
++ = pBA
->DialogToken
;
116 if (ACT_ADDBARSP
== type
) {
117 RT_TRACE(COMP_DBG
, "====>to send ADDBARSP\n");
119 put_unaligned_le16(StatusCode
, tag
);
123 put_unaligned_le16(pBA
->BaParamSet
.shortData
, tag
);
126 put_unaligned_le16(pBA
->BaTimeoutValue
, tag
);
129 if (ACT_ADDBAREQ
== type
) {
130 memcpy(tag
, (u8
*)&(pBA
->BaStartSeqCtrl
), 2);
135 print_hex_dump_bytes("rtllib_ADDBA(): ", DUMP_PREFIX_NONE
, skb
->data
,
141 static struct sk_buff
*rtllib_DELBA(struct rtllib_device
*ieee
, u8
*dst
,
142 struct ba_record
*pBA
,
143 enum tr_select TxRxSelect
, u16 ReasonCode
)
145 union delba_param_set DelbaParamSet
;
146 struct sk_buff
*skb
= NULL
;
147 struct rtllib_hdr_3addr
*Delba
= NULL
;
149 u16 len
= 6 + ieee
->tx_headroom
;
152 netdev_dbg(ieee
->dev
, "%s(): ReasonCode(%d) sentd to: %pM\n",
153 __func__
, ReasonCode
, dst
);
155 memset(&DelbaParamSet
, 0, 2);
157 DelbaParamSet
.field
.Initiator
= (TxRxSelect
== TX_DIR
) ? 1 : 0;
158 DelbaParamSet
.field
.TID
= pBA
->BaParamSet
.field
.TID
;
160 skb
= dev_alloc_skb(len
+ sizeof(struct rtllib_hdr_3addr
));
164 skb_reserve(skb
, ieee
->tx_headroom
);
166 Delba
= (struct rtllib_hdr_3addr
*) skb_put(skb
,
167 sizeof(struct rtllib_hdr_3addr
));
169 ether_addr_copy(Delba
->addr1
, dst
);
170 ether_addr_copy(Delba
->addr2
, ieee
->dev
->dev_addr
);
171 ether_addr_copy(Delba
->addr3
, ieee
->current_network
.bssid
);
172 Delba
->frame_ctl
= cpu_to_le16(RTLLIB_STYPE_MANAGE_ACT
);
174 tag
= (u8
*)skb_put(skb
, 6);
180 put_unaligned_le16(DelbaParamSet
.shortData
, tag
);
183 put_unaligned_le16(ReasonCode
, tag
);
187 print_hex_dump_bytes("rtllib_DELBA(): ", DUMP_PREFIX_NONE
, skb
->data
,
193 static void rtllib_send_ADDBAReq(struct rtllib_device
*ieee
, u8
*dst
,
194 struct ba_record
*pBA
)
196 struct sk_buff
*skb
= NULL
;
198 skb
= rtllib_ADDBA(ieee
, dst
, pBA
, 0, ACT_ADDBAREQ
);
201 RT_TRACE(COMP_DBG
, "====>to send ADDBAREQ!!!!!\n");
202 softmac_mgmt_xmit(skb
, ieee
);
204 netdev_dbg(ieee
->dev
, "Failed to generate ADDBAReq packet.\n");
208 static void rtllib_send_ADDBARsp(struct rtllib_device
*ieee
, u8
*dst
,
209 struct ba_record
*pBA
, u16 StatusCode
)
211 struct sk_buff
*skb
= NULL
;
213 skb
= rtllib_ADDBA(ieee
, dst
, pBA
, StatusCode
, ACT_ADDBARSP
);
215 softmac_mgmt_xmit(skb
, ieee
);
217 netdev_dbg(ieee
->dev
, "Failed to generate ADDBARsp packet.\n");
220 static void rtllib_send_DELBA(struct rtllib_device
*ieee
, u8
*dst
,
221 struct ba_record
*pBA
, enum tr_select TxRxSelect
,
224 struct sk_buff
*skb
= NULL
;
226 skb
= rtllib_DELBA(ieee
, dst
, pBA
, TxRxSelect
, ReasonCode
);
228 softmac_mgmt_xmit(skb
, ieee
);
230 netdev_dbg(ieee
->dev
, "Failed to generate DELBA packet.\n");
233 int rtllib_rx_ADDBAReq(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
235 struct rtllib_hdr_3addr
*req
= NULL
;
237 u8
*dst
= NULL
, *pDialogToken
= NULL
, *tag
= NULL
;
238 struct ba_record
*pBA
= NULL
;
239 union ba_param_set
*pBaParamSet
= NULL
;
240 u16
*pBaTimeoutVal
= NULL
;
241 union sequence_control
*pBaStartSeqCtrl
= NULL
;
242 struct rx_ts_record
*pTS
= NULL
;
244 if (skb
->len
< sizeof(struct rtllib_hdr_3addr
) + 9) {
245 netdev_warn(ieee
->dev
, "Invalid skb len in BAREQ(%d / %d)\n",
247 (int)(sizeof(struct rtllib_hdr_3addr
) + 9));
252 print_hex_dump_bytes("rtllib_rx_ADDBAReq(): ", DUMP_PREFIX_NONE
,
253 skb
->data
, skb
->len
);
256 req
= (struct rtllib_hdr_3addr
*) skb
->data
;
258 dst
= (u8
*)(&req
->addr2
[0]);
259 tag
+= sizeof(struct rtllib_hdr_3addr
);
260 pDialogToken
= tag
+ 2;
261 pBaParamSet
= (union ba_param_set
*)(tag
+ 3);
262 pBaTimeoutVal
= (u16
*)(tag
+ 5);
263 pBaStartSeqCtrl
= (union sequence_control
*)(req
+ 7);
265 RT_TRACE(COMP_DBG
, "====>rx ADDBAREQ from : %pM\n", dst
);
266 if (ieee
->current_network
.qos_data
.active
== 0 ||
267 (ieee
->pHTInfo
->bCurrentHTSupport
== false) ||
268 (ieee
->pHTInfo
->IOTAction
& HT_IOT_ACT_REJECT_ADDBA_REQ
)) {
269 rc
= ADDBA_STATUS_REFUSED
;
270 netdev_warn(ieee
->dev
,
271 "Failed to reply on ADDBA_REQ as some capability is not ready(%d, %d)\n",
272 ieee
->current_network
.qos_data
.active
,
273 ieee
->pHTInfo
->bCurrentHTSupport
);
274 goto OnADDBAReq_Fail
;
276 if (!GetTs(ieee
, (struct ts_common_info
**)(&pTS
), dst
,
277 (u8
)(pBaParamSet
->field
.TID
), RX_DIR
, true)) {
278 rc
= ADDBA_STATUS_REFUSED
;
279 netdev_warn(ieee
->dev
, "%s(): can't get TS\n", __func__
);
280 goto OnADDBAReq_Fail
;
282 pBA
= &pTS
->RxAdmittedBARecord
;
284 if (pBaParamSet
->field
.BAPolicy
== BA_POLICY_DELAYED
) {
285 rc
= ADDBA_STATUS_INVALID_PARAM
;
286 netdev_warn(ieee
->dev
, "%s(): BA Policy is not correct\n",
288 goto OnADDBAReq_Fail
;
291 rtllib_FlushRxTsPendingPkts(ieee
, pTS
);
293 DeActivateBAEntry(ieee
, pBA
);
294 pBA
->DialogToken
= *pDialogToken
;
295 pBA
->BaParamSet
= *pBaParamSet
;
296 pBA
->BaTimeoutValue
= *pBaTimeoutVal
;
297 pBA
->BaStartSeqCtrl
= *pBaStartSeqCtrl
;
299 if (ieee
->GetHalfNmodeSupportByAPsHandler(ieee
->dev
) ||
300 (ieee
->pHTInfo
->IOTAction
& HT_IOT_ACT_ALLOW_PEER_AGG_ONE_PKT
))
301 pBA
->BaParamSet
.field
.BufferSize
= 1;
303 pBA
->BaParamSet
.field
.BufferSize
= 32;
305 ActivateBAEntry(ieee
, pBA
, 0);
306 rtllib_send_ADDBARsp(ieee
, dst
, pBA
, ADDBA_STATUS_SUCCESS
);
314 BA
.BaParamSet
= *pBaParamSet
;
315 BA
.BaTimeoutValue
= *pBaTimeoutVal
;
316 BA
.DialogToken
= *pDialogToken
;
317 BA
.BaParamSet
.field
.BAPolicy
= BA_POLICY_IMMEDIATE
;
318 rtllib_send_ADDBARsp(ieee
, dst
, &BA
, rc
);
323 int rtllib_rx_ADDBARsp(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
325 struct rtllib_hdr_3addr
*rsp
= NULL
;
326 struct ba_record
*pPendingBA
, *pAdmittedBA
;
327 struct tx_ts_record
*pTS
= NULL
;
328 u8
*dst
= NULL
, *pDialogToken
= NULL
, *tag
= NULL
;
329 u16
*pStatusCode
= NULL
, *pBaTimeoutVal
= NULL
;
330 union ba_param_set
*pBaParamSet
= NULL
;
333 if (skb
->len
< sizeof(struct rtllib_hdr_3addr
) + 9) {
334 netdev_warn(ieee
->dev
, "Invalid skb len in BARSP(%d / %d)\n",
336 (int)(sizeof(struct rtllib_hdr_3addr
) + 9));
339 rsp
= (struct rtllib_hdr_3addr
*)skb
->data
;
341 dst
= (u8
*)(&rsp
->addr2
[0]);
342 tag
+= sizeof(struct rtllib_hdr_3addr
);
343 pDialogToken
= tag
+ 2;
344 pStatusCode
= (u16
*)(tag
+ 3);
345 pBaParamSet
= (union ba_param_set
*)(tag
+ 5);
346 pBaTimeoutVal
= (u16
*)(tag
+ 7);
348 RT_TRACE(COMP_DBG
, "====>rx ADDBARSP from : %pM\n", dst
);
349 if (ieee
->current_network
.qos_data
.active
== 0 ||
350 ieee
->pHTInfo
->bCurrentHTSupport
== false ||
351 ieee
->pHTInfo
->bCurrentAMPDUEnable
== false) {
352 netdev_warn(ieee
->dev
,
353 "reject to ADDBA_RSP as some capability is not ready(%d, %d, %d)\n",
354 ieee
->current_network
.qos_data
.active
,
355 ieee
->pHTInfo
->bCurrentHTSupport
,
356 ieee
->pHTInfo
->bCurrentAMPDUEnable
);
357 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
358 goto OnADDBARsp_Reject
;
362 if (!GetTs(ieee
, (struct ts_common_info
**)(&pTS
), dst
,
363 (u8
)(pBaParamSet
->field
.TID
), TX_DIR
, false)) {
364 netdev_warn(ieee
->dev
, "%s(): can't get TS\n", __func__
);
365 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
366 goto OnADDBARsp_Reject
;
369 pTS
->bAddBaReqInProgress
= false;
370 pPendingBA
= &pTS
->TxPendingBARecord
;
371 pAdmittedBA
= &pTS
->TxAdmittedBARecord
;
374 if (pAdmittedBA
->bValid
== true) {
375 netdev_dbg(ieee
->dev
, "%s(): ADDBA response already admitted\n",
378 } else if ((pPendingBA
->bValid
== false) ||
379 (*pDialogToken
!= pPendingBA
->DialogToken
)) {
380 netdev_warn(ieee
->dev
,
381 "%s(): ADDBA Rsp. BA invalid, DELBA!\n",
383 ReasonCode
= DELBA_REASON_UNKNOWN_BA
;
384 goto OnADDBARsp_Reject
;
386 netdev_dbg(ieee
->dev
,
387 "%s(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n",
388 __func__
, *pStatusCode
);
389 DeActivateBAEntry(ieee
, pPendingBA
);
393 if (*pStatusCode
== ADDBA_STATUS_SUCCESS
) {
394 if (pBaParamSet
->field
.BAPolicy
== BA_POLICY_DELAYED
) {
395 pTS
->bAddBaReqDelayed
= true;
396 DeActivateBAEntry(ieee
, pAdmittedBA
);
397 ReasonCode
= DELBA_REASON_END_BA
;
398 goto OnADDBARsp_Reject
;
402 pAdmittedBA
->DialogToken
= *pDialogToken
;
403 pAdmittedBA
->BaTimeoutValue
= *pBaTimeoutVal
;
404 pAdmittedBA
->BaStartSeqCtrl
= pPendingBA
->BaStartSeqCtrl
;
405 pAdmittedBA
->BaParamSet
= *pBaParamSet
;
406 DeActivateBAEntry(ieee
, pAdmittedBA
);
407 ActivateBAEntry(ieee
, pAdmittedBA
, *pBaTimeoutVal
);
409 pTS
->bAddBaReqDelayed
= true;
410 pTS
->bDisable_AddBa
= true;
411 ReasonCode
= DELBA_REASON_END_BA
;
412 goto OnADDBARsp_Reject
;
421 BA
.BaParamSet
= *pBaParamSet
;
422 rtllib_send_DELBA(ieee
, dst
, &BA
, TX_DIR
, ReasonCode
);
427 int rtllib_rx_DELBA(struct rtllib_device
*ieee
, struct sk_buff
*skb
)
429 struct rtllib_hdr_3addr
*delba
= NULL
;
430 union delba_param_set
*pDelBaParamSet
= NULL
;
431 u16
*pReasonCode
= NULL
;
434 if (skb
->len
< sizeof(struct rtllib_hdr_3addr
) + 6) {
435 netdev_warn(ieee
->dev
, "Invalid skb len in DELBA(%d / %d)\n",
437 (int)(sizeof(struct rtllib_hdr_3addr
) + 6));
441 if (ieee
->current_network
.qos_data
.active
== 0 ||
442 ieee
->pHTInfo
->bCurrentHTSupport
== false) {
443 netdev_warn(ieee
->dev
,
444 "received DELBA while QOS or HT is not supported(%d, %d)\n",
445 ieee
->current_network
. qos_data
.active
,
446 ieee
->pHTInfo
->bCurrentHTSupport
);
451 print_hex_dump_bytes("rtllib_rx_DELBA(): ", DUMP_PREFIX_NONE
, skb
->data
,
454 delba
= (struct rtllib_hdr_3addr
*)skb
->data
;
455 dst
= (u8
*)(&delba
->addr2
[0]);
456 delba
+= sizeof(struct rtllib_hdr_3addr
);
457 pDelBaParamSet
= (union delba_param_set
*)(delba
+2);
458 pReasonCode
= (u16
*)(delba
+4);
460 if (pDelBaParamSet
->field
.Initiator
== 1) {
461 struct rx_ts_record
*pRxTs
;
463 if (!GetTs(ieee
, (struct ts_common_info
**)&pRxTs
, dst
,
464 (u8
)pDelBaParamSet
->field
.TID
, RX_DIR
, false)) {
465 netdev_warn(ieee
->dev
,
466 "%s(): can't get TS for RXTS. dst:%pM TID:%d\n",
468 (u8
)pDelBaParamSet
->field
.TID
);
472 RxTsDeleteBA(ieee
, pRxTs
);
474 struct tx_ts_record
*pTxTs
;
476 if (!GetTs(ieee
, (struct ts_common_info
**)&pTxTs
, dst
,
477 (u8
)pDelBaParamSet
->field
.TID
, TX_DIR
, false)) {
478 netdev_warn(ieee
->dev
, "%s(): can't get TS for TXTS\n",
483 pTxTs
->bUsingBa
= false;
484 pTxTs
->bAddBaReqInProgress
= false;
485 pTxTs
->bAddBaReqDelayed
= false;
486 del_timer_sync(&pTxTs
->TsAddBaTimer
);
487 TxTsDeleteBA(ieee
, pTxTs
);
492 void TsInitAddBA(struct rtllib_device
*ieee
, struct tx_ts_record
*pTS
,
493 u8 Policy
, u8 bOverwritePending
)
495 struct ba_record
*pBA
= &pTS
->TxPendingBARecord
;
497 if (pBA
->bValid
== true && bOverwritePending
== false)
500 DeActivateBAEntry(ieee
, pBA
);
503 pBA
->BaParamSet
.field
.AMSDU_Support
= 0;
504 pBA
->BaParamSet
.field
.BAPolicy
= Policy
;
505 pBA
->BaParamSet
.field
.TID
=
506 pTS
->TsCommonInfo
.TSpec
.f
.TSInfo
.field
.ucTSID
;
507 pBA
->BaParamSet
.field
.BufferSize
= 32;
508 pBA
->BaTimeoutValue
= 0;
509 pBA
->BaStartSeqCtrl
.field
.SeqNum
= (pTS
->TxCurSeq
+ 3) % 4096;
511 ActivateBAEntry(ieee
, pBA
, BA_SETUP_TIMEOUT
);
513 rtllib_send_ADDBAReq(ieee
, pTS
->TsCommonInfo
.Addr
, pBA
);
516 void TsInitDelBA(struct rtllib_device
*ieee
,
517 struct ts_common_info
*pTsCommonInfo
,
518 enum tr_select TxRxSelect
)
520 if (TxRxSelect
== TX_DIR
) {
521 struct tx_ts_record
*pTxTs
=
522 (struct tx_ts_record
*)pTsCommonInfo
;
524 if (TxTsDeleteBA(ieee
, pTxTs
))
525 rtllib_send_DELBA(ieee
, pTsCommonInfo
->Addr
,
526 (pTxTs
->TxAdmittedBARecord
.bValid
) ?
527 (&pTxTs
->TxAdmittedBARecord
) :
528 (&pTxTs
->TxPendingBARecord
),
529 TxRxSelect
, DELBA_REASON_END_BA
);
530 } else if (TxRxSelect
== RX_DIR
) {
531 struct rx_ts_record
*pRxTs
=
532 (struct rx_ts_record
*)pTsCommonInfo
;
533 if (RxTsDeleteBA(ieee
, pRxTs
))
534 rtllib_send_DELBA(ieee
, pTsCommonInfo
->Addr
,
535 &pRxTs
->RxAdmittedBARecord
,
536 TxRxSelect
, DELBA_REASON_END_BA
);
540 void BaSetupTimeOut(unsigned long data
)
542 struct tx_ts_record
*pTxTs
= (struct tx_ts_record
*)data
;
544 pTxTs
->bAddBaReqInProgress
= false;
545 pTxTs
->bAddBaReqDelayed
= true;
546 pTxTs
->TxPendingBARecord
.bValid
= false;
549 void TxBaInactTimeout(unsigned long data
)
551 struct tx_ts_record
*pTxTs
= (struct tx_ts_record
*)data
;
552 struct rtllib_device
*ieee
= container_of(pTxTs
, struct rtllib_device
,
553 TxTsRecord
[pTxTs
->num
]);
554 TxTsDeleteBA(ieee
, pTxTs
);
555 rtllib_send_DELBA(ieee
, pTxTs
->TsCommonInfo
.Addr
,
556 &pTxTs
->TxAdmittedBARecord
, TX_DIR
,
557 DELBA_REASON_TIMEOUT
);
560 void RxBaInactTimeout(unsigned long data
)
562 struct rx_ts_record
*pRxTs
= (struct rx_ts_record
*)data
;
563 struct rtllib_device
*ieee
= container_of(pRxTs
, struct rtllib_device
,
564 RxTsRecord
[pRxTs
->num
]);
566 RxTsDeleteBA(ieee
, pRxTs
);
567 rtllib_send_DELBA(ieee
, pRxTs
->TsCommonInfo
.Addr
,
568 &pRxTs
->RxAdmittedBARecord
, RX_DIR
,
569 DELBA_REASON_TIMEOUT
);