ath9k_hw: move the cycle counter tracking to ath

Instead of keeping track of wraparound, clear the counters on every
access and keep separate deltas for ANI and later survey use.
Also moves the function for calculating the 'listen time' for ANI

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Bruno Randolf <br1@einfach.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/drivers/net/wireless/ath/hw.c b/drivers/net/wireless/ath/hw.c
index a8f81ea..183c282 100644
--- a/drivers/net/wireless/ath/hw.c
+++ b/drivers/net/wireless/ath/hw.c
@@ -124,3 +124,62 @@
 	REG_WRITE(ah, get_unaligned_le16(common->bssidmask + 4), AR_BSSMSKU);
 }
 EXPORT_SYMBOL(ath_hw_setbssidmask);
+
+
+/**
+ * ath_hw_cycle_counters_update - common function to update cycle counters
+ *
+ * @common: the ath_common struct for the device.
+ *
+ * This function is used to update all cycle counters in one place.
+ * It has to be called while holding common->cc_lock!
+ */
+void ath_hw_cycle_counters_update(struct ath_common *common)
+{
+	u32 cycles, busy, rx, tx;
+	void *ah = common->ah;
+
+	/* freeze */
+	REG_WRITE(ah, AR_MIBC_FMC, AR_MIBC);
+
+	/* read */
+	cycles = REG_READ(ah, AR_CCCNT);
+	busy = REG_READ(ah, AR_RCCNT);
+	rx = REG_READ(ah, AR_RFCNT);
+	tx = REG_READ(ah, AR_TFCNT);
+
+	/* clear */
+	REG_WRITE(ah, 0, AR_CCCNT);
+	REG_WRITE(ah, 0, AR_RFCNT);
+	REG_WRITE(ah, 0, AR_RCCNT);
+	REG_WRITE(ah, 0, AR_TFCNT);
+
+	/* unfreeze */
+	REG_WRITE(ah, 0, AR_MIBC);
+
+	/* update all cycle counters here */
+	common->cc_ani.cycles += cycles;
+	common->cc_ani.rx_busy += busy;
+	common->cc_ani.rx_frame += rx;
+	common->cc_ani.tx_frame += tx;
+
+	common->cc_survey.cycles += cycles;
+	common->cc_survey.rx_busy += busy;
+	common->cc_survey.rx_frame += rx;
+	common->cc_survey.tx_frame += tx;
+}
+EXPORT_SYMBOL(ath_hw_cycle_counters_update);
+
+int32_t ath_hw_get_listen_time(struct ath_common *common)
+{
+	struct ath_cycle_counters *cc = &common->cc_ani;
+	int32_t listen_time;
+
+	listen_time = (cc->cycles - cc->rx_frame - cc->tx_frame) /
+		      (common->clockrate * 1000);
+
+	memset(cc, 0, sizeof(*cc));
+
+	return listen_time;
+}
+EXPORT_SYMBOL(ath_hw_get_listen_time);