~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/base/power/wakeup.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
24
24
 */
25
25
bool events_check_enabled;
26
26
 
27
 
/* The counter of registered wakeup events. */
28
 
static atomic_t event_count = ATOMIC_INIT(0);
29
 
/* A preserved old value of event_count. */
 
27
/*
 
28
 * Combined counters of registered wakeup events and wakeup events in progress.
 
29
 * They need to be modified together atomically, so it's better to use one
 
30
 * atomic variable to hold them both.
 
31
 */
 
32
static atomic_t combined_event_count = ATOMIC_INIT(0);
 
33
 
 
34
#define IN_PROGRESS_BITS        (sizeof(int) * 4)
 
35
#define MAX_IN_PROGRESS         ((1 << IN_PROGRESS_BITS) - 1)
 
36
 
 
37
static void split_counters(unsigned int *cnt, unsigned int *inpr)
 
38
{
 
39
        unsigned int comb = atomic_read(&combined_event_count);
 
40
 
 
41
        *cnt = (comb >> IN_PROGRESS_BITS);
 
42
        *inpr = comb & MAX_IN_PROGRESS;
 
43
}
 
44
 
 
45
/* A preserved old value of the events counter. */
30
46
static unsigned int saved_count;
31
 
/* The counter of wakeup events being processed. */
32
 
static atomic_t events_in_progress = ATOMIC_INIT(0);
33
47
 
34
48
static DEFINE_SPINLOCK(events_lock);
35
49
 
96
110
        spin_lock_irq(&events_lock);
97
111
        list_add_rcu(&ws->entry, &wakeup_sources);
98
112
        spin_unlock_irq(&events_lock);
99
 
        synchronize_rcu();
100
113
}
101
114
EXPORT_SYMBOL_GPL(wakeup_source_add);
102
115
 
228
241
EXPORT_SYMBOL_GPL(device_wakeup_disable);
229
242
 
230
243
/**
 
244
 * device_set_wakeup_capable - Set/reset device wakeup capability flag.
 
245
 * @dev: Device to handle.
 
246
 * @capable: Whether or not @dev is capable of waking up the system from sleep.
 
247
 *
 
248
 * If @capable is set, set the @dev's power.can_wakeup flag and add its
 
249
 * wakeup-related attributes to sysfs.  Otherwise, unset the @dev's
 
250
 * power.can_wakeup flag and remove its wakeup-related attributes from sysfs.
 
251
 *
 
252
 * This function may sleep and it can't be called from any context where
 
253
 * sleeping is not allowed.
 
254
 */
 
255
void device_set_wakeup_capable(struct device *dev, bool capable)
 
256
{
 
257
        if (!!dev->power.can_wakeup == !!capable)
 
258
                return;
 
259
 
 
260
        if (device_is_registered(dev) && !list_empty(&dev->power.entry)) {
 
261
                if (capable) {
 
262
                        if (wakeup_sysfs_add(dev))
 
263
                                return;
 
264
                } else {
 
265
                        wakeup_sysfs_remove(dev);
 
266
                }
 
267
        }
 
268
        dev->power.can_wakeup = capable;
 
269
}
 
270
EXPORT_SYMBOL_GPL(device_set_wakeup_capable);
 
271
 
 
272
/**
231
273
 * device_init_wakeup - Device wakeup initialization.
232
274
 * @dev: Device to handle.
233
275
 * @enable: Whether or not to enable @dev as a wakeup device.
307
349
        ws->timer_expires = jiffies;
308
350
        ws->last_time = ktime_get();
309
351
 
310
 
        atomic_inc(&events_in_progress);
 
352
        /* Increment the counter of events in progress. */
 
353
        atomic_inc(&combined_event_count);
311
354
}
312
355
 
313
356
/**
394
437
        del_timer(&ws->timer);
395
438
 
396
439
        /*
397
 
         * event_count has to be incremented before events_in_progress is
398
 
         * modified, so that the callers of pm_check_wakeup_events() and
399
 
         * pm_save_wakeup_count() don't see the old value of event_count and
400
 
         * events_in_progress equal to zero at the same time.
 
440
         * Increment the counter of registered wakeup events and decrement the
 
441
         * couter of wakeup events in progress simultaneously.
401
442
         */
