--- /dev/null
+From ccae0e50c16a7f7adb029c169147400d1ce9f703 Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@lwfinger.net>
+Date: Sun, 17 Feb 2013 17:01:20 +0000
+Subject: b43: Increase number of RX DMA slots
+
+From: Larry Finger <Larry.Finger@lwfinger.net>
+
+commit ccae0e50c16a7f7adb029c169147400d1ce9f703 upstream.
+
+Bastian Bittorf reported that some of the silent freezes on a Linksys WRT54G
+were due to overflow of the RX DMA ring buffer, which was created with 64
+slots. That finding reminded me that I was seeing similar crashed on a netbook,
+which also has a relatively slow processor. After increasing the number of
+slots to 128, runs on the netbook that previously failed now worked; however,
+I found that 109 slots had been used in one test. For that reason, the number
+of slots is being increased to 256.
+
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Cc: Bastian Bittorf <bittorf@bluebottle.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/b43/dma.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/b43/dma.h
++++ b/drivers/net/wireless/b43/dma.h
+@@ -169,7 +169,7 @@ struct b43_dmadesc_generic {
+
+ /* DMA engine tuning knobs */
+ #define B43_TXRING_SLOTS 256
+-#define B43_RXRING_SLOTS 64
++#define B43_RXRING_SLOTS 256
+ #define B43_DMA0_RX_FW598_BUFSIZE (B43_DMA0_RX_FW598_FO + IEEE80211_MAX_FRAME_LEN)
+ #define B43_DMA0_RX_FW351_BUFSIZE (B43_DMA0_RX_FW351_FO + IEEE80211_MAX_FRAME_LEN)
+
--- /dev/null
+From 4fa3e78be7e985ca814ce2aa0c09cbee404efcf7 Mon Sep 17 00:00:00 2001
+From: Bjorn Helgaas <bhelgaas@google.com>
+Date: Tue, 29 Jan 2013 16:44:27 -0700
+Subject: Driver core: treat unregistered bus_types as having no devices
+
+From: Bjorn Helgaas <bhelgaas@google.com>
+
+commit 4fa3e78be7e985ca814ce2aa0c09cbee404efcf7 upstream.
+
+A bus_type has a list of devices (klist_devices), but the list and the
+subsys_private structure that contains it are not initialized until the
+bus_type is registered with bus_register().
+
+The panic/reboot path has fixups that look up devices in pci_bus_type. If
+we panic before registering pci_bus_type, the bus_type exists but the list
+does not, so mach_reboot_fixups() trips over a null pointer and panics
+again:
+
+ mach_reboot_fixups
+ pci_get_device
+ ..
+ bus_find_device(&pci_bus_type, ...)
+ bus->p is NULL
+
+Joonsoo reported a problem when panicking before PCI was initialized.
+I think this patch should be sufficient to replace the patch he posted
+here: https://lkml.org/lkml/2012/12/28/75 ("[PATCH] x86, reboot: skip
+reboot_fixups in early boot phase")
+
+Reported-by: Joonsoo Kim <js1304@gmail.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/base/bus.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/base/bus.c
++++ b/drivers/base/bus.c
+@@ -293,7 +293,7 @@ int bus_for_each_dev(struct bus_type *bu
+ struct device *dev;
+ int error = 0;
+
+- if (!bus)
++ if (!bus || !bus->p)
+ return -EINVAL;
+
+ klist_iter_init_node(&bus->p->klist_devices, &i,
+@@ -327,7 +327,7 @@ struct device *bus_find_device(struct bu
+ struct klist_iter i;
+ struct device *dev;
+
+- if (!bus)
++ if (!bus || !bus->p)
+ return NULL;
+
+ klist_iter_init_node(&bus->p->klist_devices, &i,
--- /dev/null
+From 751efd8610d3d7d67b7bdf7f62646edea7365dd7 Mon Sep 17 00:00:00 2001
+From: Robin Holt <holt@sgi.com>
+Date: Fri, 22 Feb 2013 16:35:34 -0800
+Subject: mmu_notifier_unregister NULL Pointer deref and multiple ->release() callouts
+
+From: Robin Holt <holt@sgi.com>
+
+commit 751efd8610d3d7d67b7bdf7f62646edea7365dd7 upstream.
+
+There is a race condition between mmu_notifier_unregister() and
+__mmu_notifier_release().
+
+Assume two tasks, one calling mmu_notifier_unregister() as a result of a
+filp_close() ->flush() callout (task A), and the other calling
+mmu_notifier_release() from an mmput() (task B).
+
+ A B
+t1 srcu_read_lock()
+t2 if (!hlist_unhashed())
+t3 srcu_read_unlock()
+t4 srcu_read_lock()
+t5 hlist_del_init_rcu()
+t6 synchronize_srcu()
+t7 srcu_read_unlock()
+t8 hlist_del_rcu() <--- NULL pointer deref.
+
+Additionally, the list traversal in __mmu_notifier_release() is not
+protected by the by the mmu_notifier_mm->hlist_lock which can result in
+callouts to the ->release() notifier from both mmu_notifier_unregister()
+and __mmu_notifier_release().
+
+-stable suggestions:
+
+The stable trees prior to 3.7.y need commits 21a92735f660 and
+70400303ce0c cherry-picked in that order prior to cherry-picking this
+commit. The 3.7.y tree already has those two commits.
+
+Signed-off-by: Robin Holt <holt@sgi.com>
+Cc: Andrea Arcangeli <aarcange@redhat.com>
+Cc: Wanpeng Li <liwanp@linux.vnet.ibm.com>
+Cc: Xiao Guangrong <xiaoguangrong@linux.vnet.ibm.com>
+Cc: Avi Kivity <avi@redhat.com>
+Cc: Hugh Dickins <hughd@google.com>
+Cc: Marcelo Tosatti <mtosatti@redhat.com>
+Cc: Sagi Grimberg <sagig@mellanox.co.il>
+Cc: Haggai Eran <haggaie@mellanox.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ mm/mmu_notifier.c | 82 +++++++++++++++++++++++++++---------------------------
+ 1 file changed, 42 insertions(+), 40 deletions(-)
+
+--- a/mm/mmu_notifier.c
++++ b/mm/mmu_notifier.c
+@@ -37,49 +37,51 @@ static struct srcu_struct srcu;
+ void __mmu_notifier_release(struct mm_struct *mm)
+ {
+ struct mmu_notifier *mn;
+- struct hlist_node *n;
+ int id;
+
+ /*
+- * SRCU here will block mmu_notifier_unregister until
+- * ->release returns.
++ * srcu_read_lock() here will block synchronize_srcu() in
++ * mmu_notifier_unregister() until all registered
++ * ->release() callouts this function makes have
++ * returned.
+ */
+ id = srcu_read_lock(&srcu);
+- hlist_for_each_entry_rcu(mn, n, &mm->mmu_notifier_mm->list, hlist)
+- /*
+- * if ->release runs before mmu_notifier_unregister it
+- * must be handled as it's the only way for the driver
+- * to flush all existing sptes and stop the driver
+- * from establishing any more sptes before all the
+- * pages in the mm are freed.
+- */
+- if (mn->ops->release)
+- mn->ops->release(mn, mm);
+- srcu_read_unlock(&srcu, id);
+-
+ spin_lock(&mm->mmu_notifier_mm->lock);
+ while (unlikely(!hlist_empty(&mm->mmu_notifier_mm->list))) {
+ mn = hlist_entry(mm->mmu_notifier_mm->list.first,
+ struct mmu_notifier,
+ hlist);
++
+ /*
+- * We arrived before mmu_notifier_unregister so
+- * mmu_notifier_unregister will do nothing other than
+- * to wait ->release to finish and
+- * mmu_notifier_unregister to return.
++ * Unlink. This will prevent mmu_notifier_unregister()
++ * from also making the ->release() callout.
+ */
+ hlist_del_init_rcu(&mn->hlist);
++ spin_unlock(&mm->mmu_notifier_mm->lock);
++
++ /*
++ * Clear sptes. (see 'release' description in mmu_notifier.h)
++ */
++ if (mn->ops->release)
++ mn->ops->release(mn, mm);
++
++ spin_lock(&mm->mmu_notifier_mm->lock);
+ }
+ spin_unlock(&mm->mmu_notifier_mm->lock);
+
+ /*
+- * synchronize_srcu here prevents mmu_notifier_release to
+- * return to exit_mmap (which would proceed freeing all pages
+- * in the mm) until the ->release method returns, if it was
+- * invoked by mmu_notifier_unregister.
+- *
+- * The mmu_notifier_mm can't go away from under us because one
+- * mm_count is hold by exit_mmap.
++ * All callouts to ->release() which we have done are complete.
++ * Allow synchronize_srcu() in mmu_notifier_unregister() to complete
++ */
++ srcu_read_unlock(&srcu, id);
++
++ /*
++ * mmu_notifier_unregister() may have unlinked a notifier and may
++ * still be calling out to it. Additionally, other notifiers
++ * may have been active via vmtruncate() et. al. Block here
++ * to ensure that all notifier callouts for this mm have been
++ * completed and the sptes are really cleaned up before returning
++ * to exit_mmap().
+ */
+ synchronize_srcu(&srcu);
+ }
+@@ -294,31 +296,31 @@ void mmu_notifier_unregister(struct mmu_
+ {
+ BUG_ON(atomic_read(&mm->mm_count) <= 0);
+
++ spin_lock(&mm->mmu_notifier_mm->lock);
+ if (!hlist_unhashed(&mn->hlist)) {
+- /*
+- * SRCU here will force exit_mmap to wait ->release to finish
+- * before freeing the pages.
+- */
+ int id;
+
+- id = srcu_read_lock(&srcu);
+ /*
+- * exit_mmap will block in mmu_notifier_release to
+- * guarantee ->release is called before freeing the
+- * pages.
++ * Ensure we synchronize up with __mmu_notifier_release().
+ */
++ id = srcu_read_lock(&srcu);
++
++ hlist_del_rcu(&mn->hlist);
++ spin_unlock(&mm->mmu_notifier_mm->lock);
++
+ if (mn->ops->release)
+ mn->ops->release(mn, mm);
+- srcu_read_unlock(&srcu, id);
+
+- spin_lock(&mm->mmu_notifier_mm->lock);
+- hlist_del_rcu(&mn->hlist);
++ /*
++ * Allow __mmu_notifier_release() to complete.
++ */
++ srcu_read_unlock(&srcu, id);
++ } else
+ spin_unlock(&mm->mmu_notifier_mm->lock);
+- }
+
+ /*
+- * Wait any running method to finish, of course including
+- * ->release if it was run by mmu_notifier_relase instead of us.
++ * Wait for any running method to finish, including ->release() if it
++ * was run by __mmu_notifier_release() instead of us.
+ */
+ synchronize_srcu(&srcu);
+
--- /dev/null
+From 8708aac79e4572ba673d7a21e94ddca9f3abb7fc Mon Sep 17 00:00:00 2001
+From: Larry Finger <Larry.Finger@lwfinger.net>
+Date: Fri, 8 Feb 2013 12:28:18 -0600
+Subject: rtlwifi: rtl8192cu: Add new USB ID
+
+From: Larry Finger <Larry.Finger@lwfinger.net>
+
+commit 8708aac79e4572ba673d7a21e94ddca9f3abb7fc upstream.
+
+A new model of the RTL8188CUS has appeared.
+
+Reported-and-tested-by: Thomas Rosenkrantz <tom.rosary@googlemail.com>
+Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+@@ -285,6 +285,7 @@ static struct usb_device_id rtl8192c_usb
+ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817f, rtl92cu_hal_cfg)},
+ /* RTL8188CUS-VL */
+ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x818a, rtl92cu_hal_cfg)},
++ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x819a, rtl92cu_hal_cfg)},
+ /* 8188 Combo for BC4 */
+ {RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)},
+
--- /dev/null
+From bc6b89237acb3dee6af6e64e51a18255fef89cc2 Mon Sep 17 00:00:00 2001
+From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Date: Mon, 18 Feb 2013 10:29:30 +0200
+Subject: rtlwifi: usb: allocate URB control message setup_packet and data buffer separately
+
+From: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+
+commit bc6b89237acb3dee6af6e64e51a18255fef89cc2 upstream.
+
+rtlwifi allocates both setup_packet and data buffer of control message urb,
+using shared kmalloc in _usbctrl_vendorreq_async_write. Structure used for
+allocating is:
+ struct {
+ u8 data[254];
+ struct usb_ctrlrequest dr;
+ };
+
+Because 'struct usb_ctrlrequest' is __packed, setup packet is unaligned and
+DMA mapping of both 'data' and 'dr' confuses ARM/sunxi, leading to memory
+corruptions and freezes.
+
+Patch changes setup packet to be allocated separately.
+
+[v2]:
+ - Use WARN_ON_ONCE instead of WARN_ON
+
+Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/rtlwifi/usb.c | 44 +++++++++++++++++++++++--------------
+ 1 file changed, 28 insertions(+), 16 deletions(-)
+
+--- a/drivers/net/wireless/rtlwifi/usb.c
++++ b/drivers/net/wireless/rtlwifi/usb.c
+@@ -42,8 +42,12 @@
+
+ static void usbctrl_async_callback(struct urb *urb)
+ {
+- if (urb)
+- kfree(urb->context);
++ if (urb) {
++ /* free dr */
++ kfree(urb->setup_packet);
++ /* free databuf */
++ kfree(urb->transfer_buffer);
++ }
+ }
+
+ static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
+@@ -55,39 +59,47 @@ static int _usbctrl_vendorreq_async_writ
+ u8 reqtype;
+ struct usb_ctrlrequest *dr;
+ struct urb *urb;
+- struct rtl819x_async_write_data {
+- u8 data[REALTEK_USB_VENQT_MAX_BUF_SIZE];
+- struct usb_ctrlrequest dr;
+- } *buf;
++ const u16 databuf_maxlen = REALTEK_USB_VENQT_MAX_BUF_SIZE;
++ u8 *databuf;
++
++ if (WARN_ON_ONCE(len > databuf_maxlen))
++ len = databuf_maxlen;
+
+ pipe = usb_sndctrlpipe(udev, 0); /* write_out */
+ reqtype = REALTEK_USB_VENQT_WRITE;
+
+- buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
+- if (!buf)
++ dr = kmalloc(sizeof(*dr), GFP_ATOMIC);
++ if (!dr)
+ return -ENOMEM;
+
++ databuf = kmalloc(databuf_maxlen, GFP_ATOMIC);
++ if (!databuf) {
++ kfree(dr);
++ return -ENOMEM;
++ }
++
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+- kfree(buf);
++ kfree(databuf);
++ kfree(dr);
+ return -ENOMEM;
+ }
+
+- dr = &buf->dr;
+-
+ dr->bRequestType = reqtype;
+ dr->bRequest = request;
+ dr->wValue = cpu_to_le16(value);
+ dr->wIndex = cpu_to_le16(index);
+ dr->wLength = cpu_to_le16(len);
+ /* data are already in little-endian order */
+- memcpy(buf, pdata, len);
++ memcpy(databuf, pdata, len);
+ usb_fill_control_urb(urb, udev, pipe,
+- (unsigned char *)dr, buf, len,
+- usbctrl_async_callback, buf);
++ (unsigned char *)dr, databuf, len,
++ usbctrl_async_callback, NULL);
+ rc = usb_submit_urb(urb, GFP_ATOMIC);
+- if (rc < 0)
+- kfree(buf);
++ if (rc < 0) {
++ kfree(databuf);
++ kfree(dr);
++ }
+ usb_free_urb(urb);
+ return rc;
+ }
usb-serial-fix-null-pointer-dereferences-on-disconnect.patch
serial-imx-fix-recursive-locking-bug.patch
serial_core-fix-type-definition-for-port_brcm_trumanage.patch
+b43-increase-number-of-rx-dma-slots.patch
+rtlwifi-rtl8192cu-add-new-usb-id.patch
+rtlwifi-usb-allocate-urb-control-message-setup_packet-and-data-buffer-separately.patch
+tty-vt-fix-character-insertion-overflow.patch
+xen-send-spinlock-ipi-to-all-waiters.patch
+xen-close-evtchn-port-if-binding-to-irq-fails.patch
+zram-fix-deadlock-bug-in-partial-read-write.patch
+driver-core-treat-unregistered-bus_types-as-having-no-devices.patch
+mmu_notifier_unregister-null-pointer-deref-and-multiple-release-callouts.patch
--- /dev/null
+From a883b70d8e0a88278c0a1f80753b4dc99962b541 Mon Sep 17 00:00:00 2001
+From: Nicolas Pitre <nicolas.pitre@linaro.org>
+Date: Sun, 24 Feb 2013 20:06:09 -0500
+Subject: tty vt: fix character insertion overflow
+
+From: Nicolas Pitre <nicolas.pitre@linaro.org>
+
+commit a883b70d8e0a88278c0a1f80753b4dc99962b541 upstream.
+
+Commit 81732c3b2fed ("tty vt: Fix line garbage in virtual console on
+command line edition") broke insert_char() in multiple ways. Then
+commit b1a925f44a3a ("tty vt: Fix a regression in command line edition")
+partially fixed it. However, the buffer being moved is still too large
+and overflowing beyond the end of the current line, corrupting existing
+characters on the next line.
+
+Example test case:
+
+echo -e "abc\nde\x1b[A\x1b[4h \x1b[4l\x1b[B"
+
+Expected result:
+
+ab c
+de
+
+Current result:
+
+ab c
+ e
+
+Needless to say that this is very annoying when inserting words in the
+middle of paragraphs with certain text editors.
+
+Signed-off-by: Nicolas Pitre <nico@linaro.org>
+Acked-by: Jean-François Moine <moinejf@free.fr>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/vt/vt.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/tty/vt/vt.c
++++ b/drivers/tty/vt/vt.c
+@@ -539,7 +539,7 @@ static void insert_char(struct vc_data *
+ {
+ unsigned short *p = (unsigned short *) vc->vc_pos;
+
+- scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x) * 2);
++ scr_memmovew(p + nr, p, (vc->vc_cols - vc->vc_x - nr) * 2);
+ scr_memsetw(p, vc->vc_video_erase_char, nr * 2);
+ vc->vc_need_wrap = 0;
+ if (DO_UPDATE(vc))
--- /dev/null
+From e7e44e444876478d50630f57b0c31d29f6725020 Mon Sep 17 00:00:00 2001
+From: Wei Liu <wei.liu2@citrix.com>
+Date: Mon, 18 Feb 2013 14:57:58 +0000
+Subject: xen: close evtchn port if binding to irq fails
+
+From: Wei Liu <wei.liu2@citrix.com>
+
+commit e7e44e444876478d50630f57b0c31d29f6725020 upstream.
+
+Signed-off-by: Wei Liu <wei.liu2@citrix.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/xen/evtchn.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/xen/evtchn.c
++++ b/drivers/xen/evtchn.c
+@@ -269,6 +269,14 @@ static int evtchn_bind_to_user(struct pe
+ u->name, (void *)(unsigned long)port);
+ if (rc >= 0)
+ rc = evtchn_make_refcounted(port);
++ else {
++ /* bind failed, should close the port now */
++ struct evtchn_close close;
++ close.port = port;
++ if (HYPERVISOR_event_channel_op(EVTCHNOP_close, &close) != 0)
++ BUG();
++ set_port_user(port, NULL);
++ }
+
+ return rc;
+ }
+@@ -277,6 +285,8 @@ static void evtchn_unbind_from_user(stru
+ {
+ int irq = irq_from_evtchn(port);
+
++ BUG_ON(irq < 0);
++
+ unbind_from_irqhandler(irq, (void *)(unsigned long)port);
+
+ set_port_user(port, NULL);
--- /dev/null
+From 76eaca031f0af2bb303e405986f637811956a422 Mon Sep 17 00:00:00 2001
+From: Stefan Bader <stefan.bader@canonical.com>
+Date: Fri, 15 Feb 2013 09:48:52 +0100
+Subject: xen: Send spinlock IPI to all waiters
+
+From: Stefan Bader <stefan.bader@canonical.com>
+
+commit 76eaca031f0af2bb303e405986f637811956a422 upstream.
+
+There is a loophole between Xen's current implementation of
+pv-spinlocks and the scheduler. This was triggerable through
+a testcase until v3.6 changed the TLB flushing code. The
+problem potentially is still there just not observable in the
+same way.
+
+What could happen was (is):
+
+1. CPU n tries to schedule task x away and goes into a slow
+ wait for the runq lock of CPU n-# (must be one with a lower
+ number).
+2. CPU n-#, while processing softirqs, tries to balance domains
+ and goes into a slow wait for its own runq lock (for updating
+ some records). Since this is a spin_lock_irqsave in softirq
+ context, interrupts will be re-enabled for the duration of
+ the poll_irq hypercall used by Xen.
+3. Before the runq lock of CPU n-# is unlocked, CPU n-1 receives
+ an interrupt (e.g. endio) and when processing the interrupt,
+ tries to wake up task x. But that is in schedule and still
+ on_cpu, so try_to_wake_up goes into a tight loop.
+4. The runq lock of CPU n-# gets unlocked, but the message only
+ gets sent to the first waiter, which is CPU n-# and that is
+ busily stuck.
+5. CPU n-# never returns from the nested interruption to take and
+ release the lock because the scheduler uses a busy wait.
+ And CPU n never finishes the task migration because the unlock
+ notification only went to CPU n-#.
+
+To avoid this and since the unlocking code has no real sense of
+which waiter is best suited to grab the lock, just send the IPI
+to all of them. This causes the waiters to return from the hyper-
+call (those not interrupted at least) and do active spinlocking.
+
+BugLink: http://bugs.launchpad.net/bugs/1011792
+
+Acked-by: Jan Beulich <JBeulich@suse.com>
+Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
+Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/xen/spinlock.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+--- a/arch/x86/xen/spinlock.c
++++ b/arch/x86/xen/spinlock.c
+@@ -328,7 +328,6 @@ static noinline void xen_spin_unlock_slo
+ if (per_cpu(lock_spinners, cpu) == xl) {
+ ADD_STATS(released_slow_kicked, 1);
+ xen_send_IPI_one(cpu, XEN_SPIN_UNLOCK_VECTOR);
+- break;
+ }
+ }
+ }
--- /dev/null
+From 7e5a5104c6af709a8d97d5f4711e7c917761d464 Mon Sep 17 00:00:00 2001
+From: Minchan Kim <minchan@kernel.org>
+Date: Wed, 30 Jan 2013 11:41:39 +0900
+Subject: zram: Fix deadlock bug in partial read/write
+
+From: Minchan Kim <minchan@kernel.org>
+
+commit 7e5a5104c6af709a8d97d5f4711e7c917761d464 upstream.
+
+Now zram allocates new page with GFP_KERNEL in zram I/O path
+if IO is partial. Unfortunately, It may cause deadlock with
+reclaim path like below.
+
+write_page from fs
+fs_lock
+allocation(GFP_KERNEL)
+reclaim
+pageout
+ write_page from fs
+ fs_lock <-- deadlock
+
+This patch fixes it by using GFP_NOIO. In read path, we
+reorganize code flow so that kmap_atomic is called after the
+GFP_NOIO allocation.
+
+Acked-by: Jerome Marchand <jmarchand@redhat.com>
+Acked-by: Nitin Gupta <ngupta@vflare.org>
+[ penberg@kernel.org: don't use GFP_ATOMIC ]
+Signed-off-by: Pekka Enberg <penberg@kernel.org>
+Signed-off-by: Minchan Kim <minchan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/staging/zram/zram_drv.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+--- a/drivers/staging/zram/zram_drv.c
++++ b/drivers/staging/zram/zram_drv.c
+@@ -228,11 +228,12 @@ static int zram_bvec_read(struct zram *z
+ return 0;
+ }
+
+- user_mem = kmap_atomic(page);
+ if (is_partial_io(bvec))
+ /* Use a temporary buffer to decompress the page */
+- uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL);
+- else
++ uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
++
++ user_mem = kmap_atomic(page);
++ if (!is_partial_io(bvec))
+ uncmem = user_mem;
+
+ if (!uncmem) {
+@@ -279,7 +280,7 @@ static int zram_bvec_write(struct zram *
+ * This is a partial IO. We need to read the full page
+ * before to write the changes.
+ */
+- uncmem = kmalloc(PAGE_SIZE, GFP_KERNEL);
++ uncmem = kmalloc(PAGE_SIZE, GFP_NOIO);
+ if (!uncmem) {
+ pr_info("Error allocating temp memory!\n");
+ ret = -ENOMEM;