linux/drivers/staging/rtl8192u/ieee80211/rtl819x_BAProc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/********************************************************************************************************************************
   3 * 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
   4 * related to TS, this part need some structure defined in QOS side code. Also TX RX is going to be resturctured, so how to send
   5 * ADDBAREQ ADDBARSP and DELBA packet is still on consideration. Temporarily use MANAGE QUEUE instead of Normal Queue.
   6 * WB 2008-05-27
   7 * *****************************************************************************************************************************/
   8#include <asm/byteorder.h>
   9#include <asm/unaligned.h>
  10#include "ieee80211.h"
  11#include "rtl819x_BA.h"
  12
  13/********************************************************************************************************************
  14 *function:  Activate BA entry. And if Time is nozero, start timer.
  15 *   input:  PBA_RECORD                 pBA  //BA entry to be enabled
  16 *           u16                        Time //indicate time delay.
  17 *  output:  none
  18 ********************************************************************************************************************/
  19static void ActivateBAEntry(struct ieee80211_device *ieee, PBA_RECORD pBA, u16 Time)
  20{
  21        pBA->bValid = true;
  22        if(Time != 0)
  23                mod_timer(&pBA->Timer, jiffies + msecs_to_jiffies(Time));
  24}
  25
  26/********************************************************************************************************************
  27 *function:  deactivate BA entry, including its timer.
  28 *   input:  PBA_RECORD                 pBA  //BA entry to be disabled
  29 *  output:  none
  30 ********************************************************************************************************************/
  31static void DeActivateBAEntry(struct ieee80211_device *ieee, PBA_RECORD pBA)
  32{
  33        pBA->bValid = false;
  34        del_timer_sync(&pBA->Timer);
  35}
  36/********************************************************************************************************************
  37 *function: deactivete BA entry in Tx Ts, and send DELBA.
  38 *   input:
  39 *           PTX_TS_RECORD              pTxTs //Tx Ts which is to deactivate BA entry.
  40 *  output:  none
  41 *  notice:  As PTX_TS_RECORD structure will be defined in QOS, so wait to be merged. //FIXME
  42 ********************************************************************************************************************/
  43static u8 TxTsDeleteBA(struct ieee80211_device *ieee, PTX_TS_RECORD pTxTs)
  44{
  45        PBA_RECORD              pAdmittedBa = &pTxTs->TxAdmittedBARecord;  //These two BA entries must exist in TS structure
  46        PBA_RECORD              pPendingBa = &pTxTs->TxPendingBARecord;
  47        u8                      bSendDELBA = false;
  48
  49        // Delete pending BA
  50        if (pPendingBa->bValid) {
  51                DeActivateBAEntry(ieee, pPendingBa);
  52                bSendDELBA = true;
  53        }
  54
  55        // Delete admitted BA
  56        if (pAdmittedBa->bValid) {
  57                DeActivateBAEntry(ieee, pAdmittedBa);
  58                bSendDELBA = true;
  59        }
  60
  61        return bSendDELBA;
  62}
  63
  64/********************************************************************************************************************
  65 *function: deactivete BA entry in Tx Ts, and send DELBA.
  66 *   input:
  67 *           PRX_TS_RECORD              pRxTs //Rx Ts which is to deactivate BA entry.
  68 *  output:  none
  69 *  notice:  As PRX_TS_RECORD structure will be defined in QOS, so wait to be merged. //FIXME, same with above
  70 ********************************************************************************************************************/
  71static u8 RxTsDeleteBA(struct ieee80211_device *ieee, PRX_TS_RECORD pRxTs)
  72{
  73        PBA_RECORD              pBa = &pRxTs->RxAdmittedBARecord;
  74        u8                      bSendDELBA = false;
  75
  76        if (pBa->bValid) {
  77                DeActivateBAEntry(ieee, pBa);
  78                bSendDELBA = true;
  79        }
  80
  81        return bSendDELBA;
  82}
  83
  84/********************************************************************************************************************
  85 *function: reset BA entry
  86 *   input:
  87 *           PBA_RECORD         pBA //entry to be reset
  88 *  output:  none
  89 ********************************************************************************************************************/
  90void ResetBaEntry(PBA_RECORD pBA)
  91{
  92        pBA->bValid                     = false;
  93        pBA->BaParamSet.shortData       = 0;
  94        pBA->BaTimeoutValue             = 0;
  95        pBA->DialogToken                = 0;
  96        pBA->BaStartSeqCtrl.ShortData   = 0;
  97}
  98//These functions need porting here or not?
  99/*******************************************************************************************************************************
 100 *function:  construct ADDBAREQ and ADDBARSP frame here together.
 101 *   input:  u8*                Dst     //ADDBA frame's destination
 102 *           PBA_RECORD         pBA     //BA_RECORD entry which stores the necessary information for BA.
 103 *           u16                StatusCode  //status code in RSP and I will use it to indicate whether it's RSP or REQ(will I?)
 104 *           u8                 type    //indicate whether it's RSP(ACT_ADDBARSP) ow REQ(ACT_ADDBAREQ)
 105 *  output:  none
 106 *  return:  sk_buff*           skb     //return constructed skb to xmit
 107 *******************************************************************************************************************************/
 108static struct sk_buff *ieee80211_ADDBA(struct ieee80211_device *ieee, u8 *Dst, PBA_RECORD pBA, u16 StatusCode, u8 type)
 109{
 110        struct sk_buff *skb = NULL;
 111         struct rtl_80211_hdr_3addr *BAReq = NULL;
 112        u8 *tag = NULL;
 113        u16 len = ieee->tx_headroom + 9;
 114        //category(1) + action field(1) + Dialog Token(1) + BA Parameter Set(2) +  BA Timeout Value(2) +  BA Start SeqCtrl(2)(or StatusCode(2))
 115        IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA, "========>%s(), frame(%d) sentd to:%pM, ieee->dev:%p\n", __func__, type, Dst, ieee->dev);
 116        if (pBA == NULL) {
 117                IEEE80211_DEBUG(IEEE80211_DL_ERR, "pBA is NULL\n");
 118                return NULL;
 119        }
 120        skb = dev_alloc_skb(len + sizeof( struct rtl_80211_hdr_3addr)); //need to add something others? FIXME
 121        if (!skb) {
 122                IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
 123                return NULL;
 124        }
 125
 126        memset(skb->data, 0, sizeof( struct rtl_80211_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);
 128
 129        BAReq = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
 130
 131        memcpy(BAReq->addr1, Dst, ETH_ALEN);
 132        memcpy(BAReq->addr2, ieee->dev->dev_addr, ETH_ALEN);
 133
 134        memcpy(BAReq->addr3, ieee->current_network.bssid, ETH_ALEN);
 135
 136        BAReq->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
 137
 138        //tag += sizeof( struct rtl_80211_hdr_3addr); //move to action field
 139        tag = skb_put(skb, 9);
 140        *tag ++= ACT_CAT_BA;
 141        *tag ++= type;
 142        // Dialog Token
 143        *tag ++= pBA->DialogToken;
 144
 145        if (ACT_ADDBARSP == type) {
 146                // Status Code
 147                netdev_info(ieee->dev, "=====>to send ADDBARSP\n");
 148
 149                put_unaligned_le16(StatusCode, tag);
 150                tag += 2;
 151        }
 152        // BA Parameter Set
 153
 154        put_unaligned_le16(pBA->BaParamSet.shortData, tag);
 155        tag += 2;
 156        // BA Timeout Value
 157
 158        put_unaligned_le16(pBA->BaTimeoutValue, tag);
 159        tag += 2;
 160
 161        if (ACT_ADDBAREQ == type) {
 162        // BA Start SeqCtrl
 163                memcpy(tag, (u8 *)&(pBA->BaStartSeqCtrl), 2);
 164                tag += 2;
 165        }
 166
 167        IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
 168        return skb;
 169        //return NULL;
 170}
 171
 172
 173/********************************************************************************************************************
 174 *function:  construct DELBA frame
 175 *   input:  u8*                dst     //DELBA frame's destination
 176 *           PBA_RECORD         pBA     //BA_RECORD entry which stores the necessary information for BA
 177 *           TR_SELECT          TxRxSelect  //TX RX direction
 178 *           u16                ReasonCode  //status code.
 179 *  output:  none
 180 *  return:  sk_buff*           skb     //return constructed skb to xmit
 181 ********************************************************************************************************************/
 182static struct sk_buff *ieee80211_DELBA(
 183        struct ieee80211_device  *ieee,
 184        u8                       *dst,
 185        PBA_RECORD               pBA,
 186        TR_SELECT                TxRxSelect,
 187        u16                      ReasonCode
 188        )
 189{
 190        DELBA_PARAM_SET DelbaParamSet;
 191        struct sk_buff *skb = NULL;
 192         struct rtl_80211_hdr_3addr *Delba = NULL;
 193        u8 *tag = NULL;
 194        //len = head len + DELBA Parameter Set(2) + Reason Code(2)
 195        u16 len = 6 + ieee->tx_headroom;
 196
 197        if (net_ratelimit())
 198                IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA,
 199                                "========>%s(), ReasonCode(%d) sentd to:%pM\n",
 200                                __func__, ReasonCode, dst);
 201
 202        memset(&DelbaParamSet, 0, 2);
 203
 204        DelbaParamSet.field.Initiator   = (TxRxSelect==TX_DIR)?1:0;
 205        DelbaParamSet.field.TID = pBA->BaParamSet.field.TID;
 206
 207        skb = dev_alloc_skb(len + sizeof( struct rtl_80211_hdr_3addr)); //need to add something others? FIXME
 208        if (!skb) {
 209                IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc skb for ADDBA_REQ\n");
 210                return NULL;
 211        }
 212//      memset(skb->data, 0, len+sizeof( struct rtl_80211_hdr_3addr));
 213        skb_reserve(skb, ieee->tx_headroom);
 214
 215        Delba = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
 216
 217        memcpy(Delba->addr1, dst, ETH_ALEN);
 218        memcpy(Delba->addr2, ieee->dev->dev_addr, ETH_ALEN);
 219        memcpy(Delba->addr3, ieee->current_network.bssid, ETH_ALEN);
 220        Delba->frame_ctl = cpu_to_le16(IEEE80211_STYPE_MANAGE_ACT); //action frame
 221
 222        tag = skb_put(skb, 6);
 223
 224        *tag ++= ACT_CAT_BA;
 225        *tag ++= ACT_DELBA;
 226
 227        // DELBA Parameter Set
 228
 229        put_unaligned_le16(DelbaParamSet.shortData, tag);
 230        tag += 2;
 231        // Reason Code
 232
 233        put_unaligned_le16(ReasonCode, tag);
 234        tag += 2;
 235
 236        IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
 237        if (net_ratelimit())
 238                IEEE80211_DEBUG(IEEE80211_DL_TRACE | IEEE80211_DL_BA,
 239                                "<=====%s()\n", __func__);
 240        return skb;
 241}
 242
 243/********************************************************************************************************************
 244 *function: send ADDBAReq frame out
 245 *   input:  u8*                dst     //ADDBAReq frame's destination
 246 *           PBA_RECORD         pBA     //BA_RECORD entry which stores the necessary information for BA
 247 *  output:  none
 248 *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
 249 ********************************************************************************************************************/
 250static void ieee80211_send_ADDBAReq(struct ieee80211_device *ieee,
 251                                    u8 *dst, PBA_RECORD pBA)
 252{
 253        struct sk_buff *skb;
 254        skb = ieee80211_ADDBA(ieee, dst, pBA, 0, ACT_ADDBAREQ); //construct ACT_ADDBAREQ frames so set statuscode zero.
 255
 256        if (skb) {
 257                softmac_mgmt_xmit(skb, ieee);
 258                //add statistic needed here.
 259                //and skb will be freed in softmac_mgmt_xmit(), so omit all dev_kfree_skb_any() outside softmac_mgmt_xmit()
 260                //WB
 261        }
 262        else {
 263                IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
 264        }
 265}
 266
 267/********************************************************************************************************************
 268 *function: send ADDBARSP frame out
 269 *   input:  u8*                dst     //DELBA frame's destination
 270 *           PBA_RECORD         pBA     //BA_RECORD entry which stores the necessary information for BA
 271 *           u16                StatusCode //RSP StatusCode
 272 *  output:  none
 273 *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
 274 ********************************************************************************************************************/
 275static void ieee80211_send_ADDBARsp(struct ieee80211_device *ieee, u8 *dst,
 276                                    PBA_RECORD pBA, u16 StatusCode)
 277{
 278        struct sk_buff *skb;
 279        skb = ieee80211_ADDBA(ieee, dst, pBA, StatusCode, ACT_ADDBARSP); //construct ACT_ADDBARSP frames
 280        if (skb) {
 281                softmac_mgmt_xmit(skb, ieee);
 282                //same above
 283        }
 284        else {
 285                IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
 286        }
 287
 288        return;
 289
 290}
 291/********************************************************************************************************************
 292 *function: send ADDBARSP frame out
 293 *   input:  u8*                dst     //DELBA frame's destination
 294 *           PBA_RECORD         pBA     //BA_RECORD entry which stores the necessary information for BA
 295 *           TR_SELECT          TxRxSelect //TX or RX
 296 *           u16                ReasonCode //DEL ReasonCode
 297 *  output:  none
 298 *  notice: If any possible, please hide pBA in ieee. And temporarily use Manage Queue as softmac_mgmt_xmit() usually does
 299 ********************************************************************************************************************/
 300
 301static void ieee80211_send_DELBA(struct ieee80211_device *ieee, u8 *dst,
 302                                 PBA_RECORD pBA, TR_SELECT TxRxSelect,
 303                                 u16 ReasonCode)
 304{
 305        struct sk_buff *skb;
 306        skb = ieee80211_DELBA(ieee, dst, pBA, TxRxSelect, ReasonCode); //construct ACT_ADDBARSP frames
 307        if (skb) {
 308                softmac_mgmt_xmit(skb, ieee);
 309                //same above
 310        }
 311        else {
 312                IEEE80211_DEBUG(IEEE80211_DL_ERR, "alloc skb error in function %s()\n", __func__);
 313        }
 314}
 315
 316/********************************************************************************************************************
 317 *function: RX ADDBAReq
 318 *   input:  struct sk_buff *   skb     //incoming ADDBAReq skb.
 319 *  return:  0(pass), other(fail)
 320 *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
 321 ********************************************************************************************************************/
 322int ieee80211_rx_ADDBAReq(struct ieee80211_device *ieee, struct sk_buff *skb)
 323{
 324         struct rtl_80211_hdr_3addr *req = NULL;
 325        u16 rc = 0;
 326        u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
 327        PBA_RECORD pBA = NULL;
 328        PBA_PARAM_SET   pBaParamSet = NULL;
 329        u16 *pBaTimeoutVal = NULL;
 330        PSEQUENCE_CONTROL pBaStartSeqCtrl = NULL;
 331        PRX_TS_RECORD   pTS = NULL;
 332
 333        if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 9) {
 334                IEEE80211_DEBUG(IEEE80211_DL_ERR,
 335                                " Invalid skb len in BAREQ(%d / %zu)\n",
 336                                skb->len,
 337                                (sizeof(struct rtl_80211_hdr_3addr) + 9));
 338                return -1;
 339        }
 340
 341        IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
 342
 343        req = (struct rtl_80211_hdr_3addr *) skb->data;
 344        tag = (u8 *)req;
 345        dst = &req->addr2[0];
 346        tag += sizeof(struct rtl_80211_hdr_3addr);
 347        pDialogToken = tag + 2;  //category+action
 348        pBaParamSet = (PBA_PARAM_SET)(tag + 3);   //+DialogToken
 349        pBaTimeoutVal = (u16 *)(tag + 5);
 350        pBaStartSeqCtrl = (PSEQUENCE_CONTROL)(req + 7);
 351
 352        netdev_info(ieee->dev, "====================>rx ADDBAREQ from :%pM\n", dst);
 353//some other capability is not ready now.
 354        if ((ieee->current_network.qos_data.active == 0) ||
 355                (!ieee->pHTInfo->bCurrentHTSupport)) //||
 356        //      (!ieee->pStaQos->bEnableRxImmBA)        )
 357        {
 358                rc = ADDBA_STATUS_REFUSED;
 359                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);
 360                goto OnADDBAReq_Fail;
 361        }
 362        // Search for related traffic stream.
 363        // If there is no matched TS, reject the ADDBA request.
 364        if (!GetTs(
 365                        ieee,
 366                        (PTS_COMMON_INFO *)(&pTS),
 367                        dst,
 368                        (u8)(pBaParamSet->field.TID),
 369                        RX_DIR,
 370                        true)   ) {
 371                rc = ADDBA_STATUS_REFUSED;
 372                IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __func__);
 373                goto OnADDBAReq_Fail;
 374        }
 375        pBA = &pTS->RxAdmittedBARecord;
 376        // To Determine the ADDBA Req content
 377        // We can do much more check here, including BufferSize, AMSDU_Support, Policy, StartSeqCtrl...
 378        // I want to check StartSeqCtrl to make sure when we start aggregation!!!
 379        //
 380        if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
 381                rc = ADDBA_STATUS_INVALID_PARAM;
 382                IEEE80211_DEBUG(IEEE80211_DL_ERR, "BA Policy is not correct in %s()\n", __func__);
 383                goto OnADDBAReq_Fail;
 384        }
 385                // Admit the ADDBA Request
 386        //
 387        DeActivateBAEntry(ieee, pBA);
 388        pBA->DialogToken = *pDialogToken;
 389        pBA->BaParamSet = *pBaParamSet;
 390        pBA->BaTimeoutValue = *pBaTimeoutVal;
 391        pBA->BaStartSeqCtrl = *pBaStartSeqCtrl;
 392        //for half N mode we only aggregate 1 frame
 393        if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev))
 394        pBA->BaParamSet.field.BufferSize = 1;
 395        else
 396        pBA->BaParamSet.field.BufferSize = 32;
 397        ActivateBAEntry(ieee, pBA, pBA->BaTimeoutValue);
 398        ieee80211_send_ADDBARsp(ieee, dst, pBA, ADDBA_STATUS_SUCCESS);
 399
 400        // End of procedure.
 401        return 0;
 402
 403OnADDBAReq_Fail:
 404        {
 405                BA_RECORD       BA;
 406                BA.BaParamSet = *pBaParamSet;
 407                BA.BaTimeoutValue = *pBaTimeoutVal;
 408                BA.DialogToken = *pDialogToken;
 409                BA.BaParamSet.field.BAPolicy = BA_POLICY_IMMEDIATE;
 410                ieee80211_send_ADDBARsp(ieee, dst, &BA, rc);
 411                return 0; //we send RSP out.
 412        }
 413
 414}
 415
 416/********************************************************************************************************************
 417 *function: RX ADDBARSP
 418 *   input:  struct sk_buff *   skb     //incoming ADDBAReq skb.
 419 *  return:  0(pass), other(fail)
 420 *  notice:  As this function need support of QOS, I comment some code out. And when qos is ready, this code need to be support.
 421 ********************************************************************************************************************/
 422int ieee80211_rx_ADDBARsp(struct ieee80211_device *ieee, struct sk_buff *skb)
 423{
 424         struct rtl_80211_hdr_3addr *rsp = NULL;
 425        PBA_RECORD              pPendingBA, pAdmittedBA;
 426        PTX_TS_RECORD           pTS = NULL;
 427        u8 *dst = NULL, *pDialogToken = NULL, *tag = NULL;
 428        u16 *pStatusCode = NULL, *pBaTimeoutVal = NULL;
 429        PBA_PARAM_SET           pBaParamSet = NULL;
 430        u16                     ReasonCode;
 431
 432        if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 9) {
 433                IEEE80211_DEBUG(IEEE80211_DL_ERR,
 434                                " Invalid skb len in BARSP(%d / %zu)\n",
 435                                skb->len,
 436                                (sizeof(struct rtl_80211_hdr_3addr) + 9));
 437                return -1;
 438        }
 439        rsp = (struct rtl_80211_hdr_3addr *)skb->data;
 440        tag = (u8 *)rsp;
 441        dst = &rsp->addr2[0];
 442        tag += sizeof(struct rtl_80211_hdr_3addr);
 443        pDialogToken = tag + 2;
 444        pStatusCode = (u16 *)(tag + 3);
 445        pBaParamSet = (PBA_PARAM_SET)(tag + 5);
 446        pBaTimeoutVal = (u16 *)(tag + 7);
 447
 448        // Check the capability
 449        // Since we can always receive A-MPDU, we just check if it is under HT mode.
 450        if (ieee->current_network.qos_data.active == 0  ||
 451            !ieee->pHTInfo->bCurrentHTSupport ||
 452            !ieee->pHTInfo->bCurrentAMPDUEnable) {
 453                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);
 454                ReasonCode = DELBA_REASON_UNKNOWN_BA;
 455                goto OnADDBARsp_Reject;
 456        }
 457
 458
 459        //
 460        // Search for related TS.
 461        // If there is no TS found, we wil reject ADDBA Rsp by sending DELBA frame.
 462        //
 463        if (!GetTs(
 464                        ieee,
 465                        (PTS_COMMON_INFO *)(&pTS),
 466                        dst,
 467                        (u8)(pBaParamSet->field.TID),
 468                        TX_DIR,
 469                        false)  ) {
 470                IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't get TS in %s()\n", __func__);
 471                ReasonCode = DELBA_REASON_UNKNOWN_BA;
 472                goto OnADDBARsp_Reject;
 473        }
 474
 475        pTS->bAddBaReqInProgress = false;
 476        pPendingBA = &pTS->TxPendingBARecord;
 477        pAdmittedBA = &pTS->TxAdmittedBARecord;
 478
 479
 480        //
 481        // Check if related BA is waiting for setup.
 482        // If not, reject by sending DELBA frame.
 483        //
 484        if (pAdmittedBA->bValid) {
 485                // Since BA is already setup, we ignore all other ADDBA Response.
 486                IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. Drop because already admit it! \n");
 487                return -1;
 488        }
 489        else if((!pPendingBA->bValid) ||(*pDialogToken != pPendingBA->DialogToken)) {
 490                IEEE80211_DEBUG(IEEE80211_DL_ERR,  "OnADDBARsp(): Recv ADDBA Rsp. BA invalid, DELBA! \n");
 491                ReasonCode = DELBA_REASON_UNKNOWN_BA;
 492                goto OnADDBARsp_Reject;
 493        }
 494        else {
 495                IEEE80211_DEBUG(IEEE80211_DL_BA, "OnADDBARsp(): Recv ADDBA Rsp. BA is admitted! Status code:%X\n", *pStatusCode);
 496                DeActivateBAEntry(ieee, pPendingBA);
 497        }
 498
 499
 500        if(*pStatusCode == ADDBA_STATUS_SUCCESS) {
 501                //
 502                // Determine ADDBA Rsp content here.
 503                // We can compare the value of BA parameter set that Peer returned and Self sent.
 504                // If it is OK, then admitted. Or we can send DELBA to cancel BA mechanism.
 505                //
 506                if (pBaParamSet->field.BAPolicy == BA_POLICY_DELAYED) {
 507                        // Since this is a kind of ADDBA failed, we delay next ADDBA process.
 508                        pTS->bAddBaReqDelayed = true;
 509                        DeActivateBAEntry(ieee, pAdmittedBA);
 510                        ReasonCode = DELBA_REASON_END_BA;
 511                        goto OnADDBARsp_Reject;
 512                }
 513
 514
 515                //
 516                // Admitted condition
 517                //
 518                pAdmittedBA->DialogToken = *pDialogToken;
 519                pAdmittedBA->BaTimeoutValue = *pBaTimeoutVal;
 520                pAdmittedBA->BaStartSeqCtrl = pPendingBA->BaStartSeqCtrl;
 521                pAdmittedBA->BaParamSet = *pBaParamSet;
 522                DeActivateBAEntry(ieee, pAdmittedBA);
 523                ActivateBAEntry(ieee, pAdmittedBA, *pBaTimeoutVal);
 524        }
 525        else {
 526                // Delay next ADDBA process.
 527                pTS->bAddBaReqDelayed = true;
 528        }
 529
 530        // End of procedure
 531        return 0;
 532
 533OnADDBARsp_Reject:
 534        {
 535                BA_RECORD       BA;
 536                BA.BaParamSet = *pBaParamSet;
 537                ieee80211_send_DELBA(ieee, dst, &BA, TX_DIR, ReasonCode);
 538                return 0;
 539        }
 540
 541}
 542
 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 ********************************************************************************************************************/
 549int ieee80211_rx_DELBA(struct ieee80211_device *ieee, struct sk_buff *skb)
 550{
 551         struct rtl_80211_hdr_3addr *delba = NULL;
 552        PDELBA_PARAM_SET        pDelBaParamSet = NULL;
 553        u8                      *dst = NULL;
 554
 555        if (skb->len < sizeof(struct rtl_80211_hdr_3addr) + 6) {
 556                IEEE80211_DEBUG(IEEE80211_DL_ERR,
 557                                " Invalid skb len in DELBA(%d / %zu)\n",
 558                                skb->len,
 559                                (sizeof(struct rtl_80211_hdr_3addr) + 6));
 560                return -1;
 561        }
 562
 563        if (ieee->current_network.qos_data.active == 0 ||
 564            !ieee->pHTInfo->bCurrentHTSupport) {
 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;
 567        }
 568
 569        IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
 570        delba = (struct rtl_80211_hdr_3addr *)skb->data;
 571        dst = &delba->addr2[0];
 572        pDelBaParamSet = (PDELBA_PARAM_SET)&delba->payload[2];
 573
 574        if(pDelBaParamSet->field.Initiator == 1) {
 575                PRX_TS_RECORD   pRxTs;
 576
 577                if (!GetTs(
 578                                ieee,
 579                                (PTS_COMMON_INFO *)&pRxTs,
 580                                dst,
 581                                (u8)pDelBaParamSet->field.TID,
 582                                RX_DIR,
 583                                false)  ) {
 584                        IEEE80211_DEBUG(IEEE80211_DL_ERR,  "can't get TS for RXTS in %s()\n", __func__);
 585                        return -1;
 586                }
 587
 588                RxTsDeleteBA(ieee, pRxTs);
 589        }
 590        else {
 591                PTX_TS_RECORD   pTxTs;
 592
 593                if (!GetTs(
 594                        ieee,
 595                        (PTS_COMMON_INFO *)&pTxTs,
 596                        dst,
 597                        (u8)pDelBaParamSet->field.TID,
 598                        TX_DIR,
 599                        false)  ) {
 600                        IEEE80211_DEBUG(IEEE80211_DL_ERR,  "can't get TS for TXTS in %s()\n", __func__);
 601                        return -1;
 602                }
 603
 604                pTxTs->bUsingBa = false;
 605                pTxTs->bAddBaReqInProgress = false;
 606                pTxTs->bAddBaReqDelayed = false;
 607                del_timer_sync(&pTxTs->TsAddBaTimer);
 608                //PlatformCancelTimer(Adapter, &pTxTs->TsAddBaTimer);
 609                TxTsDeleteBA(ieee, pTxTs);
 610        }
 611        return 0;
 612}
 613
 614//
 615// ADDBA initiate. This can only be called by TX side.
 616//
 617void
 618TsInitAddBA(
 619        struct ieee80211_device *ieee,
 620        PTX_TS_RECORD   pTS,
 621        u8              Policy,
 622        u8              bOverwritePending
 623        )
 624{
 625        PBA_RECORD                      pBA = &pTS->TxPendingBARecord;
 626
 627        if (pBA->bValid && !bOverwritePending)
 628                return;
 629
 630        // Set parameters to "Pending" variable set
 631        DeActivateBAEntry(ieee, pBA);
 632
 633        pBA->DialogToken++;                                             // DialogToken: Only keep the latest dialog token
 634        pBA->BaParamSet.field.AMSDU_Support = 0;        // Do not support A-MSDU with A-MPDU now!!
 635        pBA->BaParamSet.field.BAPolicy = Policy;        // Policy: Delayed or Immediate
 636        pBA->BaParamSet.field.TID = pTS->TsCommonInfo.TSpec.f.TSInfo.field.ucTSID;      // TID
 637        // BufferSize: This need to be set according to A-MPDU vector
 638        pBA->BaParamSet.field.BufferSize = 32;          // BufferSize: This need to be set according to A-MPDU vector
 639        pBA->BaTimeoutValue = 0;                                        // Timeout value: Set 0 to disable Timer
 640        pBA->BaStartSeqCtrl.field.SeqNum = (pTS->TxCurSeq + 3) % 4096;  // Block Ack will start after 3 packets later.
 641
 642        ActivateBAEntry(ieee, pBA, BA_SETUP_TIMEOUT);
 643
 644        ieee80211_send_ADDBAReq(ieee, pTS->TsCommonInfo.Addr, pBA);
 645}
 646
 647void
 648TsInitDelBA( struct ieee80211_device *ieee, PTS_COMMON_INFO pTsCommonInfo, TR_SELECT TxRxSelect)
 649{
 650
 651        if(TxRxSelect == TX_DIR) {
 652                PTX_TS_RECORD   pTxTs = (PTX_TS_RECORD)pTsCommonInfo;
 653
 654                if(TxTsDeleteBA(ieee, pTxTs))
 655                        ieee80211_send_DELBA(
 656                                ieee,
 657                                pTsCommonInfo->Addr,
 658                                (pTxTs->TxAdmittedBARecord.bValid)?(&pTxTs->TxAdmittedBARecord):(&pTxTs->TxPendingBARecord),
 659                                TxRxSelect,
 660                                DELBA_REASON_END_BA);
 661        }
 662        else if(TxRxSelect == RX_DIR) {
 663                PRX_TS_RECORD   pRxTs = (PRX_TS_RECORD)pTsCommonInfo;
 664                if(RxTsDeleteBA(ieee, pRxTs))
 665                        ieee80211_send_DELBA(
 666                                ieee,
 667                                pTsCommonInfo->Addr,
 668                                &pRxTs->RxAdmittedBARecord,
 669                                TxRxSelect,
 670                                DELBA_REASON_END_BA     );
 671        }
 672}
 673/********************************************************************************************************************
 674 *function:  BA setup timer
 675 *   input:  unsigned long       data           //acturally we send TX_TS_RECORD or RX_TS_RECORD to these timer
 676 *  return:  NULL
 677 *  notice:
 678 ********************************************************************************************************************/
 679void BaSetupTimeOut(struct timer_list *t)
 680{
 681        PTX_TS_RECORD   pTxTs = from_timer(pTxTs, t, TxPendingBARecord.Timer);
 682
 683        pTxTs->bAddBaReqInProgress = false;
 684        pTxTs->bAddBaReqDelayed = true;
 685        pTxTs->TxPendingBARecord.bValid = false;
 686}
 687
 688void TxBaInactTimeout(struct timer_list *t)
 689{
 690        PTX_TS_RECORD   pTxTs = from_timer(pTxTs, t, TxAdmittedBARecord.Timer);
 691        struct ieee80211_device *ieee = container_of(pTxTs, struct ieee80211_device, TxTsRecord[pTxTs->num]);
 692        TxTsDeleteBA(ieee, pTxTs);
 693        ieee80211_send_DELBA(
 694                ieee,
 695                pTxTs->TsCommonInfo.Addr,
 696                &pTxTs->TxAdmittedBARecord,
 697                TX_DIR,
 698                DELBA_REASON_TIMEOUT);
 699}
 700
 701void RxBaInactTimeout(struct timer_list *t)
 702{
 703        PRX_TS_RECORD   pRxTs = from_timer(pRxTs, t, RxAdmittedBARecord.Timer);
 704        struct ieee80211_device *ieee = container_of(pRxTs, struct ieee80211_device, RxTsRecord[pRxTs->num]);
 705
 706        RxTsDeleteBA(ieee, pRxTs);
 707        ieee80211_send_DELBA(
 708                ieee,
 709                pRxTs->TsCommonInfo.Addr,
 710                &pRxTs->RxAdmittedBARecord,
 711                RX_DIR,
 712                DELBA_REASON_TIMEOUT);
 713}
 714