Skip to content

Commit 211e5db

Browse files
committed
rtc: mc146818: Detect and handle broken RTCs
The recent fix for handling the UIP bit unearthed another issue in the RTC code. If the RTC is advertised but the readout is straight 0xFF because it's not available, the old code just proceeded with crappy values, but the new code hangs because it waits for the UIP bit to become low. Add a sanity check in the RTC CMOS probe function which reads the RTC_VALID register (Register D) which should have bit 0-6 cleared. If that's not the case then fail to register the CMOS. Add the same check to mc146818_get_time(), warn once when the condition is true and invalidate the rtc_time data. Reported-by: Mickaël Salaün <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Tested-by: Mickaël Salaün <[email protected]> Acked-by: Alexandre Belloni <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 13391c6 commit 211e5db

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

drivers/rtc/rtc-cmos.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,14 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)
805805

806806
spin_lock_irq(&rtc_lock);
807807

808+
/* Ensure that the RTC is accessible. Bit 0-6 must be 0! */
809+
if ((CMOS_READ(RTC_VALID) & 0x7f) != 0) {
810+
spin_unlock_irq(&rtc_lock);
811+
dev_warn(dev, "not accessible\n");
812+
retval = -ENXIO;
813+
goto cleanup1;
814+
}
815+
808816
if (!(flags & CMOS_RTC_FLAGS_NOFREQ)) {
809817
/* force periodic irq to CMOS reset default of 1024Hz;
810818
*

drivers/rtc/rtc-mc146818-lib.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ unsigned int mc146818_get_time(struct rtc_time *time)
2121

2222
again:
2323
spin_lock_irqsave(&rtc_lock, flags);
24+
/* Ensure that the RTC is accessible. Bit 0-6 must be 0! */
25+
if (WARN_ON_ONCE((CMOS_READ(RTC_VALID) & 0x7f) != 0)) {
26+
spin_unlock_irqrestore(&rtc_lock, flags);
27+
memset(time, 0xff, sizeof(*time));
28+
return 0;
29+
}
30+
2431
/*
2532
* Check whether there is an update in progress during which the
2633
* readout is unspecified. The maximum update time is ~2ms. Poll

0 commit comments

Comments
 (0)