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