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