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.
This commit is contained in:
adrian 2012-04-04 21:49:49 +00:00
parent 1a4c884636
commit 866c0e9fc2
5 changed files with 24 additions and 9 deletions

View File

@ -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);

View File

@ -336,8 +336,8 @@ extern int ar5416SetupTxQueue(struct ath_hal *ah, HAL_TX_QUEUE type,
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);

View File

@ -338,13 +338,15 @@ ar5416ChainTxDesc(struct ath_hal *ah, struct ath_desc *ds,
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, struct ath_desc *ds,
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, struct ath_desc *ds,
* 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, struct ath_desc *ds,
ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2;
ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3;
#endif
return AH_TRUE;
}

View File

@ -363,7 +363,8 @@ ath_tx_chaindesclist_subframe(struct ath_softc *sc, struct ath_buf *bf)
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,

View File

@ -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)))