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>
29 #include "phy/phy_hal.h"
35 #define AMPDU_MAX_MPDU 32 /* max number of mpdus in an ampdu */
36 #define AMPDU_NUM_MPDU_LEGACY 16 /* max number of mpdus in an ampdu to a legacy */
37 #define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
38 #define AMPDU_TX_BA_DEF_WSIZE 64 /* default Tx ba window size (in pdu) */
39 #define AMPDU_RX_BA_DEF_WSIZE 64 /* max Rx ba window size (in pdu) */
40 #define AMPDU_RX_BA_MAX_WSIZE 64 /* default Rx ba window size (in pdu) */
41 #define AMPDU_MAX_DUR 5 /* max dur of tx ampdu (in msec) */
42 #define AMPDU_DEF_RETRY_LIMIT 5 /* default tx retry limit */
43 #define AMPDU_DEF_RR_RETRY_LIMIT 2 /* default tx retry limit at reg rate */
44 #define AMPDU_DEF_TXPKT_WEIGHT 2 /* default weight of ampdu in txfifo */
45 #define AMPDU_DEF_FFPLD_RSVD 2048 /* default ffpld reserved bytes */
46 #define AMPDU_INI_FREE 10 /* # of inis to be freed on detach */
47 #define AMPDU_SCB_MAX_RELEASE 20 /* max # of mpdus released at a time */
49 #define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */
50 #define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu
53 #define FFPLD_MPDU_SIZE 1800 /* estimate of maximum mpdu size */
54 #define FFPLD_MAX_MCS 23 /* we don't deal with mcs 32 */
55 #define FFPLD_PLD_INCR 1000 /* increments in bytes */
56 #define FFPLD_MAX_AMPDU_CNT 5000 /* maximum number of ampdu we
57 * accumulate between resets.
60 #define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
62 /* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
63 #define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
64 AMPDU_DELIMITER_LEN + 3\
65 + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
67 /* structure to hold tx fifo information and pre-loading state
68 * counters specific to tx underflows of ampdus
69 * some counters might be redundant with the ones in wlc or ampdu structures.
70 * This allows to maintain a specific state independently of
71 * how often and/or when the wlc counters are updated.
73 typedef struct wlc_fifo_info {
74 u16 ampdu_pld_size; /* number of bytes to be pre-loaded */
75 u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; /* per-mcs max # of mpdus in an ampdu */
76 u16 prev_txfunfl; /* num of underflows last read from the HW macstats counter */
77 u32 accum_txfunfl; /* num of underflows since we modified pld params */
78 u32 accum_txampdu; /* num of tx ampdu since we modified pld params */
79 u32 prev_txampdu; /* previous reading of tx ampdu */
80 u32 dmaxferrate; /* estimated dma avg xfer rate in kbits/sec */
83 /* AMPDU module specific state */
85 struct wlc_info *wlc; /* pointer to main wlc structure */
86 int scb_handle; /* scb cubby handle to retrieve data from scb */
87 u8 ini_enable[AMPDU_MAX_SCB_TID]; /* per-tid initiator enable/disable of ampdu */
88 u8 ba_tx_wsize; /* Tx ba window size (in pdu) */
89 u8 ba_rx_wsize; /* Rx ba window size (in pdu) */
90 u8 retry_limit; /* mpdu transmit retry limit */
91 u8 rr_retry_limit; /* mpdu transmit retry limit at regular rate */
92 u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; /* per-tid mpdu transmit retry limit */
93 /* per-tid mpdu transmit retry limit at regular rate */
94 u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
95 u8 mpdu_density; /* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
96 s8 max_pdu; /* max pdus allowed in ampdu */
97 u8 dur; /* max duration of an ampdu (in msec) */
98 u8 txpkt_weight; /* weight of ampdu in txfifo; reduces rate lag */
99 u8 rx_factor; /* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
100 u32 ffpld_rsvd; /* number of bytes to reserve for preload */
101 u32 max_txlen[MCS_TABLE_SIZE][2][2]; /* max size of ampdu per mcs, bw and sgi */
102 void *ini_free[AMPDU_INI_FREE]; /* array of ini's to be freed on detach */
103 bool mfbr; /* enable multiple fallback rate */
104 u32 tx_max_funl; /* underflows should be kept such that
105 * (tx_max_funfl*underflows) < tx frames
107 wlc_fifo_info_t fifo_tb[NUM_FFPLD_FIFO]; /* table of fifo infos */
111 /* used for flushing ampdu packets */
112 struct cb_del_ampdu_pars {
113 struct ieee80211_sta *sta;
117 #define AMPDU_CLEANUPFLAG_RX (0x1)
118 #define AMPDU_CLEANUPFLAG_TX (0x2)
120 #define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
121 #define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
123 static void wlc_ffpld_init(struct ampdu_info *ampdu);
124 static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int f);
125 static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
127 static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
128 scb_ampdu_t *scb_ampdu,
129 u8 tid, bool override);
130 static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur);
131 static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb);
132 static void scb_ampdu_update_config_all(struct ampdu_info *ampdu);
134 #define wlc_ampdu_txflowcontrol(a, b, c) do {} while (0)
136 static void wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
138 struct sk_buff *p, tx_status_t *txs,
139 u32 frmtxstatus, u32 frmtxstatus2);
140 static bool wlc_ampdu_cap(struct ampdu_info *ampdu);
141 static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on);
143 struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc)
145 struct ampdu_info *ampdu;
148 ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
150 wiphy_err(wlc->wiphy, "wl%d: wlc_ampdu_attach: out of mem\n",
156 for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
157 ampdu->ini_enable[i] = true;
158 /* Disable ampdu for VO by default */
159 ampdu->ini_enable[PRIO_8021D_VO] = false;
160 ampdu->ini_enable[PRIO_8021D_NC] = false;
162 /* Disable ampdu for BK by default since not enough fifo space */
163 ampdu->ini_enable[PRIO_8021D_NONE] = false;
164 ampdu->ini_enable[PRIO_8021D_BK] = false;
166 ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
167 ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
168 ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
169 ampdu->max_pdu = AUTO;
170 ampdu->dur = AMPDU_MAX_DUR;
171 ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
173 ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
174 /* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
175 if (WLCISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
176 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
178 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
179 ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
180 ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
182 for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
183 ampdu->retry_limit_tid[i] = ampdu->retry_limit;
184 ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
187 ampdu_update_max_txlen(ampdu, ampdu->dur);
189 /* try to set ampdu to the default value */
190 wlc_ampdu_set(ampdu, wlc->pub->_ampdu);
192 ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
193 wlc_ffpld_init(ampdu);
198 void wlc_ampdu_detach(struct ampdu_info *ampdu)
205 /* free all ini's which were to be freed on callbacks which were never called */
206 for (i = 0; i < AMPDU_INI_FREE; i++) {
207 kfree(ampdu->ini_free[i]);
210 wlc_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
214 static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb)
216 scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
219 scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
221 /* go back to legacy size if some preloading is occurring */
222 for (i = 0; i < NUM_FFPLD_FIFO; i++) {
223 if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
224 scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
227 /* apply user override */
228 if (ampdu->max_pdu != AUTO)
229 scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
231 scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
233 if (scb_ampdu->max_rxlen)
235 min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 1600);
237 scb_ampdu->release = min(scb_ampdu->release,
238 ampdu->fifo_tb[TX_AC_BE_FIFO].
239 mcs2ampdu_table[FFPLD_MAX_MCS]);
242 static void scb_ampdu_update_config_all(struct ampdu_info *ampdu)
244 scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
247 static void wlc_ffpld_init(struct ampdu_info *ampdu)
250 wlc_fifo_info_t *fifo;
252 for (j = 0; j < NUM_FFPLD_FIFO; j++) {
253 fifo = (ampdu->fifo_tb + j);
254 fifo->ampdu_pld_size = 0;
255 for (i = 0; i <= FFPLD_MAX_MCS; i++)
256 fifo->mcs2ampdu_table[i] = 255;
257 fifo->dmaxferrate = 0;
258 fifo->accum_txampdu = 0;
259 fifo->prev_txfunfl = 0;
260 fifo->accum_txfunfl = 0;
265 /* evaluate the dma transfer rate using the tx underflows as feedback.
266 * If necessary, increase tx fifo preloading. If not enough,
267 * decrease maximum ampdu size for each mcs till underflows stop
268 * Return 1 if pre-loading not active, -1 if not an underflow event,
269 * 0 if pre-loading module took care of the event.
271 static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int fid)
273 struct ampdu_info *ampdu = wlc->ampdu;
274 u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
277 u32 current_ampdu_cnt = 0;
280 wlc_fifo_info_t *fifo = (ampdu->fifo_tb + fid);
284 /* return if we got here for a different reason than underflows */
287 M_UCODE_MACSTAT + offsetof(macstat_t, txfunfl[fid]));
288 new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
289 if (new_txunfl == 0) {
290 BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
293 fifo->prev_txfunfl = cur_txunfl;
295 if (!ampdu->tx_max_funl)
298 /* check if fifo is big enough */
299 if (wlc_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz)) {
303 if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
306 max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
307 fifo->accum_txfunfl += new_txunfl;
309 /* we need to wait for at least 10 underflows */
310 if (fifo->accum_txfunfl < 10)
313 BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n",
314 current_ampdu_cnt, fifo->accum_txfunfl);
317 compute the current ratio of tx unfl per ampdu.
318 When the current ampdu count becomes too
319 big while the ratio remains small, we reset
320 the current count in order to not
321 introduce too big of a latency in detecting a
322 large amount of tx underflows later.
325 txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
327 if (txunfl_ratio > ampdu->tx_max_funl) {
328 if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
329 fifo->accum_txfunfl = 0;
334 min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
336 /* In case max value max_pdu is already lower than
337 the fifo depth, there is nothing more we can do.
340 if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
341 fifo->accum_txfunfl = 0;
345 if (fifo->ampdu_pld_size < max_pld_size) {
347 /* increment by TX_FIFO_PLD_INC bytes */
348 fifo->ampdu_pld_size += FFPLD_PLD_INCR;
349 if (fifo->ampdu_pld_size > max_pld_size)
350 fifo->ampdu_pld_size = max_pld_size;
352 /* update scb release size */
353 scb_ampdu_update_config_all(ampdu);
356 compute a new dma xfer rate for max_mpdu @ max mcs.
357 This is the minimum dma rate that
358 can achieve no underflow condition for the current mpdu size.
360 /* note : we divide/multiply by 100 to avoid integer overflows */
363 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
364 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
366 BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
367 "pre-load size %d\n",
368 fifo->dmaxferrate, fifo->ampdu_pld_size);
371 /* decrease ampdu size */
372 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
373 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
374 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
375 AMPDU_NUM_MPDU_LEGACY - 1;
377 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
379 /* recompute the table */
380 wlc_ffpld_calc_mcs2ampdu_table(ampdu, fid);
382 /* update scb release size */
383 scb_ampdu_update_config_all(ampdu);
386 fifo->accum_txfunfl = 0;
390 static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
393 u32 phy_rate, dma_rate, tmp;
395 wlc_fifo_info_t *fifo = (ampdu->fifo_tb + f);
397 /* recompute the dma rate */
398 /* note : we divide/multiply by 100 to avoid integer overflows */
400 min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
401 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
404 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
405 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
406 fifo->dmaxferrate = dma_rate;
408 /* fill up the mcs2ampdu table; do not recalc the last mcs */
409 dma_rate = dma_rate >> 7;
410 for (i = 0; i < FFPLD_MAX_MCS; i++) {
411 /* shifting to keep it within integer range */
412 phy_rate = MCS_RATE(i, true, false) >> 7;
413 if (phy_rate > dma_rate) {
414 tmp = ((fifo->ampdu_pld_size * phy_rate) /
415 ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
416 tmp = min_t(u32, tmp, 255);
417 fifo->mcs2ampdu_table[i] = (u8) tmp;
423 wlc_ampdu_agg(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p,
426 scb_ampdu_t *scb_ampdu;
427 scb_ampdu_tid_ini_t *ini;
428 u8 tid = (u8) (p->priority);
430 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
432 /* initialize initiator on first packet; sends addba req */
433 ini = SCB_AMPDU_INI(scb_ampdu, tid);
434 if (ini->magic != INI_MAGIC) {
435 ini = wlc_ampdu_init_tid_ini(ampdu, scb_ampdu, tid, false);
441 wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
442 struct sk_buff **pdu, int prec)
444 struct wlc_info *wlc;
445 struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
448 u8 preamble_type = WLC_GF_PREAMBLE;
449 u8 fbr_preamble_type = WLC_GF_PREAMBLE;
450 u8 rts_preamble_type = WLC_LONG_PREAMBLE;
451 u8 rts_fbr_preamble_type = WLC_LONG_PREAMBLE;
453 bool rr = true, fbr = false;
454 uint i, count = 0, fifo, seg_cnt = 0;
455 u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
456 u32 ampdu_len, maxlen = 0;
457 d11txh_t *txh = NULL;
459 struct ieee80211_hdr *h;
461 scb_ampdu_t *scb_ampdu;
462 scb_ampdu_tid_ini_t *ini;
464 bool use_rts = false, use_cts = false;
465 ratespec_t rspec = 0, rspec_fallback = 0;
466 ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
467 u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
468 struct ieee80211_rts *rts;
472 struct ieee80211_tx_info *tx_info;
480 tid = (u8) (p->priority);
482 f = ampdu->fifo_tb + prio2fifo[tid];
484 scb = wlc->pub->global_scb;
485 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
486 ini = &scb_ampdu->ini[tid];
488 /* Let pressure continue to build ... */
489 qlen = pktq_plen(&qi->q, prec);
490 if (ini->tx_in_transit > 0 && qlen < scb_ampdu->max_pdu) {
494 wlc_ampdu_agg(ampdu, scb, p, tid);
496 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
500 struct ieee80211_tx_rate *txrate;
502 tx_info = IEEE80211_SKB_CB(p);
503 txrate = tx_info->status.rates;
505 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
506 err = wlc_prep_pdu(wlc, p, &fifo);
508 wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
516 wiphy_err(wiphy, "wl%d: wlc_sendampdu: "
517 "prep_xdu retry; seq 0x%x\n",
518 wlc->pub->unit, seq);
523 /* error in the packet; reject it */
524 wiphy_err(wiphy, "wl%d: wlc_sendampdu: prep_xdu "
525 "rejected; seq 0x%x\n", wlc->pub->unit, seq);
530 /* pkt is good to be aggregated */
531 txh = (d11txh_t *) p->data;
532 plcp = (u8 *) (txh + 1);
533 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
534 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
535 index = TX_SEQ_TO_INDEX(seq);
537 /* check mcl fields and test whether it can be agg'd */
538 mcl = le16_to_cpu(txh->MacTxControlLow);
539 mcl &= ~TXC_AMPDU_MASK;
540 fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
541 txh->PreloadSize = 0; /* always default to 0 */
543 /* Handle retry limits */
544 if (txrate[0].count <= rr_retry_limit) {
554 /* extract the length info */
555 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
556 : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
558 /* retrieve null delimiter count */
559 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
562 BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
563 wlc->pub->unit, count, len);
566 * aggregateable mpdu. For ucode/hw agg,
567 * test whether need to break or change the epoch
570 mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
571 /* refill the bits since might be a retx mpdu */
572 mcl |= TXC_STARTMSDU;
573 rts = (struct ieee80211_rts *)&txh->rts_frame;
575 if (ieee80211_is_rts(rts->frame_control)) {
579 if (ieee80211_is_cts(rts->frame_control)) {
584 mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
585 mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
588 len = roundup(len, 4);
589 ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
591 dma_len += (u16) brcmu_pkttotlen(p);
593 BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
594 " seg_cnt %d null delim %d\n",
595 wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
597 txh->MacTxControlLow = cpu_to_le16(mcl);
599 /* this packet is added */
602 /* patch the first MPDU */
604 u8 plcp0, plcp3, is40, sgi;
605 struct ieee80211_sta *sta;
607 sta = tx_info->control.sta;
613 plcp0 = txh->FragPLCPFallback[0];
614 plcp3 = txh->FragPLCPFallback[3];
617 is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
618 sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
619 mcs = plcp0 & ~MIMO_PLCP_40MHZ;
621 min(scb_ampdu->max_rxlen,
622 ampdu->max_txlen[mcs][is40][sgi]);
624 /* XXX Fix me to honor real max_rxlen */
625 /* can fix this as soon as ampdu_action() in mac80211.h
626 * gets extra u8buf_size par */
631 CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
632 ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
634 /* rebuild the rspec and rspec_fallback */
635 rspec = RSPEC_MIMORATE;
636 rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
637 if (plcp[0] & MIMO_PLCP_40MHZ)
638 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
640 if (fbr_iscck) /* CCK */
642 CCK_RSPEC(CCK_PHY2MAC_RATE
643 (txh->FragPLCPFallback[0]));
645 rspec_fallback = RSPEC_MIMORATE;
647 txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
648 if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
650 (PHY_TXC1_BW_40MHZ <<
654 if (use_rts || use_cts) {
656 wlc_rspec_to_rts_rspec(wlc, rspec, false,
659 wlc_rspec_to_rts_rspec(wlc, rspec_fallback,
660 false, mimo_ctlchbw);
664 /* if (first mpdu for host agg) */
665 /* test whether to add more */
666 if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
667 (count == f->mcs2ampdu_table[mcs])) {
668 BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
669 " ampdu at %d for mcs %d\n",
670 wlc->pub->unit, count, mcs);
674 if (count == scb_ampdu->max_pdu) {
678 /* check to see if the next pkt is a candidate for aggregation */
679 p = pktq_ppeek(&qi->q, prec);
680 tx_info = IEEE80211_SKB_CB(p); /* tx_info must be checked with current p */
683 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
684 ((u8) (p->priority) == tid)) {
686 plen = brcmu_pkttotlen(p) +
687 AMPDU_MAX_MPDU_OVERHEAD;
688 plen = max(scb_ampdu->min_len, plen);
690 if ((plen + ampdu_len) > maxlen) {
692 wiphy_err(wiphy, "%s: Bogus plen #1\n",
697 /* check if there are enough descriptors available */
698 if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
699 wiphy_err(wiphy, "%s: No fifo space "
704 p = brcmu_pktq_pdeq(&qi->q, prec);
711 ini->tx_in_transit += count;
714 /* patch up the last txh */
715 txh = (d11txh_t *) pkt[count - 1]->data;
716 mcl = le16_to_cpu(txh->MacTxControlLow);
717 mcl &= ~TXC_AMPDU_MASK;
718 mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
719 txh->MacTxControlLow = cpu_to_le16(mcl);
721 /* remove the null delimiter after last mpdu */
722 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
723 txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
724 ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
726 /* remove the pad len from last mpdu */
727 fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
728 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
729 : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
730 ampdu_len -= roundup(len, 4) - len;
732 /* patch up the first txh & plcp */
733 txh = (d11txh_t *) pkt[0]->data;
734 plcp = (u8 *) (txh + 1);
736 WLC_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
737 /* mark plcp to indicate ampdu */
738 WLC_SET_MIMO_PLCP_AMPDU(plcp);
740 /* reset the mixed mode header durations */
743 wlc_calc_lsig_len(wlc, rspec, ampdu_len);
744 txh->MModeLen = cpu_to_le16(mmodelen);
745 preamble_type = WLC_MM_PREAMBLE;
747 if (txh->MModeFbrLen) {
749 wlc_calc_lsig_len(wlc, rspec_fallback, ampdu_len);
750 txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
751 fbr_preamble_type = WLC_MM_PREAMBLE;
754 /* set the preload length */
755 if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
756 dma_len = min(dma_len, f->ampdu_pld_size);
757 txh->PreloadSize = cpu_to_le16(dma_len);
759 txh->PreloadSize = 0;
761 mch = le16_to_cpu(txh->MacTxControlHigh);
763 /* update RTS dur fields */
764 if (use_rts || use_cts) {
766 rts = (struct ieee80211_rts *)&txh->rts_frame;
767 if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
768 TXC_PREAMBLE_RTS_MAIN_SHORT)
769 rts_preamble_type = WLC_SHORT_PREAMBLE;
771 if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
772 TXC_PREAMBLE_RTS_FB_SHORT)
773 rts_fbr_preamble_type = WLC_SHORT_PREAMBLE;
776 wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec,
777 rspec, rts_preamble_type,
778 preamble_type, ampdu_len,
780 rts->duration = cpu_to_le16(durid);
781 durid = wlc_compute_rtscts_dur(wlc, use_cts,
784 rts_fbr_preamble_type,
787 txh->RTSDurFallback = cpu_to_le16(durid);
788 /* set TxFesTimeNormal */
789 txh->TxFesTimeNormal = rts->duration;
790 /* set fallback rate version of TxFesTimeNormal */
791 txh->TxFesTimeFallback = txh->RTSDurFallback;
794 /* set flag and plcp for fallback rate */
796 mch |= TXC_AMPDU_FBR;
797 txh->MacTxControlHigh = cpu_to_le16(mch);
798 WLC_SET_MIMO_PLCP_AMPDU(plcp);
799 WLC_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
802 BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
803 wlc->pub->unit, count, ampdu_len);
805 /* inform rate_sel if it this is a rate probe pkt */
806 frameid = le16_to_cpu(txh->TxFrameID);
807 if (frameid & TXFID_RATE_PROBE_MASK) {
808 wiphy_err(wiphy, "%s: XXX what to do with "
809 "TXFID_RATE_PROBE_MASK!?\n", __func__);
811 for (i = 0; i < count; i++)
812 wlc_txfifo(wlc, fifo, pkt[i], i == (count - 1),
813 ampdu->txpkt_weight);
821 wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
822 struct sk_buff *p, tx_status_t *txs)
824 scb_ampdu_t *scb_ampdu;
825 struct wlc_info *wlc = ampdu->wlc;
826 scb_ampdu_tid_ini_t *ini;
828 struct ieee80211_tx_info *tx_info;
830 tx_info = IEEE80211_SKB_CB(p);
832 /* BMAC_NOTE: For the split driver, second level txstatus comes later
833 * So if the ACK was received then wait for the second level else just
836 if (txs->status & TX_STATUS_ACK_RCV) {
839 /* wait till the next 8 bytes of txstatus is available */
840 while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
843 if (status_delay > 10) {
844 return; /* error condition */
848 s2 = R_REG(&wlc->regs->frmtxstatus2);
852 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
853 ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
854 wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
856 /* loop through all pkts and free */
857 u8 queue = txs->frameid & TXFID_QUEUE_MASK;
861 tx_info = IEEE80211_SKB_CB(p);
862 txh = (d11txh_t *) p->data;
863 mcl = le16_to_cpu(txh->MacTxControlLow);
864 brcmu_pkt_buf_free_skb(p);
865 /* break out if last packet of ampdu */
866 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
869 p = GETNEXTTXP(wlc, queue);
871 wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
873 wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
877 rate_status(struct wlc_info *wlc, struct ieee80211_tx_info *tx_info,
878 tx_status_t *txs, u8 mcs)
880 struct ieee80211_tx_rate *txrate = tx_info->status.rates;
883 /* clear the rest of the rates */
884 for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
890 #define SHORTNAME "AMPDU status"
893 wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
894 struct sk_buff *p, tx_status_t *txs,
897 scb_ampdu_t *scb_ampdu;
898 struct wlc_info *wlc = ampdu->wlc;
899 scb_ampdu_tid_ini_t *ini;
900 u8 bitmap[8], queue, tid;
903 struct ieee80211_hdr *h;
904 u16 seq, start_seq = 0, bindex, index, mcl;
906 bool ba_recd = false, ack_recd = false;
907 u8 suc_mpdu = 0, tot_mpdu = 0;
909 bool update_rate = true, retry = true, tx_error = false;
912 u8 retry_limit, rr_retry_limit;
913 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
914 struct wiphy *wiphy = wlc->wiphy;
917 u8 hole[AMPDU_MAX_MPDU];
918 memset(hole, 0, sizeof(hole));
921 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
922 tid = (u8) (p->priority);
924 ini = SCB_AMPDU_INI(scb_ampdu, tid);
925 retry_limit = ampdu->retry_limit_tid[tid];
926 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
927 memset(bitmap, 0, sizeof(bitmap));
928 queue = txs->frameid & TXFID_QUEUE_MASK;
929 supr_status = txs->status & TX_STATUS_SUPR_MASK;
931 if (txs->status & TX_STATUS_ACK_RCV) {
932 if (TX_STATUS_SUPR_UF == supr_status) {
936 WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
937 start_seq = txs->sequence >> SEQNUM_SHIFT;
938 bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
939 TX_STATUS_BA_BMAP03_SHIFT;
941 WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
942 WARN_ON(!(s1 & TX_STATUS_AMPDU));
945 (s1 & TX_STATUS_BA_BMAP47_MASK) <<
946 TX_STATUS_BA_BMAP47_SHIFT;
947 bitmap[1] = (s1 >> 8) & 0xff;
948 bitmap[2] = (s1 >> 16) & 0xff;
949 bitmap[3] = (s1 >> 24) & 0xff;
951 bitmap[4] = s2 & 0xff;
952 bitmap[5] = (s2 >> 8) & 0xff;
953 bitmap[6] = (s2 >> 16) & 0xff;
954 bitmap[7] = (s2 >> 24) & 0xff;
960 if (supr_status == TX_STATUS_SUPR_BADCH) {
961 wiphy_err(wiphy, "%s: Pkt tx suppressed, "
962 "illegal channel possibly %d\n",
963 __func__, CHSPEC_CHANNEL(
964 wlc->default_bss->chanspec));
966 if (supr_status != TX_STATUS_SUPR_FRAG)
967 wiphy_err(wiphy, "%s: wlc_ampdu_dotx"
968 "status:supr_status 0x%x\n",
969 __func__, supr_status);
971 /* no need to retry for badch; will fail again */
972 if (supr_status == TX_STATUS_SUPR_BADCH ||
973 supr_status == TX_STATUS_SUPR_EXPTIME) {
975 } else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
976 /* TX underflow : try tuning pre-loading or ampdu size */
977 } else if (supr_status == TX_STATUS_SUPR_FRAG) {
978 /* if there were underflows, but pre-loading is not active,
979 notify rate adaptation.
981 if (wlc_ffpld_check_txfunfl(wlc, prio2fifo[tid])
986 } else if (txs->phyerr) {
988 wiphy_err(wiphy, "wl%d: wlc_ampdu_dotxstatus: tx phy "
989 "error (0x%x)\n", wlc->pub->unit,
993 brcmu_prpkt("txpkt (AMPDU)", p);
994 wlc_print_txdesc((d11txh_t *) p->data);
996 wlc_print_txstatus(txs);
1000 /* loop through all pkts and retry if not acked */
1002 tx_info = IEEE80211_SKB_CB(p);
1003 txh = (d11txh_t *) p->data;
1004 mcl = le16_to_cpu(txh->MacTxControlLow);
1005 plcp = (u8 *) (txh + 1);
1006 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
1007 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
1009 if (tot_mpdu == 0) {
1010 mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
1011 mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
1014 index = TX_SEQ_TO_INDEX(seq);
1017 bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
1018 BCMMSG(wlc->wiphy, "tid %d seq %d,"
1019 " start_seq %d, bindex %d set %d, index %d\n",
1020 tid, seq, start_seq, bindex,
1021 isset(bitmap, bindex), index);
1022 /* if acked then clear bit and free packet */
1023 if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
1024 && isset(bitmap, bindex)) {
1025 ini->tx_in_transit--;
1026 ini->txretry[index] = 0;
1028 /* ampdu_ack_len: number of acked aggregated frames */
1029 /* ampdu_len: number of aggregated frames */
1030 rate_status(wlc, tx_info, txs, mcs);
1031 tx_info->flags |= IEEE80211_TX_STAT_ACK;
1032 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
1033 tx_info->status.ampdu_ack_len =
1034 tx_info->status.ampdu_len = 1;
1036 skb_pull(p, D11_PHY_HDR_LEN);
1037 skb_pull(p, D11_TXH_LEN);
1039 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1045 /* either retransmit or send bar if ack not recd */
1047 struct ieee80211_tx_rate *txrate =
1048 tx_info->status.rates;
1049 if (retry && (txrate[0].count < (int)retry_limit)) {
1050 ini->txretry[index]++;
1051 ini->tx_in_transit--;
1052 /* Use high prededence for retransmit to give some punch */
1053 /* wlc_txq_enq(wlc, scb, p, WLC_PRIO_TO_PREC(tid)); */
1054 wlc_txq_enq(wlc, scb, p,
1055 WLC_PRIO_TO_HI_PREC(tid));
1058 ini->tx_in_transit--;
1059 ieee80211_tx_info_clear_status(tx_info);
1060 tx_info->status.ampdu_ack_len = 0;
1061 tx_info->status.ampdu_len = 1;
1063 IEEE80211_TX_STAT_AMPDU_NO_BACK;
1064 skb_pull(p, D11_PHY_HDR_LEN);
1065 skb_pull(p, D11_TXH_LEN);
1066 wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
1067 "transit %d\n", SHORTNAME, seq,
1068 ini->tx_in_transit);
1069 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1075 /* break out if last packet of ampdu */
1076 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1080 p = GETNEXTTXP(wlc, queue);
1084 /* update rate state */
1085 antselid = wlc_antsel_antsel2id(wlc->asi, mimoantsel);
1087 wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
1090 /* initialize the initiator code for tid */
1091 static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
1092 scb_ampdu_t *scb_ampdu,
1093 u8 tid, bool override)
1095 scb_ampdu_tid_ini_t *ini;
1097 /* check for per-tid control of ampdu */
1098 if (!ampdu->ini_enable[tid]) {
1099 wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
1104 ini = SCB_AMPDU_INI(scb_ampdu, tid);
1106 ini->scb = scb_ampdu->scb;
1107 ini->magic = INI_MAGIC;
1111 static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on)
1113 struct wlc_info *wlc = ampdu->wlc;
1115 wlc->pub->_ampdu = false;
1118 if (!N_ENAB(wlc->pub)) {
1119 wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
1120 "nmode enabled\n", wlc->pub->unit);
1123 if (!wlc_ampdu_cap(ampdu)) {
1124 wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
1125 "ampdu capable\n", wlc->pub->unit);
1128 wlc->pub->_ampdu = on;
1134 static bool wlc_ampdu_cap(struct ampdu_info *ampdu)
1136 if (WLC_PHY_11N_CAP(ampdu->wlc->band))
1142 static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
1146 for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
1147 /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
1149 rate = MCS_RATE(mcs, false, false);
1150 ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
1151 /* 40 MHz, No SGI */
1152 rate = MCS_RATE(mcs, true, false);
1153 ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
1155 rate = MCS_RATE(mcs, false, true);
1156 ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
1158 rate = MCS_RATE(mcs, true, true);
1159 ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
1163 void wlc_ampdu_macaddr_upd(struct wlc_info *wlc)
1165 char template[T_RAM_ACCESS_SZ * 2];
1167 /* driver needs to write the ta in the template; ta is at offset 16 */
1168 memset(template, 0, sizeof(template));
1169 memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1170 wlc_write_template_ram(wlc, (T_BA_TPL_BASE + 16), (T_RAM_ACCESS_SZ * 2),
1174 bool wlc_aggregatable(struct wlc_info *wlc, u8 tid)
1176 return wlc->ampdu->ini_enable[tid];
1179 void wlc_ampdu_shm_upd(struct ampdu_info *ampdu)
1181 struct wlc_info *wlc = ampdu->wlc;
1183 /* Extend ucode internal watchdog timer to match larger received frames */
1184 if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1185 IEEE80211_HT_MAX_AMPDU_64K) {
1186 wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1187 wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1189 wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1190 wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1195 * callback function that helps flushing ampdu packets from a priority queue
1197 static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
1199 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
1200 struct cb_del_ampdu_pars *ampdu_pars =
1201 (struct cb_del_ampdu_pars *)arg_a;
1204 rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
1205 rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
1206 tx_info->control.sta == ampdu_pars->sta);
1207 rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
1212 * callback function that helps invalidating ampdu packets in a DMA queue
1214 static void dma_cb_fn_ampdu(void *txi, void *arg_a)
1216 struct ieee80211_sta *sta = arg_a;
1217 struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
1219 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
1220 (tx_info->control.sta == sta || sta == NULL))
1221 tx_info->control.sta = NULL;
1225 * When a remote party is no longer available for ampdu communication, any
1226 * pending tx ampdu packets in the driver have to be flushed.
1228 void wlc_ampdu_flush(struct wlc_info *wlc,
1229 struct ieee80211_sta *sta, u16 tid)
1231 struct wlc_txq_info *qi = wlc->pkt_queue;
1232 struct pktq *pq = &qi->q;
1234 struct cb_del_ampdu_pars ampdu_pars;
1236 ampdu_pars.sta = sta;
1237 ampdu_pars.tid = tid;
1238 for (prec = 0; prec < pq->num_prec; prec++) {
1239 brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
1240 (void *)&du_pars);
1242 wlc_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);