diff --git a/arch/arm/include/asm/vdso_datapage.h
b/arch/arm/include/asm/vdso_datapage.h
index 9011ec75a24b..83a752f969da 100644
--- a/arch/arm/include/asm/vdso_datapage.h
+++ b/arch/arm/include/asm/vdso_datapage.h
@@ -27,7 +27,7 @@
  * 32 bytes.
  */
 struct vdso_data {
-	u32 seq_count;		/* sequence count - odd during updates */
+	unsigned long seq;      /* sequence counter */
 	u16 use_syscall;	/* whether to fall back to syscalls */
 	u16 cs_shift;		/* clocksource shift */
 	u32 xtime_coarse_sec;	/* coarse time */
diff --git a/arch/arm/kernel/vdso.c b/arch/arm/kernel/vdso.c
index 3db74240a766..6ff2893feb45 100644
--- a/arch/arm/kernel/vdso.c
+++ b/arch/arm/kernel/vdso.c
@@ -19,6 +19,7 @@
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
+#include <linux/seqlock.h>
 #include <linux/slab.h>
 #include <linux/timekeeper_internal.h>
 #include <linux/vmalloc.h>
@@ -109,18 +110,8 @@ void arm_install_vdso(struct mm_struct *mm)
 /**
  * update_vsyscall - update the vdso data page
  *
- * Increment the sequence counter, making it odd, indicating to
- * userspace that an update is in progress.  Update the fields used
- * for coarse clocks and, if the architected system timer is in use,
- * the fields used for high precision clocks.  Increment the sequence
- * counter again, making it even, indicating to userspace that the
- * update is finished.
- *
- * Userspace is expected to sample seq_count before reading any other
- * fields from the data page.  If seq_count is odd, userspace is
- * expected to wait until it becomes even.  After copying data from
- * the page, userspace must sample seq_count again; if it has changed
- * from its previous value, userspace must retry the whole sequence.
+ * Update the fields used for coarse clocks and, if the architected
+ * system timer is in use, the fields used for high precision clocks.
  *
  * Calls to update_vsyscall are serialized by the timekeeping core.
  */
@@ -130,8 +121,11 @@ void update_vsyscall(struct timekeeper *tk)
 	struct timespec *wtm = &tk->wall_to_monotonic;
 	bool use_syscall = strcmp(tk->clock->name, "arch_sys_counter");

-	++vdso_data->seq_count;
-	smp_wmb();
+	BUILD_BUG_ON(offsetof(struct seqcount, sequence) != 0);
+	BUILD_BUG_ON(FIELD_SIZEOF(struct vdso_data, seq) !=
+		     FIELD_SIZEOF(struct seqcount, sequence));
+
+	raw_write_seqcount_begin((seqcount_t *)&vdso_data->seq);

 	xtime_coarse = __current_kernel_time();
 	vdso_data->use_syscall			= use_syscall;
@@ -149,8 +143,7 @@ void update_vsyscall(struct timekeeper *tk)
 		vdso_data->cs_mask		= tk->clock->mask;
 	}

-	smp_wmb();
-	++vdso_data->seq_count;
+	raw_write_seqcount_end((seqcount_t *)&vdso_data->seq);
 	flush_dcache_page(virt_to_page(vdso_data));
 }

diff --git a/arch/arm/kernel/vdso/vgettimeofday.c
b/arch/arm/kernel/vdso/vgettimeofday.c
index d5d12528eed9..e434769817d3 100644
--- a/arch/arm/kernel/vdso/vgettimeofday.c
+++ b/arch/arm/kernel/vdso/vgettimeofday.c
@@ -10,6 +10,7 @@

 #include <linux/compiler.h>
 #include <linux/hrtimer.h>
+#include <linux/seqlock.h>
 #include <linux/time.h>
 #include <asm/arch_timer.h>
 #include <asm/barrier.h>
@@ -23,28 +24,6 @@

 extern struct vdso_data *__get_datapage(void);

-static u32 seqcnt_acquire(struct vdso_data *vdata)
-{
-	u32 seq;
-
-	do {
-		seq = vdata->seq_count;
-
-		/* Force gcc to reload from memory when spinning. */
-		asm volatile("" : : : "memory");
-	} while (seq & 1);
-
-	dmb(ish);
-	return seq;
-}
-
-static u32 seqcnt_read(struct vdso_data *vdata)
-{
-	dmb(ish);
-
-	return ACCESS_ONCE(vdata->seq_count);
-}
-
 static long clock_gettime_fallback(clockid_t _clkid, struct timespec *_ts)
 {
 	register struct timespec *ts asm("r1") = _ts;
@@ -63,15 +42,15 @@ static long clock_gettime_fallback(clockid_t _clkid,
struct timespec *_ts)

 static int do_realtime_coarse(struct timespec *ts, struct vdso_data *vdata)
 {
-	u32 seq;
+	unsigned long seq;

 	do {
-		seq = seqcnt_acquire(vdata);
+		seq = raw_read_seqcount_begin((seqcount_t *)&vdata->seq);

 		ts->tv_sec = vdata->xtime_coarse_sec;
 		ts->tv_nsec = vdata->xtime_coarse_nsec;

-	} while (seq != seqcnt_read(vdata));
+	} while (read_seqcount_retry((seqcount_t *)&vdata->seq, seq));

 	return 0;
