Skip to content

Commit 2aaa36e

Browse files
matjonshuahkh
authored andcommitted
selftests/rtc: continuously read RTC in a loop for 30s
Some problems with reading the RTC time may happen rarely, for example while the RTC is updating. So read the RTC many times to catch these problems. For example, a previous attempt for my commit ea6fa49 ("rtc: mc146818-lib: fix RTC presence check") was incorrect and would have triggered this selftest. To avoid the risk of damaging the hardware, wait 11ms before consecutive reads. In rtc_time_to_timestamp I copied values manually instead of casting - just to be on the safe side. The 11ms wait period was chosen so that it is not a divisor of 1000ms. Signed-off-by: Mateusz Jończyk <mat.jonczyk@o2.pl> Cc: Alessandro Zummo <a.zummo@towertech.it> Cc: Alexandre Belloni <alexandre.belloni@bootlin.com> Cc: Shuah Khan <shuah@kernel.org> Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
1 parent 1900be2 commit 2aaa36e

File tree

2 files changed

+67
-1
lines changed

2 files changed

+67
-1
lines changed

tools/testing/selftests/rtc/rtctest.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020

2121
#define NUM_UIE 3
2222
#define ALARM_DELTA 3
23+
#define READ_LOOP_DURATION_SEC 30
24+
#define READ_LOOP_SLEEP_MS 11
2325

2426
static char *rtc_file = "/dev/rtc0";
2527

@@ -49,6 +51,70 @@ TEST_F(rtc, date_read) {
4951
rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
5052
}
5153

54+
static time_t rtc_time_to_timestamp(struct rtc_time *rtc_time)
55+
{
56+
struct tm tm_time = {
57+
.tm_sec = rtc_time->tm_sec,
58+
.tm_min = rtc_time->tm_min,
59+
.tm_hour = rtc_time->tm_hour,
60+
.tm_mday = rtc_time->tm_mday,
61+
.tm_mon = rtc_time->tm_mon,
62+
.tm_year = rtc_time->tm_year,
63+
};
64+
65+
return mktime(&tm_time);
66+
}
67+
68+
static void nanosleep_with_retries(long ns)
69+
{
70+
struct timespec req = {
71+
.tv_sec = 0,
72+
.tv_nsec = ns,
73+
};
74+
struct timespec rem;
75+
76+
while (nanosleep(&req, &rem) != 0) {
77+
req.tv_sec = rem.tv_sec;
78+
req.tv_nsec = rem.tv_nsec;
79+
}
80+
}
81+
82+
TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) {
83+
int rc;
84+
long iter_count = 0;
85+
struct rtc_time rtc_tm;
86+
time_t start_rtc_read, prev_rtc_read;
87+
88+
TH_LOG("Continuously reading RTC time for %ds (with %dms breaks after every read).",
89+
READ_LOOP_DURATION_SEC, READ_LOOP_SLEEP_MS);
90+
91+
rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
92+
ASSERT_NE(-1, rc);
93+
start_rtc_read = rtc_time_to_timestamp(&rtc_tm);
94+
prev_rtc_read = start_rtc_read;
95+
96+
do {
97+
time_t rtc_read;
98+
99+
rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
100+
ASSERT_NE(-1, rc);
101+
102+
rtc_read = rtc_time_to_timestamp(&rtc_tm);
103+
/* Time should not go backwards */
104+
ASSERT_LE(prev_rtc_read, rtc_read);
105+
/* Time should not increase more then 1s at a time */
106+
ASSERT_GE(prev_rtc_read + 1, rtc_read);
107+
108+
/* Sleep 11ms to avoid killing / overheating the RTC */
109+
nanosleep_with_retries(READ_LOOP_SLEEP_MS * 1000000);
110+
111+
prev_rtc_read = rtc_read;
112+
iter_count++;
113+
} while (prev_rtc_read <= start_rtc_read + READ_LOOP_DURATION_SEC);
114+
115+
TH_LOG("Performed %ld RTC time reads.", iter_count);
116+
}
117+
52118
TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) {
53119
int i, rc, irq = 0;
54120
unsigned long data;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
timeout=180
1+
timeout=210

0 commit comments

Comments
 (0)