Commit 2aaa36e9 authored by Mateusz Jończyk's avatar Mateusz Jończyk Committed by Shuah Khan

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 ea6fa496 ("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: default avatarMateusz 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: default avatarShuah Khan <skhan@linuxfoundation.org>
parent 1900be28
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
#define NUM_UIE 3 #define NUM_UIE 3
#define ALARM_DELTA 3 #define ALARM_DELTA 3
#define READ_LOOP_DURATION_SEC 30
#define READ_LOOP_SLEEP_MS 11
static char *rtc_file = "/dev/rtc0"; static char *rtc_file = "/dev/rtc0";
...@@ -49,6 +51,70 @@ TEST_F(rtc, date_read) { ...@@ -49,6 +51,70 @@ TEST_F(rtc, date_read) {
rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec); rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec);
} }
static time_t rtc_time_to_timestamp(struct rtc_time *rtc_time)
{
struct tm tm_time = {
.tm_sec = rtc_time->tm_sec,
.tm_min = rtc_time->tm_min,
.tm_hour = rtc_time->tm_hour,
.tm_mday = rtc_time->tm_mday,
.tm_mon = rtc_time->tm_mon,
.tm_year = rtc_time->tm_year,
};
return mktime(&tm_time);
}
static void nanosleep_with_retries(long ns)
{
struct timespec req = {
.tv_sec = 0,
.tv_nsec = ns,
};
struct timespec rem;
while (nanosleep(&req, &rem) != 0) {
req.tv_sec = rem.tv_sec;
req.tv_nsec = rem.tv_nsec;
}
}
TEST_F_TIMEOUT(rtc, date_read_loop, READ_LOOP_DURATION_SEC + 2) {
int rc;
long iter_count = 0;
struct rtc_time rtc_tm;
time_t start_rtc_read, prev_rtc_read;
TH_LOG("Continuously reading RTC time for %ds (with %dms breaks after every read).",
READ_LOOP_DURATION_SEC, READ_LOOP_SLEEP_MS);
rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
ASSERT_NE(-1, rc);
start_rtc_read = rtc_time_to_timestamp(&rtc_tm);
prev_rtc_read = start_rtc_read;
do {
time_t rtc_read;
rc = ioctl(self->fd, RTC_RD_TIME, &rtc_tm);
ASSERT_NE(-1, rc);
rtc_read = rtc_time_to_timestamp(&rtc_tm);
/* Time should not go backwards */
ASSERT_LE(prev_rtc_read, rtc_read);
/* Time should not increase more then 1s at a time */
ASSERT_GE(prev_rtc_read + 1, rtc_read);
/* Sleep 11ms to avoid killing / overheating the RTC */
nanosleep_with_retries(READ_LOOP_SLEEP_MS * 1000000);
prev_rtc_read = rtc_read;
iter_count++;
} while (prev_rtc_read <= start_rtc_read + READ_LOOP_DURATION_SEC);
TH_LOG("Performed %ld RTC time reads.", iter_count);
}
TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) { TEST_F_TIMEOUT(rtc, uie_read, NUM_UIE + 2) {
int i, rc, irq = 0; int i, rc, irq = 0;
unsigned long data; unsigned long data;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment