git: 8121f688bb55 - stable/14 - LinuxKPI: 802.11: adjust lower wake_queue locking

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Fri, 16 Jan 2026 19:40:41 UTC
The branch stable/14 has been updated by bz:

URL: https://cgit.FreeBSD.org/src/commit/?id=8121f688bb550af894b4b1b3ff66dba283ac16d5

commit 8121f688bb550af894b4b1b3ff66dba283ac16d5
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2025-08-29 07:39:01 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2026-01-16 19:37:45 +0000

    LinuxKPI: 802.11: adjust lower wake_queue locking
    
    In bc24342d96aa8 we added lower wake_queue locking.  There are paths,
    such as in rtw89 from a (*hw_scan_cancel)() that we can get to there and
    then would recursively acquire the wiphy lock which is not allowed.
    Adjust locking to a spin lock to match Linux driver expectations.
    
    Sponsored by:   The FreeBSD Foundation
    Fixes:          bc24342d96aa8
    
    (cherry picked from commit fc36de571f11abda5cc68a4abd963053f676f8c5)
---
 sys/compat/linuxkpi/common/src/linux_80211.c | 19 +++++++++++++++----
 sys/compat/linuxkpi/common/src/linux_80211.h |  1 +
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index 7461b5db940a..17279f3caf6c 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -5959,6 +5959,7 @@ linuxkpi_ieee80211_alloc_hw(size_t priv_len, const struct ieee80211_ops *ops)
 
 	LKPI_80211_LHW_SCAN_LOCK_INIT(lhw);
 	LKPI_80211_LHW_TXQ_LOCK_INIT(lhw);
+	spin_lock_init(&lhw->txq_lock);
 	sx_init_flags(&lhw->lvif_sx, "lhw-lvif", SX_RECURSE | SX_DUPOK);
 	TAILQ_INIT(&lhw->lvif_head);
 	for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
@@ -6058,6 +6059,7 @@ linuxkpi_ieee80211_iffree(struct ieee80211_hw *hw)
 	}
 
 	/* Cleanup more of lhw here or in wiphy_free()? */
+	spin_lock_destroy(&lhw->txq_lock);
 	LKPI_80211_LHW_TXQ_LOCK_DESTROY(lhw);
 	LKPI_80211_LHW_SCAN_LOCK_DESTROY(lhw);
 	sx_destroy(&lhw->lvif_sx);
@@ -8027,21 +8029,30 @@ lkpi_ieee80211_wake_queues_locked(struct ieee80211_hw *hw)
 void
 linuxkpi_ieee80211_wake_queues(struct ieee80211_hw *hw)
 {
-	wiphy_lock(hw->wiphy);
+	struct lkpi_hw *lhw;
+	unsigned long flags;
+
+	lhw = HW_TO_LHW(hw);
+
+	spin_lock_irqsave(&lhw->txq_lock, flags);
 	lkpi_ieee80211_wake_queues_locked(hw);
-	wiphy_unlock(hw->wiphy);
+	spin_unlock_irqrestore(&lhw->txq_lock, flags);
 }
 
 void
 linuxkpi_ieee80211_wake_queue(struct ieee80211_hw *hw, int qnum)
 {
+	struct lkpi_hw *lhw;
+	unsigned long flags;
 
 	KASSERT(qnum < hw->queues, ("%s: qnum %d >= hw->queues %d, hw %p\n",
 	    __func__, qnum, hw->queues, hw));
 
-	wiphy_lock(hw->wiphy);
+	lhw = HW_TO_LHW(hw);
+
+	spin_lock_irqsave(&lhw->txq_lock, flags);
 	lkpi_ieee80211_wake_queues(hw, qnum);
-	wiphy_unlock(hw->wiphy);
+	spin_unlock_irqrestore(&lhw->txq_lock, flags);
 }
 
 /* This is just hardware queues. */
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h
index 89afec1235bd..eb7bae811695 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.h
+++ b/sys/compat/linuxkpi/common/src/linux_80211.h
@@ -227,6 +227,7 @@ struct lkpi_hw {	/* name it mac80211_sc? */
 	struct mtx			txq_mtx;
 	uint32_t			txq_generation[IEEE80211_NUM_ACS];
 	TAILQ_HEAD(, lkpi_txq)		scheduled_txqs[IEEE80211_NUM_ACS];
+	spinlock_t			txq_lock;
 
 	/* Deferred RX path. */
 	struct task		rxq_task;