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 89*eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_tx.h> /* XXX for some support functions */ 904b44f6f2SAdrian Chadd #include <dev/ath/if_ath_tx_ht.h> 91*eb6f0de0SAdrian Chadd #include <dev/ath/if_athrate.h> 92*eb6f0de0SAdrian Chadd #include <dev/ath/if_ath_debug.h> 93*eb6f0de0SAdrian Chadd 94*eb6f0de0SAdrian Chadd /* 95*eb6f0de0SAdrian Chadd * XXX net80211? 96*eb6f0de0SAdrian Chadd */ 97*eb6f0de0SAdrian Chadd #define IEEE80211_AMPDU_SUBFRAME_DEFAULT 32 98*eb6f0de0SAdrian Chadd 99*eb6f0de0SAdrian Chadd #define ATH_AGGR_DELIM_SZ 4 /* delimiter size */ 100*eb6f0de0SAdrian Chadd #define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ 101*eb6f0de0SAdrian Chadd #define ATH_AGGR_ENCRYPTDELIM 10 /* number of delimiters for encryption padding */ 102*eb6f0de0SAdrian Chadd 103*eb6f0de0SAdrian Chadd /* 104*eb6f0de0SAdrian Chadd * returns delimiter padding required given the packet length 105*eb6f0de0SAdrian Chadd */ 106*eb6f0de0SAdrian Chadd #define ATH_AGGR_GET_NDELIM(_len) \ 107*eb6f0de0SAdrian Chadd (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ 108*eb6f0de0SAdrian Chadd (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) 109*eb6f0de0SAdrian Chadd 110*eb6f0de0SAdrian Chadd #define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) 111*eb6f0de0SAdrian Chadd 112*eb6f0de0SAdrian Chadd int ath_max_4ms_framelen[4][32] = { 113*eb6f0de0SAdrian Chadd [MCS_HT20] = { 114*eb6f0de0SAdrian Chadd 3212, 6432, 9648, 12864, 19300, 25736, 28952, 32172, 115*eb6f0de0SAdrian Chadd 6424, 12852, 19280, 25708, 38568, 51424, 57852, 64280, 116*eb6f0de0SAdrian Chadd 9628, 19260, 28896, 38528, 57792, 65532, 65532, 65532, 117*eb6f0de0SAdrian Chadd 12828, 25656, 38488, 51320, 65532, 65532, 65532, 65532, 118*eb6f0de0SAdrian Chadd }, 119*eb6f0de0SAdrian Chadd [MCS_HT20_SGI] = { 120*eb6f0de0SAdrian Chadd 3572, 7144, 10720, 14296, 21444, 28596, 32172, 35744, 121*eb6f0de0SAdrian Chadd 7140, 14284, 21428, 28568, 42856, 57144, 64288, 65532, 122*eb6f0de0SAdrian Chadd 10700, 21408, 32112, 42816, 64228, 65532, 65532, 65532, 123*eb6f0de0SAdrian Chadd 14256, 28516, 42780, 57040, 65532, 65532, 65532, 65532, 124*eb6f0de0SAdrian Chadd }, 125*eb6f0de0SAdrian Chadd [MCS_HT40] = { 126*eb6f0de0SAdrian Chadd 6680, 13360, 20044, 26724, 40092, 53456, 60140, 65532, 127*eb6f0de0SAdrian Chadd 13348, 26700, 40052, 53400, 65532, 65532, 65532, 65532, 128*eb6f0de0SAdrian Chadd 20004, 40008, 60016, 65532, 65532, 65532, 65532, 65532, 129*eb6f0de0SAdrian Chadd 26644, 53292, 65532, 65532, 65532, 65532, 65532, 65532, 130*eb6f0de0SAdrian Chadd }, 131*eb6f0de0SAdrian Chadd [MCS_HT40_SGI] = { 132*eb6f0de0SAdrian Chadd 7420, 14844, 22272, 29696, 44544, 59396, 65532, 65532, 133*eb6f0de0SAdrian Chadd 14832, 29668, 44504, 59340, 65532, 65532, 65532, 65532, 134*eb6f0de0SAdrian Chadd 22232, 44464, 65532, 65532, 65532, 65532, 65532, 65532, 135*eb6f0de0SAdrian Chadd 29616, 59232, 65532, 65532, 65532, 65532, 65532, 65532, 136*eb6f0de0SAdrian Chadd } 137*eb6f0de0SAdrian Chadd }; 138*eb6f0de0SAdrian Chadd 139*eb6f0de0SAdrian Chadd /* 140*eb6f0de0SAdrian Chadd * XXX should be in net80211 141*eb6f0de0SAdrian Chadd */ 142*eb6f0de0SAdrian Chadd static int ieee80211_mpdudensity_map[] = { 143*eb6f0de0SAdrian Chadd 0, /* IEEE80211_HTCAP_MPDUDENSITY_NA */ 144*eb6f0de0SAdrian Chadd 25, /* IEEE80211_HTCAP_MPDUDENSITY_025 */ 145*eb6f0de0SAdrian Chadd 50, /* IEEE80211_HTCAP_MPDUDENSITY_05 */ 146*eb6f0de0SAdrian Chadd 100, /* IEEE80211_HTCAP_MPDUDENSITY_1 */ 147*eb6f0de0SAdrian Chadd 200, /* IEEE80211_HTCAP_MPDUDENSITY_2 */ 148*eb6f0de0SAdrian Chadd 400, /* IEEE80211_HTCAP_MPDUDENSITY_4 */ 149*eb6f0de0SAdrian Chadd 800, /* IEEE80211_HTCAP_MPDUDENSITY_8 */ 150*eb6f0de0SAdrian Chadd 1600, /* IEEE80211_HTCAP_MPDUDENSITY_16 */ 151*eb6f0de0SAdrian Chadd }; 152*eb6f0de0SAdrian Chadd 153*eb6f0de0SAdrian Chadd /* 154*eb6f0de0SAdrian Chadd * XXX should be in the HAL/net80211 ? 155*eb6f0de0SAdrian Chadd */ 156*eb6f0de0SAdrian Chadd #define BITS_PER_BYTE 8 157*eb6f0de0SAdrian Chadd #define OFDM_PLCP_BITS 22 158*eb6f0de0SAdrian Chadd #define HT_RC_2_MCS(_rc) ((_rc) & 0x7f) 159*eb6f0de0SAdrian Chadd #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) 160*eb6f0de0SAdrian Chadd #define L_STF 8 161*eb6f0de0SAdrian Chadd #define L_LTF 8 162*eb6f0de0SAdrian Chadd #define L_SIG 4 163*eb6f0de0SAdrian Chadd #define HT_SIG 8 164*eb6f0de0SAdrian Chadd #define HT_STF 4 165*eb6f0de0SAdrian Chadd #define HT_LTF(_ns) (4 * (_ns)) 166*eb6f0de0SAdrian Chadd #define SYMBOL_TIME(_ns) ((_ns) << 2) // ns * 4 us 167*eb6f0de0SAdrian Chadd #define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) // ns * 3.6 us 168*eb6f0de0SAdrian Chadd #define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) 169*eb6f0de0SAdrian Chadd #define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) 170*eb6f0de0SAdrian Chadd #define IS_HT_RATE(_rate) ((_rate) & 0x80) 171*eb6f0de0SAdrian Chadd 172*eb6f0de0SAdrian Chadd const uint32_t bits_per_symbol[][2] = { 173*eb6f0de0SAdrian Chadd /* 20MHz 40MHz */ 174*eb6f0de0SAdrian Chadd { 26, 54 }, // 0: BPSK 175*eb6f0de0SAdrian Chadd { 52, 108 }, // 1: QPSK 1/2 176*eb6f0de0SAdrian Chadd { 78, 162 }, // 2: QPSK 3/4 177*eb6f0de0SAdrian Chadd { 104, 216 }, // 3: 16-QAM 1/2 178*eb6f0de0SAdrian Chadd { 156, 324 }, // 4: 16-QAM 3/4 179*eb6f0de0SAdrian Chadd { 208, 432 }, // 5: 64-QAM 2/3 180*eb6f0de0SAdrian Chadd { 234, 486 }, // 6: 64-QAM 3/4 181*eb6f0de0SAdrian Chadd { 260, 540 }, // 7: 64-QAM 5/6 182*eb6f0de0SAdrian Chadd { 52, 108 }, // 8: BPSK 183*eb6f0de0SAdrian Chadd { 104, 216 }, // 9: QPSK 1/2 184*eb6f0de0SAdrian Chadd { 156, 324 }, // 10: QPSK 3/4 185*eb6f0de0SAdrian Chadd { 208, 432 }, // 11: 16-QAM 1/2 186*eb6f0de0SAdrian Chadd { 312, 648 }, // 12: 16-QAM 3/4 187*eb6f0de0SAdrian Chadd { 416, 864 }, // 13: 64-QAM 2/3 188*eb6f0de0SAdrian Chadd { 468, 972 }, // 14: 64-QAM 3/4 189*eb6f0de0SAdrian Chadd { 520, 1080 }, // 15: 64-QAM 5/6 190*eb6f0de0SAdrian Chadd { 78, 162 }, // 16: BPSK 191*eb6f0de0SAdrian Chadd { 156, 324 }, // 17: QPSK 1/2 192*eb6f0de0SAdrian Chadd { 234, 486 }, // 18: QPSK 3/4 193*eb6f0de0SAdrian Chadd { 312, 648 }, // 19: 16-QAM 1/2 194*eb6f0de0SAdrian Chadd { 468, 972 }, // 20: 16-QAM 3/4 195*eb6f0de0SAdrian Chadd { 624, 1296 }, // 21: 64-QAM 2/3 196*eb6f0de0SAdrian Chadd { 702, 1458 }, // 22: 64-QAM 3/4 197*eb6f0de0SAdrian Chadd { 780, 1620 }, // 23: 64-QAM 5/6 198*eb6f0de0SAdrian Chadd { 104, 216 }, // 24: BPSK 199*eb6f0de0SAdrian Chadd { 208, 432 }, // 25: QPSK 1/2 200*eb6f0de0SAdrian Chadd { 312, 648 }, // 26: QPSK 3/4 201*eb6f0de0SAdrian Chadd { 416, 864 }, // 27: 16-QAM 1/2 202*eb6f0de0SAdrian Chadd { 624, 1296 }, // 28: 16-QAM 3/4 203*eb6f0de0SAdrian Chadd { 832, 1728 }, // 29: 64-QAM 2/3 204*eb6f0de0SAdrian Chadd { 936, 1944 }, // 30: 64-QAM 3/4 205*eb6f0de0SAdrian Chadd { 1040, 2160 }, // 31: 64-QAM 5/6 206*eb6f0de0SAdrian Chadd }; 207*eb6f0de0SAdrian Chadd 208*eb6f0de0SAdrian Chadd /* 209*eb6f0de0SAdrian Chadd * Fill in the rate array information based on the current 210*eb6f0de0SAdrian Chadd * node configuration and the choices made by the rate 211*eb6f0de0SAdrian Chadd * selection code and ath_buf setup code. 212*eb6f0de0SAdrian Chadd * 213*eb6f0de0SAdrian Chadd * Later on, this may end up also being made by the 214*eb6f0de0SAdrian Chadd * rate control code, but for now it can live here. 215*eb6f0de0SAdrian Chadd * 216*eb6f0de0SAdrian Chadd * This needs to be called just before the packet is 217*eb6f0de0SAdrian Chadd * queued to the software queue or hardware queue, 218*eb6f0de0SAdrian Chadd * so all of the needed fields in bf_state are setup. 219*eb6f0de0SAdrian Chadd */ 220*eb6f0de0SAdrian Chadd void 221*eb6f0de0SAdrian Chadd ath_tx_rate_fill_rcflags(struct ath_softc *sc, struct ath_buf *bf) 222*eb6f0de0SAdrian Chadd { 223*eb6f0de0SAdrian Chadd struct ieee80211_node *ni = bf->bf_node; 224*eb6f0de0SAdrian Chadd struct ieee80211com *ic = ni->ni_ic; 225*eb6f0de0SAdrian Chadd const HAL_RATE_TABLE *rt = sc->sc_currates; 226*eb6f0de0SAdrian Chadd struct ath_rc_series *rc = bf->bf_state.bfs_rc; 227*eb6f0de0SAdrian Chadd uint8_t rate; 228*eb6f0de0SAdrian Chadd int i; 229*eb6f0de0SAdrian Chadd 230*eb6f0de0SAdrian Chadd for (i = 0; i < ATH_RC_NUM; i++) { 231*eb6f0de0SAdrian Chadd rc[i].flags = 0; 232*eb6f0de0SAdrian Chadd if (rc[i].tries == 0) 233*eb6f0de0SAdrian Chadd continue; 234*eb6f0de0SAdrian Chadd 235*eb6f0de0SAdrian Chadd rate = rt->info[rc[i].rix].rateCode; 236*eb6f0de0SAdrian Chadd 237*eb6f0de0SAdrian Chadd /* 238*eb6f0de0SAdrian Chadd * XXX only do this for legacy rates? 239*eb6f0de0SAdrian Chadd */ 240*eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_shpream) 241*eb6f0de0SAdrian Chadd rate |= rt->info[rc[i].rix].shortPreamble; 242*eb6f0de0SAdrian Chadd 243*eb6f0de0SAdrian Chadd /* 244*eb6f0de0SAdrian Chadd * Save this, used by the TX and completion code 245*eb6f0de0SAdrian Chadd */ 246*eb6f0de0SAdrian Chadd rc[i].ratecode = rate; 247*eb6f0de0SAdrian Chadd 248*eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_flags & 249*eb6f0de0SAdrian Chadd (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) 250*eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_RTSCTS_FLAG; 251*eb6f0de0SAdrian Chadd 252*eb6f0de0SAdrian Chadd /* Only enable shortgi, 2040, dual-stream if HT is set */ 253*eb6f0de0SAdrian Chadd if (IS_HT_RATE(rate)) { 254*eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_HT_FLAG; 255*eb6f0de0SAdrian Chadd 256*eb6f0de0SAdrian Chadd if (ni->ni_chw == 40) 257*eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_CW40_FLAG; 258*eb6f0de0SAdrian Chadd 259*eb6f0de0SAdrian Chadd if (ni->ni_chw == 40 && 260*eb6f0de0SAdrian Chadd ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 && 261*eb6f0de0SAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) 262*eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_SGI_FLAG; 263*eb6f0de0SAdrian Chadd 264*eb6f0de0SAdrian Chadd if (ni->ni_chw == 20 && 265*eb6f0de0SAdrian Chadd ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 && 266*eb6f0de0SAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) 267*eb6f0de0SAdrian Chadd rc[i].flags |= ATH_RC_SGI_FLAG; 268*eb6f0de0SAdrian Chadd 269*eb6f0de0SAdrian Chadd /* XXX dual stream? and 3-stream? */ 270*eb6f0de0SAdrian Chadd } 271*eb6f0de0SAdrian Chadd 272*eb6f0de0SAdrian Chadd /* 273*eb6f0de0SAdrian Chadd * Calculate the maximum 4ms frame length based 274*eb6f0de0SAdrian Chadd * on the MCS rate, SGI and channel width flags. 275*eb6f0de0SAdrian Chadd */ 276*eb6f0de0SAdrian Chadd if ((rc[i].flags & ATH_RC_HT_FLAG) && 277*eb6f0de0SAdrian Chadd (HT_RC_2_MCS(rate) < 32)) { 278*eb6f0de0SAdrian Chadd int j; 279*eb6f0de0SAdrian Chadd if (rc[i].flags & ATH_RC_CW40_FLAG) { 280*eb6f0de0SAdrian Chadd if (rc[i].flags & ATH_RC_SGI_FLAG) 281*eb6f0de0SAdrian Chadd j = MCS_HT40_SGI; 282*eb6f0de0SAdrian Chadd else 283*eb6f0de0SAdrian Chadd j = MCS_HT40; 284*eb6f0de0SAdrian Chadd } else { 285*eb6f0de0SAdrian Chadd if (rc[i].flags & ATH_RC_SGI_FLAG) 286*eb6f0de0SAdrian Chadd j = MCS_HT20_SGI; 287*eb6f0de0SAdrian Chadd else 288*eb6f0de0SAdrian Chadd j = MCS_HT20; 289*eb6f0de0SAdrian Chadd } 290*eb6f0de0SAdrian Chadd rc[i].max4msframelen = 291*eb6f0de0SAdrian Chadd ath_max_4ms_framelen[j][HT_RC_2_MCS(rate)]; 292*eb6f0de0SAdrian Chadd } else 293*eb6f0de0SAdrian Chadd rc[i].max4msframelen = 0; 294*eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, 295*eb6f0de0SAdrian Chadd "%s: i=%d, rate=0x%x, flags=0x%x, max4ms=%d\n", 296*eb6f0de0SAdrian Chadd __func__, i, rate, rc[i].flags, rc[i].max4msframelen); 297*eb6f0de0SAdrian Chadd } 298*eb6f0de0SAdrian Chadd } 299*eb6f0de0SAdrian Chadd 300*eb6f0de0SAdrian Chadd /* 301*eb6f0de0SAdrian Chadd * Return the number of delimiters to be added to 302*eb6f0de0SAdrian Chadd * meet the minimum required mpdudensity. 303*eb6f0de0SAdrian Chadd * 304*eb6f0de0SAdrian Chadd * Caller should make sure that the rate is HT. 305*eb6f0de0SAdrian Chadd * 306*eb6f0de0SAdrian Chadd * TODO: is this delimiter calculation supposed to be the 307*eb6f0de0SAdrian Chadd * total frame length, the hdr length, the data length (including 308*eb6f0de0SAdrian Chadd * delimiters, padding, CRC, etc) or ? 309*eb6f0de0SAdrian Chadd * 310*eb6f0de0SAdrian Chadd * TODO: this should ensure that the rate control information 311*eb6f0de0SAdrian Chadd * HAS been setup for the first rate. 312*eb6f0de0SAdrian Chadd * 313*eb6f0de0SAdrian Chadd * TODO: ensure this is only called for MCS rates. 314*eb6f0de0SAdrian Chadd * 315*eb6f0de0SAdrian Chadd * TODO: enforce MCS < 31 316*eb6f0de0SAdrian Chadd */ 317*eb6f0de0SAdrian Chadd static int 318*eb6f0de0SAdrian Chadd ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf, 319*eb6f0de0SAdrian Chadd uint16_t pktlen) 320*eb6f0de0SAdrian Chadd { 321*eb6f0de0SAdrian Chadd const HAL_RATE_TABLE *rt = sc->sc_currates; 322*eb6f0de0SAdrian Chadd struct ieee80211_node *ni = first_bf->bf_node; 323*eb6f0de0SAdrian Chadd struct ieee80211vap *vap = ni->ni_vap; 324*eb6f0de0SAdrian Chadd int ndelim, mindelim = 0; 325*eb6f0de0SAdrian Chadd int mpdudensity; /* in 1/100'th of a microsecond */ 326*eb6f0de0SAdrian Chadd uint8_t rc, rix, flags; 327*eb6f0de0SAdrian Chadd int width, half_gi; 328*eb6f0de0SAdrian Chadd uint32_t nsymbits, nsymbols; 329*eb6f0de0SAdrian Chadd uint16_t minlen; 330*eb6f0de0SAdrian Chadd 331*eb6f0de0SAdrian Chadd /* 332*eb6f0de0SAdrian Chadd * vap->iv_ampdu_density is a value, rather than the actual 333*eb6f0de0SAdrian Chadd * density. 334*eb6f0de0SAdrian Chadd */ 335*eb6f0de0SAdrian Chadd if (vap->iv_ampdu_density > IEEE80211_HTCAP_MPDUDENSITY_16) 336*eb6f0de0SAdrian Chadd mpdudensity = 1600; /* maximum density */ 337*eb6f0de0SAdrian Chadd else 338*eb6f0de0SAdrian Chadd mpdudensity = ieee80211_mpdudensity_map[vap->iv_ampdu_density]; 339*eb6f0de0SAdrian Chadd 340*eb6f0de0SAdrian Chadd /* Select standard number of delimiters based on frame length */ 341*eb6f0de0SAdrian Chadd ndelim = ATH_AGGR_GET_NDELIM(pktlen); 342*eb6f0de0SAdrian Chadd 343*eb6f0de0SAdrian Chadd /* 344*eb6f0de0SAdrian Chadd * If encryption is enabled, add extra delimiters to let the 345*eb6f0de0SAdrian Chadd * crypto hardware catch up. This could be tuned per-MAC and 346*eb6f0de0SAdrian Chadd * per-rate, but for now we'll simply assume encryption is 347*eb6f0de0SAdrian Chadd * always enabled. 348*eb6f0de0SAdrian Chadd */ 349*eb6f0de0SAdrian Chadd ndelim += ATH_AGGR_ENCRYPTDELIM; 350*eb6f0de0SAdrian Chadd 351*eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, 352*eb6f0de0SAdrian Chadd "%s: pktlen=%d, ndelim=%d, mpdudensity=%d\n", 353*eb6f0de0SAdrian Chadd __func__, pktlen, ndelim, mpdudensity); 354*eb6f0de0SAdrian Chadd 355*eb6f0de0SAdrian Chadd /* 356*eb6f0de0SAdrian Chadd * If the MPDU density is 0, we can return here. 357*eb6f0de0SAdrian Chadd * Otherwise, we need to convert the desired mpdudensity 358*eb6f0de0SAdrian Chadd * into a byte length, based on the rate in the subframe. 359*eb6f0de0SAdrian Chadd */ 360*eb6f0de0SAdrian Chadd if (mpdudensity == 0) 361*eb6f0de0SAdrian Chadd return ndelim; 362*eb6f0de0SAdrian Chadd 363*eb6f0de0SAdrian Chadd /* 364*eb6f0de0SAdrian Chadd * Convert desired mpdu density from microeconds to bytes based 365*eb6f0de0SAdrian Chadd * on highest rate in rate series (i.e. first rate) to determine 366*eb6f0de0SAdrian Chadd * required minimum length for subframe. Take into account 367*eb6f0de0SAdrian Chadd * whether high rate is 20 or 40Mhz and half or full GI. 368*eb6f0de0SAdrian Chadd */ 369*eb6f0de0SAdrian Chadd rix = first_bf->bf_state.bfs_rc[0].rix; 370*eb6f0de0SAdrian Chadd rc = rt->info[rix].rateCode; 371*eb6f0de0SAdrian Chadd flags = first_bf->bf_state.bfs_rc[0].flags; 372*eb6f0de0SAdrian Chadd width = !! (flags & ATH_RC_CW40_FLAG); 373*eb6f0de0SAdrian Chadd half_gi = !! (flags & ATH_RC_SGI_FLAG); 374*eb6f0de0SAdrian Chadd 375*eb6f0de0SAdrian Chadd /* 376*eb6f0de0SAdrian Chadd * mpdudensity is in 1/100th of a usec, so divide by 100 377*eb6f0de0SAdrian Chadd */ 378*eb6f0de0SAdrian Chadd if (half_gi) 379*eb6f0de0SAdrian Chadd nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity); 380*eb6f0de0SAdrian Chadd else 381*eb6f0de0SAdrian Chadd nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity); 382*eb6f0de0SAdrian Chadd nsymbols /= 100; 383*eb6f0de0SAdrian Chadd 384*eb6f0de0SAdrian Chadd if (nsymbols == 0) 385*eb6f0de0SAdrian Chadd nsymbols = 1; 386*eb6f0de0SAdrian Chadd 387*eb6f0de0SAdrian Chadd nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; 388*eb6f0de0SAdrian Chadd minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; 389*eb6f0de0SAdrian Chadd 390*eb6f0de0SAdrian Chadd /* 391*eb6f0de0SAdrian Chadd * Min length is the minimum frame length for the 392*eb6f0de0SAdrian Chadd * required MPDU density. 393*eb6f0de0SAdrian Chadd */ 394*eb6f0de0SAdrian Chadd if (pktlen < minlen) { 395*eb6f0de0SAdrian Chadd mindelim = (minlen - pktlen) / ATH_AGGR_DELIM_SZ; 396*eb6f0de0SAdrian Chadd ndelim = MAX(mindelim, ndelim); 397*eb6f0de0SAdrian Chadd } 398*eb6f0de0SAdrian Chadd 399*eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, 400*eb6f0de0SAdrian Chadd "%s: pktlen=%d, minlen=%d, rix=%x, rc=%x, width=%d, hgi=%d, ndelim=%d\n", 401*eb6f0de0SAdrian Chadd __func__, pktlen, minlen, rix, rc, width, half_gi, ndelim); 402*eb6f0de0SAdrian Chadd 403*eb6f0de0SAdrian Chadd return ndelim; 404*eb6f0de0SAdrian Chadd } 405*eb6f0de0SAdrian Chadd 406*eb6f0de0SAdrian Chadd /* 407*eb6f0de0SAdrian Chadd * Fetch the aggregation limit. 408*eb6f0de0SAdrian Chadd * 409*eb6f0de0SAdrian Chadd * It's the lowest of the four rate series 4ms frame length. 410*eb6f0de0SAdrian Chadd */ 411*eb6f0de0SAdrian Chadd static int 412*eb6f0de0SAdrian Chadd ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf) 413*eb6f0de0SAdrian Chadd { 414*eb6f0de0SAdrian Chadd int amin = 65530; 415*eb6f0de0SAdrian Chadd int i; 416*eb6f0de0SAdrian Chadd 417*eb6f0de0SAdrian Chadd for (i = 0; i < 4; i++) { 418*eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_rc[i].tries == 0) 419*eb6f0de0SAdrian Chadd continue; 420*eb6f0de0SAdrian Chadd amin = MIN(amin, bf->bf_state.bfs_rc[i].max4msframelen); 421*eb6f0de0SAdrian Chadd } 422*eb6f0de0SAdrian Chadd 423*eb6f0de0SAdrian Chadd DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: max frame len= %d\n", 424*eb6f0de0SAdrian Chadd __func__, amin); 425*eb6f0de0SAdrian Chadd 426*eb6f0de0SAdrian Chadd return amin; 427*eb6f0de0SAdrian Chadd } 4284b44f6f2SAdrian Chadd 4294b44f6f2SAdrian Chadd /* 4304b44f6f2SAdrian Chadd * Setup a 11n rate series structure 4314b44f6f2SAdrian Chadd * 4324b44f6f2SAdrian Chadd * This should be called for both legacy and MCS rates. 433*eb6f0de0SAdrian Chadd * 434*eb6f0de0SAdrian Chadd * It, along with ath_buf_set_rate, must be called -after- a burst 435*eb6f0de0SAdrian Chadd * or aggregate is setup. 4364b44f6f2SAdrian Chadd */ 4374b44f6f2SAdrian Chadd static void 4384b44f6f2SAdrian Chadd ath_rateseries_setup(struct ath_softc *sc, struct ieee80211_node *ni, 439*eb6f0de0SAdrian Chadd struct ath_buf *bf, HAL_11N_RATE_SERIES *series) 4404b44f6f2SAdrian Chadd { 441fce6d676SAdrian Chadd #define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) 4424b44f6f2SAdrian Chadd struct ieee80211com *ic = ni->ni_ic; 4434b44f6f2SAdrian Chadd struct ath_hal *ah = sc->sc_ah; 4444b44f6f2SAdrian Chadd HAL_BOOL shortPreamble = AH_FALSE; 4454b44f6f2SAdrian Chadd const HAL_RATE_TABLE *rt = sc->sc_currates; 4464b44f6f2SAdrian Chadd int i; 447*eb6f0de0SAdrian Chadd int pktlen; 448*eb6f0de0SAdrian Chadd int flags = bf->bf_state.bfs_flags; 449*eb6f0de0SAdrian Chadd struct ath_rc_series *rc = bf->bf_state.bfs_rc; 4504b44f6f2SAdrian Chadd 4514b44f6f2SAdrian Chadd if ((ic->ic_flags & IEEE80211_F_SHPREAMBLE) && 4524b44f6f2SAdrian Chadd (ni->ni_capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)) 4534b44f6f2SAdrian Chadd shortPreamble = AH_TRUE; 4544b44f6f2SAdrian Chadd 455*eb6f0de0SAdrian Chadd /* 456*eb6f0de0SAdrian Chadd * If this is the first frame in an aggregate series, 457*eb6f0de0SAdrian Chadd * use the aggregate length. 458*eb6f0de0SAdrian Chadd */ 459*eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_aggr) 460*eb6f0de0SAdrian Chadd pktlen = bf->bf_state.bfs_al; 461*eb6f0de0SAdrian Chadd else 462*eb6f0de0SAdrian Chadd pktlen = bf->bf_state.bfs_pktlen; 463*eb6f0de0SAdrian Chadd 464*eb6f0de0SAdrian Chadd /* 465*eb6f0de0SAdrian Chadd * XXX TODO: modify this routine to use the bfs_rc[x].flags 466*eb6f0de0SAdrian Chadd * XXX fields. 467*eb6f0de0SAdrian Chadd */ 4684b44f6f2SAdrian Chadd memset(series, 0, sizeof(HAL_11N_RATE_SERIES) * 4); 4694b44f6f2SAdrian Chadd for (i = 0; i < 4; i++) { 470146b49d8SAdrian Chadd /* Only set flags for actual TX attempts */ 471*eb6f0de0SAdrian Chadd if (rc[i].tries == 0) 472146b49d8SAdrian Chadd continue; 473146b49d8SAdrian Chadd 474*eb6f0de0SAdrian Chadd series[i].Tries = rc[i].tries; 475146b49d8SAdrian Chadd 476146b49d8SAdrian Chadd /* 477146b49d8SAdrian Chadd * XXX this isn't strictly correct - sc_txchainmask 478146b49d8SAdrian Chadd * XXX isn't the currently active chainmask; 479146b49d8SAdrian Chadd * XXX it's the interface chainmask at startup. 480146b49d8SAdrian Chadd * XXX It's overridden in the HAL rate scenario function 481146b49d8SAdrian Chadd * XXX for now. 482146b49d8SAdrian Chadd */ 4834b44f6f2SAdrian Chadd series[i].ChSel = sc->sc_txchainmask; 484146b49d8SAdrian Chadd 4852b5684a8SAdrian Chadd if (flags & (HAL_TXDESC_RTSENA | HAL_TXDESC_CTSENA)) 4864b44f6f2SAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_RTS_CTS; 487146b49d8SAdrian Chadd 488532f2442SAdrian Chadd /* 489532f2442SAdrian Chadd * Transmit 40MHz frames only if the node has negotiated 490532f2442SAdrian Chadd * it rather than whether the node is capable of it or not. 491532f2442SAdrian Chadd * It's subtly different in the hostap case. 492532f2442SAdrian Chadd */ 493532f2442SAdrian Chadd if (ni->ni_chw == 40) 4944b44f6f2SAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_2040; 4956246be6eSAdrian Chadd 4967842451aSAdrian Chadd /* 4976246be6eSAdrian Chadd * Set short-GI only if the node has advertised it 4986246be6eSAdrian Chadd * the channel width is suitable, and we support it. 4996246be6eSAdrian Chadd * We don't currently have a "negotiated" set of bits - 5006246be6eSAdrian Chadd * ni_htcap is what the remote end sends, not what this 5016246be6eSAdrian Chadd * node is capable of. 5027842451aSAdrian Chadd */ 5036246be6eSAdrian Chadd if (ni->ni_chw == 40 && 5046246be6eSAdrian Chadd ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI40 && 5056246be6eSAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_SHORTGI40) 5064b44f6f2SAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_HALFGI; 5076246be6eSAdrian Chadd 5086246be6eSAdrian Chadd if (ni->ni_chw == 20 && 5096246be6eSAdrian Chadd ic->ic_htcaps & IEEE80211_HTCAP_SHORTGI20 && 5106246be6eSAdrian Chadd ni->ni_htcap & IEEE80211_HTCAP_SHORTGI20) 5116246be6eSAdrian Chadd series[i].RateFlags |= HAL_RATESERIES_HALFGI; 5124b44f6f2SAdrian Chadd 513*eb6f0de0SAdrian Chadd series[i].Rate = rt->info[rc[i].rix].rateCode; 5144b44f6f2SAdrian Chadd 5154b44f6f2SAdrian Chadd /* PktDuration doesn't include slot, ACK, RTS, etc timing - it's just the packet duration */ 5169a97e25eSAdrian Chadd if (series[i].Rate & IEEE80211_RATE_MCS) { 5174b44f6f2SAdrian Chadd series[i].PktDuration = 5184b44f6f2SAdrian Chadd ath_computedur_ht(pktlen 5199a97e25eSAdrian Chadd , series[i].Rate 520fce6d676SAdrian Chadd , HT_RC_2_STREAMS(series[i].Rate) 521fce6d676SAdrian Chadd , series[i].RateFlags & HAL_RATESERIES_2040 522f449ab1cSAdrian Chadd , series[i].RateFlags & HAL_RATESERIES_HALFGI); 5234b44f6f2SAdrian Chadd } else { 5241198947aSAdrian Chadd if (shortPreamble) 525*eb6f0de0SAdrian Chadd series[i].Rate |= 526*eb6f0de0SAdrian Chadd rt->info[rc[i].rix].shortPreamble; 5274b44f6f2SAdrian Chadd series[i].PktDuration = ath_hal_computetxtime(ah, 528*eb6f0de0SAdrian Chadd rt, pktlen, rc[i].rix, shortPreamble); 5294b44f6f2SAdrian Chadd } 5304b44f6f2SAdrian Chadd } 531fce6d676SAdrian Chadd #undef HT_RC_2_STREAMS 5324b44f6f2SAdrian Chadd } 5334b44f6f2SAdrian Chadd 5344b44f6f2SAdrian Chadd #if 0 5354b44f6f2SAdrian Chadd static void 5364b44f6f2SAdrian Chadd ath_rateseries_print(HAL_11N_RATE_SERIES *series) 5374b44f6f2SAdrian Chadd { 5384b44f6f2SAdrian Chadd int i; 5394b44f6f2SAdrian Chadd for (i = 0; i < 4; i++) { 5404b44f6f2SAdrian Chadd printf("series %d: rate %x; tries %d; pktDuration %d; chSel %d; rateFlags %x\n", 5414b44f6f2SAdrian Chadd i, 5424b44f6f2SAdrian Chadd series[i].Rate, 5434b44f6f2SAdrian Chadd series[i].Tries, 5444b44f6f2SAdrian Chadd series[i].PktDuration, 5454b44f6f2SAdrian Chadd series[i].ChSel, 5464b44f6f2SAdrian Chadd series[i].RateFlags); 5474b44f6f2SAdrian Chadd } 5484b44f6f2SAdrian Chadd } 5494b44f6f2SAdrian Chadd #endif 5504b44f6f2SAdrian Chadd 5514b44f6f2SAdrian Chadd /* 5524b44f6f2SAdrian Chadd * Setup the 11n rate scenario and burst duration for the given TX descriptor 5534b44f6f2SAdrian Chadd * list. 5544b44f6f2SAdrian Chadd * 5554b44f6f2SAdrian Chadd * This isn't useful for sending beacon frames, which has different needs 5564b44f6f2SAdrian Chadd * wrt what's passed into the rate scenario function. 5574b44f6f2SAdrian Chadd */ 5584b44f6f2SAdrian Chadd 5594b44f6f2SAdrian Chadd void 560*eb6f0de0SAdrian Chadd ath_buf_set_rate(struct ath_softc *sc, struct ieee80211_node *ni, 561*eb6f0de0SAdrian Chadd struct ath_buf *bf) 5624b44f6f2SAdrian Chadd { 5634b44f6f2SAdrian Chadd HAL_11N_RATE_SERIES series[4]; 5644b44f6f2SAdrian Chadd struct ath_desc *ds = bf->bf_desc; 5654b44f6f2SAdrian Chadd struct ath_desc *lastds = NULL; 5664b44f6f2SAdrian Chadd struct ath_hal *ah = sc->sc_ah; 567*eb6f0de0SAdrian Chadd int is_pspoll = (bf->bf_state.bfs_atype == HAL_PKT_TYPE_PSPOLL); 568*eb6f0de0SAdrian Chadd int ctsrate = bf->bf_state.bfs_ctsrate; 569*eb6f0de0SAdrian Chadd int flags = bf->bf_state.bfs_flags; 5704b44f6f2SAdrian Chadd 5714b44f6f2SAdrian Chadd /* Setup rate scenario */ 5724b44f6f2SAdrian Chadd memset(&series, 0, sizeof(series)); 5734b44f6f2SAdrian Chadd 574*eb6f0de0SAdrian Chadd ath_rateseries_setup(sc, ni, bf, series); 5754b44f6f2SAdrian Chadd 5764b44f6f2SAdrian Chadd /* Enforce AR5416 aggregate limit - can't do RTS w/ an agg frame > 8k */ 5774b44f6f2SAdrian Chadd 5784b44f6f2SAdrian Chadd /* Enforce RTS and CTS are mutually exclusive */ 5794b44f6f2SAdrian Chadd 5804b44f6f2SAdrian Chadd /* Get a pointer to the last tx descriptor in the list */ 581*eb6f0de0SAdrian Chadd lastds = bf->bf_lastds; 5824b44f6f2SAdrian Chadd 5832b5684a8SAdrian Chadd #if 0 5842b5684a8SAdrian Chadd printf("pktlen: %d; flags 0x%x\n", pktlen, flags); 5852b5684a8SAdrian Chadd ath_rateseries_print(series); 5862b5684a8SAdrian Chadd #endif 5872b5684a8SAdrian Chadd 5884b44f6f2SAdrian Chadd /* Set rate scenario */ 5894b44f6f2SAdrian Chadd ath_hal_set11nratescenario(ah, ds, 590bf26df36SAdrian Chadd !is_pspoll, /* whether to override the duration or not */ 591bf26df36SAdrian Chadd /* don't allow hardware to override the duration on ps-poll packets */ 5924b44f6f2SAdrian Chadd ctsrate, /* rts/cts rate */ 5934b44f6f2SAdrian Chadd series, /* 11n rate series */ 5944b44f6f2SAdrian Chadd 4, /* number of series */ 5954b44f6f2SAdrian Chadd flags); 5964b44f6f2SAdrian Chadd 5974b44f6f2SAdrian Chadd /* Setup the last descriptor in the chain */ 5984b44f6f2SAdrian Chadd ath_hal_setuplasttxdesc(ah, lastds, ds); 5994b44f6f2SAdrian Chadd 6004b44f6f2SAdrian Chadd /* Set burst duration */ 601*eb6f0de0SAdrian Chadd /* 602*eb6f0de0SAdrian Chadd * This is only required when doing 11n burst, not aggregation 603*eb6f0de0SAdrian Chadd * ie, if there's a second frame in a RIFS or A-MPDU burst 604*eb6f0de0SAdrian Chadd * w/ >1 A-MPDU frame bursting back to back. 605*eb6f0de0SAdrian Chadd * Normal A-MPDU doesn't do bursting -between- aggregates. 606*eb6f0de0SAdrian Chadd * 607*eb6f0de0SAdrian Chadd * .. and it's highly likely this won't ever be implemented 608*eb6f0de0SAdrian Chadd */ 6094b44f6f2SAdrian Chadd //ath_hal_set11nburstduration(ah, ds, 8192); 6104b44f6f2SAdrian Chadd } 611*eb6f0de0SAdrian Chadd 612*eb6f0de0SAdrian Chadd /* 613*eb6f0de0SAdrian Chadd * Form an aggregate packet list. 614*eb6f0de0SAdrian Chadd * 615*eb6f0de0SAdrian Chadd * This function enforces the aggregate restrictions/requirements. 616*eb6f0de0SAdrian Chadd * 617*eb6f0de0SAdrian Chadd * These are: 618*eb6f0de0SAdrian Chadd * 619*eb6f0de0SAdrian Chadd * + The aggregate size maximum (64k for AR9160 and later, 8K for 620*eb6f0de0SAdrian Chadd * AR5416 when doing RTS frame protection.) 621*eb6f0de0SAdrian Chadd * + Maximum number of sub-frames for an aggregate 622*eb6f0de0SAdrian Chadd * + The aggregate delimiter size, giving MACs time to do whatever is 623*eb6f0de0SAdrian Chadd * needed before each frame 624*eb6f0de0SAdrian Chadd * + Enforce the BAW limit 625*eb6f0de0SAdrian Chadd * 626*eb6f0de0SAdrian Chadd * Each descriptor queued should have the DMA setup. 627*eb6f0de0SAdrian Chadd * The rate series, descriptor setup, linking, etc is all done 628*eb6f0de0SAdrian Chadd * externally. This routine simply chains them together. 629*eb6f0de0SAdrian Chadd * ath_tx_setds_11n() will take care of configuring the per- 630*eb6f0de0SAdrian Chadd * descriptor setup, and ath_buf_set_rate() will configure the 631*eb6f0de0SAdrian Chadd * rate control. 632*eb6f0de0SAdrian Chadd * 633*eb6f0de0SAdrian Chadd * Note that the TID lock is only grabbed when dequeuing packets from 634*eb6f0de0SAdrian Chadd * the TID queue. If some code in another thread adds to the head of this 635*eb6f0de0SAdrian Chadd * list, very strange behaviour will occur. Since retransmission is the 636*eb6f0de0SAdrian Chadd * only reason this will occur, and this routine is designed to be called 637*eb6f0de0SAdrian Chadd * from within the scheduler task, it won't ever clash with the completion 638*eb6f0de0SAdrian Chadd * task. 639*eb6f0de0SAdrian Chadd * 640*eb6f0de0SAdrian Chadd * So if you want to call this from an upper layer context (eg, to direct- 641*eb6f0de0SAdrian Chadd * dispatch aggregate frames to the hardware), please keep this in mind. 642*eb6f0de0SAdrian Chadd */ 643*eb6f0de0SAdrian Chadd ATH_AGGR_STATUS 644*eb6f0de0SAdrian Chadd ath_tx_form_aggr(struct ath_softc *sc, struct ath_node *an, struct ath_tid *tid, 645*eb6f0de0SAdrian Chadd ath_bufhead *bf_q) 646*eb6f0de0SAdrian Chadd { 647*eb6f0de0SAdrian Chadd //struct ieee80211_node *ni = &an->an_node; 648*eb6f0de0SAdrian Chadd struct ath_buf *bf, *bf_first = NULL, *bf_prev = NULL; 649*eb6f0de0SAdrian Chadd int nframes = 0; 650*eb6f0de0SAdrian Chadd uint16_t aggr_limit = 0, al = 0, bpad = 0, al_delta, h_baw; 651*eb6f0de0SAdrian Chadd struct ieee80211_tx_ampdu *tap; 652*eb6f0de0SAdrian Chadd int status = ATH_AGGR_DONE; 653*eb6f0de0SAdrian Chadd int prev_frames = 0; /* XXX for AR5416 burst, not done here */ 654*eb6f0de0SAdrian Chadd int prev_al = 0; /* XXX also for AR5416 burst */ 655*eb6f0de0SAdrian Chadd 656*eb6f0de0SAdrian Chadd ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]); 657*eb6f0de0SAdrian Chadd 658*eb6f0de0SAdrian Chadd tap = ath_tx_get_tx_tid(an, tid->tid); 659*eb6f0de0SAdrian Chadd if (tap == NULL) { 660*eb6f0de0SAdrian Chadd status = ATH_AGGR_ERROR; 661*eb6f0de0SAdrian Chadd goto finish; 662*eb6f0de0SAdrian Chadd } 663*eb6f0de0SAdrian Chadd 664*eb6f0de0SAdrian Chadd h_baw = tap->txa_wnd / 2; 665*eb6f0de0SAdrian Chadd 666*eb6f0de0SAdrian Chadd for (;;) { 667*eb6f0de0SAdrian Chadd bf = TAILQ_FIRST(&tid->axq_q); 668*eb6f0de0SAdrian Chadd if (bf_first == NULL) 669*eb6f0de0SAdrian Chadd bf_first = bf; 670*eb6f0de0SAdrian Chadd if (bf == NULL) { 671*eb6f0de0SAdrian Chadd status = ATH_AGGR_DONE; 672*eb6f0de0SAdrian Chadd break; 673*eb6f0de0SAdrian Chadd } else { 674*eb6f0de0SAdrian Chadd /* 675*eb6f0de0SAdrian Chadd * It's the first frame; 676*eb6f0de0SAdrian Chadd * set the aggregation limit based on the 677*eb6f0de0SAdrian Chadd * rate control decision that has been made. 678*eb6f0de0SAdrian Chadd */ 679*eb6f0de0SAdrian Chadd aggr_limit = ath_get_aggr_limit(sc, bf_first); 680*eb6f0de0SAdrian Chadd } 681*eb6f0de0SAdrian Chadd 682*eb6f0de0SAdrian Chadd /* Set this early just so things don't get confused */ 683*eb6f0de0SAdrian Chadd bf->bf_next = NULL; 684*eb6f0de0SAdrian Chadd 685*eb6f0de0SAdrian Chadd /* 686*eb6f0de0SAdrian Chadd * Don't unlock the tid lock until we're sure we are going 687*eb6f0de0SAdrian Chadd * to queue this frame. 688*eb6f0de0SAdrian Chadd */ 689*eb6f0de0SAdrian Chadd 690*eb6f0de0SAdrian Chadd /* 691*eb6f0de0SAdrian Chadd * If the frame doesn't have a sequence number that we're 692*eb6f0de0SAdrian Chadd * tracking in the BAW (eg NULL QOS data frame), we can't 693*eb6f0de0SAdrian Chadd * aggregate it. Stop the aggregation process; the sender 694*eb6f0de0SAdrian Chadd * can then TX what's in the list thus far and then 695*eb6f0de0SAdrian Chadd * TX the frame individually. 696*eb6f0de0SAdrian Chadd */ 697*eb6f0de0SAdrian Chadd if (! bf->bf_state.bfs_dobaw) { 698*eb6f0de0SAdrian Chadd status = ATH_AGGR_NONAGGR; 699*eb6f0de0SAdrian Chadd break; 700*eb6f0de0SAdrian Chadd } 701*eb6f0de0SAdrian Chadd 702*eb6f0de0SAdrian Chadd /* 703*eb6f0de0SAdrian Chadd * If any of the rates are non-HT, this packet 704*eb6f0de0SAdrian Chadd * can't be aggregated. 705*eb6f0de0SAdrian Chadd * XXX TODO: add a bf_state flag which gets marked 706*eb6f0de0SAdrian Chadd * if any active rate is non-HT. 707*eb6f0de0SAdrian Chadd */ 708*eb6f0de0SAdrian Chadd 709*eb6f0de0SAdrian Chadd /* 710*eb6f0de0SAdrian Chadd * If the packet has a sequence number, do not 711*eb6f0de0SAdrian Chadd * step outside of the block-ack window. 712*eb6f0de0SAdrian Chadd */ 713*eb6f0de0SAdrian Chadd if (! BAW_WITHIN(tap->txa_start, tap->txa_wnd, 714*eb6f0de0SAdrian Chadd SEQNO(bf->bf_state.bfs_seqno))) { 715*eb6f0de0SAdrian Chadd status = ATH_AGGR_BAW_CLOSED; 716*eb6f0de0SAdrian Chadd break; 717*eb6f0de0SAdrian Chadd } 718*eb6f0de0SAdrian Chadd 719*eb6f0de0SAdrian Chadd /* 720*eb6f0de0SAdrian Chadd * XXX TODO: AR5416 has an 8K aggregation size limit 721*eb6f0de0SAdrian Chadd * when RTS is enabled, and RTS is required for dual-stream 722*eb6f0de0SAdrian Chadd * rates. 723*eb6f0de0SAdrian Chadd * 724*eb6f0de0SAdrian Chadd * For now, limit all aggregates for the AR5416 to be 8K. 725*eb6f0de0SAdrian Chadd */ 726*eb6f0de0SAdrian Chadd 727*eb6f0de0SAdrian Chadd /* 728*eb6f0de0SAdrian Chadd * do not exceed aggregation limit 729*eb6f0de0SAdrian Chadd */ 730*eb6f0de0SAdrian Chadd al_delta = ATH_AGGR_DELIM_SZ + bf->bf_state.bfs_pktlen; 731*eb6f0de0SAdrian Chadd if (nframes && 732*eb6f0de0SAdrian Chadd (aggr_limit < (al + bpad + al_delta + prev_al))) { 733*eb6f0de0SAdrian Chadd status = ATH_AGGR_LIMITED; 734*eb6f0de0SAdrian Chadd break; 735*eb6f0de0SAdrian Chadd } 736*eb6f0de0SAdrian Chadd 737*eb6f0de0SAdrian Chadd /* 738*eb6f0de0SAdrian Chadd * Do not exceed subframe limit. 739*eb6f0de0SAdrian Chadd */ 740*eb6f0de0SAdrian Chadd if ((nframes + prev_frames) >= MIN((h_baw), 741*eb6f0de0SAdrian Chadd IEEE80211_AMPDU_SUBFRAME_DEFAULT)) { 742*eb6f0de0SAdrian Chadd status = ATH_AGGR_LIMITED; 743*eb6f0de0SAdrian Chadd break; 744*eb6f0de0SAdrian Chadd } 745*eb6f0de0SAdrian Chadd 746*eb6f0de0SAdrian Chadd /* 747*eb6f0de0SAdrian Chadd * this packet is part of an aggregate. 748*eb6f0de0SAdrian Chadd */ 749*eb6f0de0SAdrian Chadd ATH_TXQ_REMOVE(tid, bf, bf_list); 750*eb6f0de0SAdrian Chadd 751*eb6f0de0SAdrian Chadd /* The TID lock is required for the BAW update */ 752*eb6f0de0SAdrian Chadd ath_tx_addto_baw(sc, an, tid, bf); 753*eb6f0de0SAdrian Chadd bf->bf_state.bfs_addedbaw = 1; 754*eb6f0de0SAdrian Chadd 755*eb6f0de0SAdrian Chadd /* 756*eb6f0de0SAdrian Chadd * XXX TODO: If any frame in the aggregate requires RTS/CTS, 757*eb6f0de0SAdrian Chadd * set the first frame. 758*eb6f0de0SAdrian Chadd */ 759*eb6f0de0SAdrian Chadd 760*eb6f0de0SAdrian Chadd /* 761*eb6f0de0SAdrian Chadd * XXX enforce ACK for aggregate frames (this needs to be 762*eb6f0de0SAdrian Chadd * XXX handled more gracefully? 763*eb6f0de0SAdrian Chadd */ 764*eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_flags & HAL_TXDESC_NOACK) { 765*eb6f0de0SAdrian Chadd device_printf(sc->sc_dev, 766*eb6f0de0SAdrian Chadd "%s: HAL_TXDESC_NOACK set for an aggregate frame?\n", 767*eb6f0de0SAdrian Chadd __func__); 768*eb6f0de0SAdrian Chadd bf->bf_state.bfs_flags &= (~HAL_TXDESC_NOACK); 769*eb6f0de0SAdrian Chadd } 770*eb6f0de0SAdrian Chadd 771*eb6f0de0SAdrian Chadd /* 772*eb6f0de0SAdrian Chadd * Add the now owned buffer (which isn't 773*eb6f0de0SAdrian Chadd * on the software TXQ any longer) to our 774*eb6f0de0SAdrian Chadd * aggregate frame list. 775*eb6f0de0SAdrian Chadd */ 776*eb6f0de0SAdrian Chadd TAILQ_INSERT_TAIL(bf_q, bf, bf_list); 777*eb6f0de0SAdrian Chadd nframes ++; 778*eb6f0de0SAdrian Chadd 779*eb6f0de0SAdrian Chadd /* Completion handler */ 780*eb6f0de0SAdrian Chadd bf->bf_comp = ath_tx_aggr_comp; 781*eb6f0de0SAdrian Chadd 782*eb6f0de0SAdrian Chadd /* 783*eb6f0de0SAdrian Chadd * add padding for previous frame to aggregation length 784*eb6f0de0SAdrian Chadd */ 785*eb6f0de0SAdrian Chadd al += bpad + al_delta; 786*eb6f0de0SAdrian Chadd 787*eb6f0de0SAdrian Chadd /* 788*eb6f0de0SAdrian Chadd * Calculate delimiters needed for the current frame 789*eb6f0de0SAdrian Chadd */ 790*eb6f0de0SAdrian Chadd bf->bf_state.bfs_ndelim = 791*eb6f0de0SAdrian Chadd ath_compute_num_delims(sc, bf_first, 792*eb6f0de0SAdrian Chadd bf->bf_state.bfs_pktlen); 793*eb6f0de0SAdrian Chadd 794*eb6f0de0SAdrian Chadd /* 795*eb6f0de0SAdrian Chadd * Calculate the padding needed from this set of delimiters, 796*eb6f0de0SAdrian Chadd * used when calculating if the next frame will fit in 797*eb6f0de0SAdrian Chadd * the aggregate. 798*eb6f0de0SAdrian Chadd */ 799*eb6f0de0SAdrian Chadd bpad = PADBYTES(al_delta) + (bf->bf_state.bfs_ndelim << 2); 800*eb6f0de0SAdrian Chadd 801*eb6f0de0SAdrian Chadd /* 802*eb6f0de0SAdrian Chadd * Chain the buffers together 803*eb6f0de0SAdrian Chadd */ 804*eb6f0de0SAdrian Chadd if (bf_prev) 805*eb6f0de0SAdrian Chadd bf_prev->bf_next = bf; 806*eb6f0de0SAdrian Chadd bf_prev = bf; 807*eb6f0de0SAdrian Chadd 808*eb6f0de0SAdrian Chadd /* 809*eb6f0de0SAdrian Chadd * XXX TODO: if any sub-frames have RTS/CTS enabled; 810*eb6f0de0SAdrian Chadd * enable it for the entire aggregate. 811*eb6f0de0SAdrian Chadd */ 812*eb6f0de0SAdrian Chadd 813*eb6f0de0SAdrian Chadd #if 0 814*eb6f0de0SAdrian Chadd /* 815*eb6f0de0SAdrian Chadd * terminate aggregation on a small packet boundary 816*eb6f0de0SAdrian Chadd */ 817*eb6f0de0SAdrian Chadd if (bf->bf_state.bfs_pktlen < ATH_AGGR_MINPLEN) { 818*eb6f0de0SAdrian Chadd status = ATH_AGGR_SHORTPKT; 819*eb6f0de0SAdrian Chadd break; 820*eb6f0de0SAdrian Chadd } 821*eb6f0de0SAdrian Chadd #endif 822*eb6f0de0SAdrian Chadd 823*eb6f0de0SAdrian Chadd } 824*eb6f0de0SAdrian Chadd 825*eb6f0de0SAdrian Chadd finish: 826*eb6f0de0SAdrian Chadd /* 827*eb6f0de0SAdrian Chadd * Just in case the list was empty when we tried to 828*eb6f0de0SAdrian Chadd * dequeue a packet .. 829*eb6f0de0SAdrian Chadd */ 830*eb6f0de0SAdrian Chadd if (bf_first) { 831*eb6f0de0SAdrian Chadd bf_first->bf_state.bfs_al = al; 832*eb6f0de0SAdrian Chadd bf_first->bf_state.bfs_nframes = nframes; 833*eb6f0de0SAdrian Chadd } 834*eb6f0de0SAdrian Chadd return status; 835*eb6f0de0SAdrian Chadd } 836