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