Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 May 2012 23:36:49 -0700
From:      Adrian Chadd <adrian@freebsd.org>
To:        freebsd-wireless@freebsd.org
Subject:   [net80211] Fix some corner cases in BAR TX handling
Message-ID:  <CAJ-Vmo=uOrK=RB_ezz-A8r=-bNOaV-6%2BqcbGMYGuC3buZZefYw@mail.gmail.com>

next in thread | raw e-mail | index | archive | help
Hi,

This patch fixes a couple of rather annoying corner cases that I've
seen with BAR TX handling in ath(4).

They showed up because I am using a very cut down set of buffers in
ath(4) (128 tx and 128 rx) rather than the older number (512) and I
can easily exhaust them whilst the TID is paused. I'll soon implement
some changes which will leave a "reserved" set of frames for
management - and if I can line all the stars up correctly, have the
management frames go out on the highest priority TX queue.

Specifically:

* ieee80211_send_bar() disables the timer and doesn't restart it
unless ic_raw_xmit() suceeds;
* if the TX fails and the timeout occurs via bar_timeout(), it'll try
calling ieee80211_send_bar() to retransmit - but if that fails, the
timer will never occur.
* Callbacks are only done via bar_tx_complete(), which is not called
if ieee80211_send_bar() fails to queue any frames to the driver.
* If the timer does get started again, BARPEND may have been cleared
(due to a failed ieee80211_send_bar() attempt to call ic_raw_xmit())
and it won't actually be processed, causing the attempts to fail.
Again.

So to maintain some semblence of predicable behaviour, I've done the following:

* The ic_bar_response() handler is called just before AMPDU is
disabled, giving the driver a chance to be told that the max number of
retries has been reached. I don't like how this is the only real way
to know that the BAR TX attempt has totally failed; I'll worry about
that later.
* If a retransmit attempt fails, set BARPEND and restart the timer.

I've verified that this fixes all the weird BAR TX stalls I've seen.

Thanks,


Adrian

Index: net80211/ieee80211_ht.c
===================================================================
--- net80211/ieee80211_ht.c     (revision 235772)
+++ net80211/ieee80211_ht.c     (working copy)
@@ -2166,6 +2166,9 @@
        }
 }

+/* XXX */
+static void bar_start_timer(struct ieee80211_tx_ampdu *tap);
+
 static void
 bar_timeout(void *arg)
 {
@@ -2184,11 +2187,34 @@
                return;
        /* XXX ? */
        if (tap->txa_attempts >= ieee80211_bar_maxtries) {
+               struct ieee80211com *ic = ni->ni_ic;
+
                ni->ni_vap->iv_stats.is_ampdu_bar_tx_fail++;
+               /*
+                * If (at least) the last BAR TX timeout was due to
+                * an ieee80211_send_bar() failures, then we need
+                * to make sure we notify the driver that a BAR
+                * TX did occur and fail.  This gives the driver
+                * a chance to undo any queue pause that may
+                * have occured.
+                */
+               ic->ic_bar_response(ni, tap, 1);
                ieee80211_ampdu_stop(ni, tap, IEEE80211_REASON_TIMEOUT);
        } else {
                ni->ni_vap->iv_stats.is_ampdu_bar_tx_retry++;
-               ieee80211_send_bar(ni, tap, tap->txa_seqpending);
+               if (ieee80211_send_bar(ni, tap, tap->txa_seqpending) != 0) {
+                       /*
+                        * If ieee80211_send_bar() fails here, the
+                        * timer may have stopped and/or the pending
+                        * flag may be clear.  Because of this,
+                        * fake the BARPEND and reset the timer.
+                        * A retransmission attempt will then occur
+                        * during the next timeout.
+                        */
+                       /* XXX locking */
+                       tap->txa_flags |= IEEE80211_AGGR_BARPEND;
+                       bar_start_timer(tap);
+               }
        }
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJ-Vmo=uOrK=RB_ezz-A8r=-bNOaV-6%2BqcbGMYGuC3buZZefYw>