Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
syscore.c
Go to the documentation of this file.
1 /*
2  * syscore.c - Execution of system core operations.
3  *
4  * Copyright (C) 2011 Rafael J. Wysocki <[email protected]>, 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 #include <linux/interrupt.h>
13 
14 static LIST_HEAD(syscore_ops_list);
15 static DEFINE_MUTEX(syscore_ops_lock);
16 
22 {
23  mutex_lock(&syscore_ops_lock);
24  list_add_tail(&ops->node, &syscore_ops_list);
25  mutex_unlock(&syscore_ops_lock);
26 }
28 
34 {
35  mutex_lock(&syscore_ops_lock);
36  list_del(&ops->node);
37  mutex_unlock(&syscore_ops_lock);
38 }
40 
41 #ifdef CONFIG_PM_SLEEP
42 
47 int syscore_suspend(void)
48 {
49  struct syscore_ops *ops;
50  int ret = 0;
51 
52  pr_debug("Checking wakeup interrupts\n");
53 
54  /* Return error code if there are any wakeup interrupts pending. */
55  ret = check_wakeup_irqs();
56  if (ret)
57  return ret;
58 
60  "Interrupts enabled before system core suspend.\n");
61 
62  list_for_each_entry_reverse(ops, &syscore_ops_list, node)
63  if (ops->suspend) {
64  if (initcall_debug)
65  pr_info("PM: Calling %pF\n", ops->suspend);
66  ret = ops->suspend();
67  if (ret)
68  goto err_out;
70  "Interrupts enabled after %pF\n", ops->suspend);
71  }
72 
73  return 0;
74 
75  err_out:
76  pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend);
77 
78  list_for_each_entry_continue(ops, &syscore_ops_list, node)
79  if (ops->resume)
80  ops->resume();
81 
82  return ret;
83 }
84 EXPORT_SYMBOL_GPL(syscore_suspend);
85 
91 void syscore_resume(void)
92 {
93  struct syscore_ops *ops;
94 
96  "Interrupts enabled before system core resume.\n");
97 
98  list_for_each_entry(ops, &syscore_ops_list, node)
99  if (ops->resume) {
100  if (initcall_debug)
101  pr_info("PM: Calling %pF\n", ops->resume);
102  ops->resume();
104  "Interrupts enabled after %pF\n", ops->resume);
105  }
106 }
107 EXPORT_SYMBOL_GPL(syscore_resume);
108 #endif /* CONFIG_PM_SLEEP */
109 
114 {
115  struct syscore_ops *ops;
116 
117  mutex_lock(&syscore_ops_lock);
118 
119  list_for_each_entry_reverse(ops, &syscore_ops_list, node)
120  if (ops->shutdown) {
121  if (initcall_debug)
122  pr_info("PM: Calling %pF\n", ops->shutdown);
123  ops->shutdown();
124  }
125 
126  mutex_unlock(&syscore_ops_lock);
127 }