From owner-svn-src-all@FreeBSD.ORG Mon Sep 24 06:42:21 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EE6AE106564A; Mon, 24 Sep 2012 06:42:20 +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 D934F8FC0C; Mon, 24 Sep 2012 06:42:20 +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 q8O6gKR5061709; Mon, 24 Sep 2012 06:42:20 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q8O6gK5u061707; Mon, 24 Sep 2012 06:42:20 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201209240642.q8O6gK5u061707@svn.freebsd.org> From: Adrian Chadd Date: Mon, 24 Sep 2012 06:42:20 +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: r240883 - head/sys/dev/ath X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 24 Sep 2012 06:42:21 -0000 Author: adrian Date: Mon Sep 24 06:42:20 2012 New Revision: 240883 URL: http://svn.freebsd.org/changeset/base/240883 Log: Prepare for software retransmission of non-aggregate frames but ensure it's disabled. The previous commit to enable CLRDMASK setting didn't do it at all correctly for non-aggregate sessions - so the CLRDMASK bit would be cleared and never re-set. * move ath_tx_update_clrdmask() to be called by functions that setup descriptors and queue frames to the hardware, rather than scattered everywhere. * Force CLRDMASK to be set on all non-aggregate session frames being transmitted. * Use ath_tx_normal_comp() now on non-aggregate sessoin frames that are queued via ath_tx_xmit_normal(). That way the TID hwq is updated and they can trigger (eventual) filter frame queue resets and software retransmits. There's still a bit more work to do in this area to reverse the silly short-sightedness on my part, however it's likely going to be better to fix this now than just reverting the patch. Thanks to people on the freebsd-wireless@ mailing list for promptly pointing this out. Modified: head/sys/dev/ath/if_ath_tx.c Modified: head/sys/dev/ath/if_ath_tx.c ============================================================================== --- head/sys/dev/ath/if_ath_tx.c Mon Sep 24 06:00:51 2012 (r240882) +++ head/sys/dev/ath/if_ath_tx.c Mon Sep 24 06:42:20 2012 (r240883) @@ -1260,6 +1260,22 @@ ath_tx_do_ratelookup(struct ath_softc *s } /* + * Update the CLRDMASK bit in the ath_buf if it needs to be set. + */ +static void +ath_tx_update_clrdmask(struct ath_softc *sc, struct ath_tid *tid, + struct ath_buf *bf) +{ + + ATH_TID_LOCK_ASSERT(sc, tid); + + if (tid->clrdmask == 1) { + bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK; + tid->clrdmask = 0; + } +} + +/* * Transmit the given frame to the hardware. * * The frame must already be setup; rate control must already have @@ -1274,9 +1290,25 @@ static void ath_tx_xmit_normal(struct ath_softc *sc, struct ath_txq *txq, struct ath_buf *bf) { + struct ath_node *an = ATH_NODE(bf->bf_node); + struct ath_tid *tid = &an->an_tid[bf->bf_state.bfs_tid]; ATH_TXQ_LOCK_ASSERT(txq); + /* + * For now, just enable CLRDMASK. ath_tx_xmit_normal() does + * set a completion handler however it doesn't (yet) properly + * handle the strict ordering requirements needed for normal, + * non-aggregate session frames. + * + * Once this is implemented, only set CLRDMASK like this for + * frames that must go out - eg management/raw frames. + */ + bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK; + + /* See if clrdmask needs to be set */ + ath_tx_update_clrdmask(sc, tid, bf); + /* Setup the descriptor before handoff */ ath_tx_do_ratelookup(sc, bf); ath_tx_calc_duration(sc, bf); @@ -1285,8 +1317,11 @@ ath_tx_xmit_normal(struct ath_softc *sc, ath_tx_rate_fill_rcflags(sc, bf); ath_tx_setds(sc, bf); - /* XXX Bump TID HWQ counter */ - /* XXX Assign a completion handler */ + /* Track per-TID hardware queue depth correctly */ + tid->hwq_depth++; + + /* Assign the completion handler */ + bf->bf_comp = ath_tx_normal_comp; /* Hand off to hardware */ ath_tx_handoff(sc, txq, bf); @@ -2485,22 +2520,6 @@ ath_tx_tid_unsched(struct ath_softc *sc, } /* - * Update the CLRDMASK bit in the ath_buf if it needs to be set. - */ -static void -ath_tx_update_clrdmask(struct ath_softc *sc, struct ath_tid *tid, - struct ath_buf *bf) -{ - - ATH_TID_LOCK_ASSERT(sc, tid); - - if (tid->clrdmask == 1) { - bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK; - tid->clrdmask = 0; - } -} - -/* * Assign a sequence number manually to the given frame. * * This should only be called for A-MPDU TX frames. @@ -2738,7 +2757,6 @@ ath_tx_swq(struct ath_softc *sc, struct } else if (txq->axq_depth < sc->sc_hwq_limit) { /* AMPDU not running, attempt direct dispatch */ DPRINTF(sc, ATH_DEBUG_SW_TX, "%s: xmit_normal\n", __func__); - ath_tx_update_clrdmask(sc, atid, bf); ath_tx_xmit_normal(sc, txq, bf); } else { /* Busy; queue */ @@ -3432,6 +3450,19 @@ ath_tx_txq_drain(struct ath_softc *sc, s /* * Handle completion of non-aggregate session frames. + * + * This (currently) doesn't implement software retransmission of + * non-aggregate frames! + * + * Software retransmission of non-aggregate frames needs to obey + * the strict sequence number ordering, and drop any frames that + * will fail this. + * + * For now, filtered frames and frame transmission will cause + * all kinds of issues. So we don't support them. + * + * So anyone queuing frames via ath_tx_normal_xmit() or + * ath_tx_hw_queue_norm() must override and set CLRDMASK. */ void ath_tx_normal_comp(struct ath_softc *sc, struct ath_buf *bf, int fail) @@ -3450,10 +3481,23 @@ ath_tx_normal_comp(struct ath_softc *sc, atid->hwq_depth--; +#if 0 + /* + * If the frame was filtered, stick it on the filter frame + * queue and complain about it. It shouldn't happen! + */ + if ((ts->ts_status & HAL_TXERR_FILT) || + (ts->ts_status != 0 && atid->isfiltered)) { + device_printf(sc->sc_dev, + "%s: isfiltered=%d, ts_status=%d: huh?\n", + __func__, + atid->isfiltered, + ts->ts_status); + ath_tx_tid_filt_comp_buf(sc, atid, bf); + } +#endif if (atid->isfiltered) - device_printf(sc->sc_dev, "%s: isfiltered=1, normal_comp?\n", - __func__); - + device_printf(sc->sc_dev, "%s: filtered?!\n", __func__); if (atid->hwq_depth < 0) device_printf(sc->sc_dev, "%s: hwq_depth < 0: %d\n", __func__, atid->hwq_depth); @@ -3471,7 +3515,6 @@ ath_tx_normal_comp(struct ath_softc *sc, */ if (atid->isfiltered) ath_tx_tid_filt_comp_complete(sc, atid); - ATH_TXQ_UNLOCK(sc->sc_ac2q[atid->ac]); /* @@ -4766,6 +4809,12 @@ ath_tx_tid_hw_queue_norm(struct ath_soft /* Normal completion handler */ bf->bf_comp = ath_tx_normal_comp; + /* + * Override this for now, until the non-aggregate + * completion handler correctly handles software retransmits. + */ + bf->bf_state.bfs_txflags |= HAL_TXDESC_CLRDMASK; + /* Update CLRDMASK just before this frame is queued */ ath_tx_update_clrdmask(sc, tid, bf);