diff options
| author | Rabin Vincent <rabin.vincent@stericsson.com> | 2011-11-22 11:03:14 +0100 | 
|---|---|---|
| committer | John Stultz <john.stultz@linaro.org> | 2011-11-22 19:25:43 -0800 | 
| commit | c0afabd3d553c521e003779c127143ffde55a16f (patch) | |
| tree | 5a4a93f244e2e9cbc87f24958de3e83397f978fb /drivers/rtc/interface.c | |
| parent | 27c9cd7e601632b3794e1c3344d37b86917ffb43 (diff) | |
| download | olio-linux-3.10-c0afabd3d553c521e003779c127143ffde55a16f.tar.xz olio-linux-3.10-c0afabd3d553c521e003779c127143ffde55a16f.zip  | |
rtc: Disable the alarm in the hardware
Currently, the RTC code does not disable the alarm in the hardware.
This means that after a sequence such as the one below (the files are in the
RTC sysfs), the box will boot up after 2 minutes even though we've
asked for the alarm to be turned off.
	# echo $((`cat since_epoch`)+120) > wakealarm
	# echo 0 > wakealarm
	# poweroff
Fix this by disabling the alarm when there are no timers to run.
Cc: stable@kernel.org
Cc: John Stultz <john.stultz@linaro.org>
Signed-off-by: Rabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Diffstat (limited to 'drivers/rtc/interface.c')
| -rw-r--r-- | drivers/rtc/interface.c | 44 | 
1 files changed, 34 insertions, 10 deletions
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 3195dbd3ec3..e3cf2f54221 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -318,6 +318,20 @@ int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)  }  EXPORT_SYMBOL_GPL(rtc_read_alarm); +static int ___rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) +{ +	int err; + +	if (!rtc->ops) +		err = -ENODEV; +	else if (!rtc->ops->set_alarm) +		err = -EINVAL; +	else +		err = rtc->ops->set_alarm(rtc->dev.parent, alarm); + +	return err; +} +  static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)  {  	struct rtc_time tm; @@ -341,14 +355,7 @@ static int __rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)  	 * over right here, before we set the alarm.  	 */ -	if (!rtc->ops) -		err = -ENODEV; -	else if (!rtc->ops->set_alarm) -		err = -EINVAL; -	else -		err = rtc->ops->set_alarm(rtc->dev.parent, alarm); - -	return err; +	return ___rtc_set_alarm(rtc, alarm);  }  int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) @@ -762,6 +769,20 @@ static int rtc_timer_enqueue(struct rtc_device *rtc, struct rtc_timer *timer)  	return 0;  } +static void rtc_alarm_disable(struct rtc_device *rtc) +{ +	struct rtc_wkalrm alarm; +	struct rtc_time tm; + +	__rtc_read_time(rtc, &tm); + +	alarm.time = rtc_ktime_to_tm(ktime_add(rtc_tm_to_ktime(tm), +				     ktime_set(300, 0))); +	alarm.enabled = 0; + +	___rtc_set_alarm(rtc, &alarm); +} +  /**   * rtc_timer_remove - Removes a rtc_timer from the rtc_device timerqueue   * @rtc rtc device @@ -783,8 +804,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); @@ -846,7 +869,8 @@ again:  		err = __rtc_set_alarm(rtc, &alarm);  		if (err == -ETIME)  			goto again; -	} +	} else +		rtc_alarm_disable(rtc);  	mutex_unlock(&rtc->ops_lock);  }  |