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