From owner-svn-src-head@FreeBSD.ORG Fri Feb 22 07:07:12 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 5E2CF1A1; Fri, 22 Feb 2013 07:07:12 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 38D70A98; Fri, 22 Feb 2013 07:07:12 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r1M77CPf059447; Fri, 22 Feb 2013 07:07:12 GMT (envelope-from adrian@svn.freebsd.org) Received: (from adrian@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r1M77C2s059446; Fri, 22 Feb 2013 07:07:12 GMT (envelope-from adrian@svn.freebsd.org) Message-Id: <201302220707.r1M77C2s059446@svn.freebsd.org> From: Adrian Chadd Date: Fri, 22 Feb 2013 07:07:12 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r247145 - head/sys/dev/ath/ath_hal/ar5416 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 22 Feb 2013 07:07:12 -0000 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); } /*