at v2.6.39 119 lines 2.9 kB view raw
1/* 2 * syscore.c - Execution of system core operations. 3 * 4 * Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc. 5 * 6 * This file is released under the GPLv2. 7 */ 8 9#include <linux/syscore_ops.h> 10#include <linux/mutex.h> 11#include <linux/module.h> 12 13static LIST_HEAD(syscore_ops_list); 14static DEFINE_MUTEX(syscore_ops_lock); 15 16/** 17 * register_syscore_ops - Register a set of system core operations. 18 * @ops: System core operations to register. 19 */ 20void register_syscore_ops(struct syscore_ops *ops) 21{ 22 mutex_lock(&syscore_ops_lock); 23 list_add_tail(&ops->node, &syscore_ops_list); 24 mutex_unlock(&syscore_ops_lock); 25} 26EXPORT_SYMBOL_GPL(register_syscore_ops); 27 28/** 29 * unregister_syscore_ops - Unregister a set of system core operations. 30 * @ops: System core operations to unregister. 31 */ 32void unregister_syscore_ops(struct syscore_ops *ops) 33{ 34 mutex_lock(&syscore_ops_lock); 35 list_del(&ops->node); 36 mutex_unlock(&syscore_ops_lock); 37} 38EXPORT_SYMBOL_GPL(unregister_syscore_ops); 39 40#ifdef CONFIG_PM_SLEEP 41/** 42 * syscore_suspend - Execute all the registered system core suspend callbacks. 43 * 44 * This function is executed with one CPU on-line and disabled interrupts. 45 */ 46int syscore_suspend(void) 47{ 48 struct syscore_ops *ops; 49 int ret = 0; 50 51 WARN_ONCE(!irqs_disabled(), 52 "Interrupts enabled before system core suspend.\n"); 53 54 list_for_each_entry_reverse(ops, &syscore_ops_list, node) 55 if (ops->suspend) { 56 if (initcall_debug) 57 pr_info("PM: Calling %pF\n", ops->suspend); 58 ret = ops->suspend(); 59 if (ret) 60 goto err_out; 61 WARN_ONCE(!irqs_disabled(), 62 "Interrupts enabled after %pF\n", ops->suspend); 63 } 64 65 return 0; 66 67 err_out: 68 pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend); 69 70 list_for_each_entry_continue(ops, &syscore_ops_list, node) 71 if (ops->resume) 72 ops->resume(); 73 74 return ret; 75} 76EXPORT_SYMBOL_GPL(syscore_suspend); 77 78/** 79 * syscore_resume - Execute all the registered system core resume callbacks. 80 * 81 * This function is executed with one CPU on-line and disabled interrupts. 82 */ 83void syscore_resume(void) 84{ 85 struct syscore_ops *ops; 86 87 WARN_ONCE(!irqs_disabled(), 88 "Interrupts enabled before system core resume.\n"); 89 90 list_for_each_entry(ops, &syscore_ops_list, node) 91 if (ops->resume) { 92 if (initcall_debug) 93 pr_info("PM: Calling %pF\n", ops->resume); 94 ops->resume(); 95 WARN_ONCE(!irqs_disabled(), 96 "Interrupts enabled after %pF\n", ops->resume); 97 } 98} 99EXPORT_SYMBOL_GPL(syscore_resume); 100#endif /* CONFIG_PM_SLEEP */ 101 102/** 103 * syscore_shutdown - Execute all the registered system core shutdown callbacks. 104 */ 105void syscore_shutdown(void) 106{ 107 struct syscore_ops *ops; 108 109 mutex_lock(&syscore_ops_lock); 110 111 list_for_each_entry_reverse(ops, &syscore_ops_list, node) 112 if (ops->shutdown) { 113 if (initcall_debug) 114 pr_info("PM: Calling %pF\n", ops->shutdown); 115 ops->shutdown(); 116 } 117 118 mutex_unlock(&syscore_ops_lock); 119}