svn commit: r224889 - user/adrian/if_ath_tx/sys/dev/ath
Adrian Chadd
adrian at FreeBSD.org
Mon Aug 15 15:26:36 UTC 2011
Author: adrian
Date: Mon Aug 15 15:26:36 2011
New Revision: 224889
URL: http://svn.freebsd.org/changeset/base/224889
Log:
More BAR related stuff, which is partially locking related stuff.
* Pause/unpause the queue when BAR TX is complete.
The problem is that we're not notified when a BAR TX times out
and the TX won't happen again - the session is just torn down.
So, to work around the API shortcomings for now, hard-code it
to cause an unpause at retry == 50.
This only works if the hardware _DOES_ call the callback upon
frame TX failure. If the callback never gets called, this will
all fall in a heap. Luckily, ath will.
* Fix locking around TXQ pause/resume calls, as they can occur from
the upper layers. This isn't entirely complete, as I'm not
similarly locking the pause/resume checks in the rest of the
code. I'll do that soon.
* Only pause the TID if the ieee80211_send_bar() call was successful.
This now seems to work fine with TX packet loss in non-aggregate mode,
but I'm not yet convinced that I'm sending the correct sequence
number in the BAR frame. I'll look at that next.
Modified:
user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c
Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c
==============================================================================
--- user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c Mon Aug 15 15:22:27 2011 (r224888)
+++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c Mon Aug 15 15:26:36 2011 (r224889)
@@ -1125,7 +1125,8 @@ ath_tx_start(struct ath_softc *sc, struc
*
* TODO: sending a BAR should be done at the management rate!
*/
- device_printf(sc->sc_dev, "%s: BAR: TX'ing direct\n", __func__);
+ DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
+ "%s: BAR: TX'ing direct\n", __func__);
ATH_TXQ_LOCK(txq);
ath_tx_handoff(sc, txq, bf);
ATH_TXQ_UNLOCK(txq);
@@ -1819,28 +1820,43 @@ ath_tx_tid_init(struct ath_softc *sc, st
/*
* Pause the current TID. This stops packets from being transmitted
* on it.
+ *
+ * XXX As this is being called from upper layers, it needs to be
+ * XXX properly locked!
*/
static void
ath_tx_tid_pause(struct ath_softc *sc, struct ath_tid *tid)
{
+ ATH_TXQ_LOCK(tid);
tid->paused++;
DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: paused = %d\n",
__func__, tid->paused);
+ ATH_TXQ_UNLOCK(tid);
}
+/*
+ * Unpause the current TID, and schedule it if needed.
+ *
+ * XXX As this is being called from upper layers, it needs to be
+ * XXX properly locked!
+ */
static void
ath_tx_tid_resume(struct ath_softc *sc, struct ath_tid *tid)
{
struct ath_txq *txq = sc->sc_ac2q[tid->ac];
+ ATH_TXQ_LOCK(tid);
+
tid->paused--;
DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: unpaused = %d\n",
__func__, tid->paused);
- if (tid->paused)
- return;
- if (tid->axq_depth == 0)
+
+ if (tid->paused || tid->axq_depth == 0) {
+ ATH_TXQ_UNLOCK(tid);
return;
+ }
+ ATH_TXQ_UNLOCK(tid);
ATH_TXQ_LOCK(txq);
ath_tx_tid_sched(sc, tid->an, tid->tid);
@@ -1977,12 +1993,13 @@ ath_tx_comp_cleanup(struct ath_softc *sc
int tid = bf->bf_state.bfs_tid;
struct ath_tid *atid = &an->an_tid[tid];
- device_printf(sc->sc_dev, "%s: TID %d: incomp=%d\n",
+ DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: TID %d: incomp=%d\n",
__func__, tid, atid->incomp);
atid->incomp--;
if (atid->incomp == 0) {
- device_printf(sc->sc_dev, "%s: TID %d: cleaned up! resume!\n",
+ DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
+ "%s: TID %d: cleaned up! resume!\n",
__func__, tid);
atid->cleanup_inprogress = 0;
ath_tx_tid_resume(sc, atid);
@@ -2009,7 +2026,8 @@ ath_tx_cleanup(struct ath_softc *sc, str
struct ieee80211_tx_ampdu *tap;
struct ath_buf *bf, *bf_next;
- device_printf(sc->sc_dev, "%s: TID %d: called\n", __func__, tid);
+ DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
+ "%s: TID %d: called\n", __func__, tid);
/*
* Update the frames in the software TX queue:
@@ -2073,7 +2091,7 @@ ath_tx_cleanup(struct ath_softc *sc, str
ath_tx_tid_resume(sc, atid);
if (atid->cleanup_inprogress)
- device_printf(sc->sc_dev,
+ DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
"%s: TID %d: cleanup needed: %d packets\n",
__func__, tid, atid->incomp);
}
@@ -2119,16 +2137,26 @@ ath_tx_aggr_retry_unaggr(struct ath_soft
ath_tx_update_baw(sc, an, atid,
SEQNO(bf->bf_state.bfs_seqno));
- /* Pause the TID */
-
/* Send BAR frame */
/*
* This'll end up going into net80211 and back out
* again, via ic->ic_raw_xmit().
*/
- device_printf(sc->sc_dev, "%s: TID %d: send BAR\n",
+ DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: TID %d: send BAR\n",
__func__, tid);
- ieee80211_send_bar(ni, tap, ni->ni_txseqs[tid]);
+ if (ieee80211_send_bar(ni, tap, ni->ni_txseqs[tid]) == 0) {
+ /*
+ * Pause the TID if this was successful.
+ * An un-successful BAR TX would never call
+ * the BAR complete / timeout methods.
+ */
+ ath_tx_tid_pause(sc, atid);
+ } else {
+ /* BAR TX failed */
+ device_printf(sc->sc_dev,
+ "%s: TID %d: BAR TX failed\n",
+ __func__, tid);
+ }
/* Free buffer, bf is free after this call */
ath_tx_default_comp(sc, bf, 0);
@@ -2544,6 +2572,11 @@ ath_addba_stop(struct ieee80211_node *ni
sc->sc_addba_stop(ni, tap);
ath_tx_cleanup(sc, an, tid);
+ /*
+ * ath_tx_cleanup will resume the TID if possible, otherwise
+ * it'll set the cleanup flag, and it'll be unpaused once
+ * things have been cleaned up.
+ */
}
/*
@@ -2552,17 +2585,32 @@ ath_addba_stop(struct ieee80211_node *ni
*
* It however will call ieee80211_ampdu_stop() which will call
* ic->ic_addba_stop().
+ *
+ * XXX This uses a hard-coded max BAR count value; the whole
+ * XXX BAR TX success or failure should be better handled!
*/
void
ath_bar_response(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap,
int status)
{
struct ath_softc *sc = ni->ni_ic->ic_ifp->if_softc;
+ int tid = WME_AC_TO_TID(tap->txa_ac);
+ struct ath_node *an = ATH_NODE(ni);
+ struct ath_tid *atid = &an->an_tid[tid];
+ int attempts = tap->txa_attempts;
- device_printf(sc->sc_dev, "%s: called\n", __func__);
+ DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
+ "%s: called; status=%d\n", __func__, status);
- sc->sc_bar_response(ni, tap, status);
/* Note: This may update the BAW details */
+ sc->sc_bar_response(ni, tap, status);
/* Unpause the TID */
+ /*
+ * XXX if this is attempt=50, the TID will be downgraded
+ * XXX to a non-aggregate session. So we must unpause the
+ * XXX TID here or it'll never be done.
+ */
+ if (status == 0 || attempts == 50)
+ ath_tx_tid_resume(sc, atid);
}
More information about the svn-src-user
mailing list