diff options
Diffstat (limited to 'drivers/rtc/interface.c')
| -rw-r--r-- | drivers/rtc/interface.c | 30 | 
1 files changed, 27 insertions, 3 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 8a1c031391d6..dc87eda65814 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -73,6 +73,8 @@ int rtc_set_time(struct rtc_device *rtc, struct rtc_time *tm)  		err = -EINVAL;  	mutex_unlock(&rtc->ops_lock); +	/* A timer might have just expired */ +	schedule_work(&rtc->irqwork);  	return err;  }  EXPORT_SYMBOL_GPL(rtc_set_time); @@ -112,6 +114,8 @@ int rtc_set_mmss(struct rtc_device *rtc, unsigned long secs)  		err = -EINVAL;  	mutex_unlock(&rtc->ops_lock); +	/* A timer might have just expired */ +	schedule_work(&rtc->irqwork);  	return err;  } @@ -380,18 +384,27 @@ EXPORT_SYMBOL_GPL(rtc_set_alarm);  int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)  {  	int err; +	struct rtc_time now;  	err = rtc_valid_tm(&alarm->time);  	if (err != 0)  		return err; +	err = rtc_read_time(rtc, &now); +	if (err) +		return err; +  	err = mutex_lock_interruptible(&rtc->ops_lock);  	if (err)  		return err;  	rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);  	rtc->aie_timer.period = ktime_set(0, 0); -	if (alarm->enabled) { + +	/* Alarm has to be enabled & in the futrure for us to enqueue it */ +	if (alarm->enabled && (rtc_tm_to_ktime(now).tv64 < +			 rtc->aie_timer.node.expires.tv64)) { +  		rtc->aie_timer.enabled = 1;  		timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node);  	} @@ -763,6 +776,14 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)  	return 0;  } +static void rtc_alarm_disable(struct rtc_device *rtc) +{ +	if (!rtc->ops || !rtc->ops->alarm_irq_enable) +		return; + +	rtc->ops->alarm_irq_enable(rtc->dev.parent, false); +} +  /**   * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue   * @rtc rtc device @@ -784,8 +805,10 @@ static void rtc_timer_remove(struct rtc_device *rtc, struct rtc_timer *timer)  		struct rtc_wkalrm alarm;  		int err;  		next = timerqueue_getnext(&rtc->timerqueue); -		if (!next) +		if (!next) { +			rtc_alarm_disable(rtc);  			return; +		}  		alarm.time = rtc_ktime_to_tm(next->expires);  		alarm.enabled = 1;  		err = __rtc_set_alarm(rtc, &alarm); @@ -847,7 +870,8 @@ again:  		err = __rtc_set_alarm(rtc, &alarm);  		if (err == -ETIME)  			goto again; -	} +	} else +		rtc_alarm_disable(rtc);  	mutex_unlock(&rtc->ops_lock);  }  | 
