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