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