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$"); 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 132219985Sadrian /* 133219985Sadrian * Transmit 40MHz frames only if the node has negotiated 134219985Sadrian * it rather than whether the node is capable of it or not. 135219985Sadrian * It's subtly different in the hostap case. 136219985Sadrian */ 137219985Sadrian if (ni->ni_chw == 40) 138219985Sadrian series[i].RateFlags |= HAL_RATESERIES_2040; 139222498Sadrian 140218779Sadrian /* 141222498Sadrian * Set short-GI only if the node has advertised it 142222498Sadrian * the channel width is suitable, and we support it. 143222498Sadrian * We don't currently have a "negotiated" set of bits - 144222498Sadrian * ni_htcap is what the remote end sends, not what this 145222498Sadrian * node is capable of. 146218779Sadrian */ 147222498Sadrian if (ni->ni_chw == 40 && 148222498Sadrian ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 && 149222498Sadrian ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) 150218159Sadrian series[i].RateFlags |= HAL_RATESERIES_HALFGI; 151218159Sadrian 152222498Sadrian if (ni->ni_chw == 20 && 153222498Sadrian ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 && 154222498Sadrian ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) 155222498Sadrian series[i].RateFlags |= HAL_RATESERIES_HALFGI; 156222498Sadrian 157218907Sadrian series[i].Rate = rt->info[rix[i]].rateCode; 158218159Sadrian 159218159Sadrian /* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */ 160218907Sadrian if (series[i].Rate & IEEE80211_RATE_MCS) { 161218159Sadrian series[i].PktDuration = 162218159Sadrian ath_computedur_ht(pktlen 163218907Sadrian , series[i].Rate 164219588Sadrian , HT_RC_2_STREAMS(series[i].Rate) 165219588Sadrian , series[i].RateFlags & HAL_RATESERIES_2040 166218566Sadrian , series[i].RateFlags & HAL_RATESERIES_HALFGI); 167218159Sadrian } else { 168219870Sadrian if (shortPreamble) 169219870Sadrian series[i].Rate |= rt->info[rix[i]].shortPreamble; 170218159Sadrian series[i].PktDuration = ath_hal_computetxtime(ah, 171218159Sadrian rt, pktlen, rix[i], shortPreamble); 172218159Sadrian } 173218159Sadrian } 174219588Sadrian#undef HT_RC_2_STREAMS 175218159Sadrian} 176218159Sadrian 177218159Sadrian#if 0 178218159Sadrianstatic void 179218159Sadrianath_rateseries_print(HAL_11N_RATE_SERIES *series) 180218159Sadrian{ 181218159Sadrian int i; 182218159Sadrian for (i = 0; i < 4; i++) { 183218159Sadrian printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n", 184218159Sadrian i, 185218159Sadrian series[i].Rate, 186218159Sadrian series[i].Tries, 187218159Sadrian series[i].PktDuration, 188218159Sadrian series[i].ChSel, 189218159Sadrian series[i].RateFlags); 190218159Sadrian } 191218159Sadrian} 192218159Sadrian#endif 193218159Sadrian 194218159Sadrian/* 195218159Sadrian * Setup the 11n rate scenario and burst duration for the given TX descriptor 196218159Sadrian * list. 197218159Sadrian * 198218159Sadrian * This isn't useful for sending beacon frames, which has different needs 199218159Sadrian * wrt what's passed into the rate scenario function. 200218159Sadrian */ 201218159Sadrian 202218159Sadrianvoid 203218159Sadrianath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, struct ath_buf *bf, 204218593Sadrian int pktlen, int flags, uint8_t ctsrate, int is_pspoll, uint8_t *rix, uint8_t *try) 205218159Sadrian{ 206218159Sadrian HAL_11N_RATE_SERIES series[4]; 207218159Sadrian struct ath_desc *ds = bf->bf_desc; 208218159Sadrian struct ath_desc *lastds = NULL; 209218159Sadrian struct ath_hal *ah = sc->sc_ah; 210218159Sadrian 211218159Sadrian /* Setup rate scenario */ 212218159Sadrian memset(&series, 0, sizeof(series)); 213218159Sadrian 214218935Sadrian ath_rateseries_setup(sc, ni, series, pktlen, rix, try, flags); 215218159Sadrian 216218159Sadrian /* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */ 217218159Sadrian 218218159Sadrian /* Enforce RTS and CTS are mutually exclusive */ 219218159Sadrian 220218159Sadrian /* Get a pointer to the last tx descriptor in the list */ 221218159Sadrian lastds = &bf->bf_desc[bf->bf_nseg - 1]; 222218159Sadrian 223218935Sadrian#if 0 224218935Sadrian printf("pktlen: %d; flags 0x%x\n", pktlen, flags); 225218935Sadrian ath_rateseries_print(series); 226218935Sadrian#endif 227218935Sadrian 228218159Sadrian /* Set rate scenario */ 229218159Sadrian ath_hal_set11nratescenario(ah, ds, 230218593Sadrian !is_pspoll, /* whether to override the duration or not */ 231218593Sadrian /* don't allow hardware to override the duration on ps-poll packets */ 232218159Sadrian ctsrate, /* rts/cts rate */ 233218159Sadrian series, /* 11n rate series */ 234218159Sadrian 4, /* number of series */ 235218159Sadrian flags); 236218159Sadrian 237218159Sadrian /* Setup the last descriptor in the chain */ 238218159Sadrian ath_hal_setuplasttxdesc(ah, lastds, ds); 239218159Sadrian 240218159Sadrian /* Set burst duration */ 241218159Sadrian /* This should only be done if aggregate protection is enabled */ 242218159Sadrian //ath_hal_set11nburstduration(ah, ds, 8192); 243218159Sadrian} 244