From: Greg Kroah-Hartman Date: Thu, 3 Aug 2017 22:11:11 +0000 (-0700) Subject: 4.9-stable patches X-Git-Tag: v4.12.5~32 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=188c96701d7f2ea13151d19995fbd3558a3c02ea;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: drm-rcar-du-simplify-and-fix-probe-error-handling.patch net-phy-do-not-perform-software-reset-for-generic-phy.patch nfc-fdp-fix-null-pointer-dereference.patch nfc-fix-hangup-of-rc-s380-in-port100_send_ack.patch smp-hotplug-move-unparking-of-percpu-threads-to-the-control-cpu.patch smp-hotplug-replace-bug_on-and-react-useful.patch --- diff --git a/queue-4.9/drm-rcar-du-simplify-and-fix-probe-error-handling.patch b/queue-4.9/drm-rcar-du-simplify-and-fix-probe-error-handling.patch new file mode 100644 index 00000000000..9f62a5a5501 --- /dev/null +++ b/queue-4.9/drm-rcar-du-simplify-and-fix-probe-error-handling.patch @@ -0,0 +1,108 @@ +From 4f7b0d263833928e947e172eff2d2997179c5cb9 Mon Sep 17 00:00:00 2001 +From: Laurent Pinchart +Date: Wed, 19 Oct 2016 00:51:35 +0300 +Subject: drm: rcar-du: Simplify and fix probe error handling + +From: Laurent Pinchart + +commit 4f7b0d263833928e947e172eff2d2997179c5cb9 upstream. + +It isn't safe to call drm_dev_unregister() without first initializing +mode setting with drm_mode_config_init(). This leads to a crash if +either IO memory can't be remapped or vblank initialization fails. + +Fix this by reordering the initialization sequence. Move vblank +initialization after the drm_mode_config_init() call, and move IO +remapping before drm_dev_alloc() to avoid the need to perform clean up +in case of failure. + +While at it remove the explicit drm_vblank_cleanup() call from +rcar_du_remove() as the drm_dev_unregister() function already cleans up +vblank. + +Signed-off-by: Laurent Pinchart +Signed-off-by: thongsyho +Signed-off-by: Nhan Nguyen +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/gpu/drm/rcar-du/rcar_du_drv.c | 30 ++++++++++-------------------- + drivers/gpu/drm/rcar-du/rcar_du_kms.c | 7 +++++++ + 2 files changed, 17 insertions(+), 20 deletions(-) + +--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c +@@ -285,7 +285,6 @@ static int rcar_du_remove(struct platfor + + drm_kms_helper_poll_fini(ddev); + drm_mode_config_cleanup(ddev); +- drm_vblank_cleanup(ddev); + + drm_dev_unref(ddev); + +@@ -305,7 +304,7 @@ static int rcar_du_probe(struct platform + return -ENODEV; + } + +- /* Allocate and initialize the DRM and R-Car device structures. */ ++ /* Allocate and initialize the R-Car device structure. */ + rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL); + if (rcdu == NULL) + return -ENOMEM; +@@ -315,31 +314,22 @@ static int rcar_du_probe(struct platform + rcdu->dev = &pdev->dev; + rcdu->info = of_match_device(rcar_du_of_table, rcdu->dev)->data; + +- ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev); +- if (IS_ERR(ddev)) +- return PTR_ERR(ddev); +- +- rcdu->ddev = ddev; +- ddev->dev_private = rcdu; +- + platform_set_drvdata(pdev, rcdu); + + /* I/O resources */ + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); + rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem); +- if (IS_ERR(rcdu->mmio)) { +- ret = PTR_ERR(rcdu->mmio); +- goto error; +- } +- +- /* Initialize vertical blanking interrupts handling. Start with vblank +- * disabled for all CRTCs. +- */ +- ret = drm_vblank_init(ddev, (1 << rcdu->info->num_crtcs) - 1); +- if (ret < 0) +- goto error; ++ if (IS_ERR(rcdu->mmio)) ++ return PTR_ERR(rcdu->mmio); + + /* DRM/KMS objects */ ++ ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev); ++ if (IS_ERR(ddev)) ++ return PTR_ERR(ddev); ++ ++ rcdu->ddev = ddev; ++ ddev->dev_private = rcdu; ++ + ret = rcar_du_modeset_init(rcdu); + if (ret < 0) { + if (ret != -EPROBE_DEFER) +--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c ++++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c +@@ -567,6 +567,13 @@ int rcar_du_modeset_init(struct rcar_du_ + if (ret < 0) + return ret; + ++ /* Initialize vertical blanking interrupts handling. Start with vblank ++ * disabled for all CRTCs. ++ */ ++ ret = drm_vblank_init(dev, (1 << rcdu->info->num_crtcs) - 1); ++ if (ret < 0) ++ return ret; ++ + /* Initialize the groups. */ + num_groups = DIV_ROUND_UP(rcdu->num_crtcs, 2); + diff --git a/queue-4.9/net-phy-do-not-perform-software-reset-for-generic-phy.patch b/queue-4.9/net-phy-do-not-perform-software-reset-for-generic-phy.patch new file mode 100644 index 00000000000..4a78dca82e2 --- /dev/null +++ b/queue-4.9/net-phy-do-not-perform-software-reset-for-generic-phy.patch @@ -0,0 +1,55 @@ +From 0878fff1f42c18e448ab5b8b4f6a3eb32365b5b6 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Sun, 5 Mar 2017 12:34:49 -0800 +Subject: net: phy: Do not perform software reset for Generic PHY + +From: Florian Fainelli + +commit 0878fff1f42c18e448ab5b8b4f6a3eb32365b5b6 upstream. + +The Generic PHY driver is a catch-all PHY driver and it should preserve +whatever prior initialization has been done by boot loader or firmware +agents. For specific PHY device configuration it is expected that a +specialized PHY driver would take over that role. + +Resetting the generic PHY was a bad idea that has lead to several +complaints and downstream workarounds e.g: in OpenWrt/LEDE so restore +the behavior prior to 87aa9f9c61ad ("net: phy: consolidate PHY +reset in phy_init_hw()"). + +Reported-by: Felix Fietkau +Fixes: 87aa9f9c61ad ("net: phy: consolidate PHY reset in phy_init_hw()") +Signed-off-by: Florian Fainelli +Signed-off-by: David S. Miller +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/phy/phy_device.c | 2 +- + include/linux/phy.h | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +--- a/drivers/net/phy/phy_device.c ++++ b/drivers/net/phy/phy_device.c +@@ -1792,7 +1792,7 @@ static struct phy_driver genphy_driver[] + .phy_id = 0xffffffff, + .phy_id_mask = 0xffffffff, + .name = "Generic PHY", +- .soft_reset = genphy_soft_reset, ++ .soft_reset = genphy_no_soft_reset, + .config_init = genphy_config_init, + .features = PHY_GBIT_FEATURES | SUPPORTED_MII | + SUPPORTED_AUI | SUPPORTED_FIBRE | +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -799,6 +799,10 @@ int genphy_read_status(struct phy_device + int genphy_suspend(struct phy_device *phydev); + int genphy_resume(struct phy_device *phydev); + int genphy_soft_reset(struct phy_device *phydev); ++static inline int genphy_no_soft_reset(struct phy_device *phydev) ++{ ++ return 0; ++} + void phy_driver_unregister(struct phy_driver *drv); + void phy_drivers_unregister(struct phy_driver *drv, int n); + int phy_driver_register(struct phy_driver *new_driver, struct module *owner); diff --git a/queue-4.9/nfc-fdp-fix-null-pointer-dereference.patch b/queue-4.9/nfc-fdp-fix-null-pointer-dereference.patch new file mode 100644 index 00000000000..892baf3997b --- /dev/null +++ b/queue-4.9/nfc-fdp-fix-null-pointer-dereference.patch @@ -0,0 +1,42 @@ +From b6355fb3f5f40bbce165847d277e64896cab8f95 Mon Sep 17 00:00:00 2001 +From: Sudip Mukherjee +Date: Tue, 20 Dec 2016 21:09:04 +0000 +Subject: nfc: fdp: fix NULL pointer dereference + +From: Sudip Mukherjee + +commit b6355fb3f5f40bbce165847d277e64896cab8f95 upstream. + +We are checking phy after dereferencing it. We can print the debug +information after checking it. If phy is NULL then we will get a good +stack trace to tell us that we are in this irq handler. + +Signed-off-by: Sudip Mukherjee +Signed-off-by: Samuel Ortiz +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/nfc/fdp/i2c.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/nfc/fdp/i2c.c ++++ b/drivers/nfc/fdp/i2c.c +@@ -210,14 +210,14 @@ static irqreturn_t fdp_nci_i2c_irq_threa + struct sk_buff *skb; + int r; + +- client = phy->i2c_dev; +- dev_dbg(&client->dev, "%s\n", __func__); +- + if (!phy || irq != phy->i2c_dev->irq) { + WARN_ON_ONCE(1); + return IRQ_NONE; + } + ++ client = phy->i2c_dev; ++ dev_dbg(&client->dev, "%s\n", __func__); ++ + r = fdp_nci_i2c_read(phy, &skb); + + if (r == -EREMOTEIO) diff --git a/queue-4.9/nfc-fix-hangup-of-rc-s380-in-port100_send_ack.patch b/queue-4.9/nfc-fix-hangup-of-rc-s380-in-port100_send_ack.patch new file mode 100644 index 00000000000..4386099cfde --- /dev/null +++ b/queue-4.9/nfc-fix-hangup-of-rc-s380-in-port100_send_ack.patch @@ -0,0 +1,106 @@ +From 2497128133f8169b24b928852ba6eae34fc495e5 Mon Sep 17 00:00:00 2001 +From: OGAWA Hirofumi +Date: Sat, 4 Feb 2017 10:16:56 +0900 +Subject: nfc: Fix hangup of RC-S380* in port100_send_ack() + +From: OGAWA Hirofumi + +commit 2497128133f8169b24b928852ba6eae34fc495e5 upstream. + +If port100_send_ack() was called twice or more, it has race to hangup. + + port100_send_ack() port100_send_ack() + init_completion() + [...] + dev->cmd_cancel = true + /* this removes previous from completion */ + init_completion() + [...] + dev->cmd_cancel = true + wait_for_completion() + /* never be waked up */ + wait_for_completion() + +Like above race, this code is not assuming port100_send_ack() is +called twice or more. + +To fix, this checks dev->cmd_cancel to know if prior cancel is +in-flight or not. And never be remove prior task from completion by +using reinit_completion(), so this guarantees to be waked up properly +soon or later. + +Signed-off-by: OGAWA Hirofumi +Signed-off-by: Samuel Ortiz +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/nfc/port100.c | 37 ++++++++++++++++++++++++------------- + 1 file changed, 24 insertions(+), 13 deletions(-) + +--- a/drivers/nfc/port100.c ++++ b/drivers/nfc/port100.c +@@ -725,23 +725,33 @@ static int port100_submit_urb_for_ack(st + + static int port100_send_ack(struct port100 *dev) + { +- int rc; ++ int rc = 0; + + mutex_lock(&dev->out_urb_lock); + +- init_completion(&dev->cmd_cancel_done); +- +- usb_kill_urb(dev->out_urb); ++ /* ++ * If prior cancel is in-flight (dev->cmd_cancel == true), we ++ * can skip to send cancel. Then this will wait the prior ++ * cancel, or merged into the next cancel rarely if next ++ * cancel was started before waiting done. In any case, this ++ * will be waked up soon or later. ++ */ ++ if (!dev->cmd_cancel) { ++ reinit_completion(&dev->cmd_cancel_done); + +- dev->out_urb->transfer_buffer = ack_frame; +- dev->out_urb->transfer_buffer_length = sizeof(ack_frame); +- rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); ++ usb_kill_urb(dev->out_urb); + +- /* Set the cmd_cancel flag only if the URB has been successfully +- * submitted. It will be reset by the out URB completion callback +- * port100_send_complete(). +- */ +- dev->cmd_cancel = !rc; ++ dev->out_urb->transfer_buffer = ack_frame; ++ dev->out_urb->transfer_buffer_length = sizeof(ack_frame); ++ rc = usb_submit_urb(dev->out_urb, GFP_KERNEL); ++ ++ /* ++ * Set the cmd_cancel flag only if the URB has been ++ * successfully submitted. It will be reset by the out ++ * URB completion callback port100_send_complete(). ++ */ ++ dev->cmd_cancel = !rc; ++ } + + mutex_unlock(&dev->out_urb_lock); + +@@ -928,8 +938,8 @@ static void port100_send_complete(struct + struct port100 *dev = urb->context; + + if (dev->cmd_cancel) { ++ complete_all(&dev->cmd_cancel_done); + dev->cmd_cancel = false; +- complete(&dev->cmd_cancel_done); + } + + switch (urb->status) { +@@ -1543,6 +1553,7 @@ static int port100_probe(struct usb_inte + PORT100_COMM_RF_HEAD_MAX_LEN; + dev->skb_tailroom = PORT100_FRAME_TAIL_LEN; + ++ init_completion(&dev->cmd_cancel_done); + INIT_WORK(&dev->cmd_complete_work, port100_wq_cmd_complete); + + /* The first thing to do with the Port-100 is to set the command type diff --git a/queue-4.9/series b/queue-4.9/series index 449cb96cb31..62687094b67 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -20,3 +20,9 @@ kvm-ppc-book3s-hv-restore-critical-sprs-to-host-values-on-guest-exit.patch kvm-ppc-book3s-hv-save-restore-host-values-of-debug-registers.patch revert-powerpc-numa-fix-percpu-allocations-to-be-numa-aware.patch staging-comedi-comedi_fops-avoid-orphaned-proc-entry.patch +drm-rcar-du-simplify-and-fix-probe-error-handling.patch +smp-hotplug-move-unparking-of-percpu-threads-to-the-control-cpu.patch +smp-hotplug-replace-bug_on-and-react-useful.patch +nfc-fix-hangup-of-rc-s380-in-port100_send_ack.patch +nfc-fdp-fix-null-pointer-dereference.patch +net-phy-do-not-perform-software-reset-for-generic-phy.patch diff --git a/queue-4.9/smp-hotplug-move-unparking-of-percpu-threads-to-the-control-cpu.patch b/queue-4.9/smp-hotplug-move-unparking-of-percpu-threads-to-the-control-cpu.patch new file mode 100644 index 00000000000..f42708c227e --- /dev/null +++ b/queue-4.9/smp-hotplug-move-unparking-of-percpu-threads-to-the-control-cpu.patch @@ -0,0 +1,159 @@ +From 9cd4f1a4e7a858849e889a081a99adff83e08e4c Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Tue, 4 Jul 2017 22:20:23 +0200 +Subject: smp/hotplug: Move unparking of percpu threads to the control CPU + +From: Thomas Gleixner + +commit 9cd4f1a4e7a858849e889a081a99adff83e08e4c upstream. + +Vikram reported the following backtrace: + + BUG: scheduling while atomic: swapper/7/0/0x00000002 + CPU: 7 PID: 0 Comm: swapper/7 Not tainted 4.9.32-perf+ #680 + schedule + schedule_hrtimeout_range_clock + schedule_hrtimeout + wait_task_inactive + __kthread_bind_mask + __kthread_bind + __kthread_unpark + kthread_unpark + cpuhp_online_idle + cpu_startup_entry + secondary_start_kernel + +He analyzed correctly that a parked cpu hotplug thread of an offlined CPU +was still on the runqueue when the CPU came back online and tried to unpark +it. This causes the thread which invoked kthread_unpark() to call +wait_task_inactive() and subsequently schedule() with preemption disabled. +His proposed workaround was to "make sure" that a parked thread has +scheduled out when the CPU goes offline, so the situation cannot happen. + +But that's still wrong because the root cause is not the fact that the +percpu thread is still on the runqueue and neither that preemption is +disabled, which could be simply solved by enabling preemption before +calling kthread_unpark(). + +The real issue is that the calling thread is the idle task of the upcoming +CPU, which is not supposed to call anything which might sleep. The moron, +who wrote that code, missed completely that kthread_unpark() might end up +in schedule(). + +The solution is simpler than expected. The thread which controls the +hotplug operation is waiting for the CPU to call complete() on the hotplug +state completion. So the idle task of the upcoming CPU can set its state to +CPUHP_AP_ONLINE_IDLE and invoke complete(). This in turn wakes the control +task on a different CPU, which then can safely do the unpark and kick the +now unparked hotplug thread of the upcoming CPU to complete the bringup to +the final target state. + +Control CPU AP + +bringup_cpu(); + __cpu_up() ------------> + bringup_ap(); + bringup_wait_for_ap() + wait_for_completion(); + cpuhp_online_idle(); + <------------ complete(); + unpark(AP->stopper); + unpark(AP->hotplugthread); + while(1) + do_idle(); + kick(AP->hotplugthread); + wait_for_completion(); hotplug_thread() + run_online_callbacks(); + complete(); + +Fixes: 8df3e07e7f21 ("cpu/hotplug: Let upcoming cpu bring itself fully up") +Reported-by: Vikram Mulukutla +Signed-off-by: Thomas Gleixner +Acked-by: Peter Zijlstra +Cc: Sebastian Sewior +Cc: Rusty Russell +Cc: Tejun Heo +Cc: Andrew Morton +Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1707042218020.2131@nanos +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/cpu.c | 37 +++++++++++++++++++------------------ + 1 file changed, 19 insertions(+), 18 deletions(-) + +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -410,11 +410,25 @@ static int notify_online(unsigned int cp + return 0; + } + ++static void __cpuhp_kick_ap_work(struct cpuhp_cpu_state *st); ++ + static int bringup_wait_for_ap(unsigned int cpu) + { + struct cpuhp_cpu_state *st = per_cpu_ptr(&cpuhp_state, cpu); + ++ /* Wait for the CPU to reach CPUHP_AP_ONLINE_IDLE */ + wait_for_completion(&st->done); ++ BUG_ON(!cpu_online(cpu)); ++ ++ /* Unpark the stopper thread and the hotplug thread of the target cpu */ ++ stop_machine_unpark(cpu); ++ kthread_unpark(st->thread); ++ ++ /* Should we go further up ? */ ++ if (st->target > CPUHP_AP_ONLINE_IDLE) { ++ __cpuhp_kick_ap_work(st); ++ wait_for_completion(&st->done); ++ } + return st->result; + } + +@@ -437,9 +451,7 @@ static int bringup_cpu(unsigned int cpu) + cpu_notify(CPU_UP_CANCELED, cpu); + return ret; + } +- ret = bringup_wait_for_ap(cpu); +- BUG_ON(!cpu_online(cpu)); +- return ret; ++ return bringup_wait_for_ap(cpu); + } + + /* +@@ -974,31 +986,20 @@ void notify_cpu_starting(unsigned int cp + } + + /* +- * Called from the idle task. We need to set active here, so we can kick off +- * the stopper thread and unpark the smpboot threads. If the target state is +- * beyond CPUHP_AP_ONLINE_IDLE we kick cpuhp thread and let it bring up the +- * cpu further. ++ * Called from the idle task. Wake up the controlling task which brings the ++ * stopper and the hotplug thread of the upcoming CPU up and then delegates ++ * the rest of the online bringup to the hotplug thread. + */ + void cpuhp_online_idle(enum cpuhp_state state) + { + struct cpuhp_cpu_state *st = this_cpu_ptr(&cpuhp_state); +- unsigned int cpu = smp_processor_id(); + + /* Happens for the boot cpu */ + if (state != CPUHP_AP_ONLINE_IDLE) + return; + + st->state = CPUHP_AP_ONLINE_IDLE; +- +- /* Unpark the stopper thread and the hotplug thread of this cpu */ +- stop_machine_unpark(cpu); +- kthread_unpark(st->thread); +- +- /* Should we go further up ? */ +- if (st->target > CPUHP_AP_ONLINE_IDLE) +- __cpuhp_kick_ap_work(st); +- else +- complete(&st->done); ++ complete(&st->done); + } + + /* Requires cpu_add_remove_lock to be held */ diff --git a/queue-4.9/smp-hotplug-replace-bug_on-and-react-useful.patch b/queue-4.9/smp-hotplug-replace-bug_on-and-react-useful.patch new file mode 100644 index 00000000000..10c9c08d594 --- /dev/null +++ b/queue-4.9/smp-hotplug-replace-bug_on-and-react-useful.patch @@ -0,0 +1,38 @@ +From dea1d0f5f1284e3defee4b8484d9fc230686cd42 Mon Sep 17 00:00:00 2001 +From: Thomas Gleixner +Date: Tue, 11 Jul 2017 22:06:24 +0200 +Subject: smp/hotplug: Replace BUG_ON and react useful + +From: Thomas Gleixner + +commit dea1d0f5f1284e3defee4b8484d9fc230686cd42 upstream. + +The move of the unpark functions to the control thread moved the BUG_ON() +there as well. While it made some sense in the idle thread of the upcoming +CPU, it's bogus to crash the control thread on the already online CPU, +especially as the function has a return value and the callsite is prepared +to handle an error return. + +Replace it with a WARN_ON_ONCE() and return a proper error code. + +Fixes: 9cd4f1a4e7a8 ("smp/hotplug: Move unparking of percpu threads to the control CPU") +Rightfully-ranted-at-by: Linux Torvalds +Signed-off-by: Thomas Gleixner +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/cpu.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -418,7 +418,8 @@ static int bringup_wait_for_ap(unsigned + + /* Wait for the CPU to reach CPUHP_AP_ONLINE_IDLE */ + wait_for_completion(&st->done); +- BUG_ON(!cpu_online(cpu)); ++ if (WARN_ON_ONCE((!cpu_online(cpu)))) ++ return -ECANCELED; + + /* Unpark the stopper thread and the hotplug thread of the target cpu */ + stop_machine_unpark(cpu);