aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2014-06-11 06:48:01 -0400
committerJohn W. Linville <linville@tuxdriver.com>2014-06-19 15:49:18 -0400
commit8d7e09dda8214e4154f45238b4c85ab1ecb5d89a (patch)
tree88de4d537ffdc6edefc9e3a4e486a7bbf3029239
parent26f16c246cea41f30ab2f63214a5529678677d0d (diff)
ath9k: save tsf in channel context
Save TSF in channel context for multiple operating channels. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c23
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c10
5 files changed, 37 insertions, 5 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index ffacbf6e9f52..4df412b71680 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -22,6 +22,7 @@
22#include <linux/interrupt.h> 22#include <linux/interrupt.h>
23#include <linux/leds.h> 23#include <linux/leds.h>
24#include <linux/completion.h> 24#include <linux/completion.h>
25#include <linux/time.h>
25 26
26#include "common.h" 27#include "common.h"
27#include "debug.h" 28#include "debug.h"
@@ -328,6 +329,8 @@ struct ath_chanctx {
328 struct list_head acq[IEEE80211_NUM_ACS]; 329 struct list_head acq[IEEE80211_NUM_ACS];
329 330
330 struct ath9k_hw_cal_data caldata; 331 struct ath9k_hw_cal_data caldata;
332 struct timespec tsf_ts;
333 u64 tsf_val;
331 334
332 u16 txpower; 335 u16 txpower;
333 bool offchannel; 336 bool offchannel;
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index e3127b52e1ee..4a7691eecdb4 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -227,6 +227,11 @@ void ath_chanctx_work(struct work_struct *work)
227 227
228 send_ps = true; 228 send_ps = true;
229 spin_lock_bh(&sc->chan_lock); 229 spin_lock_bh(&sc->chan_lock);
230
231 if (sc->cur_chan != &sc->offchannel.chan) {
232 getrawmonotonic(&sc->cur_chan->tsf_ts);
233 sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
234 }
230 } 235 }
231 sc->cur_chan = sc->next_chan; 236 sc->cur_chan = sc->next_chan;
232 sc->cur_chan->stopped = false; 237 sc->cur_chan->stopped = false;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 2a8ed8375ec0..ace4fe2740d4 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1730,6 +1730,23 @@ fail:
1730 return -EINVAL; 1730 return -EINVAL;
1731} 1731}
1732 1732
1733u32 ath9k_hw_get_tsf_offset(struct timespec *last, struct timespec *cur)
1734{
1735 struct timespec ts;
1736 s64 usec;
1737
1738 if (!cur) {
1739 getrawmonotonic(&ts);
1740 cur = &ts;
1741 }
1742
1743 usec = cur->tv_sec * 1000000ULL + cur->tv_nsec / 1000;
1744 usec -= last->tv_sec * 1000000ULL + last->tv_nsec / 1000;
1745
1746 return (u32) usec;
1747}
1748EXPORT_SYMBOL(ath9k_hw_get_tsf_offset);
1749
1733int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, 1750int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1734 struct ath9k_hw_cal_data *caldata, bool fastcc) 1751 struct ath9k_hw_cal_data *caldata, bool fastcc)
1735{ 1752{
@@ -1739,7 +1756,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1739 u32 saveDefAntenna; 1756 u32 saveDefAntenna;
1740 u32 macStaId1; 1757 u32 macStaId1;
1741 u64 tsf = 0; 1758 u64 tsf = 0;
1742 s64 usec = 0;
1743 int r; 1759 int r;
1744 bool start_mci_reset = false; 1760 bool start_mci_reset = false;
1745 bool save_fullsleep = ah->chip_fullsleep; 1761 bool save_fullsleep = ah->chip_fullsleep;
@@ -1785,7 +1801,6 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1785 /* Save TSF before chip reset, a cold reset clears it */ 1801 /* Save TSF before chip reset, a cold reset clears it */
1786 tsf = ath9k_hw_gettsf64(ah); 1802 tsf = ath9k_hw_gettsf64(ah);
1787 getrawmonotonic(&ts); 1803 getrawmonotonic(&ts);
1788 usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000;
1789 1804
1790 saveLedState = REG_READ(ah, AR_CFG_LED) & 1805 saveLedState = REG_READ(ah, AR_CFG_LED) &
1791 (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | 1806 (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL |
@@ -1818,9 +1833,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1818 } 1833 }
1819 1834
1820 /* Restore TSF */ 1835 /* Restore TSF */
1821 getrawmonotonic(&ts); 1836 ath9k_hw_settsf64(ah, tsf + ath9k_hw_get_tsf_offset(&ts, NULL));
1822 usec = ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000 - usec;
1823 ath9k_hw_settsf64(ah, tsf + usec);
1824 1837
1825 if (AR_SREV_9280_20_OR_LATER(ah)) 1838 if (AR_SREV_9280_20_OR_LATER(ah))
1826 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); 1839 REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 0acd4b5a4892..51b4ebe04c04 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -1000,6 +1000,7 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah);
1000u64 ath9k_hw_gettsf64(struct ath_hw *ah); 1000u64 ath9k_hw_gettsf64(struct ath_hw *ah);
1001void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); 1001void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64);
1002void ath9k_hw_reset_tsf(struct ath_hw *ah); 1002void ath9k_hw_reset_tsf(struct ath_hw *ah);
1003u32 ath9k_hw_get_tsf_offset(struct timespec *last, struct timespec *cur);
1003void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set); 1004void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set);
1004void ath9k_hw_init_global_settings(struct ath_hw *ah); 1005void ath9k_hw_init_global_settings(struct ath_hw *ah);
1005u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); 1006u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 85db24be8eec..6abdf99ffae4 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -240,6 +240,16 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
240 ath9k_hw_enable_interrupts(ah); 240 ath9k_hw_enable_interrupts(ah);
241 241
242 if (!sc->cur_chan->offchannel && start) { 242 if (!sc->cur_chan->offchannel && start) {
243 /* restore per chanctx TSF timer */
244 if (sc->cur_chan->tsf_val) {
245 u32 offset;
246
247 offset = ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts,
248 NULL);
249 ath9k_hw_settsf64(ah, sc->cur_chan->tsf_val + offset);
250 }
251
252
243 if (!test_bit(ATH_OP_BEACONS, &common->op_flags)) 253 if (!test_bit(ATH_OP_BEACONS, &common->op_flags))
244 goto work; 254 goto work;
245 255