diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-06-11 06:48:01 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-06-19 15:49:18 -0400 |
commit | 8d7e09dda8214e4154f45238b4c85ab1ecb5d89a (patch) | |
tree | 88de4d537ffdc6edefc9e3a4e486a7bbf3029239 | |
parent | 26f16c246cea41f30ab2f63214a5529678677d0d (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.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/channel.c | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 23 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 10 |
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 | ||
1733 | u32 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 | } | ||
1748 | EXPORT_SYMBOL(ath9k_hw_get_tsf_offset); | ||
1749 | |||
1733 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | 1750 | int 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); | |||
1000 | u64 ath9k_hw_gettsf64(struct ath_hw *ah); | 1000 | u64 ath9k_hw_gettsf64(struct ath_hw *ah); |
1001 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); | 1001 | void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); |
1002 | void ath9k_hw_reset_tsf(struct ath_hw *ah); | 1002 | void ath9k_hw_reset_tsf(struct ath_hw *ah); |
1003 | u32 ath9k_hw_get_tsf_offset(struct timespec *last, struct timespec *cur); | ||
1003 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set); | 1004 | void ath9k_hw_set_tsfadjust(struct ath_hw *ah, bool set); |
1004 | void ath9k_hw_init_global_settings(struct ath_hw *ah); | 1005 | void ath9k_hw_init_global_settings(struct ath_hw *ah); |
1005 | u32 ar9003_get_pll_sqsum_dvc(struct ath_hw *ah); | 1006 | u32 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 | ||