mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-22 06:57:57 +00:00
8b06e06832
Fixes a potential deadlock and a tx queue hang on STA assoc Signed-off-by: Felix Fietkau <nbd@nbd.name>
41 lines
1.4 KiB
Diff
41 lines
1.4 KiB
Diff
From: Alexander Wetzel <alexander@wetzel-home.de>
|
|
Date: Thu, 15 Sep 2022 14:41:20 +0200
|
|
Subject: [PATCH] mac80211: Fix deadlock: Don't start TX while holding
|
|
fq->lock
|
|
|
|
ieee80211_txq_purge() calls fq_tin_reset() and
|
|
ieee80211_purge_tx_queue(); Both are then calling
|
|
ieee80211_free_txskb(). Which can decide to TX the skb again.
|
|
|
|
There are at least two ways to get a deadlock:
|
|
|
|
1) When we have a TDLS teardown packet queued in either tin or frags
|
|
ieee80211_tdls_td_tx_handle() will call ieee80211_subif_start_xmit()
|
|
while we still hold fq->lock. ieee80211_txq_enqueue() will thus
|
|
deadlock.
|
|
|
|
2) A variant of the above happens if aggregation is up and running:
|
|
In that case ieee80211_iface_work() will deadlock with the original
|
|
task: The original tasks already holds fq->lock and tries to get
|
|
sta->lock after kicking off ieee80211_iface_work(). But the worker
|
|
can get sta->lock prior to the original task and will then spin for
|
|
fq->lock.
|
|
|
|
Avoid these deadlocks by not sending out any skbs when called via
|
|
ieee80211_free_txskb().
|
|
|
|
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
|
|
---
|
|
|
|
--- a/net/mac80211/status.c
|
|
+++ b/net/mac80211/status.c
|
|
@@ -698,7 +698,7 @@ static void ieee80211_report_used_skb(st
|
|
|
|
if (!sdata) {
|
|
skb->dev = NULL;
|
|
- } else {
|
|
+ } else if (!dropped) {
|
|
unsigned int hdr_size =
|
|
ieee80211_hdrlen(hdr->frame_control);
|
|
|