• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* kernel/power/wakelock.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 
16 #include <linux/module.h>
17 #include <linux/platform_device.h>
18 #include <linux/rtc.h>
19 #include <linux/suspend.h>
20 #include <linux/syscalls.h> /* sys_sync */
21 #include <linux/wakelock.h>
22 #ifdef CONFIG_WAKELOCK_STAT
23 #include <linux/proc_fs.h>
24 #endif
25 #include "power.h"
26 
27 enum {
28 	DEBUG_EXIT_SUSPEND = 1U << 0,
29 	DEBUG_WAKEUP = 1U << 1,
30 	DEBUG_SUSPEND = 1U << 2,
31 	DEBUG_EXPIRE = 1U << 3,
32 	DEBUG_WAKE_LOCK = 1U << 4,
33 };
34 static int debug_mask = DEBUG_EXIT_SUSPEND | DEBUG_WAKEUP;
35 module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
36 
37 #define WAKE_LOCK_TYPE_MASK              (0x0f)
38 #define WAKE_LOCK_INITIALIZED            (1U << 8)
39 #define WAKE_LOCK_ACTIVE                 (1U << 9)
40 #define WAKE_LOCK_AUTO_EXPIRE            (1U << 10)
41 #define WAKE_LOCK_PREVENTING_SUSPEND     (1U << 11)
42 
43 #define TOO_MAY_LOCKS_WARNING		"\n\ntoo many wakelocks!!!\n"
44 
45 static DEFINE_SPINLOCK(list_lock);
46 static LIST_HEAD(inactive_locks);
47 static struct list_head active_wake_locks[WAKE_LOCK_TYPE_COUNT];
48 static int current_event_num;
49 struct workqueue_struct *suspend_work_queue;
50 struct wake_lock main_wake_lock;
51 suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
52 static struct wake_lock unknown_wakeup;
53 
54 #ifdef CONFIG_WAKELOCK_STAT
55 static struct wake_lock deleted_wake_locks;
56 static ktime_t last_sleep_time_update;
57 static int wait_for_wakeup;
58 
get_expired_time(struct wake_lock * lock,ktime_t * expire_time)59 int get_expired_time(struct wake_lock *lock, ktime_t *expire_time)
60 {
61 	struct timespec ts;
62 	struct timespec kt;
63 	struct timespec tomono;
64 	struct timespec delta;
65 	unsigned long seq;
66 	long timeout;
67 
68 	if (!(lock->flags & WAKE_LOCK_AUTO_EXPIRE))
69 		return 0;
70 	do {
71 		seq = read_seqbegin(&xtime_lock);
72 		timeout = lock->expires - jiffies;
73 		if (timeout > 0)
74 			return 0;
75 		kt = current_kernel_time();
76 		tomono = wall_to_monotonic;
77 	} while (read_seqretry(&xtime_lock, seq));
78 	jiffies_to_timespec(-timeout, &delta);
79 	set_normalized_timespec(&ts, kt.tv_sec + tomono.tv_sec - delta.tv_sec,
80 				kt.tv_nsec + tomono.tv_nsec - delta.tv_nsec);
81 	*expire_time = timespec_to_ktime(ts);
82 	return 1;
83 }
84 
85 
print_lock_stat(char * buf,int len,struct wake_lock * lock)86 static int print_lock_stat(char *buf, int len, struct wake_lock *lock)
87 {
88 	int lock_count = lock->stat.count;
89 	int expire_count = lock->stat.expire_count;
90 	ktime_t active_time = ktime_set(0, 0);
91 	ktime_t total_time = lock->stat.total_time;
92 	ktime_t max_time = lock->stat.max_time;
93 	int n;
94 
95 	ktime_t prevent_suspend_time = lock->stat.prevent_suspend_time;
96 	if (lock->flags & WAKE_LOCK_ACTIVE) {
97 		ktime_t now, add_time;
98 		int expired = get_expired_time(lock, &now);
99 		if (!expired)
100 			now = ktime_get();
101 		add_time = ktime_sub(now, lock->stat.last_time);
102 		lock_count++;
103 		if (!expired)
104 			active_time = add_time;
105 		else
106 			expire_count++;
107 		total_time = ktime_add(total_time, add_time);
108 		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND)
109 			prevent_suspend_time = ktime_add(prevent_suspend_time,
110 					ktime_sub(now, last_sleep_time_update));
111 		if (add_time.tv64 > max_time.tv64)
112 			max_time = add_time;
113 	}
114 
115 	n = snprintf(buf, len,
116 		     "\"%s\"\t%d\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t%lld\n",
117 		     lock->name, lock_count, expire_count,
118 		     lock->stat.wakeup_count, ktime_to_ns(active_time),
119 		     ktime_to_ns(total_time),
120 		     ktime_to_ns(prevent_suspend_time), ktime_to_ns(max_time),
121 		     ktime_to_ns(lock->stat.last_time));
122 
123 	return n > len ? len : n;
124 }
125 
126 
wakelocks_read_proc(char * page,char ** start,off_t off,int count,int * eof,void * data)127 static int wakelocks_read_proc(char *page, char **start, off_t off,
128 			       int count, int *eof, void *data)
129 {
130 	unsigned long irqflags;
131 	struct wake_lock *lock;
132 	int len = 0;
133 	int type;
134 
135 	spin_lock_irqsave(&list_lock, irqflags);
136 
137 	len += snprintf(page + len, count - len,
138 			"name\tcount\texpire_count\twake_count\tactive_since"
139 			"\ttotal_time\tsleep_time\tmax_time\tlast_change\n");
140 	list_for_each_entry(lock, &inactive_locks, link) {
141 		len += print_lock_stat(page + len, count - len, lock);
142 	}
143 	for (type = 0; type < WAKE_LOCK_TYPE_COUNT; type++) {
144 		list_for_each_entry(lock, &active_wake_locks[type], link)
145 			len += print_lock_stat(page + len, count - len, lock);
146 	}
147 	spin_unlock_irqrestore(&list_lock, irqflags);
148 
149 	if (len == count)
150 		memcpy(page + len - strlen(TOO_MAY_LOCKS_WARNING),
151 		       TOO_MAY_LOCKS_WARNING,
152 		       strlen(TOO_MAY_LOCKS_WARNING));
153 
154 	*eof = 1;
155 
156 	return len;
157 }
158 
wake_unlock_stat_locked(struct wake_lock * lock,int expired)159 static void wake_unlock_stat_locked(struct wake_lock *lock, int expired)
160 {
161 	ktime_t duration;
162 	ktime_t now;
163 	if (!(lock->flags & WAKE_LOCK_ACTIVE))
164 		return;
165 	if (get_expired_time(lock, &now))
166 		expired = 1;
167 	else
168 		now = ktime_get();
169 	lock->stat.count++;
170 	if (expired)
171 		lock->stat.expire_count++;
172 	duration = ktime_sub(now, lock->stat.last_time);
173 	lock->stat.total_time = ktime_add(lock->stat.total_time, duration);
174 	if (ktime_to_ns(duration) > ktime_to_ns(lock->stat.max_time))
175 		lock->stat.max_time = duration;
176 	lock->stat.last_time = ktime_get();
177 	if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
178 		duration = ktime_sub(now, last_sleep_time_update);
179 		lock->stat.prevent_suspend_time = ktime_add(
180 			lock->stat.prevent_suspend_time, duration);
181 		lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
182 	}
183 }
184 
update_sleep_wait_stats_locked(int done)185 static void update_sleep_wait_stats_locked(int done)
186 {
187 	struct wake_lock *lock;
188 	ktime_t now, etime, elapsed, add;
189 	int expired;
190 
191 	now = ktime_get();
192 	elapsed = ktime_sub(now, last_sleep_time_update);
193 	list_for_each_entry(lock, &active_wake_locks[WAKE_LOCK_SUSPEND], link) {
194 		expired = get_expired_time(lock, &etime);
195 		if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
196 			if (expired)
197 				add = ktime_sub(etime, last_sleep_time_update);
198 			else
199 				add = elapsed;
200 			lock->stat.prevent_suspend_time = ktime_add(
201 				lock->stat.prevent_suspend_time, add);
202 		}
203 		if (done || expired)
204 			lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
205 		else
206 			lock->flags |= WAKE_LOCK_PREVENTING_SUSPEND;
207 	}
208 	last_sleep_time_update = now;
209 }
210 #endif
211 
212 
expire_wake_lock(struct wake_lock * lock)213 static void expire_wake_lock(struct wake_lock *lock)
214 {
215 #ifdef CONFIG_WAKELOCK_STAT
216 	wake_unlock_stat_locked(lock, 1);
217 #endif
218 	lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
219 	list_del(&lock->link);
220 	list_add(&lock->link, &inactive_locks);
221 	if (debug_mask & (DEBUG_WAKE_LOCK | DEBUG_EXPIRE))
222 		pr_info("expired wake lock %s\n", lock->name);
223 }
224 
225 /* Caller must acquire the list_lock spinlock */
print_active_locks(int type)226 static void print_active_locks(int type)
227 {
228 	unsigned long irqflags;
229 	struct wake_lock *lock;
230 
231 	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
232 	list_for_each_entry(lock, &active_wake_locks[type], link) {
233 		if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
234 			long timeout = lock->expires - jiffies;
235 			if (timeout <= 0)
236 				pr_info("wake lock %s, expired\n", lock->name);
237 			else
238 				pr_info("active wake lock %s, time left %ld\n",
239 					lock->name, timeout);
240 		} else
241 			pr_info("active wake lock %s\n", lock->name);
242 	}
243 }
244 
has_wake_lock_locked(int type)245 static long has_wake_lock_locked(int type)
246 {
247 	struct wake_lock *lock, *n;
248 	long max_timeout = 0;
249 
250 	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
251 	list_for_each_entry_safe(lock, n, &active_wake_locks[type], link) {
252 		if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
253 			long timeout = lock->expires - jiffies;
254 			if (timeout <= 0)
255 				expire_wake_lock(lock);
256 			else if (timeout > max_timeout)
257 				max_timeout = timeout;
258 		} else
259 			return -1;
260 	}
261 	return max_timeout;
262 }
263 
has_wake_lock(int type)264 long has_wake_lock(int type)
265 {
266 	long ret;
267 	unsigned long irqflags;
268 	spin_lock_irqsave(&list_lock, irqflags);
269 	ret = has_wake_lock_locked(type);
270 	spin_unlock_irqrestore(&list_lock, irqflags);
271 	return ret;
272 }
273 
suspend(struct work_struct * work)274 static void suspend(struct work_struct *work)
275 {
276 	int ret;
277 	int entry_event_num;
278 
279 	if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
280 		if (debug_mask & DEBUG_SUSPEND)
281 			pr_info("suspend: abort suspend\n");
282 		return;
283 	}
284 
285 	entry_event_num = current_event_num;
286 	sys_sync();
287 	if (debug_mask & DEBUG_SUSPEND)
288 		pr_info("suspend: enter suspend\n");
289 	ret = pm_suspend(requested_suspend_state);
290 	if (debug_mask & DEBUG_EXIT_SUSPEND) {
291 		struct timespec ts;
292 		struct rtc_time tm;
293 		getnstimeofday(&ts);
294 		rtc_time_to_tm(ts.tv_sec, &tm);
295 		pr_info("suspend: exit suspend, ret = %d "
296 			"(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n", ret,
297 			tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
298 			tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
299 	}
300 	if (current_event_num == entry_event_num) {
301 		if (debug_mask & DEBUG_SUSPEND)
302 			pr_info("suspend: pm_suspend returned with no event\n");
303 		wake_lock_timeout(&unknown_wakeup, HZ / 2);
304 	}
305 }
306 static DECLARE_WORK(suspend_work, suspend);
307 
expire_wake_locks(unsigned long data)308 static void expire_wake_locks(unsigned long data)
309 {
310 	long has_lock;
311 	unsigned long irqflags;
312 	if (debug_mask & DEBUG_EXPIRE)
313 		pr_info("expire_wake_locks: start\n");
314 	spin_lock_irqsave(&list_lock, irqflags);
315 	if (debug_mask & DEBUG_SUSPEND)
316 		print_active_locks(WAKE_LOCK_SUSPEND);
317 	has_lock = has_wake_lock_locked(WAKE_LOCK_SUSPEND);
318 	if (debug_mask & DEBUG_EXPIRE)
319 		pr_info("expire_wake_locks: done, has_lock %ld\n", has_lock);
320 	if (has_lock == 0)
321 		queue_work(suspend_work_queue, &suspend_work);
322 	spin_unlock_irqrestore(&list_lock, irqflags);
323 }
324 static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);
325 
power_suspend_late(struct platform_device * pdev,pm_message_t state)326 static int power_suspend_late(struct platform_device *pdev, pm_message_t state)
327 {
328 	int ret = has_wake_lock(WAKE_LOCK_SUSPEND) ? -EAGAIN : 0;
329 #ifdef CONFIG_WAKELOCK_STAT
330 	wait_for_wakeup = 1;
331 #endif
332 	if (debug_mask & DEBUG_SUSPEND)
333 		pr_info("power_suspend_late return %d\n", ret);
334 	return ret;
335 }
336 
337 static struct platform_driver power_driver = {
338 	.driver.name = "power",
339 	.suspend_late = power_suspend_late,
340 };
341 static struct platform_device power_device = {
342 	.name = "power",
343 };
344 
wake_lock_init(struct wake_lock * lock,int type,const char * name)345 void wake_lock_init(struct wake_lock *lock, int type, const char *name)
346 {
347 	unsigned long irqflags = 0;
348 
349 	if (name)
350 		lock->name = name;
351 	BUG_ON(!lock->name);
352 
353 	if (debug_mask & DEBUG_WAKE_LOCK)
354 		pr_info("wake_lock_init name=%s\n", lock->name);
355 #ifdef CONFIG_WAKELOCK_STAT
356 	lock->stat.count = 0;
357 	lock->stat.expire_count = 0;
358 	lock->stat.wakeup_count = 0;
359 	lock->stat.total_time = ktime_set(0, 0);
360 	lock->stat.prevent_suspend_time = ktime_set(0, 0);
361 	lock->stat.max_time = ktime_set(0, 0);
362 	lock->stat.last_time = ktime_set(0, 0);
363 #endif
364 	lock->flags = (type & WAKE_LOCK_TYPE_MASK) | WAKE_LOCK_INITIALIZED;
365 
366 	INIT_LIST_HEAD(&lock->link);
367 	spin_lock_irqsave(&list_lock, irqflags);
368 	list_add(&lock->link, &inactive_locks);
369 	spin_unlock_irqrestore(&list_lock, irqflags);
370 }
371 EXPORT_SYMBOL(wake_lock_init);
372 
wake_lock_destroy(struct wake_lock * lock)373 void wake_lock_destroy(struct wake_lock *lock)
374 {
375 	unsigned long irqflags;
376 	if (debug_mask & DEBUG_WAKE_LOCK)
377 		pr_info("wake_lock_destroy name=%s\n", lock->name);
378 	spin_lock_irqsave(&list_lock, irqflags);
379 	lock->flags &= ~WAKE_LOCK_INITIALIZED;
380 #ifdef CONFIG_WAKELOCK_STAT
381 	if (lock->stat.count) {
382 		deleted_wake_locks.stat.count += lock->stat.count;
383 		deleted_wake_locks.stat.expire_count += lock->stat.expire_count;
384 		deleted_wake_locks.stat.total_time =
385 			ktime_add(deleted_wake_locks.stat.total_time,
386 				  lock->stat.total_time);
387 		deleted_wake_locks.stat.prevent_suspend_time =
388 			ktime_add(deleted_wake_locks.stat.prevent_suspend_time,
389 				  lock->stat.prevent_suspend_time);
390 		deleted_wake_locks.stat.max_time =
391 			ktime_add(deleted_wake_locks.stat.max_time,
392 				  lock->stat.max_time);
393 	}
394 #endif
395 	list_del(&lock->link);
396 	spin_unlock_irqrestore(&list_lock, irqflags);
397 }
398 EXPORT_SYMBOL(wake_lock_destroy);
399 
wake_lock_internal(struct wake_lock * lock,long timeout,int has_timeout)400 static void wake_lock_internal(
401 	struct wake_lock *lock, long timeout, int has_timeout)
402 {
403 	int type;
404 	unsigned long irqflags;
405 	long expire_in;
406 
407 	spin_lock_irqsave(&list_lock, irqflags);
408 	type = lock->flags & WAKE_LOCK_TYPE_MASK;
409 	BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
410 	BUG_ON(!(lock->flags & WAKE_LOCK_INITIALIZED));
411 #ifdef CONFIG_WAKELOCK_STAT
412 	if (type == WAKE_LOCK_SUSPEND && wait_for_wakeup) {
413 		if (debug_mask & DEBUG_WAKEUP)
414 			pr_info("wakeup wake lock: %s\n", lock->name);
415 		wait_for_wakeup = 0;
416 		lock->stat.wakeup_count++;
417 	}
418 	if ((lock->flags & WAKE_LOCK_AUTO_EXPIRE) &&
419 	    (long)(lock->expires - jiffies) <= 0) {
420 		wake_unlock_stat_locked(lock, 0);
421 		lock->stat.last_time = ktime_get();
422 	}
423 #endif
424 	if (!(lock->flags & WAKE_LOCK_ACTIVE)) {
425 		lock->flags |= WAKE_LOCK_ACTIVE;
426 #ifdef CONFIG_WAKELOCK_STAT
427 		lock->stat.last_time = ktime_get();
428 #endif
429 	}
430 	list_del(&lock->link);
431 	if (has_timeout) {
432 		if (debug_mask & DEBUG_WAKE_LOCK)
433 			pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n",
434 				lock->name, type, timeout / HZ,
435 				(timeout % HZ) * MSEC_PER_SEC / HZ);
436 		lock->expires = jiffies + timeout;
437 		lock->flags |= WAKE_LOCK_AUTO_EXPIRE;
438 		list_add_tail(&lock->link, &active_wake_locks[type]);
439 	} else {
440 		if (debug_mask & DEBUG_WAKE_LOCK)
441 			pr_info("wake_lock: %s, type %d\n", lock->name, type);
442 		lock->expires = LONG_MAX;
443 		lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE;
444 		list_add(&lock->link, &active_wake_locks[type]);
445 	}
446 	if (type == WAKE_LOCK_SUSPEND) {
447 		current_event_num++;
448 #ifdef CONFIG_WAKELOCK_STAT
449 		if (lock == &main_wake_lock)
450 			update_sleep_wait_stats_locked(1);
451 		else if (!wake_lock_active(&main_wake_lock))
452 			update_sleep_wait_stats_locked(0);
453 #endif
454 		if (has_timeout)
455 			expire_in = has_wake_lock_locked(type);
456 		else
457 			expire_in = -1;
458 		if (expire_in > 0) {
459 			if (debug_mask & DEBUG_EXPIRE)
460 				pr_info("wake_lock: %s, start expire timer, "
461 					"%ld\n", lock->name, expire_in);
462 			mod_timer(&expire_timer, jiffies + expire_in);
463 		} else {
464 			if (del_timer(&expire_timer))
465 				if (debug_mask & DEBUG_EXPIRE)
466 					pr_info("wake_lock: %s, stop expire timer\n",
467 						lock->name);
468 			if (expire_in == 0)
469 				queue_work(suspend_work_queue, &suspend_work);
470 		}
471 	}
472 	spin_unlock_irqrestore(&list_lock, irqflags);
473 }
474 
wake_lock(struct wake_lock * lock)475 void wake_lock(struct wake_lock *lock)
476 {
477 	wake_lock_internal(lock, 0, 0);
478 }
479 EXPORT_SYMBOL(wake_lock);
480 
wake_lock_timeout(struct wake_lock * lock,long timeout)481 void wake_lock_timeout(struct wake_lock *lock, long timeout)
482 {
483 	wake_lock_internal(lock, timeout, 1);
484 }
485 EXPORT_SYMBOL(wake_lock_timeout);
486 
wake_unlock(struct wake_lock * lock)487 void wake_unlock(struct wake_lock *lock)
488 {
489 	int type;
490 	unsigned long irqflags;
491 	spin_lock_irqsave(&list_lock, irqflags);
492 	type = lock->flags & WAKE_LOCK_TYPE_MASK;
493 #ifdef CONFIG_WAKELOCK_STAT
494 	wake_unlock_stat_locked(lock, 0);
495 #endif
496 	if (debug_mask & DEBUG_WAKE_LOCK)
497 		pr_info("wake_unlock: %s\n", lock->name);
498 	lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
499 	list_del(&lock->link);
500 	list_add(&lock->link, &inactive_locks);
501 	if (type == WAKE_LOCK_SUSPEND) {
502 		long has_lock = has_wake_lock_locked(type);
503 		if (has_lock > 0) {
504 			if (debug_mask & DEBUG_EXPIRE)
505 				pr_info("wake_unlock: %s, start expire timer, "
506 					"%ld\n", lock->name, has_lock);
507 			mod_timer(&expire_timer, jiffies + has_lock);
508 		} else {
509 			if (del_timer(&expire_timer))
510 				if (debug_mask & DEBUG_EXPIRE)
511 					pr_info("wake_unlock: %s, stop expire "
512 						"timer\n", lock->name);
513 			if (has_lock == 0)
514 				queue_work(suspend_work_queue, &suspend_work);
515 		}
516 		if (lock == &main_wake_lock) {
517 			if (debug_mask & DEBUG_SUSPEND)
518 				print_active_locks(WAKE_LOCK_SUSPEND);
519 #ifdef CONFIG_WAKELOCK_STAT
520 			update_sleep_wait_stats_locked(0);
521 #endif
522 		}
523 	}
524 	spin_unlock_irqrestore(&list_lock, irqflags);
525 }
526 EXPORT_SYMBOL(wake_unlock);
527 
wake_lock_active(struct wake_lock * lock)528 int wake_lock_active(struct wake_lock *lock)
529 {
530 	return !!(lock->flags & WAKE_LOCK_ACTIVE);
531 }
532 EXPORT_SYMBOL(wake_lock_active);
533 
wakelocks_init(void)534 static int __init wakelocks_init(void)
535 {
536 	int ret;
537 	int i;
538 
539 	for (i = 0; i < ARRAY_SIZE(active_wake_locks); i++)
540 		INIT_LIST_HEAD(&active_wake_locks[i]);
541 
542 #ifdef CONFIG_WAKELOCK_STAT
543 	wake_lock_init(&deleted_wake_locks, WAKE_LOCK_SUSPEND,
544 			"deleted_wake_locks");
545 #endif
546 	wake_lock_init(&main_wake_lock, WAKE_LOCK_SUSPEND, "main");
547 	wake_lock(&main_wake_lock);
548 	wake_lock_init(&unknown_wakeup, WAKE_LOCK_SUSPEND, "unknown_wakeups");
549 
550 	ret = platform_device_register(&power_device);
551 	if (ret) {
552 		pr_err("wakelocks_init: platform_device_register failed\n");
553 		goto err_platform_device_register;
554 	}
555 	ret = platform_driver_register(&power_driver);
556 	if (ret) {
557 		pr_err("wakelocks_init: platform_driver_register failed\n");
558 		goto err_platform_driver_register;
559 	}
560 
561 	suspend_work_queue = create_singlethread_workqueue("suspend");
562 	if (suspend_work_queue == NULL) {
563 		ret = -ENOMEM;
564 		goto err_suspend_work_queue;
565 	}
566 
567 #ifdef CONFIG_WAKELOCK_STAT
568 	create_proc_read_entry("wakelocks", S_IRUGO, NULL,
569 				wakelocks_read_proc, NULL);
570 #endif
571 
572 	return 0;
573 
574 err_suspend_work_queue:
575 	platform_driver_unregister(&power_driver);
576 err_platform_driver_register:
577 	platform_device_unregister(&power_device);
578 err_platform_device_register:
579 	wake_lock_destroy(&unknown_wakeup);
580 	wake_lock_destroy(&main_wake_lock);
581 #ifdef CONFIG_WAKELOCK_STAT
582 	wake_lock_destroy(&deleted_wake_locks);
583 #endif
584 	return ret;
585 }
586 
wakelocks_exit(void)587 static void  __exit wakelocks_exit(void)
588 {
589 #ifdef CONFIG_WAKELOCK_STAT
590 	remove_proc_entry("wakelocks", NULL);
591 #endif
592 	destroy_workqueue(suspend_work_queue);
593 	platform_driver_unregister(&power_driver);
594 	platform_device_unregister(&power_device);
595 	wake_lock_destroy(&unknown_wakeup);
596 	wake_lock_destroy(&main_wake_lock);
597 #ifdef CONFIG_WAKELOCK_STAT
598 	wake_lock_destroy(&deleted_wake_locks);
599 #endif
600 }
601 
602 core_initcall(wakelocks_init);
603 module_exit(wakelocks_exit);
604