From owner-svn-src-head@FreeBSD.ORG Tue Nov 8 21:13:06 2011 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 13D46106566C; Tue, 8 Nov 2011 21:13:06 +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 037868FC14; Tue, 8 Nov 2011 21:13:06 +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 pA8LD5M8049427; Tue, 8 Nov 2011 21:13:05 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id pA8LD5Dd049423; Tue, 8 Nov 2011 21:13:05 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201111082113.pA8LD5Dd049423@svn.freebsd.org> From: Adrian Chadd Date: Tue, 8 Nov 2011 21:13:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r227359 - head/sys/dev/ath X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Nov 2011 21:13:07 -0000 Author: adrian Date: Tue Nov 8 21:13:05 2011 New Revision: 227359 URL: http://svn.freebsd.org/changeset/base/227359 Log: Change ath_buf allocation to: * Immediately return NULL if a buffer isn't available; * Track the "buffers not available" count; * Clear some fields used for tx aggregation; * Add ath_buf_clone() which clones the majority of buffer state. This is needed when retransmission of a "busy" buffer is required. Sponsored by: Hobnob, Inc. Modified: head/sys/dev/ath/if_ath.c head/sys/dev/ath/if_ath_misc.h Modified: head/sys/dev/ath/if_ath.c ============================================================================== --- head/sys/dev/ath/if_ath.c Tue Nov 8 21:06:36 2011 (r227358) +++ head/sys/dev/ath/if_ath.c Tue Nov 8 21:13:05 2011 (r227359) @@ -1890,18 +1890,89 @@ _ath_getbuf_locked(struct ath_softc *sc) ATH_TXBUF_LOCK_ASSERT(sc); bf = TAILQ_FIRST(&sc->sc_txbuf); + if (bf == NULL) { + sc->sc_stats.ast_tx_getnobuf++; + } else { + if (bf->bf_flags & ATH_BUF_BUSY) { + sc->sc_stats.ast_tx_getbusybuf++; + bf = NULL; + } + } + if (bf != NULL && (bf->bf_flags & ATH_BUF_BUSY) == 0) TAILQ_REMOVE(&sc->sc_txbuf, bf, bf_list); else bf = NULL; + if (bf == NULL) { DPRINTF(sc, ATH_DEBUG_XMIT, "%s: %s\n", __func__, TAILQ_FIRST(&sc->sc_txbuf) == NULL ? "out of xmit buffers" : "xmit buffer busy"); + return NULL; } + + /* Valid bf here; clear some basic fields */ + 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 */ + bzero(&bf->bf_state, sizeof(bf->bf_state)); + return bf; } +/* + * When retrying a software frame, buffers marked ATH_BUF_BUSY + * can't be thrown back on the queue as they could still be + * in use by the hardware. + * + * This duplicates the buffer, or returns NULL. + * + * The descriptor is also copied but the link pointers and + * the DMA segments aren't copied; this frame should thus + * be again passed through the descriptor setup/chain routines + * so the link is correct. + * + * The caller must free the buffer using ath_freebuf(). + * + * XXX TODO: this call shouldn't fail as it'll cause packet loss + * XXX in the TX pathway when retries are needed. + * XXX Figure out how to keep some buffers free, or factor the + * XXX number of busy buffers into the xmit path (ath_start()) + * XXX so we don't over-commit. + */ +struct ath_buf * +ath_buf_clone(struct ath_softc *sc, const struct ath_buf *bf) +{ + struct ath_buf *tbf; + + tbf = ath_getbuf(sc); + if (tbf == NULL) + return NULL; /* XXX failure? Why? */ + + /* Copy basics */ + tbf->bf_next = NULL; + tbf->bf_nseg = bf->bf_nseg; + tbf->bf_txflags = bf->bf_txflags; + tbf->bf_flags = bf->bf_flags & ~ATH_BUF_BUSY; + tbf->bf_status = bf->bf_status; + tbf->bf_m = bf->bf_m; + tbf->bf_node = bf->bf_node; + /* will be setup by the chain/setup function */ + tbf->bf_lastds = NULL; + /* for now, last == self */ + tbf->bf_last = tbf; + tbf->bf_comp = bf->bf_comp; + + /* NOTE: DMA segments will be setup by the setup/chain functions */ + + /* The caller has to re-init the descriptor + links */ + + /* Copy state */ + memcpy(&tbf->bf_state, &bf->bf_state, sizeof(bf->bf_state)); + + return tbf; +} + struct ath_buf * ath_getbuf(struct ath_softc *sc) { Modified: head/sys/dev/ath/if_ath_misc.h ============================================================================== --- head/sys/dev/ath/if_ath_misc.h Tue Nov 8 21:06:36 2011 (r227358) +++ head/sys/dev/ath/if_ath_misc.h Tue Nov 8 21:13:05 2011 (r227359) @@ -52,6 +52,8 @@ extern int ath_tx_findrix(const struct a extern struct ath_buf * ath_getbuf(struct ath_softc *sc); extern struct ath_buf * _ath_getbuf_locked(struct ath_softc *sc); +extern struct ath_buf * ath_buf_clone(struct ath_softc *sc, + const struct ath_buf *bf); extern int ath_reset(struct ifnet *, ATH_RESET_TYPE);