Commit ccdfeab6 authored by Jouni Malinen's avatar Jouni Malinen Committed by John W. Linville

ath9k: Update Beacon timers based on timestamp from the AP

Some APs seem to drift away from the expected TBTT (timestamp %
beacon_int_in_usec differs quite a bit from zero) which can result in
us waking up way too early to receive a Beacon frame. In order to work
around this, re-configure the Beacon timers after having received a
Beacon frame from the AP (i.e., when we know the offset between the
expected TBTT and the actual time the AP is sending out the Beacon
frame).
Signed-off-by: default avatarJouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 267a9012
...@@ -518,6 +518,7 @@ struct ath_rfkill { ...@@ -518,6 +518,7 @@ struct ath_rfkill {
#define SC_OP_WAIT_FOR_CAB BIT(16) #define SC_OP_WAIT_FOR_CAB BIT(16)
#define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17) #define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17)
#define SC_OP_WAIT_FOR_TX_ACK BIT(18) #define SC_OP_WAIT_FOR_TX_ACK BIT(18)
#define SC_OP_BEACON_SYNC BIT(19)
struct ath_bus_ops { struct ath_bus_ops {
void (*read_cachesize)(struct ath_softc *sc, int *csz); void (*read_cachesize)(struct ath_softc *sc, int *csz);
......
...@@ -487,7 +487,7 @@ static void ath9k_tasklet(unsigned long data) ...@@ -487,7 +487,7 @@ static void ath9k_tasklet(unsigned long data)
* the next Beacon. * the next Beacon.
*/ */
DPRINTF(sc, ATH_DBG_PS, "TSFOOR - Sync with next Beacon\n"); DPRINTF(sc, ATH_DBG_PS, "TSFOOR - Sync with next Beacon\n");
sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC;
} }
/* re-enable hardware interrupt */ /* re-enable hardware interrupt */
...@@ -914,6 +914,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, ...@@ -914,6 +914,13 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
if (avp->av_opmode == NL80211_IFTYPE_STATION) { if (avp->av_opmode == NL80211_IFTYPE_STATION) {
sc->curaid = bss_conf->aid; sc->curaid = bss_conf->aid;
ath9k_hw_write_associd(sc); ath9k_hw_write_associd(sc);
/*
* Request a re-configuration of Beacon related timers
* on the receipt of the first Beacon frame (i.e.,
* after time sync with the AP).
*/
sc->sc_flags |= SC_OP_BEACON_SYNC;
} }
/* Configure the beacon */ /* Configure the beacon */
......
...@@ -521,6 +521,13 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) ...@@ -521,6 +521,13 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0) if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0)
return; /* not from our current AP */ return; /* not from our current AP */
if (sc->sc_flags & SC_OP_BEACON_SYNC) {
sc->sc_flags &= ~SC_OP_BEACON_SYNC;
DPRINTF(sc, ATH_DBG_PS, "Reconfigure Beacon timers based on "
"timestamp from the AP\n");
ath_beacon_config(sc, NULL);
}
if (!(sc->hw->conf.flags & IEEE80211_CONF_PS)) { if (!(sc->hw->conf.flags & IEEE80211_CONF_PS)) {
/* We are not in PS mode anymore; remain awake */ /* We are not in PS mode anymore; remain awake */
DPRINTF(sc, ATH_DBG_PS, "Not in PS mode anymore, remain " DPRINTF(sc, ATH_DBG_PS, "Not in PS mode anymore, remain "
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment