⬢ DragonFlyBSD Kernel Audit
DF-4723 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/netif/ath/ath/if_ath_tdma.c
+++ b/sys/dev/netif/ath/ath/if_ath_tdma.c
@@ -138,13 +138,25 @@ static void
 ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval)
 {
 	struct ath_hal *ah = sc->sc_ah;
 	HAL_BEACON_TIMERS bt;
+	u_int64_t dba, swba;
 
 	bt.bt_intval = bintval | HAL_BEACON_ENA;
 	bt.bt_nexttbtt = nexttbtt;
-	bt.bt_nextdba = (nexttbtt<<3) - sc->sc_tdmadbaprep;
-	bt.bt_nextswba = (nexttbtt<<3) - sc->sc_tdmaswbaprep;
+	/*
+	 * DF-4723: nexttbtt is the full 32-bit TU value derived from the
+	 * TSF; doing the TU -> 1/8 TU conversion in 32-bit truncated the
+	 * DBA/SWBA targets once TSF crossed 2^29 TU (~6.2 days), wrapping
+	 * the alert timers while bt_nexttbtt itself stayed coherent.
+	 * Compute in 64-bit and truncate once so all three timers share
+	 * one wrap point.
+	 */
+	dba = ((u_int64_t)nexttbtt << 3) - sc->sc_tdmadbaprep;
+	swba = ((u_int64_t)nexttbtt << 3) - sc->sc_tdmaswbaprep;
+	bt.bt_nextdba = (u_int32_t)dba;
+	bt.bt_nextswba = (u_int32_t)swba;
 	bt.bt_nextatim = nexttbtt+1;
 	/* Enables TBTT, DBA, SWBA timers by default */
 	bt.bt_flags = 0;