summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarthik M <quic_karm@quicinc.com>2023-04-28 20:01:37 +0300
committerKalle Valo <quic_kvalo@quicinc.com>2023-05-05 15:57:22 +0300
commite995f3f602a3fd9c8e0f97f59b37002d4ab5ec83 (patch)
treeecf314f2ce3bf855ca9b0db5b339f53fa1c08b60
parent5189a8dba849f0153f30561e3ac257e0be01abdd (diff)
downloadlinux-stable-e995f3f602a3fd9c8e0f97f59b37002d4ab5ec83.tar.gz
linux-stable-e995f3f602a3fd9c8e0f97f59b37002d4ab5ec83.tar.bz2
linux-stable-e995f3f602a3fd9c8e0f97f59b37002d4ab5ec83.zip
wifi: ath12k: fix potential wmi_mgmt_tx_queue race condition
During stress test with maximum VAPs and peer connected, below warning is seen: [ 1079.110967] ath12k_pci 0004:01:00.0: mgmt tx queue is full [ 1079.117708] ath12k_pci 0004:01:00.0: failed to queue management frame -28 [ 1079.123191] ath12k_pci 0004:01:00.0: mgmt tx queue is full [ 1079.129960] ath12k_pci 0004:01:00.0: failed to queue management frame -28 [ 1079.135641] ath12k_pci 0004:01:00.0: mgmt tx queue is full This is caused by potential race condition while accessing skb_queue_len(). When ath12k_mgmt_over_wmi_tx_work() and ath12k_mac_mgmt_tx() is called concurrently, then skb_queue_len() might fetch list length which is modified by skb_queue_tail() or skb_dequeue(). Replace skb_queue_len() with skb_queue_len_lockless() which will prevent concurrent modified access using READ_ONCE(). And also use '>=', in case we queue a few SKBs simultaneously. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1 Signed-off-by: Karthik M <quic_karm@quicinc.com> Signed-off-by: Ramya Gnanasekar <quic_rgnanase@quicinc.com> Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com> Link: https://lore.kernel.org/r/20230419095758.19998-1-quic_rgnanase@quicinc.com
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index b52675a113f4..b337fb7f793f 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -4548,7 +4548,7 @@ static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
return -ENOSPC;
}
- if (skb_queue_len(q) == ATH12K_TX_MGMT_NUM_PENDING_MAX) {
+ if (skb_queue_len_lockless(q) >= ATH12K_TX_MGMT_NUM_PENDING_MAX) {
ath12k_warn(ar->ab, "mgmt tx queue is full\n");
return -ENOSPC;
}