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