]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: move firmware stats request outside of atomic context
authorBaochen Qiang <baochen.qiang@oss.qualcomm.com>
Wed, 19 Nov 2025 02:24:47 +0000 (10:24 +0800)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Wed, 19 Nov 2025 19:52:08 +0000 (11:52 -0800)
In ath12k_mac_op_link_sta_statistics(), the atomic context scope
introduced by dp_lock also covers firmware stats request. Since that
request could block, below issue is hit:

BUG: sleeping function called from invalid context at kernel/locking/mutex.c:575
in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 6866, name: iw
preempt_count: 201, expected: 0
RCU nest depth: 0, expected: 0
3 locks held by iw/6866:
 #0:[...]
 #1:[...]
 #2: ffff9748f43230c8 (&dp->dp_lock){+.-.}-{3:3}, at:
ath12k_mac_op_link_sta_statistics+0xc6/0x380 [ath12k]
Preemption disabled at:
[<ffffffffc0349656>] ath12k_mac_op_link_sta_statistics+0xc6/0x380 [ath12k]
Call Trace:
 <TASK>
 show_stack
 dump_stack_lvl
 dump_stack
 __might_resched.cold
 __might_sleep
 __mutex_lock
 mutex_lock_nested
 ath12k_mac_get_fw_stats
 ath12k_mac_op_link_sta_statistics
 </TASK>

Since firmware stats request doesn't require protection from dp_lock, move
it outside to fix this issue.

While moving, also refine that code hunk to make function parameters get
populated when really necessary.

Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00302-QCAHMTSWPL_V1.0_V2.0_SILICONZ-1.115823.3

Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20251119-ath12k-ng-sleep-in-atomic-v1-1-5d1a726597db@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/mac.c

index aa80afebb69ea77e6715d90aae12bf50fe718b8c..3649f58fef8488397186cbca6a52d1c84e6092f5 100644 (file)
@@ -12792,10 +12792,12 @@ void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
        db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,
                          ar->ab->wmi_ab.svc_map);
 
-       guard(spinlock_bh)(&ar->ab->dp->dp_lock);
+       spin_lock_bh(&ar->ab->dp->dp_lock);
        peer = ath12k_dp_link_peer_find_by_addr(ar->ab->dp, arsta->addr);
-       if (!peer)
+       if (!peer) {
+               spin_unlock_bh(&ar->ab->dp->dp_lock);
                return;
+       }
 
        link_sinfo->rx_duration = peer->rx_duration;
        link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_RX_DURATION);
@@ -12822,35 +12824,35 @@ void ath12k_mac_op_link_sta_statistics(struct ieee80211_hw *hw,
                link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE);
        }
 
+       link_sinfo->signal_avg = ewma_avg_rssi_read(&peer->avg_rssi);
+       if (!db2dbm)
+               link_sinfo->signal_avg += ATH12K_DEFAULT_NOISE_FLOOR;
+       link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
+
+       link_sinfo->tx_retries = peer->tx_retry_count;
+       link_sinfo->tx_failed = peer->tx_retry_failed;
+       link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
+       link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
+
        /* TODO: Use real NF instead of default one. */
        signal = peer->rssi_comb;
 
-       params.pdev_id = ar->pdev->pdev_id;
-       params.vdev_id = 0;
-       params.stats_id = WMI_REQUEST_VDEV_STAT;
+       spin_unlock_bh(&ar->ab->dp->dp_lock);
 
-       if (!signal &&
-           ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA &&
-           !(ath12k_mac_get_fw_stats(ar, &params)))
-               signal = arsta->rssi_beacon;
+       if (!signal && ahsta->ahvif->vdev_type == WMI_VDEV_TYPE_STA) {
+               params.pdev_id = ar->pdev->pdev_id;
+               params.vdev_id = 0;
+               params.stats_id = WMI_REQUEST_VDEV_STAT;
+
+               if (!ath12k_mac_get_fw_stats(ar, &params))
+                       signal = arsta->rssi_beacon;
+       }
 
        if (signal) {
                link_sinfo->signal =
                        db2dbm ? signal : signal + ATH12K_DEFAULT_NOISE_FLOOR;
                link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL);
        }
-
-       link_sinfo->signal_avg = ewma_avg_rssi_read(&peer->avg_rssi);
-
-       if (!db2dbm)
-               link_sinfo->signal_avg += ATH12K_DEFAULT_NOISE_FLOOR;
-
-       link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);
-
-       link_sinfo->tx_retries = peer->tx_retry_count;
-       link_sinfo->tx_failed = peer->tx_retry_failed;
-       link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_RETRIES);
-       link_sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);
 }
 EXPORT_SYMBOL(ath12k_mac_op_link_sta_statistics);