1 /* kernel/power/userwakelock.c
3 * Copyright (C) 2005-2008 Google, Inc.
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.
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.
16 #include <linux/ctype.h>
17 #include <linux/module.h>
18 #include <linux/wakelock.h>
23 DEBUG_FAILURE
= BIT(0),
26 DEBUG_ACCESS
= BIT(3),
27 DEBUG_LOOKUP
= BIT(4),
29 static int debug_mask
= DEBUG_FAILURE
;
30 module_param_named(debug_mask
, debug_mask
, int, S_IRUGO
| S_IWUSR
| S_IWGRP
);
32 static DEFINE_MUTEX(tree_lock
);
34 struct user_wake_lock
{
36 struct wake_lock wake_lock
;
39 struct rb_root user_wake_locks
;
41 static struct user_wake_lock
*lookup_wake_lock_name(
42 const char *buf
, int allocate
, long *timeoutptr
)
44 struct rb_node
**p
= &user_wake_locks
.rb_node
;
45 struct rb_node
*parent
= NULL
;
46 struct user_wake_lock
*l
;
52 /* Find length of lock name and start of optional timeout string */
54 while (*arg
&& !isspace(*arg
))
62 /* Process timeout string */
63 if (timeoutptr
&& *arg
) {
64 timeout
= simple_strtoull(arg
, (char **)&arg
, 0);
69 /* convert timeout from nanoseconds to jiffies > 0 */
70 timeout
+= (NSEC_PER_SEC
/ HZ
) - 1;
71 do_div(timeout
, (NSEC_PER_SEC
/ HZ
));
74 *timeoutptr
= timeout
;
80 /* Lookup wake lock in rbtree */
83 l
= rb_entry(parent
, struct user_wake_lock
, node
);
84 diff
= strncmp(buf
, l
->name
, name_len
);
85 if (!diff
&& l
->name
[name_len
])
87 if (debug_mask
& DEBUG_ERROR
)
88 pr_info("lookup_wake_lock_name: compare %.*s %s %d\n",
89 name_len
, buf
, l
->name
, diff
);
99 /* Allocate and add new wakelock to rbtree */
101 if (debug_mask
& DEBUG_ERROR
)
102 pr_info("lookup_wake_lock_name: %.*s not found\n",
104 return ERR_PTR(-EINVAL
);
106 l
= kzalloc(sizeof(*l
) + name_len
+ 1, GFP_KERNEL
);
108 if (debug_mask
& DEBUG_FAILURE
)
109 pr_err("lookup_wake_lock_name: failed to allocate "
110 "memory for %.*s\n", name_len
, buf
);
111 return ERR_PTR(-ENOMEM
);
113 memcpy(l
->name
, buf
, name_len
);
114 if (debug_mask
& DEBUG_NEW
)
115 pr_info("lookup_wake_lock_name: new wake lock %s\n", l
->name
);
116 wake_lock_init(&l
->wake_lock
, WAKE_LOCK_SUSPEND
, l
->name
);
117 rb_link_node(&l
->node
, parent
, p
);
118 rb_insert_color(&l
->node
, &user_wake_locks
);
122 if (debug_mask
& DEBUG_ERROR
)
123 pr_info("lookup_wake_lock_name: wake lock, %.*s, bad arg, %s\n",
125 return ERR_PTR(-EINVAL
);
128 ssize_t
wake_lock_show(
129 struct kobject
*kobj
, struct kobj_attribute
*attr
, char *buf
)
132 char *end
= buf
+ PAGE_SIZE
;
134 struct user_wake_lock
*l
;
136 mutex_lock(&tree_lock
);
138 for (n
= rb_first(&user_wake_locks
); n
!= NULL
; n
= rb_next(n
)) {
139 l
= rb_entry(n
, struct user_wake_lock
, node
);
140 if (wake_lock_active(&l
->wake_lock
))
141 s
+= scnprintf(s
, end
- s
, "%s ", l
->name
);
143 s
+= scnprintf(s
, end
- s
, "\n");
145 mutex_unlock(&tree_lock
);
149 ssize_t
wake_lock_store(
150 struct kobject
*kobj
, struct kobj_attribute
*attr
,
151 const char *buf
, size_t n
)
154 struct user_wake_lock
*l
;
156 mutex_lock(&tree_lock
);
157 l
= lookup_wake_lock_name(buf
, 1, &timeout
);
163 if (debug_mask
& DEBUG_ACCESS
)
164 pr_info("wake_lock_store: %s, timeout %ld\n", l
->name
, timeout
);
167 wake_lock_timeout(&l
->wake_lock
, timeout
);
169 wake_lock(&l
->wake_lock
);
171 mutex_unlock(&tree_lock
);
176 ssize_t
wake_unlock_show(
177 struct kobject
*kobj
, struct kobj_attribute
*attr
, char *buf
)
180 char *end
= buf
+ PAGE_SIZE
;
182 struct user_wake_lock
*l
;
184 mutex_lock(&tree_lock
);
186 for (n
= rb_first(&user_wake_locks
); n
!= NULL
; n
= rb_next(n
)) {
187 l
= rb_entry(n
, struct user_wake_lock
, node
);
188 if (!wake_lock_active(&l
->wake_lock
))
189 s
+= scnprintf(s
, end
- s
, "%s ", l
->name
);
191 s
+= scnprintf(s
, end
- s
, "\n");
193 mutex_unlock(&tree_lock
);
197 ssize_t
wake_unlock_store(
198 struct kobject
*kobj
, struct kobj_attribute
*attr
,
199 const char *buf
, size_t n
)
201 struct user_wake_lock
*l
;
203 mutex_lock(&tree_lock
);
204 l
= lookup_wake_lock_name(buf
, 0, NULL
);
210 if (debug_mask
& DEBUG_ACCESS
)
211 pr_info("wake_unlock_store: %s\n", l
->name
);
213 wake_unlock(&l
->wake_lock
);
215 mutex_unlock(&tree_lock
);