summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2014-08-28 07:44:59 +0000
committeradrian <adrian@FreeBSD.org>2014-08-28 07:44:59 +0000
commita3bb3db4bfc2cbf2451d297879c706700876f778 (patch)
tree8cd1da9817651908be0a6c028da11fd15046e05d
parentc96a03670809c3475989e0c44baeda3424533696 (diff)
downloadFreeBSD-src-a3bb3db4bfc2cbf2451d297879c706700876f778.zip
FreeBSD-src-a3bb3db4bfc2cbf2451d297879c706700876f778.tar.gz
Inform the rate control code if a single frame AMPDU transmission succeeds
but has some retries. Without this, single frame transmission in AMPDU will always look like it succeeded fine, and thus AMRR will think it's totally fine to just keep upping the rate upwards. Now, this is still not quite right! For multi-frame aggregates the completion happens in two parts - the TX done and the BA received. The driver is currently double accounting those a little - there's no way to say to the rate control code "I completed X frames, Y worked fine, there were Z retries." And it's a bit odd with iwn, as the firmware retransmits frames for us so we don't get to see how many retransmits happened; only that it took longer than normal. I may have to extend the rate control API to properly track that. So this may keep the rate lower than it should be, but that's better than keeping it higher than it should be. Tested: * 5100, STA mode
-rw-r--r--sys/dev/iwn/if_iwn.c39
1 files changed, 31 insertions, 8 deletions
diff --git a/sys/dev/iwn/if_iwn.c b/sys/dev/iwn/if_iwn.c
index 78991a2..34a4321 100644
--- a/sys/dev/iwn/if_iwn.c
+++ b/sys/dev/iwn/if_iwn.c
@@ -213,7 +213,7 @@ static void iwn5000_tx_done(struct iwn_softc *, struct iwn_rx_desc *,
struct iwn_rx_data *);
static void iwn_tx_done(struct iwn_softc *, struct iwn_rx_desc *, int,
uint8_t);
-static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, void *);
+static void iwn_ampdu_tx_done(struct iwn_softc *, int, int, int, int, void *);
static void iwn_cmd_done(struct iwn_softc *, struct iwn_rx_desc *);
static void iwn_notif_intr(struct iwn_softc *);
static void iwn_wakeup_intr(struct iwn_softc *);
@@ -3150,6 +3150,11 @@ iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
if (wn->agg[tid].nframes > (64 - shift))
return;
+ /*
+ * XXX does this correctly process an almost empty bitmap?
+ * (since it bails out when it sees an empty bitmap, but there
+ * may be failed bits there..)
+ */
ni = tap->txa_ni;
bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap;
for (i = 0; bitmap; i++) {
@@ -3426,7 +3431,7 @@ iwn4965_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);
if (qid >= sc->firstaggqueue) {
iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes,
- &stat->status);
+ stat->ackfailcnt, &stat->status);
} else {
iwn_tx_done(sc, desc, stat->ackfailcnt,
le32toh(stat->status) & 0xff);
@@ -3458,7 +3463,7 @@ iwn5000_tx_done(struct iwn_softc *sc, struct iwn_rx_desc *desc,
bus_dmamap_sync(ring->data_dmat, data->map, BUS_DMASYNC_POSTREAD);
if (qid >= sc->firstaggqueue) {
iwn_ampdu_tx_done(sc, qid, desc->idx, stat->nframes,
- &stat->status);
+ stat->ackfailcnt, &stat->status);
} else {
iwn_tx_done(sc, desc, stat->ackfailcnt,
le16toh(stat->status) & 0xff);
@@ -3573,7 +3578,7 @@ iwn_cmd_done(struct iwn_softc *sc, struct iwn_rx_desc *desc)
static void
iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
- void *stat)
+ int ackfailcnt, void *stat)
{
struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
@@ -3591,6 +3596,15 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
int bit, i, lastidx, *res, seqno, shift, start;
DPRINTF(sc, IWN_DEBUG_TRACE, "->%s begin\n", __func__);
+ DPRINTF(sc, IWN_DEBUG_XMIT, "%s: nframes=%d, status=0x%08x\n",
+ __func__,
+ nframes,
+ *status);
+
+ tap = sc->qid2tap[qid];
+ tid = tap->txa_tid;
+ wn = (void *)tap->txa_ni;
+ ni = tap->txa_ni;
if (nframes == 1) {
if ((*status & 0xff) != 1 && (*status & 0xff) != 2) {
@@ -3602,15 +3616,24 @@ iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
* notification is pushed up to the rate control
* layer.
*/
- tap = sc->qid2tap[qid];
- tid = tap->txa_tid;
- wn = (void *)tap->txa_ni;
- ni = tap->txa_ni;
ieee80211_ratectl_tx_complete(ni->ni_vap, ni,
IEEE80211_RATECTL_TX_FAILURE, &nframes, NULL);
}
}
+ /*
+ * We succeeded with some frames, so let's update how many
+ * retries were needed for this frame.
+ *
+ * XXX we can't yet pass tx_complete tx_cnt and success_cnt,
+ * le sigh.
+ */
+ ieee80211_ratectl_tx_complete(ni->ni_vap,
+ ni,
+ IEEE80211_RATECTL_TX_SUCCESS,
+ &ackfailcnt,
+ NULL);
+
bitmap = 0;
start = idx;
for (i = 0; i < nframes; i++) {
OpenPOWER on IntegriCloud