GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / net / wireless / broadcom / brcm80211 / brcmsmac / ampdu.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 #include <net/mac80211.h>
17
18 #include "rate.h"
19 #include "scb.h"
20 #include "phy/phy_hal.h"
21 #include "antsel.h"
22 #include "main.h"
23 #include "ampdu.h"
24 #include "debug.h"
25 #include "brcms_trace_events.h"
26
27 /* max number of mpdus in an ampdu */
28 #define AMPDU_MAX_MPDU                  32
29 /* max number of mpdus in an ampdu to a legacy */
30 #define AMPDU_NUM_MPDU_LEGACY           16
31 /* max Tx ba window size (in pdu) */
32 #define AMPDU_TX_BA_MAX_WSIZE           64
33 /* default Tx ba window size (in pdu) */
34 #define AMPDU_TX_BA_DEF_WSIZE           64
35 /* default Rx ba window size (in pdu) */
36 #define AMPDU_RX_BA_DEF_WSIZE           64
37 /* max Rx ba window size (in pdu) */
38 #define AMPDU_RX_BA_MAX_WSIZE           64
39 /* max dur of tx ampdu (in msec) */
40 #define AMPDU_MAX_DUR                   5
41 /* default tx retry limit */
42 #define AMPDU_DEF_RETRY_LIMIT           5
43 /* default tx retry limit at reg rate */
44 #define AMPDU_DEF_RR_RETRY_LIMIT        2
45 /* default ffpld reserved bytes */
46 #define AMPDU_DEF_FFPLD_RSVD            2048
47 /* # of inis to be freed on detach */
48 #define AMPDU_INI_FREE                  10
49 /* max # of mpdus released at a time */
50 #define AMPDU_SCB_MAX_RELEASE           20
51
52 #define NUM_FFPLD_FIFO 4        /* number of fifo concerned by pre-loading */
53 #define FFPLD_TX_MAX_UNFL   200 /* default value of the average number of ampdu
54                                  * without underflows
55                                  */
56 #define FFPLD_MPDU_SIZE 1800    /* estimate of maximum mpdu size */
57 #define FFPLD_MAX_MCS 23        /* we don't deal with mcs 32 */
58 #define FFPLD_PLD_INCR 1000     /* increments in bytes */
59 #define FFPLD_MAX_AMPDU_CNT 5000        /* maximum number of ampdu we
60                                          * accumulate between resets.
61                                          */
62
63 #define AMPDU_DELIMITER_LEN     4
64
65 /* max allowed number of mpdus in an ampdu (2 streams) */
66 #define AMPDU_NUM_MPDU          16
67
68 #define TX_SEQ_TO_INDEX(seq) ((seq) % AMPDU_TX_BA_MAX_WSIZE)
69
70 /* max possible overhead per mpdu in the ampdu; 3 is for roundup if needed */
71 #define AMPDU_MAX_MPDU_OVERHEAD (FCS_LEN + DOT11_ICV_AES_LEN +\
72         AMPDU_DELIMITER_LEN + 3\
73         + DOT11_A4_HDR_LEN + DOT11_QOS_LEN + DOT11_IV_MAX_LEN)
74
75 /* modulo add/sub, bound = 2^k */
76 #define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1))
77 #define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1))
78
79 /* structure to hold tx fifo information and pre-loading state
80  * counters specific to tx underflows of ampdus
81  * some counters might be redundant with the ones in wlc or ampdu structures.
82  * This allows to maintain a specific state independently of
83  * how often and/or when the wlc counters are updated.
84  *
85  * ampdu_pld_size: number of bytes to be pre-loaded
86  * mcs2ampdu_table: per-mcs max # of mpdus in an ampdu
87  * prev_txfunfl: num of underflows last read from the HW macstats counter
88  * accum_txfunfl: num of underflows since we modified pld params
89  * accum_txampdu: num of tx ampdu since we modified pld params
90  * prev_txampdu: previous reading of tx ampdu
91  * dmaxferrate: estimated dma avg xfer rate in kbits/sec
92  */
93 struct brcms_fifo_info {
94         u16 ampdu_pld_size;
95         u8 mcs2ampdu_table[FFPLD_MAX_MCS + 1];
96         u16 prev_txfunfl;
97         u32 accum_txfunfl;
98         u32 accum_txampdu;
99         u32 prev_txampdu;
100         u32 dmaxferrate;
101 };
102
103 /* AMPDU module specific state
104  *
105  * wlc: pointer to main wlc structure
106  * scb_handle: scb cubby handle to retrieve data from scb
107  * ini_enable: per-tid initiator enable/disable of ampdu
108  * ba_tx_wsize: Tx ba window size (in pdu)
109  * ba_rx_wsize: Rx ba window size (in pdu)
110  * retry_limit: mpdu transmit retry limit
111  * rr_retry_limit: mpdu transmit retry limit at regular rate
112  * retry_limit_tid: per-tid mpdu transmit retry limit
113  * rr_retry_limit_tid: per-tid mpdu transmit retry limit at regular rate
114  * mpdu_density: min mpdu spacing (0-7) ==> 2^(x-1)/8 usec
115  * max_pdu: max pdus allowed in ampdu
116  * dur: max duration of an ampdu (in msec)
117  * rx_factor: maximum rx ampdu factor (0-3) ==> 2^(13+x) bytes
118  * ffpld_rsvd: number of bytes to reserve for preload
119  * max_txlen: max size of ampdu per mcs, bw and sgi
120  * mfbr: enable multiple fallback rate
121  * tx_max_funl: underflows should be kept such that
122  *              (tx_max_funfl*underflows) < tx frames
123  * fifo_tb: table of fifo infos
124  */
125 struct ampdu_info {
126         struct brcms_c_info *wlc;
127         int scb_handle;
128         u8 ini_enable[AMPDU_MAX_SCB_TID];
129         u8 ba_tx_wsize;
130         u8 ba_rx_wsize;
131         u8 retry_limit;
132         u8 rr_retry_limit;
133         u8 retry_limit_tid[AMPDU_MAX_SCB_TID];
134         u8 rr_retry_limit_tid[AMPDU_MAX_SCB_TID];
135         u8 mpdu_density;
136         s8 max_pdu;
137         u8 dur;
138         u8 rx_factor;
139         u32 ffpld_rsvd;
140         u32 max_txlen[MCS_TABLE_SIZE][2][2];
141         bool mfbr;
142         u32 tx_max_funl;
143         struct brcms_fifo_info fifo_tb[NUM_FFPLD_FIFO];
144 };
145
146 /* used for flushing ampdu packets */
147 struct cb_del_ampdu_pars {
148         struct ieee80211_sta *sta;
149         u16 tid;
150 };
151
152 static void brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info *ampdu, u8 dur)
153 {
154         u32 rate, mcs;
155
156         for (mcs = 0; mcs < MCS_TABLE_SIZE; mcs++) {
157                 /* rate is in Kbps; dur is in msec ==> len = (rate * dur) / 8 */
158                 /* 20MHz, No SGI */
159                 rate = mcs_2_rate(mcs, false, false);
160                 ampdu->max_txlen[mcs][0][0] = (rate * dur) >> 3;
161                 /* 40 MHz, No SGI */
162                 rate = mcs_2_rate(mcs, true, false);
163                 ampdu->max_txlen[mcs][1][0] = (rate * dur) >> 3;
164                 /* 20MHz, SGI */
165                 rate = mcs_2_rate(mcs, false, true);
166                 ampdu->max_txlen[mcs][0][1] = (rate * dur) >> 3;
167                 /* 40 MHz, SGI */
168                 rate = mcs_2_rate(mcs, true, true);
169                 ampdu->max_txlen[mcs][1][1] = (rate * dur) >> 3;
170         }
171 }
172
173 static bool brcms_c_ampdu_cap(struct ampdu_info *ampdu)
174 {
175         if (BRCMS_PHY_11N_CAP(ampdu->wlc->band))
176                 return true;
177         else
178                 return false;
179 }
180
181 static int brcms_c_ampdu_set(struct ampdu_info *ampdu, bool on)
182 {
183         struct brcms_c_info *wlc = ampdu->wlc;
184         struct bcma_device *core = wlc->hw->d11core;
185
186         wlc->pub->_ampdu = false;
187
188         if (on) {
189                 if (!(wlc->pub->_n_enab & SUPPORT_11N)) {
190                         brcms_err(core, "wl%d: driver not nmode enabled\n",
191                                   wlc->pub->unit);
192                         return -ENOTSUPP;
193                 }
194                 if (!brcms_c_ampdu_cap(ampdu)) {
195                         brcms_err(core, "wl%d: device not ampdu capable\n",
196                                   wlc->pub->unit);
197                         return -ENOTSUPP;
198                 }
199                 wlc->pub->_ampdu = on;
200         }
201
202         return 0;
203 }
204
205 static void brcms_c_ffpld_init(struct ampdu_info *ampdu)
206 {
207         int i, j;
208         struct brcms_fifo_info *fifo;
209
210         for (j = 0; j < NUM_FFPLD_FIFO; j++) {
211                 fifo = (ampdu->fifo_tb + j);
212                 fifo->ampdu_pld_size = 0;
213                 for (i = 0; i <= FFPLD_MAX_MCS; i++)
214                         fifo->mcs2ampdu_table[i] = 255;
215                 fifo->dmaxferrate = 0;
216                 fifo->accum_txampdu = 0;
217                 fifo->prev_txfunfl = 0;
218                 fifo->accum_txfunfl = 0;
219
220         }
221 }
222
223 struct ampdu_info *brcms_c_ampdu_attach(struct brcms_c_info *wlc)
224 {
225         struct ampdu_info *ampdu;
226         int i;
227
228         ampdu = kzalloc(sizeof(struct ampdu_info), GFP_ATOMIC);
229         if (!ampdu)
230                 return NULL;
231
232         ampdu->wlc = wlc;
233
234         for (i = 0; i < AMPDU_MAX_SCB_TID; i++)
235                 ampdu->ini_enable[i] = true;
236         /* Disable ampdu for VO by default */
237         ampdu->ini_enable[PRIO_8021D_VO] = false;
238         ampdu->ini_enable[PRIO_8021D_NC] = false;
239
240         /* Disable ampdu for BK by default since not enough fifo space */
241         ampdu->ini_enable[PRIO_8021D_NONE] = false;
242         ampdu->ini_enable[PRIO_8021D_BK] = false;
243
244         ampdu->ba_tx_wsize = AMPDU_TX_BA_DEF_WSIZE;
245         ampdu->ba_rx_wsize = AMPDU_RX_BA_DEF_WSIZE;
246         ampdu->mpdu_density = AMPDU_DEF_MPDU_DENSITY;
247         ampdu->max_pdu = AUTO;
248         ampdu->dur = AMPDU_MAX_DUR;
249
250         ampdu->ffpld_rsvd = AMPDU_DEF_FFPLD_RSVD;
251         /*
252          * bump max ampdu rcv size to 64k for all 11n
253          * devices except 4321A0 and 4321A1
254          */
255         if (BRCMS_ISNPHY(wlc->band) && NREV_LT(wlc->band->phyrev, 2))
256                 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_32K;
257         else
258                 ampdu->rx_factor = IEEE80211_HT_MAX_AMPDU_64K;
259         ampdu->retry_limit = AMPDU_DEF_RETRY_LIMIT;
260         ampdu->rr_retry_limit = AMPDU_DEF_RR_RETRY_LIMIT;
261
262         for (i = 0; i < AMPDU_MAX_SCB_TID; i++) {
263                 ampdu->retry_limit_tid[i] = ampdu->retry_limit;
264                 ampdu->rr_retry_limit_tid[i] = ampdu->rr_retry_limit;
265         }
266
267         brcms_c_scb_ampdu_update_max_txlen(ampdu, ampdu->dur);
268         ampdu->mfbr = false;
269         /* try to set ampdu to the default value */
270         brcms_c_ampdu_set(ampdu, wlc->pub->_ampdu);
271
272         ampdu->tx_max_funl = FFPLD_TX_MAX_UNFL;
273         brcms_c_ffpld_init(ampdu);
274
275         return ampdu;
276 }
277
278 void brcms_c_ampdu_detach(struct ampdu_info *ampdu)
279 {
280         kfree(ampdu);
281 }
282
283 static void brcms_c_scb_ampdu_update_config(struct ampdu_info *ampdu,
284                                             struct scb *scb)
285 {
286         struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
287         int i;
288
289         scb_ampdu->max_pdu = AMPDU_NUM_MPDU;
290
291         /* go back to legacy size if some preloading is occurring */
292         for (i = 0; i < NUM_FFPLD_FIFO; i++) {
293                 if (ampdu->fifo_tb[i].ampdu_pld_size > FFPLD_PLD_INCR)
294                         scb_ampdu->max_pdu = AMPDU_NUM_MPDU_LEGACY;
295         }
296
297         /* apply user override */
298         if (ampdu->max_pdu != AUTO)
299                 scb_ampdu->max_pdu = (u8) ampdu->max_pdu;
300
301         scb_ampdu->release = min_t(u8, scb_ampdu->max_pdu,
302                                    AMPDU_SCB_MAX_RELEASE);
303
304         if (scb_ampdu->max_rx_ampdu_bytes)
305                 scb_ampdu->release = min_t(u8, scb_ampdu->release,
306                         scb_ampdu->max_rx_ampdu_bytes / 1600);
307
308         scb_ampdu->release = min(scb_ampdu->release,
309                                  ampdu->fifo_tb[TX_AC_BE_FIFO].
310                                  mcs2ampdu_table[FFPLD_MAX_MCS]);
311 }
312
313 static void brcms_c_scb_ampdu_update_config_all(struct ampdu_info *ampdu)
314 {
315         brcms_c_scb_ampdu_update_config(ampdu, &ampdu->wlc->pri_scb);
316 }
317
318 static void brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info *ampdu, int f)
319 {
320         int i;
321         u32 phy_rate, dma_rate, tmp;
322         u8 max_mpdu;
323         struct brcms_fifo_info *fifo = (ampdu->fifo_tb + f);
324
325         /* recompute the dma rate */
326         /* note : we divide/multiply by 100 to avoid integer overflows */
327         max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
328                          AMPDU_NUM_MPDU_LEGACY);
329         phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
330         dma_rate =
331             (((phy_rate / 100) *
332               (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
333              / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
334         fifo->dmaxferrate = dma_rate;
335
336         /* fill up the mcs2ampdu table; do not recalc the last mcs */
337         dma_rate = dma_rate >> 7;
338         for (i = 0; i < FFPLD_MAX_MCS; i++) {
339                 /* shifting to keep it within integer range */
340                 phy_rate = mcs_2_rate(i, true, false) >> 7;
341                 if (phy_rate > dma_rate) {
342                         tmp = ((fifo->ampdu_pld_size * phy_rate) /
343                                ((phy_rate - dma_rate) * FFPLD_MPDU_SIZE)) + 1;
344                         tmp = min_t(u32, tmp, 255);
345                         fifo->mcs2ampdu_table[i] = (u8) tmp;
346                 }
347         }
348 }
349
350 /* evaluate the dma transfer rate using the tx underflows as feedback.
351  * If necessary, increase tx fifo preloading. If not enough,
352  * decrease maximum ampdu size for each mcs till underflows stop
353  * Return 1 if pre-loading not active, -1 if not an underflow event,
354  * 0 if pre-loading module took care of the event.
355  */
356 static int brcms_c_ffpld_check_txfunfl(struct brcms_c_info *wlc, int fid)
357 {
358         struct ampdu_info *ampdu = wlc->ampdu;
359         u32 phy_rate = mcs_2_rate(FFPLD_MAX_MCS, true, false);
360         u32 txunfl_ratio;
361         u8 max_mpdu;
362         u32 current_ampdu_cnt = 0;
363         u16 max_pld_size;
364         u32 new_txunfl;
365         struct brcms_fifo_info *fifo = (ampdu->fifo_tb + fid);
366         uint xmtfifo_sz;
367         u16 cur_txunfl;
368
369         /* return if we got here for a different reason than underflows */
370         cur_txunfl = brcms_b_read_shm(wlc->hw,
371                                       M_UCODE_MACSTAT +
372                                       offsetof(struct macstat, txfunfl[fid]));
373         new_txunfl = (u16) (cur_txunfl - fifo->prev_txfunfl);
374         if (new_txunfl == 0) {
375                 brcms_dbg_ht(wlc->hw->d11core,
376                              "TX status FRAG set but no tx underflows\n");
377                 return -1;
378         }
379         fifo->prev_txfunfl = cur_txunfl;
380
381         if (!ampdu->tx_max_funl)
382                 return 1;
383
384         /* check if fifo is big enough */
385         if (brcms_b_xmtfifo_sz_get(wlc->hw, fid, &xmtfifo_sz))
386                 return -1;
387
388         if ((TXFIFO_SIZE_UNIT * (u32) xmtfifo_sz) <= ampdu->ffpld_rsvd)
389                 return 1;
390
391         max_pld_size = TXFIFO_SIZE_UNIT * xmtfifo_sz - ampdu->ffpld_rsvd;
392         fifo->accum_txfunfl += new_txunfl;
393
394         /* we need to wait for at least 10 underflows */
395         if (fifo->accum_txfunfl < 10)
396                 return 0;
397
398         brcms_dbg_ht(wlc->hw->d11core, "ampdu_count %d  tx_underflows %d\n",
399                      current_ampdu_cnt, fifo->accum_txfunfl);
400
401         /*
402            compute the current ratio of tx unfl per ampdu.
403            When the current ampdu count becomes too
404            big while the ratio remains small, we reset
405            the current count in order to not
406            introduce too big of a latency in detecting a
407            large amount of tx underflows later.
408          */
409
410         txunfl_ratio = current_ampdu_cnt / fifo->accum_txfunfl;
411
412         if (txunfl_ratio > ampdu->tx_max_funl) {
413                 if (current_ampdu_cnt >= FFPLD_MAX_AMPDU_CNT)
414                         fifo->accum_txfunfl = 0;
415
416                 return 0;
417         }
418         max_mpdu = min_t(u8, fifo->mcs2ampdu_table[FFPLD_MAX_MCS],
419                          AMPDU_NUM_MPDU_LEGACY);
420
421         /* In case max value max_pdu is already lower than
422            the fifo depth, there is nothing more we can do.
423          */
424
425         if (fifo->ampdu_pld_size >= max_mpdu * FFPLD_MPDU_SIZE) {
426                 fifo->accum_txfunfl = 0;
427                 return 0;
428         }
429
430         if (fifo->ampdu_pld_size < max_pld_size) {
431
432                 /* increment by TX_FIFO_PLD_INC bytes */
433                 fifo->ampdu_pld_size += FFPLD_PLD_INCR;
434                 if (fifo->ampdu_pld_size > max_pld_size)
435                         fifo->ampdu_pld_size = max_pld_size;
436
437                 /* update scb release size */
438                 brcms_c_scb_ampdu_update_config_all(ampdu);
439
440                 /*
441                  * compute a new dma xfer rate for max_mpdu @ max mcs.
442                  * This is the minimum dma rate that can achieve no
443                  * underflow condition for the current mpdu size.
444                  *
445                  * note : we divide/multiply by 100 to avoid integer overflows
446                  */
447                 fifo->dmaxferrate =
448                     (((phy_rate / 100) *
449                       (max_mpdu * FFPLD_MPDU_SIZE - fifo->ampdu_pld_size))
450                      / (max_mpdu * FFPLD_MPDU_SIZE)) * 100;
451
452                 brcms_dbg_ht(wlc->hw->d11core,
453                              "DMA estimated transfer rate %d; "
454                              "pre-load size %d\n",
455                              fifo->dmaxferrate, fifo->ampdu_pld_size);
456         } else {
457
458                 /* decrease ampdu size */
459                 if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] > 1) {
460                         if (fifo->mcs2ampdu_table[FFPLD_MAX_MCS] == 255)
461                                 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] =
462                                     AMPDU_NUM_MPDU_LEGACY - 1;
463                         else
464                                 fifo->mcs2ampdu_table[FFPLD_MAX_MCS] -= 1;
465
466                         /* recompute the table */
467                         brcms_c_ffpld_calc_mcs2ampdu_table(ampdu, fid);
468
469                         /* update scb release size */
470                         brcms_c_scb_ampdu_update_config_all(ampdu);
471                 }
472         }
473         fifo->accum_txfunfl = 0;
474         return 0;
475 }
476
477 void
478 brcms_c_ampdu_tx_operational(struct brcms_c_info *wlc, u8 tid,
479         u8 ba_wsize,            /* negotiated ba window size (in pdu) */
480         uint max_rx_ampdu_bytes) /* from ht_cap in beacon */
481 {
482         struct scb_ampdu *scb_ampdu;
483         struct scb_ampdu_tid_ini *ini;
484         struct ampdu_info *ampdu = wlc->ampdu;
485         struct scb *scb = &wlc->pri_scb;
486         scb_ampdu = &scb->scb_ampdu;
487
488         if (!ampdu->ini_enable[tid]) {
489                 brcms_err(wlc->hw->d11core, "%s: Rejecting tid %d\n",
490                           __func__, tid);
491                 return;
492         }
493
494         ini = &scb_ampdu->ini[tid];
495         ini->tid = tid;
496         ini->scb = scb_ampdu->scb;
497         ini->ba_wsize = ba_wsize;
498         scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
499 }
500
501 void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
502                                  struct brcms_c_info *wlc)
503 {
504         session->wlc = wlc;
505         skb_queue_head_init(&session->skb_list);
506         session->max_ampdu_len = 0;    /* determined from first MPDU */
507         session->max_ampdu_frames = 0; /* determined from first MPDU */
508         session->ampdu_len = 0;
509         session->dma_len = 0;
510 }
511
512 /*
513  * Preps the given packet for AMPDU based on the session data. If the
514  * frame cannot be accomodated in the current session, -ENOSPC is
515  * returned.
516  */
517 int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
518                             struct sk_buff *p)
519 {
520         struct brcms_c_info *wlc = session->wlc;
521         struct ampdu_info *ampdu = wlc->ampdu;
522         struct scb *scb = &wlc->pri_scb;
523         struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
524         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
525         struct ieee80211_tx_rate *txrate = tx_info->status.rates;
526         struct d11txh *txh = (struct d11txh *)p->data;
527         unsigned ampdu_frames;
528         u8 ndelim, tid;
529         u8 *plcp;
530         uint len;
531         u16 mcl;
532         bool fbr_iscck;
533         bool rr;
534
535         ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
536         plcp = (u8 *)(txh + 1);
537         fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
538         len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
539                           BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
540         len = roundup(len, 4) + (ndelim + 1) * AMPDU_DELIMITER_LEN;
541
542         ampdu_frames = skb_queue_len(&session->skb_list);
543         if (ampdu_frames != 0) {
544                 struct sk_buff *first;
545
546                 if (ampdu_frames + 1 > session->max_ampdu_frames ||
547                     session->ampdu_len + len > session->max_ampdu_len)
548                         return -ENOSPC;
549
550                 /*
551                  * We aren't really out of space if the new frame is of
552                  * a different priority, but we want the same behaviour
553                  * so return -ENOSPC anyway.
554                  *
555                  * XXX: The old AMPDU code did this, but is it really
556                  * necessary?
557                  */
558                 first = skb_peek(&session->skb_list);
559                 if (p->priority != first->priority)
560                         return -ENOSPC;
561         }
562
563         /*
564          * Now that we're sure this frame can be accomodated, update the
565          * session information.
566          */
567         session->ampdu_len += len;
568         session->dma_len += p->len;
569
570         tid = (u8)p->priority;
571
572         /* Handle retry limits */
573         if (txrate[0].count <= ampdu->rr_retry_limit_tid[tid]) {
574                 txrate[0].count++;
575                 rr = true;
576         } else {
577                 txrate[1].count++;
578                 rr = false;
579         }
580
581         if (ampdu_frames == 0) {
582                 u8 plcp0, plcp3, is40, sgi, mcs;
583                 uint fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
584                 struct brcms_fifo_info *f = &ampdu->fifo_tb[fifo];
585
586                 if (rr) {
587                         plcp0 = plcp[0];
588                         plcp3 = plcp[3];
589                 } else {
590                         plcp0 = txh->FragPLCPFallback[0];
591                         plcp3 = txh->FragPLCPFallback[3];
592
593                 }
594
595                 /* Limit AMPDU size based on MCS */
596                 is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
597                 sgi = plcp3_issgi(plcp3) ? 1 : 0;
598                 mcs = plcp0 & ~MIMO_PLCP_40MHZ;
599                 session->max_ampdu_len = min(scb_ampdu->max_rx_ampdu_bytes,
600                                              ampdu->max_txlen[mcs][is40][sgi]);
601
602                 session->max_ampdu_frames = scb_ampdu->max_pdu;
603                 if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
604                         session->max_ampdu_frames =
605                                 min_t(u16, f->mcs2ampdu_table[mcs],
606                                       session->max_ampdu_frames);
607                 }
608         }
609
610         /*
611          * Treat all frames as "middle" frames of AMPDU here. First and
612          * last frames must be fixed up after all MPDUs have been prepped.
613          */
614         mcl = le16_to_cpu(txh->MacTxControlLow);
615         mcl &= ~TXC_AMPDU_MASK;
616         mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
617         mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
618         txh->MacTxControlLow = cpu_to_le16(mcl);
619         txh->PreloadSize = 0;   /* always default to 0 */
620
621         skb_queue_tail(&session->skb_list, p);
622
623         return 0;
624 }
625
626 void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session)
627 {
628         struct brcms_c_info *wlc = session->wlc;
629         struct ampdu_info *ampdu = wlc->ampdu;
630         struct sk_buff *first, *last;
631         struct d11txh *txh;
632         struct ieee80211_tx_info *tx_info;
633         struct ieee80211_tx_rate *txrate;
634         u8 ndelim;
635         u8 *plcp;
636         uint len;
637         uint fifo;
638         struct brcms_fifo_info *f;
639         u16 mcl;
640         bool fbr;
641         bool fbr_iscck;
642         struct ieee80211_rts *rts;
643         bool use_rts = false, use_cts = false;
644         u16 dma_len = session->dma_len;
645         u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
646         u32 rspec = 0, rspec_fallback = 0;
647         u32 rts_rspec = 0, rts_rspec_fallback = 0;
648         u8 plcp0, is40, mcs;
649         u16 mch;
650         u8 preamble_type = BRCMS_GF_PREAMBLE;
651         u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
652         u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
653         u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
654
655         if (skb_queue_empty(&session->skb_list))
656                 return;
657
658         first = skb_peek(&session->skb_list);
659         last = skb_peek_tail(&session->skb_list);
660
661         /* Need to fix up last MPDU first to adjust AMPDU length */
662         txh = (struct d11txh *)last->data;
663         fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
664         f = &ampdu->fifo_tb[fifo];
665
666         mcl = le16_to_cpu(txh->MacTxControlLow);
667         mcl &= ~TXC_AMPDU_MASK;
668         mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
669         txh->MacTxControlLow = cpu_to_le16(mcl);
670
671         /* remove the null delimiter after last mpdu */
672         ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
673         txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
674         session->ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
675
676         /* remove the pad len from last mpdu */
677         fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
678         len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
679                           BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
680         session->ampdu_len -= roundup(len, 4) - len;
681
682         /* Now fix up the first MPDU */
683         tx_info = IEEE80211_SKB_CB(first);
684         txrate = tx_info->status.rates;
685         txh = (struct d11txh *)first->data;
686         plcp = (u8 *)(txh + 1);
687         rts = (struct ieee80211_rts *)&txh->rts_frame;
688
689         mcl = le16_to_cpu(txh->MacTxControlLow);
690         /* If only one MPDU leave it marked as last */
691         if (first != last) {
692                 mcl &= ~TXC_AMPDU_MASK;
693                 mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
694         }
695         mcl |= TXC_STARTMSDU;
696         if (ieee80211_is_rts(rts->frame_control)) {
697                 mcl |= TXC_SENDRTS;
698                 use_rts = true;
699         }
700         if (ieee80211_is_cts(rts->frame_control)) {
701                 mcl |= TXC_SENDCTS;
702                 use_cts = true;
703         }
704         txh->MacTxControlLow = cpu_to_le16(mcl);
705
706         fbr = txrate[1].count > 0;
707         if (!fbr)
708                 plcp0 = plcp[0];
709         else
710                 plcp0 = txh->FragPLCPFallback[0];
711
712         is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
713         mcs = plcp0 & ~MIMO_PLCP_40MHZ;
714
715         if (is40) {
716                 if (CHSPEC_SB_UPPER(wlc_phy_chanspec_get(wlc->band->pi)))
717                         mimo_ctlchbw = PHY_TXC1_BW_20MHZ_UP;
718                 else
719                         mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
720         }
721
722         /* rebuild the rspec and rspec_fallback */
723         rspec = RSPEC_MIMORATE;
724         rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
725         if (plcp[0] & MIMO_PLCP_40MHZ)
726                 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
727
728         fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
729         if (fbr_iscck) {
730                 rspec_fallback =
731                         cck_rspec(cck_phy2mac_rate(txh->FragPLCPFallback[0]));
732         } else {
733                 rspec_fallback = RSPEC_MIMORATE;
734                 rspec_fallback |= txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
735                 if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
736                         rspec_fallback |= PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT;
737         }
738
739         if (use_rts || use_cts) {
740                 rts_rspec =
741                         brcms_c_rspec_to_rts_rspec(wlc, rspec,
742                                                    false, mimo_ctlchbw);
743                 rts_rspec_fallback =
744                         brcms_c_rspec_to_rts_rspec(wlc, rspec_fallback,
745                                                    false, mimo_ctlchbw);
746         }
747
748         BRCMS_SET_MIMO_PLCP_LEN(plcp, session->ampdu_len);
749         /* mark plcp to indicate ampdu */
750         BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
751
752         /* reset the mixed mode header durations */
753         if (txh->MModeLen) {
754                 u16 mmodelen = brcms_c_calc_lsig_len(wlc, rspec,
755                                                      session->ampdu_len);
756                 txh->MModeLen = cpu_to_le16(mmodelen);
757                 preamble_type = BRCMS_MM_PREAMBLE;
758         }
759         if (txh->MModeFbrLen) {
760                 u16 mmfbrlen = brcms_c_calc_lsig_len(wlc, rspec_fallback,
761                                                      session->ampdu_len);
762                 txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
763                 fbr_preamble_type = BRCMS_MM_PREAMBLE;
764         }
765
766         /* set the preload length */
767         if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
768                 dma_len = min(dma_len, f->ampdu_pld_size);
769                 txh->PreloadSize = cpu_to_le16(dma_len);
770         } else {
771                 txh->PreloadSize = 0;
772         }
773
774         mch = le16_to_cpu(txh->MacTxControlHigh);
775
776         /* update RTS dur fields */
777         if (use_rts || use_cts) {
778                 u16 durid;
779                 if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
780                     TXC_PREAMBLE_RTS_MAIN_SHORT)
781                         rts_preamble_type = BRCMS_SHORT_PREAMBLE;
782
783                 if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
784                      TXC_PREAMBLE_RTS_FB_SHORT)
785                         rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
786
787                 durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
788                                                    rspec, rts_preamble_type,
789                                                    preamble_type,
790                                                    session->ampdu_len, true);
791                 rts->duration = cpu_to_le16(durid);
792                 durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
793                                                    rts_rspec_fallback,
794                                                    rspec_fallback,
795                                                    rts_fbr_preamble_type,
796                                                    fbr_preamble_type,
797                                                    session->ampdu_len, true);
798                 txh->RTSDurFallback = cpu_to_le16(durid);
799                 /* set TxFesTimeNormal */
800                 txh->TxFesTimeNormal = rts->duration;
801                 /* set fallback rate version of TxFesTimeNormal */
802                 txh->TxFesTimeFallback = txh->RTSDurFallback;
803         }
804
805         /* set flag and plcp for fallback rate */
806         if (fbr) {
807                 mch |= TXC_AMPDU_FBR;
808                 txh->MacTxControlHigh = cpu_to_le16(mch);
809                 BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
810                 BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
811         }
812
813         brcms_dbg_ht(wlc->hw->d11core, "wl%d: count %d ampdu_len %d\n",
814                      wlc->pub->unit, skb_queue_len(&session->skb_list),
815                      session->ampdu_len);
816 }
817
818 static void
819 brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
820                           struct ieee80211_tx_info *tx_info,
821                           struct tx_status *txs, u8 mcs)
822 {
823         struct ieee80211_tx_rate *txrate = tx_info->status.rates;
824         int i;
825
826         /* clear the rest of the rates */
827         for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
828                 txrate[i].idx = -1;
829                 txrate[i].count = 0;
830         }
831 }
832
833 static void
834 brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
835                               struct sk_buff *p, struct tx_status *txs,
836                               u32 s1, u32 s2)
837 {
838         struct scb_ampdu *scb_ampdu;
839         struct brcms_c_info *wlc = ampdu->wlc;
840         struct scb_ampdu_tid_ini *ini;
841         u8 bitmap[8], queue, tid;
842         struct d11txh *txh;
843         u8 *plcp;
844         struct ieee80211_hdr *h;
845         u16 seq, start_seq = 0, bindex, index, mcl;
846         u8 mcs = 0;
847         bool ba_recd = false, ack_recd = false;
848         u8 suc_mpdu = 0, tot_mpdu = 0;
849         uint supr_status;
850         bool retry = true;
851         u16 mimoantsel = 0;
852         u8 retry_limit;
853         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
854
855 #ifdef DEBUG
856         u8 hole[AMPDU_MAX_MPDU];
857         memset(hole, 0, sizeof(hole));
858 #endif
859
860         scb_ampdu = &scb->scb_ampdu;
861         tid = (u8) (p->priority);
862
863         ini = &scb_ampdu->ini[tid];
864         retry_limit = ampdu->retry_limit_tid[tid];
865         memset(bitmap, 0, sizeof(bitmap));
866         queue = txs->frameid & TXFID_QUEUE_MASK;
867         supr_status = txs->status & TX_STATUS_SUPR_MASK;
868
869         if (txs->status & TX_STATUS_ACK_RCV) {
870                 WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
871                 start_seq = txs->sequence >> SEQNUM_SHIFT;
872                 bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
873                     TX_STATUS_BA_BMAP03_SHIFT;
874
875                 WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
876                 WARN_ON(!(s1 & TX_STATUS_AMPDU));
877
878                 bitmap[0] |=
879                     (s1 & TX_STATUS_BA_BMAP47_MASK) <<
880                     TX_STATUS_BA_BMAP47_SHIFT;
881                 bitmap[1] = (s1 >> 8) & 0xff;
882                 bitmap[2] = (s1 >> 16) & 0xff;
883                 bitmap[3] = (s1 >> 24) & 0xff;
884
885                 bitmap[4] = s2 & 0xff;
886                 bitmap[5] = (s2 >> 8) & 0xff;
887                 bitmap[6] = (s2 >> 16) & 0xff;
888                 bitmap[7] = (s2 >> 24) & 0xff;
889
890                 ba_recd = true;
891         } else {
892                 if (supr_status) {
893                         if (supr_status == TX_STATUS_SUPR_BADCH) {
894                                 brcms_dbg_ht(wlc->hw->d11core,
895                                           "%s: Pkt tx suppressed, illegal channel possibly %d\n",
896                                           __func__, CHSPEC_CHANNEL(
897                                           wlc->default_bss->chanspec));
898                         } else {
899                                 if (supr_status != TX_STATUS_SUPR_FRAG)
900                                         brcms_err(wlc->hw->d11core,
901                                                   "%s: supr_status 0x%x\n",
902                                                   __func__, supr_status);
903                         }
904                         /* no need to retry for badch; will fail again */
905                         if (supr_status == TX_STATUS_SUPR_BADCH ||
906                             supr_status == TX_STATUS_SUPR_EXPTIME) {
907                                 retry = false;
908                         } else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
909                                 /* TX underflow:
910                                  *   try tuning pre-loading or ampdu size
911                                  */
912                         } else if (supr_status == TX_STATUS_SUPR_FRAG) {
913                                 /*
914                                  * if there were underflows, but pre-loading
915                                  * is not active, notify rate adaptation.
916                                  */
917                                 brcms_c_ffpld_check_txfunfl(wlc, queue);
918                         }
919                 } else if (txs->phyerr) {
920                         brcms_dbg_ht(wlc->hw->d11core,
921                                      "%s: ampdu tx phy error (0x%x)\n",
922                                      __func__, txs->phyerr);
923                 }
924         }
925
926         /* loop through all pkts and retry if not acked */
927         while (p) {
928                 tx_info = IEEE80211_SKB_CB(p);
929                 txh = (struct d11txh *) p->data;
930                 mcl = le16_to_cpu(txh->MacTxControlLow);
931                 plcp = (u8 *) (txh + 1);
932                 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
933                 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
934
935                 trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
936
937                 if (tot_mpdu == 0) {
938                         mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
939                         mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
940                 }
941
942                 index = TX_SEQ_TO_INDEX(seq);
943                 ack_recd = false;
944                 if (ba_recd) {
945                         int block_acked;
946
947                         bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
948                         if (bindex < AMPDU_TX_BA_MAX_WSIZE)
949                                 block_acked = isset(bitmap, bindex);
950                         else
951                                 block_acked = 0;
952                         brcms_dbg_ht(wlc->hw->d11core,
953                                      "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
954                                      tid, seq, start_seq, bindex,
955                                      block_acked, index);
956                         /* if acked then clear bit and free packet */
957                         if (block_acked) {
958                                 ini->txretry[index] = 0;
959
960                                 /*
961                                  * ampdu_ack_len:
962                                  *   number of acked aggregated frames
963                                  */
964                                 /* ampdu_len: number of aggregated frames */
965                                 brcms_c_ampdu_rate_status(wlc, tx_info, txs,
966                                                           mcs);
967                                 tx_info->flags |= IEEE80211_TX_STAT_ACK;
968                                 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
969                                 tx_info->status.ampdu_ack_len =
970                                         tx_info->status.ampdu_len = 1;
971
972                                 skb_pull(p, D11_PHY_HDR_LEN);
973                                 skb_pull(p, D11_TXH_LEN);
974
975                                 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
976                                                             p);
977                                 ack_recd = true;
978                                 suc_mpdu++;
979                         }
980                 }
981                 /* either retransmit or send bar if ack not recd */
982                 if (!ack_recd) {
983                         if (retry && (ini->txretry[index] < (int)retry_limit)) {
984                                 int ret;
985                                 ini->txretry[index]++;
986                                 ret = brcms_c_txfifo(wlc, queue, p);
987                                 /*
988                                  * We shouldn't be out of space in the DMA
989                                  * ring here since we're reinserting a frame
990                                  * that was just pulled out.
991                                  */
992                                 WARN_ONCE(ret, "queue %d out of txds\n", queue);
993                         } else {
994                                 /* Retry timeout */
995                                 ieee80211_tx_info_clear_status(tx_info);
996                                 tx_info->status.ampdu_ack_len = 0;
997                                 tx_info->status.ampdu_len = 1;
998                                 tx_info->flags |=
999                                     IEEE80211_TX_STAT_AMPDU_NO_BACK;
1000                                 skb_pull(p, D11_PHY_HDR_LEN);
1001                                 skb_pull(p, D11_TXH_LEN);
1002                                 brcms_dbg_ht(wlc->hw->d11core,
1003                                              "BA Timeout, seq %d\n",
1004                                              seq);
1005                                 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
1006                                                             p);
1007                         }
1008                 }
1009                 tot_mpdu++;
1010
1011                 /* break out if last packet of ampdu */
1012                 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1013                     TXC_AMPDU_LAST)
1014                         break;
1015
1016                 p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
1017         }
1018
1019         /* update rate state */
1020         brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
1021 }
1022
1023 void
1024 brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
1025                      struct sk_buff *p, struct tx_status *txs)
1026 {
1027         struct brcms_c_info *wlc = ampdu->wlc;
1028         u32 s1 = 0, s2 = 0;
1029
1030         /* BMAC_NOTE: For the split driver, second level txstatus comes later
1031          * So if the ACK was received then wait for the second level else just
1032          * call the first one
1033          */
1034         if (txs->status & TX_STATUS_ACK_RCV) {
1035                 u8 status_delay = 0;
1036
1037                 /* wait till the next 8 bytes of txstatus is available */
1038                 s1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus));
1039                 while ((s1 & TXS_V) == 0) {
1040                         udelay(1);
1041                         status_delay++;
1042                         if (status_delay > 10)
1043                                 return; /* error condition */
1044                         s1 = bcma_read32(wlc->hw->d11core,
1045                                          D11REGOFFS(frmtxstatus));
1046                 }
1047
1048                 s2 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus2));
1049         }
1050
1051         if (scb) {
1052                 brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
1053         } else {
1054                 /* loop through all pkts and free */
1055                 u8 queue = txs->frameid & TXFID_QUEUE_MASK;
1056                 struct d11txh *txh;
1057                 u16 mcl;
1058                 while (p) {
1059                         txh = (struct d11txh *) p->data;
1060                         trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
1061                                            sizeof(*txh));
1062                         mcl = le16_to_cpu(txh->MacTxControlLow);
1063                         brcmu_pkt_buf_free_skb(p);
1064                         /* break out if last packet of ampdu */
1065                         if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1066                             TXC_AMPDU_LAST)
1067                                 break;
1068                         p = dma_getnexttxp(wlc->hw->di[queue],
1069                                            DMA_RANGE_TRANSMITTED);
1070                 }
1071         }
1072 }
1073
1074 void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
1075 {
1076         char template[T_RAM_ACCESS_SZ * 2];
1077
1078         /* driver needs to write the ta in the template; ta is at offset 16 */
1079         memset(template, 0, sizeof(template));
1080         memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1081         brcms_b_write_template_ram(wlc->hw, (T_BA_TPL_BASE + 16),
1082                                   (T_RAM_ACCESS_SZ * 2),
1083                                   template);
1084 }
1085
1086 bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid)
1087 {
1088         return wlc->ampdu->ini_enable[tid];
1089 }
1090
1091 void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
1092 {
1093         struct brcms_c_info *wlc = ampdu->wlc;
1094
1095         /*
1096          * Extend ucode internal watchdog timer to
1097          * match larger received frames
1098          */
1099         if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1100             IEEE80211_HT_MAX_AMPDU_64K) {
1101                 brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1102                 brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1103         } else {
1104                 brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1105                 brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1106         }
1107 }
1108
1109 /*
1110  * callback function that helps invalidating ampdu packets in a DMA queue
1111  */
1112 static void dma_cb_fn_ampdu(void *txi, void *arg_a)
1113 {
1114         struct ieee80211_sta *sta = arg_a;
1115         struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
1116
1117         if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
1118             (tx_info->rate_driver_data[0] == sta || sta == NULL))
1119                 tx_info->rate_driver_data[0] = NULL;
1120 }
1121
1122 /*
1123  * When a remote party is no longer available for ampdu communication, any
1124  * pending tx ampdu packets in the driver have to be flushed.
1125  */
1126 void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
1127                      struct ieee80211_sta *sta, u16 tid)
1128 {
1129         brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
1130 }