xref: /freebsd/sys/dev/ath/if_ath_tx_ht.c (revision 56129906234d9d511c778a8fbd4161a2c02b4658)
14b44f6f2SAdrian Chadd /*-
24b44f6f2SAdrian Chadd  * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
34b44f6f2SAdrian Chadd  * All rights reserved.
44b44f6f2SAdrian Chadd  *
54b44f6f2SAdrian Chadd  * Redistribution and use in source and binary forms, with or without
64b44f6f2SAdrian Chadd  * modification, are permitted provided that the following conditions
74b44f6f2SAdrian Chadd  * are met:
84b44f6f2SAdrian Chadd  * 1. Redistributions of source code must retain the above copyright
94b44f6f2SAdrian Chadd  *    notice, this list of conditions and the following disclaimer,
104b44f6f2SAdrian Chadd  *    without modification.
114b44f6f2SAdrian Chadd  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
124b44f6f2SAdrian Chadd  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
134b44f6f2SAdrian Chadd  *    redistribution must be conditioned upon including a substantially
144b44f6f2SAdrian Chadd  *    similar Disclaimer requirement for further binary redistribution.
154b44f6f2SAdrian Chadd  *
164b44f6f2SAdrian Chadd  * NO WARRANTY
174b44f6f2SAdrian Chadd  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
184b44f6f2SAdrian Chadd  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
194b44f6f2SAdrian Chadd  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
204b44f6f2SAdrian Chadd  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
214b44f6f2SAdrian Chadd  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
224b44f6f2SAdrian Chadd  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
234b44f6f2SAdrian Chadd  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
244b44f6f2SAdrian Chadd  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
254b44f6f2SAdrian Chadd  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
264b44f6f2SAdrian Chadd  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
274b44f6f2SAdrian Chadd  * THE POSSIBILITY OF SUCH DAMAGES.
284b44f6f2SAdrian Chadd  */
294b44f6f2SAdrian Chadd 
304b44f6f2SAdrian Chadd #include <sys/cdefs.h>
314b44f6f2SAdrian Chadd __FBSDID("$FreeBSD$");
324b44f6f2SAdrian Chadd 
334b44f6f2SAdrian Chadd #include "opt_inet.h"
344b44f6f2SAdrian Chadd #include "opt_ath.h"
354b44f6f2SAdrian Chadd #include "opt_wlan.h"
364b44f6f2SAdrian Chadd 
374b44f6f2SAdrian Chadd #include <sys/param.h>
384b44f6f2SAdrian Chadd #include <sys/systm.h>
394b44f6f2SAdrian Chadd #include <sys/sysctl.h>
404b44f6f2SAdrian Chadd #include <sys/mbuf.h>
414b44f6f2SAdrian Chadd #include <sys/malloc.h>
424b44f6f2SAdrian Chadd #include <sys/lock.h>
434b44f6f2SAdrian Chadd #include <sys/mutex.h>
444b44f6f2SAdrian Chadd #include <sys/kernel.h>
454b44f6f2SAdrian Chadd #include <sys/socket.h>
464b44f6f2SAdrian Chadd #include <sys/sockio.h>
474b44f6f2SAdrian Chadd #include <sys/errno.h>
484b44f6f2SAdrian Chadd #include <sys/callout.h>
494b44f6f2SAdrian Chadd #include <sys/bus.h>
504b44f6f2SAdrian Chadd #include <sys/endian.h>
514b44f6f2SAdrian Chadd #include <sys/kthread.h>
524b44f6f2SAdrian Chadd #include <sys/taskqueue.h>
534b44f6f2SAdrian Chadd #include <sys/priv.h>
544b44f6f2SAdrian Chadd 
554b44f6f2SAdrian Chadd #include <machine/bus.h>
564b44f6f2SAdrian Chadd 
574b44f6f2SAdrian Chadd #include <net/if.h>
584b44f6f2SAdrian Chadd #include <net/if_dl.h>
594b44f6f2SAdrian Chadd #include <net/if_media.h>
604b44f6f2SAdrian Chadd #include <net/if_types.h>
614b44f6f2SAdrian Chadd #include <net/if_arp.h>
624b44f6f2SAdrian Chadd #include <net/ethernet.h>
634b44f6f2SAdrian Chadd #include <net/if_llc.h>
644b44f6f2SAdrian Chadd 
654b44f6f2SAdrian Chadd #include <net80211/ieee80211_var.h>
664b44f6f2SAdrian Chadd #include <net80211/ieee80211_regdomain.h>
674b44f6f2SAdrian Chadd #ifdef IEEE80211_SUPPORT_SUPERG
684b44f6f2SAdrian Chadd #include <net80211/ieee80211_superg.h>
694b44f6f2SAdrian Chadd #endif
704b44f6f2SAdrian Chadd #ifdef IEEE80211_SUPPORT_TDMA
714b44f6f2SAdrian Chadd #include <net80211/ieee80211_tdma.h>
724b44f6f2SAdrian Chadd #endif
734b44f6f2SAdrian Chadd 
744b44f6f2SAdrian Chadd #include <net/bpf.h>
754b44f6f2SAdrian Chadd 
764b44f6f2SAdrian Chadd #ifdef INET
774b44f6f2SAdrian Chadd #include <netinet/in.h>
784b44f6f2SAdrian Chadd #include <netinet/if_ether.h>
794b44f6f2SAdrian Chadd #endif
804b44f6f2SAdrian Chadd 
814b44f6f2SAdrian Chadd #include <dev/ath/if_athvar.h>
824b44f6f2SAdrian Chadd #include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
834b44f6f2SAdrian Chadd #include <dev/ath/ath_hal/ah_diagcodes.h>
844b44f6f2SAdrian Chadd 
854b44f6f2SAdrian Chadd #ifdef ATH_TX99_DIAG
864b44f6f2SAdrian Chadd #include <dev/ath/ath_tx99/ath_tx99.h>
874b44f6f2SAdrian Chadd #endif
884b44f6f2SAdrian Chadd 
89eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_tx.h>		/* XXX for some support functions */
904b44f6f2SAdrian Chadd #include <dev/ath/if_ath_tx_ht.h>
91eb6f0de0SAdrian Chadd #include <dev/ath/if_athrate.h>
92eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_debug.h>
93eb6f0de0SAdrian Chadd 
94eb6f0de0SAdrian Chadd /*
95eb6f0de0SAdrian Chadd  * XXX net80211?
96eb6f0de0SAdrian Chadd  */
97eb6f0de0SAdrian Chadd #define	IEEE80211_AMPDU_SUBFRAME_DEFAULT		32
98eb6f0de0SAdrian Chadd 
99eb6f0de0SAdrian Chadd #define	ATH_AGGR_DELIM_SZ	4	/* delimiter size */
100eb6f0de0SAdrian Chadd #define	ATH_AGGR_MINPLEN	256	/* in bytes, minimum packet length */
101b25c1f2aSAdrian Chadd /* number of delimiters for encryption padding */
102b25c1f2aSAdrian Chadd #define	ATH_AGGR_ENCRYPTDELIM	10
103eb6f0de0SAdrian Chadd 
104eb6f0de0SAdrian Chadd /*
105eb6f0de0SAdrian Chadd  * returns delimiter padding required given the packet length
106eb6f0de0SAdrian Chadd  */
107eb6f0de0SAdrian Chadd #define	ATH_AGGR_GET_NDELIM(_len)					\
108eb6f0de0SAdrian Chadd 	    (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ?	\
109eb6f0de0SAdrian Chadd 	    (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2)
110eb6f0de0SAdrian Chadd 
111eb6f0de0SAdrian Chadd #define	PADBYTES(_len)		((4 - ((_len) % 4)) % 4)
112eb6f0de0SAdrian Chadd 
113eb6f0de0SAdrian Chadd int ath_max_4ms_framelen[4][32] = {
114eb6f0de0SAdrian Chadd 	[MCS_HT20] = {
115eb6f0de0SAdrian Chadd 		3212,  6432,  9648,  12864,  19300,  25736,  28952,  32172,
116eb6f0de0SAdrian Chadd 		6424,  12852, 19280, 25708,  38568,  51424,  57852,  64280,
117eb6f0de0SAdrian Chadd 		9628,  19260, 28896, 38528,  57792,  65532,  65532,  65532,
118eb6f0de0SAdrian Chadd 		12828, 25656, 38488, 51320,  65532,  65532,  65532,  65532,
119eb6f0de0SAdrian Chadd 	},
120eb6f0de0SAdrian Chadd 	[MCS_HT20_SGI] = {
121eb6f0de0SAdrian Chadd 		3572,  7144,  10720,  14296,  21444,  28596,  32172,  35744,
122eb6f0de0SAdrian Chadd 		7140,  14284, 21428,  28568,  42856,  57144,  64288,  65532,
123eb6f0de0SAdrian Chadd 		10700, 21408, 32112,  42816,  64228,  65532,  65532,  65532,
124eb6f0de0SAdrian Chadd 		14256, 28516, 42780,  57040,  65532,  65532,  65532,  65532,
125eb6f0de0SAdrian Chadd 	},
126eb6f0de0SAdrian Chadd 	[MCS_HT40] = {
127eb6f0de0SAdrian Chadd 		6680,  13360,  20044,  26724,  40092,  53456,  60140,  65532,
128eb6f0de0SAdrian Chadd 		13348, 26700,  40052,  53400,  65532,  65532,  65532,  65532,
129eb6f0de0SAdrian Chadd 		20004, 40008,  60016,  65532,  65532,  65532,  65532,  65532,
130eb6f0de0SAdrian Chadd 		26644, 53292,  65532,  65532,  65532,  65532,  65532,  65532,
131eb6f0de0SAdrian Chadd 	},
132eb6f0de0SAdrian Chadd 	[MCS_HT40_SGI] = {
133eb6f0de0SAdrian Chadd 		7420,  14844,  22272,  29696,  44544,  59396,  65532,  65532,
134eb6f0de0SAdrian Chadd 		14832, 29668,  44504,  59340,  65532,  65532,  65532,  65532,
135eb6f0de0SAdrian Chadd 		22232, 44464,  65532,  65532,  65532,  65532,  65532,  65532,
136eb6f0de0SAdrian Chadd 		29616, 59232,  65532,  65532,  65532,  65532,  65532,  65532,
137eb6f0de0SAdrian Chadd 	}
138eb6f0de0SAdrian Chadd };
139eb6f0de0SAdrian Chadd 
140eb6f0de0SAdrian Chadd /*
141eb6f0de0SAdrian Chadd  * XXX should be in net80211
142eb6f0de0SAdrian Chadd  */
143eb6f0de0SAdrian Chadd static int ieee80211_mpdudensity_map[] = {
144eb6f0de0SAdrian Chadd 	0,		/* IEEE80211_HTCAP_MPDUDENSITY_NA */
145eb6f0de0SAdrian Chadd 	25,		/* IEEE80211_HTCAP_MPDUDENSITY_025 */
146eb6f0de0SAdrian Chadd 	50,		/* IEEE80211_HTCAP_MPDUDENSITY_05 */
147eb6f0de0SAdrian Chadd 	100,		/* IEEE80211_HTCAP_MPDUDENSITY_1 */
148eb6f0de0SAdrian Chadd 	200,		/* IEEE80211_HTCAP_MPDUDENSITY_2 */
149eb6f0de0SAdrian Chadd 	400,		/* IEEE80211_HTCAP_MPDUDENSITY_4 */
150eb6f0de0SAdrian Chadd 	800,		/* IEEE80211_HTCAP_MPDUDENSITY_8 */
151eb6f0de0SAdrian Chadd 	1600,		/* IEEE80211_HTCAP_MPDUDENSITY_16 */
152eb6f0de0SAdrian Chadd };
153eb6f0de0SAdrian Chadd 
154eb6f0de0SAdrian Chadd /*
155eb6f0de0SAdrian Chadd  * XXX should be in the HAL/net80211 ?
156eb6f0de0SAdrian Chadd  */
157eb6f0de0SAdrian Chadd #define	BITS_PER_BYTE		8
158eb6f0de0SAdrian Chadd #define	OFDM_PLCP_BITS		22
159eb6f0de0SAdrian Chadd #define	HT_RC_2_MCS(_rc)	((_rc) & 0x7f)
160eb6f0de0SAdrian Chadd #define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
161eb6f0de0SAdrian Chadd #define	L_STF			8
162eb6f0de0SAdrian Chadd #define	L_LTF			8
163eb6f0de0SAdrian Chadd #define	L_SIG			4
164eb6f0de0SAdrian Chadd #define	HT_SIG			8
165eb6f0de0SAdrian Chadd #define	HT_STF			4
166eb6f0de0SAdrian Chadd #define	HT_LTF(_ns)		(4 * (_ns))
167eb6f0de0SAdrian Chadd #define	SYMBOL_TIME(_ns)	((_ns) << 2)		// ns * 4 us
168eb6f0de0SAdrian Chadd #define	SYMBOL_TIME_HALFGI(_ns)	(((_ns) * 18 + 4) / 5)	// ns * 3.6 us
169eb6f0de0SAdrian Chadd #define	NUM_SYMBOLS_PER_USEC(_usec)	(_usec >> 2)
170eb6f0de0SAdrian Chadd #define	NUM_SYMBOLS_PER_USEC_HALFGI(_usec)	(((_usec*5)-4)/18)
171eb6f0de0SAdrian Chadd #define	IS_HT_RATE(_rate)	((_rate) & 0x80)
172eb6f0de0SAdrian Chadd 
173eb6f0de0SAdrian Chadd const uint32_t bits_per_symbol[][2] = {
174eb6f0de0SAdrian Chadd     /* 20MHz 40MHz */
175eb6f0de0SAdrian Chadd     {    26,   54 },     //  0: BPSK
176eb6f0de0SAdrian Chadd     {    52,  108 },     //  1: QPSK 1/2
177eb6f0de0SAdrian Chadd     {    78,  162 },     //  2: QPSK 3/4
178eb6f0de0SAdrian Chadd     {   104,  216 },     //  3: 16-QAM 1/2
179eb6f0de0SAdrian Chadd     {   156,  324 },     //  4: 16-QAM 3/4
180eb6f0de0SAdrian Chadd     {   208,  432 },     //  5: 64-QAM 2/3
181eb6f0de0SAdrian Chadd     {   234,  486 },     //  6: 64-QAM 3/4
182eb6f0de0SAdrian Chadd     {   260,  540 },     //  7: 64-QAM 5/6
183eb6f0de0SAdrian Chadd     {    52,  108 },     //  8: BPSK
184eb6f0de0SAdrian Chadd     {   104,  216 },     //  9: QPSK 1/2
185eb6f0de0SAdrian Chadd     {   156,  324 },     // 10: QPSK 3/4
186eb6f0de0SAdrian Chadd     {   208,  432 },     // 11: 16-QAM 1/2
187eb6f0de0SAdrian Chadd     {   312,  648 },     // 12: 16-QAM 3/4
188eb6f0de0SAdrian Chadd     {   416,  864 },     // 13: 64-QAM 2/3
189eb6f0de0SAdrian Chadd     {   468,  972 },     // 14: 64-QAM 3/4
190eb6f0de0SAdrian Chadd     {   520, 1080 },     // 15: 64-QAM 5/6
191eb6f0de0SAdrian Chadd     {    78,  162 },     // 16: BPSK
192eb6f0de0SAdrian Chadd     {   156,  324 },     // 17: QPSK 1/2
193eb6f0de0SAdrian Chadd     {   234,  486 },     // 18: QPSK 3/4
194eb6f0de0SAdrian Chadd     {   312,  648 },     // 19: 16-QAM 1/2
195eb6f0de0SAdrian Chadd     {   468,  972 },     // 20: 16-QAM 3/4
196eb6f0de0SAdrian Chadd     {   624, 1296 },     // 21: 64-QAM 2/3
197eb6f0de0SAdrian Chadd     {   702, 1458 },     // 22: 64-QAM 3/4
198eb6f0de0SAdrian Chadd     {   780, 1620 },     // 23: 64-QAM 5/6
199eb6f0de0SAdrian Chadd     {   104,  216 },     // 24: BPSK
200eb6f0de0SAdrian Chadd     {   208,  432 },     // 25: QPSK 1/2
201eb6f0de0SAdrian Chadd     {   312,  648 },     // 26: QPSK 3/4
202eb6f0de0SAdrian Chadd     {   416,  864 },     // 27: 16-QAM 1/2
203eb6f0de0SAdrian Chadd     {   624, 1296 },     // 28: 16-QAM 3/4
204eb6f0de0SAdrian Chadd     {   832, 1728 },     // 29: 64-QAM 2/3
205eb6f0de0SAdrian Chadd     {   936, 1944 },     // 30: 64-QAM 3/4
206eb6f0de0SAdrian Chadd     {  1040, 2160 },     // 31: 64-QAM 5/6
207eb6f0de0SAdrian Chadd };
208eb6f0de0SAdrian Chadd 
209eb6f0de0SAdrian Chadd /*
210eb6f0de0SAdrian Chadd  * Fill in the rate array information based on the current
211eb6f0de0SAdrian Chadd  * node configuration and the choices made by the rate
212eb6f0de0SAdrian Chadd  * selection code and ath_buf setup code.
213eb6f0de0SAdrian Chadd  *
214eb6f0de0SAdrian Chadd  * Later on, this may end up also being made by the
215eb6f0de0SAdrian Chadd  * rate control code, but for now it can live here.
216eb6f0de0SAdrian Chadd  *
217eb6f0de0SAdrian Chadd  * This needs to be called just before the packet is
218eb6f0de0SAdrian Chadd  * queued to the software queue or hardware queue,
219eb6f0de0SAdrian Chadd  * so all of the needed fields in bf_state are setup.
220eb6f0de0SAdrian Chadd  */
221eb6f0de0SAdrian Chadd void
222eb6f0de0SAdrian Chadd ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf)
223eb6f0de0SAdrian Chadd {
224eb6f0de0SAdrian Chadd 	struct ieee80211_node *ni = bf->bf_node;
225eb6f0de0SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
226eb6f0de0SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
227eb6f0de0SAdrian Chadd 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
228eb6f0de0SAdrian Chadd 	uint8_t rate;
229eb6f0de0SAdrian Chadd 	int i;
230eb6f0de0SAdrian Chadd 
231eb6f0de0SAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
232eb6f0de0SAdrian Chadd 		rc[i].flags = 0;
233eb6f0de0SAdrian Chadd 		if (rc[i].tries == 0)
234eb6f0de0SAdrian Chadd 			continue;
235eb6f0de0SAdrian Chadd 
236eb6f0de0SAdrian Chadd 		rate = rt->info[rc[i].rix].rateCode;
237eb6f0de0SAdrian Chadd 
238eb6f0de0SAdrian Chadd 		/*
239*56129906SAdrian Chadd 		 * Only enable short preamble for legacy rates
240eb6f0de0SAdrian Chadd 		 */
241*56129906SAdrian Chadd 		if (IS_HT_RATE(rate) && bf->bf_state.bfs_shpream)
242eb6f0de0SAdrian Chadd 			rate |= rt->info[rc[i].rix].shortPreamble;
243eb6f0de0SAdrian Chadd 
244eb6f0de0SAdrian Chadd 		/*
245eb6f0de0SAdrian Chadd 		 * Save this, used by the TX and completion code
246eb6f0de0SAdrian Chadd 		 */
247eb6f0de0SAdrian Chadd 		rc[i].ratecode = rate;
248eb6f0de0SAdrian Chadd 
249875a9451SAdrian Chadd 		if (bf->bf_state.bfs_txflags &
250eb6f0de0SAdrian Chadd 		    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
251eb6f0de0SAdrian Chadd 			rc[i].flags |= ATH_RC_RTSCTS_FLAG;
252eb6f0de0SAdrian Chadd 
253eb6f0de0SAdrian Chadd 		/* Only enable shortgi, 2040, dual-stream if HT is set */
254eb6f0de0SAdrian Chadd 		if (IS_HT_RATE(rate)) {
255eb6f0de0SAdrian Chadd 			rc[i].flags |= ATH_RC_HT_FLAG;
256eb6f0de0SAdrian Chadd 
257eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 40)
258eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_CW40_FLAG;
259eb6f0de0SAdrian Chadd 
260eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 40 &&
261eb6f0de0SAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
262eb6f0de0SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
263eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_SGI_FLAG;
264eb6f0de0SAdrian Chadd 
265eb6f0de0SAdrian Chadd 			if (ni->ni_chw == 20 &&
266eb6f0de0SAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
267eb6f0de0SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
268eb6f0de0SAdrian Chadd 				rc[i].flags |= ATH_RC_SGI_FLAG;
269eb6f0de0SAdrian Chadd 
270*56129906SAdrian Chadd 			/*
271*56129906SAdrian Chadd 			 * If we have STBC TX enabled and the receiver
272*56129906SAdrian Chadd 			 * can receive (at least) 1 stream STBC, AND it's
273*56129906SAdrian Chadd 			 * MCS 0-7, AND we have at least two chains enabled,
274*56129906SAdrian Chadd 			 * enable STBC.
275*56129906SAdrian Chadd 			 */
276*56129906SAdrian Chadd 			if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
277*56129906SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
278*56129906SAdrian Chadd 			    (sc->sc_cur_txchainmask > 1) &&
279*56129906SAdrian Chadd 			    HT_RC_2_STREAMS(rate) == 1) {
280*56129906SAdrian Chadd 				rc[i].flags |= ATH_RC_STBC_FLAG;
281*56129906SAdrian Chadd 			}
282*56129906SAdrian Chadd 
283eb6f0de0SAdrian Chadd 			/* XXX dual stream? and 3-stream? */
284eb6f0de0SAdrian Chadd 		}
285eb6f0de0SAdrian Chadd 
286eb6f0de0SAdrian Chadd 		/*
287eb6f0de0SAdrian Chadd 		 * Calculate the maximum 4ms frame length based
288eb6f0de0SAdrian Chadd 		 * on the MCS rate, SGI and channel width flags.
289eb6f0de0SAdrian Chadd 		 */
290eb6f0de0SAdrian Chadd 		if ((rc[i].flags & ATH_RC_HT_FLAG) &&
291eb6f0de0SAdrian Chadd 		    (HT_RC_2_MCS(rate) < 32)) {
292eb6f0de0SAdrian Chadd 			int j;
293eb6f0de0SAdrian Chadd 			if (rc[i].flags & ATH_RC_CW40_FLAG) {
294eb6f0de0SAdrian Chadd 				if (rc[i].flags & ATH_RC_SGI_FLAG)
295eb6f0de0SAdrian Chadd 					j = MCS_HT40_SGI;
296eb6f0de0SAdrian Chadd 				else
297eb6f0de0SAdrian Chadd 					j = MCS_HT40;
298eb6f0de0SAdrian Chadd 			} else {
299eb6f0de0SAdrian Chadd 				if (rc[i].flags & ATH_RC_SGI_FLAG)
300eb6f0de0SAdrian Chadd 					j = MCS_HT20_SGI;
301eb6f0de0SAdrian Chadd 				else
302eb6f0de0SAdrian Chadd 					j = MCS_HT20;
303eb6f0de0SAdrian Chadd 			}
304eb6f0de0SAdrian Chadd 			rc[i].max4msframelen =
305eb6f0de0SAdrian Chadd 			    ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)];
306eb6f0de0SAdrian Chadd 		} else
307eb6f0de0SAdrian Chadd 			rc[i].max4msframelen = 0;
308eb6f0de0SAdrian Chadd 		DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
309eb6f0de0SAdrian Chadd 		    "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n",
310eb6f0de0SAdrian Chadd 		    __func__, i, rate, rc[i].flags, rc[i].max4msframelen);
311eb6f0de0SAdrian Chadd 	}
312eb6f0de0SAdrian Chadd }
313eb6f0de0SAdrian Chadd 
314eb6f0de0SAdrian Chadd /*
315eb6f0de0SAdrian Chadd  * Return the number of delimiters to be added to
316eb6f0de0SAdrian Chadd  * meet the minimum required mpdudensity.
317eb6f0de0SAdrian Chadd  *
318eb6f0de0SAdrian Chadd  * Caller should make sure that the rate is HT.
319eb6f0de0SAdrian Chadd  *
320eb6f0de0SAdrian Chadd  * TODO: is this delimiter calculation supposed to be the
321eb6f0de0SAdrian Chadd  * total frame length, the hdr length, the data length (including
322eb6f0de0SAdrian Chadd  * delimiters, padding, CRC, etc) or ?
323eb6f0de0SAdrian Chadd  *
324eb6f0de0SAdrian Chadd  * TODO: this should ensure that the rate control information
325eb6f0de0SAdrian Chadd  * HAS been setup for the first rate.
326eb6f0de0SAdrian Chadd  *
327eb6f0de0SAdrian Chadd  * TODO: ensure this is only called for MCS rates.
328eb6f0de0SAdrian Chadd  *
329eb6f0de0SAdrian Chadd  * TODO: enforce MCS < 31
330eb6f0de0SAdrian Chadd  */
331eb6f0de0SAdrian Chadd static int
332eb6f0de0SAdrian Chadd ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf,
333eb6f0de0SAdrian Chadd     uint16_t pktlen)
334eb6f0de0SAdrian Chadd {
335eb6f0de0SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
336eb6f0de0SAdrian Chadd 	struct ieee80211_node *ni = first_bf->bf_node;
337eb6f0de0SAdrian Chadd 	struct ieee80211vap *vap = ni->ni_vap;
338eb6f0de0SAdrian Chadd 	int ndelim, mindelim = 0;
339eb6f0de0SAdrian Chadd 	int mpdudensity;	 /* in 1/100'th of a microsecond */
340eb6f0de0SAdrian Chadd 	uint8_t rc, rix, flags;
341eb6f0de0SAdrian Chadd 	int width, half_gi;
342eb6f0de0SAdrian Chadd 	uint32_t nsymbits, nsymbols;
343eb6f0de0SAdrian Chadd 	uint16_t minlen;
344eb6f0de0SAdrian Chadd 
345eb6f0de0SAdrian Chadd 	/*
346eb6f0de0SAdrian Chadd 	 * vap->iv_ampdu_density is a value, rather than the actual
347eb6f0de0SAdrian Chadd 	 * density.
348eb6f0de0SAdrian Chadd 	 */
349eb6f0de0SAdrian Chadd 	if (vap->iv_ampdu_density > IEEE80211_HTCAP_MPDUDENSITY_16)
350eb6f0de0SAdrian Chadd 		mpdudensity = 1600;		/* maximum density */
351eb6f0de0SAdrian Chadd 	else
352eb6f0de0SAdrian Chadd 		mpdudensity = ieee80211_mpdudensity_map[vap->iv_ampdu_density];
353eb6f0de0SAdrian Chadd 
354eb6f0de0SAdrian Chadd 	/* Select standard number of delimiters based on frame length */
355eb6f0de0SAdrian Chadd 	ndelim = ATH_AGGR_GET_NDELIM(pktlen);
356eb6f0de0SAdrian Chadd 
357eb6f0de0SAdrian Chadd 	/*
358eb6f0de0SAdrian Chadd 	 * If encryption is enabled, add extra delimiters to let the
359eb6f0de0SAdrian Chadd 	 * crypto hardware catch up. This could be tuned per-MAC and
360eb6f0de0SAdrian Chadd 	 * per-rate, but for now we'll simply assume encryption is
361eb6f0de0SAdrian Chadd 	 * always enabled.
3624a502c33SAdrian Chadd 	 *
3634a502c33SAdrian Chadd 	 * Also note that the Atheros reference driver inserts two
3644a502c33SAdrian Chadd 	 * delimiters by default for pre-AR9380 peers.  This will
3654a502c33SAdrian Chadd 	 * include "that" required delimiter.
366eb6f0de0SAdrian Chadd 	 */
367eb6f0de0SAdrian Chadd 	ndelim += ATH_AGGR_ENCRYPTDELIM;
368eb6f0de0SAdrian Chadd 
36964dbfc6dSAdrian Chadd 	/*
37064dbfc6dSAdrian Chadd 	 * For AR9380, there's a minimum number of delimeters
37164dbfc6dSAdrian Chadd 	 * required when doing RTS.
3724a502c33SAdrian Chadd 	 *
3734a502c33SAdrian Chadd 	 * XXX TODO: this is only needed if (a) RTS/CTS is enabled, and
3744a502c33SAdrian Chadd 	 * XXX (b) this is the first sub-frame in the aggregate.
37564dbfc6dSAdrian Chadd 	 */
37664dbfc6dSAdrian Chadd 	if (sc->sc_use_ent && (sc->sc_ent_cfg & AH_ENT_RTSCTS_DELIM_WAR)
37764dbfc6dSAdrian Chadd 	    && ndelim < AH_FIRST_DESC_NDELIMS)
37864dbfc6dSAdrian Chadd 		ndelim = AH_FIRST_DESC_NDELIMS;
37964dbfc6dSAdrian Chadd 
380a54ecf78SAdrian Chadd 	/*
381a54ecf78SAdrian Chadd 	 * If sc_delim_min_pad is non-zero, enforce it as the minimum
382a54ecf78SAdrian Chadd 	 * pad delimiter count.
383a54ecf78SAdrian Chadd 	 */
384a54ecf78SAdrian Chadd 	if (sc->sc_delim_min_pad != 0)
385a54ecf78SAdrian Chadd 		ndelim = MAX(ndelim, sc->sc_delim_min_pad);
386a54ecf78SAdrian Chadd 
387eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
388eb6f0de0SAdrian Chadd 	    "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n",
389eb6f0de0SAdrian Chadd 	    __func__, pktlen, ndelim, mpdudensity);
390eb6f0de0SAdrian Chadd 
391eb6f0de0SAdrian Chadd 	/*
392eb6f0de0SAdrian Chadd 	 * If the MPDU density is 0, we can return here.
393eb6f0de0SAdrian Chadd 	 * Otherwise, we need to convert the desired mpdudensity
394eb6f0de0SAdrian Chadd 	 * into a byte length, based on the rate in the subframe.
395eb6f0de0SAdrian Chadd 	 */
396eb6f0de0SAdrian Chadd 	if (mpdudensity == 0)
397eb6f0de0SAdrian Chadd 		return ndelim;
398eb6f0de0SAdrian Chadd 
399eb6f0de0SAdrian Chadd 	/*
400eb6f0de0SAdrian Chadd 	 * Convert desired mpdu density from microeconds to bytes based
401eb6f0de0SAdrian Chadd 	 * on highest rate in rate series (i.e. first rate) to determine
402eb6f0de0SAdrian Chadd 	 * required minimum length for subframe. Take into account
403eb6f0de0SAdrian Chadd 	 * whether high rate is 20 or 40Mhz and half or full GI.
404eb6f0de0SAdrian Chadd 	 */
405eb6f0de0SAdrian Chadd 	rix = first_bf->bf_state.bfs_rc[0].rix;
406eb6f0de0SAdrian Chadd 	rc = rt->info[rix].rateCode;
407eb6f0de0SAdrian Chadd 	flags = first_bf->bf_state.bfs_rc[0].flags;
408eb6f0de0SAdrian Chadd 	width = !! (flags & ATH_RC_CW40_FLAG);
409eb6f0de0SAdrian Chadd 	half_gi = !! (flags & ATH_RC_SGI_FLAG);
410eb6f0de0SAdrian Chadd 
411eb6f0de0SAdrian Chadd 	/*
412eb6f0de0SAdrian Chadd 	 * mpdudensity is in 1/100th of a usec, so divide by 100
413eb6f0de0SAdrian Chadd 	 */
414eb6f0de0SAdrian Chadd 	if (half_gi)
415eb6f0de0SAdrian Chadd 		nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
416eb6f0de0SAdrian Chadd 	else
417eb6f0de0SAdrian Chadd 		nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
418eb6f0de0SAdrian Chadd 	nsymbols /= 100;
419eb6f0de0SAdrian Chadd 
420eb6f0de0SAdrian Chadd 	if (nsymbols == 0)
421eb6f0de0SAdrian Chadd 		nsymbols = 1;
422eb6f0de0SAdrian Chadd 
423eb6f0de0SAdrian Chadd 	nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width];
424eb6f0de0SAdrian Chadd 	minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
425eb6f0de0SAdrian Chadd 
426eb6f0de0SAdrian Chadd 	/*
427eb6f0de0SAdrian Chadd 	 * Min length is the minimum frame length for the
428eb6f0de0SAdrian Chadd 	 * required MPDU density.
429eb6f0de0SAdrian Chadd 	 */
430eb6f0de0SAdrian Chadd 	if (pktlen < minlen) {
431eb6f0de0SAdrian Chadd 		mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ;
432eb6f0de0SAdrian Chadd 		ndelim = MAX(mindelim, ndelim);
433eb6f0de0SAdrian Chadd 	}
434eb6f0de0SAdrian Chadd 
435eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
436eb6f0de0SAdrian Chadd 	    "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n",
437eb6f0de0SAdrian Chadd 	    __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim);
438eb6f0de0SAdrian Chadd 
439eb6f0de0SAdrian Chadd 	return ndelim;
440eb6f0de0SAdrian Chadd }
441eb6f0de0SAdrian Chadd 
442eb6f0de0SAdrian Chadd /*
443eb6f0de0SAdrian Chadd  * Fetch the aggregation limit.
444eb6f0de0SAdrian Chadd  *
445eb6f0de0SAdrian Chadd  * It's the lowest of the four rate series 4ms frame length.
446eb6f0de0SAdrian Chadd  */
447eb6f0de0SAdrian Chadd static int
448eb6f0de0SAdrian Chadd ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf)
449eb6f0de0SAdrian Chadd {
4504a502c33SAdrian Chadd 	int amin = ATH_AGGR_MAXSIZE;
451eb6f0de0SAdrian Chadd 	int i;
452eb6f0de0SAdrian Chadd 
4534a502c33SAdrian Chadd 	if (sc->sc_aggr_limit > 0 && sc->sc_aggr_limit < ATH_AGGR_MAXSIZE)
4544a502c33SAdrian Chadd 		amin = sc->sc_aggr_limit;
4554a502c33SAdrian Chadd 
456b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
457eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_rc[i].tries == 0)
458eb6f0de0SAdrian Chadd 			continue;
459eb6f0de0SAdrian Chadd 		amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen);
460eb6f0de0SAdrian Chadd 	}
461eb6f0de0SAdrian Chadd 
462eb6f0de0SAdrian Chadd 	DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: max frame len= %d\n",
463eb6f0de0SAdrian Chadd 	    __func__, amin);
464eb6f0de0SAdrian Chadd 
465eb6f0de0SAdrian Chadd 	return amin;
466eb6f0de0SAdrian Chadd }
4674b44f6f2SAdrian Chadd 
4684b44f6f2SAdrian Chadd /*
4694b44f6f2SAdrian Chadd  * Setup a 11n rate series structure
4704b44f6f2SAdrian Chadd  *
4714b44f6f2SAdrian Chadd  * This should be called for both legacy and MCS rates.
472eb6f0de0SAdrian Chadd  *
473eb6f0de0SAdrian Chadd  * It, along with ath_buf_set_rate, must be called -after- a burst
474eb6f0de0SAdrian Chadd  * or aggregate is setup.
475*56129906SAdrian Chadd  *
476*56129906SAdrian Chadd  * XXX TODO: it should use the rate series information from the
477*56129906SAdrian Chadd  * ath_buf, rather than recalculating it here!
4784b44f6f2SAdrian Chadd  */
4794b44f6f2SAdrian Chadd static void
4804b44f6f2SAdrian Chadd ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
481eb6f0de0SAdrian Chadd     struct ath_buf *bf, HAL_11N_RATE_SERIES *series)
4824b44f6f2SAdrian Chadd {
4834b44f6f2SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
4844b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
4854b44f6f2SAdrian Chadd 	HAL_BOOL shortPreamble = AH_FALSE;
4864b44f6f2SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
4874b44f6f2SAdrian Chadd 	int i;
488eb6f0de0SAdrian Chadd 	int pktlen;
489875a9451SAdrian Chadd 	int flags = bf->bf_state.bfs_txflags;
490eb6f0de0SAdrian Chadd 	struct ath_rc_series *rc = bf->bf_state.bfs_rc;
4914b44f6f2SAdrian Chadd 
4924b44f6f2SAdrian Chadd 	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
4934b44f6f2SAdrian Chadd 	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
4944b44f6f2SAdrian Chadd 		shortPreamble = AH_TRUE;
4954b44f6f2SAdrian Chadd 
496eb6f0de0SAdrian Chadd 	/*
497eb6f0de0SAdrian Chadd 	 * If this is the first frame in an aggregate series,
498eb6f0de0SAdrian Chadd 	 * use the aggregate length.
499eb6f0de0SAdrian Chadd 	 */
500eb6f0de0SAdrian Chadd 	if (bf->bf_state.bfs_aggr)
501eb6f0de0SAdrian Chadd 		pktlen = bf->bf_state.bfs_al;
502eb6f0de0SAdrian Chadd 	else
503eb6f0de0SAdrian Chadd 		pktlen = bf->bf_state.bfs_pktlen;
504eb6f0de0SAdrian Chadd 
505eb6f0de0SAdrian Chadd 	/*
506eb6f0de0SAdrian Chadd 	 * XXX TODO: modify this routine to use the bfs_rc[x].flags
507eb6f0de0SAdrian Chadd 	 * XXX fields.
508eb6f0de0SAdrian Chadd 	 */
5094b44f6f2SAdrian Chadd 	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
510b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM;  i++) {
511146b49d8SAdrian Chadd 		/* Only set flags for actual TX attempts */
512eb6f0de0SAdrian Chadd 		if (rc[i].tries == 0)
513146b49d8SAdrian Chadd 			continue;
514146b49d8SAdrian Chadd 
515eb6f0de0SAdrian Chadd 		series[i].Tries = rc[i].tries;
516146b49d8SAdrian Chadd 
517146b49d8SAdrian Chadd 		/*
5184a502c33SAdrian Chadd 		 * XXX TODO: When the NIC is capable of three stream TX,
5194a502c33SAdrian Chadd 		 * transmit 1/2 stream rates on two streams.
5204a502c33SAdrian Chadd 		 *
5214a502c33SAdrian Chadd 		 * This reduces the power consumption of the NIC and
5224a502c33SAdrian Chadd 		 * keeps it within the PCIe slot power limits.
5234a502c33SAdrian Chadd 		 */
5246322256bSAdrian Chadd 		series[i].ChSel = sc->sc_cur_txchainmask;
525146b49d8SAdrian Chadd 
526*56129906SAdrian Chadd 		/*
527*56129906SAdrian Chadd 		 * Setup rate and TX power cap for this series.
528*56129906SAdrian Chadd 		 */
529*56129906SAdrian Chadd 		series[i].Rate = rt->info[rc[i].rix].rateCode;
530*56129906SAdrian Chadd 		series[i].RateIndex = rc[i].rix;
531*56129906SAdrian Chadd 		series[i].tx_power_cap = 0x3f;	/* XXX for now */
532*56129906SAdrian Chadd 
533*56129906SAdrian Chadd 		/*
534*56129906SAdrian Chadd 		 * Enable RTS/CTS as appropriate.
535*56129906SAdrian Chadd 		 */
5362b5684a8SAdrian Chadd 		if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
5374b44f6f2SAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
538146b49d8SAdrian Chadd 
539*56129906SAdrian Chadd 
540*56129906SAdrian Chadd 		if (IS_HT_RATE(rt->info[rc[i].rix].rateCode)) {
541532f2442SAdrian Chadd 			/*
542532f2442SAdrian Chadd 			 * Transmit 40MHz frames only if the node has negotiated
543532f2442SAdrian Chadd 			 * it rather than whether the node is capable of it or not.
544532f2442SAdrian Chadd 			 * It's subtly different in the hostap case.
545532f2442SAdrian Chadd 			 */
546532f2442SAdrian Chadd 			if (ni->ni_chw == 40)
5474b44f6f2SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_2040;
5486246be6eSAdrian Chadd 
5497842451aSAdrian Chadd 			/*
5506246be6eSAdrian Chadd 			 * Set short-GI only if the node has advertised it
5516246be6eSAdrian Chadd 			 * the channel width is suitable, and we support it.
5526246be6eSAdrian Chadd 			 * We don't currently have a "negotiated" set of bits -
5536246be6eSAdrian Chadd 			 * ni_htcap is what the remote end sends, not what this
5546246be6eSAdrian Chadd 			 * node is capable of.
5557842451aSAdrian Chadd 			 */
5566246be6eSAdrian Chadd 			if (ni->ni_chw == 40 &&
5576246be6eSAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
5586246be6eSAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
5594b44f6f2SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_HALFGI;
5606246be6eSAdrian Chadd 
5616246be6eSAdrian Chadd 			if (ni->ni_chw == 20 &&
5626246be6eSAdrian Chadd 			    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
5636246be6eSAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
5646246be6eSAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_HALFGI;
5654b44f6f2SAdrian Chadd 
5666322256bSAdrian Chadd 			/*
5671a3a5607SAdrian Chadd 			 * If we have STBC TX enabled and the receiver
5681a3a5607SAdrian Chadd 			 * can receive (at least) 1 stream STBC, AND it's
5691a3a5607SAdrian Chadd 			 * MCS 0-7, AND we have at least two chains enabled,
5701a3a5607SAdrian Chadd 			 * enable STBC.
5711a3a5607SAdrian Chadd 			 */
5721a3a5607SAdrian Chadd 			if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
5731a3a5607SAdrian Chadd 			    ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
5741a3a5607SAdrian Chadd 			    (sc->sc_cur_txchainmask > 1) &&
5751a3a5607SAdrian Chadd 			    HT_RC_2_STREAMS(series[i].Rate) == 1) {
5761a3a5607SAdrian Chadd 				series[i].RateFlags |= HAL_RATESERIES_STBC;
5771a3a5607SAdrian Chadd 			}
5786322256bSAdrian Chadd 			/*
5796322256bSAdrian Chadd 			 * XXX TODO: LDPC if it's possible
5806322256bSAdrian Chadd 			 */
581*56129906SAdrian Chadd 		}
5826322256bSAdrian Chadd 
583b25c1f2aSAdrian Chadd 		/*
584b25c1f2aSAdrian Chadd 		 * PktDuration doesn't include slot, ACK, RTS, etc timing -
585b25c1f2aSAdrian Chadd 		 * it's just the packet duration
586b25c1f2aSAdrian Chadd 		 */
5879a97e25eSAdrian Chadd 		if (series[i].Rate & IEEE80211_RATE_MCS) {
5884b44f6f2SAdrian Chadd 			series[i].PktDuration =
5894b44f6f2SAdrian Chadd 			    ath_computedur_ht(pktlen
5909a97e25eSAdrian Chadd 				, series[i].Rate
591fce6d676SAdrian Chadd 				, HT_RC_2_STREAMS(series[i].Rate)
592fce6d676SAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_2040
593f449ab1cSAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
5944b44f6f2SAdrian Chadd 		} else {
5951198947aSAdrian Chadd 			if (shortPreamble)
596eb6f0de0SAdrian Chadd 				series[i].Rate |=
597eb6f0de0SAdrian Chadd 				    rt->info[rc[i].rix].shortPreamble;
5984b44f6f2SAdrian Chadd 			series[i].PktDuration = ath_hal_computetxtime(ah,
599eb6f0de0SAdrian Chadd 			    rt, pktlen, rc[i].rix, shortPreamble);
6004b44f6f2SAdrian Chadd 		}
6014b44f6f2SAdrian Chadd 	}
6024b44f6f2SAdrian Chadd }
6034b44f6f2SAdrian Chadd 
6044b44f6f2SAdrian Chadd #if 0
6054b44f6f2SAdrian Chadd static void
606b25c1f2aSAdrian Chadd ath_rateseries_print(struct ath_softc *sc, HAL_11N_RATE_SERIES *series)
6074b44f6f2SAdrian Chadd {
6084b44f6f2SAdrian Chadd 	int i;
609b25c1f2aSAdrian Chadd 	for (i = 0; i < ATH_RC_NUM; i++) {
610b25c1f2aSAdrian Chadd 		device_printf(sc->sc_dev ,"series %d: rate %x; tries %d; "
61164dbfc6dSAdrian Chadd 		    "pktDuration %d; chSel %d; txpowcap %d, rateFlags %x\n",
6124b44f6f2SAdrian Chadd 		    i,
6134b44f6f2SAdrian Chadd 		    series[i].Rate,
6144b44f6f2SAdrian Chadd 		    series[i].Tries,
6154b44f6f2SAdrian Chadd 		    series[i].PktDuration,
6164b44f6f2SAdrian Chadd 		    series[i].ChSel,
61764dbfc6dSAdrian Chadd 		    series[i].tx_power_cap,
6184b44f6f2SAdrian Chadd 		    series[i].RateFlags);
6194b44f6f2SAdrian Chadd 	}
6204b44f6f2SAdrian Chadd }
6214b44f6f2SAdrian Chadd #endif
6224b44f6f2SAdrian Chadd 
6234b44f6f2SAdrian Chadd /*
6244b44f6f2SAdrian Chadd  * Setup the 11n rate scenario and burst duration for the given TX descriptor
6254b44f6f2SAdrian Chadd  * list.
6264b44f6f2SAdrian Chadd  *
6274b44f6f2SAdrian Chadd  * This isn't useful for sending beacon frames, which has different needs
6284b44f6f2SAdrian Chadd  * wrt what's passed into the rate scenario function.
6294b44f6f2SAdrian Chadd  */
6304b44f6f2SAdrian Chadd void
631eb6f0de0SAdrian Chadd ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni,
632eb6f0de0SAdrian Chadd     struct ath_buf *bf)
6334b44f6f2SAdrian Chadd {
6344b44f6f2SAdrian Chadd 	HAL_11N_RATE_SERIES series[4];
6354b44f6f2SAdrian Chadd 	struct ath_desc *ds = bf->bf_desc;
6364b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
637eb6f0de0SAdrian Chadd 	int is_pspoll = (bf->bf_state.bfs_atype == HAL_PKT_TYPE_PSPOLL);
638eb6f0de0SAdrian Chadd 	int ctsrate = bf->bf_state.bfs_ctsrate;
639875a9451SAdrian Chadd 	int flags = bf->bf_state.bfs_txflags;
6404b44f6f2SAdrian Chadd 
6414b44f6f2SAdrian Chadd 	/* Setup rate scenario */
6424b44f6f2SAdrian Chadd 	memset(&series, 0, sizeof(series));
6434b44f6f2SAdrian Chadd 
644eb6f0de0SAdrian Chadd 	ath_rateseries_setup(sc, ni, bf, series);
6454b44f6f2SAdrian Chadd 
6462b5684a8SAdrian Chadd #if 0
647b25c1f2aSAdrian Chadd 	ath_rateseries_print(sc, series);
6482b5684a8SAdrian Chadd #endif
6492b5684a8SAdrian Chadd 
6504b44f6f2SAdrian Chadd 	/* Set rate scenario */
651b25c1f2aSAdrian Chadd 	/*
652b25c1f2aSAdrian Chadd 	 * Note: Don't allow hardware to override the duration on
653b25c1f2aSAdrian Chadd 	 * ps-poll packets.
654b25c1f2aSAdrian Chadd 	 */
6554b44f6f2SAdrian Chadd 	ath_hal_set11nratescenario(ah, ds,
656bf26df36SAdrian Chadd 	    !is_pspoll,	/* whether to override the duration or not */
6574b44f6f2SAdrian Chadd 	    ctsrate,	/* rts/cts rate */
6584b44f6f2SAdrian Chadd 	    series,	/* 11n rate series */
6594b44f6f2SAdrian Chadd 	    4,		/* number of series */
6604b44f6f2SAdrian Chadd 	    flags);
6614b44f6f2SAdrian Chadd 
6624b44f6f2SAdrian Chadd 	/* Set burst duration */
663eb6f0de0SAdrian Chadd 	/*
664eb6f0de0SAdrian Chadd 	 * This is only required when doing 11n burst, not aggregation
665eb6f0de0SAdrian Chadd 	 * ie, if there's a second frame in a RIFS or A-MPDU burst
666eb6f0de0SAdrian Chadd 	 * w/ >1 A-MPDU frame bursting back to back.
667eb6f0de0SAdrian Chadd 	 * Normal A-MPDU doesn't do bursting -between- aggregates.
668eb6f0de0SAdrian Chadd 	 *
669eb6f0de0SAdrian Chadd 	 * .. and it's highly likely this won't ever be implemented
670eb6f0de0SAdrian Chadd 	 */
6714b44f6f2SAdrian Chadd 	//ath_hal_set11nburstduration(ah, ds, 8192);
6724b44f6f2SAdrian Chadd }
673eb6f0de0SAdrian Chadd 
674eb6f0de0SAdrian Chadd /*
675eb6f0de0SAdrian Chadd  * Form an aggregate packet list.
676eb6f0de0SAdrian Chadd  *
677eb6f0de0SAdrian Chadd  * This function enforces the aggregate restrictions/requirements.
678eb6f0de0SAdrian Chadd  *
679eb6f0de0SAdrian Chadd  * These are:
680eb6f0de0SAdrian Chadd  *
681eb6f0de0SAdrian Chadd  * + The aggregate size maximum (64k for AR9160 and later, 8K for
682eb6f0de0SAdrian Chadd  *   AR5416 when doing RTS frame protection.)
683eb6f0de0SAdrian Chadd  * + Maximum number of sub-frames for an aggregate
684eb6f0de0SAdrian Chadd  * + The aggregate delimiter size, giving MACs time to do whatever is
685eb6f0de0SAdrian Chadd  *   needed before each frame
686eb6f0de0SAdrian Chadd  * + Enforce the BAW limit
687eb6f0de0SAdrian Chadd  *
688eb6f0de0SAdrian Chadd  * Each descriptor queued should have the DMA setup.
689eb6f0de0SAdrian Chadd  * The rate series, descriptor setup, linking, etc is all done
690eb6f0de0SAdrian Chadd  * externally. This routine simply chains them together.
691eb6f0de0SAdrian Chadd  * ath_tx_setds_11n() will take care of configuring the per-
692eb6f0de0SAdrian Chadd  * descriptor setup, and ath_buf_set_rate() will configure the
693eb6f0de0SAdrian Chadd  * rate control.
694eb6f0de0SAdrian Chadd  *
695b25c1f2aSAdrian Chadd  * The TID lock is required for the entirety of this function.
696b25c1f2aSAdrian Chadd  *
697b25c1f2aSAdrian Chadd  * If some code in another thread adds to the head of this
698eb6f0de0SAdrian Chadd  * list, very strange behaviour will occur. Since retransmission is the
699eb6f0de0SAdrian Chadd  * only reason this will occur, and this routine is designed to be called
700eb6f0de0SAdrian Chadd  * from within the scheduler task, it won't ever clash with the completion
701eb6f0de0SAdrian Chadd  * task.
702eb6f0de0SAdrian Chadd  *
703eb6f0de0SAdrian Chadd  * So if you want to call this from an upper layer context (eg, to direct-
704eb6f0de0SAdrian Chadd  * dispatch aggregate frames to the hardware), please keep this in mind.
705eb6f0de0SAdrian Chadd  */
706eb6f0de0SAdrian Chadd ATH_AGGR_STATUS
707b25c1f2aSAdrian Chadd ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an,
708b25c1f2aSAdrian Chadd     struct ath_tid *tid, ath_bufhead *bf_q)
709eb6f0de0SAdrian Chadd {
710a108d2d6SAdrian Chadd 	//struct ieee80211_node *ni = &an->an_node;
711eb6f0de0SAdrian Chadd 	struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL;
712eb6f0de0SAdrian Chadd 	int nframes = 0;
713eb6f0de0SAdrian Chadd 	uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw;
714eb6f0de0SAdrian Chadd 	struct ieee80211_tx_ampdu *tap;
715eb6f0de0SAdrian Chadd 	int status = ATH_AGGR_DONE;
716eb6f0de0SAdrian Chadd 	int prev_frames = 0;	/* XXX for AR5416 burst, not done here */
717eb6f0de0SAdrian Chadd 	int prev_al = 0;	/* XXX also for AR5416 burst */
718eb6f0de0SAdrian Chadd 
719375307d4SAdrian Chadd 	ATH_TX_LOCK_ASSERT(sc);
720eb6f0de0SAdrian Chadd 
721eb6f0de0SAdrian Chadd 	tap = ath_tx_get_tx_tid(an, tid->tid);
722eb6f0de0SAdrian Chadd 	if (tap == NULL) {
723eb6f0de0SAdrian Chadd 		status = ATH_AGGR_ERROR;
724eb6f0de0SAdrian Chadd 		goto finish;
725eb6f0de0SAdrian Chadd 	}
726eb6f0de0SAdrian Chadd 
727eb6f0de0SAdrian Chadd 	h_baw = tap->txa_wnd / 2;
728eb6f0de0SAdrian Chadd 
729eb6f0de0SAdrian Chadd 	for (;;) {
7303e6cc97fSAdrian Chadd 		bf = ATH_TID_FIRST(tid);
731eb6f0de0SAdrian Chadd 		if (bf_first == NULL)
732eb6f0de0SAdrian Chadd 			bf_first = bf;
733eb6f0de0SAdrian Chadd 		if (bf == NULL) {
734eb6f0de0SAdrian Chadd 			status = ATH_AGGR_DONE;
735eb6f0de0SAdrian Chadd 			break;
736eb6f0de0SAdrian Chadd 		} else {
737eb6f0de0SAdrian Chadd 			/*
738eb6f0de0SAdrian Chadd 			 * It's the first frame;
739eb6f0de0SAdrian Chadd 			 * set the aggregation limit based on the
740eb6f0de0SAdrian Chadd 			 * rate control decision that has been made.
741eb6f0de0SAdrian Chadd 			 */
742eb6f0de0SAdrian Chadd 			aggr_limit = ath_get_aggr_limit(sc, bf_first);
743eb6f0de0SAdrian Chadd 		}
744eb6f0de0SAdrian Chadd 
745eb6f0de0SAdrian Chadd 		/* Set this early just so things don't get confused */
746eb6f0de0SAdrian Chadd 		bf->bf_next = NULL;
747eb6f0de0SAdrian Chadd 
748eb6f0de0SAdrian Chadd 		/*
749eb6f0de0SAdrian Chadd 		 * If the frame doesn't have a sequence number that we're
750eb6f0de0SAdrian Chadd 		 * tracking in the BAW (eg NULL QOS data frame), we can't
751eb6f0de0SAdrian Chadd 		 * aggregate it. Stop the aggregation process; the sender
752eb6f0de0SAdrian Chadd 		 * can then TX what's in the list thus far and then
753eb6f0de0SAdrian Chadd 		 * TX the frame individually.
754eb6f0de0SAdrian Chadd 		 */
755eb6f0de0SAdrian Chadd 		if (! bf->bf_state.bfs_dobaw) {
756eb6f0de0SAdrian Chadd 			status = ATH_AGGR_NONAGGR;
757eb6f0de0SAdrian Chadd 			break;
758eb6f0de0SAdrian Chadd 		}
759eb6f0de0SAdrian Chadd 
760eb6f0de0SAdrian Chadd 		/*
761eb6f0de0SAdrian Chadd 		 * If any of the rates are non-HT, this packet
762eb6f0de0SAdrian Chadd 		 * can't be aggregated.
763eb6f0de0SAdrian Chadd 		 * XXX TODO: add a bf_state flag which gets marked
764eb6f0de0SAdrian Chadd 		 * if any active rate is non-HT.
765eb6f0de0SAdrian Chadd 		 */
766eb6f0de0SAdrian Chadd 
767eb6f0de0SAdrian Chadd 		/*
768eb6f0de0SAdrian Chadd 		 * do not exceed aggregation limit
769eb6f0de0SAdrian Chadd 		 */
770eb6f0de0SAdrian Chadd 		al_delta = ATH_AGGR_DELIM_SZ + bf->bf_state.bfs_pktlen;
771eb6f0de0SAdrian Chadd 		if (nframes &&
772eb6f0de0SAdrian Chadd 		    (aggr_limit < (al + bpad + al_delta + prev_al))) {
773eb6f0de0SAdrian Chadd 			status = ATH_AGGR_LIMITED;
774eb6f0de0SAdrian Chadd 			break;
775eb6f0de0SAdrian Chadd 		}
776eb6f0de0SAdrian Chadd 
777eb6f0de0SAdrian Chadd 		/*
778045bc788SAdrian Chadd 		 * If RTS/CTS is set on the first frame, enforce
779045bc788SAdrian Chadd 		 * the RTS aggregate limit.
780045bc788SAdrian Chadd 		 */
781045bc788SAdrian Chadd 		if (bf_first->bf_state.bfs_txflags &
782045bc788SAdrian Chadd 		    (HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA)) {
783045bc788SAdrian Chadd 			if (nframes &&
784045bc788SAdrian Chadd 			   (sc->sc_rts_aggr_limit <
785045bc788SAdrian Chadd 			     (al + bpad + al_delta + prev_al))) {
786045bc788SAdrian Chadd 				status = ATH_AGGR_8K_LIMITED;
787045bc788SAdrian Chadd 				break;
788045bc788SAdrian Chadd 			}
789045bc788SAdrian Chadd 		}
790045bc788SAdrian Chadd 
791045bc788SAdrian Chadd 		/*
792eb6f0de0SAdrian Chadd 		 * Do not exceed subframe limit.
793eb6f0de0SAdrian Chadd 		 */
794eb6f0de0SAdrian Chadd 		if ((nframes + prev_frames) >= MIN((h_baw),
795eb6f0de0SAdrian Chadd 		    IEEE80211_AMPDU_SUBFRAME_DEFAULT)) {
796eb6f0de0SAdrian Chadd 			status = ATH_AGGR_LIMITED;
797eb6f0de0SAdrian Chadd 			break;
798eb6f0de0SAdrian Chadd 		}
799eb6f0de0SAdrian Chadd 
800eb6f0de0SAdrian Chadd 		/*
801045bc788SAdrian Chadd 		 * If the current frame has an RTS/CTS configuration
802781e7eafSAdrian Chadd 		 * that differs from the first frame, override the
803781e7eafSAdrian Chadd 		 * subsequent frame with this config.
804045bc788SAdrian Chadd 		 */
805d03904f1SAdrian Chadd 		if (bf != bf_first) {
806781e7eafSAdrian Chadd 			bf->bf_state.bfs_txflags &=
80776af1a93SAdrian Chadd 			    ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
808781e7eafSAdrian Chadd 			bf->bf_state.bfs_txflags |=
809781e7eafSAdrian Chadd 			    bf_first->bf_state.bfs_txflags &
810781e7eafSAdrian Chadd 			    (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA);
811d03904f1SAdrian Chadd 		}
812045bc788SAdrian Chadd 
813045bc788SAdrian Chadd 		/*
8140b96ef63SAdrian Chadd 		 * If the packet has a sequence number, do not
8150b96ef63SAdrian Chadd 		 * step outside of the block-ack window.
8160b96ef63SAdrian Chadd 		 */
8170b96ef63SAdrian Chadd 		if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd,
8180b96ef63SAdrian Chadd 		    SEQNO(bf->bf_state.bfs_seqno))) {
8190b96ef63SAdrian Chadd 			status = ATH_AGGR_BAW_CLOSED;
8200b96ef63SAdrian Chadd 			break;
8210b96ef63SAdrian Chadd 		}
8220b96ef63SAdrian Chadd 
8230b96ef63SAdrian Chadd 		/*
824eb6f0de0SAdrian Chadd 		 * this packet is part of an aggregate.
825eb6f0de0SAdrian Chadd 		 */
8263e6cc97fSAdrian Chadd 		ATH_TID_REMOVE(tid, bf, bf_list);
827eb6f0de0SAdrian Chadd 
828eb6f0de0SAdrian Chadd 		/* The TID lock is required for the BAW update */
829eb6f0de0SAdrian Chadd 		ath_tx_addto_baw(sc, an, tid, bf);
830eb6f0de0SAdrian Chadd 		bf->bf_state.bfs_addedbaw = 1;
831eb6f0de0SAdrian Chadd 
832eb6f0de0SAdrian Chadd 		/*
833eb6f0de0SAdrian Chadd 		 * XXX enforce ACK for aggregate frames (this needs to be
834eb6f0de0SAdrian Chadd 		 * XXX handled more gracefully?
835eb6f0de0SAdrian Chadd 		 */
836875a9451SAdrian Chadd 		if (bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) {
837eb6f0de0SAdrian Chadd 			device_printf(sc->sc_dev,
838eb6f0de0SAdrian Chadd 			    "%s: HAL_TXDESC_NOACK set for an aggregate frame?\n",
839eb6f0de0SAdrian Chadd 			    __func__);
840875a9451SAdrian Chadd 			bf->bf_state.bfs_txflags &= (~HAL_TXDESC_NOACK);
841eb6f0de0SAdrian Chadd 		}
842eb6f0de0SAdrian Chadd 
843eb6f0de0SAdrian Chadd 		/*
844eb6f0de0SAdrian Chadd 		 * Add the now owned buffer (which isn't
845eb6f0de0SAdrian Chadd 		 * on the software TXQ any longer) to our
846eb6f0de0SAdrian Chadd 		 * aggregate frame list.
847eb6f0de0SAdrian Chadd 		 */
848eb6f0de0SAdrian Chadd 		TAILQ_INSERT_TAIL(bf_q, bf, bf_list);
849eb6f0de0SAdrian Chadd 		nframes ++;
850eb6f0de0SAdrian Chadd 
851eb6f0de0SAdrian Chadd 		/* Completion handler */
852eb6f0de0SAdrian Chadd 		bf->bf_comp = ath_tx_aggr_comp;
853eb6f0de0SAdrian Chadd 
854eb6f0de0SAdrian Chadd 		/*
855eb6f0de0SAdrian Chadd 		 * add padding for previous frame to aggregation length
856eb6f0de0SAdrian Chadd 		 */
857eb6f0de0SAdrian Chadd 		al += bpad + al_delta;
858eb6f0de0SAdrian Chadd 
859eb6f0de0SAdrian Chadd 		/*
860eb6f0de0SAdrian Chadd 		 * Calculate delimiters needed for the current frame
861eb6f0de0SAdrian Chadd 		 */
862eb6f0de0SAdrian Chadd 		bf->bf_state.bfs_ndelim =
863eb6f0de0SAdrian Chadd 		    ath_compute_num_delims(sc, bf_first,
864eb6f0de0SAdrian Chadd 		    bf->bf_state.bfs_pktlen);
865eb6f0de0SAdrian Chadd 
866eb6f0de0SAdrian Chadd 		/*
867eb6f0de0SAdrian Chadd 		 * Calculate the padding needed from this set of delimiters,
868eb6f0de0SAdrian Chadd 		 * used when calculating if the next frame will fit in
869eb6f0de0SAdrian Chadd 		 * the aggregate.
870eb6f0de0SAdrian Chadd 		 */
871eb6f0de0SAdrian Chadd 		bpad = PADBYTES(al_delta) + (bf->bf_state.bfs_ndelim << 2);
872eb6f0de0SAdrian Chadd 
873eb6f0de0SAdrian Chadd 		/*
874eb6f0de0SAdrian Chadd 		 * Chain the buffers together
875eb6f0de0SAdrian Chadd 		 */
876eb6f0de0SAdrian Chadd 		if (bf_prev)
877eb6f0de0SAdrian Chadd 			bf_prev->bf_next = bf;
878eb6f0de0SAdrian Chadd 		bf_prev = bf;
879eb6f0de0SAdrian Chadd 
880eb6f0de0SAdrian Chadd 		/*
881eb6f0de0SAdrian Chadd 		 * XXX TODO: if any sub-frames have RTS/CTS enabled;
882eb6f0de0SAdrian Chadd 		 * enable it for the entire aggregate.
883eb6f0de0SAdrian Chadd 		 */
884eb6f0de0SAdrian Chadd 
885eb6f0de0SAdrian Chadd #if 0
886eb6f0de0SAdrian Chadd 		/*
887eb6f0de0SAdrian Chadd 		 * terminate aggregation on a small packet boundary
888eb6f0de0SAdrian Chadd 		 */
889eb6f0de0SAdrian Chadd 		if (bf->bf_state.bfs_pktlen < ATH_AGGR_MINPLEN) {
890eb6f0de0SAdrian Chadd 			status = ATH_AGGR_SHORTPKT;
891eb6f0de0SAdrian Chadd 			break;
892eb6f0de0SAdrian Chadd 		}
893eb6f0de0SAdrian Chadd #endif
894eb6f0de0SAdrian Chadd 
895eb6f0de0SAdrian Chadd 	}
896eb6f0de0SAdrian Chadd 
897eb6f0de0SAdrian Chadd finish:
898eb6f0de0SAdrian Chadd 	/*
899eb6f0de0SAdrian Chadd 	 * Just in case the list was empty when we tried to
900eb6f0de0SAdrian Chadd 	 * dequeue a packet ..
901eb6f0de0SAdrian Chadd 	 */
902eb6f0de0SAdrian Chadd 	if (bf_first) {
903eb6f0de0SAdrian Chadd 		bf_first->bf_state.bfs_al = al;
904eb6f0de0SAdrian Chadd 		bf_first->bf_state.bfs_nframes = nframes;
905eb6f0de0SAdrian Chadd 	}
906eb6f0de0SAdrian Chadd 	return status;
907eb6f0de0SAdrian Chadd }
908