2 * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/sysctl.h>
41 #include <sys/malloc.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>
50 #include <sys/endian.h>
51 #include <sys/kthread.h>
52 #include <sys/taskqueue.h>
55 #include <machine/bus.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>
65 #include <net80211/ieee80211_var.h>
66 #include <net80211/ieee80211_regdomain.h>
67 #ifdef IEEE80211_SUPPORT_SUPERG
68 #include <net80211/ieee80211_superg.h>
70 #ifdef IEEE80211_SUPPORT_TDMA
71 #include <net80211/ieee80211_tdma.h>
77 #include <netinet/in.h>
78 #include <netinet/if_ether.h>
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>
86 #include <dev/ath/ath_tx99/ath_tx99.h>
89 #include <dev/ath/if_ath_tx_ht.h>
92 * Setup a 11n rate series structure
94 * This should be called for both legacy and MCS rates.
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)
101 #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1)
102 struct ieee80211com *ic = ni->ni_ic;
103 struct ath_hal *ah = sc->sc_ah;
104 HAL_BOOL shortPreamble = AH_FALSE;
105 const HAL_RATE_TABLE *rt = sc->sc_currates;
108 if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
109 (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
110 shortPreamble = AH_TRUE;
112 memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
113 for (i = 0; i < 4; i++) {
114 /* Only set flags for actual TX attempts */
118 series[i].Tries = try[i];
121 * XXX this isn't strictly correct - sc_txchainmask
122 * XXX isn't the currently active chainmask;
123 * XXX it's the interface chainmask at startup.
124 * XXX It's overridden in the HAL rate scenario function
127 series[i].ChSel = sc->sc_txchainmask;
129 if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
130 series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
133 * Transmit 40MHz frames only if the node has negotiated
134 * it rather than whether the node is capable of it or not.
135 * It's subtly different in the hostap case.
137 if (ni->ni_chw == 40)
138 series[i].RateFlags |= HAL_RATESERIES_2040;
141 * Set short-GI only if the node has advertised it
142 * the channel width is suitable, and we support it.
143 * We don't currently have a "negotiated" set of bits -
144 * ni_htcap is what the remote end sends, not what this
145 * node is capable of.
147 if (ni->ni_chw == 40 &&
148 ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
149 ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
150 series[i].RateFlags |= HAL_RATESERIES_HALFGI;
152 if (ni->ni_chw == 20 &&
153 ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
154 ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
155 series[i].RateFlags |= HAL_RATESERIES_HALFGI;
157 series[i].Rate = rt->info[rix[i]].rateCode;
159 /* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */
160 if (series[i].Rate & IEEE80211_RATE_MCS) {
161 series[i].PktDuration =
162 ath_computedur_ht(pktlen
164 , HT_RC_2_STREAMS(series[i].Rate)
165 , series[i].RateFlags & HAL_RATESERIES_2040
166 , series[i].RateFlags & HAL_RATESERIES_HALFGI);
169 series[i].Rate |= rt->info[rix[i]].shortPreamble;
170 series[i].PktDuration = ath_hal_computetxtime(ah,
171 rt, pktlen, rix[i], shortPreamble);
174 #undef HT_RC_2_STREAMS
179 ath_rateseries_print(HAL_11N_RATE_SERIES *series)
182 for (i = 0; i < 4; i++) {
183 printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n",
187 series[i].PktDuration,
189 series[i].RateFlags);
195 * Setup the 11n rate scenario and burst duration for the given TX descriptor
198 * This isn't useful for sending beacon frames, which has different needs
199 * wrt what's passed into the rate scenario function.
203 ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
204 int pktlen, int flags, uint8_t ctsrate, int is_pspoll, uint8_t *rix, uint8_t *try)
206 HAL_11N_RATE_SERIES series[4];
207 struct ath_desc *ds = bf->bf_desc;
208 struct ath_desc *lastds = NULL;
209 struct ath_hal *ah = sc->sc_ah;
211 /* Setup rate scenario */
212 memset(&series, 0, sizeof(series));
214 ath_rateseries_setup(sc, ni, series, pktlen, rix, try, flags);
216 /* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */
218 /* Enforce RTS and CTS are mutually exclusive */
220 /* Get a pointer to the last tx descriptor in the list */
221 lastds = &bf->bf_desc[bf->bf_nseg - 1];
224 printf("pktlen: %d; flags 0x%x\n", pktlen, flags);
225 ath_rateseries_print(series);
228 /* Set rate scenario */
229 ath_hal_set11nratescenario(ah, ds,
230 !is_pspoll, /* whether to override the duration or not */
231 /* don't allow hardware to override the duration on ps-poll packets */
232 ctsrate, /* rts/cts rate */
233 series, /* 11n rate series */
234 4, /* number of series */
237 /* Setup the last descriptor in the chain */
238 ath_hal_setuplasttxdesc(ah, lastds, ds);
240 /* Set burst duration */
241 /* This should only be done if aggregate protection is enabled */
242 //ath_hal_set11nburstduration(ah, ds, 8192);