Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Apr 2012 22:16:33 -0700
From:      Adrian Chadd <adrian@freebsd.org>
To:        freebsd-wireless@freebsd.org
Subject:   Re: svn commit: r233908 - head/sys/dev/ath
Message-ID:  <CAJ-VmokW-AAtWCd9F7jcd0eYBAZdAYs3T5Kp8FZfZqnjOM0BHw@mail.gmail.com>
In-Reply-To: <201204042345.q34NjGwW030792@svn.freebsd.org>
References:  <201204042345.q34NjGwW030792@svn.freebsd.org>

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

The last thing I need to implement now (besides lots of testing) is HT
frame protection.

Then I'll flip on 11n by default on ath(4), but I'm going to disable
bgscan by default until all of those warts are fixed.

I'd really appreciate a lot of testing of this!

Thanks,



adrian

On 4 April 2012 16:45, Adrian Chadd <adrian@freebsd.org> wrote:
> Author: adrian
> Date: Wed Apr =A04 23:45:15 2012
> New Revision: 233908
> URL: http://svn.freebsd.org/changeset/base/233908
>
> Log:
> =A0Implement BAR TX.
>
> =A0A BAR frame must be transmitted when an frame in an A-MPDU session fai=
ls
> =A0to transmit - it's retried too often, or it can't be cloned for
> =A0re-transmission. =A0The BAR frame tells the remote side to advance the
> =A0left edge of the block-ack window (BAW) to a new value.
>
> =A0In order to do this:
>
> =A0* TX for that particular node/TID must be paused;
> =A0* The existing frames in the hardware queue needs to be completed, whe=
ther
> =A0 =A0they're TXed successfully or otherwise;
> =A0* The new left edge of the BAW is then communicated to the remote side
> =A0 =A0via a BAR frame;
> =A0* Once the BAR frame has been sucessfully TXed, aggregation can resume=
;
> =A0* If the BAR frame can't be successfully TXed, the aggregation session
> =A0 =A0is torn down.
>
> =A0This is a first pass that implements the above. =A0What needs to be do=
ne/
> =A0tested:
>
> =A0* What happens during say, a channel reset / stuck beacon _and_ BAR
> =A0 =A0TX. =A0It _should_ be correctly buffered and retried once the
> =A0 =A0reset has completed. =A0But if a bgscan occurs (and they shouldn't=
,
> =A0 =A0grr) the BAR frame will be forcibly failed and the aggregation ses=
sion
> =A0 =A0will be torn down.
>
> =A0 =A0Yes, another reason to disable bgscan until I've figured this out.
>
> =A0* There's way too much locking going on here. =A0I'm going to do a cou=
ple
> =A0 =A0of further passes of sanitising and refactoring so the (re) lockin=
g
> =A0 =A0isn't so heavy. =A0Right now I'm going for correctness, not speed.
>
> =A0* The BAR TX can fail if the hardware TX queue is full. =A0Since there=
's
> =A0 =A0no "free" space kept for management frames, a full TX queue (from =
eg
> =A0 =A0an iperf test) can race with your ability to allocate ath_buf/mbuf=
s
> =A0 =A0and cause issues. =A0I'll knock this on the head with a subsequent
> =A0 =A0commit.
>
> =A0* I need to do some _much_ more thorough testing in hostap mode to ens=
ure
> =A0 =A0that many concurrent traffic streams to different end nodes are co=
rrectly
> =A0 =A0handled. =A0I'll find and squish whichever bugs show up here.
>
> =A0But, this is an important step to being able to flip on 802.11n by def=
ault.
> =A0The last issue (besides bug fixes, of course) is HT frame protection a=
nd
> =A0I'll address that in a subsequent commit.
>
> Modified:
> =A0head/sys/dev/ath/if_ath_tx.c
> =A0head/sys/dev/ath/if_athvar.h
>
> Modified: head/sys/dev/ath/if_ath_tx.c
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/sys/dev/ath/if_ath_tx.c =A0 =A0 =A0 =A0Wed Apr =A04 23:40:29 201=
2 =A0 =A0 =A0 =A0(r233907)
> +++ head/sys/dev/ath/if_ath_tx.c =A0 =A0 =A0 =A0Wed Apr =A04 23:45:15 201=
2 =A0 =A0 =A0 =A0(r233908)
> @@ -2598,11 +2598,11 @@ ath_tx_tid_init(struct ath_softc *sc, st
> =A0static void
> =A0ath_tx_tid_pause(struct ath_softc *sc, struct ath_tid *tid)
> =A0{
> - =A0 =A0 =A0 ATH_TXQ_LOCK(sc->sc_ac2q[tid->ac]);
> +
> + =A0 =A0 =A0 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
> =A0 =A0 =A0 =A0tid->paused++;
> =A0 =A0 =A0 =A0DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: paused =3D %d\n",
> =A0 =A0 =A0 =A0 =A0 =A0__func__, tid->paused);
> - =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[tid->ac]);
> =A0}
>
> =A0/*
> @@ -2629,6 +2629,158 @@ ath_tx_tid_resume(struct ath_softc *sc,
> =A0}
>
> =A0/*
> + * Suspend the queue because we need to TX a BAR.
> + */
> +static void
> +ath_tx_tid_bar_suspend(struct ath_softc *sc, struct ath_tid *tid)
> +{
> + =A0 =A0 =A0 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
> +
> + =A0 =A0 =A0 DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
> + =A0 =A0 =A0 =A0 =A0 "%s: tid=3D%p, called\n",
> + =A0 =A0 =A0 =A0 =A0 __func__,
> + =A0 =A0 =A0 =A0 =A0 tid);
> +
> + =A0 =A0 =A0 /* We shouldn't be called when bar_tx is 1 */
> + =A0 =A0 =A0 if (tid->bar_tx) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 device_printf(sc->sc_dev, "%s: bar_tx is 1?=
!\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* If we've already been called, just be patient. */
> + =A0 =A0 =A0 if (tid->bar_wait)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
> +
> + =A0 =A0 =A0 /* Wait! */
> + =A0 =A0 =A0 tid->bar_wait =3D 1;
> +
> + =A0 =A0 =A0 /* Only one pause, no matter how many frames fail */
> + =A0 =A0 =A0 ath_tx_tid_pause(sc, tid);
> +}
> +
> +/*
> + * We've finished with BAR handling - either we succeeded or
> + * failed. Either way, unsuspend TX.
> + */
> +static void
> +ath_tx_tid_bar_unsuspend(struct ath_softc *sc, struct ath_tid *tid)
> +{
> + =A0 =A0 =A0 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
> +
> + =A0 =A0 =A0 DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
> + =A0 =A0 =A0 =A0 =A0 "%s: tid=3D%p, called\n",
> + =A0 =A0 =A0 =A0 =A0 __func__,
> + =A0 =A0 =A0 =A0 =A0 tid);
> +
> + =A0 =A0 =A0 if (tid->bar_tx =3D=3D 0 || tid->bar_wait =3D=3D 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 device_printf(sc->sc_dev, "%s: bar_tx=3D%d,=
 bar_wait=3D%d: ?\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__, tid->bar_tx, tid->bar_wai=
t);
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 tid->bar_tx =3D tid->bar_wait =3D 0;
> + =A0 =A0 =A0 ath_tx_tid_resume(sc, tid);
> +}
> +
> +/*
> + * Return whether we're ready to TX a BAR frame.
> + *
> + * Requires the TID lock be held.
> + */
> +static int
> +ath_tx_tid_bar_tx_ready(struct ath_softc *sc, struct ath_tid *tid)
> +{
> +
> + =A0 =A0 =A0 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
> +
> + =A0 =A0 =A0 if (tid->bar_wait =3D=3D 0 || tid->hwq_depth > 0)
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return (0);
> +
> + =A0 =A0 =A0 return (1);
> +}
> +
> +/*
> + * Check whether the current TID is ready to have a BAR
> + * TXed and if so, do the TX.
> + *
> + * Since the TID/TXQ lock can't be held during a call to
> + * ieee80211_send_bar(), we have to do the dirty thing of unlocking it,
> + * sending the BAR and locking it again.
> + *
> + * Eventually, the code to send the BAR should be broken out
> + * from this routine so the lock doesn't have to be reacquired
> + * just to be immediately dropped by the caller.
> + */
> +static void
> +ath_tx_tid_bar_tx(struct ath_softc *sc, struct ath_tid *tid)
> +{
> + =A0 =A0 =A0 struct ieee80211_tx_ampdu *tap;
> +
> + =A0 =A0 =A0 ATH_TXQ_LOCK_ASSERT(sc->sc_ac2q[tid->ac]);
> +
> + =A0 =A0 =A0 DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
> + =A0 =A0 =A0 =A0 =A0 "%s: tid=3D%p, called\n",
> + =A0 =A0 =A0 =A0 =A0 __func__,
> + =A0 =A0 =A0 =A0 =A0 tid);
> +
> + =A0 =A0 =A0 tap =3D ath_tx_get_tx_tid(tid->an, tid->tid);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* This is an error condition!
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (tid->bar_wait =3D=3D 0 || tid->bar_tx =3D=3D 1) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 device_printf(sc->sc_dev,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "%s: tid=3D%p, bar_tx=3D%d, bar_wai=
t=3D%d: ?\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tid,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tid->bar_tx,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tid->bar_wait);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Don't do anything if we still have pending frames */
> + =A0 =A0 =A0 if (tid->hwq_depth > 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "%s: tid=3D%p, hwq_depth=3D%d, wait=
ing\n",
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tid,
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 tid->hwq_depth);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* We're now about to TX */
> + =A0 =A0 =A0 tid->bar_tx =3D 1;
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Calculate new BAW left edge, now that all frames have =
either
> + =A0 =A0 =A0 =A0* succeeded or failed.
> + =A0 =A0 =A0 =A0*
> + =A0 =A0 =A0 =A0* XXX verify this is _actually_ the valid value to begin=
 at!
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 DPRINTF(sc, ATH_DEBUG_SW_TX_BAW,
> + =A0 =A0 =A0 =A0 =A0 "%s: tid=3D%p, new BAW left edge=3D%d\n",
> + =A0 =A0 =A0 =A0 =A0 __func__,
> + =A0 =A0 =A0 =A0 =A0 tid,
> + =A0 =A0 =A0 =A0 =A0 tap->txa_start);
> +
> + =A0 =A0 =A0 /* Try sending the BAR frame */
> + =A0 =A0 =A0 /* We can't hold the lock here! */
> +
> + =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[tid->ac]);
> + =A0 =A0 =A0 if (ieee80211_send_bar(&tid->an->an_node, tap, tap->txa_sta=
rt) =3D=3D 0) {
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Success? Now we wait for notification th=
at it's done */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ATH_TXQ_LOCK(sc->sc_ac2q[tid->ac]);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 return;
> + =A0 =A0 =A0 }
> +
> + =A0 =A0 =A0 /* Failure? For now, warn loudly and continue */
> + =A0 =A0 =A0 ATH_TXQ_LOCK(sc->sc_ac2q[tid->ac]);
> + =A0 =A0 =A0 device_printf(sc->sc_dev, "%s: tid=3D%p, failed to TX BAR, =
continue!\n",
> + =A0 =A0 =A0 =A0 =A0 __func__, tid);
> + =A0 =A0 =A0 ath_tx_tid_bar_unsuspend(sc, tid);
> +}
> +
> +
> +/*
> =A0* Free any packets currently pending in the software TX queue.
> =A0*
> =A0* This will be called when a node is being deleted.
> @@ -3077,7 +3229,6 @@ ath_tx_aggr_retry_unaggr(struct ath_soft
> =A0 =A0 =A0 =A0int tid =3D bf->bf_state.bfs_tid;
> =A0 =A0 =A0 =A0struct ath_tid *atid =3D &an->an_tid[tid];
> =A0 =A0 =A0 =A0struct ieee80211_tx_ampdu *tap;
> - =A0 =A0 =A0 int txseq;
>
> =A0 =A0 =A0 =A0ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
>
> @@ -3118,18 +3269,14 @@ ath_tx_aggr_retry_unaggr(struct ath_soft
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0bf->bf_state.bfs_dobaw =3D 0;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Send BAR frame */
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /*
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* This'll end up going into net80211 and=
 back out
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0* again, via ic->ic_raw_xmit().
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0*/
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 txseq =3D tap->txa_start;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Suspend the TX queue and get ready to se=
nd the BAR */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_bar_suspend(sc, atid);
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 device_printf(sc->sc_dev,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "%s: TID %d: send BAR; seq %d\n", _=
_func__, tid, txseq);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Send the BAR if there are no other frame=
s waiting */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (ath_tx_tid_bar_tx_ready(sc, atid))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_bar_tx(sc, atid)=
;
>
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* XXX TODO: send BAR */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
>
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0/* Free buffer, bf is free after this call=
 */
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ath_tx_default_comp(sc, bf, 0);
> @@ -3149,6 +3296,9 @@ ath_tx_aggr_retry_unaggr(struct ath_soft
> =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0ATH_TXQ_INSERT_HEAD(atid, bf, bf_list);
> =A0 =A0 =A0 =A0ath_tx_tid_sched(sc, atid);
> + =A0 =A0 =A0 /* Send the BAR if there are no other frames waiting */
> + =A0 =A0 =A0 if (ath_tx_tid_bar_tx_ready(sc, atid))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_bar_tx(sc, atid);
>
> =A0 =A0 =A0 =A0ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
> =A0}
> @@ -3278,17 +3428,20 @@ ath_tx_comp_aggr_error(struct ath_softc
> =A0 =A0 =A0 =A0 * in the ifnet TX context or raw TX context.)
> =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0if (drops) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 int txseq =3D tap->txa_start;
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[tid->ac]);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 device_printf(sc->sc_dev,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "%s: TID %d: send BAR; seq %d\n",
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 __func__, tid->tid, txseq);
> -
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* XXX TODO: send BAR */
> - =A0 =A0 =A0 } else {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[tid->ac]);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Suspend the TX queue and get ready to se=
nd the BAR */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_bar_suspend(sc, tid);
> =A0 =A0 =A0 =A0}
>
> + =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[tid->ac]);
> +
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Send BAR if required
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 ATH_TXQ_LOCK(sc->sc_ac2q[tid->ac]);
> + =A0 =A0 =A0 if (ath_tx_tid_bar_tx_ready(sc, tid))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_bar_tx(sc, tid);
> + =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[tid->ac]);
> +
> =A0 =A0 =A0 =A0/* Complete frames which errored out */
> =A0 =A0 =A0 =A0while ((bf =3D TAILQ_FIRST(&bf_cq)) !=3D NULL) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0TAILQ_REMOVE(&bf_cq, bf, bf_list);
> @@ -3328,6 +3481,10 @@ ath_tx_comp_cleanup_aggr(struct ath_soft
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0atid->cleanup_inprogress =3D 0;
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ath_tx_tid_resume(sc, atid);
> =A0 =A0 =A0 =A0}
> +
> + =A0 =A0 =A0 /* Send BAR if required */
> + =A0 =A0 =A0 if (ath_tx_tid_bar_tx_ready(sc, atid))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_bar_tx(sc, atid);
> =A0 =A0 =A0 =A0ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
>
> =A0 =A0 =A0 =A0/* Handle frame completion */
> @@ -3542,9 +3699,10 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
> =A0 =A0 =A0 =A0 * send bar if we dropped any frames
> =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0if (drops) {
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 device_printf(sc->sc_dev,
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 "%s: TID %d: send BAR; seq %d\n", _=
_func__, tid, txseq);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* XXX TODO: send BAR */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 /* Suspend the TX queue and get ready to se=
nd the BAR */
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_bar_suspend(sc, atid);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
> =A0 =A0 =A0 =A0}
>
> =A0 =A0 =A0 =A0/* Prepend all frames to the beginning of the queue */
> @@ -3559,6 +3717,14 @@ ath_tx_aggr_comp_aggr(struct ath_softc *
> =A0 =A0 =A0 =A0DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR,
> =A0 =A0 =A0 =A0 =A0 =A0"%s: txa_start now %d\n", __func__, tap->txa_start=
);
>
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Send BAR if required
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
> + =A0 =A0 =A0 if (ath_tx_tid_bar_tx_ready(sc, atid))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_bar_tx(sc, atid);
> + =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
> +
> =A0 =A0 =A0 =A0/* Do deferred completion */
> =A0 =A0 =A0 =A0while ((bf =3D TAILQ_FIRST(&bf_cq)) !=3D NULL) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0TAILQ_REMOVE(&bf_cq, bf, bf_list);
> @@ -3652,6 +3818,12 @@ ath_tx_aggr_comp_unaggr(struct ath_softc
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0__func__, SEQNO(bf=
->bf_state.bfs_seqno));
> =A0 =A0 =A0 =A0}
>
> + =A0 =A0 =A0 /*
> + =A0 =A0 =A0 =A0* Send BAR if required
> + =A0 =A0 =A0 =A0*/
> + =A0 =A0 =A0 if (ath_tx_tid_bar_tx_ready(sc, atid))
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_bar_tx(sc, atid);
> +
> =A0 =A0 =A0 =A0ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
>
> =A0 =A0 =A0 =A0ath_tx_default_comp(sc, bf, fail);
> @@ -4080,7 +4252,9 @@ ath_addba_request(struct ieee80211_node
> =A0 =A0 =A0 =A0 * it'll be "after" the left edge of the BAW and thus it'l=
l
> =A0 =A0 =A0 =A0 * fall within it.
> =A0 =A0 =A0 =A0 */
> + =A0 =A0 =A0 ATH_TXQ_LOCK(sc->sc_ac2q[atid->tid]);
> =A0 =A0 =A0 =A0ath_tx_tid_pause(sc, atid);
> + =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->tid]);
>
> =A0 =A0 =A0 =A0DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL,
> =A0 =A0 =A0 =A0 =A0 =A0"%s: called; dialogtoken=3D%d, baparamset=3D%d, ba=
timeout=3D%d\n",
> @@ -4166,7 +4340,9 @@ ath_addba_stop(struct ieee80211_node *ni
> =A0 =A0 =A0 =A0DPRINTF(sc, ATH_DEBUG_SW_TX_CTRL, "%s: called\n", __func__=
);
>
> =A0 =A0 =A0 =A0/* Pause TID traffic early, so there aren't any races */
> + =A0 =A0 =A0 ATH_TXQ_LOCK(sc->sc_ac2q[atid->tid]);
> =A0 =A0 =A0 =A0ath_tx_tid_pause(sc, atid);
> + =A0 =A0 =A0 ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->tid]);
>
> =A0 =A0 =A0 =A0/* There's no need to hold the TXQ lock here */
> =A0 =A0 =A0 =A0sc->sc_addba_stop(ni, tap);
> @@ -4213,7 +4389,7 @@ ath_bar_response(struct ieee80211_node *
> =A0 =A0 =A0 =A0 */
> =A0 =A0 =A0 =A0if (status =3D=3D 0 || attempts =3D=3D 50) {
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ATH_TXQ_LOCK(sc->sc_ac2q[atid->ac]);
> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_resume(sc, atid);
> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 ath_tx_tid_bar_unsuspend(sc, atid);
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]);
> =A0 =A0 =A0 =A0}
> =A0}
>
> Modified: head/sys/dev/ath/if_athvar.h
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
> --- head/sys/dev/ath/if_athvar.h =A0 =A0 =A0 =A0Wed Apr =A04 23:40:29 201=
2 =A0 =A0 =A0 =A0(r233907)
> +++ head/sys/dev/ath/if_athvar.h =A0 =A0 =A0 =A0Wed Apr =A04 23:45:15 201=
2 =A0 =A0 =A0 =A0(r233908)
> @@ -106,6 +106,8 @@ struct ath_tid {
> =A0 =A0 =A0 =A0TAILQ_ENTRY(ath_tid) =A0 =A0axq_qelem;
> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 sched;
> =A0 =A0 =A0 =A0int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 paused; /* >0 =
if the TID has been paused */
> + =A0 =A0 =A0 int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bar_wait; =A0 =
=A0 =A0 /* waiting for BAR */
> + =A0 =A0 =A0 int =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 bar_tx; =A0 =A0=
 =A0 =A0 /* BAR TXed */
>
> =A0 =A0 =A0 =A0/*
> =A0 =A0 =A0 =A0 * Is the TID being cleaned up after a transition



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJ-VmokW-AAtWCd9F7jcd0eYBAZdAYs3T5Kp8FZfZqnjOM0BHw>