rt2x00: fix stop queue
Since we clear QUEUE_STARTED in rt2x00queue_stop_queue(), following call to rt2x00queue_pause_queue() reduce to noop, i.e we do not stop queue in mac80211. To fix that introduce rt2x00queue_pause_queue_nocheck() function, which will stop queue in mac80211 directly. Note that rt2x00_start_queue() explicitly set QUEUE_PAUSED bit. Note also that reordering operations i.e. first call to rt2x00queue_pause_queue() and then clear QUEUE_STARTED bit, will race with rt2x00queue_unpause_queue(), so calling ieee80211_stop_queue() directly is the only available solution to fix the problem without major rework. Cc: stable@vger.kernel.org Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl> Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
parent
a538ae3189
commit
e2288b66fe
|
@ -936,13 +936,8 @@ void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
|
||||||
spin_unlock_irqrestore(&queue->index_lock, irqflags);
|
spin_unlock_irqrestore(&queue->index_lock, irqflags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void rt2x00queue_pause_queue(struct data_queue *queue)
|
void rt2x00queue_pause_queue_nocheck(struct data_queue *queue)
|
||||||
{
|
{
|
||||||
if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
|
|
||||||
!test_bit(QUEUE_STARTED, &queue->flags) ||
|
|
||||||
test_and_set_bit(QUEUE_PAUSED, &queue->flags))
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (queue->qid) {
|
switch (queue->qid) {
|
||||||
case QID_AC_VO:
|
case QID_AC_VO:
|
||||||
case QID_AC_VI:
|
case QID_AC_VI:
|
||||||
|
@ -958,6 +953,15 @@ void rt2x00queue_pause_queue(struct data_queue *queue)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void rt2x00queue_pause_queue(struct data_queue *queue)
|
||||||
|
{
|
||||||
|
if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) ||
|
||||||
|
!test_bit(QUEUE_STARTED, &queue->flags) ||
|
||||||
|
test_and_set_bit(QUEUE_PAUSED, &queue->flags))
|
||||||
|
return;
|
||||||
|
|
||||||
|
rt2x00queue_pause_queue_nocheck(queue);
|
||||||
|
}
|
||||||
EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue);
|
EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue);
|
||||||
|
|
||||||
void rt2x00queue_unpause_queue(struct data_queue *queue)
|
void rt2x00queue_unpause_queue(struct data_queue *queue)
|
||||||
|
@ -1019,7 +1023,7 @@ void rt2x00queue_stop_queue(struct data_queue *queue)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rt2x00queue_pause_queue(queue);
|
rt2x00queue_pause_queue_nocheck(queue);
|
||||||
|
|
||||||
queue->rt2x00dev->ops->lib->stop_queue(queue);
|
queue->rt2x00dev->ops->lib->stop_queue(queue);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue