diff options
author | Rafael J. Wysocki <rjw@sisk.pl> | 2009-04-18 07:45:13 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rjw@sisk.pl> | 2009-06-12 15:32:29 -0400 |
commit | 62b0124761b9c2e304ee07dcf4db46c4a3dfec11 (patch) | |
tree | 81f27bb0e7eb92cd2d14a3ae3088ef3fa90a3cc2 /drivers/base/sys.c | |
parent | ce4b3c55475e451cb489e857640396c37ca88974 (diff) |
PM: Warn if interrupts are enabled during suspend-resume of sysdevs
Sysdevs have to be suspended and resumed with interrupts disabled and
things usually break in a way that's difficult to debug if one of
sysdev drivers enables interrupts by mistake during suspend or
resume. Add extra checks that will generate warnings in such cases.
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
Diffstat (limited to 'drivers/base/sys.c')
-rw-r--r-- | drivers/base/sys.c | 16 |
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 3236b434b964..9742a78c9fe4 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c | |||
@@ -343,11 +343,15 @@ static void __sysdev_resume(struct sys_device *dev) | |||
343 | /* First, call the class-specific one */ | 343 | /* First, call the class-specific one */ |
344 | if (cls->resume) | 344 | if (cls->resume) |
345 | cls->resume(dev); | 345 | cls->resume(dev); |
346 | WARN_ONCE(!irqs_disabled(), | ||
347 | "Interrupts enabled after %pF\n", cls->resume); | ||
346 | 348 | ||
347 | /* Call auxillary drivers next. */ | 349 | /* Call auxillary drivers next. */ |
348 | list_for_each_entry(drv, &cls->drivers, entry) { | 350 | list_for_each_entry(drv, &cls->drivers, entry) { |
349 | if (drv->resume) | 351 | if (drv->resume) |
350 | drv->resume(dev); | 352 | drv->resume(dev); |
353 | WARN_ONCE(!irqs_disabled(), | ||
354 | "Interrupts enabled after %pF\n", drv->resume); | ||
351 | } | 355 | } |
352 | } | 356 | } |
353 | 357 | ||
@@ -377,6 +381,9 @@ int sysdev_suspend(pm_message_t state) | |||
377 | if (ret) | 381 | if (ret) |
378 | return ret; | 382 | return ret; |
379 | 383 | ||
384 | WARN_ONCE(!irqs_disabled(), | ||
385 | "Interrupts enabled while suspending system devices\n"); | ||
386 | |||
380 | pr_debug("Suspending System Devices\n"); | 387 | pr_debug("Suspending System Devices\n"); |
381 | 388 | ||
382 | list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) { | 389 | list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) { |
@@ -393,6 +400,9 @@ int sysdev_suspend(pm_message_t state) | |||
393 | if (ret) | 400 | if (ret) |
394 | goto aux_driver; | 401 | goto aux_driver; |
395 | } | 402 | } |
403 | WARN_ONCE(!irqs_disabled(), | ||
404 | "Interrupts enabled after %pF\n", | ||
405 | drv->suspend); | ||
396 | } | 406 | } |
397 | 407 | ||
398 | /* Now call the generic one */ | 408 | /* Now call the generic one */ |
@@ -400,6 +410,9 @@ int sysdev_suspend(pm_message_t state) | |||
400 | ret = cls->suspend(sysdev, state); | 410 | ret = cls->suspend(sysdev, state); |
401 | if (ret) | 411 | if (ret) |
402 | goto cls_driver; | 412 | goto cls_driver; |
413 | WARN_ONCE(!irqs_disabled(), | ||
414 | "Interrupts enabled after %pF\n", | ||
415 | cls->suspend); | ||
403 | } | 416 | } |
404 | } | 417 | } |
405 | } | 418 | } |
@@ -452,6 +465,9 @@ int sysdev_resume(void) | |||
452 | { | 465 | { |
453 | struct sysdev_class *cls; | 466 | struct sysdev_class *cls; |
454 | 467 | ||
468 | WARN_ONCE(!irqs_disabled(), | ||
469 | "Interrupts enabled while resuming system devices\n"); | ||
470 | |||
455 | pr_debug("Resuming System Devices\n"); | 471 | pr_debug("Resuming System Devices\n"); |
456 | 472 | ||
457 | list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) { | 473 | list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) { |