Date: Mon, 29 Aug 2011 20:01:27 +0800 From: Kang Yin Su <cantona@cantona.net> To: freebsd-wireless@freebsd.org Subject: [PATCH] TDMA beacon from slave station Message-ID: <CAHjFwoDRFMGRJnCCd9PQcksZ-pEg=SUAL1q-4scOnXjmTQArYQ@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
[-- Attachment #1 --]
Hi all,
This patch modify the following:
1. Relocate 'ath_hal_*' functions from if_ath.c to appropriate HAL
layer and moved those common functions to ah.c
2. The next TBTT register mistakenly used in AR6416 that cause
intermittent beacons transmit form a TDMA slave station.
- Use AR_NEXT_TBTT instead of AR_TIMER0 for AR5416.
3. Do not adjust the beacon timers when 'tudelta' value is multiple of
tdmabintval value. It causes the timers to stop and beacon stuck.
Thanks,
Yin
[-- Attachment #2 --]
Index: if_athvar.h
===================================================================
--- if_athvar.h (revision 225242)
+++ if_athvar.h (working copy)
@@ -482,6 +482,8 @@
((*(_ah)->ah_setBeaconTimers)((_ah), (_bt)))
#define ath_hal_beacontimers(_ah, _bs) \
((*(_ah)->ah_setStationBeaconTimers)((_ah), (_bs)))
+#define ath_hal_getnexttbtt(_ah) \
+ ((*(_ah)->ah_getNextTBTT)((_ah)))
#define ath_hal_setassocid(_ah, _bss, _associd) \
((*(_ah)->ah_writeAssocid)((_ah), (_bss), (_associd)))
#define ath_hal_phydisable(_ah) \
Index: ath_hal/ar5416/ar5416_attach.c
===================================================================
--- ath_hal/ar5416/ar5416_attach.c (revision 225242)
+++ ath_hal/ar5416/ar5416_attach.c (working copy)
@@ -136,6 +136,7 @@
ah->ah_gpioGet = ar5416GpioGet;
ah->ah_gpioSet = ar5416GpioSet;
ah->ah_gpioSetIntr = ar5416GpioSetIntr;
+ ah->ah_getTsf64 = ar5416GetTsf64;
ah->ah_resetTsf = ar5416ResetTsf;
ah->ah_getRfGain = ar5416GetRfgain;
ah->ah_setAntennaSwitch = ar5416SetAntennaSwitch;
@@ -160,6 +161,7 @@
ah->ah_beaconInit = ar5416BeaconInit;
ah->ah_setStationBeaconTimers = ar5416SetStaBeaconTimers;
ah->ah_resetStationBeaconTimers = ar5416ResetStaBeaconTimers;
+ ah->ah_getNextTBTT = ar5416GetNextTBTT;
/* 802.11n Functions */
ah->ah_chainTxDesc = ar5416ChainTxDesc;
Index: ath_hal/ar5416/ar5416_reset.c
===================================================================
--- ath_hal/ar5416/ar5416_reset.c (revision 225242)
+++ ath_hal/ar5416/ar5416_reset.c (working copy)
@@ -147,7 +147,7 @@
/* For chips on which the RTC reset is done, save TSF before it gets cleared */
if (AR_SREV_HOWL(ah) ||
(AR_SREV_MERLIN(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)))
- tsf = ar5212GetTsf64(ah);
+ tsf = ar5416GetTsf64(ah);
/* Mark PHY as inactive; marked active in ar5416InitBB() */
ar5416MarkPhyInactive(ah);
@@ -159,7 +159,7 @@
/* Restore TSF */
if (tsf)
- ar5212SetTsf64(ah, tsf);
+ ar5416SetTsf64(ah, tsf);
OS_MARK(ah, AH_MARK_RESET_LINE, __LINE__);
if (AR_SREV_MERLIN_10_OR_LATER(ah))
@@ -192,9 +192,9 @@
* value after the initvals have been applied, with an offset
* based on measured time difference
*/
- if (AR_SREV_HOWL(ah) && (ar5212GetTsf64(ah) < tsf)) {
+ if (AR_SREV_HOWL(ah) && (ar5416GetTsf64(ah) < tsf)) {
tsf += 1500;
- ar5212SetTsf64(ah, tsf);
+ ar5416SetTsf64(ah, tsf);
}
HALDEBUG(ah, HAL_DEBUG_RESET, ">>>2 %s: AR_PHY_DAG_CTRLCCK=0x%x\n",
@@ -503,7 +503,7 @@
chan->ic_state &= ~IEEE80211_CHANSTATE_CWINT;
ichan->channel_time = 0;
- ichan->tsf_last = ar5212GetTsf64(ah);
+ ichan->tsf_last = ar5416GetTsf64(ah);
ar5212TxEnable(ah, AH_TRUE);
return AH_TRUE;
}
Index: ath_hal/ar5416/ar5416.h
===================================================================
--- ath_hal/ar5416/ar5416.h (revision 225242)
+++ ath_hal/ar5416/ar5416.h (working copy)
@@ -169,6 +169,7 @@
extern void ar5416ResetStaBeaconTimers(struct ath_hal *ah);
extern void ar5416SetStaBeaconTimers(struct ath_hal *ah,
const HAL_BEACON_STATE *);
+extern uint64_t ar5416GetNextTBTT(struct ath_hal *);
extern HAL_BOOL ar5416EepromRead(struct ath_hal *, u_int off, uint16_t *data);
extern HAL_BOOL ar5416EepromWrite(struct ath_hal *, u_int off, uint16_t data);
@@ -186,6 +187,8 @@
extern u_int ar5416GetWirelessModes(struct ath_hal *ah);
extern void ar5416SetLedState(struct ath_hal *ah, HAL_LED_STATE state);
+extern uint64_t ar5416GetTsf64(struct ath_hal *ah);
+extern void ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64);
extern void ar5416ResetTsf(struct ath_hal *ah);
extern HAL_BOOL ar5416SetAntennaSwitch(struct ath_hal *, HAL_ANT_SETTING);
extern HAL_BOOL ar5416SetDecompMask(struct ath_hal *, uint16_t, int);
Index: ath_hal/ar5416/ar5416_beacon.c
===================================================================
--- ath_hal/ar5416/ar5416_beacon.c (revision 225242)
+++ ath_hal/ar5416/ar5416_beacon.c (working copy)
@@ -29,6 +29,15 @@
#define ONE_EIGHTH_TU_TO_USEC(_tu8) ((_tu8) << 7)
/*
+ * Return the hardware NextTBTT in TSF
+ */
+uint64_t
+ar5416GetNextTBTT(struct ath_hal *ah)
+{
+ return OS_REG_READ(ah, AR_NEXT_TBTT);
+}
+
+/*
* Initialize all of the hardware registers used to
* send beacons. Note that for station operation the
* driver calls ar5416SetStaBeaconTimers instead.
Index: ath_hal/ar5416/ar5416_misc.c
===================================================================
--- ath_hal/ar5416/ar5416_misc.c (revision 225242)
+++ ath_hal/ar5416/ar5416_misc.c (working copy)
@@ -93,6 +93,41 @@
}
/*
+ * Get the current hardware tsf for stamlme
+ */
+uint64_t
+ar5416GetTsf64(struct ath_hal *ah)
+{
+ uint32_t low1, low2, u32;
+
+ /* sync multi-word read */
+ low1 = OS_REG_READ(ah, AR_TSF_L32);
+ u32 = OS_REG_READ(ah, AR_TSF_U32);
+ low2 = OS_REG_READ(ah, AR_TSF_L32);
+ if (low2 < low1) { /* roll over */
+ /*
+ * If we are not preempted this will work. If we are
+ * then we re-reading AR_TSF_U32 does no good as the
+ * low bits will be meaningless. Likewise reading
+ * L32, U32, U32, then comparing the last two reads
+ * to check for rollover doesn't help if preempted--so
+ * we take this approach as it costs one less PCI read
+ * which can be noticeable when doing things like
+ * timestamping packets in monitor mode.
+ */
+ u32++;
+ }
+ return (((uint64_t) u32) << 32) | ((uint64_t) low2);
+}
+
+void
+ar5416SetTsf64(struct ath_hal *ah, uint64_t tsf64)
+{
+ OS_REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff);
+ OS_REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff);
+}
+
+/*
* Reset the current hardware tsf for stamlme.
*/
void
Index: ath_hal/ah.c
===================================================================
--- ath_hal/ah.c (revision 225242)
+++ ath_hal/ah.c (working copy)
@@ -1222,3 +1222,37 @@
}
return rv;
}
+
+/*
+ * Adjust the TSF.
+ */
+void
+ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
+{
+ /* XXX handle wrap/overflow */
+ OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
+}
+
+/*
+ * Enable or disable CCA.
+ */
+void
+ath_hal_setcca(struct ath_hal *ah, int ena)
+{
+ /*
+ * NB: fill me in; this is not provided by default because disabling
+ * CCA in most locales violates regulatory.
+ */
+}
+
+/*
+ * Get CCA setting.
+ */
+int
+ath_hal_getcca(struct ath_hal *ah)
+{
+ u_int32_t diag;
+ if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
+ return 1;
+ return ((diag & 0x500000) == 0);
+}
Index: ath_hal/ar5210/ar5210_attach.c
===================================================================
--- ath_hal/ar5210/ar5210_attach.c (revision 225242)
+++ ath_hal/ar5210/ar5210_attach.c (working copy)
@@ -148,6 +148,7 @@
.ah_beaconInit = ar5210BeaconInit,
.ah_setStationBeaconTimers = ar5210SetStaBeaconTimers,
.ah_resetStationBeaconTimers = ar5210ResetStaBeaconTimers,
+ .ah_getNextTBTT = ar5210GetNextTBTT,
/* Interrupt Functions */
.ah_isInterruptPending = ar5210IsInterruptPending,
Index: ath_hal/ar5210/ar5210.h
===================================================================
--- ath_hal/ar5210/ar5210.h (revision 225242)
+++ ath_hal/ar5210/ar5210.h (working copy)
@@ -268,6 +268,7 @@
extern void ar5210SetStaBeaconTimers(struct ath_hal *,
const HAL_BEACON_STATE *);
extern void ar5210ResetStaBeaconTimers(struct ath_hal *);
+extern uint64_t ar5210GetNextTBTT(struct ath_hal *);
extern HAL_BOOL ar5210IsInterruptPending(struct ath_hal *);
extern HAL_BOOL ar5210GetPendingInterrupts(struct ath_hal *, HAL_INT *);
Index: ath_hal/ar5210/ar5210_beacon.c
===================================================================
--- ath_hal/ar5210/ar5210_beacon.c (revision 225242)
+++ ath_hal/ar5210/ar5210_beacon.c (working copy)
@@ -27,6 +27,17 @@
#include "ar5210/ar5210desc.h"
/*
+ * Return the hardware NextTBTT in TSF
+ */
+uint64_t
+ar5210GetNextTBTT(struct ath_hal *ah)
+{
+#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10)
+ return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0));
+#undef TU_TO_TSF
+}
+
+/*
* Initialize all of the hardware registers used to send beacons.
*/
void
Index: ath_hal/ar5211/ar5211_attach.c
===================================================================
--- ath_hal/ar5211/ar5211_attach.c (revision 225242)
+++ ath_hal/ar5211/ar5211_attach.c (working copy)
@@ -148,6 +148,7 @@
.ah_beaconInit = ar5211BeaconInit,
.ah_setStationBeaconTimers = ar5211SetStaBeaconTimers,
.ah_resetStationBeaconTimers = ar5211ResetStaBeaconTimers,
+ .ah_getNextTBTT = ar5211GetNextTBTT,
/* Interrupt Functions */
.ah_isInterruptPending = ar5211IsInterruptPending,
Index: ath_hal/ar5211/ar5211.h
===================================================================
--- ath_hal/ar5211/ar5211.h (revision 225242)
+++ ath_hal/ar5211/ar5211.h (working copy)
@@ -296,6 +296,7 @@
extern void ar5211SetStaBeaconTimers(struct ath_hal *,
const HAL_BEACON_STATE *);
extern void ar5211ResetStaBeaconTimers(struct ath_hal *);
+extern uint64_t ar5211GetNextTBTT(struct ath_hal *);
extern HAL_BOOL ar5211IsInterruptPending(struct ath_hal *);
extern HAL_BOOL ar5211GetPendingInterrupts(struct ath_hal *, HAL_INT *);
Index: ath_hal/ar5211/ar5211_beacon.c
===================================================================
--- ath_hal/ar5211/ar5211_beacon.c (revision 225242)
+++ ath_hal/ar5211/ar5211_beacon.c (working copy)
@@ -30,6 +30,17 @@
*/
/*
+ * Return the hardware NextTBTT in TSF
+ */
+uint64_t
+ar5211GetNextTBTT(struct ath_hal *ah)
+{
+#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10)
+ return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0));
+#undef TU_TO_TSF
+}
+
+/*
* Initialize all of the hardware registers used to send beacons.
*/
void
Index: ath_hal/ar5212/ar5212_attach.c
===================================================================
--- ath_hal/ar5212/ar5212_attach.c (revision 225242)
+++ ath_hal/ar5212/ar5212_attach.c (working copy)
@@ -151,6 +151,7 @@
.ah_beaconInit = ar5212BeaconInit,
.ah_setStationBeaconTimers = ar5212SetStaBeaconTimers,
.ah_resetStationBeaconTimers = ar5212ResetStaBeaconTimers,
+ .ah_getNextTBTT = ar5212GetNextTBTT,
/* Interrupt Functions */
.ah_isInterruptPending = ar5212IsInterruptPending,
Index: ath_hal/ar5212/ar5212.h
===================================================================
--- ath_hal/ar5212/ar5212.h (revision 225242)
+++ ath_hal/ar5212/ar5212.h (working copy)
@@ -430,6 +430,7 @@
extern void ar5212ResetStaBeaconTimers(struct ath_hal *ah);
extern void ar5212SetStaBeaconTimers(struct ath_hal *ah,
const HAL_BEACON_STATE *);
+extern uint64_t ar5212GetNextTBTT(struct ath_hal *);
extern HAL_BOOL ar5212IsInterruptPending(struct ath_hal *ah);
extern HAL_BOOL ar5212GetPendingInterrupts(struct ath_hal *ah, HAL_INT *);
Index: ath_hal/ar5212/ar5212_beacon.c
===================================================================
--- ath_hal/ar5212/ar5212_beacon.c (revision 225242)
+++ ath_hal/ar5212/ar5212_beacon.c (working copy)
@@ -26,6 +26,17 @@
#include "ar5212/ar5212desc.h"
/*
+ * Return the hardware NextTBTT in TSF
+ */
+uint64_t
+ar5212GetNextTBTT(struct ath_hal *ah)
+{
+#define TU_TO_TSF(_tu) (((uint64_t)(_tu)) << 10)
+ return TU_TO_TSF(OS_REG_READ(ah, AR_TIMER0));
+#undef TU_TO_TSF
+}
+
+/*
* Initialize all of the hardware registers used to
* send beacons. Note that for station operation the
* driver calls ar5212SetStaBeaconTimers instead.
Index: ath_hal/ah.h
===================================================================
--- ath_hal/ah.h (revision 225242)
+++ ath_hal/ah.h (working copy)
@@ -996,6 +996,7 @@
void __ahdecl(*ah_setStationBeaconTimers)(struct ath_hal*,
const HAL_BEACON_STATE *);
void __ahdecl(*ah_resetStationBeaconTimers)(struct ath_hal*);
+ uint64_t __ahdecl(*ah_getNextTBTT)(struct ath_hal *);
/* 802.11n Functions */
HAL_BOOL __ahdecl(*ah_chainTxDesc)(struct ath_hal *,
@@ -1138,4 +1139,20 @@
extern uint16_t __ahdecl ath_hal_computetxtime(struct ath_hal *,
const HAL_RATE_TABLE *rates, uint32_t frameLen,
uint16_t rateix, HAL_BOOL shortPreamble);
+
+/*
+ * Adjust the TSF.
+ */
+extern void __ahdecl ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta);
+
+/*
+ * Enable or disable CCA.
+ */
+void __ahdecl ath_hal_setcca(struct ath_hal *ah, int ena);
+
+/*
+ * Get CCA setting.
+ */
+int __ahdecl ath_hal_getcca(struct ath_hal *ah);
+
#endif /* _ATH_AH_H_ */
Index: if_ath.c
===================================================================
--- if_ath.c (revision 225242)
+++ if_ath.c (working copy)
@@ -214,24 +214,6 @@
static void ath_tdma_beacon_send(struct ath_softc *sc,
struct ieee80211vap *vap);
-static __inline void
-ath_hal_setcca(struct ath_hal *ah, int ena)
-{
- /*
- * NB: fill me in; this is not provided by default because disabling
- * CCA in most locales violates regulatory.
- */
-}
-
-static __inline int
-ath_hal_getcca(struct ath_hal *ah)
-{
- u_int32_t diag;
- if (ath_hal_getcapability(ah, HAL_CAP_DIAG, 0, &diag) != HAL_OK)
- return 1;
- return ((diag & 0x500000) == 0);
-}
-
#define TDMA_EP_MULTIPLIER (1<<10) /* pow2 to optimize out * and / */
#define TDMA_LPF_LEN 6
#define TDMA_DUMMY_MARKER 0x127
@@ -5460,20 +5442,6 @@
}
#ifdef IEEE80211_SUPPORT_TDMA
-static __inline uint32_t
-ath_hal_getnexttbtt(struct ath_hal *ah)
-{
-#define AR_TIMER0 0x8028
- return OS_REG_READ(ah, AR_TIMER0);
-}
-
-static __inline void
-ath_hal_adjusttsf(struct ath_hal *ah, int32_t tsfdelta)
-{
- /* XXX handle wrap/overflow */
- OS_REG_WRITE(ah, AR_TSF_L32, OS_REG_READ(ah, AR_TSF_L32) + tsfdelta);
-}
-
static void
ath_tdma_settimers(struct ath_softc *sc, u_int32_t nexttbtt, u_int32_t bintval)
{
@@ -5629,8 +5597,8 @@
struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ath_hal *ah = sc->sc_ah;
const HAL_RATE_TABLE *rt = sc->sc_currates;
- u_int64_t tsf, rstamp, nextslot;
- u_int32_t txtime, nextslottu, timer0;
+ u_int64_t tsf, rstamp, nextslot, nexttbtt;
+ u_int32_t txtime, nextslottu;
int32_t tudelta, tsfdelta;
const struct ath_rx_status *rs;
int rix;
@@ -5677,15 +5645,15 @@
nextslottu = TSF_TO_TU(nextslot>>32, nextslot) & HAL_BEACON_PERIOD;
/*
- * TIMER0 is the h/w's idea of NextTBTT (in TU's). Convert
- * to usecs and calculate the difference between what the
+ * Retrieve the hardware NextTBTT in usecs
+ * and calculate the difference between what the
* other station thinks and what we have programmed. This
* lets us figure how to adjust our timers to match. The
* adjustments are done by pulling the TSF forward and possibly
* rewriting the beacon timers.
*/
- timer0 = ath_hal_getnexttbtt(ah);
- tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD+1)) - TU_TO_TSF(timer0));
+ nexttbtt = ath_hal_getnexttbtt(ah);
+ tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD + 1)) - nexttbtt);
DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
"tsfdelta %d avg +%d/-%d\n", tsfdelta,
@@ -5705,7 +5673,7 @@
TDMA_SAMPLE(sc->sc_avgtsfdeltap, 0);
TDMA_SAMPLE(sc->sc_avgtsfdeltam, 0);
}
- tudelta = nextslottu - timer0;
+ tudelta = nextslottu - TSF_TO_TU(nexttbtt >> 32, nexttbtt);
/*
* Copy sender's timetstamp into tdma ie so they can
@@ -5724,10 +5692,9 @@
&ni->ni_tstamp.data, 8);
#if 0
DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
- "tsf %llu nextslot %llu (%d, %d) nextslottu %u timer0 %u (%d)\n",
+ "tsf %llu nextslot %llu (%d, %d) nextslottu %u nexttbtt %llu (%d)\n",
(unsigned long long) tsf, (unsigned long long) nextslot,
- (int)(nextslot - tsf), tsfdelta,
- nextslottu, timer0, tudelta);
+ (int)(nextslot - tsf), tsfdelta, nextslottu, nexttbtt, tudelta);
#endif
/*
* Adjust the beacon timers only when pulling them forward
@@ -5736,7 +5703,8 @@
* cause the timers to stop and generally cause instability.
* This basically filters out jumps due to missed beacons.
*/
- if (tudelta != 0 && (tudelta > 0 || -tudelta < sc->sc_tdmabintval)) {
+ if (tudelta != 0 && (tudelta > 0 || -tudelta < sc->sc_tdmabintval) &&
+ (tudelta % sc->sc_tdmabintval != 0)) {
ath_tdma_settimers(sc, nextslottu, sc->sc_tdmabintval);
sc->sc_stats.ast_tdma_timers++;
}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAHjFwoDRFMGRJnCCd9PQcksZ-pEg=SUAL1q-4scOnXjmTQArYQ>
