--- a/ath/if_ath.c
+++ b/ath/if_ath.c
@@ -2785,6 +2785,44 @@
 	return 1;
 }
 
+/* Fix up the ATIM window after TSF resync */
+static int
+ath_hw_check_atim(struct ath_softc *sc, int window)
+{
+#define AR5K_TIMER0_5210       0x802c  /* Next beacon time register */
+#define AR5K_TIMER0_5211       0x8028
+#define AR5K_TIMER3_5210       0x8038  /* End of ATIM window time register */
+#define AR5K_TIMER3_5211       0x8034
+	struct ath_hal *ah = sc->sc_ah;
+	unsigned int nbtt, atim;
+	int dev = ar_device(sc->devid);
+
+	switch(dev) {
+	case 5210:
+		nbtt = OS_REG_READ(ah, AR5K_TIMER0_5210);
+		atim = OS_REG_READ(ah, AR5K_TIMER3_5210);
+		if (atim - nbtt != window) {
+			OS_REG_WRITE(ah, AR5K_TIMER3_5210, nbtt + window );
+			return atim - nbtt;
+		}
+		break;
+	case 5211:
+	case 5212:
+		nbtt = OS_REG_READ(ah, AR5K_TIMER0_5211);
+		atim = OS_REG_READ(ah, AR5K_TIMER3_5211);
+		if (atim - nbtt != window) {
+			OS_REG_WRITE(ah, AR5K_TIMER3_5211, nbtt + window );
+			return atim - nbtt;
+		}
+		break;
+	/* NB: 5416+ doesn't do ATIM in hw */
+	default:
+		break;
+	}
+	return 0;
+}
+
+
 /*
  * Reset the hardware w/o losing operational state.  This is
  * basically a more efficient way of doing ath_stop, ath_init,
@@ -6391,6 +6429,11 @@
 			DPRINTF(sc, ATH_DEBUG_BEACON, 
 				"Updated beacon timers\n");
 		}
+		if ((sc->sc_opmode == IEEE80211_M_IBSS) &&
+				IEEE80211_ADDR_EQ(ni->ni_bssid, vap->iv_bss->ni_bssid) &&
+				ath_hw_check_atim(sc, 1)) {
+			DPRINTF(sc, ATH_DEBUG_ANY, "Fixed ATIM window after beacon recv\n");
+		}
 		/* NB: Fall Through */
 	case IEEE80211_FC0_SUBTYPE_PROBE_RESP:
 		if (vap->iv_opmode == IEEE80211_M_IBSS &&
