Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1668942 > unrolled thread

[PATCH v2 0/3] rtc: make st-lpc robust against y2038/2106 bug

Started byBenjamin Gaignard <benjamin.gaignard@linaro.org>
First post2017-06-19 11:40 +0200
Last post2017-06-19 11:40 +0200
Articles 3 — 1 participant

Back to article view | Back to linux.kernel


Contents

  [PATCH v2 0/3] rtc: make st-lpc robust against y2038/2106 bug Benjamin Gaignard <benjamin.gaignard@linaro.org> - 2017-06-19 11:40 +0200
    [PATCH v2 3/3] rtc: st-lpc: make it robust against y2038/2106 bug Benjamin Gaignard <benjamin.gaignard@linaro.org> - 2017-06-19 11:40 +0200
    [PATCH v2 2/3] tool: timer: rtctest add check for problematic dates Benjamin Gaignard <benjamin.gaignard@linaro.org> - 2017-06-19 11:40 +0200

#1668942 — [PATCH v2 0/3] rtc: make st-lpc robust against y2038/2106 bug

FromBenjamin Gaignard <benjamin.gaignard@linaro.org>
Date2017-06-19 11:40 +0200
Subject[PATCH v2 0/3] rtc: make st-lpc robust against y2038/2106 bug
Message-ID<tU1k6-S2-9@gated-at.bofh.it>
On 32bits platforms "struct timeval" or "time_t" are using u32 to code the
date, this cause tools like "date" or "hwclock" failed even before setting
the RTC device if the date is superior to year 2038 (or 2106).

To avoid this problem I add one RTC test file which directly use RTC ioctl
to set and read RTC time and alarm values.
rtctest_setdate allow to set any date/time given in the command line.

On this version 2 I add check of problematics years in rtctest like suggest
by Alexandre.

Finally that had allowed me to test and fix rtc-st-lpc driver.

Benjamin Gaignard (3):
  tools: timer: add rtctest_setdate
  tool: timer: rtctest add check for problematic dates
  rtc: st-lpc: make it robust against y2038/2106 bug

 drivers/rtc/rtc-st-lpc.c                         |  19 ++--
 tools/testing/selftests/timers/Makefile          |   2 +-
 tools/testing/selftests/timers/rtctest.c         | 121 ++++++++++++++++++++++-
 tools/testing/selftests/timers/rtctest_setdate.c |  86 ++++++++++++++++
 4 files changed, 212 insertions(+), 16 deletions(-)
 create mode 100644 tools/testing/selftests/timers/rtctest_setdate.c

-- 
1.9.1

[toc] | [next] | [standalone]


#1668943 — [PATCH v2 3/3] rtc: st-lpc: make it robust against y2038/2106 bug

FromBenjamin Gaignard <benjamin.gaignard@linaro.org>
Date2017-06-19 11:40 +0200
Subject[PATCH v2 3/3] rtc: st-lpc: make it robust against y2038/2106 bug
Message-ID<tU1k6-S2-13@gated-at.bofh.it>
In reply to#1668942
Make driver use u64 variables and functions to be sure that
it will support dates after year 2038.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
Acked-by: Patrice Chotard <patrice.chotard@st.com>
---
 drivers/rtc/rtc-st-lpc.c | 19 ++++++++-----------
 1 file changed, 8 insertions(+), 11 deletions(-)

diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c
index 74c0a33..82b0af1 100644
--- a/drivers/rtc/rtc-st-lpc.c
+++ b/drivers/rtc/rtc-st-lpc.c
@@ -99,7 +99,7 @@ static int st_rtc_read_time(struct device *dev, struct rtc_time *tm)
 
 	lpt = ((unsigned long long)lpt_msb << 32) | lpt_lsb;
 	do_div(lpt, rtc->clkrate);
-	rtc_time_to_tm(lpt, tm);
+	rtc_time64_to_tm(lpt, tm);
 
 	return 0;
 }
