• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
brcms_c_scb_ampdu_update_max_txlen(struct ampdu_info * ampdu,u8 dur)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 
brcms_c_ampdu_cap(struct ampdu_info * ampdu)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 
brcms_c_ampdu_set(struct ampdu_info * ampdu,bool on)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 
brcms_c_ffpld_init(struct ampdu_info * ampdu)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 
brcms_c_ampdu_attach(struct brcms_c_info * wlc)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 
brcms_c_ampdu_detach(struct ampdu_info * ampdu)278 void brcms_c_ampdu_detach(struct ampdu_info *ampdu)
279 {
280 	kfree(ampdu);
281 }
282 
brcms_c_scb_ampdu_update_config(struct ampdu_info * ampdu,struct scb * scb)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 
brcms_c_scb_ampdu_update_config_all(struct ampdu_info * ampdu)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 
brcms_c_ffpld_calc_mcs2ampdu_table(struct ampdu_info * ampdu,int f)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  */
brcms_c_ffpld_check_txfunfl(struct brcms_c_info * wlc,int fid)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
brcms_c_ampdu_tx_operational(struct brcms_c_info * wlc,u8 tid,uint max_rx_ampdu_bytes)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 
brcms_c_ampdu_reset_session(struct brcms_ampdu_session * session,struct brcms_c_info * wlc)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  */
brcms_c_ampdu_add_frame(struct brcms_ampdu_session * session,struct sk_buff * p)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 
brcms_c_ampdu_finalize(struct brcms_ampdu_session * session)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
brcms_c_ampdu_rate_status(struct brcms_c_info * wlc,struct ieee80211_tx_info * tx_info,struct tx_status * txs,u8 mcs)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
brcms_c_ampdu_dotxstatus_complete(struct ampdu_info * ampdu,struct scb * scb,struct sk_buff * p,struct tx_status * txs,u32 s1,u32 s2)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
brcms_c_ampdu_dotxstatus(struct ampdu_info * ampdu,struct scb * scb,struct sk_buff * p,struct tx_status * txs)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 
brcms_c_ampdu_macaddr_upd(struct brcms_c_info * wlc)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 
brcms_c_aggregatable(struct brcms_c_info * wlc,u8 tid)1079 bool brcms_c_aggregatable(struct brcms_c_info *wlc, u8 tid)
1080 {
1081 	return wlc->ampdu->ini_enable[tid];
1082 }
1083 
brcms_c_ampdu_shm_upd(struct ampdu_info * ampdu)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  */
dma_cb_fn_ampdu(void * txi,void * arg_a)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  */
brcms_c_ampdu_flush(struct brcms_c_info * wlc,struct ieee80211_sta * sta,u16 tid)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 }
1124