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