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:
parent
1a4c884636
commit
866c0e9fc2
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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)))
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user