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