svn commit: r247145 - head/sys/dev/ath/ath_hal/ar5416
Adrian Chadd
adrian at freebsd.org
Fri Feb 22 07:15:26 UTC 2013
Hi,
Here's a fun little workaround for the AR5416, AR9130 and AR9160.
If you use those chips, please update to -HEAD and let me know how it goes.
Thanks!
Adrian
On 21 February 2013 23:07, Adrian Chadd <adrian at freebsd.org> wrote:
> Author: adrian
> Date: Fri Feb 22 07:07:11 2013
> New Revision: 247145
> URL: http://svnweb.freebsd.org/changeset/base/247145
>
> Log:
> Add a workaround for AR5416, AR9130 and AR9160 chipsets - work around
> an incorrectly calculated RTS duration value when transmitting aggregates.
>
> These earlier 802.11n NICs incorrectly used the ACK duration time when
> calculating what to put in the RTS of an aggregate frame. Instead it
> should have used the block-ack time. The result is that other stations
> may not reserve enough time and start transmitting _over_ the top of
> the in-progress blockack field. Tsk.
>
> This workaround is to popuate the burst duration field with the delta
> between the ACK duration the hardware is using and the required duration
> for the block-ack. The result is that the RTS field should now contain
> the correct duration for the subsequent block-ack.
>
> This doesn't apply for AR9280 and later NICs.
>
> Obtained from: Qualcomm Atheros
>
> Modified:
> head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
>
> Modified: head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
> ==============================================================================
> --- head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c Fri Feb 22 00:46:32 2013 (r247144)
> +++ head/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c Fri Feb 22 07:07:11 2013 (r247145)
> @@ -669,6 +669,26 @@ ar5416GetGlobalTxTimeout(struct ath_hal
> return MS(OS_REG_READ(ah, AR_GTXTO), AR_GTXTO_TIMEOUT_LIMIT);
> }
>
> +#define HT_RC_2_MCS(_rc) ((_rc) & 0x0f)
> +static const u_int8_t baDurationDelta[] = {
> + 24, // 0: BPSK
> + 12, // 1: QPSK 1/2
> + 12, // 2: QPSK 3/4
> + 4, // 3: 16-QAM 1/2
> + 4, // 4: 16-QAM 3/4
> + 4, // 5: 64-QAM 2/3
> + 4, // 6: 64-QAM 3/4
> + 4, // 7: 64-QAM 5/6
> + 24, // 8: BPSK
> + 12, // 9: QPSK 1/2
> + 12, // 10: QPSK 3/4
> + 4, // 11: 16-QAM 1/2
> + 4, // 12: 16-QAM 3/4
> + 4, // 13: 64-QAM 2/3
> + 4, // 14: 64-QAM 3/4
> + 4, // 15: 64-QAM 5/6
> +};
> +
> void
> ar5416Set11nRateScenario(struct ath_hal *ah, struct ath_desc *ds,
> u_int durUpdateEn, u_int rtsctsRate,
> @@ -740,17 +760,44 @@ ar5416Set11nRateScenario(struct ath_hal
> | SM(rtsctsRate, AR_RTSCTSRate);
> }
>
> +/*
> + * Note: this should be called before calling ar5416SetBurstDuration()
> + * (if it is indeed called) in order to ensure that the burst duration
> + * is correctly updated with the BA delta workaround.
> + */
> void
> ar5416Set11nAggrFirst(struct ath_hal *ah, struct ath_desc *ds, u_int aggrLen,
> u_int numDelims)
> {
> struct ar5416_desc *ads = AR5416DESC(ds);
> + uint32_t flags;
> + uint32_t burstDur;
> + uint8_t rate;
>
> ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr);
>
> ads->ds_ctl6 &= ~(AR_AggrLen | AR_PadDelim);
> ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen);
> ads->ds_ctl6 |= SM(numDelims, AR_PadDelim);
> +
> + if (! AR_SREV_MERLIN_10_OR_LATER(ah)) {
> + /*
> + * XXX It'd be nice if I were passed in the rate scenario
> + * at this point..
> + */
> + rate = MS(ads->ds_ctl3, AR_XmitRate0);
> + flags = ads->ds_ctl0 & (AR_CTSEnable | AR_RTSEnable);
> + /*
> + * WAR - MAC assumes normal ACK time instead of
> + * block ACK while computing packet duration.
> + * Add this delta to the burst duration in the descriptor.
> + */
> + if (flags && (ads->ds_ctl1 & AR_IsAggr)) {
> + burstDur = baDurationDelta[HT_RC_2_MCS(rate)];
> + ads->ds_ctl2 &= ~(AR_BurstDur);
> + ads->ds_ctl2 |= SM(burstDur, AR_BurstDur);
> + }
> + }
> }
>
> void
> @@ -792,14 +839,36 @@ ar5416Clr11nAggr(struct ath_hal *ah, str
> ads->ds_ctl6 &= ~AR_AggrLen;
> }
>
> +/*
> + * Program the burst duration, with the included BA delta if it's
> + * applicable.
> + */
> void
> ar5416Set11nBurstDuration(struct ath_hal *ah, struct ath_desc *ds,
> u_int burstDuration)
> {
> struct ar5416_desc *ads = AR5416DESC(ds);
> + uint32_t burstDur = 0;
> + uint8_t rate;
> +
> + if (! AR_SREV_MERLIN_10_OR_LATER(ah)) {
> + /*
> + * XXX It'd be nice if I were passed in the rate scenario
> + * at this point..
> + */
> + rate = MS(ads->ds_ctl3, AR_XmitDataTries0);
> + /*
> + * WAR - MAC assumes normal ACK time instead of
> + * block ACK while computing packet duration.
> + * Add this delta to the burst duration in the descriptor.
> + */
> + if (ads->ds_ctl1 & AR_IsAggr) {
> + burstDur = baDurationDelta[HT_RC_2_MCS(rate)];
> + }
> + }
>
> ads->ds_ctl2 &= ~AR_BurstDur;
> - ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur);
> + ads->ds_ctl2 |= SM(burstDur + burstDuration, AR_BurstDur);
> }
>
> /*
More information about the freebsd-wireless
mailing list