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