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>
27
#include "wlc_types.h"
33
#include "phy/wlc_phy_hal.h"
34
#include "wlc_antsel.h"
35
#include "wl_export.h"
37
#include "wlc_channel.h"
39
#include "wlc_ampdu.h"
41
#define AMPDU_MAX_MPDU 32 /* max number of mpdus in an ampdu */
42
#define AMPDU_NUM_MPDU_LEGACY 16 /* max number of mpdus in an ampdu to a legacy */
43
#define AMPDU_TX_BA_MAX_WSIZE 64 /* max Tx ba window size (in pdu) */
44
#define AMPDU_TX_BA_DEF_WSIZE 64 /* default Tx ba window size (in pdu) */
45
#define AMPDU_RX_BA_DEF_WSIZE 64 /* max Rx ba window size (in pdu) */
46
#define AMPDU_RX_BA_MAX_WSIZE 64 /* default Rx ba window size (in pdu) */
47
#define AMPDU_MAX_DUR 5 /* max dur of tx ampdu (in msec) */
48
#define AMPDU_DEF_RETRY_LIMIT 5 /* default tx retry limit */
49
#define AMPDU_DEF_RR_RETRY_LIMIT 2 /* default tx retry limit at reg rate */
50
#define AMPDU_DEF_TXPKT_WEIGHT 2 /* default weight of ampdu in txfifo */
51
#define AMPDU_DEF_FFPLD_RSVD 2048 /* default ffpld reserved bytes */
52
#define AMPDU_INI_FREE 10 /* # of inis to be freed on detach */
53
#define AMPDU_SCB_MAX_RELEASE 20 /* max # of mpdus released at a time */
55
#define NUM_FFPLD_FIFO 4 /* number of fifo concerned by pre-loading */
56
#define FFPLD_TX_MAX_UNFL 200 /* default value of the average number of ampdu
59
#define FFPLD_MPDU_SIZE 1800 /* estimate of maximum mpdu size */
60
#define FFPLD_MAX_MCS 23 /* we don't deal with mcs 32 */
61
#define FFPLD_PLD_INCR 1000 /* increments in bytes */
62
#define FFPLD_MAX_AMPDU_CNT 5000 /* maximum number of ampdu we
63
* accumulate between resets.
66
#define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
68
/* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
69
#define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
70
AMPDU_DELIMITER_LEN + 3\
71
+ DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
73
/* structure to hold tx fifo information and pre-loading state
74
* counters specific to tx underflows of ampdus
75
* some counters might be redundant with the ones in wlc or ampdu structures.
76
* This allows to maintain a specific state independently of
77
* how often and/or when the wlc counters are updated.
79
typedef struct wlc_fifo_info {
80
u16 ampdu_pld_size; /* number of bytes to be pre-loaded */
81
u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1]; /* per-mcs max # of mpdus in an ampdu */
82
u16 prev_txfunfl; /* num of underflows last read from the HW macstats counter */
83
u32 accum_txfunfl; /* num of underflows since we modified pld params */
84
u32 accum_txampdu; /* num of tx ampdu since we modified pld params */
85
u32 prev_txampdu; /* previous reading of tx ampdu */
86
u32 dmaxferrate; /* estimated dma avg xfer rate in kbits/sec */
89
/* AMPDU module specific state */
91
struct wlc_info *wlc; /* pointer to main wlc structure */
92
int scb_handle; /* scb cubby handle to retrieve data from scb */
93
u8 ini_enable[AMPDU_MAX_SCB_TID]; /* per-tid initiator enable/disable of ampdu */
94
u8 ba_tx_wsize; /* Tx ba window size (in pdu) */
95
u8 ba_rx_wsize; /* Rx ba window size (in pdu) */
96
u8 retry_limit; /* mpdu transmit retry limit */
97
u8 rr_retry_limit; /* mpdu transmit retry limit at regular rate */
98
u8 retry_limit_tid[AMPDU_MAX_SCB_TID]; /* per-tid mpdu transmit retry limit */
99
/* per-tid mpdu transmit retry limit at regular rate */
100
u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
101
u8 mpdu_density; /* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
102
s8 max_pdu; /* max pdus allowed in ampdu */
103
u8 dur; /* max duration of an ampdu (in msec) */
104
u8 txpkt_weight; /* weight of ampdu in txfifo; reduces rate lag */
105
u8 rx_factor; /* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
106
u32 ffpld_rsvd; /* number of bytes to reserve for preload */
107
u32 max_txlen[MCS_TABLE_SIZE][2][2]; /* max size of ampdu per mcs, bw and sgi */
108
void *ini_free[AMPDU_INI_FREE]; /* array of ini's to be freed on detach */
109
bool mfbr; /* enable multiple fallback rate */
110
u32 tx_max_funl; /* underflows should be kept such that
111
* (tx_max_funfl*underflows) < tx frames
113
wlc_fifo_info_t fifo_tb[NUM_FFPLD_FIFO]; /* table of fifo infos */
117
/* used for flushing ampdu packets */
118
struct cb_del_ampdu_pars {
119
struct ieee80211_sta *sta;
123
#define AMPDU_CLEANUPFLAG_RX (0x1)
124
#define AMPDU_CLEANUPFLAG_TX (0x2)
126
#define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
127
#define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
129
static void wlc_ffpld_init(struct ampdu_info *ampdu);
130
static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int f);
131
static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
133
static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
134
scb_ampdu_t *scb_ampdu,
135
u8 tid, bool override);
136
static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur);
137
static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb);
138
static void scb_ampdu_update_config_all(struct ampdu_info *ampdu);
140
#define wlc_ampdu_txflowcontrol(a, b, c) do {} while (0)
142
static void wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
144
struct sk_buff *p, tx_status_t *txs,
145
u32 frmtxstatus, u32 frmtxstatus2);
146
static bool wlc_ampdu_cap(struct ampdu_info *ampdu);
147
static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on);
149
struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc)
151
struct ampdu_info *ampdu;
154
ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
156
wiphy_err(wlc->wiphy, "wl%d: wlc_ampdu_attach: out of mem\n",
162
for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
163
ampdu->ini_enable[i] = true;
164
/* Disable ampdu for VO by default */
165
ampdu->ini_enable[PRIO_8021D_VO] = false;
166
ampdu->ini_enable[PRIO_8021D_NC] = false;
168
/* Disable ampdu for BK by default since not enough fifo space */
169
ampdu->ini_enable[PRIO_8021D_NONE] = false;
170
ampdu->ini_enable[PRIO_8021D_BK] = false;
172
ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
173
ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
174
ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
175
ampdu->max_pdu = AUTO;
176
ampdu->dur = AMPDU_MAX_DUR;
177
ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
179
ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
180
/* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
181
if (WLCISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
182
ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
184
ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
185
ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
186
ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
188
for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
189
ampdu->retry_limit_tid[i] = ampdu->retry_limit;
190
ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
193
ampdu_update_max_txlen(ampdu, ampdu->dur);
195
/* try to set ampdu to the default value */
196
wlc_ampdu_set(ampdu, wlc->pub->_ampdu);
198
ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
199
wlc_ffpld_init(ampdu);
204
void wlc_ampdu_detach(struct ampdu_info *ampdu)
211
/* free all ini's which were to be freed on callbacks which were never called */
212
for (i = 0; i < AMPDU_INI_FREE; i++) {
213
kfree(ampdu->ini_free[i]);
216
wlc_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
220
static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb)
222
scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
225
scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
227
/* go back to legacy size if some preloading is occurring */
228
for (i = 0; i < NUM_FFPLD_FIFO; i++) {
229
if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
230
scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
233
/* apply user override */
234
if (ampdu->max_pdu != AUTO)
235
scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
237
scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
239
if (scb_ampdu->max_rxlen)
241
min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 1600);
243
scb_ampdu->release = min(scb_ampdu->release,
244
ampdu->fifo_tb[TX_AC_BE_FIFO].
245
mcs2ampdu_table[FFPLD_MAX_MCS]);
248
static void scb_ampdu_update_config_all(struct ampdu_info *ampdu)
250
scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
253
static void wlc_ffpld_init(struct ampdu_info *ampdu)
256
wlc_fifo_info_t *fifo;
258
for (j = 0; j < NUM_FFPLD_FIFO; j++) {
259
fifo = (ampdu->fifo_tb + j);
260
fifo->ampdu_pld_size = 0;
261
for (i = 0; i <= FFPLD_MAX_MCS; i++)
262
fifo->mcs2ampdu_table[i] = 255;
263
fifo->dmaxferrate = 0;
264
fifo->accum_txampdu = 0;
265
fifo->prev_txfunfl = 0;
266
fifo->accum_txfunfl = 0;
271
/* evaluate the dma transfer rate using the tx underflows as feedback.
272
* If necessary, increase tx fifo preloading. If not enough,
273
* decrease maximum ampdu size for each mcs till underflows stop
274
* Return 1 if pre-loading not active, -1 if not an underflow event,
275
* 0 if pre-loading module took care of the event.
277
static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int fid)
279
struct ampdu_info *ampdu = wlc->ampdu;
280
u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
283
u32 current_ampdu_cnt = 0;
286
wlc_fifo_info_t *fifo = (ampdu->fifo_tb + fid);
290
/* return if we got here for a different reason than underflows */
293
M_UCODE_MACSTAT + offsetof(macstat_t, txfunfl[fid]));
294
new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
295
if (new_txunfl == 0) {
296
BCMMSG(wlc->wiphy, "TX status FRAG set but no tx underflows\n");
299
fifo->prev_txfunfl = cur_txunfl;
301
if (!ampdu->tx_max_funl)
304
/* check if fifo is big enough */
305
if (wlc_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz)) {
309
if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
312
max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
313
fifo->accum_txfunfl += new_txunfl;
315
/* we need to wait for at least 10 underflows */
316
if (fifo->accum_txfunfl < 10)
319
BCMMSG(wlc->wiphy, "ampdu_count %d tx_underflows %d\n",
320
current_ampdu_cnt, fifo->accum_txfunfl);
323
compute the current ratio of tx unfl per ampdu.
324
When the current ampdu count becomes too
325
big while the ratio remains small, we reset
326
the current count in order to not
327
introduce too big of a latency in detecting a
328
large amount of tx underflows later.
331
txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
333
if (txunfl_ratio > ampdu->tx_max_funl) {
334
if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
335
fifo->accum_txfunfl = 0;
340
min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
342
/* In case max value max_pdu is already lower than
343
the fifo depth, there is nothing more we can do.
346
if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
347
fifo->accum_txfunfl = 0;
351
if (fifo->ampdu_pld_size < max_pld_size) {
353
/* increment by TX_FIFO_PLD_INC bytes */
354
fifo->ampdu_pld_size += FFPLD_PLD_INCR;
355
if (fifo->ampdu_pld_size > max_pld_size)
356
fifo->ampdu_pld_size = max_pld_size;
358
/* update scb release size */
359
scb_ampdu_update_config_all(ampdu);
362
compute a new dma xfer rate for max_mpdu @ max mcs.
363
This is the minimum dma rate that
364
can achieve no underflow condition for the current mpdu size.
366
/* note : we divide/multiply by 100 to avoid integer overflows */
369
(max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
370
/ (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
372
BCMMSG(wlc->wiphy, "DMA estimated transfer rate %d; "
373
"pre-load size %d\n",
374
fifo->dmaxferrate, fifo->ampdu_pld_size);
377
/* decrease ampdu size */
378
if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
379
if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
380
fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
381
AMPDU_NUM_MPDU_LEGACY - 1;
383
fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
385
/* recompute the table */
386
wlc_ffpld_calc_mcs2ampdu_table(ampdu, fid);
388
/* update scb release size */
389
scb_ampdu_update_config_all(ampdu);
392
fifo->accum_txfunfl = 0;
396
static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
399
u32 phy_rate, dma_rate, tmp;
401
wlc_fifo_info_t *fifo = (ampdu->fifo_tb + f);
403
/* recompute the dma rate */
404
/* note : we divide/multiply by 100 to avoid integer overflows */
406
min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
407
phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
410
(max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
411
/ (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
412
fifo->dmaxferrate = dma_rate;
414
/* fill up the mcs2ampdu table; do not recalc the last mcs */
415
dma_rate = dma_rate >> 7;
416
for (i = 0; i < FFPLD_MAX_MCS; i++) {
417
/* shifting to keep it within integer range */
418
phy_rate = MCS_RATE(i, true, false) >> 7;
419
if (phy_rate > dma_rate) {
420
tmp = ((fifo->ampdu_pld_size * phy_rate) /
421
((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
422
tmp = min_t(u32, tmp, 255);
423
fifo->mcs2ampdu_table[i] = (u8) tmp;
429
wlc_ampdu_agg(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p,
432
scb_ampdu_t *scb_ampdu;
433
scb_ampdu_tid_ini_t *ini;
434
u8 tid = (u8) (p->priority);
436
scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
438
/* initialize initiator on first packet; sends addba req */
439
ini = SCB_AMPDU_INI(scb_ampdu, tid);
440
if (ini->magic != INI_MAGIC) {
441
ini = wlc_ampdu_init_tid_ini(ampdu, scb_ampdu, tid, false);
447
wlc_sendampdu(struct ampdu_info *ampdu, struct wlc_txq_info *qi,
448
struct sk_buff **pdu, int prec)
450
struct wlc_info *wlc;
451
struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
454
u8 preamble_type = WLC_GF_PREAMBLE;
455
u8 fbr_preamble_type = WLC_GF_PREAMBLE;
456
u8 rts_preamble_type = WLC_LONG_PREAMBLE;
457
u8 rts_fbr_preamble_type = WLC_LONG_PREAMBLE;
459
bool rr = true, fbr = false;
460
uint i, count = 0, fifo, seg_cnt = 0;
461
u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
462
u32 ampdu_len, maxlen = 0;
463
d11txh_t *txh = NULL;
465
struct ieee80211_hdr *h;
467
scb_ampdu_t *scb_ampdu;
468
scb_ampdu_tid_ini_t *ini;
470
bool use_rts = false, use_cts = false;
471
ratespec_t rspec = 0, rspec_fallback = 0;
472
ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
473
u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
474
struct ieee80211_rts *rts;
478
struct ieee80211_tx_info *tx_info;
486
tid = (u8) (p->priority);
488
f = ampdu->fifo_tb + prio2fifo[tid];
490
scb = wlc->pub->global_scb;
491
scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
492
ini = &scb_ampdu->ini[tid];
494
/* Let pressure continue to build ... */
495
qlen = pktq_plen(&qi->q, prec);
496
if (ini->tx_in_transit > 0 && qlen < scb_ampdu->max_pdu) {
500
wlc_ampdu_agg(ampdu, scb, p, tid);
502
if (wlc->block_datafifo) {
503
wiphy_err(wiphy, "%s: Fifo blocked\n", __func__);
506
rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
510
struct ieee80211_tx_rate *txrate;
512
tx_info = IEEE80211_SKB_CB(p);
513
txrate = tx_info->status.rates;
515
if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
516
err = wlc_prep_pdu(wlc, p, &fifo);
518
wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
526
wiphy_err(wiphy, "wl%d: wlc_sendampdu: "
527
"prep_xdu retry; seq 0x%x\n",
528
wlc->pub->unit, seq);
533
/* error in the packet; reject it */
534
wiphy_err(wiphy, "wl%d: wlc_sendampdu: prep_xdu "
535
"rejected; seq 0x%x\n", wlc->pub->unit, seq);
540
/* pkt is good to be aggregated */
541
txh = (d11txh_t *) p->data;
542
plcp = (u8 *) (txh + 1);
543
h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
544
seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
545
index = TX_SEQ_TO_INDEX(seq);
547
/* check mcl fields and test whether it can be agg'd */
548
mcl = le16_to_cpu(txh->MacTxControlLow);
549
mcl &= ~TXC_AMPDU_MASK;
550
fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
551
txh->PreloadSize = 0; /* always default to 0 */
553
/* Handle retry limits */
554
if (txrate[0].count <= rr_retry_limit) {
564
/* extract the length info */
565
len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
566
: WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
568
/* retrieve null delimiter count */
569
ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
572
BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
573
wlc->pub->unit, count, len);
576
* aggregateable mpdu. For ucode/hw agg,
577
* test whether need to break or change the epoch
580
mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
581
/* refill the bits since might be a retx mpdu */
582
mcl |= TXC_STARTMSDU;
583
rts = (struct ieee80211_rts *)&txh->rts_frame;
585
if (ieee80211_is_rts(rts->frame_control)) {
589
if (ieee80211_is_cts(rts->frame_control)) {
594
mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
595
mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
598
len = roundup(len, 4);
599
ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
601
dma_len += (u16) bcm_pkttotlen(p);
603
BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
604
" seg_cnt %d null delim %d\n",
605
wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
607
txh->MacTxControlLow = cpu_to_le16(mcl);
609
/* this packet is added */
612
/* patch the first MPDU */
614
u8 plcp0, plcp3, is40, sgi;
615
struct ieee80211_sta *sta;
617
sta = tx_info->control.sta;
623
plcp0 = txh->FragPLCPFallback[0];
624
plcp3 = txh->FragPLCPFallback[3];
627
is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
628
sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
629
mcs = plcp0 & ~MIMO_PLCP_40MHZ;
631
min(scb_ampdu->max_rxlen,
632
ampdu->max_txlen[mcs][is40][sgi]);
634
/* XXX Fix me to honor real max_rxlen */
635
/* can fix this as soon as ampdu_action() in mac80211.h
636
* gets extra u8buf_size par */
641
CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
642
? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
644
/* rebuild the rspec and rspec_fallback */
645
rspec = RSPEC_MIMORATE;
646
rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
647
if (plcp[0] & MIMO_PLCP_40MHZ)
648
rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
650
if (fbr_iscck) /* CCK */
652
CCK_RSPEC(CCK_PHY2MAC_RATE
653
(txh->FragPLCPFallback[0]));
655
rspec_fallback = RSPEC_MIMORATE;
657
txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
658
if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
660
(PHY_TXC1_BW_40MHZ <<
664
if (use_rts || use_cts) {
666
wlc_rspec_to_rts_rspec(wlc, rspec, false,
669
wlc_rspec_to_rts_rspec(wlc, rspec_fallback,
670
false, mimo_ctlchbw);
674
/* if (first mpdu for host agg) */
675
/* test whether to add more */
676
if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
677
(count == f->mcs2ampdu_table[mcs])) {
678
BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
679
" ampdu at %d for mcs %d\n",
680
wlc->pub->unit, count, mcs);
684
if (count == scb_ampdu->max_pdu) {
688
/* check to see if the next pkt is a candidate for aggregation */
689
p = pktq_ppeek(&qi->q, prec);
690
tx_info = IEEE80211_SKB_CB(p); /* tx_info must be checked with current p */
693
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
694
((u8) (p->priority) == tid)) {
697
bcm_pkttotlen(p) + AMPDU_MAX_MPDU_OVERHEAD;
698
plen = max(scb_ampdu->min_len, plen);
700
if ((plen + ampdu_len) > maxlen) {
702
wiphy_err(wiphy, "%s: Bogus plen #1\n",
707
/* check if there are enough descriptors available */
708
if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
709
wiphy_err(wiphy, "%s: No fifo space "
714
p = bcm_pktq_pdeq(&qi->q, prec);
721
ini->tx_in_transit += count;
724
/* patch up the last txh */
725
txh = (d11txh_t *) pkt[count - 1]->data;
726
mcl = le16_to_cpu(txh->MacTxControlLow);
727
mcl &= ~TXC_AMPDU_MASK;
728
mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
729
txh->MacTxControlLow = cpu_to_le16(mcl);
731
/* remove the null delimiter after last mpdu */
732
ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
733
txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
734
ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
736
/* remove the pad len from last mpdu */
737
fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
738
len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
739
: WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
740
ampdu_len -= roundup(len, 4) - len;
742
/* patch up the first txh & plcp */
743
txh = (d11txh_t *) pkt[0]->data;
744
plcp = (u8 *) (txh + 1);
746
WLC_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
747
/* mark plcp to indicate ampdu */
748
WLC_SET_MIMO_PLCP_AMPDU(plcp);
750
/* reset the mixed mode header durations */
753
wlc_calc_lsig_len(wlc, rspec, ampdu_len);
754
txh->MModeLen = cpu_to_le16(mmodelen);
755
preamble_type = WLC_MM_PREAMBLE;
757
if (txh->MModeFbrLen) {
759
wlc_calc_lsig_len(wlc, rspec_fallback, ampdu_len);
760
txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
761
fbr_preamble_type = WLC_MM_PREAMBLE;
764
/* set the preload length */
765
if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
766
dma_len = min(dma_len, f->ampdu_pld_size);
767
txh->PreloadSize = cpu_to_le16(dma_len);
769
txh->PreloadSize = 0;
771
mch = le16_to_cpu(txh->MacTxControlHigh);
773
/* update RTS dur fields */
774
if (use_rts || use_cts) {
776
rts = (struct ieee80211_rts *)&txh->rts_frame;
777
if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
778
TXC_PREAMBLE_RTS_MAIN_SHORT)
779
rts_preamble_type = WLC_SHORT_PREAMBLE;
781
if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
782
TXC_PREAMBLE_RTS_FB_SHORT)
783
rts_fbr_preamble_type = WLC_SHORT_PREAMBLE;
786
wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec,
787
rspec, rts_preamble_type,
788
preamble_type, ampdu_len,
790
rts->duration = cpu_to_le16(durid);
791
durid = wlc_compute_rtscts_dur(wlc, use_cts,
794
rts_fbr_preamble_type,
797
txh->RTSDurFallback = cpu_to_le16(durid);
798
/* set TxFesTimeNormal */
799
txh->TxFesTimeNormal = rts->duration;
800
/* set fallback rate version of TxFesTimeNormal */
801
txh->TxFesTimeFallback = txh->RTSDurFallback;
804
/* set flag and plcp for fallback rate */
806
mch |= TXC_AMPDU_FBR;
807
txh->MacTxControlHigh = cpu_to_le16(mch);
808
WLC_SET_MIMO_PLCP_AMPDU(plcp);
809
WLC_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
812
BCMMSG(wlc->wiphy, "wl%d: count %d ampdu_len %d\n",
813
wlc->pub->unit, count, ampdu_len);
815
/* inform rate_sel if it this is a rate probe pkt */
816
frameid = le16_to_cpu(txh->TxFrameID);
817
if (frameid & TXFID_RATE_PROBE_MASK) {
818
wiphy_err(wiphy, "%s: XXX what to do with "
819
"TXFID_RATE_PROBE_MASK!?\n", __func__);
821
for (i = 0; i < count; i++)
822
wlc_txfifo(wlc, fifo, pkt[i], i == (count - 1),
823
ampdu->txpkt_weight);
831
wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
832
struct sk_buff *p, tx_status_t *txs)
834
scb_ampdu_t *scb_ampdu;
835
struct wlc_info *wlc = ampdu->wlc;
836
scb_ampdu_tid_ini_t *ini;
838
struct ieee80211_tx_info *tx_info;
840
tx_info = IEEE80211_SKB_CB(p);
842
/* BMAC_NOTE: For the split driver, second level txstatus comes later
843
* So if the ACK was received then wait for the second level else just
846
if (txs->status & TX_STATUS_ACK_RCV) {
849
/* wait till the next 8 bytes of txstatus is available */
850
while (((s1 = R_REG(&wlc->regs->frmtxstatus)) & TXS_V) == 0) {
853
if (status_delay > 10) {
854
return; /* error condition */
858
s2 = R_REG(&wlc->regs->frmtxstatus2);
862
scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
863
ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
864
wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
866
/* loop through all pkts and free */
867
u8 queue = txs->frameid & TXFID_QUEUE_MASK;
871
tx_info = IEEE80211_SKB_CB(p);
872
txh = (d11txh_t *) p->data;
873
mcl = le16_to_cpu(txh->MacTxControlLow);
874
bcm_pkt_buf_free_skb(p);
875
/* break out if last packet of ampdu */
876
if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
879
p = GETNEXTTXP(wlc, queue);
881
wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
883
wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
887
rate_status(struct wlc_info *wlc, struct ieee80211_tx_info *tx_info,
888
tx_status_t *txs, u8 mcs)
890
struct ieee80211_tx_rate *txrate = tx_info->status.rates;
893
/* clear the rest of the rates */
894
for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
900
#define SHORTNAME "AMPDU status"
903
wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
904
struct sk_buff *p, tx_status_t *txs,
907
scb_ampdu_t *scb_ampdu;
908
struct wlc_info *wlc = ampdu->wlc;
909
scb_ampdu_tid_ini_t *ini;
910
u8 bitmap[8], queue, tid;
913
struct ieee80211_hdr *h;
914
u16 seq, start_seq = 0, bindex, index, mcl;
916
bool ba_recd = false, ack_recd = false;
917
u8 suc_mpdu = 0, tot_mpdu = 0;
919
bool update_rate = true, retry = true, tx_error = false;
922
u8 retry_limit, rr_retry_limit;
923
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
924
struct wiphy *wiphy = wlc->wiphy;
927
u8 hole[AMPDU_MAX_MPDU];
928
memset(hole, 0, sizeof(hole));
931
scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
932
tid = (u8) (p->priority);
934
ini = SCB_AMPDU_INI(scb_ampdu, tid);
935
retry_limit = ampdu->retry_limit_tid[tid];
936
rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
937
memset(bitmap, 0, sizeof(bitmap));
938
queue = txs->frameid & TXFID_QUEUE_MASK;
939
supr_status = txs->status & TX_STATUS_SUPR_MASK;
941
if (txs->status & TX_STATUS_ACK_RCV) {
942
if (TX_STATUS_SUPR_UF == supr_status) {
946
WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
947
start_seq = txs->sequence >> SEQNUM_SHIFT;
948
bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
949
TX_STATUS_BA_BMAP03_SHIFT;
951
WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
952
WARN_ON(!(s1 & TX_STATUS_AMPDU));
955
(s1 & TX_STATUS_BA_BMAP47_MASK) <<
956
TX_STATUS_BA_BMAP47_SHIFT;
957
bitmap[1] = (s1 >> 8) & 0xff;
958
bitmap[2] = (s1 >> 16) & 0xff;
959
bitmap[3] = (s1 >> 24) & 0xff;
961
bitmap[4] = s2 & 0xff;
962
bitmap[5] = (s2 >> 8) & 0xff;
963
bitmap[6] = (s2 >> 16) & 0xff;
964
bitmap[7] = (s2 >> 24) & 0xff;
970
if (supr_status == TX_STATUS_SUPR_BADCH) {
971
wiphy_err(wiphy, "%s: Pkt tx suppressed, "
972
"illegal channel possibly %d\n",
973
__func__, CHSPEC_CHANNEL(
974
wlc->default_bss->chanspec));
976
if (supr_status != TX_STATUS_SUPR_FRAG)
977
wiphy_err(wiphy, "%s: wlc_ampdu_dotx"
978
"status:supr_status 0x%x\n",
979
__func__, supr_status);
981
/* no need to retry for badch; will fail again */
982
if (supr_status == TX_STATUS_SUPR_BADCH ||
983
supr_status == TX_STATUS_SUPR_EXPTIME) {
985
} else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
986
/* TX underflow : try tuning pre-loading or ampdu size */
987
} else if (supr_status == TX_STATUS_SUPR_FRAG) {
988
/* if there were underflows, but pre-loading is not active,
989
notify rate adaptation.
991
if (wlc_ffpld_check_txfunfl(wlc, prio2fifo[tid])
996
} else if (txs->phyerr) {
998
wiphy_err(wiphy, "wl%d: wlc_ampdu_dotxstatus: tx phy "
999
"error (0x%x)\n", wlc->pub->unit,
1002
if (WL_ERROR_ON()) {
1003
bcm_prpkt("txpkt (AMPDU)", p);
1004
wlc_print_txdesc((d11txh_t *) p->data);
1006
wlc_print_txstatus(txs);
1010
/* loop through all pkts and retry if not acked */
1012
tx_info = IEEE80211_SKB_CB(p);
1013
txh = (d11txh_t *) p->data;
1014
mcl = le16_to_cpu(txh->MacTxControlLow);
1015
plcp = (u8 *) (txh + 1);
1016
h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
1017
seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
1019
if (tot_mpdu == 0) {
1020
mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
1021
mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
1024
index = TX_SEQ_TO_INDEX(seq);
1027
bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
1028
BCMMSG(wlc->wiphy, "tid %d seq %d,"
1029
" start_seq %d, bindex %d set %d, index %d\n",
1030
tid, seq, start_seq, bindex,
1031
isset(bitmap, bindex), index);
1032
/* if acked then clear bit and free packet */
1033
if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
1034
&& isset(bitmap, bindex)) {
1035
ini->tx_in_transit--;
1036
ini->txretry[index] = 0;
1038
/* ampdu_ack_len: number of acked aggregated frames */
1039
/* ampdu_len: number of aggregated frames */
1040
rate_status(wlc, tx_info, txs, mcs);
1041
tx_info->flags |= IEEE80211_TX_STAT_ACK;
1042
tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
1043
tx_info->status.ampdu_ack_len =
1044
tx_info->status.ampdu_len = 1;
1046
skb_pull(p, D11_PHY_HDR_LEN);
1047
skb_pull(p, D11_TXH_LEN);
1049
ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1055
/* either retransmit or send bar if ack not recd */
1057
struct ieee80211_tx_rate *txrate =
1058
tx_info->status.rates;
1059
if (retry && (txrate[0].count < (int)retry_limit)) {
1060
ini->txretry[index]++;
1061
ini->tx_in_transit--;
1062
/* Use high prededence for retransmit to give some punch */
1063
/* wlc_txq_enq(wlc, scb, p, WLC_PRIO_TO_PREC(tid)); */
1064
wlc_txq_enq(wlc, scb, p,
1065
WLC_PRIO_TO_HI_PREC(tid));
1068
ini->tx_in_transit--;
1069
ieee80211_tx_info_clear_status(tx_info);
1070
tx_info->status.ampdu_ack_len = 0;
1071
tx_info->status.ampdu_len = 1;
1073
IEEE80211_TX_STAT_AMPDU_NO_BACK;
1074
skb_pull(p, D11_PHY_HDR_LEN);
1075
skb_pull(p, D11_TXH_LEN);
1076
wiphy_err(wiphy, "%s: BA Timeout, seq %d, in_"
1077
"transit %d\n", SHORTNAME, seq,
1078
ini->tx_in_transit);
1079
ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1085
/* break out if last packet of ampdu */
1086
if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1090
p = GETNEXTTXP(wlc, queue);
1094
/* update rate state */
1095
antselid = wlc_antsel_antsel2id(wlc->asi, mimoantsel);
1097
wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
1100
/* initialize the initiator code for tid */
1101
static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
1102
scb_ampdu_t *scb_ampdu,
1103
u8 tid, bool override)
1105
scb_ampdu_tid_ini_t *ini;
1107
/* check for per-tid control of ampdu */
1108
if (!ampdu->ini_enable[tid]) {
1109
wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
1114
ini = SCB_AMPDU_INI(scb_ampdu, tid);
1116
ini->scb = scb_ampdu->scb;
1117
ini->magic = INI_MAGIC;
1121
static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on)
1123
struct wlc_info *wlc = ampdu->wlc;
1125
wlc->pub->_ampdu = false;
1128
if (!N_ENAB(wlc->pub)) {
1129
wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
1130
"nmode enabled\n", wlc->pub->unit);
1133
if (!wlc_ampdu_cap(ampdu)) {
1134
wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
1135
"ampdu capable\n", wlc->pub->unit);
1138
wlc->pub->_ampdu = on;
1144
static bool wlc_ampdu_cap(struct ampdu_info *ampdu)
1146
if (WLC_PHY_11N_CAP(ampdu->wlc->band))
1152
static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
1156
for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
1157
/* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
1159
rate = MCS_RATE(mcs, false, false);
1160
ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
1161
/* 40 MHz, No SGI */
1162
rate = MCS_RATE(mcs, true, false);
1163
ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
1165
rate = MCS_RATE(mcs, false, true);
1166
ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
1168
rate = MCS_RATE(mcs, true, true);
1169
ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
1173
void wlc_ampdu_macaddr_upd(struct wlc_info *wlc)
1175
char template[T_RAM_ACCESS_SZ * 2];
1177
/* driver needs to write the ta in the template; ta is at offset 16 */
1178
memset(template, 0, sizeof(template));
1179
memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1180
wlc_write_template_ram(wlc, (T_BA_TPL_BASE + 16), (T_RAM_ACCESS_SZ * 2),
1184
bool wlc_aggregatable(struct wlc_info *wlc, u8 tid)
1186
return wlc->ampdu->ini_enable[tid];
1189
void wlc_ampdu_shm_upd(struct ampdu_info *ampdu)
1191
struct wlc_info *wlc = ampdu->wlc;
1193
/* Extend ucode internal watchdog timer to match larger received frames */
1194
if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1195
IEEE80211_HT_MAX_AMPDU_64K) {
1196
wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1197
wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1199
wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1200
wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1205
* callback function that helps flushing ampdu packets from a priority queue
1207
static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
1209
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
1210
struct cb_del_ampdu_pars *ampdu_pars =
1211
(struct cb_del_ampdu_pars *)arg_a;
1214
rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
1215
rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
1216
tx_info->control.sta == ampdu_pars->sta);
1217
rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
1222
* callback function that helps invalidating ampdu packets in a DMA queue
1224
static void dma_cb_fn_ampdu(void *txi, void *arg_a)
1226
struct ieee80211_sta *sta = arg_a;
1227
struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
1229
if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
1230
(tx_info->control.sta == sta || sta == NULL))
1231
tx_info->control.sta = NULL;
1235
* When a remote party is no longer available for ampdu communication, any
1236
* pending tx ampdu packets in the driver have to be flushed.
1238
void wlc_ampdu_flush(struct wlc_info *wlc,
1239
struct ieee80211_sta *sta, u16 tid)
1241
struct wlc_txq_info *qi = wlc->pkt_queue;
1242
struct pktq *pq = &qi->q;
1244
struct cb_del_ampdu_pars ampdu_pars;
1246
ampdu_pars.sta = sta;
1247
ampdu_pars.tid = tid;
1248
for (prec = 0; prec < pq->num_prec; prec++) {
1249
bcm_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
1250
(void *)&du_pars);
1252
wlc_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);