diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2011-10-05 14:04:59 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-10-05 14:04:59 -0700 |
commit | 1893af4b5725b9e8bda37278f657f4f708d9dba4 (patch) | |
tree | 362dbf0493ec7f0ba8c3b84708680aa1d791421f | |
parent | 2dd4a66a1f70048b9bea047978a860d549bdb3cd (diff) | |
download | stable-queue-1893af4b5725b9e8bda37278f657f4f708d9dba4.tar.gz |
3.0 patches
-rw-r--r-- | queue-3.0/rt2x00-serialize-tx-operations-on-a-queue.patch | 118 | ||||
-rw-r--r-- | queue-3.0/series | 1 |
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 |