402
 
        atomic_inc(&event_count);
403
 
        smp_mb__before_atomic_dec();
404
 
        atomic_dec(&events_in_progress);
 
443
        atomic_add(MAX_IN_PROGRESS, &combined_event_count);
405
444
}
406
445
 
407
446
/**
556
595
 
557
596
        spin_lock_irqsave(&events_lock, flags);
558
597
        if (events_check_enabled) {
559
 
                ret = ((unsigned int)atomic_read(&event_count) != saved_count)
560
 
                        || atomic_read(&events_in_progress);
 
598
                unsigned int cnt, inpr;
 
599
 
 
600
                split_counters(&cnt, &inpr);
 
601
                ret = (cnt != saved_count || inpr > 0);
561
602
                events_check_enabled = !ret;
562
603
        }
563
604
        spin_unlock_irqrestore(&events_lock, flags);
573
614
 * Store the number of registered wakeup events at the address in @count.  Block
574
615
 * if the current number of wakeup events being processed is nonzero.
575
616
 *
576
 
 * Return false if the wait for the number of wakeup events being processed to
 
617
 * Return 'false' if the wait for the number of wakeup events being processed to
577
618
 * drop down to zero has been interrupted by a signal (and the current number
578
 
 * of wakeup events being processed is still nonzero).  Otherwise return true.
 
619
 * of wakeup events being processed is still nonzero).  Otherwise return 'true'.
579
620
 */
580
621
bool pm_get_wakeup_count(unsigned int *count)
581
622
{
582
 
        bool ret;
583
 
 
584
 
        if (capable(CAP_SYS_ADMIN))
585
 
                events_check_enabled = false;
586
 
 
587
 
        while (atomic_read(&events_in_progress) && !signal_pending(current)) {
 
623
        unsigned int cnt, inpr;
 
624
 
 
625
        for (;;) {
 
626
                split_counters(&cnt, &inpr);
 
627
                if (inpr == 0 || signal_pending(current))
 
628
                        break;
588
629
                pm_wakeup_update_hit_counts();
589
630
                schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
590
631
        }
591
632
 
592
 
        ret = !atomic_read(&events_in_progress);
593
 
        *count = atomic_read(&event_count);
594
 
        return ret;
 
633
        split_counters(&cnt, &inpr);
 
634
        *count = cnt;
 
635
        return !inpr;
595
636
}
596
637
 
597
638
/**
600
641
 *
601
642
 * If @count is equal to the current number of registered wakeup events and the
602
643
 * current number of wakeup events being processed is zero, store @count as the
603
 
 * old number of registered wakeup events to be used by pm_check_wakeup_events()
604
 
 * and return true.  Otherwise return false.
 
644
 * old number of registered wakeup events for pm_check_wakeup_events(), enable
 
645
 * wakeup events detection and return 'true'.  Otherwise disable wakeup events
 
646
 * detection and return 'false'.
605
647
 */
606
648
bool pm_save_wakeup_count(unsigned int count)
607
649
{
608
 
        bool ret = false;
 
650
        unsigned int cnt, inpr;
609
651
 
 
652
        events_check_enabled = false;
610
653
        spin_lock_irq(&events_lock);
611
 
        if (count == (unsigned int)atomic_read(&event_count)
612
 
            && !atomic_read(&events_in_progress)) {
 
654
        split_counters(&cnt, &inpr);
 
655
        if (cnt == count && inpr == 0) {
613
656
                saved_count = count;
614
657
                events_check_enabled = true;
615
 
                ret = true;
616
658
        }
617
659
        spin_unlock_irq(&events_lock);
618
 
        if (!ret)
 
660
        if (!events_check_enabled)
619
661
                pm_wakeup_update_hit_counts();
620
 
        return ret;
 
662
        return events_check_enabled;
621
663
}
622
664
 
623
665
static struct dentry *wakeup_sources_stats_dentry;