Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 4 Apr 2012 21:49:50 +0000 (UTC)
From:      Adrian Chadd <adrian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r233895 - in head/sys/dev/ath: . ath_hal ath_hal/ar5416
Message-ID:  <201204042149.q34LnouF026648@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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)))
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204042149.q34LnouF026648>