Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c0afabd3 authored by Rabin Vincent's avatar Rabin Vincent Committed by John Stultz
Browse files

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: default avatarRabin Vincent <rabin.vincent@stericsson.com>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
parent 27c9cd7e
Loading
Loading
Loading
Loading
+34 −10
Original line number Diff line number Diff line
@@ -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 @@ void rtc_timer_do_work(struct work_struct *work)
		err = __rtc_set_alarm(rtc, &alarm);
		if (err == -ETIME)
			goto again;
	}
	} else
		rtc_alarm_disable(rtc);

	mutex_unlock(&rtc->ops_lock);
}