if_ath_tx_ht.c revision 219870
1218159Sadrian/*- 2218159Sadrian * Copyright (c) 2011 Adrian Chadd, Xenion Pty Ltd. 3218159Sadrian * All rights reserved. 4218159Sadrian * 5218159Sadrian * Redistribution and use in source and binary forms, with or without 6218159Sadrian * modification, are permitted provided that the following conditions 7218159Sadrian * are met: 8218159Sadrian * 1. Redistributions of source code must retain the above copyright 9218159Sadrian * notice, this list of conditions and the following disclaimer, 10218159Sadrian * without modification. 11218159Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12218159Sadrian * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13218159Sadrian * redistribution must be conditioned upon including a substantially 14218159Sadrian * similar Disclaimer requirement for further binary redistribution. 15218159Sadrian * 16218159Sadrian * NO WARRANTY 17218159Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18218159Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19218159Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20218159Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21218159Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22218159Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23218159Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24218159Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25218159Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26218159Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27218159Sadrian * THE POSSIBILITY OF SUCH DAMAGES. 28218159Sadrian */ 29218159Sadrian 30218159Sadrian#include <sys/cdefs.h> 31218159Sadrian__FBSDID("$FreeBSD: head/sys/dev/ath/if_ath_tx_ht.c 219870 2011-03-22 13:39:00Z adrian $"); 32218159Sadrian 33218159Sadrian#include "opt_inet.h" 34218159Sadrian#include "opt_ath.h" 35218159Sadrian#include "opt_wlan.h" 36218159Sadrian 37218159Sadrian#include <sys/param.h> 38218159Sadrian#include <sys/systm.h> 39218159Sadrian#include <sys/sysctl.h> 40218159Sadrian#include <sys/mbuf.h> 41218159Sadrian#include <sys/malloc.h> 42218159Sadrian#include <sys/lock.h> 43218159Sadrian#include <sys/mutex.h> 44218159Sadrian#include <sys/kernel.h> 45218159Sadrian#include <sys/socket.h> 46218159Sadrian#include <sys/sockio.h> 47218159Sadrian#include <sys/errno.h> 48218159Sadrian#include <sys/callout.h> 49218159Sadrian#include <sys/bus.h> 50218159Sadrian#include <sys/endian.h> 51218159Sadrian#include <sys/kthread.h> 52218159Sadrian#include <sys/taskqueue.h> 53218159Sadrian#include <sys/priv.h> 54218159Sadrian 55218159Sadrian#include <machine/bus.h> 56218159Sadrian 57218159Sadrian#include <net/if.h> 58218159Sadrian#include <net/if_dl.h> 59218159Sadrian#include <net/if_media.h> 60218159Sadrian#include <net/if_types.h> 61218159Sadrian#include <net/if_arp.h> 62218159Sadrian#include <net/ethernet.h> 63218159Sadrian#include <net/if_llc.h> 64218159Sadrian 65218159Sadrian#include <net80211/ieee80211_var.h> 66218159Sadrian#include <net80211/ieee80211_regdomain.h> 67218159Sadrian#ifdef IEEE80211_SUPPORT_SUPERG 68218159Sadrian#include <net80211/ieee80211_superg.h> 69218159Sadrian#endif 70218159Sadrian#ifdef IEEE80211_SUPPORT_TDMA 71218159Sadrian#include <net80211/ieee80211_tdma.h> 72218159Sadrian#endif 73218159Sadrian 74218159Sadrian#include <net/bpf.h> 75218159Sadrian 76218159Sadrian#ifdef INET 77218159Sadrian#include <netinet/in.h> 78218159Sadrian#include <netinet/if_ether.h> 79218159Sadrian#endif 80218159Sadrian 81218159Sadrian#include <dev/ath/if_athvar.h> 82218159Sadrian#include <dev/ath/ath_hal/ah_devid.h> /* XXX for softled */ 83218159Sadrian#include <dev/ath/ath_hal/ah_diagcodes.h> 84218159Sadrian 85218159Sadrian#ifdef ATH_TX99_DIAG 86218159Sadrian#include <dev/ath/ath_tx99/ath_tx99.h> 87218159Sadrian#endif 88218159Sadrian 89218159Sadrian#include <dev/ath/if_ath_tx_ht.h> 90218159Sadrian 91218159Sadrian/* 92218159Sadrian * Setup a 11n rate series structure 93218159Sadrian * 94218159Sadrian * This should be called for both legacy and MCS rates. 95218159Sadrian */ 96218159Sadrianstatic void 97218159Sadrianath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, 98218159Sadrian HAL_11N_RATE_SERIES *series, unsigned int pktlen, uint8_t *rix, 99218935Sadrian uint8_t *try, int flags) 100218159Sadrian{ 101219588Sadrian#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) 102218159Sadrian struct ieee80211com *ic = ni->ni_ic; 103218159Sadrian struct ath_hal *ah = sc->sc_ah; 104218159Sadrian HAL_BOOL shortPreamble = AH_FALSE; 105218159Sadrian const HAL_RATE_TABLE *rt = sc->sc_currates; 106218159Sadrian int i; 107218159Sadrian 108218159Sadrian if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 109218159Sadrian (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) 110218159Sadrian shortPreamble = AH_TRUE; 111218159Sadrian 112218159Sadrian memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4); 113218159Sadrian for (i = 0; i < 4; i++) { 114218931Sadrian /* Only set flags for actual TX attempts */ 115218931Sadrian if (try[i] == 0) 116218931Sadrian continue; 117218931Sadrian 118218159Sadrian series[i].Tries = try[i]; 119218931Sadrian 120218931Sadrian /* 121218931Sadrian * XXX this isn't strictly correct - sc_txchainmask 122218931Sadrian * XXX isn't the currently active chainmask; 123218931Sadrian * XXX it's the interface chainmask at startup. 124218931Sadrian * XXX It's overridden in the HAL rate scenario function 125218931Sadrian * XXX for now. 126218931Sadrian */ 127218159Sadrian series[i].ChSel = sc->sc_txchainmask; 128218931Sadrian 129218935Sadrian if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) 130218159Sadrian series[i].RateFlags |= HAL_RATESERIES_RTS_CTS; 131218931Sadrian 132219214Sadrian#if 0 133218159Sadrian if (ni->ni_htcap & IEEE80211_HTCAP_CHWIDTH40) 134218159Sadrian series[i].RateFlags |= HAL_RATESERIES_2040; 135218779Sadrian 136218779Sadrian /* 137218779Sadrian * The hardware only supports short-gi in 40mhz mode - 138218779Sadrian * if later hardware supports it in 20mhz mode, be sure 139218779Sadrian * to add the relevant check here. 140218779Sadrian */ 141218779Sadrian if (ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) 142218159Sadrian series[i].RateFlags |= HAL_RATESERIES_HALFGI; 143219214Sadrian#endif 144218159Sadrian 145218907Sadrian series[i].Rate = rt->info[rix[i]].rateCode; 146218159Sadrian 147218159Sadrian /* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */ 148218907Sadrian if (series[i].Rate & IEEE80211_RATE_MCS) { 149218159Sadrian series[i].PktDuration = 150218159Sadrian ath_computedur_ht(pktlen 151218907Sadrian , series[i].Rate 152219588Sadrian , HT_RC_2_STREAMS(series[i].Rate) 153219588Sadrian , series[i].RateFlags & HAL_RATESERIES_2040 154218566Sadrian , series[i].RateFlags & HAL_RATESERIES_HALFGI); 155218159Sadrian } else { 156219870Sadrian if (shortPreamble) 157219870Sadrian series[i].Rate |= rt->info[rix[i]].shortPreamble; 158218159Sadrian series[i].PktDuration = ath_hal_computetxtime(ah, 159218159Sadrian rt, pktlen, rix[i], shortPreamble); 160218159Sadrian } 161218159Sadrian } 162219588Sadrian#undef HT_RC_2_STREAMS 163218159Sadrian} 164218159Sadrian 165218159Sadrian#if 0 166218159Sadrianstatic void 167218159Sadrianath_rateseries_print(HAL_11N_RATE_SERIES *series) 168218159Sadrian{ 169218159Sadrian int i; 170218159Sadrian for (i = 0; i < 4; i++) { 171218159Sadrian printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n", 172218159Sadrian i, 173218159Sadrian series[i].Rate, 174218159Sadrian series[i].Tries, 175218159Sadrian series[i].PktDuration, 176218159Sadrian series[i].ChSel, 177218159Sadrian series[i].RateFlags); 178218159Sadrian } 179218159Sadrian} 180218159Sadrian#endif 181218159Sadrian 182218159Sadrian/* 183218159Sadrian * Setup the 11n rate scenario and burst duration for the given TX descriptor 184218159Sadrian * list. 185218159Sadrian * 186218159Sadrian * This isn't useful for sending beacon frames, which has different needs 187218159Sadrian * wrt what's passed into the rate scenario function. 188218159Sadrian */ 189218159Sadrian 190218159Sadrianvoid 191218159Sadrianath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf, 192218593Sadrian int pktlen, int flags, uint8_t ctsrate, int is_pspoll, uint8_t *rix, uint8_t *try) 193218159Sadrian{ 194218159Sadrian HAL_11N_RATE_SERIES series[4]; 195218159Sadrian struct ath_desc *ds = bf->bf_desc; 196218159Sadrian struct ath_desc *lastds = NULL; 197218159Sadrian struct ath_hal *ah = sc->sc_ah; 198218159Sadrian 199218159Sadrian /* Setup rate scenario */ 200218159Sadrian memset(&series, 0, sizeof(series)); 201218159Sadrian 202218935Sadrian ath_rateseries_setup(sc, ni, series, pktlen, rix, try, flags); 203218159Sadrian 204218159Sadrian /* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */ 205218159Sadrian 206218159Sadrian /* Enforce RTS and CTS are mutually exclusive */ 207218159Sadrian 208218159Sadrian /* Get a pointer to the last tx descriptor in the list */ 209218159Sadrian lastds = &bf->bf_desc[bf->bf_nseg - 1]; 210218159Sadrian 211218935Sadrian#if 0 212218935Sadrian printf("pktlen: %d; flags 0x%x\n", pktlen, flags); 213218935Sadrian ath_rateseries_print(series); 214218935Sadrian#endif 215218935Sadrian 216218159Sadrian /* Set rate scenario */ 217218159Sadrian ath_hal_set11nratescenario(ah, ds, 218218593Sadrian !is_pspoll, /* whether to override the duration or not */ 219218593Sadrian /* don't allow hardware to override the duration on ps-poll packets */ 220218159Sadrian ctsrate, /* rts/cts rate */ 221218159Sadrian series, /* 11n rate series */ 222218159Sadrian 4, /* number of series */ 223218159Sadrian flags); 224218159Sadrian 225218159Sadrian /* Setup the last descriptor in the chain */ 226218159Sadrian ath_hal_setuplasttxdesc(ah, lastds, ds); 227218159Sadrian 228218159Sadrian /* Set burst duration */ 229218159Sadrian /* This should only be done if aggregate protection is enabled */ 230218159Sadrian //ath_hal_set11nburstduration(ah, ds, 8192); 231218159Sadrian} 232