svn commit: r308951 - head/sys/dev/ath
Adrian Chadd
adrian at FreeBSD.org
Tue Nov 22 02:42:02 UTC 2016
Author: adrian
Date: Tue Nov 22 02:42:00 2016
New Revision: 308951
URL: https://svnweb.freebsd.org/changeset/base/308951
Log:
[ath] obey the peer A-MPDU density and max-size.
* Obey the peer A-MPDU density if it's larger than the currently configured
one.
* Pay attention to the peer A-MPDU max-size and don't assume we can transmit
a full A-MPDU (64k!) if the peer announces smaller values.
Relnotes: ath(4): Fix A-MPDU transmit; obey A-MPDU density and max size.
Modified:
head/sys/dev/ath/if_ath_tx_ht.c
Modified: head/sys/dev/ath/if_ath_tx_ht.c
==============================================================================
--- head/sys/dev/ath/if_ath_tx_ht.c Tue Nov 22 02:02:13 2016 (r308950)
+++ head/sys/dev/ath/if_ath_tx_ht.c Tue Nov 22 02:42:00 2016 (r308951)
@@ -319,8 +319,8 @@ ath_tx_rate_fill_rcflags(struct ath_soft
* and we're not doing positioning, enable STBC.
*/
if (ic->ic_htcaps & IEEE80211_HTCAP_TXSTBC &&
- ni->ni_vap->iv_flags_ht & IEEE80211_FHT_STBC_TX &&
- ni->ni_htcap & IEEE80211_HTCAP_RXSTBC_1STREAM &&
+ (ni->ni_vap->iv_flags_ht & IEEE80211_FHT_STBC_TX) &&
+ (ni->ni_htcap & IEEE80211_HTCAP_RXSTBC) &&
(sc->sc_cur_txchainmask > 1) &&
(HT_RC_2_STREAMS(rate) == 1) &&
(bf->bf_flags & ATH_BUF_TOA_PROBE) == 0) {
@@ -404,24 +404,40 @@ static int
ath_compute_num_delims(struct ath_softc *sc, struct ath_buf *first_bf,
uint16_t pktlen)
{
+#define MS(_v, _f) (((_v) & _f) >> _f##_S)
const HAL_RATE_TABLE *rt = sc->sc_currates;
struct ieee80211_node *ni = first_bf->bf_node;
struct ieee80211vap *vap = ni->ni_vap;
int ndelim, mindelim = 0;
- int mpdudensity; /* in 1/100'th of a microsecond */
+ int mpdudensity; /* in 1/100'th of a microsecond */
+ int peer_mpdudensity; /* net80211 value */
uint8_t rc, rix, flags;
int width, half_gi;
uint32_t nsymbits, nsymbols;
uint16_t minlen;
/*
- * vap->iv_ampdu_density is a value, rather than the actual
- * density.
+ * Get the advertised density from the node.
*/
- if (vap->iv_ampdu_density > IEEE80211_HTCAP_MPDUDENSITY_16)
+ peer_mpdudensity = MS(ni->ni_htparam, IEEE80211_HTCAP_MPDUDENSITY);
+
+ /*
+ * vap->iv_ampdu_density is a net80211 value, rather than the actual
+ * density. Larger values are longer A-MPDU density spacing values,
+ * and we want to obey larger configured / negotiated density values
+ * per station if we get it.
+ */
+ if (vap->iv_ampdu_density > peer_mpdudensity)
+ peer_mpdudensity = vap->iv_ampdu_density;
+
+ /*
+ * Convert the A-MPDU density net80211 value to a 1/100 microsecond
+ * value for subsequent calculations.
+ */
+ if (peer_mpdudensity > IEEE80211_HTCAP_MPDUDENSITY_16)
mpdudensity = 1600; /* maximum density */
else
- mpdudensity = ieee80211_mpdudensity_map[vap->iv_ampdu_density];
+ mpdudensity = ieee80211_mpdudensity_map[peer_mpdudensity];
/* Select standard number of delimiters based on frame length */
ndelim = ATH_AGGR_GET_NDELIM(pktlen);
@@ -509,22 +525,49 @@ ath_compute_num_delims(struct ath_softc
__func__, pktlen, minlen, rix, rc, width, half_gi, ndelim);
return ndelim;
+#undef MS
}
/*
* Fetch the aggregation limit.
*
* It's the lowest of the four rate series 4ms frame length.
+ *
+ * Also take into account the hardware specific limits (8KiB on AR5416)
+ * and per-peer limits in non-STA mode.
*/
static int
-ath_get_aggr_limit(struct ath_softc *sc, struct ath_buf *bf)
+ath_get_aggr_limit(struct ath_softc *sc, struct ieee80211_node *ni,
+ struct ath_buf *bf)
{
+#define MS(_v, _f) (((_v) & _f) >> _f##_S)
int amin = ATH_AGGR_MAXSIZE;
int i;
+ /* Extract out the maximum configured driver A-MPDU limit */
if (sc->sc_aggr_limit > 0 && sc->sc_aggr_limit < ATH_AGGR_MAXSIZE)
amin = sc->sc_aggr_limit;
+ /*
+ * Check the HTCAP field for the maximum size the node has
+ * negotiated. If it's smaller than what we have, cap it there.
+ */
+ switch (MS(ni->ni_htparam, IEEE80211_HTCAP_MAXRXAMPDU)) {
+ case IEEE80211_HTCAP_MAXRXAMPDU_16K:
+ amin = MIN(amin, 16384);
+ break;
+ case IEEE80211_HTCAP_MAXRXAMPDU_32K:
+ amin = MIN(amin, 32768);
+ break;
+ case IEEE80211_HTCAP_MAXRXAMPDU_64K:
+ amin = MIN(amin, 65536);
+ break;
+ case IEEE80211_HTCAP_MAXRXAMPDU_8K:
+ default:
+ amin = MIN(amin, 8192);
+ break;
+ }
+
for (i = 0; i < ATH_RC_NUM; i++) {
if (bf->bf_state.bfs_rc[i].tries == 0)
continue;
@@ -535,6 +578,7 @@ ath_get_aggr_limit(struct ath_softc *sc,
__func__, amin);
return amin;
+#undef MS
}
/*
@@ -787,7 +831,8 @@ ath_tx_form_aggr(struct ath_softc *sc, s
* set the aggregation limit based on the
* rate control decision that has been made.
*/
- aggr_limit = ath_get_aggr_limit(sc, bf_first);
+ aggr_limit = ath_get_aggr_limit(sc, &an->an_node,
+ bf_first);
}
/* Set this early just so things don't get confused */
More information about the svn-src-all
mailing list