Blame view

drivers/base/syscore.c 3.24 KB
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
1
2
3
4
5
6
7
8
9
10
11
  /*
   *  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>
9ce7a2584   Thomas Gleixner   genirq: Simplify ...
12
  #include <linux/suspend.h>
bb3632c61   Todd E Brandt   PM / sleep: trace...
13
  #include <trace/events/power.h>
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  
  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;
bb3632c61   Todd E Brandt   PM / sleep: trace...
52
  	trace_suspend_resume(TPS("syscore_suspend"), 0, true);
887596224   Colin Cross   PM: Reintroduce d...
53
54
55
56
  	pr_debug("Checking wakeup interrupts
  ");
  
  	/* Return error code if there are any wakeup interrupts pending. */
9ce7a2584   Thomas Gleixner   genirq: Simplify ...
57
58
  	if (pm_wakeup_pending())
  		return -EBUSY;
887596224   Colin Cross   PM: Reintroduce d...
59

40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
  	WARN_ONCE(!irqs_disabled(),
  		"Interrupts enabled before system core suspend.
  ");
  
  	list_for_each_entry_reverse(ops, &syscore_ops_list, node)
  		if (ops->suspend) {
  			if (initcall_debug)
  				pr_info("PM: Calling %pF
  ", ops->suspend);
  			ret = ops->suspend();
  			if (ret)
  				goto err_out;
  			WARN_ONCE(!irqs_disabled(),
  				"Interrupts enabled after %pF
  ", ops->suspend);
  		}
bb3632c61   Todd E Brandt   PM / sleep: trace...
76
  	trace_suspend_resume(TPS("syscore_suspend"), 0, false);
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
77
78
79
80
81
82
83
84
85
86
87
88
  	return 0;
  
   err_out:
  	pr_err("PM: System core suspend callback %pF failed.
  ", ops->suspend);
  
  	list_for_each_entry_continue(ops, &syscore_ops_list, node)
  		if (ops->resume)
  			ops->resume();
  
  	return ret;
  }
19234c081   Rafael J. Wysocki   PM: Add missing s...
89
  EXPORT_SYMBOL_GPL(syscore_suspend);
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
90
91
92
93
94
95
96
97
98
  
  /**
   * 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;
bb3632c61   Todd E Brandt   PM / sleep: trace...
99
  	trace_suspend_resume(TPS("syscore_resume"), 0, true);
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  	WARN_ONCE(!irqs_disabled(),
  		"Interrupts enabled before system core resume.
  ");
  
  	list_for_each_entry(ops, &syscore_ops_list, node)
  		if (ops->resume) {
  			if (initcall_debug)
  				pr_info("PM: Calling %pF
  ", ops->resume);
  			ops->resume();
  			WARN_ONCE(!irqs_disabled(),
  				"Interrupts enabled after %pF
  ", ops->resume);
  		}
bb3632c61   Todd E Brandt   PM / sleep: trace...
114
  	trace_suspend_resume(TPS("syscore_resume"), 0, false);
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
115
  }
19234c081   Rafael J. Wysocki   PM: Add missing s...
116
  EXPORT_SYMBOL_GPL(syscore_resume);
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
  #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
  ", ops->shutdown);
  			ops->shutdown();
  		}
  
  	mutex_unlock(&syscore_ops_lock);
  }