Commit e2288b66 authored by Stanislaw Gruszka's avatar Stanislaw Gruszka Committed by John W. Linville

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: default avatarStanislaw Gruszka <stf_xl@wp.pl>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a538ae31
...@@ -936,13 +936,8 @@ void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index) ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment