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 <linux/kernel.h>
17 #include <net/mac80211.h>
20 #include <brcmu_utils.h>
30 #include "phy/phy_hal.h"
36 #define AMPDU_MAX_MPDU 32 /* max number of mpdus in an ampdu */
37 #define AMPDU_NUM_MPDU_LEGACY 16 /* max number of mpdus in an ampdu to a legacy */
38 #define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
39 #define AMPDU_TX_BA_DEF_WSIZE 64 /* default Tx ba window size (in pdu) */
40 #define AMPDU_RX_BA_DEF_WSIZE 64 /* max Rx ba window size (in pdu) */
41 #define AMPDU_RX_BA_MAX_WSIZE 64 /* default Rx ba window size (in pdu) */
42 #define AMPDU_MAX_DUR 5 /* max dur of tx ampdu (in msec) */
43 #define AMPDU_DEF_RETRY_LIMIT 5 /* default tx retry limit */
44 #define AMPDU_DEF_RR_RETRY_LIMIT 2 /* default tx retry limit at reg rate */
45 #define AMPDU_DEF_TXPKT_WEIGHT 2 /* default weight of ampdu in txfifo */
46 #define AMPDU_DEF_FFPLD_RSVD 2048 /* default ffpld reserved bytes */
47 #define AMPDU_INI_FREE 10 /* # of inis to be freed on detach */
48 #define AMPDU_SCB_MAX_RELEASE 20 /* max # of mpdus released at a time */
50 #define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */
51 #define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu
54 #define FFPLD_MPDU_SIZE 1800 /* estimate of maximum mpdu size */
55 #define FFPLD_MAX_MCS 23 /* we don't deal with mcs 32 */
56 #define FFPLD_PLD_INCR 1000 /* increments in bytes */
57 #define FFPLD_MAX_AMPDU_CNT 5000 /* maximum number of ampdu we
58 * accumulate between resets.
61 #define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
63 /* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
64 #define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
65 AMPDU_DELIMITER_LEN + 3\
66 + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
68 /* structure to hold tx fifo information and pre-loading state
69 * counters specific to tx underflows of ampdus
70 * some counters might be redundant with the ones in wlc or ampdu structures.
71 * This allows to maintain a specific state independently of
72 * how often and/or when the wlc counters are updated.
74 typedef struct wlc_fifo_info {
75 u16 ampdu_pld_size; /* number of bytes to be pre-loaded */
76 u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; /* per-mcs max # of mpdus in an ampdu */
77 u16 prev_txfunfl; /* num of underflows last read from the HW macstats counter */
78 u32 accum_txfunfl; /* num of underflows since we modified pld params */
79 u32 accum_txampdu; /* num of tx ampdu since we modified pld params */
80 u32 prev_txampdu; /* previous reading of tx ampdu */
81 u32 dmaxferrate; /* estimated dma avg xfer rate in kbits/sec */
84 /* AMPDU module specific state */
86 struct wlc_info *wlc; /* pointer to main wlc structure */
87 int scb_handle; /* scb cubby handle to retrieve data from scb */
88 u8 ini_enable[AMPDU_MAX_SCB_TID]; /* per-tid initiator enable/disable of ampdu */
89 u8 ba_tx_wsize; /* Tx ba window size (in pdu) */
90 u8 ba_rx_wsize; /* Rx ba window size (in pdu) */
91 u8 retry_limit; /* mpdu transmit retry limit */
92 u8 rr_retry_limit; /* mpdu transmit retry limit at regular rate */
93 u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; /* per-tid mpdu transmit retry limit */
94 /* per-tid mpdu transmit retry limit at regular rate */
95 u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
96 u8 mpdu_density; /* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
97 s8 max_pdu; /* max pdus allowed in ampdu */
98 u8 dur; /* max duration of an ampdu (in msec) */
99 u8 txpkt_weight; /* weight of ampdu in txfifo; reduces rate lag */
100 u8 rx_factor; /* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
101 u32 ffpld_rsvd; /* number of bytes to reserve for preload */
102 u32 max_txlen[MCS_TABLE_SIZE][2][2]; /* max size of ampdu per mcs, bw and sgi */
103 void *ini_free[AMPDU_INI_FREE]; /* array of ini's to be freed on detach */
104 bool mfbr; /* enable multiple fallback rate */
105 u32 tx_max_funl; /* underflows should be kept such that
106 * (tx_max_funfl*underflows) < tx frames
108 wlc_fifo_info_t fifo_tb[NUM_FFPLD_FIFO]; /* table of fifo infos */
112 /* used for flushing ampdu packets */
113 struct cb_del_ampdu_pars {
114 struct ieee80211_sta *sta;
118 #define AMPDU_CLEANUPFLAG_RX (0x1)
119 #define AMPDU_CLEANUPFLAG_TX (0x2)
121 #define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
122 #define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
124 static void wlc_ffpld_init(struct ampdu_info *ampdu);
125 static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int f);
126 static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
128 static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
129 scb_ampdu_t *scb_ampdu,
130 u8 tid, bool override);
131 static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur);
132 static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb);
133 static void scb_ampdu_update_config_all(struct ampdu_info *ampdu);
135 #define wlc_ampdu_txflowcontrol(a, b, c) do {} while (0)
137 static void wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
139 struct sk_buff *p, tx_status_t *txs,
140 u32 frmtxstatus, u32 frmtxstatus2);
141 static bool wlc_ampdu_cap(struct ampdu_info *ampdu);
142 static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on);
144 struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc)
146 struct ampdu_info *ampdu;
149 ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
151 wiphy_err(wlc->wiphy, "wl%d: wlc_ampdu_attach: out of mem\n",
157 for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
158 ampdu->ini_enable[i] = true;
159 /* Disable ampdu for VO by default */
160 ampdu->ini_enable[PRIO_8021D_VO] = false;
161 ampdu->ini_enable[PRIO_8021D_NC] = false;
163 /* Disable ampdu for BK by default since not enough fifo space */
164 ampdu->ini_enable[PRIO_8021D_NONE] = false;
165 ampdu->ini_enable[PRIO_8021D_BK] = false;
167 ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
168 ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
169 ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
170 ampdu->max_pdu = AUTO;
171 ampdu->dur = AMPDU_MAX_DUR;
172 ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
174 ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
175 /* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
176 if (WLCISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
177 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
179 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
180 ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
181 ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
183 for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
184 ampdu->retry_limit_tid[i] = ampdu->retry_limit;
185 ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
188 ampdu_update_max_txlen(ampdu, ampdu->dur);
190 /* try to set ampdu to the default value */
191 wlc_ampdu_set(ampdu, wlc->pub->_ampdu);
193 ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
194 wlc_ffpld_init(ampdu);
199 void wlc_ampdu_detach(struct ampdu_info *ampdu)
206 /* free all ini's which were to be freed on callbacks which were never called */
207 for (i = 0; i < AMPDU_INI_FREE; i++) {
208 kfree(ampdu->ini_free[i]);
211 wlc_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
215 static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb)
217 scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
220 scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
222 /* go back to legacy size if some preloading is occurring */
223 for (i = 0; i < NUM_FFPLD_FIFO; i++) {
224 if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
225 scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
228 /* apply user override */
229 if (ampdu->max_pdu != AUTO)
230 scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
232 scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
234 if (scb_ampdu->max_rxlen)
236 min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 1600);
238 scb_ampdu->release = min(scb_ampdu->release,
239 ampdu->fifo_tb[TX_AC_BE_FIFO].
240 mcs2ampdu_table[FFPLD_MAX_MCS]);
243 static void scb_ampdu_update_config_all(struct ampdu_info *ampdu)
245 scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
248 static void wlc_ffpld_init(struct ampdu_info *ampdu)
251 wlc_fifo_info_t *fifo;
253 for (j = 0; j < NUM_FFPLD_FIFO; j++) {
254 fifo = (ampdu->fifo_tb + j);
255 fifo->ampdu_pld_size = 0;
256 for (i = 0; i <= FFPLD_MAX_MCS; i++)
257 fifo->mcs2ampdu_table[i] = 255;
258 fifo->dmaxferrate = 0;
259 fifo->accum_txampdu = 0;
260 fifo->prev_txfunfl = 0;
261 fifo->accum_txfunfl = 0;
266 /* evaluate the dma transfer rate using the tx underflows as feedback.
267 * If necessary, increase tx fifo preloading. If not enough,
268 * decrease maximum ampdu size for each mcs till underflows stop
269 * Return 1 if pre-loading not active, -1 if not an underflow event,
270 * 0 if pre-loading module took care of the event.
272 static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int fid)
274 struct ampdu_info *ampdu = wlc->ampdu;
275 u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
278 u32 current_ampdu_cnt = 0;
281 wlc_fifo_info_t *fifo = (ampdu->fifo_tb + fid);
285 /* return if we got here for a different reason than underflows */
288 M_UCODE_MACSTAT + offsetof(macstat_t, txfunfl[fid]));
289 new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
290 if (new_txunfl == 0) {
291 BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
294 fifo->prev_txfunfl = cur_txunfl;
296 if (!ampdu->tx_max_funl)
299 /* check if fifo is big enough */
300 if (wlc_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz)) {
304 if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
307 max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
308 fifo->accum_txfunfl += new_txunfl;
310 /* we need to wait for at least 10 underflows */
311 if (fifo->accum_txfunfl < 10)
314 BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n",
315 current_ampdu_cnt, fifo->accum_txfunfl);
318 compute the current ratio of tx unfl per ampdu.
319 When the current ampdu count becomes too
320 big while the ratio remains small, we reset
321 the current count in order to not
322 introduce too big of a latency in detecting a
323 large amount of tx underflows later.
326 txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
328 if (txunfl_ratio > ampdu->tx_max_funl) {
329 if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
330 fifo->accum_txfunfl = 0;
335 min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
337 /* In case max value max_pdu is already lower than
338 the fifo depth, there is nothing more we can do.
341 if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
342 fifo->accum_txfunfl = 0;
346 if (fifo->ampdu_pld_size < max_pld_size) {
348 /* increment by TX_FIFO_PLD_INC bytes */
349 fifo->ampdu_pld_size += FFPLD_PLD_INCR;
350 if (fifo->ampdu_pld_size > max_pld_size)
351 fifo->ampdu_pld_size = max_pld_size;
353 /* update scb release size */
354 scb_ampdu_update_config_all(ampdu);
357 compute a new dma xfer rate for max_mpdu @ max mcs.
358 This is the minimum dma rate that
359 can achieve no underflow condition for the current mpdu size.
361 /* note : we divide/multiply by 100 to avoid integer overflows */
364 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
365 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
367 BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
368 "pre-load size %d\n",
369 fifo->dmaxferrate, fifo->ampdu_pld_size);
372 /* decrease ampdu size */
373 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
374 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
375 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
376 AMPDU_NUM_MPDU_LEGACY - 1;
378 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
380 /* recompute the table */
381 wlc_ffpld_calc_mcs2ampdu_table(ampdu, fid);
383 /* update scb release size */
384 scb_ampdu_update_config_all(ampdu);
387 fifo->accum_txfunfl = 0;
391 static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
394 u32 phy_rate, dma_rate, tmp;
396 wlc_fifo_info_t *fifo = (ampdu->fifo_tb + f);
398 /* recompute the dma rate */
399 /* note : we divide/multiply by 100 to avoid integer overflows */
401 min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
402 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
405 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
406 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
407 fifo->dmaxferrate = dma_rate;
409 /* fill up the mcs2ampdu table; do not recalc the last mcs */
410 dma_rate = dma_rate >> 7;
411 for (i = 0; i < FFPLD_MAX_MCS; i++) {
412 /* shifting to keep it within integer range */
413 phy_rate = MCS_RATE(i, true, false) >> 7;
414 if (phy_rate > dma_rate) {
415 tmp = ((fifo->ampdu_pld_size * phy_rate) /
416 ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
417 tmp = min_t(u32, tmp, 255);
418 fifo->mcs2ampdu_table[i] = (u8) tmp;
424 wlc_ampdu_agg(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p,
427 scb_ampdu_t *scb_ampdu;
428 scb_ampdu_tid_ini_t *ini;
429 u8 tid = (u8) (p->priority);
431 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
433 /* initialize initiator on first packet; sends addba req */
434 ini = SCB_AMPDU_INI(scb_ampdu, tid);
435 if (ini->magic != INI_MAGIC) {
436 ini = wlc_ampdu_init_tid_ini(ampdu, scb_ampdu, tid, false);
442 wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
443 struct sk_buff **pdu, int prec)
445 struct wlc_info *wlc;
446 struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
449 u8 preamble_type = WLC_GF_PREAMBLE;
450 u8 fbr_preamble_type = WLC_GF_PREAMBLE;
451 u8 rts_preamble_type = WLC_LONG_PREAMBLE;
452 u8 rts_fbr_preamble_type = WLC_LONG_PREAMBLE;
454 bool rr = true, fbr = false;
455 uint i, count = 0, fifo, seg_cnt = 0;
456 u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
457 u32 ampdu_len, maxlen = 0;
458 d11txh_t *txh = NULL;
460 struct ieee80211_hdr *h;
462 scb_ampdu_t *scb_ampdu;
463 scb_ampdu_tid_ini_t *ini;
465 bool use_rts = false, use_cts = false;
466 ratespec_t rspec = 0, rspec_fallback = 0;
467 ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
468 u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
469 struct ieee80211_rts *rts;
473 struct ieee80211_tx_info *tx_info;
481 tid = (u8) (p->priority);
483 f = ampdu->fifo_tb + prio2fifo[tid];
485 scb = wlc->pub->global_scb;
486 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
487 ini = &scb_ampdu->ini[tid];
489 /* Let pressure continue to build ... */
490 qlen = pktq_plen(&qi->q, prec);
491 if (ini->tx_in_transit > 0 && qlen < scb_ampdu->max_pdu) {
495 wlc_ampdu_agg(ampdu, scb, p, tid);
497 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
501 struct ieee80211_tx_rate *txrate;
503 tx_info = IEEE80211_SKB_CB(p);
504 txrate = tx_info->status.rates;
506 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
507 err = wlc_prep_pdu(wlc, p, &fifo);
509 wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
517 wiphy_err(wiphy, "wl%d: wlc_sendampdu: "
518 "prep_xdu retry; seq 0x%x\n",
519 wlc->pub->unit, seq);
524 /* error in the packet; reject it */
525 wiphy_err(wiphy, "wl%d: wlc_sendampdu: prep_xdu "
526 "rejected; seq 0x%x\n", wlc->pub->unit, seq);
531 /* pkt is good to be aggregated */
532 txh = (d11txh_t *) p->data;
533 plcp = (u8 *) (txh + 1);
534 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
535 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
536 index = TX_SEQ_TO_INDEX(seq);
538 /* check mcl fields and test whether it can be agg'd */
539 mcl = le16_to_cpu(txh->MacTxControlLow);
540 mcl &= ~TXC_AMPDU_MASK;
541 fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
542 txh->PreloadSize = 0; /* always default to 0 */
544 /* Handle retry limits */
545 if (txrate[0].count <= rr_retry_limit) {
555 /* extract the length info */
556 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
557 : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
559 /* retrieve null delimiter count */
560 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
563 BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
564 wlc->pub->unit, count, len);
567 * aggregateable mpdu. For ucode/hw agg,
568 * test whether need to break or change the epoch
571 mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
572 /* refill the bits since might be a retx mpdu */
573 mcl |= TXC_STARTMSDU;
574 rts = (struct ieee80211_rts *)&txh->rts_frame;
576 if (ieee80211_is_rts(rts->frame_control)) {
580 if (ieee80211_is_cts(rts->frame_control)) {
585 mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
586 mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
589 len = roundup(len, 4);
590 ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
592 dma_len += (u16) brcmu_pkttotlen(p);
594 BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
595 " seg_cnt %d null delim %d\n",
596 wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
598 txh->MacTxControlLow = cpu_to_le16(mcl);
600 /* this packet is added */
603 /* patch the first MPDU */
605 u8 plcp0, plcp3, is40, sgi;
606 struct ieee80211_sta *sta;
608 sta = tx_info->control.sta;
614 plcp0 = txh->FragPLCPFallback[0];
615 plcp3 = txh->FragPLCPFallback[3];
618 is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
619 sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
620 mcs = plcp0 & ~MIMO_PLCP_40MHZ;
622 min(scb_ampdu->max_rxlen,
623 ampdu->max_txlen[mcs][is40][sgi]);
625 /* XXX Fix me to honor real max_rxlen */
626 /* can fix this as soon as ampdu_action() in mac80211.h
627 * gets extra u8buf_size par */
632 CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
633 ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
635 /* rebuild the rspec and rspec_fallback */
636 rspec = RSPEC_MIMORATE;
637 rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
638 if (plcp[0] & MIMO_PLCP_40MHZ)
639 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
641 if (fbr_iscck) /* CCK */
643 CCK_RSPEC(CCK_PHY2MAC_RATE
644 (txh->FragPLCPFallback[0]));
646 rspec_fallback = RSPEC_MIMORATE;
648 txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
649 if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
651 (PHY_TXC1_BW_40MHZ <<
655 if (use_rts || use_cts) {
657 wlc_rspec_to_rts_rspec(wlc, rspec, false,
660 wlc_rspec_to_rts_rspec(wlc, rspec_fallback,
661 false, mimo_ctlchbw);
665 /* if (first mpdu for host agg) */
666 /* test whether to add more */
667 if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
668 (count == f->mcs2ampdu_table[mcs])) {
669 BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
670 " ampdu at %d for mcs %d\n",
671 wlc->pub->unit, count, mcs);
675 if (count == scb_ampdu->max_pdu) {
679 /* check to see if the next pkt is a candidate for aggregation */
680 p = pktq_ppeek(&qi->q, prec);
681 tx_info = IEEE80211_SKB_CB(p); /* tx_info must be checked with current p */
684 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
685 ((u8) (p->priority) == tid)) {
687 plen = brcmu_pkttotlen(p) +
688 AMPDU_MAX_MPDU_OVERHEAD;
689 plen = max(scb_ampdu->min_len, plen);
691 if ((plen + ampdu_len) > maxlen) {
693 wiphy_err(wiphy, "%s: Bogus plen #1\n",
698 /* check if there are enough descriptors available */
699 if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
700 wiphy_err(wiphy, "%s: No fifo space "
705 p = brcmu_pktq_pdeq(&qi->q, prec);
712 ini->tx_in_transit += count;
715 /* patch up the last txh */
716 txh = (d11txh_t *) pkt[count - 1]->data;
717 mcl = le16_to_cpu(txh->MacTxControlLow);
718 mcl &= ~TXC_AMPDU_MASK;
719 mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
720 txh->MacTxControlLow = cpu_to_le16(mcl);
722 /* remove the null delimiter after last mpdu */
723 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
724 txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
725 ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
727 /* remove the pad len from last mpdu */
728 fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
729 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
730 : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
731 ampdu_len -= roundup(len, 4) - len;
733 /* patch up the first txh & plcp */
734 txh = (d11txh_t *) pkt[0]->data;
735 plcp = (u8 *) (txh + 1);
737 WLC_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
738 /* mark plcp to indicate ampdu */
739 WLC_SET_MIMO_PLCP_AMPDU(plcp);
741 /* reset the mixed mode header durations */
744 wlc_calc_lsig_len(wlc, rspec, ampdu_len);
745 txh->MModeLen = cpu_to_le16(mmodelen);
746 preamble_type = WLC_MM_PREAMBLE;
748 if (txh->MModeFbrLen) {
750 wlc_calc_lsig_len(wlc, rspec_fallback, ampdu_len);
751 txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
752 fbr_preamble_type = WLC_MM_PREAMBLE;
755 /* set the preload length */
756 if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
757 dma_len = min(dma_len, f->ampdu_pld_size);
758 txh->PreloadSize = cpu_to_le16(dma_len);
760 txh->PreloadSize = 0;
762 mch = le16_to_cpu(txh->MacTxControlHigh);
764 /* update RTS dur fields */
765 if (use_rts || use_cts) {
767 rts = (struct ieee80211_rts *)&txh->rts_frame;
768 if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
769 TXC_PREAMBLE_RTS_MAIN_SHORT)
770 rts_preamble_type = WLC_SHORT_PREAMBLE;
772 if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
773 TXC_PREAMBLE_RTS_FB_SHORT)
774 rts_fbr_preamble_type = WLC_SHORT_PREAMBLE;
777 wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec,
778 rspec, rts_preamble_type,
779 preamble_type, ampdu_len,
781 rts->duration = cpu_to_le16(durid);
782 durid = wlc_compute_rtscts_dur(wlc, use_cts,
785 rts_fbr_preamble_type,
788 txh->RTSDurFallback = cpu_to_le16(durid);
789 /* set TxFesTimeNormal */
790 txh->TxFesTimeNormal = rts->duration;
791 /* set fallback rate version of TxFesTimeNormal */
792 txh->TxFesTimeFallback = txh->RTSDurFallback;
795 /* set flag and plcp for fallback rate */
797 mch |= TXC_AMPDU_FBR;
798 txh->MacTxControlHigh = cpu_to_le16(mch);
799 WLC_SET_MIMO_PLCP_AMPDU(plcp);
800 WLC_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
803 BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
804 wlc->pub->unit, count, ampdu_len);
806 /* inform rate_sel if it this is a rate probe pkt */
807 frameid = le16_to_cpu(txh->TxFrameID);
808 if (frameid & TXFID_RATE_PROBE_MASK) {
809 wiphy_err(wiphy, "%s: XXX what to do with "
810 "TXFID_RATE_PROBE_MASK!?\n", __func__);
812 for (i = 0; i < count; i++)
813 wlc_txfifo(wlc, fifo, pkt[i], i == (count - 1),
814 ampdu->txpkt_weight);
822 wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
823 struct sk_buff *p, tx_status_t *txs)
825 scb_ampdu_t *scb_ampdu;
826 struct wlc_info *wlc = ampdu->wlc;
827 scb_ampdu_tid_ini_t *ini;
829 struct ieee80211_tx_info *tx_info;
831 tx_info = IEEE80211_SKB_CB(p);
833 /* BMAC_NOTE: For the split driver, second level txstatus comes later
834 * So if the ACK was received then wait for the second level else just
837 if (txs->status & TX_STATUS_ACK_RCV) {
840 /* wait till the next 8 bytes of txstatus is available */
841 while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
844 if (status_delay > 10) {
845 return; /* error condition */
849 s2 = R_REG(&wlc->regs->frmtxstatus2);
853 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
854 ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
855 wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
857 /* loop through all pkts and free */
858 u8 queue = txs->frameid & TXFID_QUEUE_MASK;
862 tx_info = IEEE80211_SKB_CB(p);
863 txh = (d11txh_t *) p->data;
864 mcl = le16_to_cpu(txh->MacTxControlLow);
865 brcmu_pkt_buf_free_skb(p);
866 /* break out if last packet of ampdu */
867 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
870 p = GETNEXTTXP(wlc, queue);
872 wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
874 wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
878 rate_status(struct wlc_info *wlc, struct ieee80211_tx_info *tx_info,
879 tx_status_t *txs, u8 mcs)
881 struct ieee80211_tx_rate *txrate = tx_info->status.rates;
884 /* clear the rest of the rates */
885 for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
891 #define SHORTNAME "AMPDU status"
894 wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
895 struct sk_buff *p, tx_status_t *txs,
898 scb_ampdu_t *scb_ampdu;
899 struct wlc_info *wlc = ampdu->wlc;
900 scb_ampdu_tid_ini_t *ini;
901 u8 bitmap[8], queue, tid;
904 struct ieee80211_hdr *h;
905 u16 seq, start_seq = 0, bindex, index, mcl;
907 bool ba_recd = false, ack_recd = false;
908 u8 suc_mpdu = 0, tot_mpdu = 0;
910 bool update_rate = true, retry = true, tx_error = false;
913 u8 retry_limit, rr_retry_limit;
914 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
915 struct wiphy *wiphy = wlc->wiphy;
918 u8 hole[AMPDU_MAX_MPDU];
919 memset(hole, 0, sizeof(hole));
922 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
923 tid = (u8) (p->priority);
925 ini = SCB_AMPDU_INI(scb_ampdu, tid);
926 retry_limit = ampdu->retry_limit_tid[tid];
927 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
928 memset(bitmap, 0, sizeof(bitmap));
929 queue = txs->frameid & TXFID_QUEUE_MASK;
930 supr_status = txs->status & TX_STATUS_SUPR_MASK;
932 if (txs->status & TX_STATUS_ACK_RCV) {
933 if (TX_STATUS_SUPR_UF == supr_status) {
937 WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
938 start_seq = txs->sequence >> SEQNUM_SHIFT;
939 bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
940 TX_STATUS_BA_BMAP03_SHIFT;
942 WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
943 WARN_ON(!(s1 & TX_STATUS_AMPDU));
946 (s1 & TX_STATUS_BA_BMAP47_MASK) <<
947 TX_STATUS_BA_BMAP47_SHIFT;
948 bitmap[1] = (s1 >> 8) & 0xff;
949 bitmap[2] = (s1 >> 16) & 0xff;
950 bitmap[3] = (s1 >> 24) & 0xff;
952 bitmap[4] = s2 & 0xff;
953 bitmap[5] = (s2 >> 8) & 0xff;
954 bitmap[6] = (s2 >> 16) & 0xff;
955 bitmap[7] = (s2 >> 24) & 0xff;
961 if (supr_status == TX_STATUS_SUPR_BADCH) {
962 wiphy_err(wiphy, "%s: Pkt tx suppressed, "
963 "illegal channel possibly %d\n",
964 __func__, CHSPEC_CHANNEL(
965 wlc->default_bss->chanspec));
967 if (supr_status != TX_STATUS_SUPR_FRAG)
968 wiphy_err(wiphy, "%s: wlc_ampdu_dotx"
969 "status:supr_status 0x%x\n",
970 __func__, supr_status);
972 /* no need to retry for badch; will fail again */
973 if (supr_status == TX_STATUS_SUPR_BADCH ||
974 supr_status == TX_STATUS_SUPR_EXPTIME) {
976 } else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
977 /* TX underflow : try tuning pre-loading or ampdu size */
978 } else if (supr_status == TX_STATUS_SUPR_FRAG) {
979 /* if there were underflows, but pre-loading is not active,
980 notify rate adaptation.
982 if (wlc_ffpld_check_txfunfl(wlc, prio2fifo[tid])
987 } else if (txs->phyerr) {
989 wiphy_err(wiphy, "wl%d: wlc_ampdu_dotxstatus: tx phy "
990 "error (0x%x)\n", wlc->pub->unit,
994 brcmu_prpkt("txpkt (AMPDU)", p);
995 wlc_print_txdesc((d11txh_t *) p->data);
997 wlc_print_txstatus(txs);
1001 /* loop through all pkts and retry if not acked */
1003 tx_info = IEEE80211_SKB_CB(p);
1004 txh = (d11txh_t *) p->data;
1005 mcl = le16_to_cpu(txh->MacTxControlLow);
1006 plcp = (u8 *) (txh + 1);
1007 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
1008 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
1010 if (tot_mpdu == 0) {
1011 mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
1012 mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
1015 index = TX_SEQ_TO_INDEX(seq);
1018 bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
1019 BCMMSG(wlc->wiphy, "tid %d seq %d,"
1020 " start_seq %d, bindex %d set %d, index %d\n",
1021 tid, seq, start_seq, bindex,
1022 isset(bitmap, bindex), index);
1023 /* if acked then clear bit and free packet */
1024 if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
1025 && isset(bitmap, bindex)) {
1026 ini->tx_in_transit--;
1027 ini->txretry[index] = 0;
1029 /* ampdu_ack_len: number of acked aggregated frames */
1030 /* ampdu_len: number of aggregated frames */
1031 rate_status(wlc, tx_info, txs, mcs);
1032 tx_info->flags |= IEEE80211_TX_STAT_ACK;
1033 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
1034 tx_info->status.ampdu_ack_len =
1035 tx_info->status.ampdu_len = 1;
1037 skb_pull(p, D11_PHY_HDR_LEN);
1038 skb_pull(p, D11_TXH_LEN);
1040 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1046 /* either retransmit or send bar if ack not recd */
1048 struct ieee80211_tx_rate *txrate =
1049 tx_info->status.rates;
1050 if (retry && (txrate[0].count < (int)retry_limit)) {
1051 ini->txretry[index]++;
1052 ini->tx_in_transit--;
1053 /* Use high prededence for retransmit to give some punch */
1054 /* wlc_txq_enq(wlc, scb, p, WLC_PRIO_TO_PREC(tid)); */
1055 wlc_txq_enq(wlc, scb, p,
1056 WLC_PRIO_TO_HI_PREC(tid));
1059 ini->tx_in_transit--;
1060 ieee80211_tx_info_clear_status(tx_info);
1061 tx_info->status.ampdu_ack_len = 0;
1062 tx_info->status.ampdu_len = 1;
1064 IEEE80211_TX_STAT_AMPDU_NO_BACK;
1065 skb_pull(p, D11_PHY_HDR_LEN);
1066 skb_pull(p, D11_TXH_LEN);
1067 wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
1068 "transit %d\n", SHORTNAME, seq,
1069 ini->tx_in_transit);
1070 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1076 /* break out if last packet of ampdu */
1077 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1081 p = GETNEXTTXP(wlc, queue);
1085 /* update rate state */
1086 antselid = wlc_antsel_antsel2id(wlc->asi, mimoantsel);
1088 wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
1091 /* initialize the initiator code for tid */
1092 static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
1093 scb_ampdu_t *scb_ampdu,
1094 u8 tid, bool override)
1096 scb_ampdu_tid_ini_t *ini;
1098 /* check for per-tid control of ampdu */
1099 if (!ampdu->ini_enable[tid]) {
1100 wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
1105 ini = SCB_AMPDU_INI(scb_ampdu, tid);
1107 ini->scb = scb_ampdu->scb;
1108 ini->magic = INI_MAGIC;
1112 static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on)
1114 struct wlc_info *wlc = ampdu->wlc;
1116 wlc->pub->_ampdu = false;
1119 if (!N_ENAB(wlc->pub)) {
1120 wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
1121 "nmode enabled\n", wlc->pub->unit);
1124 if (!wlc_ampdu_cap(ampdu)) {
1125 wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
1126 "ampdu capable\n", wlc->pub->unit);
1129 wlc->pub->_ampdu = on;
1135 static bool wlc_ampdu_cap(struct ampdu_info *ampdu)
1137 if (WLC_PHY_11N_CAP(ampdu->wlc->band))
1143 static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
1147 for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
1148 /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
1150 rate = MCS_RATE(mcs, false, false);
1151 ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
1152 /* 40 MHz, No SGI */
1153 rate = MCS_RATE(mcs, true, false);
1154 ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
1156 rate = MCS_RATE(mcs, false, true);
1157 ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
1159 rate = MCS_RATE(mcs, true, true);
1160 ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
1164 void wlc_ampdu_macaddr_upd(struct wlc_info *wlc)
1166 char template[T_RAM_ACCESS_SZ * 2];
1168 /* driver needs to write the ta in the template; ta is at offset 16 */
1169 memset(template, 0, sizeof(template));
1170 memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1171 wlc_write_template_ram(wlc, (T_BA_TPL_BASE + 16), (T_RAM_ACCESS_SZ * 2),
1175 bool wlc_aggregatable(struct wlc_info *wlc, u8 tid)
1177 return wlc->ampdu->ini_enable[tid];
1180 void wlc_ampdu_shm_upd(struct ampdu_info *ampdu)
1182 struct wlc_info *wlc = ampdu->wlc;
1184 /* Extend ucode internal watchdog timer to match larger received frames */
1185 if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1186 IEEE80211_HT_MAX_AMPDU_64K) {
1187 wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1188 wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1190 wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1191 wlc_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 wlc_ampdu_flush(struct wlc_info *wlc,
1230 struct ieee80211_sta *sta, u16 tid)
1232 struct wlc_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);
1243 wlc_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);