xref: /freebsd/sys/dev/ath/if_ath_tx_ht.c (revision 7ff1939db0436c79d58549fd5bfc69b9ab233413)
14b44f6f2SAdrian Chadd /*-
24b44f6f2SAdrian Chadd  * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
34b44f6f2SAdrian Chadd  * All rights reserved.
44b44f6f2SAdrian Chadd  *
54b44f6f2SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
64b44f6f2SAdrian Chadd  * modification, are permitted provided that the following conditions
74b44f6f2SAdrian Chadd  * are met:
84b44f6f2SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
94b44f6f2SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
104b44f6f2SAdrian Chadd  *    without modification.
114b44f6f2SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
124b44f6f2SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
134b44f6f2SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
144b44f6f2SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
154b44f6f2SAdrian Chadd  *
164b44f6f2SAdrian Chadd  * NO WARRANTY
174b44f6f2SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
184b44f6f2SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
194b44f6f2SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
204b44f6f2SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
214b44f6f2SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
224b44f6f2SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
234b44f6f2SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
244b44f6f2SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
254b44f6f2SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
264b44f6f2SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
274b44f6f2SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
284b44f6f2SAdrian Chadd  */
294b44f6f2SAdrian Chadd 
304b44f6f2SAdrian Chadd #include <sys/cdefs.h>
314b44f6f2SAdrian Chadd __FBSDID("$FreeBSD$");
324b44f6f2SAdrian Chadd 
334b44f6f2SAdrian Chadd #include "opt_inet.h"
344b44f6f2SAdrian Chadd #include "opt_ath.h"
354b44f6f2SAdrian Chadd #include "opt_wlan.h"
364b44f6f2SAdrian Chadd 
374b44f6f2SAdrian Chadd #include <sys/param.h>
384b44f6f2SAdrian Chadd #include <sys/systm.h>
394b44f6f2SAdrian Chadd #include <sys/sysctl.h>
404b44f6f2SAdrian Chadd #include <sys/mbuf.h>
414b44f6f2SAdrian Chadd #include <sys/malloc.h>
424b44f6f2SAdrian Chadd #include <sys/lock.h>
434b44f6f2SAdrian Chadd #include <sys/mutex.h>
444b44f6f2SAdrian Chadd #include <sys/kernel.h>
454b44f6f2SAdrian Chadd #include <sys/socket.h>
464b44f6f2SAdrian Chadd #include <sys/sockio.h>
474b44f6f2SAdrian Chadd #include <sys/errno.h>
484b44f6f2SAdrian Chadd #include <sys/callout.h>
494b44f6f2SAdrian Chadd #include <sys/bus.h>
504b44f6f2SAdrian Chadd #include <sys/endian.h>
514b44f6f2SAdrian Chadd #include <sys/kthread.h>
524b44f6f2SAdrian Chadd #include <sys/taskqueue.h>
534b44f6f2SAdrian Chadd #include <sys/priv.h>
544b44f6f2SAdrian Chadd 
554b44f6f2SAdrian Chadd #include <machine/bus.h>
564b44f6f2SAdrian Chadd 
574b44f6f2SAdrian Chadd #include <net/if.h>
584b44f6f2SAdrian Chadd #include <net/if_dl.h>
594b44f6f2SAdrian Chadd #include <net/if_media.h>
604b44f6f2SAdrian Chadd #include <net/if_types.h>
614b44f6f2SAdrian Chadd #include <net/if_arp.h>
624b44f6f2SAdrian Chadd #include <net/ethernet.h>
634b44f6f2SAdrian Chadd #include <net/if_llc.h>
644b44f6f2SAdrian Chadd 
654b44f6f2SAdrian Chadd #include <net80211/ieee80211_var.h>
664b44f6f2SAdrian Chadd #include <net80211/ieee80211_regdomain.h>
674b44f6f2SAdrian Chadd #ifdef IEEE80211_SUPPORT_SUPERG
684b44f6f2SAdrian Chadd #include <net80211/ieee80211_superg.h>
694b44f6f2SAdrian Chadd #endif
704b44f6f2SAdrian Chadd #ifdef IEEE80211_SUPPORT_TDMA
714b44f6f2SAdrian Chadd #include <net80211/ieee80211_tdma.h>
724b44f6f2SAdrian Chadd #endif
734b44f6f2SAdrian Chadd 
744b44f6f2SAdrian Chadd #include <net/bpf.h>
754b44f6f2SAdrian Chadd 
764b44f6f2SAdrian Chadd #ifdef INET
774b44f6f2SAdrian Chadd #include <netinet/in.h>
784b44f6f2SAdrian Chadd #include <netinet/if_ether.h>
794b44f6f2SAdrian Chadd #endif
804b44f6f2SAdrian Chadd 
814b44f6f2SAdrian Chadd #include <dev/ath/if_athvar.h>
824b44f6f2SAdrian Chadd #include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
834b44f6f2SAdrian Chadd #include <dev/ath/ath_hal/ah_diagcodes.h>
844b44f6f2SAdrian Chadd 
854b44f6f2SAdrian Chadd #ifdef ATH_TX99_DIAG
864b44f6f2SAdrian Chadd #include <dev/ath/ath_tx99/ath_tx99.h>
874b44f6f2SAdrian Chadd #endif
884b44f6f2SAdrian Chadd 
89eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_tx.h>		/* XXX for some support functions */
904b44f6f2SAdrian Chadd #include <dev/ath/if_ath_tx_ht.h>
91eb6f0de0SAdrian Chadd #include <dev/ath/if_athrate.h>
92eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_debug.h>
93eb6f0de0SAdrian Chadd 
94eb6f0de0SAdrian Chadd /*
95eb6f0de0SAdrian Chadd  * XXX net80211?
96eb6f0de0SAdrian Chadd  */
97eb6f0de0SAdrian Chadd #define	IEEE80211_AMPDU_SUBFRAME_DEFAULT		32
98eb6f0de0SAdrian Chadd 
99eb6f0de0SAdrian Chadd #define	ATH_AGGR_DELIM_SZ	4	/* delimiter size */
100eb6f0de0SAdrian Chadd #define	ATH_AGGR_MINPLEN	256	/* in bytes, minimum packet length */
101b25c1f2aSAdrian Chadd /* number of delimiters for encryption padding */
102b25c1f2aSAdrian Chadd #define	ATH_AGGR_ENCRYPTDELIM	10
103eb6f0de0SAdrian Chadd 
104eb6f0de0SAdrian Chadd /*
105eb6f0de0SAdrian Chadd  * returns delimiter padding required given the packet length
106eb6f0de0SAdrian Chadd  */
107eb6f0de0SAdrian Chadd #define	ATH_AGGR_GET_NDELIM(_len)					\
108eb6f0de0SAdrian Chadd 	    (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?	\
109eb6f0de0SAdrian Chadd 	    (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
110eb6f0de0SAdrian Chadd 
111eb6f0de0SAdrian Chadd #define	PADBYTES(_len)		((4 - ((_len) % 4)) % 4)
112eb6f0de0SAdrian Chadd 
113eb6f0de0SAdrian Chadd int ath_max_4ms_framelen[4][32] = {
114eb6f0de0SAdrian Chadd 	[MCS_HT20] = {
115eb6f0de0SAdrian Chadd 		3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
116eb6f0de0SAdrian Chadd 		6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
117eb6f0de0SAdrian Chadd 		9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
118eb6f0de0SAdrian Chadd 		12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
119eb6f0de0SAdrian Chadd 	},
120eb6f0de0SAdrian Chadd 	[MCS_HT20_SGI] = {
121eb6f0de0SAdrian Chadd 		3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
122eb6f0de0SAdrian Chadd 		7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
123eb6f0de0SAdrian Chadd 		10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
124eb6f0de0SAdrian Chadd 		14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
125eb6f0de0SAdrian Chadd 	},
126eb6f0de0SAdrian Chadd 	[MCS_HT40] = {
127eb6f0de0SAdrian Chadd 		6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
128eb6f0de0SAdrian Chadd 		13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
129eb6f0de0SAdrian Chadd 		20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
130eb6f0de0SAdrian Chadd 		26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
131eb6f0de0SAdrian Chadd 	},
132eb6f0de0SAdrian Chadd 	[MCS_HT40_SGI] = {
133eb6f0de0SAdrian Chadd 		7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
134eb6f0de0SAdrian Chadd 		14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
135eb6f0de0SAdrian Chadd 		22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
136eb6f0de0SAdrian Chadd 		29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
137eb6f0de0SAdrian Chadd 	}
138eb6f0de0SAdrian Chadd };
139eb6f0de0SAdrian Chadd 
140eb6f0de0SAdrian Chadd /*
141eb6f0de0SAdrian Chadd  * XXX should be in net80211
142eb6f0de0SAdrian Chadd  */
143eb6f0de0SAdrian Chadd static int ieee80211_mpdudensity_map[] = {
144eb6f0de0SAdrian Chadd 	0,		/* IEEE80211_HTCAP_MPDUDENSITY_NA */
145eb6f0de0SAdrian Chadd 	25,		/* IEEE80211_HTCAP_MPDUDENSITY_025 */
146eb6f0de0SAdrian Chadd 	50,		/* IEEE80211_HTCAP_MPDUDENSITY_05 */
147eb6f0de0SAdrian Chadd 	100,		/* IEEE80211_HTCAP_MPDUDENSITY_1 */
148eb6f0de0SAdrian Chadd 	200,		/* IEEE80211_HTCAP_MPDUDENSITY_2 */
149eb6f0de0SAdrian Chadd 	400,		/* IEEE80211_HTCAP_MPDUDENSITY_4 */
150eb6f0de0SAdrian Chadd 	800,		/* IEEE80211_HTCAP_MPDUDENSITY_8 */
151eb6f0de0SAdrian Chadd 	1600,		/* IEEE80211_HTCAP_MPDUDENSITY_16 */
152eb6f0de0SAdrian Chadd };
153eb6f0de0SAdrian Chadd 
154eb6f0de0SAdrian Chadd /*
155eb6f0de0SAdrian Chadd  * XXX should be in the HAL/net80211 ?
156eb6f0de0SAdrian Chadd  */
157eb6f0de0SAdrian Chadd #define	BITS_PER_BYTE		8
158eb6f0de0SAdrian Chadd #define	OFDM_PLCP_BITS		22
159eb6f0de0SAdrian Chadd #define	HT_RC_2_MCS(_rc)	((_rc) & 0x7f)
160eb6f0de0SAdrian Chadd #define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
161eb6f0de0SAdrian Chadd #define	L_STF			8
162eb6f0de0SAdrian Chadd #define	L_LTF			8
163eb6f0de0SAdrian Chadd #define	L_SIG			4
164eb6f0de0SAdrian Chadd #define	HT_SIG			8
165eb6f0de0SAdrian Chadd #define	HT_STF			4
166eb6f0de0SAdrian Chadd #define	HT_LTF(_ns)		(4 * (_ns))
167eb6f0de0SAdrian Chadd #define	SYMBOL_TIME(_ns)	((_ns) << 2)		// ns * 4 us
168eb6f0de0SAdrian Chadd #define	SYMBOL_TIME_HALFGI(_ns)	(((_ns) * 18 + 4) / 5)	// ns * 3.6 us
169eb6f0de0SAdrian Chadd #define	NUM_SYMBOLS_PER_USEC(_usec)	(_usec >> 2)
170eb6f0de0SAdrian Chadd #define	NUM_SYMBOLS_PER_USEC_HALFGI(_usec)	(((_usec*5)-4)/18)
171eb6f0de0SAdrian Chadd #define	IS_HT_RATE(_rate)	((_rate) & 0x80)
172eb6f0de0SAdrian Chadd 
173eb6f0de0SAdrian Chadd const uint32_t bits_per_symbol[][2] = {
174eb6f0de0SAdrian Chadd     /* 20MHz 40MHz */
175eb6f0de0SAdrian Chadd     {    26,   54 },     //  0: BPSK
176eb6f0de0SAdrian Chadd     {    52,  108 },     //  1: QPSK 1/2
177eb6f0de0SAdrian Chadd     {    78,  162 },     //  2: QPSK 3/4
178eb6f0de0SAdrian Chadd     {   104,  216 },     //  3: 16-QAM 1/2
179eb6f0de0SAdrian Chadd     {   156,  324 },     //  4: 16-QAM 3/4
180eb6f0de0SAdrian Chadd     {   208,  432 },     //  5: 64-QAM 2/3
181eb6f0de0SAdrian Chadd     {   234,  486 },     //  6: 64-QAM 3/4
182eb6f0de0SAdrian Chadd     {   260,  540 },     //  7: 64-QAM 5/6
183eb6f0de0SAdrian Chadd     {    52,  108 },     //  8: BPSK
184eb6f0de0SAdrian Chadd     {   104,  216 },     //  9: QPSK 1/2
185eb6f0de0SAdrian Chadd     {   156,  324 },     // 10: QPSK 3/4
186eb6f0de0SAdrian Chadd     {   208,  432 },     // 11: 16-QAM 1/2
187eb6f0de0SAdrian Chadd     {   312,  648 },     // 12: 16-QAM 3/4
188eb6f0de0SAdrian Chadd     {   416,  864 },     // 13: 64-QAM 2/3
189eb6f0de0SAdrian Chadd     {   468,  972 },     // 14: 64-QAM 3/4
190eb6f0de0SAdrian Chadd     {   520, 1080 },     // 15: 64-QAM 5/6
191eb6f0de0SAdrian Chadd     {    78,  162 },     // 16: BPSK
192eb6f0de0SAdrian Chadd     {   156,  324 },     // 17: QPSK 1/2
193eb6f0de0SAdrian Chadd     {   234,  486 },     // 18: QPSK 3/4
194eb6f0de0SAdrian Chadd     {   312,  648 },     // 19: 16-QAM 1/2
195eb6f0de0SAdrian Chadd     {   468,  972 },     // 20: 16-QAM 3/4
196eb6f0de0SAdrian Chadd     {   624, 1296 },     // 21: 64-QAM 2/3
197eb6f0de0SAdrian Chadd     {   702, 1458 },     // 22: 64-QAM 3/4
198eb6f0de0SAdrian Chadd     {   780, 1620 },     // 23: 64-QAM 5/6
199eb6f0de0SAdrian Chadd     {   104,  216 },     // 24: BPSK
200eb6f0de0SAdrian Chadd     {   208,  432 },     // 25: QPSK 1/2
201eb6f0de0SAdrian Chadd     {   312,  648 },     // 26: QPSK 3/4
202eb6f0de0SAdrian Chadd     {   416,  864 },     // 27: 16-QAM 1/2
203eb6f0de0SAdrian Chadd     {   624, 1296 },     // 28: 16-QAM 3/4
204eb6f0de0SAdrian Chadd     {   832, 1728 },     // 29: 64-QAM 2/3
205eb6f0de0SAdrian Chadd     {   936, 1944 },     // 30: 64-QAM 3/4
206eb6f0de0SAdrian Chadd     {  1040, 2160 },     // 31: 64-QAM 5/6
207eb6f0de0SAdrian Chadd };
208eb6f0de0SAdrian Chadd 
209eb6f0de0SAdrian Chadd /*
210eb6f0de0SAdrian Chadd  * Fill in the rate array information based on the current
211eb6f0de0SAdrian Chadd  * node configuration and the choices made by the rate
212eb6f0de0SAdrian Chadd  * selection code and ath_buf setup code.
213eb6f0de0SAdrian Chadd  *
214eb6f0de0SAdrian Chadd  * Later on, this may end up also being made by the
215eb6f0de0SAdrian Chadd  * rate control code, but for now it can live here.
216eb6f0de0SAdrian Chadd  *
217eb6f0de0SAdrian Chadd  * This needs to be called just before the packet is
218eb6f0de0SAdrian Chadd  * queued to the software queue or hardware queue,
219eb6f0de0SAdrian Chadd  * so all of the needed fields in bf_state are setup.
220eb6f0de0SAdrian Chadd  */
221eb6f0de0SAdrian Chadd void
222eb6f0de0SAdrian Chadd ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
223eb6f0de0SAdrian Chadd {
224eb6f0de0SAdrian Chadd 	struct ieee80211_node *ni = bf->bf_node;
225a7038bd1SAdrian Chadd 	struct ieee80211vap *vap = ni->ni_vap;
226eb6f0de0SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
227eb6f0de0SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
228eb6f0de0SAdrian Chadd 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
229eb6f0de0SAdrian Chadd 	uint8_t rate;
230eb6f0de0SAdrian Chadd 	int i;
231ce725c8eSAdrian Chadd 	int do_ldpc;
232ce725c8eSAdrian Chadd 	int do_stbc;
233ce725c8eSAdrian Chadd 
234ce725c8eSAdrian Chadd 	/*
235ce725c8eSAdrian Chadd 	 * We only do LDPC if the rate is 11n, both we and the
236ce725c8eSAdrian Chadd 	 * receiver support LDPC and it's enabled.
237ce725c8eSAdrian Chadd 	 *
238ce725c8eSAdrian Chadd 	 * It's a global flag, not a per-try flag, so we clear
239ce725c8eSAdrian Chadd 	 * it if any of the rate entries aren't 11n.
240ce725c8eSAdrian Chadd 	 */
241a0391187SAdrian Chadd 	do_ldpc = 0;
242ce725c8eSAdrian Chadd 	if ((ni->ni_vap->iv_htcaps & IEEE80211_HTCAP_LDPC) &&
243ce725c8eSAdrian Chadd 	    (ni->ni_htcap & IEEE80211_HTCAP_LDPC))
244ce725c8eSAdrian Chadd 		do_ldpc = 1;
245ce725c8eSAdrian Chadd 	do_stbc = 0;
246eb6f0de0SAdrian Chadd 
247eb6f0de0SAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
248eb6f0de0SAdrian Chadd 		rc[i].flags = 0;
249eb6f0de0SAdrian Chadd 		if (rc[i].tries == 0)
250eb6f0de0SAdrian Chadd 			continue;
251eb6f0de0SAdrian Chadd 
252eb6f0de0SAdrian Chadd 		rate = rt->info[rc[i].rix].rateCode;
253eb6f0de0SAdrian Chadd 
254eb6f0de0SAdrian Chadd 		/*
25556129906SAdrian Chadd 		 * Only enable short preamble for legacy rates
256eb6f0de0SAdrian Chadd 		 */
2577a27f0a3SAdrian Chadd 		if ((! IS_HT_RATE(rate)) && bf->bf_state.bfs_shpream)
258eb6f0de0SAdrian Chadd 			rate |= rt->info[rc[i].rix].shortPreamble;
259eb6f0de0SAdrian Chadd 
260eb6f0de0SAdrian Chadd 		/*
261eb6f0de0SAdrian Chadd 		 * Save this, used by the TX and completion code
262eb6f0de0SAdrian Chadd 		 */
263eb6f0de0SAdrian Chadd 		rc[i].ratecode = rate;
264eb6f0de0SAdrian Chadd 
265875a9451SAdrian Chadd 		if (bf->bf_state.bfs_txflags &
266eb6f0de0SAdrian Chadd 		    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
267eb6f0de0SAdrian Chadd 			rc[i].flags |= ATH_RC_RTSCTS_FLAG;
268eb6f0de0SAdrian Chadd 
269ce725c8eSAdrian Chadd 		/*
270ce725c8eSAdrian Chadd 		 * If we can't do LDPC, don't.
271ce725c8eSAdrian Chadd 		 */
272ce725c8eSAdrian Chadd 		if (! IS_HT_RATE(rate))
273ce725c8eSAdrian Chadd 			do_ldpc = 0;
274ce725c8eSAdrian Chadd 
275eb6f0de0SAdrian Chadd 		/* Only enable shortgi, 2040, dual-stream if HT is set */
276eb6f0de0SAdrian Chadd 		if (IS_HT_RATE(rate)) {
277eb6f0de0SAdrian Chadd 			rc[i].flags |= ATH_RC_HT_FLAG;
278eb6f0de0SAdrian Chadd 
279eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 40)
280eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_CW40_FLAG;
281eb6f0de0SAdrian Chadd 
282eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 40 &&
283eb6f0de0SAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
284a7038bd1SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40 &&
285a7038bd1SAdrian Chadd 			    vap->iv_flags_ht & IEEE80211_FHT_SHORTGI40)
286eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_SGI_FLAG;
287eb6f0de0SAdrian Chadd 
288eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 20 &&
289eb6f0de0SAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
290a7038bd1SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20 &&
291a7038bd1SAdrian Chadd 			    vap->iv_flags_ht & IEEE80211_FHT_SHORTGI20)
292eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_SGI_FLAG;
293eb6f0de0SAdrian Chadd 
29456129906SAdrian Chadd 			/*
29556129906SAdrian Chadd 			 * If we have STBC TX enabled and the receiver
29656129906SAdrian Chadd 			 * can receive (at least) 1 stream STBC, AND it's
29756129906SAdrian Chadd 			 * MCS 0-7, AND we have at least two chains enabled,
29856129906SAdrian Chadd 			 * enable STBC.
29956129906SAdrian Chadd 			 */
30056129906SAdrian Chadd 			if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
301f026d693SAdrian Chadd 			    ni->ni_vap->iv_flags_ht & IEEE80211_FHT_STBC_TX &&
30256129906SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
30356129906SAdrian Chadd 			    (sc->sc_cur_txchainmask > 1) &&
30456129906SAdrian Chadd 			    HT_RC_2_STREAMS(rate) == 1) {
30556129906SAdrian Chadd 				rc[i].flags |= ATH_RC_STBC_FLAG;
306ce725c8eSAdrian Chadd 				do_stbc = 1;
30756129906SAdrian Chadd 			}
30856129906SAdrian Chadd 
309de00e5cbSAdrian Chadd 			/*
310de00e5cbSAdrian Chadd 			 * Dual / Triple stream rate?
311de00e5cbSAdrian Chadd 			 */
312de00e5cbSAdrian Chadd 			if (HT_RC_2_STREAMS(rate) == 2)
313de00e5cbSAdrian Chadd 				rc[i].flags |= ATH_RC_DS_FLAG;
314de00e5cbSAdrian Chadd 			else if (HT_RC_2_STREAMS(rate) == 3)
315de00e5cbSAdrian Chadd 				rc[i].flags |= ATH_RC_TS_FLAG;
316eb6f0de0SAdrian Chadd 		}
317eb6f0de0SAdrian Chadd 
318eb6f0de0SAdrian Chadd 		/*
319de00e5cbSAdrian Chadd 		 * Calculate the maximum TX power cap for the current
320de00e5cbSAdrian Chadd 		 * node.
321de00e5cbSAdrian Chadd 		 */
322de00e5cbSAdrian Chadd 		rc[i].tx_power_cap = ieee80211_get_node_txpower(ni);
323de00e5cbSAdrian Chadd 
324de00e5cbSAdrian Chadd 		/*
325eb6f0de0SAdrian Chadd 		 * Calculate the maximum 4ms frame length based
326eb6f0de0SAdrian Chadd 		 * on the MCS rate, SGI and channel width flags.
327eb6f0de0SAdrian Chadd 		 */
328eb6f0de0SAdrian Chadd 		if ((rc[i].flags & ATH_RC_HT_FLAG) &&
329eb6f0de0SAdrian Chadd 		    (HT_RC_2_MCS(rate) < 32)) {
330eb6f0de0SAdrian Chadd 			int j;
331eb6f0de0SAdrian Chadd 			if (rc[i].flags & ATH_RC_CW40_FLAG) {
332eb6f0de0SAdrian Chadd 				if (rc[i].flags & ATH_RC_SGI_FLAG)
333eb6f0de0SAdrian Chadd 					j = MCS_HT40_SGI;
334eb6f0de0SAdrian Chadd 				else
335eb6f0de0SAdrian Chadd 					j = MCS_HT40;
336eb6f0de0SAdrian Chadd 			} else {
337eb6f0de0SAdrian Chadd 				if (rc[i].flags & ATH_RC_SGI_FLAG)
338eb6f0de0SAdrian Chadd 					j = MCS_HT20_SGI;
339eb6f0de0SAdrian Chadd 				else
340eb6f0de0SAdrian Chadd 					j = MCS_HT20;
341eb6f0de0SAdrian Chadd 			}
342eb6f0de0SAdrian Chadd 			rc[i].max4msframelen =
343eb6f0de0SAdrian Chadd 			    ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)];
344eb6f0de0SAdrian Chadd 		} else
345eb6f0de0SAdrian Chadd 			rc[i].max4msframelen = 0;
346eb6f0de0SAdrian Chadd 		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
347eb6f0de0SAdrian Chadd 		    "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
348eb6f0de0SAdrian Chadd 		    __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
349eb6f0de0SAdrian Chadd 	}
350ce725c8eSAdrian Chadd 
351ce725c8eSAdrian Chadd 	/*
352ce725c8eSAdrian Chadd 	 * LDPC is a global flag, so ...
353ce725c8eSAdrian Chadd 	 */
354ce725c8eSAdrian Chadd 	if (do_ldpc) {
355ce725c8eSAdrian Chadd 		bf->bf_state.bfs_txflags |= HAL_TXDESC_LDPC;
356ce725c8eSAdrian Chadd 		sc->sc_stats.ast_tx_ldpc++;
357ce725c8eSAdrian Chadd 	}
358ce725c8eSAdrian Chadd 
359ce725c8eSAdrian Chadd 	if (do_stbc) {
360ce725c8eSAdrian Chadd 		sc->sc_stats.ast_tx_stbc++;
361ce725c8eSAdrian Chadd 	}
362eb6f0de0SAdrian Chadd }
363eb6f0de0SAdrian Chadd 
364eb6f0de0SAdrian Chadd /*
365eb6f0de0SAdrian Chadd  * Return the number of delimiters to be added to
366eb6f0de0SAdrian Chadd  * meet the minimum required mpdudensity.
367eb6f0de0SAdrian Chadd  *
368eb6f0de0SAdrian Chadd  * Caller should make sure that the rate is HT.
369eb6f0de0SAdrian Chadd  *
370eb6f0de0SAdrian Chadd  * TODO: is this delimiter calculation supposed to be the
371eb6f0de0SAdrian Chadd  * total frame length, the hdr length, the data length (including
372eb6f0de0SAdrian Chadd  * delimiters, padding, CRC, etc) or ?
373eb6f0de0SAdrian Chadd  *
374eb6f0de0SAdrian Chadd  * TODO: this should ensure that the rate control information
375eb6f0de0SAdrian Chadd  * HAS been setup for the first rate.
376eb6f0de0SAdrian Chadd  *
377eb6f0de0SAdrian Chadd  * TODO: ensure this is only called for MCS rates.
378eb6f0de0SAdrian Chadd  *
379eb6f0de0SAdrian Chadd  * TODO: enforce MCS < 31
380eb6f0de0SAdrian Chadd  */
381eb6f0de0SAdrian Chadd static int
382eb6f0de0SAdrian Chadd ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf,
383eb6f0de0SAdrian Chadd     uint16_t pktlen)
384eb6f0de0SAdrian Chadd {
385eb6f0de0SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
386eb6f0de0SAdrian Chadd 	struct ieee80211_node *ni = first_bf->bf_node;
387eb6f0de0SAdrian Chadd 	struct ieee80211vap *vap = ni->ni_vap;
388eb6f0de0SAdrian Chadd 	int ndelim, mindelim = 0;
389eb6f0de0SAdrian Chadd 	int mpdudensity;	 /* in 1/100'th of a microsecond */
390eb6f0de0SAdrian Chadd 	uint8_t rc, rix, flags;
391eb6f0de0SAdrian Chadd 	int width, half_gi;
392eb6f0de0SAdrian Chadd 	uint32_t nsymbits, nsymbols;
393eb6f0de0SAdrian Chadd 	uint16_t minlen;
394eb6f0de0SAdrian Chadd 
395eb6f0de0SAdrian Chadd 	/*
396eb6f0de0SAdrian Chadd 	 * vap->iv_ampdu_density is a value, rather than the actual
397eb6f0de0SAdrian Chadd 	 * density.
398eb6f0de0SAdrian Chadd 	 */
399eb6f0de0SAdrian Chadd 	if (vap->iv_ampdu_density > IEEE80211_HTCAP_MPDUDENSITY_16)
400eb6f0de0SAdrian Chadd 		mpdudensity = 1600;		/* maximum density */
401eb6f0de0SAdrian Chadd 	else
402eb6f0de0SAdrian Chadd 		mpdudensity = ieee80211_mpdudensity_map[vap->iv_ampdu_density];
403eb6f0de0SAdrian Chadd 
404eb6f0de0SAdrian Chadd 	/* Select standard number of delimiters based on frame length */
405eb6f0de0SAdrian Chadd 	ndelim = ATH_AGGR_GET_NDELIM(pktlen);
406eb6f0de0SAdrian Chadd 
407eb6f0de0SAdrian Chadd 	/*
408eb6f0de0SAdrian Chadd 	 * If encryption is enabled, add extra delimiters to let the
409eb6f0de0SAdrian Chadd 	 * crypto hardware catch up. This could be tuned per-MAC and
410eb6f0de0SAdrian Chadd 	 * per-rate, but for now we'll simply assume encryption is
411eb6f0de0SAdrian Chadd 	 * always enabled.
4124a502c33SAdrian Chadd 	 *
4134a502c33SAdrian Chadd 	 * Also note that the Atheros reference driver inserts two
4144a502c33SAdrian Chadd 	 * delimiters by default for pre-AR9380 peers.  This will
4154a502c33SAdrian Chadd 	 * include "that" required delimiter.
416eb6f0de0SAdrian Chadd 	 */
417eb6f0de0SAdrian Chadd 	ndelim += ATH_AGGR_ENCRYPTDELIM;
418eb6f0de0SAdrian Chadd 
41964dbfc6dSAdrian Chadd 	/*
42064dbfc6dSAdrian Chadd 	 * For AR9380, there's a minimum number of delimeters
42164dbfc6dSAdrian Chadd 	 * required when doing RTS.
4224a502c33SAdrian Chadd 	 *
4234a502c33SAdrian Chadd 	 * XXX TODO: this is only needed if (a) RTS/CTS is enabled, and
4244a502c33SAdrian Chadd 	 * XXX (b) this is the first sub-frame in the aggregate.
42564dbfc6dSAdrian Chadd 	 */
42664dbfc6dSAdrian Chadd 	if (sc->sc_use_ent && (sc->sc_ent_cfg & AH_ENT_RTSCTS_DELIM_WAR)
42764dbfc6dSAdrian Chadd 	    && ndelim < AH_FIRST_DESC_NDELIMS)
42864dbfc6dSAdrian Chadd 		ndelim = AH_FIRST_DESC_NDELIMS;
42964dbfc6dSAdrian Chadd 
430a54ecf78SAdrian Chadd 	/*
431a54ecf78SAdrian Chadd 	 * If sc_delim_min_pad is non-zero, enforce it as the minimum
432a54ecf78SAdrian Chadd 	 * pad delimiter count.
433a54ecf78SAdrian Chadd 	 */
434a54ecf78SAdrian Chadd 	if (sc->sc_delim_min_pad != 0)
435a54ecf78SAdrian Chadd 		ndelim = MAX(ndelim, sc->sc_delim_min_pad);
436a54ecf78SAdrian Chadd 
437eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
438eb6f0de0SAdrian Chadd 	    "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n",
439eb6f0de0SAdrian Chadd 	    __func__, pktlen, ndelim, mpdudensity);
440eb6f0de0SAdrian Chadd 
441eb6f0de0SAdrian Chadd 	/*
442eb6f0de0SAdrian Chadd 	 * If the MPDU density is 0, we can return here.
443eb6f0de0SAdrian Chadd 	 * Otherwise, we need to convert the desired mpdudensity
444eb6f0de0SAdrian Chadd 	 * into a byte length, based on the rate in the subframe.
445eb6f0de0SAdrian Chadd 	 */
446eb6f0de0SAdrian Chadd 	if (mpdudensity == 0)
447eb6f0de0SAdrian Chadd 		return ndelim;
448eb6f0de0SAdrian Chadd 
449eb6f0de0SAdrian Chadd 	/*
450eb6f0de0SAdrian Chadd 	 * Convert desired mpdu density from microeconds to bytes based
451eb6f0de0SAdrian Chadd 	 * on highest rate in rate series (i.e. first rate) to determine
452eb6f0de0SAdrian Chadd 	 * required minimum length for subframe. Take into account
453eb6f0de0SAdrian Chadd 	 * whether high rate is 20 or 40Mhz and half or full GI.
454eb6f0de0SAdrian Chadd 	 */
455eb6f0de0SAdrian Chadd 	rix = first_bf->bf_state.bfs_rc[0].rix;
456eb6f0de0SAdrian Chadd 	rc = rt->info[rix].rateCode;
457eb6f0de0SAdrian Chadd 	flags = first_bf->bf_state.bfs_rc[0].flags;
458eb6f0de0SAdrian Chadd 	width = !! (flags & ATH_RC_CW40_FLAG);
459eb6f0de0SAdrian Chadd 	half_gi = !! (flags & ATH_RC_SGI_FLAG);
460eb6f0de0SAdrian Chadd 
461eb6f0de0SAdrian Chadd 	/*
462eb6f0de0SAdrian Chadd 	 * mpdudensity is in 1/100th of a usec, so divide by 100
463eb6f0de0SAdrian Chadd 	 */
464eb6f0de0SAdrian Chadd 	if (half_gi)
465eb6f0de0SAdrian Chadd 		nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
466eb6f0de0SAdrian Chadd 	else
467eb6f0de0SAdrian Chadd 		nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
468eb6f0de0SAdrian Chadd 	nsymbols /= 100;
469eb6f0de0SAdrian Chadd 
470eb6f0de0SAdrian Chadd 	if (nsymbols == 0)
471eb6f0de0SAdrian Chadd 		nsymbols = 1;
472eb6f0de0SAdrian Chadd 
473eb6f0de0SAdrian Chadd 	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
474eb6f0de0SAdrian Chadd 	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
475eb6f0de0SAdrian Chadd 
476eb6f0de0SAdrian Chadd 	/*
477eb6f0de0SAdrian Chadd 	 * Min length is the minimum frame length for the
478eb6f0de0SAdrian Chadd 	 * required MPDU density.
479eb6f0de0SAdrian Chadd 	 */
480eb6f0de0SAdrian Chadd 	if (pktlen < minlen) {
481eb6f0de0SAdrian Chadd 		mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ;
482eb6f0de0SAdrian Chadd 		ndelim = MAX(mindelim, ndelim);
483eb6f0de0SAdrian Chadd 	}
484eb6f0de0SAdrian Chadd 
485eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
486eb6f0de0SAdrian Chadd 	    "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n",
487eb6f0de0SAdrian Chadd 	    __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim);
488eb6f0de0SAdrian Chadd 
489eb6f0de0SAdrian Chadd 	return ndelim;
490eb6f0de0SAdrian Chadd }
491eb6f0de0SAdrian Chadd 
492eb6f0de0SAdrian Chadd /*
493eb6f0de0SAdrian Chadd  * Fetch the aggregation limit.
494eb6f0de0SAdrian Chadd  *
495eb6f0de0SAdrian Chadd  * It's the lowest of the four rate series 4ms frame length.
496eb6f0de0SAdrian Chadd  */
497eb6f0de0SAdrian Chadd static int
498eb6f0de0SAdrian Chadd ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf)
499eb6f0de0SAdrian Chadd {
5004a502c33SAdrian Chadd 	int amin = ATH_AGGR_MAXSIZE;
501eb6f0de0SAdrian Chadd 	int i;
502eb6f0de0SAdrian Chadd 
5034a502c33SAdrian Chadd 	if (sc->sc_aggr_limit > 0 && sc->sc_aggr_limit < ATH_AGGR_MAXSIZE)
5044a502c33SAdrian Chadd 		amin = sc->sc_aggr_limit;
5054a502c33SAdrian Chadd 
506b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
507eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_rc[i].tries == 0)
508eb6f0de0SAdrian Chadd 			continue;
509eb6f0de0SAdrian Chadd 		amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen);
510eb6f0de0SAdrian Chadd 	}
511eb6f0de0SAdrian Chadd 
512eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: max frame len= %d\n",
513eb6f0de0SAdrian Chadd 	    __func__, amin);
514eb6f0de0SAdrian Chadd 
515eb6f0de0SAdrian Chadd 	return amin;
516eb6f0de0SAdrian Chadd }
5174b44f6f2SAdrian Chadd 
5184b44f6f2SAdrian Chadd /*
5194b44f6f2SAdrian Chadd  * Setup a 11n rate series structure
5204b44f6f2SAdrian Chadd  *
5214b44f6f2SAdrian Chadd  * This should be called for both legacy and MCS rates.
522eb6f0de0SAdrian Chadd  *
523de00e5cbSAdrian Chadd  * This uses the rate series stuf from ath_tx_rate_fill_rcflags().
524de00e5cbSAdrian Chadd  *
525eb6f0de0SAdrian Chadd  * It, along with ath_buf_set_rate, must be called -after- a burst
526eb6f0de0SAdrian Chadd  * or aggregate is setup.
5274b44f6f2SAdrian Chadd  */
5284b44f6f2SAdrian Chadd static void
5294b44f6f2SAdrian Chadd ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
530eb6f0de0SAdrian Chadd     struct ath_buf *bf, HAL_11N_RATE_SERIES *series)
5314b44f6f2SAdrian Chadd {
5324b44f6f2SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
5334b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
5344b44f6f2SAdrian Chadd 	HAL_BOOL shortPreamble = AH_FALSE;
5354b44f6f2SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
5364b44f6f2SAdrian Chadd 	int i;
537eb6f0de0SAdrian Chadd 	int pktlen;
538eb6f0de0SAdrian Chadd 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
5394b44f6f2SAdrian Chadd 
5404b44f6f2SAdrian Chadd 	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
5414b44f6f2SAdrian Chadd 	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
5424b44f6f2SAdrian Chadd 		shortPreamble = AH_TRUE;
5434b44f6f2SAdrian Chadd 
544eb6f0de0SAdrian Chadd 	/*
545eb6f0de0SAdrian Chadd 	 * If this is the first frame in an aggregate series,
546eb6f0de0SAdrian Chadd 	 * use the aggregate length.
547eb6f0de0SAdrian Chadd 	 */
548eb6f0de0SAdrian Chadd 	if (bf->bf_state.bfs_aggr)
549eb6f0de0SAdrian Chadd 		pktlen = bf->bf_state.bfs_al;
550eb6f0de0SAdrian Chadd 	else
551eb6f0de0SAdrian Chadd 		pktlen = bf->bf_state.bfs_pktlen;
552eb6f0de0SAdrian Chadd 
553eb6f0de0SAdrian Chadd 	/*
554eb6f0de0SAdrian Chadd 	 * XXX TODO: modify this routine to use the bfs_rc[x].flags
555eb6f0de0SAdrian Chadd 	 * XXX fields.
556eb6f0de0SAdrian Chadd 	 */
5574b44f6f2SAdrian Chadd 	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
558b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM;  i++) {
559146b49d8SAdrian Chadd 		/* Only set flags for actual TX attempts */
560eb6f0de0SAdrian Chadd 		if (rc[i].tries == 0)
561146b49d8SAdrian Chadd 			continue;
562146b49d8SAdrian Chadd 
563eb6f0de0SAdrian Chadd 		series[i].Tries = rc[i].tries;
564146b49d8SAdrian Chadd 
565146b49d8SAdrian Chadd 		/*
5664a502c33SAdrian Chadd 		 * XXX TODO: When the NIC is capable of three stream TX,
5674a502c33SAdrian Chadd 		 * transmit 1/2 stream rates on two streams.
5684a502c33SAdrian Chadd 		 *
5694a502c33SAdrian Chadd 		 * This reduces the power consumption of the NIC and
5704a502c33SAdrian Chadd 		 * keeps it within the PCIe slot power limits.
5714a502c33SAdrian Chadd 		 */
5726322256bSAdrian Chadd 		series[i].ChSel = sc->sc_cur_txchainmask;
573146b49d8SAdrian Chadd 
57456129906SAdrian Chadd 		/*
57556129906SAdrian Chadd 		 * Setup rate and TX power cap for this series.
57656129906SAdrian Chadd 		 */
57756129906SAdrian Chadd 		series[i].Rate = rt->info[rc[i].rix].rateCode;
57856129906SAdrian Chadd 		series[i].RateIndex = rc[i].rix;
579de00e5cbSAdrian Chadd 		series[i].tx_power_cap = rc[i].tx_power_cap;
58056129906SAdrian Chadd 
58156129906SAdrian Chadd 		/*
58256129906SAdrian Chadd 		 * Enable RTS/CTS as appropriate.
58356129906SAdrian Chadd 		 */
584de00e5cbSAdrian Chadd 		if (rc[i].flags & ATH_RC_RTSCTS_FLAG)
5854b44f6f2SAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
586146b49d8SAdrian Chadd 
587532f2442SAdrian Chadd 		/*
588de00e5cbSAdrian Chadd 		 * 11n rate? Update 11n flags.
589532f2442SAdrian Chadd 		 */
590de00e5cbSAdrian Chadd 		if (rc[i].flags & ATH_RC_HT_FLAG) {
591de00e5cbSAdrian Chadd 			if (rc[i].flags & ATH_RC_CW40_FLAG)
5924b44f6f2SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_2040;
5936246be6eSAdrian Chadd 
594de00e5cbSAdrian Chadd 			if (rc[i].flags & ATH_RC_SGI_FLAG)
5954b44f6f2SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_HALFGI;
5966246be6eSAdrian Chadd 
597de00e5cbSAdrian Chadd 			if (rc[i].flags & ATH_RC_STBC_FLAG)
5981a3a5607SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_STBC;
5991a3a5607SAdrian Chadd 		}
6006322256bSAdrian Chadd 
601b25c1f2aSAdrian Chadd 		/*
602f026d693SAdrian Chadd 		 * TODO: If we're all doing 11n rates then we can set LDPC.
603f026d693SAdrian Chadd 		 * If we've been asked to /do/ LDPC but we are handed a
604f026d693SAdrian Chadd 		 * legacy rate, then we should complain.  Loudly.
605f026d693SAdrian Chadd 		 */
606f026d693SAdrian Chadd 
607f026d693SAdrian Chadd 		/*
608b25c1f2aSAdrian Chadd 		 * PktDuration doesn't include slot, ACK, RTS, etc timing -
609b25c1f2aSAdrian Chadd 		 * it's just the packet duration
610b25c1f2aSAdrian Chadd 		 */
611de00e5cbSAdrian Chadd 		if (rc[i].flags & ATH_RC_HT_FLAG) {
6124b44f6f2SAdrian Chadd 			series[i].PktDuration =
6134b44f6f2SAdrian Chadd 			    ath_computedur_ht(pktlen
6149a97e25eSAdrian Chadd 				, series[i].Rate
615fce6d676SAdrian Chadd 				, HT_RC_2_STREAMS(series[i].Rate)
616fce6d676SAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_2040
617f449ab1cSAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
6184b44f6f2SAdrian Chadd 		} else {
6191198947aSAdrian Chadd 			if (shortPreamble)
620eb6f0de0SAdrian Chadd 				series[i].Rate |=
621eb6f0de0SAdrian Chadd 				    rt->info[rc[i].rix].shortPreamble;
622*7ff1939dSAdrian Chadd 			/* XXX TODO: don't include SIFS */
6234b44f6f2SAdrian Chadd 			series[i].PktDuration = ath_hal_computetxtime(ah,
624*7ff1939dSAdrian Chadd 			    rt, pktlen, rc[i].rix, shortPreamble, AH_TRUE);
6254b44f6f2SAdrian Chadd 		}
6264b44f6f2SAdrian Chadd 	}
6274b44f6f2SAdrian Chadd }
6284b44f6f2SAdrian Chadd 
62919b34b56SAdrian Chadd #ifdef	ATH_DEBUG
6304b44f6f2SAdrian Chadd static void
631b25c1f2aSAdrian Chadd ath_rateseries_print(struct ath_softc *sc, HAL_11N_RATE_SERIES *series)
6324b44f6f2SAdrian Chadd {
6334b44f6f2SAdrian Chadd 	int i;
634b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
635b25c1f2aSAdrian Chadd 		device_printf(sc->sc_dev ,"series %d: rate %x; tries %d; "
63664dbfc6dSAdrian Chadd 		    "pktDuration %d; chSel %d; txpowcap %d, rateFlags %x\n",
6374b44f6f2SAdrian Chadd 		    i,
6384b44f6f2SAdrian Chadd 		    series[i].Rate,
6394b44f6f2SAdrian Chadd 		    series[i].Tries,
6404b44f6f2SAdrian Chadd 		    series[i].PktDuration,
6414b44f6f2SAdrian Chadd 		    series[i].ChSel,
64264dbfc6dSAdrian Chadd 		    series[i].tx_power_cap,
6434b44f6f2SAdrian Chadd 		    series[i].RateFlags);
6444b44f6f2SAdrian Chadd 	}
6454b44f6f2SAdrian Chadd }
6464b44f6f2SAdrian Chadd #endif
6474b44f6f2SAdrian Chadd 
6484b44f6f2SAdrian Chadd /*
6494b44f6f2SAdrian Chadd  * Setup the 11n rate scenario and burst duration for the given TX descriptor
6504b44f6f2SAdrian Chadd  * list.
6514b44f6f2SAdrian Chadd  *
6524b44f6f2SAdrian Chadd  * This isn't useful for sending beacon frames, which has different needs
6534b44f6f2SAdrian Chadd  * wrt what's passed into the rate scenario function.
6544b44f6f2SAdrian Chadd  */
6554b44f6f2SAdrian Chadd void
656eb6f0de0SAdrian Chadd ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni,
657eb6f0de0SAdrian Chadd     struct ath_buf *bf)
6584b44f6f2SAdrian Chadd {
6594b44f6f2SAdrian Chadd 	HAL_11N_RATE_SERIES series[4];
6604b44f6f2SAdrian Chadd 	struct ath_desc *ds = bf->bf_desc;
6614b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
662eb6f0de0SAdrian Chadd 	int is_pspoll = (bf->bf_state.bfs_atype == HAL_PKT_TYPE_PSPOLL);
663eb6f0de0SAdrian Chadd 	int ctsrate = bf->bf_state.bfs_ctsrate;
664875a9451SAdrian Chadd 	int flags = bf->bf_state.bfs_txflags;
6654b44f6f2SAdrian Chadd 
6664b44f6f2SAdrian Chadd 	/* Setup rate scenario */
6674b44f6f2SAdrian Chadd 	memset(&series, 0, sizeof(series));
6684b44f6f2SAdrian Chadd 
669eb6f0de0SAdrian Chadd 	ath_rateseries_setup(sc, ni, bf, series);
6704b44f6f2SAdrian Chadd 
67119b34b56SAdrian Chadd #ifdef	ATH_DEBUG
67220b0b9eaSAdrian Chadd 	if (sc->sc_debug & ATH_DEBUG_XMIT)
673b25c1f2aSAdrian Chadd 		ath_rateseries_print(sc, series);
6742b5684a8SAdrian Chadd #endif
6752b5684a8SAdrian Chadd 
6764b44f6f2SAdrian Chadd 	/* Set rate scenario */
677b25c1f2aSAdrian Chadd 	/*
678b25c1f2aSAdrian Chadd 	 * Note: Don't allow hardware to override the duration on
679b25c1f2aSAdrian Chadd 	 * ps-poll packets.
680b25c1f2aSAdrian Chadd 	 */
6814b44f6f2SAdrian Chadd 	ath_hal_set11nratescenario(ah, ds,
682bf26df36SAdrian Chadd 	    !is_pspoll,	/* whether to override the duration or not */
6834b44f6f2SAdrian Chadd 	    ctsrate,	/* rts/cts rate */
6844b44f6f2SAdrian Chadd 	    series,	/* 11n rate series */
6854b44f6f2SAdrian Chadd 	    4,		/* number of series */
6864b44f6f2SAdrian Chadd 	    flags);
6874b44f6f2SAdrian Chadd 
6884b44f6f2SAdrian Chadd 	/* Set burst duration */
689eb6f0de0SAdrian Chadd 	/*
690eb6f0de0SAdrian Chadd 	 * This is only required when doing 11n burst, not aggregation
691eb6f0de0SAdrian Chadd 	 * ie, if there's a second frame in a RIFS or A-MPDU burst
692eb6f0de0SAdrian Chadd 	 * w/ >1 A-MPDU frame bursting back to back.
693eb6f0de0SAdrian Chadd 	 * Normal A-MPDU doesn't do bursting -between- aggregates.
694eb6f0de0SAdrian Chadd 	 *
695eb6f0de0SAdrian Chadd 	 * .. and it's highly likely this won't ever be implemented
696eb6f0de0SAdrian Chadd 	 */
6974b44f6f2SAdrian Chadd 	//ath_hal_set11nburstduration(ah, ds, 8192);
6984b44f6f2SAdrian Chadd }
699eb6f0de0SAdrian Chadd 
700eb6f0de0SAdrian Chadd /*
701eb6f0de0SAdrian Chadd  * Form an aggregate packet list.
702eb6f0de0SAdrian Chadd  *
703eb6f0de0SAdrian Chadd  * This function enforces the aggregate restrictions/requirements.
704eb6f0de0SAdrian Chadd  *
705eb6f0de0SAdrian Chadd  * These are:
706eb6f0de0SAdrian Chadd  *
707eb6f0de0SAdrian Chadd  * + The aggregate size maximum (64k for AR9160 and later, 8K for
708eb6f0de0SAdrian Chadd  *   AR5416 when doing RTS frame protection.)
709eb6f0de0SAdrian Chadd  * + Maximum number of sub-frames for an aggregate
710eb6f0de0SAdrian Chadd  * + The aggregate delimiter size, giving MACs time to do whatever is
711eb6f0de0SAdrian Chadd  *   needed before each frame
712eb6f0de0SAdrian Chadd  * + Enforce the BAW limit
713eb6f0de0SAdrian Chadd  *
714eb6f0de0SAdrian Chadd  * Each descriptor queued should have the DMA setup.
715eb6f0de0SAdrian Chadd  * The rate series, descriptor setup, linking, etc is all done
716eb6f0de0SAdrian Chadd  * externally. This routine simply chains them together.
717eb6f0de0SAdrian Chadd  * ath_tx_setds_11n() will take care of configuring the per-
718eb6f0de0SAdrian Chadd  * descriptor setup, and ath_buf_set_rate() will configure the
719eb6f0de0SAdrian Chadd  * rate control.
720eb6f0de0SAdrian Chadd  *
721b25c1f2aSAdrian Chadd  * The TID lock is required for the entirety of this function.
722b25c1f2aSAdrian Chadd  *
723b25c1f2aSAdrian Chadd  * If some code in another thread adds to the head of this
724eb6f0de0SAdrian Chadd  * list, very strange behaviour will occur. Since retransmission is the
725eb6f0de0SAdrian Chadd  * only reason this will occur, and this routine is designed to be called
726eb6f0de0SAdrian Chadd  * from within the scheduler task, it won't ever clash with the completion
727eb6f0de0SAdrian Chadd  * task.
728eb6f0de0SAdrian Chadd  *
729eb6f0de0SAdrian Chadd  * So if you want to call this from an upper layer context (eg, to direct-
730eb6f0de0SAdrian Chadd  * dispatch aggregate frames to the hardware), please keep this in mind.
731eb6f0de0SAdrian Chadd  */
732eb6f0de0SAdrian Chadd ATH_AGGR_STATUS
733b25c1f2aSAdrian Chadd ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an,
734b25c1f2aSAdrian Chadd     struct ath_tid *tid, ath_bufhead *bf_q)
735eb6f0de0SAdrian Chadd {
736a108d2d6SAdrian Chadd 	//struct ieee80211_node *ni = &an->an_node;
737eb6f0de0SAdrian Chadd 	struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
738eb6f0de0SAdrian Chadd 	int nframes = 0;
739eb6f0de0SAdrian Chadd 	uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw;
740eb6f0de0SAdrian Chadd 	struct ieee80211_tx_ampdu *tap;
741eb6f0de0SAdrian Chadd 	int status = ATH_AGGR_DONE;
742eb6f0de0SAdrian Chadd 	int prev_frames = 0;	/* XXX for AR5416 burst, not done here */
743eb6f0de0SAdrian Chadd 	int prev_al = 0;	/* XXX also for AR5416 burst */
744eb6f0de0SAdrian Chadd 
745375307d4SAdrian Chadd 	ATH_TX_LOCK_ASSERT(sc);
746eb6f0de0SAdrian Chadd 
747eb6f0de0SAdrian Chadd 	tap = ath_tx_get_tx_tid(an, tid->tid);
748eb6f0de0SAdrian Chadd 	if (tap == NULL) {
749eb6f0de0SAdrian Chadd 		status = ATH_AGGR_ERROR;
750eb6f0de0SAdrian Chadd 		goto finish;
751eb6f0de0SAdrian Chadd 	}
752eb6f0de0SAdrian Chadd 
753eb6f0de0SAdrian Chadd 	h_baw = tap->txa_wnd / 2;
754eb6f0de0SAdrian Chadd 
755eb6f0de0SAdrian Chadd 	for (;;) {
7563e6cc97fSAdrian Chadd 		bf = ATH_TID_FIRST(tid);
757eb6f0de0SAdrian Chadd 		if (bf_first == NULL)
758eb6f0de0SAdrian Chadd 			bf_first = bf;
759eb6f0de0SAdrian Chadd 		if (bf == NULL) {
760eb6f0de0SAdrian Chadd 			status = ATH_AGGR_DONE;
761eb6f0de0SAdrian Chadd 			break;
762eb6f0de0SAdrian Chadd 		} else {
763eb6f0de0SAdrian Chadd 			/*
764eb6f0de0SAdrian Chadd 			 * It's the first frame;
765eb6f0de0SAdrian Chadd 			 * set the aggregation limit based on the
766eb6f0de0SAdrian Chadd 			 * rate control decision that has been made.
767eb6f0de0SAdrian Chadd 			 */
768eb6f0de0SAdrian Chadd 			aggr_limit = ath_get_aggr_limit(sc, bf_first);
769eb6f0de0SAdrian Chadd 		}
770eb6f0de0SAdrian Chadd 
771eb6f0de0SAdrian Chadd 		/* Set this early just so things don't get confused */
772eb6f0de0SAdrian Chadd 		bf->bf_next = NULL;
773eb6f0de0SAdrian Chadd 
774eb6f0de0SAdrian Chadd 		/*
775eb6f0de0SAdrian Chadd 		 * If the frame doesn't have a sequence number that we're
776eb6f0de0SAdrian Chadd 		 * tracking in the BAW (eg NULL QOS data frame), we can't
777eb6f0de0SAdrian Chadd 		 * aggregate it. Stop the aggregation process; the sender
778eb6f0de0SAdrian Chadd 		 * can then TX what's in the list thus far and then
779eb6f0de0SAdrian Chadd 		 * TX the frame individually.
780eb6f0de0SAdrian Chadd 		 */
781eb6f0de0SAdrian Chadd 		if (! bf->bf_state.bfs_dobaw) {
782eb6f0de0SAdrian Chadd 			status = ATH_AGGR_NONAGGR;
783eb6f0de0SAdrian Chadd 			break;
784eb6f0de0SAdrian Chadd 		}
785eb6f0de0SAdrian Chadd 
786eb6f0de0SAdrian Chadd 		/*
787eb6f0de0SAdrian Chadd 		 * If any of the rates are non-HT, this packet
788eb6f0de0SAdrian Chadd 		 * can't be aggregated.
789eb6f0de0SAdrian Chadd 		 * XXX TODO: add a bf_state flag which gets marked
790eb6f0de0SAdrian Chadd 		 * if any active rate is non-HT.
791eb6f0de0SAdrian Chadd 		 */
792eb6f0de0SAdrian Chadd 
793eb6f0de0SAdrian Chadd 		/*
794eb6f0de0SAdrian Chadd 		 * do not exceed aggregation limit
795eb6f0de0SAdrian Chadd 		 */
796eb6f0de0SAdrian Chadd 		al_delta = ATH_AGGR_DELIM_SZ + bf->bf_state.bfs_pktlen;
797eb6f0de0SAdrian Chadd 		if (nframes &&
798eb6f0de0SAdrian Chadd 		    (aggr_limit < (al + bpad + al_delta + prev_al))) {
799eb6f0de0SAdrian Chadd 			status = ATH_AGGR_LIMITED;
800eb6f0de0SAdrian Chadd 			break;
801eb6f0de0SAdrian Chadd 		}
802eb6f0de0SAdrian Chadd 
803eb6f0de0SAdrian Chadd 		/*
804045bc788SAdrian Chadd 		 * If RTS/CTS is set on the first frame, enforce
805045bc788SAdrian Chadd 		 * the RTS aggregate limit.
806045bc788SAdrian Chadd 		 */
807045bc788SAdrian Chadd 		if (bf_first->bf_state.bfs_txflags &
808045bc788SAdrian Chadd 		    (HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA)) {
809045bc788SAdrian Chadd 			if (nframes &&
810045bc788SAdrian Chadd 			   (sc->sc_rts_aggr_limit <
811045bc788SAdrian Chadd 			     (al + bpad + al_delta + prev_al))) {
812045bc788SAdrian Chadd 				status = ATH_AGGR_8K_LIMITED;
813045bc788SAdrian Chadd 				break;
814045bc788SAdrian Chadd 			}
815045bc788SAdrian Chadd 		}
816045bc788SAdrian Chadd 
817045bc788SAdrian Chadd 		/*
818eb6f0de0SAdrian Chadd 		 * Do not exceed subframe limit.
819eb6f0de0SAdrian Chadd 		 */
820eb6f0de0SAdrian Chadd 		if ((nframes + prev_frames) >= MIN((h_baw),
821eb6f0de0SAdrian Chadd 		    IEEE80211_AMPDU_SUBFRAME_DEFAULT)) {
822eb6f0de0SAdrian Chadd 			status = ATH_AGGR_LIMITED;
823eb6f0de0SAdrian Chadd 			break;
824eb6f0de0SAdrian Chadd 		}
825eb6f0de0SAdrian Chadd 
826eb6f0de0SAdrian Chadd 		/*
827045bc788SAdrian Chadd 		 * If the current frame has an RTS/CTS configuration
828781e7eafSAdrian Chadd 		 * that differs from the first frame, override the
829781e7eafSAdrian Chadd 		 * subsequent frame with this config.
830045bc788SAdrian Chadd 		 */
831d03904f1SAdrian Chadd 		if (bf != bf_first) {
832781e7eafSAdrian Chadd 			bf->bf_state.bfs_txflags &=
83376af1a93SAdrian Chadd 			    ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
834781e7eafSAdrian Chadd 			bf->bf_state.bfs_txflags |=
835781e7eafSAdrian Chadd 			    bf_first->bf_state.bfs_txflags &
836781e7eafSAdrian Chadd 			    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
837d03904f1SAdrian Chadd 		}
838045bc788SAdrian Chadd 
839045bc788SAdrian Chadd 		/*
8400b96ef63SAdrian Chadd 		 * If the packet has a sequence number, do not
8410b96ef63SAdrian Chadd 		 * step outside of the block-ack window.
8420b96ef63SAdrian Chadd 		 */
8430b96ef63SAdrian Chadd 		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
8440b96ef63SAdrian Chadd 		    SEQNO(bf->bf_state.bfs_seqno))) {
8450b96ef63SAdrian Chadd 			status = ATH_AGGR_BAW_CLOSED;
8460b96ef63SAdrian Chadd 			break;
8470b96ef63SAdrian Chadd 		}
8480b96ef63SAdrian Chadd 
8490b96ef63SAdrian Chadd 		/*
850eb6f0de0SAdrian Chadd 		 * this packet is part of an aggregate.
851eb6f0de0SAdrian Chadd 		 */
8523e6cc97fSAdrian Chadd 		ATH_TID_REMOVE(tid, bf, bf_list);
853eb6f0de0SAdrian Chadd 
854eb6f0de0SAdrian Chadd 		/* The TID lock is required for the BAW update */
855eb6f0de0SAdrian Chadd 		ath_tx_addto_baw(sc, an, tid, bf);
856eb6f0de0SAdrian Chadd 		bf->bf_state.bfs_addedbaw = 1;
857eb6f0de0SAdrian Chadd 
858eb6f0de0SAdrian Chadd 		/*
859eb6f0de0SAdrian Chadd 		 * XXX enforce ACK for aggregate frames (this needs to be
860eb6f0de0SAdrian Chadd 		 * XXX handled more gracefully?
861eb6f0de0SAdrian Chadd 		 */
862875a9451SAdrian Chadd 		if (bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) {
863eb6f0de0SAdrian Chadd 			device_printf(sc->sc_dev,
864eb6f0de0SAdrian Chadd 			    "%s: HAL_TXDESC_NOACK set for an aggregate frame?\n",
865eb6f0de0SAdrian Chadd 			    __func__);
866875a9451SAdrian Chadd 			bf->bf_state.bfs_txflags &= (~HAL_TXDESC_NOACK);
867eb6f0de0SAdrian Chadd 		}
868eb6f0de0SAdrian Chadd 
869eb6f0de0SAdrian Chadd 		/*
870eb6f0de0SAdrian Chadd 		 * Add the now owned buffer (which isn't
871eb6f0de0SAdrian Chadd 		 * on the software TXQ any longer) to our
872eb6f0de0SAdrian Chadd 		 * aggregate frame list.
873eb6f0de0SAdrian Chadd 		 */
874eb6f0de0SAdrian Chadd 		TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
875eb6f0de0SAdrian Chadd 		nframes ++;
876eb6f0de0SAdrian Chadd 
877eb6f0de0SAdrian Chadd 		/* Completion handler */
878eb6f0de0SAdrian Chadd 		bf->bf_comp = ath_tx_aggr_comp;
879eb6f0de0SAdrian Chadd 
880eb6f0de0SAdrian Chadd 		/*
881eb6f0de0SAdrian Chadd 		 * add padding for previous frame to aggregation length
882eb6f0de0SAdrian Chadd 		 */
883eb6f0de0SAdrian Chadd 		al += bpad + al_delta;
884eb6f0de0SAdrian Chadd 
885eb6f0de0SAdrian Chadd 		/*
886eb6f0de0SAdrian Chadd 		 * Calculate delimiters needed for the current frame
887eb6f0de0SAdrian Chadd 		 */
888eb6f0de0SAdrian Chadd 		bf->bf_state.bfs_ndelim =
889eb6f0de0SAdrian Chadd 		    ath_compute_num_delims(sc, bf_first,
890eb6f0de0SAdrian Chadd 		    bf->bf_state.bfs_pktlen);
891eb6f0de0SAdrian Chadd 
892eb6f0de0SAdrian Chadd 		/*
893eb6f0de0SAdrian Chadd 		 * Calculate the padding needed from this set of delimiters,
894eb6f0de0SAdrian Chadd 		 * used when calculating if the next frame will fit in
895eb6f0de0SAdrian Chadd 		 * the aggregate.
896eb6f0de0SAdrian Chadd 		 */
897eb6f0de0SAdrian Chadd 		bpad = PADBYTES(al_delta) + (bf->bf_state.bfs_ndelim << 2);
898eb6f0de0SAdrian Chadd 
899eb6f0de0SAdrian Chadd 		/*
900eb6f0de0SAdrian Chadd 		 * Chain the buffers together
901eb6f0de0SAdrian Chadd 		 */
902eb6f0de0SAdrian Chadd 		if (bf_prev)
903eb6f0de0SAdrian Chadd 			bf_prev->bf_next = bf;
904eb6f0de0SAdrian Chadd 		bf_prev = bf;
905eb6f0de0SAdrian Chadd 
906eb6f0de0SAdrian Chadd 		/*
90722a3aee6SAdrian Chadd 		 * If we're leaking frames, just return at this point;
90822a3aee6SAdrian Chadd 		 * we've queued a single frame and we don't want to add
90922a3aee6SAdrian Chadd 		 * any more.
910eb6f0de0SAdrian Chadd 		 */
91122a3aee6SAdrian Chadd 		if (tid->an->an_leak_count) {
91222a3aee6SAdrian Chadd 			status = ATH_AGGR_LEAK_CLOSED;
91322a3aee6SAdrian Chadd 			break;
91422a3aee6SAdrian Chadd 		}
915eb6f0de0SAdrian Chadd 
916eb6f0de0SAdrian Chadd #if 0
917eb6f0de0SAdrian Chadd 		/*
918eb6f0de0SAdrian Chadd 		 * terminate aggregation on a small packet boundary
919eb6f0de0SAdrian Chadd 		 */
920eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_pktlen < ATH_AGGR_MINPLEN) {
921eb6f0de0SAdrian Chadd 			status = ATH_AGGR_SHORTPKT;
922eb6f0de0SAdrian Chadd 			break;
923eb6f0de0SAdrian Chadd 		}
924eb6f0de0SAdrian Chadd #endif
925eb6f0de0SAdrian Chadd 
926eb6f0de0SAdrian Chadd 	}
927eb6f0de0SAdrian Chadd 
928eb6f0de0SAdrian Chadd finish:
929eb6f0de0SAdrian Chadd 	/*
930eb6f0de0SAdrian Chadd 	 * Just in case the list was empty when we tried to
931eb6f0de0SAdrian Chadd 	 * dequeue a packet ..
932eb6f0de0SAdrian Chadd 	 */
933eb6f0de0SAdrian Chadd 	if (bf_first) {
934eb6f0de0SAdrian Chadd 		bf_first->bf_state.bfs_al = al;
935eb6f0de0SAdrian Chadd 		bf_first->bf_state.bfs_nframes = nframes;
936eb6f0de0SAdrian Chadd 	}
937eb6f0de0SAdrian Chadd 	return status;
938eb6f0de0SAdrian Chadd }
939