if_ath_tx_ht.c revision 219985
1278307Srpaulo/*-
2278307Srpaulo * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd.
3278307Srpaulo * All rights reserved.
4278307Srpaulo *
5278307Srpaulo * Redistribution and use in source and binary forms, with or without
6278307Srpaulo * modification, are permitted provided that the following conditions
7278307Srpaulo * are met:
8278307Srpaulo * 1. Redistributions of source code must retain the above copyright
9278307Srpaulo *    notice, this list of conditions and the following disclaimer,
10278307Srpaulo *    without modification.
11278307Srpaulo * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12278307Srpaulo *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13278307Srpaulo *    redistribution must be conditioned upon including a substantially
14278307Srpaulo *    similar Disclaimer requirement for further binary redistribution.
15278307Srpaulo *
16278307Srpaulo * NO WARRANTY
17278307Srpaulo * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18278307Srpaulo * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19278307Srpaulo * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20278307Srpaulo * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21278307Srpaulo * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22278307Srpaulo * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23278307Srpaulo * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24278307Srpaulo * 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: head/sys/dev/ath/if_ath_tx_ht.c 219985 2011-03-25 10:55:25Z adrian $");
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 */
96static void
97ath_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#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;
106	int i;
107
108	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
109	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
110		shortPreamble = AH_TRUE;
111
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 */
115		if (try[i] == 0)
116			continue;
117
118		series[i].Tries = try[i];
119
120		/*
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
125		 * XXX for now.
126		 */
127		series[i].ChSel = sc->sc_txchainmask;
128
129		if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
130			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
131
132		/*
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.
136	 	 */
137		if (ni->ni_chw == 40)
138			series[i].RateFlags |= HAL_RATESERIES_2040;
139#if 0
140		/*
141		 * The hardware only supports short-gi in 40mhz mode -
142		 * if later hardware supports it in 20mhz mode, be sure
143		 * to add the relevant check here.
144		 */
145		if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
146			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
147#endif
148
149		series[i].Rate = rt->info[rix[i]].rateCode;
150
151		/* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */
152		if (series[i].Rate & IEEE80211_RATE_MCS) {
153			series[i].PktDuration =
154			    ath_computedur_ht(pktlen
155				, series[i].Rate
156				, HT_RC_2_STREAMS(series[i].Rate)
157				, series[i].RateFlags & HAL_RATESERIES_2040
158				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
159		} else {
160			if (shortPreamble)
161				series[i].Rate |= rt->info[rix[i]].shortPreamble;
162			series[i].PktDuration = ath_hal_computetxtime(ah,
163			    rt, pktlen, rix[i], shortPreamble);
164		}
165	}
166#undef	HT_RC_2_STREAMS
167}
168
169#if 0
170static void
171ath_rateseries_print(HAL_11N_RATE_SERIES *series)
172{
173	int i;
174	for (i = 0; i < 4; i++) {
175		printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n",
176		    i,
177		    series[i].Rate,
178		    series[i].Tries,
179		    series[i].PktDuration,
180		    series[i].ChSel,
181		    series[i].RateFlags);
182	}
183}
184#endif
185
186/*
187 * Setup the 11n rate scenario and burst duration for the given TX descriptor
188 * list.
189 *
190 * This isn't useful for sending beacon frames, which has different needs
191 * wrt what's passed into the rate scenario function.
192 */
193
194void
195ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
196    int pktlen, int flags, uint8_t ctsrate, int is_pspoll, uint8_t *rix, uint8_t *try)
197{
198	HAL_11N_RATE_SERIES series[4];
199	struct ath_desc *ds = bf->bf_desc;
200	struct ath_desc *lastds = NULL;
201	struct ath_hal *ah = sc->sc_ah;
202
203	/* Setup rate scenario */
204	memset(&series, 0, sizeof(series));
205
206	ath_rateseries_setup(sc, ni, series, pktlen, rix, try, flags);
207
208	/* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */
209
210	/* Enforce RTS and CTS are mutually exclusive */
211
212	/* Get a pointer to the last tx descriptor in the list */
213	lastds = &bf->bf_desc[bf->bf_nseg - 1];
214
215#if 0
216	printf("pktlen: %d; flags 0x%x\n", pktlen, flags);
217	ath_rateseries_print(series);
218#endif
219
220	/* Set rate scenario */
221	ath_hal_set11nratescenario(ah, ds,
222	    !is_pspoll,	/* whether to override the duration or not */
223			/* don't allow hardware to override the duration on ps-poll packets */
224	    ctsrate,	/* rts/cts rate */
225	    series,	/* 11n rate series */
226	    4,		/* number of series */
227	    flags);
228
229	/* Setup the last descriptor in the chain */
230	ath_hal_setuplasttxdesc(ah, lastds, ds);
231
232	/* Set burst duration */
233	/* This should only be done if aggregate protection is enabled */
234	//ath_hal_set11nburstduration(ah, ds, 8192);
235}
236