@@ -107,13 +107,10 @@ static int st_rtc_read_time(struct device *dev, struct rtc_time *tm)
 static int st_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
 	struct st_rtc *rtc = dev_get_drvdata(dev);
-	unsigned long long lpt;
-	unsigned long secs, flags;
-	int ret;
+	unsigned long long lpt, secs;
+	unsigned long flags;
 
-	ret = rtc_tm_to_time(tm, &secs);
-	if (ret)
-		return ret;
+	secs = rtc_tm_to_time64(tm);
 
 	lpt = (unsigned long long)secs * rtc->clkrate;
 
@@ -161,13 +158,13 @@ static int st_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *t)
 {
 	struct st_rtc *rtc = dev_get_drvdata(dev);
 	struct rtc_time now;
-	unsigned long now_secs;
-	unsigned long alarm_secs;
+	unsigned long long now_secs;
+	unsigned long long alarm_secs;
 	unsigned long long lpa;
 
 	st_rtc_read_time(dev, &now);
-	rtc_tm_to_time(&now, &now_secs);
-	rtc_tm_to_time(&t->time, &alarm_secs);
+	now_secs = rtc_tm_to_time64(&now);
+	alarm_secs = rtc_tm_to_time64(&t->time);
 
 	/* Invalid alarm time */
 	if (now_secs > alarm_secs)
-- 
1.9.1

[toc] | [prev] | [next] | [standalone]


#1668945 — [PATCH v2 2/3] tool: timer: rtctest add check for problematic dates

FromBenjamin Gaignard <benjamin.gaignard@linaro.org>
Date2017-06-19 11:40 +0200
Subject[PATCH v2 2/3] tool: timer: rtctest add check for problematic dates
Message-ID<tU1k6-S2-17@gated-at.bofh.it>
In reply to#1668942
Some dates could be problematic because they reach the limits of
RTC hardware capabilities.
This patch add various of them but since it will change RTC date
it will be activated only when 'd' args is set.

Signed-off-by: Benjamin Gaignard <benjamin.gaignard@linaro.org>
---
 tools/testing/selftests/timers/rtctest.c | 121 ++++++++++++++++++++++++++++++-
 1 file changed, 117 insertions(+), 4 deletions(-)

diff --git a/tools/testing/selftests/timers/rtctest.c b/tools/testing/selftests/timers/rtctest.c
index 4230d30..715a016 100644
--- a/tools/testing/selftests/timers/rtctest.c
+++ b/tools/testing/selftests/timers/rtctest.c
@@ -21,6 +21,9 @@
 #include <stdlib.h>
 #include <errno.h>
 
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
 
 /*
  * This expects the new RTC class driver framework, working with
@@ -29,23 +32,77 @@
  */
 static const char default_rtc[] = "/dev/rtc0";
 
+static struct rtc_time cutoff_dates[] = {
+	{
+		.tm_year = 70, /* 1970 -1900 */
+		.tm_mday = 1,
+	},
+	{
+		.tm_year = 137, /* 2037 -1900 */
+		.tm_mday = 1,
+	},
+	{
+		.tm_year = 138, /* 2038 -1900 */
+		.tm_mday = 1,
+	},
+	{
+		.tm_year = 199, /* 2099 -1900 */
+		.tm_mday = 1,
+	},
+	{
+		.tm_year = 200, /* 2100 -1900 */
+		.tm_mday = 1,
+	},
+	{
+		.tm_year = 205, /* 2105 -1900 */
+		.tm_mday = 1,
+	},
+	{
+		.tm_year = 206, /* 2106 -1900 */
+		.tm_mday = 1,
+	},
+	{
+		.tm_year = 361, /* 2261 -1900 */
+		.tm_mday = 1,
+	},
+	{
+		.tm_year = 362, /* 2262 -1900 */
+		.tm_mday = 1,
+	},
+};
+
+static int compare_dates(struct rtc_time *a, struct rtc_time *b)
+{
+	if (a->tm_year != b->tm_year ||
+	    a->tm_mon != b->tm_mon ||
+	    a->tm_mday != b->tm_mday ||
+	    a->tm_hour != b->tm_hour ||
+	    a->tm_min != b->tm_min ||
+	    ((b->tm_sec - a->tm_sec) > 1))
+		return 1;
+
+	return 0;
+}
 
 int main(int argc, char **argv)
 {
-	int i, fd, retval, irqcount = 0;
+	int i, fd, retval, irqcount = 0, dangerous = 0;
 	unsigned long tmp, data;
 	struct rtc_time rtc_tm;
 	const char *rtc = default_rtc;
 	struct timeval start, end, diff;
 
 	switch (argc) {
+	case 3:
+		if (*argv[2] == 'd')
+			dangerous = 1;
 	case 2:
 		rtc = argv[1];
 		/* FALLTHROUGH */
 	case 1:
 		break;
 	default:
-		fprintf(stderr, "usage:  rtctest [rtcdev]\n");
+		fprintf(stderr, "usage:  rtctest [rtcdev] [d]\n");
 		return 1;
 	}
 
@@ -202,7 +259,7 @@ int main(int argc, char **argv)
 		/* not all RTCs support periodic IRQs */
 		if (errno == EINVAL) {
 			fprintf(stderr, "\nNo periodic IRQ support\n");
-			goto done;
+			goto test_DATE;
 		}
 		perror("RTC_IRQP_READ ioctl");
 		exit(errno);
@@ -221,7 +278,7 @@ int main(int argc, char **argv)
 			if (errno == EINVAL) {
 				fprintf(stderr,
 					"\n...Periodic IRQ rate is fixed\n");
-				goto done;
+				goto test_DATE;
 			}
 			perror("RTC_IRQP_SET ioctl");
 			exit(errno);
@@ -269,6 +326,62 @@ int main(int argc, char **argv)
 		}
 	}
 
