[PATCH] wifi: ath9k: count spectral samples in the driver's own RX stats

From: Nerijus Bendžiūnas

Date: Thu Sep 03 2026 - 13:48:26 EST


ath_cmn_process_fft() is shared by ath9k and ath9k_htc, but it takes
common->priv for a struct ath_softc to reach the sample counters. On
ath9k_htc that pointer is a struct ath9k_htc_priv, 2664 bytes long, and
with CONFIG_ATH9K_DEBUGFS the increment lands 11912 bytes into it, well
past the end of the ieee80211_hw allocation, once for every FFT sample
the card delivers. Give the parser a pointer to the driver's own struct
ath_rx_stats instead, set when the debugfs files are created. Both
drivers keep one and both print it through the shared recv file, which
also makes the two counters count on ath9k_htc for the first time.

Fixes: 03224678c013 ("ath9k: add counters for good and errorneous FFT/spectral frames")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Nerijus Bendžiūnas <nerijus.bendziunas@xxxxxxxxx>
---
.../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: ca800a9302764c445de0da0e84d2252400a770ee
--
2.55.0