Message ID | 20230315190731.145997-1-alexander@wetzel-home.de (mailing list archive) |
---|---|
State | Accepted |
Delegated to: | Johannes Berg |
Headers | show |
Series | [v2] wifi: mac80211: Serialize ieee80211_handle_wake_tx_queue() | expand |
Hi, this patch fixes the bug for me too. Thanks for fixing it! Regards On Wed, 15 Mar 2023 20:07:31 +0100 Alexander Wetzel <alexander@wetzel-home.de> wrote: > ieee80211_handle_wake_tx_queue must not run concurrent. > It calls ieee80211_txq_schedule_start() and the drivers migrated to > iTXQ do not expect overlapping drv_tx() calls. > > This fixes commit c850e31f79f0 ("wifi: mac80211: add internal handler > for wake_tx_queue"), which introduced > ieee80211_handle_wake_tx_queue(). Drivers started to use it with > commit a790cc3a4fad ("wifi: mac80211: add wake_tx_queue callback to > drivers"). But only after fixing an independent bug with commit > 4444bc2116ae ("wifi: mac80211: Proper mark iTXQs for resumption") > problematic concurrent calls really happened and exposed the initial > issue. > > Fixes: c850e31f79f0 ("wifi: mac80211: add internal handler for > wake_tx_queue") Reported-by: Thomas Mann <rauchwolke@gmx.net> > Link: https://bugzilla.kernel.org/show_bug.cgi?id=217119 > Link: > https://lore.kernel.org/r/b8efebc6-4399-d0b8-b2a0-66843314616b@leemhuis.info/ > Link: > https://lore.kernel.org/r/b7445607128a6b9ed7c17fcdcf3679bfaf4aaea.camel@sipsolutions.net> > CC: <stable@vger.kernel.org> Signed-off-by: Alexander Wetzel > <alexander@wetzel-home.de> --- > > V1..V2 > Added the missing spinlock Felix pointed out and fixed the commit > references with the feedback from Kalle. > --- > net/mac80211/ieee80211_i.h | 3 +++ > net/mac80211/main.c | 1 + > net/mac80211/util.c | 3 +++ > 3 files changed, 7 insertions(+) > > diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h > index ecc232eb1ee8..e082582e0aa2 100644 > --- a/net/mac80211/ieee80211_i.h > +++ b/net/mac80211/ieee80211_i.h > @@ -1284,6 +1284,9 @@ struct ieee80211_local { > struct list_head active_txqs[IEEE80211_NUM_ACS]; > u16 schedule_round[IEEE80211_NUM_ACS]; > > + /* serializes ieee80211_handle_wake_tx_queue */ > + spinlock_t handle_wake_tx_queue_lock; > + > u16 airtime_flags; > u32 aql_txq_limit_low[IEEE80211_NUM_ACS]; > u32 aql_txq_limit_high[IEEE80211_NUM_ACS]; > diff --git a/net/mac80211/main.c b/net/mac80211/main.c > index 846528850612..3b622f2b787b 100644 > --- a/net/mac80211/main.c > +++ b/net/mac80211/main.c > @@ -788,6 +788,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t > priv_data_len, spin_lock_init(&local->filter_lock); > spin_lock_init(&local->rx_path_lock); > spin_lock_init(&local->queue_stop_reason_lock); > + spin_lock_init(&local->handle_wake_tx_queue_lock); > > for (i = 0; i < IEEE80211_NUM_ACS; i++) { > INIT_LIST_HEAD(&local->active_txqs[i]); > diff --git a/net/mac80211/util.c b/net/mac80211/util.c > index 1a28fe5cb614..3aceb3b731bf 100644 > --- a/net/mac80211/util.c > +++ b/net/mac80211/util.c > @@ -314,6 +314,8 @@ void ieee80211_handle_wake_tx_queue(struct > ieee80211_hw *hw, struct ieee80211_sub_if_data *sdata = > vif_to_sdata(txq->vif); struct ieee80211_txq *queue; > > + spin_lock(&local->handle_wake_tx_queue_lock); > + > /* Use ieee80211_next_txq() for airtime fairness accounting > */ ieee80211_txq_schedule_start(hw, txq->ac); > while ((queue = ieee80211_next_txq(hw, txq->ac))) { > @@ -321,6 +323,7 @@ void ieee80211_handle_wake_tx_queue(struct > ieee80211_hw *hw, ieee80211_return_txq(hw, queue, false); > } > ieee80211_txq_schedule_end(hw, txq->ac); > + spin_unlock(&local->handle_wake_tx_queue_lock); > } > EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue); >
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ecc232eb1ee8..e082582e0aa2 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1284,6 +1284,9 @@ struct ieee80211_local { struct list_head active_txqs[IEEE80211_NUM_ACS]; u16 schedule_round[IEEE80211_NUM_ACS]; + /* serializes ieee80211_handle_wake_tx_queue */ + spinlock_t handle_wake_tx_queue_lock; + u16 airtime_flags; u32 aql_txq_limit_low[IEEE80211_NUM_ACS]; u32 aql_txq_limit_high[IEEE80211_NUM_ACS]; diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 846528850612..3b622f2b787b 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -788,6 +788,7 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len, spin_lock_init(&local->filter_lock); spin_lock_init(&local->rx_path_lock); spin_lock_init(&local->queue_stop_reason_lock); + spin_lock_init(&local->handle_wake_tx_queue_lock); for (i = 0; i < IEEE80211_NUM_ACS; i++) { INIT_LIST_HEAD(&local->active_txqs[i]); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1a28fe5cb614..3aceb3b731bf 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -314,6 +314,8 @@ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw, struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->vif); struct ieee80211_txq *queue; + spin_lock(&local->handle_wake_tx_queue_lock); + /* Use ieee80211_next_txq() for airtime fairness accounting */ ieee80211_txq_schedule_start(hw, txq->ac); while ((queue = ieee80211_next_txq(hw, txq->ac))) { @@ -321,6 +323,7 @@ void ieee80211_handle_wake_tx_queue(struct ieee80211_hw *hw, ieee80211_return_txq(hw, queue, false); } ieee80211_txq_schedule_end(hw, txq->ac); + spin_unlock(&local->handle_wake_tx_queue_lock); } EXPORT_SYMBOL(ieee80211_handle_wake_tx_queue);
ieee80211_handle_wake_tx_queue must not run concurrent. It calls ieee80211_txq_schedule_start() and the drivers migrated to iTXQ do not expect overlapping drv_tx() calls. This fixes commit c850e31f79f0 ("wifi: mac80211: add internal handler for wake_tx_queue"), which introduced ieee80211_handle_wake_tx_queue(). Drivers started to use it with commit a790cc3a4fad ("wifi: mac80211: add wake_tx_queue callback to drivers"). But only after fixing an independent bug with commit 4444bc2116ae ("wifi: mac80211: Proper mark iTXQs for resumption") problematic concurrent calls really happened and exposed the initial issue. Fixes: c850e31f79f0 ("wifi: mac80211: add internal handler for wake_tx_queue") Reported-by: Thomas Mann <rauchwolke@gmx.net> Link: https://bugzilla.kernel.org/show_bug.cgi?id=217119 Link: https://lore.kernel.org/r/b8efebc6-4399-d0b8-b2a0-66843314616b@leemhuis.info/ Link: https://lore.kernel.org/r/b7445607128a6b9ed7c17fcdcf3679bfaf4aaea.camel@sipsolutions.net> CC: <stable@vger.kernel.org> Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de> --- V1..V2 Added the missing spinlock Felix pointed out and fixed the commit references with the feedback from Kalle. --- net/mac80211/ieee80211_i.h | 3 +++ net/mac80211/main.c | 1 + net/mac80211/util.c | 3 +++ 3 files changed, 7 insertions(+)