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 <adr...@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);
>  }
>
>  /*
_______________________________________________
freebsd-wireless@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-wireless
To unsubscribe, send any mail to "freebsd-wireless-unsubscr...@freebsd.org"

Reply via email to