* [PATCH] rtc: Don't lose a minute-resolution alarm that rounds down into the past
@ 2026-11-10 7:13 Arun Iyengar via B4 Relay
2026-11-10 7:48 ` Alexandre Belloni
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Arun Iyengar via B4 Relay @ 2026-11-10 7:13 UTC (permalink / raw)
To: Alexandre Belloni; +Cc: linux-rtc, linux-kernel, stable
From: Arun Iyengar <aiyengar1990@gmail.com>
For an RTC with RTC_FEATURE_ALARM_RES_MINUTE, rtc_set_alarm() rounds the
alarm down to the start of its minute, so that it never fires late. When
the alarm is less than a minute away and in the same minute as the
current time, the rounded time is already in the past.
rtc_timer_enqueue() then gets -ETIME from __rtc_set_alarm() and expires
the timer from the irq work right away, and the hardware alarm is never
armed.
That loses every short wake alarm. With a HYM8563, which has minute
resolution, "rtcwake -m freeze -s 15" sets an alarm that expires in
software before the system suspends, so nothing wakes it: with the
alarm set at 17:55:00 for 17:55:17, /proc/driver/rtc reads back
"alrm_time: 17:55:00, alarm_IRQ: no", and the system stays in
suspend-to-idle until something else wakes it.
Round the alarm up to the next minute when rounding down would put an
alarm that is still in the future into the past. It then fires at most
59 seconds late instead of never. Alarms that are already in the past,
or that round down to a time still in the future, are handled as before.
Fixes: d87f741dddab ("rtc: handle alarms with a minute resolution")
Cc: stable@vger.kernel.org
Signed-off-by: Arun Iyengar <aiyengar1990@gmail.com>
---
Tested on an Orange Pi 5 (RK3588S) with a HYM8563: "rtcwake -m no -s 15"
now reads back the alarm at the next full minute with "alarm_IRQ: yes",
and 47 consecutive "rtcwake -m freeze -s 15" cycles all woke from the
RTC interrupt. Before the fix the alarm was lost whenever the 15 s
stayed inside the current minute, and the system never woke.
This patch was developed with Claude (Anthropic) as a coding assistant:
it wrote the code and the commit message, and I reviewed and tested it
as described above.
---
drivers/rtc/interface.c | 33 +++++++++++++++++++++++++++------
1 file changed, 27 insertions(+), 6 deletions(-)
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index 96626f8068f9..004819c9a846 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -535,18 +535,39 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
rtc_timer_remove(rtc, &rtc->aie_timer);
alarm_time = rtc_tm_to_ktime(alarm->time);
- /*
- * Round down so we never miss a deadline, checking for past deadline is
- * done in __rtc_set_alarm
- */
- if (test_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features))
- alarm_time = ktime_sub_ns(alarm_time, (u64)alarm->time.tm_sec * NSEC_PER_SEC);
+ if (test_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features) &&
+ alarm->time.tm_sec) {
+ ktime_t down = ktime_sub_ns(alarm_time,
+ (u64)alarm->time.tm_sec * NSEC_PER_SEC);
+ struct rtc_time tm;
+ ktime_t now;
+
+ err = __rtc_read_time(rtc, &tm);
+ if (err)
+ goto unlock;
+ now = rtc_tm_to_ktime(tm);
+
+ /*
+ * Round down so we never miss a deadline. If that puts an alarm
+ * that is still in the future into the past, the timer would
+ * expire right away and the hardware alarm would never be
+ * armed: whoever relies on it, e.g. to wake the system from
+ * suspend, would wait forever. Round up to the next minute
+ * instead. An alarm already in the past is left alone, it is
+ * handled by __rtc_set_alarm.
+ */
+ if (ktime_after(down, now) || !ktime_after(alarm_time, now))
+ alarm_time = down;
+ else
+ alarm_time = ktime_add_ns(down, 60 * NSEC_PER_SEC);
+ }
rtc->aie_timer.node.expires = alarm_time;
rtc->aie_timer.period = 0;
if (alarm->enabled)
err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
+unlock:
mutex_unlock(&rtc->ops_lock);
return err;
---
base-commit: 7485659ecb81d5fce3a3edf2cae9fcb29c17b1cd
change-id: 20261110-rtc-minute-alarm-1d8af9689d23
Best regards,
--
Arun Iyengar <aiyengar1990@gmail.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] rtc: Don't lose a minute-resolution alarm that rounds down into the past
2026-11-10 7:13 [PATCH] rtc: Don't lose a minute-resolution alarm that rounds down into the past Arun Iyengar via B4 Relay
@ 2026-11-10 7:48 ` Alexandre Belloni
2026-11-10 11:01 ` kernel test robot
2026-11-10 14:31 ` kernel test robot
2 siblings, 0 replies; 4+ messages in thread
From: Alexandre Belloni @ 2026-11-10 7:48 UTC (permalink / raw)
To: aiyengar1990; +Cc: linux-rtc, linux-kernel, stable
On 10/11/2026 07:13:47+0000, Arun Iyengar via B4 Relay wrote:
> From: Arun Iyengar <aiyengar1990@gmail.com>
>
> For an RTC with RTC_FEATURE_ALARM_RES_MINUTE, rtc_set_alarm() rounds the
> alarm down to the start of its minute, so that it never fires late. When
> the alarm is less than a minute away and in the same minute as the
> current time, the rounded time is already in the past.
> rtc_timer_enqueue() then gets -ETIME from __rtc_set_alarm() and expires
> the timer from the irq work right away, and the hardware alarm is never
> armed.
This is the expected behaviour, userspace has to handle the error
properly: the alarm can't be set, set it for a later time or stop there
and don't suspend.
>
> That loses every short wake alarm. With a HYM8563, which has minute
> resolution, "rtcwake -m freeze -s 15" sets an alarm that expires in
> software before the system suspends, so nothing wakes it: with the
> alarm set at 17:55:00 for 17:55:17, /proc/driver/rtc reads back
> "alrm_time: 17:55:00, alarm_IRQ: no", and the system stays in
> suspend-to-idle until something else wakes it.
>
> Round the alarm up to the next minute when rounding down would put an
> alarm that is still in the future into the past. It then fires at most
> 59 seconds late instead of never. Alarms that are already in the past,
> or that round down to a time still in the future, are handled as before.
Never round up, you are going to miss deadlines.
--
Alexandre Belloni, co-owner and COO, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] rtc: Don't lose a minute-resolution alarm that rounds down into the past
2026-11-10 7:13 [PATCH] rtc: Don't lose a minute-resolution alarm that rounds down into the past Arun Iyengar via B4 Relay
2026-11-10 7:48 ` Alexandre Belloni
@ 2026-11-10 11:01 ` kernel test robot
2026-11-10 14:31 ` kernel test robot
2 siblings, 0 replies; 4+ messages in thread
From: kernel test robot @ 2026-11-10 11:01 UTC (permalink / raw)
To: Arun Iyengar via B4 Relay, Alexandre Belloni
Cc: oe-kbuild-all, linux-rtc, linux-kernel, stable
Hi Arun,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 7485659ecb81d5fce3a3edf2cae9fcb29c17b1cd]
url: https://github.com/intel-lab-lkp/linux/commits/Arun-Iyengar-via-B4-Relay/rtc-Don-t-lose-a-minute-resolution-alarm-that-rounds-down-into-the-past/20261110-071347
base: 7485659ecb81d5fce3a3edf2cae9fcb29c17b1cd
patch link: https://lore.kernel.org/r/20261110-rtc-minute-alarm-v1-1-be9d7c5227a1%40gmail.com
patch subject: [PATCH] rtc: Don't lose a minute-resolution alarm that rounds down into the past
config: parisc-allnoconfig (https://download.01.org/0day-ci/archive/20261110/202611101839.fRQuN29G-lkp@intel.com/config)
compiler: hppa-linux-gcc (GCC) 16.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261110/202611101839.fRQuN29G-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202611101839.fRQuN29G-lkp@intel.com/
All warnings (new ones prefixed by >>):
In file included from include/linux/timer.h:6,
from include/linux/uprobes.h:18,
from include/linux/mm_types.h:16,
from include/linux/mmzone.h:22,
from include/linux/topology.h:34,
from include/linux/irq.h:19,
from arch/parisc/include/asm/hardirq.h:13,
from include/linux/hardirq.h:11,
from include/linux/interrupt.h:11,
from include/linux/rtc.h:18,
from drivers/rtc/interface.c:11:
drivers/rtc/interface.c: In function 'rtc_set_alarm':
>> drivers/rtc/interface.c:562:60: warning: integer overflow in expression of type 'long int' results in '-129542144' [-Woverflow]
562 | alarm_time = ktime_add_ns(down, 60 * NSEC_PER_SEC);
| ^
include/linux/ktime.h:60:50: note: in definition of macro 'ktime_add_ns'
60 | #define ktime_add_ns(kt, nsval) ((kt) + (nsval))
| ^~~~~
vim +562 drivers/rtc/interface.c
512
513 int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
514 {
515 ktime_t alarm_time;
516 int err;
517
518 if (!rtc->ops)
519 return -ENODEV;
520 else if (!test_bit(RTC_FEATURE_ALARM, rtc->features))
521 return -EINVAL;
522
523 err = rtc_valid_tm(&alarm->time);
524 if (err != 0)
525 return err;
526
527 err = rtc_valid_range(rtc, &alarm->time);
528 if (err)
529 return err;
530
531 err = mutex_lock_interruptible(&rtc->ops_lock);
532 if (err)
533 return err;
534 if (rtc->aie_timer.enabled)
535 rtc_timer_remove(rtc, &rtc->aie_timer);
536
537 alarm_time = rtc_tm_to_ktime(alarm->time);
538 if (test_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features) &&
539 alarm->time.tm_sec) {
540 ktime_t down = ktime_sub_ns(alarm_time,
541 (u64)alarm->time.tm_sec * NSEC_PER_SEC);
542 struct rtc_time tm;
543 ktime_t now;
544
545 err = __rtc_read_time(rtc, &tm);
546 if (err)
547 goto unlock;
548 now = rtc_tm_to_ktime(tm);
549
550 /*
551 * Round down so we never miss a deadline. If that puts an alarm
552 * that is still in the future into the past, the timer would
553 * expire right away and the hardware alarm would never be
554 * armed: whoever relies on it, e.g. to wake the system from
555 * suspend, would wait forever. Round up to the next minute
556 * instead. An alarm already in the past is left alone, it is
557 * handled by __rtc_set_alarm.
558 */
559 if (ktime_after(down, now) || !ktime_after(alarm_time, now))
560 alarm_time = down;
561 else
> 562 alarm_time = ktime_add_ns(down, 60 * NSEC_PER_SEC);
563 }
564
565 rtc->aie_timer.node.expires = alarm_time;
566 rtc->aie_timer.period = 0;
567 if (alarm->enabled)
568 err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
569
570 unlock:
571 mutex_unlock(&rtc->ops_lock);
572
573 return err;
574 }
575 EXPORT_SYMBOL_GPL(rtc_set_alarm);
576
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH] rtc: Don't lose a minute-resolution alarm that rounds down into the past
2026-11-10 7:13 [PATCH] rtc: Don't lose a minute-resolution alarm that rounds down into the past Arun Iyengar via B4 Relay
2026-11-10 7:48 ` Alexandre Belloni
2026-11-10 11:01 ` kernel test robot
@ 2026-11-10 14:31 ` kernel test robot
2 siblings, 0 replies; 4+ messages in thread
From: kernel test robot @ 2026-11-10 14:31 UTC (permalink / raw)
To: Arun Iyengar via B4 Relay, Alexandre Belloni
Cc: llvm, oe-kbuild-all, linux-rtc, linux-kernel, stable
Hi Arun,
kernel test robot noticed the following build warnings:
[auto build test WARNING on 7485659ecb81d5fce3a3edf2cae9fcb29c17b1cd]
url: https://github.com/intel-lab-lkp/linux/commits/Arun-Iyengar-via-B4-Relay/rtc-Don-t-lose-a-minute-resolution-alarm-that-rounds-down-into-the-past/20261110-071347
base: 7485659ecb81d5fce3a3edf2cae9fcb29c17b1cd
patch link: https://lore.kernel.org/r/20261110-rtc-minute-alarm-v1-1-be9d7c5227a1%40gmail.com
patch subject: [PATCH] rtc: Don't lose a minute-resolution alarm that rounds down into the past
config: i386-defconfig (https://download.01.org/0day-ci/archive/20261110/202611102202.ZY3wJ35v-lkp@intel.com/config)
compiler: clang version 22.1.8 (https://github.com/llvm/llvm-project ca7933e47d3a3451d81e72ac174dcb5aa28b59d1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20261110/202611102202.ZY3wJ35v-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202611102202.ZY3wJ35v-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/rtc/interface.c:562:39: warning: overflow in expression; result is -129'542'144 with type 'long' [-Winteger-overflow]
562 | alarm_time = ktime_add_ns(down, 60 * NSEC_PER_SEC);
| ~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~
include/linux/ktime.h:60:43: note: expanded from macro 'ktime_add_ns'
60 | #define ktime_add_ns(kt, nsval) ((kt) + (nsval))
| ^~~~~
1 warning generated.
vim +562 drivers/rtc/interface.c
512
513 int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
514 {
515 ktime_t alarm_time;
516 int err;
517
518 if (!rtc->ops)
519 return -ENODEV;
520 else if (!test_bit(RTC_FEATURE_ALARM, rtc->features))
521 return -EINVAL;
522
523 err = rtc_valid_tm(&alarm->time);
524 if (err != 0)
525 return err;
526
527 err = rtc_valid_range(rtc, &alarm->time);
528 if (err)
529 return err;
530
531 err = mutex_lock_interruptible(&rtc->ops_lock);
532 if (err)
533 return err;
534 if (rtc->aie_timer.enabled)
535 rtc_timer_remove(rtc, &rtc->aie_timer);
536
537 alarm_time = rtc_tm_to_ktime(alarm->time);
538 if (test_bit(RTC_FEATURE_ALARM_RES_MINUTE, rtc->features) &&
539 alarm->time.tm_sec) {
540 ktime_t down = ktime_sub_ns(alarm_time,
541 (u64)alarm->time.tm_sec * NSEC_PER_SEC);
542 struct rtc_time tm;
543 ktime_t now;
544
545 err = __rtc_read_time(rtc, &tm);
546 if (err)
547 goto unlock;
548 now = rtc_tm_to_ktime(tm);
549
550 /*
551 * Round down so we never miss a deadline. If that puts an alarm
552 * that is still in the future into the past, the timer would
553 * expire right away and the hardware alarm would never be
554 * armed: whoever relies on it, e.g. to wake the system from
555 * suspend, would wait forever. Round up to the next minute
556 * instead. An alarm already in the past is left alone, it is
557 * handled by __rtc_set_alarm.
558 */
559 if (ktime_after(down, now) || !ktime_after(alarm_time, now))
560 alarm_time = down;
561 else
> 562 alarm_time = ktime_add_ns(down, 60 * NSEC_PER_SEC);
563 }
564
565 rtc->aie_timer.node.expires = alarm_time;
566 rtc->aie_timer.period = 0;
567 if (alarm->enabled)
568 err = rtc_timer_enqueue(rtc, &rtc->aie_timer);
569
570 unlock:
571 mutex_unlock(&rtc->ops_lock);
572
573 return err;
574 }
575 EXPORT_SYMBOL_GPL(rtc_set_alarm);
576
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-10 14:32 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-10 7:13 [PATCH] rtc: Don't lose a minute-resolution alarm that rounds down into the past Arun Iyengar via B4 Relay
2026-11-10 7:48 ` Alexandre Belloni
2026-11-10 11:01 ` kernel test robot
2026-11-10 14:31 ` kernel test robot
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®