summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c')
-rw-r--r--sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c71
1 files changed, 70 insertions, 1 deletions
diff --git a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
index 36f968f..945c766 100644
--- a/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
+++ b/sys/dev/ath/ath_hal/ar5416/ar5416_xmit.c
@@ -669,6 +669,26 @@ ar5416GetGlobalTxTimeout(struct ath_hal *ah)
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 *ah, struct ath_desc *ds,
| 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, struct ath_desc *ds)
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);
}
/*
OpenPOWER on IntegriCloud