Blame view

drivers/base/syscore.c 3 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>
887596224   Colin Cross   PM: Reintroduce d...
12
  #include <linux/interrupt.h>
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
13
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
  
  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;
887596224   Colin Cross   PM: Reintroduce d...
51
52
53
54
55
56
57
  	pr_debug("Checking wakeup interrupts
  ");
  
  	/* Return error code if there are any wakeup interrupts pending. */
  	ret = check_wakeup_irqs();
  	if (ret)
  		return ret;
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  	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);
  		}
  
  	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...
87
  EXPORT_SYMBOL_GPL(syscore_suspend);
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
  
  /**
   * 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.
  ");
  
  	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);
  		}
  }
19234c081   Rafael J. Wysocki   PM: Add missing s...
113
  EXPORT_SYMBOL_GPL(syscore_resume);
40dc166cb   Rafael J. Wysocki   PM / Core: Introd...
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
  #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);
  }