xref: /freebsd/sys/dev/ath/if_ath_tx_ht.c (revision 5dcd9c10612684d1c823670cbb5b4715028784e7)
1 /*-
2  * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 #include "opt_inet.h"
34 #include "opt_ath.h"
35 #include "opt_wlan.h"
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/sysctl.h>
40 #include <sys/mbuf.h>
41 #include <sys/malloc.h>
42 #include <sys/lock.h>
43 #include <sys/mutex.h>
44 #include <sys/kernel.h>
45 #include <sys/socket.h>
46 #include <sys/sockio.h>
47 #include <sys/errno.h>
48 #include <sys/callout.h>
49 #include <sys/bus.h>
50 #include <sys/endian.h>
51 #include <sys/kthread.h>
52 #include <sys/taskqueue.h>
53 #include <sys/priv.h>
54 
55 #include <machine/bus.h>
56 
57 #include <net/if.h>
58 #include <net/if_dl.h>
59 #include <net/if_media.h>
60 #include <net/if_types.h>
61 #include <net/if_arp.h>
62 #include <net/ethernet.h>
63 #include <net/if_llc.h>
64 
65 #include <net80211/ieee80211_var.h>
66 #include <net80211/ieee80211_regdomain.h>
67 #ifdef IEEE80211_SUPPORT_SUPERG
68 #include <net80211/ieee80211_superg.h>
69 #endif
70 #ifdef IEEE80211_SUPPORT_TDMA
71 #include <net80211/ieee80211_tdma.h>
72 #endif
73 
74 #include <net/bpf.h>
75 
76 #ifdef INET
77 #include <netinet/in.h>
78 #include <netinet/if_ether.h>
79 #endif
80 
81 #include <dev/ath/if_athvar.h>
82 #include <dev/ath/ath_hal/ah_devid.h>		/* XXX for softled */
83 #include <dev/ath/ath_hal/ah_diagcodes.h>
84 
85 #ifdef ATH_TX99_DIAG
86 #include <dev/ath/ath_tx99/ath_tx99.h>
87 #endif
88 
89 #include <dev/ath/if_ath_tx_ht.h>
90 
91 /*
92  * Setup a 11n rate series structure
93  *
94  * This should be called for both legacy and MCS rates.
95  */
96 static void
97 ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
98     HAL_11N_RATE_SERIES *series, unsigned int pktlen, uint8_t *rix,
99     uint8_t *try, int flags)
100 {
101 	struct ieee80211com *ic = ni->ni_ic;
102 	struct ath_hal *ah = sc->sc_ah;
103 	HAL_BOOL shortPreamble = AH_FALSE;
104 	const HAL_RATE_TABLE *rt = sc->sc_currates;
105 	int i;
106 
107 	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
108 	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
109 		shortPreamble = AH_TRUE;
110 
111 	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
112 	for (i = 0; i < 4;  i++) {
113 		/* Only set flags for actual TX attempts */
114 		if (try[i] == 0)
115 			continue;
116 
117 		series[i].Tries = try[i];
118 
119 		/*
120 		 * XXX this isn't strictly correct - sc_txchainmask
121 		 * XXX isn't the currently active chainmask;
122 		 * XXX it's the interface chainmask at startup.
123 		 * XXX It's overridden in the HAL rate scenario function
124 		 * XXX for now.
125 		 */
126 		series[i].ChSel = sc->sc_txchainmask;
127 
128 		if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
129 			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
130 
131 		if (ni->ni_htcap & IEEE80211_HTCAP_CHWIDTH40)
132 			series[i].RateFlags |= HAL_RATESERIES_2040;
133 
134 		/*
135 		 * The hardware only supports short-gi in 40mhz mode -
136 		 * if later hardware supports it in 20mhz mode, be sure
137 		 * to add the relevant check here.
138 		 */
139 		if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
140 			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
141 
142 		series[i].Rate = rt->info[rix[i]].rateCode;
143 		/* the short preamble field is only applicable for non-MCS rates */
144 		if (shortPreamble && ! (series[i].Rate & IEEE80211_RATE_MCS))
145 			series[i].Rate |= rt->info[rix[i]].shortPreamble;
146 
147 		/* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */
148 		if (series[i].Rate & IEEE80211_RATE_MCS) {
149 			series[i].PktDuration =
150 			    ath_computedur_ht(pktlen
151 				, series[i].Rate
152 				, ic->ic_txstream
153 				, (ni->ni_htcap & IEEE80211_HTCAP_CHWIDTH40)
154 				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
155 		} else {
156 			series[i].PktDuration = ath_hal_computetxtime(ah,
157 			    rt, pktlen, rix[i], shortPreamble);
158 		}
159 	}
160 }
161 
162 #if 0
163 static void
164 ath_rateseries_print(HAL_11N_RATE_SERIES *series)
165 {
166 	int i;
167 	for (i = 0; i < 4; i++) {
168 		printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n",
169 		    i,
170 		    series[i].Rate,
171 		    series[i].Tries,
172 		    series[i].PktDuration,
173 		    series[i].ChSel,
174 		    series[i].RateFlags);
175 	}
176 }
177 #endif
178 
179 /*
180  * Setup the 11n rate scenario and burst duration for the given TX descriptor
181  * list.
182  *
183  * This isn't useful for sending beacon frames, which has different needs
184  * wrt what's passed into the rate scenario function.
185  */
186 
187 void
188 ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
189     int pktlen, int flags, uint8_t ctsrate, int is_pspoll, uint8_t *rix, uint8_t *try)
190 {
191 	HAL_11N_RATE_SERIES series[4];
192 	struct ath_desc *ds = bf->bf_desc;
193 	struct ath_desc *lastds = NULL;
194 	struct ath_hal *ah = sc->sc_ah;
195 
196 	/* Setup rate scenario */
197 	memset(&series, 0, sizeof(series));
198 
199 	ath_rateseries_setup(sc, ni, series, pktlen, rix, try, flags);
200 
201 	/* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */
202 
203 	/* Enforce RTS and CTS are mutually exclusive */
204 
205 	/* Get a pointer to the last tx descriptor in the list */
206 	lastds = &bf->bf_desc[bf->bf_nseg - 1];
207 
208 #if 0
209 	printf("pktlen: %d; flags 0x%x\n", pktlen, flags);
210 	ath_rateseries_print(series);
211 #endif
212 
213 	/* Set rate scenario */
214 	ath_hal_set11nratescenario(ah, ds,
215 	    !is_pspoll,	/* whether to override the duration or not */
216 			/* don't allow hardware to override the duration on ps-poll packets */
217 	    ctsrate,	/* rts/cts rate */
218 	    series,	/* 11n rate series */
219 	    4,		/* number of series */
220 	    flags);
221 
222 	/* Setup the last descriptor in the chain */
223 	ath_hal_setuplasttxdesc(ah, lastds, ds);
224 
225 	/* Set burst duration */
226 	/* This should only be done if aggregate protection is enabled */
227 	//ath_hal_set11nburstduration(ah, ds, 8192);
228 }
229