main.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. /*
  2. * kernel/power/main.c - PM subsystem core functionality.
  3. *
  4. * Copyright (c) 2003 Patrick Mochel
  5. * Copyright (c) 2003 Open Source Development Lab
  6. *
  7. * This file is released under the GPLv2
  8. *
  9. */
  10. #include <linux/kobject.h>
  11. #include <linux/string.h>
  12. #include <linux/resume-trace.h>
  13. #include <linux/workqueue.h>
  14. #include "power.h"
  15. DEFINE_MUTEX(pm_mutex);
  16. unsigned int pm_flags;
  17. EXPORT_SYMBOL(pm_flags);
  18. #ifdef CONFIG_PM_SLEEP
  19. /* Routines for PM-transition notifications */
  20. static BLOCKING_NOTIFIER_HEAD(pm_chain_head);
  21. int register_pm_notifier(struct notifier_block *nb)
  22. {
  23. return blocking_notifier_chain_register(&pm_chain_head, nb);
  24. }
  25. EXPORT_SYMBOL_GPL(register_pm_notifier);
  26. int unregister_pm_notifier(struct notifier_block *nb)
  27. {
  28. return blocking_notifier_chain_unregister(&pm_chain_head, nb);
  29. }
  30. EXPORT_SYMBOL_GPL(unregister_pm_notifier);
  31. int pm_notifier_call_chain(unsigned long val)
  32. {
  33. return (blocking_notifier_call_chain(&pm_chain_head, val, NULL)
  34. == NOTIFY_BAD) ? -EINVAL : 0;
  35. }
  36. /* If set, devices may be suspended and resumed asynchronously. */
  37. int pm_async_enabled = 1;
  38. static ssize_t pm_async_show(struct kobject *kobj, struct kobj_attribute *attr,
  39. char *buf)
  40. {
  41. return sprintf(buf, "%d\n", pm_async_enabled);
  42. }
  43. static ssize_t pm_async_store(struct kobject *kobj, struct kobj_attribute *attr,
  44. const char *buf, size_t n)
  45. {
  46. unsigned long val;
  47. if (strict_strtoul(buf, 10, &val))
  48. return -EINVAL;
  49. if (val > 1)
  50. return -EINVAL;
  51. pm_async_enabled = val;
  52. return n;
  53. }
  54. power_attr(pm_async);
  55. #ifdef CONFIG_PM_DEBUG
  56. int pm_test_level = TEST_NONE;
  57. static const char * const pm_tests[__TEST_AFTER_LAST] = {
  58. [TEST_NONE] = "none",
  59. [TEST_CORE] = "core",
  60. [TEST_CPUS] = "processors",
  61. [TEST_PLATFORM] = "platform",
  62. [TEST_DEVICES] = "devices",
  63. [TEST_FREEZER] = "freezer",
  64. };
  65. static ssize_t pm_test_show(struct kobject *kobj, struct kobj_attribute *attr,
  66. char *buf)
  67. {
  68. char *s = buf;
  69. int level;
  70. for (level = TEST_FIRST; level <= TEST_MAX; level++)
  71. if (pm_tests[level]) {
  72. if (level == pm_test_level)
  73. s += sprintf(s, "[%s] ", pm_tests[level]);
  74. else
  75. s += sprintf(s, "%s ", pm_tests[level]);
  76. }
  77. if (s != buf)
  78. /* convert the last space to a newline */
  79. *(s-1) = '\n';
  80. return (s - buf);
  81. }
  82. static ssize_t pm_test_store(struct kobject *kobj, struct kobj_attribute *attr,
  83. const char *buf, size_t n)
  84. {
  85. const char * const *s;
  86. int level;
  87. char *p;
  88. int len;
  89. int error = -EINVAL;
  90. p = memchr(buf, '\n', n);
  91. len = p ? p - buf : n;
  92. mutex_lock(&pm_mutex);
  93. level = TEST_FIRST;
  94. for (s = &pm_tests[level]; level <= TEST_MAX; s++, level++)
  95. if (*s && len == strlen(*s) && !strncmp(buf, *s, len)) {
  96. pm_test_level = level;
  97. error = 0;
  98. break;
  99. }
  100. mutex_unlock(&pm_mutex);
  101. return error ? error : n;
  102. }
  103. power_attr(pm_test);
  104. #endif /* CONFIG_PM_DEBUG */
  105. #endif /* CONFIG_PM_SLEEP */
  106. struct kobject *power_kobj;
  107. /**
  108. * state - control system power state.
  109. *
  110. * show() returns what states are supported, which is hard-coded to
  111. * 'standby' (Power-On Suspend), 'mem' (Suspend-to-RAM), and
  112. * 'disk' (Suspend-to-Disk).
  113. *
  114. * store() accepts one of those strings, translates it into the
  115. * proper enumerated value, and initiates a suspend transition.
  116. */
  117. static ssize_t state_show(struct kobject *kobj, struct kobj_attribute *attr,
  118. char *buf)
  119. {
  120. char *s = buf;
  121. #ifdef CONFIG_SUSPEND
  122. int i;
  123. for (i = 0; i < PM_SUSPEND_MAX; i++) {
  124. if (pm_states[i] && valid_state(i))
  125. s += sprintf(s,"%s ", pm_states[i]);
  126. }
  127. #endif
  128. #ifdef CONFIG_HIBERNATION
  129. s += sprintf(s, "%s\n", "disk");
  130. #else
  131. if (s != buf)
  132. /* convert the last space to a newline */
  133. *(s-1) = '\n';
  134. #endif
  135. return (s - buf);
  136. }
  137. static ssize_t state_store(struct kobject *kobj, struct kobj_attribute *attr,
  138. const char *buf, size_t n)
  139. {
  140. #ifdef CONFIG_SUSPEND
  141. suspend_state_t state = PM_SUSPEND_STANDBY;
  142. const char * const *s;
  143. #endif
  144. char *p;
  145. int len;
  146. int error = -EINVAL;
  147. p = memchr(buf, '\n', n);
  148. len = p ? p - buf : n;
  149. /* First, check if we are requested to hibernate */
  150. if (len == 4 && !strncmp(buf, "disk", len)) {
  151. error = hibernate();
  152. goto Exit;
  153. }
  154. #ifdef CONFIG_SUSPEND
  155. for (s = &pm_states[state]; state < PM_SUSPEND_MAX; s++, state++) {
  156. if (*s && len == strlen(*s) && !strncmp(buf, *s, len))
  157. break;
  158. }
  159. if (state < PM_SUSPEND_MAX && *s)
  160. error = enter_state(state);
  161. #endif
  162. Exit:
  163. return error ? error : n;
  164. }
  165. power_attr(state);
  166. #ifdef CONFIG_PM_SLEEP
  167. /*
  168. * The 'wakeup_count' attribute, along with the functions defined in
  169. * drivers/base/power/wakeup.c, provides a means by which wakeup events can be
  170. * handled in a non-racy way.
  171. *
  172. * If a wakeup event occurs when the system is in a sleep state, it simply is
  173. * woken up. In turn, if an event that would wake the system up from a sleep
  174. * state occurs when it is undergoing a transition to that sleep state, the
  175. * transition should be aborted. Moreover, if such an event occurs when the
  176. * system is in the working state, an attempt to start a transition to the
  177. * given sleep state should fail during certain period after the detection of
  178. * the event. Using the 'state' attribute alone is not sufficient to satisfy
  179. * these requirements, because a wakeup event may occur exactly when 'state'
  180. * is being written to and may be delivered to user space right before it is
  181. * frozen, so the event will remain only partially processed until the system is
  182. * woken up by another event. In particular, it won't cause the transition to
  183. * a sleep state to be aborted.
  184. *
  185. * This difficulty may be overcome if user space uses 'wakeup_count' before
  186. * writing to 'state'. It first should read from 'wakeup_count' and store
  187. * the read value. Then, after carrying out its own preparations for the system
  188. * transition to a sleep state, it should write the stored value to
  189. * 'wakeup_count'. If that fails, at least one wakeup event has occured since
  190. * 'wakeup_count' was read and 'state' should not be written to. Otherwise, it
  191. * is allowed to write to 'state', but the transition will be aborted if there
  192. * are any wakeup events detected after 'wakeup_count' was written to.
  193. */
  194. static ssize_t wakeup_count_show(struct kobject *kobj,
  195. struct kobj_attribute *attr,
  196. char *buf)
  197. {
  198. unsigned long val;
  199. return pm_get_wakeup_count(&val) ? sprintf(buf, "%lu\n", val) : -EINTR;
  200. }
  201. static ssize_t wakeup_count_store(struct kobject *kobj,
  202. struct kobj_attribute *attr,
  203. const char *buf, size_t n)
  204. {
  205. unsigned long val;
  206. if (sscanf(buf, "%lu", &val) == 1) {
  207. if (pm_save_wakeup_count(val))
  208. return n;
  209. }
  210. return -EINVAL;
  211. }
  212. power_attr(wakeup_count);
  213. #endif /* CONFIG_PM_SLEEP */
  214. #ifdef CONFIG_PM_TRACE
  215. int pm_trace_enabled;
  216. static ssize_t pm_trace_show(struct kobject *kobj, struct kobj_attribute *attr,
  217. char *buf)
  218. {
  219. return sprintf(buf, "%d\n", pm_trace_enabled);
  220. }
  221. static ssize_t
  222. pm_trace_store(struct kobject *kobj, struct kobj_attribute *attr,
  223. const char *buf, size_t n)
  224. {
  225. int val;
  226. if (sscanf(buf, "%d", &val) == 1) {
  227. pm_trace_enabled = !!val;
  228. return n;
  229. }
  230. return -EINVAL;
  231. }
  232. power_attr(pm_trace);
  233. #endif /* CONFIG_PM_TRACE */
  234. static struct attribute * g[] = {
  235. &state_attr.attr,
  236. #ifdef CONFIG_PM_TRACE
  237. &pm_trace_attr.attr,
  238. #endif
  239. #ifdef CONFIG_PM_SLEEP
  240. &pm_async_attr.attr,
  241. &wakeup_count_attr.attr,
  242. #ifdef CONFIG_PM_DEBUG
  243. &pm_test_attr.attr,
  244. #endif
  245. #endif
  246. NULL,
  247. };
  248. static struct attribute_group attr_group = {
  249. .attrs = g,
  250. };
  251. #ifdef CONFIG_PM_RUNTIME
  252. struct workqueue_struct *pm_wq;
  253. EXPORT_SYMBOL_GPL(pm_wq);
  254. static int __init pm_start_workqueue(void)
  255. {
  256. pm_wq = create_freezeable_workqueue("pm");
  257. return pm_wq ? 0 : -ENOMEM;
  258. }
  259. #else
  260. static inline int pm_start_workqueue(void) { return 0; }
  261. #endif
  262. static int __init pm_init(void)
  263. {
  264. int error = pm_start_workqueue();
  265. if (error)
  266. return error;
  267. power_kobj = kobject_create_and_add("power", NULL);
  268. if (!power_kobj)
  269. return -ENOMEM;
  270. return sysfs_create_group(power_kobj, &attr_group);
  271. }
  272. core_initcall(pm_init);