summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2011-10-05 14:04:59 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2011-10-05 14:04:59 -0700
commit1893af4b5725b9e8bda37278f657f4f708d9dba4 (patch)
tree362dbf0493ec7f0ba8c3b84708680aa1d791421f
parent2dd4a66a1f70048b9bea047978a860d549bdb3cd (diff)
downloadstable-queue-1893af4b5725b9e8bda37278f657f4f708d9dba4.tar.gz
3.0 patches
-rw-r--r--queue-3.0/rt2x00-serialize-tx-operations-on-a-queue.patch118
-rw-r--r--queue-3.0/series1
2 files changed, 119 insertions, 0 deletions
diff --git a/queue-3.0/rt2x00-serialize-tx-operations-on-a-queue.patch b/queue-3.0/rt2x00-serialize-tx-operations-on-a-queue.patch
new file mode 100644
index 0000000000..a842c58045
--- /dev/null
+++ b/queue-3.0/rt2x00-serialize-tx-operations-on-a-queue.patch
@@ -0,0 +1,118 @@
+From 77a861c405da75d81e9e6e32c50eb7f9777777e8 Mon Sep 17 00:00:00 2001
+From: Gertjan van Wingerde <gwingerde@gmail.com>
+Date: Wed, 6 Jul 2011 22:56:24 +0200
+Subject: rt2x00: Serialize TX operations on a queue.
+
+From: Gertjan van Wingerde <gwingerde@gmail.com>
+
+commit 77a861c405da75d81e9e6e32c50eb7f9777777e8 upstream.
+
+The rt2x00 driver gets frequent occurrences of the following error message
+when operating under load:
+phy0 -> rt2x00queue_write_tx_frame: Error - Arrived at non-free entry in the
+non-full queue 2.
+
+This is caused by simultaneous attempts from mac80211 to send a frame via
+rt2x00, which are not properly serialized inside rt2x00queue_write_tx_frame,
+causing the second frame to fail sending with the above mentioned error
+message.
+
+Fix this by introducing a per-queue spinlock to serialize the TX operations
+on that queue.
+
+Reported-by: Andreas Hartmann <andihartmann@01019freenet.de>
+Signed-off-by: Gertjan van Wingerde <gwingerde@gmail.com>
+Acked-by: Helmut Schaa <helmut.schaa@googlemail.com>
+Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Cc: Tim Gardner <tim.gardner@canonical.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+
+---
+ drivers/net/wireless/rt2x00/rt2x00queue.c | 21 ++++++++++++++++-----
+ drivers/net/wireless/rt2x00/rt2x00queue.h | 2 ++
+ 2 files changed, 18 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
+@@ -556,15 +556,21 @@ int rt2x00queue_write_tx_frame(struct da
+ bool local)
+ {
+ struct ieee80211_tx_info *tx_info;
+- struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX);
++ struct queue_entry *entry;
+ struct txentry_desc txdesc;
+ struct skb_frame_desc *skbdesc;
+ u8 rate_idx, rate_flags;
++ int ret = 0;
++
++ spin_lock(&queue->tx_lock);
++
++ entry = rt2x00queue_get_entry(queue, Q_INDEX);
+
+ if (unlikely(rt2x00queue_full(queue))) {
+ ERROR(queue->rt2x00dev,
+ "Dropping frame due to full tx queue %d.\n", queue->qid);
+- return -ENOBUFS;
++ ret = -ENOBUFS;
++ goto out;
+ }
+
+ if (unlikely(test_and_set_bit(ENTRY_OWNER_DEVICE_DATA,
+@@ -573,7 +579,8 @@ int rt2x00queue_write_tx_frame(struct da
+ "Arrived at non-free entry in the non-full queue %d.\n"
+ "Please file bug report to %s.\n",
+ queue->qid, DRV_PROJECT);
+- return -EINVAL;
++ ret = -EINVAL;
++ goto out;
+ }
+
+ /*
+@@ -635,7 +642,8 @@ int rt2x00queue_write_tx_frame(struct da
+ if (unlikely(rt2x00queue_write_tx_data(entry, &txdesc))) {
+ clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags);
+ entry->skb = NULL;
+- return -EIO;
++ ret = -EIO;
++ goto out;
+ }
+
+ set_bit(ENTRY_DATA_PENDING, &entry->flags);
+@@ -644,7 +652,9 @@ int rt2x00queue_write_tx_frame(struct da
+ rt2x00queue_write_tx_descriptor(entry, &txdesc);
+ rt2x00queue_kick_tx_queue(queue, &txdesc);
+
+- return 0;
++out:
++ spin_unlock(&queue->tx_lock);
++ return ret;
+ }
+
+ int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
+@@ -1185,6 +1195,7 @@ static void rt2x00queue_init(struct rt2x
+ struct data_queue *queue, enum data_queue_qid qid)
+ {
+ mutex_init(&queue->status_lock);
++ spin_lock_init(&queue->tx_lock);
+ spin_lock_init(&queue->index_lock);
+
+ queue->rt2x00dev = rt2x00dev;
+--- a/drivers/net/wireless/rt2x00/rt2x00queue.h
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.h
+@@ -432,6 +432,7 @@ enum data_queue_flags {
+ * @flags: Entry flags, see &enum queue_entry_flags.
+ * @status_lock: The mutex for protecting the start/stop/flush
+ * handling on this queue.
++ * @tx_lock: Spinlock to serialize tx operations on this queue.
+ * @index_lock: Spinlock to protect index handling. Whenever @index, @index_done or
+ * @index_crypt needs to be changed this lock should be grabbed to prevent
+ * index corruption due to concurrency.
+@@ -458,6 +459,7 @@ struct data_queue {
+ unsigned long flags;
+
+ struct mutex status_lock;
++ spinlock_t tx_lock;
+ spinlock_t index_lock;
+
+ unsigned int count;
diff --git a/queue-3.0/series b/queue-3.0/series
index 1592d3ddb5..dbcf9bbdcf 100644
--- a/queue-3.0/series
+++ b/queue-3.0/series
@@ -17,3 +17,4 @@ drm-radeon-kms-fix-regression-in-dp-aux-defer-handling.patch
drm-radeon-kms-add-retry-limits-for-native-dp-aux-defer.patch
drm-radeon-kms-fix-channel_remap-setup-v2.patch
ptp-fix-l2-event-message-recognition.patch
+rt2x00-serialize-tx-operations-on-a-queue.patch