aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2018-09-04 10:51:29 -0400
committerAlexandre Belloni <alexandre.belloni@bootlin.com>2018-11-07 11:13:55 -0500
commitfbb974ba693bbfb4e24a62181ef16d4e45febc37 (patch)
treeeb77bc1c8c37007494dfc63d8a5c88ad8ba04ab8
parent651022382c7f8da46cb4872a545ee1da6d097d2a (diff)
rtc: cmos: Do not export alarm rtc_ops when we do not support alarms
When there is no IRQ configured for the RTC, the rtc-cmos code does not support alarms, all alarm rtc_ops fail with -EIO / -EINVAL. The rtc-core expects a rtc driver which does not support rtc alarms to not have alarm ops at all. Otherwise the wakealarm sysfs attr will read as empty rather then returning an error, making it impossible for userspace to find out beforehand if alarms are supported. A system without an IRQ for the RTC before this patch: [root@localhost ~]# cat /sys/class/rtc/rtc0/wakealarm [root@localhost ~]# After this patch: [root@localhost ~]# cat /sys/class/rtc/rtc0/wakealarm cat: /sys/class/rtc/rtc0/wakealarm: No such file or directory [root@localhost ~]# This fixes gnome-session + systemd trying to use suspend-then-hibernate, which causes systemd to abort the suspend when writing the RTC alarm fails. BugLink: https://github.com/systemd/systemd/issues/9988 Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
-rw-r--r--drivers/rtc/rtc-cmos.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index df0c5776d49b..a5a19ff10535 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -257,6 +257,7 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)
257 struct cmos_rtc *cmos = dev_get_drvdata(dev); 257 struct cmos_rtc *cmos = dev_get_drvdata(dev);
258 unsigned char rtc_control; 258 unsigned char rtc_control;
259 259
260 /* This not only a rtc_op, but also called directly */
260 if (!is_valid_irq(cmos->irq)) 261 if (!is_valid_irq(cmos->irq))
261 return -EIO; 262 return -EIO;
262 263
@@ -452,6 +453,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)
452 unsigned char mon, mday, hrs, min, sec, rtc_control; 453 unsigned char mon, mday, hrs, min, sec, rtc_control;
453 int ret; 454 int ret;
454 455
456 /* This not only a rtc_op, but also called directly */
455 if (!is_valid_irq(cmos->irq)) 457 if (!is_valid_irq(cmos->irq))
456 return -EIO; 458 return -EIO;
457 459
@@ -516,9 +518,6 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
516 struct cmos_rtc *cmos = dev_get_drvdata(dev); 518 struct cmos_rtc *cmos = dev_get_drvdata(dev);
517 unsigned long flags; 519 unsigned long flags;
518 520
519 if (!is_valid_irq(cmos->irq))
520 return -EINVAL;
521
522 spin_lock_irqsave(&rtc_lock, flags); 521 spin_lock_irqsave(&rtc_lock, flags);
523 522
524 if (enabled) 523 if (enabled)
@@ -579,6 +578,12 @@ static const struct rtc_class_ops cmos_rtc_ops = {
579 .alarm_irq_enable = cmos_alarm_irq_enable, 578 .alarm_irq_enable = cmos_alarm_irq_enable,
580}; 579};
581 580
581static const struct rtc_class_ops cmos_rtc_ops_no_alarm = {
582 .read_time = cmos_read_time,
583 .set_time = cmos_set_time,
584 .proc = cmos_procfs,
585};
586
582/*----------------------------------------------------------------*/ 587/*----------------------------------------------------------------*/
583 588
584/* 589/*
@@ -855,9 +860,12 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
855 dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq); 860 dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);
856 goto cleanup1; 861 goto cleanup1;
857 } 862 }
863
864 cmos_rtc.rtc->ops = &cmos_rtc_ops;
865 } else {
866 cmos_rtc.rtc->ops = &cmos_rtc_ops_no_alarm;
858 } 867 }
859 868
860 cmos_rtc.rtc->ops = &cmos_rtc_ops;
861 cmos_rtc.rtc->nvram_old_abi = true; 869 cmos_rtc.rtc->nvram_old_abi = true;
862 retval = rtc_register_device(cmos_rtc.rtc); 870 retval = rtc_register_device(cmos_rtc.rtc);
863 if (retval) 871 if (retval)