[PATCH] ath10k: handle cycle count wrap around

Srinivasa Duvvuri sduvvuri at google.com
Wed May 13 18:56:51 PDT 2015


When the cycle counts part of wmi_ch_info_ev_arg reach max value of
0xffffffff The HW/FW right shifts all the counters by 1 . The cycle
count will be reset to 0x7fffffff and starts counting from 0x7fffffff.
At the same time all the other counters will also have their values
right shifted by 1 (divided by 2). There is no way to handle this odd
wrap around. Detect and ignore the wrap around case.
This change has 2 parts.

 1) Ignore all the cycle counts , if the cycle count field wraps around.
 2) With HW frequency of 88MHz the cycle count wraps around every 24
seconds. the survey_last_cycle_count saved will become stale with in
24 seconds. Reset it to 0 at every scan start.

Signed-off-by: Srinivasa Duvvuri <sduvvuri at chromium.org>

diff --git a/drivers/net/wireless-3.18/ath/ath10k/wmi.c
b/drivers/net/wireless-3.18/ath/ath10k/wmi.c
index 720b6eb..09616bb 100644
--- a/drivers/net/wireless-3.18/ath/ath10k/wmi.c
+++ b/drivers/net/wireless-3.18/ath/ath10k/wmi.c
@@ -1158,6 +1158,8 @@
  complete(&ar->scan.started);
  break;
  }
+ /* reset the last cycle count as the last cycle count is stale from
last scan. */
+ ar->survey_last_cycle_count = 0;
 }

 static void ath10k_wmi_event_scan_start_failed(struct ath10k *ar)
@@ -1716,21 +1718,36 @@
  goto exit;
  }

- if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE) {
+ if (cmd_flags & WMI_CHAN_INFO_FLAG_COMPLETE && ar->survey_last_cycle_count) {
  /* During scanning chan info is reported twice for each
- * visited channel. The reported cycle count is global
+ * visited channel. The reported cycle count is global
  * and per-channel cycle count must be calculated */

- cycle_count -= ar->survey_last_cycle_count;
- rx_clear_count -= ar->survey_last_rx_clear_count;
-
  survey = &ar->survey[idx];
- survey->channel_time = WMI_CHAN_INFO_MSEC(cycle_count);
- survey->channel_time_rx = WMI_CHAN_INFO_MSEC(rx_clear_count);
+
+ if (cycle_count  <  ar->survey_last_cycle_count) {
+ /*
+  * Ignore the wrapped arust_cycnd data. When the total cycle count
+  * wraps around, FW/HW will right shift all the counts
+  * (including total cycle counts) by 1.The cycle counts wrap around
+  * every 24 seconds. To handle this wrap around behavior,
+  * we need the value of each counter at the time of wrap around which
+  * FW does not provide. For now ignore the data.
+  */
+ survey->filled &= ~(SURVEY_INFO_CHANNEL_TIME |
+    SURVEY_INFO_CHANNEL_TIME_BUSY);
+ } else {
+ cycle_count -= ar->survey_last_cycle_count;
+ rx_clear_count -= ar->survey_last_rx_clear_count;
+
+ survey->channel_time = WMI_CHAN_INFO_MSEC(cycle_count);
+ /* the rx_clear_count count indicates the busy time */
+ survey->channel_time_busy = WMI_CHAN_INFO_MSEC(rx_clear_count);
+ survey->filled = SURVEY_INFO_CHANNEL_TIME |
+ SURVEY_INFO_CHANNEL_TIME_BUSY;
+ }
  survey->noise = noise_floor;
- survey->filled = SURVEY_INFO_CHANNEL_TIME |
- SURVEY_INFO_CHANNEL_TIME_RX |
- SURVEY_INFO_NOISE_DBM;
+ survey->filled |= SURVEY_INFO_NOISE_DBM;
  }

  ar->survey_last_rx_clear_count = rx_clear_count;



More information about the ath10k mailing list