Esempio n. 1
0
int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)
{
	int err;

	err = rtc_valid_tm(tm);
	if (err != 0)
		return err;

	err = rtc_valid_range(rtc, tm);
	if (err)
		return err;

	rtc_subtract_offset(rtc, tm);

	err = mutex_lock_interruptible(&rtc->ops_lock);
	if (err)
		return err;

	if (!rtc->ops)
		err = -ENODEV;
	else if (rtc->ops->set_time)
		err = rtc->ops->set_time(rtc->dev.parent, tm);
	else
		err = -EINVAL;

	pm_stay_awake(rtc->dev.parent);
	mutex_unlock(&rtc->ops_lock);
	/* A timer might have just expired */
	schedule_work(&rtc->irqwork);

	trace_rtc_set_time(rtc_tm_to_time64(tm), err);
	return err;
}
Esempio n. 2
0
static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
{
	struct rtc_time tm;
	time64_t now, scheduled;
	int err;

	err = rtc_valid_tm(&alarm->time);
	if (err)
		return err;

	scheduled = rtc_tm_to_time64(&alarm->time);

	/* Make sure we're not setting alarms in the past */
	err = __rtc_read_time(rtc, &tm);
	if (err)
		return err;
	now = rtc_tm_to_time64(&tm);
	if (scheduled <= now)
		return -ETIME;
	/*
	 * XXX - We just checked to make sure the alarm time is not
	 * in the past, but there is still a race window where if
	 * the is alarm set for the next second and the second ticks
	 * over right here, before we set the alarm.
	 */

	rtc_subtract_offset(rtc, &alarm->time);

	if (!rtc->ops)
		err = -ENODEV;
	else if (!rtc->ops->set_alarm)
		err = -EINVAL;
	else
		err = rtc->ops->set_alarm(rtc->dev.parent, alarm);

	trace_rtc_set_alarm(rtc_tm_to_time64(&alarm->time), err);
	return err;
}