at v2.6.39-rc3 117 lines 2.8 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} 76 77/** 78 * syscore_resume - Execute all the registered system core resume callbacks. 79 * 80 * This function is executed with one CPU on-line and disabled interrupts. 81 */ 82void syscore_resume(void) 83{ 84 struct syscore_ops *ops; 85 86 WARN_ONCE(!irqs_disabled(), 87 "Interrupts enabled before system core resume.\n"); 88 89 list_for_each_entry(ops, &syscore_ops_list, node) 90 if (ops->resume) { 91 if (initcall_debug) 92 pr_info("PM: Calling %pF\n", ops->resume); 93 ops->resume(); 94 WARN_ONCE(!irqs_disabled(), 95 "Interrupts enabled after %pF\n", ops->resume); 96 } 97} 98#endif /* CONFIG_PM_SLEEP */ 99 100/** 101 * syscore_shutdown - Execute all the registered system core shutdown callbacks. 102 */ 103void syscore_shutdown(void) 104{ 105 struct syscore_ops *ops; 106 107 mutex_lock(&syscore_ops_lock); 108 109 list_for_each_entry_reverse(ops, &syscore_ops_list, node) 110 if (ops->shutdown) { 111 if (initcall_debug) 112 pr_info("PM: Calling %pF\n", ops->shutdown); 113 ops->shutdown(); 114 } 115 116 mutex_unlock(&syscore_ops_lock); 117}