Merge drm/drm-next into drm-intel-gt-next
[linux-block.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         uint max_rx_ampdu_bytes) /* from ht_cap in beacon */
480 {
481         struct scb_ampdu *scb_ampdu;
482         struct ampdu_info *ampdu = wlc->ampdu;
483         struct scb *scb = &wlc->pri_scb;
484         scb_ampdu = &scb->scb_ampdu;
485
486         if (!ampdu->ini_enable[tid]) {
487                 brcms_err(wlc->hw->d11core, "%s: Rejecting tid %d\n",
488                           __func__, tid);
489                 return;
490         }
491
492         scb_ampdu->max_rx_ampdu_bytes = max_rx_ampdu_bytes;
493 }
494
495 void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,
496                                  struct brcms_c_info *wlc)
497 {
498         session->wlc = wlc;
499         skb_queue_head_init(&session->skb_list);
500         session->max_ampdu_len = 0;    /* determined from first MPDU */
501         session->max_ampdu_frames = 0; /* determined from first MPDU */
502         session->ampdu_len = 0;
503         session->dma_len = 0;
504 }
505
506 /*
507  * Preps the given packet for AMPDU based on the session data. If the
508  * frame cannot be accomodated in the current session, -ENOSPC is
509  * returned.
510  */
511 int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
512                             struct sk_buff *p)
513 {
514         struct brcms_c_info *wlc = session->wlc;
515         struct ampdu_info *ampdu = wlc->ampdu;
516         struct scb *scb = &wlc->pri_scb;
517         struct scb_ampdu *scb_ampdu = &scb->scb_ampdu;
518         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
519         struct ieee80211_tx_rate *txrate = tx_info->status.rates;
520         struct d11txh *txh = (struct d11txh *)p->data;
521         unsigned ampdu_frames;
522         u8 ndelim, tid;
523         u8 *plcp;
524         uint len;
525         u16 mcl;
526         bool fbr_iscck;
527         bool rr;
528
529         ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
530         plcp = (u8 *)(txh + 1);
531         fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
532         len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
533                           BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
534         len = roundup(len, 4) + (ndelim + 1) * AMPDU_DELIMITER_LEN;
535
536         ampdu_frames = skb_queue_len(&session->skb_list);
537         if (ampdu_frames != 0) {
538                 struct sk_buff *first;
539
540                 if (ampdu_frames + 1 > session->max_ampdu_frames ||
541                     session->ampdu_len + len > session->max_ampdu_len)
542                         return -ENOSPC;
543
544                 /*
545                  * We aren't really out of space if the new frame is of
546                  * a different priority, but we want the same behaviour
547                  * so return -ENOSPC anyway.
548                  *
549                  * XXX: The old AMPDU code did this, but is it really
550                  * necessary?
551                  */
552                 first = skb_peek(&session->skb_list);
553                 if (p->priority != first->priority)
554                         return -ENOSPC;
555         }
556
557         /*
558          * Now that we're sure this frame can be accomodated, update the
559          * session information.
560          */
561         session->ampdu_len += len;
562         session->dma_len += p->len;
563
564         tid = (u8)p->priority;
565
566         /* Handle retry limits */
567         if (txrate[0].count <= ampdu->rr_retry_limit_tid[tid]) {
568                 txrate[0].count++;
569                 rr = true;
570         } else {
571                 txrate[1].count++;
572                 rr = false;
573         }
574
575         if (ampdu_frames == 0) {
576                 u8 plcp0, plcp3, is40, sgi, mcs;
577                 uint fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
578                 struct brcms_fifo_info *f = &ampdu->fifo_tb[fifo];
579
580                 if (rr) {
581                         plcp0 = plcp[0];
582                         plcp3 = plcp[3];
583                 } else {
584                         plcp0 = txh->FragPLCPFallback[0];
585                         plcp3 = txh->FragPLCPFallback[3];
586
587                 }
588
589                 /* Limit AMPDU size based on MCS */
590                 is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
591                 sgi = plcp3_issgi(plcp3) ? 1 : 0;
592                 mcs = plcp0 & ~MIMO_PLCP_40MHZ;
593                 session->max_ampdu_len = min(scb_ampdu->max_rx_ampdu_bytes,
594                                              ampdu->max_txlen[mcs][is40][sgi]);
595
596                 session->max_ampdu_frames = scb_ampdu->max_pdu;
597                 if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
598                         session->max_ampdu_frames =
599                                 min_t(u16, f->mcs2ampdu_table[mcs],
600                                       session->max_ampdu_frames);
601                 }
602         }
603
604         /*
605          * Treat all frames as "middle" frames of AMPDU here. First and
606          * last frames must be fixed up after all MPDUs have been prepped.
607          */
608         mcl = le16_to_cpu(txh->MacTxControlLow);
609         mcl &= ~TXC_AMPDU_MASK;
610         mcl |= (TXC_AMPDU_MIDDLE << TXC_AMPDU_SHIFT);
611         mcl &= ~(TXC_STARTMSDU | TXC_SENDRTS | TXC_SENDCTS);
612         txh->MacTxControlLow = cpu_to_le16(mcl);
613         txh->PreloadSize = 0;   /* always default to 0 */
614
615         skb_queue_tail(&session->skb_list, p);
616
617         return 0;
618 }
619
620 void brcms_c_ampdu_finalize(struct brcms_ampdu_session *session)
621 {
622         struct brcms_c_info *wlc = session->wlc;
623         struct ampdu_info *ampdu = wlc->ampdu;
624         struct sk_buff *first, *last;
625         struct d11txh *txh;
626         struct ieee80211_tx_info *tx_info;
627         struct ieee80211_tx_rate *txrate;
628         u8 ndelim;
629         u8 *plcp;
630         uint len;
631         uint fifo;
632         struct brcms_fifo_info *f;
633         u16 mcl;
634         bool fbr;
635         bool fbr_iscck;
636         struct ieee80211_rts *rts;
637         bool use_rts = false, use_cts = false;
638         u16 dma_len = session->dma_len;
639         u16 mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
640         u32 rspec = 0, rspec_fallback = 0;
641         u32 rts_rspec = 0, rts_rspec_fallback = 0;
642         u8 plcp0, is40, mcs;
643         u16 mch;
644         u8 preamble_type = BRCMS_GF_PREAMBLE;
645         u8 fbr_preamble_type = BRCMS_GF_PREAMBLE;
646         u8 rts_preamble_type = BRCMS_LONG_PREAMBLE;
647         u8 rts_fbr_preamble_type = BRCMS_LONG_PREAMBLE;
648
649         if (skb_queue_empty(&session->skb_list))
650                 return;
651
652         first = skb_peek(&session->skb_list);
653         last = skb_peek_tail(&session->skb_list);
654
655         /* Need to fix up last MPDU first to adjust AMPDU length */
656         txh = (struct d11txh *)last->data;
657         fifo = le16_to_cpu(txh->TxFrameID) & TXFID_QUEUE_MASK;
658         f = &ampdu->fifo_tb[fifo];
659
660         mcl = le16_to_cpu(txh->MacTxControlLow);
661         mcl &= ~TXC_AMPDU_MASK;
662         mcl |= (TXC_AMPDU_LAST << TXC_AMPDU_SHIFT);
663         txh->MacTxControlLow = cpu_to_le16(mcl);
664
665         /* remove the null delimiter after last mpdu */
666         ndelim = txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM];
667         txh->RTSPLCPFallback[AMPDU_FBR_NULL_DELIM] = 0;
668         session->ampdu_len -= ndelim * AMPDU_DELIMITER_LEN;
669
670         /* remove the pad len from last mpdu */
671         fbr_iscck = ((le16_to_cpu(txh->XtraFrameTypes) & 0x3) == 0);
672         len = fbr_iscck ? BRCMS_GET_CCK_PLCP_LEN(txh->FragPLCPFallback) :
673                           BRCMS_GET_MIMO_PLCP_LEN(txh->FragPLCPFallback);
674         session->ampdu_len -= roundup(len, 4) - len;
675
676         /* Now fix up the first MPDU */
677         tx_info = IEEE80211_SKB_CB(first);
678         txrate = tx_info->status.rates;
679         txh = (struct d11txh *)first->data;
680         plcp = (u8 *)(txh + 1);
681         rts = (struct ieee80211_rts *)&txh->rts_frame;
682
683         mcl = le16_to_cpu(txh->MacTxControlLow);
684         /* If only one MPDU leave it marked as last */
685         if (first != last) {
686                 mcl &= ~TXC_AMPDU_MASK;
687                 mcl |= (TXC_AMPDU_FIRST << TXC_AMPDU_SHIFT);
688         }
689         mcl |= TXC_STARTMSDU;
690         if (ieee80211_is_rts(rts->frame_control)) {
691                 mcl |= TXC_SENDRTS;
692                 use_rts = true;
693         }
694         if (ieee80211_is_cts(rts->frame_control)) {
695                 mcl |= TXC_SENDCTS;
696                 use_cts = true;
697         }
698         txh->MacTxControlLow = cpu_to_le16(mcl);
699
700         fbr = txrate[1].count > 0;
701         if (!fbr)
702                 plcp0 = plcp[0];
703         else
704                 plcp0 = txh->FragPLCPFallback[0];
705
706         is40 = (plcp0 & MIMO_PLCP_40MHZ) ? 1 : 0;
707         mcs = plcp0 & ~MIMO_PLCP_40MHZ;
708
709         if (is40) {
710                 if (CHSPEC_SB_UPPER(wlc_phy_chanspec_get(wlc->band->pi)))
711                         mimo_ctlchbw = PHY_TXC1_BW_20MHZ_UP;
712                 else
713                         mimo_ctlchbw = PHY_TXC1_BW_20MHZ;
714         }
715
716         /* rebuild the rspec and rspec_fallback */
717         rspec = RSPEC_MIMORATE;
718         rspec |= plcp[0] & ~MIMO_PLCP_40MHZ;
719         if (plcp[0] & MIMO_PLCP_40MHZ)
720                 rspec |= (PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT);
721
722         fbr_iscck = !(le16_to_cpu(txh->XtraFrameTypes) & 0x03);
723         if (fbr_iscck) {
724                 rspec_fallback =
725                         cck_rspec(cck_phy2mac_rate(txh->FragPLCPFallback[0]));
726         } else {
727                 rspec_fallback = RSPEC_MIMORATE;
728                 rspec_fallback |= txh->FragPLCPFallback[0] & ~MIMO_PLCP_40MHZ;
729                 if (txh->FragPLCPFallback[0] & MIMO_PLCP_40MHZ)
730                         rspec_fallback |= PHY_TXC1_BW_40MHZ << RSPEC_BW_SHIFT;
731         }
732
733         if (use_rts || use_cts) {
734                 rts_rspec =
735                         brcms_c_rspec_to_rts_rspec(wlc, rspec,
736                                                    false, mimo_ctlchbw);
737                 rts_rspec_fallback =
738                         brcms_c_rspec_to_rts_rspec(wlc, rspec_fallback,
739                                                    false, mimo_ctlchbw);
740         }
741
742         BRCMS_SET_MIMO_PLCP_LEN(plcp, session->ampdu_len);
743         /* mark plcp to indicate ampdu */
744         BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
745
746         /* reset the mixed mode header durations */
747         if (txh->MModeLen) {
748                 u16 mmodelen = brcms_c_calc_lsig_len(wlc, rspec,
749                                                      session->ampdu_len);
750                 txh->MModeLen = cpu_to_le16(mmodelen);
751                 preamble_type = BRCMS_MM_PREAMBLE;
752         }
753         if (txh->MModeFbrLen) {
754                 u16 mmfbrlen = brcms_c_calc_lsig_len(wlc, rspec_fallback,
755                                                      session->ampdu_len);
756                 txh->MModeFbrLen = cpu_to_le16(mmfbrlen);
757                 fbr_preamble_type = BRCMS_MM_PREAMBLE;
758         }
759
760         /* set the preload length */
761         if (mcs_2_rate(mcs, true, false) >= f->dmaxferrate) {
762                 dma_len = min(dma_len, f->ampdu_pld_size);
763                 txh->PreloadSize = cpu_to_le16(dma_len);
764         } else {
765                 txh->PreloadSize = 0;
766         }
767
768         mch = le16_to_cpu(txh->MacTxControlHigh);
769
770         /* update RTS dur fields */
771         if (use_rts || use_cts) {
772                 u16 durid;
773                 if ((mch & TXC_PREAMBLE_RTS_MAIN_SHORT) ==
774                     TXC_PREAMBLE_RTS_MAIN_SHORT)
775                         rts_preamble_type = BRCMS_SHORT_PREAMBLE;
776
777                 if ((mch & TXC_PREAMBLE_RTS_FB_SHORT) ==
778                      TXC_PREAMBLE_RTS_FB_SHORT)
779                         rts_fbr_preamble_type = BRCMS_SHORT_PREAMBLE;
780
781                 durid = brcms_c_compute_rtscts_dur(wlc, use_cts, rts_rspec,
782                                                    rspec, rts_preamble_type,
783                                                    preamble_type,
784                                                    session->ampdu_len, true);
785                 rts->duration = cpu_to_le16(durid);
786                 durid = brcms_c_compute_rtscts_dur(wlc, use_cts,
787                                                    rts_rspec_fallback,
788                                                    rspec_fallback,
789                                                    rts_fbr_preamble_type,
790                                                    fbr_preamble_type,
791                                                    session->ampdu_len, true);
792                 txh->RTSDurFallback = cpu_to_le16(durid);
793                 /* set TxFesTimeNormal */
794                 txh->TxFesTimeNormal = rts->duration;
795                 /* set fallback rate version of TxFesTimeNormal */
796                 txh->TxFesTimeFallback = txh->RTSDurFallback;
797         }
798
799         /* set flag and plcp for fallback rate */
800         if (fbr) {
801                 mch |= TXC_AMPDU_FBR;
802                 txh->MacTxControlHigh = cpu_to_le16(mch);
803                 BRCMS_SET_MIMO_PLCP_AMPDU(plcp);
804                 BRCMS_SET_MIMO_PLCP_AMPDU(txh->FragPLCPFallback);
805         }
806
807         brcms_dbg_ht(wlc->hw->d11core, "wl%d: count %d ampdu_len %d\n",
808                      wlc->pub->unit, skb_queue_len(&session->skb_list),
809                      session->ampdu_len);
810 }
811
812 static void
813 brcms_c_ampdu_rate_status(struct brcms_c_info *wlc,
814                           struct ieee80211_tx_info *tx_info,
815                           struct tx_status *txs, u8 mcs)
816 {
817         struct ieee80211_tx_rate *txrate = tx_info->status.rates;
818         int i;
819
820         /* clear the rest of the rates */
821         for (i = 2; i < IEEE80211_TX_MAX_RATES; i++) {
822                 txrate[i].idx = -1;
823                 txrate[i].count = 0;
824         }
825 }
826
827 static void
828 brcms_c_ampdu_dotxstatus_complete(struct ampdu_info *ampdu, struct scb *scb,
829                               struct sk_buff *p, struct tx_status *txs,
830                               u32 s1, u32 s2)
831 {
832         struct scb_ampdu *scb_ampdu;
833         struct brcms_c_info *wlc = ampdu->wlc;
834         struct scb_ampdu_tid_ini *ini;
835         u8 bitmap[8], queue, tid;
836         struct d11txh *txh;
837         u8 *plcp;
838         struct ieee80211_hdr *h;
839         u16 seq, start_seq = 0, bindex, index, mcl;
840         u8 mcs = 0;
841         bool ba_recd = false, ack_recd = false;
842         u8 tot_mpdu = 0;
843         uint supr_status;
844         bool retry = true;
845         u16 mimoantsel = 0;
846         u8 retry_limit;
847         struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(p);
848
849 #ifdef DEBUG
850         u8 hole[AMPDU_MAX_MPDU];
851         memset(hole, 0, sizeof(hole));
852 #endif
853
854         scb_ampdu = &scb->scb_ampdu;
855         tid = (u8) (p->priority);
856
857         ini = &scb_ampdu->ini[tid];
858         retry_limit = ampdu->retry_limit_tid[tid];
859         memset(bitmap, 0, sizeof(bitmap));
860         queue = txs->frameid & TXFID_QUEUE_MASK;
861         supr_status = txs->status & TX_STATUS_SUPR_MASK;
862
863         if (txs->status & TX_STATUS_ACK_RCV) {
864                 WARN_ON(!(txs->status & TX_STATUS_INTERMEDIATE));
865                 start_seq = txs->sequence >> SEQNUM_SHIFT;
866                 bitmap[0] = (txs->status & TX_STATUS_BA_BMAP03_MASK) >>
867                     TX_STATUS_BA_BMAP03_SHIFT;
868
869                 WARN_ON(s1 & TX_STATUS_INTERMEDIATE);
870                 WARN_ON(!(s1 & TX_STATUS_AMPDU));
871
872                 bitmap[0] |=
873                     (s1 & TX_STATUS_BA_BMAP47_MASK) <<
874                     TX_STATUS_BA_BMAP47_SHIFT;
875                 bitmap[1] = (s1 >> 8) & 0xff;
876                 bitmap[2] = (s1 >> 16) & 0xff;
877                 bitmap[3] = (s1 >> 24) & 0xff;
878
879                 bitmap[4] = s2 & 0xff;
880                 bitmap[5] = (s2 >> 8) & 0xff;
881                 bitmap[6] = (s2 >> 16) & 0xff;
882                 bitmap[7] = (s2 >> 24) & 0xff;
883
884                 ba_recd = true;
885         } else {
886                 if (supr_status) {
887                         if (supr_status == TX_STATUS_SUPR_BADCH) {
888                                 brcms_dbg_ht(wlc->hw->d11core,
889                                           "%s: Pkt tx suppressed, illegal channel possibly %d\n",
890                                           __func__, CHSPEC_CHANNEL(
891                                           wlc->default_bss->chanspec));
892                         } else {
893                                 if (supr_status != TX_STATUS_SUPR_FRAG)
894                                         brcms_err(wlc->hw->d11core,
895                                                   "%s: supr_status 0x%x\n",
896                                                   __func__, supr_status);
897                         }
898                         /* no need to retry for badch; will fail again */
899                         if (supr_status == TX_STATUS_SUPR_BADCH ||
900                             supr_status == TX_STATUS_SUPR_EXPTIME) {
901                                 retry = false;
902                         } else if (supr_status == TX_STATUS_SUPR_EXPTIME) {
903                                 /* TX underflow:
904                                  *   try tuning pre-loading or ampdu size
905                                  */
906                         } else if (supr_status == TX_STATUS_SUPR_FRAG) {
907                                 /*
908                                  * if there were underflows, but pre-loading
909                                  * is not active, notify rate adaptation.
910                                  */
911                                 brcms_c_ffpld_check_txfunfl(wlc, queue);
912                         }
913                 } else if (txs->phyerr) {
914                         brcms_dbg_ht(wlc->hw->d11core,
915                                      "%s: ampdu tx phy error (0x%x)\n",
916                                      __func__, txs->phyerr);
917                 }
918         }
919
920         /* loop through all pkts and retry if not acked */
921         while (p) {
922                 tx_info = IEEE80211_SKB_CB(p);
923                 txh = (struct d11txh *) p->data;
924                 mcl = le16_to_cpu(txh->MacTxControlLow);
925                 plcp = (u8 *) (txh + 1);
926                 h = (struct ieee80211_hdr *)(plcp + D11_PHY_HDR_LEN);
927                 seq = le16_to_cpu(h->seq_ctrl) >> SEQNUM_SHIFT;
928
929                 trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, sizeof(*txh));
930
931                 if (tot_mpdu == 0) {
932                         mcs = plcp[0] & MIMO_PLCP_MCS_MASK;
933                         mimoantsel = le16_to_cpu(txh->ABI_MimoAntSel);
934                 }
935
936                 index = TX_SEQ_TO_INDEX(seq);
937                 ack_recd = false;
938                 if (ba_recd) {
939                         int block_acked;
940
941                         bindex = MODSUB_POW2(seq, start_seq, SEQNUM_MAX);
942                         if (bindex < AMPDU_TX_BA_MAX_WSIZE)
943                                 block_acked = isset(bitmap, bindex);
944                         else
945                                 block_acked = 0;
946                         brcms_dbg_ht(wlc->hw->d11core,
947                                      "tid %d seq %d, start_seq %d, bindex %d set %d, index %d\n",
948                                      tid, seq, start_seq, bindex,
949                                      block_acked, index);
950                         /* if acked then clear bit and free packet */
951                         if (block_acked) {
952                                 ini->txretry[index] = 0;
953
954                                 /*
955                                  * ampdu_ack_len:
956                                  *   number of acked aggregated frames
957                                  */
958                                 /* ampdu_len: number of aggregated frames */
959                                 brcms_c_ampdu_rate_status(wlc, tx_info, txs,
960                                                           mcs);
961                                 tx_info->flags |= IEEE80211_TX_STAT_ACK;
962                                 tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
963                                 tx_info->status.ampdu_ack_len =
964                                         tx_info->status.ampdu_len = 1;
965
966                                 skb_pull(p, D11_PHY_HDR_LEN);
967                                 skb_pull(p, D11_TXH_LEN);
968
969                                 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
970                                                             p);
971                                 ack_recd = true;
972                         }
973                 }
974                 /* either retransmit or send bar if ack not recd */
975                 if (!ack_recd) {
976                         if (retry && (ini->txretry[index] < (int)retry_limit)) {
977                                 int ret;
978                                 ini->txretry[index]++;
979                                 ret = brcms_c_txfifo(wlc, queue, p);
980                                 /*
981                                  * We shouldn't be out of space in the DMA
982                                  * ring here since we're reinserting a frame
983                                  * that was just pulled out.
984                                  */
985                                 WARN_ONCE(ret, "queue %d out of txds\n", queue);
986                         } else {
987                                 /* Retry timeout */
988                                 ieee80211_tx_info_clear_status(tx_info);
989                                 tx_info->status.ampdu_ack_len = 0;
990                                 tx_info->status.ampdu_len = 1;
991                                 tx_info->flags |=
992                                     IEEE80211_TX_STAT_AMPDU_NO_BACK;
993                                 skb_pull(p, D11_PHY_HDR_LEN);
994                                 skb_pull(p, D11_TXH_LEN);
995                                 brcms_dbg_ht(wlc->hw->d11core,
996                                              "BA Timeout, seq %d\n",
997                                              seq);
998                                 ieee80211_tx_status_irqsafe(wlc->pub->ieee_hw,
999                                                             p);
1000                         }
1001                 }
1002                 tot_mpdu++;
1003
1004                 /* break out if last packet of ampdu */
1005                 if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1006                     TXC_AMPDU_LAST)
1007                         break;
1008
1009                 p = dma_getnexttxp(wlc->hw->di[queue], DMA_RANGE_TRANSMITTED);
1010         }
1011
1012         /* update rate state */
1013         brcms_c_antsel_antsel2id(wlc->asi, mimoantsel);
1014 }
1015
1016 void
1017 brcms_c_ampdu_dotxstatus(struct ampdu_info *ampdu, struct scb *scb,
1018                      struct sk_buff *p, struct tx_status *txs)
1019 {
1020         struct brcms_c_info *wlc = ampdu->wlc;
1021         u32 s1 = 0, s2 = 0;
1022
1023         /* BMAC_NOTE: For the split driver, second level txstatus comes later
1024          * So if the ACK was received then wait for the second level else just
1025          * call the first one
1026          */
1027         if (txs->status & TX_STATUS_ACK_RCV) {
1028                 u8 status_delay = 0;
1029
1030                 /* wait till the next 8 bytes of txstatus is available */
1031                 s1 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus));
1032                 while ((s1 & TXS_V) == 0) {
1033                         udelay(1);
1034                         status_delay++;
1035                         if (status_delay > 10)
1036                                 return; /* error condition */
1037                         s1 = bcma_read32(wlc->hw->d11core,
1038                                          D11REGOFFS(frmtxstatus));
1039                 }
1040
1041                 s2 = bcma_read32(wlc->hw->d11core, D11REGOFFS(frmtxstatus2));
1042         }
1043
1044         if (scb) {
1045                 brcms_c_ampdu_dotxstatus_complete(ampdu, scb, p, txs, s1, s2);
1046         } else {
1047                 /* loop through all pkts and free */
1048                 u8 queue = txs->frameid & TXFID_QUEUE_MASK;
1049                 struct d11txh *txh;
1050                 u16 mcl;
1051                 while (p) {
1052                         txh = (struct d11txh *) p->data;
1053                         trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
1054                                            sizeof(*txh));
1055                         mcl = le16_to_cpu(txh->MacTxControlLow);
1056                         brcmu_pkt_buf_free_skb(p);
1057                         /* break out if last packet of ampdu */
1058                         if (((mcl & TXC_AMPDU_MASK) >> TXC_AMPDU_SHIFT) ==
1059                             TXC_AMPDU_LAST)
1060                                 break;
1061                         p = dma_getnexttxp(wlc->hw->di[queue],
1062                                            DMA_RANGE_TRANSMITTED);
1063                 }
1064         }
1065 }
1066
1067 void brcms_c_ampdu_macaddr_upd(struct brcms_c_info *wlc)
1068 {
1069         char template[T_RAM_ACCESS_SZ * 2];
1070
1071         /* driver needs to write the ta in the template; ta is at offset 16 */
1072         memset(template, 0, sizeof(template));
1073         memcpy(template, wlc->pub->cur_etheraddr, ETH_ALEN);
1074         brcms_b_write_template_ram(wlc->hw, (T_BA_TPL_BASE + 16),
1075                                   (T_RAM_ACCESS_SZ * 2),
1076                                   template);
1077 }
1078
1079 bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid)
1080 {
1081         return wlc->ampdu->ini_enable[tid];
1082 }
1083
1084 void brcms_c_ampdu_shm_upd(struct ampdu_info *ampdu)
1085 {
1086         struct brcms_c_info *wlc = ampdu->wlc;
1087
1088         /*
1089          * Extend ucode internal watchdog timer to
1090          * match larger received frames
1091          */
1092         if ((ampdu->rx_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) ==
1093             IEEE80211_HT_MAX_AMPDU_64K) {
1094                 brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_MAX);
1095                 brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_MAX);
1096         } else {
1097                 brcms_b_write_shm(wlc->hw, M_MIMO_MAXSYM, MIMO_MAXSYM_DEF);
1098                 brcms_b_write_shm(wlc->hw, M_WATCHDOG_8TU, WATCHDOG_8TU_DEF);
1099         }
1100 }
1101
1102 /*
1103  * callback function that helps invalidating ampdu packets in a DMA queue
1104  */
1105 static void dma_cb_fn_ampdu(void *txi, void *arg_a)
1106 {
1107         struct ieee80211_sta *sta = arg_a;
1108         struct ieee80211_tx_info *tx_info = (struct ieee80211_tx_info *)txi;
1109
1110         if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
1111             (tx_info->rate_driver_data[0] == sta || sta == NULL))
1112                 tx_info->rate_driver_data[0] = NULL;
1113 }
1114
1115 /*
1116  * When a remote party is no longer available for ampdu communication, any
1117  * pending tx ampdu packets in the driver have to be flushed.
1118  */
1119 void brcms_c_ampdu_flush(struct brcms_c_info *wlc,
1120                      struct ieee80211_sta *sta, u16 tid)
1121 {
1122         brcms_c_inval_dma_pkts(wlc->hw, sta, dma_cb_fn_ampdu);
1123 }