xref: /freebsd/sys/dev/ath/if_ath_tx_ht.c (revision 6246be6e58d86770e7db34dd8d30cc453a19eab8)
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 
894b44f6f2SAdrian Chadd #include <dev/ath/if_ath_tx_ht.h>
904b44f6f2SAdrian Chadd 
914b44f6f2SAdrian Chadd /*
924b44f6f2SAdrian Chadd  * Setup a 11n rate series structure
934b44f6f2SAdrian Chadd  *
944b44f6f2SAdrian Chadd  * This should be called for both legacy and MCS rates.
954b44f6f2SAdrian Chadd  */
964b44f6f2SAdrian Chadd static void
974b44f6f2SAdrian Chadd ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni,
984b44f6f2SAdrian Chadd     HAL_11N_RATE_SERIES *series, unsigned int pktlen, uint8_t *rix,
992b5684a8SAdrian Chadd     uint8_t *try, int flags)
1004b44f6f2SAdrian Chadd {
101fce6d676SAdrian Chadd #define	HT_RC_2_STREAMS(_rc)	((((_rc) & 0x78) >> 3) + 1)
1024b44f6f2SAdrian Chadd 	struct ieee80211com *ic = ni->ni_ic;
1034b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
1044b44f6f2SAdrian Chadd 	HAL_BOOL shortPreamble = AH_FALSE;
1054b44f6f2SAdrian Chadd 	const HAL_RATE_TABLE *rt = sc->sc_currates;
1064b44f6f2SAdrian Chadd 	int i;
1074b44f6f2SAdrian Chadd 
1084b44f6f2SAdrian Chadd 	if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) &&
1094b44f6f2SAdrian Chadd 	    (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE))
1104b44f6f2SAdrian Chadd 		shortPreamble = AH_TRUE;
1114b44f6f2SAdrian Chadd 
1124b44f6f2SAdrian Chadd 	memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4);
1134b44f6f2SAdrian Chadd 	for (i = 0; i < 4;  i++) {
114146b49d8SAdrian Chadd 		/* Only set flags for actual TX attempts */
115146b49d8SAdrian Chadd 		if (try[i] == 0)
116146b49d8SAdrian Chadd 			continue;
117146b49d8SAdrian Chadd 
1184b44f6f2SAdrian Chadd 		series[i].Tries = try[i];
119146b49d8SAdrian Chadd 
120146b49d8SAdrian Chadd 		/*
121146b49d8SAdrian Chadd 		 * XXX this isn't strictly correct - sc_txchainmask
122146b49d8SAdrian Chadd 		 * XXX isn't the currently active chainmask;
123146b49d8SAdrian Chadd 		 * XXX it's the interface chainmask at startup.
124146b49d8SAdrian Chadd 		 * XXX It's overridden in the HAL rate scenario function
125146b49d8SAdrian Chadd 		 * XXX for now.
126146b49d8SAdrian Chadd 		 */
1274b44f6f2SAdrian Chadd 		series[i].ChSel = sc->sc_txchainmask;
128146b49d8SAdrian Chadd 
1292b5684a8SAdrian Chadd 		if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA))
1304b44f6f2SAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_RTS_CTS;
131146b49d8SAdrian Chadd 
132532f2442SAdrian Chadd 		/*
133532f2442SAdrian Chadd 		 * Transmit 40MHz frames only if the node has negotiated
134532f2442SAdrian Chadd 		 * it rather than whether the node is capable of it or not.
135532f2442SAdrian Chadd 	 	 * It's subtly different in the hostap case.
136532f2442SAdrian Chadd 	 	 */
137532f2442SAdrian Chadd 		if (ni->ni_chw == 40)
1384b44f6f2SAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_2040;
139*6246be6eSAdrian Chadd 
1407842451aSAdrian Chadd 		/*
141*6246be6eSAdrian Chadd 		 * Set short-GI only if the node has advertised it
142*6246be6eSAdrian Chadd 		 * the channel width is suitable, and we support it.
143*6246be6eSAdrian Chadd 		 * We don't currently have a "negotiated" set of bits -
144*6246be6eSAdrian Chadd 		 * ni_htcap is what the remote end sends, not what this
145*6246be6eSAdrian Chadd 		 * node is capable of.
1467842451aSAdrian Chadd 		 */
147*6246be6eSAdrian Chadd 		if (ni->ni_chw == 40 &&
148*6246be6eSAdrian Chadd 		    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 &&
149*6246be6eSAdrian Chadd 		    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40)
1504b44f6f2SAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
151*6246be6eSAdrian Chadd 
152*6246be6eSAdrian Chadd 		if (ni->ni_chw == 20 &&
153*6246be6eSAdrian Chadd 		    ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 &&
154*6246be6eSAdrian Chadd 		    ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20)
155*6246be6eSAdrian Chadd 			series[i].RateFlags |= HAL_RATESERIES_HALFGI;
1564b44f6f2SAdrian Chadd 
1579a97e25eSAdrian Chadd 		series[i].Rate = rt->info[rix[i]].rateCode;
1584b44f6f2SAdrian Chadd 
1594b44f6f2SAdrian Chadd 		/* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */
1609a97e25eSAdrian Chadd 		if (series[i].Rate & IEEE80211_RATE_MCS) {
1614b44f6f2SAdrian Chadd 			series[i].PktDuration =
1624b44f6f2SAdrian Chadd 			    ath_computedur_ht(pktlen
1639a97e25eSAdrian Chadd 				, series[i].Rate
164fce6d676SAdrian Chadd 				, HT_RC_2_STREAMS(series[i].Rate)
165fce6d676SAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_2040
166f449ab1cSAdrian Chadd 				, series[i].RateFlags & HAL_RATESERIES_HALFGI);
1674b44f6f2SAdrian Chadd 		} else {
1681198947aSAdrian Chadd 			if (shortPreamble)
1691198947aSAdrian Chadd 				series[i].Rate |= rt->info[rix[i]].shortPreamble;
1704b44f6f2SAdrian Chadd 			series[i].PktDuration = ath_hal_computetxtime(ah,
1714b44f6f2SAdrian Chadd 			    rt, pktlen, rix[i], shortPreamble);
1724b44f6f2SAdrian Chadd 		}
1734b44f6f2SAdrian Chadd 	}
174fce6d676SAdrian Chadd #undef	HT_RC_2_STREAMS
1754b44f6f2SAdrian Chadd }
1764b44f6f2SAdrian Chadd 
1774b44f6f2SAdrian Chadd #if 0
1784b44f6f2SAdrian Chadd static void
1794b44f6f2SAdrian Chadd ath_rateseries_print(HAL_11N_RATE_SERIES *series)
1804b44f6f2SAdrian Chadd {
1814b44f6f2SAdrian Chadd 	int i;
1824b44f6f2SAdrian Chadd 	for (i = 0; i < 4; i++) {
1834b44f6f2SAdrian Chadd 		printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n",
1844b44f6f2SAdrian Chadd 		    i,
1854b44f6f2SAdrian Chadd 		    series[i].Rate,
1864b44f6f2SAdrian Chadd 		    series[i].Tries,
1874b44f6f2SAdrian Chadd 		    series[i].PktDuration,
1884b44f6f2SAdrian Chadd 		    series[i].ChSel,
1894b44f6f2SAdrian Chadd 		    series[i].RateFlags);
1904b44f6f2SAdrian Chadd 	}
1914b44f6f2SAdrian Chadd }
1924b44f6f2SAdrian Chadd #endif
1934b44f6f2SAdrian Chadd 
1944b44f6f2SAdrian Chadd /*
1954b44f6f2SAdrian Chadd  * Setup the 11n rate scenario and burst duration for the given TX descriptor
1964b44f6f2SAdrian Chadd  * list.
1974b44f6f2SAdrian Chadd  *
1984b44f6f2SAdrian Chadd  * This isn't useful for sending beacon frames, which has different needs
1994b44f6f2SAdrian Chadd  * wrt what's passed into the rate scenario function.
2004b44f6f2SAdrian Chadd  */
2014b44f6f2SAdrian Chadd 
2024b44f6f2SAdrian Chadd void
2034b44f6f2SAdrian Chadd ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf,
204bf26df36SAdrian Chadd     int pktlen, int flags, uint8_t ctsrate, int is_pspoll, uint8_t *rix, uint8_t *try)
2054b44f6f2SAdrian Chadd {
2064b44f6f2SAdrian Chadd 	HAL_11N_RATE_SERIES series[4];
2074b44f6f2SAdrian Chadd 	struct ath_desc *ds = bf->bf_desc;
2084b44f6f2SAdrian Chadd 	struct ath_desc *lastds = NULL;
2094b44f6f2SAdrian Chadd 	struct ath_hal *ah = sc->sc_ah;
2104b44f6f2SAdrian Chadd 
2114b44f6f2SAdrian Chadd 	/* Setup rate scenario */
2124b44f6f2SAdrian Chadd 	memset(&series, 0, sizeof(series));
2134b44f6f2SAdrian Chadd 
2142b5684a8SAdrian Chadd 	ath_rateseries_setup(sc, ni, series, pktlen, rix, try, flags);
2154b44f6f2SAdrian Chadd 
2164b44f6f2SAdrian Chadd 	/* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */
2174b44f6f2SAdrian Chadd 
2184b44f6f2SAdrian Chadd 	/* Enforce RTS and CTS are mutually exclusive */
2194b44f6f2SAdrian Chadd 
2204b44f6f2SAdrian Chadd 	/* Get a pointer to the last tx descriptor in the list */
2214b44f6f2SAdrian Chadd 	lastds = &bf->bf_desc[bf->bf_nseg - 1];
2224b44f6f2SAdrian Chadd 
2232b5684a8SAdrian Chadd #if 0
2242b5684a8SAdrian Chadd 	printf("pktlen: %d; flags 0x%x\n", pktlen, flags);
2252b5684a8SAdrian Chadd 	ath_rateseries_print(series);
2262b5684a8SAdrian Chadd #endif
2272b5684a8SAdrian Chadd 
2284b44f6f2SAdrian Chadd 	/* Set rate scenario */
2294b44f6f2SAdrian Chadd 	ath_hal_set11nratescenario(ah, ds,
230bf26df36SAdrian Chadd 	    !is_pspoll,	/* whether to override the duration or not */
231bf26df36SAdrian Chadd 			/* don't allow hardware to override the duration on ps-poll packets */
2324b44f6f2SAdrian Chadd 	    ctsrate,	/* rts/cts rate */
2334b44f6f2SAdrian Chadd 	    series,	/* 11n rate series */
2344b44f6f2SAdrian Chadd 	    4,		/* number of series */
2354b44f6f2SAdrian Chadd 	    flags);
2364b44f6f2SAdrian Chadd 
2374b44f6f2SAdrian Chadd 	/* Setup the last descriptor in the chain */
2384b44f6f2SAdrian Chadd 	ath_hal_setuplasttxdesc(ah, lastds, ds);
2394b44f6f2SAdrian Chadd 
2404b44f6f2SAdrian Chadd 	/* Set burst duration */
2414b44f6f2SAdrian Chadd 	/* This should only be done if aggregate protection is enabled */
2424b44f6f2SAdrian Chadd 	//ath_hal_set11nburstduration(ah, ds, 8192);
2434b44f6f2SAdrian Chadd }
244