From owner-svn-src-head@FreeBSD.ORG Thu Nov 15 03:00:49 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 896B85A2; Thu, 15 Nov 2012 03:00:49 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 6BC008FC18; Thu, 15 Nov 2012 03:00:49 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id qAF30nlx001744; Thu, 15 Nov 2012 03:00:49 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id qAF30nmY001743; Thu, 15 Nov 2012 03:00:49 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201211150300.qAF30nmY001743@svn.freebsd.org> From: Adrian Chadd Date: Thu, 15 Nov 2012 03:00:49 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r243047 - head/sys/dev/ath X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 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: Thu, 15 Nov 2012 03:00:49 -0000 Author: adrian Date: Thu Nov 15 03:00:49 2012 New Revision: 243047 URL: http://svnweb.freebsd.org/changeset/base/243047 Log: Make sure the final descriptor in an aggregate has rate control information. This was broken by me when merging the 802.11n aggregate descriptor chain setup with the default descriptor chain setup, in preparation for supporting AR9380 NICs. The corner case here is quite specific - if you queue an aggregate frame with >1 frames in it, and the last subframe has only one descriptor making it up, then that descriptor won't have the rate control information copied into it. Look at what happens inside ar5416FillTxDesc() if both firstSeg and lastSeg are set to 1. Then when ar5416ProcTxDesc() goes to fill out ts_rate based on the transmit index, it looks at the rate control fields in that descriptor and dutifully sets it to be 0. It doesn't happen for non-aggregate frames - if they have one descriptor, the first descriptor already has rate control info. I removed the call to ath_hal_setuplasttxdesc() when I migrated the code to use the "new" style aggregate chain routines from the HAL. But I missed this particular corner case. This is a bit inefficient with MIPS boards as it involves a few redundant writes into non-cachable memory. I'll chase that up when it matters. Tested: * AR9280 STA mode, TCP iperf traffic * Rui Paulo first reported this and has verified it on his AR9160 based AP. PR: kern/173636 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 Thu Nov 15 00:51:57 2012 (r243046) +++ head/sys/dev/ath/if_ath_tx.c Thu Nov 15 03:00:49 2012 (r243047) @@ -623,6 +623,31 @@ ath_tx_setds_11n(struct ath_softc *sc, s */ bf_first->bf_last = bf_prev; + /* + * For non-AR9300 NICs, which require the rate control + * in the final descriptor - let's set that up now. + * + * This is because the filltxdesc() HAL call doesn't + * populate the last segment with rate control information + * if firstSeg is also true. For non-aggregate frames + * that is fine, as the first frame already has rate control + * info. But if the last frame in an aggregate has one + * descriptor, both firstseg and lastseg will be true and + * the rate info isn't copied. + * + * This is inefficient on MIPS/ARM platforms that have + * non-cachable memory for TX descriptors, but we'll just + * make do for now. + * + * As to why the rate table is stashed in the last descriptor + * rather than the first descriptor? Because proctxdesc() + * is called on the final descriptor in an MPDU or A-MPDU - + * ie, the one that gets updated by the hardware upon + * completion. That way proctxdesc() doesn't need to know + * about the first _and_ last TX descriptor. + */ + ath_hal_setuplasttxdesc(sc->sc_ah, bf_prev->bf_lastds, ds0); + DPRINTF(sc, ATH_DEBUG_SW_TX_AGGR, "%s: end\n", __func__); }