Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Stanislaw Gruszka and committed by
John W. Linville
e2288b66 a538ae31

+11 -7
+11 -7
drivers/net/wireless/rt2x00/rt2x00queue.c
··· 936 936 spin_unlock_irqrestore(&queue->index_lock, irqflags); 937 937 } 938 938 939 - void rt2x00queue_pause_queue(struct data_queue *queue) 939 + void rt2x00queue_pause_queue_nocheck(struct data_queue *queue) 940 940 { 941 - if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || 942 - !test_bit(QUEUE_STARTED, &queue->flags) || 943 - test_and_set_bit(QUEUE_PAUSED, &queue->flags)) 944 - return; 945 - 946 941 switch (queue->qid) { 947 942 case QID_AC_VO: 948 943 case QID_AC_VI: ··· 952 957 default: 953 958 break; 954 959 } 960 + } 961 + void rt2x00queue_pause_queue(struct data_queue *queue) 962 + { 963 + if (!test_bit(DEVICE_STATE_PRESENT, &queue->rt2x00dev->flags) || 964 + !test_bit(QUEUE_STARTED, &queue->flags) || 965 + test_and_set_bit(QUEUE_PAUSED, &queue->flags)) 966 + return; 967 + 968 + rt2x00queue_pause_queue_nocheck(queue); 955 969 } 956 970 EXPORT_SYMBOL_GPL(rt2x00queue_pause_queue); 957 971 ··· 1023 1019 return; 1024 1020 } 1025 1021 1026 - rt2x00queue_pause_queue(queue); 1022 + rt2x00queue_pause_queue_nocheck(queue); 1027 1023 1028 1024 queue->rt2x00dev->ops->lib->stop_queue(queue); 1029 1025