]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/staging/brcm80211/brcmsmac/ampdu.c
b8c6002e57f5d942a25f4101149bf99ae6105a70
[mv-sheeva.git] / drivers / staging / brcm80211 / brcmsmac / ampdu.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 #include <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 typedef struct wlc_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 } wlc_fifo_info_t;
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         wlc_fifo_info_t fifo_tb[NUM_FFPLD_FIFO];        /* table of fifo infos  */
98
99 };
100
101 /* used for flushing ampdu packets */
102 struct cb_del_ampdu_pars {
103         struct ieee80211_sta *sta;
104         u16 tid;
105 };
106
107 #define AMPDU_CLEANUPFLAG_RX   (0x1)
108 #define AMPDU_CLEANUPFLAG_TX   (0x2)
109
110 #define SCB_AMPDU_CUBBY(ampdu, scb) (&(scb->scb_ampdu))
111 #define SCB_AMPDU_INI(scb_ampdu, tid) (&(scb_ampdu->ini[tid]))
112
113 static void brcms_c_ffpld_init(struct ampdu_info *ampdu);
114 static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int f);
115 static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f);
116
117 static scb_ampdu_tid_ini_t *brcms_c_ampdu_init_tid_ini(struct ampdu_info *ampdu,
118                                                    scb_ampdu_t *scb_ampdu,
119                                                    u8 tid, bool override);
120 static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu,
121                                                u8 dur);
122 static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
123                                             struct scb *scb);
124 static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu);
125
126 #define brcms_c_ampdu_txflowcontrol(a, b, c)    do {} while (0)
127
128 static void brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu,
129                                           struct scb *scb,
130                                           struct sk_buff *p, tx_status_t *txs,
131                                           u32 frmtxstatus, u32 frmtxstatus2);
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 (WLCISNPHY(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         scb_ampdu_t *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_rxlen)
227                 scb_ampdu->release =
228                     min_t(u8, scb_ampdu->release, scb_ampdu->max_rxlen / 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         wlc_fifo_info_t *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         wlc_fifo_info_t *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 =
279             brcms_c_read_shm(wlc,
280                          M_UCODE_MACSTAT + offsetof(macstat_t, 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         wlc_fifo_info_t *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 static void
415 brcms_c_ampdu_agg(struct ampdu_info *ampdu, struct scb *scb, struct sk_buff *p,
416               uint prec)
417 {
418         scb_ampdu_t *scb_ampdu;
419         scb_ampdu_tid_ini_t *ini;
420         u8 tid = (u8) (p->priority);
421
422         scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
423
424         /* initialize initiator on first packet; sends addba req */
425         ini = SCB_AMPDU_INI(scb_ampdu, tid);
426         if (ini->magic != INI_MAGIC) {
427                 ini = brcms_c_ampdu_init_tid_ini(ampdu, scb_ampdu, tid, false);
428         }
429         return;
430 }
431
432 int
433 brcms_c_sendampdu(struct ampdu_info *ampdu, struct brcms_c_txq_info *qi,
434               struct sk_buff **pdu, int prec)
435 {
436         struct brcms_c_info *wlc;
437         struct sk_buff *p, *pkt[AMPDU_MAX_MPDU];
438         u8 tid, ndelim;
439         int err = 0;
440         u8 preamble_type = WLC_GF_PREAMBLE;
441         u8 fbr_preamble_type = WLC_GF_PREAMBLE;
442         u8 rts_preamble_type = WLC_LONG_PREAMBLE;
443         u8 rts_fbr_preamble_type = WLC_LONG_PREAMBLE;
444
445         bool rr = true, fbr = false;
446         uint i, count = 0, fifo, seg_cnt = 0;
447         u16 plen, len, seq = 0, mcl, mch, index, frameid, dma_len = 0;
448         u32 ampdu_len, maxlen = 0;
449         d11txh_t *txh = NULL;
450         u8 *plcp;
451         struct ieee80211_hdr *h;
452         struct scb *scb;
453         scb_ampdu_t *scb_ampdu;
454         scb_ampdu_tid_ini_t *ini;
455         u8 mcs = 0;
456         bool use_rts = false, use_cts = false;
457         ratespec_t rspec = 0, rspec_fallback = 0;
458         ratespec_t rts_rspec = 0, rts_rspec_fallback = 0;
459         u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
460         struct ieee80211_rts *rts;
461         u8 rr_retry_limit;
462         wlc_fifo_info_t *f;
463         bool fbr_iscck;
464         struct ieee80211_tx_info *tx_info;
465         u16 qlen;
466         struct wiphy *wiphy;
467
468         wlc = ampdu->wlc;
469         wiphy = wlc->wiphy;
470         p = *pdu;
471
472         tid = (u8) (p->priority);
473
474         f = ampdu->fifo_tb + prio2fifo[tid];
475
476         scb = wlc->pub->global_scb;
477         scb_ampdu = SCB_AMPDU_CUBBY(ampdu, scb);
478         ini = &scb_ampdu->ini[tid];
479
480         /* Let pressure continue to build ... */
481         qlen = pktq_plen(&qi->q, prec);
482         if (ini->tx_in_transit > 0 && qlen < scb_ampdu->max_pdu) {
483                 return -EBUSY;
484         }
485
486         brcms_c_ampdu_agg(ampdu, scb, p, tid);
487
488         rr_retry_limit = ampdu->rr_retry_limit_tid[tid];
489         ampdu_len = 0;
490         dma_len = 0;
491         while (p) {
492                 struct ieee80211_tx_rate *txrate;
493
494                 tx_info = IEEE80211_SKB_CB(p);
495                 txrate = tx_info->status.rates;
496
497                 if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) {
498                         err = brcms_c_prep_pdu(wlc, p, &fifo);
499                 } else {
500                         wiphy_err(wiphy, "%s: AMPDU flag is off!\n", __func__);
501                         *pdu = NULL;
502                         err = 0;
503                         break;
504                 }
505
506                 if (err) {
507                         if (err == -EBUSY) {
508                                 wiphy_err(wiphy, "wl%d: wlc_sendampdu: "
509                                           "prep_xdu retry; seq 0x%x\n",
510                                           wlc->pub->unit, seq);
511                                 *pdu = p;
512                                 break;
513                         }
514
515                         /* error in the packet; reject it */
516                         wiphy_err(wiphy, "wl%d: wlc_sendampdu: prep_xdu "
517                                   "rejected; seq 0x%x\n", wlc->pub->unit, seq);
518                         *pdu = NULL;
519                         break;
520                 }
521
522                 /* pkt is good to be aggregated */
523                 txh = (d11txh_t *) p->data;
524                 plcp = (u8 *) (txh + 1);
525                 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
526                 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
527                 index = TX_SEQ_TO_INDEX(seq);
528
529                 /* check mcl fields and test whether it can be agg'd */
530                 mcl = le16_to_cpu(txh->MacTxControlLow);
531                 mcl &= ~TXC_AMPDU_MASK;
532                 fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x3);
533                 txh->PreloadSize = 0;   /* always default to 0 */
534
535                 /*  Handle retry limits */
536                 if (txrate[0].count <= rr_retry_limit) {
537                         txrate[0].count++;
538                         rr = true;
539                         fbr = false;
540                 } else {
541                         fbr = true;
542                         rr = false;
543                         txrate[1].count++;
544                 }
545
546                 /* extract the length info */
547                 len = fbr_iscck ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
548                     : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
549
550                 /* retrieve null delimiter count */
551                 ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
552                 seg_cnt += 1;
553
554                 BCMMSG(wlc->wiphy, "wl%d: mpdu %d plcp_len %d\n",
555                         wlc->pub->unit, count, len);
556
557                 /*
558                  * aggregateable mpdu. For ucode/hw agg,
559                  * test whether need to break or change the epoch
560                  */
561                 if (count == 0) {
562                         mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
563                         /* refill the bits since might be a retx mpdu */
564                         mcl |= TXC_STARTMSDU;
565                         rts = (struct ieee80211_rts *)&txh->rts_frame;
566
567                         if (ieee80211_is_rts(rts->frame_control)) {
568                                 mcl |= TXC_SENDRTS;
569                                 use_rts = true;
570                         }
571                         if (ieee80211_is_cts(rts->frame_control)) {
572                                 mcl |= TXC_SENDCTS;
573                                 use_cts = true;
574                         }
575                 } else {
576                         mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
577                         mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
578                 }
579
580                 len = roundup(len, 4);
581                 ampdu_len += (len + (ndelim + 1) * AMPDU_DELIMITER_LEN);
582
583                 dma_len += (u16) brcmu_pkttotlen(p);
584
585                 BCMMSG(wlc->wiphy, "wl%d: ampdu_len %d"
586                         " seg_cnt %d null delim %d\n",
587                         wlc->pub->unit, ampdu_len, seg_cnt, ndelim);
588
589                 txh->MacTxControlLow = cpu_to_le16(mcl);
590
591                 /* this packet is added */
592                 pkt[count++] = p;
593
594                 /* patch the first MPDU */
595                 if (count == 1) {
596                         u8 plcp0, plcp3, is40, sgi;
597                         struct ieee80211_sta *sta;
598
599                         sta = tx_info->control.sta;
600
601                         if (rr) {
602                                 plcp0 = plcp[0];
603                                 plcp3 = plcp[3];
604                         } else {
605                                 plcp0 = txh->FragPLCPFallback[0];
606                                 plcp3 = txh->FragPLCPFallback[3];
607
608                         }
609                         is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
610                         sgi = PLCP3_ISSGI(plcp3) ? 1 : 0;
611                         mcs = plcp0 & ~MIMO_PLCP_40MHZ;
612                         maxlen =
613                             min(scb_ampdu->max_rxlen,
614                                 ampdu->max_txlen[mcs][is40][sgi]);
615
616                         /* XXX Fix me to honor real max_rxlen */
617                         /* can fix this as soon as ampdu_action() in mac80211.h
618                          * gets extra u8buf_size par */
619                         maxlen = 64 * 1024;
620
621                         if (is40)
622                                 mimo_ctlchbw =
623                                     CHSPEC_SB_UPPER(WLC_BAND_PI_RADIO_CHANSPEC)
624                                     ? PHY_TXC1_BW_20MHZ_UP : PHY_TXC1_BW_20MHZ;
625
626                         /* rebuild the rspec and rspec_fallback */
627                         rspec = RSPEC_MIMORATE;
628                         rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
629                         if (plcp[0] & MIMO_PLCP_40MHZ)
630                                 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
631
632                         if (fbr_iscck)  /* CCK */
633                                 rspec_fallback =
634                                     CCK_RSPEC(CCK_PHY2MAC_RATE
635                                               (txh->FragPLCPFallback[0]));
636                         else {  /* MIMO */
637                                 rspec_fallback = RSPEC_MIMORATE;
638                                 rspec_fallback |=
639                                     txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
640                                 if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
641                                         rspec_fallback |=
642                                             (PHY_TXC1_BW_40MHZ <<
643                                              RSPEC_BW_SHIFT);
644                         }
645
646                         if (use_rts || use_cts) {
647                                 rts_rspec =
648                                     brcms_c_rspec_to_rts_rspec(wlc,
649                                         rspec, false, mimo_ctlchbw);
650                                 rts_rspec_fallback =
651                                     brcms_c_rspec_to_rts_rspec(wlc,
652                                         rspec_fallback, false, mimo_ctlchbw);
653                         }
654                 }
655
656                 /* if (first mpdu for host agg) */
657                 /* test whether to add more */
658                 if ((MCS_RATE(mcs, true, false) >= f->dmaxferrate) &&
659                     (count == f->mcs2ampdu_table[mcs])) {
660                         BCMMSG(wlc->wiphy, "wl%d: PR 37644: stopping"
661                                 " ampdu at %d for mcs %d\n",
662                                 wlc->pub->unit, count, mcs);
663                         break;
664                 }
665
666                 if (count == scb_ampdu->max_pdu) {
667                         break;
668                 }
669
670                 /* check to see if the next pkt is a candidate for aggregation */
671                 p = pktq_ppeek(&qi->q, prec);
672                 tx_info = IEEE80211_SKB_CB(p);  /* tx_info must be checked with current p */
673
674                 if (p) {
675                         if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
676                             ((u8) (p->priority) == tid)) {
677
678                                 plen = brcmu_pkttotlen(p) +
679                                        AMPDU_MAX_MPDU_OVERHEAD;
680                                 plen = max(scb_ampdu->min_len, plen);
681
682                                 if ((plen + ampdu_len) > maxlen) {
683                                         p = NULL;
684                                         wiphy_err(wiphy, "%s: Bogus plen #1\n",
685                                                 __func__);
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 = (d11txh_t *) 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 ? WLC_GET_CCK_PLCP_LEN(txh->FragPLCPFallback)
721                     : WLC_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
722                 ampdu_len -= roundup(len, 4) - len;
723
724                 /* patch up the first txh & plcp */
725                 txh = (d11txh_t *) pkt[0]->data;
726                 plcp = (u8 *) (txh + 1);
727
728                 WLC_SET_MIMO_PLCP_LEN(plcp, ampdu_len);
729                 /* mark plcp to indicate ampdu */
730                 WLC_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 = WLC_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 = WLC_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 = WLC_SHORT_PREAMBLE;
763
764                         if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
765                             TXC_PREAMBLE_RTS_FB_SHORT)
766                                 rts_fbr_preamble_type = WLC_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                         WLC_SET_MIMO_PLCP_AMPDU(plcp);
792                         WLC_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, tx_status_t *txs)
816 {
817         scb_ampdu_t *scb_ampdu;
818         struct brcms_c_info *wlc = ampdu->wlc;
819         scb_ampdu_tid_ini_t *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                 d11txh_t *txh;
852                 u16 mcl;
853                 while (p) {
854                         tx_info = IEEE80211_SKB_CB(p);
855                         txh = (d11txh_t *) 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                           tx_status_t *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, tx_status_t *txs,
889                               u32 s1, u32 s2)
890 {
891         scb_ampdu_t *scb_ampdu;
892         struct brcms_c_info *wlc = ampdu->wlc;
893         scb_ampdu_tid_ini_t *ini;
894         u8 bitmap[8], queue, tid;
895         d11txh_t *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((d11txh_t *) 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 = (d11txh_t *) 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                                  * WLC_PRIO_TO_PREC(tid)); */
1050                                 brcms_c_txq_enq(wlc, scb, p,
1051                                             WLC_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 /* initialize the initiator code for tid */
1087 static scb_ampdu_tid_ini_t *brcms_c_ampdu_init_tid_ini(struct ampdu_info *ampdu,
1088                                                    scb_ampdu_t *scb_ampdu,
1089                                                    u8 tid, bool override)
1090 {
1091         scb_ampdu_tid_ini_t *ini;
1092
1093         /* check for per-tid control of ampdu */
1094         if (!ampdu->ini_enable[tid]) {
1095                 wiphy_err(ampdu->wlc->wiphy, "%s: Rejecting tid %d\n",
1096                           __func__, tid);
1097                 return NULL;
1098         }
1099
1100         ini = SCB_AMPDU_INI(scb_ampdu, tid);
1101         ini->tid = tid;
1102         ini->scb = scb_ampdu->scb;
1103         ini->magic = INI_MAGIC;
1104         return ini;
1105 }
1106
1107 static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
1108 {
1109         struct brcms_c_info *wlc = ampdu->wlc;
1110
1111         wlc->pub->_ampdu = false;
1112
1113         if (on) {
1114                 if (!N_ENAB(wlc->pub)) {
1115                         wiphy_err(ampdu->wlc->wiphy, "wl%d: driver not "
1116                                 "nmode enabled\n", wlc->pub->unit);
1117                         return -ENOTSUPP;
1118                 }
1119                 if (!brcms_c_ampdu_cap(ampdu)) {
1120                         wiphy_err(ampdu->wlc->wiphy, "wl%d: device not "
1121                                 "ampdu capable\n", wlc->pub->unit);
1122                         return -ENOTSUPP;
1123                 }
1124                 wlc->pub->_ampdu = on;
1125         }
1126
1127         return 0;
1128 }
1129
1130 static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
1131 {
1132         if (WLC_PHY_11N_CAP(ampdu->wlc->band))
1133                 return true;
1134         else
1135                 return false;
1136 }
1137
1138 static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
1139 {
1140         u32 rate, mcs;
1141
1142         for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
1143                 /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
1144                 /* 20MHz, No SGI */
1145                 rate = MCS_RATE(mcs, false, false);
1146                 ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
1147                 /* 40 MHz, No SGI */
1148                 rate = MCS_RATE(mcs, true, false);
1149                 ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
1150                 /* 20MHz, SGI */
1151                 rate = MCS_RATE(mcs, false, true);
1152                 ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
1153                 /* 40 MHz, SGI */
1154                 rate = MCS_RATE(mcs, true, true);
1155                 ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
1156         }
1157 }
1158
1159 void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
1160 {
1161         char template[T_RAM_ACCESS_SZ * 2];
1162
1163         /* driver needs to write the ta in the template; ta is at offset 16 */
1164         memset(template, 0, sizeof(template));
1165         memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1166         brcms_c_write_template_ram(wlc, (T_BA_TPL_BASE + 16),
1167                                   (T_RAM_ACCESS_SZ * 2),
1168                                   template);
1169 }
1170
1171 bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid)
1172 {
1173         return wlc->ampdu->ini_enable[tid];
1174 }
1175
1176 void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
1177 {
1178         struct brcms_c_info *wlc = ampdu->wlc;
1179
1180         /* Extend ucode internal watchdog timer to match larger received frames */
1181         if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1182             IEEE80211_HT_MAX_AMPDU_64K) {
1183                 brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1184                 brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1185         } else {
1186                 brcms_c_write_shm(wlc, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1187                 brcms_c_write_shm(wlc, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1188         }
1189 }
1190
1191 /*
1192  * callback function that helps flushing ampdu packets from a priority queue
1193  */
1194 static bool cb_del_ampdu_pkt(struct sk_buff *mpdu, void *arg_a)
1195 {
1196         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(mpdu);
1197         struct cb_del_ampdu_pars *ampdu_pars =
1198                                  (struct cb_del_ampdu_pars *)arg_a;
1199         bool rc;
1200
1201         rc = tx_info->flags & IEEE80211_TX_CTL_AMPDU ? true : false;
1202         rc = rc && (tx_info->control.sta == NULL || ampdu_pars->sta == NULL ||
1203                     tx_info->control.sta == ampdu_pars->sta);
1204         rc = rc && ((u8)(mpdu->priority) == ampdu_pars->tid);
1205         return rc;
1206 }
1207
1208 /*
1209  * callback function that helps invalidating ampdu packets in a DMA queue
1210  */
1211 static void dma_cb_fn_ampdu(void *txi, void *arg_a)
1212 {
1213         struct ieee80211_sta *sta = arg_a;
1214         struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
1215
1216         if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
1217             (tx_info->control.sta == sta || sta == NULL))
1218                 tx_info->control.sta = NULL;
1219 }
1220
1221 /*
1222  * When a remote party is no longer available for ampdu communication, any
1223  * pending tx ampdu packets in the driver have to be flushed.
1224  */
1225 void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
1226                      struct ieee80211_sta *sta, u16 tid)
1227 {
1228         struct brcms_c_txq_info *qi = wlc->pkt_queue;
1229         struct pktq *pq = &qi->q;
1230         int prec;
1231         struct cb_del_ampdu_pars ampdu_pars;
1232
1233         ampdu_pars.sta = sta;
1234         ampdu_pars.tid = tid;
1235         for (prec = 0; prec < pq->num_prec; prec++) {
1236                 brcmu_pktq_pflush(pq, prec, true, cb_del_ampdu_pkt,
1237                             (void *)&ampdu_pars);
1238         }
1239         brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
1240 }