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>
26 #include "wlc_types.h"
32 #include "phy/wlc_phy_hal.h"
33 #include "wlc_antsel.h"
34 #include "wl_export.h"
36 #include "wlc_channel.h"
38 #include "wlc_ampdu.h"
40 #define AMPDU_MAX_MPDU 32 /* max number of mpdus in an ampdu */
41 #define AMPDU_NUM_MPDU_LEGACY 16 /* max number of mpdus in an ampdu to a legacy */
42 #define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
43 #define AMPDU_TX_BA_DEF_WSIZE 64 /* default Tx ba window size (in pdu) */
44 #define AMPDU_RX_BA_DEF_WSIZE 64 /* max Rx ba window size (in pdu) */
45 #define AMPDU_RX_BA_MAX_WSIZE 64 /* default Rx ba window size (in pdu) */
46 #define AMPDU_MAX_DUR 5 /* max dur of tx ampdu (in msec) */
47 #define AMPDU_DEF_RETRY_LIMIT 5 /* default tx retry limit */
48 #define AMPDU_DEF_RR_RETRY_LIMIT 2 /* default tx retry limit at reg rate */
49 #define AMPDU_DEF_TXPKT_WEIGHT 2 /* default weight of ampdu in txfifo */
50 #define AMPDU_DEF_FFPLD_RSVD 2048 /* default ffpld reserved bytes */
51 #define AMPDU_INI_FREE 10 /* # of inis to be freed on detach */
52 #define AMPDU_SCB_MAX_RELEASE 20 /* max # of mpdus released at a time */
54 #define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */
55 #define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu
58 #define FFPLD_MPDU_SIZE 1800 /* estimate of maximum mpdu size */
59 #define FFPLD_MAX_MCS 23 /* we don't deal with mcs 32 */
60 #define FFPLD_PLD_INCR 1000 /* increments in bytes */
61 #define FFPLD_MAX_AMPDU_CNT 5000 /* maximum number of ampdu we
62 * accumulate between resets.
65 #define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
67 /* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
68 #define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
69 AMPDU_DELIMITER_LEN + 3\
70 + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
72 /* structure to hold tx fifo information and pre-loading state
73 * counters specific to tx underflows of ampdus
74 * some counters might be redundant with the ones in wlc or ampdu structures.
75 * This allows to maintain a specific state independently of
76 * how often and/or when the wlc counters are updated.
78 typedef struct wlc_fifo_info {
79 u16 ampdu_pld_size; /* number of bytes to be pre-loaded */
80 u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; /* per-mcs max # of mpdus in an ampdu */
81 u16 prev_txfunfl; /* num of underflows last read from the HW macstats counter */
82 u32 accum_txfunfl; /* num of underflows since we modified pld params */
83 u32 accum_txampdu; /* num of tx ampdu since we modified pld params */
84 u32 prev_txampdu; /* previous reading of tx ampdu */
85 u32 dmaxferrate; /* estimated dma avg xfer rate in kbits/sec */
88 /* AMPDU module specific state */
90 struct wlc_info *wlc; /* pointer to main wlc structure */
91 int scb_handle; /* scb cubby handle to retrieve data from scb */
92 u8 ini_enable[AMPDU_MAX_SCB_TID]; /* per-tid initiator enable/disable of ampdu */
93 u8 ba_tx_wsize; /* Tx ba window size (in pdu) */
94 u8 ba_rx_wsize; /* Rx ba window size (in pdu) */
95 u8 retry_limit; /* mpdu transmit retry limit */
96 u8 rr_retry_limit; /* mpdu transmit retry limit at regular rate */
97 u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; /* per-tid mpdu transmit retry limit */
98 /* per-tid mpdu transmit retry limit at regular rate */
99 u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
100 u8 mpdu_density; /* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
101 s8 max_pdu; /* max pdus allowed in ampdu */
102 u8 dur; /* max duration of an ampdu (in msec) */
103 u8 txpkt_weight; /* weight of ampdu in txfifo; reduces rate lag */
104 u8 rx_factor; /* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
105 u32 ffpld_rsvd; /* number of bytes to reserve for preload */
106 u32 max_txlen[MCS_TABLE_SIZE][2][2]; /* max size of ampdu per mcs, bw and sgi */
107 void *ini_free[AMPDU_INI_FREE]; /* array of ini's to be freed on detach */
108 bool mfbr; /* enable multiple fallback rate */
109 u32 tx_max_funl; /* underflows should be kept such that
110 * (tx_max_funfl*underflows) < tx frames
112 wlc_fifo_info_t fifo_tb[NUM_FFPLD_FIFO]; /* table of fifo infos */
116 /* used for flushing ampdu packets */
117 struct cb_del_ampdu_pars {
118 struct ieee80211_sta *sta;
122 #define AMPDU_CLEANUPFLAG_RX (0x1)
123 #define AMPDU_CLEANUPFLAG_TX (0x2)
125 #define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
126 #define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
128 static void wlc_ffpld_init(struct ampdu_info *ampdu);
129 static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int f);
130 static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
132 static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
133 scb_ampdu_t *scb_ampdu,
134 u8 tid, bool override);
135 static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur);
136 static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb);
137 static void scb_ampdu_update_config_all(struct ampdu_info *ampdu);
139 #define wlc_ampdu_txflowcontrol(a, b, c) do {} while (0)
141 static void wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
143 struct sk_buff *p, tx_status_t *txs,
144 u32 frmtxstatus, u32 frmtxstatus2);
145 static bool wlc_ampdu_cap(struct ampdu_info *ampdu);
146 static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on);
148 struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc)
150 struct ampdu_info *ampdu;
153 ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
155 wiphy_err(wlc->wiphy, "wl%d: wlc_ampdu_attach: out of mem\n",
161 for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
162 ampdu->ini_enable[i] = true;
163 /* Disable ampdu for VO by default */
164 ampdu->ini_enable[PRIO_8021D_VO] = false;
165 ampdu->ini_enable[PRIO_8021D_NC] = false;
167 /* Disable ampdu for BK by default since not enough fifo space */
168 ampdu->ini_enable[PRIO_8021D_NONE] = false;
169 ampdu->ini_enable[PRIO_8021D_BK] = false;
171 ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
172 ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
173 ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
174 ampdu->max_pdu = AUTO;
175 ampdu->dur = AMPDU_MAX_DUR;
176 ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
178 ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
179 /* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
180 if (WLCISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
181 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
183 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
184 ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
185 ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
187 for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
188 ampdu->retry_limit_tid[i] = ampdu->retry_limit;
189 ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
192 ampdu_update_max_txlen(ampdu, ampdu->dur);
194 /* try to set ampdu to the default value */
195 wlc_ampdu_set(ampdu, wlc->pub->_ampdu);
197 ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
198 wlc_ffpld_init(ampdu);
203 void wlc_ampdu_detach(struct ampdu_info *ampdu)
210 /* free all ini's which were to be freed on callbacks which were never called */
211 for (i = 0; i < AMPDU_INI_FREE; i++) {
212 kfree(ampdu->ini_free[i]);
215 wlc_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
219 static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb)
221 scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
224 scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
226 /* go back to legacy size if some preloading is occurring */
227 for (i = 0; i < NUM_FFPLD_FIFO; i++) {
228 if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
229 scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
232 /* apply user override */
233 if (ampdu->max_pdu != AUTO)
234 scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
236 scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
238 if (scb_ampdu->max_rxlen)
240 min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 1600);
242 scb_ampdu->release = min(scb_ampdu->release,
243 ampdu->fifo_tb[TX_AC_BE_FIFO].
244 mcs2ampdu_table[FFPLD_MAX_MCS]);
247 static void scb_ampdu_update_config_all(struct ampdu_info *ampdu)
249 scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
252 static void wlc_ffpld_init(struct ampdu_info *ampdu)
255 wlc_fifo_info_t *fifo;
257 for (j = 0; j < NUM_FFPLD_FIFO; j++) {
258 fifo = (ampdu->fifo_tb + j);
259 fifo->ampdu_pld_size = 0;
260 for (i = 0; i <= FFPLD_MAX_MCS; i++)
261 fifo->mcs2ampdu_table[i] = 255;
262 fifo->dmaxferrate = 0;
263 fifo->accum_txampdu = 0;
264 fifo->prev_txfunfl = 0;
265 fifo->accum_txfunfl = 0;
270 /* evaluate the dma transfer rate using the tx underflows as feedback.
271 * If necessary, increase tx fifo preloading. If not enough,
272 * decrease maximum ampdu size for each mcs till underflows stop
273 * Return 1 if pre-loading not active, -1 if not an underflow event,
274 * 0 if pre-loading module took care of the event.
276 static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int fid)
278 struct ampdu_info *ampdu = wlc->ampdu;
279 u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
282 u32 current_ampdu_cnt = 0;
285 wlc_fifo_info_t *fifo = (ampdu->fifo_tb + fid);
289 /* return if we got here for a different reason than underflows */
292 M_UCODE_MACSTAT + offsetof(macstat_t, txfunfl[fid]));
293 new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
294 if (new_txunfl == 0) {
295 BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
298 fifo->prev_txfunfl = cur_txunfl;
300 if (!ampdu->tx_max_funl)
303 /* check if fifo is big enough */
304 if (wlc_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz)) {
308 if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
311 max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
312 fifo->accum_txfunfl += new_txunfl;
314 /* we need to wait for at least 10 underflows */
315 if (fifo->accum_txfunfl < 10)
318 BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n",
319 current_ampdu_cnt, fifo->accum_txfunfl);
322 compute the current ratio of tx unfl per ampdu.
323 When the current ampdu count becomes too
324 big while the ratio remains small, we reset
325 the current count in order to not
326 introduce too big of a latency in detecting a
327 large amount of tx underflows later.
330 txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
332 if (txunfl_ratio > ampdu->tx_max_funl) {
333 if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
334 fifo->accum_txfunfl = 0;
339 min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
341 /* In case max value max_pdu is already lower than
342 the fifo depth, there is nothing more we can do.
345 if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
346 fifo->accum_txfunfl = 0;
350 if (fifo->ampdu_pld_size < max_pld_size) {
352 /* increment by TX_FIFO_PLD_INC bytes */
353 fifo->ampdu_pld_size += FFPLD_PLD_INCR;
354 if (fifo->ampdu_pld_size > max_pld_size)
355 fifo->ampdu_pld_size = max_pld_size;
357 /* update scb release size */
358 scb_ampdu_update_config_all(ampdu);
361 compute a new dma xfer rate for max_mpdu @ max mcs.
362 This is the minimum dma rate that
363 can achieve no underflow condition for the current mpdu size.
365 /* note : we divide/multiply by 100 to avoid integer overflows */
368 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
369 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
371 BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
372 "pre-load size %d\n",
373 fifo->dmaxferrate, fifo->ampdu_pld_size);
376 /* decrease ampdu size */
377 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
378 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
379 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
380 AMPDU_NUM_MPDU_LEGACY - 1;
382 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
384 /* recompute the table */
385 wlc_ffpld_calc_mcs2ampdu_table(ampdu, fid);
387 /* update scb release size */
388 scb_ampdu_update_config_all(ampdu);
391 fifo->accum_txfunfl = 0;
395 static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
398 u32 phy_rate, dma_rate, tmp;
400 wlc_fifo_info_t *fifo = (ampdu->fifo_tb + f);
402 /* recompute the dma rate */
403 /* note : we divide/multiply by 100 to avoid integer overflows */
405 min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
406 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
409 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
410 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
411 fifo->dmaxferrate = dma_rate;
413 /* fill up the mcs2ampdu table; do not recalc the last mcs */
414 dma_rate = dma_rate >> 7;
415 for (i = 0; i < FFPLD_MAX_MCS; i++) {
416 /* shifting to keep it within integer range */
417 phy_rate = MCS_RATE(i, true, false) >> 7;
418 if (phy_rate > dma_rate) {
419 tmp = ((fifo->ampdu_pld_size * phy_rate) /
420 ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
421 tmp = min_t(u32, tmp, 255);
422 fifo->mcs2ampdu_table[i] = (u8) tmp;
428 wlc_ampdu_agg(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p,
431 scb_ampdu_t *scb_ampdu;
432 scb_ampdu_tid_ini_t *ini;
433 u8 tid = (u8) (p->priority);
435 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
437 /* initialize initiator on first packet; sends addba req */
438 ini = SCB_AMPDU_INI(scb_ampdu, tid);
439 if (ini->magic != INI_MAGIC) {
440 ini = wlc_ampdu_init_tid_ini(ampdu, scb_ampdu, tid, false);
446 wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
447 struct sk_buff **pdu, int prec)
449 struct wlc_info *wlc;
450 struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
453 u8 preamble_type = WLC_GF_PREAMBLE;
454 u8 fbr_preamble_type = WLC_GF_PREAMBLE;
455 u8 rts_preamble_type = WLC_LONG_PREAMBLE;
456 u8 rts_fbr_preamble_type = WLC_LONG_PREAMBLE;
458 bool rr = true, fbr = false;
459 uint i, count = 0, fifo, seg_cnt = 0;
460 u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
461 u32 ampdu_len, maxlen = 0;
462 d11txh_t *txh = NULL;
464 struct ieee80211_hdr *h;
466 scb_ampdu_t *scb_ampdu;
467 scb_ampdu_tid_ini_t *ini;
469 bool use_rts = false, use_cts = false;
470 ratespec_t rspec = 0, rspec_fallback = 0;
471 ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
472 u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
473 struct ieee80211_rts *rts;
477 struct ieee80211_tx_info *tx_info;
485 tid = (u8) (p->priority);
487 f = ampdu->fifo_tb + prio2fifo[tid];
489 scb = wlc->pub->global_scb;
490 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
491 ini = &scb_ampdu->ini[tid];
493 /* Let pressure continue to build ... */
494 qlen = pktq_plen(&qi->q, prec);
495 if (ini->tx_in_transit > 0 && qlen < scb_ampdu->max_pdu) {
499 wlc_ampdu_agg(ampdu, scb, p, tid);
501 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
505 struct ieee80211_tx_rate *txrate;
507 tx_info = IEEE80211_SKB_CB(p);
508 txrate = tx_info->status.rates;
510 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
511 err = wlc_prep_pdu(wlc, p, &fifo);
513 wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
521 wiphy_err(wiphy, "wl%d: wlc_sendampdu: "
522 "prep_xdu retry; seq 0x%x\n",
523 wlc->pub->unit, seq);
528 /* error in the packet; reject it */
529 wiphy_err(wiphy, "wl%d: wlc_sendampdu: prep_xdu "
530 "rejected; seq 0x%x\n", wlc->pub->unit, seq);
535 /* pkt is good to be aggregated */
536 txh = (d11txh_t *) p->data;
537 plcp = (u8 *) (txh + 1);
538 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
539 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
540 index = TX_SEQ_TO_INDEX(seq);
542 /* check mcl fields and test whether it can be agg'd */
543 mcl = le16_to_cpu(txh->MacTxControlLow);
544 mcl &= ~TXC_AMPDU_MASK;
545 fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
546 txh->PreloadSize = 0; /* always default to 0 */
548 /* Handle retry limits */
549 if (txrate[0].count <= rr_retry_limit) {
559 /* extract the length info */
560 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
561 : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
563 /* retrieve null delimiter count */
564 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
567 BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
568 wlc->pub->unit, count, len);
571 * aggregateable mpdu. For ucode/hw agg,
572 * test whether need to break or change the epoch
575 mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
576 /* refill the bits since might be a retx mpdu */
577 mcl |= TXC_STARTMSDU;
578 rts = (struct ieee80211_rts *)&txh->rts_frame;
580 if (ieee80211_is_rts(rts->frame_control)) {
584 if (ieee80211_is_cts(rts->frame_control)) {
589 mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
590 mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
593 len = roundup(len, 4);
594 ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
596 dma_len += (u16) bcm_pkttotlen(p);
598 BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
599 " seg_cnt %d null delim %d\n",
600 wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
602 txh->MacTxControlLow = cpu_to_le16(mcl);
604 /* this packet is added */
607 /* patch the first MPDU */
609 u8 plcp0, plcp3, is40, sgi;
610 struct ieee80211_sta *sta;
612 sta = tx_info->control.sta;
618 plcp0 = txh->FragPLCPFallback[0];
619 plcp3 = txh->FragPLCPFallback[3];
622 is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
623 sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
624 mcs = plcp0 & ~MIMO_PLCP_40MHZ;
626 min(scb_ampdu->max_rxlen,
627 ampdu->max_txlen[mcs][is40][sgi]);
629 /* XXX Fix me to honor real max_rxlen */
630 /* can fix this as soon as ampdu_action() in mac80211.h
631 * gets extra u8buf_size par */
636 CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
637 ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
639 /* rebuild the rspec and rspec_fallback */
640 rspec = RSPEC_MIMORATE;
641 rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
642 if (plcp[0] & MIMO_PLCP_40MHZ)
643 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
645 if (fbr_iscck) /* CCK */
647 CCK_RSPEC(CCK_PHY2MAC_RATE
648 (txh->FragPLCPFallback[0]));
650 rspec_fallback = RSPEC_MIMORATE;
652 txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
653 if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
655 (PHY_TXC1_BW_40MHZ <<
659 if (use_rts || use_cts) {
661 wlc_rspec_to_rts_rspec(wlc, rspec, false,
664 wlc_rspec_to_rts_rspec(wlc, rspec_fallback,
665 false, mimo_ctlchbw);
669 /* if (first mpdu for host agg) */
670 /* test whether to add more */
671 if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
672 (count == f->mcs2ampdu_table[mcs])) {
673 BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
674 " ampdu at %d for mcs %d\n",
675 wlc->pub->unit, count, mcs);
679 if (count == scb_ampdu->max_pdu) {
683 /* check to see if the next pkt is a candidate for aggregation */
684 p = pktq_ppeek(&qi->q, prec);
685 tx_info = IEEE80211_SKB_CB(p); /* tx_info must be checked with current p */
688 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
689 ((u8) (p->priority) == tid)) {
692 bcm_pkttotlen(p) + AMPDU_MAX_MPDU_OVERHEAD;
693 plen = max(scb_ampdu->min_len, plen);
695 if ((plen + ampdu_len) > maxlen) {
697 wiphy_err(wiphy, "%s: Bogus plen #1\n",
702 /* check if there are enough descriptors available */
703 if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
704 wiphy_err(wiphy, "%s: No fifo space "
709 p = bcm_pktq_pdeq(&qi->q, prec);
716 ini->tx_in_transit += count;
719 /* patch up the last txh */
720 txh = (d11txh_t *) pkt[count - 1]->data;
721 mcl = le16_to_cpu(txh->MacTxControlLow);
722 mcl &= ~TXC_AMPDU_MASK;
723 mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
724 txh->MacTxControlLow = cpu_to_le16(mcl);
726 /* remove the null delimiter after last mpdu */
727 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
728 txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
729 ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
731 /* remove the pad len from last mpdu */
732 fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
733 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
734 : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
735 ampdu_len -= roundup(len, 4) - len;
737 /* patch up the first txh & plcp */
738 txh = (d11txh_t *) pkt[0]->data;
739 plcp = (u8 *) (txh + 1);
741 WLC_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
742 /* mark plcp to indicate ampdu */
743 WLC_SET_MIMO_PLCP_AMPDU(plcp);
745 /* reset the mixed mode header durations */
748 wlc_calc_lsig_len(wlc, rspec, ampdu_len);
749 txh->MModeLen = cpu_to_le16(mmodelen);
750 preamble_type = WLC_MM_PREAMBLE;
752 if (txh->MModeFbrLen) {
754 wlc_calc_lsig_len(wlc, rspec_fallback, ampdu_len);
755 txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
756 fbr_preamble_type = WLC_MM_PREAMBLE;
759 /* set the preload length */
760 if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
761 dma_len = min(dma_len, f->ampdu_pld_size);
762 txh->PreloadSize = cpu_to_le16(dma_len);
764 txh->PreloadSize = 0;
766 mch = le16_to_cpu(txh->MacTxControlHigh);
768 /* update RTS dur fields */
769 if (use_rts || use_cts) {
771 rts = (struct ieee80211_rts *)&txh->rts_frame;
772 if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
773 TXC_PREAMBLE_RTS_MAIN_SHORT)
774 rts_preamble_type = WLC_SHORT_PREAMBLE;
776 if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
777 TXC_PREAMBLE_RTS_FB_SHORT)
778 rts_fbr_preamble_type = WLC_SHORT_PREAMBLE;
781 wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec,
782 rspec, rts_preamble_type,
783 preamble_type, ampdu_len,
785 rts->duration = cpu_to_le16(durid);
786 durid = wlc_compute_rtscts_dur(wlc, use_cts,
789 rts_fbr_preamble_type,
792 txh->RTSDurFallback = cpu_to_le16(durid);
793 /* set TxFesTimeNormal */
794 txh->TxFesTimeNormal = rts->duration;
795 /* set fallback rate version of TxFesTimeNormal */
796 txh->TxFesTimeFallback = txh->RTSDurFallback;
799 /* set flag and plcp for fallback rate */
801 mch |= TXC_AMPDU_FBR;
802 txh->MacTxControlHigh = cpu_to_le16(mch);
803 WLC_SET_MIMO_PLCP_AMPDU(plcp);
804 WLC_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
807 BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
808 wlc->pub->unit, count, ampdu_len);
810 /* inform rate_sel if it this is a rate probe pkt */
811 frameid = le16_to_cpu(txh->TxFrameID);
812 if (frameid & TXFID_RATE_PROBE_MASK) {
813 wiphy_err(wiphy, "%s: XXX what to do with "
814 "TXFID_RATE_PROBE_MASK!?\n", __func__);
816 for (i = 0; i < count; i++)
817 wlc_txfifo(wlc, fifo, pkt[i], i == (count - 1),
818 ampdu->txpkt_weight);
826 wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
827 struct sk_buff *p, tx_status_t *txs)
829 scb_ampdu_t *scb_ampdu;
830 struct wlc_info *wlc = ampdu->wlc;
831 scb_ampdu_tid_ini_t *ini;
833 struct ieee80211_tx_info *tx_info;
835 tx_info = IEEE80211_SKB_CB(p);
837 /* BMAC_NOTE: For the split driver, second level txstatus comes later
838 * So if the ACK was received then wait for the second level else just
841 if (txs->status & TX_STATUS_ACK_RCV) {
844 /* wait till the next 8 bytes of txstatus is available */
845 while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
848 if (status_delay > 10) {
849 return; /* error condition */
853 s2 = R_REG(&wlc->regs->frmtxstatus2);
857 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
858 ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
859 wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
861 /* loop through all pkts and free */
862 u8 queue = txs->frameid & TXFID_QUEUE_MASK;
866 tx_info = IEEE80211_SKB_CB(p);
867 txh = (d11txh_t *) p->data;
868 mcl = le16_to_cpu(txh->MacTxControlLow);
869 bcm_pkt_buf_free_skb(p);
870 /* break out if last packet of ampdu */
871 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
874 p = GETNEXTTXP(wlc, queue);
876 wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
878 wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
882 rate_status(struct wlc_info *wlc, struct ieee80211_tx_info *tx_info,
883 tx_status_t *txs, u8 mcs)
885 struct ieee80211_tx_rate *txrate = tx_info->status.rates;
888 /* clear the rest of the rates */
889 for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
895 #define SHORTNAME "AMPDU status"
898 wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
899 struct sk_buff *p, tx_status_t *txs,
902 scb_ampdu_t *scb_ampdu;
903 struct wlc_info *wlc = ampdu->wlc;
904 scb_ampdu_tid_ini_t *ini;
905 u8 bitmap[8], queue, tid;
908 struct ieee80211_hdr *h;
909 u16 seq, start_seq = 0, bindex, index, mcl;
911 bool ba_recd = false, ack_recd = false;
912 u8 suc_mpdu = 0, tot_mpdu = 0;
914 bool update_rate = true, retry = true, tx_error = false;
917 u8 retry_limit, rr_retry_limit;
918 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
919 struct wiphy *wiphy = wlc->wiphy;
922 u8 hole[AMPDU_MAX_MPDU];
923 memset(hole, 0, sizeof(hole));
926 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
927 tid = (u8) (p->priority);
929 ini = SCB_AMPDU_INI(scb_ampdu, tid);
930 retry_limit = ampdu->retry_limit_tid[tid];
931 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
932 memset(bitmap, 0, sizeof(bitmap));
933 queue = txs->frameid & TXFID_QUEUE_MASK;
934 supr_status = txs->status & TX_STATUS_SUPR_MASK;
936 if (txs->status & TX_STATUS_ACK_RCV) {
937 if (TX_STATUS_SUPR_UF == supr_status) {
941 WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
942 start_seq = txs->sequence >> SEQNUM_SHIFT;
943 bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
944 TX_STATUS_BA_BMAP03_SHIFT;
946 WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
947 WARN_ON(!(s1 & TX_STATUS_AMPDU));
950 (s1 & TX_STATUS_BA_BMAP47_MASK) <<
951 TX_STATUS_BA_BMAP47_SHIFT;
952 bitmap[1] = (s1 >> 8) & 0xff;
953 bitmap[2] = (s1 >> 16) & 0xff;
954 bitmap[3] = (s1 >> 24) & 0xff;
956 bitmap[4] = s2 & 0xff;
957 bitmap[5] = (s2 >> 8) & 0xff;
958 bitmap[6] = (s2 >> 16) & 0xff;
959 bitmap[7] = (s2 >> 24) & 0xff;
965 if (supr_status == TX_STATUS_SUPR_BADCH) {
966 wiphy_err(wiphy, "%s: Pkt tx suppressed, "
967 "illegal channel possibly %d\n",
968 __func__, CHSPEC_CHANNEL(
969 wlc->default_bss->chanspec));
971 if (supr_status != TX_STATUS_SUPR_FRAG)
972 wiphy_err(wiphy, "%s: wlc_ampdu_dotx"
973 "status:supr_status 0x%x\n",
974 __func__, supr_status);
976 /* no need to retry for badch; will fail again */
977 if (supr_status == TX_STATUS_SUPR_BADCH ||
978 supr_status == TX_STATUS_SUPR_EXPTIME) {
980 } else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
981 /* TX underflow : try tuning pre-loading or ampdu size */
982 } else if (supr_status == TX_STATUS_SUPR_FRAG) {
983 /* if there were underflows, but pre-loading is not active,
984 notify rate adaptation.
986 if (wlc_ffpld_check_txfunfl(wlc, prio2fifo[tid])
991 } else if (txs->phyerr) {
993 wiphy_err(wiphy, "wl%d: wlc_ampdu_dotxstatus: tx phy "
994 "error (0x%x)\n", wlc->pub->unit,
998 bcm_prpkt("txpkt (AMPDU)", p);
999 wlc_print_txdesc((d11txh_t *) p->data);
1001 wlc_print_txstatus(txs);
1005 /* loop through all pkts and retry if not acked */
1007 tx_info = IEEE80211_SKB_CB(p);
1008 txh = (d11txh_t *) p->data;
1009 mcl = le16_to_cpu(txh->MacTxControlLow);
1010 plcp = (u8 *) (txh + 1);
1011 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
1012 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
1014 if (tot_mpdu == 0) {
1015 mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
1016 mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
1019 index = TX_SEQ_TO_INDEX(seq);
1022 bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
1023 BCMMSG(wlc->wiphy, "tid %d seq %d,"
1024 " start_seq %d, bindex %d set %d, index %d\n",
1025 tid, seq, start_seq, bindex,
1026 isset(bitmap, bindex), index);
1027 /* if acked then clear bit and free packet */
1028 if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
1029 && isset(bitmap, bindex)) {
1030 ini->tx_in_transit--;
1031 ini->txretry[index] = 0;
1033 /* ampdu_ack_len: number of acked aggregated frames */
1034 /* ampdu_len: number of aggregated frames */
1035 rate_status(wlc, tx_info, txs, mcs);
1036 tx_info->flags |= IEEE80211_TX_STAT_ACK;
1037 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
1038 tx_info->status.ampdu_ack_len =
1039 tx_info->status.ampdu_len = 1;
1041 skb_pull(p, D11_PHY_HDR_LEN);
1042 skb_pull(p, D11_TXH_LEN);
1044 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1050 /* either retransmit or send bar if ack not recd */
1052 struct ieee80211_tx_rate *txrate =
1053 tx_info->status.rates;
1054 if (retry && (txrate[0].count < (int)retry_limit)) {
1055 ini->txretry[index]++;
1056 ini->tx_in_transit--;
1057 /* Use high prededence for retransmit to give some punch */
1058 /* wlc_txq_enq(wlc, scb, p, WLC_PRIO_TO_PREC(tid)); */
1059 wlc_txq_enq(wlc, scb, p,
1060 WLC_PRIO_TO_HI_PREC(tid));
1063 ini->tx_in_transit--;
1064 ieee80211_tx_info_clear_status(tx_info);
1065 tx_info->status.ampdu_ack_len = 0;
1066 tx_info->status.ampdu_len = 1;
1068 IEEE80211_TX_STAT_AMPDU_NO_BACK;
1069 skb_pull(p, D11_PHY_HDR_LEN);
1070 skb_pull(p, D11_TXH_LEN);
1071 wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
1072 "transit %d\n", SHORTNAME, seq,
1073 ini->tx_in_transit);
1074 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1080 /* break out if last packet of ampdu */
1081 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1085 p = GETNEXTTXP(wlc, queue);
1089 /* update rate state */
1090 antselid = wlc_antsel_antsel2id(wlc->asi, mimoantsel);
1092 wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
1095 /* initialize the initiator code for tid */
1096 static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
1097 scb_ampdu_t *scb_ampdu,
1098 u8 tid, bool override)
1100 scb_ampdu_tid_ini_t *ini;
1102 /* check for per-tid control of ampdu */
1103 if (!ampdu->ini_enable[tid]) {
1104 wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
1109 ini = SCB_AMPDU_INI(scb_ampdu, tid);
1111 ini->scb = scb_ampdu->scb;
1112 ini->magic = INI_MAGIC;
1116 static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on)
1118 struct wlc_info *wlc = ampdu->wlc;
1120 wlc->pub->_ampdu = false;
1123 if (!N_ENAB(wlc->pub)) {
1124 wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
1125 "nmode enabled\n", wlc->pub->unit);
1128 if (!wlc_ampdu_cap(ampdu)) {
1129 wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
1130 "ampdu capable\n", wlc->pub->unit);
1133 wlc->pub->_ampdu = on;
1139 static bool wlc_ampdu_cap(struct ampdu_info *ampdu)
1141 if (WLC_PHY_11N_CAP(ampdu->wlc->band))
1147 static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
1151 for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
1152 /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
1154 rate = MCS_RATE(mcs, false, false);
1155 ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
1156 /* 40 MHz, No SGI */
1157 rate = MCS_RATE(mcs, true, false);
1158 ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
1160 rate = MCS_RATE(mcs, false, true);
1161 ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
1163 rate = MCS_RATE(mcs, true, true);
1164 ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
1168 void wlc_ampdu_macaddr_upd(struct wlc_info *wlc)
1170 char template[T_RAM_ACCESS_SZ * 2];
1172 /* driver needs to write the ta in the template; ta is at offset 16 */
1173 memset(template, 0, sizeof(template));
1174 memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1175 wlc_write_template_ram(wlc, (T_BA_TPL_BASE + 16), (T_RAM_ACCESS_SZ * 2),
1179 bool wlc_aggregatable(struct wlc_info *wlc, u8 tid)
1181 return wlc->ampdu->ini_enable[tid];
1184 void wlc_ampdu_shm_upd(struct ampdu_info *ampdu)
1186 struct wlc_info *wlc = ampdu->wlc;
1188 /* Extend ucode internal watchdog timer to match larger received frames */
1189 if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1190 IEEE80211_HT_MAX_AMPDU_64K) {
1191 wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1192 wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1194 wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1195 wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1200 * callback function that helps flushing ampdu packets from a priority queue
1202 static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
1204 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
1205 struct cb_del_ampdu_pars *ampdu_pars =
1206 (struct cb_del_ampdu_pars *)arg_a;
1209 rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
1210 rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
1211 tx_info->control.sta == ampdu_pars->sta);
1212 rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
1217 * callback function that helps invalidating ampdu packets in a DMA queue
1219 static void dma_cb_fn_ampdu(void *txi, void *arg_a)
1221 struct ieee80211_sta *sta = arg_a;
1222 struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
1224 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
1225 (tx_info->control.sta == sta || sta == NULL))
1226 tx_info->control.sta = NULL;
1230 * When a remote party is no longer available for ampdu communication, any
1231 * pending tx ampdu packets in the driver have to be flushed.
1233 void wlc_ampdu_flush(struct wlc_info *wlc,
1234 struct ieee80211_sta *sta, u16 tid)
1236 struct wlc_txq_info *qi = wlc->pkt_queue;
1237 struct pktq *pq = &qi->q;
1239 struct cb_del_ampdu_pars ampdu_pars;
1241 ampdu_pars.sta = sta;
1242 ampdu_pars.tid = tid;
1243 for (prec = 0; prec < pq->num_prec; prec++) {
1244 bcm_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
1245 (void *)&du_pars);
1247 wlc_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);