OSDN Git Service

Merge tag 'v3.10.52' into android-3.10
[android-x86/kernel.git] / kernel / time / alarmtimer.c
index f11d83b..28ef745 100644 (file)
@@ -199,6 +199,12 @@ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
 
 }
 
+ktime_t alarm_expires_remaining(const struct alarm *alarm)
+{
+       struct alarm_base *base = &alarm_bases[alarm->type];
+       return ktime_sub(alarm->node.expires, base->gettime());
+}
+
 #ifdef CONFIG_RTC_CLASS
 /**
  * alarmtimer_suspend - Suspend time callback
@@ -305,7 +311,7 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
 }
 
 /**
- * alarm_start - Sets an alarm to fire
+ * alarm_start - Sets an absolute alarm to fire
  * @alarm: ptr to alarm to set
  * @start: time to run the alarm
  */
@@ -325,6 +331,31 @@ int alarm_start(struct alarm *alarm, ktime_t start)
 }
 
 /**
+ * alarm_start_relative - Sets a relative alarm to fire
+ * @alarm: ptr to alarm to set
+ * @start: time relative to now to run the alarm
+ */
+int alarm_start_relative(struct alarm *alarm, ktime_t start)
+{
+       struct alarm_base *base = &alarm_bases[alarm->type];
+
+       start = ktime_add(start, base->gettime());
+       return alarm_start(alarm, start);
+}
+
+void alarm_restart(struct alarm *alarm)
+{
+       struct alarm_base *base = &alarm_bases[alarm->type];
+       unsigned long flags;
+
+       spin_lock_irqsave(&base->lock, flags);
+       hrtimer_set_expires(&alarm->timer, alarm->node.expires);
+       hrtimer_restart(&alarm->timer);
+       alarmtimer_enqueue(base, alarm);
+       spin_unlock_irqrestore(&base->lock, flags);
+}
+
+/**
  * alarm_try_to_cancel - Tries to cancel an alarm timer
  * @alarm: ptr to alarm to be canceled
  *
@@ -394,6 +425,12 @@ u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval)
        return overrun;
 }
 
+u64 alarm_forward_now(struct alarm *alarm, ktime_t interval)
+{
+       struct alarm_base *base = &alarm_bases[alarm->type];
+
+       return alarm_forward(alarm, base->gettime(), interval);
+}
 
 
 
@@ -445,7 +482,7 @@ static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp)
        clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid;
 
        if (!alarmtimer_get_rtcdev())
-               return -ENOTSUPP;
+               return -EINVAL;
 
        return hrtimer_get_res(baseid, tp);
 }
@@ -462,7 +499,7 @@ static int alarm_clock_get(clockid_t which_clock, struct timespec *tp)
        struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];
 
        if (!alarmtimer_get_rtcdev())
-               return -ENOTSUPP;
+               return -EINVAL;
 
        *tp = ktime_to_timespec(base->gettime());
        return 0;
@@ -540,9 +577,14 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
                                struct itimerspec *new_setting,
                                struct itimerspec *old_setting)
 {
+       ktime_t exp;
+
        if (!rtcdev)
                return -ENOTSUPP;
 
+       if (flags & ~TIMER_ABSTIME)
+               return -EINVAL;
+
        if (old_setting)
                alarm_timer_get(timr, old_setting);
 
@@ -552,8 +594,16 @@ static int alarm_timer_set(struct k_itimer *timr, int flags,
 
        /* start the timer */
        timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval);
-       alarm_start(&timr->it.alarm.alarmtimer,
-                       timespec_to_ktime(new_setting->it_value));
+       exp = timespec_to_ktime(new_setting->it_value);
+       /* Convert (if necessary) to absolute time */
+       if (flags != TIMER_ABSTIME) {
+               ktime_t now;
+
+               now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime();
+               exp = ktime_add(now, exp);
+       }
+
+       alarm_start(&timr->it.alarm.alarmtimer, exp);
        return 0;
 }
 
@@ -685,6 +735,9 @@ static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
        if (!alarmtimer_get_rtcdev())
                return -ENOTSUPP;
 
+       if (flags & ~TIMER_ABSTIME)
+               return -EINVAL;
+
        if (!capable(CAP_WAKE_ALARM))
                return -EPERM;