summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath10k/hw.c
diff options
context:
space:
mode:
authorMichal Kazior <michal.kazior@tieto.com>2015-05-25 14:06:18 +0200
committerKalle Valo <kvalo@qca.qualcomm.com>2015-05-29 16:34:45 +0200
commit587f7031f303bae561caecb0d5b23ba4d2585522 (patch)
tree72b3dfbb049d0f83e754aebdb3a425099263e5ed /drivers/net/wireless/ath/ath10k/hw.c
parentath10k: move cycle_count macro (diff)
downloadlinux-587f7031f303bae561caecb0d5b23ba4d2585522.tar.xz
linux-587f7031f303bae561caecb0d5b23ba4d2585522.zip
ath10k: handle cycle counter wraparound
When QCA988X cycle counter HW register wraps around it resets to 0x7fffffff instead of 0. All other cycle counter related registers are divided by 2 so they never wraparound themselves. QCA61X4 has a uniform CC and it wraparounds in a regular fashion though. Worst case wraparound time is approx 24 seconds (2**31 / 88MHz). Since scan channel visit times are max 5 seconds (offchannel case) it is guaranteed there's been at most 1 wraparound and it is possible to compute survey active time value. It is, however, impossible to determine the point at which Rx Clear Count has been divided by two so it is not reported upon wraparound. This fixes some occasional incorrect survey data on QCA988X as some channels (depending on how/when scan/offchannel requests were requested) would have approx 24 sec active time which wasn't actually the case. This should improve hostapd ACS a little bit. Reported-by: Srinivasa Duvvuri <sduvvuri@chromium.org> Signed-off-by: Michal Kazior <michal.kazior@tieto.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/hw.c')
-rw-r--r--drivers/net/wireless/ath/ath10k/hw.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c
index 839a8791fb9e..5997f00afe3b 100644
--- a/drivers/net/wireless/ath/ath10k/hw.c
+++ b/drivers/net/wireless/ath/ath10k/hw.c
@@ -15,6 +15,7 @@
*/
#include <linux/types.h>
+#include "core.h"
#include "hw.h"
const struct ath10k_hw_regs qca988x_regs = {
@@ -56,3 +57,23 @@ const struct ath10k_hw_regs qca6174_regs = {
.soc_chip_id_address = 0x000f0,
.scratch_3_address = 0x0028,
};
+
+void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey,
+ u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev)
+{
+ u32 cc_fix = 0;
+
+ survey->filled |= SURVEY_INFO_TIME |
+ SURVEY_INFO_TIME_BUSY;
+
+ if (ar->hw_params.has_shifted_cc_wraparound && cc < cc_prev) {
+ cc_fix = 0x7fffffff;
+ survey->filled &= ~SURVEY_INFO_TIME_BUSY;
+ }
+
+ cc -= cc_prev - cc_fix;
+ rcc -= rcc_prev;
+
+ survey->time = CCNT_TO_MSEC(cc);
+ survey->time_busy = CCNT_TO_MSEC(rcc);
+}