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; 230eb6f0de0SAdrian Chadd 231eb6f0de0SAdrian Chadd for (i = 0; i < ATH_RC_NUM; i++) { 232eb6f0de0SAdrian Chadd rc[i].flags = 0; 233eb6f0de0SAdrian Chadd if (rc[i].tries == 0) 234eb6f0de0SAdrian Chadd continue; 235eb6f0de0SAdrian Chadd 236eb6f0de0SAdrian Chadd rate = rt->info[rc[i].rix].rateCode; 237eb6f0de0SAdrian Chadd 238eb6f0de0SAdrian Chadd /* 239eb6f0de0SAdrian Chadd * XXX only do this for legacy rates? 240eb6f0de0SAdrian Chadd */ 241eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_shpream) 242eb6f0de0SAdrian Chadd rate |= rt->info[rc[i].rix].shortPreamble; 243eb6f0de0SAdrian Chadd 244eb6f0de0SAdrian Chadd /* 245eb6f0de0SAdrian Chadd * Save this, used by the TX and completion code 246eb6f0de0SAdrian Chadd */ 247eb6f0de0SAdrian Chadd rc[i].ratecode = rate; 248eb6f0de0SAdrian Chadd 249875a9451SAdrian Chadd if (bf->bf_state.bfs_txflags & 250eb6f0de0SAdrian Chadd (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) 251eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_RTSCTS_FLAG; 252eb6f0de0SAdrian Chadd 253eb6f0de0SAdrian Chadd /* Only enable shortgi, 2040, dual-stream if HT is set */ 254eb6f0de0SAdrian Chadd if (IS_HT_RATE(rate)) { 255eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_HT_FLAG; 256eb6f0de0SAdrian Chadd 257eb6f0de0SAdrian Chadd if (ni->ni_chw == 40) 258eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_CW40_FLAG; 259eb6f0de0SAdrian Chadd 260eb6f0de0SAdrian Chadd if (ni->ni_chw == 40 && 261eb6f0de0SAdrian Chadd ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 && 262eb6f0de0SAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) 263eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_SGI_FLAG; 264eb6f0de0SAdrian Chadd 265eb6f0de0SAdrian Chadd if (ni->ni_chw == 20 && 266eb6f0de0SAdrian Chadd ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 && 267eb6f0de0SAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) 268eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_SGI_FLAG; 269eb6f0de0SAdrian Chadd 270eb6f0de0SAdrian Chadd /* XXX dual stream? and 3-stream? */ 271eb6f0de0SAdrian Chadd } 272eb6f0de0SAdrian Chadd 273eb6f0de0SAdrian Chadd /* 274eb6f0de0SAdrian Chadd * Calculate the maximum 4ms frame length based 275eb6f0de0SAdrian Chadd * on the MCS rate, SGI and channel width flags. 276eb6f0de0SAdrian Chadd */ 277eb6f0de0SAdrian Chadd if ((rc[i].flags & ATH_RC_HT_FLAG) && 278eb6f0de0SAdrian Chadd (HT_RC_2_MCS(rate) < 32)) { 279eb6f0de0SAdrian Chadd int j; 280eb6f0de0SAdrian Chadd if (rc[i].flags & ATH_RC_CW40_FLAG) { 281eb6f0de0SAdrian Chadd if (rc[i].flags & ATH_RC_SGI_FLAG) 282eb6f0de0SAdrian Chadd j = MCS_HT40_SGI; 283eb6f0de0SAdrian Chadd else 284eb6f0de0SAdrian Chadd j = MCS_HT40; 285eb6f0de0SAdrian Chadd } else { 286eb6f0de0SAdrian Chadd if (rc[i].flags & ATH_RC_SGI_FLAG) 287eb6f0de0SAdrian Chadd j = MCS_HT20_SGI; 288eb6f0de0SAdrian Chadd else 289eb6f0de0SAdrian Chadd j = MCS_HT20; 290eb6f0de0SAdrian Chadd } 291eb6f0de0SAdrian Chadd rc[i].max4msframelen = 292eb6f0de0SAdrian Chadd ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)]; 293eb6f0de0SAdrian Chadd } else 294eb6f0de0SAdrian Chadd rc[i].max4msframelen = 0; 295eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, 296eb6f0de0SAdrian Chadd "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n", 297eb6f0de0SAdrian Chadd __func__, i, rate, rc[i].flags, rc[i].max4msframelen); 298eb6f0de0SAdrian Chadd } 299eb6f0de0SAdrian Chadd } 300eb6f0de0SAdrian Chadd 301eb6f0de0SAdrian Chadd /* 302eb6f0de0SAdrian Chadd * Return the number of delimiters to be added to 303eb6f0de0SAdrian Chadd * meet the minimum required mpdudensity. 304eb6f0de0SAdrian Chadd * 305eb6f0de0SAdrian Chadd * Caller should make sure that the rate is HT. 306eb6f0de0SAdrian Chadd * 307eb6f0de0SAdrian Chadd * TODO: is this delimiter calculation supposed to be the 308eb6f0de0SAdrian Chadd * total frame length, the hdr length, the data length (including 309eb6f0de0SAdrian Chadd * delimiters, padding, CRC, etc) or ? 310eb6f0de0SAdrian Chadd * 311eb6f0de0SAdrian Chadd * TODO: this should ensure that the rate control information 312eb6f0de0SAdrian Chadd * HAS been setup for the first rate. 313eb6f0de0SAdrian Chadd * 314eb6f0de0SAdrian Chadd * TODO: ensure this is only called for MCS rates. 315eb6f0de0SAdrian Chadd * 316eb6f0de0SAdrian Chadd * TODO: enforce MCS < 31 317eb6f0de0SAdrian Chadd */ 318eb6f0de0SAdrian Chadd static int 319eb6f0de0SAdrian Chadd ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf, 320eb6f0de0SAdrian Chadd uint16_t pktlen) 321eb6f0de0SAdrian Chadd { 322eb6f0de0SAdrian Chadd const HAL_RATE_TABLE *rt = sc->sc_currates; 323eb6f0de0SAdrian Chadd struct ieee80211_node *ni = first_bf->bf_node; 324eb6f0de0SAdrian Chadd struct ieee80211vap *vap = ni->ni_vap; 325eb6f0de0SAdrian Chadd int ndelim, mindelim = 0; 326eb6f0de0SAdrian Chadd int mpdudensity; /* in 1/100'th of a microsecond */ 327eb6f0de0SAdrian Chadd uint8_t rc, rix, flags; 328eb6f0de0SAdrian Chadd int width, half_gi; 329eb6f0de0SAdrian Chadd uint32_t nsymbits, nsymbols; 330eb6f0de0SAdrian Chadd uint16_t minlen; 331eb6f0de0SAdrian Chadd 332eb6f0de0SAdrian Chadd /* 333eb6f0de0SAdrian Chadd * vap->iv_ampdu_density is a value, rather than the actual 334eb6f0de0SAdrian Chadd * density. 335eb6f0de0SAdrian Chadd */ 336eb6f0de0SAdrian Chadd if (vap->iv_ampdu_density > IEEE80211_HTCAP_MPDUDENSITY_16) 337eb6f0de0SAdrian Chadd mpdudensity = 1600; /* maximum density */ 338eb6f0de0SAdrian Chadd else 339eb6f0de0SAdrian Chadd mpdudensity = ieee80211_mpdudensity_map[vap->iv_ampdu_density]; 340eb6f0de0SAdrian Chadd 341eb6f0de0SAdrian Chadd /* Select standard number of delimiters based on frame length */ 342eb6f0de0SAdrian Chadd ndelim = ATH_AGGR_GET_NDELIM(pktlen); 343eb6f0de0SAdrian Chadd 344eb6f0de0SAdrian Chadd /* 345eb6f0de0SAdrian Chadd * If encryption is enabled, add extra delimiters to let the 346eb6f0de0SAdrian Chadd * crypto hardware catch up. This could be tuned per-MAC and 347eb6f0de0SAdrian Chadd * per-rate, but for now we'll simply assume encryption is 348eb6f0de0SAdrian Chadd * always enabled. 349*4a502c33SAdrian Chadd * 350*4a502c33SAdrian Chadd * Also note that the Atheros reference driver inserts two 351*4a502c33SAdrian Chadd * delimiters by default for pre-AR9380 peers. This will 352*4a502c33SAdrian Chadd * include "that" required delimiter. 353eb6f0de0SAdrian Chadd */ 354eb6f0de0SAdrian Chadd ndelim += ATH_AGGR_ENCRYPTDELIM; 355eb6f0de0SAdrian Chadd 35664dbfc6dSAdrian Chadd /* 35764dbfc6dSAdrian Chadd * For AR9380, there's a minimum number of delimeters 35864dbfc6dSAdrian Chadd * required when doing RTS. 359*4a502c33SAdrian Chadd * 360*4a502c33SAdrian Chadd * XXX TODO: this is only needed if (a) RTS/CTS is enabled, and 361*4a502c33SAdrian Chadd * XXX (b) this is the first sub-frame in the aggregate. 36264dbfc6dSAdrian Chadd */ 36364dbfc6dSAdrian Chadd if (sc->sc_use_ent && (sc->sc_ent_cfg & AH_ENT_RTSCTS_DELIM_WAR) 36464dbfc6dSAdrian Chadd && ndelim < AH_FIRST_DESC_NDELIMS) 36564dbfc6dSAdrian Chadd ndelim = AH_FIRST_DESC_NDELIMS; 36664dbfc6dSAdrian Chadd 367eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, 368eb6f0de0SAdrian Chadd "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n", 369eb6f0de0SAdrian Chadd __func__, pktlen, ndelim, mpdudensity); 370eb6f0de0SAdrian Chadd 371eb6f0de0SAdrian Chadd /* 372eb6f0de0SAdrian Chadd * If the MPDU density is 0, we can return here. 373eb6f0de0SAdrian Chadd * Otherwise, we need to convert the desired mpdudensity 374eb6f0de0SAdrian Chadd * into a byte length, based on the rate in the subframe. 375eb6f0de0SAdrian Chadd */ 376eb6f0de0SAdrian Chadd if (mpdudensity == 0) 377eb6f0de0SAdrian Chadd return ndelim; 378eb6f0de0SAdrian Chadd 379eb6f0de0SAdrian Chadd /* 380eb6f0de0SAdrian Chadd * Convert desired mpdu density from microeconds to bytes based 381eb6f0de0SAdrian Chadd * on highest rate in rate series (i.e. first rate) to determine 382eb6f0de0SAdrian Chadd * required minimum length for subframe. Take into account 383eb6f0de0SAdrian Chadd * whether high rate is 20 or 40Mhz and half or full GI. 384eb6f0de0SAdrian Chadd */ 385eb6f0de0SAdrian Chadd rix = first_bf->bf_state.bfs_rc[0].rix; 386eb6f0de0SAdrian Chadd rc = rt->info[rix].rateCode; 387eb6f0de0SAdrian Chadd flags = first_bf->bf_state.bfs_rc[0].flags; 388eb6f0de0SAdrian Chadd width = !! (flags & ATH_RC_CW40_FLAG); 389eb6f0de0SAdrian Chadd half_gi = !! (flags & ATH_RC_SGI_FLAG); 390eb6f0de0SAdrian Chadd 391eb6f0de0SAdrian Chadd /* 392eb6f0de0SAdrian Chadd * mpdudensity is in 1/100th of a usec, so divide by 100 393eb6f0de0SAdrian Chadd */ 394eb6f0de0SAdrian Chadd if (half_gi) 395eb6f0de0SAdrian Chadd nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); 396eb6f0de0SAdrian Chadd else 397eb6f0de0SAdrian Chadd nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity); 398eb6f0de0SAdrian Chadd nsymbols /= 100; 399eb6f0de0SAdrian Chadd 400eb6f0de0SAdrian Chadd if (nsymbols == 0) 401eb6f0de0SAdrian Chadd nsymbols = 1; 402eb6f0de0SAdrian Chadd 403eb6f0de0SAdrian Chadd nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; 404eb6f0de0SAdrian Chadd minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; 405eb6f0de0SAdrian Chadd 406eb6f0de0SAdrian Chadd /* 407eb6f0de0SAdrian Chadd * Min length is the minimum frame length for the 408eb6f0de0SAdrian Chadd * required MPDU density. 409eb6f0de0SAdrian Chadd */ 410eb6f0de0SAdrian Chadd if (pktlen < minlen) { 411eb6f0de0SAdrian Chadd mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ; 412eb6f0de0SAdrian Chadd ndelim = MAX(mindelim, ndelim); 413eb6f0de0SAdrian Chadd } 414eb6f0de0SAdrian Chadd 415eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, 416eb6f0de0SAdrian Chadd "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n", 417eb6f0de0SAdrian Chadd __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim); 418eb6f0de0SAdrian Chadd 419eb6f0de0SAdrian Chadd return ndelim; 420eb6f0de0SAdrian Chadd } 421eb6f0de0SAdrian Chadd 422eb6f0de0SAdrian Chadd /* 423eb6f0de0SAdrian Chadd * Fetch the aggregation limit. 424eb6f0de0SAdrian Chadd * 425eb6f0de0SAdrian Chadd * It's the lowest of the four rate series 4ms frame length. 426eb6f0de0SAdrian Chadd */ 427eb6f0de0SAdrian Chadd static int 428eb6f0de0SAdrian Chadd ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf) 429eb6f0de0SAdrian Chadd { 430*4a502c33SAdrian Chadd int amin = ATH_AGGR_MAXSIZE; 431eb6f0de0SAdrian Chadd int i; 432eb6f0de0SAdrian Chadd 433*4a502c33SAdrian Chadd if (sc->sc_aggr_limit > 0 && sc->sc_aggr_limit < ATH_AGGR_MAXSIZE) 434*4a502c33SAdrian Chadd amin = sc->sc_aggr_limit; 435*4a502c33SAdrian Chadd 436b25c1f2aSAdrian Chadd for (i = 0; i < ATH_RC_NUM; i++) { 437eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_rc[i].tries == 0) 438eb6f0de0SAdrian Chadd continue; 439eb6f0de0SAdrian Chadd amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen); 440eb6f0de0SAdrian Chadd } 441eb6f0de0SAdrian Chadd 442eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: max frame len= %d\n", 443eb6f0de0SAdrian Chadd __func__, amin); 444eb6f0de0SAdrian Chadd 445eb6f0de0SAdrian Chadd return amin; 446eb6f0de0SAdrian Chadd } 4474b44f6f2SAdrian Chadd 4484b44f6f2SAdrian Chadd /* 4494b44f6f2SAdrian Chadd * Setup a 11n rate series structure 4504b44f6f2SAdrian Chadd * 4514b44f6f2SAdrian Chadd * This should be called for both legacy and MCS rates. 452eb6f0de0SAdrian Chadd * 453eb6f0de0SAdrian Chadd * It, along with ath_buf_set_rate, must be called -after- a burst 454eb6f0de0SAdrian Chadd * or aggregate is setup. 4554b44f6f2SAdrian Chadd */ 4564b44f6f2SAdrian Chadd static void 4574b44f6f2SAdrian Chadd ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, 458eb6f0de0SAdrian Chadd struct ath_buf *bf, HAL_11N_RATE_SERIES *series) 4594b44f6f2SAdrian Chadd { 4604b44f6f2SAdrian Chadd struct ieee80211com *ic = ni->ni_ic; 4614b44f6f2SAdrian Chadd struct ath_hal *ah = sc->sc_ah; 4624b44f6f2SAdrian Chadd HAL_BOOL shortPreamble = AH_FALSE; 4634b44f6f2SAdrian Chadd const HAL_RATE_TABLE *rt = sc->sc_currates; 4644b44f6f2SAdrian Chadd int i; 465eb6f0de0SAdrian Chadd int pktlen; 466875a9451SAdrian Chadd int flags = bf->bf_state.bfs_txflags; 467eb6f0de0SAdrian Chadd struct ath_rc_series *rc = bf->bf_state.bfs_rc; 4684b44f6f2SAdrian Chadd 4694b44f6f2SAdrian Chadd if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 4704b44f6f2SAdrian Chadd (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) 4714b44f6f2SAdrian Chadd shortPreamble = AH_TRUE; 4724b44f6f2SAdrian Chadd 473eb6f0de0SAdrian Chadd /* 474eb6f0de0SAdrian Chadd * If this is the first frame in an aggregate series, 475eb6f0de0SAdrian Chadd * use the aggregate length. 476eb6f0de0SAdrian Chadd */ 477eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_aggr) 478eb6f0de0SAdrian Chadd pktlen = bf->bf_state.bfs_al; 479eb6f0de0SAdrian Chadd else 480eb6f0de0SAdrian Chadd pktlen = bf->bf_state.bfs_pktlen; 481eb6f0de0SAdrian Chadd 482eb6f0de0SAdrian Chadd /* 483eb6f0de0SAdrian Chadd * XXX TODO: modify this routine to use the bfs_rc[x].flags 484eb6f0de0SAdrian Chadd * XXX fields. 485eb6f0de0SAdrian Chadd */ 4864b44f6f2SAdrian Chadd memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4); 487b25c1f2aSAdrian Chadd for (i = 0; i < ATH_RC_NUM; i++) { 488146b49d8SAdrian Chadd /* Only set flags for actual TX attempts */ 489eb6f0de0SAdrian Chadd if (rc[i].tries == 0) 490146b49d8SAdrian Chadd continue; 491146b49d8SAdrian Chadd 492eb6f0de0SAdrian Chadd series[i].Tries = rc[i].tries; 493146b49d8SAdrian Chadd 494146b49d8SAdrian Chadd /* 495146b49d8SAdrian Chadd * XXX this isn't strictly correct - sc_txchainmask 496146b49d8SAdrian Chadd * XXX isn't the currently active chainmask; 497146b49d8SAdrian Chadd * XXX it's the interface chainmask at startup. 498146b49d8SAdrian Chadd * XXX It's overridden in the HAL rate scenario function 499146b49d8SAdrian Chadd * XXX for now. 500146b49d8SAdrian Chadd */ 501*4a502c33SAdrian Chadd /* 502*4a502c33SAdrian Chadd * XXX TODO: When the NIC is capable of three stream TX, 503*4a502c33SAdrian Chadd * transmit 1/2 stream rates on two streams. 504*4a502c33SAdrian Chadd * 505*4a502c33SAdrian Chadd * This reduces the power consumption of the NIC and 506*4a502c33SAdrian Chadd * keeps it within the PCIe slot power limits. 507*4a502c33SAdrian Chadd */ 5084b44f6f2SAdrian Chadd series[i].ChSel = sc->sc_txchainmask; 509146b49d8SAdrian Chadd 5102b5684a8SAdrian Chadd if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) 5114b44f6f2SAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_RTS_CTS; 512146b49d8SAdrian Chadd 513532f2442SAdrian Chadd /* 514532f2442SAdrian Chadd * Transmit 40MHz frames only if the node has negotiated 515532f2442SAdrian Chadd * it rather than whether the node is capable of it or not. 516532f2442SAdrian Chadd * It's subtly different in the hostap case. 517532f2442SAdrian Chadd */ 518532f2442SAdrian Chadd if (ni->ni_chw == 40) 5194b44f6f2SAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_2040; 5206246be6eSAdrian Chadd 5217842451aSAdrian Chadd /* 5226246be6eSAdrian Chadd * Set short-GI only if the node has advertised it 5236246be6eSAdrian Chadd * the channel width is suitable, and we support it. 5246246be6eSAdrian Chadd * We don't currently have a "negotiated" set of bits - 5256246be6eSAdrian Chadd * ni_htcap is what the remote end sends, not what this 5266246be6eSAdrian Chadd * node is capable of. 5277842451aSAdrian Chadd */ 5286246be6eSAdrian Chadd if (ni->ni_chw == 40 && 5296246be6eSAdrian Chadd ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 && 5306246be6eSAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) 5314b44f6f2SAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_HALFGI; 5326246be6eSAdrian Chadd 5336246be6eSAdrian Chadd if (ni->ni_chw == 20 && 5346246be6eSAdrian Chadd ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 && 5356246be6eSAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) 5366246be6eSAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_HALFGI; 5374b44f6f2SAdrian Chadd 538eb6f0de0SAdrian Chadd series[i].Rate = rt->info[rc[i].rix].rateCode; 5393e647f1cSAdrian Chadd series[i].RateIndex = rc[i].rix; 5403e647f1cSAdrian Chadd series[i].tx_power_cap = 0x3f; /* XXX for now */ 5414b44f6f2SAdrian Chadd 542b25c1f2aSAdrian Chadd /* 543b25c1f2aSAdrian Chadd * PktDuration doesn't include slot, ACK, RTS, etc timing - 544b25c1f2aSAdrian Chadd * it's just the packet duration 545b25c1f2aSAdrian Chadd */ 5469a97e25eSAdrian Chadd if (series[i].Rate & IEEE80211_RATE_MCS) { 5474b44f6f2SAdrian Chadd series[i].PktDuration = 5484b44f6f2SAdrian Chadd ath_computedur_ht(pktlen 5499a97e25eSAdrian Chadd , series[i].Rate 550fce6d676SAdrian Chadd , HT_RC_2_STREAMS(series[i].Rate) 551fce6d676SAdrian Chadd , series[i].RateFlags & HAL_RATESERIES_2040 552f449ab1cSAdrian Chadd , series[i].RateFlags & HAL_RATESERIES_HALFGI); 5534b44f6f2SAdrian Chadd } else { 5541198947aSAdrian Chadd if (shortPreamble) 555eb6f0de0SAdrian Chadd series[i].Rate |= 556eb6f0de0SAdrian Chadd rt->info[rc[i].rix].shortPreamble; 5574b44f6f2SAdrian Chadd series[i].PktDuration = ath_hal_computetxtime(ah, 558eb6f0de0SAdrian Chadd rt, pktlen, rc[i].rix, shortPreamble); 5594b44f6f2SAdrian Chadd } 5604b44f6f2SAdrian Chadd } 5614b44f6f2SAdrian Chadd } 5624b44f6f2SAdrian Chadd 5634b44f6f2SAdrian Chadd #if 0 5644b44f6f2SAdrian Chadd static void 565b25c1f2aSAdrian Chadd ath_rateseries_print(struct ath_softc *sc, HAL_11N_RATE_SERIES *series) 5664b44f6f2SAdrian Chadd { 5674b44f6f2SAdrian Chadd int i; 568b25c1f2aSAdrian Chadd for (i = 0; i < ATH_RC_NUM; i++) { 569b25c1f2aSAdrian Chadd device_printf(sc->sc_dev ,"series %d: rate %x; tries %d; " 57064dbfc6dSAdrian Chadd "pktDuration %d; chSel %d; txpowcap %d, rateFlags %x\n", 5714b44f6f2SAdrian Chadd i, 5724b44f6f2SAdrian Chadd series[i].Rate, 5734b44f6f2SAdrian Chadd series[i].Tries, 5744b44f6f2SAdrian Chadd series[i].PktDuration, 5754b44f6f2SAdrian Chadd series[i].ChSel, 57664dbfc6dSAdrian Chadd series[i].tx_power_cap, 5774b44f6f2SAdrian Chadd series[i].RateFlags); 5784b44f6f2SAdrian Chadd } 5794b44f6f2SAdrian Chadd } 5804b44f6f2SAdrian Chadd #endif 5814b44f6f2SAdrian Chadd 5824b44f6f2SAdrian Chadd /* 5834b44f6f2SAdrian Chadd * Setup the 11n rate scenario and burst duration for the given TX descriptor 5844b44f6f2SAdrian Chadd * list. 5854b44f6f2SAdrian Chadd * 5864b44f6f2SAdrian Chadd * This isn't useful for sending beacon frames, which has different needs 5874b44f6f2SAdrian Chadd * wrt what's passed into the rate scenario function. 5884b44f6f2SAdrian Chadd */ 5894b44f6f2SAdrian Chadd void 590eb6f0de0SAdrian Chadd ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, 591eb6f0de0SAdrian Chadd struct ath_buf *bf) 5924b44f6f2SAdrian Chadd { 5934b44f6f2SAdrian Chadd HAL_11N_RATE_SERIES series[4]; 5944b44f6f2SAdrian Chadd struct ath_desc *ds = bf->bf_desc; 5954b44f6f2SAdrian Chadd struct ath_hal *ah = sc->sc_ah; 596eb6f0de0SAdrian Chadd int is_pspoll = (bf->bf_state.bfs_atype == HAL_PKT_TYPE_PSPOLL); 597eb6f0de0SAdrian Chadd int ctsrate = bf->bf_state.bfs_ctsrate; 598875a9451SAdrian Chadd int flags = bf->bf_state.bfs_txflags; 5994b44f6f2SAdrian Chadd 6004b44f6f2SAdrian Chadd /* Setup rate scenario */ 6014b44f6f2SAdrian Chadd memset(&series, 0, sizeof(series)); 6024b44f6f2SAdrian Chadd 603eb6f0de0SAdrian Chadd ath_rateseries_setup(sc, ni, bf, series); 6044b44f6f2SAdrian Chadd 6052b5684a8SAdrian Chadd #if 0 606b25c1f2aSAdrian Chadd ath_rateseries_print(sc, series); 6072b5684a8SAdrian Chadd #endif 6082b5684a8SAdrian Chadd 6094b44f6f2SAdrian Chadd /* Set rate scenario */ 610b25c1f2aSAdrian Chadd /* 611b25c1f2aSAdrian Chadd * Note: Don't allow hardware to override the duration on 612b25c1f2aSAdrian Chadd * ps-poll packets. 613b25c1f2aSAdrian Chadd */ 6144b44f6f2SAdrian Chadd ath_hal_set11nratescenario(ah, ds, 615bf26df36SAdrian Chadd !is_pspoll, /* whether to override the duration or not */ 6164b44f6f2SAdrian Chadd ctsrate, /* rts/cts rate */ 6174b44f6f2SAdrian Chadd series, /* 11n rate series */ 6184b44f6f2SAdrian Chadd 4, /* number of series */ 6194b44f6f2SAdrian Chadd flags); 6204b44f6f2SAdrian Chadd 6214b44f6f2SAdrian Chadd /* Set burst duration */ 622eb6f0de0SAdrian Chadd /* 623eb6f0de0SAdrian Chadd * This is only required when doing 11n burst, not aggregation 624eb6f0de0SAdrian Chadd * ie, if there's a second frame in a RIFS or A-MPDU burst 625eb6f0de0SAdrian Chadd * w/ >1 A-MPDU frame bursting back to back. 626eb6f0de0SAdrian Chadd * Normal A-MPDU doesn't do bursting -between- aggregates. 627eb6f0de0SAdrian Chadd * 628eb6f0de0SAdrian Chadd * .. and it's highly likely this won't ever be implemented 629eb6f0de0SAdrian Chadd */ 6304b44f6f2SAdrian Chadd //ath_hal_set11nburstduration(ah, ds, 8192); 6314b44f6f2SAdrian Chadd } 632eb6f0de0SAdrian Chadd 633eb6f0de0SAdrian Chadd /* 634eb6f0de0SAdrian Chadd * Form an aggregate packet list. 635eb6f0de0SAdrian Chadd * 636eb6f0de0SAdrian Chadd * This function enforces the aggregate restrictions/requirements. 637eb6f0de0SAdrian Chadd * 638eb6f0de0SAdrian Chadd * These are: 639eb6f0de0SAdrian Chadd * 640eb6f0de0SAdrian Chadd * + The aggregate size maximum (64k for AR9160 and later, 8K for 641eb6f0de0SAdrian Chadd * AR5416 when doing RTS frame protection.) 642eb6f0de0SAdrian Chadd * + Maximum number of sub-frames for an aggregate 643eb6f0de0SAdrian Chadd * + The aggregate delimiter size, giving MACs time to do whatever is 644eb6f0de0SAdrian Chadd * needed before each frame 645eb6f0de0SAdrian Chadd * + Enforce the BAW limit 646eb6f0de0SAdrian Chadd * 647eb6f0de0SAdrian Chadd * Each descriptor queued should have the DMA setup. 648eb6f0de0SAdrian Chadd * The rate series, descriptor setup, linking, etc is all done 649eb6f0de0SAdrian Chadd * externally. This routine simply chains them together. 650eb6f0de0SAdrian Chadd * ath_tx_setds_11n() will take care of configuring the per- 651eb6f0de0SAdrian Chadd * descriptor setup, and ath_buf_set_rate() will configure the 652eb6f0de0SAdrian Chadd * rate control. 653eb6f0de0SAdrian Chadd * 654b25c1f2aSAdrian Chadd * The TID lock is required for the entirety of this function. 655b25c1f2aSAdrian Chadd * 656b25c1f2aSAdrian Chadd * If some code in another thread adds to the head of this 657eb6f0de0SAdrian Chadd * list, very strange behaviour will occur. Since retransmission is the 658eb6f0de0SAdrian Chadd * only reason this will occur, and this routine is designed to be called 659eb6f0de0SAdrian Chadd * from within the scheduler task, it won't ever clash with the completion 660eb6f0de0SAdrian Chadd * task. 661eb6f0de0SAdrian Chadd * 662eb6f0de0SAdrian Chadd * So if you want to call this from an upper layer context (eg, to direct- 663eb6f0de0SAdrian Chadd * dispatch aggregate frames to the hardware), please keep this in mind. 664eb6f0de0SAdrian Chadd */ 665eb6f0de0SAdrian Chadd ATH_AGGR_STATUS 666b25c1f2aSAdrian Chadd ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, 667b25c1f2aSAdrian Chadd struct ath_tid *tid, ath_bufhead *bf_q) 668eb6f0de0SAdrian Chadd { 669a108d2d6SAdrian Chadd //struct ieee80211_node *ni = &an->an_node; 670eb6f0de0SAdrian Chadd struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL; 671eb6f0de0SAdrian Chadd int nframes = 0; 672eb6f0de0SAdrian Chadd uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw; 673eb6f0de0SAdrian Chadd struct ieee80211_tx_ampdu *tap; 674eb6f0de0SAdrian Chadd int status = ATH_AGGR_DONE; 675eb6f0de0SAdrian Chadd int prev_frames = 0; /* XXX for AR5416 burst, not done here */ 676eb6f0de0SAdrian Chadd int prev_al = 0; /* XXX also for AR5416 burst */ 677eb6f0de0SAdrian Chadd 678375307d4SAdrian Chadd ATH_TX_LOCK_ASSERT(sc); 679eb6f0de0SAdrian Chadd 680eb6f0de0SAdrian Chadd tap = ath_tx_get_tx_tid(an, tid->tid); 681eb6f0de0SAdrian Chadd if (tap == NULL) { 682eb6f0de0SAdrian Chadd status = ATH_AGGR_ERROR; 683eb6f0de0SAdrian Chadd goto finish; 684eb6f0de0SAdrian Chadd } 685eb6f0de0SAdrian Chadd 686eb6f0de0SAdrian Chadd h_baw = tap->txa_wnd / 2; 687eb6f0de0SAdrian Chadd 688eb6f0de0SAdrian Chadd for (;;) { 6893e6cc97fSAdrian Chadd bf = ATH_TID_FIRST(tid); 690eb6f0de0SAdrian Chadd if (bf_first == NULL) 691eb6f0de0SAdrian Chadd bf_first = bf; 692eb6f0de0SAdrian Chadd if (bf == NULL) { 693eb6f0de0SAdrian Chadd status = ATH_AGGR_DONE; 694eb6f0de0SAdrian Chadd break; 695eb6f0de0SAdrian Chadd } else { 696eb6f0de0SAdrian Chadd /* 697eb6f0de0SAdrian Chadd * It's the first frame; 698eb6f0de0SAdrian Chadd * set the aggregation limit based on the 699eb6f0de0SAdrian Chadd * rate control decision that has been made. 700eb6f0de0SAdrian Chadd */ 701eb6f0de0SAdrian Chadd aggr_limit = ath_get_aggr_limit(sc, bf_first); 702eb6f0de0SAdrian Chadd } 703eb6f0de0SAdrian Chadd 704eb6f0de0SAdrian Chadd /* Set this early just so things don't get confused */ 705eb6f0de0SAdrian Chadd bf->bf_next = NULL; 706eb6f0de0SAdrian Chadd 707eb6f0de0SAdrian Chadd /* 708eb6f0de0SAdrian Chadd * If the frame doesn't have a sequence number that we're 709eb6f0de0SAdrian Chadd * tracking in the BAW (eg NULL QOS data frame), we can't 710eb6f0de0SAdrian Chadd * aggregate it. Stop the aggregation process; the sender 711eb6f0de0SAdrian Chadd * can then TX what's in the list thus far and then 712eb6f0de0SAdrian Chadd * TX the frame individually. 713eb6f0de0SAdrian Chadd */ 714eb6f0de0SAdrian Chadd if (! bf->bf_state.bfs_dobaw) { 715eb6f0de0SAdrian Chadd status = ATH_AGGR_NONAGGR; 716eb6f0de0SAdrian Chadd break; 717eb6f0de0SAdrian Chadd } 718eb6f0de0SAdrian Chadd 719eb6f0de0SAdrian Chadd /* 720eb6f0de0SAdrian Chadd * If any of the rates are non-HT, this packet 721eb6f0de0SAdrian Chadd * can't be aggregated. 722eb6f0de0SAdrian Chadd * XXX TODO: add a bf_state flag which gets marked 723eb6f0de0SAdrian Chadd * if any active rate is non-HT. 724eb6f0de0SAdrian Chadd */ 725eb6f0de0SAdrian Chadd 726eb6f0de0SAdrian Chadd /* 727eb6f0de0SAdrian Chadd * do not exceed aggregation limit 728eb6f0de0SAdrian Chadd */ 729eb6f0de0SAdrian Chadd al_delta = ATH_AGGR_DELIM_SZ + bf->bf_state.bfs_pktlen; 730eb6f0de0SAdrian Chadd if (nframes && 731eb6f0de0SAdrian Chadd (aggr_limit < (al + bpad + al_delta + prev_al))) { 732eb6f0de0SAdrian Chadd status = ATH_AGGR_LIMITED; 733eb6f0de0SAdrian Chadd break; 734eb6f0de0SAdrian Chadd } 735eb6f0de0SAdrian Chadd 736eb6f0de0SAdrian Chadd /* 737045bc788SAdrian Chadd * If RTS/CTS is set on the first frame, enforce 738045bc788SAdrian Chadd * the RTS aggregate limit. 739045bc788SAdrian Chadd */ 740045bc788SAdrian Chadd if (bf_first->bf_state.bfs_txflags & 741045bc788SAdrian Chadd (HAL_TXDESC_CTSENA | HAL_TXDESC_RTSENA)) { 742045bc788SAdrian Chadd if (nframes && 743045bc788SAdrian Chadd (sc->sc_rts_aggr_limit < 744045bc788SAdrian Chadd (al + bpad + al_delta + prev_al))) { 745045bc788SAdrian Chadd status = ATH_AGGR_8K_LIMITED; 746045bc788SAdrian Chadd break; 747045bc788SAdrian Chadd } 748045bc788SAdrian Chadd } 749045bc788SAdrian Chadd 750045bc788SAdrian Chadd /* 751eb6f0de0SAdrian Chadd * Do not exceed subframe limit. 752eb6f0de0SAdrian Chadd */ 753eb6f0de0SAdrian Chadd if ((nframes + prev_frames) >= MIN((h_baw), 754eb6f0de0SAdrian Chadd IEEE80211_AMPDU_SUBFRAME_DEFAULT)) { 755eb6f0de0SAdrian Chadd status = ATH_AGGR_LIMITED; 756eb6f0de0SAdrian Chadd break; 757eb6f0de0SAdrian Chadd } 758eb6f0de0SAdrian Chadd 759eb6f0de0SAdrian Chadd /* 760045bc788SAdrian Chadd * If the current frame has an RTS/CTS configuration 761781e7eafSAdrian Chadd * that differs from the first frame, override the 762781e7eafSAdrian Chadd * subsequent frame with this config. 763045bc788SAdrian Chadd */ 764d03904f1SAdrian Chadd if (bf != bf_first) { 765781e7eafSAdrian Chadd bf->bf_state.bfs_txflags &= 76676af1a93SAdrian Chadd ~ (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA); 767781e7eafSAdrian Chadd bf->bf_state.bfs_txflags |= 768781e7eafSAdrian Chadd bf_first->bf_state.bfs_txflags & 769781e7eafSAdrian Chadd (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA); 770d03904f1SAdrian Chadd } 771045bc788SAdrian Chadd 772045bc788SAdrian Chadd /* 7730b96ef63SAdrian Chadd * If the packet has a sequence number, do not 7740b96ef63SAdrian Chadd * step outside of the block-ack window. 7750b96ef63SAdrian Chadd */ 7760b96ef63SAdrian Chadd if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd, 7770b96ef63SAdrian Chadd SEQNO(bf->bf_state.bfs_seqno))) { 7780b96ef63SAdrian Chadd status = ATH_AGGR_BAW_CLOSED; 7790b96ef63SAdrian Chadd break; 7800b96ef63SAdrian Chadd } 7810b96ef63SAdrian Chadd 7820b96ef63SAdrian Chadd /* 783eb6f0de0SAdrian Chadd * this packet is part of an aggregate. 784eb6f0de0SAdrian Chadd */ 7853e6cc97fSAdrian Chadd ATH_TID_REMOVE(tid, bf, bf_list); 786eb6f0de0SAdrian Chadd 787eb6f0de0SAdrian Chadd /* The TID lock is required for the BAW update */ 788eb6f0de0SAdrian Chadd ath_tx_addto_baw(sc, an, tid, bf); 789eb6f0de0SAdrian Chadd bf->bf_state.bfs_addedbaw = 1; 790eb6f0de0SAdrian Chadd 791eb6f0de0SAdrian Chadd /* 792eb6f0de0SAdrian Chadd * XXX enforce ACK for aggregate frames (this needs to be 793eb6f0de0SAdrian Chadd * XXX handled more gracefully? 794eb6f0de0SAdrian Chadd */ 795875a9451SAdrian Chadd if (bf->bf_state.bfs_txflags & HAL_TXDESC_NOACK) { 796eb6f0de0SAdrian Chadd device_printf(sc->sc_dev, 797eb6f0de0SAdrian Chadd "%s: HAL_TXDESC_NOACK set for an aggregate frame?\n", 798eb6f0de0SAdrian Chadd __func__); 799875a9451SAdrian Chadd bf->bf_state.bfs_txflags &= (~HAL_TXDESC_NOACK); 800eb6f0de0SAdrian Chadd } 801eb6f0de0SAdrian Chadd 802eb6f0de0SAdrian Chadd /* 803eb6f0de0SAdrian Chadd * Add the now owned buffer (which isn't 804eb6f0de0SAdrian Chadd * on the software TXQ any longer) to our 805eb6f0de0SAdrian Chadd * aggregate frame list. 806eb6f0de0SAdrian Chadd */ 807eb6f0de0SAdrian Chadd TAILQ_INSERT_TAIL(bf_q, bf, bf_list); 808eb6f0de0SAdrian Chadd nframes ++; 809eb6f0de0SAdrian Chadd 810eb6f0de0SAdrian Chadd /* Completion handler */ 811eb6f0de0SAdrian Chadd bf->bf_comp = ath_tx_aggr_comp; 812eb6f0de0SAdrian Chadd 813eb6f0de0SAdrian Chadd /* 814eb6f0de0SAdrian Chadd * add padding for previous frame to aggregation length 815eb6f0de0SAdrian Chadd */ 816eb6f0de0SAdrian Chadd al += bpad + al_delta; 817eb6f0de0SAdrian Chadd 818eb6f0de0SAdrian Chadd /* 819eb6f0de0SAdrian Chadd * Calculate delimiters needed for the current frame 820eb6f0de0SAdrian Chadd */ 821eb6f0de0SAdrian Chadd bf->bf_state.bfs_ndelim = 822eb6f0de0SAdrian Chadd ath_compute_num_delims(sc, bf_first, 823eb6f0de0SAdrian Chadd bf->bf_state.bfs_pktlen); 824eb6f0de0SAdrian Chadd 825eb6f0de0SAdrian Chadd /* 826eb6f0de0SAdrian Chadd * Calculate the padding needed from this set of delimiters, 827eb6f0de0SAdrian Chadd * used when calculating if the next frame will fit in 828eb6f0de0SAdrian Chadd * the aggregate. 829eb6f0de0SAdrian Chadd */ 830eb6f0de0SAdrian Chadd bpad = PADBYTES(al_delta) + (bf->bf_state.bfs_ndelim << 2); 831eb6f0de0SAdrian Chadd 832eb6f0de0SAdrian Chadd /* 833eb6f0de0SAdrian Chadd * Chain the buffers together 834eb6f0de0SAdrian Chadd */ 835eb6f0de0SAdrian Chadd if (bf_prev) 836eb6f0de0SAdrian Chadd bf_prev->bf_next = bf; 837eb6f0de0SAdrian Chadd bf_prev = bf; 838eb6f0de0SAdrian Chadd 839eb6f0de0SAdrian Chadd /* 840eb6f0de0SAdrian Chadd * XXX TODO: if any sub-frames have RTS/CTS enabled; 841eb6f0de0SAdrian Chadd * enable it for the entire aggregate. 842eb6f0de0SAdrian Chadd */ 843eb6f0de0SAdrian Chadd 844eb6f0de0SAdrian Chadd #if 0 845eb6f0de0SAdrian Chadd /* 846eb6f0de0SAdrian Chadd * terminate aggregation on a small packet boundary 847eb6f0de0SAdrian Chadd */ 848eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_pktlen < ATH_AGGR_MINPLEN) { 849eb6f0de0SAdrian Chadd status = ATH_AGGR_SHORTPKT; 850eb6f0de0SAdrian Chadd break; 851eb6f0de0SAdrian Chadd } 852eb6f0de0SAdrian Chadd #endif 853eb6f0de0SAdrian Chadd 854eb6f0de0SAdrian Chadd } 855eb6f0de0SAdrian Chadd 856eb6f0de0SAdrian Chadd finish: 857eb6f0de0SAdrian Chadd /* 858eb6f0de0SAdrian Chadd * Just in case the list was empty when we tried to 859eb6f0de0SAdrian Chadd * dequeue a packet .. 860eb6f0de0SAdrian Chadd */ 861eb6f0de0SAdrian Chadd if (bf_first) { 862eb6f0de0SAdrian Chadd bf_first->bf_state.bfs_al = al; 863eb6f0de0SAdrian Chadd bf_first->bf_state.bfs_nframes = nframes; 864eb6f0de0SAdrian Chadd } 865eb6f0de0SAdrian Chadd return status; 866eb6f0de0SAdrian Chadd } 867