* [PATCH v2 1/2] wifi: ath9k_htc: derive the PHY error filter bits from software state
2026-09-04 19:03 [PATCH v2 0/2] wifi: ath9k_htc: cope with lost WMI reads Nerijus Bendžiūnas
@ 2026-09-04 19:03 ` Nerijus Bendžiūnas
2026-09-04 19:03 ` [PATCH v2 2/2] wifi: ath9k_htc: count WMI commands and timeouts in debugfs Nerijus Bendžiūnas
1 sibling, 0 replies; 3+ messages in thread
From: Nerijus Bendžiūnas @ 2026-09-04 19:03 UTC (permalink / raw)
To: Toke Høiland-Jørgensen, linux-wireless; +Cc: linux-kernel
ath9k_htc_calcrxfilter() calls ath9k_hw_getrxfilter(), which reads
AR_RX_FILTER and AR_PHY_ERR back from the device, to preserve the PHY
error bits that a spectral scan may have set. On USB each read is a
WMI round trip. When the AR_RX_FILTER read times out ath9k_regread()
returns -1, the recalculated filter has PHYERR and PHYRADAR set with no
scan running, and the device forwards every PHY error frame to the
host until the next recalculation.
The spectral mode is already tracked in priv->spec_priv. Set the two
bits from it and drop the readback. This saves two round trips per
recalculation, and the bits are now cleared when the scan is disabled
instead of staying set until the next reset. The bits still go through
ath9k_hw_setrxfilter(), so AR_PHY_ERR and AR_RXCFG_ZLFDMA follow the
filter as before.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Nerijus Bendžiūnas <nerijus.bendziunas@gmail.com>
---
drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | 12 +++++-------
1 file changed, 5 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index bed7ea2425a0..299064a7fa49 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -868,14 +868,14 @@ int ath9k_htc_cabq_setup(struct ath9k_htc_priv *priv)
*/
u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv)
{
-#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR)
-
struct ath_hw *ah = priv->ah;
u32 rfilt;
- rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE)
- | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
- | ATH9K_RX_FILTER_MCAST;
+ rfilt = ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST |
+ ATH9K_RX_FILTER_MCAST;
+
+ if (priv->spec_priv.spectral_mode != SPECTRAL_DISABLED)
+ rfilt |= ATH9K_RX_FILTER_PHYRADAR | ATH9K_RX_FILTER_PHYERR;
if (priv->rxfilter & FIF_PROBE_REQ)
rfilt |= ATH9K_RX_FILTER_PROBEREQ;
@@ -906,8 +906,6 @@ u32 ath9k_htc_calcrxfilter(struct ath9k_htc_priv *priv)
rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL;
return rfilt;
-
-#undef RX_FILTER_PRESERVE
}
/*
--
2.55.0
^ permalink raw reply [flat|nested] 3+ messages in thread* [PATCH v2 2/2] wifi: ath9k_htc: count WMI commands and timeouts in debugfs
2026-09-04 19:03 [PATCH v2 0/2] wifi: ath9k_htc: cope with lost WMI reads Nerijus Bendžiūnas
2026-09-04 19:03 ` [PATCH v2 1/2] wifi: ath9k_htc: derive the PHY error filter bits from software state Nerijus Bendžiūnas
@ 2026-09-04 19:03 ` Nerijus Bendžiūnas
1 sibling, 0 replies; 3+ messages in thread
From: Nerijus Bendžiūnas @ 2026-09-04 19:03 UTC (permalink / raw)
To: Toke Høiland-Jørgensen, linux-wireless; +Cc: linux-kernel
A WMI command that times out is only visible with CONFIG_ATH_DEBUG and
the WMI debug bit set. A register read that returns -1 gives no
indication whether the register holds all ones or the command never
completed.
Count the commands issued and the commands that timed out in struct
wmi and expose both in a new "wmi" debugfs file, so timeouts can be
seen on a kernel built without debug output.
Assisted-by: Claude:claude-fable-5-1
Signed-off-by: Nerijus Bendžiūnas <nerijus.bendziunas@gmail.com>
---
.../net/wireless/ath/ath9k/htc_drv_debug.c | 25 +++++++++++++++++++
drivers/net/wireless/ath/ath9k/wmi.c | 2 ++
drivers/net/wireless/ath/ath9k/wmi.h | 2 ++
3 files changed, 29 insertions(+)
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index 9437d69877cc..fab613199ca2 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -310,6 +310,29 @@ static const struct file_operations fops_slot = {
.llseek = default_llseek,
};
+static ssize_t read_file_wmi(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath9k_htc_priv *priv = file->private_data;
+ char buf[128];
+ unsigned int len;
+
+ len = scnprintf(buf, sizeof(buf),
+ "%20s : %10u\n"
+ "%20s : %10u\n",
+ "Issued", priv->wmi->cmds_issued,
+ "Timeouts", priv->wmi->cmds_timed_out);
+
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static const struct file_operations fops_wmi = {
+ .read = read_file_wmi,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
static ssize_t read_file_queue(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -505,6 +528,8 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
debugfs_create_file("slot", 0400, priv->debug.debugfs_phy,
priv, &fops_slot);
+ debugfs_create_file("wmi", 0400, priv->debug.debugfs_phy,
+ priv, &fops_wmi);
debugfs_create_file("queue", 0400, priv->debug.debugfs_phy,
priv, &fops_queue);
debugfs_create_file("debug", 0600, priv->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/wmi.c b/drivers/net/wireless/ath/ath9k/wmi.c
index 284e8c13b043..552ae9f8bdaf 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.c
+++ b/drivers/net/wireless/ath/ath9k/wmi.c
@@ -345,8 +345,10 @@ int ath9k_wmi_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id,
if (ret)
goto out;
+ wmi->cmds_issued++;
time_left = wait_for_completion_timeout(&wmi->cmd_wait, timeout);
if (!time_left) {
+ wmi->cmds_timed_out++;
ath_dbg(common, WMI, "Timeout waiting for WMI command: %s\n",
wmi_cmd_to_name(cmd_id));
spin_lock_irqsave(&wmi->wmi_lock, flags);
diff --git a/drivers/net/wireless/ath/ath9k/wmi.h b/drivers/net/wireless/ath/ath9k/wmi.h
index 5c3b710b8f31..ee72b0fba31b 100644
--- a/drivers/net/wireless/ath/ath9k/wmi.h
+++ b/drivers/net/wireless/ath/ath9k/wmi.h
@@ -158,6 +158,8 @@ struct wmi {
u8 *cmd_rsp_buf;
u32 cmd_rsp_len;
bool stopped;
+ u32 cmds_issued;
+ u32 cmds_timed_out;
struct list_head pending_tx_events;
spinlock_t event_lock;
--
2.55.0
^ permalink raw reply [flat|nested] 3+ messages in thread