Johannes Berg <johannes@xxxxxxxxxxxxxxxx> writes: > From: Johannes Berg <johannes.berg@xxxxxxxxx> > > Drivers typically expect this, as it's the case for almost all cases > where this is called (i.e. from the TX path). Also, the code in mac80211 > itself (if the driver calls ieee80211_tx_dequeue()) expects this as it > uses this_cpu_ptr() without additional protection. > > This should fix various reports of the problem: > https://bugzilla.kernel.org/show_bug.cgi?id=204127 > https://lore.kernel.org/linux-wireless/CAN5HydrWb3o_FE6A1XDnP1E+xS66d5kiEuhHfiGKkLNQokx13Q@xxxxxxxxxxxxxx/ > https://lore.kernel.org/lkml/nycvar.YFH.7.76.1909111238470.473@xxxxxxxxxxxxx/ > > Reported-by: Jiri Kosina <jikos@xxxxxxxxxx> > Reported-by: Aaron Hill <aa1ronham@xxxxxxxxx> > Reported-by: Lukas Redlinger <rel+kernel@xxxxxxxxxx> > Reported-by: Oleksii Shevchuk <alxchk@xxxxxxxxx> > Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx> > --- > net/mac80211/util.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/net/mac80211/util.c b/net/mac80211/util.c > index 051a02ddcb85..ad1e88958da2 100644 > --- a/net/mac80211/util.c > +++ b/net/mac80211/util.c > @@ -273,9 +273,9 @@ static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac) > &txqi->flags)) > continue; > > - spin_unlock_bh(&fq->lock); > + spin_unlock(&fq->lock); > drv_wake_tx_queue(local, txqi); > - spin_lock_bh(&fq->lock); > + spin_lock(&fq->lock); Okay, so this will mean that the drv_wake_tx_queue() entry point will be called with bhs disabled. But there are lots of uses of spin_{,un}lock_bh() in tx.c: $ git grep lock_bh tx.c tx.c: spin_lock_bh(&fq->lock); tx.c: spin_unlock_bh(&fq->lock); tx.c: spin_lock_bh(&fq->lock); tx.c: spin_unlock_bh(&fq->lock); tx.c: spin_lock_bh(&fq->lock); tx.c: spin_unlock_bh(&fq->lock); tx.c: spin_lock_bh(&local->active_txq_lock[txqi->txq.ac]); tx.c: spin_unlock_bh(&local->active_txq_lock[txqi->txq.ac]); tx.c: spin_lock_bh(&fq->lock); tx.c: spin_unlock_bh(&fq->lock); tx.c: spin_lock_bh(&fq->lock); tx.c: spin_unlock_bh(&fq->lock); tx.c: spin_lock_bh(&sta->lock); tx.c: spin_unlock_bh(&sta->lock); tx.c: spin_lock_bh(&sta->lock); tx.c: spin_unlock_bh(&sta->lock); tx.c: spin_lock_bh(&fq->lock); tx.c: spin_unlock_bh(&fq->lock); tx.c: spin_lock_bh(&fq->lock); tx.c: spin_unlock_bh(&fq->lock); tx.c: spin_lock_bh(&fq->lock); tx.c: spin_unlock_bh(&fq->lock); tx.c: spin_unlock_bh(&fq->lock); tx.c: spin_lock_bh(&local->active_txq_lock[ac]); tx.c: spin_unlock_bh(&local->active_txq_lock[ac]); tx.c: spin_lock_bh(&local->active_txq_lock[txq->ac]); tx.c: spin_unlock_bh(&local->active_txq_lock[txq->ac]); tx.c: spin_lock_bh(&local->active_txq_lock[ac]); tx.c: spin_unlock_bh(&local->active_txq_lock[ac]); tx.c: spin_unlock_bh(&local->active_txq_lock[ac]); tx.c: spin_lock_bh(&local->active_txq_lock[ac]); tx.c: spin_unlock_bh(&local->active_txq_lock[ac]); tx.c: spin_lock_bh(&local->tim_lock); tx.c: spin_unlock_bh(&local->tim_lock); so won't that mean that the driver still gets bhs re-enabled after (for instance) the first call to ieee80211_tx_dequeue()? I must admit that I'm a bit fuzzy on this whole bh/not-bh thing; I've mostly been cargo-culting the _bh variant of the locking... :) -Toke