diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2017-08-20 05:46:46 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2017-08-20 05:46:46 -0400 |
commit | 4e2a809703e2b2300438a425b0a3f2013b55fcc6 (patch) | |
tree | b3233970c706fdd93f9d381c1f48186fe0f8a252 | |
parent | 3cf294962df8fcde710eb5e762e0929e2ba49947 (diff) | |
parent | 47b4a457e4cc816b3fdd2ee55c65fda8ea6de051 (diff) |
Merge branch 'fortglx/4.14/time' of https://git.linaro.org/people/john.stultz/linux into timers/core
Pull timekeepig updates from John Stultz
- kselftest improvements
- Use the proper timekeeper in the debug code
- Prevent accessing an unavailable wakeup source in the alarmtimer sysfs
interface.
-rw-r--r-- | kernel/time/alarmtimer.c | 11 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 2 | ||||
-rw-r--r-- | tools/testing/selftests/timers/freq-step.c | 8 | ||||
-rw-r--r-- | tools/testing/selftests/timers/set-timer-lat.c | 103 |
4 files changed, 106 insertions, 18 deletions
diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index 0b8ff7d257ea..73a2b476e59f 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c | |||
@@ -56,9 +56,9 @@ static ktime_t freezer_delta; | |||
56 | static DEFINE_SPINLOCK(freezer_delta_lock); | 56 | static DEFINE_SPINLOCK(freezer_delta_lock); |
57 | #endif | 57 | #endif |
58 | 58 | ||
59 | #ifdef CONFIG_RTC_CLASS | ||
59 | static struct wakeup_source *ws; | 60 | static struct wakeup_source *ws; |
60 | 61 | ||
61 | #ifdef CONFIG_RTC_CLASS | ||
62 | /* rtc timer and device for setting alarm wakeups at suspend */ | 62 | /* rtc timer and device for setting alarm wakeups at suspend */ |
63 | static struct rtc_timer rtctimer; | 63 | static struct rtc_timer rtctimer; |
64 | static struct rtc_device *rtcdev; | 64 | static struct rtc_device *rtcdev; |
@@ -89,6 +89,7 @@ static int alarmtimer_rtc_add_device(struct device *dev, | |||
89 | { | 89 | { |
90 | unsigned long flags; | 90 | unsigned long flags; |
91 | struct rtc_device *rtc = to_rtc_device(dev); | 91 | struct rtc_device *rtc = to_rtc_device(dev); |
92 | struct wakeup_source *__ws; | ||
92 | 93 | ||
93 | if (rtcdev) | 94 | if (rtcdev) |
94 | return -EBUSY; | 95 | return -EBUSY; |
@@ -98,13 +99,20 @@ static int alarmtimer_rtc_add_device(struct device *dev, | |||
98 | if (!device_may_wakeup(rtc->dev.parent)) | 99 | if (!device_may_wakeup(rtc->dev.parent)) |
99 | return -1; | 100 | return -1; |
100 | 101 | ||
102 | __ws = wakeup_source_register("alarmtimer"); | ||
103 | |||
101 | spin_lock_irqsave(&rtcdev_lock, flags); | 104 | spin_lock_irqsave(&rtcdev_lock, flags); |
102 | if (!rtcdev) { | 105 | if (!rtcdev) { |
103 | rtcdev = rtc; | 106 | rtcdev = rtc; |
104 | /* hold a reference so it doesn't go away */ | 107 | /* hold a reference so it doesn't go away */ |
105 | get_device(dev); | 108 | get_device(dev); |
109 | ws = __ws; | ||
110 | __ws = NULL; | ||
106 | } | 111 | } |
107 | spin_unlock_irqrestore(&rtcdev_lock, flags); | 112 | spin_unlock_irqrestore(&rtcdev_lock, flags); |
113 | |||
114 | wakeup_source_unregister(__ws); | ||
115 | |||
108 | return 0; | 116 | return 0; |
109 | } | 117 | } |
110 | 118 | ||
@@ -860,7 +868,6 @@ static int __init alarmtimer_init(void) | |||
860 | error = PTR_ERR(pdev); | 868 | error = PTR_ERR(pdev); |
861 | goto out_drv; | 869 | goto out_drv; |
862 | } | 870 | } |
863 | ws = wakeup_source_register("alarmtimer"); | ||
864 | return 0; | 871 | return 0; |
865 | 872 | ||
866 | out_drv: | 873 | out_drv: |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index cedafa008de5..8f5866981883 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -2066,7 +2066,7 @@ void update_wall_time(void) | |||
2066 | goto out; | 2066 | goto out; |
2067 | 2067 | ||
2068 | /* Do some additional sanity checking */ | 2068 | /* Do some additional sanity checking */ |
2069 | timekeeping_check_update(real_tk, offset); | 2069 | timekeeping_check_update(tk, offset); |
2070 | 2070 | ||
2071 | /* | 2071 | /* |
2072 | * With NO_HZ we may have to accumulate many cycle_intervals | 2072 | * With NO_HZ we may have to accumulate many cycle_intervals |
diff --git a/tools/testing/selftests/timers/freq-step.c b/tools/testing/selftests/timers/freq-step.c index e8c61830825a..926828ea84d1 100644 --- a/tools/testing/selftests/timers/freq-step.c +++ b/tools/testing/selftests/timers/freq-step.c | |||
@@ -33,6 +33,10 @@ | |||
33 | #define MAX_FREQ_ERROR 10e-6 | 33 | #define MAX_FREQ_ERROR 10e-6 |
34 | #define MAX_STDDEV 1000e-9 | 34 | #define MAX_STDDEV 1000e-9 |
35 | 35 | ||
36 | #ifndef ADJ_SETOFFSET | ||
37 | #define ADJ_SETOFFSET 0x0100 | ||
38 | #endif | ||
39 | |||
36 | struct sample { | 40 | struct sample { |
37 | double offset; | 41 | double offset; |
38 | double time; | 42 | double time; |
@@ -262,7 +266,7 @@ int main(int argc, char **argv) | |||
262 | set_frequency(0.0); | 266 | set_frequency(0.0); |
263 | 267 | ||
264 | if (fails) | 268 | if (fails) |
265 | ksft_exit_fail(); | 269 | return ksft_exit_fail(); |
266 | 270 | ||
267 | ksft_exit_pass(); | 271 | return ksft_exit_pass(); |
268 | } | 272 | } |
diff --git a/tools/testing/selftests/timers/set-timer-lat.c b/tools/testing/selftests/timers/set-timer-lat.c index 4fc98c5b0899..15434da23b04 100644 --- a/tools/testing/selftests/timers/set-timer-lat.c +++ b/tools/testing/selftests/timers/set-timer-lat.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | 22 | ||
23 | #include <errno.h> | ||
23 | #include <stdio.h> | 24 | #include <stdio.h> |
24 | #include <unistd.h> | 25 | #include <unistd.h> |
25 | #include <time.h> | 26 | #include <time.h> |
@@ -63,6 +64,7 @@ int alarmcount; | |||
63 | int clock_id; | 64 | int clock_id; |
64 | struct timespec start_time; | 65 | struct timespec start_time; |
65 | long long max_latency_ns; | 66 | long long max_latency_ns; |
67 | int timer_fired_early; | ||
66 | 68 | ||
67 | char *clockstring(int clockid) | 69 | char *clockstring(int clockid) |
68 | { | 70 | { |
@@ -115,16 +117,23 @@ void sigalarm(int signo) | |||
115 | delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount; | 117 | delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount; |
116 | 118 | ||
117 | if (delta_ns < 0) | 119 | if (delta_ns < 0) |
118 | printf("%s timer fired early: FAIL\n", clockstring(clock_id)); | 120 | timer_fired_early = 1; |
119 | 121 | ||
120 | if (delta_ns > max_latency_ns) | 122 | if (delta_ns > max_latency_ns) |
121 | max_latency_ns = delta_ns; | 123 | max_latency_ns = delta_ns; |
122 | } | 124 | } |
123 | 125 | ||
124 | int do_timer(int clock_id, int flags) | 126 | void describe_timer(int flags, int interval) |
127 | { | ||
128 | printf("%-22s %s %s ", | ||
129 | clockstring(clock_id), | ||
130 | flags ? "ABSTIME":"RELTIME", | ||
131 | interval ? "PERIODIC":"ONE-SHOT"); | ||
132 | } | ||
133 | |||
134 | int setup_timer(int clock_id, int flags, int interval, timer_t *tm1) | ||
125 | { | 135 | { |
126 | struct sigevent se; | 136 | struct sigevent se; |
127 | timer_t tm1; | ||
128 | struct itimerspec its1, its2; | 137 | struct itimerspec its1, its2; |
129 | int err; | 138 | int err; |
130 | 139 | ||
@@ -136,8 +145,9 @@ int do_timer(int clock_id, int flags) | |||
136 | 145 | ||
137 | max_latency_ns = 0; | 146 | max_latency_ns = 0; |
138 | alarmcount = 0; | 147 | alarmcount = 0; |
148 | timer_fired_early = 0; | ||
139 | 149 | ||
140 | err = timer_create(clock_id, &se, &tm1); | 150 | err = timer_create(clock_id, &se, tm1); |
141 | if (err) { | 151 | if (err) { |
142 | if ((clock_id == CLOCK_REALTIME_ALARM) || | 152 | if ((clock_id == CLOCK_REALTIME_ALARM) || |
143 | (clock_id == CLOCK_BOOTTIME_ALARM)) { | 153 | (clock_id == CLOCK_BOOTTIME_ALARM)) { |
@@ -158,32 +168,97 @@ int do_timer(int clock_id, int flags) | |||
158 | its1.it_value.tv_sec = TIMER_SECS; | 168 | its1.it_value.tv_sec = TIMER_SECS; |
159 | its1.it_value.tv_nsec = 0; | 169 | its1.it_value.tv_nsec = 0; |
160 | } | 170 | } |
161 | its1.it_interval.tv_sec = TIMER_SECS; | 171 | its1.it_interval.tv_sec = interval; |
162 | its1.it_interval.tv_nsec = 0; | 172 | its1.it_interval.tv_nsec = 0; |
163 | 173 | ||
164 | err = timer_settime(tm1, flags, &its1, &its2); | 174 | err = timer_settime(*tm1, flags, &its1, &its2); |
165 | if (err) { | 175 | if (err) { |
166 | printf("%s - timer_settime() failed\n", clockstring(clock_id)); | 176 | printf("%s - timer_settime() failed\n", clockstring(clock_id)); |
167 | return -1; | 177 | return -1; |
168 | } | 178 | } |
169 | 179 | ||
170 | while (alarmcount < 5) | 180 | return 0; |
171 | sleep(1); | 181 | } |
172 | 182 | ||
173 | printf("%-22s %s max latency: %10lld ns : ", | 183 | int check_timer_latency(int flags, int interval) |
174 | clockstring(clock_id), | 184 | { |
175 | flags ? "ABSTIME":"RELTIME", | 185 | int err = 0; |
176 | max_latency_ns); | 186 | |
187 | describe_timer(flags, interval); | ||
188 | printf("timer fired early: %7d : ", timer_fired_early); | ||
189 | if (!timer_fired_early) { | ||
190 | printf("[OK]\n"); | ||
191 | } else { | ||
192 | printf("[FAILED]\n"); | ||
193 | err = -1; | ||
194 | } | ||
195 | |||
196 | describe_timer(flags, interval); | ||
197 | printf("max latency: %10lld ns : ", max_latency_ns); | ||
177 | 198 | ||
178 | timer_delete(tm1); | ||
179 | if (max_latency_ns < UNRESONABLE_LATENCY) { | 199 | if (max_latency_ns < UNRESONABLE_LATENCY) { |
180 | printf("[OK]\n"); | 200 | printf("[OK]\n"); |
201 | } else { | ||
202 | printf("[FAILED]\n"); | ||
203 | err = -1; | ||
204 | } | ||
205 | return err; | ||
206 | } | ||
207 | |||
208 | int check_alarmcount(int flags, int interval) | ||
209 | { | ||
210 | describe_timer(flags, interval); | ||
211 | printf("count: %19d : ", alarmcount); | ||
212 | if (alarmcount == 1) { | ||
213 | printf("[OK]\n"); | ||
181 | return 0; | 214 | return 0; |
182 | } | 215 | } |
183 | printf("[FAILED]\n"); | 216 | printf("[FAILED]\n"); |
184 | return -1; | 217 | return -1; |
185 | } | 218 | } |
186 | 219 | ||
220 | int do_timer(int clock_id, int flags) | ||
221 | { | ||
222 | timer_t tm1; | ||
223 | const int interval = TIMER_SECS; | ||
224 | int err; | ||
225 | |||
226 | err = setup_timer(clock_id, flags, interval, &tm1); | ||
227 | if (err) | ||
228 | return err; | ||
229 | |||
230 | while (alarmcount < 5) | ||
231 | sleep(1); | ||
232 | |||
233 | timer_delete(tm1); | ||
234 | return check_timer_latency(flags, interval); | ||
235 | } | ||
236 | |||
237 | int do_timer_oneshot(int clock_id, int flags) | ||
238 | { | ||
239 | timer_t tm1; | ||
240 | const int interval = 0; | ||
241 | struct timeval timeout; | ||
242 | fd_set fds; | ||
243 | int err; | ||
244 | |||
245 | err = setup_timer(clock_id, flags, interval, &tm1); | ||
246 | if (err) | ||
247 | return err; | ||
248 | |||
249 | memset(&timeout, 0, sizeof(timeout)); | ||
250 | timeout.tv_sec = 5; | ||
251 | FD_ZERO(&fds); | ||
252 | do { | ||
253 | err = select(FD_SETSIZE, &fds, NULL, NULL, &timeout); | ||
254 | } while (err == -1 && errno == EINTR); | ||
255 | |||
256 | timer_delete(tm1); | ||
257 | err = check_timer_latency(flags, interval); | ||
258 | err |= check_alarmcount(flags, interval); | ||
259 | return err; | ||
260 | } | ||
261 | |||
187 | int main(void) | 262 | int main(void) |
188 | { | 263 | { |
189 | struct sigaction act; | 264 | struct sigaction act; |
@@ -209,6 +284,8 @@ int main(void) | |||
209 | 284 | ||
210 | ret |= do_timer(clock_id, TIMER_ABSTIME); | 285 | ret |= do_timer(clock_id, TIMER_ABSTIME); |
211 | ret |= do_timer(clock_id, 0); | 286 | ret |= do_timer(clock_id, 0); |
287 | ret |= do_timer_oneshot(clock_id, TIMER_ABSTIME); | ||
288 | ret |= do_timer_oneshot(clock_id, 0); | ||
212 | } | 289 | } |
213 | if (ret) | 290 | if (ret) |
214 | return ksft_exit_fail(); | 291 | return ksft_exit_fail(); |