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