userwakelock.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /* kernel/power/userwakelock.c
  2. *
  3. * Copyright (C) 2005-2008 Google, Inc.
  4. *
  5. * This software is licensed under the terms of the GNU General Public
  6. * License version 2, as published by the Free Software Foundation, and
  7. * may be copied, distributed, and modified under those terms.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. */
  15. #include <linux/ctype.h>
  16. #include <linux/module.h>
  17. #include <linux/wakelock.h>
  18. #include <linux/slab.h>
  19. #include "power.h"
  20. enum {
  21. DEBUG_FAILURE = BIT(0),
  22. DEBUG_ERROR = BIT(1),
  23. DEBUG_NEW = BIT(2),
  24. DEBUG_ACCESS = BIT(3),
  25. DEBUG_LOOKUP = BIT(4),
  26. };
  27. static int debug_mask = DEBUG_FAILURE;
  28. module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
  29. static DEFINE_MUTEX(tree_lock);
  30. struct user_wake_lock {
  31. struct rb_node node;
  32. struct wake_lock wake_lock;
  33. char name[0];
  34. };
  35. struct rb_root user_wake_locks;
  36. static struct user_wake_lock *lookup_wake_lock_name(
  37. const char *buf, int allocate, long *timeoutptr)
  38. {
  39. struct rb_node **p = &user_wake_locks.rb_node;
  40. struct rb_node *parent = NULL;
  41. struct user_wake_lock *l;
  42. int diff;
  43. u64 timeout;
  44. int name_len;
  45. const char *arg;
  46. /* Find length of lock name and start of optional timeout string */
  47. arg = buf;
  48. while (*arg && !isspace(*arg))
  49. arg++;
  50. name_len = arg - buf;
  51. if (!name_len)
  52. goto bad_arg;
  53. while (isspace(*arg))
  54. arg++;
  55. /* Process timeout string */
  56. if (timeoutptr && *arg) {
  57. timeout = simple_strtoull(arg, (char **)&arg, 0);
  58. while (isspace(*arg))
  59. arg++;
  60. if (*arg)
  61. goto bad_arg;
  62. /* convert timeout from nanoseconds to jiffies > 0 */
  63. timeout += (NSEC_PER_SEC / HZ) - 1;
  64. do_div(timeout, (NSEC_PER_SEC / HZ));
  65. if (timeout <= 0)
  66. timeout = 1;
  67. *timeoutptr = timeout;
  68. } else if (*arg)
  69. goto bad_arg;
  70. else if (timeoutptr)
  71. *timeoutptr = 0;
  72. /* Lookup wake lock in rbtree */
  73. while (*p) {
  74. parent = *p;
  75. l = rb_entry(parent, struct user_wake_lock, node);
  76. diff = strncmp(buf, l->name, name_len);
  77. if (!diff && l->name[name_len])
  78. diff = -1;
  79. if (debug_mask & DEBUG_ERROR)
  80. pr_info("lookup_wake_lock_name: compare %.*s %s %d\n",
  81. name_len, buf, l->name, diff);
  82. if (diff < 0)
  83. p = &(*p)->rb_left;
  84. else if (diff > 0)
  85. p = &(*p)->rb_right;
  86. else
  87. return l;
  88. }
  89. /* Allocate and add new wakelock to rbtree */
  90. if (!allocate) {
  91. if (debug_mask & DEBUG_ERROR)
  92. pr_info("lookup_wake_lock_name: %.*s not found\n",
  93. name_len, buf);
  94. return ERR_PTR(-EINVAL);
  95. }
  96. l = kzalloc(sizeof(*l) + name_len + 1, GFP_KERNEL);
  97. if (l == NULL) {
  98. if (debug_mask & DEBUG_FAILURE)
  99. pr_err("lookup_wake_lock_name: failed to allocate "
  100. "memory for %.*s\n", name_len, buf);
  101. return ERR_PTR(-ENOMEM);
  102. }
  103. memcpy(l->name, buf, name_len);
  104. if (debug_mask & DEBUG_NEW)
  105. pr_info("lookup_wake_lock_name: new wake lock %s\n", l->name);
  106. wake_lock_init(&l->wake_lock, WAKE_LOCK_SUSPEND, l->name);
  107. rb_link_node(&l->node, parent, p);
  108. rb_insert_color(&l->node, &user_wake_locks);
  109. return l;
  110. bad_arg:
  111. if (debug_mask & DEBUG_ERROR)
  112. pr_info("lookup_wake_lock_name: wake lock, %.*s, bad arg, %s\n",
  113. name_len, buf, arg);
  114. return ERR_PTR(-EINVAL);
  115. }
  116. ssize_t wake_lock_show(
  117. struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  118. {
  119. char *s = buf;
  120. char *end = buf + PAGE_SIZE;
  121. struct rb_node *n;
  122. struct user_wake_lock *l;
  123. mutex_lock(&tree_lock);
  124. for (n = rb_first(&user_wake_locks); n != NULL; n = rb_next(n)) {
  125. l = rb_entry(n, struct user_wake_lock, node);
  126. if (wake_lock_active(&l->wake_lock))
  127. s += scnprintf(s, end - s, "%s ", l->name);
  128. }
  129. s += scnprintf(s, end - s, "\n");
  130. mutex_unlock(&tree_lock);
  131. return (s - buf);
  132. }
  133. ssize_t wake_lock_store(
  134. struct kobject *kobj, struct kobj_attribute *attr,
  135. const char *buf, size_t n)
  136. {
  137. long timeout;
  138. struct user_wake_lock *l;
  139. mutex_lock(&tree_lock);
  140. l = lookup_wake_lock_name(buf, 1, &timeout);
  141. if (IS_ERR(l)) {
  142. n = PTR_ERR(l);
  143. goto bad_name;
  144. }
  145. if (debug_mask & DEBUG_ACCESS)
  146. pr_info("wake_lock_store: %s, timeout %ld\n", l->name, timeout);
  147. if (timeout)
  148. wake_lock_timeout(&l->wake_lock, timeout);
  149. else
  150. wake_lock(&l->wake_lock);
  151. bad_name:
  152. mutex_unlock(&tree_lock);
  153. return n;
  154. }
  155. ssize_t wake_unlock_show(
  156. struct kobject *kobj, struct kobj_attribute *attr, char *buf)
  157. {
  158. char *s = buf;
  159. char *end = buf + PAGE_SIZE;
  160. struct rb_node *n;
  161. struct user_wake_lock *l;
  162. mutex_lock(&tree_lock);
  163. for (n = rb_first(&user_wake_locks); n != NULL; n = rb_next(n)) {
  164. l = rb_entry(n, struct user_wake_lock, node);
  165. if (!wake_lock_active(&l->wake_lock))
  166. s += scnprintf(s, end - s, "%s ", l->name);
  167. }
  168. s += scnprintf(s, end - s, "\n");
  169. mutex_unlock(&tree_lock);
  170. return (s - buf);
  171. }
  172. ssize_t wake_unlock_store(
  173. struct kobject *kobj, struct kobj_attribute *attr,
  174. const char *buf, size_t n)
  175. {
  176. struct user_wake_lock *l;
  177. mutex_lock(&tree_lock);
  178. l = lookup_wake_lock_name(buf, 0, NULL);
  179. if (IS_ERR(l)) {
  180. n = PTR_ERR(l);
  181. goto not_found;
  182. }
  183. if (debug_mask & DEBUG_ACCESS)
  184. pr_info("wake_unlock_store: %s\n", l->name);
  185. wake_unlock(&l->wake_lock);
  186. not_found:
  187. mutex_unlock(&tree_lock);
  188. return n;
  189. }