rtc: efi: Enable SET/GET WAKEUP services as optional
authorShanker Donthineni <sdonthineni@nvidia.com>
Mon, 2 Jan 2023 23:06:30 +0000 (17:06 -0600)
committerAlexandre Belloni <alexandre.belloni@bootlin.com>
Mon, 9 Jan 2023 21:05:54 +0000 (22:05 +0100)
The current implementation of rtc-efi is expecting all the 4
time services GET{SET}_TIME{WAKEUP} must be supported by UEFI
firmware. As per the EFI_RT_PROPERTIES_TABLE, the platform
specific implementations can choose to enable selective time
services based on the RTC device capabilities.

This patch does the following changes to provide GET/SET RTC
services on platforms that do not support the WAKEUP feature.

1) Relax time services cap check when creating a platform device.
2) Clear RTC_FEATURE_ALARM bit in the absence of WAKEUP services.
3) Conditional alarm entries in '/proc/driver/rtc'.

Cc: <stable@vger.kernel.org> # v6.0+
Signed-off-by: Shanker Donthineni <sdonthineni@nvidia.com>
Link: https://lore.kernel.org/r/20230102230630.192911-1-sdonthineni@nvidia.com
Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
drivers/rtc/rtc-efi.c
include/linux/efi.h

index e991ccc..1e8bc6c 100644 (file)
@@ -188,9 +188,10 @@ static int efi_set_time(struct device *dev, struct rtc_time *tm)
 
 static int efi_procfs(struct device *dev, struct seq_file *seq)
 {
-       efi_time_t      eft, alm;
-       efi_time_cap_t  cap;
-       efi_bool_t      enabled, pending;
+       efi_time_t        eft, alm;
+       efi_time_cap_t    cap;
+       efi_bool_t        enabled, pending;
+       struct rtc_device *rtc = dev_get_drvdata(dev);
 
        memset(&eft, 0, sizeof(eft));
        memset(&alm, 0, sizeof(alm));
@@ -213,23 +214,25 @@ static int efi_procfs(struct device *dev, struct seq_file *seq)
                /* XXX fixme: convert to string? */
                seq_printf(seq, "Timezone\t: %u\n", eft.timezone);
 
-       seq_printf(seq,
-                  "Alarm Time\t: %u:%u:%u.%09u\n"
-                  "Alarm Date\t: %u-%u-%u\n"
-                  "Alarm Daylight\t: %u\n"
-                  "Enabled\t\t: %s\n"
-                  "Pending\t\t: %s\n",
-                  alm.hour, alm.minute, alm.second, alm.nanosecond,
-                  alm.year, alm.month, alm.day,
-                  alm.daylight,
-                  enabled == 1 ? "yes" : "no",
-                  pending == 1 ? "yes" : "no");
-
-       if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE)
-               seq_puts(seq, "Timezone\t: unspecified\n");
-       else
-               /* XXX fixme: convert to string? */
-               seq_printf(seq, "Timezone\t: %u\n", alm.timezone);
+       if (test_bit(RTC_FEATURE_ALARM, rtc->features)) {
+               seq_printf(seq,
+                          "Alarm Time\t: %u:%u:%u.%09u\n"
+                          "Alarm Date\t: %u-%u-%u\n"
+                          "Alarm Daylight\t: %u\n"
+                          "Enabled\t\t: %s\n"
+                          "Pending\t\t: %s\n",
+                          alm.hour, alm.minute, alm.second, alm.nanosecond,
+                          alm.year, alm.month, alm.day,
+                          alm.daylight,
+                          enabled == 1 ? "yes" : "no",
+                          pending == 1 ? "yes" : "no");
+
+               if (eft.timezone == EFI_UNSPECIFIED_TIMEZONE)
+                       seq_puts(seq, "Timezone\t: unspecified\n");
+               else
+                       /* XXX fixme: convert to string? */
+                       seq_printf(seq, "Timezone\t: %u\n", alm.timezone);
+       }
 
        /*
         * now prints the capabilities
@@ -269,7 +272,10 @@ static int __init efi_rtc_probe(struct platform_device *dev)
 
        rtc->ops = &efi_rtc_ops;
        clear_bit(RTC_FEATURE_UPDATE_INTERRUPT, rtc->features);
-       set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, rtc->features);
+       if (efi_rt_services_supported(EFI_RT_SUPPORTED_WAKEUP_SERVICES))
+               set_bit(RTC_FEATURE_ALARM_WAKEUP_ONLY, rtc->features);
+       else
+               clear_bit(RTC_FEATURE_ALARM, rtc->features);
 
        device_init_wakeup(&dev->dev, true);
 
index 4b27519..98598bd 100644 (file)
@@ -668,7 +668,8 @@ extern struct efi {
 
 #define EFI_RT_SUPPORTED_ALL                                   0x3fff
 
-#define EFI_RT_SUPPORTED_TIME_SERVICES                         0x000f
+#define EFI_RT_SUPPORTED_TIME_SERVICES                         0x0003
+#define EFI_RT_SUPPORTED_WAKEUP_SERVICES                       0x000c
 #define EFI_RT_SUPPORTED_VARIABLE_SERVICES                     0x0070
 
 extern struct mm_struct efi_mm;