OSDN Git Service

ath9k: Handle channel context in get_/set_/reset_tsf
authorBenjamin Berg <benjamin.berg@open-mesh.com>
Mon, 4 Jul 2016 12:37:21 +0000 (14:37 +0200)
committerKalle Valo <kvalo@qca.qualcomm.com>
Fri, 8 Jul 2016 14:03:24 +0000 (17:03 +0300)
The ath9k TSF handling routines need to be aware of the channel context that
is being modified. With this change the TSF related values that are stored
in each channel context will be correctly tracked and the harware will only
be updated if the modified context is currently the active one.

Without this change the TSF modifications done using these routines would
for example be lost during a hardware reset as done by ath_complete_reset.

Signed-off-by: Benjamin Berg <benjamin.berg@open-mesh.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
drivers/net/wireless/ath/ath9k/main.c

index 8b63988..375c2ac 100644 (file)
@@ -1823,11 +1823,18 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
 static u64 ath9k_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
        struct ath_softc *sc = hw->priv;
+       struct ath_vif *avp = (void *)vif->drv_priv;
        u64 tsf;
 
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
-       tsf = ath9k_hw_gettsf64(sc->sc_ah);
+       /* Get current TSF either from HW or kernel time. */
+       if (sc->cur_chan == avp->chanctx) {
+               tsf = ath9k_hw_gettsf64(sc->sc_ah);
+       } else {
+               tsf = sc->cur_chan->tsf_val +
+                     ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
+       }
        ath9k_ps_restore(sc);
        mutex_unlock(&sc->mutex);
 
@@ -1839,10 +1846,14 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw,
                          u64 tsf)
 {
        struct ath_softc *sc = hw->priv;
+       struct ath_vif *avp = (void *)vif->drv_priv;
 
        mutex_lock(&sc->mutex);
        ath9k_ps_wakeup(sc);
-       ath9k_hw_settsf64(sc->sc_ah, tsf);
+       getrawmonotonic(&avp->chanctx->tsf_ts);
+       if (sc->cur_chan == avp->chanctx)
+               ath9k_hw_settsf64(sc->sc_ah, tsf);
+       avp->chanctx->tsf_val = tsf;
        ath9k_ps_restore(sc);
        mutex_unlock(&sc->mutex);
 }
@@ -1850,11 +1861,15 @@ static void ath9k_set_tsf(struct ieee80211_hw *hw,
 static void ath9k_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 {
        struct ath_softc *sc = hw->priv;
+       struct ath_vif *avp = (void *)vif->drv_priv;
 
        mutex_lock(&sc->mutex);
 
        ath9k_ps_wakeup(sc);
-       ath9k_hw_reset_tsf(sc->sc_ah);
+       getrawmonotonic(&avp->chanctx->tsf_ts);
+       if (sc->cur_chan == avp->chanctx)
+               ath9k_hw_reset_tsf(sc->sc_ah);
+       avp->chanctx->tsf_val = 0;
        ath9k_ps_restore(sc);
 
        mutex_unlock(&sc->mutex);