From owner-svn-src-all@FreeBSD.ORG Wed Apr 4 21:49:50 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 65FF5106566B; Wed, 4 Apr 2012 21:49:50 +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 515438FC17; Wed, 4 Apr 2012 21:49:50 +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 q34LnoYw026654; Wed, 4 Apr 2012 21:49:50 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q34LnouF026648; Wed, 4 Apr 2012 21:49:50 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201204042149.q34LnouF026648@svn.freebsd.org> From: Adrian Chadd Date: Wed, 4 Apr 2012 21:49:50 +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: r233895 - in head/sys/dev/ath: . ath_hal ath_hal/ar5416 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: Wed, 04 Apr 2012 21:49:50 -0000 Author: adrian Date: Wed Apr 4 21:49:49 2012 New Revision: 233895 URL: http://svn.freebsd.org/changeset/base/233895 Log: Correctly handle AR_MoreAggr when assembling multi-descriptor final frames. Linux ath9k doesn't have this issue as it doesn't try queuing multi- descriptor frames to the hardware. Before, I was only setting the first and last descriptor in the final frame correctly - and that was done by accident. The first descriptor in the last sub-frame was being correctly updated by ath_tx_setds_11n(); the last descriptor in the last sub-frame was being correctly updated by ath_buf_set_rate(). But both of those are "incorrect". The correct behaviour is: * AR_IsAggr is set for all descriptors for all subframes in an aggregate. * AR_MoreAggr is set for all descriptors for all non-final sub-frames in an aggregate. Ie, all descriptors in the last sub-frame of an aggregate must have this field set to 0. I still need to do a couple of extra passes to ensure the pad delimiter field is being correctly handled in all descriptors in the last sub-frame. Modified: head/sys/dev/ath/ath_hal/ah.h head/sys/dev/ath/ath_hal/ar5416/ar5416.h head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c head/sys/dev/ath/if_ath_tx.c head/sys/dev/ath/if_athvar.h Modified: head/sys/dev/ath/ath_hal/ah.h ============================================================================== --- head/sys/dev/ath/ath_hal/ah.h Wed Apr 4 21:38:26 2012 (r233894) +++ head/sys/dev/ath/ath_hal/ah.h Wed Apr 4 21:49:49 2012 (r233895) @@ -1010,7 +1010,7 @@ struct ath_hal { HAL_BOOL __ahdecl(*ah_chainTxDesc)(struct ath_hal *, struct ath_desc *, u_int, u_int, HAL_PKT_TYPE, u_int, HAL_CIPHER, uint8_t, u_int, HAL_BOOL, - HAL_BOOL); + HAL_BOOL, HAL_BOOL); HAL_BOOL __ahdecl(*ah_setupFirstTxDesc)(struct ath_hal *, struct ath_desc *, u_int, u_int, u_int, u_int, u_int, u_int, u_int, u_int); Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416.h ============================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416.h Wed Apr 4 21:38:26 2012 (r233894) +++ head/sys/dev/ath/ath_hal/ar5416/ar5416.h Wed Apr 4 21:49:49 2012 (r233895) @@ -336,8 +336,8 @@ extern int ar5416SetupTxQueue(struct ath extern HAL_BOOL ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds, u_int pktLen, u_int hdrLen, HAL_PKT_TYPE type, u_int keyIx, - HAL_CIPHER cipher, uint8_t delims, u_int segLen, HAL_BOOL firstSeg, - HAL_BOOL lastSeg); + HAL_CIPHER cipher, uint8_t delims, u_int segLen, + HAL_BOOL firstSeg, HAL_BOOL lastSeg, HAL_BOOL lastAggr); extern HAL_BOOL ar5416SetupFirstTxDesc(struct ath_hal *ah, struct ath_desc *ds, u_int aggrLen, u_int flags, u_int txPower, u_int txRate0, u_int txTries0, u_int antMode, u_int rtsctsRate, u_int rtsctsDuration); Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c ============================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c Wed Apr 4 21:38:26 2012 (r233894) +++ head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c Wed Apr 4 21:49:49 2012 (r233895) @@ -338,13 +338,15 @@ ar5416ChainTxDesc(struct ath_hal *ah, st uint8_t delims, u_int segLen, HAL_BOOL firstSeg, - HAL_BOOL lastSeg) + HAL_BOOL lastSeg, + HAL_BOOL lastAggr) { struct ar5416_desc *ads = AR5416DESC(ds); uint32_t *ds_txstatus = AR5416_DS_TXSTATUS(ah,ads); struct ath_hal_5416 *ahp = AH5416(ah); int isaggr = 0; + uint32_t last_aggr = 0; (void) hdrLen; (void) ah; @@ -355,6 +357,8 @@ ar5416ChainTxDesc(struct ath_hal *ah, st if (type == HAL_PKT_TYPE_AMPDU) { type = HAL_PKT_TYPE_NORMAL; isaggr = 1; + if (lastAggr == AH_FALSE) + last_aggr = AR_MoreAggr; } /* @@ -372,8 +376,19 @@ ar5416ChainTxDesc(struct ath_hal *ah, st * Note: VEOL should only be for the last descriptor in the chain. */ ads->ds_ctl0 = (pktLen & AR_FrameLen); + + /* + * For aggregates: + * + IsAggr must be set for all descriptors of all subframes of + * the aggregate + * + MoreAggr must be set for all descriptors of all subframes + * of the aggregate EXCEPT the last subframe; + * + MoreAggr must be _CLEAR_ for all descrpitors of the last + * subframe of the aggregate. + */ ads->ds_ctl1 = (type << AR_FrameType_S) - | (isaggr ? (AR_IsAggr | AR_MoreAggr) : 0); + | (isaggr ? (AR_IsAggr | last_aggr) : 0); + ads->ds_ctl2 = 0; ads->ds_ctl3 = 0; if (keyIx != HAL_TXKEYIX_INVALID) { @@ -483,7 +498,6 @@ ar5416SetupLastTxDesc(struct ath_hal *ah ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; #endif - return AH_TRUE; } Modified: head/sys/dev/ath/if_ath_tx.c ============================================================================== --- head/sys/dev/ath/if_ath_tx.c Wed Apr 4 21:38:26 2012 (r233894) +++ head/sys/dev/ath/if_ath_tx.c Wed Apr 4 21:49:49 2012 (r233895) @@ -363,7 +363,8 @@ ath_tx_chaindesclist_subframe(struct ath bf->bf_state.bfs_ndelim, bf->bf_segs[i].ds_len, /* segment length */ i == 0, /* first segment */ - i == bf->bf_nseg - 1 /* last segment */ + i == bf->bf_nseg - 1, /* last segment */ + bf->bf_next == NULL /* last sub-frame in aggr */ ); DPRINTF(sc, ATH_DEBUG_XMIT, Modified: head/sys/dev/ath/if_athvar.h ============================================================================== --- head/sys/dev/ath/if_athvar.h Wed Apr 4 21:38:26 2012 (r233894) +++ head/sys/dev/ath/if_athvar.h Wed Apr 4 21:49:49 2012 (r233895) @@ -957,10 +957,10 @@ void ath_intr(void *); ((*(_ah)->ah_setupFirstTxDesc)((_ah), (_ds), (_aggrlen), (_flags), \ (_txpower), (_txr0), (_txtr0), (_antm), (_rcr), (_rcd))) #define ath_hal_chaintxdesc(_ah, _ds, _pktlen, _hdrlen, _type, _keyix, \ - _cipher, _delims, _seglen, _first, _last) \ + _cipher, _delims, _seglen, _first, _last, _lastaggr) \ ((*(_ah)->ah_chainTxDesc)((_ah), (_ds), (_pktlen), (_hdrlen), \ (_type), (_keyix), (_cipher), (_delims), (_seglen), \ - (_first), (_last))) + (_first), (_last), (_lastaggr))) #define ath_hal_setuplasttxdesc(_ah, _ds, _ds0) \ ((*(_ah)->ah_setupLastTxDesc)((_ah), (_ds), (_ds0)))