forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 466
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PM / Core: Introduce struct syscore_ops for core subsystems PM
Some subsystems need to carry out suspend/resume and shutdown operations with one CPU on-line and interrupts disabled. The only way to register such operations is to define a sysdev class and a sysdev specifically for this purpose which is cumbersome and inefficient. Moreover, the arguments taken by sysdev suspend, resume and shutdown callbacks are practically never necessary. For this reason, introduce a simpler interface allowing subsystems to register operations to be executed very late during system suspend and shutdown and very early during resume in the form of strcut syscore_ops objects. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
- Loading branch information
Showing
6 changed files
with
164 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
/* | ||
* syscore.c - Execution of system core operations. | ||
* | ||
* Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
* | ||
* This file is released under the GPLv2. | ||
*/ | ||
|
||
#include <linux/syscore_ops.h> | ||
#include <linux/mutex.h> | ||
#include <linux/module.h> | ||
|
||
static LIST_HEAD(syscore_ops_list); | ||
static DEFINE_MUTEX(syscore_ops_lock); | ||
|
||
/** | ||
* register_syscore_ops - Register a set of system core operations. | ||
* @ops: System core operations to register. | ||
*/ | ||
void register_syscore_ops(struct syscore_ops *ops) | ||
{ | ||
mutex_lock(&syscore_ops_lock); | ||
list_add_tail(&ops->node, &syscore_ops_list); | ||
mutex_unlock(&syscore_ops_lock); | ||
} | ||
EXPORT_SYMBOL_GPL(register_syscore_ops); | ||
|
||
/** | ||
* unregister_syscore_ops - Unregister a set of system core operations. | ||
* @ops: System core operations to unregister. | ||
*/ | ||
void unregister_syscore_ops(struct syscore_ops *ops) | ||
{ | ||
mutex_lock(&syscore_ops_lock); | ||
list_del(&ops->node); | ||
mutex_unlock(&syscore_ops_lock); | ||
} | ||
EXPORT_SYMBOL_GPL(unregister_syscore_ops); | ||
|
||
#ifdef CONFIG_PM_SLEEP | ||
/** | ||
* syscore_suspend - Execute all the registered system core suspend callbacks. | ||
* | ||
* This function is executed with one CPU on-line and disabled interrupts. | ||
*/ | ||
int syscore_suspend(void) | ||
{ | ||
struct syscore_ops *ops; | ||
int ret = 0; | ||
|
||
WARN_ONCE(!irqs_disabled(), | ||
"Interrupts enabled before system core suspend.\n"); | ||
|
||
list_for_each_entry_reverse(ops, &syscore_ops_list, node) | ||
if (ops->suspend) { | ||
if (initcall_debug) | ||
pr_info("PM: Calling %pF\n", ops->suspend); | ||
ret = ops->suspend(); | ||
if (ret) | ||
goto err_out; | ||
WARN_ONCE(!irqs_disabled(), | ||
"Interrupts enabled after %pF\n", ops->suspend); | ||
} | ||
|
||
return 0; | ||
|
||
err_out: | ||
pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend); | ||
|
||
list_for_each_entry_continue(ops, &syscore_ops_list, node) | ||
if (ops->resume) | ||
ops->resume(); | ||
|
||
return ret; | ||
} | ||
|
||
/** | ||
* syscore_resume - Execute all the registered system core resume callbacks. | ||
* | ||
* This function is executed with one CPU on-line and disabled interrupts. | ||
*/ | ||
void syscore_resume(void) | ||
{ | ||
struct syscore_ops *ops; | ||
|
||
WARN_ONCE(!irqs_disabled(), | ||
"Interrupts enabled before system core resume.\n"); | ||
|
||
list_for_each_entry(ops, &syscore_ops_list, node) | ||
if (ops->resume) { | ||
if (initcall_debug) | ||
pr_info("PM: Calling %pF\n", ops->resume); | ||
ops->resume(); | ||
WARN_ONCE(!irqs_disabled(), | ||
"Interrupts enabled after %pF\n", ops->resume); | ||
} | ||
} | ||
#endif /* CONFIG_PM_SLEEP */ | ||
|
||
/** | ||
* syscore_shutdown - Execute all the registered system core shutdown callbacks. | ||
*/ | ||
void syscore_shutdown(void) | ||
{ | ||
struct syscore_ops *ops; | ||
|
||
mutex_lock(&syscore_ops_lock); | ||
|
||
list_for_each_entry_reverse(ops, &syscore_ops_list, node) | ||
if (ops->shutdown) { | ||
if (initcall_debug) | ||
pr_info("PM: Calling %pF\n", ops->shutdown); | ||
ops->shutdown(); | ||
} | ||
|
||
mutex_unlock(&syscore_ops_lock); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
/* | ||
* syscore_ops.h - System core operations. | ||
* | ||
* Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. | ||
* | ||
* This file is released under the GPLv2. | ||
*/ | ||
|
||
#ifndef _LINUX_SYSCORE_OPS_H | ||
#define _LINUX_SYSCORE_OPS_H | ||
|
||
#include <linux/list.h> | ||
|
||
struct syscore_ops { | ||
struct list_head node; | ||
int (*suspend)(void); | ||
void (*resume)(void); | ||
void (*shutdown)(void); | ||
}; | ||
|
||
extern void register_syscore_ops(struct syscore_ops *ops); | ||
extern void unregister_syscore_ops(struct syscore_ops *ops); | ||
#ifdef CONFIG_PM_SLEEP | ||
extern int syscore_suspend(void); | ||
extern void syscore_resume(void); | ||
#endif | ||
extern void syscore_shutdown(void); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters