linux/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2010 Broadcom Corporation
   3 *
   4 * Permission to use, copy, modify, and/or distribute this software for any
   5 * purpose with or without fee is hereby granted, provided that the above
   6 * copyright notice and this permission notice appear in all copies.
   7 *
   8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  15 */
  16#include <net/mac80211.h>
  17
  18#include "rate.h"
  19#include "scb.h"
  20#include "phy/phy_hal.h"
  21#include "antsel.h"
  22#include "main.h"
  23#include "ampdu.h"
  24#include "debug.h"
  25#include "brcms_trace_events.h"
  26
  27/* max number of mpdus in an ampdu */
  28#define AMPDU_MAX_MPDU                  32
  29/* max number of mpdus in an ampdu to a legacy */
  30#define AMPDU_NUM_MPDU_LEGACY           16
  31/* max Tx ba window size (in pdu) */
  32#define AMPDU_TX_BA_MAX_WSIZE           64
  33/* default Tx ba window size (in pdu) */
  34#define AMPDU_TX_BA_DEF_WSIZE           64
  35/* default Rx ba window size (in pdu) */
  36#define AMPDU_RX_BA_DEF_WSIZE           64
  37/* max Rx ba window size (in pdu) */
  38#define AMPDU_RX_BA_MAX_WSIZE           64
  39/* max dur of tx ampdu (in msec) */
  40#define AMPDU_MAX_DUR                   5
  41/* default tx retry limit */
  42#define AMPDU_DEF_RETRY_LIMIT           5
  43/* default tx retry limit at reg rate */
  44#define AMPDU_DEF_RR_RETRY_LIMIT        2
  45/* default ffpld reserved bytes */
  46#define AMPDU_DEF_FFPLD_RSVD            2048
  47/* # of inis to be freed on detach */
  48#define AMPDU_INI_FREE                  10
  49/* max # of mpdus released at a time */
  50#define AMPDU_SCB_MAX_RELEASE           20
  51
  52#define NUM_FFPLD_FIFO 4        /* number of fifo concerned by pre-loading */
  53#define FFPLD_TX_MAX_UNFL   200 /* default value of the average number of ampdu
  54                                 * without underflows
  55                                 */
  56#define FFPLD_MPDU_SIZE 1800    /* estimate of maximum mpdu size */
  57#define FFPLD_MAX_MCS 23        /* we don't deal with mcs 32 */
  58#define FFPLD_PLD_INCR 1000     /* increments in bytes */
  59#define FFPLD_MAX_AMPDU_CNT 5000        /* maximum number of ampdu we
  60                                         * accumulate between resets.
  61                                         */
  62
  63#define AMPDU_DELIMITER_LEN     4
  64
  65/* max allowed number of mpdus in an ampdu (2 streams) */
  66#define AMPDU_NUM_MPDU          16
  67
  68#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
  69
  70/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
  71#define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
  72        AMPDU_DELIMITER_LEN + 3\
  73        + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
  74
  75/* modulo add/sub, bound = 2^k */
  76#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
  77#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
  78
  79/* structure to hold tx fifo information and pre-loading state
  80 * counters specific to tx underflows of ampdus
  81 * some counters might be redundant with the ones in wlc or ampdu structures.
  82 * This allows to maintain a specific state independently of
  83 * how often and/or when the wlc counters are updated.
  84 *
  85 * ampdu_pld_size: number of bytes to be pre-loaded
  86 * mcs2ampdu_table: per-mcs max # of mpdus in an ampdu
  87 * prev_txfunfl: num of underflows last read from the HW macstats counter
  88 * accum_txfunfl: num of underflows since we modified pld params
  89 * accum_txampdu: num of tx ampdu since we modified pld params
  90 * prev_txampdu: previous reading of tx ampdu
  91 * dmaxferrate: estimated dma avg xfer rate in kbits/sec
  92 */
  93struct brcms_fifo_info {
  94        u16 ampdu_pld_size;
  95        u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];
  96        u16 prev_txfunfl;
  97        u32 accum_txfunfl;
  98        u32 accum_txampdu;
  99        u32 prev_txampdu;
 100        u32 dmaxferrate;
 101};
 102
 103/* AMPDU module specific state
 104 *
 105 * wlc: pointer to main wlc structure
 106 * scb_handle: scb cubby handle to retrieve data from scb
 107 * ini_enable: per-tid initiator enable/disable of ampdu
 108 * ba_tx_wsize: Tx ba window size (in pdu)
 109 * ba_rx_wsize: Rx ba window size (in pdu)
 110 * retry_limit: mpdu transmit retry limit
 111 * rr_retry_limit: mpdu transmit retry limit at regular rate
 112 * retry_limit_tid: per-tid mpdu transmit retry limit
 113 * rr_retry_limit_tid: per-tid mpdu transmit retry limit at regular rate
 114 * mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec
 115 * max_pdu: max pdus allowed in ampdu
 116 * dur: max duration of an ampdu (in msec)
 117 * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes
 118 * ffpld_rsvd: number of bytes to reserve for preload
 119 * max_txlen: max size of ampdu per mcs, bw and sgi
 120 * mfbr: enable multiple fallback rate
 121 * tx_max_funl: underflows should be kept such that
 122 *              (tx_max_funfl*underflows) < tx frames
 123 * fifo_tb: table of fifo infos
 124 */
 125struct ampdu_info {
 126        struct brcms_c_info *wlc;
 127        int scb_handle;
 128        u8 ini_enable[AMPDU_MAX_SCB_TID];
 129        u8 ba_tx_wsize;
 130        u8 ba_rx_wsize;
 131        u8 retry_limit;
 132        u8 rr_retry_limit;
 133        u8 retry_limit_tid[AMPDU_MAX_SCB_TID];
 134        u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
 135        u8 mpdu_density;
 136        s8 max_pdu;
 137        u8 dur;
 138        u8 rx_factor;
 139        u32 ffpld_rsvd;
 140        u32 max_txlen[MCS_TABLE_SIZE][2][2];
 141        bool mfbr;
 142        u32 tx_max_funl;
 143        struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO];
 144};
 145
 146/* used for flushing ampdu packets */
 147struct cb_del_ampdu_pars {
 148        struct ieee80211_sta *sta;
 149        u16 tid;
 150};
 151
 152static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
 153{
 154        u32 rate, mcs;
 155
 156        for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
 157                /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
 158                /* 20MHz, No SGI */
 159                rate = mcs_2_rate(mcs, false, false);
 160                ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
 161                /* 40 MHz, No SGI */
 162                rate = mcs_2_rate(mcs, true, false);
 163                ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
 164                /* 20MHz, SGI */
 165                rate = mcs_2_rate(mcs, false, true);
 166                ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
 167                /* 40 MHz, SGI */
 168                rate = mcs_2_rate(mcs, true, true);
 169                ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
 170        }
 171}
 172
 173static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
 174{
 175        if (BRCMS_PHY_11N_CAP(ampdu->wlc->band))
 176                return true;
 177        else
 178                return false;
 179}
 180
 181static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
 182{
 183        struct brcms_c_info *wlc = ampdu->wlc;
 184        struct bcma_device *core = wlc->hw->d11core;
 185
 186        wlc->pub->_ampdu = false;
 187
 188        if (on) {
 189                if (!(wlc->pub->_n_enab & SUPPORT_11N)) {
 190                        brcms_err(core, "wl%d: driver not nmode enabled\n",
 191                                  wlc->pub->unit);
 192                        return -ENOTSUPP;
 193                }
 194                if (!brcms_c_ampdu_cap(ampdu)) {
 195                        brcms_err(core, "wl%d: device not ampdu capable\n",
 196                                  wlc->pub->unit);
 197                        return -ENOTSUPP;
 198                }
 199                wlc->pub->_ampdu = on;
 200        }
 201
 202        return 0;
 203}
 204
 205static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
 206{
 207        int i, j;
 208        struct brcms_fifo_info *fifo;
 209
 210        for (j = 0; j < NUM_FFPLD_FIFO; j++) {
 211                fifo = (ampdu->fifo_tb + j);
 212                fifo->ampdu_pld_size = 0;
 213                for (i = 0; i <= FFPLD_MAX_MCS; i++)
 214                        fifo->mcs2ampdu_table[i] = 255;
 215                fifo->dmaxferrate = 0;
 216                fifo->accum_txampdu = 0;
 217                fifo->prev_txfunfl = 0;
 218                fifo->accum_txfunfl = 0;
 219
 220        }
 221}
 222
 223struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
 224{
 225        struct ampdu_info *ampdu;
 226        int i;
 227
 228        ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
 229        if (!ampdu)
 230                return NULL;
 231
 232        ampdu->wlc = wlc;
 233
 234        for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
 235                ampdu->ini_enable[i] = true;
 236        /* Disable ampdu for VO by default */
 237        ampdu->ini_enable[PRIO_8021D_VO] = false;
 238        ampdu->ini_enable[PRIO_8021D_NC] = false;
 239
 240        /* Disable ampdu for BK by default since not enough fifo space */
 241        ampdu->ini_enable[PRIO_8021D_NONE] = false;
 242        ampdu->ini_enable[PRIO_8021D_BK] = false;
 243
 244        ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
 245        ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
 246        ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
 247        ampdu->max_pdu = AUTO;
 248        ampdu->dur = AMPDU_MAX_DUR;
 249
 250        ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
 251        /*
 252         * bump max ampdu rcv size to 64k for all 11n
 253         * devices except 4321A0 and 4321A1
 254         */
 255        if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
 256                ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
 257        else
 258                ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
 259        ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
 260        ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
 261
 262        for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
 263                ampdu->retry_limit_tid[i] = ampdu->retry_limit;
 264                ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
 265        }
 266
 267        brcms_c_scb_ampdu_update_max_txlen(ampdu, ampdu->dur);
 268        ampdu->mfbr = false;
 269        /* try to set ampdu to the default value */
 270        brcms_c_ampdu_set(ampdu, wlc->pub->_ampdu);
 271
 272        ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
 273        brcms_c_ffpld_init(ampdu);
 274
 275        return ampdu;
 276}
 277
 278void brcms_c_ampdu_detach(struct ampdu_info *ampdu)
 279{
 280        kfree(ampdu);
 281}
 282
 283static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
 284                                            struct scb *scb)
 285{
 286        struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
 287        int i;
 288
 289        scb_ampdu->max_pdu = AMPDU_NUM_MPDU;
 290
 291        /* go back to legacy size if some preloading is occurring */
 292        for (i = 0; i < NUM_FFPLD_FIFO; i++) {
 293                if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
 294                        scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
 295        }
 296
 297        /* apply user override */
 298        if (ampdu->max_pdu != AUTO)
 299                scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
 300
 301        scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu,
 302                                   AMPDU_SCB_MAX_RELEASE);
 303
 304        if (scb_ampdu->max_rx_ampdu_bytes)
 305                scb_ampdu->release = min_t(u8, scb_ampdu->release,
 306                        scb_ampdu->max_rx_ampdu_bytes / 1600);
 307
 308        scb_ampdu->release = min(scb_ampdu->release,
 309                                 ampdu->fifo_tb[TX_AC_BE_FIFO].
 310                                 mcs2ampdu_table[FFPLD_MAX_MCS]);
 311}
 312
 313static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu)
 314{
 315        brcms_c_scb_ampdu_update_config(ampdu, &ampdu->wlc->pri_scb);
 316}
 317
 318static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
 319{
 320        int i;
 321        u32 phy_rate, dma_rate, tmp;
 322        u8 max_mpdu;
 323        struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f);
 324
 325        /* recompute the dma rate */
 326        /* note : we divide/multiply by 100 to avoid integer overflows */
 327        max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
 328                         AMPDU_NUM_MPDU_LEGACY);
 329        phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
 330        dma_rate =
 331            (((phy_rate / 100) *
 332              (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
 333             / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
 334        fifo->dmaxferrate = dma_rate;
 335
 336        /* fill up the mcs2ampdu table; do not recalc the last mcs */
 337        dma_rate = dma_rate >> 7;
 338        for (i = 0; i < FFPLD_MAX_MCS; i++) {
 339                /* shifting to keep it within integer range */
 340                phy_rate = mcs_2_rate(i, true, false) >> 7;
 341                if (phy_rate > dma_rate) {
 342                        tmp = ((fifo->ampdu_pld_size * phy_rate) /
 343                               ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
 344                        tmp = min_t(u32, tmp, 255);
 345                        fifo->mcs2ampdu_table[i] = (u8) tmp;
 346                }
 347        }
 348}
 349
 350/* evaluate the dma transfer rate using the tx underflows as feedback.
 351 * If necessary, increase tx fifo preloading. If not enough,
 352 * decrease maximum ampdu size for each mcs till underflows stop
 353 * Return 1 if pre-loading not active, -1 if not an underflow event,
 354 * 0 if pre-loading module took care of the event.
 355 */
 356static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
 357{
 358        struct ampdu_info *ampdu = wlc->ampdu;
 359        u32 phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
 360        u32 txunfl_ratio;
 361        u8 max_mpdu;
 362        u32 current_ampdu_cnt = 0;
 363        u16 max_pld_size;
 364        u32 new_txunfl;
 365        struct brcms_fifo_info *fifo = (ampdu->fifo_tb + fid);
 366        uint xmtfifo_sz;
 367        u16 cur_txunfl;
 368
 369        /* return if we got here for a different reason than underflows */
 370        cur_txunfl = brcms_b_read_shm(wlc->hw,
 371                                      M_UCODE_MACSTAT +
 372                                      offsetof(struct macstat, txfunfl[fid]));
 373        new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
 374        if (new_txunfl == 0) {
 375                brcms_dbg_ht(wlc->hw->d11core,
 376                             "TX status FRAG set but no tx underflows\n");
 377                return -1;
 378        }
 379        fifo->prev_txfunfl = cur_txunfl;
 380
 381        if (!ampdu->tx_max_funl)
 382                return 1;
 383
 384        /* check if fifo is big enough */
 385        if (brcms_b_xmtfifo_sz_get(wlc->hw, fid, &xmtfifo_sz))
 386                return -1;
 387
 388        if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
 389                return 1;
 390
 391        max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
 392        fifo->accum_txfunfl += new_txunfl;
 393
 394        /* we need to wait for at least 10 underflows */
 395        if (fifo->accum_txfunfl < 10)
 396                return 0;
 397
 398        brcms_dbg_ht(wlc->hw->d11core, "ampdu_count %d  tx_underflows %d\n",
 399                     current_ampdu_cnt, fifo->accum_txfunfl);
 400
 401        /*
 402           compute the current ratio of tx unfl per ampdu.
 403           When the current ampdu count becomes too
 404           big while the ratio remains small, we reset
 405           the current count in order to not
 406           introduce too big of a latency in detecting a
 407           large amount of tx underflows later.
 408         */
 409
 410        txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
 411
 412        if (txunfl_ratio > ampdu->tx_max_funl) {
 413                if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT)
 414                        fifo->accum_txfunfl = 0;
 415
 416                return 0;
 417        }
 418        max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
 419                         AMPDU_NUM_MPDU_LEGACY);
 420
 421        /* In case max value max_pdu is already lower than
 422           the fifo depth, there is nothing more we can do.
 423         */
 424
 425        if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
 426                fifo->accum_txfunfl = 0;
 427                return 0;
 428        }
 429
 430        if (fifo->ampdu_pld_size < max_pld_size) {
 431
 432                /* increment by TX_FIFO_PLD_INC bytes */
 433                fifo->ampdu_pld_size += FFPLD_PLD_INCR;
 434                if (fifo->ampdu_pld_size > max_pld_size)
 435                        fifo->ampdu_pld_size = max_pld_size;
 436
 437                /* update scb release size */
 438                brcms_c_scb_ampdu_update_config_all(ampdu);
 439
 440                /*
 441                 * compute a new dma xfer rate for max_mpdu @ max mcs.
 442                 * This is the minimum dma rate that can achieve no
 443                 * underflow condition for the current mpdu size.
 444                 *
 445                 * note : we divide/multiply by 100 to avoid integer overflows
 446                 */
 447                fifo->dmaxferrate =
 448                    (((phy_rate / 100) *
 449                      (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
 450                     / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
 451
 452                brcms_dbg_ht(wlc->hw->d11core,
 453                             "DMA estimated transfer rate %d; "
 454                             "pre-load size %d\n",
 455                             fifo->dmaxferrate, fifo->ampdu_pld_size);
 456        } else {
 457
 458                /* decrease ampdu size */
 459                if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
 460                        if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
 461                                fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
 462                                    AMPDU_NUM_MPDU_LEGACY - 1;
 463                        else
 464                                fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
 465
 466                        /* recompute the table */
 467                        brcms_c_ffpld_calc_mcs2ampdu_table(ampdu, fid);
 468
 469                        /* update scb release size */
 470                        brcms_c_scb_ampdu_update_config_all(ampdu);
 471                }
 472        }
 473        fifo->accum_txfunfl = 0;
 474        return 0;
 475}
 476
 477void
 478brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
 479        u8 ba_wsize,            /* negotiated ba window size (in pdu) */
 480        uint max_rx_ampdu_bytes) /* from ht_cap in beacon */
 481{
 482        struct scb_ampdu *scb_ampdu;
 483        struct scb_ampdu_tid_ini *ini;
 484        struct ampdu_info *ampdu = wlc->ampdu;
 485        struct scb *scb = &wlc->pri_scb;
 486        scb_ampdu = &scb->scb_ampdu;
 487
 488        if (!ampdu->ini_enable[tid]) {
 489                brcms_err(wlc->hw->d11core, "%s: Rejecting tid %d\n",
 490                          __func__, tid);
 491                return;
 492        }
 493
 494        ini = &scb_ampdu->ini[tid];
 495        ini->tid = tid;
 496        ini->scb = scb_ampdu->scb;
 497        ini->ba_wsize = ba_wsize;
 498        scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
 499}
 500
 501void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
 502                                 struct brcms_c_info *wlc)
 503{
 504        session->wlc = wlc;
 505        skb_queue_head_init(&session->skb_list);
 506        session->max_ampdu_len = 0;    /* determined from first MPDU */
 507        session->max_ampdu_frames = 0; /* determined from first MPDU */
 508        session->ampdu_len = 0;
 509        session->dma_len = 0;
 510}
 511
 512/*
 513 * Preps the given packet for AMPDU based on the session data. If the
 514 * frame cannot be accomodated in the current session, -ENOSPC is
 515 * returned.
 516 */
 517int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
 518                            struct sk_buff *p)
 519{
 520        struct brcms_c_info *wlc = session->wlc;
 521        struct ampdu_info *ampdu = wlc->ampdu;
 522        struct scb *scb = &wlc->pri_scb;
 523        struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
 524        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
 525        struct ieee80211_tx_rate *txrate = tx_info->status.rates;
 526        struct d11txh *txh = (struct d11txh *)p->data;
 527        unsigned ampdu_frames;
 528        u8 ndelim, tid;
 529        u8 *plcp;
 530        uint len;
 531        u16 mcl;
 532        bool fbr_iscck;
 533        bool rr;
 534
 535        ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
 536        plcp = (u8 *)(txh + 1);
 537        fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
 538        len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
 539                          BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
 540        len = roundup(len, 4) + (ndelim + 1) * AMPDU_DELIMITER_LEN;
 541
 542        ampdu_frames = skb_queue_len(&session->skb_list);
 543        if (ampdu_frames != 0) {
 544                struct sk_buff *first;
 545
 546                if (ampdu_frames + 1 > session->max_ampdu_frames ||
 547                    session->ampdu_len + len > session->max_ampdu_len)
 548                        return -ENOSPC;
 549
 550                /*
 551                 * We aren't really out of space if the new frame is of
 552                 * a different priority, but we want the same behaviour
 553                 * so return -ENOSPC anyway.
 554                 *
 555                 * XXX: The old AMPDU code did this, but is it really
 556                 * necessary?
 557                 */
 558                first = skb_peek(&session->skb_list);
 559                if (p->priority != first->priority)
 560                        return -ENOSPC;
 561        }
 562
 563        /*
 564         * Now that we're sure this frame can be accomodated, update the
 565         * session information.
 566         */
 567        session->ampdu_len += len;
 568        session->dma_len += p->len;
 569
 570        tid = (u8)p->priority;
 571
 572        /* Handle retry limits */
 573        if (txrate[0].count <= ampdu->rr_retry_limit_tid[tid]) {
 574                txrate[0].count++;
 575                rr = true;
 576        } else {
 577                txrate[1].count++;
 578                rr = false;
 579        }
 580
 581        if (ampdu_frames == 0) {
 582                u8 plcp0, plcp3, is40, sgi, mcs;
 583                uint fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
 584                struct brcms_fifo_info *f = &ampdu->fifo_tb[fifo];
 585
 586                if (rr) {
 587                        plcp0 = plcp[0];
 588                        plcp3 = plcp[3];
 589                } else {
 590                        plcp0 = txh->FragPLCPFallback[0];
 591                        plcp3 = txh->FragPLCPFallback[3];
 592
 593                }
 594
 595                /* Limit AMPDU size based on MCS */
 596                is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
 597                sgi = plcp3_issgi(plcp3) ? 1 : 0;
 598                mcs = plcp0 & ~MIMO_PLCP_40MHZ;
 599                session->max_ampdu_len = min(scb_ampdu->max_rx_ampdu_bytes,
 600                                             ampdu->max_txlen[mcs][is40][sgi]);
 601
 602                session->max_ampdu_frames = scb_ampdu->max_pdu;
 603                if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
 604                        session->max_ampdu_frames =
 605                                min_t(u16, f->mcs2ampdu_table[mcs],
 606                                      session->max_ampdu_frames);
 607                }
 608        }
 609
 610        /*
 611         * Treat all frames as "middle" frames of AMPDU here. First and
 612         * last frames must be fixed up after all MPDUs have been prepped.
 613         */
 614        mcl = le16_to_cpu(txh->MacTxControlLow);
 615        mcl &= ~TXC_AMPDU_MASK;
 616        mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
 617        mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
 618        txh->MacTxControlLow = cpu_to_le16(mcl);
 619        txh->PreloadSize = 0;   /* always default to 0 */
 620
 621        skb_queue_tail(&session->skb_list, p);
 622
 623        return 0;
 624}
 625
 626void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session)
 627{
 628        struct brcms_c_info *wlc = session->wlc;
 629        struct ampdu_info *ampdu = wlc->ampdu;
 630        struct sk_buff *first, *last;
 631        struct d11txh *txh;
 632        struct ieee80211_tx_info *tx_info;
 633        struct ieee80211_tx_rate *txrate;
 634        u8 ndelim;
 635        u8 *plcp;
 636        uint len;
 637        uint fifo;
 638        struct brcms_fifo_info *f;
 639        u16 mcl;
 640        bool fbr;
 641        bool fbr_iscck;
 642        struct ieee80211_rts *rts;
 643        bool use_rts = false, use_cts = false;
 644        u16 dma_len = session->dma_len;
 645        u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
 646        u32 rspec = 0, rspec_fallback = 0;
 647        u32 rts_rspec = 0, rts_rspec_fallback = 0;
 648        u8 plcp0, plcp3, is40, sgi, mcs;
 649        u16 mch;
 650        u8 preamble_type = BRCMS_GF_PREAMBLE;
 651        u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
 652        u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
 653        u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
 654
 655        if (skb_queue_empty(&session->skb_list))
 656                return;
 657
 658        first = skb_peek(&session->skb_list);
 659        last = skb_peek_tail(&session->skb_list);
 660
 661        /* Need to fix up last MPDU first to adjust AMPDU length */
 662        txh = (struct d11txh *)last->data;
 663        fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
 664        f = &ampdu->fifo_tb[fifo];
 665
 666        mcl = le16_to_cpu(txh->MacTxControlLow);
 667        mcl &= ~TXC_AMPDU_MASK;
 668        mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
 669        txh->MacTxControlLow = cpu_to_le16(mcl);
 670
 671        /* remove the null delimiter after last mpdu */
 672        ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
 673        txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
 674        session->ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
 675
 676        /* remove the pad len from last mpdu */
 677        fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
 678        len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
 679                          BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
 680        session->ampdu_len -= roundup(len, 4) - len;
 681
 682        /* Now fix up the first MPDU */
 683        tx_info = IEEE80211_SKB_CB(first);
 684        txrate = tx_info->status.rates;
 685        txh = (struct d11txh *)first->data;
 686        plcp = (u8 *)(txh + 1);
 687        rts = (struct ieee80211_rts *)&txh->rts_frame;
 688
 689        mcl = le16_to_cpu(txh->MacTxControlLow);
 690        /* If only one MPDU leave it marked as last */
 691        if (first != last) {
 692                mcl &= ~TXC_AMPDU_MASK;
 693                mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
 694        }
 695        mcl |= TXC_STARTMSDU;
 696        if (ieee80211_is_rts(rts->frame_control)) {
 697                mcl |= TXC_SENDRTS;
 698                use_rts = true;
 699        }
 700        if (ieee80211_is_cts(rts->frame_control)) {
 701                mcl |= TXC_SENDCTS;
 702                use_cts = true;
 703        }
 704        txh->MacTxControlLow = cpu_to_le16(mcl);
 705
 706        fbr = txrate[1].count > 0;
 707        if (!fbr) {
 708                plcp0 = plcp[0];
 709                plcp3 = plcp[3];
 710        } else {
 711                plcp0 = txh->FragPLCPFallback[0];
 712                plcp3 = txh->FragPLCPFallback[3];
 713        }
 714        is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
 715        sgi = plcp3_issgi(plcp3) ? 1 : 0;
 716        mcs = plcp0 & ~MIMO_PLCP_40MHZ;
 717
 718        if (is40) {
 719                if (CHSPEC_SB_UPPER(wlc_phy_chanspec_get(wlc->band->pi)))
 720                        mimo_ctlchbw = PHY_TXC1_BW_20MHZ_UP;
 721                else
 722                        mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
 723        }
 724
 725        /* rebuild the rspec and rspec_fallback */
 726        rspec = RSPEC_MIMORATE;
 727        rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
 728        if (plcp[0] & MIMO_PLCP_40MHZ)
 729                rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
 730
 731        fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
 732        if (fbr_iscck) {
 733                rspec_fallback =
 734                        cck_rspec(cck_phy2mac_rate(txh->FragPLCPFallback[0]));
 735        } else {
 736                rspec_fallback = RSPEC_MIMORATE;
 737                rspec_fallback |= txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
 738                if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
 739                        rspec_fallback |= PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT;
 740        }
 741
 742        if (use_rts || use_cts) {
 743                rts_rspec =
 744                        brcms_c_rspec_to_rts_rspec(wlc, rspec,
 745                                                   false, mimo_ctlchbw);
 746                rts_rspec_fallback =
 747                        brcms_c_rspec_to_rts_rspec(wlc, rspec_fallback,
 748                                                   false, mimo_ctlchbw);
 749        }
 750
 751        BRCMS_SET_MIMO_PLCP_LEN(plcp, session->ampdu_len);
 752        /* mark plcp to indicate ampdu */
 753        BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
 754
 755        /* reset the mixed mode header durations */
 756        if (txh->MModeLen) {
 757                u16 mmodelen = brcms_c_calc_lsig_len(wlc, rspec,
 758                                                     session->ampdu_len);
 759                txh->MModeLen = cpu_to_le16(mmodelen);
 760                preamble_type = BRCMS_MM_PREAMBLE;
 761        }
 762        if (txh->MModeFbrLen) {
 763                u16 mmfbrlen = brcms_c_calc_lsig_len(wlc, rspec_fallback,
 764                                                     session->ampdu_len);
 765                txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
 766                fbr_preamble_type = BRCMS_MM_PREAMBLE;
 767        }
 768
 769        /* set the preload length */
 770        if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
 771                dma_len = min(dma_len, f->ampdu_pld_size);
 772                txh->PreloadSize = cpu_to_le16(dma_len);
 773        } else {
 774                txh->PreloadSize = 0;
 775        }
 776
 777        mch = le16_to_cpu(txh->MacTxControlHigh);
 778
 779        /* update RTS dur fields */
 780        if (use_rts || use_cts) {
 781                u16 durid;
 782                if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
 783                    TXC_PREAMBLE_RTS_MAIN_SHORT)
 784                        rts_preamble_type = BRCMS_SHORT_PREAMBLE;
 785
 786                if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
 787                     TXC_PREAMBLE_RTS_FB_SHORT)
 788                        rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
 789
 790                durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
 791                                                   rspec, rts_preamble_type,
 792                                                   preamble_type,
 793                                                   session->ampdu_len, true);
 794                rts->duration = cpu_to_le16(durid);
 795                durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
 796                                                   rts_rspec_fallback,
 797                                                   rspec_fallback,
 798                                                   rts_fbr_preamble_type,
 799                                                   fbr_preamble_type,
 800                                                   session->ampdu_len, true);
 801                txh->RTSDurFallback = cpu_to_le16(durid);
 802                /* set TxFesTimeNormal */
 803                txh->TxFesTimeNormal = rts->duration;
 804                /* set fallback rate version of TxFesTimeNormal */
 805                txh->TxFesTimeFallback = txh->RTSDurFallback;
 806        }
 807
 808        /* set flag and plcp for fallback rate */
 809        if (fbr) {
 810                mch |= TXC_AMPDU_FBR;
 811                txh->MacTxControlHigh = cpu_to_le16(mch);
 812                BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
 813                BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
 814        }
 815
 816        brcms_dbg_ht(wlc->hw->d11core, "wl%d: count %d ampdu_len %d\n",
 817                     wlc->pub->unit, skb_queue_len(&session->skb_list),
 818                     session->ampdu_len);
 819}
 820
 821static void
 822brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
 823                          struct ieee80211_tx_info *tx_info,
 824                          struct tx_status *txs, u8 mcs)
 825{
 826        struct ieee80211_tx_rate *txrate = tx_info->status.rates;
 827        int i;
 828
 829        /* clear the rest of the rates */
 830        for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
 831                txrate[i].idx = -1;
 832                txrate[i].count = 0;
 833        }
 834}
 835
 836static void
 837brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
 838                              struct sk_buff *p, struct tx_status *txs,
 839                              u32 s1, u32 s2)
 840{
 841        struct scb_ampdu *scb_ampdu;
 842        struct brcms_c_info *wlc = ampdu->wlc;
 843        struct scb_ampdu_tid_ini *ini;
 844        u8 bitmap[8], queue, tid;
 845        struct d11txh *txh;
 846        u8 *plcp;
 847        struct ieee80211_hdr *h;
 848        u16 seq, start_seq = 0, bindex, index, mcl;
 849        u8 mcs = 0;
 850        bool ba_recd = false, ack_recd = false;
 851        u8 suc_mpdu = 0, tot_mpdu = 0;
 852        uint supr_status;
 853        bool update_rate = true, retry = true, tx_error = false;
 854        u16 mimoantsel = 0;
 855        u8 antselid = 0;
 856        u8 retry_limit, rr_retry_limit;
 857        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
 858
 859#ifdef DEBUG
 860        u8 hole[AMPDU_MAX_MPDU];
 861        memset(hole, 0, sizeof(hole));
 862#endif
 863
 864        scb_ampdu = &scb->scb_ampdu;
 865        tid = (u8) (p->priority);
 866
 867        ini = &scb_ampdu->ini[tid];
 868        retry_limit = ampdu->retry_limit_tid[tid];
 869        rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
 870        memset(bitmap, 0, sizeof(bitmap));
 871        queue = txs->frameid & TXFID_QUEUE_MASK;
 872        supr_status = txs->status & TX_STATUS_SUPR_MASK;
 873
 874        if (txs->status & TX_STATUS_ACK_RCV) {
 875                if (TX_STATUS_SUPR_UF == supr_status)
 876                        update_rate = false;
 877
 878                WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
 879                start_seq = txs->sequence >> SEQNUM_SHIFT;
 880                bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
 881                    TX_STATUS_BA_BMAP03_SHIFT;
 882
 883                WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
 884                WARN_ON(!(s1 & TX_STATUS_AMPDU));
 885
 886                bitmap[0] |=
 887                    (s1 & TX_STATUS_BA_BMAP47_MASK) <<
 888                    TX_STATUS_BA_BMAP47_SHIFT;
 889                bitmap[1] = (s1 >> 8) & 0xff;
 890                bitmap[2] = (s1 >> 16) & 0xff;
 891                bitmap[3] = (s1 >> 24) & 0xff;
 892
 893                bitmap[4] = s2 & 0xff;
 894                bitmap[5] = (s2 >> 8) & 0xff;
 895                bitmap[6] = (s2 >> 16) & 0xff;
 896                bitmap[7] = (s2 >> 24) & 0xff;
 897
 898                ba_recd = true;
 899        } else {
 900                if (supr_status) {
 901                        update_rate = false;
 902                        if (supr_status == TX_STATUS_SUPR_BADCH) {
 903                                brcms_dbg_ht(wlc->hw->d11core,
 904                                          "%s: Pkt tx suppressed, illegal channel possibly %d\n",
 905                                          __func__, CHSPEC_CHANNEL(
 906                                          wlc->default_bss->chanspec));
 907                        } else {
 908                                if (supr_status != TX_STATUS_SUPR_FRAG)
 909                                        brcms_err(wlc->hw->d11core,
 910                                                  "%s: supr_status 0x%x\n",
 911                                                  __func__, supr_status);
 912                        }
 913                        /* no need to retry for badch; will fail again */
 914                        if (supr_status == TX_STATUS_SUPR_BADCH ||
 915                            supr_status == TX_STATUS_SUPR_EXPTIME) {
 916                                retry = false;
 917                        } else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
 918                                /* TX underflow:
 919                                 *   try tuning pre-loading or ampdu size
 920                                 */
 921                        } else if (supr_status == TX_STATUS_SUPR_FRAG) {
 922                                /*
 923                                 * if there were underflows, but pre-loading
 924                                 * is not active, notify rate adaptation.
 925                                 */
 926                                if (brcms_c_ffpld_check_txfunfl(wlc, queue) > 0)
 927                                        tx_error = true;
 928                        }
 929                } else if (txs->phyerr) {
 930                        update_rate = false;
 931                        brcms_dbg_ht(wlc->hw->d11core,
 932                                     "%s: ampdu tx phy error (0x%x)\n",
 933                                     __func__, txs->phyerr);
 934                }
 935        }
 936
 937        /* loop through all pkts and retry if not acked */
 938        while (p) {
 939                tx_info = IEEE80211_SKB_CB(p);
 940                txh = (struct d11txh *) p->data;
 941                mcl = le16_to_cpu(txh->MacTxControlLow);
 942                plcp = (u8 *) (txh + 1);
 943                h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
 944                seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
 945
 946                trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
 947
 948                if (tot_mpdu == 0) {
 949                        mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
 950                        mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
 951                }
 952
 953                index = TX_SEQ_TO_INDEX(seq);
 954                ack_recd = false;
 955                if (ba_recd) {
 956                        bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
 957                        brcms_dbg_ht(wlc->hw->d11core,
 958                                     "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
 959                                     tid, seq, start_seq, bindex,
 960                                     isset(bitmap, bindex), index);
 961                        /* if acked then clear bit and free packet */
 962                        if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
 963                            && isset(bitmap, bindex)) {
 964                                ini->txretry[index] = 0;
 965
 966                                /*
 967                                 * ampdu_ack_len:
 968                                 *   number of acked aggregated frames
 969                                 */
 970                                /* ampdu_len: number of aggregated frames */
 971                                brcms_c_ampdu_rate_status(wlc, tx_info, txs,
 972                                                          mcs);
 973                                tx_info->flags |= IEEE80211_TX_STAT_ACK;
 974                                tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
 975                                tx_info->status.ampdu_ack_len =
 976                                        tx_info->status.ampdu_len = 1;
 977
 978                                skb_pull(p, D11_PHY_HDR_LEN);
 979                                skb_pull(p, D11_TXH_LEN);
 980
 981                                ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
 982                                                            p);
 983                                ack_recd = true;
 984                                suc_mpdu++;
 985                        }
 986                }
 987                /* either retransmit or send bar if ack not recd */
 988                if (!ack_recd) {
 989                        if (retry && (ini->txretry[index] < (int)retry_limit)) {
 990                                int ret;
 991                                ini->txretry[index]++;
 992                                ret = brcms_c_txfifo(wlc, queue, p);
 993                                /*
 994                                 * We shouldn't be out of space in the DMA
 995                                 * ring here since we're reinserting a frame
 996                                 * that was just pulled out.
 997                                 */
 998                                WARN_ONCE(ret, "queue %d out of txds\n", queue);
 999                        } else {
1000                                /* Retry timeout */
1001                                ieee80211_tx_info_clear_status(tx_info);
1002                                tx_info->status.ampdu_ack_len = 0;
1003                                tx_info->status.ampdu_len = 1;
1004                                tx_info->flags |=
1005                                    IEEE80211_TX_STAT_AMPDU_NO_BACK;
1006                                skb_pull(p, D11_PHY_HDR_LEN);
1007                                skb_pull(p, D11_TXH_LEN);
1008                                brcms_dbg_ht(wlc->hw->d11core,
1009                                             "BA Timeout, seq %d\n",
1010                                             seq);
1011                                ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1012                                                            p);
1013                        }
1014                }
1015                tot_mpdu++;
1016
1017                /* break out if last packet of ampdu */
1018                if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1019                    TXC_AMPDU_LAST)
1020                        break;
1021
1022                p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
1023        }
1024
1025        /* update rate state */
1026        antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
1027}
1028
1029void
1030brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
1031                     struct sk_buff *p, struct tx_status *txs)
1032{
1033        struct scb_ampdu *scb_ampdu;
1034        struct brcms_c_info *wlc = ampdu->wlc;
1035        struct scb_ampdu_tid_ini *ini;
1036        u32 s1 = 0, s2 = 0;
1037        struct ieee80211_tx_info *tx_info;
1038
1039        tx_info = IEEE80211_SKB_CB(p);
1040
1041        /* BMAC_NOTE: For the split driver, second level txstatus comes later
1042         * So if the ACK was received then wait for the second level else just
1043         * call the first one
1044         */
1045        if (txs->status & TX_STATUS_ACK_RCV) {
1046                u8 status_delay = 0;
1047
1048                /* wait till the next 8 bytes of txstatus is available */
1049                s1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus));
1050                while ((s1 & TXS_V) == 0) {
1051                        udelay(1);
1052                        status_delay++;
1053                        if (status_delay > 10)
1054                                return; /* error condition */
1055                        s1 = bcma_read32(wlc->hw->d11core,
1056                                         D11REGOFFS(frmtxstatus));
1057                }
1058
1059                s2 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus2));
1060        }
1061
1062        if (scb) {
1063                scb_ampdu = &scb->scb_ampdu;
1064                ini = &scb_ampdu->ini[p->priority];
1065                brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
1066        } else {
1067                /* loop through all pkts and free */
1068                u8 queue = txs->frameid & TXFID_QUEUE_MASK;
1069                struct d11txh *txh;
1070                u16 mcl;
1071                while (p) {
1072                        tx_info = IEEE80211_SKB_CB(p);
1073                        txh = (struct d11txh *) p->data;
1074                        trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
1075                                           sizeof(*txh));
1076                        mcl = le16_to_cpu(txh->MacTxControlLow);
1077                        brcmu_pkt_buf_free_skb(p);
1078                        /* break out if last packet of ampdu */
1079                        if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1080                            TXC_AMPDU_LAST)
1081                                break;
1082                        p = dma_getnexttxp(wlc->hw->di[queue],
1083                                           DMA_RANGE_TRANSMITTED);
1084                }
1085        }
1086}
1087
1088void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
1089{
1090        char template[T_RAM_ACCESS_SZ * 2];
1091
1092        /* driver needs to write the ta in the template; ta is at offset 16 */
1093        memset(template, 0, sizeof(template));
1094        memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1095        brcms_b_write_template_ram(wlc->hw, (T_BA_TPL_BASE + 16),
1096                                  (T_RAM_ACCESS_SZ * 2),
1097                                  template);
1098}
1099
1100bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid)
1101{
1102        return wlc->ampdu->ini_enable[tid];
1103}
1104
1105void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
1106{
1107        struct brcms_c_info *wlc = ampdu->wlc;
1108
1109        /*
1110         * Extend ucode internal watchdog timer to
1111         * match larger received frames
1112         */
1113        if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1114            IEEE80211_HT_MAX_AMPDU_64K) {
1115                brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1116                brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1117        } else {
1118                brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1119                brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1120        }
1121}
1122
1123/*
1124 * callback function that helps invalidating ampdu packets in a DMA queue
1125 */
1126static void dma_cb_fn_ampdu(void *txi, void *arg_a)
1127{
1128        struct ieee80211_sta *sta = arg_a;
1129        struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
1130
1131        if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
1132            (tx_info->rate_driver_data[0] == sta || sta == NULL))
1133                tx_info->rate_driver_data[0] = NULL;
1134}
1135
1136/*
1137 * When a remote party is no longer available for ampdu communication, any
1138 * pending tx ampdu packets in the driver have to be flushed.
1139 */
1140void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
1141                     struct ieee80211_sta *sta, u16 tid)
1142{
1143        brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
1144}
1145