2 * Copyright (c) 2010 Broadcom Corporation
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.
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.
16 #include <net/mac80211.h>
20 #include "phy/phy_hal.h"
25 /* max number of mpdus in an ampdu */
26 #define AMPDU_MAX_MPDU 32
27 /* max number of mpdus in an ampdu to a legacy */
28 #define AMPDU_NUM_MPDU_LEGACY 16
29 /* max Tx ba window size (in pdu) */
30 #define AMPDU_TX_BA_MAX_WSIZE 64
31 /* default Tx ba window size (in pdu) */
32 #define AMPDU_TX_BA_DEF_WSIZE 64
33 /* default Rx ba window size (in pdu) */
34 #define AMPDU_RX_BA_DEF_WSIZE 64
35 /* max Rx ba window size (in pdu) */
36 #define AMPDU_RX_BA_MAX_WSIZE 64
37 /* max dur of tx ampdu (in msec) */
38 #define AMPDU_MAX_DUR 5
39 /* default tx retry limit */
40 #define AMPDU_DEF_RETRY_LIMIT 5
41 /* default tx retry limit at reg rate */
42 #define AMPDU_DEF_RR_RETRY_LIMIT 2
43 /* default weight of ampdu in txfifo */
44 #define AMPDU_DEF_TXPKT_WEIGHT 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
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
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.
63 #define AMPDU_DELIMITER_LEN 4
65 /* max allowed number of mpdus in an ampdu (2 streams) */
66 #define AMPDU_NUM_MPDU 16
68 #define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
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)
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))
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.
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
93 struct brcms_fifo_info {
95 u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];
103 /* AMPDU module specific state
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 * txpkt_weight: weight of ampdu in txfifo; reduces rate lag
118 * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes
119 * ffpld_rsvd: number of bytes to reserve for preload
120 * max_txlen: max size of ampdu per mcs, bw and sgi
121 * mfbr: enable multiple fallback rate
122 * tx_max_funl: underflows should be kept such that
123 * (tx_max_funfl*underflows) < tx frames
124 * fifo_tb: table of fifo infos
127 struct brcms_c_info *wlc;
129 u8 ini_enable[AMPDU_MAX_SCB_TID];
134 u8 retry_limit_tid[AMPDU_MAX_SCB_TID];
135 u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
142 u32 max_txlen[MCS_TABLE_SIZE][2][2];
145 struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO];
148 /* used for flushing ampdu packets */
149 struct cb_del_ampdu_pars {
150 struct ieee80211_sta *sta;
154 static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
158 for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
159 /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
161 rate = mcs_2_rate(mcs, false, false);
162 ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
164 rate = mcs_2_rate(mcs, true, false);
165 ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
167 rate = mcs_2_rate(mcs, false, true);
168 ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
170 rate = mcs_2_rate(mcs, true, true);
171 ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
175 static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
177 if (BRCMS_PHY_11N_CAP(ampdu->wlc->band))
183 static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
185 struct brcms_c_info *wlc = ampdu->wlc;
187 wlc->pub->_ampdu = false;
190 if (!(wlc->pub->_n_enab & SUPPORT_11N)) {
191 wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
192 "nmode enabled\n", wlc->pub->unit);
195 if (!brcms_c_ampdu_cap(ampdu)) {
196 wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
197 "ampdu capable\n", wlc->pub->unit);
200 wlc->pub->_ampdu = on;
206 static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
209 struct brcms_fifo_info *fifo;
211 for (j = 0; j < NUM_FFPLD_FIFO; j++) {
212 fifo = (ampdu->fifo_tb + j);
213 fifo->ampdu_pld_size = 0;
214 for (i = 0; i <= FFPLD_MAX_MCS; i++)
215 fifo->mcs2ampdu_table[i] = 255;
216 fifo->dmaxferrate = 0;
217 fifo->accum_txampdu = 0;
218 fifo->prev_txfunfl = 0;
219 fifo->accum_txfunfl = 0;
224 struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
226 struct ampdu_info *ampdu;
229 ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
231 wiphy_err(wlc->wiphy, "wl%d: brcms_c_ampdu_attach: out of mem"
232 "\n", wlc->pub->unit);
237 for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
238 ampdu->ini_enable[i] = true;
239 /* Disable ampdu for VO by default */
240 ampdu->ini_enable[PRIO_8021D_VO] = false;
241 ampdu->ini_enable[PRIO_8021D_NC] = false;
243 /* Disable ampdu for BK by default since not enough fifo space */
244 ampdu->ini_enable[PRIO_8021D_NONE] = false;
245 ampdu->ini_enable[PRIO_8021D_BK] = false;
247 ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
248 ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
249 ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
250 ampdu->max_pdu = AUTO;
251 ampdu->dur = AMPDU_MAX_DUR;
252 ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
254 ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
256 * bump max ampdu rcv size to 64k for all 11n
257 * devices except 4321A0 and 4321A1
259 if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
260 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
262 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
263 ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
264 ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
266 for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
267 ampdu->retry_limit_tid[i] = ampdu->retry_limit;
268 ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
271 brcms_c_scb_ampdu_update_max_txlen(ampdu, ampdu->dur);
273 /* try to set ampdu to the default value */
274 brcms_c_ampdu_set(ampdu, wlc->pub->_ampdu);
276 ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
277 brcms_c_ffpld_init(ampdu);
282 void brcms_c_ampdu_detach(struct ampdu_info *ampdu)
287 static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
290 struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
293 scb_ampdu->max_pdu = AMPDU_NUM_MPDU;
295 /* go back to legacy size if some preloading is occurring */
296 for (i = 0; i < NUM_FFPLD_FIFO; i++) {
297 if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
298 scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
301 /* apply user override */
302 if (ampdu->max_pdu != AUTO)
303 scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
305 scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu,
306 AMPDU_SCB_MAX_RELEASE);
308 if (scb_ampdu->max_rx_ampdu_bytes)
309 scb_ampdu->release = min_t(u8, scb_ampdu->release,
310 scb_ampdu->max_rx_ampdu_bytes / 1600);
312 scb_ampdu->release = min(scb_ampdu->release,
313 ampdu->fifo_tb[TX_AC_BE_FIFO].
314 mcs2ampdu_table[FFPLD_MAX_MCS]);
317 static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu)
319 brcms_c_scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
322 static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
325 u32 phy_rate, dma_rate, tmp;
327 struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f);
329 /* recompute the dma rate */
330 /* note : we divide/multiply by 100 to avoid integer overflows */
331 max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
332 AMPDU_NUM_MPDU_LEGACY);
333 phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
336 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
337 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
338 fifo->dmaxferrate = dma_rate;
340 /* fill up the mcs2ampdu table; do not recalc the last mcs */
341 dma_rate = dma_rate >> 7;
342 for (i = 0; i < FFPLD_MAX_MCS; i++) {
343 /* shifting to keep it within integer range */
344 phy_rate = mcs_2_rate(i, true, false) >> 7;
345 if (phy_rate > dma_rate) {
346 tmp = ((fifo->ampdu_pld_size * phy_rate) /
347 ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
348 tmp = min_t(u32, tmp, 255);
349 fifo->mcs2ampdu_table[i] = (u8) tmp;
354 /* evaluate the dma transfer rate using the tx underflows as feedback.
355 * If necessary, increase tx fifo preloading. If not enough,
356 * decrease maximum ampdu size for each mcs till underflows stop
357 * Return 1 if pre-loading not active, -1 if not an underflow event,
358 * 0 if pre-loading module took care of the event.
360 static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
362 struct ampdu_info *ampdu = wlc->ampdu;
363 u32 phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
366 u32 current_ampdu_cnt = 0;
369 struct brcms_fifo_info *fifo = (ampdu->fifo_tb + fid);
373 /* return if we got here for a different reason than underflows */
374 cur_txunfl = brcms_c_read_shm(wlc,
376 offsetof(struct macstat, txfunfl[fid]));
377 new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
378 if (new_txunfl == 0) {
379 BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
382 fifo->prev_txfunfl = cur_txunfl;
384 if (!ampdu->tx_max_funl)
387 /* check if fifo is big enough */
388 if (brcms_c_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz))
391 if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
394 max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
395 fifo->accum_txfunfl += new_txunfl;
397 /* we need to wait for at least 10 underflows */
398 if (fifo->accum_txfunfl < 10)
401 BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n",
402 current_ampdu_cnt, fifo->accum_txfunfl);
405 compute the current ratio of tx unfl per ampdu.
406 When the current ampdu count becomes too
407 big while the ratio remains small, we reset
408 the current count in order to not
409 introduce too big of a latency in detecting a
410 large amount of tx underflows later.
413 txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
415 if (txunfl_ratio > ampdu->tx_max_funl) {
416 if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT)
417 fifo->accum_txfunfl = 0;
421 max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
422 AMPDU_NUM_MPDU_LEGACY);
424 /* In case max value max_pdu is already lower than
425 the fifo depth, there is nothing more we can do.
428 if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
429 fifo->accum_txfunfl = 0;
433 if (fifo->ampdu_pld_size < max_pld_size) {
435 /* increment by TX_FIFO_PLD_INC bytes */
436 fifo->ampdu_pld_size += FFPLD_PLD_INCR;
437 if (fifo->ampdu_pld_size > max_pld_size)
438 fifo->ampdu_pld_size = max_pld_size;
440 /* update scb release size */
441 brcms_c_scb_ampdu_update_config_all(ampdu);
444 * compute a new dma xfer rate for max_mpdu @ max mcs.
445 * This is the minimum dma rate that can achieve no
446 * underflow condition for the current mpdu size.
448 * note : we divide/multiply by 100 to avoid integer overflows
452 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
453 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
455 BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
456 "pre-load size %d\n",
457 fifo->dmaxferrate, fifo->ampdu_pld_size);
460 /* decrease ampdu size */
461 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
462 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
463 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
464 AMPDU_NUM_MPDU_LEGACY - 1;
466 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
468 /* recompute the table */
469 brcms_c_ffpld_calc_mcs2ampdu_table(ampdu, fid);
471 /* update scb release size */
472 brcms_c_scb_ampdu_update_config_all(ampdu);
475 fifo->accum_txfunfl = 0;
480 brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
481 u8 ba_wsize, /* negotiated ba window size (in pdu) */
482 uint max_rx_ampdu_bytes) /* from ht_cap in beacon */
484 struct scb_ampdu *scb_ampdu;
485 struct scb_ampdu_tid_ini *ini;
486 struct ampdu_info *ampdu = wlc->ampdu;
487 struct scb *scb = wlc->pub->global_scb;
488 scb_ampdu = &scb->scb_ampdu;
490 if (!ampdu->ini_enable[tid]) {
491 wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
496 ini = &scb_ampdu->ini[tid];
498 ini->scb = scb_ampdu->scb;
499 ini->ba_wsize = ba_wsize;
500 scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
504 brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
505 struct sk_buff **pdu, int prec)
507 struct brcms_c_info *wlc;
508 struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
511 u8 preamble_type = BRCMS_GF_PREAMBLE;
512 u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
513 u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
514 u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
516 bool rr = true, fbr = false;
517 uint i, count = 0, fifo, seg_cnt = 0;
518 u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
519 u32 ampdu_len, max_ampdu_bytes = 0;
520 struct d11txh *txh = NULL;
522 struct ieee80211_hdr *h;
524 struct scb_ampdu *scb_ampdu;
525 struct scb_ampdu_tid_ini *ini;
527 bool use_rts = false, use_cts = false;
528 u32 rspec = 0, rspec_fallback = 0;
529 u32 rts_rspec = 0, rts_rspec_fallback = 0;
530 u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
531 struct ieee80211_rts *rts;
533 struct brcms_fifo_info *f;
535 struct ieee80211_tx_info *tx_info;
543 tid = (u8) (p->priority);
545 f = ampdu->fifo_tb + prio2fifo[tid];
547 scb = wlc->pub->global_scb;
548 scb_ampdu = &scb->scb_ampdu;
549 ini = &scb_ampdu->ini[tid];
551 /* Let pressure continue to build ... */
552 qlen = pktq_plen(&qi->q, prec);
553 if (ini->tx_in_transit > 0 &&
554 qlen < min(scb_ampdu->max_pdu, ini->ba_wsize))
555 /* Collect multiple MPDU's to be sent in the next AMPDU */
558 /* at this point we intend to transmit an AMPDU */
559 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
563 struct ieee80211_tx_rate *txrate;
565 tx_info = IEEE80211_SKB_CB(p);
566 txrate = tx_info->status.rates;
568 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
569 err = brcms_c_prep_pdu(wlc, p, &fifo);
571 wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
579 wiphy_err(wiphy, "wl%d: sendampdu: "
580 "prep_xdu retry; seq 0x%x\n",
581 wlc->pub->unit, seq);
586 /* error in the packet; reject it */
587 wiphy_err(wiphy, "wl%d: sendampdu: prep_xdu "
588 "rejected; seq 0x%x\n", wlc->pub->unit, seq);
593 /* pkt is good to be aggregated */
594 txh = (struct d11txh *) p->data;
595 plcp = (u8 *) (txh + 1);
596 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
597 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
598 index = TX_SEQ_TO_INDEX(seq);
600 /* check mcl fields and test whether it can be agg'd */
601 mcl = le16_to_cpu(txh->MacTxControlLow);
602 mcl &= ~TXC_AMPDU_MASK;
603 fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
604 txh->PreloadSize = 0; /* always default to 0 */
606 /* Handle retry limits */
607 if (txrate[0].count <= rr_retry_limit) {
617 /* extract the length info */
618 len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
619 : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
621 /* retrieve null delimiter count */
622 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
625 BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
626 wlc->pub->unit, count, len);
629 * aggregateable mpdu. For ucode/hw agg,
630 * test whether need to break or change the epoch
633 mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
634 /* refill the bits since might be a retx mpdu */
635 mcl |= TXC_STARTMSDU;
636 rts = (struct ieee80211_rts *)&txh->rts_frame;
638 if (ieee80211_is_rts(rts->frame_control)) {
642 if (ieee80211_is_cts(rts->frame_control)) {
647 mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
648 mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
651 len = roundup(len, 4);
652 ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
654 dma_len += (u16) brcmu_pkttotlen(p);
656 BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
657 " seg_cnt %d null delim %d\n",
658 wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
660 txh->MacTxControlLow = cpu_to_le16(mcl);
662 /* this packet is added */
665 /* patch the first MPDU */
667 u8 plcp0, plcp3, is40, sgi;
668 struct ieee80211_sta *sta;
670 sta = tx_info->control.sta;
676 plcp0 = txh->FragPLCPFallback[0];
677 plcp3 = txh->FragPLCPFallback[3];
680 is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
681 sgi = plcp3_issgi(plcp3) ? 1 : 0;
682 mcs = plcp0 & ~MIMO_PLCP_40MHZ;
684 min(scb_ampdu->max_rx_ampdu_bytes,
685 ampdu->max_txlen[mcs][is40][sgi]);
689 CHSPEC_SB_UPPER(wlc_phy_chanspec_get(
691 ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
693 /* rebuild the rspec and rspec_fallback */
694 rspec = RSPEC_MIMORATE;
695 rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
696 if (plcp[0] & MIMO_PLCP_40MHZ)
697 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
699 if (fbr_iscck) /* CCK */
700 rspec_fallback = cck_rspec(cck_phy2mac_rate
701 (txh->FragPLCPFallback[0]));
703 rspec_fallback = RSPEC_MIMORATE;
705 txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
706 if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
708 (PHY_TXC1_BW_40MHZ <<
712 if (use_rts || use_cts) {
714 brcms_c_rspec_to_rts_rspec(wlc,
715 rspec, false, mimo_ctlchbw);
717 brcms_c_rspec_to_rts_rspec(wlc,
718 rspec_fallback, false, mimo_ctlchbw);
722 /* if (first mpdu for host agg) */
723 /* test whether to add more */
724 if ((mcs_2_rate(mcs, true, false) >= f->dmaxferrate) &&
725 (count == f->mcs2ampdu_table[mcs])) {
726 BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
727 " ampdu at %d for mcs %d\n",
728 wlc->pub->unit, count, mcs);
732 if (count == scb_ampdu->max_pdu)
736 * check to see if the next pkt is
737 * a candidate for aggregation
739 p = pktq_ppeek(&qi->q, prec);
740 /* tx_info must be checked with current p */
741 tx_info = IEEE80211_SKB_CB(p);
744 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
745 ((u8) (p->priority) == tid)) {
747 plen = brcmu_pkttotlen(p) +
748 AMPDU_MAX_MPDU_OVERHEAD;
749 plen = max(scb_ampdu->min_len, plen);
751 if ((plen + ampdu_len) > max_ampdu_bytes) {
757 * check if there are enough
758 * descriptors available
760 if (*wlc->core->txavail[fifo] <= seg_cnt + 1) {
761 wiphy_err(wiphy, "%s: No fifo space "
766 p = brcmu_pktq_pdeq(&qi->q, prec);
773 ini->tx_in_transit += count;
776 /* patch up the last txh */
777 txh = (struct d11txh *) pkt[count - 1]->data;
778 mcl = le16_to_cpu(txh->MacTxControlLow);
779 mcl &= ~TXC_AMPDU_MASK;
780 mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
781 txh->MacTxControlLow = cpu_to_le16(mcl);
783 /* remove the null delimiter after last mpdu */
784 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
785 txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
786 ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
788 /* remove the pad len from last mpdu */
789 fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
790 len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
791 : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
792 ampdu_len -= roundup(len, 4) - len;
794 /* patch up the first txh & plcp */
795 txh = (struct d11txh *) pkt[0]->data;
796 plcp = (u8 *) (txh + 1);
798 BRCMS_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
799 /* mark plcp to indicate ampdu */
800 BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
802 /* reset the mixed mode header durations */
805 brcms_c_calc_lsig_len(wlc, rspec, ampdu_len);
806 txh->MModeLen = cpu_to_le16(mmodelen);
807 preamble_type = BRCMS_MM_PREAMBLE;
809 if (txh->MModeFbrLen) {
811 brcms_c_calc_lsig_len(wlc, rspec_fallback,
813 txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
814 fbr_preamble_type = BRCMS_MM_PREAMBLE;
817 /* set the preload length */
818 if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
819 dma_len = min(dma_len, f->ampdu_pld_size);
820 txh->PreloadSize = cpu_to_le16(dma_len);
822 txh->PreloadSize = 0;
824 mch = le16_to_cpu(txh->MacTxControlHigh);
826 /* update RTS dur fields */
827 if (use_rts || use_cts) {
829 rts = (struct ieee80211_rts *)&txh->rts_frame;
830 if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
831 TXC_PREAMBLE_RTS_MAIN_SHORT)
832 rts_preamble_type = BRCMS_SHORT_PREAMBLE;
834 if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
835 TXC_PREAMBLE_RTS_FB_SHORT)
836 rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
839 brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
840 rspec, rts_preamble_type,
841 preamble_type, ampdu_len,
843 rts->duration = cpu_to_le16(durid);
844 durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
847 rts_fbr_preamble_type,
850 txh->RTSDurFallback = cpu_to_le16(durid);
851 /* set TxFesTimeNormal */
852 txh->TxFesTimeNormal = rts->duration;
853 /* set fallback rate version of TxFesTimeNormal */
854 txh->TxFesTimeFallback = txh->RTSDurFallback;
857 /* set flag and plcp for fallback rate */
859 mch |= TXC_AMPDU_FBR;
860 txh->MacTxControlHigh = cpu_to_le16(mch);
861 BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
862 BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
865 BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
866 wlc->pub->unit, count, ampdu_len);
868 /* inform rate_sel if it this is a rate probe pkt */
869 frameid = le16_to_cpu(txh->TxFrameID);
870 if (frameid & TXFID_RATE_PROBE_MASK)
871 wiphy_err(wiphy, "%s: XXX what to do with "
872 "TXFID_RATE_PROBE_MASK!?\n", __func__);
874 for (i = 0; i < count; i++)
875 brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1),
876 ampdu->txpkt_weight);
884 brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
885 struct ieee80211_tx_info *tx_info,
886 struct tx_status *txs, u8 mcs)
888 struct ieee80211_tx_rate *txrate = tx_info->status.rates;
891 /* clear the rest of the rates */
892 for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
899 brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
900 struct sk_buff *p, struct tx_status *txs,
903 struct scb_ampdu *scb_ampdu;
904 struct brcms_c_info *wlc = ampdu->wlc;
905 struct scb_ampdu_tid_ini *ini;
906 u8 bitmap[8], queue, tid;
909 struct ieee80211_hdr *h;
910 u16 seq, start_seq = 0, bindex, index, mcl;
912 bool ba_recd = false, ack_recd = false;
913 u8 suc_mpdu = 0, tot_mpdu = 0;
915 bool update_rate = true, retry = true, tx_error = false;
918 u8 retry_limit, rr_retry_limit;
919 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
920 struct wiphy *wiphy = wlc->wiphy;
923 u8 hole[AMPDU_MAX_MPDU];
924 memset(hole, 0, sizeof(hole));
927 scb_ampdu = &scb->scb_ampdu;
928 tid = (u8) (p->priority);
930 ini = &scb_ampdu->ini[tid];
931 retry_limit = ampdu->retry_limit_tid[tid];
932 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
933 memset(bitmap, 0, sizeof(bitmap));
934 queue = txs->frameid & TXFID_QUEUE_MASK;
935 supr_status = txs->status & TX_STATUS_SUPR_MASK;
937 if (txs->status & TX_STATUS_ACK_RCV) {
938 if (TX_STATUS_SUPR_UF == supr_status)
941 WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
942 start_seq = txs->sequence >> SEQNUM_SHIFT;
943 bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
944 TX_STATUS_BA_BMAP03_SHIFT;
946 WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
947 WARN_ON(!(s1 & TX_STATUS_AMPDU));
950 (s1 & TX_STATUS_BA_BMAP47_MASK) <<
951 TX_STATUS_BA_BMAP47_SHIFT;
952 bitmap[1] = (s1 >> 8) & 0xff;
953 bitmap[2] = (s1 >> 16) & 0xff;
954 bitmap[3] = (s1 >> 24) & 0xff;
956 bitmap[4] = s2 & 0xff;
957 bitmap[5] = (s2 >> 8) & 0xff;
958 bitmap[6] = (s2 >> 16) & 0xff;
959 bitmap[7] = (s2 >> 24) & 0xff;
965 if (supr_status == TX_STATUS_SUPR_BADCH) {
966 wiphy_err(wiphy, "%s: Pkt tx suppressed, "
967 "illegal channel possibly %d\n",
968 __func__, CHSPEC_CHANNEL(
969 wlc->default_bss->chanspec));
971 if (supr_status != TX_STATUS_SUPR_FRAG)
972 wiphy_err(wiphy, "%s:"
973 "supr_status 0x%x\n",
974 __func__, supr_status);
976 /* no need to retry for badch; will fail again */
977 if (supr_status == TX_STATUS_SUPR_BADCH ||
978 supr_status == TX_STATUS_SUPR_EXPTIME) {
980 } else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
982 * try tuning pre-loading or ampdu size
984 } else if (supr_status == TX_STATUS_SUPR_FRAG) {
986 * if there were underflows, but pre-loading
987 * is not active, notify rate adaptation.
989 if (brcms_c_ffpld_check_txfunfl(wlc,
993 } else if (txs->phyerr) {
995 wiphy_err(wiphy, "wl%d: ampdu tx phy "
996 "error (0x%x)\n", wlc->pub->unit,
999 if (brcm_msg_level & LOG_ERROR_VAL) {
1000 brcmu_prpkt("txpkt (AMPDU)", p);
1001 brcms_c_print_txdesc((struct d11txh *) p->data);
1003 brcms_c_print_txstatus(txs);
1007 /* loop through all pkts and retry if not acked */
1009 tx_info = IEEE80211_SKB_CB(p);
1010 txh = (struct d11txh *) p->data;
1011 mcl = le16_to_cpu(txh->MacTxControlLow);
1012 plcp = (u8 *) (txh + 1);
1013 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
1014 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
1016 if (tot_mpdu == 0) {
1017 mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
1018 mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
1021 index = TX_SEQ_TO_INDEX(seq);
1024 bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
1025 BCMMSG(wlc->wiphy, "tid %d seq %d,"
1026 " start_seq %d, bindex %d set %d, index %d\n",
1027 tid, seq, start_seq, bindex,
1028 isset(bitmap, bindex), index);
1029 /* if acked then clear bit and free packet */
1030 if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
1031 && isset(bitmap, bindex)) {
1032 ini->tx_in_transit--;
1033 ini->txretry[index] = 0;
1037 * number of acked aggregated frames
1039 /* ampdu_len: number of aggregated frames */
1040 brcms_c_ampdu_rate_status(wlc, tx_info, txs,
1042 tx_info->flags |= IEEE80211_TX_STAT_ACK;
1043 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
1044 tx_info->status.ampdu_ack_len =
1045 tx_info->status.ampdu_len = 1;
1047 skb_pull(p, D11_PHY_HDR_LEN);
1048 skb_pull(p, D11_TXH_LEN);
1050 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1056 /* either retransmit or send bar if ack not recd */
1058 struct ieee80211_tx_rate *txrate =
1059 tx_info->status.rates;
1060 if (retry && (txrate[0].count < (int)retry_limit)) {
1061 ini->txretry[index]++;
1062 ini->tx_in_transit--;
1064 * Use high prededence for retransmit to
1067 /* brcms_c_txq_enq(wlc, scb, p,
1068 * BRCMS_PRIO_TO_PREC(tid)); */
1069 brcms_c_txq_enq(wlc, scb, p,
1070 BRCMS_PRIO_TO_HI_PREC(tid));
1073 ini->tx_in_transit--;
1074 ieee80211_tx_info_clear_status(tx_info);
1075 tx_info->status.ampdu_ack_len = 0;
1076 tx_info->status.ampdu_len = 1;
1078 IEEE80211_TX_STAT_AMPDU_NO_BACK;
1079 skb_pull(p, D11_PHY_HDR_LEN);
1080 skb_pull(p, D11_TXH_LEN);
1081 wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
1082 "transit %d\n", "AMPDU status", seq,
1083 ini->tx_in_transit);
1084 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1090 /* break out if last packet of ampdu */
1091 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1095 p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
1097 brcms_c_send_q(wlc);
1099 /* update rate state */
1100 antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
1102 brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
1106 brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
1107 struct sk_buff *p, struct tx_status *txs)
1109 struct scb_ampdu *scb_ampdu;
1110 struct brcms_c_info *wlc = ampdu->wlc;
1111 struct scb_ampdu_tid_ini *ini;
1113 struct ieee80211_tx_info *tx_info;
1115 tx_info = IEEE80211_SKB_CB(p);
1117 /* BMAC_NOTE: For the split driver, second level txstatus comes later
1118 * So if the ACK was received then wait for the second level else just
1119 * call the first one
1121 if (txs->status & TX_STATUS_ACK_RCV) {
1122 u8 status_delay = 0;
1124 /* wait till the next 8 bytes of txstatus is available */
1125 while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
1128 if (status_delay > 10)
1129 return; /* error condition */
1132 s2 = R_REG(&wlc->regs->frmtxstatus2);
1136 scb_ampdu = &scb->scb_ampdu;
1137 ini = &scb_ampdu->ini[p->priority];
1138 brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
1140 /* loop through all pkts and free */
1141 u8 queue = txs->frameid & TXFID_QUEUE_MASK;
1145 tx_info = IEEE80211_SKB_CB(p);
1146 txh = (struct d11txh *) p->data;
1147 mcl = le16_to_cpu(txh->MacTxControlLow);
1148 brcmu_pkt_buf_free_skb(p);
1149 /* break out if last packet of ampdu */
1150 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1153 p = dma_getnexttxp(wlc->hw->di[queue],
1154 DMA_RANGE_TRANSMITTED);
1156 brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
1160 void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
1162 char template[T_RAM_ACCESS_SZ * 2];
1164 /* driver needs to write the ta in the template; ta is at offset 16 */
1165 memset(template, 0, sizeof(template));
1166 memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1167 brcms_c_write_template_ram(wlc, (T_BA_TPL_BASE + 16),
1168 (T_RAM_ACCESS_SZ * 2),
1172 bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid)
1174 return wlc->ampdu->ini_enable[tid];
1177 void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
1179 struct brcms_c_info *wlc = ampdu->wlc;
1182 * Extend ucode internal watchdog timer to
1183 * match larger received frames
1185 if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1186 IEEE80211_HT_MAX_AMPDU_64K) {
1187 brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1188 brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1190 brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1191 brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1196 * callback function that helps flushing ampdu packets from a priority queue
1198 static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
1200 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
1201 struct cb_del_ampdu_pars *ampdu_pars =
1202 (struct cb_del_ampdu_pars *)arg_a;
1205 rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
1206 rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
1207 tx_info->control.sta == ampdu_pars->sta);
1208 rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
1213 * callback function that helps invalidating ampdu packets in a DMA queue
1215 static void dma_cb_fn_ampdu(void *txi, void *arg_a)
1217 struct ieee80211_sta *sta = arg_a;
1218 struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
1220 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
1221 (tx_info->control.sta == sta || sta == NULL))
1222 tx_info->control.sta = NULL;
1226 * When a remote party is no longer available for ampdu communication, any
1227 * pending tx ampdu packets in the driver have to be flushed.
1229 void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
1230 struct ieee80211_sta *sta, u16 tid)
1232 struct brcms_txq_info *qi = wlc->pkt_queue;
1233 struct pktq *pq = &qi->q;
1235 struct cb_del_ampdu_pars ampdu_pars;
1237 ampdu_pars.sta = sta;
1238 ampdu_pars.tid = tid;
1239 for (prec = 0; prec < pq->num_prec; prec++)
1240 brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
1241 (void *)&du_pars);
1242 brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);