+test_DATE:
+	if (!dangerous)
+		goto done;
+
+	fprintf(stderr, "\nTesting problematic dates\n");
+
+	for (i = 0; i < ARRAY_SIZE(cutoff_dates); i++) {
+		struct rtc_time current;
+
+		/* Write the new date in RTC */
+		retval = ioctl(fd, RTC_SET_TIME, &cutoff_dates[i]);
+		if (retval == -1) {
+			perror("RTC_SET_TIME ioctl");
+			close(fd);
+			exit(errno);
+		}
+
+		/* Read back */
+		retval = ioctl(fd, RTC_RD_TIME, &current);
+		if (retval == -1) {
+			perror("RTC_RD_TIME ioctl");
+			exit(errno);
+		}
+
+		if(compare_dates(&cutoff_dates[i], &current)) {
+			fprintf(stderr,"Setting date %d failed\n",
+			        cutoff_dates[i].tm_year + 1900);
+			goto done;
+		}
+
+		cutoff_dates[i].tm_sec += 5;
+
+		/* Write the new alarm in RTC */
+		retval = ioctl(fd, RTC_ALM_SET, &cutoff_dates[i]);
+		if (retval == -1) {
+			perror("RTC_ALM_SET ioctl");
+			close(fd);
+			exit(errno);
+		}
+
+		/* Read back */
+		retval = ioctl(fd, RTC_ALM_READ, &current);
+		if (retval == -1) {
+			perror("RTC_ALM_READ ioctl");
+			exit(errno);
+		}
+
+		if(compare_dates(&cutoff_dates[i], &current)) {
+			fprintf(stderr,"Setting alarm %d failed\n",
+			        cutoff_dates[i].tm_year + 1900);
+			goto done;
+		}
+
+		fprintf(stderr, "Setting year %d is OK \n",
+			cutoff_dates[i].tm_year + 1900);
+	}
 done:
 	fprintf(stderr, "\n\n\t\t\t *** Test complete ***\n");
 
-- 
1.9.1

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web