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