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