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