* [PATCH] RTC: Restore alarm after resume
@ 2014-12-22 19:19 Matthew Garrett
2015-01-05 22:41 ` Andrew Morton
2015-03-27 13:22 ` Alexandre Belloni
0 siblings, 2 replies; 4+ messages in thread
From: Matthew Garrett @ 2014-12-22 19:19 UTC (permalink / raw)
To: a.zummo; +Cc: rtc-linux, linux-kernel, Matthew Garrett
Some platform firmware may interfere with the RTC alarm over suspend,
resulting in the kernel and hardware having different ideas about system state
but also potentially causing problems with firmware that assumes the OS will
clean this case up. This patch saves the RTC alarm state on suspend and will
restore it on resume if the alarm has not yet fired - if it has, it will clear
the RTC alarm.
Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
Tested-by: Gabriele Mazzotta <gabriele.mzt@gmail.com>
---
drivers/rtc/class.c | 24 ++++++++++++++++++++++++
include/linux/rtc.h | 4 ++++
2 files changed, 28 insertions(+)
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index 472a5ad..c7e09e2 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -55,6 +55,8 @@ static int rtc_suspend(struct device *dev)
struct timespec64 delta, delta_delta;
int err;
+ rtc->valid_alarm = !rtc_read_alarm(rtc, &rtc->alarm);
+
if (has_persistent_clock())
return 0;
@@ -102,6 +104,27 @@ static int rtc_resume(struct device *dev)
struct timespec64 sleep_time;
int err;
+ /*
+ * Ensure that the platform hasn't overwritten a pending alarm while
+ * suspended
+ */
+ if (rtc->valid_alarm) {
+ long now, scheduled;
+
+ rtc_read_time(rtc, &tm);
+ rtc_tm_to_time(&rtc->alarm.time, &scheduled);
+ rtc_tm_to_time(&tm, &now);
+
+ /* Clear the alarm registers if it went off during suspend */
+ if (scheduled <= now) {
+ rtc_time_to_tm(0, &rtc->alarm.time);
+ rtc->alarm.enabled = 0;
+ }
+
+ if (rtc->ops && rtc->ops->set_alarm)
+ rtc->ops->set_alarm(rtc->dev.parent, &rtc->alarm);
+ }
+
if (has_persistent_clock())
return 0;
@@ -145,6 +168,7 @@ static int rtc_resume(struct device *dev)
if (sleep_time.tv_sec >= 0)
timekeeping_inject_sleeptime64(&sleep_time);
rtc_hctosys_ret = 0;
+
return 0;
}
diff --git a/include/linux/rtc.h b/include/linux/rtc.h
index 6d6be09..bc805ff 100644
--- a/include/linux/rtc.h
+++ b/include/linux/rtc.h
@@ -133,6 +133,10 @@ struct rtc_device
/* Some hardware can't support UIE mode */
int uie_unsupported;
+#ifdef CONFIG_PM_SLEEP
+ struct rtc_wkalrm alarm;
+ bool valid_alarm;
+#endif
#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL
struct work_struct uie_task;
struct timer_list uie_timer;
--
2.1.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH] RTC: Restore alarm after resume
2014-12-22 19:19 [PATCH] RTC: Restore alarm after resume Matthew Garrett
@ 2015-01-05 22:41 ` Andrew Morton
2015-01-05 22:50 ` Matthew Garrett
2015-03-27 13:22 ` Alexandre Belloni
1 sibling, 1 reply; 4+ messages in thread
From: Andrew Morton @ 2015-01-05 22:41 UTC (permalink / raw)
To: Matthew Garrett; +Cc: a.zummo, rtc-linux, linux-kernel
On Mon, 22 Dec 2014 19:19:39 +0000 Matthew Garrett <matthew.garrett@nebula.com> wrote:
> Some platform firmware may interfere with the RTC alarm over suspend,
> resulting in the kernel and hardware having different ideas about system state
> but also potentially causing problems with firmware that assumes the OS will
> clean this case up. This patch saves the RTC alarm state on suspend and will
> restore it on resume if the alarm has not yet fired - if it has, it will clear
> the RTC alarm.
There's not really enough info here for me to decide which kernel
version(s) need the patch. Can we please expand on "some"? Any
suggestions regarding the importance/timing of the fix?
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] RTC: Restore alarm after resume
2015-01-05 22:41 ` Andrew Morton
@ 2015-01-05 22:50 ` Matthew Garrett
0 siblings, 0 replies; 4+ messages in thread
From: Matthew Garrett @ 2015-01-05 22:50 UTC (permalink / raw)
To: akpm@linux-foundation.org
Cc: linux-kernel@vger.kernel.org, a.zummo@towertech.it,
rtc-linux@googlegroups.com
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 2602 bytes --]
On Mon, 2015-01-05 at 14:41 -0800, Andrew Morton wrote:
> On Mon, 22 Dec 2014 19:19:39 +0000 Matthew Garrett <matthew.garrett@nebula.com> wrote:
>
> > Some platform firmware may interfere with the RTC alarm over suspend,
> > resulting in the kernel and hardware having different ideas about system state
> > but also potentially causing problems with firmware that assumes the OS will
> > clean this case up. This patch saves the RTC alarm state on suspend and will
> > restore it on resume if the alarm has not yet fired - if it has, it will clear
> > the RTC alarm.
>
> There's not really enough info here for me to decide which kernel
> version(s) need the patch. Can we please expand on "some"? Any
> suggestions regarding the importance/timing of the fix?
The case we've seen is Intel Rapid Start, which is a firmware-mediated
feature that automatically transitions systems from suspend-to-RAM to
suspend-to-disk without OS involvement. It does this by setting the RTC
alarm and a flag that indicates that on wake it should perform the
transition rather than re-starting the OS. However, if the OS has set a
wakeup alarm that would wake the machine earlier, it refuses to
overwrite it and allows the system to wake instead.
This fails in the following situation:
1) User configures Intel Rapid Start to transition after (say) 15
minutes
2) User suspends to RAM. Firmware sets the wakeup alarm for 15 minutes
in the future
3) User resumes after 5 minutes. Firmware does not reset the alarm, and
as such it is still set for 10 minutes in the future
4) User suspends after 5 minutes. Firmware notices that the alarm is set
for 5 minutes in the future, which is less than the 15 minute transition
threshold. It therefore assumes that the user wants the machine to wake
in 5 minutes
5) System resumes after 5 minutes
The worst case scenario here is that the user may have put the system in
a bag between (4) and (5), resulting in it running in a confined space
and potentially overheating. This seems reasonably important. The Rapid
Start support code got added in 3.11, but it can be configured in the
firmware regardless of kernel support.
I'd like to hear some feedback from the RTC maintainers regarding
whether this is the preferred fix. Doing it in the Rapid Start driver
doesn't seem correct, since as mentioned the feature doesn't require any
kernel support - the kernel code just provides a means for runtime
configuration.
ÿôèº{.nÇ+·®+%Ëÿ±éݶ\x17¥wÿº{.nÇ+·¥{±þG«éÿ{ayº\x1dÊÚë,j\a¢f£¢·hïêÿêçz_è®\x03(éÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?¨èÚ&£ø§~á¶iOæ¬z·vØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?I¥
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: RTC: Restore alarm after resume
2014-12-22 19:19 [PATCH] RTC: Restore alarm after resume Matthew Garrett
2015-01-05 22:41 ` Andrew Morton
@ 2015-03-27 13:22 ` Alexandre Belloni
1 sibling, 0 replies; 4+ messages in thread
From: Alexandre Belloni @ 2015-03-27 13:22 UTC (permalink / raw)
To: Matthew Garrett; +Cc: a.zummo, rtc-linux, linux-kernel
Hi Matthew,
On 22/12/2014 at 19:19:39 +0000, Matthew Garrett wrote :
> Some platform firmware may interfere with the RTC alarm over suspend,
> resulting in the kernel and hardware having different ideas about system state
> but also potentially causing problems with firmware that assumes the OS will
> clean this case up. This patch saves the RTC alarm state on suspend and will
> restore it on resume if the alarm has not yet fired - if it has, it will clear
> the RTC alarm.
>
> Signed-off-by: Matthew Garrett <matthew.garrett@nebula.com>
> Tested-by: Gabriele Mazzotta <gabriele.mzt@gmail.com>
> ---
> drivers/rtc/class.c | 24 ++++++++++++++++++++++++
> include/linux/rtc.h | 4 ++++
> 2 files changed, 28 insertions(+)
>
> diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
> index 472a5ad..c7e09e2 100644
> --- a/drivers/rtc/class.c
> +++ b/drivers/rtc/class.c
> @@ -55,6 +55,8 @@ static int rtc_suspend(struct device *dev)
> struct timespec64 delta, delta_delta;
> int err;
>
> + rtc->valid_alarm = !rtc_read_alarm(rtc, &rtc->alarm);
> +
> if (has_persistent_clock())
> return 0;
>
> @@ -102,6 +104,27 @@ static int rtc_resume(struct device *dev)
> struct timespec64 sleep_time;
> int err;
>
> + /*
> + * Ensure that the platform hasn't overwritten a pending alarm while
> + * suspended
> + */
> + if (rtc->valid_alarm) {
> + long now, scheduled;
> +
> + rtc_read_time(rtc, &tm);
> + rtc_tm_to_time(&rtc->alarm.time, &scheduled);
> + rtc_tm_to_time(&tm, &now);
> +
> + /* Clear the alarm registers if it went off during suspend */
> + if (scheduled <= now) {
> + rtc_time_to_tm(0, &rtc->alarm.time);
> + rtc->alarm.enabled = 0;
> + }
> +
> + if (rtc->ops && rtc->ops->set_alarm)
> + rtc->ops->set_alarm(rtc->dev.parent, &rtc->alarm);
> + }
> +
My main concern here is that reading the time and the alarm can be slow,
in particular with i2c RTC.
Isn't that issue pretty much specific to x86? I know you think otherwise
but I believe this would better be done from your driver. If more
platforms/RTCs are affected, it will still be time to try to solve it in
a more generic way.
Moreover, the class suspend/resume functions are only defined when
CONFIG_RTC_HCTOSYS is set so you may still have broken platforms with
some configurations.
--
Alexandre Belloni, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2015-03-27 13:22 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-12-22 19:19 [PATCH] RTC: Restore alarm after resume Matthew Garrett
2015-01-05 22:41 ` Andrew Morton
2015-01-05 22:50 ` Matthew Garrett
2015-03-27 13:22 ` Alexandre Belloni
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox