public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Mario Limonciello <superm1@kernel.org>
To: "Mateusz Jończyk" <mat.jonczyk@o2.pl>,
	"John Stultz" <jstultz@google.com>,
	"Thomas Gleixner" <tglx@linutronix.de>
Cc: Stephen Boyd <sboyd@kernel.org>,
	linux-kernel@vger.kernel.org (open list:TIMEKEEPING,
	CLOCKSOURCE CORE, NTP, ALARMTIMER),
	Mario Limonciello <mario.limonciello@amd.com>
Subject: [PATCH RESEND] alarmtimer: Use aie_timer from RTC device instead of own timer
Date: Mon, 30 Sep 2024 13:29:45 -0500	[thread overview]
Message-ID: <20240930182945.3332896-1-superm1@kernel.org> (raw)

From: Mario Limonciello <mario.limonciello@amd.com>

It was reported that suspend-then-hibernate stopped working with modern
systemd versions on an AMD Cezanne system. The reason for this breakage
was because systemd switched to using alarmtimer instead of the wakealarm
sysfs file.

The wakealarm sysfs file programs the time to the `rtc->aie_timer` member
of the RTC, whereas the alarmtimer suspend routine programs it to it's
own device.

On AMD Cezanne systems rtc_read_alarm() is used to program a secondary
timer with the value of the timer. This behavior was introduced by
commit 59348401ebed9 ("platform/x86: amd-pmc: Add special handling
for timer based S0i3 wakeup").

As rtc_read_alarm() uses the `rtc->aie_timer` to report the cached
timer no alarm is provided as enabled.

To fix this issue, drop the use of a dedicated timer for the alarmtimer
and instead use `rtc->aie_timer` in the alarmtimer suspend/resume routines.

Link: https://github.com/systemd/systemd/commit/1bbbefe7a68059eb55d864c3e0e670d00269683a
Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/3591
Signed-off-by: Mario Limonciello <mario.limonciello@amd.com>
---
Originally sent as https://lore.kernel.org/all/20240910122258.129540-1-superm1@kernel.org/
No feedback for 3 weeks, travel, merge window etc so resending.
Rebased on 6.12-rc1.

 kernel/time/alarmtimer.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)

diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c
index 8bf888641694..a774dc0a7253 100644
--- a/kernel/time/alarmtimer.c
+++ b/kernel/time/alarmtimer.c
@@ -59,7 +59,6 @@ static DEFINE_SPINLOCK(freezer_delta_lock);
 
 #ifdef CONFIG_RTC_CLASS
 /* rtc timer and device for setting alarm wakeups at suspend */
-static struct rtc_timer		rtctimer;
 static struct rtc_device	*rtcdev;
 static DEFINE_SPINLOCK(rtcdev_lock);
 
@@ -123,11 +122,6 @@ static int alarmtimer_rtc_add_device(struct device *dev)
 	return ret;
 }
 
-static inline void alarmtimer_rtc_timer_init(void)
-{
-	rtc_timer_init(&rtctimer, NULL, NULL);
-}
-
 static struct class_interface alarmtimer_rtc_interface = {
 	.add_dev = &alarmtimer_rtc_add_device,
 };
@@ -144,7 +138,6 @@ static void alarmtimer_rtc_interface_remove(void)
 #else
 static inline int alarmtimer_rtc_interface_setup(void) { return 0; }
 static inline void alarmtimer_rtc_interface_remove(void) { }
-static inline void alarmtimer_rtc_timer_init(void) { }
 #endif
 
 /**
@@ -287,7 +280,7 @@ static int alarmtimer_suspend(struct device *dev)
 	trace_alarmtimer_suspend(expires, type);
 
 	/* Setup an rtc timer to fire that far in the future */
-	rtc_timer_cancel(rtc, &rtctimer);
+	rtc_timer_cancel(rtc, &rtc->aie_timer);
 	rtc_read_time(rtc, &tm);
 	now = rtc_tm_to_ktime(tm);
 
@@ -304,7 +297,7 @@ static int alarmtimer_suspend(struct device *dev)
 	now = ktime_add(now, min);
 
 	/* Set alarm, if in the past reject suspend briefly to handle */
-	ret = rtc_timer_start(rtc, &rtctimer, now, 0);
+	ret = rtc_timer_start(rtc, &rtc->aie_timer, now, 0);
 	if (ret < 0)
 		pm_wakeup_event(dev, MSEC_PER_SEC);
 	return ret;
@@ -316,7 +309,7 @@ static int alarmtimer_resume(struct device *dev)
 
 	rtc = alarmtimer_get_rtcdev();
 	if (rtc)
-		rtc_timer_cancel(rtc, &rtctimer);
+		rtc_timer_cancel(rtc, &rtc->aie_timer);
 	return 0;
 }
 
@@ -939,8 +932,6 @@ static int __init alarmtimer_init(void)
 	int error;
 	int i;
 
-	alarmtimer_rtc_timer_init();
-
 	/* Initialize alarm bases */
 	alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;
 	alarm_bases[ALARM_REALTIME].get_ktime = &ktime_get_real;
-- 
2.43.0


             reply	other threads:[~2024-09-30 18:29 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-09-30 18:29 Mario Limonciello [this message]
2024-10-01  8:30 ` [PATCH RESEND] alarmtimer: Use aie_timer from RTC device instead of own timer Thomas Gleixner
2024-10-01 13:41   ` Mario Limonciello
2024-10-02 14:45     ` Thomas Gleixner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240930182945.3332896-1-superm1@kernel.org \
    --to=superm1@kernel.org \
    --cc=jstultz@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mario.limonciello@amd.com \
    --cc=mat.jonczyk@o2.pl \
    --cc=sboyd@kernel.org \
    --cc=tglx@linutronix.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox