]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.9-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Aug 2017 22:11:11 +0000 (15:11 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 3 Aug 2017 22:11:11 +0000 (15:11 -0700)
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

queue-4.9/drm-rcar-du-simplify-and-fix-probe-error-handling.patch [new file with mode: 0644]
queue-4.9/net-phy-do-not-perform-software-reset-for-generic-phy.patch [new file with mode: 0644]
queue-4.9/nfc-fdp-fix-null-pointer-dereference.patch [new file with mode: 0644]
queue-4.9/nfc-fix-hangup-of-rc-s380-in-port100_send_ack.patch [new file with mode: 0644]
queue-4.9/series
queue-4.9/smp-hotplug-move-unparking-of-percpu-threads-to-the-control-cpu.patch [new file with mode: 0644]
queue-4.9/smp-hotplug-replace-bug_on-and-react-useful.patch [new file with mode: 0644]

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 (file)
index 0000000..9f62a5a
--- /dev/null
@@ -0,0 +1,108 @@
+From 4f7b0d263833928e947e172eff2d2997179c5cb9 Mon Sep 17 00:00:00 2001
+From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+Date: Wed, 19 Oct 2016 00:51:35 +0300
+Subject: drm: rcar-du: Simplify and fix probe error handling
+
+From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
+
+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 <laurent.pinchart+renesas@ideasonboard.com>
+Signed-off-by: thongsyho <thong.ho.px@rvc.renesas.com>
+Signed-off-by: Nhan Nguyen <nhan.nguyen.yb@renesas.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..4a78dca
--- /dev/null
@@ -0,0 +1,55 @@
+From 0878fff1f42c18e448ab5b8b4f6a3eb32365b5b6 Mon Sep 17 00:00:00 2001
+From: Florian Fainelli <f.fainelli@gmail.com>
+Date: Sun, 5 Mar 2017 12:34:49 -0800
+Subject: net: phy: Do not perform software reset for Generic PHY
+
+From: Florian Fainelli <f.fainelli@gmail.com>
+
+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 <nbd@nbd.name>
+Fixes: 87aa9f9c61ad ("net: phy: consolidate PHY reset in phy_init_hw()")
+Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..892baf3
--- /dev/null
@@ -0,0 +1,42 @@
+From b6355fb3f5f40bbce165847d277e64896cab8f95 Mon Sep 17 00:00:00 2001
+From: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+Date: Tue, 20 Dec 2016 21:09:04 +0000
+Subject: nfc: fdp: fix NULL pointer dereference
+
+From: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
+
+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 <sudip.mukherjee@codethink.co.uk>
+Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..4386099
--- /dev/null
@@ -0,0 +1,106 @@
+From 2497128133f8169b24b928852ba6eae34fc495e5 Mon Sep 17 00:00:00 2001
+From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
+Date: Sat, 4 Feb 2017 10:16:56 +0900
+Subject: nfc: Fix hangup of RC-S380* in port100_send_ack()
+
+From: OGAWA Hirofumi <hirofumi@mail.parknet.co.jp>
+
+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 <hirofumi@mail.parknet.co.jp>
+Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
+Signed-off-by: Amit Pundir <amit.pundir@linaro.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
index 449cb96cb31dcd39831e7ce4a99e2f2fd83028ef..62687094b6779f2062bc1104189db12ff0b6abf6 100644 (file)
@@ -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 (file)
index 0000000..f42708c
--- /dev/null
@@ -0,0 +1,159 @@
+From 9cd4f1a4e7a858849e889a081a99adff83e08e4c Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 4 Jul 2017 22:20:23 +0200
+Subject: smp/hotplug: Move unparking of percpu threads to the control CPU
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+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 <markivx@codeaurora.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Peter Zijlstra <peterz@infradead.org>
+Cc: Sebastian Sewior <bigeasy@linutronix.de>
+Cc: Rusty Russell <rusty@rustcorp.com.au>
+Cc: Tejun Heo <tj@kernel.org>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Link: http://lkml.kernel.org/r/alpine.DEB.2.20.1707042218020.2131@nanos
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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 (file)
index 0000000..10c9c08
--- /dev/null
@@ -0,0 +1,38 @@
+From dea1d0f5f1284e3defee4b8484d9fc230686cd42 Mon Sep 17 00:00:00 2001
+From: Thomas Gleixner <tglx@linutronix.de>
+Date: Tue, 11 Jul 2017 22:06:24 +0200
+Subject: smp/hotplug: Replace BUG_ON and react useful
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+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 <torvalds@linux-foundation.org>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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);