xref: /freebsd/sys/dev/ath/if_ath_tx_ht.c (revision cce634440284f96a81443c77edc4893decda1f0c)
14b44f6f2SAdrian Chadd /*-
2718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3718cf2ccSPedro F. Giffuni  *
44b44f6f2SAdrian Chadd  * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
54b44f6f2SAdrian Chadd  * All rights reserved.
64b44f6f2SAdrian Chadd  *
74b44f6f2SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
84b44f6f2SAdrian Chadd  * modification, are permitted provided that the following conditions
94b44f6f2SAdrian Chadd  * are met:
104b44f6f2SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
114b44f6f2SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
124b44f6f2SAdrian Chadd  *    without modification.
134b44f6f2SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
144b44f6f2SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
154b44f6f2SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
164b44f6f2SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
174b44f6f2SAdrian Chadd  *
184b44f6f2SAdrian Chadd  * NO WARRANTY
194b44f6f2SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
204b44f6f2SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
214b44f6f2SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
224b44f6f2SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
234b44f6f2SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
244b44f6f2SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
254b44f6f2SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
264b44f6f2SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
274b44f6f2SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
284b44f6f2SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
294b44f6f2SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
304b44f6f2SAdrian Chadd  */
314b44f6f2SAdrian Chadd 
324b44f6f2SAdrian Chadd #include <sys/cdefs.h>
334b44f6f2SAdrian Chadd __FBSDID("$FreeBSD$");
344b44f6f2SAdrian Chadd 
354b44f6f2SAdrian Chadd #include "opt_inet.h"
364b44f6f2SAdrian Chadd #include "opt_ath.h"
374b44f6f2SAdrian Chadd #include "opt_wlan.h"
384b44f6f2SAdrian Chadd 
394b44f6f2SAdrian Chadd #include <sys/param.h>
404b44f6f2SAdrian Chadd #include <sys/systm.h>
414b44f6f2SAdrian Chadd #include <sys/sysctl.h>
424b44f6f2SAdrian Chadd #include <sys/mbuf.h>
434b44f6f2SAdrian Chadd #include <sys/malloc.h>
444b44f6f2SAdrian Chadd #include <sys/lock.h>
454b44f6f2SAdrian Chadd #include <sys/mutex.h>
464b44f6f2SAdrian Chadd #include <sys/kernel.h>
474b44f6f2SAdrian Chadd #include <sys/socket.h>
484b44f6f2SAdrian Chadd #include <sys/sockio.h>
494b44f6f2SAdrian Chadd #include <sys/errno.h>
504b44f6f2SAdrian Chadd #include <sys/callout.h>
514b44f6f2SAdrian Chadd #include <sys/bus.h>
524b44f6f2SAdrian Chadd #include <sys/endian.h>
534b44f6f2SAdrian Chadd #include <sys/kthread.h>
544b44f6f2SAdrian Chadd #include <sys/taskqueue.h>
554b44f6f2SAdrian Chadd #include <sys/priv.h>
564b44f6f2SAdrian Chadd 
574b44f6f2SAdrian Chadd #include <machine/bus.h>
584b44f6f2SAdrian Chadd 
594b44f6f2SAdrian Chadd #include <net/if.h>
604b44f6f2SAdrian Chadd #include <net/if_dl.h>
614b44f6f2SAdrian Chadd #include <net/if_media.h>
624b44f6f2SAdrian Chadd #include <net/if_types.h>
634b44f6f2SAdrian Chadd #include <net/if_arp.h>
644b44f6f2SAdrian Chadd #include <net/ethernet.h>
654b44f6f2SAdrian Chadd #include <net/if_llc.h>
664b44f6f2SAdrian Chadd 
674b44f6f2SAdrian Chadd #include <net80211/ieee80211_var.h>
684b44f6f2SAdrian Chadd #include <net80211/ieee80211_regdomain.h>
694b44f6f2SAdrian Chadd #ifdef IEEE80211_SUPPORT_SUPERG
704b44f6f2SAdrian Chadd #include <net80211/ieee80211_superg.h>
714b44f6f2SAdrian Chadd #endif
724b44f6f2SAdrian Chadd #ifdef IEEE80211_SUPPORT_TDMA
734b44f6f2SAdrian Chadd #include <net80211/ieee80211_tdma.h>
744b44f6f2SAdrian Chadd #endif
754b44f6f2SAdrian Chadd 
764b44f6f2SAdrian Chadd #include <net/bpf.h>
774b44f6f2SAdrian Chadd 
784b44f6f2SAdrian Chadd #ifdef INET
794b44f6f2SAdrian Chadd #include <netinet/in.h>
804b44f6f2SAdrian Chadd #include <netinet/if_ether.h>
814b44f6f2SAdrian Chadd #endif
824b44f6f2SAdrian Chadd 
834b44f6f2SAdrian Chadd #include <dev/ath/if_athvar.h>
844b44f6f2SAdrian Chadd #include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
854b44f6f2SAdrian Chadd #include <dev/ath/ath_hal/ah_diagcodes.h>
864b44f6f2SAdrian Chadd 
874b44f6f2SAdrian Chadd #ifdef ATH_TX99_DIAG
884b44f6f2SAdrian Chadd #include <dev/ath/ath_tx99/ath_tx99.h>
894b44f6f2SAdrian Chadd #endif
904b44f6f2SAdrian Chadd 
91eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_tx.h>		/* XXX for some support functions */
924b44f6f2SAdrian Chadd #include <dev/ath/if_ath_tx_ht.h>
93eb6f0de0SAdrian Chadd #include <dev/ath/if_athrate.h>
94eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_debug.h>
95eb6f0de0SAdrian Chadd 
96eb6f0de0SAdrian Chadd /*
97eb6f0de0SAdrian Chadd  * XXX net80211?
98eb6f0de0SAdrian Chadd  */
99eb6f0de0SAdrian Chadd #define	IEEE80211_AMPDU_SUBFRAME_DEFAULT		32
100eb6f0de0SAdrian Chadd 
101eb6f0de0SAdrian Chadd #define	ATH_AGGR_DELIM_SZ	4	/* delimiter size */
102eb6f0de0SAdrian Chadd #define	ATH_AGGR_MINPLEN	256	/* in bytes, minimum packet length */
103b25c1f2aSAdrian Chadd /* number of delimiters for encryption padding */
104b25c1f2aSAdrian Chadd #define	ATH_AGGR_ENCRYPTDELIM	10
105eb6f0de0SAdrian Chadd 
106eb6f0de0SAdrian Chadd /*
107eb6f0de0SAdrian Chadd  * returns delimiter padding required given the packet length
108eb6f0de0SAdrian Chadd  */
109eb6f0de0SAdrian Chadd #define	ATH_AGGR_GET_NDELIM(_len)					\
110eb6f0de0SAdrian Chadd 	    (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?	\
111eb6f0de0SAdrian Chadd 	    (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
112eb6f0de0SAdrian Chadd 
113eb6f0de0SAdrian Chadd #define	PADBYTES(_len)		((4 - ((_len) % 4)) % 4)
114eb6f0de0SAdrian Chadd 
115eb6f0de0SAdrian Chadd int ath_max_4ms_framelen[4][32] = {
116eb6f0de0SAdrian Chadd 	[MCS_HT20] = {
117eb6f0de0SAdrian Chadd 		3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
118eb6f0de0SAdrian Chadd 		6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
119eb6f0de0SAdrian Chadd 		9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
120eb6f0de0SAdrian Chadd 		12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
121eb6f0de0SAdrian Chadd 	},
122eb6f0de0SAdrian Chadd 	[MCS_HT20_SGI] = {
123eb6f0de0SAdrian Chadd 		3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
124eb6f0de0SAdrian Chadd 		7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
125eb6f0de0SAdrian Chadd 		10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
126eb6f0de0SAdrian Chadd 		14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
127eb6f0de0SAdrian Chadd 	},
128eb6f0de0SAdrian Chadd 	[MCS_HT40] = {
129eb6f0de0SAdrian Chadd 		6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
130eb6f0de0SAdrian Chadd 		13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
131eb6f0de0SAdrian Chadd 		20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
132eb6f0de0SAdrian Chadd 		26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
133eb6f0de0SAdrian Chadd 	},
134eb6f0de0SAdrian Chadd 	[MCS_HT40_SGI] = {
135eb6f0de0SAdrian Chadd 		7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
136eb6f0de0SAdrian Chadd 		14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
137eb6f0de0SAdrian Chadd 		22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
138eb6f0de0SAdrian Chadd 		29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
139eb6f0de0SAdrian Chadd 	}
140eb6f0de0SAdrian Chadd };
141eb6f0de0SAdrian Chadd 
142eb6f0de0SAdrian Chadd /*
143eb6f0de0SAdrian Chadd  * XXX should be in net80211
144eb6f0de0SAdrian Chadd  */
145eb6f0de0SAdrian Chadd static int ieee80211_mpdudensity_map[] = {
146eb6f0de0SAdrian Chadd 	0,		/* IEEE80211_HTCAP_MPDUDENSITY_NA */
147eb6f0de0SAdrian Chadd 	25,		/* IEEE80211_HTCAP_MPDUDENSITY_025 */
148eb6f0de0SAdrian Chadd 	50,		/* IEEE80211_HTCAP_MPDUDENSITY_05 */
149eb6f0de0SAdrian Chadd 	100,		/* IEEE80211_HTCAP_MPDUDENSITY_1 */
150eb6f0de0SAdrian Chadd 	200,		/* IEEE80211_HTCAP_MPDUDENSITY_2 */
151eb6f0de0SAdrian Chadd 	400,		/* IEEE80211_HTCAP_MPDUDENSITY_4 */
152eb6f0de0SAdrian Chadd 	800,		/* IEEE80211_HTCAP_MPDUDENSITY_8 */
153eb6f0de0SAdrian Chadd 	1600,		/* IEEE80211_HTCAP_MPDUDENSITY_16 */
154eb6f0de0SAdrian Chadd };
155eb6f0de0SAdrian Chadd 
156eb6f0de0SAdrian Chadd /*
157eb6f0de0SAdrian Chadd  * XXX should be in the HAL/net80211 ?
158eb6f0de0SAdrian Chadd  */
159eb6f0de0SAdrian Chadd #define	BITS_PER_BYTE		8
160eb6f0de0SAdrian Chadd #define	OFDM_PLCP_BITS		22
161eb6f0de0SAdrian Chadd #define	HT_RC_2_MCS(_rc)	((_rc) & 0x7f)
162eb6f0de0SAdrian Chadd #define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
163eb6f0de0SAdrian Chadd #define	L_STF			8
164eb6f0de0SAdrian Chadd #define	L_LTF			8
165eb6f0de0SAdrian Chadd #define	L_SIG			4
166eb6f0de0SAdrian Chadd #define	HT_SIG			8
167eb6f0de0SAdrian Chadd #define	HT_STF			4
168eb6f0de0SAdrian Chadd #define	HT_LTF(_ns)		(4 * (_ns))
169eb6f0de0SAdrian Chadd #define	SYMBOL_TIME(_ns)	((_ns) << 2)		// ns * 4 us
170eb6f0de0SAdrian Chadd #define	SYMBOL_TIME_HALFGI(_ns)	(((_ns) * 18 + 4) / 5)	// ns * 3.6 us
171eb6f0de0SAdrian Chadd #define	NUM_SYMBOLS_PER_USEC(_usec)	(_usec >> 2)
172eb6f0de0SAdrian Chadd #define	NUM_SYMBOLS_PER_USEC_HALFGI(_usec)	(((_usec*5)-4)/18)
173eb6f0de0SAdrian Chadd #define	IS_HT_RATE(_rate)	((_rate) & 0x80)
174eb6f0de0SAdrian Chadd 
175eb6f0de0SAdrian Chadd const uint32_t bits_per_symbol[][2] = {
176eb6f0de0SAdrian Chadd     /* 20MHz 40MHz */
177eb6f0de0SAdrian Chadd     {    26,   54 },     //  0: BPSK
178eb6f0de0SAdrian Chadd     {    52,  108 },     //  1: QPSK 1/2
179eb6f0de0SAdrian Chadd     {    78,  162 },     //  2: QPSK 3/4
180eb6f0de0SAdrian Chadd     {   104,  216 },     //  3: 16-QAM 1/2
181eb6f0de0SAdrian Chadd     {   156,  324 },     //  4: 16-QAM 3/4
182eb6f0de0SAdrian Chadd     {   208,  432 },     //  5: 64-QAM 2/3
183eb6f0de0SAdrian Chadd     {   234,  486 },     //  6: 64-QAM 3/4
184eb6f0de0SAdrian Chadd     {   260,  540 },     //  7: 64-QAM 5/6
185eb6f0de0SAdrian Chadd     {    52,  108 },     //  8: BPSK
186eb6f0de0SAdrian Chadd     {   104,  216 },     //  9: QPSK 1/2
187eb6f0de0SAdrian Chadd     {   156,  324 },     // 10: QPSK 3/4
188eb6f0de0SAdrian Chadd     {   208,  432 },     // 11: 16-QAM 1/2
189eb6f0de0SAdrian Chadd     {   312,  648 },     // 12: 16-QAM 3/4
190eb6f0de0SAdrian Chadd     {   416,  864 },     // 13: 64-QAM 2/3
191eb6f0de0SAdrian Chadd     {   468,  972 },     // 14: 64-QAM 3/4
192eb6f0de0SAdrian Chadd     {   520, 1080 },     // 15: 64-QAM 5/6
193eb6f0de0SAdrian Chadd     {    78,  162 },     // 16: BPSK
194eb6f0de0SAdrian Chadd     {   156,  324 },     // 17: QPSK 1/2
195eb6f0de0SAdrian Chadd     {   234,  486 },     // 18: QPSK 3/4
196eb6f0de0SAdrian Chadd     {   312,  648 },     // 19: 16-QAM 1/2
197eb6f0de0SAdrian Chadd     {   468,  972 },     // 20: 16-QAM 3/4
198eb6f0de0SAdrian Chadd     {   624, 1296 },     // 21: 64-QAM 2/3
199eb6f0de0SAdrian Chadd     {   702, 1458 },     // 22: 64-QAM 3/4
200eb6f0de0SAdrian Chadd     {   780, 1620 },     // 23: 64-QAM 5/6
201eb6f0de0SAdrian Chadd     {   104,  216 },     // 24: BPSK
202eb6f0de0SAdrian Chadd     {   208,  432 },     // 25: QPSK 1/2
203eb6f0de0SAdrian Chadd     {   312,  648 },     // 26: QPSK 3/4
204eb6f0de0SAdrian Chadd     {   416,  864 },     // 27: 16-QAM 1/2
205eb6f0de0SAdrian Chadd     {   624, 1296 },     // 28: 16-QAM 3/4
206eb6f0de0SAdrian Chadd     {   832, 1728 },     // 29: 64-QAM 2/3
207eb6f0de0SAdrian Chadd     {   936, 1944 },     // 30: 64-QAM 3/4
208eb6f0de0SAdrian Chadd     {  1040, 2160 },     // 31: 64-QAM 5/6
209eb6f0de0SAdrian Chadd };
210eb6f0de0SAdrian Chadd 
211eb6f0de0SAdrian Chadd /*
212eb6f0de0SAdrian Chadd  * Fill in the rate array information based on the current
213eb6f0de0SAdrian Chadd  * node configuration and the choices made by the rate
214eb6f0de0SAdrian Chadd  * selection code and ath_buf setup code.
215eb6f0de0SAdrian Chadd  *
216eb6f0de0SAdrian Chadd  * Later on, this may end up also being made by the
217eb6f0de0SAdrian Chadd  * rate control code, but for now it can live here.
218eb6f0de0SAdrian Chadd  *
219eb6f0de0SAdrian Chadd  * This needs to be called just before the packet is
220eb6f0de0SAdrian Chadd  * queued to the software queue or hardware queue,
221eb6f0de0SAdrian Chadd  * so all of the needed fields in bf_state are setup.
222eb6f0de0SAdrian Chadd  */
223eb6f0de0SAdrian Chadd void
224eb6f0de0SAdrian Chadd ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
225eb6f0de0SAdrian Chadd {
226eb6f0de0SAdrian Chadd 	struct ieee80211_node *ni = bf->bf_node;
227a7038bd1SAdrian Chadd 	struct ieee80211vap *vap = ni->ni_vap;
228eb6f0de0SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
229eb6f0de0SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
230eb6f0de0SAdrian Chadd 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
231eb6f0de0SAdrian Chadd 	uint8_t rate;
232eb6f0de0SAdrian Chadd 	int i;
233ce725c8eSAdrian Chadd 	int do_ldpc;
234ce725c8eSAdrian Chadd 	int do_stbc;
235ce725c8eSAdrian Chadd 
236ce725c8eSAdrian Chadd 	/*
237ce725c8eSAdrian Chadd 	 * We only do LDPC if the rate is 11n, both we and the
238ce725c8eSAdrian Chadd 	 * receiver support LDPC and it's enabled.
239ce725c8eSAdrian Chadd 	 *
240ce725c8eSAdrian Chadd 	 * It's a global flag, not a per-try flag, so we clear
241ce725c8eSAdrian Chadd 	 * it if any of the rate entries aren't 11n.
242ce725c8eSAdrian Chadd 	 */
243a0391187SAdrian Chadd 	do_ldpc = 0;
2448f1e1139SAndriy Voskoboinyk 	if ((ni->ni_vap->iv_flags_ht & IEEE80211_FHT_LDPC_TX) &&
245ce725c8eSAdrian Chadd 	    (ni->ni_htcap & IEEE80211_HTCAP_LDPC))
246ce725c8eSAdrian Chadd 		do_ldpc = 1;
247ffa25becSAdrian Chadd 
248ffa25becSAdrian Chadd 	/*
249ffa25becSAdrian Chadd 	 * The 11n duration calculation doesn't know about LDPC,
250ffa25becSAdrian Chadd 	 * so don't enable it for positioning.
251ffa25becSAdrian Chadd 	 */
252ffa25becSAdrian Chadd 	if (bf->bf_flags & ATH_BUF_TOA_PROBE)
253ffa25becSAdrian Chadd 		do_ldpc = 0;
254ffa25becSAdrian Chadd 
255ce725c8eSAdrian Chadd 	do_stbc = 0;
256eb6f0de0SAdrian Chadd 
257eb6f0de0SAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
258eb6f0de0SAdrian Chadd 		rc[i].flags = 0;
259eb6f0de0SAdrian Chadd 		if (rc[i].tries == 0)
260eb6f0de0SAdrian Chadd 			continue;
261eb6f0de0SAdrian Chadd 
262eb6f0de0SAdrian Chadd 		rate = rt->info[rc[i].rix].rateCode;
263eb6f0de0SAdrian Chadd 
264eb6f0de0SAdrian Chadd 		/*
26556129906SAdrian Chadd 		 * Only enable short preamble for legacy rates
266eb6f0de0SAdrian Chadd 		 */
2677a27f0a3SAdrian Chadd 		if ((! IS_HT_RATE(rate)) && bf->bf_state.bfs_shpream)
268eb6f0de0SAdrian Chadd 			rate |= rt->info[rc[i].rix].shortPreamble;
269eb6f0de0SAdrian Chadd 
270eb6f0de0SAdrian Chadd 		/*
271eb6f0de0SAdrian Chadd 		 * Save this, used by the TX and completion code
272eb6f0de0SAdrian Chadd 		 */
273eb6f0de0SAdrian Chadd 		rc[i].ratecode = rate;
274eb6f0de0SAdrian Chadd 
275875a9451SAdrian Chadd 		if (bf->bf_state.bfs_txflags &
276eb6f0de0SAdrian Chadd 		    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
277eb6f0de0SAdrian Chadd 			rc[i].flags |= ATH_RC_RTSCTS_FLAG;
278eb6f0de0SAdrian Chadd 
279ce725c8eSAdrian Chadd 		/*
280ce725c8eSAdrian Chadd 		 * If we can't do LDPC, don't.
281ce725c8eSAdrian Chadd 		 */
282ce725c8eSAdrian Chadd 		if (! IS_HT_RATE(rate))
283ce725c8eSAdrian Chadd 			do_ldpc = 0;
284ce725c8eSAdrian Chadd 
285eb6f0de0SAdrian Chadd 		/* Only enable shortgi, 2040, dual-stream if HT is set */
286eb6f0de0SAdrian Chadd 		if (IS_HT_RATE(rate)) {
287eb6f0de0SAdrian Chadd 			rc[i].flags |= ATH_RC_HT_FLAG;
288eb6f0de0SAdrian Chadd 
289eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 40)
290eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_CW40_FLAG;
291eb6f0de0SAdrian Chadd 
292ffa25becSAdrian Chadd 			/*
293ffa25becSAdrian Chadd 			 * NOTE: Don't do short-gi for positioning frames.
294ffa25becSAdrian Chadd 			 *
295ffa25becSAdrian Chadd 			 * For now, the ath_hal and net80211 HT duration
296ffa25becSAdrian Chadd 			 * calculation rounds up the 11n data txtime
297ffa25becSAdrian Chadd 			 * to the nearest multiple of 3.6 microseconds
298ffa25becSAdrian Chadd 			 * and doesn't return the fractional part, so
299ffa25becSAdrian Chadd 			 * we are always "out" by some amount.
300ffa25becSAdrian Chadd 			 */
301eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 40 &&
302eb6f0de0SAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
303a7038bd1SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40 &&
304ffa25becSAdrian Chadd 			    vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40 &&
305ffa25becSAdrian Chadd 			    (bf->bf_flags & ATH_BUF_TOA_PROBE) == 0) {
306eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_SGI_FLAG;
307ffa25becSAdrian Chadd 			}
308eb6f0de0SAdrian Chadd 
309eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 20 &&
310eb6f0de0SAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
311a7038bd1SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20 &&
312ffa25becSAdrian Chadd 			    vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20 &&
313ffa25becSAdrian Chadd 			    (bf->bf_flags & ATH_BUF_TOA_PROBE) == 0) {
314eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_SGI_FLAG;
315ffa25becSAdrian Chadd 			}
316eb6f0de0SAdrian Chadd 
31756129906SAdrian Chadd 			/*
31856129906SAdrian Chadd 			 * If we have STBC TX enabled and the receiver
31956129906SAdrian Chadd 			 * can receive (at least) 1 stream STBC, AND it's
32056129906SAdrian Chadd 			 * MCS 0-7, AND we have at least two chains enabled,
321ffa25becSAdrian Chadd 			 * and we're not doing positioning, enable STBC.
32256129906SAdrian Chadd 			 */
32356129906SAdrian Chadd 			if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
324c969f82dSAdrian Chadd 			    (ni->ni_vap->iv_flags_ht & IEEE80211_FHT_STBC_TX) &&
325c969f82dSAdrian Chadd 			    (ni->ni_htcap & IEEE80211_HTCAP_RXSTBC) &&
32656129906SAdrian Chadd 			    (sc->sc_cur_txchainmask > 1) &&
327ffa25becSAdrian Chadd 			    (HT_RC_2_STREAMS(rate) == 1) &&
328ffa25becSAdrian Chadd 			    (bf->bf_flags & ATH_BUF_TOA_PROBE) == 0) {
32956129906SAdrian Chadd 				rc[i].flags |= ATH_RC_STBC_FLAG;
330ce725c8eSAdrian Chadd 				do_stbc = 1;
33156129906SAdrian Chadd 			}
33256129906SAdrian Chadd 
333de00e5cbSAdrian Chadd 			/*
334de00e5cbSAdrian Chadd 			 * Dual / Triple stream rate?
335de00e5cbSAdrian Chadd 			 */
336de00e5cbSAdrian Chadd 			if (HT_RC_2_STREAMS(rate) == 2)
337de00e5cbSAdrian Chadd 				rc[i].flags |= ATH_RC_DS_FLAG;
338de00e5cbSAdrian Chadd 			else if (HT_RC_2_STREAMS(rate) == 3)
339de00e5cbSAdrian Chadd 				rc[i].flags |= ATH_RC_TS_FLAG;
340eb6f0de0SAdrian Chadd 		}
341eb6f0de0SAdrian Chadd 
342eb6f0de0SAdrian Chadd 		/*
343de00e5cbSAdrian Chadd 		 * Calculate the maximum TX power cap for the current
344de00e5cbSAdrian Chadd 		 * node.
345de00e5cbSAdrian Chadd 		 */
346de00e5cbSAdrian Chadd 		rc[i].tx_power_cap = ieee80211_get_node_txpower(ni);
347de00e5cbSAdrian Chadd 
348de00e5cbSAdrian Chadd 		/*
349eb6f0de0SAdrian Chadd 		 * Calculate the maximum 4ms frame length based
350eb6f0de0SAdrian Chadd 		 * on the MCS rate, SGI and channel width flags.
351eb6f0de0SAdrian Chadd 		 */
352eb6f0de0SAdrian Chadd 		if ((rc[i].flags & ATH_RC_HT_FLAG) &&
353eb6f0de0SAdrian Chadd 		    (HT_RC_2_MCS(rate) < 32)) {
354eb6f0de0SAdrian Chadd 			int j;
355eb6f0de0SAdrian Chadd 			if (rc[i].flags & ATH_RC_CW40_FLAG) {
356eb6f0de0SAdrian Chadd 				if (rc[i].flags & ATH_RC_SGI_FLAG)
357eb6f0de0SAdrian Chadd 					j = MCS_HT40_SGI;
358eb6f0de0SAdrian Chadd 				else
359eb6f0de0SAdrian Chadd 					j = MCS_HT40;
360eb6f0de0SAdrian Chadd 			} else {
361eb6f0de0SAdrian Chadd 				if (rc[i].flags & ATH_RC_SGI_FLAG)
362eb6f0de0SAdrian Chadd 					j = MCS_HT20_SGI;
363eb6f0de0SAdrian Chadd 				else
364eb6f0de0SAdrian Chadd 					j = MCS_HT20;
365eb6f0de0SAdrian Chadd 			}
366eb6f0de0SAdrian Chadd 			rc[i].max4msframelen =
367eb6f0de0SAdrian Chadd 			    ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)];
368eb6f0de0SAdrian Chadd 		} else
369eb6f0de0SAdrian Chadd 			rc[i].max4msframelen = 0;
370eb6f0de0SAdrian Chadd 		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
371eb6f0de0SAdrian Chadd 		    "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
372eb6f0de0SAdrian Chadd 		    __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
373eb6f0de0SAdrian Chadd 	}
374ce725c8eSAdrian Chadd 
375ce725c8eSAdrian Chadd 	/*
376ce725c8eSAdrian Chadd 	 * LDPC is a global flag, so ...
377ce725c8eSAdrian Chadd 	 */
378ce725c8eSAdrian Chadd 	if (do_ldpc) {
379ce725c8eSAdrian Chadd 		bf->bf_state.bfs_txflags |= HAL_TXDESC_LDPC;
380ce725c8eSAdrian Chadd 		sc->sc_stats.ast_tx_ldpc++;
381ce725c8eSAdrian Chadd 	}
382ce725c8eSAdrian Chadd 
383ce725c8eSAdrian Chadd 	if (do_stbc) {
384ce725c8eSAdrian Chadd 		sc->sc_stats.ast_tx_stbc++;
385ce725c8eSAdrian Chadd 	}
386eb6f0de0SAdrian Chadd }
387eb6f0de0SAdrian Chadd 
388eb6f0de0SAdrian Chadd /*
389eb6f0de0SAdrian Chadd  * Return the number of delimiters to be added to
390eb6f0de0SAdrian Chadd  * meet the minimum required mpdudensity.
391eb6f0de0SAdrian Chadd  *
392eb6f0de0SAdrian Chadd  * Caller should make sure that the rate is HT.
393eb6f0de0SAdrian Chadd  *
394eb6f0de0SAdrian Chadd  * TODO: is this delimiter calculation supposed to be the
395eb6f0de0SAdrian Chadd  * total frame length, the hdr length, the data length (including
396eb6f0de0SAdrian Chadd  * delimiters, padding, CRC, etc) or ?
397eb6f0de0SAdrian Chadd  *
398eb6f0de0SAdrian Chadd  * TODO: this should ensure that the rate control information
399eb6f0de0SAdrian Chadd  * HAS been setup for the first rate.
400eb6f0de0SAdrian Chadd  *
401eb6f0de0SAdrian Chadd  * TODO: ensure this is only called for MCS rates.
402eb6f0de0SAdrian Chadd  *
403eb6f0de0SAdrian Chadd  * TODO: enforce MCS < 31
404eb6f0de0SAdrian Chadd  */
405eb6f0de0SAdrian Chadd static int
406eb6f0de0SAdrian Chadd ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf,
407a2d74cc3SAdrian Chadd     uint16_t pktlen, int is_first)
408eb6f0de0SAdrian Chadd {
409c969f82dSAdrian Chadd #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
410eb6f0de0SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
411eb6f0de0SAdrian Chadd 	struct ieee80211_node *ni = first_bf->bf_node;
412eb6f0de0SAdrian Chadd 	struct ieee80211vap *vap = ni->ni_vap;
413eb6f0de0SAdrian Chadd 	int ndelim, mindelim = 0;
414eb6f0de0SAdrian Chadd 	int mpdudensity;	/* in 1/100'th of a microsecond */
415c969f82dSAdrian Chadd 	int peer_mpdudensity;	/* net80211 value */
416eb6f0de0SAdrian Chadd 	uint8_t rc, rix, flags;
417eb6f0de0SAdrian Chadd 	int width, half_gi;
418eb6f0de0SAdrian Chadd 	uint32_t nsymbits, nsymbols;
419eb6f0de0SAdrian Chadd 	uint16_t minlen;
420eb6f0de0SAdrian Chadd 
421eb6f0de0SAdrian Chadd 	/*
422c969f82dSAdrian Chadd 	 * Get the advertised density from the node.
423eb6f0de0SAdrian Chadd 	 */
424c969f82dSAdrian Chadd 	peer_mpdudensity = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY);
425c969f82dSAdrian Chadd 
426c969f82dSAdrian Chadd 	/*
427c969f82dSAdrian Chadd 	 * vap->iv_ampdu_density is a net80211 value, rather than the actual
428c969f82dSAdrian Chadd 	 * density.  Larger values are longer A-MPDU density spacing values,
429c969f82dSAdrian Chadd 	 * and we want to obey larger configured / negotiated density values
430c969f82dSAdrian Chadd 	 * per station if we get it.
431c969f82dSAdrian Chadd 	 */
432c969f82dSAdrian Chadd 	if (vap->iv_ampdu_density > peer_mpdudensity)
433c969f82dSAdrian Chadd 		peer_mpdudensity = vap->iv_ampdu_density;
434c969f82dSAdrian Chadd 
435c969f82dSAdrian Chadd 	/*
436c969f82dSAdrian Chadd 	 * Convert the A-MPDU density net80211 value to a 1/100 microsecond
437c969f82dSAdrian Chadd 	 * value for subsequent calculations.
438c969f82dSAdrian Chadd 	 */
439c969f82dSAdrian Chadd 	if (peer_mpdudensity > IEEE80211_HTCAP_MPDUDENSITY_16)
440eb6f0de0SAdrian Chadd 		mpdudensity = 1600;		/* maximum density */
441eb6f0de0SAdrian Chadd 	else
442c969f82dSAdrian Chadd 		mpdudensity = ieee80211_mpdudensity_map[peer_mpdudensity];
443eb6f0de0SAdrian Chadd 
444eb6f0de0SAdrian Chadd 	/* Select standard number of delimiters based on frame length */
445eb6f0de0SAdrian Chadd 	ndelim = ATH_AGGR_GET_NDELIM(pktlen);
446eb6f0de0SAdrian Chadd 
447eb6f0de0SAdrian Chadd 	/*
448eb6f0de0SAdrian Chadd 	 * If encryption is enabled, add extra delimiters to let the
449eb6f0de0SAdrian Chadd 	 * crypto hardware catch up. This could be tuned per-MAC and
450eb6f0de0SAdrian Chadd 	 * per-rate, but for now we'll simply assume encryption is
451eb6f0de0SAdrian Chadd 	 * always enabled.
4524a502c33SAdrian Chadd 	 *
4534a502c33SAdrian Chadd 	 * Also note that the Atheros reference driver inserts two
4544a502c33SAdrian Chadd 	 * delimiters by default for pre-AR9380 peers.  This will
4554a502c33SAdrian Chadd 	 * include "that" required delimiter.
456eb6f0de0SAdrian Chadd 	 */
457eb6f0de0SAdrian Chadd 	ndelim += ATH_AGGR_ENCRYPTDELIM;
458eb6f0de0SAdrian Chadd 
45964dbfc6dSAdrian Chadd 	/*
46064dbfc6dSAdrian Chadd 	 * For AR9380, there's a minimum number of delimeters
46164dbfc6dSAdrian Chadd 	 * required when doing RTS.
4624a502c33SAdrian Chadd 	 *
463a2d74cc3SAdrian Chadd 	 * XXX TODO: this is only needed if (a) RTS/CTS is enabled for
464a2d74cc3SAdrian Chadd 	 * this exchange, and (b) (done) this is the first sub-frame
465a2d74cc3SAdrian Chadd 	 * in the aggregate.
46664dbfc6dSAdrian Chadd 	 */
46764dbfc6dSAdrian Chadd 	if (sc->sc_use_ent && (sc->sc_ent_cfg & AH_ENT_RTSCTS_DELIM_WAR)
468a2d74cc3SAdrian Chadd 	    && ndelim < AH_FIRST_DESC_NDELIMS && is_first)
46964dbfc6dSAdrian Chadd 		ndelim = AH_FIRST_DESC_NDELIMS;
47064dbfc6dSAdrian Chadd 
471a54ecf78SAdrian Chadd 	/*
472a54ecf78SAdrian Chadd 	 * If sc_delim_min_pad is non-zero, enforce it as the minimum
473a54ecf78SAdrian Chadd 	 * pad delimiter count.
474a54ecf78SAdrian Chadd 	 */
475a54ecf78SAdrian Chadd 	if (sc->sc_delim_min_pad != 0)
476a54ecf78SAdrian Chadd 		ndelim = MAX(ndelim, sc->sc_delim_min_pad);
477a54ecf78SAdrian Chadd 
478eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
479eb6f0de0SAdrian Chadd 	    "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n",
480eb6f0de0SAdrian Chadd 	    __func__, pktlen, ndelim, mpdudensity);
481eb6f0de0SAdrian Chadd 
482eb6f0de0SAdrian Chadd 	/*
483eb6f0de0SAdrian Chadd 	 * If the MPDU density is 0, we can return here.
484eb6f0de0SAdrian Chadd 	 * Otherwise, we need to convert the desired mpdudensity
485eb6f0de0SAdrian Chadd 	 * into a byte length, based on the rate in the subframe.
486eb6f0de0SAdrian Chadd 	 */
487eb6f0de0SAdrian Chadd 	if (mpdudensity == 0)
488eb6f0de0SAdrian Chadd 		return ndelim;
489eb6f0de0SAdrian Chadd 
490eb6f0de0SAdrian Chadd 	/*
491eb6f0de0SAdrian Chadd 	 * Convert desired mpdu density from microeconds to bytes based
492eb6f0de0SAdrian Chadd 	 * on highest rate in rate series (i.e. first rate) to determine
493eb6f0de0SAdrian Chadd 	 * required minimum length for subframe. Take into account
494eb6f0de0SAdrian Chadd 	 * whether high rate is 20 or 40Mhz and half or full GI.
495eb6f0de0SAdrian Chadd 	 */
496eb6f0de0SAdrian Chadd 	rix = first_bf->bf_state.bfs_rc[0].rix;
497eb6f0de0SAdrian Chadd 	rc = rt->info[rix].rateCode;
498eb6f0de0SAdrian Chadd 	flags = first_bf->bf_state.bfs_rc[0].flags;
499eb6f0de0SAdrian Chadd 	width = !! (flags & ATH_RC_CW40_FLAG);
500eb6f0de0SAdrian Chadd 	half_gi = !! (flags & ATH_RC_SGI_FLAG);
501eb6f0de0SAdrian Chadd 
502eb6f0de0SAdrian Chadd 	/*
503eb6f0de0SAdrian Chadd 	 * mpdudensity is in 1/100th of a usec, so divide by 100
504eb6f0de0SAdrian Chadd 	 */
505eb6f0de0SAdrian Chadd 	if (half_gi)
506eb6f0de0SAdrian Chadd 		nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
507eb6f0de0SAdrian Chadd 	else
508eb6f0de0SAdrian Chadd 		nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
509eb6f0de0SAdrian Chadd 	nsymbols /= 100;
510eb6f0de0SAdrian Chadd 
511eb6f0de0SAdrian Chadd 	if (nsymbols == 0)
512eb6f0de0SAdrian Chadd 		nsymbols = 1;
513eb6f0de0SAdrian Chadd 
514eb6f0de0SAdrian Chadd 	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
515eb6f0de0SAdrian Chadd 	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
516eb6f0de0SAdrian Chadd 
517eb6f0de0SAdrian Chadd 	/*
518eb6f0de0SAdrian Chadd 	 * Min length is the minimum frame length for the
519eb6f0de0SAdrian Chadd 	 * required MPDU density.
520eb6f0de0SAdrian Chadd 	 */
521eb6f0de0SAdrian Chadd 	if (pktlen < minlen) {
522eb6f0de0SAdrian Chadd 		mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ;
523eb6f0de0SAdrian Chadd 		ndelim = MAX(mindelim, ndelim);
524eb6f0de0SAdrian Chadd 	}
525eb6f0de0SAdrian Chadd 
526eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
527eb6f0de0SAdrian Chadd 	    "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n",
528eb6f0de0SAdrian Chadd 	    __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim);
529eb6f0de0SAdrian Chadd 
530eb6f0de0SAdrian Chadd 	return ndelim;
531c969f82dSAdrian Chadd #undef	MS
532eb6f0de0SAdrian Chadd }
533eb6f0de0SAdrian Chadd 
534eb6f0de0SAdrian Chadd /*
535707210ffSAdrian Chadd  * XXX TODO: put into net80211
536707210ffSAdrian Chadd  */
537707210ffSAdrian Chadd static int
538707210ffSAdrian Chadd ath_rx_ampdu_to_byte(char a)
539707210ffSAdrian Chadd {
540707210ffSAdrian Chadd 	switch (a) {
541707210ffSAdrian Chadd 	case IEEE80211_HTCAP_MAXRXAMPDU_16K:
542707210ffSAdrian Chadd 		return 16384;
543707210ffSAdrian Chadd 		break;
544707210ffSAdrian Chadd 	case IEEE80211_HTCAP_MAXRXAMPDU_32K:
545707210ffSAdrian Chadd 		return 32768;
546707210ffSAdrian Chadd 		break;
547707210ffSAdrian Chadd 	case IEEE80211_HTCAP_MAXRXAMPDU_64K:
548707210ffSAdrian Chadd 		return 65536;
549707210ffSAdrian Chadd 		break;
550707210ffSAdrian Chadd 	case IEEE80211_HTCAP_MAXRXAMPDU_8K:
551707210ffSAdrian Chadd 	default:
552707210ffSAdrian Chadd 		return 8192;
553707210ffSAdrian Chadd 		break;
554707210ffSAdrian Chadd 	}
555707210ffSAdrian Chadd }
556707210ffSAdrian Chadd 
557707210ffSAdrian Chadd /*
558eb6f0de0SAdrian Chadd  * Fetch the aggregation limit.
559eb6f0de0SAdrian Chadd  *
560eb6f0de0SAdrian Chadd  * It's the lowest of the four rate series 4ms frame length.
561c969f82dSAdrian Chadd  *
562c969f82dSAdrian Chadd  * Also take into account the hardware specific limits (8KiB on AR5416)
563c969f82dSAdrian Chadd  * and per-peer limits in non-STA mode.
564eb6f0de0SAdrian Chadd  */
565eb6f0de0SAdrian Chadd static int
566c969f82dSAdrian Chadd ath_get_aggr_limit(struct ath_softc *sc, struct ieee80211_node *ni,
567c969f82dSAdrian Chadd     struct ath_buf *bf)
568eb6f0de0SAdrian Chadd {
569707210ffSAdrian Chadd 	struct ieee80211vap *vap = ni->ni_vap;
570707210ffSAdrian Chadd 
571c969f82dSAdrian Chadd #define	MS(_v, _f)	(((_v) & _f) >> _f##_S)
5724a502c33SAdrian Chadd 	int amin = ATH_AGGR_MAXSIZE;
573eb6f0de0SAdrian Chadd 	int i;
574eb6f0de0SAdrian Chadd 
575c969f82dSAdrian Chadd 	/* Extract out the maximum configured driver A-MPDU limit */
5764a502c33SAdrian Chadd 	if (sc->sc_aggr_limit > 0 && sc->sc_aggr_limit < ATH_AGGR_MAXSIZE)
5774a502c33SAdrian Chadd 		amin = sc->sc_aggr_limit;
5784a502c33SAdrian Chadd 
579707210ffSAdrian Chadd 	/* Check the vap configured transmit limit */
580707210ffSAdrian Chadd 	amin = MIN(amin, ath_rx_ampdu_to_byte(vap->iv_ampdu_limit));
581707210ffSAdrian Chadd 
582c969f82dSAdrian Chadd 	/*
583c969f82dSAdrian Chadd 	 * Check the HTCAP field for the maximum size the node has
584c969f82dSAdrian Chadd 	 * negotiated.  If it's smaller than what we have, cap it there.
585c969f82dSAdrian Chadd 	 */
586707210ffSAdrian Chadd 	amin = MIN(amin, ath_rx_ampdu_to_byte(MS(ni->ni_htparam,
587707210ffSAdrian Chadd 	    IEEE80211_HTCAP_MAXRXAMPDU)));
588c969f82dSAdrian Chadd 
589b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
590eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_rc[i].tries == 0)
591eb6f0de0SAdrian Chadd 			continue;
592eb6f0de0SAdrian Chadd 		amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen);
593eb6f0de0SAdrian Chadd 	}
594eb6f0de0SAdrian Chadd 
59528dc144eSAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
59628dc144eSAdrian Chadd 	    "%s: aggr_limit=%d, iv_ampdu_limit=%d, "
59728dc144eSAdrian Chadd 	    "peer maxrxampdu=%d, max frame len=%d\n",
59828dc144eSAdrian Chadd 	    __func__,
59928dc144eSAdrian Chadd 	    sc->sc_aggr_limit,
60028dc144eSAdrian Chadd 	    vap->iv_ampdu_limit,
60128dc144eSAdrian Chadd 	    MS(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU),
60228dc144eSAdrian Chadd 	    amin);
603eb6f0de0SAdrian Chadd 
604eb6f0de0SAdrian Chadd 	return amin;
605c969f82dSAdrian Chadd #undef	MS
606eb6f0de0SAdrian Chadd }
6074b44f6f2SAdrian Chadd 
6084b44f6f2SAdrian Chadd /*
6094b44f6f2SAdrian Chadd  * Setup a 11n rate series structure
6104b44f6f2SAdrian Chadd  *
6114b44f6f2SAdrian Chadd  * This should be called for both legacy and MCS rates.
612eb6f0de0SAdrian Chadd  *
613de00e5cbSAdrian Chadd  * This uses the rate series stuf from ath_tx_rate_fill_rcflags().
614de00e5cbSAdrian Chadd  *
615eb6f0de0SAdrian Chadd  * It, along with ath_buf_set_rate, must be called -after- a burst
616eb6f0de0SAdrian Chadd  * or aggregate is setup.
6174b44f6f2SAdrian Chadd  */
6184b44f6f2SAdrian Chadd static void
6194b44f6f2SAdrian Chadd ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
620eb6f0de0SAdrian Chadd     struct ath_buf *bf, HAL_11N_RATE_SERIES *series)
6214b44f6f2SAdrian Chadd {
6224b44f6f2SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
6234b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
6244b44f6f2SAdrian Chadd 	HAL_BOOL shortPreamble = AH_FALSE;
6254b44f6f2SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
6264b44f6f2SAdrian Chadd 	int i;
627eb6f0de0SAdrian Chadd 	int pktlen;
628eb6f0de0SAdrian Chadd 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
6294b44f6f2SAdrian Chadd 
6304b44f6f2SAdrian Chadd 	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
6314b44f6f2SAdrian Chadd 	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
6324b44f6f2SAdrian Chadd 		shortPreamble = AH_TRUE;
6334b44f6f2SAdrian Chadd 
634eb6f0de0SAdrian Chadd 	/*
635eb6f0de0SAdrian Chadd 	 * If this is the first frame in an aggregate series,
636eb6f0de0SAdrian Chadd 	 * use the aggregate length.
637eb6f0de0SAdrian Chadd 	 */
638eb6f0de0SAdrian Chadd 	if (bf->bf_state.bfs_aggr)
639eb6f0de0SAdrian Chadd 		pktlen = bf->bf_state.bfs_al;
640eb6f0de0SAdrian Chadd 	else
641eb6f0de0SAdrian Chadd 		pktlen = bf->bf_state.bfs_pktlen;
642eb6f0de0SAdrian Chadd 
643eb6f0de0SAdrian Chadd 	/*
644eb6f0de0SAdrian Chadd 	 * XXX TODO: modify this routine to use the bfs_rc[x].flags
645eb6f0de0SAdrian Chadd 	 * XXX fields.
646eb6f0de0SAdrian Chadd 	 */
6474b44f6f2SAdrian Chadd 	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
648b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM;  i++) {
649146b49d8SAdrian Chadd 		/* Only set flags for actual TX attempts */
650eb6f0de0SAdrian Chadd 		if (rc[i].tries == 0)
651146b49d8SAdrian Chadd 			continue;
652146b49d8SAdrian Chadd 
653eb6f0de0SAdrian Chadd 		series[i].Tries = rc[i].tries;
654146b49d8SAdrian Chadd 
655146b49d8SAdrian Chadd 		/*
6564a502c33SAdrian Chadd 		 * XXX TODO: When the NIC is capable of three stream TX,
6574a502c33SAdrian Chadd 		 * transmit 1/2 stream rates on two streams.
6584a502c33SAdrian Chadd 		 *
6594a502c33SAdrian Chadd 		 * This reduces the power consumption of the NIC and
6604a502c33SAdrian Chadd 		 * keeps it within the PCIe slot power limits.
6614a502c33SAdrian Chadd 		 */
6626322256bSAdrian Chadd 		series[i].ChSel = sc->sc_cur_txchainmask;
663146b49d8SAdrian Chadd 
66456129906SAdrian Chadd 		/*
66556129906SAdrian Chadd 		 * Setup rate and TX power cap for this series.
66656129906SAdrian Chadd 		 */
66756129906SAdrian Chadd 		series[i].Rate = rt->info[rc[i].rix].rateCode;
66856129906SAdrian Chadd 		series[i].RateIndex = rc[i].rix;
669de00e5cbSAdrian Chadd 		series[i].tx_power_cap = rc[i].tx_power_cap;
67056129906SAdrian Chadd 
67156129906SAdrian Chadd 		/*
67256129906SAdrian Chadd 		 * Enable RTS/CTS as appropriate.
67356129906SAdrian Chadd 		 */
674de00e5cbSAdrian Chadd 		if (rc[i].flags & ATH_RC_RTSCTS_FLAG)
6754b44f6f2SAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
676146b49d8SAdrian Chadd 
677532f2442SAdrian Chadd 		/*
678de00e5cbSAdrian Chadd 		 * 11n rate? Update 11n flags.
679532f2442SAdrian Chadd 		 */
680de00e5cbSAdrian Chadd 		if (rc[i].flags & ATH_RC_HT_FLAG) {
681de00e5cbSAdrian Chadd 			if (rc[i].flags & ATH_RC_CW40_FLAG)
6824b44f6f2SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_2040;
6836246be6eSAdrian Chadd 
684de00e5cbSAdrian Chadd 			if (rc[i].flags & ATH_RC_SGI_FLAG)
6854b44f6f2SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_HALFGI;
6866246be6eSAdrian Chadd 
687de00e5cbSAdrian Chadd 			if (rc[i].flags & ATH_RC_STBC_FLAG)
6881a3a5607SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_STBC;
6891a3a5607SAdrian Chadd 		}
6906322256bSAdrian Chadd 
691b25c1f2aSAdrian Chadd 		/*
692f026d693SAdrian Chadd 		 * TODO: If we're all doing 11n rates then we can set LDPC.
693f026d693SAdrian Chadd 		 * If we've been asked to /do/ LDPC but we are handed a
694f026d693SAdrian Chadd 		 * legacy rate, then we should complain.  Loudly.
695f026d693SAdrian Chadd 		 */
696f026d693SAdrian Chadd 
697f026d693SAdrian Chadd 		/*
698b25c1f2aSAdrian Chadd 		 * PktDuration doesn't include slot, ACK, RTS, etc timing -
699b25c1f2aSAdrian Chadd 		 * it's just the packet duration
700b25c1f2aSAdrian Chadd 		 */
701de00e5cbSAdrian Chadd 		if (rc[i].flags & ATH_RC_HT_FLAG) {
7024b44f6f2SAdrian Chadd 			series[i].PktDuration =
7034b44f6f2SAdrian Chadd 			    ath_computedur_ht(pktlen
7049a97e25eSAdrian Chadd 				, series[i].Rate
705fce6d676SAdrian Chadd 				, HT_RC_2_STREAMS(series[i].Rate)
706fce6d676SAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_2040
707f449ab1cSAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
7084b44f6f2SAdrian Chadd 		} else {
7091198947aSAdrian Chadd 			if (shortPreamble)
710eb6f0de0SAdrian Chadd 				series[i].Rate |=
711eb6f0de0SAdrian Chadd 				    rt->info[rc[i].rix].shortPreamble;
7127ff1939dSAdrian Chadd 			/* XXX TODO: don't include SIFS */
7134b44f6f2SAdrian Chadd 			series[i].PktDuration = ath_hal_computetxtime(ah,
7147ff1939dSAdrian Chadd 			    rt, pktlen, rc[i].rix, shortPreamble, AH_TRUE);
7154b44f6f2SAdrian Chadd 		}
7164b44f6f2SAdrian Chadd 	}
7174b44f6f2SAdrian Chadd }
7184b44f6f2SAdrian Chadd 
71919b34b56SAdrian Chadd #ifdef	ATH_DEBUG
7204b44f6f2SAdrian Chadd static void
721b25c1f2aSAdrian Chadd ath_rateseries_print(struct ath_softc *sc, HAL_11N_RATE_SERIES *series)
7224b44f6f2SAdrian Chadd {
7234b44f6f2SAdrian Chadd 	int i;
724b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
725b25c1f2aSAdrian Chadd 		device_printf(sc->sc_dev ,"series %d: rate %x; tries %d; "
72664dbfc6dSAdrian Chadd 		    "pktDuration %d; chSel %d; txpowcap %d, rateFlags %x\n",
7274b44f6f2SAdrian Chadd 		    i,
7284b44f6f2SAdrian Chadd 		    series[i].Rate,
7294b44f6f2SAdrian Chadd 		    series[i].Tries,
7304b44f6f2SAdrian Chadd 		    series[i].PktDuration,
7314b44f6f2SAdrian Chadd 		    series[i].ChSel,
73264dbfc6dSAdrian Chadd 		    series[i].tx_power_cap,
7334b44f6f2SAdrian Chadd 		    series[i].RateFlags);
7344b44f6f2SAdrian Chadd 	}
7354b44f6f2SAdrian Chadd }
7364b44f6f2SAdrian Chadd #endif
7374b44f6f2SAdrian Chadd 
7384b44f6f2SAdrian Chadd /*
7394b44f6f2SAdrian Chadd  * Setup the 11n rate scenario and burst duration for the given TX descriptor
7404b44f6f2SAdrian Chadd  * list.
7414b44f6f2SAdrian Chadd  *
7424b44f6f2SAdrian Chadd  * This isn't useful for sending beacon frames, which has different needs
7434b44f6f2SAdrian Chadd  * wrt what's passed into the rate scenario function.
7444b44f6f2SAdrian Chadd  */
7454b44f6f2SAdrian Chadd void
746eb6f0de0SAdrian Chadd ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni,
747eb6f0de0SAdrian Chadd     struct ath_buf *bf)
7484b44f6f2SAdrian Chadd {
7494b44f6f2SAdrian Chadd 	HAL_11N_RATE_SERIES series[4];
7504b44f6f2SAdrian Chadd 	struct ath_desc *ds = bf->bf_desc;
7514b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
752eb6f0de0SAdrian Chadd 	int is_pspoll = (bf->bf_state.bfs_atype == HAL_PKT_TYPE_PSPOLL);
753eb6f0de0SAdrian Chadd 	int ctsrate = bf->bf_state.bfs_ctsrate;
754875a9451SAdrian Chadd 	int flags = bf->bf_state.bfs_txflags;
7554b44f6f2SAdrian Chadd 
7564b44f6f2SAdrian Chadd 	/* Setup rate scenario */
7574b44f6f2SAdrian Chadd 	memset(&series, 0, sizeof(series));
7584b44f6f2SAdrian Chadd 
759eb6f0de0SAdrian Chadd 	ath_rateseries_setup(sc, ni, bf, series);
7604b44f6f2SAdrian Chadd 
76119b34b56SAdrian Chadd #ifdef	ATH_DEBUG
76220b0b9eaSAdrian Chadd 	if (sc->sc_debug & ATH_DEBUG_XMIT)
763b25c1f2aSAdrian Chadd 		ath_rateseries_print(sc, series);
7642b5684a8SAdrian Chadd #endif
7652b5684a8SAdrian Chadd 
7664b44f6f2SAdrian Chadd 	/* Set rate scenario */
767b25c1f2aSAdrian Chadd 	/*
768b25c1f2aSAdrian Chadd 	 * Note: Don't allow hardware to override the duration on
769b25c1f2aSAdrian Chadd 	 * ps-poll packets.
770b25c1f2aSAdrian Chadd 	 */
7714b44f6f2SAdrian Chadd 	ath_hal_set11nratescenario(ah, ds,
772bf26df36SAdrian Chadd 	    !is_pspoll,	/* whether to override the duration or not */
7734b44f6f2SAdrian Chadd 	    ctsrate,	/* rts/cts rate */
7744b44f6f2SAdrian Chadd 	    series,	/* 11n rate series */
7754b44f6f2SAdrian Chadd 	    4,		/* number of series */
7764b44f6f2SAdrian Chadd 	    flags);
7774b44f6f2SAdrian Chadd 
7784b44f6f2SAdrian Chadd 	/* Set burst duration */
779eb6f0de0SAdrian Chadd 	/*
780eb6f0de0SAdrian Chadd 	 * This is only required when doing 11n burst, not aggregation
781eb6f0de0SAdrian Chadd 	 * ie, if there's a second frame in a RIFS or A-MPDU burst
782eb6f0de0SAdrian Chadd 	 * w/ >1 A-MPDU frame bursting back to back.
783eb6f0de0SAdrian Chadd 	 * Normal A-MPDU doesn't do bursting -between- aggregates.
784eb6f0de0SAdrian Chadd 	 *
785eb6f0de0SAdrian Chadd 	 * .. and it's highly likely this won't ever be implemented
786eb6f0de0SAdrian Chadd 	 */
7874b44f6f2SAdrian Chadd 	//ath_hal_set11nburstduration(ah, ds, 8192);
7884b44f6f2SAdrian Chadd }
789eb6f0de0SAdrian Chadd 
790eb6f0de0SAdrian Chadd /*
791eb6f0de0SAdrian Chadd  * Form an aggregate packet list.
792eb6f0de0SAdrian Chadd  *
793eb6f0de0SAdrian Chadd  * This function enforces the aggregate restrictions/requirements.
794eb6f0de0SAdrian Chadd  *
795eb6f0de0SAdrian Chadd  * These are:
796eb6f0de0SAdrian Chadd  *
797eb6f0de0SAdrian Chadd  * + The aggregate size maximum (64k for AR9160 and later, 8K for
798eb6f0de0SAdrian Chadd  *   AR5416 when doing RTS frame protection.)
799eb6f0de0SAdrian Chadd  * + Maximum number of sub-frames for an aggregate
800eb6f0de0SAdrian Chadd  * + The aggregate delimiter size, giving MACs time to do whatever is
801eb6f0de0SAdrian Chadd  *   needed before each frame
802eb6f0de0SAdrian Chadd  * + Enforce the BAW limit
803eb6f0de0SAdrian Chadd  *
804eb6f0de0SAdrian Chadd  * Each descriptor queued should have the DMA setup.
805eb6f0de0SAdrian Chadd  * The rate series, descriptor setup, linking, etc is all done
806eb6f0de0SAdrian Chadd  * externally. This routine simply chains them together.
807eb6f0de0SAdrian Chadd  * ath_tx_setds_11n() will take care of configuring the per-
808eb6f0de0SAdrian Chadd  * descriptor setup, and ath_buf_set_rate() will configure the
809eb6f0de0SAdrian Chadd  * rate control.
810eb6f0de0SAdrian Chadd  *
811b25c1f2aSAdrian Chadd  * The TID lock is required for the entirety of this function.
812b25c1f2aSAdrian Chadd  *
813b25c1f2aSAdrian Chadd  * If some code in another thread adds to the head of this
814eb6f0de0SAdrian Chadd  * list, very strange behaviour will occur. Since retransmission is the
815eb6f0de0SAdrian Chadd  * only reason this will occur, and this routine is designed to be called
816eb6f0de0SAdrian Chadd  * from within the scheduler task, it won't ever clash with the completion
817eb6f0de0SAdrian Chadd  * task.
818eb6f0de0SAdrian Chadd  *
819eb6f0de0SAdrian Chadd  * So if you want to call this from an upper layer context (eg, to direct-
820eb6f0de0SAdrian Chadd  * dispatch aggregate frames to the hardware), please keep this in mind.
821eb6f0de0SAdrian Chadd  */
822eb6f0de0SAdrian Chadd ATH_AGGR_STATUS
823b25c1f2aSAdrian Chadd ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an,
824b25c1f2aSAdrian Chadd     struct ath_tid *tid, ath_bufhead *bf_q)
825eb6f0de0SAdrian Chadd {
826a108d2d6SAdrian Chadd 	//struct ieee80211_node *ni = &an->an_node;
827eb6f0de0SAdrian Chadd 	struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
828eb6f0de0SAdrian Chadd 	int nframes = 0;
829eb6f0de0SAdrian Chadd 	uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw;
830eb6f0de0SAdrian Chadd 	struct ieee80211_tx_ampdu *tap;
831eb6f0de0SAdrian Chadd 	int status = ATH_AGGR_DONE;
832eb6f0de0SAdrian Chadd 	int prev_frames = 0;	/* XXX for AR5416 burst, not done here */
833eb6f0de0SAdrian Chadd 	int prev_al = 0;	/* XXX also for AR5416 burst */
834eb6f0de0SAdrian Chadd 
835375307d4SAdrian Chadd 	ATH_TX_LOCK_ASSERT(sc);
836eb6f0de0SAdrian Chadd 
837eb6f0de0SAdrian Chadd 	tap = ath_tx_get_tx_tid(an, tid->tid);
838eb6f0de0SAdrian Chadd 	if (tap == NULL) {
839eb6f0de0SAdrian Chadd 		status = ATH_AGGR_ERROR;
840eb6f0de0SAdrian Chadd 		goto finish;
841eb6f0de0SAdrian Chadd 	}
842eb6f0de0SAdrian Chadd 
843*cce63444SAdrian Chadd 	/*
844*cce63444SAdrian Chadd 	 * Limit the maximum number of frames in this A-MPDU
845*cce63444SAdrian Chadd 	 * to half of the window size.  This is done to prevent
846*cce63444SAdrian Chadd 	 * sending a LOT of frames that may fail in one batch
847*cce63444SAdrian Chadd 	 * when operating in higher MCS rates.  If there are more
848*cce63444SAdrian Chadd 	 * frames available to send then up to two A-MPDUs will
849*cce63444SAdrian Chadd 	 * be queued per hardware queue, so we'll "just" get
850*cce63444SAdrian Chadd 	 * a second A-MPDU.
851*cce63444SAdrian Chadd 	 */
852eb6f0de0SAdrian Chadd 	h_baw = tap->txa_wnd / 2;
853eb6f0de0SAdrian Chadd 
854eb6f0de0SAdrian Chadd 	for (;;) {
8553e6cc97fSAdrian Chadd 		bf = ATH_TID_FIRST(tid);
856eb6f0de0SAdrian Chadd 		if (bf == NULL) {
857eb6f0de0SAdrian Chadd 			status = ATH_AGGR_DONE;
858eb6f0de0SAdrian Chadd 			break;
859*cce63444SAdrian Chadd 		}
860*cce63444SAdrian Chadd 		if (bf_first == NULL) {
861*cce63444SAdrian Chadd 			bf_first = bf;
862eb6f0de0SAdrian Chadd 			/*
863eb6f0de0SAdrian Chadd 			 * It's the first frame;
864eb6f0de0SAdrian Chadd 			 * set the aggregation limit based on the
865eb6f0de0SAdrian Chadd 			 * rate control decision that has been made.
866eb6f0de0SAdrian Chadd 			 */
867c969f82dSAdrian Chadd 			aggr_limit = ath_get_aggr_limit(sc, &an->an_node,
868c969f82dSAdrian Chadd 			    bf_first);
869*cce63444SAdrian Chadd 			if (bf_first->bf_state.bfs_rc_maxpktlen > 0) {
870*cce63444SAdrian Chadd 				aggr_limit = MIN(aggr_limit,
871*cce63444SAdrian Chadd 				    bf_first->bf_state.bfs_rc_maxpktlen);
872*cce63444SAdrian Chadd 			}
873eb6f0de0SAdrian Chadd 		}
874eb6f0de0SAdrian Chadd 
875eb6f0de0SAdrian Chadd 		/* Set this early just so things don't get confused */
876eb6f0de0SAdrian Chadd 		bf->bf_next = NULL;
877eb6f0de0SAdrian Chadd 
878eb6f0de0SAdrian Chadd 		/*
879eb6f0de0SAdrian Chadd 		 * If the frame doesn't have a sequence number that we're
880eb6f0de0SAdrian Chadd 		 * tracking in the BAW (eg NULL QOS data frame), we can't
881eb6f0de0SAdrian Chadd 		 * aggregate it. Stop the aggregation process; the sender
882eb6f0de0SAdrian Chadd 		 * can then TX what's in the list thus far and then
883eb6f0de0SAdrian Chadd 		 * TX the frame individually.
884eb6f0de0SAdrian Chadd 		 */
885eb6f0de0SAdrian Chadd 		if (! bf->bf_state.bfs_dobaw) {
886eb6f0de0SAdrian Chadd 			status = ATH_AGGR_NONAGGR;
887eb6f0de0SAdrian Chadd 			break;
888eb6f0de0SAdrian Chadd 		}
889eb6f0de0SAdrian Chadd 
890eb6f0de0SAdrian Chadd 		/*
891eb6f0de0SAdrian Chadd 		 * If any of the rates are non-HT, this packet
892eb6f0de0SAdrian Chadd 		 * can't be aggregated.
893eb6f0de0SAdrian Chadd 		 * XXX TODO: add a bf_state flag which gets marked
894eb6f0de0SAdrian Chadd 		 * if any active rate is non-HT.
895eb6f0de0SAdrian Chadd 		 */
896eb6f0de0SAdrian Chadd 
897eb6f0de0SAdrian Chadd 		/*
898eb6f0de0SAdrian Chadd 		 * do not exceed aggregation limit
899eb6f0de0SAdrian Chadd 		 */
900eb6f0de0SAdrian Chadd 		al_delta = ATH_AGGR_DELIM_SZ + bf->bf_state.bfs_pktlen;
901eb6f0de0SAdrian Chadd 		if (nframes &&
902eb6f0de0SAdrian Chadd 		    (aggr_limit < (al + bpad + al_delta + prev_al))) {
903eb6f0de0SAdrian Chadd 			status = ATH_AGGR_LIMITED;
904eb6f0de0SAdrian Chadd 			break;
905eb6f0de0SAdrian Chadd 		}
906eb6f0de0SAdrian Chadd 
907eb6f0de0SAdrian Chadd 		/*
908045bc788SAdrian Chadd 		 * If RTS/CTS is set on the first frame, enforce
909045bc788SAdrian Chadd 		 * the RTS aggregate limit.
910045bc788SAdrian Chadd 		 */
911045bc788SAdrian Chadd 		if (bf_first->bf_state.bfs_txflags &
912045bc788SAdrian Chadd 		    (HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA)) {
913045bc788SAdrian Chadd 			if (nframes &&
914045bc788SAdrian Chadd 			   (sc->sc_rts_aggr_limit <
915045bc788SAdrian Chadd 			     (al + bpad + al_delta + prev_al))) {
916045bc788SAdrian Chadd 				status = ATH_AGGR_8K_LIMITED;
917045bc788SAdrian Chadd 				break;
918045bc788SAdrian Chadd 			}
919045bc788SAdrian Chadd 		}
920045bc788SAdrian Chadd 
921045bc788SAdrian Chadd 		/*
922eb6f0de0SAdrian Chadd 		 * Do not exceed subframe limit.
923eb6f0de0SAdrian Chadd 		 */
924eb6f0de0SAdrian Chadd 		if ((nframes + prev_frames) >= MIN((h_baw),
925eb6f0de0SAdrian Chadd 		    IEEE80211_AMPDU_SUBFRAME_DEFAULT)) {
926eb6f0de0SAdrian Chadd 			status = ATH_AGGR_LIMITED;
927eb6f0de0SAdrian Chadd 			break;
928eb6f0de0SAdrian Chadd 		}
929eb6f0de0SAdrian Chadd 
930eb6f0de0SAdrian Chadd 		/*
931045bc788SAdrian Chadd 		 * If the current frame has an RTS/CTS configuration
932781e7eafSAdrian Chadd 		 * that differs from the first frame, override the
933781e7eafSAdrian Chadd 		 * subsequent frame with this config.
934045bc788SAdrian Chadd 		 */
935d03904f1SAdrian Chadd 		if (bf != bf_first) {
936781e7eafSAdrian Chadd 			bf->bf_state.bfs_txflags &=
93776af1a93SAdrian Chadd 			    ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
938781e7eafSAdrian Chadd 			bf->bf_state.bfs_txflags |=
939781e7eafSAdrian Chadd 			    bf_first->bf_state.bfs_txflags &
940781e7eafSAdrian Chadd 			    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
941d03904f1SAdrian Chadd 		}
942045bc788SAdrian Chadd 
943045bc788SAdrian Chadd 		/*
9440b96ef63SAdrian Chadd 		 * If the packet has a sequence number, do not
9450b96ef63SAdrian Chadd 		 * step outside of the block-ack window.
9460b96ef63SAdrian Chadd 		 */
9470b96ef63SAdrian Chadd 		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
9480b96ef63SAdrian Chadd 		    SEQNO(bf->bf_state.bfs_seqno))) {
9490b96ef63SAdrian Chadd 			status = ATH_AGGR_BAW_CLOSED;
9500b96ef63SAdrian Chadd 			break;
9510b96ef63SAdrian Chadd 		}
9520b96ef63SAdrian Chadd 
9530b96ef63SAdrian Chadd 		/*
954eb6f0de0SAdrian Chadd 		 * this packet is part of an aggregate.
955eb6f0de0SAdrian Chadd 		 */
9563e6cc97fSAdrian Chadd 		ATH_TID_REMOVE(tid, bf, bf_list);
957eb6f0de0SAdrian Chadd 
958eb6f0de0SAdrian Chadd 		/* The TID lock is required for the BAW update */
959eb6f0de0SAdrian Chadd 		ath_tx_addto_baw(sc, an, tid, bf);
960eb6f0de0SAdrian Chadd 		bf->bf_state.bfs_addedbaw = 1;
961eb6f0de0SAdrian Chadd 
962eb6f0de0SAdrian Chadd 		/*
963eb6f0de0SAdrian Chadd 		 * XXX enforce ACK for aggregate frames (this needs to be
964eb6f0de0SAdrian Chadd 		 * XXX handled more gracefully?
965eb6f0de0SAdrian Chadd 		 */
966875a9451SAdrian Chadd 		if (bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) {
967eb6f0de0SAdrian Chadd 			device_printf(sc->sc_dev,
968eb6f0de0SAdrian Chadd 			    "%s: HAL_TXDESC_NOACK set for an aggregate frame?\n",
969eb6f0de0SAdrian Chadd 			    __func__);
970875a9451SAdrian Chadd 			bf->bf_state.bfs_txflags &= (~HAL_TXDESC_NOACK);
971eb6f0de0SAdrian Chadd 		}
972eb6f0de0SAdrian Chadd 
973eb6f0de0SAdrian Chadd 		/*
974eb6f0de0SAdrian Chadd 		 * Add the now owned buffer (which isn't
975eb6f0de0SAdrian Chadd 		 * on the software TXQ any longer) to our
976eb6f0de0SAdrian Chadd 		 * aggregate frame list.
977eb6f0de0SAdrian Chadd 		 */
978eb6f0de0SAdrian Chadd 		TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
979eb6f0de0SAdrian Chadd 		nframes ++;
980eb6f0de0SAdrian Chadd 
981eb6f0de0SAdrian Chadd 		/* Completion handler */
982eb6f0de0SAdrian Chadd 		bf->bf_comp = ath_tx_aggr_comp;
983eb6f0de0SAdrian Chadd 
984eb6f0de0SAdrian Chadd 		/*
985eb6f0de0SAdrian Chadd 		 * add padding for previous frame to aggregation length
986eb6f0de0SAdrian Chadd 		 */
987eb6f0de0SAdrian Chadd 		al += bpad + al_delta;
988eb6f0de0SAdrian Chadd 
989eb6f0de0SAdrian Chadd 		/*
990eb6f0de0SAdrian Chadd 		 * Calculate delimiters needed for the current frame
991eb6f0de0SAdrian Chadd 		 */
992eb6f0de0SAdrian Chadd 		bf->bf_state.bfs_ndelim =
993eb6f0de0SAdrian Chadd 		    ath_compute_num_delims(sc, bf_first,
994a2d74cc3SAdrian Chadd 		    bf->bf_state.bfs_pktlen, (bf_first == bf));
995eb6f0de0SAdrian Chadd 
996eb6f0de0SAdrian Chadd 		/*
997eb6f0de0SAdrian Chadd 		 * Calculate the padding needed from this set of delimiters,
998eb6f0de0SAdrian Chadd 		 * used when calculating if the next frame will fit in
999eb6f0de0SAdrian Chadd 		 * the aggregate.
1000eb6f0de0SAdrian Chadd 		 */
1001eb6f0de0SAdrian Chadd 		bpad = PADBYTES(al_delta) + (bf->bf_state.bfs_ndelim << 2);
1002eb6f0de0SAdrian Chadd 
1003eb6f0de0SAdrian Chadd 		/*
1004eb6f0de0SAdrian Chadd 		 * Chain the buffers together
1005eb6f0de0SAdrian Chadd 		 */
1006eb6f0de0SAdrian Chadd 		if (bf_prev)
1007eb6f0de0SAdrian Chadd 			bf_prev->bf_next = bf;
1008eb6f0de0SAdrian Chadd 		bf_prev = bf;
1009eb6f0de0SAdrian Chadd 
1010eb6f0de0SAdrian Chadd 		/*
101122a3aee6SAdrian Chadd 		 * If we're leaking frames, just return at this point;
101222a3aee6SAdrian Chadd 		 * we've queued a single frame and we don't want to add
101322a3aee6SAdrian Chadd 		 * any more.
1014eb6f0de0SAdrian Chadd 		 */
101522a3aee6SAdrian Chadd 		if (tid->an->an_leak_count) {
101622a3aee6SAdrian Chadd 			status = ATH_AGGR_LEAK_CLOSED;
101722a3aee6SAdrian Chadd 			break;
101822a3aee6SAdrian Chadd 		}
1019eb6f0de0SAdrian Chadd 
1020eb6f0de0SAdrian Chadd #if 0
1021eb6f0de0SAdrian Chadd 		/*
1022eb6f0de0SAdrian Chadd 		 * terminate aggregation on a small packet boundary
1023eb6f0de0SAdrian Chadd 		 */
1024eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_pktlen < ATH_AGGR_MINPLEN) {
1025eb6f0de0SAdrian Chadd 			status = ATH_AGGR_SHORTPKT;
1026eb6f0de0SAdrian Chadd 			break;
1027eb6f0de0SAdrian Chadd 		}
1028eb6f0de0SAdrian Chadd #endif
1029eb6f0de0SAdrian Chadd 
1030eb6f0de0SAdrian Chadd 	}
1031eb6f0de0SAdrian Chadd 
1032eb6f0de0SAdrian Chadd finish:
1033eb6f0de0SAdrian Chadd 	/*
1034eb6f0de0SAdrian Chadd 	 * Just in case the list was empty when we tried to
1035eb6f0de0SAdrian Chadd 	 * dequeue a packet ..
1036eb6f0de0SAdrian Chadd 	 */
1037eb6f0de0SAdrian Chadd 	if (bf_first) {
1038*cce63444SAdrian Chadd 		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
1039*cce63444SAdrian Chadd 		"%s: al=%d bytes; requested %d bytes\n",
1040*cce63444SAdrian Chadd 		__func__, al, bf_first->bf_state.bfs_rc_maxpktlen);
1041*cce63444SAdrian Chadd 
1042eb6f0de0SAdrian Chadd 		bf_first->bf_state.bfs_al = al;
1043eb6f0de0SAdrian Chadd 		bf_first->bf_state.bfs_nframes = nframes;
1044eb6f0de0SAdrian Chadd 	}
1045eb6f0de0SAdrian Chadd 	return status;
1046eb6f0de0SAdrian Chadd }
1047