Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b5bfc568 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville
Browse files

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: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarBruno Randolf <br1@einfach.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 9d119f3e
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <linux/skbuff.h>
#include <linux/if_ether.h>
#include <linux/spinlock.h>
#include <net/mac80211.h>

/*
@@ -42,6 +43,13 @@ struct ath_ani {
	struct timer_list timer;
};

struct ath_cycle_counters {
	u32 cycles;
	u32 rx_busy;
	u32 rx_frame;
	u32 tx_frame;
};

enum ath_device_state {
	ATH_HW_UNAVAILABLE,
	ATH_HW_INITIALIZED,
@@ -147,6 +155,10 @@ struct ath_common {

	unsigned int clockrate;

	spinlock_t cc_lock;
	struct ath_cycle_counters cc_ani;
	struct ath_cycle_counters cc_survey;

	struct ath_regulatory regulatory;
	const struct ath_ops *ops;
	const struct ath_bus_ops *bus_ops;
@@ -163,5 +175,7 @@ int ath_key_config(struct ath_common *common,
			  struct ieee80211_sta *sta,
			  struct ieee80211_key_conf *key);
bool ath_hw_keyreset(struct ath_common *common, u16 entry);
void ath_hw_cycle_counters_update(struct ath_common *common);
int32_t ath_hw_get_listen_time(struct ath_common *common);

#endif /* ATH_H */
+3 −61
Original line number Diff line number Diff line
@@ -465,18 +465,6 @@ static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah)
		ath9k_hw_set_cck_nil(ah, aniState->cckNoiseImmunityLevel - 1);
}

static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah)
{
	struct ath_common *common = ath9k_hw_common(ah);
	int32_t listen_time;

	ath9k_hw_update_cycle_counters(ah);
	listen_time = ah->listen_time / (common->clockrate * 1000);
	ah->listen_time = 0;

	return listen_time;
}

static void ath9k_ani_reset_old(struct ath_hw *ah, bool is_scanning)
{
	struct ar5416AniState *aniState;
@@ -655,7 +643,9 @@ static void ath9k_hw_ani_read_counters(struct ath_hw *ah)
	u32 phyCnt1, phyCnt2;
	int32_t listenTime;

	listenTime = ath9k_hw_ani_get_listen_time(ah);
	ath_hw_cycle_counters_update(common);
	listenTime = ath_hw_get_listen_time(common);

	if (listenTime < 0) {
		ah->stats.ast_ani_lneg++;
		ath9k_ani_restart(ah);
@@ -796,54 +786,6 @@ void ath9k_hw_disable_mib_counters(struct ath_hw *ah)
}
EXPORT_SYMBOL(ath9k_hw_disable_mib_counters);

void ath9k_hw_update_cycle_counters(struct ath_hw *ah)
{
	struct ath_cycle_counters cc;
	bool clear;

	memcpy(&cc, &ah->cc, sizeof(cc));

	/* freeze counters */
	REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC);

	ah->cc.cycles = REG_READ(ah, AR_CCCNT);
	if (ah->cc.cycles < cc.cycles) {
		clear = true;
		goto skip;
	}

	ah->cc.rx_clear = REG_READ(ah, AR_RCCNT);
	ah->cc.rx_frame = REG_READ(ah, AR_RFCNT);
	ah->cc.tx_frame = REG_READ(ah, AR_TFCNT);

	/* prevent wraparound */
	if (ah->cc.cycles & BIT(31))
		clear = true;

#define CC_DELTA(_field, _reg) ah->cc_delta._field += ah->cc._field - cc._field
	CC_DELTA(cycles, AR_CCCNT);
	CC_DELTA(rx_frame, AR_RFCNT);
	CC_DELTA(rx_clear, AR_RCCNT);
	CC_DELTA(tx_frame, AR_TFCNT);
#undef CC_DELTA

	ah->listen_time += (ah->cc.cycles - cc.cycles) -
		 ((ah->cc.rx_frame - cc.rx_frame) +
		  (ah->cc.tx_frame - cc.tx_frame));

skip:
	if (clear) {
		REG_WRITE(ah, AR_CCCNT, 0);
		REG_WRITE(ah, AR_RFCNT, 0);
		REG_WRITE(ah, AR_RCCNT, 0);
		REG_WRITE(ah, AR_TFCNT, 0);
		memset(&ah->cc, 0, sizeof(ah->cc));
	}

	/* unfreeze counters */
	REG_WRITE(ah, AR_MIBC, 0);
}

/*
 * Process a MIB interrupt.  We may potentially be invoked because
 * any of the MIB counters overflow/trigger so don't assume we're
+0 −8
Original line number Diff line number Diff line
@@ -93,13 +93,6 @@ struct ath9k_mib_stats {
	u32 beacons;
};

struct ath_cycle_counters {
	u32 cycles;
	u32 rx_frame;
	u32 rx_clear;
	u32 tx_frame;
};

/* INI default values for ANI registers */
struct ath9k_ani_default {
	u16 m1ThreshLow;
@@ -164,7 +157,6 @@ struct ar5416Stats {

void ath9k_enable_mib_counters(struct ath_hw *ah);
void ath9k_hw_disable_mib_counters(struct ath_hw *ah);
void ath9k_hw_update_cycle_counters(struct ath_hw *ah);
void ath9k_hw_ani_setup(struct ath_hw *ah);
void ath9k_hw_ani_init(struct ath_hw *ah);
int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah,
+3 −4
Original line number Diff line number Diff line
@@ -1254,13 +1254,12 @@ void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah)
		  "** BB mode: BB_gen_controls=0x%08x **\n",
		  REG_READ(ah, AR_PHY_GEN_CTRL));

	ath9k_hw_update_cycle_counters(ah);
#define PCT(_field) (ah->cc_delta._field * 100 / ah->cc_delta.cycles)
	if (ah->cc_delta.cycles)
#define PCT(_field) (common->cc_survey._field * 100 / common->cc_survey.cycles)
	if (common->cc_survey.cycles)
		ath_print(common, ATH_DBG_RESET,
			  "** BB busy times: rx_clear=%d%%, "
			  "rx_frame=%d%%, tx_frame=%d%% **\n",
			  PCT(rx_clear), PCT(rx_frame), PCT(tx_frame));
			  PCT(rx_busy), PCT(rx_frame), PCT(tx_frame));

	ath_print(common, ATH_DBG_RESET,
		  "==== BB update: done ====\n\n");
+0 −2
Original line number Diff line number Diff line
@@ -740,8 +740,6 @@ struct ath_hw {
	int coarse_low[5];
	int firpwr[5];
	enum ath9k_ani_cmd ani_function;
	struct ath_cycle_counters cc, cc_delta;
	int32_t listen_time;

	/* Bluetooth coexistance */
	struct ath_btcoex_hw btcoex_hw;
Loading