wifi: mac80211: Serialize ieee80211_handle_wake_tx_queue()
ieee80211_handle_wake_tx_queue must not run concurrent multiple times.
It calls ieee80211_txq_schedule_start() and the drivers migrated to iTXQ
do not expect overlapping drv_tx() calls.
This fixes 'c850e31f79f0 ("wifi: mac80211: add internal handler for
wake_tx_queue")', which introduced ieee80211_handle_wake_tx_queue.
Drivers started to use it with 'a790cc3a4fad ("wifi: mac80211: add
wake_tx_queue callback to drivers")'.
But only after fixing an independent bug with
'4444bc2116ae ("wifi: mac80211: Proper mark iTXQs for resumption")'
problematic concurrent calls really happened and exposed the initial
issue.
Fixes: c850e31f79
("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>
Link: https://lore.kernel.org/r/20230314211122.111688-1-alexander@wetzel-home.de
[add missing spin_lock_init() noticed by Felix]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Родитель
139f6973bf
Коммит
007ae9b268
|
@ -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];
|
||||
|
|
|
@ -802,6 +802,8 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
|
|||
local->aql_threshold = IEEE80211_AQL_THRESHOLD;
|
||||
atomic_set(&local->aql_total_pending_airtime, 0);
|
||||
|
||||
spin_lock_init(&local->handle_wake_tx_queue_lock);
|
||||
|
||||
INIT_LIST_HEAD(&local->chanctx_list);
|
||||
mutex_init(&local->chanctx_mtx);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче