xref: /freebsd/sys/dev/ath/if_ath_tx_ht.c (revision eb6f0de09db233bf9b4b75b7aa79d9319b5fc7c1)
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 
89*eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_tx.h>		/* XXX for some support functions */
904b44f6f2SAdrian Chadd #include <dev/ath/if_ath_tx_ht.h>
91*eb6f0de0SAdrian Chadd #include <dev/ath/if_athrate.h>
92*eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_debug.h>
93*eb6f0de0SAdrian Chadd 
94*eb6f0de0SAdrian Chadd /*
95*eb6f0de0SAdrian Chadd  * XXX net80211?
96*eb6f0de0SAdrian Chadd  */
97*eb6f0de0SAdrian Chadd #define	IEEE80211_AMPDU_SUBFRAME_DEFAULT		32
98*eb6f0de0SAdrian Chadd 
99*eb6f0de0SAdrian Chadd #define	ATH_AGGR_DELIM_SZ	4	/* delimiter size   */
100*eb6f0de0SAdrian Chadd #define	ATH_AGGR_MINPLEN	256	/* in bytes, minimum packet length */
101*eb6f0de0SAdrian Chadd #define	ATH_AGGR_ENCRYPTDELIM	10	/* number of delimiters for encryption padding */
102*eb6f0de0SAdrian Chadd 
103*eb6f0de0SAdrian Chadd /*
104*eb6f0de0SAdrian Chadd  * returns delimiter padding required given the packet length
105*eb6f0de0SAdrian Chadd  */
106*eb6f0de0SAdrian Chadd #define	ATH_AGGR_GET_NDELIM(_len)					\
107*eb6f0de0SAdrian Chadd 	    (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?	\
108*eb6f0de0SAdrian Chadd 	    (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
109*eb6f0de0SAdrian Chadd 
110*eb6f0de0SAdrian Chadd #define	PADBYTES(_len)		((4 - ((_len) % 4)) % 4)
111*eb6f0de0SAdrian Chadd 
112*eb6f0de0SAdrian Chadd int ath_max_4ms_framelen[4][32] = {
113*eb6f0de0SAdrian Chadd 	[MCS_HT20] = {
114*eb6f0de0SAdrian Chadd 		3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
115*eb6f0de0SAdrian Chadd 		6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
116*eb6f0de0SAdrian Chadd 		9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
117*eb6f0de0SAdrian Chadd 		12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
118*eb6f0de0SAdrian Chadd 	},
119*eb6f0de0SAdrian Chadd 	[MCS_HT20_SGI] = {
120*eb6f0de0SAdrian Chadd 		3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
121*eb6f0de0SAdrian Chadd 		7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
122*eb6f0de0SAdrian Chadd 		10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
123*eb6f0de0SAdrian Chadd 		14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
124*eb6f0de0SAdrian Chadd 	},
125*eb6f0de0SAdrian Chadd 	[MCS_HT40] = {
126*eb6f0de0SAdrian Chadd 		6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
127*eb6f0de0SAdrian Chadd 		13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
128*eb6f0de0SAdrian Chadd 		20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
129*eb6f0de0SAdrian Chadd 		26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
130*eb6f0de0SAdrian Chadd 	},
131*eb6f0de0SAdrian Chadd 	[MCS_HT40_SGI] = {
132*eb6f0de0SAdrian Chadd 		7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
133*eb6f0de0SAdrian Chadd 		14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
134*eb6f0de0SAdrian Chadd 		22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
135*eb6f0de0SAdrian Chadd 		29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
136*eb6f0de0SAdrian Chadd 	}
137*eb6f0de0SAdrian Chadd };
138*eb6f0de0SAdrian Chadd 
139*eb6f0de0SAdrian Chadd /*
140*eb6f0de0SAdrian Chadd  * XXX should be in net80211
141*eb6f0de0SAdrian Chadd  */
142*eb6f0de0SAdrian Chadd static int ieee80211_mpdudensity_map[] = {
143*eb6f0de0SAdrian Chadd 	0,		/* IEEE80211_HTCAP_MPDUDENSITY_NA */
144*eb6f0de0SAdrian Chadd 	25,		/* IEEE80211_HTCAP_MPDUDENSITY_025 */
145*eb6f0de0SAdrian Chadd 	50,		/* IEEE80211_HTCAP_MPDUDENSITY_05 */
146*eb6f0de0SAdrian Chadd 	100,		/* IEEE80211_HTCAP_MPDUDENSITY_1 */
147*eb6f0de0SAdrian Chadd 	200,		/* IEEE80211_HTCAP_MPDUDENSITY_2 */
148*eb6f0de0SAdrian Chadd 	400,		/* IEEE80211_HTCAP_MPDUDENSITY_4 */
149*eb6f0de0SAdrian Chadd 	800,		/* IEEE80211_HTCAP_MPDUDENSITY_8 */
150*eb6f0de0SAdrian Chadd 	1600,		/* IEEE80211_HTCAP_MPDUDENSITY_16 */
151*eb6f0de0SAdrian Chadd };
152*eb6f0de0SAdrian Chadd 
153*eb6f0de0SAdrian Chadd /*
154*eb6f0de0SAdrian Chadd  * XXX should be in the HAL/net80211 ?
155*eb6f0de0SAdrian Chadd  */
156*eb6f0de0SAdrian Chadd #define	BITS_PER_BYTE		8
157*eb6f0de0SAdrian Chadd #define	OFDM_PLCP_BITS		22
158*eb6f0de0SAdrian Chadd #define	HT_RC_2_MCS(_rc)	((_rc) & 0x7f)
159*eb6f0de0SAdrian Chadd #define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
160*eb6f0de0SAdrian Chadd #define	L_STF			8
161*eb6f0de0SAdrian Chadd #define	L_LTF			8
162*eb6f0de0SAdrian Chadd #define	L_SIG			4
163*eb6f0de0SAdrian Chadd #define	HT_SIG			8
164*eb6f0de0SAdrian Chadd #define	HT_STF			4
165*eb6f0de0SAdrian Chadd #define	HT_LTF(_ns)		(4 * (_ns))
166*eb6f0de0SAdrian Chadd #define	SYMBOL_TIME(_ns)	((_ns) << 2)		// ns * 4 us
167*eb6f0de0SAdrian Chadd #define	SYMBOL_TIME_HALFGI(_ns)	(((_ns) * 18 + 4) / 5)	// ns * 3.6 us
168*eb6f0de0SAdrian Chadd #define	NUM_SYMBOLS_PER_USEC(_usec)	(_usec >> 2)
169*eb6f0de0SAdrian Chadd #define	NUM_SYMBOLS_PER_USEC_HALFGI(_usec)	(((_usec*5)-4)/18)
170*eb6f0de0SAdrian Chadd #define	IS_HT_RATE(_rate)	((_rate) & 0x80)
171*eb6f0de0SAdrian Chadd 
172*eb6f0de0SAdrian Chadd const uint32_t bits_per_symbol[][2] = {
173*eb6f0de0SAdrian Chadd     /* 20MHz 40MHz */
174*eb6f0de0SAdrian Chadd     {    26,   54 },     //  0: BPSK
175*eb6f0de0SAdrian Chadd     {    52,  108 },     //  1: QPSK 1/2
176*eb6f0de0SAdrian Chadd     {    78,  162 },     //  2: QPSK 3/4
177*eb6f0de0SAdrian Chadd     {   104,  216 },     //  3: 16-QAM 1/2
178*eb6f0de0SAdrian Chadd     {   156,  324 },     //  4: 16-QAM 3/4
179*eb6f0de0SAdrian Chadd     {   208,  432 },     //  5: 64-QAM 2/3
180*eb6f0de0SAdrian Chadd     {   234,  486 },     //  6: 64-QAM 3/4
181*eb6f0de0SAdrian Chadd     {   260,  540 },     //  7: 64-QAM 5/6
182*eb6f0de0SAdrian Chadd     {    52,  108 },     //  8: BPSK
183*eb6f0de0SAdrian Chadd     {   104,  216 },     //  9: QPSK 1/2
184*eb6f0de0SAdrian Chadd     {   156,  324 },     // 10: QPSK 3/4
185*eb6f0de0SAdrian Chadd     {   208,  432 },     // 11: 16-QAM 1/2
186*eb6f0de0SAdrian Chadd     {   312,  648 },     // 12: 16-QAM 3/4
187*eb6f0de0SAdrian Chadd     {   416,  864 },     // 13: 64-QAM 2/3
188*eb6f0de0SAdrian Chadd     {   468,  972 },     // 14: 64-QAM 3/4
189*eb6f0de0SAdrian Chadd     {   520, 1080 },     // 15: 64-QAM 5/6
190*eb6f0de0SAdrian Chadd     {    78,  162 },     // 16: BPSK
191*eb6f0de0SAdrian Chadd     {   156,  324 },     // 17: QPSK 1/2
192*eb6f0de0SAdrian Chadd     {   234,  486 },     // 18: QPSK 3/4
193*eb6f0de0SAdrian Chadd     {   312,  648 },     // 19: 16-QAM 1/2
194*eb6f0de0SAdrian Chadd     {   468,  972 },     // 20: 16-QAM 3/4
195*eb6f0de0SAdrian Chadd     {   624, 1296 },     // 21: 64-QAM 2/3
196*eb6f0de0SAdrian Chadd     {   702, 1458 },     // 22: 64-QAM 3/4
197*eb6f0de0SAdrian Chadd     {   780, 1620 },     // 23: 64-QAM 5/6
198*eb6f0de0SAdrian Chadd     {   104,  216 },     // 24: BPSK
199*eb6f0de0SAdrian Chadd     {   208,  432 },     // 25: QPSK 1/2
200*eb6f0de0SAdrian Chadd     {   312,  648 },     // 26: QPSK 3/4
201*eb6f0de0SAdrian Chadd     {   416,  864 },     // 27: 16-QAM 1/2
202*eb6f0de0SAdrian Chadd     {   624, 1296 },     // 28: 16-QAM 3/4
203*eb6f0de0SAdrian Chadd     {   832, 1728 },     // 29: 64-QAM 2/3
204*eb6f0de0SAdrian Chadd     {   936, 1944 },     // 30: 64-QAM 3/4
205*eb6f0de0SAdrian Chadd     {  1040, 2160 },     // 31: 64-QAM 5/6
206*eb6f0de0SAdrian Chadd };
207*eb6f0de0SAdrian Chadd 
208*eb6f0de0SAdrian Chadd /*
209*eb6f0de0SAdrian Chadd  * Fill in the rate array information based on the current
210*eb6f0de0SAdrian Chadd  * node configuration and the choices made by the rate
211*eb6f0de0SAdrian Chadd  * selection code and ath_buf setup code.
212*eb6f0de0SAdrian Chadd  *
213*eb6f0de0SAdrian Chadd  * Later on, this may end up also being made by the
214*eb6f0de0SAdrian Chadd  * rate control code, but for now it can live here.
215*eb6f0de0SAdrian Chadd  *
216*eb6f0de0SAdrian Chadd  * This needs to be called just before the packet is
217*eb6f0de0SAdrian Chadd  * queued to the software queue or hardware queue,
218*eb6f0de0SAdrian Chadd  * so all of the needed fields in bf_state are setup.
219*eb6f0de0SAdrian Chadd  */
220*eb6f0de0SAdrian Chadd void
221*eb6f0de0SAdrian Chadd ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
222*eb6f0de0SAdrian Chadd {
223*eb6f0de0SAdrian Chadd 	struct ieee80211_node *ni = bf->bf_node;
224*eb6f0de0SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
225*eb6f0de0SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
226*eb6f0de0SAdrian Chadd 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
227*eb6f0de0SAdrian Chadd 	uint8_t rate;
228*eb6f0de0SAdrian Chadd 	int i;
229*eb6f0de0SAdrian Chadd 
230*eb6f0de0SAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
231*eb6f0de0SAdrian Chadd 		rc[i].flags = 0;
232*eb6f0de0SAdrian Chadd 		if (rc[i].tries == 0)
233*eb6f0de0SAdrian Chadd 			continue;
234*eb6f0de0SAdrian Chadd 
235*eb6f0de0SAdrian Chadd 		rate = rt->info[rc[i].rix].rateCode;
236*eb6f0de0SAdrian Chadd 
237*eb6f0de0SAdrian Chadd 		/*
238*eb6f0de0SAdrian Chadd 		 * XXX only do this for legacy rates?
239*eb6f0de0SAdrian Chadd 		 */
240*eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_shpream)
241*eb6f0de0SAdrian Chadd 			rate |= rt->info[rc[i].rix].shortPreamble;
242*eb6f0de0SAdrian Chadd 
243*eb6f0de0SAdrian Chadd 		/*
244*eb6f0de0SAdrian Chadd 		 * Save this, used by the TX and completion code
245*eb6f0de0SAdrian Chadd 		 */
246*eb6f0de0SAdrian Chadd 		rc[i].ratecode = rate;
247*eb6f0de0SAdrian Chadd 
248*eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_flags &
249*eb6f0de0SAdrian Chadd 		    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
250*eb6f0de0SAdrian Chadd 			rc[i].flags |= ATH_RC_RTSCTS_FLAG;
251*eb6f0de0SAdrian Chadd 
252*eb6f0de0SAdrian Chadd 		/* Only enable shortgi, 2040, dual-stream if HT is set */
253*eb6f0de0SAdrian Chadd 		if (IS_HT_RATE(rate)) {
254*eb6f0de0SAdrian Chadd 			rc[i].flags |= ATH_RC_HT_FLAG;
255*eb6f0de0SAdrian Chadd 
256*eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 40)
257*eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_CW40_FLAG;
258*eb6f0de0SAdrian Chadd 
259*eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 40 &&
260*eb6f0de0SAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
261*eb6f0de0SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
262*eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_SGI_FLAG;
263*eb6f0de0SAdrian Chadd 
264*eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 20 &&
265*eb6f0de0SAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
266*eb6f0de0SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
267*eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_SGI_FLAG;
268*eb6f0de0SAdrian Chadd 
269*eb6f0de0SAdrian Chadd 			/* XXX dual stream? and 3-stream? */
270*eb6f0de0SAdrian Chadd 		}
271*eb6f0de0SAdrian Chadd 
272*eb6f0de0SAdrian Chadd 		/*
273*eb6f0de0SAdrian Chadd 		 * Calculate the maximum 4ms frame length based
274*eb6f0de0SAdrian Chadd 		 * on the MCS rate, SGI and channel width flags.
275*eb6f0de0SAdrian Chadd 		 */
276*eb6f0de0SAdrian Chadd 		if ((rc[i].flags & ATH_RC_HT_FLAG) &&
277*eb6f0de0SAdrian Chadd 		    (HT_RC_2_MCS(rate) < 32)) {
278*eb6f0de0SAdrian Chadd 			int j;
279*eb6f0de0SAdrian Chadd 			if (rc[i].flags & ATH_RC_CW40_FLAG) {
280*eb6f0de0SAdrian Chadd 				if (rc[i].flags & ATH_RC_SGI_FLAG)
281*eb6f0de0SAdrian Chadd 					j = MCS_HT40_SGI;
282*eb6f0de0SAdrian Chadd 				else
283*eb6f0de0SAdrian Chadd 					j = MCS_HT40;
284*eb6f0de0SAdrian Chadd 			} else {
285*eb6f0de0SAdrian Chadd 				if (rc[i].flags & ATH_RC_SGI_FLAG)
286*eb6f0de0SAdrian Chadd 					j = MCS_HT20_SGI;
287*eb6f0de0SAdrian Chadd 				else
288*eb6f0de0SAdrian Chadd 					j = MCS_HT20;
289*eb6f0de0SAdrian Chadd 			}
290*eb6f0de0SAdrian Chadd 			rc[i].max4msframelen =
291*eb6f0de0SAdrian Chadd 			    ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)];
292*eb6f0de0SAdrian Chadd 		} else
293*eb6f0de0SAdrian Chadd 			rc[i].max4msframelen = 0;
294*eb6f0de0SAdrian Chadd 		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
295*eb6f0de0SAdrian Chadd 		    "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
296*eb6f0de0SAdrian Chadd 		    __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
297*eb6f0de0SAdrian Chadd 	}
298*eb6f0de0SAdrian Chadd }
299*eb6f0de0SAdrian Chadd 
300*eb6f0de0SAdrian Chadd /*
301*eb6f0de0SAdrian Chadd  * Return the number of delimiters to be added to
302*eb6f0de0SAdrian Chadd  * meet the minimum required mpdudensity.
303*eb6f0de0SAdrian Chadd  *
304*eb6f0de0SAdrian Chadd  * Caller should make sure that the rate is HT.
305*eb6f0de0SAdrian Chadd  *
306*eb6f0de0SAdrian Chadd  * TODO: is this delimiter calculation supposed to be the
307*eb6f0de0SAdrian Chadd  * total frame length, the hdr length, the data length (including
308*eb6f0de0SAdrian Chadd  * delimiters, padding, CRC, etc) or ?
309*eb6f0de0SAdrian Chadd  *
310*eb6f0de0SAdrian Chadd  * TODO: this should ensure that the rate control information
311*eb6f0de0SAdrian Chadd  * HAS been setup for the first rate.
312*eb6f0de0SAdrian Chadd  *
313*eb6f0de0SAdrian Chadd  * TODO: ensure this is only called for MCS rates.
314*eb6f0de0SAdrian Chadd  *
315*eb6f0de0SAdrian Chadd  * TODO: enforce MCS < 31
316*eb6f0de0SAdrian Chadd  */
317*eb6f0de0SAdrian Chadd static int
318*eb6f0de0SAdrian Chadd ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf,
319*eb6f0de0SAdrian Chadd     uint16_t pktlen)
320*eb6f0de0SAdrian Chadd {
321*eb6f0de0SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
322*eb6f0de0SAdrian Chadd 	struct ieee80211_node *ni = first_bf->bf_node;
323*eb6f0de0SAdrian Chadd 	struct ieee80211vap *vap = ni->ni_vap;
324*eb6f0de0SAdrian Chadd 	int ndelim, mindelim = 0;
325*eb6f0de0SAdrian Chadd 	int mpdudensity;	 /* in 1/100'th of a microsecond */
326*eb6f0de0SAdrian Chadd 	uint8_t rc, rix, flags;
327*eb6f0de0SAdrian Chadd 	int width, half_gi;
328*eb6f0de0SAdrian Chadd 	uint32_t nsymbits, nsymbols;
329*eb6f0de0SAdrian Chadd 	uint16_t minlen;
330*eb6f0de0SAdrian Chadd 
331*eb6f0de0SAdrian Chadd 	/*
332*eb6f0de0SAdrian Chadd 	 * vap->iv_ampdu_density is a value, rather than the actual
333*eb6f0de0SAdrian Chadd 	 * density.
334*eb6f0de0SAdrian Chadd 	 */
335*eb6f0de0SAdrian Chadd 	if (vap->iv_ampdu_density > IEEE80211_HTCAP_MPDUDENSITY_16)
336*eb6f0de0SAdrian Chadd 		mpdudensity = 1600;		/* maximum density */
337*eb6f0de0SAdrian Chadd 	else
338*eb6f0de0SAdrian Chadd 		mpdudensity = ieee80211_mpdudensity_map[vap->iv_ampdu_density];
339*eb6f0de0SAdrian Chadd 
340*eb6f0de0SAdrian Chadd 	/* Select standard number of delimiters based on frame length */
341*eb6f0de0SAdrian Chadd 	ndelim = ATH_AGGR_GET_NDELIM(pktlen);
342*eb6f0de0SAdrian Chadd 
343*eb6f0de0SAdrian Chadd 	/*
344*eb6f0de0SAdrian Chadd 	 * If encryption is enabled, add extra delimiters to let the
345*eb6f0de0SAdrian Chadd 	 * crypto hardware catch up. This could be tuned per-MAC and
346*eb6f0de0SAdrian Chadd 	 * per-rate, but for now we'll simply assume encryption is
347*eb6f0de0SAdrian Chadd 	 * always enabled.
348*eb6f0de0SAdrian Chadd 	 */
349*eb6f0de0SAdrian Chadd 	ndelim += ATH_AGGR_ENCRYPTDELIM;
350*eb6f0de0SAdrian Chadd 
351*eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
352*eb6f0de0SAdrian Chadd 	    "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n",
353*eb6f0de0SAdrian Chadd 	    __func__, pktlen, ndelim, mpdudensity);
354*eb6f0de0SAdrian Chadd 
355*eb6f0de0SAdrian Chadd 	/*
356*eb6f0de0SAdrian Chadd 	 * If the MPDU density is 0, we can return here.
357*eb6f0de0SAdrian Chadd 	 * Otherwise, we need to convert the desired mpdudensity
358*eb6f0de0SAdrian Chadd 	 * into a byte length, based on the rate in the subframe.
359*eb6f0de0SAdrian Chadd 	 */
360*eb6f0de0SAdrian Chadd 	if (mpdudensity == 0)
361*eb6f0de0SAdrian Chadd 		return ndelim;
362*eb6f0de0SAdrian Chadd 
363*eb6f0de0SAdrian Chadd 	/*
364*eb6f0de0SAdrian Chadd 	 * Convert desired mpdu density from microeconds to bytes based
365*eb6f0de0SAdrian Chadd 	 * on highest rate in rate series (i.e. first rate) to determine
366*eb6f0de0SAdrian Chadd 	 * required minimum length for subframe. Take into account
367*eb6f0de0SAdrian Chadd 	 * whether high rate is 20 or 40Mhz and half or full GI.
368*eb6f0de0SAdrian Chadd 	 */
369*eb6f0de0SAdrian Chadd 	rix = first_bf->bf_state.bfs_rc[0].rix;
370*eb6f0de0SAdrian Chadd 	rc = rt->info[rix].rateCode;
371*eb6f0de0SAdrian Chadd 	flags = first_bf->bf_state.bfs_rc[0].flags;
372*eb6f0de0SAdrian Chadd 	width = !! (flags & ATH_RC_CW40_FLAG);
373*eb6f0de0SAdrian Chadd 	half_gi = !! (flags & ATH_RC_SGI_FLAG);
374*eb6f0de0SAdrian Chadd 
375*eb6f0de0SAdrian Chadd 	/*
376*eb6f0de0SAdrian Chadd 	 * mpdudensity is in 1/100th of a usec, so divide by 100
377*eb6f0de0SAdrian Chadd 	 */
378*eb6f0de0SAdrian Chadd 	if (half_gi)
379*eb6f0de0SAdrian Chadd 		nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
380*eb6f0de0SAdrian Chadd 	else
381*eb6f0de0SAdrian Chadd 		nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
382*eb6f0de0SAdrian Chadd 	nsymbols /= 100;
383*eb6f0de0SAdrian Chadd 
384*eb6f0de0SAdrian Chadd 	if (nsymbols == 0)
385*eb6f0de0SAdrian Chadd 		nsymbols = 1;
386*eb6f0de0SAdrian Chadd 
387*eb6f0de0SAdrian Chadd 	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
388*eb6f0de0SAdrian Chadd 	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
389*eb6f0de0SAdrian Chadd 
390*eb6f0de0SAdrian Chadd 	/*
391*eb6f0de0SAdrian Chadd 	 * Min length is the minimum frame length for the
392*eb6f0de0SAdrian Chadd 	 * required MPDU density.
393*eb6f0de0SAdrian Chadd 	 */
394*eb6f0de0SAdrian Chadd 	if (pktlen < minlen) {
395*eb6f0de0SAdrian Chadd 		mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ;
396*eb6f0de0SAdrian Chadd 		ndelim = MAX(mindelim, ndelim);
397*eb6f0de0SAdrian Chadd 	}
398*eb6f0de0SAdrian Chadd 
399*eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
400*eb6f0de0SAdrian Chadd 	    "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n",
401*eb6f0de0SAdrian Chadd 	    __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim);
402*eb6f0de0SAdrian Chadd 
403*eb6f0de0SAdrian Chadd 	return ndelim;
404*eb6f0de0SAdrian Chadd }
405*eb6f0de0SAdrian Chadd 
406*eb6f0de0SAdrian Chadd /*
407*eb6f0de0SAdrian Chadd  * Fetch the aggregation limit.
408*eb6f0de0SAdrian Chadd  *
409*eb6f0de0SAdrian Chadd  * It's the lowest of the four rate series 4ms frame length.
410*eb6f0de0SAdrian Chadd  */
411*eb6f0de0SAdrian Chadd static int
412*eb6f0de0SAdrian Chadd ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf)
413*eb6f0de0SAdrian Chadd {
414*eb6f0de0SAdrian Chadd 	int amin = 65530;
415*eb6f0de0SAdrian Chadd 	int i;
416*eb6f0de0SAdrian Chadd 
417*eb6f0de0SAdrian Chadd 	for (i = 0; i < 4; i++) {
418*eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_rc[i].tries == 0)
419*eb6f0de0SAdrian Chadd 			continue;
420*eb6f0de0SAdrian Chadd 		amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen);
421*eb6f0de0SAdrian Chadd 	}
422*eb6f0de0SAdrian Chadd 
423*eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: max frame len= %d\n",
424*eb6f0de0SAdrian Chadd 	    __func__, amin);
425*eb6f0de0SAdrian Chadd 
426*eb6f0de0SAdrian Chadd 	return amin;
427*eb6f0de0SAdrian Chadd }
4284b44f6f2SAdrian Chadd 
4294b44f6f2SAdrian Chadd /*
4304b44f6f2SAdrian Chadd  * Setup a 11n rate series structure
4314b44f6f2SAdrian Chadd  *
4324b44f6f2SAdrian Chadd  * This should be called for both legacy and MCS rates.
433*eb6f0de0SAdrian Chadd  *
434*eb6f0de0SAdrian Chadd  * It, along with ath_buf_set_rate, must be called -after- a burst
435*eb6f0de0SAdrian Chadd  * or aggregate is setup.
4364b44f6f2SAdrian Chadd  */
4374b44f6f2SAdrian Chadd static void
4384b44f6f2SAdrian Chadd ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
439*eb6f0de0SAdrian Chadd     struct ath_buf *bf, HAL_11N_RATE_SERIES *series)
4404b44f6f2SAdrian Chadd {
441fce6d676SAdrian Chadd #define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
4424b44f6f2SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
4434b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
4444b44f6f2SAdrian Chadd 	HAL_BOOL shortPreamble = AH_FALSE;
4454b44f6f2SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
4464b44f6f2SAdrian Chadd 	int i;
447*eb6f0de0SAdrian Chadd 	int pktlen;
448*eb6f0de0SAdrian Chadd 	int flags = bf->bf_state.bfs_flags;
449*eb6f0de0SAdrian Chadd 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
4504b44f6f2SAdrian Chadd 
4514b44f6f2SAdrian Chadd 	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
4524b44f6f2SAdrian Chadd 	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
4534b44f6f2SAdrian Chadd 		shortPreamble = AH_TRUE;
4544b44f6f2SAdrian Chadd 
455*eb6f0de0SAdrian Chadd 	/*
456*eb6f0de0SAdrian Chadd 	 * If this is the first frame in an aggregate series,
457*eb6f0de0SAdrian Chadd 	 * use the aggregate length.
458*eb6f0de0SAdrian Chadd 	 */
459*eb6f0de0SAdrian Chadd 	if (bf->bf_state.bfs_aggr)
460*eb6f0de0SAdrian Chadd 		pktlen = bf->bf_state.bfs_al;
461*eb6f0de0SAdrian Chadd 	else
462*eb6f0de0SAdrian Chadd 		pktlen = bf->bf_state.bfs_pktlen;
463*eb6f0de0SAdrian Chadd 
464*eb6f0de0SAdrian Chadd 	/*
465*eb6f0de0SAdrian Chadd 	 * XXX TODO: modify this routine to use the bfs_rc[x].flags
466*eb6f0de0SAdrian Chadd 	 * XXX fields.
467*eb6f0de0SAdrian Chadd 	 */
4684b44f6f2SAdrian Chadd 	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
4694b44f6f2SAdrian Chadd 	for (i = 0; i < 4;  i++) {
470146b49d8SAdrian Chadd 		/* Only set flags for actual TX attempts */
471*eb6f0de0SAdrian Chadd 		if (rc[i].tries == 0)
472146b49d8SAdrian Chadd 			continue;
473146b49d8SAdrian Chadd 
474*eb6f0de0SAdrian Chadd 		series[i].Tries = rc[i].tries;
475146b49d8SAdrian Chadd 
476146b49d8SAdrian Chadd 		/*
477146b49d8SAdrian Chadd 		 * XXX this isn't strictly correct - sc_txchainmask
478146b49d8SAdrian Chadd 		 * XXX isn't the currently active chainmask;
479146b49d8SAdrian Chadd 		 * XXX it's the interface chainmask at startup.
480146b49d8SAdrian Chadd 		 * XXX It's overridden in the HAL rate scenario function
481146b49d8SAdrian Chadd 		 * XXX for now.
482146b49d8SAdrian Chadd 		 */
4834b44f6f2SAdrian Chadd 		series[i].ChSel = sc->sc_txchainmask;
484146b49d8SAdrian Chadd 
4852b5684a8SAdrian Chadd 		if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
4864b44f6f2SAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
487146b49d8SAdrian Chadd 
488532f2442SAdrian Chadd 		/*
489532f2442SAdrian Chadd 		 * Transmit 40MHz frames only if the node has negotiated
490532f2442SAdrian Chadd 		 * it rather than whether the node is capable of it or not.
491532f2442SAdrian Chadd 	 	 * It's subtly different in the hostap case.
492532f2442SAdrian Chadd 	 	 */
493532f2442SAdrian Chadd 		if (ni->ni_chw == 40)
4944b44f6f2SAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_2040;
4956246be6eSAdrian Chadd 
4967842451aSAdrian Chadd 		/*
4976246be6eSAdrian Chadd 		 * Set short-GI only if the node has advertised it
4986246be6eSAdrian Chadd 		 * the channel width is suitable, and we support it.
4996246be6eSAdrian Chadd 		 * We don't currently have a "negotiated" set of bits -
5006246be6eSAdrian Chadd 		 * ni_htcap is what the remote end sends, not what this
5016246be6eSAdrian Chadd 		 * node is capable of.
5027842451aSAdrian Chadd 		 */
5036246be6eSAdrian Chadd 		if (ni->ni_chw == 40 &&
5046246be6eSAdrian Chadd 		    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
5056246be6eSAdrian Chadd 		    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
5064b44f6f2SAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
5076246be6eSAdrian Chadd 
5086246be6eSAdrian Chadd 		if (ni->ni_chw == 20 &&
5096246be6eSAdrian Chadd 		    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
5106246be6eSAdrian Chadd 		    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
5116246be6eSAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
5124b44f6f2SAdrian Chadd 
513*eb6f0de0SAdrian Chadd 		series[i].Rate = rt->info[rc[i].rix].rateCode;
5144b44f6f2SAdrian Chadd 
5154b44f6f2SAdrian Chadd 		/* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */
5169a97e25eSAdrian Chadd 		if (series[i].Rate & IEEE80211_RATE_MCS) {
5174b44f6f2SAdrian Chadd 			series[i].PktDuration =
5184b44f6f2SAdrian Chadd 			    ath_computedur_ht(pktlen
5199a97e25eSAdrian Chadd 				, series[i].Rate
520fce6d676SAdrian Chadd 				, HT_RC_2_STREAMS(series[i].Rate)
521fce6d676SAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_2040
522f449ab1cSAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
5234b44f6f2SAdrian Chadd 		} else {
5241198947aSAdrian Chadd 			if (shortPreamble)
525*eb6f0de0SAdrian Chadd 				series[i].Rate |=
526*eb6f0de0SAdrian Chadd 				    rt->info[rc[i].rix].shortPreamble;
5274b44f6f2SAdrian Chadd 			series[i].PktDuration = ath_hal_computetxtime(ah,
528*eb6f0de0SAdrian Chadd 			    rt, pktlen, rc[i].rix, shortPreamble);
5294b44f6f2SAdrian Chadd 		}
5304b44f6f2SAdrian Chadd 	}
531fce6d676SAdrian Chadd #undef	HT_RC_2_STREAMS
5324b44f6f2SAdrian Chadd }
5334b44f6f2SAdrian Chadd 
5344b44f6f2SAdrian Chadd #if 0
5354b44f6f2SAdrian Chadd static void
5364b44f6f2SAdrian Chadd ath_rateseries_print(HAL_11N_RATE_SERIES *series)
5374b44f6f2SAdrian Chadd {
5384b44f6f2SAdrian Chadd 	int i;
5394b44f6f2SAdrian Chadd 	for (i = 0; i < 4; i++) {
5404b44f6f2SAdrian Chadd 		printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n",
5414b44f6f2SAdrian Chadd 		    i,
5424b44f6f2SAdrian Chadd 		    series[i].Rate,
5434b44f6f2SAdrian Chadd 		    series[i].Tries,
5444b44f6f2SAdrian Chadd 		    series[i].PktDuration,
5454b44f6f2SAdrian Chadd 		    series[i].ChSel,
5464b44f6f2SAdrian Chadd 		    series[i].RateFlags);
5474b44f6f2SAdrian Chadd 	}
5484b44f6f2SAdrian Chadd }
5494b44f6f2SAdrian Chadd #endif
5504b44f6f2SAdrian Chadd 
5514b44f6f2SAdrian Chadd /*
5524b44f6f2SAdrian Chadd  * Setup the 11n rate scenario and burst duration for the given TX descriptor
5534b44f6f2SAdrian Chadd  * list.
5544b44f6f2SAdrian Chadd  *
5554b44f6f2SAdrian Chadd  * This isn't useful for sending beacon frames, which has different needs
5564b44f6f2SAdrian Chadd  * wrt what's passed into the rate scenario function.
5574b44f6f2SAdrian Chadd  */
5584b44f6f2SAdrian Chadd 
5594b44f6f2SAdrian Chadd void
560*eb6f0de0SAdrian Chadd ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni,
561*eb6f0de0SAdrian Chadd     struct ath_buf *bf)
5624b44f6f2SAdrian Chadd {
5634b44f6f2SAdrian Chadd 	HAL_11N_RATE_SERIES series[4];
5644b44f6f2SAdrian Chadd 	struct ath_desc *ds = bf->bf_desc;
5654b44f6f2SAdrian Chadd 	struct ath_desc *lastds = NULL;
5664b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
567*eb6f0de0SAdrian Chadd 	int is_pspoll = (bf->bf_state.bfs_atype == HAL_PKT_TYPE_PSPOLL);
568*eb6f0de0SAdrian Chadd 	int ctsrate = bf->bf_state.bfs_ctsrate;
569*eb6f0de0SAdrian Chadd 	int flags = bf->bf_state.bfs_flags;
5704b44f6f2SAdrian Chadd 
5714b44f6f2SAdrian Chadd 	/* Setup rate scenario */
5724b44f6f2SAdrian Chadd 	memset(&series, 0, sizeof(series));
5734b44f6f2SAdrian Chadd 
574*eb6f0de0SAdrian Chadd 	ath_rateseries_setup(sc, ni, bf, series);
5754b44f6f2SAdrian Chadd 
5764b44f6f2SAdrian Chadd 	/* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */
5774b44f6f2SAdrian Chadd 
5784b44f6f2SAdrian Chadd 	/* Enforce RTS and CTS are mutually exclusive */
5794b44f6f2SAdrian Chadd 
5804b44f6f2SAdrian Chadd 	/* Get a pointer to the last tx descriptor in the list */
581*eb6f0de0SAdrian Chadd 	lastds = bf->bf_lastds;
5824b44f6f2SAdrian Chadd 
5832b5684a8SAdrian Chadd #if 0
5842b5684a8SAdrian Chadd 	printf("pktlen: %d; flags 0x%x\n", pktlen, flags);
5852b5684a8SAdrian Chadd 	ath_rateseries_print(series);
5862b5684a8SAdrian Chadd #endif
5872b5684a8SAdrian Chadd 
5884b44f6f2SAdrian Chadd 	/* Set rate scenario */
5894b44f6f2SAdrian Chadd 	ath_hal_set11nratescenario(ah, ds,
590bf26df36SAdrian Chadd 	    !is_pspoll,	/* whether to override the duration or not */
591bf26df36SAdrian Chadd 			/* don't allow hardware to override the duration on ps-poll packets */
5924b44f6f2SAdrian Chadd 	    ctsrate,	/* rts/cts rate */
5934b44f6f2SAdrian Chadd 	    series,	/* 11n rate series */
5944b44f6f2SAdrian Chadd 	    4,		/* number of series */
5954b44f6f2SAdrian Chadd 	    flags);
5964b44f6f2SAdrian Chadd 
5974b44f6f2SAdrian Chadd 	/* Setup the last descriptor in the chain */
5984b44f6f2SAdrian Chadd 	ath_hal_setuplasttxdesc(ah, lastds, ds);
5994b44f6f2SAdrian Chadd 
6004b44f6f2SAdrian Chadd 	/* Set burst duration */
601*eb6f0de0SAdrian Chadd 	/*
602*eb6f0de0SAdrian Chadd 	 * This is only required when doing 11n burst, not aggregation
603*eb6f0de0SAdrian Chadd 	 * ie, if there's a second frame in a RIFS or A-MPDU burst
604*eb6f0de0SAdrian Chadd 	 * w/ >1 A-MPDU frame bursting back to back.
605*eb6f0de0SAdrian Chadd 	 * Normal A-MPDU doesn't do bursting -between- aggregates.
606*eb6f0de0SAdrian Chadd 	 *
607*eb6f0de0SAdrian Chadd 	 * .. and it's highly likely this won't ever be implemented
608*eb6f0de0SAdrian Chadd 	 */
6094b44f6f2SAdrian Chadd 	//ath_hal_set11nburstduration(ah, ds, 8192);
6104b44f6f2SAdrian Chadd }
611*eb6f0de0SAdrian Chadd 
612*eb6f0de0SAdrian Chadd /*
613*eb6f0de0SAdrian Chadd  * Form an aggregate packet list.
614*eb6f0de0SAdrian Chadd  *
615*eb6f0de0SAdrian Chadd  * This function enforces the aggregate restrictions/requirements.
616*eb6f0de0SAdrian Chadd  *
617*eb6f0de0SAdrian Chadd  * These are:
618*eb6f0de0SAdrian Chadd  *
619*eb6f0de0SAdrian Chadd  * + The aggregate size maximum (64k for AR9160 and later, 8K for
620*eb6f0de0SAdrian Chadd  *   AR5416 when doing RTS frame protection.)
621*eb6f0de0SAdrian Chadd  * + Maximum number of sub-frames for an aggregate
622*eb6f0de0SAdrian Chadd  * + The aggregate delimiter size, giving MACs time to do whatever is
623*eb6f0de0SAdrian Chadd  *   needed before each frame
624*eb6f0de0SAdrian Chadd  * + Enforce the BAW limit
625*eb6f0de0SAdrian Chadd  *
626*eb6f0de0SAdrian Chadd  * Each descriptor queued should have the DMA setup.
627*eb6f0de0SAdrian Chadd  * The rate series, descriptor setup, linking, etc is all done
628*eb6f0de0SAdrian Chadd  * externally. This routine simply chains them together.
629*eb6f0de0SAdrian Chadd  * ath_tx_setds_11n() will take care of configuring the per-
630*eb6f0de0SAdrian Chadd  * descriptor setup, and ath_buf_set_rate() will configure the
631*eb6f0de0SAdrian Chadd  * rate control.
632*eb6f0de0SAdrian Chadd  *
633*eb6f0de0SAdrian Chadd  * Note that the TID lock is only grabbed when dequeuing packets from
634*eb6f0de0SAdrian Chadd  * the TID queue. If some code in another thread adds to the head of this
635*eb6f0de0SAdrian Chadd  * list, very strange behaviour will occur. Since retransmission is the
636*eb6f0de0SAdrian Chadd  * only reason this will occur, and this routine is designed to be called
637*eb6f0de0SAdrian Chadd  * from within the scheduler task, it won't ever clash with the completion
638*eb6f0de0SAdrian Chadd  * task.
639*eb6f0de0SAdrian Chadd  *
640*eb6f0de0SAdrian Chadd  * So if you want to call this from an upper layer context (eg, to direct-
641*eb6f0de0SAdrian Chadd  * dispatch aggregate frames to the hardware), please keep this in mind.
642*eb6f0de0SAdrian Chadd  */
643*eb6f0de0SAdrian Chadd ATH_AGGR_STATUS
644*eb6f0de0SAdrian Chadd ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, struct ath_tid *tid,
645*eb6f0de0SAdrian Chadd     ath_bufhead *bf_q)
646*eb6f0de0SAdrian Chadd {
647*eb6f0de0SAdrian Chadd 	//struct ieee80211_node *ni = &an->an_node;
648*eb6f0de0SAdrian Chadd 	struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
649*eb6f0de0SAdrian Chadd 	int nframes = 0;
650*eb6f0de0SAdrian Chadd 	uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw;
651*eb6f0de0SAdrian Chadd 	struct ieee80211_tx_ampdu *tap;
652*eb6f0de0SAdrian Chadd 	int status = ATH_AGGR_DONE;
653*eb6f0de0SAdrian Chadd 	int prev_frames = 0;	/* XXX for AR5416 burst, not done here */
654*eb6f0de0SAdrian Chadd 	int prev_al = 0;	/* XXX also for AR5416 burst */
655*eb6f0de0SAdrian Chadd 
656*eb6f0de0SAdrian Chadd 	ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
657*eb6f0de0SAdrian Chadd 
658*eb6f0de0SAdrian Chadd 	tap = ath_tx_get_tx_tid(an, tid->tid);
659*eb6f0de0SAdrian Chadd 	if (tap == NULL) {
660*eb6f0de0SAdrian Chadd 		status = ATH_AGGR_ERROR;
661*eb6f0de0SAdrian Chadd 		goto finish;
662*eb6f0de0SAdrian Chadd 	}
663*eb6f0de0SAdrian Chadd 
664*eb6f0de0SAdrian Chadd 	h_baw = tap->txa_wnd / 2;
665*eb6f0de0SAdrian Chadd 
666*eb6f0de0SAdrian Chadd 	for (;;) {
667*eb6f0de0SAdrian Chadd 		bf = TAILQ_FIRST(&tid->axq_q);
668*eb6f0de0SAdrian Chadd 		if (bf_first == NULL)
669*eb6f0de0SAdrian Chadd 			bf_first = bf;
670*eb6f0de0SAdrian Chadd 		if (bf == NULL) {
671*eb6f0de0SAdrian Chadd 			status = ATH_AGGR_DONE;
672*eb6f0de0SAdrian Chadd 			break;
673*eb6f0de0SAdrian Chadd 		} else {
674*eb6f0de0SAdrian Chadd 			/*
675*eb6f0de0SAdrian Chadd 			 * It's the first frame;
676*eb6f0de0SAdrian Chadd 			 * set the aggregation limit based on the
677*eb6f0de0SAdrian Chadd 			 * rate control decision that has been made.
678*eb6f0de0SAdrian Chadd 			 */
679*eb6f0de0SAdrian Chadd 			aggr_limit = ath_get_aggr_limit(sc, bf_first);
680*eb6f0de0SAdrian Chadd 		}
681*eb6f0de0SAdrian Chadd 
682*eb6f0de0SAdrian Chadd 		/* Set this early just so things don't get confused */
683*eb6f0de0SAdrian Chadd 		bf->bf_next = NULL;
684*eb6f0de0SAdrian Chadd 
685*eb6f0de0SAdrian Chadd 		/*
686*eb6f0de0SAdrian Chadd 		 * Don't unlock the tid lock until we're sure we are going
687*eb6f0de0SAdrian Chadd 		 * to queue this frame.
688*eb6f0de0SAdrian Chadd 		 */
689*eb6f0de0SAdrian Chadd 
690*eb6f0de0SAdrian Chadd 		/*
691*eb6f0de0SAdrian Chadd 		 * If the frame doesn't have a sequence number that we're
692*eb6f0de0SAdrian Chadd 		 * tracking in the BAW (eg NULL QOS data frame), we can't
693*eb6f0de0SAdrian Chadd 		 * aggregate it. Stop the aggregation process; the sender
694*eb6f0de0SAdrian Chadd 		 * can then TX what's in the list thus far and then
695*eb6f0de0SAdrian Chadd 		 * TX the frame individually.
696*eb6f0de0SAdrian Chadd 		 */
697*eb6f0de0SAdrian Chadd 		if (! bf->bf_state.bfs_dobaw) {
698*eb6f0de0SAdrian Chadd 			status = ATH_AGGR_NONAGGR;
699*eb6f0de0SAdrian Chadd 			break;
700*eb6f0de0SAdrian Chadd 		}
701*eb6f0de0SAdrian Chadd 
702*eb6f0de0SAdrian Chadd 		/*
703*eb6f0de0SAdrian Chadd 		 * If any of the rates are non-HT, this packet
704*eb6f0de0SAdrian Chadd 		 * can't be aggregated.
705*eb6f0de0SAdrian Chadd 		 * XXX TODO: add a bf_state flag which gets marked
706*eb6f0de0SAdrian Chadd 		 * if any active rate is non-HT.
707*eb6f0de0SAdrian Chadd 		 */
708*eb6f0de0SAdrian Chadd 
709*eb6f0de0SAdrian Chadd 		/*
710*eb6f0de0SAdrian Chadd 		 * If the packet has a sequence number, do not
711*eb6f0de0SAdrian Chadd 		 * step outside of the block-ack window.
712*eb6f0de0SAdrian Chadd 		 */
713*eb6f0de0SAdrian Chadd 		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
714*eb6f0de0SAdrian Chadd 		    SEQNO(bf->bf_state.bfs_seqno))) {
715*eb6f0de0SAdrian Chadd 		    status = ATH_AGGR_BAW_CLOSED;
716*eb6f0de0SAdrian Chadd 		    break;
717*eb6f0de0SAdrian Chadd 		}
718*eb6f0de0SAdrian Chadd 
719*eb6f0de0SAdrian Chadd 		/*
720*eb6f0de0SAdrian Chadd 		 * XXX TODO: AR5416 has an 8K aggregation size limit
721*eb6f0de0SAdrian Chadd 		 * when RTS is enabled, and RTS is required for dual-stream
722*eb6f0de0SAdrian Chadd 		 * rates.
723*eb6f0de0SAdrian Chadd 		 *
724*eb6f0de0SAdrian Chadd 		 * For now, limit all aggregates for the AR5416 to be 8K.
725*eb6f0de0SAdrian Chadd 		 */
726*eb6f0de0SAdrian Chadd 
727*eb6f0de0SAdrian Chadd 		/*
728*eb6f0de0SAdrian Chadd 		 * do not exceed aggregation limit
729*eb6f0de0SAdrian Chadd 		 */
730*eb6f0de0SAdrian Chadd 		al_delta = ATH_AGGR_DELIM_SZ + bf->bf_state.bfs_pktlen;
731*eb6f0de0SAdrian Chadd 		if (nframes &&
732*eb6f0de0SAdrian Chadd 		    (aggr_limit < (al + bpad + al_delta + prev_al))) {
733*eb6f0de0SAdrian Chadd 			status = ATH_AGGR_LIMITED;
734*eb6f0de0SAdrian Chadd 			break;
735*eb6f0de0SAdrian Chadd 		}
736*eb6f0de0SAdrian Chadd 
737*eb6f0de0SAdrian Chadd 		/*
738*eb6f0de0SAdrian Chadd 		 * Do not exceed subframe limit.
739*eb6f0de0SAdrian Chadd 		 */
740*eb6f0de0SAdrian Chadd 		if ((nframes + prev_frames) >= MIN((h_baw),
741*eb6f0de0SAdrian Chadd 		    IEEE80211_AMPDU_SUBFRAME_DEFAULT)) {
742*eb6f0de0SAdrian Chadd 			status = ATH_AGGR_LIMITED;
743*eb6f0de0SAdrian Chadd 			break;
744*eb6f0de0SAdrian Chadd 		}
745*eb6f0de0SAdrian Chadd 
746*eb6f0de0SAdrian Chadd 		/*
747*eb6f0de0SAdrian Chadd 		 * this packet is part of an aggregate.
748*eb6f0de0SAdrian Chadd 		 */
749*eb6f0de0SAdrian Chadd 		ATH_TXQ_REMOVE(tid, bf, bf_list);
750*eb6f0de0SAdrian Chadd 
751*eb6f0de0SAdrian Chadd 		/* The TID lock is required for the BAW update */
752*eb6f0de0SAdrian Chadd 		ath_tx_addto_baw(sc, an, tid, bf);
753*eb6f0de0SAdrian Chadd 		bf->bf_state.bfs_addedbaw = 1;
754*eb6f0de0SAdrian Chadd 
755*eb6f0de0SAdrian Chadd 		/*
756*eb6f0de0SAdrian Chadd 		 * XXX TODO: If any frame in the aggregate requires RTS/CTS,
757*eb6f0de0SAdrian Chadd 		 * set the first frame.
758*eb6f0de0SAdrian Chadd 		 */
759*eb6f0de0SAdrian Chadd 
760*eb6f0de0SAdrian Chadd 		/*
761*eb6f0de0SAdrian Chadd 		 * XXX enforce ACK for aggregate frames (this needs to be
762*eb6f0de0SAdrian Chadd 		 * XXX handled more gracefully?
763*eb6f0de0SAdrian Chadd 		 */
764*eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_flags & HAL_TXDESC_NOACK) {
765*eb6f0de0SAdrian Chadd 			device_printf(sc->sc_dev,
766*eb6f0de0SAdrian Chadd 			    "%s: HAL_TXDESC_NOACK set for an aggregate frame?\n",
767*eb6f0de0SAdrian Chadd 			    __func__);
768*eb6f0de0SAdrian Chadd 			bf->bf_state.bfs_flags &= (~HAL_TXDESC_NOACK);
769*eb6f0de0SAdrian Chadd 		}
770*eb6f0de0SAdrian Chadd 
771*eb6f0de0SAdrian Chadd 		/*
772*eb6f0de0SAdrian Chadd 		 * Add the now owned buffer (which isn't
773*eb6f0de0SAdrian Chadd 		 * on the software TXQ any longer) to our
774*eb6f0de0SAdrian Chadd 		 * aggregate frame list.
775*eb6f0de0SAdrian Chadd 		 */
776*eb6f0de0SAdrian Chadd 		TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
777*eb6f0de0SAdrian Chadd 		nframes ++;
778*eb6f0de0SAdrian Chadd 
779*eb6f0de0SAdrian Chadd 		/* Completion handler */
780*eb6f0de0SAdrian Chadd 		bf->bf_comp = ath_tx_aggr_comp;
781*eb6f0de0SAdrian Chadd 
782*eb6f0de0SAdrian Chadd 		/*
783*eb6f0de0SAdrian Chadd 		 * add padding for previous frame to aggregation length
784*eb6f0de0SAdrian Chadd 		 */
785*eb6f0de0SAdrian Chadd 		al += bpad + al_delta;
786*eb6f0de0SAdrian Chadd 
787*eb6f0de0SAdrian Chadd 		/*
788*eb6f0de0SAdrian Chadd 		 * Calculate delimiters needed for the current frame
789*eb6f0de0SAdrian Chadd 		 */
790*eb6f0de0SAdrian Chadd 		bf->bf_state.bfs_ndelim =
791*eb6f0de0SAdrian Chadd 		    ath_compute_num_delims(sc, bf_first,
792*eb6f0de0SAdrian Chadd 		    bf->bf_state.bfs_pktlen);
793*eb6f0de0SAdrian Chadd 
794*eb6f0de0SAdrian Chadd 		/*
795*eb6f0de0SAdrian Chadd 		 * Calculate the padding needed from this set of delimiters,
796*eb6f0de0SAdrian Chadd 		 * used when calculating if the next frame will fit in
797*eb6f0de0SAdrian Chadd 		 * the aggregate.
798*eb6f0de0SAdrian Chadd 		 */
799*eb6f0de0SAdrian Chadd 		bpad = PADBYTES(al_delta) + (bf->bf_state.bfs_ndelim << 2);
800*eb6f0de0SAdrian Chadd 
801*eb6f0de0SAdrian Chadd 		/*
802*eb6f0de0SAdrian Chadd 		 * Chain the buffers together
803*eb6f0de0SAdrian Chadd 		 */
804*eb6f0de0SAdrian Chadd 		if (bf_prev)
805*eb6f0de0SAdrian Chadd 			bf_prev->bf_next = bf;
806*eb6f0de0SAdrian Chadd 		bf_prev = bf;
807*eb6f0de0SAdrian Chadd 
808*eb6f0de0SAdrian Chadd 		/*
809*eb6f0de0SAdrian Chadd 		 * XXX TODO: if any sub-frames have RTS/CTS enabled;
810*eb6f0de0SAdrian Chadd 		 * enable it for the entire aggregate.
811*eb6f0de0SAdrian Chadd 		 */
812*eb6f0de0SAdrian Chadd 
813*eb6f0de0SAdrian Chadd #if 0
814*eb6f0de0SAdrian Chadd 		/*
815*eb6f0de0SAdrian Chadd 		 * terminate aggregation on a small packet boundary
816*eb6f0de0SAdrian Chadd 		 */
817*eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_pktlen < ATH_AGGR_MINPLEN) {
818*eb6f0de0SAdrian Chadd 			status = ATH_AGGR_SHORTPKT;
819*eb6f0de0SAdrian Chadd 			break;
820*eb6f0de0SAdrian Chadd 		}
821*eb6f0de0SAdrian Chadd #endif
822*eb6f0de0SAdrian Chadd 
823*eb6f0de0SAdrian Chadd 	}
824*eb6f0de0SAdrian Chadd 
825*eb6f0de0SAdrian Chadd finish:
826*eb6f0de0SAdrian Chadd 	/*
827*eb6f0de0SAdrian Chadd 	 * Just in case the list was empty when we tried to
828*eb6f0de0SAdrian Chadd 	 * dequeue a packet ..
829*eb6f0de0SAdrian Chadd 	 */
830*eb6f0de0SAdrian Chadd 	if (bf_first) {
831*eb6f0de0SAdrian Chadd 		bf_first->bf_state.bfs_al = al;
832*eb6f0de0SAdrian Chadd 		bf_first->bf_state.bfs_nframes = nframes;
833*eb6f0de0SAdrian Chadd 	}
834*eb6f0de0SAdrian Chadd 	return status;
835*eb6f0de0SAdrian Chadd }
836