xref: /freebsd/sys/dev/ath/if_ath_tx_ht.c (revision 707210ff0ee4678b32f8022259ee27a33b5d614c)
14b44f6f2SAdrian Chadd /*-
24b44f6f2SAdrian Chadd  * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
34b44f6f2SAdrian Chadd  * All rights reserved.
44b44f6f2SAdrian Chadd  *
54b44f6f2SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
64b44f6f2SAdrian Chadd  * modification, are permitted provided that the following conditions
74b44f6f2SAdrian Chadd  * are met:
84b44f6f2SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
94b44f6f2SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
104b44f6f2SAdrian Chadd  *    without modification.
114b44f6f2SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
124b44f6f2SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
134b44f6f2SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
144b44f6f2SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
154b44f6f2SAdrian Chadd  *
164b44f6f2SAdrian Chadd  * NO WARRANTY
174b44f6f2SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
184b44f6f2SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
194b44f6f2SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
204b44f6f2SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
214b44f6f2SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
224b44f6f2SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
234b44f6f2SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
244b44f6f2SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
254b44f6f2SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
264b44f6f2SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
274b44f6f2SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
284b44f6f2SAdrian Chadd  */
294b44f6f2SAdrian Chadd 
304b44f6f2SAdrian Chadd #include <sys/cdefs.h>
314b44f6f2SAdrian Chadd __FBSDID("$FreeBSD$");
324b44f6f2SAdrian Chadd 
334b44f6f2SAdrian Chadd #include "opt_inet.h"
344b44f6f2SAdrian Chadd #include "opt_ath.h"
354b44f6f2SAdrian Chadd #include "opt_wlan.h"
364b44f6f2SAdrian Chadd 
374b44f6f2SAdrian Chadd #include <sys/param.h>
384b44f6f2SAdrian Chadd #include <sys/systm.h>
394b44f6f2SAdrian Chadd #include <sys/sysctl.h>
404b44f6f2SAdrian Chadd #include <sys/mbuf.h>
414b44f6f2SAdrian Chadd #include <sys/malloc.h>
424b44f6f2SAdrian Chadd #include <sys/lock.h>
434b44f6f2SAdrian Chadd #include <sys/mutex.h>
444b44f6f2SAdrian Chadd #include <sys/kernel.h>
454b44f6f2SAdrian Chadd #include <sys/socket.h>
464b44f6f2SAdrian Chadd #include <sys/sockio.h>
474b44f6f2SAdrian Chadd #include <sys/errno.h>
484b44f6f2SAdrian Chadd #include <sys/callout.h>
494b44f6f2SAdrian Chadd #include <sys/bus.h>
504b44f6f2SAdrian Chadd #include <sys/endian.h>
514b44f6f2SAdrian Chadd #include <sys/kthread.h>
524b44f6f2SAdrian Chadd #include <sys/taskqueue.h>
534b44f6f2SAdrian Chadd #include <sys/priv.h>
544b44f6f2SAdrian Chadd 
554b44f6f2SAdrian Chadd #include <machine/bus.h>
564b44f6f2SAdrian Chadd 
574b44f6f2SAdrian Chadd #include <net/if.h>
584b44f6f2SAdrian Chadd #include <net/if_dl.h>
594b44f6f2SAdrian Chadd #include <net/if_media.h>
604b44f6f2SAdrian Chadd #include <net/if_types.h>
614b44f6f2SAdrian Chadd #include <net/if_arp.h>
624b44f6f2SAdrian Chadd #include <net/ethernet.h>
634b44f6f2SAdrian Chadd #include <net/if_llc.h>
644b44f6f2SAdrian Chadd 
654b44f6f2SAdrian Chadd #include <net80211/ieee80211_var.h>
664b44f6f2SAdrian Chadd #include <net80211/ieee80211_regdomain.h>
674b44f6f2SAdrian Chadd #ifdef IEEE80211_SUPPORT_SUPERG
684b44f6f2SAdrian Chadd #include <net80211/ieee80211_superg.h>
694b44f6f2SAdrian Chadd #endif
704b44f6f2SAdrian Chadd #ifdef IEEE80211_SUPPORT_TDMA
714b44f6f2SAdrian Chadd #include <net80211/ieee80211_tdma.h>
724b44f6f2SAdrian Chadd #endif
734b44f6f2SAdrian Chadd 
744b44f6f2SAdrian Chadd #include <net/bpf.h>
754b44f6f2SAdrian Chadd 
764b44f6f2SAdrian Chadd #ifdef INET
774b44f6f2SAdrian Chadd #include <netinet/in.h>
784b44f6f2SAdrian Chadd #include <netinet/if_ether.h>
794b44f6f2SAdrian Chadd #endif
804b44f6f2SAdrian Chadd 
814b44f6f2SAdrian Chadd #include <dev/ath/if_athvar.h>
824b44f6f2SAdrian Chadd #include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
834b44f6f2SAdrian Chadd #include <dev/ath/ath_hal/ah_diagcodes.h>
844b44f6f2SAdrian Chadd 
854b44f6f2SAdrian Chadd #ifdef ATH_TX99_DIAG
864b44f6f2SAdrian Chadd #include <dev/ath/ath_tx99/ath_tx99.h>
874b44f6f2SAdrian Chadd #endif
884b44f6f2SAdrian Chadd 
89eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_tx.h>		/* XXX for some support functions */
904b44f6f2SAdrian Chadd #include <dev/ath/if_ath_tx_ht.h>
91eb6f0de0SAdrian Chadd #include <dev/ath/if_athrate.h>
92eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_debug.h>
93eb6f0de0SAdrian Chadd 
94eb6f0de0SAdrian Chadd /*
95eb6f0de0SAdrian Chadd  * XXX net80211?
96eb6f0de0SAdrian Chadd  */
97eb6f0de0SAdrian Chadd #define	IEEE80211_AMPDU_SUBFRAME_DEFAULT		32
98eb6f0de0SAdrian Chadd 
99eb6f0de0SAdrian Chadd #define	ATH_AGGR_DELIM_SZ	4	/* delimiter size */
100eb6f0de0SAdrian Chadd #define	ATH_AGGR_MINPLEN	256	/* in bytes, minimum packet length */
101b25c1f2aSAdrian Chadd /* number of delimiters for encryption padding */
102b25c1f2aSAdrian Chadd #define	ATH_AGGR_ENCRYPTDELIM	10
103eb6f0de0SAdrian Chadd 
104eb6f0de0SAdrian Chadd /*
105eb6f0de0SAdrian Chadd  * returns delimiter padding required given the packet length
106eb6f0de0SAdrian Chadd  */
107eb6f0de0SAdrian Chadd #define	ATH_AGGR_GET_NDELIM(_len)					\
108eb6f0de0SAdrian Chadd 	    (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?	\
109eb6f0de0SAdrian Chadd 	    (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
110eb6f0de0SAdrian Chadd 
111eb6f0de0SAdrian Chadd #define	PADBYTES(_len)		((4 - ((_len) % 4)) % 4)
112eb6f0de0SAdrian Chadd 
113eb6f0de0SAdrian Chadd int ath_max_4ms_framelen[4][32] = {
114eb6f0de0SAdrian Chadd 	[MCS_HT20] = {
115eb6f0de0SAdrian Chadd 		3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
116eb6f0de0SAdrian Chadd 		6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
117eb6f0de0SAdrian Chadd 		9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
118eb6f0de0SAdrian Chadd 		12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
119eb6f0de0SAdrian Chadd 	},
120eb6f0de0SAdrian Chadd 	[MCS_HT20_SGI] = {
121eb6f0de0SAdrian Chadd 		3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
122eb6f0de0SAdrian Chadd 		7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
123eb6f0de0SAdrian Chadd 		10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
124eb6f0de0SAdrian Chadd 		14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
125eb6f0de0SAdrian Chadd 	},
126eb6f0de0SAdrian Chadd 	[MCS_HT40] = {
127eb6f0de0SAdrian Chadd 		6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
128eb6f0de0SAdrian Chadd 		13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
129eb6f0de0SAdrian Chadd 		20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
130eb6f0de0SAdrian Chadd 		26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
131eb6f0de0SAdrian Chadd 	},
132eb6f0de0SAdrian Chadd 	[MCS_HT40_SGI] = {
133eb6f0de0SAdrian Chadd 		7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
134eb6f0de0SAdrian Chadd 		14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
135eb6f0de0SAdrian Chadd 		22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
136eb6f0de0SAdrian Chadd 		29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
137eb6f0de0SAdrian Chadd 	}
138eb6f0de0SAdrian Chadd };
139eb6f0de0SAdrian Chadd 
140eb6f0de0SAdrian Chadd /*
141eb6f0de0SAdrian Chadd  * XXX should be in net80211
142eb6f0de0SAdrian Chadd  */
143eb6f0de0SAdrian Chadd static int ieee80211_mpdudensity_map[] = {
144eb6f0de0SAdrian Chadd 	0,		/* IEEE80211_HTCAP_MPDUDENSITY_NA */
145eb6f0de0SAdrian Chadd 	25,		/* IEEE80211_HTCAP_MPDUDENSITY_025 */
146eb6f0de0SAdrian Chadd 	50,		/* IEEE80211_HTCAP_MPDUDENSITY_05 */
147eb6f0de0SAdrian Chadd 	100,		/* IEEE80211_HTCAP_MPDUDENSITY_1 */
148eb6f0de0SAdrian Chadd 	200,		/* IEEE80211_HTCAP_MPDUDENSITY_2 */
149eb6f0de0SAdrian Chadd 	400,		/* IEEE80211_HTCAP_MPDUDENSITY_4 */
150eb6f0de0SAdrian Chadd 	800,		/* IEEE80211_HTCAP_MPDUDENSITY_8 */
151eb6f0de0SAdrian Chadd 	1600,		/* IEEE80211_HTCAP_MPDUDENSITY_16 */
152eb6f0de0SAdrian Chadd };
153eb6f0de0SAdrian Chadd 
154eb6f0de0SAdrian Chadd /*
155eb6f0de0SAdrian Chadd  * XXX should be in the HAL/net80211 ?
156eb6f0de0SAdrian Chadd  */
157eb6f0de0SAdrian Chadd #define	BITS_PER_BYTE		8
158eb6f0de0SAdrian Chadd #define	OFDM_PLCP_BITS		22
159eb6f0de0SAdrian Chadd #define	HT_RC_2_MCS(_rc)	((_rc) & 0x7f)
160eb6f0de0SAdrian Chadd #define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
161eb6f0de0SAdrian Chadd #define	L_STF			8
162eb6f0de0SAdrian Chadd #define	L_LTF			8
163eb6f0de0SAdrian Chadd #define	L_SIG			4
164eb6f0de0SAdrian Chadd #define	HT_SIG			8
165eb6f0de0SAdrian Chadd #define	HT_STF			4
166eb6f0de0SAdrian Chadd #define	HT_LTF(_ns)		(4 * (_ns))
167eb6f0de0SAdrian Chadd #define	SYMBOL_TIME(_ns)	((_ns) << 2)		// ns * 4 us
168eb6f0de0SAdrian Chadd #define	SYMBOL_TIME_HALFGI(_ns)	(((_ns) * 18 + 4) / 5)	// ns * 3.6 us
169eb6f0de0SAdrian Chadd #define	NUM_SYMBOLS_PER_USEC(_usec)	(_usec >> 2)
170eb6f0de0SAdrian Chadd #define	NUM_SYMBOLS_PER_USEC_HALFGI(_usec)	(((_usec*5)-4)/18)
171eb6f0de0SAdrian Chadd #define	IS_HT_RATE(_rate)	((_rate) & 0x80)
172eb6f0de0SAdrian Chadd 
173eb6f0de0SAdrian Chadd const uint32_t bits_per_symbol[][2] = {
174eb6f0de0SAdrian Chadd     /* 20MHz 40MHz */
175eb6f0de0SAdrian Chadd     {    26,   54 },     //  0: BPSK
176eb6f0de0SAdrian Chadd     {    52,  108 },     //  1: QPSK 1/2
177eb6f0de0SAdrian Chadd     {    78,  162 },     //  2: QPSK 3/4
178eb6f0de0SAdrian Chadd     {   104,  216 },     //  3: 16-QAM 1/2
179eb6f0de0SAdrian Chadd     {   156,  324 },     //  4: 16-QAM 3/4
180eb6f0de0SAdrian Chadd     {   208,  432 },     //  5: 64-QAM 2/3
181eb6f0de0SAdrian Chadd     {   234,  486 },     //  6: 64-QAM 3/4
182eb6f0de0SAdrian Chadd     {   260,  540 },     //  7: 64-QAM 5/6
183eb6f0de0SAdrian Chadd     {    52,  108 },     //  8: BPSK
184eb6f0de0SAdrian Chadd     {   104,  216 },     //  9: QPSK 1/2
185eb6f0de0SAdrian Chadd     {   156,  324 },     // 10: QPSK 3/4
186eb6f0de0SAdrian Chadd     {   208,  432 },     // 11: 16-QAM 1/2
187eb6f0de0SAdrian Chadd     {   312,  648 },     // 12: 16-QAM 3/4
188eb6f0de0SAdrian Chadd     {   416,  864 },     // 13: 64-QAM 2/3
189eb6f0de0SAdrian Chadd     {   468,  972 },     // 14: 64-QAM 3/4
190eb6f0de0SAdrian Chadd     {   520, 1080 },     // 15: 64-QAM 5/6
191eb6f0de0SAdrian Chadd     {    78,  162 },     // 16: BPSK
192eb6f0de0SAdrian Chadd     {   156,  324 },     // 17: QPSK 1/2
193eb6f0de0SAdrian Chadd     {   234,  486 },     // 18: QPSK 3/4
194eb6f0de0SAdrian Chadd     {   312,  648 },     // 19: 16-QAM 1/2
195eb6f0de0SAdrian Chadd     {   468,  972 },     // 20: 16-QAM 3/4
196eb6f0de0SAdrian Chadd     {   624, 1296 },     // 21: 64-QAM 2/3
197eb6f0de0SAdrian Chadd     {   702, 1458 },     // 22: 64-QAM 3/4
198eb6f0de0SAdrian Chadd     {   780, 1620 },     // 23: 64-QAM 5/6
199eb6f0de0SAdrian Chadd     {   104,  216 },     // 24: BPSK
200eb6f0de0SAdrian Chadd     {   208,  432 },     // 25: QPSK 1/2
201eb6f0de0SAdrian Chadd     {   312,  648 },     // 26: QPSK 3/4
202eb6f0de0SAdrian Chadd     {   416,  864 },     // 27: 16-QAM 1/2
203eb6f0de0SAdrian Chadd     {   624, 1296 },     // 28: 16-QAM 3/4
204eb6f0de0SAdrian Chadd     {   832, 1728 },     // 29: 64-QAM 2/3
205eb6f0de0SAdrian Chadd     {   936, 1944 },     // 30: 64-QAM 3/4
206eb6f0de0SAdrian Chadd     {  1040, 2160 },     // 31: 64-QAM 5/6
207eb6f0de0SAdrian Chadd };
208eb6f0de0SAdrian Chadd 
209eb6f0de0SAdrian Chadd /*
210eb6f0de0SAdrian Chadd  * Fill in the rate array information based on the current
211eb6f0de0SAdrian Chadd  * node configuration and the choices made by the rate
212eb6f0de0SAdrian Chadd  * selection code and ath_buf setup code.
213eb6f0de0SAdrian Chadd  *
214eb6f0de0SAdrian Chadd  * Later on, this may end up also being made by the
215eb6f0de0SAdrian Chadd  * rate control code, but for now it can live here.
216eb6f0de0SAdrian Chadd  *
217eb6f0de0SAdrian Chadd  * This needs to be called just before the packet is
218eb6f0de0SAdrian Chadd  * queued to the software queue or hardware queue,
219eb6f0de0SAdrian Chadd  * so all of the needed fields in bf_state are setup.
220eb6f0de0SAdrian Chadd  */
221eb6f0de0SAdrian Chadd void
222eb6f0de0SAdrian Chadd ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
223eb6f0de0SAdrian Chadd {
224eb6f0de0SAdrian Chadd 	struct ieee80211_node *ni = bf->bf_node;
225a7038bd1SAdrian Chadd 	struct ieee80211vap *vap = ni->ni_vap;
226eb6f0de0SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
227eb6f0de0SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
228eb6f0de0SAdrian Chadd 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
229eb6f0de0SAdrian Chadd 	uint8_t rate;
230eb6f0de0SAdrian Chadd 	int i;
231ce725c8eSAdrian Chadd 	int do_ldpc;
232ce725c8eSAdrian Chadd 	int do_stbc;
233ce725c8eSAdrian Chadd 
234ce725c8eSAdrian Chadd 	/*
235ce725c8eSAdrian Chadd 	 * We only do LDPC if the rate is 11n, both we and the
236ce725c8eSAdrian Chadd 	 * receiver support LDPC and it's enabled.
237ce725c8eSAdrian Chadd 	 *
238ce725c8eSAdrian Chadd 	 * It's a global flag, not a per-try flag, so we clear
239ce725c8eSAdrian Chadd 	 * it if any of the rate entries aren't 11n.
240ce725c8eSAdrian Chadd 	 */
241a0391187SAdrian Chadd 	do_ldpc = 0;
242ce725c8eSAdrian Chadd 	if ((ni->ni_vap->iv_htcaps & IEEE80211_HTCAP_LDPC) &&
243ce725c8eSAdrian Chadd 	    (ni->ni_htcap & IEEE80211_HTCAP_LDPC))
244ce725c8eSAdrian Chadd 		do_ldpc = 1;
245ffa25becSAdrian Chadd 
246ffa25becSAdrian Chadd 	/*
247ffa25becSAdrian Chadd 	 * The 11n duration calculation doesn't know about LDPC,
248ffa25becSAdrian Chadd 	 * so don't enable it for positioning.
249ffa25becSAdrian Chadd 	 */
250ffa25becSAdrian Chadd 	if (bf->bf_flags & ATH_BUF_TOA_PROBE)
251ffa25becSAdrian Chadd 		do_ldpc = 0;
252ffa25becSAdrian Chadd 
253ce725c8eSAdrian Chadd 	do_stbc = 0;
254eb6f0de0SAdrian Chadd 
255eb6f0de0SAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
256eb6f0de0SAdrian Chadd 		rc[i].flags = 0;
257eb6f0de0SAdrian Chadd 		if (rc[i].tries == 0)
258eb6f0de0SAdrian Chadd 			continue;
259eb6f0de0SAdrian Chadd 
260eb6f0de0SAdrian Chadd 		rate = rt->info[rc[i].rix].rateCode;
261eb6f0de0SAdrian Chadd 
262eb6f0de0SAdrian Chadd 		/*
26356129906SAdrian Chadd 		 * Only enable short preamble for legacy rates
264eb6f0de0SAdrian Chadd 		 */
2657a27f0a3SAdrian Chadd 		if ((! IS_HT_RATE(rate)) && bf->bf_state.bfs_shpream)
266eb6f0de0SAdrian Chadd 			rate |= rt->info[rc[i].rix].shortPreamble;
267eb6f0de0SAdrian Chadd 
268eb6f0de0SAdrian Chadd 		/*
269eb6f0de0SAdrian Chadd 		 * Save this, used by the TX and completion code
270eb6f0de0SAdrian Chadd 		 */
271eb6f0de0SAdrian Chadd 		rc[i].ratecode = rate;
272eb6f0de0SAdrian Chadd 
273875a9451SAdrian Chadd 		if (bf->bf_state.bfs_txflags &
274eb6f0de0SAdrian Chadd 		    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
275eb6f0de0SAdrian Chadd 			rc[i].flags |= ATH_RC_RTSCTS_FLAG;
276eb6f0de0SAdrian Chadd 
277ce725c8eSAdrian Chadd 		/*
278ce725c8eSAdrian Chadd 		 * If we can't do LDPC, don't.
279ce725c8eSAdrian Chadd 		 */
280ce725c8eSAdrian Chadd 		if (! IS_HT_RATE(rate))
281ce725c8eSAdrian Chadd 			do_ldpc = 0;
282ce725c8eSAdrian Chadd 
283eb6f0de0SAdrian Chadd 		/* Only enable shortgi, 2040, dual-stream if HT is set */
284eb6f0de0SAdrian Chadd 		if (IS_HT_RATE(rate)) {
285eb6f0de0SAdrian Chadd 			rc[i].flags |= ATH_RC_HT_FLAG;
286eb6f0de0SAdrian Chadd 
287eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 40)
288eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_CW40_FLAG;
289eb6f0de0SAdrian Chadd 
290ffa25becSAdrian Chadd 			/*
291ffa25becSAdrian Chadd 			 * NOTE: Don't do short-gi for positioning frames.
292ffa25becSAdrian Chadd 			 *
293ffa25becSAdrian Chadd 			 * For now, the ath_hal and net80211 HT duration
294ffa25becSAdrian Chadd 			 * calculation rounds up the 11n data txtime
295ffa25becSAdrian Chadd 			 * to the nearest multiple of 3.6 microseconds
296ffa25becSAdrian Chadd 			 * and doesn't return the fractional part, so
297ffa25becSAdrian Chadd 			 * we are always "out" by some amount.
298ffa25becSAdrian Chadd 			 */
299eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 40 &&
300eb6f0de0SAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
301a7038bd1SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40 &&
302ffa25becSAdrian Chadd 			    vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40 &&
303ffa25becSAdrian Chadd 			    (bf->bf_flags & ATH_BUF_TOA_PROBE) == 0) {
304eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_SGI_FLAG;
305ffa25becSAdrian Chadd 			}
306eb6f0de0SAdrian Chadd 
307eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 20 &&
308eb6f0de0SAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
309a7038bd1SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20 &&
310ffa25becSAdrian Chadd 			    vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20 &&
311ffa25becSAdrian Chadd 			    (bf->bf_flags & ATH_BUF_TOA_PROBE) == 0) {
312eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_SGI_FLAG;
313ffa25becSAdrian Chadd 			}
314eb6f0de0SAdrian Chadd 
31556129906SAdrian Chadd 			/*
31656129906SAdrian Chadd 			 * If we have STBC TX enabled and the receiver
31756129906SAdrian Chadd 			 * can receive (at least) 1 stream STBC, AND it's
31856129906SAdrian Chadd 			 * MCS 0-7, AND we have at least two chains enabled,
319ffa25becSAdrian Chadd 			 * and we're not doing positioning, enable STBC.
32056129906SAdrian Chadd 			 */
32156129906SAdrian Chadd 			if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
322c969f82dSAdrian Chadd 			    (ni->ni_vap->iv_flags_ht & IEEE80211_FHT_STBC_TX) &&
323c969f82dSAdrian Chadd 			    (ni->ni_htcap & IEEE80211_HTCAP_RXSTBC) &&
32456129906SAdrian Chadd 			    (sc->sc_cur_txchainmask > 1) &&
325ffa25becSAdrian Chadd 			    (HT_RC_2_STREAMS(rate) == 1) &&
326ffa25becSAdrian Chadd 			    (bf->bf_flags & ATH_BUF_TOA_PROBE) == 0) {
32756129906SAdrian Chadd 				rc[i].flags |= ATH_RC_STBC_FLAG;
328ce725c8eSAdrian Chadd 				do_stbc = 1;
32956129906SAdrian Chadd 			}
33056129906SAdrian Chadd 
331de00e5cbSAdrian Chadd 			/*
332de00e5cbSAdrian Chadd 			 * Dual / Triple stream rate?
333de00e5cbSAdrian Chadd 			 */
334de00e5cbSAdrian Chadd 			if (HT_RC_2_STREAMS(rate) == 2)
335de00e5cbSAdrian Chadd 				rc[i].flags |= ATH_RC_DS_FLAG;
336de00e5cbSAdrian Chadd 			else if (HT_RC_2_STREAMS(rate) == 3)
337de00e5cbSAdrian Chadd 				rc[i].flags |= ATH_RC_TS_FLAG;
338eb6f0de0SAdrian Chadd 		}
339eb6f0de0SAdrian Chadd 
340eb6f0de0SAdrian Chadd 		/*
341de00e5cbSAdrian Chadd 		 * Calculate the maximum TX power cap for the current
342de00e5cbSAdrian Chadd 		 * node.
343de00e5cbSAdrian Chadd 		 */
344de00e5cbSAdrian Chadd 		rc[i].tx_power_cap = ieee80211_get_node_txpower(ni);
345de00e5cbSAdrian Chadd 
346de00e5cbSAdrian Chadd 		/*
347eb6f0de0SAdrian Chadd 		 * Calculate the maximum 4ms frame length based
348eb6f0de0SAdrian Chadd 		 * on the MCS rate, SGI and channel width flags.
349eb6f0de0SAdrian Chadd 		 */
350eb6f0de0SAdrian Chadd 		if ((rc[i].flags & ATH_RC_HT_FLAG) &&
351eb6f0de0SAdrian Chadd 		    (HT_RC_2_MCS(rate) < 32)) {
352eb6f0de0SAdrian Chadd 			int j;
353eb6f0de0SAdrian Chadd 			if (rc[i].flags & ATH_RC_CW40_FLAG) {
354eb6f0de0SAdrian Chadd 				if (rc[i].flags & ATH_RC_SGI_FLAG)
355eb6f0de0SAdrian Chadd 					j = MCS_HT40_SGI;
356eb6f0de0SAdrian Chadd 				else
357eb6f0de0SAdrian Chadd 					j = MCS_HT40;
358eb6f0de0SAdrian Chadd 			} else {
359eb6f0de0SAdrian Chadd 				if (rc[i].flags & ATH_RC_SGI_FLAG)
360eb6f0de0SAdrian Chadd 					j = MCS_HT20_SGI;
361eb6f0de0SAdrian Chadd 				else
362eb6f0de0SAdrian Chadd 					j = MCS_HT20;
363eb6f0de0SAdrian Chadd 			}
364eb6f0de0SAdrian Chadd 			rc[i].max4msframelen =
365eb6f0de0SAdrian Chadd 			    ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)];
366eb6f0de0SAdrian Chadd 		} else
367eb6f0de0SAdrian Chadd 			rc[i].max4msframelen = 0;
368eb6f0de0SAdrian Chadd 		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
369eb6f0de0SAdrian Chadd 		    "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
370eb6f0de0SAdrian Chadd 		    __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
371eb6f0de0SAdrian Chadd 	}
372ce725c8eSAdrian Chadd 
373ce725c8eSAdrian Chadd 	/*
374ce725c8eSAdrian Chadd 	 * LDPC is a global flag, so ...
375ce725c8eSAdrian Chadd 	 */
376ce725c8eSAdrian Chadd 	if (do_ldpc) {
377ce725c8eSAdrian Chadd 		bf->bf_state.bfs_txflags |= HAL_TXDESC_LDPC;
378ce725c8eSAdrian Chadd 		sc->sc_stats.ast_tx_ldpc++;
379ce725c8eSAdrian Chadd 	}
380ce725c8eSAdrian Chadd 
381ce725c8eSAdrian Chadd 	if (do_stbc) {
382ce725c8eSAdrian Chadd 		sc->sc_stats.ast_tx_stbc++;
383ce725c8eSAdrian Chadd 	}
384eb6f0de0SAdrian Chadd }
385eb6f0de0SAdrian Chadd 
386eb6f0de0SAdrian Chadd /*
387eb6f0de0SAdrian Chadd  * Return the number of delimiters to be added to
388eb6f0de0SAdrian Chadd  * meet the minimum required mpdudensity.
389eb6f0de0SAdrian Chadd  *
390eb6f0de0SAdrian Chadd  * Caller should make sure that the rate is HT.
391eb6f0de0SAdrian Chadd  *
392eb6f0de0SAdrian Chadd  * TODO: is this delimiter calculation supposed to be the
393eb6f0de0SAdrian Chadd  * total frame length, the hdr length, the data length (including
394eb6f0de0SAdrian Chadd  * delimiters, padding, CRC, etc) or ?
395eb6f0de0SAdrian Chadd  *
396eb6f0de0SAdrian Chadd  * TODO: this should ensure that the rate control information
397eb6f0de0SAdrian Chadd  * HAS been setup for the first rate.
398eb6f0de0SAdrian Chadd  *
399eb6f0de0SAdrian Chadd  * TODO: ensure this is only called for MCS rates.
400eb6f0de0SAdrian Chadd  *
401eb6f0de0SAdrian Chadd  * TODO: enforce MCS < 31
402eb6f0de0SAdrian Chadd  */
403eb6f0de0SAdrian Chadd static int
404eb6f0de0SAdrian Chadd ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf,
405eb6f0de0SAdrian Chadd     uint16_t pktlen)
406eb6f0de0SAdrian Chadd {
407c969f82dSAdrian Chadd #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
408eb6f0de0SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
409eb6f0de0SAdrian Chadd 	struct ieee80211_node *ni = first_bf->bf_node;
410eb6f0de0SAdrian Chadd 	struct ieee80211vap *vap = ni->ni_vap;
411eb6f0de0SAdrian Chadd 	int ndelim, mindelim = 0;
412eb6f0de0SAdrian Chadd 	int mpdudensity;	/* in 1/100'th of a microsecond */
413c969f82dSAdrian Chadd 	int peer_mpdudensity;	/* net80211 value */
414eb6f0de0SAdrian Chadd 	uint8_t rc, rix, flags;
415eb6f0de0SAdrian Chadd 	int width, half_gi;
416eb6f0de0SAdrian Chadd 	uint32_t nsymbits, nsymbols;
417eb6f0de0SAdrian Chadd 	uint16_t minlen;
418eb6f0de0SAdrian Chadd 
419eb6f0de0SAdrian Chadd 	/*
420c969f82dSAdrian Chadd 	 * Get the advertised density from the node.
421eb6f0de0SAdrian Chadd 	 */
422c969f82dSAdrian Chadd 	peer_mpdudensity = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY);
423c969f82dSAdrian Chadd 
424c969f82dSAdrian Chadd 	/*
425c969f82dSAdrian Chadd 	 * vap->iv_ampdu_density is a net80211 value, rather than the actual
426c969f82dSAdrian Chadd 	 * density.  Larger values are longer A-MPDU density spacing values,
427c969f82dSAdrian Chadd 	 * and we want to obey larger configured / negotiated density values
428c969f82dSAdrian Chadd 	 * per station if we get it.
429c969f82dSAdrian Chadd 	 */
430c969f82dSAdrian Chadd 	if (vap->iv_ampdu_density > peer_mpdudensity)
431c969f82dSAdrian Chadd 		peer_mpdudensity = vap->iv_ampdu_density;
432c969f82dSAdrian Chadd 
433c969f82dSAdrian Chadd 	/*
434c969f82dSAdrian Chadd 	 * Convert the A-MPDU density net80211 value to a 1/100 microsecond
435c969f82dSAdrian Chadd 	 * value for subsequent calculations.
436c969f82dSAdrian Chadd 	 */
437c969f82dSAdrian Chadd 	if (peer_mpdudensity > IEEE80211_HTCAP_MPDUDENSITY_16)
438eb6f0de0SAdrian Chadd 		mpdudensity = 1600;		/* maximum density */
439eb6f0de0SAdrian Chadd 	else
440c969f82dSAdrian Chadd 		mpdudensity = ieee80211_mpdudensity_map[peer_mpdudensity];
441eb6f0de0SAdrian Chadd 
442eb6f0de0SAdrian Chadd 	/* Select standard number of delimiters based on frame length */
443eb6f0de0SAdrian Chadd 	ndelim = ATH_AGGR_GET_NDELIM(pktlen);
444eb6f0de0SAdrian Chadd 
445eb6f0de0SAdrian Chadd 	/*
446eb6f0de0SAdrian Chadd 	 * If encryption is enabled, add extra delimiters to let the
447eb6f0de0SAdrian Chadd 	 * crypto hardware catch up. This could be tuned per-MAC and
448eb6f0de0SAdrian Chadd 	 * per-rate, but for now we'll simply assume encryption is
449eb6f0de0SAdrian Chadd 	 * always enabled.
4504a502c33SAdrian Chadd 	 *
4514a502c33SAdrian Chadd 	 * Also note that the Atheros reference driver inserts two
4524a502c33SAdrian Chadd 	 * delimiters by default for pre-AR9380 peers.  This will
4534a502c33SAdrian Chadd 	 * include "that" required delimiter.
454eb6f0de0SAdrian Chadd 	 */
455eb6f0de0SAdrian Chadd 	ndelim += ATH_AGGR_ENCRYPTDELIM;
456eb6f0de0SAdrian Chadd 
45764dbfc6dSAdrian Chadd 	/*
45864dbfc6dSAdrian Chadd 	 * For AR9380, there's a minimum number of delimeters
45964dbfc6dSAdrian Chadd 	 * required when doing RTS.
4604a502c33SAdrian Chadd 	 *
4614a502c33SAdrian Chadd 	 * XXX TODO: this is only needed if (a) RTS/CTS is enabled, and
4624a502c33SAdrian Chadd 	 * XXX (b) this is the first sub-frame in the aggregate.
46364dbfc6dSAdrian Chadd 	 */
46464dbfc6dSAdrian Chadd 	if (sc->sc_use_ent && (sc->sc_ent_cfg & AH_ENT_RTSCTS_DELIM_WAR)
46564dbfc6dSAdrian Chadd 	    && ndelim < AH_FIRST_DESC_NDELIMS)
46664dbfc6dSAdrian Chadd 		ndelim = AH_FIRST_DESC_NDELIMS;
46764dbfc6dSAdrian Chadd 
468a54ecf78SAdrian Chadd 	/*
469a54ecf78SAdrian Chadd 	 * If sc_delim_min_pad is non-zero, enforce it as the minimum
470a54ecf78SAdrian Chadd 	 * pad delimiter count.
471a54ecf78SAdrian Chadd 	 */
472a54ecf78SAdrian Chadd 	if (sc->sc_delim_min_pad != 0)
473a54ecf78SAdrian Chadd 		ndelim = MAX(ndelim, sc->sc_delim_min_pad);
474a54ecf78SAdrian Chadd 
475eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
476eb6f0de0SAdrian Chadd 	    "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n",
477eb6f0de0SAdrian Chadd 	    __func__, pktlen, ndelim, mpdudensity);
478eb6f0de0SAdrian Chadd 
479eb6f0de0SAdrian Chadd 	/*
480eb6f0de0SAdrian Chadd 	 * If the MPDU density is 0, we can return here.
481eb6f0de0SAdrian Chadd 	 * Otherwise, we need to convert the desired mpdudensity
482eb6f0de0SAdrian Chadd 	 * into a byte length, based on the rate in the subframe.
483eb6f0de0SAdrian Chadd 	 */
484eb6f0de0SAdrian Chadd 	if (mpdudensity == 0)
485eb6f0de0SAdrian Chadd 		return ndelim;
486eb6f0de0SAdrian Chadd 
487eb6f0de0SAdrian Chadd 	/*
488eb6f0de0SAdrian Chadd 	 * Convert desired mpdu density from microeconds to bytes based
489eb6f0de0SAdrian Chadd 	 * on highest rate in rate series (i.e. first rate) to determine
490eb6f0de0SAdrian Chadd 	 * required minimum length for subframe. Take into account
491eb6f0de0SAdrian Chadd 	 * whether high rate is 20 or 40Mhz and half or full GI.
492eb6f0de0SAdrian Chadd 	 */
493eb6f0de0SAdrian Chadd 	rix = first_bf->bf_state.bfs_rc[0].rix;
494eb6f0de0SAdrian Chadd 	rc = rt->info[rix].rateCode;
495eb6f0de0SAdrian Chadd 	flags = first_bf->bf_state.bfs_rc[0].flags;
496eb6f0de0SAdrian Chadd 	width = !! (flags & ATH_RC_CW40_FLAG);
497eb6f0de0SAdrian Chadd 	half_gi = !! (flags & ATH_RC_SGI_FLAG);
498eb6f0de0SAdrian Chadd 
499eb6f0de0SAdrian Chadd 	/*
500eb6f0de0SAdrian Chadd 	 * mpdudensity is in 1/100th of a usec, so divide by 100
501eb6f0de0SAdrian Chadd 	 */
502eb6f0de0SAdrian Chadd 	if (half_gi)
503eb6f0de0SAdrian Chadd 		nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
504eb6f0de0SAdrian Chadd 	else
505eb6f0de0SAdrian Chadd 		nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
506eb6f0de0SAdrian Chadd 	nsymbols /= 100;
507eb6f0de0SAdrian Chadd 
508eb6f0de0SAdrian Chadd 	if (nsymbols == 0)
509eb6f0de0SAdrian Chadd 		nsymbols = 1;
510eb6f0de0SAdrian Chadd 
511eb6f0de0SAdrian Chadd 	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
512eb6f0de0SAdrian Chadd 	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
513eb6f0de0SAdrian Chadd 
514eb6f0de0SAdrian Chadd 	/*
515eb6f0de0SAdrian Chadd 	 * Min length is the minimum frame length for the
516eb6f0de0SAdrian Chadd 	 * required MPDU density.
517eb6f0de0SAdrian Chadd 	 */
518eb6f0de0SAdrian Chadd 	if (pktlen < minlen) {
519eb6f0de0SAdrian Chadd 		mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ;
520eb6f0de0SAdrian Chadd 		ndelim = MAX(mindelim, ndelim);
521eb6f0de0SAdrian Chadd 	}
522eb6f0de0SAdrian Chadd 
523eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
524eb6f0de0SAdrian Chadd 	    "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n",
525eb6f0de0SAdrian Chadd 	    __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim);
526eb6f0de0SAdrian Chadd 
527eb6f0de0SAdrian Chadd 	return ndelim;
528c969f82dSAdrian Chadd #undef	MS
529eb6f0de0SAdrian Chadd }
530eb6f0de0SAdrian Chadd 
531eb6f0de0SAdrian Chadd /*
532*707210ffSAdrian Chadd  * XXX TODO: put into net80211
533*707210ffSAdrian Chadd  */
534*707210ffSAdrian Chadd static int
535*707210ffSAdrian Chadd ath_rx_ampdu_to_byte(char a)
536*707210ffSAdrian Chadd {
537*707210ffSAdrian Chadd 	switch (a) {
538*707210ffSAdrian Chadd 	case IEEE80211_HTCAP_MAXRXAMPDU_16K:
539*707210ffSAdrian Chadd 		return 16384;
540*707210ffSAdrian Chadd 		break;
541*707210ffSAdrian Chadd 	case IEEE80211_HTCAP_MAXRXAMPDU_32K:
542*707210ffSAdrian Chadd 		return 32768;
543*707210ffSAdrian Chadd 		break;
544*707210ffSAdrian Chadd 	case IEEE80211_HTCAP_MAXRXAMPDU_64K:
545*707210ffSAdrian Chadd 		return 65536;
546*707210ffSAdrian Chadd 		break;
547*707210ffSAdrian Chadd 	case IEEE80211_HTCAP_MAXRXAMPDU_8K:
548*707210ffSAdrian Chadd 	default:
549*707210ffSAdrian Chadd 		return 8192;
550*707210ffSAdrian Chadd 		break;
551*707210ffSAdrian Chadd 	}
552*707210ffSAdrian Chadd }
553*707210ffSAdrian Chadd 
554*707210ffSAdrian Chadd /*
555eb6f0de0SAdrian Chadd  * Fetch the aggregation limit.
556eb6f0de0SAdrian Chadd  *
557eb6f0de0SAdrian Chadd  * It's the lowest of the four rate series 4ms frame length.
558c969f82dSAdrian Chadd  *
559c969f82dSAdrian Chadd  * Also take into account the hardware specific limits (8KiB on AR5416)
560c969f82dSAdrian Chadd  * and per-peer limits in non-STA mode.
561eb6f0de0SAdrian Chadd  */
562eb6f0de0SAdrian Chadd static int
563c969f82dSAdrian Chadd ath_get_aggr_limit(struct ath_softc *sc, struct ieee80211_node *ni,
564c969f82dSAdrian Chadd     struct ath_buf *bf)
565eb6f0de0SAdrian Chadd {
566*707210ffSAdrian Chadd 	struct ieee80211vap *vap = ni->ni_vap;
567*707210ffSAdrian Chadd 
568c969f82dSAdrian Chadd #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
5694a502c33SAdrian Chadd 	int amin = ATH_AGGR_MAXSIZE;
570eb6f0de0SAdrian Chadd 	int i;
571eb6f0de0SAdrian Chadd 
572c969f82dSAdrian Chadd 	/* Extract out the maximum configured driver A-MPDU limit */
5734a502c33SAdrian Chadd 	if (sc->sc_aggr_limit > 0 && sc->sc_aggr_limit < ATH_AGGR_MAXSIZE)
5744a502c33SAdrian Chadd 		amin = sc->sc_aggr_limit;
5754a502c33SAdrian Chadd 
576*707210ffSAdrian Chadd 	/* Check the vap configured transmit limit */
577*707210ffSAdrian Chadd 	amin = MIN(amin, ath_rx_ampdu_to_byte(vap->iv_ampdu_limit));
578*707210ffSAdrian Chadd 
579c969f82dSAdrian Chadd 	/*
580c969f82dSAdrian Chadd 	 * Check the HTCAP field for the maximum size the node has
581c969f82dSAdrian Chadd 	 * negotiated.  If it's smaller than what we have, cap it there.
582c969f82dSAdrian Chadd 	 */
583*707210ffSAdrian Chadd 	amin = MIN(amin, ath_rx_ampdu_to_byte(MS(ni->ni_htparam,
584*707210ffSAdrian Chadd 	    IEEE80211_HTCAP_MAXRXAMPDU)));
585c969f82dSAdrian Chadd 
586b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
587eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_rc[i].tries == 0)
588eb6f0de0SAdrian Chadd 			continue;
589eb6f0de0SAdrian Chadd 		amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen);
590eb6f0de0SAdrian Chadd 	}
591eb6f0de0SAdrian Chadd 
592eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: max frame len= %d\n",
593eb6f0de0SAdrian Chadd 	    __func__, amin);
594eb6f0de0SAdrian Chadd 
595eb6f0de0SAdrian Chadd 	return amin;
596c969f82dSAdrian Chadd #undef	MS
597eb6f0de0SAdrian Chadd }
5984b44f6f2SAdrian Chadd 
5994b44f6f2SAdrian Chadd /*
6004b44f6f2SAdrian Chadd  * Setup a 11n rate series structure
6014b44f6f2SAdrian Chadd  *
6024b44f6f2SAdrian Chadd  * This should be called for both legacy and MCS rates.
603eb6f0de0SAdrian Chadd  *
604de00e5cbSAdrian Chadd  * This uses the rate series stuf from ath_tx_rate_fill_rcflags().
605de00e5cbSAdrian Chadd  *
606eb6f0de0SAdrian Chadd  * It, along with ath_buf_set_rate, must be called -after- a burst
607eb6f0de0SAdrian Chadd  * or aggregate is setup.
6084b44f6f2SAdrian Chadd  */
6094b44f6f2SAdrian Chadd static void
6104b44f6f2SAdrian Chadd ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
611eb6f0de0SAdrian Chadd     struct ath_buf *bf, HAL_11N_RATE_SERIES *series)
6124b44f6f2SAdrian Chadd {
6134b44f6f2SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
6144b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
6154b44f6f2SAdrian Chadd 	HAL_BOOL shortPreamble = AH_FALSE;
6164b44f6f2SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
6174b44f6f2SAdrian Chadd 	int i;
618eb6f0de0SAdrian Chadd 	int pktlen;
619eb6f0de0SAdrian Chadd 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
6204b44f6f2SAdrian Chadd 
6214b44f6f2SAdrian Chadd 	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
6224b44f6f2SAdrian Chadd 	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
6234b44f6f2SAdrian Chadd 		shortPreamble = AH_TRUE;
6244b44f6f2SAdrian Chadd 
625eb6f0de0SAdrian Chadd 	/*
626eb6f0de0SAdrian Chadd 	 * If this is the first frame in an aggregate series,
627eb6f0de0SAdrian Chadd 	 * use the aggregate length.
628eb6f0de0SAdrian Chadd 	 */
629eb6f0de0SAdrian Chadd 	if (bf->bf_state.bfs_aggr)
630eb6f0de0SAdrian Chadd 		pktlen = bf->bf_state.bfs_al;
631eb6f0de0SAdrian Chadd 	else
632eb6f0de0SAdrian Chadd 		pktlen = bf->bf_state.bfs_pktlen;
633eb6f0de0SAdrian Chadd 
634eb6f0de0SAdrian Chadd 	/*
635eb6f0de0SAdrian Chadd 	 * XXX TODO: modify this routine to use the bfs_rc[x].flags
636eb6f0de0SAdrian Chadd 	 * XXX fields.
637eb6f0de0SAdrian Chadd 	 */
6384b44f6f2SAdrian Chadd 	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
639b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM;  i++) {
640146b49d8SAdrian Chadd 		/* Only set flags for actual TX attempts */
641eb6f0de0SAdrian Chadd 		if (rc[i].tries == 0)
642146b49d8SAdrian Chadd 			continue;
643146b49d8SAdrian Chadd 
644eb6f0de0SAdrian Chadd 		series[i].Tries = rc[i].tries;
645146b49d8SAdrian Chadd 
646146b49d8SAdrian Chadd 		/*
6474a502c33SAdrian Chadd 		 * XXX TODO: When the NIC is capable of three stream TX,
6484a502c33SAdrian Chadd 		 * transmit 1/2 stream rates on two streams.
6494a502c33SAdrian Chadd 		 *
6504a502c33SAdrian Chadd 		 * This reduces the power consumption of the NIC and
6514a502c33SAdrian Chadd 		 * keeps it within the PCIe slot power limits.
6524a502c33SAdrian Chadd 		 */
6536322256bSAdrian Chadd 		series[i].ChSel = sc->sc_cur_txchainmask;
654146b49d8SAdrian Chadd 
65556129906SAdrian Chadd 		/*
65656129906SAdrian Chadd 		 * Setup rate and TX power cap for this series.
65756129906SAdrian Chadd 		 */
65856129906SAdrian Chadd 		series[i].Rate = rt->info[rc[i].rix].rateCode;
65956129906SAdrian Chadd 		series[i].RateIndex = rc[i].rix;
660de00e5cbSAdrian Chadd 		series[i].tx_power_cap = rc[i].tx_power_cap;
66156129906SAdrian Chadd 
66256129906SAdrian Chadd 		/*
66356129906SAdrian Chadd 		 * Enable RTS/CTS as appropriate.
66456129906SAdrian Chadd 		 */
665de00e5cbSAdrian Chadd 		if (rc[i].flags & ATH_RC_RTSCTS_FLAG)
6664b44f6f2SAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
667146b49d8SAdrian Chadd 
668532f2442SAdrian Chadd 		/*
669de00e5cbSAdrian Chadd 		 * 11n rate? Update 11n flags.
670532f2442SAdrian Chadd 		 */
671de00e5cbSAdrian Chadd 		if (rc[i].flags & ATH_RC_HT_FLAG) {
672de00e5cbSAdrian Chadd 			if (rc[i].flags & ATH_RC_CW40_FLAG)
6734b44f6f2SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_2040;
6746246be6eSAdrian Chadd 
675de00e5cbSAdrian Chadd 			if (rc[i].flags & ATH_RC_SGI_FLAG)
6764b44f6f2SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_HALFGI;
6776246be6eSAdrian Chadd 
678de00e5cbSAdrian Chadd 			if (rc[i].flags & ATH_RC_STBC_FLAG)
6791a3a5607SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_STBC;
6801a3a5607SAdrian Chadd 		}
6816322256bSAdrian Chadd 
682b25c1f2aSAdrian Chadd 		/*
683f026d693SAdrian Chadd 		 * TODO: If we're all doing 11n rates then we can set LDPC.
684f026d693SAdrian Chadd 		 * If we've been asked to /do/ LDPC but we are handed a
685f026d693SAdrian Chadd 		 * legacy rate, then we should complain.  Loudly.
686f026d693SAdrian Chadd 		 */
687f026d693SAdrian Chadd 
688f026d693SAdrian Chadd 		/*
689b25c1f2aSAdrian Chadd 		 * PktDuration doesn't include slot, ACK, RTS, etc timing -
690b25c1f2aSAdrian Chadd 		 * it's just the packet duration
691b25c1f2aSAdrian Chadd 		 */
692de00e5cbSAdrian Chadd 		if (rc[i].flags & ATH_RC_HT_FLAG) {
6934b44f6f2SAdrian Chadd 			series[i].PktDuration =
6944b44f6f2SAdrian Chadd 			    ath_computedur_ht(pktlen
6959a97e25eSAdrian Chadd 				, series[i].Rate
696fce6d676SAdrian Chadd 				, HT_RC_2_STREAMS(series[i].Rate)
697fce6d676SAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_2040
698f449ab1cSAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
6994b44f6f2SAdrian Chadd 		} else {
7001198947aSAdrian Chadd 			if (shortPreamble)
701eb6f0de0SAdrian Chadd 				series[i].Rate |=
702eb6f0de0SAdrian Chadd 				    rt->info[rc[i].rix].shortPreamble;
7037ff1939dSAdrian Chadd 			/* XXX TODO: don't include SIFS */
7044b44f6f2SAdrian Chadd 			series[i].PktDuration = ath_hal_computetxtime(ah,
7057ff1939dSAdrian Chadd 			    rt, pktlen, rc[i].rix, shortPreamble, AH_TRUE);
7064b44f6f2SAdrian Chadd 		}
7074b44f6f2SAdrian Chadd 	}
7084b44f6f2SAdrian Chadd }
7094b44f6f2SAdrian Chadd 
71019b34b56SAdrian Chadd #ifdef	ATH_DEBUG
7114b44f6f2SAdrian Chadd static void
712b25c1f2aSAdrian Chadd ath_rateseries_print(struct ath_softc *sc, HAL_11N_RATE_SERIES *series)
7134b44f6f2SAdrian Chadd {
7144b44f6f2SAdrian Chadd 	int i;
715b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
716b25c1f2aSAdrian Chadd 		device_printf(sc->sc_dev ,"series %d: rate %x; tries %d; "
71764dbfc6dSAdrian Chadd 		    "pktDuration %d; chSel %d; txpowcap %d, rateFlags %x\n",
7184b44f6f2SAdrian Chadd 		    i,
7194b44f6f2SAdrian Chadd 		    series[i].Rate,
7204b44f6f2SAdrian Chadd 		    series[i].Tries,
7214b44f6f2SAdrian Chadd 		    series[i].PktDuration,
7224b44f6f2SAdrian Chadd 		    series[i].ChSel,
72364dbfc6dSAdrian Chadd 		    series[i].tx_power_cap,
7244b44f6f2SAdrian Chadd 		    series[i].RateFlags);
7254b44f6f2SAdrian Chadd 	}
7264b44f6f2SAdrian Chadd }
7274b44f6f2SAdrian Chadd #endif
7284b44f6f2SAdrian Chadd 
7294b44f6f2SAdrian Chadd /*
7304b44f6f2SAdrian Chadd  * Setup the 11n rate scenario and burst duration for the given TX descriptor
7314b44f6f2SAdrian Chadd  * list.
7324b44f6f2SAdrian Chadd  *
7334b44f6f2SAdrian Chadd  * This isn't useful for sending beacon frames, which has different needs
7344b44f6f2SAdrian Chadd  * wrt what's passed into the rate scenario function.
7354b44f6f2SAdrian Chadd  */
7364b44f6f2SAdrian Chadd void
737eb6f0de0SAdrian Chadd ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni,
738eb6f0de0SAdrian Chadd     struct ath_buf *bf)
7394b44f6f2SAdrian Chadd {
7404b44f6f2SAdrian Chadd 	HAL_11N_RATE_SERIES series[4];
7414b44f6f2SAdrian Chadd 	struct ath_desc *ds = bf->bf_desc;
7424b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
743eb6f0de0SAdrian Chadd 	int is_pspoll = (bf->bf_state.bfs_atype == HAL_PKT_TYPE_PSPOLL);
744eb6f0de0SAdrian Chadd 	int ctsrate = bf->bf_state.bfs_ctsrate;
745875a9451SAdrian Chadd 	int flags = bf->bf_state.bfs_txflags;
7464b44f6f2SAdrian Chadd 
7474b44f6f2SAdrian Chadd 	/* Setup rate scenario */
7484b44f6f2SAdrian Chadd 	memset(&series, 0, sizeof(series));
7494b44f6f2SAdrian Chadd 
750eb6f0de0SAdrian Chadd 	ath_rateseries_setup(sc, ni, bf, series);
7514b44f6f2SAdrian Chadd 
75219b34b56SAdrian Chadd #ifdef	ATH_DEBUG
75320b0b9eaSAdrian Chadd 	if (sc->sc_debug & ATH_DEBUG_XMIT)
754b25c1f2aSAdrian Chadd 		ath_rateseries_print(sc, series);
7552b5684a8SAdrian Chadd #endif
7562b5684a8SAdrian Chadd 
7574b44f6f2SAdrian Chadd 	/* Set rate scenario */
758b25c1f2aSAdrian Chadd 	/*
759b25c1f2aSAdrian Chadd 	 * Note: Don't allow hardware to override the duration on
760b25c1f2aSAdrian Chadd 	 * ps-poll packets.
761b25c1f2aSAdrian Chadd 	 */
7624b44f6f2SAdrian Chadd 	ath_hal_set11nratescenario(ah, ds,
763bf26df36SAdrian Chadd 	    !is_pspoll,	/* whether to override the duration or not */
7644b44f6f2SAdrian Chadd 	    ctsrate,	/* rts/cts rate */
7654b44f6f2SAdrian Chadd 	    series,	/* 11n rate series */
7664b44f6f2SAdrian Chadd 	    4,		/* number of series */
7674b44f6f2SAdrian Chadd 	    flags);
7684b44f6f2SAdrian Chadd 
7694b44f6f2SAdrian Chadd 	/* Set burst duration */
770eb6f0de0SAdrian Chadd 	/*
771eb6f0de0SAdrian Chadd 	 * This is only required when doing 11n burst, not aggregation
772eb6f0de0SAdrian Chadd 	 * ie, if there's a second frame in a RIFS or A-MPDU burst
773eb6f0de0SAdrian Chadd 	 * w/ >1 A-MPDU frame bursting back to back.
774eb6f0de0SAdrian Chadd 	 * Normal A-MPDU doesn't do bursting -between- aggregates.
775eb6f0de0SAdrian Chadd 	 *
776eb6f0de0SAdrian Chadd 	 * .. and it's highly likely this won't ever be implemented
777eb6f0de0SAdrian Chadd 	 */
7784b44f6f2SAdrian Chadd 	//ath_hal_set11nburstduration(ah, ds, 8192);
7794b44f6f2SAdrian Chadd }
780eb6f0de0SAdrian Chadd 
781eb6f0de0SAdrian Chadd /*
782eb6f0de0SAdrian Chadd  * Form an aggregate packet list.
783eb6f0de0SAdrian Chadd  *
784eb6f0de0SAdrian Chadd  * This function enforces the aggregate restrictions/requirements.
785eb6f0de0SAdrian Chadd  *
786eb6f0de0SAdrian Chadd  * These are:
787eb6f0de0SAdrian Chadd  *
788eb6f0de0SAdrian Chadd  * + The aggregate size maximum (64k for AR9160 and later, 8K for
789eb6f0de0SAdrian Chadd  *   AR5416 when doing RTS frame protection.)
790eb6f0de0SAdrian Chadd  * + Maximum number of sub-frames for an aggregate
791eb6f0de0SAdrian Chadd  * + The aggregate delimiter size, giving MACs time to do whatever is
792eb6f0de0SAdrian Chadd  *   needed before each frame
793eb6f0de0SAdrian Chadd  * + Enforce the BAW limit
794eb6f0de0SAdrian Chadd  *
795eb6f0de0SAdrian Chadd  * Each descriptor queued should have the DMA setup.
796eb6f0de0SAdrian Chadd  * The rate series, descriptor setup, linking, etc is all done
797eb6f0de0SAdrian Chadd  * externally. This routine simply chains them together.
798eb6f0de0SAdrian Chadd  * ath_tx_setds_11n() will take care of configuring the per-
799eb6f0de0SAdrian Chadd  * descriptor setup, and ath_buf_set_rate() will configure the
800eb6f0de0SAdrian Chadd  * rate control.
801eb6f0de0SAdrian Chadd  *
802b25c1f2aSAdrian Chadd  * The TID lock is required for the entirety of this function.
803b25c1f2aSAdrian Chadd  *
804b25c1f2aSAdrian Chadd  * If some code in another thread adds to the head of this
805eb6f0de0SAdrian Chadd  * list, very strange behaviour will occur. Since retransmission is the
806eb6f0de0SAdrian Chadd  * only reason this will occur, and this routine is designed to be called
807eb6f0de0SAdrian Chadd  * from within the scheduler task, it won't ever clash with the completion
808eb6f0de0SAdrian Chadd  * task.
809eb6f0de0SAdrian Chadd  *
810eb6f0de0SAdrian Chadd  * So if you want to call this from an upper layer context (eg, to direct-
811eb6f0de0SAdrian Chadd  * dispatch aggregate frames to the hardware), please keep this in mind.
812eb6f0de0SAdrian Chadd  */
813eb6f0de0SAdrian Chadd ATH_AGGR_STATUS
814b25c1f2aSAdrian Chadd ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an,
815b25c1f2aSAdrian Chadd     struct ath_tid *tid, ath_bufhead *bf_q)
816eb6f0de0SAdrian Chadd {
817a108d2d6SAdrian Chadd 	//struct ieee80211_node *ni = &an->an_node;
818eb6f0de0SAdrian Chadd 	struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
819eb6f0de0SAdrian Chadd 	int nframes = 0;
820eb6f0de0SAdrian Chadd 	uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw;
821eb6f0de0SAdrian Chadd 	struct ieee80211_tx_ampdu *tap;
822eb6f0de0SAdrian Chadd 	int status = ATH_AGGR_DONE;
823eb6f0de0SAdrian Chadd 	int prev_frames = 0;	/* XXX for AR5416 burst, not done here */
824eb6f0de0SAdrian Chadd 	int prev_al = 0;	/* XXX also for AR5416 burst */
825eb6f0de0SAdrian Chadd 
826375307d4SAdrian Chadd 	ATH_TX_LOCK_ASSERT(sc);
827eb6f0de0SAdrian Chadd 
828eb6f0de0SAdrian Chadd 	tap = ath_tx_get_tx_tid(an, tid->tid);
829eb6f0de0SAdrian Chadd 	if (tap == NULL) {
830eb6f0de0SAdrian Chadd 		status = ATH_AGGR_ERROR;
831eb6f0de0SAdrian Chadd 		goto finish;
832eb6f0de0SAdrian Chadd 	}
833eb6f0de0SAdrian Chadd 
834eb6f0de0SAdrian Chadd 	h_baw = tap->txa_wnd / 2;
835eb6f0de0SAdrian Chadd 
836eb6f0de0SAdrian Chadd 	for (;;) {
8373e6cc97fSAdrian Chadd 		bf = ATH_TID_FIRST(tid);
838eb6f0de0SAdrian Chadd 		if (bf_first == NULL)
839eb6f0de0SAdrian Chadd 			bf_first = bf;
840eb6f0de0SAdrian Chadd 		if (bf == NULL) {
841eb6f0de0SAdrian Chadd 			status = ATH_AGGR_DONE;
842eb6f0de0SAdrian Chadd 			break;
843eb6f0de0SAdrian Chadd 		} else {
844eb6f0de0SAdrian Chadd 			/*
845eb6f0de0SAdrian Chadd 			 * It's the first frame;
846eb6f0de0SAdrian Chadd 			 * set the aggregation limit based on the
847eb6f0de0SAdrian Chadd 			 * rate control decision that has been made.
848eb6f0de0SAdrian Chadd 			 */
849c969f82dSAdrian Chadd 			aggr_limit = ath_get_aggr_limit(sc, &an->an_node,
850c969f82dSAdrian Chadd 			    bf_first);
851eb6f0de0SAdrian Chadd 		}
852eb6f0de0SAdrian Chadd 
853eb6f0de0SAdrian Chadd 		/* Set this early just so things don't get confused */
854eb6f0de0SAdrian Chadd 		bf->bf_next = NULL;
855eb6f0de0SAdrian Chadd 
856eb6f0de0SAdrian Chadd 		/*
857eb6f0de0SAdrian Chadd 		 * If the frame doesn't have a sequence number that we're
858eb6f0de0SAdrian Chadd 		 * tracking in the BAW (eg NULL QOS data frame), we can't
859eb6f0de0SAdrian Chadd 		 * aggregate it. Stop the aggregation process; the sender
860eb6f0de0SAdrian Chadd 		 * can then TX what's in the list thus far and then
861eb6f0de0SAdrian Chadd 		 * TX the frame individually.
862eb6f0de0SAdrian Chadd 		 */
863eb6f0de0SAdrian Chadd 		if (! bf->bf_state.bfs_dobaw) {
864eb6f0de0SAdrian Chadd 			status = ATH_AGGR_NONAGGR;
865eb6f0de0SAdrian Chadd 			break;
866eb6f0de0SAdrian Chadd 		}
867eb6f0de0SAdrian Chadd 
868eb6f0de0SAdrian Chadd 		/*
869eb6f0de0SAdrian Chadd 		 * If any of the rates are non-HT, this packet
870eb6f0de0SAdrian Chadd 		 * can't be aggregated.
871eb6f0de0SAdrian Chadd 		 * XXX TODO: add a bf_state flag which gets marked
872eb6f0de0SAdrian Chadd 		 * if any active rate is non-HT.
873eb6f0de0SAdrian Chadd 		 */
874eb6f0de0SAdrian Chadd 
875eb6f0de0SAdrian Chadd 		/*
876eb6f0de0SAdrian Chadd 		 * do not exceed aggregation limit
877eb6f0de0SAdrian Chadd 		 */
878eb6f0de0SAdrian Chadd 		al_delta = ATH_AGGR_DELIM_SZ + bf->bf_state.bfs_pktlen;
879eb6f0de0SAdrian Chadd 		if (nframes &&
880eb6f0de0SAdrian Chadd 		    (aggr_limit < (al + bpad + al_delta + prev_al))) {
881eb6f0de0SAdrian Chadd 			status = ATH_AGGR_LIMITED;
882eb6f0de0SAdrian Chadd 			break;
883eb6f0de0SAdrian Chadd 		}
884eb6f0de0SAdrian Chadd 
885eb6f0de0SAdrian Chadd 		/*
886045bc788SAdrian Chadd 		 * If RTS/CTS is set on the first frame, enforce
887045bc788SAdrian Chadd 		 * the RTS aggregate limit.
888045bc788SAdrian Chadd 		 */
889045bc788SAdrian Chadd 		if (bf_first->bf_state.bfs_txflags &
890045bc788SAdrian Chadd 		    (HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA)) {
891045bc788SAdrian Chadd 			if (nframes &&
892045bc788SAdrian Chadd 			   (sc->sc_rts_aggr_limit <
893045bc788SAdrian Chadd 			     (al + bpad + al_delta + prev_al))) {
894045bc788SAdrian Chadd 				status = ATH_AGGR_8K_LIMITED;
895045bc788SAdrian Chadd 				break;
896045bc788SAdrian Chadd 			}
897045bc788SAdrian Chadd 		}
898045bc788SAdrian Chadd 
899045bc788SAdrian Chadd 		/*
900eb6f0de0SAdrian Chadd 		 * Do not exceed subframe limit.
901eb6f0de0SAdrian Chadd 		 */
902eb6f0de0SAdrian Chadd 		if ((nframes + prev_frames) >= MIN((h_baw),
903eb6f0de0SAdrian Chadd 		    IEEE80211_AMPDU_SUBFRAME_DEFAULT)) {
904eb6f0de0SAdrian Chadd 			status = ATH_AGGR_LIMITED;
905eb6f0de0SAdrian Chadd 			break;
906eb6f0de0SAdrian Chadd 		}
907eb6f0de0SAdrian Chadd 
908eb6f0de0SAdrian Chadd 		/*
909045bc788SAdrian Chadd 		 * If the current frame has an RTS/CTS configuration
910781e7eafSAdrian Chadd 		 * that differs from the first frame, override the
911781e7eafSAdrian Chadd 		 * subsequent frame with this config.
912045bc788SAdrian Chadd 		 */
913d03904f1SAdrian Chadd 		if (bf != bf_first) {
914781e7eafSAdrian Chadd 			bf->bf_state.bfs_txflags &=
91576af1a93SAdrian Chadd 			    ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
916781e7eafSAdrian Chadd 			bf->bf_state.bfs_txflags |=
917781e7eafSAdrian Chadd 			    bf_first->bf_state.bfs_txflags &
918781e7eafSAdrian Chadd 			    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
919d03904f1SAdrian Chadd 		}
920045bc788SAdrian Chadd 
921045bc788SAdrian Chadd 		/*
9220b96ef63SAdrian Chadd 		 * If the packet has a sequence number, do not
9230b96ef63SAdrian Chadd 		 * step outside of the block-ack window.
9240b96ef63SAdrian Chadd 		 */
9250b96ef63SAdrian Chadd 		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
9260b96ef63SAdrian Chadd 		    SEQNO(bf->bf_state.bfs_seqno))) {
9270b96ef63SAdrian Chadd 			status = ATH_AGGR_BAW_CLOSED;
9280b96ef63SAdrian Chadd 			break;
9290b96ef63SAdrian Chadd 		}
9300b96ef63SAdrian Chadd 
9310b96ef63SAdrian Chadd 		/*
932eb6f0de0SAdrian Chadd 		 * this packet is part of an aggregate.
933eb6f0de0SAdrian Chadd 		 */
9343e6cc97fSAdrian Chadd 		ATH_TID_REMOVE(tid, bf, bf_list);
935eb6f0de0SAdrian Chadd 
936eb6f0de0SAdrian Chadd 		/* The TID lock is required for the BAW update */
937eb6f0de0SAdrian Chadd 		ath_tx_addto_baw(sc, an, tid, bf);
938eb6f0de0SAdrian Chadd 		bf->bf_state.bfs_addedbaw = 1;
939eb6f0de0SAdrian Chadd 
940eb6f0de0SAdrian Chadd 		/*
941eb6f0de0SAdrian Chadd 		 * XXX enforce ACK for aggregate frames (this needs to be
942eb6f0de0SAdrian Chadd 		 * XXX handled more gracefully?
943eb6f0de0SAdrian Chadd 		 */
944875a9451SAdrian Chadd 		if (bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) {
945eb6f0de0SAdrian Chadd 			device_printf(sc->sc_dev,
946eb6f0de0SAdrian Chadd 			    "%s: HAL_TXDESC_NOACK set for an aggregate frame?\n",
947eb6f0de0SAdrian Chadd 			    __func__);
948875a9451SAdrian Chadd 			bf->bf_state.bfs_txflags &= (~HAL_TXDESC_NOACK);
949eb6f0de0SAdrian Chadd 		}
950eb6f0de0SAdrian Chadd 
951eb6f0de0SAdrian Chadd 		/*
952eb6f0de0SAdrian Chadd 		 * Add the now owned buffer (which isn't
953eb6f0de0SAdrian Chadd 		 * on the software TXQ any longer) to our
954eb6f0de0SAdrian Chadd 		 * aggregate frame list.
955eb6f0de0SAdrian Chadd 		 */
956eb6f0de0SAdrian Chadd 		TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
957eb6f0de0SAdrian Chadd 		nframes ++;
958eb6f0de0SAdrian Chadd 
959eb6f0de0SAdrian Chadd 		/* Completion handler */
960eb6f0de0SAdrian Chadd 		bf->bf_comp = ath_tx_aggr_comp;
961eb6f0de0SAdrian Chadd 
962eb6f0de0SAdrian Chadd 		/*
963eb6f0de0SAdrian Chadd 		 * add padding for previous frame to aggregation length
964eb6f0de0SAdrian Chadd 		 */
965eb6f0de0SAdrian Chadd 		al += bpad + al_delta;
966eb6f0de0SAdrian Chadd 
967eb6f0de0SAdrian Chadd 		/*
968eb6f0de0SAdrian Chadd 		 * Calculate delimiters needed for the current frame
969eb6f0de0SAdrian Chadd 		 */
970eb6f0de0SAdrian Chadd 		bf->bf_state.bfs_ndelim =
971eb6f0de0SAdrian Chadd 		    ath_compute_num_delims(sc, bf_first,
972eb6f0de0SAdrian Chadd 		    bf->bf_state.bfs_pktlen);
973eb6f0de0SAdrian Chadd 
974eb6f0de0SAdrian Chadd 		/*
975eb6f0de0SAdrian Chadd 		 * Calculate the padding needed from this set of delimiters,
976eb6f0de0SAdrian Chadd 		 * used when calculating if the next frame will fit in
977eb6f0de0SAdrian Chadd 		 * the aggregate.
978eb6f0de0SAdrian Chadd 		 */
979eb6f0de0SAdrian Chadd 		bpad = PADBYTES(al_delta) + (bf->bf_state.bfs_ndelim << 2);
980eb6f0de0SAdrian Chadd 
981eb6f0de0SAdrian Chadd 		/*
982eb6f0de0SAdrian Chadd 		 * Chain the buffers together
983eb6f0de0SAdrian Chadd 		 */
984eb6f0de0SAdrian Chadd 		if (bf_prev)
985eb6f0de0SAdrian Chadd 			bf_prev->bf_next = bf;
986eb6f0de0SAdrian Chadd 		bf_prev = bf;
987eb6f0de0SAdrian Chadd 
988eb6f0de0SAdrian Chadd 		/*
98922a3aee6SAdrian Chadd 		 * If we're leaking frames, just return at this point;
99022a3aee6SAdrian Chadd 		 * we've queued a single frame and we don't want to add
99122a3aee6SAdrian Chadd 		 * any more.
992eb6f0de0SAdrian Chadd 		 */
99322a3aee6SAdrian Chadd 		if (tid->an->an_leak_count) {
99422a3aee6SAdrian Chadd 			status = ATH_AGGR_LEAK_CLOSED;
99522a3aee6SAdrian Chadd 			break;
99622a3aee6SAdrian Chadd 		}
997eb6f0de0SAdrian Chadd 
998eb6f0de0SAdrian Chadd #if 0
999eb6f0de0SAdrian Chadd 		/*
1000eb6f0de0SAdrian Chadd 		 * terminate aggregation on a small packet boundary
1001eb6f0de0SAdrian Chadd 		 */
1002eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_pktlen < ATH_AGGR_MINPLEN) {
1003eb6f0de0SAdrian Chadd 			status = ATH_AGGR_SHORTPKT;
1004eb6f0de0SAdrian Chadd 			break;
1005eb6f0de0SAdrian Chadd 		}
1006eb6f0de0SAdrian Chadd #endif
1007eb6f0de0SAdrian Chadd 
1008eb6f0de0SAdrian Chadd 	}
1009eb6f0de0SAdrian Chadd 
1010eb6f0de0SAdrian Chadd finish:
1011eb6f0de0SAdrian Chadd 	/*
1012eb6f0de0SAdrian Chadd 	 * Just in case the list was empty when we tried to
1013eb6f0de0SAdrian Chadd 	 * dequeue a packet ..
1014eb6f0de0SAdrian Chadd 	 */
1015eb6f0de0SAdrian Chadd 	if (bf_first) {
1016eb6f0de0SAdrian Chadd 		bf_first->bf_state.bfs_al = al;
1017eb6f0de0SAdrian Chadd 		bf_first->bf_state.bfs_nframes = nframes;
1018eb6f0de0SAdrian Chadd 	}
1019eb6f0de0SAdrian Chadd 	return status;
1020eb6f0de0SAdrian Chadd }
1021