svn commit: r233895 - in head/sys/dev/ath: . ath_hal ath_hal/ar5416
Adrian Chadd
adrian at FreeBSD.org
Wed Apr 4 21:49:50 UTC 2012
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)))
More information about the svn-src-all
mailing list