[3.5.y.z,extended,stable] Patch "rt2x00: fix stop queue" has been added to staging queue

Message ID 1375609773-11899-1-git-send-email-luis.henriques@canonical.com
State New
Headers show

Commit Message

Luis Henriques Aug. 4, 2013, 9:49 a.m.
This is a note to let you know that I have just added a patch titled

    rt2x00: fix stop queue

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:


If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see



From 5b7a49f4569e2f100d33307a448d1a59b1bc603c Mon Sep 17 00:00:00 2001
From: Stanislaw Gruszka <stf_xl@wp.pl>
Date: Sun, 28 Jul 2013 13:17:22 +0200
Subject: [PATCH] rt2x00: fix stop queue

commit e2288b66fe7ff0288382b2af671b4da558b44472 upstream.

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.

Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Signed-off-by: Luis Henriques <luis.henriques@canonical.com>
 drivers/net/wireless/rt2x00/rt2x00queue.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)



diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 2fd8301..6d0c651 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -877,13 +877,8 @@  void rt2x00queue_index_inc(struct queue_entry *entry, enum queue_index index)
 	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) {
 	case QID_AC_VO:
 	case QID_AC_VI:
@@ -899,6 +894,15 @@  void rt2x00queue_pause_queue(struct data_queue *queue)
+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);

 void rt2x00queue_unpause_queue(struct data_queue *queue)
@@ -960,7 +964,7 @@  void rt2x00queue_stop_queue(struct data_queue *queue)

-	rt2x00queue_pause_queue(queue);
+	rt2x00queue_pause_queue_nocheck(queue);