Hello,
as described in the commit log of the two commits the rtc-mt6397 driver relies on these fixes as soon as it should store dates later than 2027-12-31. On one of the patches has a Fixes line, so this submission is done to ensure that both patches are backported.
The patches sent in reply to this mail are (trivial) backports to v6.15.1, they should get backported to the older stable kernels, too, to (somewhat) ensure that in 2028 no surprises happen. `git am` is able to apply the patches as is to 6.14.y, 6.12.y, 6.6.y, 6.1.y and 5.15.y.
5.10 and 5.4 need an adaption, I didn't look into that yet but can follow up with backports for these.
The two fixes were accompanied by 3 test updates:
46351921cbe1 ("rtc: test: Emit the seconds-since-1970 value instead of days-since-1970") da62b49830f8 ("rtc: test: Also test time and wday outcome of rtc_time64_to_tm()") ccb2dba3c19f ("rtc: test: Test date conversion for dates starting in 1900")
that cover one of the patches. Would you consider it sensible to backport these, too?
Best regards Uwe
Alexandre Mergnat (2): rtc: Make rtc_time64_to_tm() support dates before 1970 rtc: Fix offset calculation for .start_secs < 0
drivers/rtc/class.c | 2 +- drivers/rtc/lib.c | 24 +++++++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-)
base-commit: 3ef49626da6dd67013fc2cf0a4e4c9e158bb59f7
From: Alexandre Mergnat amergnat@baylibre.com
commit 7df4cfef8b351fec3156160bedfc7d6d29de4cce upstream.
Conversion of dates before 1970 is still relevant today because these dates are reused on some hardwares to store dates bigger than the maximal date that is representable in the device's native format. This prominently and very soon affects the hardware covered by the rtc-mt6397 driver that can only natively store dates in the interval 1900-01-01 up to 2027-12-31. So to store the date 2028-01-01 00:00:00 to such a device, rtc_time64_to_tm() must do the right thing for time=-2208988800.
Signed-off-by: Alexandre Mergnat amergnat@baylibre.com Reviewed-by: Uwe Kleine-König u.kleine-koenig@baylibre.com Link: https://lore.kernel.org/r/20250428-enable-rtc-v4-1-2b2f7e3f9349@baylibre.com Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Signed-off-by: Uwe Kleine-König u.kleine-koenig@baylibre.com --- drivers/rtc/lib.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-)
diff --git a/drivers/rtc/lib.c b/drivers/rtc/lib.c index fe361652727a..13b5b1f20465 100644 --- a/drivers/rtc/lib.c +++ b/drivers/rtc/lib.c @@ -46,24 +46,38 @@ EXPORT_SYMBOL(rtc_year_days); * rtc_time64_to_tm - converts time64_t to rtc_time. * * @time: The number of seconds since 01-01-1970 00:00:00. - * (Must be positive.) + * Works for values since at least 1900 * @tm: Pointer to the struct rtc_time. */ void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) { - unsigned int secs; - int days; + int days, secs;
u64 u64tmp; u32 u32tmp, udays, century, day_of_century, year_of_century, year, day_of_year, month, day; bool is_Jan_or_Feb, is_leap_year;
- /* time must be positive */ + /* + * Get days and seconds while preserving the sign to + * handle negative time values (dates before 1970-01-01) + */ days = div_s64_rem(time, 86400, &secs);
+ /* + * We need 0 <= secs < 86400 which isn't given for negative + * values of time. Fixup accordingly. + */ + if (secs < 0) { + days -= 1; + secs += 86400; + } + /* day of the week, 1970-01-01 was a Thursday */ tm->tm_wday = (days + 4) % 7; + /* Ensure tm_wday is always positive */ + if (tm->tm_wday < 0) + tm->tm_wday += 7;
/* * The following algorithm is, basically, Proposition 6.3 of Neri @@ -93,7 +107,7 @@ void rtc_time64_to_tm(time64_t time, struct rtc_time *tm) * thus, is slightly different from [1]. */
- udays = ((u32) days) + 719468; + udays = days + 719468;
u32tmp = 4 * udays + 3; century = u32tmp / 146097;
From: Alexandre Mergnat amergnat@baylibre.com
commit fe9f5f96cfe8b82d0f24cbfa93718925560f4f8d upstream.
The comparison
rtc->start_secs > rtc->range_max
has a signed left-hand side and an unsigned right-hand side. So the comparison might become true for negative start_secs which is interpreted as a (possibly very large) positive value.
As a negative value can never be bigger than an unsigned value the correct representation of the (mathematical) comparison
rtc->start_secs > rtc->range_max
in C is:
rtc->start_secs >= 0 && rtc->start_secs > rtc->range_max
Use that to fix the offset calculation currently used in the rtc-mt6397 driver.
Fixes: 989515647e783 ("rtc: Add one offset seconds to expand RTC range") Signed-off-by: Alexandre Mergnat amergnat@baylibre.com Reviewed-by: Uwe Kleine-König u.kleine-koenig@baylibre.com Link: https://lore.kernel.org/r/20250428-enable-rtc-v4-2-2b2f7e3f9349@baylibre.com Signed-off-by: Alexandre Belloni alexandre.belloni@bootlin.com Signed-off-by: Uwe Kleine-König u.kleine-koenig@baylibre.com --- drivers/rtc/class.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index b88cd4fb295b..b1a2be1f9e3b 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c @@ -326,7 +326,7 @@ static void rtc_device_get_offset(struct rtc_device *rtc) * * Otherwise the offset seconds should be 0. */ - if (rtc->start_secs > rtc->range_max || + if ((rtc->start_secs >= 0 && rtc->start_secs > rtc->range_max) || rtc->start_secs + range_secs - 1 < rtc->range_min) rtc->offset_secs = rtc->start_secs - rtc->range_min; else if (rtc->start_secs > rtc->range_min)
On Fri, Jun 06, 2025 at 05:44:37PM +0200, Uwe Kleine-König wrote:
Hello,
as described in the commit log of the two commits the rtc-mt6397 driver relies on these fixes as soon as it should store dates later than 2027-12-31. On one of the patches has a Fixes line, so this submission is done to ensure that both patches are backported.
The patches sent in reply to this mail are (trivial) backports to v6.15.1, they should get backported to the older stable kernels, too, to (somewhat) ensure that in 2028 no surprises happen. `git am` is able to apply the patches as is to 6.14.y, 6.12.y, 6.6.y, 6.1.y and 5.15.y.
5.10 and 5.4 need an adaption, I didn't look into that yet but can follow up with backports for these.
The two fixes were accompanied by 3 test updates:
46351921cbe1 ("rtc: test: Emit the seconds-since-1970 value instead of days-since-1970") da62b49830f8 ("rtc: test: Also test time and wday outcome of rtc_time64_to_tm()") ccb2dba3c19f ("rtc: test: Test date conversion for dates starting in 1900")
that cover one of the patches. Would you consider it sensible to backport these, too?
If you want to, sure, but normally people run the latest in-kernel selftests for older kernel trees.
thanks,
greg k-h
linux-stable-mirror@lists.linaro.org