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