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 #define AMPDU_MAX_MPDU 32 /* max number of mpdus in an ampdu */
26 #define AMPDU_NUM_MPDU_LEGACY 16 /* max number of mpdus in an ampdu to a legacy */
27 #define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
28 #define AMPDU_TX_BA_DEF_WSIZE 64 /* default Tx ba window size (in pdu) */
29 #define AMPDU_RX_BA_DEF_WSIZE 64 /* max Rx ba window size (in pdu) */
30 #define AMPDU_RX_BA_MAX_WSIZE 64 /* default Rx ba window size (in pdu) */
31 #define AMPDU_MAX_DUR 5 /* max dur of tx ampdu (in msec) */
32 #define AMPDU_DEF_RETRY_LIMIT 5 /* default tx retry limit */
33 #define AMPDU_DEF_RR_RETRY_LIMIT 2 /* default tx retry limit at reg rate */
34 #define AMPDU_DEF_TXPKT_WEIGHT 2 /* default weight of ampdu in txfifo */
35 #define AMPDU_DEF_FFPLD_RSVD 2048 /* default ffpld reserved bytes */
36 #define AMPDU_INI_FREE 10 /* # of inis to be freed on detach */
37 #define AMPDU_SCB_MAX_RELEASE 20 /* max # of mpdus released at a time */
39 #define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */
40 #define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu
43 #define FFPLD_MPDU_SIZE 1800 /* estimate of maximum mpdu size */
44 #define FFPLD_MAX_MCS 23 /* we don't deal with mcs 32 */
45 #define FFPLD_PLD_INCR 1000 /* increments in bytes */
46 #define FFPLD_MAX_AMPDU_CNT 5000 /* maximum number of ampdu we
47 * accumulate between resets.
50 #define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
52 /* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
53 #define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
54 AMPDU_DELIMITER_LEN + 3\
55 + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
57 /* structure to hold tx fifo information and pre-loading state
58 * counters specific to tx underflows of ampdus
59 * some counters might be redundant with the ones in wlc or ampdu structures.
60 * This allows to maintain a specific state independently of
61 * how often and/or when the wlc counters are updated.
63 struct brcms_fifo_info {
64 u16 ampdu_pld_size; /* number of bytes to be pre-loaded */
65 u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; /* per-mcs max # of mpdus in an ampdu */
66 u16 prev_txfunfl; /* num of underflows last read from the HW macstats counter */
67 u32 accum_txfunfl; /* num of underflows since we modified pld params */
68 u32 accum_txampdu; /* num of tx ampdu since we modified pld params */
69 u32 prev_txampdu; /* previous reading of tx ampdu */
70 u32 dmaxferrate; /* estimated dma avg xfer rate in kbits/sec */
73 /* AMPDU module specific state */
75 struct brcms_c_info *wlc; /* pointer to main wlc structure */
76 int scb_handle; /* scb cubby handle to retrieve data from scb */
77 u8 ini_enable[AMPDU_MAX_SCB_TID]; /* per-tid initiator enable/disable of ampdu */
78 u8 ba_tx_wsize; /* Tx ba window size (in pdu) */
79 u8 ba_rx_wsize; /* Rx ba window size (in pdu) */
80 u8 retry_limit; /* mpdu transmit retry limit */
81 u8 rr_retry_limit; /* mpdu transmit retry limit at regular rate */
82 u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; /* per-tid mpdu transmit retry limit */
83 /* per-tid mpdu transmit retry limit at regular rate */
84 u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
85 u8 mpdu_density; /* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
86 s8 max_pdu; /* max pdus allowed in ampdu */
87 u8 dur; /* max duration of an ampdu (in msec) */
88 u8 txpkt_weight; /* weight of ampdu in txfifo; reduces rate lag */
89 u8 rx_factor; /* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
90 u32 ffpld_rsvd; /* number of bytes to reserve for preload */
91 u32 max_txlen[MCS_TABLE_SIZE][2][2]; /* max size of ampdu per mcs, bw and sgi */
92 void *ini_free[AMPDU_INI_FREE]; /* array of ini's to be freed on detach */
93 bool mfbr; /* enable multiple fallback rate */
94 u32 tx_max_funl; /* underflows should be kept such that
95 * (tx_max_funfl*underflows) < tx frames
97 /* table of fifo infos */
98 struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO];
102 /* used for flushing ampdu packets */
103 struct cb_del_ampdu_pars {
104 struct ieee80211_sta *sta;
108 #define AMPDU_CLEANUPFLAG_RX (0x1)
109 #define AMPDU_CLEANUPFLAG_TX (0x2)
111 #define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
112 #define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
114 static void brcms_c_ffpld_init(struct ampdu_info *ampdu);
115 static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int f);
116 static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
118 static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu,
120 static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
122 static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu);
124 #define brcms_c_ampdu_txflowcontrol(a, b, c) do {} while (0)
127 brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
129 struct sk_buff *p, struct tx_status *txs,
130 u32 frmtxstatus, u32 frmtxstatus2);
132 static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu);
133 static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on);
135 struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
137 struct ampdu_info *ampdu;
140 ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
142 wiphy_err(wlc->wiphy, "wl%d: brcms_c_ampdu_attach: out of mem"
143 "\n", wlc->pub->unit);
148 for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
149 ampdu->ini_enable[i] = true;
150 /* Disable ampdu for VO by default */
151 ampdu->ini_enable[PRIO_8021D_VO] = false;
152 ampdu->ini_enable[PRIO_8021D_NC] = false;
154 /* Disable ampdu for BK by default since not enough fifo space */
155 ampdu->ini_enable[PRIO_8021D_NONE] = false;
156 ampdu->ini_enable[PRIO_8021D_BK] = false;
158 ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
159 ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
160 ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
161 ampdu->max_pdu = AUTO;
162 ampdu->dur = AMPDU_MAX_DUR;
163 ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
165 ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
166 /* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
167 if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
168 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
170 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
171 ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
172 ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
174 for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
175 ampdu->retry_limit_tid[i] = ampdu->retry_limit;
176 ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
179 brcms_c_scb_ampdu_update_max_txlen(ampdu, ampdu->dur);
181 /* try to set ampdu to the default value */
182 brcms_c_ampdu_set(ampdu, wlc->pub->_ampdu);
184 ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
185 brcms_c_ffpld_init(ampdu);
190 void brcms_c_ampdu_detach(struct ampdu_info *ampdu)
197 /* free all ini's which were to be freed on callbacks which were never called */
198 for (i = 0; i < AMPDU_INI_FREE; i++) {
199 kfree(ampdu->ini_free[i]);
202 brcms_c_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
206 static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
209 struct scb_ampdu *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
212 scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
214 /* go back to legacy size if some preloading is occurring */
215 for (i = 0; i < NUM_FFPLD_FIFO; i++) {
216 if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
217 scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
220 /* apply user override */
221 if (ampdu->max_pdu != AUTO)
222 scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
224 scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
226 if (scb_ampdu->max_rx_ampdu_bytes)
227 scb_ampdu->release = min_t(u8, scb_ampdu->release,
228 scb_ampdu->max_rx_ampdu_bytes / 1600);
230 scb_ampdu->release = min(scb_ampdu->release,
231 ampdu->fifo_tb[TX_AC_BE_FIFO].
232 mcs2ampdu_table[FFPLD_MAX_MCS]);
235 static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu)
237 brcms_c_scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
240 static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
243 struct brcms_fifo_info *fifo;
245 for (j = 0; j < NUM_FFPLD_FIFO; j++) {
246 fifo = (ampdu->fifo_tb + j);
247 fifo->ampdu_pld_size = 0;
248 for (i = 0; i <= FFPLD_MAX_MCS; i++)
249 fifo->mcs2ampdu_table[i] = 255;
250 fifo->dmaxferrate = 0;
251 fifo->accum_txampdu = 0;
252 fifo->prev_txfunfl = 0;
253 fifo->accum_txfunfl = 0;
258 /* evaluate the dma transfer rate using the tx underflows as feedback.
259 * If necessary, increase tx fifo preloading. If not enough,
260 * decrease maximum ampdu size for each mcs till underflows stop
261 * Return 1 if pre-loading not active, -1 if not an underflow event,
262 * 0 if pre-loading module took care of the event.
264 static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
266 struct ampdu_info *ampdu = wlc->ampdu;
267 u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
270 u32 current_ampdu_cnt = 0;
273 struct brcms_fifo_info *fifo = (ampdu->fifo_tb + fid);
277 /* return if we got here for a different reason than underflows */
278 cur_txunfl = brcms_c_read_shm(wlc,
280 offsetof(struct macstat, txfunfl[fid]));
281 new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
282 if (new_txunfl == 0) {
283 BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
286 fifo->prev_txfunfl = cur_txunfl;
288 if (!ampdu->tx_max_funl)
291 /* check if fifo is big enough */
292 if (brcms_c_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz))
295 if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
298 max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
299 fifo->accum_txfunfl += new_txunfl;
301 /* we need to wait for at least 10 underflows */
302 if (fifo->accum_txfunfl < 10)
305 BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n",
306 current_ampdu_cnt, fifo->accum_txfunfl);
309 compute the current ratio of tx unfl per ampdu.
310 When the current ampdu count becomes too
311 big while the ratio remains small, we reset
312 the current count in order to not
313 introduce too big of a latency in detecting a
314 large amount of tx underflows later.
317 txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
319 if (txunfl_ratio > ampdu->tx_max_funl) {
320 if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
321 fifo->accum_txfunfl = 0;
326 min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
328 /* In case max value max_pdu is already lower than
329 the fifo depth, there is nothing more we can do.
332 if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
333 fifo->accum_txfunfl = 0;
337 if (fifo->ampdu_pld_size < max_pld_size) {
339 /* increment by TX_FIFO_PLD_INC bytes */
340 fifo->ampdu_pld_size += FFPLD_PLD_INCR;
341 if (fifo->ampdu_pld_size > max_pld_size)
342 fifo->ampdu_pld_size = max_pld_size;
344 /* update scb release size */
345 brcms_c_scb_ampdu_update_config_all(ampdu);
348 compute a new dma xfer rate for max_mpdu @ max mcs.
349 This is the minimum dma rate that
350 can achieve no underflow condition for the current mpdu size.
352 /* note : we divide/multiply by 100 to avoid integer overflows */
355 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
356 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
358 BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
359 "pre-load size %d\n",
360 fifo->dmaxferrate, fifo->ampdu_pld_size);
363 /* decrease ampdu size */
364 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
365 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
366 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
367 AMPDU_NUM_MPDU_LEGACY - 1;
369 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
371 /* recompute the table */
372 brcms_c_ffpld_calc_mcs2ampdu_table(ampdu, fid);
374 /* update scb release size */
375 brcms_c_scb_ampdu_update_config_all(ampdu);
378 fifo->accum_txfunfl = 0;
382 static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
385 u32 phy_rate, dma_rate, tmp;
387 struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f);
389 /* recompute the dma rate */
390 /* note : we divide/multiply by 100 to avoid integer overflows */
392 min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
393 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
396 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
397 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
398 fifo->dmaxferrate = dma_rate;
400 /* fill up the mcs2ampdu table; do not recalc the last mcs */
401 dma_rate = dma_rate >> 7;
402 for (i = 0; i < FFPLD_MAX_MCS; i++) {
403 /* shifting to keep it within integer range */
404 phy_rate = MCS_RATE(i, true, false) >> 7;
405 if (phy_rate > dma_rate) {
406 tmp = ((fifo->ampdu_pld_size * phy_rate) /
407 ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
408 tmp = min_t(u32, tmp, 255);
409 fifo->mcs2ampdu_table[i] = (u8) tmp;
415 brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
416 u8 ba_wsize, /* negotiated ba window size (in pdu) */
417 uint max_rx_ampdu_bytes) /* from ht_cap in beacon */
419 struct scb_ampdu *scb_ampdu;
420 struct scb_ampdu_tid_ini *ini;
421 struct ampdu_info *ampdu = wlc->ampdu;
422 struct scb *scb = wlc->pub->global_scb;
423 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
425 if (!ampdu->ini_enable[tid]) {
426 wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
431 ini = SCB_AMPDU_INI(scb_ampdu, tid);
433 ini->scb = scb_ampdu->scb;
434 ini->ba_wsize = ba_wsize;
435 scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
439 brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_txq_info *qi,
440 struct sk_buff **pdu, int prec)
442 struct brcms_c_info *wlc;
443 struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
446 u8 preamble_type = BRCMS_GF_PREAMBLE;
447 u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
448 u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
449 u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
451 bool rr = true, fbr = false;
452 uint i, count = 0, fifo, seg_cnt = 0;
453 u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
454 u32 ampdu_len, max_ampdu_bytes = 0;
455 struct d11txh *txh = NULL;
457 struct ieee80211_hdr *h;
459 struct scb_ampdu *scb_ampdu;
460 struct scb_ampdu_tid_ini *ini;
462 bool use_rts = false, use_cts = false;
463 ratespec_t rspec = 0, rspec_fallback = 0;
464 ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
465 u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
466 struct ieee80211_rts *rts;
468 struct brcms_fifo_info *f;
470 struct ieee80211_tx_info *tx_info;
478 tid = (u8) (p->priority);
480 f = ampdu->fifo_tb + prio2fifo[tid];
482 scb = wlc->pub->global_scb;
483 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
484 ini = &scb_ampdu->ini[tid];
486 /* Let pressure continue to build ... */
487 qlen = pktq_plen(&qi->q, prec);
488 if (ini->tx_in_transit > 0 &&
489 qlen < min(scb_ampdu->max_pdu, ini->ba_wsize)) {
490 /* Collect multiple MPDU's to be sent in the next AMPDU */
494 /* at this point we intend to transmit an AMPDU */
495 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
499 struct ieee80211_tx_rate *txrate;
501 tx_info = IEEE80211_SKB_CB(p);
502 txrate = tx_info->status.rates;
504 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
505 err = brcms_c_prep_pdu(wlc, p, &fifo);
507 wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
515 wiphy_err(wiphy, "wl%d: sendampdu: "
516 "prep_xdu retry; seq 0x%x\n",
517 wlc->pub->unit, seq);
522 /* error in the packet; reject it */
523 wiphy_err(wiphy, "wl%d: sendampdu: prep_xdu "
524 "rejected; seq 0x%x\n", wlc->pub->unit, seq);
529 /* pkt is good to be aggregated */
530 txh = (struct d11txh *) p->data;
531 plcp = (u8 *) (txh + 1);
532 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
533 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
534 index = TX_SEQ_TO_INDEX(seq);
536 /* check mcl fields and test whether it can be agg'd */
537 mcl = le16_to_cpu(txh->MacTxControlLow);
538 mcl &= ~TXC_AMPDU_MASK;
539 fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
540 txh->PreloadSize = 0; /* always default to 0 */
542 /* Handle retry limits */
543 if (txrate[0].count <= rr_retry_limit) {
553 /* extract the length info */
554 len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
555 : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
557 /* retrieve null delimiter count */
558 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
561 BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
562 wlc->pub->unit, count, len);
565 * aggregateable mpdu. For ucode/hw agg,
566 * test whether need to break or change the epoch
569 mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
570 /* refill the bits since might be a retx mpdu */
571 mcl |= TXC_STARTMSDU;
572 rts = (struct ieee80211_rts *)&txh->rts_frame;
574 if (ieee80211_is_rts(rts->frame_control)) {
578 if (ieee80211_is_cts(rts->frame_control)) {
583 mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
584 mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
587 len = roundup(len, 4);
588 ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
590 dma_len += (u16) brcmu_pkttotlen(p);
592 BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
593 " seg_cnt %d null delim %d\n",
594 wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
596 txh->MacTxControlLow = cpu_to_le16(mcl);
598 /* this packet is added */
601 /* patch the first MPDU */
603 u8 plcp0, plcp3, is40, sgi;
604 struct ieee80211_sta *sta;
606 sta = tx_info->control.sta;
612 plcp0 = txh->FragPLCPFallback[0];
613 plcp3 = txh->FragPLCPFallback[3];
616 is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
617 sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
618 mcs = plcp0 & ~MIMO_PLCP_40MHZ;
620 min(scb_ampdu->max_rx_ampdu_bytes,
621 ampdu->max_txlen[mcs][is40][sgi]);
625 CHSPEC_SB_UPPER(BRCMS_BAND_PI_RADIO_CHANSPEC)
626 ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
628 /* rebuild the rspec and rspec_fallback */
629 rspec = RSPEC_MIMORATE;
630 rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
631 if (plcp[0] & MIMO_PLCP_40MHZ)
632 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
634 if (fbr_iscck) /* CCK */
636 CCK_RSPEC(CCK_PHY2MAC_RATE
637 (txh->FragPLCPFallback[0]));
639 rspec_fallback = RSPEC_MIMORATE;
641 txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
642 if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
644 (PHY_TXC1_BW_40MHZ <<
648 if (use_rts || use_cts) {
650 brcms_c_rspec_to_rts_rspec(wlc,
651 rspec, false, mimo_ctlchbw);
653 brcms_c_rspec_to_rts_rspec(wlc,
654 rspec_fallback, false, mimo_ctlchbw);
658 /* if (first mpdu for host agg) */
659 /* test whether to add more */
660 if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
661 (count == f->mcs2ampdu_table[mcs])) {
662 BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
663 " ampdu at %d for mcs %d\n",
664 wlc->pub->unit, count, mcs);
668 if (count == scb_ampdu->max_pdu) {
672 /* check to see if the next pkt is a candidate for aggregation */
673 p = pktq_ppeek(&qi->q, prec);
674 tx_info = IEEE80211_SKB_CB(p); /* tx_info must be checked with current p */
677 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
678 ((u8) (p->priority) == tid)) {
680 plen = brcmu_pkttotlen(p) +
681 AMPDU_MAX_MPDU_OVERHEAD;
682 plen = max(scb_ampdu->min_len, plen);
684 if ((plen + ampdu_len) > max_ampdu_bytes) {
689 /* check if there are enough descriptors available */
690 if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
691 wiphy_err(wiphy, "%s: No fifo space "
696 p = brcmu_pktq_pdeq(&qi->q, prec);
703 ini->tx_in_transit += count;
706 /* patch up the last txh */
707 txh = (struct d11txh *) pkt[count - 1]->data;
708 mcl = le16_to_cpu(txh->MacTxControlLow);
709 mcl &= ~TXC_AMPDU_MASK;
710 mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
711 txh->MacTxControlLow = cpu_to_le16(mcl);
713 /* remove the null delimiter after last mpdu */
714 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
715 txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
716 ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
718 /* remove the pad len from last mpdu */
719 fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
720 len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
721 : BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
722 ampdu_len -= roundup(len, 4) - len;
724 /* patch up the first txh & plcp */
725 txh = (struct d11txh *) pkt[0]->data;
726 plcp = (u8 *) (txh + 1);
728 BRCMS_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
729 /* mark plcp to indicate ampdu */
730 BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
732 /* reset the mixed mode header durations */
735 brcms_c_calc_lsig_len(wlc, rspec, ampdu_len);
736 txh->MModeLen = cpu_to_le16(mmodelen);
737 preamble_type = BRCMS_MM_PREAMBLE;
739 if (txh->MModeFbrLen) {
741 brcms_c_calc_lsig_len(wlc, rspec_fallback,
743 txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
744 fbr_preamble_type = BRCMS_MM_PREAMBLE;
747 /* set the preload length */
748 if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
749 dma_len = min(dma_len, f->ampdu_pld_size);
750 txh->PreloadSize = cpu_to_le16(dma_len);
752 txh->PreloadSize = 0;
754 mch = le16_to_cpu(txh->MacTxControlHigh);
756 /* update RTS dur fields */
757 if (use_rts || use_cts) {
759 rts = (struct ieee80211_rts *)&txh->rts_frame;
760 if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
761 TXC_PREAMBLE_RTS_MAIN_SHORT)
762 rts_preamble_type = BRCMS_SHORT_PREAMBLE;
764 if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
765 TXC_PREAMBLE_RTS_FB_SHORT)
766 rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
769 brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
770 rspec, rts_preamble_type,
771 preamble_type, ampdu_len,
773 rts->duration = cpu_to_le16(durid);
774 durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
777 rts_fbr_preamble_type,
780 txh->RTSDurFallback = cpu_to_le16(durid);
781 /* set TxFesTimeNormal */
782 txh->TxFesTimeNormal = rts->duration;
783 /* set fallback rate version of TxFesTimeNormal */
784 txh->TxFesTimeFallback = txh->RTSDurFallback;
787 /* set flag and plcp for fallback rate */
789 mch |= TXC_AMPDU_FBR;
790 txh->MacTxControlHigh = cpu_to_le16(mch);
791 BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
792 BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
795 BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
796 wlc->pub->unit, count, ampdu_len);
798 /* inform rate_sel if it this is a rate probe pkt */
799 frameid = le16_to_cpu(txh->TxFrameID);
800 if (frameid & TXFID_RATE_PROBE_MASK) {
801 wiphy_err(wiphy, "%s: XXX what to do with "
802 "TXFID_RATE_PROBE_MASK!?\n", __func__);
804 for (i = 0; i < count; i++)
805 brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1),
806 ampdu->txpkt_weight);
814 brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
815 struct sk_buff *p, struct tx_status *txs)
817 struct scb_ampdu *scb_ampdu;
818 struct brcms_c_info *wlc = ampdu->wlc;
819 struct scb_ampdu_tid_ini *ini;
821 struct ieee80211_tx_info *tx_info;
823 tx_info = IEEE80211_SKB_CB(p);
825 /* BMAC_NOTE: For the split driver, second level txstatus comes later
826 * So if the ACK was received then wait for the second level else just
829 if (txs->status & TX_STATUS_ACK_RCV) {
832 /* wait till the next 8 bytes of txstatus is available */
833 while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
836 if (status_delay > 10) {
837 return; /* error condition */
841 s2 = R_REG(&wlc->regs->frmtxstatus2);
845 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
846 ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
847 brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
849 /* loop through all pkts and free */
850 u8 queue = txs->frameid & TXFID_QUEUE_MASK;
854 tx_info = IEEE80211_SKB_CB(p);
855 txh = (struct d11txh *) p->data;
856 mcl = le16_to_cpu(txh->MacTxControlLow);
857 brcmu_pkt_buf_free_skb(p);
858 /* break out if last packet of ampdu */
859 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
862 p = GETNEXTTXP(wlc, queue);
864 brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
866 brcms_c_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
870 brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
871 struct ieee80211_tx_info *tx_info,
872 struct tx_status *txs, u8 mcs)
874 struct ieee80211_tx_rate *txrate = tx_info->status.rates;
877 /* clear the rest of the rates */
878 for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
884 #define SHORTNAME "AMPDU status"
887 brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
888 struct sk_buff *p, struct tx_status *txs,
891 struct scb_ampdu *scb_ampdu;
892 struct brcms_c_info *wlc = ampdu->wlc;
893 struct scb_ampdu_tid_ini *ini;
894 u8 bitmap[8], queue, tid;
897 struct ieee80211_hdr *h;
898 u16 seq, start_seq = 0, bindex, index, mcl;
900 bool ba_recd = false, ack_recd = false;
901 u8 suc_mpdu = 0, tot_mpdu = 0;
903 bool update_rate = true, retry = true, tx_error = false;
906 u8 retry_limit, rr_retry_limit;
907 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
908 struct wiphy *wiphy = wlc->wiphy;
911 u8 hole[AMPDU_MAX_MPDU];
912 memset(hole, 0, sizeof(hole));
915 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
916 tid = (u8) (p->priority);
918 ini = SCB_AMPDU_INI(scb_ampdu, tid);
919 retry_limit = ampdu->retry_limit_tid[tid];
920 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
921 memset(bitmap, 0, sizeof(bitmap));
922 queue = txs->frameid & TXFID_QUEUE_MASK;
923 supr_status = txs->status & TX_STATUS_SUPR_MASK;
925 if (txs->status & TX_STATUS_ACK_RCV) {
926 if (TX_STATUS_SUPR_UF == supr_status) {
930 WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
931 start_seq = txs->sequence >> SEQNUM_SHIFT;
932 bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
933 TX_STATUS_BA_BMAP03_SHIFT;
935 WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
936 WARN_ON(!(s1 & TX_STATUS_AMPDU));
939 (s1 & TX_STATUS_BA_BMAP47_MASK) <<
940 TX_STATUS_BA_BMAP47_SHIFT;
941 bitmap[1] = (s1 >> 8) & 0xff;
942 bitmap[2] = (s1 >> 16) & 0xff;
943 bitmap[3] = (s1 >> 24) & 0xff;
945 bitmap[4] = s2 & 0xff;
946 bitmap[5] = (s2 >> 8) & 0xff;
947 bitmap[6] = (s2 >> 16) & 0xff;
948 bitmap[7] = (s2 >> 24) & 0xff;
954 if (supr_status == TX_STATUS_SUPR_BADCH) {
955 wiphy_err(wiphy, "%s: Pkt tx suppressed, "
956 "illegal channel possibly %d\n",
957 __func__, CHSPEC_CHANNEL(
958 wlc->default_bss->chanspec));
960 if (supr_status != TX_STATUS_SUPR_FRAG)
961 wiphy_err(wiphy, "%s:"
962 "supr_status 0x%x\n",
963 __func__, supr_status);
965 /* no need to retry for badch; will fail again */
966 if (supr_status == TX_STATUS_SUPR_BADCH ||
967 supr_status == TX_STATUS_SUPR_EXPTIME) {
969 } else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
970 /* TX underflow : try tuning pre-loading or ampdu size */
971 } else if (supr_status == TX_STATUS_SUPR_FRAG) {
972 /* if there were underflows, but pre-loading is not active,
973 notify rate adaptation.
975 if (brcms_c_ffpld_check_txfunfl(wlc,
976 prio2fifo[tid]) > 0) {
980 } else if (txs->phyerr) {
982 wiphy_err(wiphy, "wl%d: ampdu tx phy "
983 "error (0x%x)\n", wlc->pub->unit,
987 brcmu_prpkt("txpkt (AMPDU)", p);
988 brcms_c_print_txdesc((struct d11txh *) p->data);
990 brcms_c_print_txstatus(txs);
994 /* loop through all pkts and retry if not acked */
996 tx_info = IEEE80211_SKB_CB(p);
997 txh = (struct d11txh *) p->data;
998 mcl = le16_to_cpu(txh->MacTxControlLow);
999 plcp = (u8 *) (txh + 1);
1000 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
1001 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
1003 if (tot_mpdu == 0) {
1004 mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
1005 mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
1008 index = TX_SEQ_TO_INDEX(seq);
1011 bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
1012 BCMMSG(wlc->wiphy, "tid %d seq %d,"
1013 " start_seq %d, bindex %d set %d, index %d\n",
1014 tid, seq, start_seq, bindex,
1015 isset(bitmap, bindex), index);
1016 /* if acked then clear bit and free packet */
1017 if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
1018 && isset(bitmap, bindex)) {
1019 ini->tx_in_transit--;
1020 ini->txretry[index] = 0;
1022 /* ampdu_ack_len: number of acked aggregated frames */
1023 /* ampdu_len: number of aggregated frames */
1024 brcms_c_ampdu_rate_status(wlc, tx_info, txs,
1026 tx_info->flags |= IEEE80211_TX_STAT_ACK;
1027 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
1028 tx_info->status.ampdu_ack_len =
1029 tx_info->status.ampdu_len = 1;
1031 skb_pull(p, D11_PHY_HDR_LEN);
1032 skb_pull(p, D11_TXH_LEN);
1034 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1040 /* either retransmit or send bar if ack not recd */
1042 struct ieee80211_tx_rate *txrate =
1043 tx_info->status.rates;
1044 if (retry && (txrate[0].count < (int)retry_limit)) {
1045 ini->txretry[index]++;
1046 ini->tx_in_transit--;
1047 /* Use high prededence for retransmit to give some punch */
1048 /* brcms_c_txq_enq(wlc, scb, p,
1049 * BRCMS_PRIO_TO_PREC(tid)); */
1050 brcms_c_txq_enq(wlc, scb, p,
1051 BRCMS_PRIO_TO_HI_PREC(tid));
1054 ini->tx_in_transit--;
1055 ieee80211_tx_info_clear_status(tx_info);
1056 tx_info->status.ampdu_ack_len = 0;
1057 tx_info->status.ampdu_len = 1;
1059 IEEE80211_TX_STAT_AMPDU_NO_BACK;
1060 skb_pull(p, D11_PHY_HDR_LEN);
1061 skb_pull(p, D11_TXH_LEN);
1062 wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
1063 "transit %d\n", SHORTNAME, seq,
1064 ini->tx_in_transit);
1065 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1071 /* break out if last packet of ampdu */
1072 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1076 p = GETNEXTTXP(wlc, queue);
1078 brcms_c_send_q(wlc);
1080 /* update rate state */
1081 antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
1083 brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
1086 static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
1088 struct brcms_c_info *wlc = ampdu->wlc;
1090 wlc->pub->_ampdu = false;
1093 if (!N_ENAB(wlc->pub)) {
1094 wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
1095 "nmode enabled\n", wlc->pub->unit);
1098 if (!brcms_c_ampdu_cap(ampdu)) {
1099 wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
1100 "ampdu capable\n", wlc->pub->unit);
1103 wlc->pub->_ampdu = on;
1109 static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
1111 if (BRCMS_PHY_11N_CAP(ampdu->wlc->band))
1117 static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
1121 for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
1122 /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
1124 rate = MCS_RATE(mcs, false, false);
1125 ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
1126 /* 40 MHz, No SGI */
1127 rate = MCS_RATE(mcs, true, false);
1128 ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
1130 rate = MCS_RATE(mcs, false, true);
1131 ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
1133 rate = MCS_RATE(mcs, true, true);
1134 ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
1138 void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
1140 char template[T_RAM_ACCESS_SZ * 2];
1142 /* driver needs to write the ta in the template; ta is at offset 16 */
1143 memset(template, 0, sizeof(template));
1144 memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1145 brcms_c_write_template_ram(wlc, (T_BA_TPL_BASE + 16),
1146 (T_RAM_ACCESS_SZ * 2),
1150 bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid)
1152 return wlc->ampdu->ini_enable[tid];
1155 void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
1157 struct brcms_c_info *wlc = ampdu->wlc;
1159 /* Extend ucode internal watchdog timer to match larger received frames */
1160 if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1161 IEEE80211_HT_MAX_AMPDU_64K) {
1162 brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1163 brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1165 brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1166 brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1171 * callback function that helps flushing ampdu packets from a priority queue
1173 static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
1175 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
1176 struct cb_del_ampdu_pars *ampdu_pars =
1177 (struct cb_del_ampdu_pars *)arg_a;
1180 rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
1181 rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
1182 tx_info->control.sta == ampdu_pars->sta);
1183 rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
1188 * callback function that helps invalidating ampdu packets in a DMA queue
1190 static void dma_cb_fn_ampdu(void *txi, void *arg_a)
1192 struct ieee80211_sta *sta = arg_a;
1193 struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
1195 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
1196 (tx_info->control.sta == sta || sta == NULL))
1197 tx_info->control.sta = NULL;
1201 * When a remote party is no longer available for ampdu communication, any
1202 * pending tx ampdu packets in the driver have to be flushed.
1204 void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
1205 struct ieee80211_sta *sta, u16 tid)
1207 struct brcms_txq_info *qi = wlc->pkt_queue;
1208 struct pktq *pq = &qi->q;
1210 struct cb_del_ampdu_pars ampdu_pars;
1212 ampdu_pars.sta = sta;
1213 ampdu_pars.tid = tid;
1214 for (prec = 0; prec < pq->num_prec; prec++) {
1215 brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
1216 (void *)&du_pars);
1218 brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);