if_ath_tx_ht.c revision 233966
1218159Sadrian/*-
2218159Sadrian * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
3218159Sadrian * All rights reserved.
4218159Sadrian *
5218159Sadrian * Redistribution and use in source and binary forms, with or without
6218159Sadrian * modification, are permitted provided that the following conditions
7218159Sadrian * are met:
8218159Sadrian * 1. Redistributions of source code must retain the above copyright
9218159Sadrian *    notice, this list of conditions and the following disclaimer,
10218159Sadrian *    without modification.
11218159Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12218159Sadrian *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13218159Sadrian *    redistribution must be conditioned upon including a substantially
14218159Sadrian *    similar Disclaimer requirement for further binary redistribution.
15218159Sadrian *
16218159Sadrian * NO WARRANTY
17218159Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18218159Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19218159Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20218159Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21218159Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22218159Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23218159Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24218159Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25218159Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26218159Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27218159Sadrian * THE POSSIBILITY OF SUCH DAMAGES.
28218159Sadrian */
29218159Sadrian
30218159Sadrian#include <sys/cdefs.h>
31218159Sadrian__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx_ht.c 233966 2012-04-07 02:01:26Z adrian $");
32218159Sadrian
33218159Sadrian#include "opt_inet.h"
34218159Sadrian#include "opt_ath.h"
35218159Sadrian#include "opt_wlan.h"
36218159Sadrian
37218159Sadrian#include <sys/param.h>
38218159Sadrian#include <sys/systm.h>
39218159Sadrian#include <sys/sysctl.h>
40218159Sadrian#include <sys/mbuf.h>
41218159Sadrian#include <sys/malloc.h>
42218159Sadrian#include <sys/lock.h>
43218159Sadrian#include <sys/mutex.h>
44218159Sadrian#include <sys/kernel.h>
45218159Sadrian#include <sys/socket.h>
46218159Sadrian#include <sys/sockio.h>
47218159Sadrian#include <sys/errno.h>
48218159Sadrian#include <sys/callout.h>
49218159Sadrian#include <sys/bus.h>
50218159Sadrian#include <sys/endian.h>
51218159Sadrian#include <sys/kthread.h>
52218159Sadrian#include <sys/taskqueue.h>
53218159Sadrian#include <sys/priv.h>
54218159Sadrian
55218159Sadrian#include <machine/bus.h>
56218159Sadrian
57218159Sadrian#include <net/if.h>
58218159Sadrian#include <net/if_dl.h>
59218159Sadrian#include <net/if_media.h>
60218159Sadrian#include <net/if_types.h>
61218159Sadrian#include <net/if_arp.h>
62218159Sadrian#include <net/ethernet.h>
63218159Sadrian#include <net/if_llc.h>
64218159Sadrian
65218159Sadrian#include <net80211/ieee80211_var.h>
66218159Sadrian#include <net80211/ieee80211_regdomain.h>
67218159Sadrian#ifdef IEEE80211_SUPPORT_SUPERG
68218159Sadrian#include <net80211/ieee80211_superg.h>
69218159Sadrian#endif
70218159Sadrian#ifdef IEEE80211_SUPPORT_TDMA
71218159Sadrian#include <net80211/ieee80211_tdma.h>
72218159Sadrian#endif
73218159Sadrian
74218159Sadrian#include <net/bpf.h>
75218159Sadrian
76218159Sadrian#ifdef INET
77218159Sadrian#include <netinet/in.h>
78218159Sadrian#include <netinet/if_ether.h>
79218159Sadrian#endif
80218159Sadrian
81218159Sadrian#include <dev/ath/if_athvar.h>
82218159Sadrian#include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
83218159Sadrian#include <dev/ath/ath_hal/ah_diagcodes.h>
84218159Sadrian
85218159Sadrian#ifdef ATH_TX99_DIAG
86218159Sadrian#include <dev/ath/ath_tx99/ath_tx99.h>
87218159Sadrian#endif
88218159Sadrian
89227364Sadrian#include <dev/ath/if_ath_tx.h>		/* XXX for some support functions */
90218159Sadrian#include <dev/ath/if_ath_tx_ht.h>
91227364Sadrian#include <dev/ath/if_athrate.h>
92227364Sadrian#include <dev/ath/if_ath_debug.h>
93218159Sadrian
94218159Sadrian/*
95227364Sadrian * XXX net80211?
96227364Sadrian */
97227364Sadrian#define	IEEE80211_AMPDU_SUBFRAME_DEFAULT		32
98227364Sadrian
99227364Sadrian#define	ATH_AGGR_DELIM_SZ	4	/* delimiter size   */
100227364Sadrian#define	ATH_AGGR_MINPLEN	256	/* in bytes, minimum packet length */
101227364Sadrian#define	ATH_AGGR_ENCRYPTDELIM	10	/* number of delimiters for encryption padding */
102227364Sadrian
103227364Sadrian/*
104227364Sadrian * returns delimiter padding required given the packet length
105227364Sadrian */
106227364Sadrian#define	ATH_AGGR_GET_NDELIM(_len)					\
107227364Sadrian	    (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?	\
108227364Sadrian	    (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
109227364Sadrian
110227364Sadrian#define	PADBYTES(_len)		((4 - ((_len) % 4)) % 4)
111227364Sadrian
112227364Sadrianint ath_max_4ms_framelen[4][32] = {
113227364Sadrian	[MCS_HT20] = {
114227364Sadrian		3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
115227364Sadrian		6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
116227364Sadrian		9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
117227364Sadrian		12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
118227364Sadrian	},
119227364Sadrian	[MCS_HT20_SGI] = {
120227364Sadrian		3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
121227364Sadrian		7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
122227364Sadrian		10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
123227364Sadrian		14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
124227364Sadrian	},
125227364Sadrian	[MCS_HT40] = {
126227364Sadrian		6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
127227364Sadrian		13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
128227364Sadrian		20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
129227364Sadrian		26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
130227364Sadrian	},
131227364Sadrian	[MCS_HT40_SGI] = {
132227364Sadrian		7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
133227364Sadrian		14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
134227364Sadrian		22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
135227364Sadrian		29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
136227364Sadrian	}
137227364Sadrian};
138227364Sadrian
139227364Sadrian/*
140227364Sadrian * XXX should be in net80211
141227364Sadrian */
142227364Sadrianstatic int ieee80211_mpdudensity_map[] = {
143227364Sadrian	0,		/* IEEE80211_HTCAP_MPDUDENSITY_NA */
144227364Sadrian	25,		/* IEEE80211_HTCAP_MPDUDENSITY_025 */
145227364Sadrian	50,		/* IEEE80211_HTCAP_MPDUDENSITY_05 */
146227364Sadrian	100,		/* IEEE80211_HTCAP_MPDUDENSITY_1 */
147227364Sadrian	200,		/* IEEE80211_HTCAP_MPDUDENSITY_2 */
148227364Sadrian	400,		/* IEEE80211_HTCAP_MPDUDENSITY_4 */
149227364Sadrian	800,		/* IEEE80211_HTCAP_MPDUDENSITY_8 */
150227364Sadrian	1600,		/* IEEE80211_HTCAP_MPDUDENSITY_16 */
151227364Sadrian};
152227364Sadrian
153227364Sadrian/*
154227364Sadrian * XXX should be in the HAL/net80211 ?
155227364Sadrian */
156227364Sadrian#define	BITS_PER_BYTE		8
157227364Sadrian#define	OFDM_PLCP_BITS		22
158227364Sadrian#define	HT_RC_2_MCS(_rc)	((_rc) & 0x7f)
159227364Sadrian#define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
160227364Sadrian#define	L_STF			8
161227364Sadrian#define	L_LTF			8
162227364Sadrian#define	L_SIG			4
163227364Sadrian#define	HT_SIG			8
164227364Sadrian#define	HT_STF			4
165227364Sadrian#define	HT_LTF(_ns)		(4 * (_ns))
166227364Sadrian#define	SYMBOL_TIME(_ns)	((_ns) << 2)		// ns * 4 us
167227364Sadrian#define	SYMBOL_TIME_HALFGI(_ns)	(((_ns) * 18 + 4) / 5)	// ns * 3.6 us
168227364Sadrian#define	NUM_SYMBOLS_PER_USEC(_usec)	(_usec >> 2)
169227364Sadrian#define	NUM_SYMBOLS_PER_USEC_HALFGI(_usec)	(((_usec*5)-4)/18)
170227364Sadrian#define	IS_HT_RATE(_rate)	((_rate) & 0x80)
171227364Sadrian
172227364Sadrianconst uint32_t bits_per_symbol[][2] = {
173227364Sadrian    /* 20MHz 40MHz */
174227364Sadrian    {    26,   54 },     //  0: BPSK
175227364Sadrian    {    52,  108 },     //  1: QPSK 1/2
176227364Sadrian    {    78,  162 },     //  2: QPSK 3/4
177227364Sadrian    {   104,  216 },     //  3: 16-QAM 1/2
178227364Sadrian    {   156,  324 },     //  4: 16-QAM 3/4
179227364Sadrian    {   208,  432 },     //  5: 64-QAM 2/3
180227364Sadrian    {   234,  486 },     //  6: 64-QAM 3/4
181227364Sadrian    {   260,  540 },     //  7: 64-QAM 5/6
182227364Sadrian    {    52,  108 },     //  8: BPSK
183227364Sadrian    {   104,  216 },     //  9: QPSK 1/2
184227364Sadrian    {   156,  324 },     // 10: QPSK 3/4
185227364Sadrian    {   208,  432 },     // 11: 16-QAM 1/2
186227364Sadrian    {   312,  648 },     // 12: 16-QAM 3/4
187227364Sadrian    {   416,  864 },     // 13: 64-QAM 2/3
188227364Sadrian    {   468,  972 },     // 14: 64-QAM 3/4
189227364Sadrian    {   520, 1080 },     // 15: 64-QAM 5/6
190227364Sadrian    {    78,  162 },     // 16: BPSK
191227364Sadrian    {   156,  324 },     // 17: QPSK 1/2
192227364Sadrian    {   234,  486 },     // 18: QPSK 3/4
193227364Sadrian    {   312,  648 },     // 19: 16-QAM 1/2
194227364Sadrian    {   468,  972 },     // 20: 16-QAM 3/4
195227364Sadrian    {   624, 1296 },     // 21: 64-QAM 2/3
196227364Sadrian    {   702, 1458 },     // 22: 64-QAM 3/4
197227364Sadrian    {   780, 1620 },     // 23: 64-QAM 5/6
198227364Sadrian    {   104,  216 },     // 24: BPSK
199227364Sadrian    {   208,  432 },     // 25: QPSK 1/2
200227364Sadrian    {   312,  648 },     // 26: QPSK 3/4
201227364Sadrian    {   416,  864 },     // 27: 16-QAM 1/2
202227364Sadrian    {   624, 1296 },     // 28: 16-QAM 3/4
203227364Sadrian    {   832, 1728 },     // 29: 64-QAM 2/3
204227364Sadrian    {   936, 1944 },     // 30: 64-QAM 3/4
205227364Sadrian    {  1040, 2160 },     // 31: 64-QAM 5/6
206227364Sadrian};
207227364Sadrian
208227364Sadrian/*
209227364Sadrian * Fill in the rate array information based on the current
210227364Sadrian * node configuration and the choices made by the rate
211227364Sadrian * selection code and ath_buf setup code.
212227364Sadrian *
213227364Sadrian * Later on, this may end up also being made by the
214227364Sadrian * rate control code, but for now it can live here.
215227364Sadrian *
216227364Sadrian * This needs to be called just before the packet is
217227364Sadrian * queued to the software queue or hardware queue,
218227364Sadrian * so all of the needed fields in bf_state are setup.
219227364Sadrian */
220227364Sadrianvoid
221227364Sadrianath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
222227364Sadrian{
223227364Sadrian	struct ieee80211_node *ni = bf->bf_node;
224227364Sadrian	struct ieee80211com *ic = ni->ni_ic;
225227364Sadrian	const HAL_RATE_TABLE *rt = sc->sc_currates;
226227364Sadrian	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
227227364Sadrian	uint8_t rate;
228227364Sadrian	int i;
229227364Sadrian
230227364Sadrian	for (i = 0; i < ATH_RC_NUM; i++) {
231227364Sadrian		rc[i].flags = 0;
232227364Sadrian		if (rc[i].tries == 0)
233227364Sadrian			continue;
234227364Sadrian
235227364Sadrian		rate = rt->info[rc[i].rix].rateCode;
236227364Sadrian
237227364Sadrian		/*
238227364Sadrian		 * XXX only do this for legacy rates?
239227364Sadrian		 */
240227364Sadrian		if (bf->bf_state.bfs_shpream)
241227364Sadrian			rate |= rt->info[rc[i].rix].shortPreamble;
242227364Sadrian
243227364Sadrian		/*
244227364Sadrian		 * Save this, used by the TX and completion code
245227364Sadrian		 */
246227364Sadrian		rc[i].ratecode = rate;
247227364Sadrian
248233966Sadrian		if (bf->bf_state.bfs_txflags &
249227364Sadrian		    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
250227364Sadrian			rc[i].flags |= ATH_RC_RTSCTS_FLAG;
251227364Sadrian
252227364Sadrian		/* Only enable shortgi, 2040, dual-stream if HT is set */
253227364Sadrian		if (IS_HT_RATE(rate)) {
254227364Sadrian			rc[i].flags |= ATH_RC_HT_FLAG;
255227364Sadrian
256227364Sadrian			if (ni->ni_chw == 40)
257227364Sadrian				rc[i].flags |= ATH_RC_CW40_FLAG;
258227364Sadrian
259227364Sadrian			if (ni->ni_chw == 40 &&
260227364Sadrian			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
261227364Sadrian			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
262227364Sadrian				rc[i].flags |= ATH_RC_SGI_FLAG;
263227364Sadrian
264227364Sadrian			if (ni->ni_chw == 20 &&
265227364Sadrian			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
266227364Sadrian			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
267227364Sadrian				rc[i].flags |= ATH_RC_SGI_FLAG;
268227364Sadrian
269227364Sadrian			/* XXX dual stream? and 3-stream? */
270227364Sadrian		}
271227364Sadrian
272227364Sadrian		/*
273227364Sadrian		 * Calculate the maximum 4ms frame length based
274227364Sadrian		 * on the MCS rate, SGI and channel width flags.
275227364Sadrian		 */
276227364Sadrian		if ((rc[i].flags & ATH_RC_HT_FLAG) &&
277227364Sadrian		    (HT_RC_2_MCS(rate) < 32)) {
278227364Sadrian			int j;
279227364Sadrian			if (rc[i].flags & ATH_RC_CW40_FLAG) {
280227364Sadrian				if (rc[i].flags & ATH_RC_SGI_FLAG)
281227364Sadrian					j = MCS_HT40_SGI;
282227364Sadrian				else
283227364Sadrian					j = MCS_HT40;
284227364Sadrian			} else {
285227364Sadrian				if (rc[i].flags & ATH_RC_SGI_FLAG)
286227364Sadrian					j = MCS_HT20_SGI;
287227364Sadrian				else
288227364Sadrian					j = MCS_HT20;
289227364Sadrian			}
290227364Sadrian			rc[i].max4msframelen =
291227364Sadrian			    ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)];
292227364Sadrian		} else
293227364Sadrian			rc[i].max4msframelen = 0;
294227364Sadrian		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
295227364Sadrian		    "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
296227364Sadrian		    __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
297227364Sadrian	}
298227364Sadrian}
299227364Sadrian
300227364Sadrian/*
301227364Sadrian * Return the number of delimiters to be added to
302227364Sadrian * meet the minimum required mpdudensity.
303227364Sadrian *
304227364Sadrian * Caller should make sure that the rate is HT.
305227364Sadrian *
306227364Sadrian * TODO: is this delimiter calculation supposed to be the
307227364Sadrian * total frame length, the hdr length, the data length (including
308227364Sadrian * delimiters, padding, CRC, etc) or ?
309227364Sadrian *
310227364Sadrian * TODO: this should ensure that the rate control information
311227364Sadrian * HAS been setup for the first rate.
312227364Sadrian *
313227364Sadrian * TODO: ensure this is only called for MCS rates.
314227364Sadrian *
315227364Sadrian * TODO: enforce MCS < 31
316227364Sadrian */
317227364Sadrianstatic int
318227364Sadrianath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf,
319227364Sadrian    uint16_t pktlen)
320227364Sadrian{
321227364Sadrian	const HAL_RATE_TABLE *rt = sc->sc_currates;
322227364Sadrian	struct ieee80211_node *ni = first_bf->bf_node;
323227364Sadrian	struct ieee80211vap *vap = ni->ni_vap;
324227364Sadrian	int ndelim, mindelim = 0;
325227364Sadrian	int mpdudensity;	 /* in 1/100'th of a microsecond */
326227364Sadrian	uint8_t rc, rix, flags;
327227364Sadrian	int width, half_gi;
328227364Sadrian	uint32_t nsymbits, nsymbols;
329227364Sadrian	uint16_t minlen;
330227364Sadrian
331227364Sadrian	/*
332227364Sadrian	 * vap->iv_ampdu_density is a value, rather than the actual
333227364Sadrian	 * density.
334227364Sadrian	 */
335227364Sadrian	if (vap->iv_ampdu_density > IEEE80211_HTCAP_MPDUDENSITY_16)
336227364Sadrian		mpdudensity = 1600;		/* maximum density */
337227364Sadrian	else
338227364Sadrian		mpdudensity = ieee80211_mpdudensity_map[vap->iv_ampdu_density];
339227364Sadrian
340227364Sadrian	/* Select standard number of delimiters based on frame length */
341227364Sadrian	ndelim = ATH_AGGR_GET_NDELIM(pktlen);
342227364Sadrian
343227364Sadrian	/*
344227364Sadrian	 * If encryption is enabled, add extra delimiters to let the
345227364Sadrian	 * crypto hardware catch up. This could be tuned per-MAC and
346227364Sadrian	 * per-rate, but for now we'll simply assume encryption is
347227364Sadrian	 * always enabled.
348227364Sadrian	 */
349227364Sadrian	ndelim += ATH_AGGR_ENCRYPTDELIM;
350227364Sadrian
351227364Sadrian	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
352227364Sadrian	    "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n",
353227364Sadrian	    __func__, pktlen, ndelim, mpdudensity);
354227364Sadrian
355227364Sadrian	/*
356227364Sadrian	 * If the MPDU density is 0, we can return here.
357227364Sadrian	 * Otherwise, we need to convert the desired mpdudensity
358227364Sadrian	 * into a byte length, based on the rate in the subframe.
359227364Sadrian	 */
360227364Sadrian	if (mpdudensity == 0)
361227364Sadrian		return ndelim;
362227364Sadrian
363227364Sadrian	/*
364227364Sadrian	 * Convert desired mpdu density from microeconds to bytes based
365227364Sadrian	 * on highest rate in rate series (i.e. first rate) to determine
366227364Sadrian	 * required minimum length for subframe. Take into account
367227364Sadrian	 * whether high rate is 20 or 40Mhz and half or full GI.
368227364Sadrian	 */
369227364Sadrian	rix = first_bf->bf_state.bfs_rc[0].rix;
370227364Sadrian	rc = rt->info[rix].rateCode;
371227364Sadrian	flags = first_bf->bf_state.bfs_rc[0].flags;
372227364Sadrian	width = !! (flags & ATH_RC_CW40_FLAG);
373227364Sadrian	half_gi = !! (flags & ATH_RC_SGI_FLAG);
374227364Sadrian
375227364Sadrian	/*
376227364Sadrian	 * mpdudensity is in 1/100th of a usec, so divide by 100
377227364Sadrian	 */
378227364Sadrian	if (half_gi)
379227364Sadrian		nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
380227364Sadrian	else
381227364Sadrian		nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
382227364Sadrian	nsymbols /= 100;
383227364Sadrian
384227364Sadrian	if (nsymbols == 0)
385227364Sadrian		nsymbols = 1;
386227364Sadrian
387227364Sadrian	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
388227364Sadrian	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
389227364Sadrian
390227364Sadrian	/*
391227364Sadrian	 * Min length is the minimum frame length for the
392227364Sadrian	 * required MPDU density.
393227364Sadrian	 */
394227364Sadrian	if (pktlen < minlen) {
395227364Sadrian		mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ;
396227364Sadrian		ndelim = MAX(mindelim, ndelim);
397227364Sadrian	}
398227364Sadrian
399227364Sadrian	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
400227364Sadrian	    "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n",
401227364Sadrian	    __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim);
402227364Sadrian
403227364Sadrian	return ndelim;
404227364Sadrian}
405227364Sadrian
406227364Sadrian/*
407227364Sadrian * Fetch the aggregation limit.
408227364Sadrian *
409227364Sadrian * It's the lowest of the four rate series 4ms frame length.
410227364Sadrian */
411227364Sadrianstatic int
412227364Sadrianath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf)
413227364Sadrian{
414227364Sadrian	int amin = 65530;
415227364Sadrian	int i;
416227364Sadrian
417227364Sadrian	for (i = 0; i < 4; i++) {
418227364Sadrian		if (bf->bf_state.bfs_rc[i].tries == 0)
419227364Sadrian			continue;
420227364Sadrian		amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen);
421227364Sadrian	}
422227364Sadrian
423227364Sadrian	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: max frame len= %d\n",
424227364Sadrian	    __func__, amin);
425227364Sadrian
426227364Sadrian	return amin;
427227364Sadrian}
428227364Sadrian
429227364Sadrian/*
430218159Sadrian * Setup a 11n rate series structure
431218159Sadrian *
432218159Sadrian * This should be called for both legacy and MCS rates.
433227364Sadrian *
434227364Sadrian * It, along with ath_buf_set_rate, must be called -after- a burst
435227364Sadrian * or aggregate is setup.
436218159Sadrian */
437218159Sadrianstatic void
438218159Sadrianath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
439227364Sadrian    struct ath_buf *bf, HAL_11N_RATE_SERIES *series)
440218159Sadrian{
441219588Sadrian#define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
442218159Sadrian	struct ieee80211com *ic = ni->ni_ic;
443218159Sadrian	struct ath_hal *ah = sc->sc_ah;
444218159Sadrian	HAL_BOOL shortPreamble = AH_FALSE;
445218159Sadrian	const HAL_RATE_TABLE *rt = sc->sc_currates;
446218159Sadrian	int i;
447227364Sadrian	int pktlen;
448233966Sadrian	int flags = bf->bf_state.bfs_txflags;
449227364Sadrian	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
450218159Sadrian
451218159Sadrian	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
452218159Sadrian	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
453218159Sadrian		shortPreamble = AH_TRUE;
454218159Sadrian
455227364Sadrian	/*
456227364Sadrian	 * If this is the first frame in an aggregate series,
457227364Sadrian	 * use the aggregate length.
458227364Sadrian	 */
459227364Sadrian	if (bf->bf_state.bfs_aggr)
460227364Sadrian		pktlen = bf->bf_state.bfs_al;
461227364Sadrian	else
462227364Sadrian		pktlen = bf->bf_state.bfs_pktlen;
463227364Sadrian
464227364Sadrian	/*
465227364Sadrian	 * XXX TODO: modify this routine to use the bfs_rc[x].flags
466227364Sadrian	 * XXX fields.
467227364Sadrian	 */
468218159Sadrian	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
469218159Sadrian	for (i = 0; i < 4;  i++) {
470218931Sadrian		/* Only set flags for actual TX attempts */
471227364Sadrian		if (rc[i].tries == 0)
472218931Sadrian			continue;
473218931Sadrian
474227364Sadrian		series[i].Tries = rc[i].tries;
475218931Sadrian
476218931Sadrian		/*
477218931Sadrian		 * XXX this isn't strictly correct - sc_txchainmask
478218931Sadrian		 * XXX isn't the currently active chainmask;
479218931Sadrian		 * XXX it's the interface chainmask at startup.
480218931Sadrian		 * XXX It's overridden in the HAL rate scenario function
481218931Sadrian		 * XXX for now.
482218931Sadrian		 */
483218159Sadrian		series[i].ChSel = sc->sc_txchainmask;
484218931Sadrian
485218935Sadrian		if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
486218159Sadrian			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
487218931Sadrian
488219985Sadrian		/*
489219985Sadrian		 * Transmit 40MHz frames only if the node has negotiated
490219985Sadrian		 * it rather than whether the node is capable of it or not.
491219985Sadrian	 	 * It's subtly different in the hostap case.
492219985Sadrian	 	 */
493219985Sadrian		if (ni->ni_chw == 40)
494219985Sadrian			series[i].RateFlags |= HAL_RATESERIES_2040;
495222498Sadrian
496218779Sadrian		/*
497222498Sadrian		 * Set short-GI only if the node has advertised it
498222498Sadrian		 * the channel width is suitable, and we support it.
499222498Sadrian		 * We don't currently have a "negotiated" set of bits -
500222498Sadrian		 * ni_htcap is what the remote end sends, not what this
501222498Sadrian		 * node is capable of.
502218779Sadrian		 */
503222498Sadrian		if (ni->ni_chw == 40 &&
504222498Sadrian		    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
505222498Sadrian		    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
506218159Sadrian			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
507218159Sadrian
508222498Sadrian		if (ni->ni_chw == 20 &&
509222498Sadrian		    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
510222498Sadrian		    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
511222498Sadrian			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
512222498Sadrian
513227364Sadrian		series[i].Rate = rt->info[rc[i].rix].rateCode;
514218159Sadrian
515218159Sadrian		/* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */
516218907Sadrian		if (series[i].Rate & IEEE80211_RATE_MCS) {
517218159Sadrian			series[i].PktDuration =
518218159Sadrian			    ath_computedur_ht(pktlen
519218907Sadrian				, series[i].Rate
520219588Sadrian				, HT_RC_2_STREAMS(series[i].Rate)
521219588Sadrian				, series[i].RateFlags & HAL_RATESERIES_2040
522218566Sadrian				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
523218159Sadrian		} else {
524219870Sadrian			if (shortPreamble)
525227364Sadrian				series[i].Rate |=
526227364Sadrian				    rt->info[rc[i].rix].shortPreamble;
527218159Sadrian			series[i].PktDuration = ath_hal_computetxtime(ah,
528227364Sadrian			    rt, pktlen, rc[i].rix, shortPreamble);
529218159Sadrian		}
530218159Sadrian	}
531219588Sadrian#undef	HT_RC_2_STREAMS
532218159Sadrian}
533218159Sadrian
534218159Sadrian#if 0
535218159Sadrianstatic void
536218159Sadrianath_rateseries_print(HAL_11N_RATE_SERIES *series)
537218159Sadrian{
538218159Sadrian	int i;
539218159Sadrian	for (i = 0; i < 4; i++) {
540218159Sadrian		printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n",
541218159Sadrian		    i,
542218159Sadrian		    series[i].Rate,
543218159Sadrian		    series[i].Tries,
544218159Sadrian		    series[i].PktDuration,
545218159Sadrian		    series[i].ChSel,
546218159Sadrian		    series[i].RateFlags);
547218159Sadrian	}
548218159Sadrian}
549218159Sadrian#endif
550218159Sadrian
551218159Sadrian/*
552218159Sadrian * Setup the 11n rate scenario and burst duration for the given TX descriptor
553218159Sadrian * list.
554218159Sadrian *
555218159Sadrian * This isn't useful for sending beacon frames, which has different needs
556218159Sadrian * wrt what's passed into the rate scenario function.
557218159Sadrian */
558218159Sadrian
559218159Sadrianvoid
560227364Sadrianath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni,
561227364Sadrian    struct ath_buf *bf)
562218159Sadrian{
563218159Sadrian	HAL_11N_RATE_SERIES series[4];
564218159Sadrian	struct ath_desc *ds = bf->bf_desc;
565218159Sadrian	struct ath_desc *lastds = NULL;
566218159Sadrian	struct ath_hal *ah = sc->sc_ah;
567227364Sadrian	int is_pspoll = (bf->bf_state.bfs_atype == HAL_PKT_TYPE_PSPOLL);
568227364Sadrian	int ctsrate = bf->bf_state.bfs_ctsrate;
569233966Sadrian	int flags = bf->bf_state.bfs_txflags;
570218159Sadrian
571218159Sadrian	/* Setup rate scenario */
572218159Sadrian	memset(&series, 0, sizeof(series));
573218159Sadrian
574227364Sadrian	ath_rateseries_setup(sc, ni, bf, series);
575218159Sadrian
576218159Sadrian	/* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */
577218159Sadrian
578218159Sadrian	/* Enforce RTS and CTS are mutually exclusive */
579218159Sadrian
580218159Sadrian	/* Get a pointer to the last tx descriptor in the list */
581227364Sadrian	lastds = bf->bf_lastds;
582218159Sadrian
583218935Sadrian#if 0
584218935Sadrian	printf("pktlen: %d; flags 0x%x\n", pktlen, flags);
585218935Sadrian	ath_rateseries_print(series);
586218935Sadrian#endif
587218935Sadrian
588218159Sadrian	/* Set rate scenario */
589218159Sadrian	ath_hal_set11nratescenario(ah, ds,
590218593Sadrian	    !is_pspoll,	/* whether to override the duration or not */
591218593Sadrian			/* don't allow hardware to override the duration on ps-poll packets */
592218159Sadrian	    ctsrate,	/* rts/cts rate */
593218159Sadrian	    series,	/* 11n rate series */
594218159Sadrian	    4,		/* number of series */
595218159Sadrian	    flags);
596218159Sadrian
597218159Sadrian	/* Setup the last descriptor in the chain */
598218159Sadrian	ath_hal_setuplasttxdesc(ah, lastds, ds);
599218159Sadrian
600218159Sadrian	/* Set burst duration */
601227364Sadrian	/*
602227364Sadrian	 * This is only required when doing 11n burst, not aggregation
603227364Sadrian	 * ie, if there's a second frame in a RIFS or A-MPDU burst
604227364Sadrian	 * w/ >1 A-MPDU frame bursting back to back.
605227364Sadrian	 * Normal A-MPDU doesn't do bursting -between- aggregates.
606227364Sadrian	 *
607227364Sadrian	 * .. and it's highly likely this won't ever be implemented
608227364Sadrian	 */
609218159Sadrian	//ath_hal_set11nburstduration(ah, ds, 8192);
610218159Sadrian}
611227364Sadrian
612227364Sadrian/*
613227364Sadrian * Form an aggregate packet list.
614227364Sadrian *
615227364Sadrian * This function enforces the aggregate restrictions/requirements.
616227364Sadrian *
617227364Sadrian * These are:
618227364Sadrian *
619227364Sadrian * + The aggregate size maximum (64k for AR9160 and later, 8K for
620227364Sadrian *   AR5416 when doing RTS frame protection.)
621227364Sadrian * + Maximum number of sub-frames for an aggregate
622227364Sadrian * + The aggregate delimiter size, giving MACs time to do whatever is
623227364Sadrian *   needed before each frame
624227364Sadrian * + Enforce the BAW limit
625227364Sadrian *
626227364Sadrian * Each descriptor queued should have the DMA setup.
627227364Sadrian * The rate series, descriptor setup, linking, etc is all done
628227364Sadrian * externally. This routine simply chains them together.
629227364Sadrian * ath_tx_setds_11n() will take care of configuring the per-
630227364Sadrian * descriptor setup, and ath_buf_set_rate() will configure the
631227364Sadrian * rate control.
632227364Sadrian *
633227364Sadrian * Note that the TID lock is only grabbed when dequeuing packets from
634227364Sadrian * the TID queue. If some code in another thread adds to the head of this
635227364Sadrian * list, very strange behaviour will occur. Since retransmission is the
636227364Sadrian * only reason this will occur, and this routine is designed to be called
637227364Sadrian * from within the scheduler task, it won't ever clash with the completion
638227364Sadrian * task.
639227364Sadrian *
640227364Sadrian * So if you want to call this from an upper layer context (eg, to direct-
641227364Sadrian * dispatch aggregate frames to the hardware), please keep this in mind.
642227364Sadrian */
643227364SadrianATH_AGGR_STATUS
644227364Sadrianath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, struct ath_tid *tid,
645227364Sadrian    ath_bufhead *bf_q)
646227364Sadrian{
647233227Sadrian	struct ieee80211_node *ni = &an->an_node;
648227364Sadrian	struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
649227364Sadrian	int nframes = 0;
650227364Sadrian	uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw;
651227364Sadrian	struct ieee80211_tx_ampdu *tap;
652227364Sadrian	int status = ATH_AGGR_DONE;
653227364Sadrian	int prev_frames = 0;	/* XXX for AR5416 burst, not done here */
654227364Sadrian	int prev_al = 0;	/* XXX also for AR5416 burst */
655227364Sadrian
656227364Sadrian	ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
657227364Sadrian
658227364Sadrian	tap = ath_tx_get_tx_tid(an, tid->tid);
659227364Sadrian	if (tap == NULL) {
660227364Sadrian		status = ATH_AGGR_ERROR;
661227364Sadrian		goto finish;
662227364Sadrian	}
663227364Sadrian
664227364Sadrian	h_baw = tap->txa_wnd / 2;
665227364Sadrian
666227364Sadrian	for (;;) {
667227364Sadrian		bf = TAILQ_FIRST(&tid->axq_q);
668227364Sadrian		if (bf_first == NULL)
669227364Sadrian			bf_first = bf;
670227364Sadrian		if (bf == NULL) {
671227364Sadrian			status = ATH_AGGR_DONE;
672227364Sadrian			break;
673227364Sadrian		} else {
674227364Sadrian			/*
675227364Sadrian			 * It's the first frame;
676227364Sadrian			 * set the aggregation limit based on the
677227364Sadrian			 * rate control decision that has been made.
678227364Sadrian			 */
679227364Sadrian			aggr_limit = ath_get_aggr_limit(sc, bf_first);
680227364Sadrian		}
681227364Sadrian
682227364Sadrian		/* Set this early just so things don't get confused */
683227364Sadrian		bf->bf_next = NULL;
684227364Sadrian
685227364Sadrian		/*
686227364Sadrian		 * Don't unlock the tid lock until we're sure we are going
687227364Sadrian		 * to queue this frame.
688227364Sadrian		 */
689227364Sadrian
690227364Sadrian		/*
691227364Sadrian		 * If the frame doesn't have a sequence number that we're
692227364Sadrian		 * tracking in the BAW (eg NULL QOS data frame), we can't
693227364Sadrian		 * aggregate it. Stop the aggregation process; the sender
694227364Sadrian		 * can then TX what's in the list thus far and then
695227364Sadrian		 * TX the frame individually.
696227364Sadrian		 */
697227364Sadrian		if (! bf->bf_state.bfs_dobaw) {
698227364Sadrian			status = ATH_AGGR_NONAGGR;
699227364Sadrian			break;
700227364Sadrian		}
701227364Sadrian
702227364Sadrian		/*
703227364Sadrian		 * If any of the rates are non-HT, this packet
704227364Sadrian		 * can't be aggregated.
705227364Sadrian		 * XXX TODO: add a bf_state flag which gets marked
706227364Sadrian		 * if any active rate is non-HT.
707227364Sadrian		 */
708227364Sadrian
709227364Sadrian		/*
710227364Sadrian		 * XXX TODO: AR5416 has an 8K aggregation size limit
711227364Sadrian		 * when RTS is enabled, and RTS is required for dual-stream
712227364Sadrian		 * rates.
713227364Sadrian		 *
714227364Sadrian		 * For now, limit all aggregates for the AR5416 to be 8K.
715227364Sadrian		 */
716227364Sadrian
717227364Sadrian		/*
718227364Sadrian		 * do not exceed aggregation limit
719227364Sadrian		 */
720227364Sadrian		al_delta = ATH_AGGR_DELIM_SZ + bf->bf_state.bfs_pktlen;
721227364Sadrian		if (nframes &&
722227364Sadrian		    (aggr_limit < (al + bpad + al_delta + prev_al))) {
723227364Sadrian			status = ATH_AGGR_LIMITED;
724227364Sadrian			break;
725227364Sadrian		}
726227364Sadrian
727227364Sadrian		/*
728227364Sadrian		 * Do not exceed subframe limit.
729227364Sadrian		 */
730227364Sadrian		if ((nframes + prev_frames) >= MIN((h_baw),
731227364Sadrian		    IEEE80211_AMPDU_SUBFRAME_DEFAULT)) {
732227364Sadrian			status = ATH_AGGR_LIMITED;
733227364Sadrian			break;
734227364Sadrian		}
735227364Sadrian
736227364Sadrian		/*
737233227Sadrian		 * TODO: If it's _before_ the BAW left edge, complain very loudly.
738233227Sadrian		 * This means something (else) has slid the left edge along
739233227Sadrian		 * before we got a chance to be TXed.
740233227Sadrian		 */
741233227Sadrian
742233227Sadrian		/*
743233227Sadrian		 * Check if we have space in the BAW for this frame before
744233227Sadrian		 * we add it.
745233227Sadrian		 *
746233227Sadrian		 * see ath_tx_xmit_aggr() for more info.
747233227Sadrian		 */
748233227Sadrian		if (bf->bf_state.bfs_dobaw) {
749233514Sadrian			ieee80211_seq seqno;
750233514Sadrian
751233514Sadrian			/*
752233514Sadrian			 * If the sequence number is allocated, use it.
753233514Sadrian			 * Otherwise, use the sequence number we WOULD
754233514Sadrian			 * allocate.
755233514Sadrian			 */
756233514Sadrian			if (bf->bf_state.bfs_seqno_assigned)
757233514Sadrian				seqno = SEQNO(bf->bf_state.bfs_seqno);
758233514Sadrian			else
759233514Sadrian				seqno = ni->ni_txseqs[bf->bf_state.bfs_tid];
760233514Sadrian
761233514Sadrian			/*
762233514Sadrian			 * Check whether either the currently allocated
763233514Sadrian			 * sequence number _OR_ the to-be allocated
764233514Sadrian			 * sequence number is inside the BAW.
765233514Sadrian			 */
766233227Sadrian			if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
767233514Sadrian			    seqno)) {
768233227Sadrian				status = ATH_AGGR_BAW_CLOSED;
769233227Sadrian				break;
770233227Sadrian			}
771233514Sadrian
772233227Sadrian			/* XXX check for bfs_need_seqno? */
773233227Sadrian			if (! bf->bf_state.bfs_seqno_assigned) {
774233514Sadrian				int seqno;
775233227Sadrian				seqno = ath_tx_tid_seqno_assign(sc, ni, bf, bf->bf_m);
776233227Sadrian				if (seqno < 0) {
777233227Sadrian					device_printf(sc->sc_dev,
778233227Sadrian					    "%s: bf=%p, huh, seqno=-1?\n",
779233227Sadrian					    __func__,
780233227Sadrian					    bf);
781233227Sadrian					/* XXX what can we even do here? */
782233227Sadrian				}
783233227Sadrian				/* Flush seqno update to RAM */
784233227Sadrian				/*
785233227Sadrian				 * XXX This is required because the dmasetup
786233227Sadrian				 * XXX is done early rather than at dispatch
787233227Sadrian				 * XXX time. Ew, we should fix this!
788233227Sadrian				 */
789233227Sadrian				bus_dmamap_sync(sc->sc_dmat, bf->bf_dmamap,
790233227Sadrian				    BUS_DMASYNC_PREWRITE);
791233227Sadrian			}
792233227Sadrian		}
793233227Sadrian
794233227Sadrian		/*
795233227Sadrian		 * If the packet has a sequence number, do not
796233227Sadrian		 * step outside of the block-ack window.
797233227Sadrian		 */
798233227Sadrian		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
799233227Sadrian		    SEQNO(bf->bf_state.bfs_seqno))) {
800233227Sadrian			device_printf(sc->sc_dev,
801233227Sadrian			    "%s: bf=%p, seqno=%d, outside?!\n",
802233227Sadrian			    __func__, bf, SEQNO(bf->bf_state.bfs_seqno));
803233227Sadrian			status = ATH_AGGR_BAW_CLOSED;
804233227Sadrian			break;
805233227Sadrian		}
806233227Sadrian
807233227Sadrian		/*
808227364Sadrian		 * this packet is part of an aggregate.
809227364Sadrian		 */
810227364Sadrian		ATH_TXQ_REMOVE(tid, bf, bf_list);
811227364Sadrian
812227364Sadrian		/* The TID lock is required for the BAW update */
813227364Sadrian		ath_tx_addto_baw(sc, an, tid, bf);
814227364Sadrian		bf->bf_state.bfs_addedbaw = 1;
815227364Sadrian
816227364Sadrian		/*
817227364Sadrian		 * XXX TODO: If any frame in the aggregate requires RTS/CTS,
818227364Sadrian		 * set the first frame.
819227364Sadrian		 */
820227364Sadrian
821227364Sadrian		/*
822227364Sadrian		 * XXX enforce ACK for aggregate frames (this needs to be
823227364Sadrian		 * XXX handled more gracefully?
824227364Sadrian		 */
825233966Sadrian		if (bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) {
826227364Sadrian			device_printf(sc->sc_dev,
827227364Sadrian			    "%s: HAL_TXDESC_NOACK set for an aggregate frame?\n",
828227364Sadrian			    __func__);
829233966Sadrian			bf->bf_state.bfs_txflags &= (~HAL_TXDESC_NOACK);
830227364Sadrian		}
831227364Sadrian
832227364Sadrian		/*
833227364Sadrian		 * Add the now owned buffer (which isn't
834227364Sadrian		 * on the software TXQ any longer) to our
835227364Sadrian		 * aggregate frame list.
836227364Sadrian		 */
837227364Sadrian		TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
838227364Sadrian		nframes ++;
839227364Sadrian
840227364Sadrian		/* Completion handler */
841227364Sadrian		bf->bf_comp = ath_tx_aggr_comp;
842227364Sadrian
843227364Sadrian		/*
844227364Sadrian		 * add padding for previous frame to aggregation length
845227364Sadrian		 */
846227364Sadrian		al += bpad + al_delta;
847227364Sadrian
848227364Sadrian		/*
849227364Sadrian		 * Calculate delimiters needed for the current frame
850227364Sadrian		 */
851227364Sadrian		bf->bf_state.bfs_ndelim =
852227364Sadrian		    ath_compute_num_delims(sc, bf_first,
853227364Sadrian		    bf->bf_state.bfs_pktlen);
854227364Sadrian
855227364Sadrian		/*
856227364Sadrian		 * Calculate the padding needed from this set of delimiters,
857227364Sadrian		 * used when calculating if the next frame will fit in
858227364Sadrian		 * the aggregate.
859227364Sadrian		 */
860227364Sadrian		bpad = PADBYTES(al_delta) + (bf->bf_state.bfs_ndelim << 2);
861227364Sadrian
862227364Sadrian		/*
863227364Sadrian		 * Chain the buffers together
864227364Sadrian		 */
865227364Sadrian		if (bf_prev)
866227364Sadrian			bf_prev->bf_next = bf;
867227364Sadrian		bf_prev = bf;
868227364Sadrian
869227364Sadrian		/*
870227364Sadrian		 * XXX TODO: if any sub-frames have RTS/CTS enabled;
871227364Sadrian		 * enable it for the entire aggregate.
872227364Sadrian		 */
873227364Sadrian
874227364Sadrian#if 0
875227364Sadrian		/*
876227364Sadrian		 * terminate aggregation on a small packet boundary
877227364Sadrian		 */
878227364Sadrian		if (bf->bf_state.bfs_pktlen < ATH_AGGR_MINPLEN) {
879227364Sadrian			status = ATH_AGGR_SHORTPKT;
880227364Sadrian			break;
881227364Sadrian		}
882227364Sadrian#endif
883227364Sadrian
884227364Sadrian	}
885227364Sadrian
886227364Sadrianfinish:
887227364Sadrian	/*
888227364Sadrian	 * Just in case the list was empty when we tried to
889227364Sadrian	 * dequeue a packet ..
890227364Sadrian	 */
891227364Sadrian	if (bf_first) {
892227364Sadrian		bf_first->bf_state.bfs_al = al;
893227364Sadrian		bf_first->bf_state.bfs_nframes = nframes;
894227364Sadrian	}
895227364Sadrian	return status;
896227364Sadrian}
897