From: Greg Kroah-Hartman Date: Fri, 28 Sep 2012 00:29:57 +0000 (-0700) Subject: 3.5-stable patches X-Git-Tag: v3.0.44~16 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1ef60c79694af6166ab9aa05abdaa2e0b9f3ff0d;p=thirdparty%2Fkernel%2Fstable-queue.git 3.5-stable patches added patches: irq_remap-disable-irq-remapping-if-any-ioapic-lacks-an-iommu.patch kthread_worker-reimplement-flush_kthread_work-to-allow-freeing-the-work-item-being-executed.patch kthread_worker-reorganize-to-prepare-for-flush_kthread_work-reimplementation.patch net-qmi_wwan-add-sierra-wireless-devices.patch net-qmi_wwan-new-devices-uml290-and-k5006-z.patch nfsd-introduce-nfsd_destroy-helper.patch nfsd-set-nfsd_serv-to-null-after-service-destruction.patch usb-chipidea-cleanup-dma_pool-if-udc_start-fails.patch usb-chipidea-udc-fix-error-path-in-udc_start.patch --- diff --git a/queue-3.5/irq_remap-disable-irq-remapping-if-any-ioapic-lacks-an-iommu.patch b/queue-3.5/irq_remap-disable-irq-remapping-if-any-ioapic-lacks-an-iommu.patch new file mode 100644 index 00000000000..fef97ffdcb7 --- /dev/null +++ b/queue-3.5/irq_remap-disable-irq-remapping-if-any-ioapic-lacks-an-iommu.patch @@ -0,0 +1,69 @@ +From 32ab31e01e2def6f48294d872d9bb42573aae00f Mon Sep 17 00:00:00 2001 +From: Seth Forshee +Date: Wed, 8 Aug 2012 08:27:03 -0500 +Subject: irq_remap: disable IRQ remapping if any IOAPIC lacks an IOMMU + +From: Seth Forshee + +commit 32ab31e01e2def6f48294d872d9bb42573aae00f upstream. + +The ACPI tables in the Macbook Air 5,1 define a single IOAPIC with id 2, +but the only remapping unit described in the DMAR table matches id 0. +Interrupt remapping fails as a result, and the kernel panics with the +message "timer doesn't work through Interrupt-remapped IO-APIC." + +To fix this, check each IOAPIC for a corresponding IOMMU. If an IOMMU is +not found, do not allow IRQ remapping to be enabled. + +v2: Move check to parse_ioapics_under_ir(), raise log level to KERN_ERR, + and add FW_BUG to the log message +v3: Skip check if IOMMU doesn't support interrupt remapping and remove + existing check that the IOMMU count equals the IOAPIC count + +Acked-by: Suresh Siddha +Signed-off-by: Seth Forshee +Acked-by: Yinghai Lu +Signed-off-by: Joerg Roedel +Acked-by: Cho, Yu-Chen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/iommu/intel_irq_remapping.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +--- a/drivers/iommu/intel_irq_remapping.c ++++ b/drivers/iommu/intel_irq_remapping.c +@@ -736,6 +736,7 @@ int __init parse_ioapics_under_ir(void) + { + struct dmar_drhd_unit *drhd; + int ir_supported = 0; ++ int ioapic_idx; + + for_each_drhd_unit(drhd) { + struct intel_iommu *iommu = drhd->iommu; +@@ -748,13 +749,20 @@ int __init parse_ioapics_under_ir(void) + } + } + +- if (ir_supported && ir_ioapic_num != nr_ioapics) { +- printk(KERN_WARNING +- "Not all IO-APIC's listed under remapping hardware\n"); +- return -1; ++ if (!ir_supported) ++ return 0; ++ ++ for (ioapic_idx = 0; ioapic_idx < nr_ioapics; ioapic_idx++) { ++ int ioapic_id = mpc_ioapic_id(ioapic_idx); ++ if (!map_ioapic_to_ir(ioapic_id)) { ++ pr_err(FW_BUG "ioapic %d has no mapping iommu, " ++ "interrupt remapping will be disabled\n", ++ ioapic_id); ++ return -1; ++ } + } + +- return ir_supported; ++ return 1; + } + + int __init ir_dev_scope_init(void) diff --git a/queue-3.5/kthread_worker-reimplement-flush_kthread_work-to-allow-freeing-the-work-item-being-executed.patch b/queue-3.5/kthread_worker-reimplement-flush_kthread_work-to-allow-freeing-the-work-item-being-executed.patch new file mode 100644 index 00000000000..b055db3c833 --- /dev/null +++ b/queue-3.5/kthread_worker-reimplement-flush_kthread_work-to-allow-freeing-the-work-item-being-executed.patch @@ -0,0 +1,152 @@ +From 46f3d976213452350f9d10b0c2780c2681f7075b Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Thu, 19 Jul 2012 13:52:53 -0700 +Subject: kthread_worker: reimplement flush_kthread_work() to allow freeing the work item being executed + +From: Tejun Heo + +commit 46f3d976213452350f9d10b0c2780c2681f7075b upstream. + +kthread_worker provides minimalistic workqueue-like interface for +users which need a dedicated worker thread (e.g. for realtime +priority). It has basic queue, flush_work, flush_worker operations +which mostly match the workqueue counterparts; however, due to the way +flush_work() is implemented, it has a noticeable difference of not +allowing work items to be freed while being executed. + +While the current users of kthread_worker are okay with the current +behavior, the restriction does impede some valid use cases. Also, +removing this difference isn't difficult and actually makes the code +easier to understand. + +This patch reimplements flush_kthread_work() such that it uses a +flush_work item instead of queue/done sequence numbers. + +Signed-off-by: Tejun Heo +Cc: Colin Cross +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/kthread.h | 8 +------ + kernel/kthread.c | 52 ++++++++++++++++++++++++++---------------------- + 2 files changed, 31 insertions(+), 29 deletions(-) + +--- a/include/linux/kthread.h ++++ b/include/linux/kthread.h +@@ -49,8 +49,6 @@ extern int tsk_fork_get_node(struct task + * can be queued and flushed using queue/flush_kthread_work() + * respectively. Queued kthread_works are processed by a kthread + * running kthread_worker_fn(). +- * +- * A kthread_work can't be freed while it is executing. + */ + struct kthread_work; + typedef void (*kthread_work_func_t)(struct kthread_work *work); +@@ -59,15 +57,14 @@ struct kthread_worker { + spinlock_t lock; + struct list_head work_list; + struct task_struct *task; ++ struct kthread_work *current_work; + }; + + struct kthread_work { + struct list_head node; + kthread_work_func_t func; + wait_queue_head_t done; +- atomic_t flushing; +- int queue_seq; +- int done_seq; ++ struct kthread_worker *worker; + }; + + #define KTHREAD_WORKER_INIT(worker) { \ +@@ -79,7 +76,6 @@ struct kthread_work { + .node = LIST_HEAD_INIT((work).node), \ + .func = (fn), \ + .done = __WAIT_QUEUE_HEAD_INITIALIZER((work).done), \ +- .flushing = ATOMIC_INIT(0), \ + } + + #define DEFINE_KTHREAD_WORKER(worker) \ +--- a/kernel/kthread.c ++++ b/kernel/kthread.c +@@ -360,16 +360,12 @@ repeat: + struct kthread_work, node); + list_del_init(&work->node); + } ++ worker->current_work = work; + spin_unlock_irq(&worker->lock); + + if (work) { + __set_current_state(TASK_RUNNING); + work->func(work); +- smp_wmb(); /* wmb worker-b0 paired with flush-b1 */ +- work->done_seq = work->queue_seq; +- smp_mb(); /* mb worker-b1 paired with flush-b0 */ +- if (atomic_read(&work->flushing)) +- wake_up_all(&work->done); + } else if (!freezing(current)) + schedule(); + +@@ -386,7 +382,7 @@ static void insert_kthread_work(struct k + lockdep_assert_held(&worker->lock); + + list_add_tail(&work->node, pos); +- work->queue_seq++; ++ work->worker = worker; + if (likely(worker->task)) + wake_up_process(worker->task); + } +@@ -436,25 +432,35 @@ static void kthread_flush_work_fn(struct + */ + void flush_kthread_work(struct kthread_work *work) + { +- int seq = work->queue_seq; ++ struct kthread_flush_work fwork = { ++ KTHREAD_WORK_INIT(fwork.work, kthread_flush_work_fn), ++ COMPLETION_INITIALIZER_ONSTACK(fwork.done), ++ }; ++ struct kthread_worker *worker; ++ bool noop = false; ++ ++retry: ++ worker = work->worker; ++ if (!worker) ++ return; ++ ++ spin_lock_irq(&worker->lock); ++ if (work->worker != worker) { ++ spin_unlock_irq(&worker->lock); ++ goto retry; ++ } ++ ++ if (!list_empty(&work->node)) ++ insert_kthread_work(worker, &fwork.work, work->node.next); ++ else if (worker->current_work == work) ++ insert_kthread_work(worker, &fwork.work, worker->work_list.next); ++ else ++ noop = true; + +- atomic_inc(&work->flushing); ++ spin_unlock_irq(&worker->lock); + +- /* +- * mb flush-b0 paired with worker-b1, to make sure either +- * worker sees the above increment or we see done_seq update. +- */ +- smp_mb__after_atomic_inc(); +- +- /* A - B <= 0 tests whether B is in front of A regardless of overflow */ +- wait_event(work->done, seq - work->done_seq <= 0); +- atomic_dec(&work->flushing); +- +- /* +- * rmb flush-b1 paired with worker-b0, to make sure our caller +- * sees every change made by work->func(). +- */ +- smp_mb__after_atomic_dec(); ++ if (!noop) ++ wait_for_completion(&fwork.done); + } + EXPORT_SYMBOL_GPL(flush_kthread_work); + diff --git a/queue-3.5/kthread_worker-reorganize-to-prepare-for-flush_kthread_work-reimplementation.patch b/queue-3.5/kthread_worker-reorganize-to-prepare-for-flush_kthread_work-reimplementation.patch new file mode 100644 index 00000000000..1e6c38bb54a --- /dev/null +++ b/queue-3.5/kthread_worker-reorganize-to-prepare-for-flush_kthread_work-reimplementation.patch @@ -0,0 +1,100 @@ +From 9a2e03d8ed518a61154f18d83d6466628e519f94 Mon Sep 17 00:00:00 2001 +From: Tejun Heo +Date: Thu, 19 Jul 2012 13:52:53 -0700 +Subject: kthread_worker: reorganize to prepare for flush_kthread_work() reimplementation + +From: Tejun Heo + +commit 9a2e03d8ed518a61154f18d83d6466628e519f94 upstream. + +Make the following two non-functional changes. + +* Separate out insert_kthread_work() from queue_kthread_work(). + +* Relocate struct kthread_flush_work and kthread_flush_work_fn() + definitions above flush_kthread_work(). + +v2: Added lockdep_assert_held() in insert_kthread_work() as suggested + by Andy Walls. + +Signed-off-by: Tejun Heo +Acked-by: Andy Walls +Cc: Colin Cross +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/kthread.c | 42 ++++++++++++++++++++++++++---------------- + 1 file changed, 26 insertions(+), 16 deletions(-) + +--- a/kernel/kthread.c ++++ b/kernel/kthread.c +@@ -378,6 +378,19 @@ repeat: + } + EXPORT_SYMBOL_GPL(kthread_worker_fn); + ++/* insert @work before @pos in @worker */ ++static void insert_kthread_work(struct kthread_worker *worker, ++ struct kthread_work *work, ++ struct list_head *pos) ++{ ++ lockdep_assert_held(&worker->lock); ++ ++ list_add_tail(&work->node, pos); ++ work->queue_seq++; ++ if (likely(worker->task)) ++ wake_up_process(worker->task); ++} ++ + /** + * queue_kthread_work - queue a kthread_work + * @worker: target kthread_worker +@@ -395,10 +408,7 @@ bool queue_kthread_work(struct kthread_w + + spin_lock_irqsave(&worker->lock, flags); + if (list_empty(&work->node)) { +- list_add_tail(&work->node, &worker->work_list); +- work->queue_seq++; +- if (likely(worker->task)) +- wake_up_process(worker->task); ++ insert_kthread_work(worker, work, &worker->work_list); + ret = true; + } + spin_unlock_irqrestore(&worker->lock, flags); +@@ -406,6 +416,18 @@ bool queue_kthread_work(struct kthread_w + } + EXPORT_SYMBOL_GPL(queue_kthread_work); + ++struct kthread_flush_work { ++ struct kthread_work work; ++ struct completion done; ++}; ++ ++static void kthread_flush_work_fn(struct kthread_work *work) ++{ ++ struct kthread_flush_work *fwork = ++ container_of(work, struct kthread_flush_work, work); ++ complete(&fwork->done); ++} ++ + /** + * flush_kthread_work - flush a kthread_work + * @work: work to flush +@@ -436,18 +458,6 @@ void flush_kthread_work(struct kthread_w + } + EXPORT_SYMBOL_GPL(flush_kthread_work); + +-struct kthread_flush_work { +- struct kthread_work work; +- struct completion done; +-}; +- +-static void kthread_flush_work_fn(struct kthread_work *work) +-{ +- struct kthread_flush_work *fwork = +- container_of(work, struct kthread_flush_work, work); +- complete(&fwork->done); +-} +- + /** + * flush_kthread_worker - flush all current works on a kthread_worker + * @worker: worker to flush diff --git a/queue-3.5/net-qmi_wwan-add-sierra-wireless-devices.patch b/queue-3.5/net-qmi_wwan-add-sierra-wireless-devices.patch new file mode 100644 index 00000000000..4e58e881e9e --- /dev/null +++ b/queue-3.5/net-qmi_wwan-add-sierra-wireless-devices.patch @@ -0,0 +1,107 @@ +From bjorn@mork.no Thu Sep 27 16:54:06 2012 +From: Bjørn Mork +Date: Thu, 23 Aug 2012 12:13:57 +0200 +Subject: net: qmi_wwan: add Sierra Wireless devices +To: stable@vger.kernel.org +Cc: Bjørn Mork , David Miller +Message-ID: <1345716838-24023-7-git-send-email-bjorn@mork.no> + +From: Bjørn Mork + +commit 9b469a60d68b13c288d5c3fc23de29d9d482dbe6 upstream. + +Add 6 new devices and one modified device, based on +information from laptop vendor Windows drivers. + +Sony provides a driver with two new devices using +a Gobi 2k+ layout (1199:68a5 and 1199:68a9). The +Sony driver also adds a non-standard QMI/net +interface to the already supported 1199:9011 +Gobi device. We do not know whether this is an +alternate interface number or an additional +interface which might be present, but that doesn't +really matter. + +Lenovo provides a driver supporting 4 new devices: + - MC7770 (1199:901b) with standard Gobi 2k+ layout + - MC7700 (0f3d:68a2) with layout similar to MC7710 + - MC7750 (114f:68a2) with layout similar to MC7710 + - EM7700 (1199:901c) with layout similar to MC7710 + +Note regaring the three devices similar to MC7710: + +The Windows drivers only support interface #8 on these +devices. The MC7710 can support QMI/net functions on +interface #19 and #20 as well, and this driver is +verified to work on interface #19 (a firmware bug is +suspected to prevent #20 from working). + +We do not enable these additional interfaces until they +either show up in a Windows driver or are verified to +work in some other way. Therefore limiting the new +devices to interface #8 for now. + +[bmork: backported to 3.4: use driver whitelisting] +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- +for stable: v3.4 and v3.5 + + drivers/net/usb/qmi_wwan.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -534,6 +534,33 @@ static const struct usb_device_id produc + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_sierra, + }, ++ { /* Sierra Wireless MC7700 */ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x0f3d, ++ .idProduct = 0x68a2, ++ .bInterfaceClass = 0xff, ++ .bInterfaceSubClass = 0xff, ++ .bInterfaceProtocol = 0xff, ++ .driver_info = (unsigned long)&qmi_wwan_sierra, ++ }, ++ { /* Sierra Wireless MC7750 */ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x114f, ++ .idProduct = 0x68a2, ++ .bInterfaceClass = 0xff, ++ .bInterfaceSubClass = 0xff, ++ .bInterfaceProtocol = 0xff, ++ .driver_info = (unsigned long)&qmi_wwan_sierra, ++ }, ++ { /* Sierra Wireless EM7700 */ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x1199, ++ .idProduct = 0x901c, ++ .bInterfaceClass = 0xff, ++ .bInterfaceSubClass = 0xff, ++ .bInterfaceProtocol = 0xff, ++ .driver_info = (unsigned long)&qmi_wwan_sierra, ++ }, + + /* Gobi 1000 devices */ + {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ +@@ -561,6 +588,8 @@ static const struct usb_device_id produc + {QMI_GOBI_DEVICE(0x05c6, 0x9265)}, /* Asus Gobi 2000 Modem device (VR305) */ + {QMI_GOBI_DEVICE(0x05c6, 0x9235)}, /* Top Global Gobi 2000 Modem device (VR306) */ + {QMI_GOBI_DEVICE(0x05c6, 0x9275)}, /* iRex Technologies Gobi 2000 Modem device (VR307) */ ++ {QMI_GOBI_DEVICE(0x1199, 0x68a5)}, /* Sierra Wireless Modem */ ++ {QMI_GOBI_DEVICE(0x1199, 0x68a9)}, /* Sierra Wireless Modem */ + {QMI_GOBI_DEVICE(0x1199, 0x9001)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9002)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ + {QMI_GOBI_DEVICE(0x1199, 0x9003)}, /* Sierra Wireless Gobi 2000 Modem device (VT773) */ +@@ -577,6 +606,8 @@ static const struct usb_device_id produc + {QMI_GOBI_DEVICE(0x1199, 0x9013)}, /* Sierra Wireless Gobi 3000 Modem device (MC8355) */ + {QMI_GOBI_DEVICE(0x1199, 0x9015)}, /* Sierra Wireless Gobi 3000 Modem device */ + {QMI_GOBI_DEVICE(0x1199, 0x9019)}, /* Sierra Wireless Gobi 3000 Modem device */ ++ {QMI_GOBI_DEVICE(0x1199, 0x901b)}, /* Sierra Wireless MC7770 */ ++ + { } /* END */ + }; + MODULE_DEVICE_TABLE(usb, products); diff --git a/queue-3.5/net-qmi_wwan-new-devices-uml290-and-k5006-z.patch b/queue-3.5/net-qmi_wwan-new-devices-uml290-and-k5006-z.patch new file mode 100644 index 00000000000..8ad97e9ab9d --- /dev/null +++ b/queue-3.5/net-qmi_wwan-new-devices-uml290-and-k5006-z.patch @@ -0,0 +1,64 @@ +From bjorn@mork.no Thu Sep 27 16:55:03 2012 +From: Bjørn Mork +Date: Thu, 23 Aug 2012 12:13:58 +0200 +Subject: net: qmi_wwan: new devices: UML290 and K5006-Z +To: stable@vger.kernel.org +Cc: Bjørn Mork , David Miller , Dan Williams , Thomas Schäfer +Message-ID: <1345716838-24023-8-git-send-email-bjorn@mork.no> + +From: Bjørn Mork + +commit 10cbc1d97a7c7f9ae862fffe27b771ef0da9c461 upstream. + +Newer firmware versions for the Pantech UML290 use a different +subclass ID. The Windows driver match on both IDs, so we do +that as well. + +The ZTE (Vodafone) K5006-Z is a new device. + +Cc: Dan Williams +Cc: Thomas Schäfer +[bmork: backported to 3.4: use driver whitelisting] +Signed-off-by: Bjørn Mork +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- +for stable: v3.4 and v3.5 + + drivers/net/usb/qmi_wwan.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/drivers/net/usb/qmi_wwan.c ++++ b/drivers/net/usb/qmi_wwan.c +@@ -444,6 +444,15 @@ static const struct usb_device_id produc + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_shared, + }, ++ { /* Pantech UML290 - newer firmware */ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x106c, ++ .idProduct = 0x3718, ++ .bInterfaceClass = 0xff, ++ .bInterfaceSubClass = 0xf1, ++ .bInterfaceProtocol = 0xff, ++ .driver_info = (unsigned long)&qmi_wwan_shared, ++ }, + { /* ZTE MF820D */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, +@@ -516,6 +525,15 @@ static const struct usb_device_id produc + .bInterfaceProtocol = 0xff, + .driver_info = (unsigned long)&qmi_wwan_force_int4, + }, ++ { /* ZTE (Vodafone) K5006-Z */ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, ++ .idVendor = 0x19d2, ++ .idProduct = 0x1018, ++ .bInterfaceClass = 0xff, ++ .bInterfaceSubClass = 0xff, ++ .bInterfaceProtocol = 0xff, ++ .driver_info = (unsigned long)&qmi_wwan_force_int3, ++ }, + { /* ZTE MF60 */ + .match_flags = USB_DEVICE_ID_MATCH_DEVICE | USB_DEVICE_ID_MATCH_INT_INFO, + .idVendor = 0x19d2, diff --git a/queue-3.5/nfsd-introduce-nfsd_destroy-helper.patch b/queue-3.5/nfsd-introduce-nfsd_destroy-helper.patch new file mode 100644 index 00000000000..4bc151e487a --- /dev/null +++ b/queue-3.5/nfsd-introduce-nfsd_destroy-helper.patch @@ -0,0 +1,98 @@ +From 19f7e2ca44dfc3c1b3f499fc46801f98d403500f Mon Sep 17 00:00:00 2001 +From: Stanislav Kinsbursky +Date: Tue, 3 Jul 2012 16:46:41 +0400 +Subject: NFSd: introduce nfsd_destroy() helper + +From: Stanislav Kinsbursky + +commit 19f7e2ca44dfc3c1b3f499fc46801f98d403500f upstream. + +Signed-off-by: Stanislav Kinsbursky +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfsctl.c | 8 ++------ + fs/nfsd/nfsd.h | 9 +++++++++ + fs/nfsd/nfssvc.c | 14 +++----------- + 3 files changed, 14 insertions(+), 17 deletions(-) + +--- a/fs/nfsd/nfsctl.c ++++ b/fs/nfsd/nfsctl.c +@@ -673,9 +673,7 @@ static ssize_t __write_ports_addfd(char + + err = svc_addsock(nfsd_serv, fd, buf, SIMPLE_TRANSACTION_LIMIT); + if (err < 0) { +- if (nfsd_serv->sv_nrthreads == 1) +- svc_shutdown_net(nfsd_serv, net); +- svc_destroy(nfsd_serv); ++ nfsd_destroy(net); + return err; + } + +@@ -744,9 +742,7 @@ out_close: + svc_xprt_put(xprt); + } + out_err: +- if (nfsd_serv->sv_nrthreads == 1) +- svc_shutdown_net(nfsd_serv, net); +- svc_destroy(nfsd_serv); ++ nfsd_destroy(net); + return err; + } + +--- a/fs/nfsd/nfsd.h ++++ b/fs/nfsd/nfsd.h +@@ -73,6 +73,15 @@ int nfsd_nrpools(void); + int nfsd_get_nrthreads(int n, int *); + int nfsd_set_nrthreads(int n, int *); + ++static inline void nfsd_destroy(struct net *net) ++{ ++ int destroy = (nfsd_serv->sv_nrthreads == 1); ++ ++ if (destroy) ++ svc_shutdown_net(nfsd_serv, net); ++ svc_destroy(nfsd_serv); ++} ++ + #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) + #ifdef CONFIG_NFSD_V2_ACL + extern struct svc_version nfsd_acl_version2; +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -427,11 +427,7 @@ int nfsd_set_nrthreads(int n, int *nthre + if (err) + break; + } +- +- if (nfsd_serv->sv_nrthreads == 1) +- svc_shutdown_net(nfsd_serv, net); +- svc_destroy(nfsd_serv); +- ++ nfsd_destroy(net); + return err; + } + +@@ -478,9 +474,7 @@ out_shutdown: + if (error < 0 && !nfsd_up_before) + nfsd_shutdown(); + out_destroy: +- if (nfsd_serv->sv_nrthreads == 1) +- svc_shutdown_net(nfsd_serv, net); +- svc_destroy(nfsd_serv); /* Release server */ ++ nfsd_destroy(net); /* Release server */ + out: + mutex_unlock(&nfsd_mutex); + return error; +@@ -682,9 +676,7 @@ int nfsd_pool_stats_release(struct inode + + mutex_lock(&nfsd_mutex); + /* this function really, really should have been called svc_put() */ +- if (nfsd_serv->sv_nrthreads == 1) +- svc_shutdown_net(nfsd_serv, net); +- svc_destroy(nfsd_serv); ++ nfsd_destroy(net); + mutex_unlock(&nfsd_mutex); + return ret; + } diff --git a/queue-3.5/nfsd-set-nfsd_serv-to-null-after-service-destruction.patch b/queue-3.5/nfsd-set-nfsd_serv-to-null-after-service-destruction.patch new file mode 100644 index 00000000000..e16ce37338b --- /dev/null +++ b/queue-3.5/nfsd-set-nfsd_serv-to-null-after-service-destruction.patch @@ -0,0 +1,82 @@ +From 57c8b13e3cd0f94944c9691ce7f58e5fcef8a12d Mon Sep 17 00:00:00 2001 +From: Stanislav Kinsbursky +Date: Tue, 3 Jul 2012 16:46:41 +0400 +Subject: NFSd: set nfsd_serv to NULL after service destruction + +From: Stanislav Kinsbursky + +commit 57c8b13e3cd0f94944c9691ce7f58e5fcef8a12d upstream. + +In nfsd_destroy(): + + if (destroy) + svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_server); + +svc_shutdown_net(nfsd_serv, net) calls nfsd_last_thread(), which sets +nfsd_serv to NULL, causing a NULL dereference on the following line. + +Signed-off-by: Stanislav Kinsbursky +Signed-off-by: J. Bruce Fields +Signed-off-by: Greg Kroah-Hartman + +--- + fs/nfsd/nfsd.h | 2 ++ + fs/nfsd/nfssvc.c | 10 +++++----- + 2 files changed, 7 insertions(+), 5 deletions(-) + +--- a/fs/nfsd/nfsd.h ++++ b/fs/nfsd/nfsd.h +@@ -80,6 +80,8 @@ static inline void nfsd_destroy(struct n + if (destroy) + svc_shutdown_net(nfsd_serv, net); + svc_destroy(nfsd_serv); ++ if (destroy) ++ nfsd_serv = NULL; + } + + #if defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) +--- a/fs/nfsd/nfssvc.c ++++ b/fs/nfsd/nfssvc.c +@@ -254,8 +254,6 @@ static void nfsd_shutdown(void) + + static void nfsd_last_thread(struct svc_serv *serv, struct net *net) + { +- /* When last nfsd thread exits we need to do some clean-up */ +- nfsd_serv = NULL; + nfsd_shutdown(); + + svc_rpcb_cleanup(serv, net); +@@ -332,6 +330,7 @@ static int nfsd_get_default_max_blksize( + int nfsd_create_serv(void) + { + int error; ++ struct net *net = current->nsproxy->net_ns; + + WARN_ON(!mutex_is_locked(&nfsd_mutex)); + if (nfsd_serv) { +@@ -346,7 +345,7 @@ int nfsd_create_serv(void) + if (nfsd_serv == NULL) + return -ENOMEM; + +- error = svc_bind(nfsd_serv, current->nsproxy->net_ns); ++ error = svc_bind(nfsd_serv, net); + if (error < 0) { + svc_destroy(nfsd_serv); + return error; +@@ -557,12 +556,13 @@ nfsd(void *vrqstp) + nfsdstats.th_cnt --; + + out: +- if (rqstp->rq_server->sv_nrthreads == 1) +- svc_shutdown_net(rqstp->rq_server, &init_net); ++ rqstp->rq_server = NULL; + + /* Release the thread */ + svc_exit_thread(rqstp); + ++ nfsd_destroy(&init_net); ++ + /* Release module */ + mutex_unlock(&nfsd_mutex); + module_put_and_exit(0); diff --git a/queue-3.5/series b/queue-3.5/series index d776b31098a..76ad686c1b3 100644 --- a/queue-3.5/series +++ b/queue-3.5/series @@ -242,3 +242,12 @@ i2c-powermac-improve-detection-of-devices-from-device-tree.patch sound-aoa-adapt-to-new-i2c-probing-scheme.patch nfs-fix-oopses-in-nfs_lookup_revalidate-and-nfs4_lookup_revalidate.patch net-qmi_wwan-add-zte-mf821d.patch +net-qmi_wwan-add-sierra-wireless-devices.patch +net-qmi_wwan-new-devices-uml290-and-k5006-z.patch +irq_remap-disable-irq-remapping-if-any-ioapic-lacks-an-iommu.patch +nfsd-introduce-nfsd_destroy-helper.patch +nfsd-set-nfsd_serv-to-null-after-service-destruction.patch +kthread_worker-reorganize-to-prepare-for-flush_kthread_work-reimplementation.patch +kthread_worker-reimplement-flush_kthread_work-to-allow-freeing-the-work-item-being-executed.patch +usb-chipidea-udc-fix-error-path-in-udc_start.patch +usb-chipidea-cleanup-dma_pool-if-udc_start-fails.patch diff --git a/queue-3.5/usb-chipidea-cleanup-dma_pool-if-udc_start-fails.patch b/queue-3.5/usb-chipidea-cleanup-dma_pool-if-udc_start-fails.patch new file mode 100644 index 00000000000..446c0774e0d --- /dev/null +++ b/queue-3.5/usb-chipidea-cleanup-dma_pool-if-udc_start-fails.patch @@ -0,0 +1,83 @@ +From ad6b1b97fe8504957d017cd6e4168cac8903d3f3 Mon Sep 17 00:00:00 2001 +From: Marc Kleine-Budde +Date: Wed, 12 Sep 2012 14:58:03 +0300 +Subject: usb: chipidea: cleanup dma_pool if udc_start() fails + +From: Marc Kleine-Budde + +commit ad6b1b97fe8504957d017cd6e4168cac8903d3f3 upstream. + +If udc_start() fails the qh_pool dma-pool cannot be closed because +it's still in use. This patch factors out the dma_pool_free() loop +into destroy_eps() and calls it in the error path of udc_start(), +too. + +Reviewed-by: Richard Zhao +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Alexander Shishkin +Signed-off-by: Greg Kroah-Hartman +[mkl: backport to v3.5] +Signed-off-by: Marc Kleine-Budde + +--- + drivers/usb/chipidea/udc.c | 23 +++++++++++++++-------- + 1 file changed, 15 insertions(+), 8 deletions(-) + +--- a/drivers/usb/chipidea/udc.c ++++ b/drivers/usb/chipidea/udc.c +@@ -1500,6 +1500,17 @@ static int init_eps(struct ci13xxx *udc) + return retval; + } + ++static void destroy_eps(struct ci13xxx *udc) ++{ ++ int i; ++ ++ for (i = 0; i < udc->hw_ep_max; i++) { ++ struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; ++ ++ dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma); ++ } ++} ++ + /** + * ci13xxx_start: register a gadget driver + * @gadget: our gadget +@@ -1709,7 +1720,7 @@ static int udc_start(struct ci13xxx *udc + if (udc->udc_driver->flags & CI13XXX_REQUIRE_TRANSCEIVER) { + if (udc->transceiver == NULL) { + retval = -ENODEV; +- goto free_pools; ++ goto destroy_eps; + } + } + +@@ -1759,6 +1770,8 @@ unreg_device: + put_transceiver: + if (udc->transceiver) + usb_put_transceiver(udc->transceiver); ++destroy_eps: ++ destroy_eps(udc); + free_pools: + dma_pool_destroy(udc->td_pool); + free_qh_pool: +@@ -1773,18 +1786,12 @@ free_qh_pool: + */ + static void udc_stop(struct ci13xxx *udc) + { +- int i; +- + if (udc == NULL) + return; + + usb_del_gadget_udc(&udc->gadget); + +- for (i = 0; i < udc->hw_ep_max; i++) { +- struct ci13xxx_ep *mEp = &udc->ci13xxx_ep[i]; +- +- dma_pool_free(udc->qh_pool, mEp->qh.ptr, mEp->qh.dma); +- } ++ destroy_eps(udc); + + dma_pool_destroy(udc->td_pool); + dma_pool_destroy(udc->qh_pool); diff --git a/queue-3.5/usb-chipidea-udc-fix-error-path-in-udc_start.patch b/queue-3.5/usb-chipidea-udc-fix-error-path-in-udc_start.patch new file mode 100644 index 00000000000..6796f705e53 --- /dev/null +++ b/queue-3.5/usb-chipidea-udc-fix-error-path-in-udc_start.patch @@ -0,0 +1,33 @@ +From c9d1f947a85e38b6dded469470c95ed62430cb3f Mon Sep 17 00:00:00 2001 +From: Marc Kleine-Budde +Date: Wed, 12 Sep 2012 14:58:02 +0300 +Subject: usb: chipidea: udc: fix error path in udc_start() + +From: Marc Kleine-Budde + +commit c9d1f947a85e38b6dded469470c95ed62430cb3f upstream. + +This patch fixes the error path of udc_start(). Now NULL is used to +unset the peripheral with otg_set_peripheral(). + +Cc: stable +Reviewed-by: Richard Zhao +Signed-off-by: Marc Kleine-Budde +Signed-off-by: Alexander Shishkin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/chipidea/udc.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/chipidea/udc.c ++++ b/drivers/usb/chipidea/udc.c +@@ -1747,7 +1747,7 @@ static int udc_start(struct ci13xxx *udc + + remove_trans: + if (udc->transceiver) { +- otg_set_peripheral(udc->transceiver->otg, &udc->gadget); ++ otg_set_peripheral(udc->transceiver->otg, NULL); + usb_put_transceiver(udc->transceiver); + } +