From: Aaron Esau <aaron1esau@gmail.com>
To: linux-wireless@vger.kernel.org
Cc: miriam.rachel.korenblit@intel.com, stable@vger.kernel.org,
Aaron Esau <aaron1esau@gmail.com>
Subject: [PATCH] wifi: iwlwifi: mld: bail out from TX when firmware is dead
Date: Mon, 13 Apr 2026 13:43:37 -0500 [thread overview]
Message-ID: <20260413184337.413259-1-aaron1esau@gmail.com> (raw)
The drain loop in iwl_mld_tx_from_txq() keeps dequeuing and processing
packets while stop_full is not set and mac80211 has buffered frames.
When firmware crashes, STATUS_FW_ERROR may not be set before softirq TX
paths enter this loop. Each iteration performs expensive GSO segmentation
via iwl_tx_tso_segment() -> skb_gso_segment() while holding the netdev
TX queue spinlock (HARD_TX_LOCK from __dev_queue_xmit), blocking all
other CPUs attempting to transmit.
The existing backpressure mechanism (stop_full, set via iwl_txq_stop()
when the hardware ring crosses its high water mark) is insufficient:
iwl_trans_pcie_tx() silently absorbs frames into its overflow_q and
returns success even when the ring is full and firmware is not consuming
descriptors. This delays the stop_full signal long enough for the loop
to hold the TX lock for tens of seconds, triggering soft lockups across
multiple CPUs that cascade into SLUB freelist corruption during the
subsequent driver reprobe.
Add a test_bit(STATUS_FW_ERROR) check to the drain loop so that it
exits promptly when firmware is no longer alive.
Fixes: d1e879ec600f ("wifi: iwlwifi: add iwlmld sub-driver")
Cc: stable@vger.kernel.org
Signed-off-by: Aaron Esau <aaron1esau@gmail.com>
---
Found while investigating a complete system freeze on a Lenovo ThinkPad
(Intel Core Ultra 7 155H, Intel Wi-Fi 7 BE200) running kernel 6.19.11.
The firmware LMAC crashed (NMI_INTERRUPT_UNKNOWN, both LMACs halted at
0xd0), the drain loop held HARD_TX_LOCK for 26+ seconds, 7 CPUs soft
locked, and the subsequent reprobe corrupted SLUB freelist pointers
(non-canonical address 0x54c991d5bf7e0cce in __kmalloc), killing Xorg,
systemd --user, and requiring a hard power off.
CachyOS/linux-cachyos#673 reports the same crash signature on BE200
with kernel 6.18+, confirming the pattern. The documented workaround
(ethtool -K <iface> tso off gso off) works because it eliminates the
per-packet skb_gso_segment() cost, allowing the ring to fill and
stop_full to trip before the watchdog fires.
drivers/net/wireless/intel/iwlwifi/mld/tx.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tx.c b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
index e3fb4fc4f..5e8a63e24 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tx.c
@@ -989,6 +989,8 @@ void iwl_mld_tx_from_txq(struct iwl_mld *mld, struct ieee80211_txq *txq)
rcu_read_lock();
do {
while (likely(!mld_txq->status.stop_full) &&
+ !test_bit(STATUS_FW_ERROR,
+ &mld->trans->status) &&
(skb = ieee80211_tx_dequeue(mld->hw, txq)))
iwl_mld_tx_skb(mld, skb, txq);
} while (atomic_dec_return(&mld_txq->tx_request));
--
2.49.0
reply other threads:[~2026-04-13 18:43 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260413184337.413259-1-aaron1esau@gmail.com \
--to=aaron1esau@gmail.com \
--cc=linux-wireless@vger.kernel.org \
--cc=miriam.rachel.korenblit@intel.com \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox