staging: brcm80211: remove nested include statements
[pandora-kernel.git] / drivers / staging / brcm80211 / brcmsmac / wlc_ampdu.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
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.
7  *
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.
15  */
16 #include <linux/kernel.h>
17 #include <net/mac80211.h>
18
19 #include <proto/802.1d.h>
20 #include <osl.h>
21 #include <bcmdefs.h>
22 #include <bcmutils.h>
23 #include <siutils.h>
24 #include <wlioctl.h>
25 #include <sbhndpio.h>
26 #include <sbhnddma.h>
27 #include <hnddma.h>
28 #include <d11.h>
29
30 #include "wlc_types.h"
31 #include "wlc_cfg.h"
32 #include "wlc_rate.h"
33 #include "wlc_scb.h"
34 #include "wlc_pub.h"
35 #include "wlc_key.h"
36 #include "phy/wlc_phy_hal.h"
37 #include "wlc_antsel.h"
38 #include "wl_export.h"
39 #include "wl_dbg.h"
40 #include "wlc_bsscfg.h"
41 #include "wlc_channel.h"
42 #include "wlc_mac80211.h"
43 #include "wlc_ampdu.h"
44
45 /*
46  *      Disable AMPDU statistics counters for now
47  */
48 #define WLCNTINCR(a)
49 #define WLCNTADD(a, b)
50
51 #define AMPDU_MAX_MPDU          32      /* max number of mpdus in an ampdu */
52 #define AMPDU_NUM_MPDU_LEGACY   16      /* max number of mpdus in an ampdu to a legacy */
53 #define AMPDU_TX_BA_MAX_WSIZE   64      /* max Tx ba window size (in pdu) */
54 #define AMPDU_TX_BA_DEF_WSIZE   64      /* default Tx ba window size (in pdu) */
55 #define AMPDU_RX_BA_DEF_WSIZE   64      /* max Rx ba window size (in pdu) */
56 #define AMPDU_RX_BA_MAX_WSIZE   64      /* default Rx ba window size (in pdu) */
57 #define AMPDU_MAX_DUR           5       /* max dur of tx ampdu (in msec) */
58 #define AMPDU_DEF_RETRY_LIMIT   5       /* default tx retry limit */
59 #define AMPDU_DEF_RR_RETRY_LIMIT        2       /* default tx retry limit at reg rate */
60 #define AMPDU_DEF_TXPKT_WEIGHT  2       /* default weight of ampdu in txfifo */
61 #define AMPDU_DEF_FFPLD_RSVD    2048    /* default ffpld reserved bytes */
62 #define AMPDU_INI_FREE          10      /* # of inis to be freed on detach */
63 #define AMPDU_SCB_MAX_RELEASE   20      /* max # of mpdus released at a time */
64
65 #define NUM_FFPLD_FIFO 4        /* number of fifo concerned by pre-loading */
66 #define FFPLD_TX_MAX_UNFL   200 /* default value of the average number of ampdu
67                                  * without underflows
68                                  */
69 #define FFPLD_MPDU_SIZE 1800    /* estimate of maximum mpdu size */
70 #define FFPLD_MAX_MCS 23        /* we don't deal with mcs 32 */
71 #define FFPLD_PLD_INCR 1000     /* increments in bytes */
72 #define FFPLD_MAX_AMPDU_CNT 5000        /* maximum number of ampdu we
73                                          * accumulate between resets.
74                                          */
75
76 #define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
77
78 /* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
79 #define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
80         AMPDU_DELIMITER_LEN + 3\
81         + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
82
83 #ifdef BCMDBG
84 u32 wl_ampdu_dbg =
85     WL_AMPDU_UPDN_VAL |
86     WL_AMPDU_ERR_VAL |
87     WL_AMPDU_TX_VAL |
88     WL_AMPDU_RX_VAL |
89     WL_AMPDU_CTL_VAL |
90     WL_AMPDU_HW_VAL | WL_AMPDU_HWTXS_VAL | WL_AMPDU_HWDBG_VAL;
91 #endif
92
93 /* structure to hold tx fifo information and pre-loading state
94  * counters specific to tx underflows of ampdus
95  * some counters might be redundant with the ones in wlc or ampdu structures.
96  * This allows to maintain a specific state independantly of
97  * how often and/or when the wlc counters are updated.
98  */
99 typedef struct wlc_fifo_info {
100         u16 ampdu_pld_size;     /* number of bytes to be pre-loaded */
101         u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];  /* per-mcs max # of mpdus in an ampdu */
102         u16 prev_txfunfl;       /* num of underflows last read from the HW macstats counter */
103         u32 accum_txfunfl;      /* num of underflows since we modified pld params */
104         u32 accum_txampdu;      /* num of tx ampdu since we modified pld params  */
105         u32 prev_txampdu;       /* previous reading of tx ampdu */
106         u32 dmaxferrate;        /* estimated dma avg xfer rate in kbits/sec */
107 } wlc_fifo_info_t;
108
109 /* AMPDU module specific state */
110 struct ampdu_info {
111         struct wlc_info *wlc;   /* pointer to main wlc structure */
112         int scb_handle;         /* scb cubby handle to retrieve data from scb */
113         u8 ini_enable[AMPDU_MAX_SCB_TID];       /* per-tid initiator enable/disable of ampdu */
114         u8 ba_tx_wsize; /* Tx ba window size (in pdu) */
115         u8 ba_rx_wsize; /* Rx ba window size (in pdu) */
116         u8 retry_limit; /* mpdu transmit retry limit */
117         u8 rr_retry_limit;      /* mpdu transmit retry limit at regular rate */
118         u8 retry_limit_tid[AMPDU_MAX_SCB_TID];  /* per-tid mpdu transmit retry limit */
119         /* per-tid mpdu transmit retry limit at regular rate */
120         u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
121         u8 mpdu_density;        /* min mpdu spacing (0-7) ==> 2^(x-1)/8 usec */
122         s8 max_pdu;             /* max pdus allowed in ampdu */
123         u8 dur;         /* max duration of an ampdu (in msec) */
124         u8 txpkt_weight;        /* weight of ampdu in txfifo; reduces rate lag */
125         u8 rx_factor;   /* maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes */
126         u32 ffpld_rsvd; /* number of bytes to reserve for preload */
127         u32 max_txlen[MCS_TABLE_SIZE][2][2];    /* max size of ampdu per mcs, bw and sgi */
128         void *ini_free[AMPDU_INI_FREE]; /* array of ini's to be freed on detach */
129         bool mfbr;              /* enable multiple fallback rate */
130         u32 tx_max_funl;        /* underflows should be kept such that
131                                  * (tx_max_funfl*underflows) < tx frames
132                                  */
133         wlc_fifo_info_t fifo_tb[NUM_FFPLD_FIFO];        /* table of fifo infos  */
134
135 };
136
137 #define AMPDU_CLEANUPFLAG_RX   (0x1)
138 #define AMPDU_CLEANUPFLAG_TX   (0x2)
139
140 #define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
141 #define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
142
143 static void wlc_ffpld_init(struct ampdu_info *ampdu);
144 static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int f);
145 static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
146
147 static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
148                                                    scb_ampdu_t *scb_ampdu,
149                                                    u8 tid, bool override);
150 static void ampdu_cleanup_tid_ini(struct ampdu_info *ampdu,
151                                   scb_ampdu_t *scb_ampdu,
152                                   u8 tid, bool force);
153 static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur);
154 static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb);
155 static void scb_ampdu_update_config_all(struct ampdu_info *ampdu);
156
157 #define wlc_ampdu_txflowcontrol(a, b, c)        do {} while (0)
158
159 static void wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
160                                           struct scb *scb,
161                                           struct sk_buff *p, tx_status_t *txs,
162                                           u32 frmtxstatus, u32 frmtxstatus2);
163 static bool wlc_ampdu_cap(struct ampdu_info *ampdu);
164 static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on);
165
166 struct ampdu_info *wlc_ampdu_attach(struct wlc_info *wlc)
167 {
168         struct ampdu_info *ampdu;
169         int i;
170
171         /* some code depends on packed structures */
172         ASSERT(DOT11_MAXNUMFRAGS == NBITS(u16));
173         ASSERT(ISPOWEROF2(AMPDU_TX_BA_MAX_WSIZE));
174         ASSERT(ISPOWEROF2(AMPDU_RX_BA_MAX_WSIZE));
175         ASSERT(wlc->pub->tunables->ampdunummpdu <= AMPDU_MAX_MPDU);
176         ASSERT(wlc->pub->tunables->ampdunummpdu > 0);
177
178         ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
179         if (!ampdu) {
180                 WL_ERROR("wl%d: wlc_ampdu_attach: out of mem\n",
181                          wlc->pub->unit);
182                 return NULL;
183         }
184         ampdu->wlc = wlc;
185
186         for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
187                 ampdu->ini_enable[i] = true;
188         /* Disable ampdu for VO by default */
189         ampdu->ini_enable[PRIO_8021D_VO] = false;
190         ampdu->ini_enable[PRIO_8021D_NC] = false;
191
192         /* Disable ampdu for BK by default since not enough fifo space */
193         ampdu->ini_enable[PRIO_8021D_NONE] = false;
194         ampdu->ini_enable[PRIO_8021D_BK] = false;
195
196         ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
197         ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
198         ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
199         ampdu->max_pdu = AUTO;
200         ampdu->dur = AMPDU_MAX_DUR;
201         ampdu->txpkt_weight = AMPDU_DEF_TXPKT_WEIGHT;
202
203         ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
204         /* bump max ampdu rcv size to 64k for all 11n devices except 4321A0 and 4321A1 */
205         if (WLCISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
206                 ampdu->rx_factor = AMPDU_RX_FACTOR_32K;
207         else
208                 ampdu->rx_factor = AMPDU_RX_FACTOR_64K;
209         ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
210         ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
211
212         for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
213                 ampdu->retry_limit_tid[i] = ampdu->retry_limit;
214                 ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
215         }
216
217         ampdu_update_max_txlen(ampdu, ampdu->dur);
218         ampdu->mfbr = false;
219         /* try to set ampdu to the default value */
220         wlc_ampdu_set(ampdu, wlc->pub->_ampdu);
221
222         ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
223         wlc_ffpld_init(ampdu);
224
225         return ampdu;
226 }
227
228 void wlc_ampdu_detach(struct ampdu_info *ampdu)
229 {
230         int i;
231
232         if (!ampdu)
233                 return;
234
235         /* free all ini's which were to be freed on callbacks which were never called */
236         for (i = 0; i < AMPDU_INI_FREE; i++) {
237                 if (ampdu->ini_free[i]) {
238                         kfree(ampdu->ini_free[i]);
239                 }
240         }
241
242         wlc_module_unregister(ampdu->wlc->pub, "ampdu", ampdu);
243         kfree(ampdu);
244 }
245
246 void scb_ampdu_cleanup(struct ampdu_info *ampdu, struct scb *scb)
247 {
248         scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
249         u8 tid;
250
251         WL_AMPDU_UPDN("scb_ampdu_cleanup: enter\n");
252         ASSERT(scb_ampdu);
253
254         for (tid = 0; tid < AMPDU_MAX_SCB_TID; tid++) {
255                 ampdu_cleanup_tid_ini(ampdu, scb_ampdu, tid, false);
256         }
257 }
258
259 /* reset the ampdu state machine so that it can gracefully handle packets that were
260  * freed from the dma and tx queues during reinit
261  */
262 void wlc_ampdu_reset(struct ampdu_info *ampdu)
263 {
264         WL_NONE("%s: Entering\n", __func__);
265 }
266
267 static void scb_ampdu_update_config(struct ampdu_info *ampdu, struct scb *scb)
268 {
269         scb_ampdu_t *scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
270         int i;
271
272         scb_ampdu->max_pdu = (u8) ampdu->wlc->pub->tunables->ampdunummpdu;
273
274         /* go back to legacy size if some preloading is occuring */
275         for (i = 0; i < NUM_FFPLD_FIFO; i++) {
276                 if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
277                         scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
278         }
279
280         /* apply user override */
281         if (ampdu->max_pdu != AUTO)
282                 scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
283
284         scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu, AMPDU_SCB_MAX_RELEASE);
285
286         if (scb_ampdu->max_rxlen)
287                 scb_ampdu->release =
288                     min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 1600);
289
290         scb_ampdu->release = min(scb_ampdu->release,
291                                  ampdu->fifo_tb[TX_AC_BE_FIFO].
292                                  mcs2ampdu_table[FFPLD_MAX_MCS]);
293
294         ASSERT(scb_ampdu->release);
295 }
296
297 void scb_ampdu_update_config_all(struct ampdu_info *ampdu)
298 {
299         scb_ampdu_update_config(ampdu, ampdu->wlc->pub->global_scb);
300 }
301
302 static void wlc_ffpld_init(struct ampdu_info *ampdu)
303 {
304         int i, j;
305         wlc_fifo_info_t *fifo;
306
307         for (j = 0; j < NUM_FFPLD_FIFO; j++) {
308                 fifo = (ampdu->fifo_tb + j);
309                 fifo->ampdu_pld_size = 0;
310                 for (i = 0; i <= FFPLD_MAX_MCS; i++)
311                         fifo->mcs2ampdu_table[i] = 255;
312                 fifo->dmaxferrate = 0;
313                 fifo->accum_txampdu = 0;
314                 fifo->prev_txfunfl = 0;
315                 fifo->accum_txfunfl = 0;
316
317         }
318 }
319
320 /* evaluate the dma transfer rate using the tx underflows as feedback.
321  * If necessary, increase tx fifo preloading. If not enough,
322  * decrease maximum ampdu size for each mcs till underflows stop
323  * Return 1 if pre-loading not active, -1 if not an underflow event,
324  * 0 if pre-loading module took care of the event.
325  */
326 static int wlc_ffpld_check_txfunfl(struct wlc_info *wlc, int fid)
327 {
328         struct ampdu_info *ampdu = wlc->ampdu;
329         u32 phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
330         u32 txunfl_ratio;
331         u8 max_mpdu;
332         u32 current_ampdu_cnt = 0;
333         u16 max_pld_size;
334         u32 new_txunfl;
335         wlc_fifo_info_t *fifo = (ampdu->fifo_tb + fid);
336         uint xmtfifo_sz;
337         u16 cur_txunfl;
338
339         /* return if we got here for a different reason than underflows */
340         cur_txunfl =
341             wlc_read_shm(wlc,
342                          M_UCODE_MACSTAT + offsetof(macstat_t, txfunfl[fid]));
343         new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
344         if (new_txunfl == 0) {
345                 WL_FFPLD("check_txunfl : TX status FRAG set but no tx underflows\n");
346                 return -1;
347         }
348         fifo->prev_txfunfl = cur_txunfl;
349
350         if (!ampdu->tx_max_funl)
351                 return 1;
352
353         /* check if fifo is big enough */
354         if (wlc_xmtfifo_sz_get(wlc, fid, &xmtfifo_sz)) {
355                 WL_FFPLD("check_txunfl : get xmtfifo_sz failed\n");
356                 return -1;
357         }
358
359         if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
360                 return 1;
361
362         max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
363         fifo->accum_txfunfl += new_txunfl;
364
365         /* we need to wait for at least 10 underflows */
366         if (fifo->accum_txfunfl < 10)
367                 return 0;
368
369         WL_FFPLD("ampdu_count %d  tx_underflows %d\n",
370                  current_ampdu_cnt, fifo->accum_txfunfl);
371
372         /*
373            compute the current ratio of tx unfl per ampdu.
374            When the current ampdu count becomes too
375            big while the ratio remains small, we reset
376            the current count in order to not
377            introduce too big of a latency in detecting a
378            large amount of tx underflows later.
379          */
380
381         txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
382
383         if (txunfl_ratio > ampdu->tx_max_funl) {
384                 if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT) {
385                         fifo->accum_txfunfl = 0;
386                 }
387                 return 0;
388         }
389         max_mpdu =
390             min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
391
392         /* In case max value max_pdu is already lower than
393            the fifo depth, there is nothing more we can do.
394          */
395
396         if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
397                 WL_FFPLD(("tx fifo pld : max ampdu fits in fifo\n)"));
398                 fifo->accum_txfunfl = 0;
399                 return 0;
400         }
401
402         if (fifo->ampdu_pld_size < max_pld_size) {
403
404                 /* increment by TX_FIFO_PLD_INC bytes */
405                 fifo->ampdu_pld_size += FFPLD_PLD_INCR;
406                 if (fifo->ampdu_pld_size > max_pld_size)
407                         fifo->ampdu_pld_size = max_pld_size;
408
409                 /* update scb release size */
410                 scb_ampdu_update_config_all(ampdu);
411
412                 /*
413                    compute a new dma xfer rate for max_mpdu @ max mcs.
414                    This is the minimum dma rate that
415                    can acheive no unferflow condition for the current mpdu size.
416                  */
417                 /* note : we divide/multiply by 100 to avoid integer overflows */
418                 fifo->dmaxferrate =
419                     (((phy_rate / 100) *
420                       (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
421                      / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
422
423                 WL_FFPLD("DMA estimated transfer rate %d; pre-load size %d\n",
424                          fifo->dmaxferrate, fifo->ampdu_pld_size);
425         } else {
426
427                 /* decrease ampdu size */
428                 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
429                         if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
430                                 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
431                                     AMPDU_NUM_MPDU_LEGACY - 1;
432                         else
433                                 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
434
435                         /* recompute the table */
436                         wlc_ffpld_calc_mcs2ampdu_table(ampdu, fid);
437
438                         /* update scb release size */
439                         scb_ampdu_update_config_all(ampdu);
440                 }
441         }
442         fifo->accum_txfunfl = 0;
443         return 0;
444 }
445
446 static void wlc_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
447 {
448         int i;
449         u32 phy_rate, dma_rate, tmp;
450         u8 max_mpdu;
451         wlc_fifo_info_t *fifo = (ampdu->fifo_tb + f);
452
453         /* recompute the dma rate */
454         /* note : we divide/multiply by 100 to avoid integer overflows */
455         max_mpdu =
456             min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS], AMPDU_NUM_MPDU_LEGACY);
457         phy_rate = MCS_RATE(FFPLD_MAX_MCS, true, false);
458         dma_rate =
459             (((phy_rate / 100) *
460               (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
461              / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
462         fifo->dmaxferrate = dma_rate;
463
464         /* fill up the mcs2ampdu table; do not recalc the last mcs */
465         dma_rate = dma_rate >> 7;
466         for (i = 0; i < FFPLD_MAX_MCS; i++) {
467                 /* shifting to keep it within integer range */
468                 phy_rate = MCS_RATE(i, true, false) >> 7;
469                 if (phy_rate > dma_rate) {
470                         tmp = ((fifo->ampdu_pld_size * phy_rate) /
471                                ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
472                         tmp = min_t(u32, tmp, 255);
473                         fifo->mcs2ampdu_table[i] = (u8) tmp;
474                 }
475         }
476 }
477
478 static void BCMFASTPATH
479 wlc_ampdu_agg(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p,
480               uint prec)
481 {
482         scb_ampdu_t *scb_ampdu;
483         scb_ampdu_tid_ini_t *ini;
484         u8 tid = (u8) (p->priority);
485
486         scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
487
488         /* initialize initiator on first packet; sends addba req */
489         ini = SCB_AMPDU_INI(scb_ampdu, tid);
490         if (ini->magic != INI_MAGIC) {
491                 ini = wlc_ampdu_init_tid_ini(ampdu, scb_ampdu, tid, false);
492         }
493         return;
494 }
495
496 int BCMFASTPATH
497 wlc_sendampdu(struct ampdu_info *ampdu, wlc_txq_info_t *qi,
498               struct sk_buff **pdu, int prec)
499 {
500         struct wlc_info *wlc;
501         struct osl_info *osh;
502         struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
503         u8 tid, ndelim;
504         int err = 0;
505         u8 preamble_type = WLC_GF_PREAMBLE;
506         u8 fbr_preamble_type = WLC_GF_PREAMBLE;
507         u8 rts_preamble_type = WLC_LONG_PREAMBLE;
508         u8 rts_fbr_preamble_type = WLC_LONG_PREAMBLE;
509
510         bool rr = true, fbr = false;
511         uint i, count = 0, fifo, seg_cnt = 0;
512         u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
513         u32 ampdu_len, maxlen = 0;
514         d11txh_t *txh = NULL;
515         u8 *plcp;
516         struct ieee80211_hdr *h;
517         struct scb *scb;
518         scb_ampdu_t *scb_ampdu;
519         scb_ampdu_tid_ini_t *ini;
520         u8 mcs = 0;
521         bool use_rts = false, use_cts = false;
522         ratespec_t rspec = 0, rspec_fallback = 0;
523         ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
524         u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
525         struct ieee80211_rts *rts;
526         u8 rr_retry_limit;
527         wlc_fifo_info_t *f;
528         bool fbr_iscck;
529         struct ieee80211_tx_info *tx_info;
530         u16 qlen;
531
532         wlc = ampdu->wlc;
533         osh = wlc->osh;
534         p = *pdu;
535
536         ASSERT(p);
537
538         tid = (u8) (p->priority);
539         ASSERT(tid < AMPDU_MAX_SCB_TID);
540
541         f = ampdu->fifo_tb + prio2fifo[tid];
542
543         scb = wlc->pub->global_scb;
544         ASSERT(scb->magic == SCB_MAGIC);
545
546         scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
547         ASSERT(scb_ampdu);
548         ini = &scb_ampdu->ini[tid];
549
550         /* Let pressure continue to build ... */
551         qlen = pktq_plen(&qi->q, prec);
552         if (ini->tx_in_transit > 0 && qlen < scb_ampdu->max_pdu) {
553                 return BCME_BUSY;
554         }
555
556         wlc_ampdu_agg(ampdu, scb, p, tid);
557
558         if (wlc->block_datafifo) {
559                 WL_ERROR("%s: Fifo blocked\n", __func__);
560                 return BCME_BUSY;
561         }
562         rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
563         ampdu_len = 0;
564         dma_len = 0;
565         while (p) {
566                 struct ieee80211_tx_rate *txrate;
567
568                 tx_info = IEEE80211_SKB_CB(p);
569                 txrate = tx_info->status.rates;
570
571                 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
572                         err = wlc_prep_pdu(wlc, p, &fifo);
573                 } else {
574                         WL_ERROR("%s: AMPDU flag is off!\n", __func__);
575                         *pdu = NULL;
576                         err = 0;
577                         break;
578                 }
579
580                 if (err) {
581                         if (err == BCME_BUSY) {
582                                 WL_ERROR("wl%d: wlc_sendampdu: prep_xdu retry; seq 0x%x\n",
583                                          wlc->pub->unit, seq);
584                                 WLCNTINCR(ampdu->cnt->sduretry);
585                                 *pdu = p;
586                                 break;
587                         }
588
589                         /* error in the packet; reject it */
590                         WL_AMPDU_ERR("wl%d: wlc_sendampdu: prep_xdu rejected; seq 0x%x\n",
591                                      wlc->pub->unit, seq);
592                         WLCNTINCR(ampdu->cnt->sdurejected);
593
594                         *pdu = NULL;
595                         break;
596                 }
597
598                 /* pkt is good to be aggregated */
599                 ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
600                 txh = (d11txh_t *) p->data;
601                 plcp = (u8 *) (txh + 1);
602                 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
603                 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
604                 index = TX_SEQ_TO_INDEX(seq);
605
606                 /* check mcl fields and test whether it can be agg'd */
607                 mcl = le16_to_cpu(txh->MacTxControlLow);
608                 mcl &= ~TXC_AMPDU_MASK;
609                 fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
610                 ASSERT(!fbr_iscck);
611                 txh->PreloadSize = 0;   /* always default to 0 */
612
613                 /*  Handle retry limits */
614                 if (txrate[0].count <= rr_retry_limit) {
615                         txrate[0].count++;
616                         rr = true;
617                         fbr = false;
618                         ASSERT(!fbr);
619                 } else {
620                         fbr = true;
621                         rr = false;
622                         txrate[1].count++;
623                 }
624
625                 /* extract the length info */
626                 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
627                     : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
628
629                 /* retrieve null delimiter count */
630                 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
631                 seg_cnt += 1;
632
633                 WL_AMPDU_TX("wl%d: wlc_sendampdu: mpdu %d plcp_len %d\n",
634                             wlc->pub->unit, count, len);
635
636                 /*
637                  * aggregateable mpdu. For ucode/hw agg,
638                  * test whether need to break or change the epoch
639                  */
640                 if (count == 0) {
641                         u16 fc;
642                         mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
643                         /* refill the bits since might be a retx mpdu */
644                         mcl |= TXC_STARTMSDU;
645                         rts = (struct ieee80211_rts *)&txh->rts_frame;
646                         fc = le16_to_cpu(rts->frame_control);
647                         if ((fc & FC_KIND_MASK) == FC_RTS) {
648                                 mcl |= TXC_SENDRTS;
649                                 use_rts = true;
650                         }
651                         if ((fc & FC_KIND_MASK) == FC_CTS) {
652                                 mcl |= TXC_SENDCTS;
653                                 use_cts = true;
654                         }
655                 } else {
656                         mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
657                         mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
658                 }
659
660                 len = roundup(len, 4);
661                 ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
662
663                 dma_len += (u16) pkttotlen(osh, p);
664
665                 WL_AMPDU_TX("wl%d: wlc_sendampdu: ampdu_len %d seg_cnt %d null delim %d\n",
666                             wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
667
668                 txh->MacTxControlLow = cpu_to_le16(mcl);
669
670                 /* this packet is added */
671                 pkt[count++] = p;
672
673                 /* patch the first MPDU */
674                 if (count == 1) {
675                         u8 plcp0, plcp3, is40, sgi;
676                         struct ieee80211_sta *sta;
677
678                         sta = tx_info->control.sta;
679
680                         if (rr) {
681                                 plcp0 = plcp[0];
682                                 plcp3 = plcp[3];
683                         } else {
684                                 plcp0 = txh->FragPLCPFallback[0];
685                                 plcp3 = txh->FragPLCPFallback[3];
686
687                         }
688                         is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
689                         sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
690                         mcs = plcp0 & ~MIMO_PLCP_40MHZ;
691                         ASSERT(mcs < MCS_TABLE_SIZE);
692                         maxlen =
693                             min(scb_ampdu->max_rxlen,
694                                 ampdu->max_txlen[mcs][is40][sgi]);
695
696                         WL_NONE("sendampdu: sgi %d, is40 %d, mcs %d\n",
697                                 sgi, is40, mcs);
698
699                         maxlen = 64 * 1024;     /* XXX Fix me to honor real max_rxlen */
700
701                         if (is40)
702                                 mimo_ctlchbw =
703                                     CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
704                                     ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
705
706                         /* rebuild the rspec and rspec_fallback */
707                         rspec = RSPEC_MIMORATE;
708                         rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
709                         if (plcp[0] & MIMO_PLCP_40MHZ)
710                                 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
711
712                         if (fbr_iscck)  /* CCK */
713                                 rspec_fallback =
714                                     CCK_RSPEC(CCK_PHY2MAC_RATE
715                                               (txh->FragPLCPFallback[0]));
716                         else {  /* MIMO */
717                                 rspec_fallback = RSPEC_MIMORATE;
718                                 rspec_fallback |=
719                                     txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
720                                 if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
721                                         rspec_fallback |=
722                                             (PHY_TXC1_BW_40MHZ <<
723                                              RSPEC_BW_SHIFT);
724                         }
725
726                         if (use_rts || use_cts) {
727                                 rts_rspec =
728                                     wlc_rspec_to_rts_rspec(wlc, rspec, false,
729                                                            mimo_ctlchbw);
730                                 rts_rspec_fallback =
731                                     wlc_rspec_to_rts_rspec(wlc, rspec_fallback,
732                                                            false, mimo_ctlchbw);
733                         }
734                 }
735
736                 /* if (first mpdu for host agg) */
737                 /* test whether to add more */
738                 if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
739                     (count == f->mcs2ampdu_table[mcs])) {
740                         WL_AMPDU_ERR("wl%d: PR 37644: stopping ampdu at %d for mcs %d\n",
741                                      wlc->pub->unit, count, mcs);
742                         break;
743                 }
744
745                 if (count == scb_ampdu->max_pdu) {
746                         WL_NONE("Stop taking from q, reached %d deep\n",
747                                 scb_ampdu->max_pdu);
748                         break;
749                 }
750
751                 /* check to see if the next pkt is a candidate for aggregation */
752                 p = pktq_ppeek(&qi->q, prec);
753                 tx_info = IEEE80211_SKB_CB(p);  /* tx_info must be checked with current p */
754
755                 if (p) {
756                         if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
757                             ((u8) (p->priority) == tid)) {
758
759                                 plen =
760                                     pkttotlen(osh, p) + AMPDU_MAX_MPDU_OVERHEAD;
761                                 plen = max(scb_ampdu->min_len, plen);
762
763                                 if ((plen + ampdu_len) > maxlen) {
764                                         p = NULL;
765                                         WL_ERROR("%s: Bogus plen #1\n",
766                                                  __func__);
767                                         ASSERT(3 == 4);
768                                         continue;
769                                 }
770
771                                 /* check if there are enough descriptors available */
772                                 if (TXAVAIL(wlc, fifo) <= (seg_cnt + 1)) {
773                                         WL_ERROR("%s: No fifo space   !!!!!!\n",
774                                                  __func__);
775                                         p = NULL;
776                                         continue;
777                                 }
778                                 p = pktq_pdeq(&qi->q, prec);
779                                 ASSERT(p);
780                         } else {
781                                 p = NULL;
782                         }
783                 }
784         }                       /* end while(p) */
785
786         ini->tx_in_transit += count;
787
788         if (count) {
789                 WLCNTADD(ampdu->cnt->txmpdu, count);
790
791                 /* patch up the last txh */
792                 txh = (d11txh_t *) pkt[count - 1]->data;
793                 mcl = le16_to_cpu(txh->MacTxControlLow);
794                 mcl &= ~TXC_AMPDU_MASK;
795                 mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
796                 txh->MacTxControlLow = cpu_to_le16(mcl);
797
798                 /* remove the null delimiter after last mpdu */
799                 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
800                 txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
801                 ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
802
803                 /* remove the pad len from last mpdu */
804                 fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
805                 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
806                     : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
807                 ampdu_len -= roundup(len, 4) - len;
808
809                 /* patch up the first txh & plcp */
810                 txh = (d11txh_t *) pkt[0]->data;
811                 plcp = (u8 *) (txh + 1);
812
813                 WLC_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
814                 /* mark plcp to indicate ampdu */
815                 WLC_SET_MIMO_PLCP_AMPDU(plcp);
816
817                 /* reset the mixed mode header durations */
818                 if (txh->MModeLen) {
819                         u16 mmodelen =
820                             wlc_calc_lsig_len(wlc, rspec, ampdu_len);
821                         txh->MModeLen = cpu_to_le16(mmodelen);
822                         preamble_type = WLC_MM_PREAMBLE;
823                 }
824                 if (txh->MModeFbrLen) {
825                         u16 mmfbrlen =
826                             wlc_calc_lsig_len(wlc, rspec_fallback, ampdu_len);
827                         txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
828                         fbr_preamble_type = WLC_MM_PREAMBLE;
829                 }
830
831                 /* set the preload length */
832                 if (MCS_RATE(mcs, true, false) >= f->dmaxferrate) {
833                         dma_len = min(dma_len, f->ampdu_pld_size);
834                         txh->PreloadSize = cpu_to_le16(dma_len);
835                 } else
836                         txh->PreloadSize = 0;
837
838                 mch = le16_to_cpu(txh->MacTxControlHigh);
839
840                 /* update RTS dur fields */
841                 if (use_rts || use_cts) {
842                         u16 durid;
843                         rts = (struct ieee80211_rts *)&txh->rts_frame;
844                         if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
845                             TXC_PREAMBLE_RTS_MAIN_SHORT)
846                                 rts_preamble_type = WLC_SHORT_PREAMBLE;
847
848                         if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
849                             TXC_PREAMBLE_RTS_FB_SHORT)
850                                 rts_fbr_preamble_type = WLC_SHORT_PREAMBLE;
851
852                         durid =
853                             wlc_compute_rtscts_dur(wlc, use_cts, rts_rspec,
854                                                    rspec, rts_preamble_type,
855                                                    preamble_type, ampdu_len,
856                                                    true);
857                         rts->duration = cpu_to_le16(durid);
858                         durid = wlc_compute_rtscts_dur(wlc, use_cts,
859                                                        rts_rspec_fallback,
860                                                        rspec_fallback,
861                                                        rts_fbr_preamble_type,
862                                                        fbr_preamble_type,
863                                                        ampdu_len, true);
864                         txh->RTSDurFallback = cpu_to_le16(durid);
865                         /* set TxFesTimeNormal */
866                         txh->TxFesTimeNormal = rts->duration;
867                         /* set fallback rate version of TxFesTimeNormal */
868                         txh->TxFesTimeFallback = txh->RTSDurFallback;
869                 }
870
871                 /* set flag and plcp for fallback rate */
872                 if (fbr) {
873                         WLCNTADD(ampdu->cnt->txfbr_mpdu, count);
874                         WLCNTINCR(ampdu->cnt->txfbr_ampdu);
875                         mch |= TXC_AMPDU_FBR;
876                         txh->MacTxControlHigh = cpu_to_le16(mch);
877                         WLC_SET_MIMO_PLCP_AMPDU(plcp);
878                         WLC_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
879                 }
880
881                 WL_AMPDU_TX("wl%d: wlc_sendampdu: count %d ampdu_len %d\n",
882                             wlc->pub->unit, count, ampdu_len);
883
884                 /* inform rate_sel if it this is a rate probe pkt */
885                 frameid = le16_to_cpu(txh->TxFrameID);
886                 if (frameid & TXFID_RATE_PROBE_MASK) {
887                         WL_ERROR("%s: XXX what to do with TXFID_RATE_PROBE_MASK!?\n",
888                                  __func__);
889                 }
890                 for (i = 0; i < count; i++)
891                         wlc_txfifo(wlc, fifo, pkt[i], i == (count - 1),
892                                    ampdu->txpkt_weight);
893
894         }
895         /* endif (count) */
896         return err;
897 }
898
899 void BCMFASTPATH
900 wlc_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
901                      struct sk_buff *p, tx_status_t *txs)
902 {
903         scb_ampdu_t *scb_ampdu;
904         struct wlc_info *wlc = ampdu->wlc;
905         scb_ampdu_tid_ini_t *ini;
906         u32 s1 = 0, s2 = 0;
907         struct ieee80211_tx_info *tx_info;
908
909         tx_info = IEEE80211_SKB_CB(p);
910         ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
911         ASSERT(scb);
912         ASSERT(scb->magic == SCB_MAGIC);
913         ASSERT(txs->status & TX_STATUS_AMPDU);
914         scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
915         ASSERT(scb_ampdu);
916         ini = SCB_AMPDU_INI(scb_ampdu, p->priority);
917         ASSERT(ini->scb == scb);
918
919         /* BMAC_NOTE: For the split driver, second level txstatus comes later
920          * So if the ACK was received then wait for the second level else just
921          * call the first one
922          */
923         if (txs->status & TX_STATUS_ACK_RCV) {
924                 u8 status_delay = 0;
925
926                 /* wait till the next 8 bytes of txstatus is available */
927                 while (((s1 =
928                          R_REG(wlc->osh,
929                                &wlc->regs->frmtxstatus)) & TXS_V) == 0) {
930                         udelay(1);
931                         status_delay++;
932                         if (status_delay > 10) {
933                                 ASSERT(status_delay <= 10);
934                                 return;
935                         }
936                 }
937
938                 ASSERT(!(s1 & TX_STATUS_INTERMEDIATE));
939                 ASSERT(s1 & TX_STATUS_AMPDU);
940                 s2 = R_REG(wlc->osh, &wlc->regs->frmtxstatus2);
941         }
942
943         wlc_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
944         wlc_ampdu_txflowcontrol(wlc, scb_ampdu, ini);
945 }
946
947 void
948 rate_status(struct wlc_info *wlc, struct ieee80211_tx_info *tx_info,
949             tx_status_t *txs, u8 mcs)
950 {
951         struct ieee80211_tx_rate *txrate = tx_info->status.rates;
952         int i;
953
954         /* clear the rest of the rates */
955         for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
956                 txrate[i].idx = -1;
957                 txrate[i].count = 0;
958         }
959 }
960
961 #define SHORTNAME "AMPDU status"
962
963 static void BCMFASTPATH
964 wlc_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
965                               struct sk_buff *p, tx_status_t *txs,
966                               u32 s1, u32 s2)
967 {
968         scb_ampdu_t *scb_ampdu;
969         struct wlc_info *wlc = ampdu->wlc;
970         scb_ampdu_tid_ini_t *ini;
971         u8 bitmap[8], queue, tid;
972         d11txh_t *txh;
973         u8 *plcp;
974         struct ieee80211_hdr *h;
975         u16 seq, start_seq = 0, bindex, index, mcl;
976         u8 mcs = 0;
977         bool ba_recd = false, ack_recd = false;
978         u8 suc_mpdu = 0, tot_mpdu = 0;
979         uint supr_status;
980         bool update_rate = true, retry = true, tx_error = false;
981         u16 mimoantsel = 0;
982         u8 antselid = 0;
983         u8 retry_limit, rr_retry_limit;
984         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
985
986 #ifdef BCMDBG
987         u8 hole[AMPDU_MAX_MPDU];
988         memset(hole, 0, sizeof(hole));
989 #endif
990
991         ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
992         ASSERT(txs->status & TX_STATUS_AMPDU);
993
994         scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
995         ASSERT(scb_ampdu);
996
997         tid = (u8) (p->priority);
998
999         ini = SCB_AMPDU_INI(scb_ampdu, tid);
1000         retry_limit = ampdu->retry_limit_tid[tid];
1001         rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
1002
1003         ASSERT(ini->scb == scb);
1004
1005         memset(bitmap, 0, sizeof(bitmap));
1006         queue = txs->frameid & TXFID_QUEUE_MASK;
1007         ASSERT(queue < AC_COUNT);
1008
1009         supr_status = txs->status & TX_STATUS_SUPR_MASK;
1010
1011         if (txs->status & TX_STATUS_ACK_RCV) {
1012                 if (TX_STATUS_SUPR_UF == supr_status) {
1013                         update_rate = false;
1014                 }
1015
1016                 ASSERT(txs->status & TX_STATUS_INTERMEDIATE);
1017                 start_seq = txs->sequence >> SEQNUM_SHIFT;
1018                 bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
1019                     TX_STATUS_BA_BMAP03_SHIFT;
1020
1021                 ASSERT(!(s1 & TX_STATUS_INTERMEDIATE));
1022                 ASSERT(s1 & TX_STATUS_AMPDU);
1023
1024                 bitmap[0] |=
1025                     (s1 & TX_STATUS_BA_BMAP47_MASK) <<
1026                     TX_STATUS_BA_BMAP47_SHIFT;
1027                 bitmap[1] = (s1 >> 8) & 0xff;
1028                 bitmap[2] = (s1 >> 16) & 0xff;
1029                 bitmap[3] = (s1 >> 24) & 0xff;
1030
1031                 bitmap[4] = s2 & 0xff;
1032                 bitmap[5] = (s2 >> 8) & 0xff;
1033                 bitmap[6] = (s2 >> 16) & 0xff;
1034                 bitmap[7] = (s2 >> 24) & 0xff;
1035
1036                 ba_recd = true;
1037         } else {
1038                 WLCNTINCR(ampdu->cnt->noba);
1039                 if (supr_status) {
1040                         update_rate = false;
1041                         if (supr_status == TX_STATUS_SUPR_BADCH) {
1042                                 WL_ERROR("%s: Pkt tx suppressed, illegal channel possibly %d\n",
1043                                          __func__,
1044                                          CHSPEC_CHANNEL(wlc->default_bss->chanspec));
1045                         } else {
1046                                 if (supr_status == TX_STATUS_SUPR_FRAG)
1047                                         WL_NONE("%s: AMPDU frag err\n",
1048                                                 __func__);
1049                                 else
1050                                         WL_ERROR("%s: wlc_ampdu_dotxstatus: supr_status 0x%x\n",
1051                                                  __func__, supr_status);
1052                         }
1053                         /* no need to retry for badch; will fail again */
1054                         if (supr_status == TX_STATUS_SUPR_BADCH ||
1055                             supr_status == TX_STATUS_SUPR_EXPTIME) {
1056                                 retry = false;
1057                                 wlc->pub->_cnt->txchanrej++;
1058                         } else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
1059
1060                                 wlc->pub->_cnt->txexptime++;
1061
1062                                 /* TX underflow : try tuning pre-loading or ampdu size */
1063                         } else if (supr_status == TX_STATUS_SUPR_FRAG) {
1064                                 /* if there were underflows, but pre-loading is not active,
1065                                    notify rate adaptation.
1066                                  */
1067                                 if (wlc_ffpld_check_txfunfl(wlc, prio2fifo[tid])
1068                                     > 0) {
1069                                         tx_error = true;
1070                                 }
1071                         }
1072                 } else if (txs->phyerr) {
1073                         update_rate = false;
1074                         wlc->pub->_cnt->txphyerr++;
1075                         WL_ERROR("wl%d: wlc_ampdu_dotxstatus: tx phy error (0x%x)\n",
1076                                  wlc->pub->unit, txs->phyerr);
1077
1078                         if (WL_ERROR_ON()) {
1079                                 prpkt("txpkt (AMPDU)", wlc->osh, p);
1080                                 wlc_print_txdesc((d11txh_t *) p->data);
1081                         }
1082                         wlc_print_txstatus(txs);
1083                 }
1084         }
1085
1086         /* loop through all pkts and retry if not acked */
1087         while (p) {
1088                 tx_info = IEEE80211_SKB_CB(p);
1089                 ASSERT(tx_info->flags & IEEE80211_TX_CTL_AMPDU);
1090                 txh = (d11txh_t *) p->data;
1091                 mcl = le16_to_cpu(txh->MacTxControlLow);
1092                 plcp = (u8 *) (txh + 1);
1093                 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
1094                 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
1095
1096                 if (tot_mpdu == 0) {
1097                         mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
1098                         mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
1099                 }
1100
1101                 index = TX_SEQ_TO_INDEX(seq);
1102                 ack_recd = false;
1103                 if (ba_recd) {
1104                         bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
1105
1106                         WL_AMPDU_TX("%s: tid %d seq is %d, start_seq is %d, bindex is %d set %d, index %d\n",
1107                                     __func__, tid, seq, start_seq, bindex,
1108                                     isset(bitmap, bindex), index);
1109
1110                         /* if acked then clear bit and free packet */
1111                         if ((bindex < AMPDU_TX_BA_MAX_WSIZE)
1112                             && isset(bitmap, bindex)) {
1113                                 ini->tx_in_transit--;
1114                                 ini->txretry[index] = 0;
1115
1116                                 /* ampdu_ack_len: number of acked aggregated frames */
1117                                 /* ampdu_ack_map: block ack bit map for the aggregation */
1118                                 /* ampdu_len: number of aggregated frames */
1119                                 rate_status(wlc, tx_info, txs, mcs);
1120                                 tx_info->flags |= IEEE80211_TX_STAT_ACK;
1121                                 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
1122
1123                                 /* XXX TODO: Make these accurate. */
1124                                 tx_info->status.ampdu_ack_len =
1125                                     (txs->
1126                                      status & TX_STATUS_FRM_RTX_MASK) >>
1127                                     TX_STATUS_FRM_RTX_SHIFT;
1128                                 tx_info->status.ampdu_len =
1129                                     (txs->
1130                                      status & TX_STATUS_FRM_RTX_MASK) >>
1131                                     TX_STATUS_FRM_RTX_SHIFT;
1132
1133                                 skb_pull(p, D11_PHY_HDR_LEN);
1134                                 skb_pull(p, D11_TXH_LEN);
1135
1136                                 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1137                                                             p);
1138                                 ack_recd = true;
1139                                 suc_mpdu++;
1140                         }
1141                 }
1142                 /* either retransmit or send bar if ack not recd */
1143                 if (!ack_recd) {
1144                         struct ieee80211_tx_rate *txrate =
1145                             tx_info->status.rates;
1146                         if (retry && (txrate[0].count < (int)retry_limit)) {
1147                                 ini->txretry[index]++;
1148                                 ini->tx_in_transit--;
1149                                 /* Use high prededence for retransmit to give some punch */
1150                                 /* wlc_txq_enq(wlc, scb, p, WLC_PRIO_TO_PREC(tid)); */
1151                                 wlc_txq_enq(wlc, scb, p,
1152                                             WLC_PRIO_TO_HI_PREC(tid));
1153                         } else {
1154                                 /* Retry timeout */
1155                                 ini->tx_in_transit--;
1156                                 ieee80211_tx_info_clear_status(tx_info);
1157                                 tx_info->flags |=
1158                                     IEEE80211_TX_STAT_AMPDU_NO_BACK;
1159                                 skb_pull(p, D11_PHY_HDR_LEN);
1160                                 skb_pull(p, D11_TXH_LEN);
1161                                 WL_ERROR("%s: BA Timeout, seq %d, in_transit %d\n",
1162                                          SHORTNAME, seq, ini->tx_in_transit);
1163                                 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1164                                                             p);
1165                         }
1166                 }
1167                 tot_mpdu++;
1168
1169                 /* break out if last packet of ampdu */
1170                 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1171                     TXC_AMPDU_LAST)
1172                         break;
1173
1174                 p = GETNEXTTXP(wlc, queue);
1175                 if (p == NULL) {
1176                         ASSERT(p);
1177                         break;
1178                 }
1179         }
1180         wlc_send_q(wlc, wlc->active_queue);
1181
1182         /* update rate state */
1183         if (WLANTSEL_ENAB(wlc))
1184                 antselid = wlc_antsel_antsel2id(wlc->asi, mimoantsel);
1185
1186         wlc_txfifo_complete(wlc, queue, ampdu->txpkt_weight);
1187 }
1188
1189 static void
1190 ampdu_cleanup_tid_ini(struct ampdu_info *ampdu, scb_ampdu_t *scb_ampdu, u8 tid,
1191                       bool force)
1192 {
1193         scb_ampdu_tid_ini_t *ini;
1194         ini = SCB_AMPDU_INI(scb_ampdu, tid);
1195         if (!ini)
1196                 return;
1197
1198         WL_AMPDU_CTL("wl%d: ampdu_cleanup_tid_ini: tid %d\n",
1199                      ampdu->wlc->pub->unit, tid);
1200
1201         if (ini->tx_in_transit && !force)
1202                 return;
1203
1204         scb_ampdu = SCB_AMPDU_CUBBY(ampdu, ini->scb);
1205         ASSERT(ini == &scb_ampdu->ini[ini->tid]);
1206
1207         /* free all buffered tx packets */
1208         pktq_pflush(ampdu->wlc->osh, &scb_ampdu->txq, ini->tid, true, NULL, 0);
1209 }
1210
1211 /* initialize the initiator code for tid */
1212 static scb_ampdu_tid_ini_t *wlc_ampdu_init_tid_ini(struct ampdu_info *ampdu,
1213                                                    scb_ampdu_t *scb_ampdu,
1214                                                    u8 tid, bool override)
1215 {
1216         scb_ampdu_tid_ini_t *ini;
1217
1218         ASSERT(scb_ampdu);
1219         ASSERT(scb_ampdu->scb);
1220         ASSERT(SCB_AMPDU(scb_ampdu->scb));
1221         ASSERT(tid < AMPDU_MAX_SCB_TID);
1222
1223         /* check for per-tid control of ampdu */
1224         if (!ampdu->ini_enable[tid]) {
1225                 WL_ERROR("%s: Rejecting tid %d\n", __func__, tid);
1226                 return NULL;
1227         }
1228
1229         ini = SCB_AMPDU_INI(scb_ampdu, tid);
1230         ini->tid = tid;
1231         ini->scb = scb_ampdu->scb;
1232         ini->magic = INI_MAGIC;
1233         WLCNTINCR(ampdu->cnt->txaddbareq);
1234
1235         return ini;
1236 }
1237
1238 static int wlc_ampdu_set(struct ampdu_info *ampdu, bool on)
1239 {
1240         struct wlc_info *wlc = ampdu->wlc;
1241
1242         wlc->pub->_ampdu = false;
1243
1244         if (on) {
1245                 if (!N_ENAB(wlc->pub)) {
1246                         WL_AMPDU_ERR("wl%d: driver not nmode enabled\n",
1247                                      wlc->pub->unit);
1248                         return BCME_UNSUPPORTED;
1249                 }
1250                 if (!wlc_ampdu_cap(ampdu)) {
1251                         WL_AMPDU_ERR("wl%d: device not ampdu capable\n",
1252                                      wlc->pub->unit);
1253                         return BCME_UNSUPPORTED;
1254                 }
1255                 wlc->pub->_ampdu = on;
1256         }
1257
1258         return 0;
1259 }
1260
1261 static bool wlc_ampdu_cap(struct ampdu_info *ampdu)
1262 {
1263         if (WLC_PHY_11N_CAP(ampdu->wlc->band))
1264                 return true;
1265         else
1266                 return false;
1267 }
1268
1269 static void ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
1270 {
1271         u32 rate, mcs;
1272
1273         for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
1274                 /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
1275                 /* 20MHz, No SGI */
1276                 rate = MCS_RATE(mcs, false, false);
1277                 ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
1278                 /* 40 MHz, No SGI */
1279                 rate = MCS_RATE(mcs, true, false);
1280                 ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
1281                 /* 20MHz, SGI */
1282                 rate = MCS_RATE(mcs, false, true);
1283                 ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
1284                 /* 40 MHz, SGI */
1285                 rate = MCS_RATE(mcs, true, true);
1286                 ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
1287         }
1288 }
1289
1290 u8 BCMFASTPATH
1291 wlc_ampdu_null_delim_cnt(struct ampdu_info *ampdu, struct scb *scb,
1292                          ratespec_t rspec, int phylen)
1293 {
1294         scb_ampdu_t *scb_ampdu;
1295         int bytes, cnt, tmp;
1296         u8 tx_density;
1297
1298         ASSERT(scb);
1299         ASSERT(SCB_AMPDU(scb));
1300
1301         scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
1302         ASSERT(scb_ampdu);
1303
1304         if (scb_ampdu->mpdu_density == 0)
1305                 return 0;
1306
1307         /* RSPEC2RATE is in kbps units ==> ~RSPEC2RATE/2^13 is in bytes/usec
1308            density x is in 2^(x-4) usec
1309            ==> # of bytes needed for req density = rate/2^(17-x)
1310            ==> # of null delimiters = ceil(ceil(rate/2^(17-x)) - phylen)/4)
1311          */
1312
1313         tx_density = scb_ampdu->mpdu_density;
1314
1315         ASSERT(tx_density <= AMPDU_MAX_MPDU_DENSITY);
1316         tmp = 1 << (17 - tx_density);
1317         bytes = CEIL(RSPEC2RATE(rspec), tmp);
1318
1319         if (bytes > phylen) {
1320                 cnt = CEIL(bytes - phylen, AMPDU_DELIMITER_LEN);
1321                 ASSERT(cnt <= 255);
1322                 return (u8) cnt;
1323         } else
1324                 return 0;
1325 }
1326
1327 void wlc_ampdu_macaddr_upd(struct wlc_info *wlc)
1328 {
1329         char template[T_RAM_ACCESS_SZ * 2];
1330
1331         /* driver needs to write the ta in the template; ta is at offset 16 */
1332         memset(template, 0, sizeof(template));
1333         memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1334         wlc_write_template_ram(wlc, (T_BA_TPL_BASE + 16), (T_RAM_ACCESS_SZ * 2),
1335                                template);
1336 }
1337
1338 bool wlc_aggregatable(struct wlc_info *wlc, u8 tid)
1339 {
1340         return wlc->ampdu->ini_enable[tid];
1341 }
1342
1343 void wlc_ampdu_shm_upd(struct ampdu_info *ampdu)
1344 {
1345         struct wlc_info *wlc = ampdu->wlc;
1346
1347         /* Extend ucode internal watchdog timer to match larger received frames */
1348         if ((ampdu->rx_factor & HT_PARAMS_RX_FACTOR_MASK) ==
1349             AMPDU_RX_FACTOR_64K) {
1350                 wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1351                 wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1352         } else {
1353                 wlc_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1354                 wlc_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1355         }
1356 }