008ee49cfba64c7ec671d96615eba05d576dedd7
[openwrt/staging/981213.git] /
1 From: Johannes Berg <johannes.berg@intel.com>
2 Date: Mon, 29 Nov 2021 15:32:47 +0200
3 Subject: [PATCH] mac80211: agg-tx: don't schedule_and_wake_txq() under
4 sta->lock
5
6 When we call ieee80211_agg_start_txq(), that will in turn call
7 schedule_and_wake_txq(). Called from ieee80211_stop_tx_ba_cb()
8 this is done under sta->lock, which leads to certain circular
9 lock dependencies, as reported by Chris Murphy:
10 https://lore.kernel.org/r/CAJCQCtSXJ5qA4bqSPY=oLRMbv-irihVvP7A2uGutEbXQVkoNaw@mail.gmail.com
11
12 In general, ieee80211_agg_start_txq() is usually not called
13 with sta->lock held, only in this one place. But it's always
14 called with sta->ampdu_mlme.mtx held, and that's therefore
15 clearly sufficient.
16
17 Change ieee80211_stop_tx_ba_cb() to also call it without the
18 sta->lock held, by factoring it out of ieee80211_remove_tid_tx()
19 (which is only called in this one place).
20
21 This breaks the locking chain and makes it less likely that
22 we'll have similar locking chain problems in the future.
23
24 Reported-by: Chris Murphy <lists@colorremedies.com>
25 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
26 Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
27 ---
28
29 --- a/net/mac80211/agg-tx.c
30 +++ b/net/mac80211/agg-tx.c
31 @@ -9,7 +9,7 @@
32 * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
33 * Copyright 2007-2010, Intel Corporation
34 * Copyright(c) 2015-2017 Intel Deutschland GmbH
35 - * Copyright (C) 2018 - 2020 Intel Corporation
36 + * Copyright (C) 2018 - 2021 Intel Corporation
37 */
38
39 #include <linux/ieee80211.h>
40 @@ -213,6 +213,8 @@ ieee80211_agg_start_txq(struct sta_info
41 struct ieee80211_txq *txq = sta->sta.txq[tid];
42 struct txq_info *txqi;
43
44 + lockdep_assert_held(&sta->ampdu_mlme.mtx);
45 +
46 if (!txq)
47 return;
48
49 @@ -290,7 +292,6 @@ static void ieee80211_remove_tid_tx(stru
50 ieee80211_assign_tid_tx(sta, tid, NULL);
51
52 ieee80211_agg_splice_finish(sta->sdata, tid);
53 - ieee80211_agg_start_txq(sta, tid, false);
54
55 kfree_rcu(tid_tx, rcu_head);
56 }
57 @@ -889,6 +890,7 @@ void ieee80211_stop_tx_ba_cb(struct sta_
58 {
59 struct ieee80211_sub_if_data *sdata = sta->sdata;
60 bool send_delba = false;
61 + bool start_txq = false;
62
63 ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n",
64 sta->sta.addr, tid);
65 @@ -906,10 +908,14 @@ void ieee80211_stop_tx_ba_cb(struct sta_
66 send_delba = true;
67
68 ieee80211_remove_tid_tx(sta, tid);
69 + start_txq = true;
70
71 unlock_sta:
72 spin_unlock_bh(&sta->lock);
73
74 + if (start_txq)
75 + ieee80211_agg_start_txq(sta, tid, false);
76 +
77 if (send_delba)
78 ieee80211_send_delba(sdata, sta->sta.addr, tid,
79 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);