linux/net/mac80211/agg-tx.c
<<
>>
Prefs
   1/*
   2 * HT handling
   3 *
   4 * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
   5 * Copyright 2002-2005, Instant802 Networks, Inc.
   6 * Copyright 2005-2006, Devicescape Software, Inc.
   7 * Copyright 2006-2007  Jiri Benc <jbenc@suse.cz>
   8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
   9 * Copyright 2007-2009, Intel Corporation
  10 *
  11 * This program is free software; you can redistribute it and/or modify
  12 * it under the terms of the GNU General Public License version 2 as
  13 * published by the Free Software Foundation.
  14 */
  15
  16#include <linux/ieee80211.h>
  17#include <net/mac80211.h>
  18#include "ieee80211_i.h"
  19#include "wme.h"
  20
  21/**
  22 * DOC: TX aggregation
  23 *
  24 * Aggregation on the TX side requires setting the hardware flag
  25 * %IEEE80211_HW_AMPDU_AGGREGATION as well as, if present, the @ampdu_queues
  26 * hardware parameter to the number of hardware AMPDU queues. If there are no
  27 * hardware queues then the driver will (currently) have to do all frame
  28 * buffering.
  29 *
  30 * When TX aggregation is started by some subsystem (usually the rate control
  31 * algorithm would be appropriate) by calling the
  32 * ieee80211_start_tx_ba_session() function, the driver will be notified via
  33 * its @ampdu_action function, with the %IEEE80211_AMPDU_TX_START action.
  34 *
  35 * In response to that, the driver is later required to call the
  36 * ieee80211_start_tx_ba_cb() (or ieee80211_start_tx_ba_cb_irqsafe())
  37 * function, which will start the aggregation session.
  38 *
  39 * Similarly, when the aggregation session is stopped by
  40 * ieee80211_stop_tx_ba_session(), the driver's @ampdu_action function will
  41 * be called with the action %IEEE80211_AMPDU_TX_STOP. In this case, the
  42 * call must not fail, and the driver must later call ieee80211_stop_tx_ba_cb()
  43 * (or ieee80211_stop_tx_ba_cb_irqsafe()).
  44 */
  45
  46static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
  47                                         const u8 *da, u16 tid,
  48                                         u8 dialog_token, u16 start_seq_num,
  49                                         u16 agg_size, u16 timeout)
  50{
  51        struct ieee80211_local *local = sdata->local;
  52        struct sk_buff *skb;
  53        struct ieee80211_mgmt *mgmt;
  54        u16 capab;
  55
  56        skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom);
  57
  58        if (!skb) {
  59                printk(KERN_ERR "%s: failed to allocate buffer "
  60                                "for addba request frame\n", sdata->dev->name);
  61                return;
  62        }
  63        skb_reserve(skb, local->hw.extra_tx_headroom);
  64        mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24);
  65        memset(mgmt, 0, 24);
  66        memcpy(mgmt->da, da, ETH_ALEN);
  67        memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN);
  68        if (sdata->vif.type == NL80211_IFTYPE_AP ||
  69            sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
  70                memcpy(mgmt->bssid, sdata->dev->dev_addr, ETH_ALEN);
  71        else if (sdata->vif.type == NL80211_IFTYPE_STATION)
  72                memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
  73
  74        mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
  75                                          IEEE80211_STYPE_ACTION);
  76
  77        skb_put(skb, 1 + sizeof(mgmt->u.action.u.addba_req));
  78
  79        mgmt->u.action.category = WLAN_CATEGORY_BACK;
  80        mgmt->u.action.u.addba_req.action_code = WLAN_ACTION_ADDBA_REQ;
  81
  82        mgmt->u.action.u.addba_req.dialog_token = dialog_token;
  83        capab = (u16)(1 << 1);          /* bit 1 aggregation policy */
  84        capab |= (u16)(tid << 2);       /* bit 5:2 TID number */
  85        capab |= (u16)(agg_size << 6);  /* bit 15:6 max size of aggergation */
  86
  87        mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab);
  88
  89        mgmt->u.action.u.addba_req.timeout = cpu_to_le16(timeout);
  90        mgmt->u.action.u.addba_req.start_seq_num =
  91                                        cpu_to_le16(start_seq_num << 4);
  92
  93        ieee80211_tx_skb(sdata, skb, 1);
  94}
  95
  96void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn)
  97{
  98        struct ieee80211_local *local = sdata->local;
  99        struct sk_buff *skb;
 100        struct ieee80211_bar *bar;
 101        u16 bar_control = 0;
 102
 103        skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom);
 104        if (!skb) {
 105                printk(KERN_ERR "%s: failed to allocate buffer for "
 106                        "bar frame\n", sdata->dev->name);
 107                return;
 108        }
 109        skb_reserve(skb, local->hw.extra_tx_headroom);
 110        bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar));
 111        memset(bar, 0, sizeof(*bar));
 112        bar->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL |
 113                                         IEEE80211_STYPE_BACK_REQ);
 114        memcpy(bar->ra, ra, ETH_ALEN);
 115        memcpy(bar->ta, sdata->dev->dev_addr, ETH_ALEN);
 116        bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL;
 117        bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA;
 118        bar_control |= (u16)(tid << 12);
 119        bar->control = cpu_to_le16(bar_control);
 120        bar->start_seq_num = cpu_to_le16(ssn);
 121
 122        ieee80211_tx_skb(sdata, skb, 0);
 123}
 124
 125static int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 126                                           enum ieee80211_back_parties initiator)
 127{
 128        struct ieee80211_local *local = sta->local;
 129        int ret;
 130        u8 *state;
 131
 132        state = &sta->ampdu_mlme.tid_state_tx[tid];
 133
 134        *state = HT_AGG_STATE_REQ_STOP_BA_MSK |
 135                (initiator << HT_AGG_STATE_INITIATOR_SHIFT);
 136
 137        ret = local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_STOP,
 138                                       &sta->sta, tid, NULL);
 139
 140        /* HW shall not deny going back to legacy */
 141        if (WARN_ON(ret)) {
 142                *state = HT_AGG_STATE_OPERATIONAL;
 143                /*
 144                 * We may have pending packets get stuck in this case...
 145                 * Not bothering with a workaround for now.
 146                 */
 147        }
 148
 149        return ret;
 150}
 151
 152/*
 153 * After sending add Block Ack request we activated a timer until
 154 * add Block Ack response will arrive from the recipient.
 155 * If this timer expires sta_addba_resp_timer_expired will be executed.
 156 */
 157static void sta_addba_resp_timer_expired(unsigned long data)
 158{
 159        /* not an elegant detour, but there is no choice as the timer passes
 160         * only one argument, and both sta_info and TID are needed, so init
 161         * flow in sta_info_create gives the TID as data, while the timer_to_id
 162         * array gives the sta through container_of */
 163        u16 tid = *(u8 *)data;
 164        struct sta_info *sta = container_of((void *)data,
 165                struct sta_info, timer_to_tid[tid]);
 166        u8 *state;
 167
 168        state = &sta->ampdu_mlme.tid_state_tx[tid];
 169
 170        /* check if the TID waits for addBA response */
 171        spin_lock_bh(&sta->lock);
 172        if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
 173                spin_unlock_bh(&sta->lock);
 174                *state = HT_AGG_STATE_IDLE;
 175#ifdef CONFIG_MAC80211_HT_DEBUG
 176                printk(KERN_DEBUG "timer expired on tid %d but we are not "
 177                                "expecting addBA response there", tid);
 178#endif
 179                return;
 180        }
 181
 182#ifdef CONFIG_MAC80211_HT_DEBUG
 183        printk(KERN_DEBUG "addBA response timer expired on tid %d\n", tid);
 184#endif
 185
 186        ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
 187        spin_unlock_bh(&sta->lock);
 188}
 189
 190static inline int ieee80211_ac_from_tid(int tid)
 191{
 192        return ieee802_1d_to_ac[tid & 7];
 193}
 194
 195int ieee80211_start_tx_ba_session(struct ieee80211_hw *hw, u8 *ra, u16 tid)
 196{
 197        struct ieee80211_local *local = hw_to_local(hw);
 198        struct sta_info *sta;
 199        struct ieee80211_sub_if_data *sdata;
 200        u8 *state;
 201        int ret = 0;
 202        u16 start_seq_num;
 203
 204        if (WARN_ON(!local->ops->ampdu_action))
 205                return -EINVAL;
 206
 207        if ((tid >= STA_TID_NUM) || !(hw->flags & IEEE80211_HW_AMPDU_AGGREGATION))
 208                return -EINVAL;
 209
 210#ifdef CONFIG_MAC80211_HT_DEBUG
 211        printk(KERN_DEBUG "Open BA session requested for %pM tid %u\n",
 212               ra, tid);
 213#endif /* CONFIG_MAC80211_HT_DEBUG */
 214
 215        rcu_read_lock();
 216
 217        sta = sta_info_get(local, ra);
 218        if (!sta) {
 219#ifdef CONFIG_MAC80211_HT_DEBUG
 220                printk(KERN_DEBUG "Could not find the station\n");
 221#endif
 222                ret = -ENOENT;
 223                goto unlock;
 224        }
 225
 226        /*
 227         * The aggregation code is not prepared to handle
 228         * anything but STA/AP due to the BSSID handling.
 229         * IBSS could work in the code but isn't supported
 230         * by drivers or the standard.
 231         */
 232        if (sta->sdata->vif.type != NL80211_IFTYPE_STATION &&
 233            sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
 234            sta->sdata->vif.type != NL80211_IFTYPE_AP) {
 235                ret = -EINVAL;
 236                goto unlock;
 237        }
 238
 239        if (test_sta_flags(sta, WLAN_STA_SUSPEND)) {
 240#ifdef CONFIG_MAC80211_HT_DEBUG
 241                printk(KERN_DEBUG "Suspend in progress. "
 242                       "Denying BA session request\n");
 243#endif
 244                ret = -EINVAL;
 245                goto unlock;
 246        }
 247
 248        spin_lock_bh(&sta->lock);
 249        spin_lock(&local->ampdu_lock);
 250
 251        sdata = sta->sdata;
 252
 253        /* we have tried too many times, receiver does not want A-MPDU */
 254        if (sta->ampdu_mlme.addba_req_num[tid] > HT_AGG_MAX_RETRIES) {
 255                ret = -EBUSY;
 256                goto err_unlock_sta;
 257        }
 258
 259        state = &sta->ampdu_mlme.tid_state_tx[tid];
 260        /* check if the TID is not in aggregation flow already */
 261        if (*state != HT_AGG_STATE_IDLE) {
 262#ifdef CONFIG_MAC80211_HT_DEBUG
 263                printk(KERN_DEBUG "BA request denied - session is not "
 264                                 "idle on tid %u\n", tid);
 265#endif /* CONFIG_MAC80211_HT_DEBUG */
 266                ret = -EAGAIN;
 267                goto err_unlock_sta;
 268        }
 269
 270        /*
 271         * While we're asking the driver about the aggregation,
 272         * stop the AC queue so that we don't have to worry
 273         * about frames that came in while we were doing that,
 274         * which would require us to put them to the AC pending
 275         * afterwards which just makes the code more complex.
 276         */
 277        ieee80211_stop_queue_by_reason(
 278                &local->hw, ieee80211_ac_from_tid(tid),
 279                IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
 280
 281        /* prepare A-MPDU MLME for Tx aggregation */
 282        sta->ampdu_mlme.tid_tx[tid] =
 283                        kmalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC);
 284        if (!sta->ampdu_mlme.tid_tx[tid]) {
 285#ifdef CONFIG_MAC80211_HT_DEBUG
 286                if (net_ratelimit())
 287                        printk(KERN_ERR "allocate tx mlme to tid %d failed\n",
 288                                        tid);
 289#endif
 290                ret = -ENOMEM;
 291                goto err_wake_queue;
 292        }
 293
 294        skb_queue_head_init(&sta->ampdu_mlme.tid_tx[tid]->pending);
 295
 296        /* Tx timer */
 297        sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.function =
 298                        sta_addba_resp_timer_expired;
 299        sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.data =
 300                        (unsigned long)&sta->timer_to_tid[tid];
 301        init_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
 302
 303        /* Ok, the Addba frame hasn't been sent yet, but if the driver calls the
 304         * call back right away, it must see that the flow has begun */
 305        *state |= HT_ADDBA_REQUESTED_MSK;
 306
 307        start_seq_num = sta->tid_seq[tid];
 308
 309        ret = local->ops->ampdu_action(hw, IEEE80211_AMPDU_TX_START,
 310                                       &sta->sta, tid, &start_seq_num);
 311
 312        if (ret) {
 313#ifdef CONFIG_MAC80211_HT_DEBUG
 314                printk(KERN_DEBUG "BA request denied - HW unavailable for"
 315                                        " tid %d\n", tid);
 316#endif /* CONFIG_MAC80211_HT_DEBUG */
 317                *state = HT_AGG_STATE_IDLE;
 318                goto err_free;
 319        }
 320
 321        /* Driver vetoed or OKed, but we can take packets again now */
 322        ieee80211_wake_queue_by_reason(
 323                &local->hw, ieee80211_ac_from_tid(tid),
 324                IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
 325
 326        spin_unlock(&local->ampdu_lock);
 327        spin_unlock_bh(&sta->lock);
 328
 329        /* send an addBA request */
 330        sta->ampdu_mlme.dialog_token_allocator++;
 331        sta->ampdu_mlme.tid_tx[tid]->dialog_token =
 332                        sta->ampdu_mlme.dialog_token_allocator;
 333        sta->ampdu_mlme.tid_tx[tid]->ssn = start_seq_num;
 334
 335        ieee80211_send_addba_request(sta->sdata, ra, tid,
 336                         sta->ampdu_mlme.tid_tx[tid]->dialog_token,
 337                         sta->ampdu_mlme.tid_tx[tid]->ssn,
 338                         0x40, 5000);
 339        /* activate the timer for the recipient's addBA response */
 340        sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer.expires =
 341                                jiffies + ADDBA_RESP_INTERVAL;
 342        add_timer(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
 343#ifdef CONFIG_MAC80211_HT_DEBUG
 344        printk(KERN_DEBUG "activated addBA response timer on tid %d\n", tid);
 345#endif
 346        goto unlock;
 347
 348 err_free:
 349        kfree(sta->ampdu_mlme.tid_tx[tid]);
 350        sta->ampdu_mlme.tid_tx[tid] = NULL;
 351 err_wake_queue:
 352        ieee80211_wake_queue_by_reason(
 353                &local->hw, ieee80211_ac_from_tid(tid),
 354                IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
 355 err_unlock_sta:
 356        spin_unlock(&local->ampdu_lock);
 357        spin_unlock_bh(&sta->lock);
 358 unlock:
 359        rcu_read_unlock();
 360        return ret;
 361}
 362EXPORT_SYMBOL(ieee80211_start_tx_ba_session);
 363
 364/*
 365 * splice packets from the STA's pending to the local pending,
 366 * requires a call to ieee80211_agg_splice_finish and holding
 367 * local->ampdu_lock across both calls.
 368 */
 369static void ieee80211_agg_splice_packets(struct ieee80211_local *local,
 370                                         struct sta_info *sta, u16 tid)
 371{
 372        unsigned long flags;
 373        u16 queue = ieee80211_ac_from_tid(tid);
 374
 375        ieee80211_stop_queue_by_reason(
 376                &local->hw, queue,
 377                IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
 378
 379        if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) {
 380                spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
 381                /* mark queue as pending, it is stopped already */
 382                __set_bit(IEEE80211_QUEUE_STOP_REASON_PENDING,
 383                          &local->queue_stop_reasons[queue]);
 384                /* copy over remaining packets */
 385                skb_queue_splice_tail_init(
 386                        &sta->ampdu_mlme.tid_tx[tid]->pending,
 387                        &local->pending[queue]);
 388                spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
 389        }
 390}
 391
 392static void ieee80211_agg_splice_finish(struct ieee80211_local *local,
 393                                        struct sta_info *sta, u16 tid)
 394{
 395        u16 queue = ieee80211_ac_from_tid(tid);
 396
 397        ieee80211_wake_queue_by_reason(
 398                &local->hw, queue,
 399                IEEE80211_QUEUE_STOP_REASON_AGGREGATION);
 400}
 401
 402/* caller must hold sta->lock */
 403static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
 404                                         struct sta_info *sta, u16 tid)
 405{
 406#ifdef CONFIG_MAC80211_HT_DEBUG
 407        printk(KERN_DEBUG "Aggregation is on for tid %d \n", tid);
 408#endif
 409
 410        spin_lock(&local->ampdu_lock);
 411        ieee80211_agg_splice_packets(local, sta, tid);
 412        /*
 413         * NB: we rely on sta->lock being taken in the TX
 414         * processing here when adding to the pending queue,
 415         * otherwise we could only change the state of the
 416         * session to OPERATIONAL _here_.
 417         */
 418        ieee80211_agg_splice_finish(local, sta, tid);
 419        spin_unlock(&local->ampdu_lock);
 420
 421        local->ops->ampdu_action(&local->hw, IEEE80211_AMPDU_TX_OPERATIONAL,
 422                                 &sta->sta, tid, NULL);
 423}
 424
 425void ieee80211_start_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u16 tid)
 426{
 427        struct ieee80211_local *local = hw_to_local(hw);
 428        struct sta_info *sta;
 429        u8 *state;
 430
 431        if (tid >= STA_TID_NUM) {
 432#ifdef CONFIG_MAC80211_HT_DEBUG
 433                printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
 434                                tid, STA_TID_NUM);
 435#endif
 436                return;
 437        }
 438
 439        rcu_read_lock();
 440        sta = sta_info_get(local, ra);
 441        if (!sta) {
 442                rcu_read_unlock();
 443#ifdef CONFIG_MAC80211_HT_DEBUG
 444                printk(KERN_DEBUG "Could not find station: %pM\n", ra);
 445#endif
 446                return;
 447        }
 448
 449        state = &sta->ampdu_mlme.tid_state_tx[tid];
 450        spin_lock_bh(&sta->lock);
 451
 452        if (WARN_ON(!(*state & HT_ADDBA_REQUESTED_MSK))) {
 453#ifdef CONFIG_MAC80211_HT_DEBUG
 454                printk(KERN_DEBUG "addBA was not requested yet, state is %d\n",
 455                                *state);
 456#endif
 457                spin_unlock_bh(&sta->lock);
 458                rcu_read_unlock();
 459                return;
 460        }
 461
 462        if (WARN_ON(*state & HT_ADDBA_DRV_READY_MSK))
 463                goto out;
 464
 465        *state |= HT_ADDBA_DRV_READY_MSK;
 466
 467        if (*state == HT_AGG_STATE_OPERATIONAL)
 468                ieee80211_agg_tx_operational(local, sta, tid);
 469
 470 out:
 471        spin_unlock_bh(&sta->lock);
 472        rcu_read_unlock();
 473}
 474EXPORT_SYMBOL(ieee80211_start_tx_ba_cb);
 475
 476void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
 477                                      const u8 *ra, u16 tid)
 478{
 479        struct ieee80211_local *local = hw_to_local(hw);
 480        struct ieee80211_ra_tid *ra_tid;
 481        struct sk_buff *skb = dev_alloc_skb(0);
 482
 483        if (unlikely(!skb)) {
 484#ifdef CONFIG_MAC80211_HT_DEBUG
 485                if (net_ratelimit())
 486                        printk(KERN_WARNING "%s: Not enough memory, "
 487                               "dropping start BA session", skb->dev->name);
 488#endif
 489                return;
 490        }
 491        ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
 492        memcpy(&ra_tid->ra, ra, ETH_ALEN);
 493        ra_tid->tid = tid;
 494
 495        skb->pkt_type = IEEE80211_ADDBA_MSG;
 496        skb_queue_tail(&local->skb_queue, skb);
 497        tasklet_schedule(&local->tasklet);
 498}
 499EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
 500
 501int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 502                                   enum ieee80211_back_parties initiator)
 503{
 504        u8 *state;
 505        int ret;
 506
 507        /* check if the TID is in aggregation */
 508        state = &sta->ampdu_mlme.tid_state_tx[tid];
 509        spin_lock_bh(&sta->lock);
 510
 511        if (*state != HT_AGG_STATE_OPERATIONAL) {
 512                ret = -ENOENT;
 513                goto unlock;
 514        }
 515
 516#ifdef CONFIG_MAC80211_HT_DEBUG
 517        printk(KERN_DEBUG "Tx BA session stop requested for %pM tid %u\n",
 518               sta->sta.addr, tid);
 519#endif /* CONFIG_MAC80211_HT_DEBUG */
 520
 521        ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator);
 522
 523 unlock:
 524        spin_unlock_bh(&sta->lock);
 525        return ret;
 526}
 527
 528int ieee80211_stop_tx_ba_session(struct ieee80211_hw *hw,
 529                                 u8 *ra, u16 tid,
 530                                 enum ieee80211_back_parties initiator)
 531{
 532        struct ieee80211_local *local = hw_to_local(hw);
 533        struct sta_info *sta;
 534        int ret = 0;
 535
 536        if (WARN_ON(!local->ops->ampdu_action))
 537                return -EINVAL;
 538
 539        if (tid >= STA_TID_NUM)
 540                return -EINVAL;
 541
 542        rcu_read_lock();
 543        sta = sta_info_get(local, ra);
 544        if (!sta) {
 545                rcu_read_unlock();
 546                return -ENOENT;
 547        }
 548
 549        ret = __ieee80211_stop_tx_ba_session(sta, tid, initiator);
 550        rcu_read_unlock();
 551        return ret;
 552}
 553EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
 554
 555void ieee80211_stop_tx_ba_cb(struct ieee80211_hw *hw, u8 *ra, u8 tid)
 556{
 557        struct ieee80211_local *local = hw_to_local(hw);
 558        struct sta_info *sta;
 559        u8 *state;
 560
 561        if (tid >= STA_TID_NUM) {
 562#ifdef CONFIG_MAC80211_HT_DEBUG
 563                printk(KERN_DEBUG "Bad TID value: tid = %d (>= %d)\n",
 564                                tid, STA_TID_NUM);
 565#endif
 566                return;
 567        }
 568
 569#ifdef CONFIG_MAC80211_HT_DEBUG
 570        printk(KERN_DEBUG "Stopping Tx BA session for %pM tid %d\n",
 571               ra, tid);
 572#endif /* CONFIG_MAC80211_HT_DEBUG */
 573
 574        rcu_read_lock();
 575        sta = sta_info_get(local, ra);
 576        if (!sta) {
 577#ifdef CONFIG_MAC80211_HT_DEBUG
 578                printk(KERN_DEBUG "Could not find station: %pM\n", ra);
 579#endif
 580                rcu_read_unlock();
 581                return;
 582        }
 583        state = &sta->ampdu_mlme.tid_state_tx[tid];
 584
 585        /* NOTE: no need to use sta->lock in this state check, as
 586         * ieee80211_stop_tx_ba_session will let only one stop call to
 587         * pass through per sta/tid
 588         */
 589        if ((*state & HT_AGG_STATE_REQ_STOP_BA_MSK) == 0) {
 590#ifdef CONFIG_MAC80211_HT_DEBUG
 591                printk(KERN_DEBUG "unexpected callback to A-MPDU stop\n");
 592#endif
 593                rcu_read_unlock();
 594                return;
 595        }
 596
 597        if (*state & HT_AGG_STATE_INITIATOR_MSK)
 598                ieee80211_send_delba(sta->sdata, ra, tid,
 599                        WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
 600
 601        spin_lock_bh(&sta->lock);
 602        spin_lock(&local->ampdu_lock);
 603
 604        ieee80211_agg_splice_packets(local, sta, tid);
 605
 606        *state = HT_AGG_STATE_IDLE;
 607        /* from now on packets are no longer put onto sta->pending */
 608        sta->ampdu_mlme.addba_req_num[tid] = 0;
 609        kfree(sta->ampdu_mlme.tid_tx[tid]);
 610        sta->ampdu_mlme.tid_tx[tid] = NULL;
 611
 612        ieee80211_agg_splice_finish(local, sta, tid);
 613
 614        spin_unlock(&local->ampdu_lock);
 615        spin_unlock_bh(&sta->lock);
 616
 617        rcu_read_unlock();
 618}
 619EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb);
 620
 621void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_hw *hw,
 622                                     const u8 *ra, u16 tid)
 623{
 624        struct ieee80211_local *local = hw_to_local(hw);
 625        struct ieee80211_ra_tid *ra_tid;
 626        struct sk_buff *skb = dev_alloc_skb(0);
 627
 628        if (unlikely(!skb)) {
 629#ifdef CONFIG_MAC80211_HT_DEBUG
 630                if (net_ratelimit())
 631                        printk(KERN_WARNING "%s: Not enough memory, "
 632                               "dropping stop BA session", skb->dev->name);
 633#endif
 634                return;
 635        }
 636        ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
 637        memcpy(&ra_tid->ra, ra, ETH_ALEN);
 638        ra_tid->tid = tid;
 639
 640        skb->pkt_type = IEEE80211_DELBA_MSG;
 641        skb_queue_tail(&local->skb_queue, skb);
 642        tasklet_schedule(&local->tasklet);
 643}
 644EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
 645
 646
 647void ieee80211_process_addba_resp(struct ieee80211_local *local,
 648                                  struct sta_info *sta,
 649                                  struct ieee80211_mgmt *mgmt,
 650                                  size_t len)
 651{
 652        u16 capab, tid;
 653        u8 *state;
 654
 655        capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab);
 656        tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2;
 657
 658        state = &sta->ampdu_mlme.tid_state_tx[tid];
 659
 660        spin_lock_bh(&sta->lock);
 661
 662        if (!(*state & HT_ADDBA_REQUESTED_MSK)) {
 663                spin_unlock_bh(&sta->lock);
 664                return;
 665        }
 666
 667        if (mgmt->u.action.u.addba_resp.dialog_token !=
 668                sta->ampdu_mlme.tid_tx[tid]->dialog_token) {
 669                spin_unlock_bh(&sta->lock);
 670#ifdef CONFIG_MAC80211_HT_DEBUG
 671                printk(KERN_DEBUG "wrong addBA response token, tid %d\n", tid);
 672#endif /* CONFIG_MAC80211_HT_DEBUG */
 673                return;
 674        }
 675
 676        del_timer_sync(&sta->ampdu_mlme.tid_tx[tid]->addba_resp_timer);
 677#ifdef CONFIG_MAC80211_HT_DEBUG
 678        printk(KERN_DEBUG "switched off addBA timer for tid %d \n", tid);
 679#endif /* CONFIG_MAC80211_HT_DEBUG */
 680        if (le16_to_cpu(mgmt->u.action.u.addba_resp.status)
 681                        == WLAN_STATUS_SUCCESS) {
 682                u8 curstate = *state;
 683
 684                *state |= HT_ADDBA_RECEIVED_MSK;
 685
 686                if (*state != curstate && *state == HT_AGG_STATE_OPERATIONAL)
 687                        ieee80211_agg_tx_operational(local, sta, tid);
 688
 689                sta->ampdu_mlme.addba_req_num[tid] = 0;
 690        } else {
 691                sta->ampdu_mlme.addba_req_num[tid]++;
 692                ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR);
 693        }
 694        spin_unlock_bh(&sta->lock);
 695}
 696