[PATCH v2] wifi: ath9k: count spectral samples in the driver's own RX stats
From: Nerijus Bendžiūnas
Date: Fri Sep 04 2026 - 14:41:13 EST
ath_cmn_process_fft() is shared by ath9k and ath9k_htc, but it casts
common->priv to struct ath_softc to reach the rx_spectral_sample_good
and rx_spectral_sample_err counters. On ath9k_htc common->priv is a
struct ath9k_htc_priv, and with CONFIG_ATH9K_DEBUGFS the increment
lands far past the end of that allocation, once per FFT sample. On
x86-64 with a distribution config the structure is 2664 bytes and the
counters sit at offset 11912 of struct ath_softc.
Store a pointer to the driver's struct ath_rx_stats in struct
ath_spec_scan_priv and count through it. Both drivers pass their own
stats to ath9k_cmn_spectral_init_debug(), and both print them in the
shared recv debugfs file, so the two counters now also work on
ath9k_htc. A pointer keeps the common code free of driver structures,
which a check on the driver type would not. Without debugfs the
pointer stays NULL and nothing is counted, as before.
Fixes: 03224678c013 ("ath9k: add counters for good and errorneous FFT/spectral frames")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Nerijus Bendžiūnas <nerijus.bendziunas@xxxxxxxxx>
---
Changes in v2:
- Say where the quoted sizes come from and why a stats pointer rather
than a check on the driver type.
- Add Assisted-by, rewrite the commit message, rebase onto ath-next. No
code change.
.../net/wireless/ath/ath9k/common-spectral.c | 29 ++++++++++++-------
.../net/wireless/ath/ath9k/common-spectral.h | 11 +++++--
drivers/net/wireless/ath/ath9k/debug.c | 3 +-
.../net/wireless/ath/ath9k/htc_drv_debug.c | 3 +-
4 files changed, 32 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c
index ca01a07f6630..d8be24ebcd24 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.c
@@ -465,6 +465,20 @@ ath_cmn_is_fft_buf_full(struct ath_spec_scan_priv *spec_priv)
return 0;
}
+static void ath_cmn_count_fft_sample(struct ath_spec_scan_priv *spec_priv,
+ int ret)
+{
+ struct ath_rx_stats *rx_stats = spec_priv->rx_stats;
+
+ if (!rx_stats)
+ return;
+
+ if (ret == 0)
+ rx_stats->rx_spectral_sample_good++;
+ else
+ rx_stats->rx_spectral_sample_err++;
+}
+
/* returns 1 if this was a spectral frame, even if not handled. */
int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr,
struct ath_rx_status *rs, u64 tsf)
@@ -472,7 +486,6 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
u8 sample_buf[SPECTRAL_SAMPLE_MAX_LEN] = {0};
struct ath_hw *ah = spec_priv->ah;
struct ath_common *common = ath9k_hw_common(spec_priv->ah);
- struct ath_softc *sc = common->priv;
u8 num_bins, *vdata = (u8 *)hdr;
struct ath_radar_info *radar_info;
int len = rs->rs_datalen;
@@ -624,10 +637,7 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
ret = fft_handler(rs, spec_priv, sample_buf,
tsf, freq, chan_type);
- if (ret == 0)
- RX_STAT_INC(sc, rx_spectral_sample_good);
- else
- RX_STAT_INC(sc, rx_spectral_sample_err);
+ ath_cmn_count_fft_sample(spec_priv, ret);
/* Mix the received bins to the /dev/random
* pool
@@ -642,10 +652,7 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
ret = fft_handler(rs, spec_priv, sample_start,
tsf, freq, chan_type);
- if (ret == 0)
- RX_STAT_INC(sc, rx_spectral_sample_good);
- else
- RX_STAT_INC(sc, rx_spectral_sample_err);
+ ath_cmn_count_fft_sample(spec_priv, ret);
/* Mix the received bins to the /dev/random
* pool
@@ -1052,8 +1059,10 @@ void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv)
EXPORT_SYMBOL(ath9k_cmn_spectral_deinit_debug);
void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv,
- struct dentry *debugfs_phy)
+ struct dentry *debugfs_phy,
+ struct ath_rx_stats *rx_stats)
{
+ spec_priv->rx_stats = rx_stats;
spec_priv->rfs_chan_spec_scan = relay_open("spectral_scan",
debugfs_phy,
1024, 256, &rfs_spec_scan_cb,
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.h b/drivers/net/wireless/ath/ath9k/common-spectral.h
index 011d8ab8b974..0e2c7d6d3487 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.h
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.h
@@ -94,12 +94,16 @@ struct ath_ht20_40_fft_packet {
struct ath_radar_info radar_info;
} __packed;
+struct ath_rx_stats;
+
struct ath_spec_scan_priv {
struct ath_hw *ah;
/* relay(fs) channel for spectral scan */
struct rchan *rfs_chan_spec_scan;
enum spectral_mode spectral_mode;
struct ath_spec_scan spec_config;
+ /* driver's RX statistics to account samples into, if any */
+ struct ath_rx_stats *rx_stats;
};
#define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet))
@@ -169,7 +173,9 @@ static inline u8 spectral_bitmap_weight(u8 *bins)
}
#ifdef CONFIG_ATH9K_COMMON_SPECTRAL
-void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy);
+void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv,
+ struct dentry *debugfs_phy,
+ struct ath_rx_stats *rx_stats);
void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv);
void ath9k_cmn_spectral_scan_trigger(struct ath_common *common,
@@ -181,7 +187,8 @@ int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_h
struct ath_rx_status *rs, u64 tsf);
#else
static inline void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv,
- struct dentry *debugfs_phy)
+ struct dentry *debugfs_phy,
+ struct ath_rx_stats *rx_stats)
{
}
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 74a0134075cf..042a4f542a94 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1389,7 +1389,8 @@ int ath9k_init_debug(struct ath_hw *ah)
ath9k_dfs_init_debug(sc);
ath9k_tx99_init_debug(sc);
- ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy);
+ ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy,
+ &sc->debug.stats.rxstats);
debugfs_create_devm_seqfile(sc->dev, "dma", sc->debug.debugfs_phy,
read_file_dma);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index 9437d69877cc..9d354b1d929c 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -487,7 +487,8 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
priv->debug.debugfs_phy = debugfs_create_dir(KBUILD_MODNAME,
priv->hw->wiphy->debugfsdir);
- ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy);
+ ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy,
+ &priv->debug.rx_stats);
debugfs_create_file("tgt_int_stats", 0400, priv->debug.debugfs_phy,
priv, &fops_tgt_int_stats);
base-commit: 1d8e73163ef933624341075f576e2f36ef9133f7
--
2.55.0