2 * Copyright (c) 2010 Broadcom Corporation
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 #include <net/mac80211.h>
20 #include "phy/phy_hal.h"
25 #define AMPDU_MAX_MPDU 32 /* max number of mpdus in an ampdu */
26 #define AMPDU_NUM_MPDU_LEGACY 16 /* max number of mpdus in an ampdu to a legacy */
27 #define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
28 #define AMPDU_TX_BA_DEF_WSIZE 64 /* default Tx ba window size (in pdu) */
29 #define AMPDU_RX_BA_DEF_WSIZE 64 /* max Rx ba window size (in pdu) */
30 #define AMPDU_RX_BA_MAX_WSIZE 64 /* default Rx ba window size (in pdu) */
31 #define AMPDU_MAX_DUR 5 /* max dur of tx ampdu (in msec) */
32 #define AMPDU_DEF_RETRY_LIMIT 5 /* default tx retry limit */
33 #define AMPDU_DEF_RR_RETRY_LIMIT 2 /* default tx retry limit at reg rate */
34 #define AMPDU_DEF_TXPKT_WEIGHT 2 /* default weight of ampdu in txfifo */
35 #define AMPDU_DEF_FFPLD_RSVD 2048 /* default ffpld reserved bytes */
36 #define AMPDU_INI_FREE 10 /* # of inis to be freed on detach */
37 #define AMPDU_SCB_MAX_RELEASE 20 /* max # of mpdus released at a time */
39 #define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */
40 #define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu
43 #define FFPLD_MPDU_SIZE 1800 /* estimate of maximum mpdu size */
44 #define FFPLD_MAX_MCS 23 /* we don't deal with mcs 32 */
45 #define FFPLD_PLD_INCR 1000 /* increments in bytes */
46 #define FFPLD_MAX_AMPDU_CNT 5000 /* maximum number of ampdu we
47 * accumulate between resets.
50 #define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
52 /* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
53 #define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
54 AMPDU_DELIMITER_LEN + 3\
55 + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
57 /* structure to hold tx fifo information and pre-loading state
58 * counters specific to tx underflows of ampdus
59 * some counters might be redundant with the ones in wlc or ampdu structures.
60 * This allows to maintain a specific state independently of
61 * how often and/or when the wlc counters are updated.
63 typedef struct wlc_fifo_info {
64 u16 ampdu_pld_size; /* number of bytes to be pre-loaded */
65 u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; /* per-mcs max # of mpdus in an ampdu */
66 u16 prev_txfunfl; /* num of underflows last read from the HW macstats counter */
67 u32 accum_txfunfl; /* num of underflows since we modified pld params */
68 u32 accum_txampdu; /* num of tx ampdu since we modified pld params */
69 u32 prev_txampdu; /* previous reading of tx ampdu */
70 u32 dmaxferrate; /* estimated dma avg xfer rate in kbits/sec */
73 /* AMPDU module specific state */
75 struct brcms_c_info *wlc; /* pointer to main wlc structure */
76 int scb_handle; /* scb cubby handle to retrieve data from scb */
77 u8 ini_enable[AMPDU_MAX_SCB_TID]; /* per-tid initiator enable/disable of ampdu */
78 u8 ba_tx_wsize; /* Tx ba window size (in pdu) */
79 u8 ba_rx_wsize; /* Rx ba window size (in pdu) */
80 u8 retry_limit; /* mpdu transmit retry limit */
81 u8 rr_retry_limit; /* mpdu transmit retry limit at regular rate */
82 u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; /* per-tid mpdu transmit retry limit */
83 /* per-tid mpdu transmit retry limit at regular rate */
84 u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
85 u8 mpdu_density; /* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
86 s8 max_pdu; /* max pdus allowed in ampdu */
87 u8 dur; /* max duration of an ampdu (in msec) */
88 u8 txpkt_weight; /* weight of ampdu in txfifo; reduces rate lag */
89 u8 rx_factor; /* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
90 u32 ffpld_rsvd; /* number of bytes to reserve for preload */
91 u32 max_txlen[MCS_TABLE_SIZE][2][2]; /* max size of ampdu per mcs, bw and sgi */
92 void *ini_free[AMPDU_INI_FREE]; /* array of ini's to be freed on detach */
93 bool mfbr; /* enable multiple fallback rate */
94 u32 tx_max_funl; /* underflows should be kept such that
95 * (tx_max_funfl*underflows) < tx frames
97 wlc_fifo_info_t fifo_tb[NUM_FFPLD_FIFO]; /* table of fifo infos */
101 /* used for flushing ampdu packets */
102 struct cb_del_ampdu_pars {
103 struct ieee80211_sta *sta;
107 #define AMPDU_CLEANUPFLAG_RX (0x1)
108 #define AMPDU_CLEANUPFLAG_TX (0x2)
110 #define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
111 #define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
113 static void brcms_c_ffpld_init(struct ampdu_info *ampdu);
114 static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int f);
115 static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
117 static scb_ampdu_tid_ini_t *brcms_c_ampdu_init_tid_ini(struct ampdu_info *ampdu,
118 scb_ampdu_t *scb_ampdu,
119 u8 tid, bool override);
120 static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu,
122 static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
124 static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu);
126 #define brcms_c_ampdu_txflowcontrol(a, b, c) do {} while (0)
128 static void brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
130 struct sk_buff *p, tx_status_t *txs,
131 u32 frmtxstatus, u32 frmtxstatus2);
132 static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu);
133 static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on);
135 struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
137 struct ampdu_info *ampdu;
140 ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
142 wiphy_err(wlc->wiphy, "wl%d: brcms_c_ampdu_attach: out of mem"
143 "\n", wlc->pub->unit);
148 for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
149 ampdu->ini_enable[i] = true;
150 /* Disable ampdu for VO by default */
151 ampdu->ini_enable[PRIO_8021D_VO] = false;
152 ampdu->ini_enable[PRIO_8021D_NC] = false;
154 /* Disable ampdu for BK by default since not enough fifo space */
155 ampdu->ini_enable[PRIO_8021D_NONE] = false;
156 ampdu->ini_enable[PRIO_8021D_BK] = false;
158 ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
159 ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
160 ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
161 ampdu->max_pdu = AUTO;
162 ampdu->dur = AMPDU_MAX_DUR;
163 ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
165 ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
166 /* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
167 if (WLCISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
168 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
170 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
171 ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
172 ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
174 for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
175 ampdu->retry_limit_tid[i] = ampdu->retry_limit;
176 ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
179 brcms_c_scb_ampdu_update_max_txlen(ampdu, ampdu->dur);
181 /* try to set ampdu to the default value */
182 brcms_c_ampdu_set(ampdu, wlc->pub->_ampdu);
184 ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
185 brcms_c_ffpld_init(ampdu);
190 void brcms_c_ampdu_detach(struct ampdu_info *ampdu)
197 /* free all ini's which were to be freed on callbacks which were never called */
198 for (i = 0; i < AMPDU_INI_FREE; i++) {
199 kfree(ampdu->ini_free[i]);
202 brcms_c_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
206 static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
209 scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
212 scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
214 /* go back to legacy size if some preloading is occurring */
215 for (i = 0; i < NUM_FFPLD_FIFO; i++) {
216 if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
217 scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
220 /* apply user override */
221 if (ampdu->max_pdu != AUTO)
222 scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
224 scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
226 if (scb_ampdu->max_rxlen)
228 min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 1600);
230 scb_ampdu->release = min(scb_ampdu->release,
231 ampdu->fifo_tb[TX_AC_BE_FIFO].
232 mcs2ampdu_table[FFPLD_MAX_MCS]);
235 static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu)
237 brcms_c_scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
240 static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
243 wlc_fifo_info_t *fifo;
245 for (j = 0; j < NUM_FFPLD_FIFO; j++) {
246 fifo = (ampdu->fifo_tb + j);
247 fifo->ampdu_pld_size = 0;
248 for (i = 0; i <= FFPLD_MAX_MCS; i++)
249 fifo->mcs2ampdu_table[i] = 255;
250 fifo->dmaxferrate = 0;
251 fifo->accum_txampdu = 0;
252 fifo->prev_txfunfl = 0;
253 fifo->accum_txfunfl = 0;
258 /* evaluate the dma transfer rate using the tx underflows as feedback.
259 * If necessary, increase tx fifo preloading. If not enough,
260 * decrease maximum ampdu size for each mcs till underflows stop
261 * Return 1 if pre-loading not active, -1 if not an underflow event,
262 * 0 if pre-loading module took care of the event.
264 static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
266 struct ampdu_info *ampdu = wlc->ampdu;
267 u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
270 u32 current_ampdu_cnt = 0;
273 wlc_fifo_info_t *fifo = (ampdu->fifo_tb + fid);
277 /* return if we got here for a different reason than underflows */
279 brcms_c_read_shm(wlc,
280 M_UCODE_MACSTAT + offsetof(macstat_t, txfunfl[fid]));
281 new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
282 if (new_txunfl == 0) {
283 BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
286 fifo->prev_txfunfl = cur_txunfl;
288 if (!ampdu->tx_max_funl)
291 /* check if fifo is big enough */
292 if (brcms_c_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz))
295 if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
298 max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
299 fifo->accum_txfunfl += new_txunfl;
301 /* we need to wait for at least 10 underflows */
302 if (fifo->accum_txfunfl < 10)
305 BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n",
306 current_ampdu_cnt, fifo->accum_txfunfl);
309 compute the current ratio of tx unfl per ampdu.
310 When the current ampdu count becomes too
311 big while the ratio remains small, we reset
312 the current count in order to not
313 introduce too big of a latency in detecting a
314 large amount of tx underflows later.
317 txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
319 if (txunfl_ratio > ampdu->tx_max_funl) {
320 if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
321 fifo->accum_txfunfl = 0;
326 min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
328 /* In case max value max_pdu is already lower than
329 the fifo depth, there is nothing more we can do.
332 if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
333 fifo->accum_txfunfl = 0;
337 if (fifo->ampdu_pld_size < max_pld_size) {
339 /* increment by TX_FIFO_PLD_INC bytes */
340 fifo->ampdu_pld_size += FFPLD_PLD_INCR;
341 if (fifo->ampdu_pld_size > max_pld_size)
342 fifo->ampdu_pld_size = max_pld_size;
344 /* update scb release size */
345 brcms_c_scb_ampdu_update_config_all(ampdu);
348 compute a new dma xfer rate for max_mpdu @ max mcs.
349 This is the minimum dma rate that
350 can achieve no underflow condition for the current mpdu size.
352 /* note : we divide/multiply by 100 to avoid integer overflows */
355 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
356 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
358 BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
359 "pre-load size %d\n",
360 fifo->dmaxferrate, fifo->ampdu_pld_size);
363 /* decrease ampdu size */
364 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
365 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
366 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
367 AMPDU_NUM_MPDU_LEGACY - 1;
369 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
371 /* recompute the table */
372 brcms_c_ffpld_calc_mcs2ampdu_table(ampdu, fid);
374 /* update scb release size */
375 brcms_c_scb_ampdu_update_config_all(ampdu);
378 fifo->accum_txfunfl = 0;
382 static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
385 u32 phy_rate, dma_rate, tmp;
387 wlc_fifo_info_t *fifo = (ampdu->fifo_tb + f);
389 /* recompute the dma rate */
390 /* note : we divide/multiply by 100 to avoid integer overflows */
392 min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
393 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
396 (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
397 / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
398 fifo->dmaxferrate = dma_rate;
400 /* fill up the mcs2ampdu table; do not recalc the last mcs */
401 dma_rate = dma_rate >> 7;
402 for (i = 0; i < FFPLD_MAX_MCS; i++) {
403 /* shifting to keep it within integer range */
404 phy_rate = MCS_RATE(i, true, false) >> 7;
405 if (phy_rate > dma_rate) {
406 tmp = ((fifo->ampdu_pld_size * phy_rate) /
407 ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
408 tmp = min_t(u32, tmp, 255);
409 fifo->mcs2ampdu_table[i] = (u8) tmp;
415 brcms_c_ampdu_agg(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p,
418 scb_ampdu_t *scb_ampdu;
419 scb_ampdu_tid_ini_t *ini;
420 u8 tid = (u8) (p->priority);
422 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
424 /* initialize initiator on first packet; sends addba req */
425 ini = SCB_AMPDU_INI(scb_ampdu, tid);
426 if (ini->magic != INI_MAGIC) {
427 ini = brcms_c_ampdu_init_tid_ini(ampdu, scb_ampdu, tid, false);
433 brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_c_txq_info *qi,
434 struct sk_buff **pdu, int prec)
436 struct brcms_c_info *wlc;
437 struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
440 u8 preamble_type = WLC_GF_PREAMBLE;
441 u8 fbr_preamble_type = WLC_GF_PREAMBLE;
442 u8 rts_preamble_type = WLC_LONG_PREAMBLE;
443 u8 rts_fbr_preamble_type = WLC_LONG_PREAMBLE;
445 bool rr = true, fbr = false;
446 uint i, count = 0, fifo, seg_cnt = 0;
447 u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
448 u32 ampdu_len, maxlen = 0;
449 d11txh_t *txh = NULL;
451 struct ieee80211_hdr *h;
453 scb_ampdu_t *scb_ampdu;
454 scb_ampdu_tid_ini_t *ini;
456 bool use_rts = false, use_cts = false;
457 ratespec_t rspec = 0, rspec_fallback = 0;
458 ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
459 u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
460 struct ieee80211_rts *rts;
464 struct ieee80211_tx_info *tx_info;
472 tid = (u8) (p->priority);
474 f = ampdu->fifo_tb + prio2fifo[tid];
476 scb = wlc->pub->global_scb;
477 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
478 ini = &scb_ampdu->ini[tid];
480 /* Let pressure continue to build ... */
481 qlen = pktq_plen(&qi->q, prec);
482 if (ini->tx_in_transit > 0 && qlen < scb_ampdu->max_pdu) {
486 brcms_c_ampdu_agg(ampdu, scb, p, tid);
488 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
492 struct ieee80211_tx_rate *txrate;
494 tx_info = IEEE80211_SKB_CB(p);
495 txrate = tx_info->status.rates;
497 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
498 err = brcms_c_prep_pdu(wlc, p, &fifo);
500 wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
508 wiphy_err(wiphy, "wl%d: wlc_sendampdu: "
509 "prep_xdu retry; seq 0x%x\n",
510 wlc->pub->unit, seq);
515 /* error in the packet; reject it */
516 wiphy_err(wiphy, "wl%d: wlc_sendampdu: prep_xdu "
517 "rejected; seq 0x%x\n", wlc->pub->unit, seq);
522 /* pkt is good to be aggregated */
523 txh = (d11txh_t *) p->data;
524 plcp = (u8 *) (txh + 1);
525 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
526 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
527 index = TX_SEQ_TO_INDEX(seq);
529 /* check mcl fields and test whether it can be agg'd */
530 mcl = le16_to_cpu(txh->MacTxControlLow);
531 mcl &= ~TXC_AMPDU_MASK;
532 fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
533 txh->PreloadSize = 0; /* always default to 0 */
535 /* Handle retry limits */
536 if (txrate[0].count <= rr_retry_limit) {
546 /* extract the length info */
547 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
548 : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
550 /* retrieve null delimiter count */
551 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
554 BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
555 wlc->pub->unit, count, len);
558 * aggregateable mpdu. For ucode/hw agg,
559 * test whether need to break or change the epoch
562 mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
563 /* refill the bits since might be a retx mpdu */
564 mcl |= TXC_STARTMSDU;
565 rts = (struct ieee80211_rts *)&txh->rts_frame;
567 if (ieee80211_is_rts(rts->frame_control)) {
571 if (ieee80211_is_cts(rts->frame_control)) {
576 mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
577 mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
580 len = roundup(len, 4);
581 ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
583 dma_len += (u16) brcmu_pkttotlen(p);
585 BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
586 " seg_cnt %d null delim %d\n",
587 wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
589 txh->MacTxControlLow = cpu_to_le16(mcl);
591 /* this packet is added */
594 /* patch the first MPDU */
596 u8 plcp0, plcp3, is40, sgi;
597 struct ieee80211_sta *sta;
599 sta = tx_info->control.sta;
605 plcp0 = txh->FragPLCPFallback[0];
606 plcp3 = txh->FragPLCPFallback[3];
609 is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
610 sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
611 mcs = plcp0 & ~MIMO_PLCP_40MHZ;
613 min(scb_ampdu->max_rxlen,
614 ampdu->max_txlen[mcs][is40][sgi]);
616 /* XXX Fix me to honor real max_rxlen */
617 /* can fix this as soon as ampdu_action() in mac80211.h
618 * gets extra u8buf_size par */
623 CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
624 ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
626 /* rebuild the rspec and rspec_fallback */
627 rspec = RSPEC_MIMORATE;
628 rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
629 if (plcp[0] & MIMO_PLCP_40MHZ)
630 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
632 if (fbr_iscck) /* CCK */
634 CCK_RSPEC(CCK_PHY2MAC_RATE
635 (txh->FragPLCPFallback[0]));
637 rspec_fallback = RSPEC_MIMORATE;
639 txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
640 if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
642 (PHY_TXC1_BW_40MHZ <<
646 if (use_rts || use_cts) {
648 brcms_c_rspec_to_rts_rspec(wlc,
649 rspec, false, mimo_ctlchbw);
651 brcms_c_rspec_to_rts_rspec(wlc,
652 rspec_fallback, false, mimo_ctlchbw);
656 /* if (first mpdu for host agg) */
657 /* test whether to add more */
658 if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
659 (count == f->mcs2ampdu_table[mcs])) {
660 BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
661 " ampdu at %d for mcs %d\n",
662 wlc->pub->unit, count, mcs);
666 if (count == scb_ampdu->max_pdu) {
670 /* check to see if the next pkt is a candidate for aggregation */
671 p = pktq_ppeek(&qi->q, prec);
672 tx_info = IEEE80211_SKB_CB(p); /* tx_info must be checked with current p */
675 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
676 ((u8) (p->priority) == tid)) {
678 plen = brcmu_pkttotlen(p) +
679 AMPDU_MAX_MPDU_OVERHEAD;
680 plen = max(scb_ampdu->min_len, plen);
682 if ((plen + ampdu_len) > maxlen) {
684 wiphy_err(wiphy, "%s: Bogus plen #1\n",
689 /* check if there are enough descriptors available */
690 if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
691 wiphy_err(wiphy, "%s: No fifo space "
696 p = brcmu_pktq_pdeq(&qi->q, prec);
703 ini->tx_in_transit += count;
706 /* patch up the last txh */
707 txh = (d11txh_t *) pkt[count - 1]->data;
708 mcl = le16_to_cpu(txh->MacTxControlLow);
709 mcl &= ~TXC_AMPDU_MASK;
710 mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
711 txh->MacTxControlLow = cpu_to_le16(mcl);
713 /* remove the null delimiter after last mpdu */
714 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
715 txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
716 ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
718 /* remove the pad len from last mpdu */
719 fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
720 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
721 : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
722 ampdu_len -= roundup(len, 4) - len;
724 /* patch up the first txh & plcp */
725 txh = (d11txh_t *) pkt[0]->data;
726 plcp = (u8 *) (txh + 1);
728 WLC_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
729 /* mark plcp to indicate ampdu */
730 WLC_SET_MIMO_PLCP_AMPDU(plcp);
732 /* reset the mixed mode header durations */
735 brcms_c_calc_lsig_len(wlc, rspec, ampdu_len);
736 txh->MModeLen = cpu_to_le16(mmodelen);
737 preamble_type = WLC_MM_PREAMBLE;
739 if (txh->MModeFbrLen) {
741 brcms_c_calc_lsig_len(wlc, rspec_fallback,
743 txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
744 fbr_preamble_type = WLC_MM_PREAMBLE;
747 /* set the preload length */
748 if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
749 dma_len = min(dma_len, f->ampdu_pld_size);
750 txh->PreloadSize = cpu_to_le16(dma_len);
752 txh->PreloadSize = 0;
754 mch = le16_to_cpu(txh->MacTxControlHigh);
756 /* update RTS dur fields */
757 if (use_rts || use_cts) {
759 rts = (struct ieee80211_rts *)&txh->rts_frame;
760 if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
761 TXC_PREAMBLE_RTS_MAIN_SHORT)
762 rts_preamble_type = WLC_SHORT_PREAMBLE;
764 if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
765 TXC_PREAMBLE_RTS_FB_SHORT)
766 rts_fbr_preamble_type = WLC_SHORT_PREAMBLE;
769 brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
770 rspec, rts_preamble_type,
771 preamble_type, ampdu_len,
773 rts->duration = cpu_to_le16(durid);
774 durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
777 rts_fbr_preamble_type,
780 txh->RTSDurFallback = cpu_to_le16(durid);
781 /* set TxFesTimeNormal */
782 txh->TxFesTimeNormal = rts->duration;
783 /* set fallback rate version of TxFesTimeNormal */
784 txh->TxFesTimeFallback = txh->RTSDurFallback;
787 /* set flag and plcp for fallback rate */
789 mch |= TXC_AMPDU_FBR;
790 txh->MacTxControlHigh = cpu_to_le16(mch);
791 WLC_SET_MIMO_PLCP_AMPDU(plcp);
792 WLC_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
795 BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
796 wlc->pub->unit, count, ampdu_len);
798 /* inform rate_sel if it this is a rate probe pkt */
799 frameid = le16_to_cpu(txh->TxFrameID);
800 if (frameid & TXFID_RATE_PROBE_MASK) {
801 wiphy_err(wiphy, "%s: XXX what to do with "
802 "TXFID_RATE_PROBE_MASK!?\n", __func__);
804 for (i = 0; i < count; i++)
805 brcms_c_txfifo(wlc, fifo, pkt[i], i == (count - 1),
806 ampdu->txpkt_weight);
814 brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
815 struct sk_buff *p, tx_status_t *txs)
817 scb_ampdu_t *scb_ampdu;
818 struct brcms_c_info *wlc = ampdu->wlc;
819 scb_ampdu_tid_ini_t *ini;
821 struct ieee80211_tx_info *tx_info;
823 tx_info = IEEE80211_SKB_CB(p);
825 /* BMAC_NOTE: For the split driver, second level txstatus comes later
826 * So if the ACK was received then wait for the second level else just
829 if (txs->status & TX_STATUS_ACK_RCV) {
832 /* wait till the next 8 bytes of txstatus is available */
833 while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
836 if (status_delay > 10) {
837 return; /* error condition */
841 s2 = R_REG(&wlc->regs->frmtxstatus2);
845 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
846 ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
847 brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
849 /* loop through all pkts and free */
850 u8 queue = txs->frameid & TXFID_QUEUE_MASK;
854 tx_info = IEEE80211_SKB_CB(p);
855 txh = (d11txh_t *) p->data;
856 mcl = le16_to_cpu(txh->MacTxControlLow);
857 brcmu_pkt_buf_free_skb(p);
858 /* break out if last packet of ampdu */
859 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
862 p = GETNEXTTXP(wlc, queue);
864 brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
866 brcms_c_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
870 brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
871 struct ieee80211_tx_info *tx_info,
872 tx_status_t *txs, u8 mcs)
874 struct ieee80211_tx_rate *txrate = tx_info->status.rates;
877 /* clear the rest of the rates */
878 for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
884 #define SHORTNAME "AMPDU status"
887 brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
888 struct sk_buff *p, tx_status_t *txs,
891 scb_ampdu_t *scb_ampdu;
892 struct brcms_c_info *wlc = ampdu->wlc;
893 scb_ampdu_tid_ini_t *ini;
894 u8 bitmap[8], queue, tid;
897 struct ieee80211_hdr *h;
898 u16 seq, start_seq = 0, bindex, index, mcl;
900 bool ba_recd = false, ack_recd = false;
901 u8 suc_mpdu = 0, tot_mpdu = 0;
903 bool update_rate = true, retry = true, tx_error = false;
906 u8 retry_limit, rr_retry_limit;
907 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
908 struct wiphy *wiphy = wlc->wiphy;
911 u8 hole[AMPDU_MAX_MPDU];
912 memset(hole, 0, sizeof(hole));
915 scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
916 tid = (u8) (p->priority);
918 ini = SCB_AMPDU_INI(scb_ampdu, tid);
919 retry_limit = ampdu->retry_limit_tid[tid];
920 rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
921 memset(bitmap, 0, sizeof(bitmap));
922 queue = txs->frameid & TXFID_QUEUE_MASK;
923 supr_status = txs->status & TX_STATUS_SUPR_MASK;
925 if (txs->status & TX_STATUS_ACK_RCV) {
926 if (TX_STATUS_SUPR_UF == supr_status) {
930 WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
931 start_seq = txs->sequence >> SEQNUM_SHIFT;
932 bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
933 TX_STATUS_BA_BMAP03_SHIFT;
935 WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
936 WARN_ON(!(s1 & TX_STATUS_AMPDU));
939 (s1 & TX_STATUS_BA_BMAP47_MASK) <<
940 TX_STATUS_BA_BMAP47_SHIFT;
941 bitmap[1] = (s1 >> 8) & 0xff;
942 bitmap[2] = (s1 >> 16) & 0xff;
943 bitmap[3] = (s1 >> 24) & 0xff;
945 bitmap[4] = s2 & 0xff;
946 bitmap[5] = (s2 >> 8) & 0xff;
947 bitmap[6] = (s2 >> 16) & 0xff;
948 bitmap[7] = (s2 >> 24) & 0xff;
954 if (supr_status == TX_STATUS_SUPR_BADCH) {
955 wiphy_err(wiphy, "%s: Pkt tx suppressed, "
956 "illegal channel possibly %d\n",
957 __func__, CHSPEC_CHANNEL(
958 wlc->default_bss->chanspec));
960 if (supr_status != TX_STATUS_SUPR_FRAG)
961 wiphy_err(wiphy, "%s:"
962 "supr_status 0x%x\n",
963 __func__, supr_status);
965 /* no need to retry for badch; will fail again */
966 if (supr_status == TX_STATUS_SUPR_BADCH ||
967 supr_status == TX_STATUS_SUPR_EXPTIME) {
969 } else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
970 /* TX underflow : try tuning pre-loading or ampdu size */
971 } else if (supr_status == TX_STATUS_SUPR_FRAG) {
972 /* if there were underflows, but pre-loading is not active,
973 notify rate adaptation.
975 if (brcms_c_ffpld_check_txfunfl(wlc,
976 prio2fifo[tid]) > 0) {
980 } else if (txs->phyerr) {
982 wiphy_err(wiphy, "wl%d: ampdu tx phy "
983 "error (0x%x)\n", wlc->pub->unit,
987 brcmu_prpkt("txpkt (AMPDU)", p);
988 brcms_c_print_txdesc((d11txh_t *) p->data);
990 brcms_c_print_txstatus(txs);
994 /* loop through all pkts and retry if not acked */
996 tx_info = IEEE80211_SKB_CB(p);
997 txh = (d11txh_t *) p->data;
998 mcl = le16_to_cpu(txh->MacTxControlLow);
999 plcp = (u8 *) (txh + 1);
1000 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
1001 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
1003 if (tot_mpdu == 0) {
1004 mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
1005 mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
1008 index = TX_SEQ_TO_INDEX(seq);
1011 bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
1012 BCMMSG(wlc->wiphy, "tid %d seq %d,"
1013 " start_seq %d, bindex %d set %d, index %d\n",
1014 tid, seq, start_seq, bindex,
1015 isset(bitmap, bindex), index);
1016 /* if acked then clear bit and free packet */
1017 if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
1018 && isset(bitmap, bindex)) {
1019 ini->tx_in_transit--;
1020 ini->txretry[index] = 0;
1022 /* ampdu_ack_len: number of acked aggregated frames */
1023 /* ampdu_len: number of aggregated frames */
1024 brcms_c_ampdu_rate_status(wlc, tx_info, txs,
1026 tx_info->flags |= IEEE80211_TX_STAT_ACK;
1027 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
1028 tx_info->status.ampdu_ack_len =
1029 tx_info->status.ampdu_len = 1;
1031 skb_pull(p, D11_PHY_HDR_LEN);
1032 skb_pull(p, D11_TXH_LEN);
1034 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1040 /* either retransmit or send bar if ack not recd */
1042 struct ieee80211_tx_rate *txrate =
1043 tx_info->status.rates;
1044 if (retry && (txrate[0].count < (int)retry_limit)) {
1045 ini->txretry[index]++;
1046 ini->tx_in_transit--;
1047 /* Use high prededence for retransmit to give some punch */
1048 /* brcms_c_txq_enq(wlc, scb, p,
1049 * WLC_PRIO_TO_PREC(tid)); */
1050 brcms_c_txq_enq(wlc, scb, p,
1051 WLC_PRIO_TO_HI_PREC(tid));
1054 ini->tx_in_transit--;
1055 ieee80211_tx_info_clear_status(tx_info);
1056 tx_info->status.ampdu_ack_len = 0;
1057 tx_info->status.ampdu_len = 1;
1059 IEEE80211_TX_STAT_AMPDU_NO_BACK;
1060 skb_pull(p, D11_PHY_HDR_LEN);
1061 skb_pull(p, D11_TXH_LEN);
1062 wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
1063 "transit %d\n", SHORTNAME, seq,
1064 ini->tx_in_transit);
1065 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1071 /* break out if last packet of ampdu */
1072 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1076 p = GETNEXTTXP(wlc, queue);
1078 brcms_c_send_q(wlc);
1080 /* update rate state */
1081 antselid = brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
1083 brcms_c_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
1086 /* initialize the initiator code for tid */
1087 static scb_ampdu_tid_ini_t *brcms_c_ampdu_init_tid_ini(struct ampdu_info *ampdu,
1088 scb_ampdu_t *scb_ampdu,
1089 u8 tid, bool override)
1091 scb_ampdu_tid_ini_t *ini;
1093 /* check for per-tid control of ampdu */
1094 if (!ampdu->ini_enable[tid]) {
1095 wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
1100 ini = SCB_AMPDU_INI(scb_ampdu, tid);
1102 ini->scb = scb_ampdu->scb;
1103 ini->magic = INI_MAGIC;
1107 static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
1109 struct brcms_c_info *wlc = ampdu->wlc;
1111 wlc->pub->_ampdu = false;
1114 if (!N_ENAB(wlc->pub)) {
1115 wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
1116 "nmode enabled\n", wlc->pub->unit);
1119 if (!brcms_c_ampdu_cap(ampdu)) {
1120 wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
1121 "ampdu capable\n", wlc->pub->unit);
1124 wlc->pub->_ampdu = on;
1130 static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
1132 if (WLC_PHY_11N_CAP(ampdu->wlc->band))
1138 static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
1142 for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
1143 /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
1145 rate = MCS_RATE(mcs, false, false);
1146 ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
1147 /* 40 MHz, No SGI */
1148 rate = MCS_RATE(mcs, true, false);
1149 ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
1151 rate = MCS_RATE(mcs, false, true);
1152 ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
1154 rate = MCS_RATE(mcs, true, true);
1155 ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
1159 void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
1161 char template[T_RAM_ACCESS_SZ * 2];
1163 /* driver needs to write the ta in the template; ta is at offset 16 */
1164 memset(template, 0, sizeof(template));
1165 memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1166 brcms_c_write_template_ram(wlc, (T_BA_TPL_BASE + 16),
1167 (T_RAM_ACCESS_SZ * 2),
1171 bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid)
1173 return wlc->ampdu->ini_enable[tid];
1176 void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
1178 struct brcms_c_info *wlc = ampdu->wlc;
1180 /* Extend ucode internal watchdog timer to match larger received frames */
1181 if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1182 IEEE80211_HT_MAX_AMPDU_64K) {
1183 brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1184 brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1186 brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1187 brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1192 * callback function that helps flushing ampdu packets from a priority queue
1194 static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
1196 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
1197 struct cb_del_ampdu_pars *ampdu_pars =
1198 (struct cb_del_ampdu_pars *)arg_a;
1201 rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
1202 rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
1203 tx_info->control.sta == ampdu_pars->sta);
1204 rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
1209 * callback function that helps invalidating ampdu packets in a DMA queue
1211 static void dma_cb_fn_ampdu(void *txi, void *arg_a)
1213 struct ieee80211_sta *sta = arg_a;
1214 struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
1216 if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
1217 (tx_info->control.sta == sta || sta == NULL))
1218 tx_info->control.sta = NULL;
1222 * When a remote party is no longer available for ampdu communication, any
1223 * pending tx ampdu packets in the driver have to be flushed.
1225 void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
1226 struct ieee80211_sta *sta, u16 tid)
1228 struct brcms_c_txq_info *qi = wlc->pkt_queue;
1229 struct pktq *pq = &qi->q;
1231 struct cb_del_ampdu_pars ampdu_pars;
1233 ampdu_pars.sta = sta;
1234 ampdu_pars.tid = tid;
1235 for (prec = 0; prec < pq->num_prec; prec++) {
1236 brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
1237 (void *)&du_pars);
1239 brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);