From: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Date: Tue, 2 Aug 2016 12:18:30 +0000 (+0100)
Subject: greybus: timesync: Implement a retry mechanism
X-Git-Url: http://git.maquefel.me/?a=commitdiff_plain;h=7aa278b771505f8fb85406a891af0b7743710620;p=linux.git

greybus: timesync: Implement a retry mechanism

It's possible the AP could miss an incoming SVC timesync pulse i.e. the AP
could have interrupts switched off for long enough that one SVC GPIO strobe
ends up over-lapping another one. TimeSync should be able to deal with this
type of transitory failure by retrying a failed synchronous TimeSync resync
up to 'n' number of times. For this patch 'n' has been set to five, which
is a hand-wavy choice that 'feels' right.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
---

diff --git a/drivers/staging/greybus/timesync.c b/drivers/staging/greybus/timesync.c
index ec0a51d6378d2..744ae0c9d586d 100644
--- a/drivers/staging/greybus/timesync.c
+++ b/drivers/staging/greybus/timesync.c
@@ -34,6 +34,9 @@
 #define GB_TIMESYNC_KTIME_UPDATE		msecs_to_jiffies(1000)
 #define GB_TIMESYNC_MAX_KTIME_CONVERSION	15
 
+/* Maximum number of times we'll retry a failed synchronous sync */
+#define GB_TIMESYNC_MAX_RETRIES			5
+
 /* Reported nanoseconds/femtoseconds per clock */
 static u64 gb_timesync_ns_per_clock;
 static u64 gb_timesync_fs_per_clock;
@@ -870,19 +873,26 @@ int gb_timesync_schedule_synchronous(struct gb_interface *interface)
 {
 	int ret;
 	struct gb_timesync_svc *timesync_svc;
+	int retries;
 
 	if (!(interface->features & GREYBUS_INTERFACE_FEATURE_TIMESYNC))
 		return 0;
 
 	mutex_lock(&gb_timesync_svc_list_mutex);
-	timesync_svc = gb_timesync_find_timesync_svc(interface->hd);
-	if (!timesync_svc) {
-		ret = -ENODEV;
-		goto done;
-	}
+	for (retries = 0; retries < GB_TIMESYNC_MAX_RETRIES; retries++) {
+		timesync_svc = gb_timesync_find_timesync_svc(interface->hd);
+		if (!timesync_svc) {
+			ret = -ENODEV;
+			goto done;
+		}
 
-	ret = __gb_timesync_schedule_synchronous(timesync_svc,
+		ret = __gb_timesync_schedule_synchronous(timesync_svc,
 						 GB_TIMESYNC_STATE_INIT);
+		if (!ret)
+			break;
+	}
+	if (ret && retries == GB_TIMESYNC_MAX_RETRIES)
+		ret = -ETIMEDOUT;
 done:
 	mutex_unlock(&gb_timesync_svc_list_mutex);
 	return ret;