diff options
author | Tina Ruchandani <ruchandani.tina@gmail.com> | 2016-03-19 14:21:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-03-20 16:47:13 -0400 |
commit | ebf918cf9922748b9d4d9bf6a2620530cdc5a1d0 (patch) | |
tree | 815830cb374a7c8d945af83d1ed00ff89930a269 /drivers/isdn | |
parent | 4320f21935534dad44e8d112fc085d13c29e7f66 (diff) |
isdn: Use ktime_t instead of 'struct timeval'
'struct timeval' uses 32-bit representation for seconds which will
overflow in year 2038 and beyond. mISDN/clock.c needs to compute and
store elapsed time in intervals of 125 microseconds. This patch replaces
the usage of 'struct timeval' with 64-bit ktime_t which is y2038 safe.
The patch also replaces do_gettimeofday() (wall-clock time) with
ktime_get() (monotonic time) since we only care about elapsed time here.
Signed-off-by: Tina Ruchandani <ruchandani.tina@gmail.com>
Suggested-by: Arnd Bergmnann <arnd@arndb.de>
Suggested-by: David Miller <davem@davemloft.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/isdn')
-rw-r--r-- | drivers/isdn/mISDN/clock.c | 69 |
1 files changed, 29 insertions, 40 deletions
diff --git a/drivers/isdn/mISDN/clock.c b/drivers/isdn/mISDN/clock.c index 693fb7c9b59a..f8f659f1ce1b 100644 --- a/drivers/isdn/mISDN/clock.c +++ b/drivers/isdn/mISDN/clock.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/types.h> | 37 | #include <linux/types.h> |
38 | #include <linux/stddef.h> | 38 | #include <linux/stddef.h> |
39 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
40 | #include <linux/ktime.h> | ||
40 | #include <linux/mISDNif.h> | 41 | #include <linux/mISDNif.h> |
41 | #include <linux/export.h> | 42 | #include <linux/export.h> |
42 | #include "core.h" | 43 | #include "core.h" |
@@ -45,15 +46,15 @@ static u_int *debug; | |||
45 | static LIST_HEAD(iclock_list); | 46 | static LIST_HEAD(iclock_list); |
46 | static DEFINE_RWLOCK(iclock_lock); | 47 | static DEFINE_RWLOCK(iclock_lock); |
47 | static u16 iclock_count; /* counter of last clock */ | 48 | static u16 iclock_count; /* counter of last clock */ |
48 | static struct timeval iclock_tv; /* time stamp of last clock */ | 49 | static ktime_t iclock_timestamp; /* time stamp of last clock */ |
49 | static int iclock_tv_valid; /* already received one timestamp */ | 50 | static int iclock_timestamp_valid; /* already received one timestamp */ |
50 | static struct mISDNclock *iclock_current; | 51 | static struct mISDNclock *iclock_current; |
51 | 52 | ||
52 | void | 53 | void |
53 | mISDN_init_clock(u_int *dp) | 54 | mISDN_init_clock(u_int *dp) |
54 | { | 55 | { |
55 | debug = dp; | 56 | debug = dp; |
56 | do_gettimeofday(&iclock_tv); | 57 | iclock_timestamp = ktime_get(); |
57 | } | 58 | } |
58 | 59 | ||
59 | static void | 60 | static void |
@@ -86,7 +87,7 @@ select_iclock(void) | |||
86 | } | 87 | } |
87 | if (bestclock != iclock_current) { | 88 | if (bestclock != iclock_current) { |
88 | /* no clock received yet */ | 89 | /* no clock received yet */ |
89 | iclock_tv_valid = 0; | 90 | iclock_timestamp_valid = 0; |
90 | } | 91 | } |
91 | iclock_current = bestclock; | 92 | iclock_current = bestclock; |
92 | } | 93 | } |
@@ -139,12 +140,11 @@ mISDN_unregister_clock(struct mISDNclock *iclock) | |||
139 | EXPORT_SYMBOL(mISDN_unregister_clock); | 140 | EXPORT_SYMBOL(mISDN_unregister_clock); |
140 | 141 | ||
141 | void | 142 | void |
142 | mISDN_clock_update(struct mISDNclock *iclock, int samples, struct timeval *tv) | 143 | mISDN_clock_update(struct mISDNclock *iclock, int samples, ktime_t *timestamp) |
143 | { | 144 | { |
144 | u_long flags; | 145 | u_long flags; |
145 | struct timeval tv_now; | 146 | ktime_t timestamp_now; |
146 | time_t elapsed_sec; | 147 | u16 delta; |
147 | int elapsed_8000th; | ||
148 | 148 | ||
149 | write_lock_irqsave(&iclock_lock, flags); | 149 | write_lock_irqsave(&iclock_lock, flags); |
150 | if (iclock_current != iclock) { | 150 | if (iclock_current != iclock) { |
@@ -156,33 +156,27 @@ mISDN_clock_update(struct mISDNclock *iclock, int samples, struct timeval *tv) | |||
156 | write_unlock_irqrestore(&iclock_lock, flags); | 156 | write_unlock_irqrestore(&iclock_lock, flags); |
157 | return; | 157 | return; |
158 | } | 158 | } |
159 | if (iclock_tv_valid) { | 159 | if (iclock_timestamp_valid) { |
160 | /* increment sample counter by given samples */ | 160 | /* increment sample counter by given samples */ |
161 | iclock_count += samples; | 161 | iclock_count += samples; |
162 | if (tv) { /* tv must be set, if function call is delayed */ | 162 | if (timestamp) { /* timestamp must be set, if function call is delayed */ |
163 | iclock_tv.tv_sec = tv->tv_sec; | 163 | iclock_timestamp = *timestamp; |
164 | iclock_tv.tv_usec = tv->tv_usec; | 164 | } else { |
165 | } else | 165 | iclock_timestamp = ktime_get(); |
166 | do_gettimeofday(&iclock_tv); | 166 | } |
167 | } else { | 167 | } else { |
168 | /* calc elapsed time by system clock */ | 168 | /* calc elapsed time by system clock */ |
169 | if (tv) { /* tv must be set, if function call is delayed */ | 169 | if (timestamp) { /* timestamp must be set, if function call is delayed */ |
170 | tv_now.tv_sec = tv->tv_sec; | 170 | timestamp_now = *timestamp; |
171 | tv_now.tv_usec = tv->tv_usec; | 171 | } else { |
172 | } else | 172 | timestamp_now = ktime_get(); |
173 | do_gettimeofday(&tv_now); | ||
174 | elapsed_sec = tv_now.tv_sec - iclock_tv.tv_sec; | ||
175 | elapsed_8000th = (tv_now.tv_usec / 125) | ||
176 | - (iclock_tv.tv_usec / 125); | ||
177 | if (elapsed_8000th < 0) { | ||
178 | elapsed_sec -= 1; | ||
179 | elapsed_8000th += 8000; | ||
180 | } | 173 | } |
174 | delta = ktime_divns(ktime_sub(timestamp_now, iclock_timestamp), | ||
175 | (NSEC_PER_SEC / 8000)); | ||
181 | /* add elapsed time to counter and set new timestamp */ | 176 | /* add elapsed time to counter and set new timestamp */ |
182 | iclock_count += elapsed_sec * 8000 + elapsed_8000th; | 177 | iclock_count += delta; |
183 | iclock_tv.tv_sec = tv_now.tv_sec; | 178 | iclock_timestamp = timestamp_now; |
184 | iclock_tv.tv_usec = tv_now.tv_usec; | 179 | iclock_timestamp_valid = 1; |
185 | iclock_tv_valid = 1; | ||
186 | if (*debug & DEBUG_CLOCK) | 180 | if (*debug & DEBUG_CLOCK) |
187 | printk("Received first clock from source '%s'.\n", | 181 | printk("Received first clock from source '%s'.\n", |
188 | iclock_current ? iclock_current->name : "nothing"); | 182 | iclock_current ? iclock_current->name : "nothing"); |
@@ -195,22 +189,17 @@ unsigned short | |||
195 | mISDN_clock_get(void) | 189 | mISDN_clock_get(void) |
196 | { | 190 | { |
197 | u_long flags; | 191 | u_long flags; |
198 | struct timeval tv_now; | 192 | ktime_t timestamp_now; |
199 | time_t elapsed_sec; | 193 | u16 delta; |
200 | int elapsed_8000th; | ||
201 | u16 count; | 194 | u16 count; |
202 | 195 | ||
203 | read_lock_irqsave(&iclock_lock, flags); | 196 | read_lock_irqsave(&iclock_lock, flags); |
204 | /* calc elapsed time by system clock */ | 197 | /* calc elapsed time by system clock */ |
205 | do_gettimeofday(&tv_now); | 198 | timestamp_now = ktime_get(); |
206 | elapsed_sec = tv_now.tv_sec - iclock_tv.tv_sec; | 199 | delta = ktime_divns(ktime_sub(timestamp_now, iclock_timestamp), |
207 | elapsed_8000th = (tv_now.tv_usec / 125) - (iclock_tv.tv_usec / 125); | 200 | (NSEC_PER_SEC / 8000)); |
208 | if (elapsed_8000th < 0) { | ||
209 | elapsed_sec -= 1; | ||
210 | elapsed_8000th += 8000; | ||
211 | } | ||
212 | /* add elapsed time to counter */ | 201 | /* add elapsed time to counter */ |
213 | count = iclock_count + elapsed_sec * 8000 + elapsed_8000th; | 202 | count = iclock_count + delta; |
214 | read_unlock_irqrestore(&iclock_lock, flags); | 203 | read_unlock_irqrestore(&iclock_lock, flags); |
215 | return count; | 204 | return count; |
216 | } | 205 | } |