From: Bruno Randolf <bruno@thinktube.com>
To: ath5k-devel@lists.ath5k.org
Cc: mcgrof@gmail.com, jirislaby@gmail.com, mickflemm@gmail.com,
linux-wireless@vger.kernel.org, linville@tuxdriver.com
Subject: [PATCH 4/4] ath5k: work around wrong beacon rx timestamp in IBSS mode
Date: Wed, 05 Mar 2008 18:36:26 +0900 [thread overview]
Message-ID: <20080305093626.5670.51643.stgit@one> (raw)
In-Reply-To: <20080305091347.5670.40944.stgit@one>
atheros hardware has a problem with the rx timestamp of some IBSS beacons when
they caused a TSF update (they have the same BSSID).
the rx timestamp is wrong especially if the beacon frames get bigger than 78
byte (at least on AR5213 and AR5414 hardware). in that case ath5k_extend_tsf()
will assume a rs_tstamp overflow and give us a timestamp too far in the past
which will cause mac80211 to merge IBSS on every beacon (which is not necessary
since the BSSID already matches). but in this case we know that the HW must
have synced to the beacons TSF and the rx timestamp must be later than that so
we can adjust mactime accordingly.
also rename the function to ath5k_check_ibss_tsf() and change comments, since
"hw merge" is better described as a TSF update.
drivers/net/wireless/ath5k/base.c: Changes-licensed-under: 3-Clause-BSD
Signed-off-by: Bruno Randolf <bruno@thinktube.com>
---
drivers/net/wireless/ath5k/base.c | 59 ++++++++++++++++++++++++++++---------
1 files changed, 45 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c
index 03e05fe..5139217 100644
--- a/drivers/net/wireless/ath5k/base.c
+++ b/drivers/net/wireless/ath5k/base.c
@@ -1712,8 +1712,10 @@ ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds,
static void
-ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
+ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb,
+ struct ieee80211_rx_status *rxs)
{
+ u64 tsf, bc_tstamp;
u32 hw_tu;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data;
@@ -1724,16 +1726,45 @@ ath5k_check_ibss_hw_merge(struct ath5k_softc *sc, struct sk_buff *skb)
le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS &&
memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) {
/*
- * Received an IBSS beacon with the same BSSID. Hardware might
- * have updated the TSF, check if we need to update timers.
+ * Received an IBSS beacon with the same BSSID. Hardware *must*
+ * have updated the local TSF. We have to work around various
+ * hardware bugs, though...
*/
- hw_tu = TSF_TO_TU(ath5k_hw_get_tsf64(sc->ah));
- if (hw_tu >= sc->nexttbtt) {
- ath5k_beacon_update_timers(sc,
- le64_to_cpu(mgmt->u.beacon.timestamp));
+ tsf = ath5k_hw_get_tsf64(sc->ah);
+ bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp);
+ hw_tu = TSF_TO_TU(tsf);
+
+ ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
+ "beacon %llx mactime %llx (diff %lld) tsf now %llx\n",
+ bc_tstamp, rxs->mactime,
+ (rxs->mactime - bc_tstamp), tsf);
+
+ /*
+ * Sometimes the HW will give us a wrong tstamp in the rx
+ * status, causing the timestamp extension to go wrong.
+ * (This seems to happen especially with beacon frames bigger
+ * than 78 byte (incl. FCS))
+ * But we know that the receive timestamp must be later than the
+ * timestamp of the beacon since HW must have synced to that.
+ *
+ * NOTE: here we assume mactime to be after the frame was
+ * received, not like mac80211 which defines it at the start.
+ */
+ if (bc_tstamp > rxs->mactime) {
ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON,
- "detected HW merge from received beacon\n");
+ "fixing mactime from %llx to %llx\n",
+ rxs->mactime, tsf);
+ rxs->mactime = tsf;
}
+
+ /*
+ * Local TSF might have moved higher than our beacon timers,
+ * in that case we have to update them to continue sending
+ * beacons. This also takes care of synchronizing beacon sending
+ * times with other stations.
+ */
+ if (hw_tu >= sc->nexttbtt)
+ ath5k_beacon_update_timers(sc, bc_tstamp);
}
}
@@ -1882,7 +1913,7 @@ accept:
/* check beacons in IBSS mode */
if (sc->opmode == IEEE80211_IF_TYPE_IBSS)
- ath5k_check_ibss_hw_merge(sc, skb);
+ ath5k_check_ibss_tsf(sc, skb, &rxs);
__ieee80211_rx(sc->hw, skb, &rxs);
sc->led_rxrate = rs.rs_rate;
@@ -2115,7 +2146,7 @@ ath5k_beacon_send(struct ath5k_softc *sc)
* beacon timer registers.
*
* This is called in a variety of situations, e.g. when a beacon is received,
- * when a HW merge has been detected, but also when an new IBSS is created or
+ * when a TSF update has been detected, but also when an new IBSS is created or
* when we otherwise know we have to update the timers, but we keep it in this
* function to have it all together in one place.
*/
@@ -2215,7 +2246,7 @@ ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf)
* another AP to associate with.
*
* In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA
- * interrupts to detect HW merges only.
+ * interrupts to detect TSF updates only.
*
* AP mode is missing.
*/
@@ -2235,7 +2266,7 @@ ath5k_beacon_config(struct ath5k_softc *sc)
* hardware send the beacons automatically. We have to load it
* only once here.
* We use the SWBA interrupt only to keep track of the beacon
- * timers in order to detect HW merges (automatic TSF updates).
+ * timers in order to detect automatic TSF updates.
*/
ath5k_beaconq_config(sc);
@@ -2448,8 +2479,8 @@ ath5k_intr(int irq, void *dev_id)
*
* In IBSS mode we use this interrupt just to
* keep track of the next TBTT (target beacon
- * transmission time) in order to detect hardware
- * merges (TSF updates).
+ * transmission time) in order to detect wether
+ * automatic TSF updates happened.
*/
if (sc->opmode == IEEE80211_IF_TYPE_IBSS) {
/* XXX: only if VEOL suppported */
prev parent reply other threads:[~2008-03-05 9:36 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-03-05 9:34 [PATCH 0/4] ath5k descriptor cleanup + ibss beacon fix Bruno Randolf
2008-03-05 9:35 ` [PATCH 1/4] ath5k: struct ath5k_desc cleanups Bruno Randolf
2008-03-05 9:57 ` [PATCH] " Bruno Randolf
2008-03-05 9:35 ` [PATCH 2/4] ath5k: move rx and tx status structures out of hardware descriptor Bruno Randolf
2008-03-05 9:36 ` [PATCH 3/4] ath5k: add notes about rx timestamp Bruno Randolf
2008-03-05 9:36 ` Bruno Randolf [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20080305093626.5670.51643.stgit@one \
--to=bruno@thinktube.com \
--cc=ath5k-devel@lists.ath5k.org \
--cc=jirislaby@gmail.com \
--cc=linux-wireless@vger.kernel.org \
--cc=linville@tuxdriver.com \
--cc=mcgrof@gmail.com \
--cc=mickflemm@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).