xref: /dragonfly/sys/dev/netif/ath/ath/if_ath_tx_ht.c (revision 2b3f93ea)
1572ff6f6SMatthew Dillon /*-
2572ff6f6SMatthew Dillon  * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
3572ff6f6SMatthew Dillon  * All rights reserved.
4572ff6f6SMatthew Dillon  *
5572ff6f6SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
6572ff6f6SMatthew Dillon  * modification, are permitted provided that the following conditions
7572ff6f6SMatthew Dillon  * are met:
8572ff6f6SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
9572ff6f6SMatthew Dillon  *    notice, this list of conditions and the following disclaimer,
10572ff6f6SMatthew Dillon  *    without modification.
11572ff6f6SMatthew Dillon  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12572ff6f6SMatthew Dillon  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13572ff6f6SMatthew Dillon  *    redistribution must be conditioned upon including a substantially
14572ff6f6SMatthew Dillon  *    similar Disclaimer requirement for further binary redistribution.
15572ff6f6SMatthew Dillon  *
16572ff6f6SMatthew Dillon  * NO WARRANTY
17572ff6f6SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18572ff6f6SMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19df052c2aSSascha Wildner  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTABILITY
20572ff6f6SMatthew Dillon  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21572ff6f6SMatthew Dillon  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22572ff6f6SMatthew Dillon  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23572ff6f6SMatthew Dillon  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24572ff6f6SMatthew Dillon  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25572ff6f6SMatthew Dillon  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26572ff6f6SMatthew Dillon  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27572ff6f6SMatthew Dillon  * THE POSSIBILITY OF SUCH DAMAGES.
28572ff6f6SMatthew Dillon  */
29572ff6f6SMatthew Dillon 
30572ff6f6SMatthew Dillon #include <sys/cdefs.h>
31848b370cSMatthew Dillon __FBSDID("$FreeBSD$");
32572ff6f6SMatthew Dillon 
33572ff6f6SMatthew Dillon #include "opt_inet.h"
34572ff6f6SMatthew Dillon #include "opt_ath.h"
35572ff6f6SMatthew Dillon #include "opt_wlan.h"
36572ff6f6SMatthew Dillon 
37572ff6f6SMatthew Dillon #include <sys/param.h>
38572ff6f6SMatthew Dillon #include <sys/systm.h>
39572ff6f6SMatthew Dillon #include <sys/sysctl.h>
40572ff6f6SMatthew Dillon #include <sys/mbuf.h>
41572ff6f6SMatthew Dillon #include <sys/malloc.h>
42572ff6f6SMatthew Dillon #include <sys/lock.h>
43572ff6f6SMatthew Dillon #include <sys/kernel.h>
44572ff6f6SMatthew Dillon #include <sys/socket.h>
45572ff6f6SMatthew Dillon #include <sys/sockio.h>
46572ff6f6SMatthew Dillon #include <sys/errno.h>
47572ff6f6SMatthew Dillon #include <sys/callout.h>
48572ff6f6SMatthew Dillon #include <sys/bus.h>
49572ff6f6SMatthew Dillon #include <sys/endian.h>
50572ff6f6SMatthew Dillon #include <sys/kthread.h>
51572ff6f6SMatthew Dillon #include <sys/taskqueue.h>
52*2b3f93eaSMatthew Dillon #include <sys/caps.h>
53572ff6f6SMatthew Dillon 
54dc249793SMatthew Dillon #if defined(__DragonFly__)
55dc249793SMatthew Dillon /* empty */
56dc249793SMatthew Dillon #else
57b14ca477SMatthew Dillon #include <machine/bus.h>
58dc249793SMatthew Dillon #endif
59b14ca477SMatthew Dillon 
60572ff6f6SMatthew Dillon #include <net/if.h>
61572ff6f6SMatthew Dillon #include <net/if_dl.h>
62572ff6f6SMatthew Dillon #include <net/if_media.h>
63572ff6f6SMatthew Dillon #include <net/if_types.h>
64572ff6f6SMatthew Dillon #include <net/if_arp.h>
65572ff6f6SMatthew Dillon #include <net/ethernet.h>
66572ff6f6SMatthew Dillon #include <net/if_llc.h>
67572ff6f6SMatthew Dillon 
68dc249793SMatthew Dillon #include <netproto/802_11/ieee80211_var.h>
69dc249793SMatthew Dillon #include <netproto/802_11/ieee80211_regdomain.h>
70572ff6f6SMatthew Dillon #ifdef IEEE80211_SUPPORT_SUPERG
71dc249793SMatthew Dillon #include <netproto/802_11/ieee80211_superg.h>
72572ff6f6SMatthew Dillon #endif
73572ff6f6SMatthew Dillon #ifdef IEEE80211_SUPPORT_TDMA
74dc249793SMatthew Dillon #include <netproto/802_11/ieee80211_tdma.h>
75572ff6f6SMatthew Dillon #endif
76572ff6f6SMatthew Dillon 
77572ff6f6SMatthew Dillon #include <net/bpf.h>
78572ff6f6SMatthew Dillon 
79572ff6f6SMatthew Dillon #ifdef INET
80572ff6f6SMatthew Dillon #include <netinet/in.h>
81572ff6f6SMatthew Dillon #include <netinet/if_ether.h>
82572ff6f6SMatthew Dillon #endif
83572ff6f6SMatthew Dillon 
84dc249793SMatthew Dillon #include <dev/netif/ath/ath/if_athvar.h>
85dc249793SMatthew Dillon #include <dev/netif/ath/ath_hal/ah_devid.h>		/* XXX for softled */
86dc249793SMatthew Dillon #include <dev/netif/ath/ath_hal/ah_diagcodes.h>
87572ff6f6SMatthew Dillon 
88572ff6f6SMatthew Dillon #ifdef ATH_TX99_DIAG
89dc249793SMatthew Dillon #include <dev/netif/ath/ath_tx99/ath_tx99.h>
90572ff6f6SMatthew Dillon #endif
91572ff6f6SMatthew Dillon 
92dc249793SMatthew Dillon #include <dev/netif/ath/ath/if_ath_tx.h>		/* XXX for some support functions */
93dc249793SMatthew Dillon #include <dev/netif/ath/ath/if_ath_tx_ht.h>
94dc249793SMatthew Dillon #include <dev/netif/ath/ath/if_athrate.h>
95dc249793SMatthew Dillon #include <dev/netif/ath/ath/if_ath_debug.h>
96572ff6f6SMatthew Dillon 
97572ff6f6SMatthew Dillon /*
98572ff6f6SMatthew Dillon  * XXX net80211?
99572ff6f6SMatthew Dillon  */
100572ff6f6SMatthew Dillon #define	IEEE80211_AMPDU_SUBFRAME_DEFAULT		32
101572ff6f6SMatthew Dillon 
102572ff6f6SMatthew Dillon #define	ATH_AGGR_DELIM_SZ	4	/* delimiter size */
103572ff6f6SMatthew Dillon #define	ATH_AGGR_MINPLEN	256	/* in bytes, minimum packet length */
104572ff6f6SMatthew Dillon /* number of delimiters for encryption padding */
105572ff6f6SMatthew Dillon #define	ATH_AGGR_ENCRYPTDELIM	10
106572ff6f6SMatthew Dillon 
107572ff6f6SMatthew Dillon /*
108572ff6f6SMatthew Dillon  * returns delimiter padding required given the packet length
109572ff6f6SMatthew Dillon  */
110572ff6f6SMatthew Dillon #define	ATH_AGGR_GET_NDELIM(_len)					\
111572ff6f6SMatthew Dillon 	    (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?	\
112572ff6f6SMatthew Dillon 	    (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
113572ff6f6SMatthew Dillon 
114572ff6f6SMatthew Dillon #define	PADBYTES(_len)		((4 - ((_len) % 4)) % 4)
115572ff6f6SMatthew Dillon 
116572ff6f6SMatthew Dillon int ath_max_4ms_framelen[4][32] = {
117572ff6f6SMatthew Dillon 	[MCS_HT20] = {
118572ff6f6SMatthew Dillon 		3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
119572ff6f6SMatthew Dillon 		6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
120572ff6f6SMatthew Dillon 		9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
121572ff6f6SMatthew Dillon 		12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
122572ff6f6SMatthew Dillon 	},
123572ff6f6SMatthew Dillon 	[MCS_HT20_SGI] = {
124572ff6f6SMatthew Dillon 		3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
125572ff6f6SMatthew Dillon 		7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
126572ff6f6SMatthew Dillon 		10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
127572ff6f6SMatthew Dillon 		14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
128572ff6f6SMatthew Dillon 	},
129572ff6f6SMatthew Dillon 	[MCS_HT40] = {
130572ff6f6SMatthew Dillon 		6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
131572ff6f6SMatthew Dillon 		13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
132572ff6f6SMatthew Dillon 		20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
133572ff6f6SMatthew Dillon 		26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
134572ff6f6SMatthew Dillon 	},
135572ff6f6SMatthew Dillon 	[MCS_HT40_SGI] = {
136572ff6f6SMatthew Dillon 		7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
137572ff6f6SMatthew Dillon 		14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
138572ff6f6SMatthew Dillon 		22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
139572ff6f6SMatthew Dillon 		29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
140572ff6f6SMatthew Dillon 	}
141572ff6f6SMatthew Dillon };
142572ff6f6SMatthew Dillon 
143572ff6f6SMatthew Dillon /*
144572ff6f6SMatthew Dillon  * XXX should be in net80211
145572ff6f6SMatthew Dillon  */
146572ff6f6SMatthew Dillon static int ieee80211_mpdudensity_map[] = {
147572ff6f6SMatthew Dillon 	0,		/* IEEE80211_HTCAP_MPDUDENSITY_NA */
148572ff6f6SMatthew Dillon 	25,		/* IEEE80211_HTCAP_MPDUDENSITY_025 */
149572ff6f6SMatthew Dillon 	50,		/* IEEE80211_HTCAP_MPDUDENSITY_05 */
150572ff6f6SMatthew Dillon 	100,		/* IEEE80211_HTCAP_MPDUDENSITY_1 */
151572ff6f6SMatthew Dillon 	200,		/* IEEE80211_HTCAP_MPDUDENSITY_2 */
152572ff6f6SMatthew Dillon 	400,		/* IEEE80211_HTCAP_MPDUDENSITY_4 */
153572ff6f6SMatthew Dillon 	800,		/* IEEE80211_HTCAP_MPDUDENSITY_8 */
154572ff6f6SMatthew Dillon 	1600,		/* IEEE80211_HTCAP_MPDUDENSITY_16 */
155572ff6f6SMatthew Dillon };
156572ff6f6SMatthew Dillon 
157572ff6f6SMatthew Dillon /*
158572ff6f6SMatthew Dillon  * XXX should be in the HAL/net80211 ?
159572ff6f6SMatthew Dillon  */
160572ff6f6SMatthew Dillon #define	BITS_PER_BYTE		8
161572ff6f6SMatthew Dillon #define	OFDM_PLCP_BITS		22
162572ff6f6SMatthew Dillon #define	HT_RC_2_MCS(_rc)	((_rc) & 0x7f)
163572ff6f6SMatthew Dillon #define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
164572ff6f6SMatthew Dillon #define	L_STF			8
165572ff6f6SMatthew Dillon #define	L_LTF			8
166572ff6f6SMatthew Dillon #define	L_SIG			4
167572ff6f6SMatthew Dillon #define	HT_SIG			8
168572ff6f6SMatthew Dillon #define	HT_STF			4
169572ff6f6SMatthew Dillon #define	HT_LTF(_ns)		(4 * (_ns))
170572ff6f6SMatthew Dillon #define	SYMBOL_TIME(_ns)	((_ns) << 2)		// ns * 4 us
171572ff6f6SMatthew Dillon #define	SYMBOL_TIME_HALFGI(_ns)	(((_ns) * 18 + 4) / 5)	// ns * 3.6 us
172572ff6f6SMatthew Dillon #define	NUM_SYMBOLS_PER_USEC(_usec)	(_usec >> 2)
173572ff6f6SMatthew Dillon #define	NUM_SYMBOLS_PER_USEC_HALFGI(_usec)	(((_usec*5)-4)/18)
174572ff6f6SMatthew Dillon #define	IS_HT_RATE(_rate)	((_rate) & 0x80)
175572ff6f6SMatthew Dillon 
176572ff6f6SMatthew Dillon const uint32_t bits_per_symbol[][2] = {
177572ff6f6SMatthew Dillon     /* 20MHz 40MHz */
178572ff6f6SMatthew Dillon     {    26,   54 },     //  0: BPSK
179572ff6f6SMatthew Dillon     {    52,  108 },     //  1: QPSK 1/2
180572ff6f6SMatthew Dillon     {    78,  162 },     //  2: QPSK 3/4
181572ff6f6SMatthew Dillon     {   104,  216 },     //  3: 16-QAM 1/2
182572ff6f6SMatthew Dillon     {   156,  324 },     //  4: 16-QAM 3/4
183572ff6f6SMatthew Dillon     {   208,  432 },     //  5: 64-QAM 2/3
184572ff6f6SMatthew Dillon     {   234,  486 },     //  6: 64-QAM 3/4
185572ff6f6SMatthew Dillon     {   260,  540 },     //  7: 64-QAM 5/6
186572ff6f6SMatthew Dillon     {    52,  108 },     //  8: BPSK
187572ff6f6SMatthew Dillon     {   104,  216 },     //  9: QPSK 1/2
188572ff6f6SMatthew Dillon     {   156,  324 },     // 10: QPSK 3/4
189572ff6f6SMatthew Dillon     {   208,  432 },     // 11: 16-QAM 1/2
190572ff6f6SMatthew Dillon     {   312,  648 },     // 12: 16-QAM 3/4
191572ff6f6SMatthew Dillon     {   416,  864 },     // 13: 64-QAM 2/3
192572ff6f6SMatthew Dillon     {   468,  972 },     // 14: 64-QAM 3/4
193572ff6f6SMatthew Dillon     {   520, 1080 },     // 15: 64-QAM 5/6
194572ff6f6SMatthew Dillon     {    78,  162 },     // 16: BPSK
195572ff6f6SMatthew Dillon     {   156,  324 },     // 17: QPSK 1/2
196572ff6f6SMatthew Dillon     {   234,  486 },     // 18: QPSK 3/4
197572ff6f6SMatthew Dillon     {   312,  648 },     // 19: 16-QAM 1/2
198572ff6f6SMatthew Dillon     {   468,  972 },     // 20: 16-QAM 3/4
199572ff6f6SMatthew Dillon     {   624, 1296 },     // 21: 64-QAM 2/3
200572ff6f6SMatthew Dillon     {   702, 1458 },     // 22: 64-QAM 3/4
201572ff6f6SMatthew Dillon     {   780, 1620 },     // 23: 64-QAM 5/6
202572ff6f6SMatthew Dillon     {   104,  216 },     // 24: BPSK
203572ff6f6SMatthew Dillon     {   208,  432 },     // 25: QPSK 1/2
204572ff6f6SMatthew Dillon     {   312,  648 },     // 26: QPSK 3/4
205572ff6f6SMatthew Dillon     {   416,  864 },     // 27: 16-QAM 1/2
206572ff6f6SMatthew Dillon     {   624, 1296 },     // 28: 16-QAM 3/4
207572ff6f6SMatthew Dillon     {   832, 1728 },     // 29: 64-QAM 2/3
208572ff6f6SMatthew Dillon     {   936, 1944 },     // 30: 64-QAM 3/4
209572ff6f6SMatthew Dillon     {  1040, 2160 },     // 31: 64-QAM 5/6
210572ff6f6SMatthew Dillon };
211572ff6f6SMatthew Dillon 
212572ff6f6SMatthew Dillon /*
213572ff6f6SMatthew Dillon  * Fill in the rate array information based on the current
214572ff6f6SMatthew Dillon  * node configuration and the choices made by the rate
215572ff6f6SMatthew Dillon  * selection code and ath_buf setup code.
216572ff6f6SMatthew Dillon  *
217572ff6f6SMatthew Dillon  * Later on, this may end up also being made by the
218572ff6f6SMatthew Dillon  * rate control code, but for now it can live here.
219572ff6f6SMatthew Dillon  *
220572ff6f6SMatthew Dillon  * This needs to be called just before the packet is
221572ff6f6SMatthew Dillon  * queued to the software queue or hardware queue,
222572ff6f6SMatthew Dillon  * so all of the needed fields in bf_state are setup.
223572ff6f6SMatthew Dillon  */
224572ff6f6SMatthew Dillon void
ath_tx_rate_fill_rcflags(struct ath_softc * sc,struct ath_buf * bf)225572ff6f6SMatthew Dillon ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
226572ff6f6SMatthew Dillon {
227572ff6f6SMatthew Dillon 	struct ieee80211_node *ni = bf->bf_node;
228572ff6f6SMatthew Dillon 	struct ieee80211com *ic = ni->ni_ic;
229572ff6f6SMatthew Dillon 	const HAL_RATE_TABLE *rt = sc->sc_currates;
230572ff6f6SMatthew Dillon 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
231572ff6f6SMatthew Dillon 	uint8_t rate;
232572ff6f6SMatthew Dillon 	int i;
233b14ca477SMatthew Dillon 	int do_ldpc;
234b14ca477SMatthew Dillon 	int do_stbc;
235b14ca477SMatthew Dillon 
236b14ca477SMatthew Dillon 	/*
237b14ca477SMatthew Dillon 	 * We only do LDPC if the rate is 11n, both we and the
238b14ca477SMatthew Dillon 	 * receiver support LDPC and it's enabled.
239b14ca477SMatthew Dillon 	 *
240b14ca477SMatthew Dillon 	 * It's a global flag, not a per-try flag, so we clear
241b14ca477SMatthew Dillon 	 * it if any of the rate entries aren't 11n.
242b14ca477SMatthew Dillon 	 */
243b14ca477SMatthew Dillon 	do_ldpc = 0;
244b14ca477SMatthew Dillon 	if ((ni->ni_vap->iv_htcaps & IEEE80211_HTCAP_LDPC) &&
245b14ca477SMatthew Dillon 	    (ni->ni_htcap & IEEE80211_HTCAP_LDPC))
246b14ca477SMatthew Dillon 		do_ldpc = 1;
247b14ca477SMatthew Dillon 	do_stbc = 0;
248572ff6f6SMatthew Dillon 
249572ff6f6SMatthew Dillon 	for (i = 0; i < ATH_RC_NUM; i++) {
250572ff6f6SMatthew Dillon 		rc[i].flags = 0;
251572ff6f6SMatthew Dillon 		if (rc[i].tries == 0)
252572ff6f6SMatthew Dillon 			continue;
253572ff6f6SMatthew Dillon 
254572ff6f6SMatthew Dillon 		rate = rt->info[rc[i].rix].rateCode;
255572ff6f6SMatthew Dillon 
256572ff6f6SMatthew Dillon 		/*
257572ff6f6SMatthew Dillon 		 * Only enable short preamble for legacy rates
258572ff6f6SMatthew Dillon 		 */
259572ff6f6SMatthew Dillon 		if ((! IS_HT_RATE(rate)) && bf->bf_state.bfs_shpream)
260572ff6f6SMatthew Dillon 			rate |= rt->info[rc[i].rix].shortPreamble;
261572ff6f6SMatthew Dillon 
262572ff6f6SMatthew Dillon 		/*
263572ff6f6SMatthew Dillon 		 * Save this, used by the TX and completion code
264572ff6f6SMatthew Dillon 		 */
265572ff6f6SMatthew Dillon 		rc[i].ratecode = rate;
266572ff6f6SMatthew Dillon 
267572ff6f6SMatthew Dillon 		if (bf->bf_state.bfs_txflags &
268572ff6f6SMatthew Dillon 		    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
269572ff6f6SMatthew Dillon 			rc[i].flags |= ATH_RC_RTSCTS_FLAG;
270572ff6f6SMatthew Dillon 
271b14ca477SMatthew Dillon 		/*
272b14ca477SMatthew Dillon 		 * If we can't do LDPC, don't.
273b14ca477SMatthew Dillon 		 */
274b14ca477SMatthew Dillon 		if (! IS_HT_RATE(rate))
275b14ca477SMatthew Dillon 			do_ldpc = 0;
276b14ca477SMatthew Dillon 
277572ff6f6SMatthew Dillon 		/* Only enable shortgi, 2040, dual-stream if HT is set */
278572ff6f6SMatthew Dillon 		if (IS_HT_RATE(rate)) {
279572ff6f6SMatthew Dillon 			rc[i].flags |= ATH_RC_HT_FLAG;
280572ff6f6SMatthew Dillon 
281572ff6f6SMatthew Dillon 			if (ni->ni_chw == 40)
282572ff6f6SMatthew Dillon 				rc[i].flags |= ATH_RC_CW40_FLAG;
283572ff6f6SMatthew Dillon 
284572ff6f6SMatthew Dillon 			if (ni->ni_chw == 40 &&
285572ff6f6SMatthew Dillon 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
286572ff6f6SMatthew Dillon 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
287572ff6f6SMatthew Dillon 				rc[i].flags |= ATH_RC_SGI_FLAG;
288572ff6f6SMatthew Dillon 
289572ff6f6SMatthew Dillon 			if (ni->ni_chw == 20 &&
290572ff6f6SMatthew Dillon 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
291572ff6f6SMatthew Dillon 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
292572ff6f6SMatthew Dillon 				rc[i].flags |= ATH_RC_SGI_FLAG;
293572ff6f6SMatthew Dillon 
294572ff6f6SMatthew Dillon 			/*
295572ff6f6SMatthew Dillon 			 * If we have STBC TX enabled and the receiver
296572ff6f6SMatthew Dillon 			 * can receive (at least) 1 stream STBC, AND it's
297572ff6f6SMatthew Dillon 			 * MCS 0-7, AND we have at least two chains enabled,
298572ff6f6SMatthew Dillon 			 * enable STBC.
299b14ca477SMatthew Dillon 			 *
300b14ca477SMatthew Dillon 			 * XXX TODO: .. and the rate is an 11n rate?
301572ff6f6SMatthew Dillon 			 */
302572ff6f6SMatthew Dillon 			if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
303b14ca477SMatthew Dillon 			    ni->ni_vap->iv_flags_ht & IEEE80211_FHT_STBC_TX &&
304572ff6f6SMatthew Dillon 			    ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
305572ff6f6SMatthew Dillon 			    (sc->sc_cur_txchainmask > 1) &&
306572ff6f6SMatthew Dillon 			    HT_RC_2_STREAMS(rate) == 1) {
307572ff6f6SMatthew Dillon 				rc[i].flags |= ATH_RC_STBC_FLAG;
308b14ca477SMatthew Dillon 				do_stbc = 1;
309572ff6f6SMatthew Dillon 			}
310572ff6f6SMatthew Dillon 
311572ff6f6SMatthew Dillon 			/*
312572ff6f6SMatthew Dillon 			 * Dual / Triple stream rate?
313572ff6f6SMatthew Dillon 			 */
314572ff6f6SMatthew Dillon 			if (HT_RC_2_STREAMS(rate) == 2)
315572ff6f6SMatthew Dillon 				rc[i].flags |= ATH_RC_DS_FLAG;
316572ff6f6SMatthew Dillon 			else if (HT_RC_2_STREAMS(rate) == 3)
317572ff6f6SMatthew Dillon 				rc[i].flags |= ATH_RC_TS_FLAG;
318572ff6f6SMatthew Dillon 		}
319572ff6f6SMatthew Dillon 
320572ff6f6SMatthew Dillon 		/*
321572ff6f6SMatthew Dillon 		 * Calculate the maximum TX power cap for the current
322572ff6f6SMatthew Dillon 		 * node.
323572ff6f6SMatthew Dillon 		 */
324572ff6f6SMatthew Dillon 		rc[i].tx_power_cap = ieee80211_get_node_txpower(ni);
325572ff6f6SMatthew Dillon 
326572ff6f6SMatthew Dillon 		/*
327572ff6f6SMatthew Dillon 		 * Calculate the maximum 4ms frame length based
328572ff6f6SMatthew Dillon 		 * on the MCS rate, SGI and channel width flags.
329572ff6f6SMatthew Dillon 		 */
330572ff6f6SMatthew Dillon 		if ((rc[i].flags & ATH_RC_HT_FLAG) &&
331572ff6f6SMatthew Dillon 		    (HT_RC_2_MCS(rate) < 32)) {
332572ff6f6SMatthew Dillon 			int j;
333572ff6f6SMatthew Dillon 			if (rc[i].flags & ATH_RC_CW40_FLAG) {
334572ff6f6SMatthew Dillon 				if (rc[i].flags & ATH_RC_SGI_FLAG)
335572ff6f6SMatthew Dillon 					j = MCS_HT40_SGI;
336572ff6f6SMatthew Dillon 				else
337572ff6f6SMatthew Dillon 					j = MCS_HT40;
338572ff6f6SMatthew Dillon 			} else {
339572ff6f6SMatthew Dillon 				if (rc[i].flags & ATH_RC_SGI_FLAG)
340572ff6f6SMatthew Dillon 					j = MCS_HT20_SGI;
341572ff6f6SMatthew Dillon 				else
342572ff6f6SMatthew Dillon 					j = MCS_HT20;
343572ff6f6SMatthew Dillon 			}
344572ff6f6SMatthew Dillon 			rc[i].max4msframelen =
345572ff6f6SMatthew Dillon 			    ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)];
346572ff6f6SMatthew Dillon 		} else
347572ff6f6SMatthew Dillon 			rc[i].max4msframelen = 0;
348572ff6f6SMatthew Dillon 		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
349572ff6f6SMatthew Dillon 		    "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
350572ff6f6SMatthew Dillon 		    __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
351572ff6f6SMatthew Dillon 	}
352b14ca477SMatthew Dillon 
353b14ca477SMatthew Dillon 	/*
354b14ca477SMatthew Dillon 	 * LDPC is a global flag, so ...
355b14ca477SMatthew Dillon 	 */
356b14ca477SMatthew Dillon 	if (do_ldpc) {
357b14ca477SMatthew Dillon 		bf->bf_state.bfs_txflags |= HAL_TXDESC_LDPC;
358b14ca477SMatthew Dillon 		sc->sc_stats.ast_tx_ldpc++;
359b14ca477SMatthew Dillon 	}
360b14ca477SMatthew Dillon 
361b14ca477SMatthew Dillon 	if (do_stbc) {
362b14ca477SMatthew Dillon 		sc->sc_stats.ast_tx_stbc++;
363b14ca477SMatthew Dillon 	}
364572ff6f6SMatthew Dillon }
365572ff6f6SMatthew Dillon 
366572ff6f6SMatthew Dillon /*
367572ff6f6SMatthew Dillon  * Return the number of delimiters to be added to
368572ff6f6SMatthew Dillon  * meet the minimum required mpdudensity.
369572ff6f6SMatthew Dillon  *
370572ff6f6SMatthew Dillon  * Caller should make sure that the rate is HT.
371572ff6f6SMatthew Dillon  *
372572ff6f6SMatthew Dillon  * TODO: is this delimiter calculation supposed to be the
373572ff6f6SMatthew Dillon  * total frame length, the hdr length, the data length (including
374572ff6f6SMatthew Dillon  * delimiters, padding, CRC, etc) or ?
375572ff6f6SMatthew Dillon  *
376572ff6f6SMatthew Dillon  * TODO: this should ensure that the rate control information
377572ff6f6SMatthew Dillon  * HAS been setup for the first rate.
378572ff6f6SMatthew Dillon  *
379572ff6f6SMatthew Dillon  * TODO: ensure this is only called for MCS rates.
380572ff6f6SMatthew Dillon  *
381572ff6f6SMatthew Dillon  * TODO: enforce MCS < 31
382572ff6f6SMatthew Dillon  */
383572ff6f6SMatthew Dillon static int
ath_compute_num_delims(struct ath_softc * sc,struct ath_buf * first_bf,uint16_t pktlen)384572ff6f6SMatthew Dillon ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf,
385572ff6f6SMatthew Dillon     uint16_t pktlen)
386572ff6f6SMatthew Dillon {
387572ff6f6SMatthew Dillon 	const HAL_RATE_TABLE *rt = sc->sc_currates;
388572ff6f6SMatthew Dillon 	struct ieee80211_node *ni = first_bf->bf_node;
389572ff6f6SMatthew Dillon 	struct ieee80211vap *vap = ni->ni_vap;
390572ff6f6SMatthew Dillon 	int ndelim, mindelim = 0;
391572ff6f6SMatthew Dillon 	int mpdudensity;	 /* in 1/100'th of a microsecond */
392572ff6f6SMatthew Dillon 	uint8_t rc, rix, flags;
393572ff6f6SMatthew Dillon 	int width, half_gi;
394572ff6f6SMatthew Dillon 	uint32_t nsymbits, nsymbols;
395572ff6f6SMatthew Dillon 	uint16_t minlen;
396572ff6f6SMatthew Dillon 
397572ff6f6SMatthew Dillon 	/*
398572ff6f6SMatthew Dillon 	 * vap->iv_ampdu_density is a value, rather than the actual
399572ff6f6SMatthew Dillon 	 * density.
400572ff6f6SMatthew Dillon 	 */
401572ff6f6SMatthew Dillon 	if (vap->iv_ampdu_density > IEEE80211_HTCAP_MPDUDENSITY_16)
402572ff6f6SMatthew Dillon 		mpdudensity = 1600;		/* maximum density */
403572ff6f6SMatthew Dillon 	else
404572ff6f6SMatthew Dillon 		mpdudensity = ieee80211_mpdudensity_map[vap->iv_ampdu_density];
405572ff6f6SMatthew Dillon 
406572ff6f6SMatthew Dillon 	/* Select standard number of delimiters based on frame length */
407572ff6f6SMatthew Dillon 	ndelim = ATH_AGGR_GET_NDELIM(pktlen);
408572ff6f6SMatthew Dillon 
409572ff6f6SMatthew Dillon 	/*
410572ff6f6SMatthew Dillon 	 * If encryption is enabled, add extra delimiters to let the
411572ff6f6SMatthew Dillon 	 * crypto hardware catch up. This could be tuned per-MAC and
412572ff6f6SMatthew Dillon 	 * per-rate, but for now we'll simply assume encryption is
413572ff6f6SMatthew Dillon 	 * always enabled.
414572ff6f6SMatthew Dillon 	 *
415572ff6f6SMatthew Dillon 	 * Also note that the Atheros reference driver inserts two
416572ff6f6SMatthew Dillon 	 * delimiters by default for pre-AR9380 peers.  This will
417572ff6f6SMatthew Dillon 	 * include "that" required delimiter.
418572ff6f6SMatthew Dillon 	 */
419572ff6f6SMatthew Dillon 	ndelim += ATH_AGGR_ENCRYPTDELIM;
420572ff6f6SMatthew Dillon 
421572ff6f6SMatthew Dillon 	/*
422572ff6f6SMatthew Dillon 	 * For AR9380, there's a minimum number of delimeters
423572ff6f6SMatthew Dillon 	 * required when doing RTS.
424572ff6f6SMatthew Dillon 	 *
425572ff6f6SMatthew Dillon 	 * XXX TODO: this is only needed if (a) RTS/CTS is enabled, and
426572ff6f6SMatthew Dillon 	 * XXX (b) this is the first sub-frame in the aggregate.
427572ff6f6SMatthew Dillon 	 */
428572ff6f6SMatthew Dillon 	if (sc->sc_use_ent && (sc->sc_ent_cfg & AH_ENT_RTSCTS_DELIM_WAR)
429572ff6f6SMatthew Dillon 	    && ndelim < AH_FIRST_DESC_NDELIMS)
430572ff6f6SMatthew Dillon 		ndelim = AH_FIRST_DESC_NDELIMS;
431572ff6f6SMatthew Dillon 
432572ff6f6SMatthew Dillon 	/*
433572ff6f6SMatthew Dillon 	 * If sc_delim_min_pad is non-zero, enforce it as the minimum
434572ff6f6SMatthew Dillon 	 * pad delimiter count.
435572ff6f6SMatthew Dillon 	 */
436572ff6f6SMatthew Dillon 	if (sc->sc_delim_min_pad != 0)
437572ff6f6SMatthew Dillon 		ndelim = MAX(ndelim, sc->sc_delim_min_pad);
438572ff6f6SMatthew Dillon 
439572ff6f6SMatthew Dillon 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
440572ff6f6SMatthew Dillon 	    "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n",
441572ff6f6SMatthew Dillon 	    __func__, pktlen, ndelim, mpdudensity);
442572ff6f6SMatthew Dillon 
443572ff6f6SMatthew Dillon 	/*
444572ff6f6SMatthew Dillon 	 * If the MPDU density is 0, we can return here.
445572ff6f6SMatthew Dillon 	 * Otherwise, we need to convert the desired mpdudensity
446572ff6f6SMatthew Dillon 	 * into a byte length, based on the rate in the subframe.
447572ff6f6SMatthew Dillon 	 */
448572ff6f6SMatthew Dillon 	if (mpdudensity == 0)
449572ff6f6SMatthew Dillon 		return ndelim;
450572ff6f6SMatthew Dillon 
451572ff6f6SMatthew Dillon 	/*
452572ff6f6SMatthew Dillon 	 * Convert desired mpdu density from microeconds to bytes based
453572ff6f6SMatthew Dillon 	 * on highest rate in rate series (i.e. first rate) to determine
454572ff6f6SMatthew Dillon 	 * required minimum length for subframe. Take into account
455572ff6f6SMatthew Dillon 	 * whether high rate is 20 or 40Mhz and half or full GI.
456572ff6f6SMatthew Dillon 	 */
457572ff6f6SMatthew Dillon 	rix = first_bf->bf_state.bfs_rc[0].rix;
458572ff6f6SMatthew Dillon 	rc = rt->info[rix].rateCode;
459572ff6f6SMatthew Dillon 	flags = first_bf->bf_state.bfs_rc[0].flags;
460572ff6f6SMatthew Dillon 	width = !! (flags & ATH_RC_CW40_FLAG);
461572ff6f6SMatthew Dillon 	half_gi = !! (flags & ATH_RC_SGI_FLAG);
462572ff6f6SMatthew Dillon 
463572ff6f6SMatthew Dillon 	/*
464572ff6f6SMatthew Dillon 	 * mpdudensity is in 1/100th of a usec, so divide by 100
465572ff6f6SMatthew Dillon 	 */
466572ff6f6SMatthew Dillon 	if (half_gi)
467572ff6f6SMatthew Dillon 		nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
468572ff6f6SMatthew Dillon 	else
469572ff6f6SMatthew Dillon 		nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
470572ff6f6SMatthew Dillon 	nsymbols /= 100;
471572ff6f6SMatthew Dillon 
472572ff6f6SMatthew Dillon 	if (nsymbols == 0)
473572ff6f6SMatthew Dillon 		nsymbols = 1;
474572ff6f6SMatthew Dillon 
475572ff6f6SMatthew Dillon 	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
476572ff6f6SMatthew Dillon 	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
477572ff6f6SMatthew Dillon 
478572ff6f6SMatthew Dillon 	/*
479572ff6f6SMatthew Dillon 	 * Min length is the minimum frame length for the
480572ff6f6SMatthew Dillon 	 * required MPDU density.
481572ff6f6SMatthew Dillon 	 */
482572ff6f6SMatthew Dillon 	if (pktlen < minlen) {
483572ff6f6SMatthew Dillon 		mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ;
484572ff6f6SMatthew Dillon 		ndelim = MAX(mindelim, ndelim);
485572ff6f6SMatthew Dillon 	}
486572ff6f6SMatthew Dillon 
487572ff6f6SMatthew Dillon 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
488572ff6f6SMatthew Dillon 	    "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n",
489572ff6f6SMatthew Dillon 	    __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim);
490572ff6f6SMatthew Dillon 
491572ff6f6SMatthew Dillon 	return ndelim;
492572ff6f6SMatthew Dillon }
493572ff6f6SMatthew Dillon 
494572ff6f6SMatthew Dillon /*
495572ff6f6SMatthew Dillon  * Fetch the aggregation limit.
496572ff6f6SMatthew Dillon  *
497572ff6f6SMatthew Dillon  * It's the lowest of the four rate series 4ms frame length.
498572ff6f6SMatthew Dillon  */
499572ff6f6SMatthew Dillon static int
ath_get_aggr_limit(struct ath_softc * sc,struct ath_buf * bf)500572ff6f6SMatthew Dillon ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf)
501572ff6f6SMatthew Dillon {
502572ff6f6SMatthew Dillon 	int amin = ATH_AGGR_MAXSIZE;
503572ff6f6SMatthew Dillon 	int i;
504572ff6f6SMatthew Dillon 
505572ff6f6SMatthew Dillon 	if (sc->sc_aggr_limit > 0 && sc->sc_aggr_limit < ATH_AGGR_MAXSIZE)
506572ff6f6SMatthew Dillon 		amin = sc->sc_aggr_limit;
507572ff6f6SMatthew Dillon 
508572ff6f6SMatthew Dillon 	for (i = 0; i < ATH_RC_NUM; i++) {
509572ff6f6SMatthew Dillon 		if (bf->bf_state.bfs_rc[i].tries == 0)
510572ff6f6SMatthew Dillon 			continue;
511572ff6f6SMatthew Dillon 		amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen);
512572ff6f6SMatthew Dillon 	}
513572ff6f6SMatthew Dillon 
514572ff6f6SMatthew Dillon 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: max frame len= %d\n",
515572ff6f6SMatthew Dillon 	    __func__, amin);
516572ff6f6SMatthew Dillon 
517572ff6f6SMatthew Dillon 	return amin;
518572ff6f6SMatthew Dillon }
519572ff6f6SMatthew Dillon 
520572ff6f6SMatthew Dillon /*
521572ff6f6SMatthew Dillon  * Setup a 11n rate series structure
522572ff6f6SMatthew Dillon  *
523572ff6f6SMatthew Dillon  * This should be called for both legacy and MCS rates.
524572ff6f6SMatthew Dillon  *
525572ff6f6SMatthew Dillon  * This uses the rate series stuf from ath_tx_rate_fill_rcflags().
526572ff6f6SMatthew Dillon  *
527572ff6f6SMatthew Dillon  * It, along with ath_buf_set_rate, must be called -after- a burst
528572ff6f6SMatthew Dillon  * or aggregate is setup.
529572ff6f6SMatthew Dillon  */
530572ff6f6SMatthew Dillon static void
ath_rateseries_setup(struct ath_softc * sc,struct ieee80211_node * ni,struct ath_buf * bf,HAL_11N_RATE_SERIES * series)531572ff6f6SMatthew Dillon ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
532572ff6f6SMatthew Dillon     struct ath_buf *bf, HAL_11N_RATE_SERIES *series)
533572ff6f6SMatthew Dillon {
534572ff6f6SMatthew Dillon 	struct ieee80211com *ic = ni->ni_ic;
535572ff6f6SMatthew Dillon 	struct ath_hal *ah = sc->sc_ah;
536572ff6f6SMatthew Dillon 	HAL_BOOL shortPreamble = AH_FALSE;
537572ff6f6SMatthew Dillon 	const HAL_RATE_TABLE *rt = sc->sc_currates;
538572ff6f6SMatthew Dillon 	int i;
539572ff6f6SMatthew Dillon 	int pktlen;
540572ff6f6SMatthew Dillon 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
541572ff6f6SMatthew Dillon 
542572ff6f6SMatthew Dillon 	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
543572ff6f6SMatthew Dillon 	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
544572ff6f6SMatthew Dillon 		shortPreamble = AH_TRUE;
545572ff6f6SMatthew Dillon 
546572ff6f6SMatthew Dillon 	/*
547572ff6f6SMatthew Dillon 	 * If this is the first frame in an aggregate series,
548572ff6f6SMatthew Dillon 	 * use the aggregate length.
549572ff6f6SMatthew Dillon 	 */
550572ff6f6SMatthew Dillon 	if (bf->bf_state.bfs_aggr)
551572ff6f6SMatthew Dillon 		pktlen = bf->bf_state.bfs_al;
552572ff6f6SMatthew Dillon 	else
553572ff6f6SMatthew Dillon 		pktlen = bf->bf_state.bfs_pktlen;
554572ff6f6SMatthew Dillon 
555572ff6f6SMatthew Dillon 	/*
556572ff6f6SMatthew Dillon 	 * XXX TODO: modify this routine to use the bfs_rc[x].flags
557572ff6f6SMatthew Dillon 	 * XXX fields.
558572ff6f6SMatthew Dillon 	 */
559572ff6f6SMatthew Dillon 	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
560572ff6f6SMatthew Dillon 	for (i = 0; i < ATH_RC_NUM;  i++) {
561572ff6f6SMatthew Dillon 		/* Only set flags for actual TX attempts */
562572ff6f6SMatthew Dillon 		if (rc[i].tries == 0)
563572ff6f6SMatthew Dillon 			continue;
564572ff6f6SMatthew Dillon 
565572ff6f6SMatthew Dillon 		series[i].Tries = rc[i].tries;
566572ff6f6SMatthew Dillon 
567572ff6f6SMatthew Dillon 		/*
568572ff6f6SMatthew Dillon 		 * XXX TODO: When the NIC is capable of three stream TX,
569572ff6f6SMatthew Dillon 		 * transmit 1/2 stream rates on two streams.
570572ff6f6SMatthew Dillon 		 *
571572ff6f6SMatthew Dillon 		 * This reduces the power consumption of the NIC and
572572ff6f6SMatthew Dillon 		 * keeps it within the PCIe slot power limits.
573572ff6f6SMatthew Dillon 		 */
574572ff6f6SMatthew Dillon 		series[i].ChSel = sc->sc_cur_txchainmask;
575572ff6f6SMatthew Dillon 
576572ff6f6SMatthew Dillon 		/*
577572ff6f6SMatthew Dillon 		 * Setup rate and TX power cap for this series.
578572ff6f6SMatthew Dillon 		 */
579572ff6f6SMatthew Dillon 		series[i].Rate = rt->info[rc[i].rix].rateCode;
580572ff6f6SMatthew Dillon 		series[i].RateIndex = rc[i].rix;
581572ff6f6SMatthew Dillon 		series[i].tx_power_cap = rc[i].tx_power_cap;
582572ff6f6SMatthew Dillon 
583572ff6f6SMatthew Dillon 		/*
584572ff6f6SMatthew Dillon 		 * Enable RTS/CTS as appropriate.
585572ff6f6SMatthew Dillon 		 */
586572ff6f6SMatthew Dillon 		if (rc[i].flags & ATH_RC_RTSCTS_FLAG)
587572ff6f6SMatthew Dillon 			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
588572ff6f6SMatthew Dillon 
589572ff6f6SMatthew Dillon 		/*
590572ff6f6SMatthew Dillon 		 * 11n rate? Update 11n flags.
591572ff6f6SMatthew Dillon 		 */
592572ff6f6SMatthew Dillon 		if (rc[i].flags & ATH_RC_HT_FLAG) {
593572ff6f6SMatthew Dillon 			if (rc[i].flags & ATH_RC_CW40_FLAG)
594572ff6f6SMatthew Dillon 				series[i].RateFlags |= HAL_RATESERIES_2040;
595572ff6f6SMatthew Dillon 
596572ff6f6SMatthew Dillon 			if (rc[i].flags & ATH_RC_SGI_FLAG)
597572ff6f6SMatthew Dillon 				series[i].RateFlags |= HAL_RATESERIES_HALFGI;
598572ff6f6SMatthew Dillon 
599572ff6f6SMatthew Dillon 			if (rc[i].flags & ATH_RC_STBC_FLAG)
600572ff6f6SMatthew Dillon 				series[i].RateFlags |= HAL_RATESERIES_STBC;
601572ff6f6SMatthew Dillon 		}
602572ff6f6SMatthew Dillon 
603572ff6f6SMatthew Dillon 		/*
604b14ca477SMatthew Dillon 		 * TODO: If we're all doing 11n rates then we can set LDPC.
605b14ca477SMatthew Dillon 		 * If we've been asked to /do/ LDPC but we are handed a
606b14ca477SMatthew Dillon 		 * legacy rate, then we should complain.  Loudly.
607b14ca477SMatthew Dillon 		 */
608b14ca477SMatthew Dillon 
609b14ca477SMatthew Dillon 		/*
610572ff6f6SMatthew Dillon 		 * PktDuration doesn't include slot, ACK, RTS, etc timing -
611572ff6f6SMatthew Dillon 		 * it's just the packet duration
612572ff6f6SMatthew Dillon 		 */
613572ff6f6SMatthew Dillon 		if (rc[i].flags & ATH_RC_HT_FLAG) {
614572ff6f6SMatthew Dillon 			series[i].PktDuration =
615572ff6f6SMatthew Dillon 			    ath_computedur_ht(pktlen
616572ff6f6SMatthew Dillon 				, series[i].Rate
617572ff6f6SMatthew Dillon 				, HT_RC_2_STREAMS(series[i].Rate)
618572ff6f6SMatthew Dillon 				, series[i].RateFlags & HAL_RATESERIES_2040
619572ff6f6SMatthew Dillon 				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
620572ff6f6SMatthew Dillon 		} else {
621572ff6f6SMatthew Dillon 			if (shortPreamble)
622572ff6f6SMatthew Dillon 				series[i].Rate |=
623572ff6f6SMatthew Dillon 				    rt->info[rc[i].rix].shortPreamble;
624572ff6f6SMatthew Dillon 			series[i].PktDuration = ath_hal_computetxtime(ah,
625572ff6f6SMatthew Dillon 			    rt, pktlen, rc[i].rix, shortPreamble);
626572ff6f6SMatthew Dillon 		}
627572ff6f6SMatthew Dillon 	}
628572ff6f6SMatthew Dillon }
629572ff6f6SMatthew Dillon 
630b14ca477SMatthew Dillon #ifdef	ATH_DEBUG
631572ff6f6SMatthew Dillon static void
ath_rateseries_print(struct ath_softc * sc,HAL_11N_RATE_SERIES * series)632572ff6f6SMatthew Dillon ath_rateseries_print(struct ath_softc *sc, HAL_11N_RATE_SERIES *series)
633572ff6f6SMatthew Dillon {
634572ff6f6SMatthew Dillon 	int i;
635572ff6f6SMatthew Dillon 	for (i = 0; i < ATH_RC_NUM; i++) {
636572ff6f6SMatthew Dillon 		device_printf(sc->sc_dev ,"series %d: rate %x; tries %d; "
637572ff6f6SMatthew Dillon 		    "pktDuration %d; chSel %d; txpowcap %d, rateFlags %x\n",
638572ff6f6SMatthew Dillon 		    i,
639572ff6f6SMatthew Dillon 		    series[i].Rate,
640572ff6f6SMatthew Dillon 		    series[i].Tries,
641572ff6f6SMatthew Dillon 		    series[i].PktDuration,
642572ff6f6SMatthew Dillon 		    series[i].ChSel,
643572ff6f6SMatthew Dillon 		    series[i].tx_power_cap,
644572ff6f6SMatthew Dillon 		    series[i].RateFlags);
645572ff6f6SMatthew Dillon 	}
646572ff6f6SMatthew Dillon }
647572ff6f6SMatthew Dillon #endif
648572ff6f6SMatthew Dillon 
649572ff6f6SMatthew Dillon /*
650572ff6f6SMatthew Dillon  * Setup the 11n rate scenario and burst duration for the given TX descriptor
651572ff6f6SMatthew Dillon  * list.
652572ff6f6SMatthew Dillon  *
653572ff6f6SMatthew Dillon  * This isn't useful for sending beacon frames, which has different needs
654572ff6f6SMatthew Dillon  * wrt what's passed into the rate scenario function.
655572ff6f6SMatthew Dillon  */
656572ff6f6SMatthew Dillon void
ath_buf_set_rate(struct ath_softc * sc,struct ieee80211_node * ni,struct ath_buf * bf)657572ff6f6SMatthew Dillon ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni,
658572ff6f6SMatthew Dillon     struct ath_buf *bf)
659572ff6f6SMatthew Dillon {
660572ff6f6SMatthew Dillon 	HAL_11N_RATE_SERIES series[4];
661572ff6f6SMatthew Dillon 	struct ath_desc *ds = bf->bf_desc;
662572ff6f6SMatthew Dillon 	struct ath_hal *ah = sc->sc_ah;
663572ff6f6SMatthew Dillon 	int is_pspoll = (bf->bf_state.bfs_atype == HAL_PKT_TYPE_PSPOLL);
664572ff6f6SMatthew Dillon 	int ctsrate = bf->bf_state.bfs_ctsrate;
665572ff6f6SMatthew Dillon 	int flags = bf->bf_state.bfs_txflags;
666572ff6f6SMatthew Dillon 
667572ff6f6SMatthew Dillon 	/* Setup rate scenario */
668572ff6f6SMatthew Dillon 	memset(&series, 0, sizeof(series));
669572ff6f6SMatthew Dillon 
670572ff6f6SMatthew Dillon 	ath_rateseries_setup(sc, ni, bf, series);
671572ff6f6SMatthew Dillon 
672b14ca477SMatthew Dillon #ifdef	ATH_DEBUG
673b14ca477SMatthew Dillon 	if (sc->sc_debug & ATH_DEBUG_XMIT)
674572ff6f6SMatthew Dillon 		ath_rateseries_print(sc, series);
675572ff6f6SMatthew Dillon #endif
676572ff6f6SMatthew Dillon 
677572ff6f6SMatthew Dillon 	/* Set rate scenario */
678572ff6f6SMatthew Dillon 	/*
679572ff6f6SMatthew Dillon 	 * Note: Don't allow hardware to override the duration on
680572ff6f6SMatthew Dillon 	 * ps-poll packets.
681572ff6f6SMatthew Dillon 	 */
682572ff6f6SMatthew Dillon 	ath_hal_set11nratescenario(ah, ds,
683572ff6f6SMatthew Dillon 	    !is_pspoll,	/* whether to override the duration or not */
684572ff6f6SMatthew Dillon 	    ctsrate,	/* rts/cts rate */
685572ff6f6SMatthew Dillon 	    series,	/* 11n rate series */
686572ff6f6SMatthew Dillon 	    4,		/* number of series */
687572ff6f6SMatthew Dillon 	    flags);
688572ff6f6SMatthew Dillon 
689572ff6f6SMatthew Dillon 	/* Set burst duration */
690572ff6f6SMatthew Dillon 	/*
691572ff6f6SMatthew Dillon 	 * This is only required when doing 11n burst, not aggregation
692572ff6f6SMatthew Dillon 	 * ie, if there's a second frame in a RIFS or A-MPDU burst
693572ff6f6SMatthew Dillon 	 * w/ >1 A-MPDU frame bursting back to back.
694572ff6f6SMatthew Dillon 	 * Normal A-MPDU doesn't do bursting -between- aggregates.
695572ff6f6SMatthew Dillon 	 *
696572ff6f6SMatthew Dillon 	 * .. and it's highly likely this won't ever be implemented
697572ff6f6SMatthew Dillon 	 */
698572ff6f6SMatthew Dillon 	//ath_hal_set11nburstduration(ah, ds, 8192);
699572ff6f6SMatthew Dillon }
700572ff6f6SMatthew Dillon 
701572ff6f6SMatthew Dillon /*
702572ff6f6SMatthew Dillon  * Form an aggregate packet list.
703572ff6f6SMatthew Dillon  *
704572ff6f6SMatthew Dillon  * This function enforces the aggregate restrictions/requirements.
705572ff6f6SMatthew Dillon  *
706572ff6f6SMatthew Dillon  * These are:
707572ff6f6SMatthew Dillon  *
708572ff6f6SMatthew Dillon  * + The aggregate size maximum (64k for AR9160 and later, 8K for
709572ff6f6SMatthew Dillon  *   AR5416 when doing RTS frame protection.)
710572ff6f6SMatthew Dillon  * + Maximum number of sub-frames for an aggregate
711572ff6f6SMatthew Dillon  * + The aggregate delimiter size, giving MACs time to do whatever is
712572ff6f6SMatthew Dillon  *   needed before each frame
713572ff6f6SMatthew Dillon  * + Enforce the BAW limit
714572ff6f6SMatthew Dillon  *
715572ff6f6SMatthew Dillon  * Each descriptor queued should have the DMA setup.
716572ff6f6SMatthew Dillon  * The rate series, descriptor setup, linking, etc is all done
717572ff6f6SMatthew Dillon  * externally. This routine simply chains them together.
718572ff6f6SMatthew Dillon  * ath_tx_setds_11n() will take care of configuring the per-
719572ff6f6SMatthew Dillon  * descriptor setup, and ath_buf_set_rate() will configure the
720572ff6f6SMatthew Dillon  * rate control.
721572ff6f6SMatthew Dillon  *
722572ff6f6SMatthew Dillon  * The TID lock is required for the entirety of this function.
723572ff6f6SMatthew Dillon  *
724572ff6f6SMatthew Dillon  * If some code in another thread adds to the head of this
725572ff6f6SMatthew Dillon  * list, very strange behaviour will occur. Since retransmission is the
726572ff6f6SMatthew Dillon  * only reason this will occur, and this routine is designed to be called
727572ff6f6SMatthew Dillon  * from within the scheduler task, it won't ever clash with the completion
728572ff6f6SMatthew Dillon  * task.
729572ff6f6SMatthew Dillon  *
730572ff6f6SMatthew Dillon  * So if you want to call this from an upper layer context (eg, to direct-
731572ff6f6SMatthew Dillon  * dispatch aggregate frames to the hardware), please keep this in mind.
732572ff6f6SMatthew Dillon  */
733572ff6f6SMatthew Dillon ATH_AGGR_STATUS
ath_tx_form_aggr(struct ath_softc * sc,struct ath_node * an,struct ath_tid * tid,ath_bufhead * bf_q)734572ff6f6SMatthew Dillon ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an,
735572ff6f6SMatthew Dillon     struct ath_tid *tid, ath_bufhead *bf_q)
736572ff6f6SMatthew Dillon {
737572ff6f6SMatthew Dillon 	//struct ieee80211_node *ni = &an->an_node;
738572ff6f6SMatthew Dillon 	struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
739572ff6f6SMatthew Dillon 	int nframes = 0;
740572ff6f6SMatthew Dillon 	uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw;
741572ff6f6SMatthew Dillon 	struct ieee80211_tx_ampdu *tap;
742572ff6f6SMatthew Dillon 	int status = ATH_AGGR_DONE;
743572ff6f6SMatthew Dillon 	int prev_frames = 0;	/* XXX for AR5416 burst, not done here */
744572ff6f6SMatthew Dillon 	int prev_al = 0;	/* XXX also for AR5416 burst */
745572ff6f6SMatthew Dillon 
746572ff6f6SMatthew Dillon 	ATH_TX_LOCK_ASSERT(sc);
747572ff6f6SMatthew Dillon 
748572ff6f6SMatthew Dillon 	tap = ath_tx_get_tx_tid(an, tid->tid);
749572ff6f6SMatthew Dillon 	if (tap == NULL) {
750572ff6f6SMatthew Dillon 		status = ATH_AGGR_ERROR;
751572ff6f6SMatthew Dillon 		goto finish;
752572ff6f6SMatthew Dillon 	}
753572ff6f6SMatthew Dillon 
754572ff6f6SMatthew Dillon 	h_baw = tap->txa_wnd / 2;
755572ff6f6SMatthew Dillon 
756572ff6f6SMatthew Dillon 	for (;;) {
757572ff6f6SMatthew Dillon 		bf = ATH_TID_FIRST(tid);
758572ff6f6SMatthew Dillon 		if (bf_first == NULL)
759572ff6f6SMatthew Dillon 			bf_first = bf;
760572ff6f6SMatthew Dillon 		if (bf == NULL) {
761572ff6f6SMatthew Dillon 			status = ATH_AGGR_DONE;
762572ff6f6SMatthew Dillon 			break;
763572ff6f6SMatthew Dillon 		} else {
764572ff6f6SMatthew Dillon 			/*
765572ff6f6SMatthew Dillon 			 * It's the first frame;
766572ff6f6SMatthew Dillon 			 * set the aggregation limit based on the
767572ff6f6SMatthew Dillon 			 * rate control decision that has been made.
768572ff6f6SMatthew Dillon 			 */
769572ff6f6SMatthew Dillon 			aggr_limit = ath_get_aggr_limit(sc, bf_first);
770572ff6f6SMatthew Dillon 		}
771572ff6f6SMatthew Dillon 
772572ff6f6SMatthew Dillon 		/* Set this early just so things don't get confused */
773572ff6f6SMatthew Dillon 		bf->bf_next = NULL;
774572ff6f6SMatthew Dillon 
775572ff6f6SMatthew Dillon 		/*
776572ff6f6SMatthew Dillon 		 * If the frame doesn't have a sequence number that we're
777572ff6f6SMatthew Dillon 		 * tracking in the BAW (eg NULL QOS data frame), we can't
778572ff6f6SMatthew Dillon 		 * aggregate it. Stop the aggregation process; the sender
779572ff6f6SMatthew Dillon 		 * can then TX what's in the list thus far and then
780572ff6f6SMatthew Dillon 		 * TX the frame individually.
781572ff6f6SMatthew Dillon 		 */
782572ff6f6SMatthew Dillon 		if (! bf->bf_state.bfs_dobaw) {
783572ff6f6SMatthew Dillon 			status = ATH_AGGR_NONAGGR;
784572ff6f6SMatthew Dillon 			break;
785572ff6f6SMatthew Dillon 		}
786572ff6f6SMatthew Dillon 
787572ff6f6SMatthew Dillon 		/*
788572ff6f6SMatthew Dillon 		 * If any of the rates are non-HT, this packet
789572ff6f6SMatthew Dillon 		 * can't be aggregated.
790572ff6f6SMatthew Dillon 		 * XXX TODO: add a bf_state flag which gets marked
791572ff6f6SMatthew Dillon 		 * if any active rate is non-HT.
792572ff6f6SMatthew Dillon 		 */
793572ff6f6SMatthew Dillon 
794572ff6f6SMatthew Dillon 		/*
795572ff6f6SMatthew Dillon 		 * do not exceed aggregation limit
796572ff6f6SMatthew Dillon 		 */
797572ff6f6SMatthew Dillon 		al_delta = ATH_AGGR_DELIM_SZ + bf->bf_state.bfs_pktlen;
798572ff6f6SMatthew Dillon 		if (nframes &&
799572ff6f6SMatthew Dillon 		    (aggr_limit < (al + bpad + al_delta + prev_al))) {
800572ff6f6SMatthew Dillon 			status = ATH_AGGR_LIMITED;
801572ff6f6SMatthew Dillon 			break;
802572ff6f6SMatthew Dillon 		}
803572ff6f6SMatthew Dillon 
804572ff6f6SMatthew Dillon 		/*
805572ff6f6SMatthew Dillon 		 * If RTS/CTS is set on the first frame, enforce
806572ff6f6SMatthew Dillon 		 * the RTS aggregate limit.
807572ff6f6SMatthew Dillon 		 */
808572ff6f6SMatthew Dillon 		if (bf_first->bf_state.bfs_txflags &
809572ff6f6SMatthew Dillon 		    (HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA)) {
810572ff6f6SMatthew Dillon 			if (nframes &&
811572ff6f6SMatthew Dillon 			   (sc->sc_rts_aggr_limit <
812572ff6f6SMatthew Dillon 			     (al + bpad + al_delta + prev_al))) {
813572ff6f6SMatthew Dillon 				status = ATH_AGGR_8K_LIMITED;
814572ff6f6SMatthew Dillon 				break;
815572ff6f6SMatthew Dillon 			}
816572ff6f6SMatthew Dillon 		}
817572ff6f6SMatthew Dillon 
818572ff6f6SMatthew Dillon 		/*
819572ff6f6SMatthew Dillon 		 * Do not exceed subframe limit.
820572ff6f6SMatthew Dillon 		 */
821572ff6f6SMatthew Dillon 		if ((nframes + prev_frames) >= MIN((h_baw),
822572ff6f6SMatthew Dillon 		    IEEE80211_AMPDU_SUBFRAME_DEFAULT)) {
823572ff6f6SMatthew Dillon 			status = ATH_AGGR_LIMITED;
824572ff6f6SMatthew Dillon 			break;
825572ff6f6SMatthew Dillon 		}
826572ff6f6SMatthew Dillon 
827572ff6f6SMatthew Dillon 		/*
828572ff6f6SMatthew Dillon 		 * If the current frame has an RTS/CTS configuration
829572ff6f6SMatthew Dillon 		 * that differs from the first frame, override the
830572ff6f6SMatthew Dillon 		 * subsequent frame with this config.
831572ff6f6SMatthew Dillon 		 */
832572ff6f6SMatthew Dillon 		if (bf != bf_first) {
833572ff6f6SMatthew Dillon 			bf->bf_state.bfs_txflags &=
834572ff6f6SMatthew Dillon 			    ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
835572ff6f6SMatthew Dillon 			bf->bf_state.bfs_txflags |=
836572ff6f6SMatthew Dillon 			    bf_first->bf_state.bfs_txflags &
837572ff6f6SMatthew Dillon 			    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
838572ff6f6SMatthew Dillon 		}
839572ff6f6SMatthew Dillon 
840572ff6f6SMatthew Dillon 		/*
841572ff6f6SMatthew Dillon 		 * If the packet has a sequence number, do not
842572ff6f6SMatthew Dillon 		 * step outside of the block-ack window.
843572ff6f6SMatthew Dillon 		 */
844572ff6f6SMatthew Dillon 		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
845572ff6f6SMatthew Dillon 		    SEQNO(bf->bf_state.bfs_seqno))) {
846572ff6f6SMatthew Dillon 			status = ATH_AGGR_BAW_CLOSED;
847572ff6f6SMatthew Dillon 			break;
848572ff6f6SMatthew Dillon 		}
849572ff6f6SMatthew Dillon 
850572ff6f6SMatthew Dillon 		/*
851572ff6f6SMatthew Dillon 		 * this packet is part of an aggregate.
852572ff6f6SMatthew Dillon 		 */
853572ff6f6SMatthew Dillon 		ATH_TID_REMOVE(tid, bf, bf_list);
854572ff6f6SMatthew Dillon 
855572ff6f6SMatthew Dillon 		/* The TID lock is required for the BAW update */
856572ff6f6SMatthew Dillon 		ath_tx_addto_baw(sc, an, tid, bf);
857572ff6f6SMatthew Dillon 		bf->bf_state.bfs_addedbaw = 1;
858572ff6f6SMatthew Dillon 
859572ff6f6SMatthew Dillon 		/*
860572ff6f6SMatthew Dillon 		 * XXX enforce ACK for aggregate frames (this needs to be
861572ff6f6SMatthew Dillon 		 * XXX handled more gracefully?
862572ff6f6SMatthew Dillon 		 */
863572ff6f6SMatthew Dillon 		if (bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) {
864572ff6f6SMatthew Dillon 			device_printf(sc->sc_dev,
865572ff6f6SMatthew Dillon 			    "%s: HAL_TXDESC_NOACK set for an aggregate frame?\n",
866572ff6f6SMatthew Dillon 			    __func__);
867572ff6f6SMatthew Dillon 			bf->bf_state.bfs_txflags &= (~HAL_TXDESC_NOACK);
868572ff6f6SMatthew Dillon 		}
869572ff6f6SMatthew Dillon 
870572ff6f6SMatthew Dillon 		/*
871572ff6f6SMatthew Dillon 		 * Add the now owned buffer (which isn't
872572ff6f6SMatthew Dillon 		 * on the software TXQ any longer) to our
873572ff6f6SMatthew Dillon 		 * aggregate frame list.
874572ff6f6SMatthew Dillon 		 */
875572ff6f6SMatthew Dillon 		TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
876572ff6f6SMatthew Dillon 		nframes ++;
877572ff6f6SMatthew Dillon 
878572ff6f6SMatthew Dillon 		/* Completion handler */
879572ff6f6SMatthew Dillon 		bf->bf_comp = ath_tx_aggr_comp;
880572ff6f6SMatthew Dillon 
881572ff6f6SMatthew Dillon 		/*
882572ff6f6SMatthew Dillon 		 * add padding for previous frame to aggregation length
883572ff6f6SMatthew Dillon 		 */
884572ff6f6SMatthew Dillon 		al += bpad + al_delta;
885572ff6f6SMatthew Dillon 
886572ff6f6SMatthew Dillon 		/*
887572ff6f6SMatthew Dillon 		 * Calculate delimiters needed for the current frame
888572ff6f6SMatthew Dillon 		 */
889572ff6f6SMatthew Dillon 		bf->bf_state.bfs_ndelim =
890572ff6f6SMatthew Dillon 		    ath_compute_num_delims(sc, bf_first,
891572ff6f6SMatthew Dillon 		    bf->bf_state.bfs_pktlen);
892572ff6f6SMatthew Dillon 
893572ff6f6SMatthew Dillon 		/*
894572ff6f6SMatthew Dillon 		 * Calculate the padding needed from this set of delimiters,
895572ff6f6SMatthew Dillon 		 * used when calculating if the next frame will fit in
896572ff6f6SMatthew Dillon 		 * the aggregate.
897572ff6f6SMatthew Dillon 		 */
898572ff6f6SMatthew Dillon 		bpad = PADBYTES(al_delta) + (bf->bf_state.bfs_ndelim << 2);
899572ff6f6SMatthew Dillon 
900572ff6f6SMatthew Dillon 		/*
901572ff6f6SMatthew Dillon 		 * Chain the buffers together
902572ff6f6SMatthew Dillon 		 */
903572ff6f6SMatthew Dillon 		if (bf_prev)
904572ff6f6SMatthew Dillon 			bf_prev->bf_next = bf;
905572ff6f6SMatthew Dillon 		bf_prev = bf;
906572ff6f6SMatthew Dillon 
907572ff6f6SMatthew Dillon 		/*
908572ff6f6SMatthew Dillon 		 * If we're leaking frames, just return at this point;
909572ff6f6SMatthew Dillon 		 * we've queued a single frame and we don't want to add
910572ff6f6SMatthew Dillon 		 * any more.
911572ff6f6SMatthew Dillon 		 */
912572ff6f6SMatthew Dillon 		if (tid->an->an_leak_count) {
913572ff6f6SMatthew Dillon 			status = ATH_AGGR_LEAK_CLOSED;
914572ff6f6SMatthew Dillon 			break;
915572ff6f6SMatthew Dillon 		}
916572ff6f6SMatthew Dillon 
917572ff6f6SMatthew Dillon #if 0
918572ff6f6SMatthew Dillon 		/*
919572ff6f6SMatthew Dillon 		 * terminate aggregation on a small packet boundary
920572ff6f6SMatthew Dillon 		 */
921572ff6f6SMatthew Dillon 		if (bf->bf_state.bfs_pktlen < ATH_AGGR_MINPLEN) {
922572ff6f6SMatthew Dillon 			status = ATH_AGGR_SHORTPKT;
923572ff6f6SMatthew Dillon 			break;
924572ff6f6SMatthew Dillon 		}
925572ff6f6SMatthew Dillon #endif
926572ff6f6SMatthew Dillon 
927572ff6f6SMatthew Dillon 	}
928572ff6f6SMatthew Dillon 
929572ff6f6SMatthew Dillon finish:
930572ff6f6SMatthew Dillon 	/*
931572ff6f6SMatthew Dillon 	 * Just in case the list was empty when we tried to
932572ff6f6SMatthew Dillon 	 * dequeue a packet ..
933572ff6f6SMatthew Dillon 	 */
934572ff6f6SMatthew Dillon 	if (bf_first) {
935572ff6f6SMatthew Dillon 		bf_first->bf_state.bfs_al = al;
936572ff6f6SMatthew Dillon 		bf_first->bf_state.bfs_nframes = nframes;
937572ff6f6SMatthew Dillon 	}
938572ff6f6SMatthew Dillon 	return status;
939572ff6f6SMatthew Dillon }
940