aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Syrjälä <ville.syrjala@linux.intel.com>2017-11-07 16:08:10 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2017-11-08 17:02:43 -0500
commitff1656790b3a4caca94505c52fd0250f981ea187 (patch)
tree82938b2c4652d44bf3662509da8532ff8750ee0d
parenta192aa923b66a435aae56983c4912ee150bc9b32 (diff)
ACPI / PM: Fix acpi_pm_notifier_lock vs flush_workqueue() deadlock
acpi_remove_pm_notifier() ends up calling flush_workqueue() while holding acpi_pm_notifier_lock, and that same lock is taken by by the work via acpi_pm_notify_handler(). This can deadlock. To fix the problem let's split the single lock into two: one to protect the dev->wakeup between the work vs. add/remove, and another one to handle notifier installation vs. removal. After commit a1d14934ea4b "workqueue/lockdep: 'Fix' flush_work() annotation" I was able to kill the machine (Intel Braswell) very easily with 'powertop --auto-tune', runtime suspending i915, and trying to wake it up via the USB keyboard. The cases when it didn't die are presumably explained by lockdep getting disabled by something else (cpu hotplug locking issues usually). Fortunately I still got a lockdep report over netconsole (trickling in very slowly), even though the machine was otherwise practically dead: [ 112.179806] ====================================================== [ 114.670858] WARNING: possible circular locking dependency detected [ 117.155663] 4.13.0-rc6-bsw-bisect-00169-ga1d14934ea4b #119 Not tainted [ 119.658101] ------------------------------------------------------ [ 121.310242] xhci_hcd 0000:00:14.0: xHCI host not responding to stop endpoint command. [ 121.313294] xhci_hcd 0000:00:14.0: xHCI host controller not responding, assume dead [ 121.313346] xhci_hcd 0000:00:14.0: HC died; cleaning up [ 121.313485] usb 1-6: USB disconnect, device number 3 [ 121.313501] usb 1-6.2: USB disconnect, device number 4 [ 134.747383] kworker/0:2/47 is trying to acquire lock: [ 137.220790] (acpi_pm_notifier_lock){+.+.}, at: [<ffffffff813cafdf>] acpi_pm_notify_handler+0x2f/0x80 [ 139.721524] [ 139.721524] but task is already holding lock: [ 144.672922] ((&dpc->work)){+.+.}, at: [<ffffffff8109ce90>] process_one_work+0x160/0x720 [ 147.184450] [ 147.184450] which lock already depends on the new lock. [ 147.184450] [ 154.604711] [ 154.604711] the existing dependency chain (in reverse order) is: [ 159.447888] [ 159.447888] -> #2 ((&dpc->work)){+.+.}: [ 164.183486] __lock_acquire+0x1255/0x13f0 [ 166.504313] lock_acquire+0xb5/0x210 [ 168.778973] process_one_work+0x1b9/0x720 [ 171.030316] worker_thread+0x4c/0x440 [ 173.257184] kthread+0x154/0x190 [ 175.456143] ret_from_fork+0x27/0x40 [ 177.624348] [ 177.624348] -> #1 ("kacpi_notify"){+.+.}: [ 181.850351] __lock_acquire+0x1255/0x13f0 [ 183.941695] lock_acquire+0xb5/0x210 [ 186.046115] flush_workqueue+0xdd/0x510 [ 190.408153] acpi_os_wait_events_complete+0x31/0x40 [ 192.625303] acpi_remove_notify_handler+0x133/0x188 [ 194.820829] acpi_remove_pm_notifier+0x56/0x90 [ 196.989068] acpi_dev_pm_detach+0x5f/0xa0 [ 199.145866] dev_pm_domain_detach+0x27/0x30 [ 201.285614] i2c_device_probe+0x100/0x210 [ 203.411118] driver_probe_device+0x23e/0x310 [ 205.522425] __driver_attach+0xa3/0xb0 [ 207.634268] bus_for_each_dev+0x69/0xa0 [ 209.714797] driver_attach+0x1e/0x20 [ 211.778258] bus_add_driver+0x1bc/0x230 [ 213.837162] driver_register+0x60/0xe0 [ 215.868162] i2c_register_driver+0x42/0x70 [ 217.869551] 0xffffffffa0172017 [ 219.863009] do_one_initcall+0x45/0x170 [ 221.843863] do_init_module+0x5f/0x204 [ 223.817915] load_module+0x225b/0x29b0 [ 225.757234] SyS_finit_module+0xc6/0xd0 [ 227.661851] do_syscall_64+0x5c/0x120 [ 229.536819] return_from_SYSCALL_64+0x0/0x7a [ 231.392444] [ 231.392444] -> #0 (acpi_pm_notifier_lock){+.+.}: [ 235.124914] check_prev_add+0x44e/0x8a0 [ 237.024795] __lock_acquire+0x1255/0x13f0 [ 238.937351] lock_acquire+0xb5/0x210 [ 240.840799] __mutex_lock+0x75/0x940 [ 242.709517] mutex_lock_nested+0x1c/0x20 [ 244.551478] acpi_pm_notify_handler+0x2f/0x80 [ 246.382052] acpi_ev_notify_dispatch+0x44/0x5c [ 248.194412] acpi_os_execute_deferred+0x14/0x30 [ 250.003925] process_one_work+0x1ec/0x720 [ 251.803191] worker_thread+0x4c/0x440 [ 253.605307] kthread+0x154/0x190 [ 255.387498] ret_from_fork+0x27/0x40 [ 257.153175] [ 257.153175] other info that might help us debug this: [ 257.153175] [ 262.324392] Chain exists of: [ 262.324392] acpi_pm_notifier_lock --> "kacpi_notify" --> (&dpc->work) [ 262.324392] [ 267.391997] Possible unsafe locking scenario: [ 267.391997] [ 270.758262] CPU0 CPU1 [ 272.431713] ---- ---- [ 274.060756] lock((&dpc->work)); [ 275.646532] lock("kacpi_notify"); [ 277.260772] lock((&dpc->work)); [ 278.839146] lock(acpi_pm_notifier_lock); [ 280.391902] [ 280.391902] *** DEADLOCK *** [ 280.391902] [ 284.986385] 2 locks held by kworker/0:2/47: [ 286.524895] #0: ("kacpi_notify"){+.+.}, at: [<ffffffff8109ce90>] process_one_work+0x160/0x720 [ 288.112927] #1: ((&dpc->work)){+.+.}, at: [<ffffffff8109ce90>] process_one_work+0x160/0x720 [ 289.727725] Fixes: c072530f391e (ACPI / PM: Revork the handling of ACPI device wakeup notifications) Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Cc: 3.17+ <stable@vger.kernel.org> # 3.17+ Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
-rw-r--r--drivers/acpi/device_pm.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/drivers/acpi/device_pm.c b/drivers/acpi/device_pm.c
index 17e8eb93a76c..69ffd1dc1de7 100644
--- a/drivers/acpi/device_pm.c
+++ b/drivers/acpi/device_pm.c
@@ -387,6 +387,7 @@ EXPORT_SYMBOL(acpi_bus_power_manageable);
387 387
388#ifdef CONFIG_PM 388#ifdef CONFIG_PM
389static DEFINE_MUTEX(acpi_pm_notifier_lock); 389static DEFINE_MUTEX(acpi_pm_notifier_lock);
390static DEFINE_MUTEX(acpi_pm_notifier_install_lock);
390 391
391void acpi_pm_wakeup_event(struct device *dev) 392void acpi_pm_wakeup_event(struct device *dev)
392{ 393{
@@ -443,24 +444,25 @@ acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
443 if (!dev && !func) 444 if (!dev && !func)
444 return AE_BAD_PARAMETER; 445 return AE_BAD_PARAMETER;
445 446
446 mutex_lock(&acpi_pm_notifier_lock); 447 mutex_lock(&acpi_pm_notifier_install_lock);
447 448
448 if (adev->wakeup.flags.notifier_present) 449 if (adev->wakeup.flags.notifier_present)
449 goto out; 450 goto out;
450 451
451 adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev));
452 adev->wakeup.context.dev = dev;
453 adev->wakeup.context.func = func;
454
455 status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY, 452 status = acpi_install_notify_handler(adev->handle, ACPI_SYSTEM_NOTIFY,
456 acpi_pm_notify_handler, NULL); 453 acpi_pm_notify_handler, NULL);
457 if (ACPI_FAILURE(status)) 454 if (ACPI_FAILURE(status))
458 goto out; 455 goto out;
459 456
457 mutex_lock(&acpi_pm_notifier_lock);
458 adev->wakeup.ws = wakeup_source_register(dev_name(&adev->dev));
459 adev->wakeup.context.dev = dev;
460 adev->wakeup.context.func = func;
460 adev->wakeup.flags.notifier_present = true; 461 adev->wakeup.flags.notifier_present = true;
462 mutex_unlock(&acpi_pm_notifier_lock);
461 463
462 out: 464 out:
463 mutex_unlock(&acpi_pm_notifier_lock); 465 mutex_unlock(&acpi_pm_notifier_install_lock);
464 return status; 466 return status;
465} 467}
466 468
@@ -472,7 +474,7 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
472{ 474{
473 acpi_status status = AE_BAD_PARAMETER; 475 acpi_status status = AE_BAD_PARAMETER;
474 476
475 mutex_lock(&acpi_pm_notifier_lock); 477 mutex_lock(&acpi_pm_notifier_install_lock);
476 478
477 if (!adev->wakeup.flags.notifier_present) 479 if (!adev->wakeup.flags.notifier_present)
478 goto out; 480 goto out;
@@ -483,14 +485,15 @@ acpi_status acpi_remove_pm_notifier(struct acpi_device *adev)
483 if (ACPI_FAILURE(status)) 485 if (ACPI_FAILURE(status))
484 goto out; 486 goto out;
485 487
488 mutex_lock(&acpi_pm_notifier_lock);
486 adev->wakeup.context.func = NULL; 489 adev->wakeup.context.func = NULL;
487 adev->wakeup.context.dev = NULL; 490 adev->wakeup.context.dev = NULL;
488 wakeup_source_unregister(adev->wakeup.ws); 491 wakeup_source_unregister(adev->wakeup.ws);
489
490 adev->wakeup.flags.notifier_present = false; 492 adev->wakeup.flags.notifier_present = false;
493 mutex_unlock(&acpi_pm_notifier_lock);
491 494
492 out: 495 out:
493 mutex_unlock(&acpi_pm_notifier_lock); 496 mutex_unlock(&acpi_pm_notifier_install_lock);
494 return status; 497 return status;
495} 498}
496 499