From fcb4ccbb15df44dec8d354318c7eaa9488db9682 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 25 Feb 2013 09:39:58 -0800 Subject: [PATCH] 3.8-stable patches added patches: b43-increase-number-of-rx-dma-slots.patch driver-core-treat-unregistered-bus_types-as-having-no-devices.patch mmu_notifier_unregister-null-pointer-deref-and-multiple-release-callouts.patch pps-add-pps_lookup_dev-function.patch pps-fix-a-use-after-free-bug-when-unregistering-a-source.patch pps-use-pps_lookup_dev-to-reduce-ldisc-coupling.patch rtlwifi-rtl8192cu-add-new-usb-id.patch rtlwifi-rtl8192cu-fix-null-dereference-bug-when-using-new_id.patch rtlwifi-usb-allocate-urb-control-message-setup_packet-and-data-buffer-separately.patch tty-vt-fix-character-insertion-overflow.patch xen-close-evtchn-port-if-binding-to-irq-fails.patch xen-send-spinlock-ipi-to-all-waiters.patch zram-fix-deadlock-bug-in-partial-read-write.patch --- .../b43-increase-number-of-rx-dma-slots.patch | 37 ++++ ...tered-bus_types-as-having-no-devices.patch | 57 ++++++ ...-deref-and-multiple-release-callouts.patch | 180 ++++++++++++++++++ .../pps-add-pps_lookup_dev-function.patch | 125 ++++++++++++ ...free-bug-when-unregistering-a-source.patch | 80 ++++++++ ..._lookup_dev-to-reduce-ldisc-coupling.patch | 69 +++++++ .../rtlwifi-rtl8192cu-add-new-usb-id.patch | 30 +++ ...ll-dereference-bug-when-using-new_id.patch | 76 ++++++++ ...up_packet-and-data-buffer-separately.patch | 113 +++++++++++ queue-3.8/series | 13 ++ ...-vt-fix-character-insertion-overflow.patch | 53 ++++++ ...-evtchn-port-if-binding-to-irq-fails.patch | 43 +++++ ...xen-send-spinlock-ipi-to-all-waiters.patch | 63 ++++++ ...x-deadlock-bug-in-partial-read-write.patch | 63 ++++++ 14 files changed, 1002 insertions(+) create mode 100644 queue-3.8/b43-increase-number-of-rx-dma-slots.patch create mode 100644 queue-3.8/driver-core-treat-unregistered-bus_types-as-having-no-devices.patch create mode 100644 queue-3.8/mmu_notifier_unregister-null-pointer-deref-and-multiple-release-callouts.patch create mode 100644 queue-3.8/pps-add-pps_lookup_dev-function.patch create mode 100644 queue-3.8/pps-fix-a-use-after-free-bug-when-unregistering-a-source.patch create mode 100644 queue-3.8/pps-use-pps_lookup_dev-to-reduce-ldisc-coupling.patch create mode 100644 queue-3.8/rtlwifi-rtl8192cu-add-new-usb-id.patch create mode 100644 queue-3.8/rtlwifi-rtl8192cu-fix-null-dereference-bug-when-using-new_id.patch create mode 100644 queue-3.8/rtlwifi-usb-allocate-urb-control-message-setup_packet-and-data-buffer-separately.patch create mode 100644 queue-3.8/tty-vt-fix-character-insertion-overflow.patch create mode 100644 queue-3.8/xen-close-evtchn-port-if-binding-to-irq-fails.patch create mode 100644 queue-3.8/xen-send-spinlock-ipi-to-all-waiters.patch create mode 100644 queue-3.8/zram-fix-deadlock-bug-in-partial-read-write.patch diff --git a/queue-3.8/b43-increase-number-of-rx-dma-slots.patch b/queue-3.8/b43-increase-number-of-rx-dma-slots.patch new file mode 100644 index 00000000000..8300fc88462 --- /dev/null +++ b/queue-3.8/b43-increase-number-of-rx-dma-slots.patch @@ -0,0 +1,37 @@ +From ccae0e50c16a7f7adb029c169147400d1ce9f703 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Sun, 17 Feb 2013 17:01:20 +0000 +Subject: b43: Increase number of RX DMA slots + +From: Larry Finger + +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 +Cc: Bastian Bittorf +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + 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) + diff --git a/queue-3.8/driver-core-treat-unregistered-bus_types-as-having-no-devices.patch b/queue-3.8/driver-core-treat-unregistered-bus_types-as-having-no-devices.patch new file mode 100644 index 00000000000..4de81b322c3 --- /dev/null +++ b/queue-3.8/driver-core-treat-unregistered-bus_types-as-having-no-devices.patch @@ -0,0 +1,57 @@ +From 4fa3e78be7e985ca814ce2aa0c09cbee404efcf7 Mon Sep 17 00:00:00 2001 +From: Bjorn Helgaas +Date: Tue, 29 Jan 2013 16:44:27 -0700 +Subject: Driver core: treat unregistered bus_types as having no devices + +From: Bjorn Helgaas + +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 +Signed-off-by: Bjorn Helgaas +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/base/bus.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/base/bus.c ++++ b/drivers/base/bus.c +@@ -290,7 +290,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, +@@ -324,7 +324,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, diff --git a/queue-3.8/mmu_notifier_unregister-null-pointer-deref-and-multiple-release-callouts.patch b/queue-3.8/mmu_notifier_unregister-null-pointer-deref-and-multiple-release-callouts.patch new file mode 100644 index 00000000000..05d3c725386 --- /dev/null +++ b/queue-3.8/mmu_notifier_unregister-null-pointer-deref-and-multiple-release-callouts.patch @@ -0,0 +1,180 @@ +From 751efd8610d3d7d67b7bdf7f62646edea7365dd7 Mon Sep 17 00:00:00 2001 +From: Robin Holt +Date: Fri, 22 Feb 2013 16:35:34 -0800 +Subject: mmu_notifier_unregister NULL Pointer deref and multiple ->release() callouts + +From: Robin Holt + +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 +Cc: Andrea Arcangeli +Cc: Wanpeng Li +Cc: Xiao Guangrong +Cc: Avi Kivity +Cc: Hugh Dickins +Cc: Marcelo Tosatti +Cc: Sagi Grimberg +Cc: Haggai Eran +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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); + diff --git a/queue-3.8/pps-add-pps_lookup_dev-function.patch b/queue-3.8/pps-add-pps_lookup_dev-function.patch new file mode 100644 index 00000000000..ae4e0330e55 --- /dev/null +++ b/queue-3.8/pps-add-pps_lookup_dev-function.patch @@ -0,0 +1,125 @@ +From 513b032c98b4b9414aa4e9b4a315cb1bf0380101 Mon Sep 17 00:00:00 2001 +From: George Spelvin +Date: Sun, 10 Feb 2013 04:08:32 -0500 +Subject: pps: Add pps_lookup_dev() function + +From: George Spelvin + +commit 513b032c98b4b9414aa4e9b4a315cb1bf0380101 upstream. + +The PPS serial line discipline wants to attach a PPS device to a tty +without changing the tty code to add a struct pps_device * pointer. + +Since the number of PPS devices in a typical system is generally very low +(n=1 is by far the most common), it's practical to search the entire list +of allocated pps devices. (We capture the timestamp before the lookup, +so the timing isn't affected.) + +It is a bit ugly that this function, which is part of the in-kernel +PPS API, has to be in pps.c as opposed to kapi,c, but that's not +something that affects users. + +Signed-off-by: George Spelvin +Acked-by: Rodolfo Giometti +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pps/pps.c | 33 +++++++++++++++++++++++++++++++++ + include/linux/pps_kernel.h | 17 ++++++++++++++--- + 2 files changed, 47 insertions(+), 3 deletions(-) + +--- a/drivers/pps/pps.c ++++ b/drivers/pps/pps.c +@@ -352,11 +352,44 @@ free_idr: + + void pps_unregister_cdev(struct pps_device *pps) + { ++ pps->lookup_cookie = NULL; + device_destroy(pps_class, pps->dev->devt); + cdev_del(&pps->cdev); + } + + /* ++ * Look up a pps device by magic cookie. ++ * The cookie is usually a pointer to some enclosing device, but this ++ * code doesn't care; you should never be dereferencing it. ++ * ++ * This is a bit of a kludge that is currently used only by the PPS ++ * serial line discipline. It may need to be tweaked when a second user ++ * is found. ++ * ++ * There is no function interface for setting the lookup_cookie field. ++ * It's initialized to NULL when the pps device is created, and if a ++ * client wants to use it, just fill it in afterward. ++ * ++ * The cookie is automatically set to NULL in pps_unregister_source() ++ * so that it will not be used again, even if the pps device cannot ++ * be removed from the idr due to pending references holding the minor ++ * number in use. ++ */ ++struct pps_device *pps_lookup_dev(void const *cookie) ++{ ++ struct pps_device *pps; ++ unsigned id; ++ ++ rcu_read_lock(); ++ idr_for_each_entry(&pps_idr, pps, id) ++ if (cookie == pps->lookup_cookie) ++ break; ++ rcu_read_unlock(); ++ return pps; ++} ++EXPORT_SYMBOL(pps_lookup_dev); ++ ++/* + * Module stuff + */ + +--- a/include/linux/pps_kernel.h ++++ b/include/linux/pps_kernel.h +@@ -43,7 +43,7 @@ struct pps_source_info { + int event, void *data); /* PPS echo function */ + + struct module *owner; +- struct device *dev; ++ struct device *dev; /* Parent device for device_create */ + }; + + struct pps_event_time { +@@ -69,6 +69,7 @@ struct pps_device { + wait_queue_head_t queue; /* PPS event queue */ + + unsigned int id; /* PPS source unique ID */ ++ void const *lookup_cookie; /* pps_lookup_dev only */ + struct cdev cdev; + struct device *dev; + struct fasync_struct *async_queue; /* fasync method */ +@@ -82,16 +83,26 @@ struct pps_device { + extern struct device_attribute pps_attrs[]; + + /* ++ * Internal functions. ++ * ++ * These are not actually part of the exported API, but this is a ++ * convenient header file to put them in. ++ */ ++ ++extern int pps_register_cdev(struct pps_device *pps); ++extern void pps_unregister_cdev(struct pps_device *pps); ++ ++/* + * Exported functions + */ + + extern struct pps_device *pps_register_source( + struct pps_source_info *info, int default_params); + extern void pps_unregister_source(struct pps_device *pps); +-extern int pps_register_cdev(struct pps_device *pps); +-extern void pps_unregister_cdev(struct pps_device *pps); + extern void pps_event(struct pps_device *pps, + struct pps_event_time *ts, int event, void *data); ++/* Look up a pps device by magic cookie */ ++struct pps_device *pps_lookup_dev(void const *cookie); + + static inline void timespec_to_pps_ktime(struct pps_ktime *kt, + struct timespec ts) diff --git a/queue-3.8/pps-fix-a-use-after-free-bug-when-unregistering-a-source.patch b/queue-3.8/pps-fix-a-use-after-free-bug-when-unregistering-a-source.patch new file mode 100644 index 00000000000..95baae17232 --- /dev/null +++ b/queue-3.8/pps-fix-a-use-after-free-bug-when-unregistering-a-source.patch @@ -0,0 +1,80 @@ +From d953e0e837e65ecc1ddaa4f9560f7925878a0de6 Mon Sep 17 00:00:00 2001 +From: George Spelvin +Date: Tue, 12 Feb 2013 02:27:20 -0500 +Subject: pps: Fix a use-after free bug when unregistering a source. + +From: George Spelvin + +commit d953e0e837e65ecc1ddaa4f9560f7925878a0de6 upstream. + +Remove the cdev from the system (with cdev_del) *before* deallocating it +(in pps_device_destruct, called via kobject_put from device_destroy). + +Also prevent deallocating a device with open file handles. + +A better long-term fix is probably to remove the cdev from the pps_device +entirely, and instead have all devices reference one global cdev. Then +the deallocation ordering becomes simpler. + +But that's more complex and invasive change, so we leave that +for later. + +Signed-off-by: George Spelvin +Acked-by: Rodolfo Giometti +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pps/pps.c | 14 ++++++++++---- + 1 file changed, 10 insertions(+), 4 deletions(-) + +--- a/drivers/pps/pps.c ++++ b/drivers/pps/pps.c +@@ -247,12 +247,15 @@ static int pps_cdev_open(struct inode *i + struct pps_device *pps = container_of(inode->i_cdev, + struct pps_device, cdev); + file->private_data = pps; +- ++ kobject_get(&pps->dev->kobj); + return 0; + } + + static int pps_cdev_release(struct inode *inode, struct file *file) + { ++ struct pps_device *pps = container_of(inode->i_cdev, ++ struct pps_device, cdev); ++ kobject_put(&pps->dev->kobj); + return 0; + } + +@@ -274,8 +277,10 @@ static void pps_device_destruct(struct d + { + struct pps_device *pps = dev_get_drvdata(dev); + +- /* release id here to protect others from using it while it's +- * still in use */ ++ cdev_del(&pps->cdev); ++ ++ /* Now we can release the ID for re-use */ ++ pr_debug("deallocating pps%d\n", pps->id); + mutex_lock(&pps_idr_lock); + idr_remove(&pps_idr, pps->id); + mutex_unlock(&pps_idr_lock); +@@ -332,6 +337,7 @@ int pps_register_cdev(struct pps_device + goto del_cdev; + } + ++ /* Override the release function with our own */ + pps->dev->release = pps_device_destruct; + + pr_debug("source %s got cdev (%d:%d)\n", pps->info.name, +@@ -352,9 +358,9 @@ free_idr: + + void pps_unregister_cdev(struct pps_device *pps) + { ++ pr_debug("unregistering pps%d\n", pps->id); + pps->lookup_cookie = NULL; + device_destroy(pps_class, pps->dev->devt); +- cdev_del(&pps->cdev); + } + + /* diff --git a/queue-3.8/pps-use-pps_lookup_dev-to-reduce-ldisc-coupling.patch b/queue-3.8/pps-use-pps_lookup_dev-to-reduce-ldisc-coupling.patch new file mode 100644 index 00000000000..7aeabad886f --- /dev/null +++ b/queue-3.8/pps-use-pps_lookup_dev-to-reduce-ldisc-coupling.patch @@ -0,0 +1,69 @@ +From 03a7ffe4e542310838bac70ef85acc17536b6d7c Mon Sep 17 00:00:00 2001 +From: George Spelvin +Date: Sun, 10 Feb 2013 04:41:56 -0500 +Subject: pps: Use pps_lookup_dev to reduce ldisc coupling + +From: George Spelvin + +commit 03a7ffe4e542310838bac70ef85acc17536b6d7c upstream. + +Now that N_TTY uses tty->disc_data for its private data, +'subclass' ldiscs cannot use ->disc_data for their own private data. +(This is a regression is v3.8-rc1) + +Use pps_lookup_dev to associate the tty with the pps source instead. + +This fixes a crashing regression in 3.8-rc1. + +Signed-off-by: George Spelvin +Acked-by: Rodolfo Giometti +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pps/clients/pps-ldisc.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +--- a/drivers/pps/clients/pps-ldisc.c ++++ b/drivers/pps/clients/pps-ldisc.c +@@ -31,7 +31,7 @@ + static void pps_tty_dcd_change(struct tty_struct *tty, unsigned int status, + struct pps_event_time *ts) + { +- struct pps_device *pps = (struct pps_device *)tty->disc_data; ++ struct pps_device *pps = pps_lookup_dev(tty); + + BUG_ON(pps == NULL); + +@@ -67,9 +67,9 @@ static int pps_tty_open(struct tty_struc + pr_err("cannot register PPS source \"%s\"\n", info.path); + return -ENOMEM; + } +- tty->disc_data = pps; ++ pps->lookup_cookie = tty; + +- /* Should open N_TTY ldisc too */ ++ /* Now open the base class N_TTY ldisc */ + ret = alias_n_tty_open(tty); + if (ret < 0) { + pr_err("cannot open tty ldisc \"%s\"\n", info.path); +@@ -81,7 +81,6 @@ static int pps_tty_open(struct tty_struc + return 0; + + err_unregister: +- tty->disc_data = NULL; + pps_unregister_source(pps); + return ret; + } +@@ -90,11 +89,10 @@ static void (*alias_n_tty_close)(struct + + static void pps_tty_close(struct tty_struct *tty) + { +- struct pps_device *pps = (struct pps_device *)tty->disc_data; ++ struct pps_device *pps = pps_lookup_dev(tty); + + alias_n_tty_close(tty); + +- tty->disc_data = NULL; + dev_info(pps->dev, "removed\n"); + pps_unregister_source(pps); + } diff --git a/queue-3.8/rtlwifi-rtl8192cu-add-new-usb-id.patch b/queue-3.8/rtlwifi-rtl8192cu-add-new-usb-id.patch new file mode 100644 index 00000000000..20377052606 --- /dev/null +++ b/queue-3.8/rtlwifi-rtl8192cu-add-new-usb-id.patch @@ -0,0 +1,30 @@ +From 8708aac79e4572ba673d7a21e94ddca9f3abb7fc Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Fri, 8 Feb 2013 12:28:18 -0600 +Subject: rtlwifi: rtl8192cu: Add new USB ID + +From: Larry Finger + +commit 8708aac79e4572ba673d7a21e94ddca9f3abb7fc upstream. + +A new model of the RTL8188CUS has appeared. + +Reported-and-tested-by: Thomas Rosenkrantz +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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)}, + diff --git a/queue-3.8/rtlwifi-rtl8192cu-fix-null-dereference-bug-when-using-new_id.patch b/queue-3.8/rtlwifi-rtl8192cu-fix-null-dereference-bug-when-using-new_id.patch new file mode 100644 index 00000000000..d63b60070b5 --- /dev/null +++ b/queue-3.8/rtlwifi-rtl8192cu-fix-null-dereference-bug-when-using-new_id.patch @@ -0,0 +1,76 @@ +From 957f4aca5fa0db69635271bc4621cc0b65b2d590 Mon Sep 17 00:00:00 2001 +From: Larry Finger +Date: Wed, 6 Feb 2013 12:54:17 -0600 +Subject: rtlwifi: rtl8192cu: Fix NULL dereference BUG when using new_id + +From: Larry Finger + +commit 957f4aca5fa0db69635271bc4621cc0b65b2d590 upstream. + +When the new_id entry in /sysfs is used for a foreign USB device, rtlwifi +BUGS with a NULL pointer dereference because the per-driver configuration +data is not available. The probe function has been restructured as +suggested by Ben Hutchings . + +Signed-off-by: Larry Finger +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | 8 +++++++- + drivers/net/wireless/rtlwifi/usb.c | 5 +++-- + drivers/net/wireless/rtlwifi/usb.h | 3 ++- + 3 files changed, 12 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c ++++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +@@ -363,9 +363,15 @@ static struct usb_device_id rtl8192c_usb + + MODULE_DEVICE_TABLE(usb, rtl8192c_usb_ids); + ++static int rtl8192cu_probe(struct usb_interface *intf, ++ const struct usb_device_id *id) ++{ ++ return rtl_usb_probe(intf, id, &rtl92cu_hal_cfg); ++} ++ + static struct usb_driver rtl8192cu_driver = { + .name = "rtl8192cu", +- .probe = rtl_usb_probe, ++ .probe = rtl8192cu_probe, + .disconnect = rtl_usb_disconnect, + .id_table = rtl8192c_usb_ids, + +--- a/drivers/net/wireless/rtlwifi/usb.c ++++ b/drivers/net/wireless/rtlwifi/usb.c +@@ -941,7 +941,8 @@ static struct rtl_intf_ops rtl_usb_ops = + }; + + int rtl_usb_probe(struct usb_interface *intf, +- const struct usb_device_id *id) ++ const struct usb_device_id *id, ++ struct rtl_hal_cfg *rtl_hal_cfg) + { + int err; + struct ieee80211_hw *hw = NULL; +@@ -976,7 +977,7 @@ int rtl_usb_probe(struct usb_interface * + usb_set_intfdata(intf, hw); + /* init cfg & intf_ops */ + rtlpriv->rtlhal.interface = INTF_USB; +- rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_info); ++ rtlpriv->cfg = rtl_hal_cfg; + rtlpriv->intf_ops = &rtl_usb_ops; + rtl_dbgp_flag_init(hw); + /* Init IO handler */ +--- a/drivers/net/wireless/rtlwifi/usb.h ++++ b/drivers/net/wireless/rtlwifi/usb.h +@@ -157,7 +157,8 @@ struct rtl_usb_priv { + + + int rtl_usb_probe(struct usb_interface *intf, +- const struct usb_device_id *id); ++ const struct usb_device_id *id, ++ struct rtl_hal_cfg *rtl92cu_hal_cfg); + void rtl_usb_disconnect(struct usb_interface *intf); + int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message); + int rtl_usb_resume(struct usb_interface *pusb_intf); diff --git a/queue-3.8/rtlwifi-usb-allocate-urb-control-message-setup_packet-and-data-buffer-separately.patch b/queue-3.8/rtlwifi-usb-allocate-urb-control-message-setup_packet-and-data-buffer-separately.patch new file mode 100644 index 00000000000..72b63c913a6 --- /dev/null +++ b/queue-3.8/rtlwifi-usb-allocate-urb-control-message-setup_packet-and-data-buffer-separately.patch @@ -0,0 +1,113 @@ +From bc6b89237acb3dee6af6e64e51a18255fef89cc2 Mon Sep 17 00:00:00 2001 +From: Jussi Kivilinna +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 + +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 +Signed-off-by: John W. Linville +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } diff --git a/queue-3.8/series b/queue-3.8/series index b2772513b15..4cd591083cb 100644 --- a/queue-3.8/series +++ b/queue-3.8/series @@ -17,3 +17,16 @@ tty-set_termios-set_termiox-should-not-return-eintr.patch 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-fix-null-dereference-bug-when-using-new_id.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 +pps-add-pps_lookup_dev-function.patch +pps-use-pps_lookup_dev-to-reduce-ldisc-coupling.patch +pps-fix-a-use-after-free-bug-when-unregistering-a-source.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 diff --git a/queue-3.8/tty-vt-fix-character-insertion-overflow.patch b/queue-3.8/tty-vt-fix-character-insertion-overflow.patch new file mode 100644 index 00000000000..483111802ba --- /dev/null +++ b/queue-3.8/tty-vt-fix-character-insertion-overflow.patch @@ -0,0 +1,53 @@ +From a883b70d8e0a88278c0a1f80753b4dc99962b541 Mon Sep 17 00:00:00 2001 +From: Nicolas Pitre +Date: Sun, 24 Feb 2013 20:06:09 -0500 +Subject: tty vt: fix character insertion overflow + +From: Nicolas Pitre + +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 +Acked-by: Jean-François Moine +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + 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)) diff --git a/queue-3.8/xen-close-evtchn-port-if-binding-to-irq-fails.patch b/queue-3.8/xen-close-evtchn-port-if-binding-to-irq-fails.patch new file mode 100644 index 00000000000..c74e73fc732 --- /dev/null +++ b/queue-3.8/xen-close-evtchn-port-if-binding-to-irq-fails.patch @@ -0,0 +1,43 @@ +From e7e44e444876478d50630f57b0c31d29f6725020 Mon Sep 17 00:00:00 2001 +From: Wei Liu +Date: Mon, 18 Feb 2013 14:57:58 +0000 +Subject: xen: close evtchn port if binding to irq fails + +From: Wei Liu + +commit e7e44e444876478d50630f57b0c31d29f6725020 upstream. + +Signed-off-by: Wei Liu +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + 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); diff --git a/queue-3.8/xen-send-spinlock-ipi-to-all-waiters.patch b/queue-3.8/xen-send-spinlock-ipi-to-all-waiters.patch new file mode 100644 index 00000000000..d4c724b745c --- /dev/null +++ b/queue-3.8/xen-send-spinlock-ipi-to-all-waiters.patch @@ -0,0 +1,63 @@ +From 76eaca031f0af2bb303e405986f637811956a422 Mon Sep 17 00:00:00 2001 +From: Stefan Bader +Date: Fri, 15 Feb 2013 09:48:52 +0100 +Subject: xen: Send spinlock IPI to all waiters + +From: Stefan Bader + +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 +Signed-off-by: Stefan Bader +Signed-off-by: Konrad Rzeszutek Wilk +Signed-off-by: Greg Kroah-Hartman + +--- + 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; + } + } + } diff --git a/queue-3.8/zram-fix-deadlock-bug-in-partial-read-write.patch b/queue-3.8/zram-fix-deadlock-bug-in-partial-read-write.patch new file mode 100644 index 00000000000..38774a45b2a --- /dev/null +++ b/queue-3.8/zram-fix-deadlock-bug-in-partial-read-write.patch @@ -0,0 +1,63 @@ +From 7e5a5104c6af709a8d97d5f4711e7c917761d464 Mon Sep 17 00:00:00 2001 +From: Minchan Kim +Date: Wed, 30 Jan 2013 11:41:39 +0900 +Subject: zram: Fix deadlock bug in partial read/write + +From: Minchan Kim + +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 +Acked-by: Nitin Gupta +[ penberg@kernel.org: don't use GFP_ATOMIC ] +Signed-off-by: Pekka Enberg +Signed-off-by: Minchan Kim +Signed-off-by: Greg Kroah-Hartman + +--- + 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; -- 2.47.3