2023-06-07 10:04:24

by Wen Gong

[permalink] [raw]
Subject: [PATCH v4 3/5] wifi: ath11k: fix a possible dead lock caused by ab->base_lock

From: Baochen Qiang <[email protected]>

spin_lock/spin_unlock are used in ath11k_reg_chan_list_event to
acquire/release ab->base_lock, for now this is safe because that
function is only called in soft IRQ context. But in an upcoming
patch ath11k_reg_chan_list_event() will be called from process
context, and this can result in a deadlock if ab->base_lock is
acquired in process context and then soft IRQ occurs on the same
CPU and tries to acquire that lock.

Fix it by using spin_lock_bh and spin_unlock_bh instead.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3.6510.23

Fixes: 69a0fcf8a9f2 ("ath11k: Avoid reg rules update during firmware recovery")
Signed-off-by: Baochen Qiang <[email protected]>
Signed-off-by: Wen Gong <[email protected]>
---
drivers/net/wireless/ath/ath11k/wmi.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 77de11985f5a..2965dffe8ceb 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -7039,13 +7039,13 @@ int ath11k_reg_handle_chan_list(struct ath11k_base *ab,
/* Avoid default reg rule updates sent during FW recovery if
* it is already available
*/
- spin_lock(&ab->base_lock);
+ spin_lock_bh(&ab->base_lock);
if (test_bit(ATH11K_FLAG_RECOVERY, &ab->dev_flags) &&
ab->default_regd[pdev_idx]) {
- spin_unlock(&ab->base_lock);
+ spin_unlock_bh(&ab->base_lock);
goto retfail;
}
- spin_unlock(&ab->base_lock);
+ spin_unlock_bh(&ab->base_lock);

if (pdev_idx >= ab->num_radios) {
/* Process the event for phy0 only if single_pdev_only
@@ -7095,7 +7095,7 @@ int ath11k_reg_handle_chan_list(struct ath11k_base *ab,
ab->reg_info_store[pdev_idx] = *reg_info;
}

- spin_lock(&ab->base_lock);
+ spin_lock_bh(&ab->base_lock);
if (ab->default_regd[pdev_idx]) {
/* The initial rules from FW after WMI Init is to build
* the default regd. From then on, any rules updated for
@@ -7115,7 +7115,7 @@ int ath11k_reg_handle_chan_list(struct ath11k_base *ab,
ab->default_regd[pdev_idx] = regd;
}
ab->dfs_region = reg_info->dfs_region;
- spin_unlock(&ab->base_lock);
+ spin_unlock_bh(&ab->base_lock);

return 0;

--
2.40.1