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 89eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_tx.h> /* XXX for some support functions */ 904b44f6f2SAdrian Chadd #include <dev/ath/if_ath_tx_ht.h> 91eb6f0de0SAdrian Chadd #include <dev/ath/if_athrate.h> 92eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_debug.h> 93eb6f0de0SAdrian Chadd 94eb6f0de0SAdrian Chadd /* 95eb6f0de0SAdrian Chadd * XXX net80211? 96eb6f0de0SAdrian Chadd */ 97eb6f0de0SAdrian Chadd #define IEEE80211_AMPDU_SUBFRAME_DEFAULT 32 98eb6f0de0SAdrian Chadd 99eb6f0de0SAdrian Chadd #define ATH_AGGR_DELIM_SZ 4 /* delimiter size */ 100eb6f0de0SAdrian Chadd #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ 101b25c1f2aSAdrian Chadd /* number of delimiters for encryption padding */ 102b25c1f2aSAdrian Chadd #define ATH_AGGR_ENCRYPTDELIM 10 103eb6f0de0SAdrian Chadd 104eb6f0de0SAdrian Chadd /* 105eb6f0de0SAdrian Chadd * returns delimiter padding required given the packet length 106eb6f0de0SAdrian Chadd */ 107eb6f0de0SAdrian Chadd #define ATH_AGGR_GET_NDELIM(_len) \ 108eb6f0de0SAdrian Chadd (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ 109eb6f0de0SAdrian Chadd (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) 110eb6f0de0SAdrian Chadd 111eb6f0de0SAdrian Chadd #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) 112eb6f0de0SAdrian Chadd 113eb6f0de0SAdrian Chadd int ath_max_4ms_framelen[4][32] = { 114eb6f0de0SAdrian Chadd [MCS_HT20] = { 115eb6f0de0SAdrian Chadd 3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172, 116eb6f0de0SAdrian Chadd 6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280, 117eb6f0de0SAdrian Chadd 9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532, 118eb6f0de0SAdrian Chadd 12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532, 119eb6f0de0SAdrian Chadd }, 120eb6f0de0SAdrian Chadd [MCS_HT20_SGI] = { 121eb6f0de0SAdrian Chadd 3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744, 122eb6f0de0SAdrian Chadd 7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532, 123eb6f0de0SAdrian Chadd 10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532, 124eb6f0de0SAdrian Chadd 14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532, 125eb6f0de0SAdrian Chadd }, 126eb6f0de0SAdrian Chadd [MCS_HT40] = { 127eb6f0de0SAdrian Chadd 6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532, 128eb6f0de0SAdrian Chadd 13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532, 129eb6f0de0SAdrian Chadd 20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532, 130eb6f0de0SAdrian Chadd 26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532, 131eb6f0de0SAdrian Chadd }, 132eb6f0de0SAdrian Chadd [MCS_HT40_SGI] = { 133eb6f0de0SAdrian Chadd 7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532, 134eb6f0de0SAdrian Chadd 14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532, 135eb6f0de0SAdrian Chadd 22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532, 136eb6f0de0SAdrian Chadd 29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532, 137eb6f0de0SAdrian Chadd } 138eb6f0de0SAdrian Chadd }; 139eb6f0de0SAdrian Chadd 140eb6f0de0SAdrian Chadd /* 141eb6f0de0SAdrian Chadd * XXX should be in net80211 142eb6f0de0SAdrian Chadd */ 143eb6f0de0SAdrian Chadd static int ieee80211_mpdudensity_map[] = { 144eb6f0de0SAdrian Chadd 0, /* IEEE80211_HTCAP_MPDUDENSITY_NA */ 145eb6f0de0SAdrian Chadd 25, /* IEEE80211_HTCAP_MPDUDENSITY_025 */ 146eb6f0de0SAdrian Chadd 50, /* IEEE80211_HTCAP_MPDUDENSITY_05 */ 147eb6f0de0SAdrian Chadd 100, /* IEEE80211_HTCAP_MPDUDENSITY_1 */ 148eb6f0de0SAdrian Chadd 200, /* IEEE80211_HTCAP_MPDUDENSITY_2 */ 149eb6f0de0SAdrian Chadd 400, /* IEEE80211_HTCAP_MPDUDENSITY_4 */ 150eb6f0de0SAdrian Chadd 800, /* IEEE80211_HTCAP_MPDUDENSITY_8 */ 151eb6f0de0SAdrian Chadd 1600, /* IEEE80211_HTCAP_MPDUDENSITY_16 */ 152eb6f0de0SAdrian Chadd }; 153eb6f0de0SAdrian Chadd 154eb6f0de0SAdrian Chadd /* 155eb6f0de0SAdrian Chadd * XXX should be in the HAL/net80211 ? 156eb6f0de0SAdrian Chadd */ 157eb6f0de0SAdrian Chadd #define BITS_PER_BYTE 8 158eb6f0de0SAdrian Chadd #define OFDM_PLCP_BITS 22 159eb6f0de0SAdrian Chadd #define HT_RC_2_MCS(_rc) ((_rc) & 0x7f) 160eb6f0de0SAdrian Chadd #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) 161eb6f0de0SAdrian Chadd #define L_STF 8 162eb6f0de0SAdrian Chadd #define L_LTF 8 163eb6f0de0SAdrian Chadd #define L_SIG 4 164eb6f0de0SAdrian Chadd #define HT_SIG 8 165eb6f0de0SAdrian Chadd #define HT_STF 4 166eb6f0de0SAdrian Chadd #define HT_LTF(_ns) (4 * (_ns)) 167eb6f0de0SAdrian Chadd #define SYMBOL_TIME(_ns) ((_ns) << 2) // ns * 4 us 168eb6f0de0SAdrian Chadd #define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) // ns * 3.6 us 169eb6f0de0SAdrian Chadd #define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) 170eb6f0de0SAdrian Chadd #define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) 171eb6f0de0SAdrian Chadd #define IS_HT_RATE(_rate) ((_rate) & 0x80) 172eb6f0de0SAdrian Chadd 173eb6f0de0SAdrian Chadd const uint32_t bits_per_symbol[][2] = { 174eb6f0de0SAdrian Chadd /* 20MHz 40MHz */ 175eb6f0de0SAdrian Chadd { 26, 54 }, // 0: BPSK 176eb6f0de0SAdrian Chadd { 52, 108 }, // 1: QPSK 1/2 177eb6f0de0SAdrian Chadd { 78, 162 }, // 2: QPSK 3/4 178eb6f0de0SAdrian Chadd { 104, 216 }, // 3: 16-QAM 1/2 179eb6f0de0SAdrian Chadd { 156, 324 }, // 4: 16-QAM 3/4 180eb6f0de0SAdrian Chadd { 208, 432 }, // 5: 64-QAM 2/3 181eb6f0de0SAdrian Chadd { 234, 486 }, // 6: 64-QAM 3/4 182eb6f0de0SAdrian Chadd { 260, 540 }, // 7: 64-QAM 5/6 183eb6f0de0SAdrian Chadd { 52, 108 }, // 8: BPSK 184eb6f0de0SAdrian Chadd { 104, 216 }, // 9: QPSK 1/2 185eb6f0de0SAdrian Chadd { 156, 324 }, // 10: QPSK 3/4 186eb6f0de0SAdrian Chadd { 208, 432 }, // 11: 16-QAM 1/2 187eb6f0de0SAdrian Chadd { 312, 648 }, // 12: 16-QAM 3/4 188eb6f0de0SAdrian Chadd { 416, 864 }, // 13: 64-QAM 2/3 189eb6f0de0SAdrian Chadd { 468, 972 }, // 14: 64-QAM 3/4 190eb6f0de0SAdrian Chadd { 520, 1080 }, // 15: 64-QAM 5/6 191eb6f0de0SAdrian Chadd { 78, 162 }, // 16: BPSK 192eb6f0de0SAdrian Chadd { 156, 324 }, // 17: QPSK 1/2 193eb6f0de0SAdrian Chadd { 234, 486 }, // 18: QPSK 3/4 194eb6f0de0SAdrian Chadd { 312, 648 }, // 19: 16-QAM 1/2 195eb6f0de0SAdrian Chadd { 468, 972 }, // 20: 16-QAM 3/4 196eb6f0de0SAdrian Chadd { 624, 1296 }, // 21: 64-QAM 2/3 197eb6f0de0SAdrian Chadd { 702, 1458 }, // 22: 64-QAM 3/4 198eb6f0de0SAdrian Chadd { 780, 1620 }, // 23: 64-QAM 5/6 199eb6f0de0SAdrian Chadd { 104, 216 }, // 24: BPSK 200eb6f0de0SAdrian Chadd { 208, 432 }, // 25: QPSK 1/2 201eb6f0de0SAdrian Chadd { 312, 648 }, // 26: QPSK 3/4 202eb6f0de0SAdrian Chadd { 416, 864 }, // 27: 16-QAM 1/2 203eb6f0de0SAdrian Chadd { 624, 1296 }, // 28: 16-QAM 3/4 204eb6f0de0SAdrian Chadd { 832, 1728 }, // 29: 64-QAM 2/3 205eb6f0de0SAdrian Chadd { 936, 1944 }, // 30: 64-QAM 3/4 206eb6f0de0SAdrian Chadd { 1040, 2160 }, // 31: 64-QAM 5/6 207eb6f0de0SAdrian Chadd }; 208eb6f0de0SAdrian Chadd 209eb6f0de0SAdrian Chadd /* 210eb6f0de0SAdrian Chadd * Fill in the rate array information based on the current 211eb6f0de0SAdrian Chadd * node configuration and the choices made by the rate 212eb6f0de0SAdrian Chadd * selection code and ath_buf setup code. 213eb6f0de0SAdrian Chadd * 214eb6f0de0SAdrian Chadd * Later on, this may end up also being made by the 215eb6f0de0SAdrian Chadd * rate control code, but for now it can live here. 216eb6f0de0SAdrian Chadd * 217eb6f0de0SAdrian Chadd * This needs to be called just before the packet is 218eb6f0de0SAdrian Chadd * queued to the software queue or hardware queue, 219eb6f0de0SAdrian Chadd * so all of the needed fields in bf_state are setup. 220eb6f0de0SAdrian Chadd */ 221eb6f0de0SAdrian Chadd void 222eb6f0de0SAdrian Chadd ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf) 223eb6f0de0SAdrian Chadd { 224eb6f0de0SAdrian Chadd struct ieee80211_node *ni = bf->bf_node; 225eb6f0de0SAdrian Chadd struct ieee80211com *ic = ni->ni_ic; 226eb6f0de0SAdrian Chadd const HAL_RATE_TABLE *rt = sc->sc_currates; 227eb6f0de0SAdrian Chadd struct ath_rc_series *rc = bf->bf_state.bfs_rc; 228eb6f0de0SAdrian Chadd uint8_t rate; 229eb6f0de0SAdrian Chadd int i; 230ce725c8eSAdrian Chadd int do_ldpc; 231ce725c8eSAdrian Chadd int do_stbc; 232ce725c8eSAdrian Chadd 233ce725c8eSAdrian Chadd /* 234ce725c8eSAdrian Chadd * We only do LDPC if the rate is 11n, both we and the 235ce725c8eSAdrian Chadd * receiver support LDPC and it's enabled. 236ce725c8eSAdrian Chadd * 237ce725c8eSAdrian Chadd * It's a global flag, not a per-try flag, so we clear 238ce725c8eSAdrian Chadd * it if any of the rate entries aren't 11n. 239ce725c8eSAdrian Chadd */ 240*a0391187SAdrian Chadd do_ldpc = 0; 241ce725c8eSAdrian Chadd if ((ni->ni_vap->iv_htcaps & IEEE80211_HTCAP_LDPC) && 242ce725c8eSAdrian Chadd (ni->ni_htcap & IEEE80211_HTCAP_LDPC)) 243ce725c8eSAdrian Chadd do_ldpc = 1; 244ce725c8eSAdrian Chadd do_stbc = 0; 245eb6f0de0SAdrian Chadd 246eb6f0de0SAdrian Chadd for (i = 0; i < ATH_RC_NUM; i++) { 247eb6f0de0SAdrian Chadd rc[i].flags = 0; 248eb6f0de0SAdrian Chadd if (rc[i].tries == 0) 249eb6f0de0SAdrian Chadd continue; 250eb6f0de0SAdrian Chadd 251eb6f0de0SAdrian Chadd rate = rt->info[rc[i].rix].rateCode; 252eb6f0de0SAdrian Chadd 253eb6f0de0SAdrian Chadd /* 25456129906SAdrian Chadd * Only enable short preamble for legacy rates 255eb6f0de0SAdrian Chadd */ 2567a27f0a3SAdrian Chadd if ((! IS_HT_RATE(rate)) && bf->bf_state.bfs_shpream) 257eb6f0de0SAdrian Chadd rate |= rt->info[rc[i].rix].shortPreamble; 258eb6f0de0SAdrian Chadd 259eb6f0de0SAdrian Chadd /* 260eb6f0de0SAdrian Chadd * Save this, used by the TX and completion code 261eb6f0de0SAdrian Chadd */ 262eb6f0de0SAdrian Chadd rc[i].ratecode = rate; 263eb6f0de0SAdrian Chadd 264875a9451SAdrian Chadd if (bf->bf_state.bfs_txflags & 265eb6f0de0SAdrian Chadd (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) 266eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_RTSCTS_FLAG; 267eb6f0de0SAdrian Chadd 268ce725c8eSAdrian Chadd /* 269ce725c8eSAdrian Chadd * If we can't do LDPC, don't. 270ce725c8eSAdrian Chadd */ 271ce725c8eSAdrian Chadd if (! IS_HT_RATE(rate)) 272ce725c8eSAdrian Chadd do_ldpc = 0; 273ce725c8eSAdrian Chadd 274eb6f0de0SAdrian Chadd /* Only enable shortgi, 2040, dual-stream if HT is set */ 275eb6f0de0SAdrian Chadd if (IS_HT_RATE(rate)) { 276eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_HT_FLAG; 277eb6f0de0SAdrian Chadd 278eb6f0de0SAdrian Chadd if (ni->ni_chw == 40) 279eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_CW40_FLAG; 280eb6f0de0SAdrian Chadd 281eb6f0de0SAdrian Chadd if (ni->ni_chw == 40 && 282eb6f0de0SAdrian Chadd ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 && 283eb6f0de0SAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) 284eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_SGI_FLAG; 285eb6f0de0SAdrian Chadd 286eb6f0de0SAdrian Chadd if (ni->ni_chw == 20 && 287eb6f0de0SAdrian Chadd ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 && 288eb6f0de0SAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) 289eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_SGI_FLAG; 290eb6f0de0SAdrian Chadd 29156129906SAdrian Chadd /* 29256129906SAdrian Chadd * If we have STBC TX enabled and the receiver 29356129906SAdrian Chadd * can receive (at least) 1 stream STBC, AND it's 29456129906SAdrian Chadd * MCS 0-7, AND we have at least two chains enabled, 29556129906SAdrian Chadd * enable STBC. 296f026d693SAdrian Chadd * 297f026d693SAdrian Chadd * XXX TODO: .. and the rate is an 11n rate? 29856129906SAdrian Chadd */ 29956129906SAdrian Chadd if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC && 300f026d693SAdrian Chadd ni->ni_vap->iv_flags_ht & IEEE80211_FHT_STBC_TX && 30156129906SAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM && 30256129906SAdrian Chadd (sc->sc_cur_txchainmask > 1) && 30356129906SAdrian Chadd HT_RC_2_STREAMS(rate) == 1) { 30456129906SAdrian Chadd rc[i].flags |= ATH_RC_STBC_FLAG; 305ce725c8eSAdrian Chadd do_stbc = 1; 30656129906SAdrian Chadd } 30756129906SAdrian Chadd 308de00e5cbSAdrian Chadd /* 309de00e5cbSAdrian Chadd * Dual / Triple stream rate? 310de00e5cbSAdrian Chadd */ 311de00e5cbSAdrian Chadd if (HT_RC_2_STREAMS(rate) == 2) 312de00e5cbSAdrian Chadd rc[i].flags |= ATH_RC_DS_FLAG; 313de00e5cbSAdrian Chadd else if (HT_RC_2_STREAMS(rate) == 3) 314de00e5cbSAdrian Chadd rc[i].flags |= ATH_RC_TS_FLAG; 315eb6f0de0SAdrian Chadd } 316eb6f0de0SAdrian Chadd 317eb6f0de0SAdrian Chadd /* 318de00e5cbSAdrian Chadd * Calculate the maximum TX power cap for the current 319de00e5cbSAdrian Chadd * node. 320de00e5cbSAdrian Chadd */ 321de00e5cbSAdrian Chadd rc[i].tx_power_cap = ieee80211_get_node_txpower(ni); 322de00e5cbSAdrian Chadd 323de00e5cbSAdrian Chadd /* 324eb6f0de0SAdrian Chadd * Calculate the maximum 4ms frame length based 325eb6f0de0SAdrian Chadd * on the MCS rate, SGI and channel width flags. 326eb6f0de0SAdrian Chadd */ 327eb6f0de0SAdrian Chadd if ((rc[i].flags & ATH_RC_HT_FLAG) && 328eb6f0de0SAdrian Chadd (HT_RC_2_MCS(rate) < 32)) { 329eb6f0de0SAdrian Chadd int j; 330eb6f0de0SAdrian Chadd if (rc[i].flags & ATH_RC_CW40_FLAG) { 331eb6f0de0SAdrian Chadd if (rc[i].flags & ATH_RC_SGI_FLAG) 332eb6f0de0SAdrian Chadd j = MCS_HT40_SGI; 333eb6f0de0SAdrian Chadd else 334eb6f0de0SAdrian Chadd j = MCS_HT40; 335eb6f0de0SAdrian Chadd } else { 336eb6f0de0SAdrian Chadd if (rc[i].flags & ATH_RC_SGI_FLAG) 337eb6f0de0SAdrian Chadd j = MCS_HT20_SGI; 338eb6f0de0SAdrian Chadd else 339eb6f0de0SAdrian Chadd j = MCS_HT20; 340eb6f0de0SAdrian Chadd } 341eb6f0de0SAdrian Chadd rc[i].max4msframelen = 342eb6f0de0SAdrian Chadd ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)]; 343eb6f0de0SAdrian Chadd } else 344eb6f0de0SAdrian Chadd rc[i].max4msframelen = 0; 345eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, 346eb6f0de0SAdrian Chadd "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n", 347eb6f0de0SAdrian Chadd __func__, i, rate, rc[i].flags, rc[i].max4msframelen); 348eb6f0de0SAdrian Chadd } 349ce725c8eSAdrian Chadd 350ce725c8eSAdrian Chadd /* 351ce725c8eSAdrian Chadd * LDPC is a global flag, so ... 352ce725c8eSAdrian Chadd */ 353ce725c8eSAdrian Chadd if (do_ldpc) { 354ce725c8eSAdrian Chadd bf->bf_state.bfs_txflags |= HAL_TXDESC_LDPC; 355ce725c8eSAdrian Chadd sc->sc_stats.ast_tx_ldpc++; 356ce725c8eSAdrian Chadd } 357ce725c8eSAdrian Chadd 358ce725c8eSAdrian Chadd if (do_stbc) { 359ce725c8eSAdrian Chadd sc->sc_stats.ast_tx_stbc++; 360ce725c8eSAdrian Chadd } 361eb6f0de0SAdrian Chadd } 362eb6f0de0SAdrian Chadd 363eb6f0de0SAdrian Chadd /* 364eb6f0de0SAdrian Chadd * Return the number of delimiters to be added to 365eb6f0de0SAdrian Chadd * meet the minimum required mpdudensity. 366eb6f0de0SAdrian Chadd * 367eb6f0de0SAdrian Chadd * Caller should make sure that the rate is HT. 368eb6f0de0SAdrian Chadd * 369eb6f0de0SAdrian Chadd * TODO: is this delimiter calculation supposed to be the 370eb6f0de0SAdrian Chadd * total frame length, the hdr length, the data length (including 371eb6f0de0SAdrian Chadd * delimiters, padding, CRC, etc) or ? 372eb6f0de0SAdrian Chadd * 373eb6f0de0SAdrian Chadd * TODO: this should ensure that the rate control information 374eb6f0de0SAdrian Chadd * HAS been setup for the first rate. 375eb6f0de0SAdrian Chadd * 376eb6f0de0SAdrian Chadd * TODO: ensure this is only called for MCS rates. 377eb6f0de0SAdrian Chadd * 378eb6f0de0SAdrian Chadd * TODO: enforce MCS < 31 379eb6f0de0SAdrian Chadd */ 380eb6f0de0SAdrian Chadd static int 381eb6f0de0SAdrian Chadd ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf, 382eb6f0de0SAdrian Chadd uint16_t pktlen) 383eb6f0de0SAdrian Chadd { 384eb6f0de0SAdrian Chadd const HAL_RATE_TABLE *rt = sc->sc_currates; 385eb6f0de0SAdrian Chadd struct ieee80211_node *ni = first_bf->bf_node; 386eb6f0de0SAdrian Chadd struct ieee80211vap *vap = ni->ni_vap; 387eb6f0de0SAdrian Chadd int ndelim, mindelim = 0; 388eb6f0de0SAdrian Chadd int mpdudensity; /* in 1/100'th of a microsecond */ 389eb6f0de0SAdrian Chadd uint8_t rc, rix, flags; 390eb6f0de0SAdrian Chadd int width, half_gi; 391eb6f0de0SAdrian Chadd uint32_t nsymbits, nsymbols; 392eb6f0de0SAdrian Chadd uint16_t minlen; 393eb6f0de0SAdrian Chadd 394eb6f0de0SAdrian Chadd /* 395eb6f0de0SAdrian Chadd * vap->iv_ampdu_density is a value, rather than the actual 396eb6f0de0SAdrian Chadd * density. 397eb6f0de0SAdrian Chadd */ 398eb6f0de0SAdrian Chadd if (vap->iv_ampdu_density > IEEE80211_HTCAP_MPDUDENSITY_16) 399eb6f0de0SAdrian Chadd mpdudensity = 1600; /* maximum density */ 400eb6f0de0SAdrian Chadd else 401eb6f0de0SAdrian Chadd mpdudensity = ieee80211_mpdudensity_map[vap->iv_ampdu_density]; 402eb6f0de0SAdrian Chadd 403eb6f0de0SAdrian Chadd /* Select standard number of delimiters based on frame length */ 404eb6f0de0SAdrian Chadd ndelim = ATH_AGGR_GET_NDELIM(pktlen); 405eb6f0de0SAdrian Chadd 406eb6f0de0SAdrian Chadd /* 407eb6f0de0SAdrian Chadd * If encryption is enabled, add extra delimiters to let the 408eb6f0de0SAdrian Chadd * crypto hardware catch up. This could be tuned per-MAC and 409eb6f0de0SAdrian Chadd * per-rate, but for now we'll simply assume encryption is 410eb6f0de0SAdrian Chadd * always enabled. 4114a502c33SAdrian Chadd * 4124a502c33SAdrian Chadd * Also note that the Atheros reference driver inserts two 4134a502c33SAdrian Chadd * delimiters by default for pre-AR9380 peers. This will 4144a502c33SAdrian Chadd * include "that" required delimiter. 415eb6f0de0SAdrian Chadd */ 416eb6f0de0SAdrian Chadd ndelim += ATH_AGGR_ENCRYPTDELIM; 417eb6f0de0SAdrian Chadd 41864dbfc6dSAdrian Chadd /* 41964dbfc6dSAdrian Chadd * For AR9380, there's a minimum number of delimeters 42064dbfc6dSAdrian Chadd * required when doing RTS. 4214a502c33SAdrian Chadd * 4224a502c33SAdrian Chadd * XXX TODO: this is only needed if (a) RTS/CTS is enabled, and 4234a502c33SAdrian Chadd * XXX (b) this is the first sub-frame in the aggregate. 42464dbfc6dSAdrian Chadd */ 42564dbfc6dSAdrian Chadd if (sc->sc_use_ent && (sc->sc_ent_cfg & AH_ENT_RTSCTS_DELIM_WAR) 42664dbfc6dSAdrian Chadd && ndelim < AH_FIRST_DESC_NDELIMS) 42764dbfc6dSAdrian Chadd ndelim = AH_FIRST_DESC_NDELIMS; 42864dbfc6dSAdrian Chadd 429a54ecf78SAdrian Chadd /* 430a54ecf78SAdrian Chadd * If sc_delim_min_pad is non-zero, enforce it as the minimum 431a54ecf78SAdrian Chadd * pad delimiter count. 432a54ecf78SAdrian Chadd */ 433a54ecf78SAdrian Chadd if (sc->sc_delim_min_pad != 0) 434a54ecf78SAdrian Chadd ndelim = MAX(ndelim, sc->sc_delim_min_pad); 435a54ecf78SAdrian Chadd 436eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, 437eb6f0de0SAdrian Chadd "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n", 438eb6f0de0SAdrian Chadd __func__, pktlen, ndelim, mpdudensity); 439eb6f0de0SAdrian Chadd 440eb6f0de0SAdrian Chadd /* 441eb6f0de0SAdrian Chadd * If the MPDU density is 0, we can return here. 442eb6f0de0SAdrian Chadd * Otherwise, we need to convert the desired mpdudensity 443eb6f0de0SAdrian Chadd * into a byte length, based on the rate in the subframe. 444eb6f0de0SAdrian Chadd */ 445eb6f0de0SAdrian Chadd if (mpdudensity == 0) 446eb6f0de0SAdrian Chadd return ndelim; 447eb6f0de0SAdrian Chadd 448eb6f0de0SAdrian Chadd /* 449eb6f0de0SAdrian Chadd * Convert desired mpdu density from microeconds to bytes based 450eb6f0de0SAdrian Chadd * on highest rate in rate series (i.e. first rate) to determine 451eb6f0de0SAdrian Chadd * required minimum length for subframe. Take into account 452eb6f0de0SAdrian Chadd * whether high rate is 20 or 40Mhz and half or full GI. 453eb6f0de0SAdrian Chadd */ 454eb6f0de0SAdrian Chadd rix = first_bf->bf_state.bfs_rc[0].rix; 455eb6f0de0SAdrian Chadd rc = rt->info[rix].rateCode; 456eb6f0de0SAdrian Chadd flags = first_bf->bf_state.bfs_rc[0].flags; 457eb6f0de0SAdrian Chadd width = !! (flags & ATH_RC_CW40_FLAG); 458eb6f0de0SAdrian Chadd half_gi = !! (flags & ATH_RC_SGI_FLAG); 459eb6f0de0SAdrian Chadd 460eb6f0de0SAdrian Chadd /* 461eb6f0de0SAdrian Chadd * mpdudensity is in 1/100th of a usec, so divide by 100 462eb6f0de0SAdrian Chadd */ 463eb6f0de0SAdrian Chadd if (half_gi) 464eb6f0de0SAdrian Chadd nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); 465eb6f0de0SAdrian Chadd else 466eb6f0de0SAdrian Chadd nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity); 467eb6f0de0SAdrian Chadd nsymbols /= 100; 468eb6f0de0SAdrian Chadd 469eb6f0de0SAdrian Chadd if (nsymbols == 0) 470eb6f0de0SAdrian Chadd nsymbols = 1; 471eb6f0de0SAdrian Chadd 472eb6f0de0SAdrian Chadd nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; 473eb6f0de0SAdrian Chadd minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; 474eb6f0de0SAdrian Chadd 475eb6f0de0SAdrian Chadd /* 476eb6f0de0SAdrian Chadd * Min length is the minimum frame length for the 477eb6f0de0SAdrian Chadd * required MPDU density. 478eb6f0de0SAdrian Chadd */ 479eb6f0de0SAdrian Chadd if (pktlen < minlen) { 480eb6f0de0SAdrian Chadd mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ; 481eb6f0de0SAdrian Chadd ndelim = MAX(mindelim, ndelim); 482eb6f0de0SAdrian Chadd } 483eb6f0de0SAdrian Chadd 484eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, 485eb6f0de0SAdrian Chadd "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n", 486eb6f0de0SAdrian Chadd __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim); 487eb6f0de0SAdrian Chadd 488eb6f0de0SAdrian Chadd return ndelim; 489eb6f0de0SAdrian Chadd } 490eb6f0de0SAdrian Chadd 491eb6f0de0SAdrian Chadd /* 492eb6f0de0SAdrian Chadd * Fetch the aggregation limit. 493eb6f0de0SAdrian Chadd * 494eb6f0de0SAdrian Chadd * It's the lowest of the four rate series 4ms frame length. 495eb6f0de0SAdrian Chadd */ 496eb6f0de0SAdrian Chadd static int 497eb6f0de0SAdrian Chadd ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf) 498eb6f0de0SAdrian Chadd { 4994a502c33SAdrian Chadd int amin = ATH_AGGR_MAXSIZE; 500eb6f0de0SAdrian Chadd int i; 501eb6f0de0SAdrian Chadd 5024a502c33SAdrian Chadd if (sc->sc_aggr_limit > 0 && sc->sc_aggr_limit < ATH_AGGR_MAXSIZE) 5034a502c33SAdrian Chadd amin = sc->sc_aggr_limit; 5044a502c33SAdrian Chadd 505b25c1f2aSAdrian Chadd for (i = 0; i < ATH_RC_NUM; i++) { 506eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_rc[i].tries == 0) 507eb6f0de0SAdrian Chadd continue; 508eb6f0de0SAdrian Chadd amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen); 509eb6f0de0SAdrian Chadd } 510eb6f0de0SAdrian Chadd 511eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: max frame len= %d\n", 512eb6f0de0SAdrian Chadd __func__, amin); 513eb6f0de0SAdrian Chadd 514eb6f0de0SAdrian Chadd return amin; 515eb6f0de0SAdrian Chadd } 5164b44f6f2SAdrian Chadd 5174b44f6f2SAdrian Chadd /* 5184b44f6f2SAdrian Chadd * Setup a 11n rate series structure 5194b44f6f2SAdrian Chadd * 5204b44f6f2SAdrian Chadd * This should be called for both legacy and MCS rates. 521eb6f0de0SAdrian Chadd * 522de00e5cbSAdrian Chadd * This uses the rate series stuf from ath_tx_rate_fill_rcflags(). 523de00e5cbSAdrian Chadd * 524eb6f0de0SAdrian Chadd * It, along with ath_buf_set_rate, must be called -after- a burst 525eb6f0de0SAdrian Chadd * or aggregate is setup. 5264b44f6f2SAdrian Chadd */ 5274b44f6f2SAdrian Chadd static void 5284b44f6f2SAdrian Chadd ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, 529eb6f0de0SAdrian Chadd struct ath_buf *bf, HAL_11N_RATE_SERIES *series) 5304b44f6f2SAdrian Chadd { 5314b44f6f2SAdrian Chadd struct ieee80211com *ic = ni->ni_ic; 5324b44f6f2SAdrian Chadd struct ath_hal *ah = sc->sc_ah; 5334b44f6f2SAdrian Chadd HAL_BOOL shortPreamble = AH_FALSE; 5344b44f6f2SAdrian Chadd const HAL_RATE_TABLE *rt = sc->sc_currates; 5354b44f6f2SAdrian Chadd int i; 536eb6f0de0SAdrian Chadd int pktlen; 537eb6f0de0SAdrian Chadd struct ath_rc_series *rc = bf->bf_state.bfs_rc; 5384b44f6f2SAdrian Chadd 5394b44f6f2SAdrian Chadd if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 5404b44f6f2SAdrian Chadd (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) 5414b44f6f2SAdrian Chadd shortPreamble = AH_TRUE; 5424b44f6f2SAdrian Chadd 543eb6f0de0SAdrian Chadd /* 544eb6f0de0SAdrian Chadd * If this is the first frame in an aggregate series, 545eb6f0de0SAdrian Chadd * use the aggregate length. 546eb6f0de0SAdrian Chadd */ 547eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_aggr) 548eb6f0de0SAdrian Chadd pktlen = bf->bf_state.bfs_al; 549eb6f0de0SAdrian Chadd else 550eb6f0de0SAdrian Chadd pktlen = bf->bf_state.bfs_pktlen; 551eb6f0de0SAdrian Chadd 552eb6f0de0SAdrian Chadd /* 553eb6f0de0SAdrian Chadd * XXX TODO: modify this routine to use the bfs_rc[x].flags 554eb6f0de0SAdrian Chadd * XXX fields. 555eb6f0de0SAdrian Chadd */ 5564b44f6f2SAdrian Chadd memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4); 557b25c1f2aSAdrian Chadd for (i = 0; i < ATH_RC_NUM; i++) { 558146b49d8SAdrian Chadd /* Only set flags for actual TX attempts */ 559eb6f0de0SAdrian Chadd if (rc[i].tries == 0) 560146b49d8SAdrian Chadd continue; 561146b49d8SAdrian Chadd 562eb6f0de0SAdrian Chadd series[i].Tries = rc[i].tries; 563146b49d8SAdrian Chadd 564146b49d8SAdrian Chadd /* 5654a502c33SAdrian Chadd * XXX TODO: When the NIC is capable of three stream TX, 5664a502c33SAdrian Chadd * transmit 1/2 stream rates on two streams. 5674a502c33SAdrian Chadd * 5684a502c33SAdrian Chadd * This reduces the power consumption of the NIC and 5694a502c33SAdrian Chadd * keeps it within the PCIe slot power limits. 5704a502c33SAdrian Chadd */ 5716322256bSAdrian Chadd series[i].ChSel = sc->sc_cur_txchainmask; 572146b49d8SAdrian Chadd 57356129906SAdrian Chadd /* 57456129906SAdrian Chadd * Setup rate and TX power cap for this series. 57556129906SAdrian Chadd */ 57656129906SAdrian Chadd series[i].Rate = rt->info[rc[i].rix].rateCode; 57756129906SAdrian Chadd series[i].RateIndex = rc[i].rix; 578de00e5cbSAdrian Chadd series[i].tx_power_cap = rc[i].tx_power_cap; 57956129906SAdrian Chadd 58056129906SAdrian Chadd /* 58156129906SAdrian Chadd * Enable RTS/CTS as appropriate. 58256129906SAdrian Chadd */ 583de00e5cbSAdrian Chadd if (rc[i].flags & ATH_RC_RTSCTS_FLAG) 5844b44f6f2SAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_RTS_CTS; 585146b49d8SAdrian Chadd 586532f2442SAdrian Chadd /* 587de00e5cbSAdrian Chadd * 11n rate? Update 11n flags. 588532f2442SAdrian Chadd */ 589de00e5cbSAdrian Chadd if (rc[i].flags & ATH_RC_HT_FLAG) { 590de00e5cbSAdrian Chadd if (rc[i].flags & ATH_RC_CW40_FLAG) 5914b44f6f2SAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_2040; 5926246be6eSAdrian Chadd 593de00e5cbSAdrian Chadd if (rc[i].flags & ATH_RC_SGI_FLAG) 5944b44f6f2SAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_HALFGI; 5956246be6eSAdrian Chadd 596de00e5cbSAdrian Chadd if (rc[i].flags & ATH_RC_STBC_FLAG) 5971a3a5607SAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_STBC; 5981a3a5607SAdrian Chadd } 5996322256bSAdrian Chadd 600b25c1f2aSAdrian Chadd /* 601f026d693SAdrian Chadd * TODO: If we're all doing 11n rates then we can set LDPC. 602f026d693SAdrian Chadd * If we've been asked to /do/ LDPC but we are handed a 603f026d693SAdrian Chadd * legacy rate, then we should complain. Loudly. 604f026d693SAdrian Chadd */ 605f026d693SAdrian Chadd 606f026d693SAdrian Chadd /* 607b25c1f2aSAdrian Chadd * PktDuration doesn't include slot, ACK, RTS, etc timing - 608b25c1f2aSAdrian Chadd * it's just the packet duration 609b25c1f2aSAdrian Chadd */ 610de00e5cbSAdrian Chadd if (rc[i].flags & ATH_RC_HT_FLAG) { 6114b44f6f2SAdrian Chadd series[i].PktDuration = 6124b44f6f2SAdrian Chadd ath_computedur_ht(pktlen 6139a97e25eSAdrian Chadd , series[i].Rate 614fce6d676SAdrian Chadd , HT_RC_2_STREAMS(series[i].Rate) 615fce6d676SAdrian Chadd , series[i].RateFlags & HAL_RATESERIES_2040 616f449ab1cSAdrian Chadd , series[i].RateFlags & HAL_RATESERIES_HALFGI); 6174b44f6f2SAdrian Chadd } else { 6181198947aSAdrian Chadd if (shortPreamble) 619eb6f0de0SAdrian Chadd series[i].Rate |= 620eb6f0de0SAdrian Chadd rt->info[rc[i].rix].shortPreamble; 6214b44f6f2SAdrian Chadd series[i].PktDuration = ath_hal_computetxtime(ah, 622eb6f0de0SAdrian Chadd rt, pktlen, rc[i].rix, shortPreamble); 6234b44f6f2SAdrian Chadd } 6244b44f6f2SAdrian Chadd } 6254b44f6f2SAdrian Chadd } 6264b44f6f2SAdrian Chadd 62719b34b56SAdrian Chadd #ifdef ATH_DEBUG 6284b44f6f2SAdrian Chadd static void 629b25c1f2aSAdrian Chadd ath_rateseries_print(struct ath_softc *sc, HAL_11N_RATE_SERIES *series) 6304b44f6f2SAdrian Chadd { 6314b44f6f2SAdrian Chadd int i; 632b25c1f2aSAdrian Chadd for (i = 0; i < ATH_RC_NUM; i++) { 633b25c1f2aSAdrian Chadd device_printf(sc->sc_dev ,"series %d: rate %x; tries %d; " 63464dbfc6dSAdrian Chadd "pktDuration %d; chSel %d; txpowcap %d, rateFlags %x\n", 6354b44f6f2SAdrian Chadd i, 6364b44f6f2SAdrian Chadd series[i].Rate, 6374b44f6f2SAdrian Chadd series[i].Tries, 6384b44f6f2SAdrian Chadd series[i].PktDuration, 6394b44f6f2SAdrian Chadd series[i].ChSel, 64064dbfc6dSAdrian Chadd series[i].tx_power_cap, 6414b44f6f2SAdrian Chadd series[i].RateFlags); 6424b44f6f2SAdrian Chadd } 6434b44f6f2SAdrian Chadd } 6444b44f6f2SAdrian Chadd #endif 6454b44f6f2SAdrian Chadd 6464b44f6f2SAdrian Chadd /* 6474b44f6f2SAdrian Chadd * Setup the 11n rate scenario and burst duration for the given TX descriptor 6484b44f6f2SAdrian Chadd * list. 6494b44f6f2SAdrian Chadd * 6504b44f6f2SAdrian Chadd * This isn't useful for sending beacon frames, which has different needs 6514b44f6f2SAdrian Chadd * wrt what's passed into the rate scenario function. 6524b44f6f2SAdrian Chadd */ 6534b44f6f2SAdrian Chadd void 654eb6f0de0SAdrian Chadd ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, 655eb6f0de0SAdrian Chadd struct ath_buf *bf) 6564b44f6f2SAdrian Chadd { 6574b44f6f2SAdrian Chadd HAL_11N_RATE_SERIES series[4]; 6584b44f6f2SAdrian Chadd struct ath_desc *ds = bf->bf_desc; 6594b44f6f2SAdrian Chadd struct ath_hal *ah = sc->sc_ah; 660eb6f0de0SAdrian Chadd int is_pspoll = (bf->bf_state.bfs_atype == HAL_PKT_TYPE_PSPOLL); 661eb6f0de0SAdrian Chadd int ctsrate = bf->bf_state.bfs_ctsrate; 662875a9451SAdrian Chadd int flags = bf->bf_state.bfs_txflags; 6634b44f6f2SAdrian Chadd 6644b44f6f2SAdrian Chadd /* Setup rate scenario */ 6654b44f6f2SAdrian Chadd memset(&series, 0, sizeof(series)); 6664b44f6f2SAdrian Chadd 667eb6f0de0SAdrian Chadd ath_rateseries_setup(sc, ni, bf, series); 6684b44f6f2SAdrian Chadd 66919b34b56SAdrian Chadd #ifdef ATH_DEBUG 67020b0b9eaSAdrian Chadd if (sc->sc_debug & ATH_DEBUG_XMIT) 671b25c1f2aSAdrian Chadd ath_rateseries_print(sc, series); 6722b5684a8SAdrian Chadd #endif 6732b5684a8SAdrian Chadd 6744b44f6f2SAdrian Chadd /* Set rate scenario */ 675b25c1f2aSAdrian Chadd /* 676b25c1f2aSAdrian Chadd * Note: Don't allow hardware to override the duration on 677b25c1f2aSAdrian Chadd * ps-poll packets. 678b25c1f2aSAdrian Chadd */ 6794b44f6f2SAdrian Chadd ath_hal_set11nratescenario(ah, ds, 680bf26df36SAdrian Chadd !is_pspoll, /* whether to override the duration or not */ 6814b44f6f2SAdrian Chadd ctsrate, /* rts/cts rate */ 6824b44f6f2SAdrian Chadd series, /* 11n rate series */ 6834b44f6f2SAdrian Chadd 4, /* number of series */ 6844b44f6f2SAdrian Chadd flags); 6854b44f6f2SAdrian Chadd 6864b44f6f2SAdrian Chadd /* Set burst duration */ 687eb6f0de0SAdrian Chadd /* 688eb6f0de0SAdrian Chadd * This is only required when doing 11n burst, not aggregation 689eb6f0de0SAdrian Chadd * ie, if there's a second frame in a RIFS or A-MPDU burst 690eb6f0de0SAdrian Chadd * w/ >1 A-MPDU frame bursting back to back. 691eb6f0de0SAdrian Chadd * Normal A-MPDU doesn't do bursting -between- aggregates. 692eb6f0de0SAdrian Chadd * 693eb6f0de0SAdrian Chadd * .. and it's highly likely this won't ever be implemented 694eb6f0de0SAdrian Chadd */ 6954b44f6f2SAdrian Chadd //ath_hal_set11nburstduration(ah, ds, 8192); 6964b44f6f2SAdrian Chadd } 697eb6f0de0SAdrian Chadd 698eb6f0de0SAdrian Chadd /* 699eb6f0de0SAdrian Chadd * Form an aggregate packet list. 700eb6f0de0SAdrian Chadd * 701eb6f0de0SAdrian Chadd * This function enforces the aggregate restrictions/requirements. 702eb6f0de0SAdrian Chadd * 703eb6f0de0SAdrian Chadd * These are: 704eb6f0de0SAdrian Chadd * 705eb6f0de0SAdrian Chadd * + The aggregate size maximum (64k for AR9160 and later, 8K for 706eb6f0de0SAdrian Chadd * AR5416 when doing RTS frame protection.) 707eb6f0de0SAdrian Chadd * + Maximum number of sub-frames for an aggregate 708eb6f0de0SAdrian Chadd * + The aggregate delimiter size, giving MACs time to do whatever is 709eb6f0de0SAdrian Chadd * needed before each frame 710eb6f0de0SAdrian Chadd * + Enforce the BAW limit 711eb6f0de0SAdrian Chadd * 712eb6f0de0SAdrian Chadd * Each descriptor queued should have the DMA setup. 713eb6f0de0SAdrian Chadd * The rate series, descriptor setup, linking, etc is all done 714eb6f0de0SAdrian Chadd * externally. This routine simply chains them together. 715eb6f0de0SAdrian Chadd * ath_tx_setds_11n() will take care of configuring the per- 716eb6f0de0SAdrian Chadd * descriptor setup, and ath_buf_set_rate() will configure the 717eb6f0de0SAdrian Chadd * rate control. 718eb6f0de0SAdrian Chadd * 719b25c1f2aSAdrian Chadd * The TID lock is required for the entirety of this function. 720b25c1f2aSAdrian Chadd * 721b25c1f2aSAdrian Chadd * If some code in another thread adds to the head of this 722eb6f0de0SAdrian Chadd * list, very strange behaviour will occur. Since retransmission is the 723eb6f0de0SAdrian Chadd * only reason this will occur, and this routine is designed to be called 724eb6f0de0SAdrian Chadd * from within the scheduler task, it won't ever clash with the completion 725eb6f0de0SAdrian Chadd * task. 726eb6f0de0SAdrian Chadd * 727eb6f0de0SAdrian Chadd * So if you want to call this from an upper layer context (eg, to direct- 728eb6f0de0SAdrian Chadd * dispatch aggregate frames to the hardware), please keep this in mind. 729eb6f0de0SAdrian Chadd */ 730eb6f0de0SAdrian Chadd ATH_AGGR_STATUS 731b25c1f2aSAdrian Chadd ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, 732b25c1f2aSAdrian Chadd struct ath_tid *tid, ath_bufhead *bf_q) 733eb6f0de0SAdrian Chadd { 734a108d2d6SAdrian Chadd //struct ieee80211_node *ni = &an->an_node; 735eb6f0de0SAdrian Chadd struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL; 736eb6f0de0SAdrian Chadd int nframes = 0; 737eb6f0de0SAdrian Chadd uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw; 738eb6f0de0SAdrian Chadd struct ieee80211_tx_ampdu *tap; 739eb6f0de0SAdrian Chadd int status = ATH_AGGR_DONE; 740eb6f0de0SAdrian Chadd int prev_frames = 0; /* XXX for AR5416 burst, not done here */ 741eb6f0de0SAdrian Chadd int prev_al = 0; /* XXX also for AR5416 burst */ 742eb6f0de0SAdrian Chadd 743375307d4SAdrian Chadd ATH_TX_LOCK_ASSERT(sc); 744eb6f0de0SAdrian Chadd 745eb6f0de0SAdrian Chadd tap = ath_tx_get_tx_tid(an, tid->tid); 746eb6f0de0SAdrian Chadd if (tap == NULL) { 747eb6f0de0SAdrian Chadd status = ATH_AGGR_ERROR; 748eb6f0de0SAdrian Chadd goto finish; 749eb6f0de0SAdrian Chadd } 750eb6f0de0SAdrian Chadd 751eb6f0de0SAdrian Chadd h_baw = tap->txa_wnd / 2; 752eb6f0de0SAdrian Chadd 753eb6f0de0SAdrian Chadd for (;;) { 7543e6cc97fSAdrian Chadd bf = ATH_TID_FIRST(tid); 755eb6f0de0SAdrian Chadd if (bf_first == NULL) 756eb6f0de0SAdrian Chadd bf_first = bf; 757eb6f0de0SAdrian Chadd if (bf == NULL) { 758eb6f0de0SAdrian Chadd status = ATH_AGGR_DONE; 759eb6f0de0SAdrian Chadd break; 760eb6f0de0SAdrian Chadd } else { 761eb6f0de0SAdrian Chadd /* 762eb6f0de0SAdrian Chadd * It's the first frame; 763eb6f0de0SAdrian Chadd * set the aggregation limit based on the 764eb6f0de0SAdrian Chadd * rate control decision that has been made. 765eb6f0de0SAdrian Chadd */ 766eb6f0de0SAdrian Chadd aggr_limit = ath_get_aggr_limit(sc, bf_first); 767eb6f0de0SAdrian Chadd } 768eb6f0de0SAdrian Chadd 769eb6f0de0SAdrian Chadd /* Set this early just so things don't get confused */ 770eb6f0de0SAdrian Chadd bf->bf_next = NULL; 771eb6f0de0SAdrian Chadd 772eb6f0de0SAdrian Chadd /* 773eb6f0de0SAdrian Chadd * If the frame doesn't have a sequence number that we're 774eb6f0de0SAdrian Chadd * tracking in the BAW (eg NULL QOS data frame), we can't 775eb6f0de0SAdrian Chadd * aggregate it. Stop the aggregation process; the sender 776eb6f0de0SAdrian Chadd * can then TX what's in the list thus far and then 777eb6f0de0SAdrian Chadd * TX the frame individually. 778eb6f0de0SAdrian Chadd */ 779eb6f0de0SAdrian Chadd if (! bf->bf_state.bfs_dobaw) { 780eb6f0de0SAdrian Chadd status = ATH_AGGR_NONAGGR; 781eb6f0de0SAdrian Chadd break; 782eb6f0de0SAdrian Chadd } 783eb6f0de0SAdrian Chadd 784eb6f0de0SAdrian Chadd /* 785eb6f0de0SAdrian Chadd * If any of the rates are non-HT, this packet 786eb6f0de0SAdrian Chadd * can't be aggregated. 787eb6f0de0SAdrian Chadd * XXX TODO: add a bf_state flag which gets marked 788eb6f0de0SAdrian Chadd * if any active rate is non-HT. 789eb6f0de0SAdrian Chadd */ 790eb6f0de0SAdrian Chadd 791eb6f0de0SAdrian Chadd /* 792eb6f0de0SAdrian Chadd * do not exceed aggregation limit 793eb6f0de0SAdrian Chadd */ 794eb6f0de0SAdrian Chadd al_delta = ATH_AGGR_DELIM_SZ + bf->bf_state.bfs_pktlen; 795eb6f0de0SAdrian Chadd if (nframes && 796eb6f0de0SAdrian Chadd (aggr_limit < (al + bpad + al_delta + prev_al))) { 797eb6f0de0SAdrian Chadd status = ATH_AGGR_LIMITED; 798eb6f0de0SAdrian Chadd break; 799eb6f0de0SAdrian Chadd } 800eb6f0de0SAdrian Chadd 801eb6f0de0SAdrian Chadd /* 802045bc788SAdrian Chadd * If RTS/CTS is set on the first frame, enforce 803045bc788SAdrian Chadd * the RTS aggregate limit. 804045bc788SAdrian Chadd */ 805045bc788SAdrian Chadd if (bf_first->bf_state.bfs_txflags & 806045bc788SAdrian Chadd (HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA)) { 807045bc788SAdrian Chadd if (nframes && 808045bc788SAdrian Chadd (sc->sc_rts_aggr_limit < 809045bc788SAdrian Chadd (al + bpad + al_delta + prev_al))) { 810045bc788SAdrian Chadd status = ATH_AGGR_8K_LIMITED; 811045bc788SAdrian Chadd break; 812045bc788SAdrian Chadd } 813045bc788SAdrian Chadd } 814045bc788SAdrian Chadd 815045bc788SAdrian Chadd /* 816eb6f0de0SAdrian Chadd * Do not exceed subframe limit. 817eb6f0de0SAdrian Chadd */ 818eb6f0de0SAdrian Chadd if ((nframes + prev_frames) >= MIN((h_baw), 819eb6f0de0SAdrian Chadd IEEE80211_AMPDU_SUBFRAME_DEFAULT)) { 820eb6f0de0SAdrian Chadd status = ATH_AGGR_LIMITED; 821eb6f0de0SAdrian Chadd break; 822eb6f0de0SAdrian Chadd } 823eb6f0de0SAdrian Chadd 824eb6f0de0SAdrian Chadd /* 825045bc788SAdrian Chadd * If the current frame has an RTS/CTS configuration 826781e7eafSAdrian Chadd * that differs from the first frame, override the 827781e7eafSAdrian Chadd * subsequent frame with this config. 828045bc788SAdrian Chadd */ 829d03904f1SAdrian Chadd if (bf != bf_first) { 830781e7eafSAdrian Chadd bf->bf_state.bfs_txflags &= 83176af1a93SAdrian Chadd ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA); 832781e7eafSAdrian Chadd bf->bf_state.bfs_txflags |= 833781e7eafSAdrian Chadd bf_first->bf_state.bfs_txflags & 834781e7eafSAdrian Chadd (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA); 835d03904f1SAdrian Chadd } 836045bc788SAdrian Chadd 837045bc788SAdrian Chadd /* 8380b96ef63SAdrian Chadd * If the packet has a sequence number, do not 8390b96ef63SAdrian Chadd * step outside of the block-ack window. 8400b96ef63SAdrian Chadd */ 8410b96ef63SAdrian Chadd if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd, 8420b96ef63SAdrian Chadd SEQNO(bf->bf_state.bfs_seqno))) { 8430b96ef63SAdrian Chadd status = ATH_AGGR_BAW_CLOSED; 8440b96ef63SAdrian Chadd break; 8450b96ef63SAdrian Chadd } 8460b96ef63SAdrian Chadd 8470b96ef63SAdrian Chadd /* 848eb6f0de0SAdrian Chadd * this packet is part of an aggregate. 849eb6f0de0SAdrian Chadd */ 8503e6cc97fSAdrian Chadd ATH_TID_REMOVE(tid, bf, bf_list); 851eb6f0de0SAdrian Chadd 852eb6f0de0SAdrian Chadd /* The TID lock is required for the BAW update */ 853eb6f0de0SAdrian Chadd ath_tx_addto_baw(sc, an, tid, bf); 854eb6f0de0SAdrian Chadd bf->bf_state.bfs_addedbaw = 1; 855eb6f0de0SAdrian Chadd 856eb6f0de0SAdrian Chadd /* 857eb6f0de0SAdrian Chadd * XXX enforce ACK for aggregate frames (this needs to be 858eb6f0de0SAdrian Chadd * XXX handled more gracefully? 859eb6f0de0SAdrian Chadd */ 860875a9451SAdrian Chadd if (bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) { 861eb6f0de0SAdrian Chadd device_printf(sc->sc_dev, 862eb6f0de0SAdrian Chadd "%s: HAL_TXDESC_NOACK set for an aggregate frame?\n", 863eb6f0de0SAdrian Chadd __func__); 864875a9451SAdrian Chadd bf->bf_state.bfs_txflags &= (~HAL_TXDESC_NOACK); 865eb6f0de0SAdrian Chadd } 866eb6f0de0SAdrian Chadd 867eb6f0de0SAdrian Chadd /* 868eb6f0de0SAdrian Chadd * Add the now owned buffer (which isn't 869eb6f0de0SAdrian Chadd * on the software TXQ any longer) to our 870eb6f0de0SAdrian Chadd * aggregate frame list. 871eb6f0de0SAdrian Chadd */ 872eb6f0de0SAdrian Chadd TAILQ_INSERT_TAIL(bf_q, bf, bf_list); 873eb6f0de0SAdrian Chadd nframes ++; 874eb6f0de0SAdrian Chadd 875eb6f0de0SAdrian Chadd /* Completion handler */ 876eb6f0de0SAdrian Chadd bf->bf_comp = ath_tx_aggr_comp; 877eb6f0de0SAdrian Chadd 878eb6f0de0SAdrian Chadd /* 879eb6f0de0SAdrian Chadd * add padding for previous frame to aggregation length 880eb6f0de0SAdrian Chadd */ 881eb6f0de0SAdrian Chadd al += bpad + al_delta; 882eb6f0de0SAdrian Chadd 883eb6f0de0SAdrian Chadd /* 884eb6f0de0SAdrian Chadd * Calculate delimiters needed for the current frame 885eb6f0de0SAdrian Chadd */ 886eb6f0de0SAdrian Chadd bf->bf_state.bfs_ndelim = 887eb6f0de0SAdrian Chadd ath_compute_num_delims(sc, bf_first, 888eb6f0de0SAdrian Chadd bf->bf_state.bfs_pktlen); 889eb6f0de0SAdrian Chadd 890eb6f0de0SAdrian Chadd /* 891eb6f0de0SAdrian Chadd * Calculate the padding needed from this set of delimiters, 892eb6f0de0SAdrian Chadd * used when calculating if the next frame will fit in 893eb6f0de0SAdrian Chadd * the aggregate. 894eb6f0de0SAdrian Chadd */ 895eb6f0de0SAdrian Chadd bpad = PADBYTES(al_delta) + (bf->bf_state.bfs_ndelim << 2); 896eb6f0de0SAdrian Chadd 897eb6f0de0SAdrian Chadd /* 898eb6f0de0SAdrian Chadd * Chain the buffers together 899eb6f0de0SAdrian Chadd */ 900eb6f0de0SAdrian Chadd if (bf_prev) 901eb6f0de0SAdrian Chadd bf_prev->bf_next = bf; 902eb6f0de0SAdrian Chadd bf_prev = bf; 903eb6f0de0SAdrian Chadd 904eb6f0de0SAdrian Chadd /* 90522a3aee6SAdrian Chadd * If we're leaking frames, just return at this point; 90622a3aee6SAdrian Chadd * we've queued a single frame and we don't want to add 90722a3aee6SAdrian Chadd * any more. 908eb6f0de0SAdrian Chadd */ 90922a3aee6SAdrian Chadd if (tid->an->an_leak_count) { 91022a3aee6SAdrian Chadd status = ATH_AGGR_LEAK_CLOSED; 91122a3aee6SAdrian Chadd break; 91222a3aee6SAdrian Chadd } 913eb6f0de0SAdrian Chadd 914eb6f0de0SAdrian Chadd #if 0 915eb6f0de0SAdrian Chadd /* 916eb6f0de0SAdrian Chadd * terminate aggregation on a small packet boundary 917eb6f0de0SAdrian Chadd */ 918eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_pktlen < ATH_AGGR_MINPLEN) { 919eb6f0de0SAdrian Chadd status = ATH_AGGR_SHORTPKT; 920eb6f0de0SAdrian Chadd break; 921eb6f0de0SAdrian Chadd } 922eb6f0de0SAdrian Chadd #endif 923eb6f0de0SAdrian Chadd 924eb6f0de0SAdrian Chadd } 925eb6f0de0SAdrian Chadd 926eb6f0de0SAdrian Chadd finish: 927eb6f0de0SAdrian Chadd /* 928eb6f0de0SAdrian Chadd * Just in case the list was empty when we tried to 929eb6f0de0SAdrian Chadd * dequeue a packet .. 930eb6f0de0SAdrian Chadd */ 931eb6f0de0SAdrian Chadd if (bf_first) { 932eb6f0de0SAdrian Chadd bf_first->bf_state.bfs_al = al; 933eb6f0de0SAdrian Chadd bf_first->bf_state.bfs_nframes = nframes; 934eb6f0de0SAdrian Chadd } 935eb6f0de0SAdrian Chadd return status; 936eb6f0de0SAdrian Chadd } 937