--- /dev/null
+From 3780d038fdf4b5ef26ead10b0604ab1f46dd9510 Mon Sep 17 00:00:00 2001
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Fri, 9 Mar 2012 12:39:54 +0100
+Subject: rt2x00: fix random stalls
+
+From: Stanislaw Gruszka <sgruszka@redhat.com>
+
+commit 3780d038fdf4b5ef26ead10b0604ab1f46dd9510 upstream.
+
+Is possible that we stop queue and then do not wake up it again,
+especially when packets are transmitted fast. That can be easily
+reproduced with modified tx queue entry_num to some small value e.g. 16.
+
+If mac80211 already hold local->queue_stop_reason_lock, then we can wait
+on that lock in both rt2x00queue_pause_queue() and
+rt2x00queue_unpause_queue(). After drooping ->queue_stop_reason_lock
+is possible that __ieee80211_wake_queue() will be performed before
+__ieee80211_stop_queue(), hence we stop queue and newer wake up it
+again.
+
+Another race condition is possible when between rt2x00queue_threshold()
+check and rt2x00queue_pause_queue() we will process all pending tx
+buffers on different cpu. This might happen if for example interrupt
+will be triggered on cpu performing rt2x00mac_tx().
+
+To prevent race conditions serialize pause/unpause by queue->tx_lock.
+
+Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+Acked-by: Gertjan van Wingerde <gwingerde@gmail.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/rt2x00/rt2x00dev.c | 6 +++++-
+ drivers/net/wireless/rt2x00/rt2x00mac.c | 9 +++++++++
+ drivers/net/wireless/rt2x00/rt2x00queue.c | 3 +++
+ 3 files changed, 17 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
++++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
+@@ -410,10 +410,14 @@ void rt2x00lib_txdone(struct queue_entry
+ /*
+ * If the data queue was below the threshold before the txdone
+ * handler we must make sure the packet queue in the mac80211 stack
+- * is reenabled when the txdone handler has finished.
++ * is reenabled when the txdone handler has finished. This has to be
++ * serialized with rt2x00mac_tx(), otherwise we can wake up queue
++ * before it was stopped.
+ */
++ spin_lock_bh(&entry->queue->tx_lock);
+ if (!rt2x00queue_threshold(entry->queue))
+ rt2x00queue_unpause_queue(entry->queue);
++ spin_unlock_bh(&entry->queue->tx_lock);
+ }
+ EXPORT_SYMBOL_GPL(rt2x00lib_txdone);
+
+--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
++++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
+@@ -152,13 +152,22 @@ void rt2x00mac_tx(struct ieee80211_hw *h
+ if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false)))
+ goto exit_fail;
+
++ /*
++ * Pausing queue has to be serialized with rt2x00lib_txdone(). Note
++ * we should not use spin_lock_bh variant as bottom halve was already
++ * disabled before ieee80211_xmit() call.
++ */
++ spin_lock(&queue->tx_lock);
+ if (rt2x00queue_threshold(queue))
+ rt2x00queue_pause_queue(queue);
++ spin_unlock(&queue->tx_lock);
+
+ return;
+
+ exit_fail:
++ spin_lock(&queue->tx_lock);
+ rt2x00queue_pause_queue(queue);
++ spin_unlock(&queue->tx_lock);
+ exit_free_skb:
+ dev_kfree_skb_any(skb);
+ }
+--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
++++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
+@@ -562,6 +562,9 @@ int rt2x00queue_write_tx_frame(struct da
+ u8 rate_idx, rate_flags;
+ int ret = 0;
+
++ /*
++ * That function must be called with bh disabled.
++ */
+ spin_lock(&queue->tx_lock);
+
+ entry = rt2x00queue_get_entry(queue, Q_INDEX);
--- /dev/null
+From 097b180ca09b581ef0dc24fbcfc1b227de3875df Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@suse.cz>
+Date: Tue, 6 Mar 2012 13:56:33 +0100
+Subject: vfs: fix double put after complete_walk()
+
+From: Miklos Szeredi <mszeredi@suse.cz>
+
+commit 097b180ca09b581ef0dc24fbcfc1b227de3875df upstream.
+
+complete_walk() already puts nd->path, no need to do it again at cleanup time.
+
+This would result in Oopses if triggered, apparently the codepath is not too
+well exercised.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/namei.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -2208,7 +2208,7 @@ static struct file *do_last(struct namei
+ /* Why this, you ask? _Now_ we might have grown LOOKUP_JUMPED... */
+ error = complete_walk(nd);
+ if (error)
+- goto exit;
++ return ERR_PTR(error);
+ error = -EISDIR;
+ if (S_ISDIR(nd->inode->i_mode))
+ goto exit;
--- /dev/null
+From 7f6c7e62fcc123e6bd9206da99a2163fe3facc31 Mon Sep 17 00:00:00 2001
+From: Miklos Szeredi <mszeredi@suse.cz>
+Date: Tue, 6 Mar 2012 13:56:34 +0100
+Subject: vfs: fix return value from do_last()
+
+From: Miklos Szeredi <mszeredi@suse.cz>
+
+commit 7f6c7e62fcc123e6bd9206da99a2163fe3facc31 upstream.
+
+complete_walk() returns either ECHILD or ESTALE. do_last() turns this into
+ECHILD unconditionally. If not in RCU mode, this error will reach userspace
+which is complete nonsense.
+
+Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/namei.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -2109,7 +2109,7 @@ static struct file *do_last(struct namei
+ /* sayonara */
+ error = complete_walk(nd);
+ if (error)
+- return ERR_PTR(-ECHILD);
++ return ERR_PTR(error);
+
+ error = -ENOTDIR;
+ if (nd->flags & LOOKUP_DIRECTORY) {