[PATCH v2] rtc: efi: Defer driver initialization to prioritize more capable RTCs

Ming Wang posted 1 patch 3 months, 4 weeks ago
drivers/rtc/rtc-efi.c | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
[PATCH v2] rtc: efi: Defer driver initialization to prioritize more capable RTCs
Posted by Ming Wang 3 months, 4 weeks ago
The EFI GetWakeupTime call, used by efi_read_alarm() to fetch RTC
wakeup alarm information, is specified to return EFI_UNSUPPORTED on
EFI firmware v1.10 and later. This effectively means that on most
modern systems, the efi-rtc driver cannot provide working RTC alarm
functionality.

If efi-rtc registers early during boot, it might become the primary
RTC device (e.g., /dev/rtc0). This can lead to a situation where the
system appears to have an RTC, but userspace utilities cannot set or
get RTC alarms, even if other RTC hardware (like rtc-cmos, which
typically supports alarms) is present but registers later.

To address this, change the efi-rtc driver initialization from
module_init() to late_initcall(). By deferring its initialization,
we give other, potentially more capable RTC drivers (such as rtc-cmos)
a better chance to register first and become the primary RTC.

This change increases the likelihood that systems with multiple RTC
sources will use the one with the most complete feature set (including
alarms) as the primary RTC. The efi-rtc driver can still serve as a
time source or a fallback RTC if no other RTC is available or preferred.

Signed-off-by: Ming Wang <wangming01@loongson.cn>
---
Changes in v2:
- Fixed a section mismatch warning reported by the kernel test robot.
  The efi_rtc_probe function was previously marked __init, which
  caused a conflict when efi_rtc_driver (in .data) directly
  referenced it after its initialization was deferred. Removed the
  __init attribute from efi_rtc_probe to resolve this.
---
 drivers/rtc/rtc-efi.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c
index fa8bf82df948..c941f52ea3fe 100644
--- a/drivers/rtc/rtc-efi.c
+++ b/drivers/rtc/rtc-efi.c
@@ -254,7 +254,7 @@ static const struct rtc_class_ops efi_rtc_ops = {
 	.proc		= efi_procfs,
 };
 
-static int __init efi_rtc_probe(struct platform_device *dev)
+static int efi_rtc_probe(struct platform_device *dev)
 {
 	struct rtc_device *rtc;
 	efi_time_t eft;
@@ -286,9 +286,20 @@ static struct platform_driver efi_rtc_driver = {
 	.driver = {
 		.name = "rtc-efi",
 	},
+	.probe = efi_rtc_probe,
 };
 
-module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe);
+static int __init efi_rtc_driver_init(void)
+{
+	return platform_driver_register(&efi_rtc_driver);
+}
+late_initcall(efi_rtc_driver_init);
+
+static void __exit efi_rtc_driver_exit(void)
+{
+	platform_driver_unregister(&efi_rtc_driver);
+}
+module_exit(efi_rtc_driver_exit);
 
 MODULE_AUTHOR("dann frazier <dannf@dannf.org>");
 MODULE_LICENSE("GPL");
-- 
2.43.0
Re: [PATCH v2] rtc: efi: Defer driver initialization to prioritize more capable RTCs
Posted by Huacai Chen 3 months, 3 weeks ago
On Fri, Jun 13, 2025 at 2:18 PM Ming Wang <wangming01@loongson.cn> wrote:
>
> The EFI GetWakeupTime call, used by efi_read_alarm() to fetch RTC
> wakeup alarm information, is specified to return EFI_UNSUPPORTED on
> EFI firmware v1.10 and later. This effectively means that on most
> modern systems, the efi-rtc driver cannot provide working RTC alarm
> functionality.
>
> If efi-rtc registers early during boot, it might become the primary
> RTC device (e.g., /dev/rtc0). This can lead to a situation where the
> system appears to have an RTC, but userspace utilities cannot set or
> get RTC alarms, even if other RTC hardware (like rtc-cmos, which
> typically supports alarms) is present but registers later.
>
> To address this, change the efi-rtc driver initialization from
> module_init() to late_initcall(). By deferring its initialization,
> we give other, potentially more capable RTC drivers (such as rtc-cmos)
> a better chance to register first and become the primary RTC.
>
> This change increases the likelihood that systems with multiple RTC
> sources will use the one with the most complete feature set (including
> alarms) as the primary RTC. The efi-rtc driver can still serve as a
> time source or a fallback RTC if no other RTC is available or preferred.
This makes sense because platform-specific RTCs usually have richer
features (so preferable) than EFI-RTC, and some test programs (such as
LTP) only operate on /dev/rtc0.

Reviewed-by: Huacai Chen <chenhuacai@loongson.cn>

>
> Signed-off-by: Ming Wang <wangming01@loongson.cn>
> ---
> Changes in v2:
> - Fixed a section mismatch warning reported by the kernel test robot.
>   The efi_rtc_probe function was previously marked __init, which
>   caused a conflict when efi_rtc_driver (in .data) directly
>   referenced it after its initialization was deferred. Removed the
>   __init attribute from efi_rtc_probe to resolve this.
> ---
>  drivers/rtc/rtc-efi.c | 15 +++++++++++++--
>  1 file changed, 13 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/rtc/rtc-efi.c b/drivers/rtc/rtc-efi.c
> index fa8bf82df948..c941f52ea3fe 100644
> --- a/drivers/rtc/rtc-efi.c
> +++ b/drivers/rtc/rtc-efi.c
> @@ -254,7 +254,7 @@ static const struct rtc_class_ops efi_rtc_ops = {
>         .proc           = efi_procfs,
>  };
>
> -static int __init efi_rtc_probe(struct platform_device *dev)
> +static int efi_rtc_probe(struct platform_device *dev)
>  {
>         struct rtc_device *rtc;
>         efi_time_t eft;
> @@ -286,9 +286,20 @@ static struct platform_driver efi_rtc_driver = {
>         .driver = {
>                 .name = "rtc-efi",
>         },
> +       .probe = efi_rtc_probe,
>  };
>
> -module_platform_driver_probe(efi_rtc_driver, efi_rtc_probe);
> +static int __init efi_rtc_driver_init(void)
> +{
> +       return platform_driver_register(&efi_rtc_driver);
> +}
> +late_initcall(efi_rtc_driver_init);
> +
> +static void __exit efi_rtc_driver_exit(void)
> +{
> +       platform_driver_unregister(&efi_rtc_driver);
> +}
> +module_exit(efi_rtc_driver_exit);
>
>  MODULE_AUTHOR("dann frazier <dannf@dannf.org>");
>  MODULE_LICENSE("GPL");
> --
> 2.43.0
>