Date: Thu, 21 Feb 2013 23:15:24 -0800 From: Adrian Chadd <adrian@freebsd.org> To: freebsd-wireless@freebsd.org Subject: Re: svn commit: r247145 - head/sys/dev/ath/ath_hal/ar5416 Message-ID: <CAJ-Vmo=N0Pm8114z9tQ7gL=NS4RO4h9_wLvkM%2BN=boX6ZiHjtw@mail.gmail.com> In-Reply-To: <201302220707.r1M77C2s059446@svn.freebsd.org> References: <201302220707.r1M77C2s059446@svn.freebsd.org>
next in thread | previous in thread | raw e-mail | index | archive | help
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@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); > } > > /*
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAJ-Vmo=N0Pm8114z9tQ7gL=NS4RO4h9_wLvkM%2BN=boX6ZiHjtw>