1/* 2 * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. 3 */ 4 5#ifndef _ASM_SPARC_VVAR_DATA_H 6#define _ASM_SPARC_VVAR_DATA_H 7 8#include <asm/clocksource.h> 9#include <linux/seqlock.h> 10#include <linux/time.h> 11#include <linux/types.h> 12 13struct vvar_data { 14 unsigned int seq; 15 16 int vclock_mode; 17 struct { /* extract of a clocksource struct */ 18 u64 cycle_last; 19 u64 mask; 20 int mult; 21 int shift; 22 } clock; 23 /* open coded 'struct timespec' */ 24 u64 wall_time_sec; 25 u64 wall_time_snsec; 26 u64 monotonic_time_snsec; 27 u64 monotonic_time_sec; 28 u64 monotonic_time_coarse_sec; 29 u64 monotonic_time_coarse_nsec; 30 u64 wall_time_coarse_sec; 31 u64 wall_time_coarse_nsec; 32 33 int tz_minuteswest; 34 int tz_dsttime; 35}; 36 37extern struct vvar_data *vvar_data; 38extern int vdso_fix_stick; 39 40static inline unsigned int vvar_read_begin(const struct vvar_data *s) 41{ 42 unsigned int ret; 43 44repeat: 45 ret = READ_ONCE(s->seq); 46 if (unlikely(ret & 1)) { 47 cpu_relax(); 48 goto repeat; 49 } 50 smp_rmb(); /* Finish all reads before we return seq */ 51 return ret; 52} 53 54static inline int vvar_read_retry(const struct vvar_data *s, 55 unsigned int start) 56{ 57 smp_rmb(); /* Finish all reads before checking the value of seq */ 58 return unlikely(s->seq != start); 59} 60 61static inline void vvar_write_begin(struct vvar_data *s) 62{ 63 ++s->seq; 64 smp_wmb(); /* Makes sure that increment of seq is reflected */ 65} 66 67static inline void vvar_write_end(struct vvar_data *s) 68{ 69 smp_wmb(); /* Makes the value of seq current before we increment */ 70 ++s->seq; 71} 72 73 74#endif /* _ASM_SPARC_VVAR_DATA_H */ 75