From owner-svn-src-user@FreeBSD.ORG Tue Aug 23 23:33:39 2011 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4EEDC106564A; Tue, 23 Aug 2011 23:33:39 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 3DDC08FC08; Tue, 23 Aug 2011 23:33:39 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p7NNXdGJ024120; Tue, 23 Aug 2011 23:33:39 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p7NNXdOh024116; Tue, 23 Aug 2011 23:33:39 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201108232333.p7NNXdOh024116@svn.freebsd.org> From: Adrian Chadd Date: Tue, 23 Aug 2011 23:33:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r225124 - user/adrian/if_ath_tx/sys/dev/ath X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 23 Aug 2011 23:33:39 -0000 Author: adrian Date: Tue Aug 23 23:33:38 2011 New Revision: 225124 URL: http://svn.freebsd.org/changeset/base/225124 Log: Try to make the ATH_BUF_BUSY handling work again. * add bf_last to ath_buf, which points to the last frame in an aggregate, or itself for a single frame * Set ATH_BUF_BUSY in the last frame in an aggregate - that's the ath_buf which the hardware may be currently tinkering with. * Restore the ATH_BUF_BUSY clearing in ath_tx_processq() - clear the ATH_BUF_BUSY flag in the last entry on the free list before adding the next buffer - it's assumed the hardware has finished with that descriptor. This should restore the current behaviour that ATH_BUF_BUSY protects against, but: * retries which use ATH_BUF_BUSY buffers need to result in the ath_buf being cloned, rather than reused. That buffer then needs to be returned to the free list. * This code seems like it'll only work for a single TX queue. As in, if TXQ 0 has been handled and the last buffer is marked BUSY, then TXQ 1 runs - the last buffer on the free list will be marked as non-busy. ath9k and the reference code uses a more complicated "holding descriptor" setup which keeps the descriptor on the TXQ list and frees it when needed. This will be eventually needed! Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath.c user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath.c ============================================================================== --- user/adrian/if_ath_tx/sys/dev/ath/if_ath.c Tue Aug 23 21:10:23 2011 (r225123) +++ user/adrian/if_ath_tx/sys/dev/ath/if_ath.c Tue Aug 23 23:33:38 2011 (r225124) @@ -1885,6 +1885,7 @@ _ath_getbuf_locked(struct ath_softc *sc) "out of xmit buffers" : "xmit buffer busy"); } else { bf->bf_next = NULL; /* XXX just to be sure */ + bf->bf_last = NULL; /* XXX again, just to be sure */ bf->bf_comp = NULL; /* XXX again, just to be sure */ } return bf; @@ -2433,6 +2434,7 @@ ath_beacon_setup(struct ath_softc *sc, s /* setup descriptors */ ds = bf->bf_desc; + bf->bf_last = bf; flags = HAL_TXDESC_NOACK; if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) { @@ -4248,7 +4250,7 @@ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) { struct ath_hal *ah = sc->sc_ah; - struct ath_buf *bf; + struct ath_buf *bf, *last; struct ath_desc *ds, *ds0; struct ath_tx_status *ts; struct ieee80211_node *ni; @@ -4289,8 +4291,12 @@ ath_tx_processq(struct ath_softc *sc, st * More frames follow. Mark the buffer busy * so it's not re-used while the hardware may * still re-read the link field in the descriptor. + * + * Use the last buffer in an aggregate as that + * is where the hardware may be - intermediate + * descriptors won't be "busy". */ - bf->bf_flags |= ATH_BUF_BUSY; + bf->bf_last->bf_flags |= ATH_BUF_BUSY; } else #else if (txq->axq_depth == 0) @@ -4321,6 +4327,20 @@ ath_tx_processq(struct ath_softc *sc, st ath_tx_update_stats(sc, ts, bf); } + /* + * Since the last frame may still be marked + * as ATH_BUF_BUSY, unmark it here before + * finishing the frame processing. + * Since we've completed a frame (aggregate + * or otherwise), the hardware has moved on + * and is no longer referencing the previous + * descriptor. + */ + ATH_TXBUF_LOCK(sc); + last = TAILQ_LAST(&sc->sc_txbuf, ath_bufhead_s); + if (last != NULL) + last->bf_flags &= ~ATH_BUF_BUSY; + ATH_TXBUF_UNLOCK(sc); /* * Call the completion handler. @@ -4574,6 +4594,11 @@ ath_tx_draintxq(struct ath_softc *sc, st * functions, we -must- call it for aggregation * destinations or BAW tracking will get upset. */ + /* + * Clear ATH_BUF_BUSY; the completion handler + * will free the buffer. + */ + bf->bf_flags &= ~ATH_BUF_BUSY; if (bf->bf_comp) bf->bf_comp(sc, bf, 1); else 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 Tue Aug 23 21:10:23 2011 (r225123) +++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c Tue Aug 23 23:33:38 2011 (r225124) @@ -444,6 +444,12 @@ ath_tx_setds_11n(struct ath_softc *sc, s */ bf_first->bf_lastds = bf_prev->bf_lastds; + /* + * And bf_last in the first descriptor points to the end of + * the aggregate list. + */ + bf_first->bf_last = bf_prev; + DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: end\n", __func__); } @@ -739,6 +745,7 @@ ath_tx_setds(struct ath_softc *sc, struc * This will be overriden when the descriptor chain is written. */ bf->bf_lastds = ds; + bf->bf_last = bf; /* XXX TODO: Setup descriptor chain */ } Modified: user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h ============================================================================== --- user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h Tue Aug 23 21:10:23 2011 (r225123) +++ user/adrian/if_ath_tx/sys/dev/ath/if_athvar.h Tue Aug 23 23:33:38 2011 (r225124) @@ -183,6 +183,7 @@ struct ath_buf { struct mbuf *bf_m; /* mbuf for buf */ struct ieee80211_node *bf_node; /* pointer to the node */ struct ath_desc *bf_lastds; /* last descriptor for comp status */ + struct ath_buf *bf_last; /* last buffer in aggregate, or self for non-aggregate */ bus_size_t bf_mapsize; #define ATH_MAX_SCATTER ATH_TXDESC /* max(tx,rx,beacon) desc's */ bus_dma_segment_t bf_segs[ATH_MAX_SCATTER];