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