mac80211: Ensure off-channel frames don't get queued
Commit 6c17b77b67
(mac80211: Fix tx queue
handling during scans) contains a bug that causes off-channel frames to
get queued when they should be handed down to the driver for transmit.
Prevent this from happening.
Reported-by: Fabio Rossi <rossi.f@inwind.it>
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Родитель
163df6cf29
Коммит
a7679ed5a0
|
@ -1231,34 +1231,40 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local,
|
||||||
if (local->queue_stop_reasons[q] ||
|
if (local->queue_stop_reasons[q] ||
|
||||||
(!txpending && !skb_queue_empty(&local->pending[q]))) {
|
(!txpending && !skb_queue_empty(&local->pending[q]))) {
|
||||||
if (unlikely(info->flags &
|
if (unlikely(info->flags &
|
||||||
IEEE80211_TX_INTFL_OFFCHAN_TX_OK &&
|
IEEE80211_TX_INTFL_OFFCHAN_TX_OK)) {
|
||||||
local->queue_stop_reasons[q] &
|
if (local->queue_stop_reasons[q] &
|
||||||
~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL))) {
|
~BIT(IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL)) {
|
||||||
|
/*
|
||||||
|
* Drop off-channel frames if queues
|
||||||
|
* are stopped for any reason other
|
||||||
|
* than off-channel operation. Never
|
||||||
|
* queue them.
|
||||||
|
*/
|
||||||
|
spin_unlock_irqrestore(
|
||||||
|
&local->queue_stop_reason_lock,
|
||||||
|
flags);
|
||||||
|
ieee80211_purge_tx_queue(&local->hw,
|
||||||
|
skbs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drop off-channel frames if queues are stopped
|
* Since queue is stopped, queue up frames for
|
||||||
* for any reason other than off-channel
|
* later transmission from the tx-pending
|
||||||
* operation. Never queue them.
|
* tasklet when the queue is woken again.
|
||||||
*/
|
*/
|
||||||
spin_unlock_irqrestore(
|
if (txpending)
|
||||||
&local->queue_stop_reason_lock, flags);
|
skb_queue_splice_init(skbs,
|
||||||
ieee80211_purge_tx_queue(&local->hw, skbs);
|
&local->pending[q]);
|
||||||
return true;
|
else
|
||||||
|
skb_queue_splice_tail_init(skbs,
|
||||||
|
&local->pending[q]);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&local->queue_stop_reason_lock,
|
||||||
|
flags);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Since queue is stopped, queue up frames for later
|
|
||||||
* transmission from the tx-pending tasklet when the
|
|
||||||
* queue is woken again.
|
|
||||||
*/
|
|
||||||
if (txpending)
|
|
||||||
skb_queue_splice_init(skbs, &local->pending[q]);
|
|
||||||
else
|
|
||||||
skb_queue_splice_tail_init(skbs,
|
|
||||||
&local->pending[q]);
|
|
||||||
|
|
||||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock,
|
|
||||||
flags);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче