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