History

Merge branch 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull timer fixes from Thomas Gleixner: "The timer departement delivers: - a regression fix for the NTP code along with a proper selftest - prevent a spurious timer interrupt in the NOHZ lowres code - a fix for user space interfaces returning the remaining time on architectures with CONFIG_TIME_LOW_RES=y - a few patches to fix COMPILE_TEST fallout" * 'timers-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: tick/nohz: Set the correct expiry when switching to nohz/lowres mode clocksource: Fix dependencies for archs w/o HAS_IOMEM clocksource: Select CLKSRC_MMIO where needed tick/sched: Hide unused oneshot timer code kselftests: timers: Add adjtimex SETOFFSET validity tests ntp: Fix ADJ_SETOFFSET being used w/ ADJ_NANO itimers: Handle relative timers with CONFIG_TIME_LOW_RES proper posix-timers: Handle relative timers with CONFIG_TIME_LOW_RES proper timerfd: Handle relative timers with CONFIG_TIME_LOW_RES proper hrtimer: Handle remaining time proper for TIME_LOW_RES clockevents/tcb_clksrc: Prevent disabling an already disabled clock

Linus Torvalds committed 10 years ago

Commit dc799d02 parents 7ab85d4 1ca8ec511 files · +245 −36Browse files

Unified · Split

11 files
  1. drivers/clocksource/Kconfig +12 −0
  2. drivers/clocksource/tcb_clksrc.c +2 −1
  3. fs/timerfd.c +1 −1
  4. include/linux/hrtimer.h +31 −3
  5. kernel/time/hrtimer.c +37 −18
  6. kernel/time/itimer.c +1 −1
  7. kernel/time/ntp.c +12 −2
  8. kernel/time/posix-timers.c +1 −1
  9. kernel/time/tick-sched.c +9 −7
  10. kernel/time/timer_list.c +1 −1
  11. tools/testing/selftests/timers/valid-adjtimex.c +138 −1
drivers/clocksource/Kconfig+12−0
@@ -30,6 +30,8 @@ config CLKSRC_MMIO · 29 unmodified lines
3030 config DIGICOLOR_TIMER
3131 bool "Digicolor timer driver" if COMPILE_TEST
3232 depends on GENERIC_CLOCKEVENTS
33+ select CLKSRC_MMIO
34+ depends on HAS_IOMEM
3335 help
3436 Enables the support for the digicolor timer driver.
3537
@@ -55,6 +57,7 @@ config ARMADA_370_XP_TIMER · 19 unmodified lines
5557 bool "Armada 370 and XP timer driver" if COMPILE_TEST
5658 depends on ARM
5759 select CLKSRC_OF
60+ select CLKSRC_MMIO
5861 help
5962 Enables the support for the Armada 370 and XP timer driver.
6063
@@ -76,6 +79,7 @@ config ORION_TIMER · 15 unmodified lines
7679 config SUN4I_TIMER
7780 bool "Sun4i timer driver" if COMPILE_TEST
7881 depends on GENERIC_CLOCKEVENTS
82+ depends on HAS_IOMEM
7983 select CLKSRC_MMIO
8084 help
8185 Enables support for the Sun4i timer.
@@ -89,6 +93,7 @@ config SUN5I_HSTIMER · 7 unmodified lines
8993
9094 config TEGRA_TIMER
9195 bool "Tegra timer driver" if COMPILE_TEST
96+ select CLKSRC_MMIO
9297 depends on ARM
9398 help
9499 Enables support for the Tegra driver.
@@ -96,6 +101,7 @@ config TEGRA_TIMER · 1 unmodified line
96101 config VT8500_TIMER
97102 bool "VT8500 timer driver" if COMPILE_TEST
98103 depends on GENERIC_CLOCKEVENTS
104+ depends on HAS_IOMEM
99105 help
100106 Enables support for the VT8500 driver.
101107
@@ -131,6 +137,7 @@ config CLKSRC_NOMADIK_MTU_SCHED_CLOCK · 29 unmodified lines
131137 config CLKSRC_DBX500_PRCMU
132138 bool "Clocksource PRCMU Timer" if COMPILE_TEST
133139 depends on GENERIC_CLOCKEVENTS
140+ depends on HAS_IOMEM
134141 help
135142 Use the always on PRCMU Timer as clocksource
136143
@@ -248,6 +255,7 @@ config CLKSRC_EXYNOS_MCT · 111 unmodified lines
248255 config CLKSRC_SAMSUNG_PWM
249256 bool "PWM timer drvier for Samsung S3C, S5P" if COMPILE_TEST
250257 depends on GENERIC_CLOCKEVENTS
258+ depends on HAS_IOMEM
251259 help
252260 This is a new clocksource driver for the PWM timer found in
253261 Samsung S3C, S5P and Exynos SoCs, replacing an earlier driver
@@ -257,12 +265,14 @@ config CLKSRC_SAMSUNG_PWM · 3 unmodified lines
257265 config FSL_FTM_TIMER
258266 bool "Freescale FlexTimer Module driver" if COMPILE_TEST
259267 depends on GENERIC_CLOCKEVENTS
268+ depends on HAS_IOMEM
260269 select CLKSRC_MMIO
261270 help
262271 Support for Freescale FlexTimer Module (FTM) timer.
263272
264273 config VF_PIT_TIMER
265274 bool
275+ select CLKSRC_MMIO
266276 help
267277 Support for Period Interrupt Timer on Freescale Vybrid Family SoCs.
268278
@@ -360,6 +370,7 @@ config CLKSRC_TANGO_XTAL · 91 unmodified lines
360370 config CLKSRC_PXA
361371 bool "Clocksource for PXA or SA-11x0 platform" if COMPILE_TEST
362372 depends on GENERIC_CLOCKEVENTS
373+ depends on HAS_IOMEM
363374 select CLKSRC_MMIO
364375 help
365376 This enables OST0 support available on PXA and SA-11x0
@@ -394,6 +405,7 @@ config CLKSRC_ST_LPC · 28 unmodified lines
394405 bool "Low power clocksource found in the LPC" if COMPILE_TEST
395406 select CLKSRC_OF if OF
396407 depends on HAS_IOMEM
408+ select CLKSRC_MMIO
397409 help
398410 Enable this option to use the Low Power controller timer
399411 as clocksource.
drivers/clocksource/tcb_clksrc.c+2−1
@@ -98,7 +98,8 @@ static int tc_shutdown(struct clock_event_device *d) · 97 unmodified lines
9898
9999 __raw_writel(0xff, regs + ATMEL_TC_REG(2, IDR));
100100 __raw_writel(ATMEL_TC_CLKDIS, regs + ATMEL_TC_REG(2, CCR));
101− clk_disable(tcd->clk);
101+ if (!clockevent_state_detached(d))
102+ clk_disable(tcd->clk);
102103
103104 return 0;
104105 }
fs/timerfd.c+1−1
@@ -153,7 +153,7 @@ static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx) · 152 unmodified lines
153153 if (isalarm(ctx))
154154 remaining = alarm_expires_remaining(&ctx->t.alarm);
155155 else
156− remaining = hrtimer_expires_remaining(&ctx->t.tmr);
156+ remaining = hrtimer_expires_remaining_adjusted(&ctx->t.tmr);
157157
158158 return remaining.tv64 < 0 ? ktime_set(0, 0): remaining;
159159 }
include/linux/hrtimer.h+31−3
@@ -87,7 +87,8 @@ enum hrtimer_restart { · 86 unmodified lines
8787 * @function: timer expiry callback function
8888 * @base: pointer to the timer base (per cpu and per clock)
8989 * @state: state information (See bit values above)
90− * @start_pid: timer statistics field to store the pid of the task which
90+ * @is_rel: Set if the timer was armed relative
91+ * @start_pid: timer statistics field to store the pid of the task which
9192 * started the timer
9293 * @start_site: timer statistics field to store the site where the timer
9394 * was started
@@ -101,7 +102,8 @@ struct hrtimer { · 7 unmodified lines
101102 ktime_t _softexpires;
102103 enum hrtimer_restart (*function)(struct hrtimer *);
103104 struct hrtimer_clock_base *base;
104− unsigned long state;
105+ u8 state;
106+ u8 is_rel;
105107 #ifdef CONFIG_TIMER_STATS
106108 int start_pid;
107109 void *start_site;
@@ -321,6 +323,27 @@ static inline void clock_was_set_delayed(void) { } · 213 unmodified lines
321323
322324 #endif
323325
326+static inline ktime_t
327+__hrtimer_expires_remaining_adjusted(const struct hrtimer *timer, ktime_t now)
328+{
329+ ktime_t rem = ktime_sub(timer->node.expires, now);
330+
331+ /*
332+ * Adjust relative timers for the extra we added in
333+ * hrtimer_start_range_ns() to prevent short timeouts.
334+ */
335+ if (IS_ENABLED(CONFIG_TIME_LOW_RES) && timer->is_rel)
336+ rem.tv64 -= hrtimer_resolution;
337+ return rem;
338+}
339+
340+static inline ktime_t
341+hrtimer_expires_remaining_adjusted(const struct hrtimer *timer)
342+{
343+ return __hrtimer_expires_remaining_adjusted(timer,
344+ timer->base->get_time());
345+}
346+
324347 extern void clock_was_set(void);
325348 #ifdef CONFIG_TIMERFD
326349 extern void timerfd_clock_was_set(void);
@@ -390,7 +413,12 @@ static inline void hrtimer_restart(struct hrtimer *timer) · 63 unmodified lines
390413 }
391414
392415 /* Query timers: */
393−extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
416+extern ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust);
417+
418+static inline ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
419+{
420+ return __hrtimer_get_remaining(timer, false);
421+}
394422
395423 extern u64 hrtimer_get_next_event(void);
396424
kernel/time/hrtimer.c+37−18
@@ -897,10 +897,10 @@ static int enqueue_hrtimer(struct hrtimer *timer, · 896 unmodified lines
897897 */
898898 static void __remove_hrtimer(struct hrtimer *timer,
899899 struct hrtimer_clock_base *base,
900− unsigned long newstate, int reprogram)
900+ u8 newstate, int reprogram)
901901 {
902902 struct hrtimer_cpu_base *cpu_base = base->cpu_base;
903− unsigned int state = timer->state;
903+ u8 state = timer->state;
904904
905905 timer->state = newstate;
906906 if (!(state & HRTIMER_STATE_ENQUEUED))
@@ -930,7 +930,7 @@ static inline int · 23 unmodified lines
930930 remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart)
931931 {
932932 if (hrtimer_is_queued(timer)) {
933− unsigned long state = timer->state;
933+ u8 state = timer->state;
934934 int reprogram;
935935
936936 /*
@@ -954,6 +954,22 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool rest · 17 unmodified lines
954954 return 0;
955955 }
956956
957+static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
958+ const enum hrtimer_mode mode)
959+{
960+#ifdef CONFIG_TIME_LOW_RES
961+ /*
962+ * CONFIG_TIME_LOW_RES indicates that the system has no way to return
963+ * granular time values. For relative timers we add hrtimer_resolution
964+ * (i.e. one jiffie) to prevent short timeouts.
965+ */
966+ timer->is_rel = mode & HRTIMER_MODE_REL;
967+ if (timer->is_rel)
968+ tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution));
969+#endif
970+ return tim;
971+}
972+
957973 /**
958974 * hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
959975 * @timer: the timer to be added
@@ -974,19 +990,10 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim, · 14 unmodified lines
974990 /* Remove an active timer from the queue: */
975991 remove_hrtimer(timer, base, true);
976992
977− if (mode & HRTIMER_MODE_REL) {
993+ if (mode & HRTIMER_MODE_REL)
978994 tim = ktime_add_safe(tim, base->get_time());
979− /*
980− * CONFIG_TIME_LOW_RES is a temporary way for architectures
981− * to signal that they simply return xtime in
982− * do_gettimeoffset(). In this case we want to round up by
983− * resolution when starting a relative timer, to avoid short
984− * timeouts. This will go away with the GTOD framework.
985− */
986−#ifdef CONFIG_TIME_LOW_RES
987− tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution));
988−#endif
989− }
995+
996+ tim = hrtimer_update_lowres(timer, tim, mode);
990997
991998 hrtimer_set_expires_range_ns(timer, tim, delta_ns);
992999
@@ -1074,19 +1081,23 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel); · 81 unmodified lines
10741081 /**
10751082 * hrtimer_get_remaining - get remaining time for the timer
10761083 * @timer: the timer to read
1084+ * @adjust: adjust relative timers when CONFIG_TIME_LOW_RES=y
10771085 */
1078−ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
1086+ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust)
10791087 {
10801088 unsigned long flags;
10811089 ktime_t rem;
10821090
10831091 lock_hrtimer_base(timer, &flags);
1084− rem = hrtimer_expires_remaining(timer);
1092+ if (IS_ENABLED(CONFIG_TIME_LOW_RES) && adjust)
1093+ rem = hrtimer_expires_remaining_adjusted(timer);
1094+ else
1095+ rem = hrtimer_expires_remaining(timer);
10851096 unlock_hrtimer_base(timer, &flags);
10861097
10871098 return rem;
10881099 }
1089−EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
1100+EXPORT_SYMBOL_GPL(__hrtimer_get_remaining);
10901101
10911102 #ifdef CONFIG_NO_HZ_COMMON
10921103 /**
@@ -1219,6 +1230,14 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base, · 126 unmodified lines
12191230 timer_stats_account_hrtimer(timer);
12201231 fn = timer->function;
12211232
1233+ /*
1234+ * Clear the 'is relative' flag for the TIME_LOW_RES case. If the
1235+ * timer is restarted with a period then it becomes an absolute
1236+ * timer. If its not restarted it does not matter.
1237+ */
1238+ if (IS_ENABLED(CONFIG_TIME_LOW_RES))
1239+ timer->is_rel = false;
1240+
12221241 /*
12231242 * Because we run timers from hardirq context, there is no chance
12241243 * they get migrated to another cpu, therefore its safe to unlock
kernel/time/itimer.c+1−1
@@ -26,7 +26,7 @@ · 25 unmodified lines
2626 */
2727 static struct timeval itimer_get_remtime(struct hrtimer *timer)
2828 {
29− ktime_t rem = hrtimer_get_remaining(timer);
29+ ktime_t rem = __hrtimer_get_remaining(timer, true);
3030
3131 /*
3232 * Racy but safe: if the itimer expires after the above
kernel/time/ntp.c+12−2
@@ -685,8 +685,18 @@ int ntp_validate_timex(struct timex *txc) · 684 unmodified lines
685685 if (!capable(CAP_SYS_TIME))
686686 return -EPERM;
687687
688− if (!timeval_inject_offset_valid(&txc->time))
689− return -EINVAL;
688+ if (txc->modes & ADJ_NANO) {
689+ struct timespec ts;
690+
691+ ts.tv_sec = txc->time.tv_sec;
692+ ts.tv_nsec = txc->time.tv_usec;
693+ if (!timespec_inject_offset_valid(&ts))
694+ return -EINVAL;
695+
696+ } else {
697+ if (!timeval_inject_offset_valid(&txc->time))
698+ return -EINVAL;
699+ }
690700 }
691701
692702 /*
kernel/time/posix-timers.c+1−1
@@ -760,7 +760,7 @@ common_timer_get(struct k_itimer *timr, struct itimerspec *cur_setting) · 759 unmodified lines
760760 (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
761761 timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
762762
763− remaining = ktime_sub(hrtimer_get_expires(timer), now);
763+ remaining = __hrtimer_expires_remaining_adjusted(timer, now);
764764 /* Return 0 only, when the timer is expired and not pending */
765765 if (remaining.tv64 <= 0) {
766766 /*
kernel/time/tick-sched.c+9−7
@@ -36,16 +36,17 @@ · 35 unmodified lines
3636 */
3737 static DEFINE_PER_CPU(struct tick_sched, tick_cpu_sched);
3838
39−/*
40− * The time, when the last jiffy update happened. Protected by jiffies_lock.
41− */
42−static ktime_t last_jiffies_update;
43−
4439 struct tick_sched *tick_get_tick_sched(int cpu)
4540 {
4641 return &per_cpu(tick_cpu_sched, cpu);
4742 }
4843
44+#if defined(CONFIG_NO_HZ_COMMON) || defined(CONFIG_HIGH_RES_TIMERS)
45+/*
46+ * The time, when the last jiffy update happened. Protected by jiffies_lock.
47+ */
48+static ktime_t last_jiffies_update;
49+
4950 /*
5051 * Must be called with interrupts disabled !
5152 */
@@ -151,6 +152,7 @@ static void tick_sched_handle(struct tick_sched *ts, struct pt_regs *regs) · 99 unmodified lines
151152 update_process_times(user_mode(regs));
152153 profile_tick(CPU_PROFILING);
153154 }
155+#endif
154156
155157 #ifdef CONFIG_NO_HZ_FULL
156158 cpumask_var_t tick_nohz_full_mask;
@@ -993,9 +995,9 @@ static void tick_nohz_switch_to_nohz(void) · 836 unmodified lines
993995 /* Get the next period */
994996 next = tick_init_jiffy_update();
995997
996− hrtimer_forward_now(&ts->sched_timer, tick_period);
997998 hrtimer_set_expires(&ts->sched_timer, next);
998− tick_program_event(next, 1);
999+ hrtimer_forward_now(&ts->sched_timer, tick_period);
1000+ tick_program_event(hrtimer_get_expires(&ts->sched_timer), 1);
9991001 tick_nohz_activate(ts, NOHZ_MODE_LOWRES);
10001002 }
10011003
kernel/time/timer_list.c+1−1
@@ -69,7 +69,7 @@ print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer, · 68 unmodified lines
6969 print_name_offset(m, taddr);
7070 SEQ_printf(m, ", ");
7171 print_name_offset(m, timer->function);
72− SEQ_printf(m, ", S:%02lx", timer->state);
72+ SEQ_printf(m, ", S:%02x", timer->state);
7373 #ifdef CONFIG_TIMER_STATS
7474 SEQ_printf(m, ", ");
7575 print_name_offset(m, timer->start_site);
tools/testing/selftests/timers/valid-adjtimex.c+138−1
@@ -45,7 +45,17 @@ static inline int ksft_exit_fail(void) · 44 unmodified lines
4545 }
4646 #endif
4747
48−#define NSEC_PER_SEC 1000000000L
48+#define NSEC_PER_SEC 1000000000LL
49+#define USEC_PER_SEC 1000000LL
50+
51+#define ADJ_SETOFFSET 0x0100
52+
53+#include <sys/syscall.h>
54+static int clock_adjtime(clockid_t id, struct timex *tx)
55+{
56+ return syscall(__NR_clock_adjtime, id, tx);
57+}
58+
4959
5060 /* clear NTP time_status & time_state */
5161 int clear_time_state(void)
@@ -193,10 +203,137 @@ out: · 141 unmodified lines
193203 }
194204
195205
206+int set_offset(long long offset, int use_nano)
207+{
208+ struct timex tmx = {};
209+ int ret;
210+
211+ tmx.modes = ADJ_SETOFFSET;
212+ if (use_nano) {
213+ tmx.modes |= ADJ_NANO;
214+
215+ tmx.time.tv_sec = offset / NSEC_PER_SEC;
216+ tmx.time.tv_usec = offset % NSEC_PER_SEC;
217+
218+ if (offset < 0 && tmx.time.tv_usec) {
219+ tmx.time.tv_sec -= 1;
220+ tmx.time.tv_usec += NSEC_PER_SEC;
221+ }
222+ } else {
223+ tmx.time.tv_sec = offset / USEC_PER_SEC;
224+ tmx.time.tv_usec = offset % USEC_PER_SEC;
225+
226+ if (offset < 0 && tmx.time.tv_usec) {
227+ tmx.time.tv_sec -= 1;
228+ tmx.time.tv_usec += USEC_PER_SEC;
229+ }
230+ }
231+
232+ ret = clock_adjtime(CLOCK_REALTIME, &tmx);
233+ if (ret < 0) {
234+ printf("(sec: %ld usec: %ld) ", tmx.time.tv_sec, tmx.time.tv_usec);
235+ printf("[FAIL]\n");
236+ return -1;
237+ }
238+ return 0;
239+}
240+
241+int set_bad_offset(long sec, long usec, int use_nano)
242+{
243+ struct timex tmx = {};
244+ int ret;
245+
246+ tmx.modes = ADJ_SETOFFSET;
247+ if (use_nano)
248+ tmx.modes |= ADJ_NANO;
249+
250+ tmx.time.tv_sec = sec;
251+ tmx.time.tv_usec = usec;
252+ ret = clock_adjtime(CLOCK_REALTIME, &tmx);
253+ if (ret >= 0) {
254+ printf("Invalid (sec: %ld usec: %ld) did not fail! ", tmx.time.tv_sec, tmx.time.tv_usec);
255+ printf("[FAIL]\n");
256+ return -1;
257+ }
258+ return 0;
259+}
260+
261+int validate_set_offset(void)
262+{
263+ printf("Testing ADJ_SETOFFSET... ");
264+
265+ /* Test valid values */
266+ if (set_offset(NSEC_PER_SEC - 1, 1))
267+ return -1;
268+
269+ if (set_offset(-NSEC_PER_SEC + 1, 1))
270+ return -1;
271+
272+ if (set_offset(-NSEC_PER_SEC - 1, 1))
273+ return -1;
274+
275+ if (set_offset(5 * NSEC_PER_SEC, 1))
276+ return -1;
277+
278+ if (set_offset(-5 * NSEC_PER_SEC, 1))
279+ return -1;
280+
281+ if (set_offset(5 * NSEC_PER_SEC + NSEC_PER_SEC / 2, 1))
282+ return -1;
283+
284+ if (set_offset(-5 * NSEC_PER_SEC - NSEC_PER_SEC / 2, 1))
285+ return -1;
286+
287+ if (set_offset(USEC_PER_SEC - 1, 0))
288+ return -1;
289+
290+ if (set_offset(-USEC_PER_SEC + 1, 0))
291+ return -1;
292+
293+ if (set_offset(-USEC_PER_SEC - 1, 0))
294+ return -1;
295+
296+ if (set_offset(5 * USEC_PER_SEC, 0))
297+ return -1;
298+
299+ if (set_offset(-5 * USEC_PER_SEC, 0))
300+ return -1;
301+
302+ if (set_offset(5 * USEC_PER_SEC + USEC_PER_SEC / 2, 0))
303+ return -1;
304+
305+ if (set_offset(-5 * USEC_PER_SEC - USEC_PER_SEC / 2, 0))
306+ return -1;
307+
308+ /* Test invalid values */
309+ if (set_bad_offset(0, -1, 1))
310+ return -1;
311+ if (set_bad_offset(0, -1, 0))
312+ return -1;
313+ if (set_bad_offset(0, 2 * NSEC_PER_SEC, 1))
314+ return -1;
315+ if (set_bad_offset(0, 2 * USEC_PER_SEC, 0))
316+ return -1;
317+ if (set_bad_offset(0, NSEC_PER_SEC, 1))
318+ return -1;
319+ if (set_bad_offset(0, USEC_PER_SEC, 0))
320+ return -1;
321+ if (set_bad_offset(0, -NSEC_PER_SEC, 1))
322+ return -1;
323+ if (set_bad_offset(0, -USEC_PER_SEC, 0))
324+ return -1;
325+
326+ printf("[OK]\n");
327+ return 0;
328+}
329+
196330 int main(int argc, char **argv)
197331 {
198332 if (validate_freq())
199333 return ksft_exit_fail();
200334
335+ if (validate_set_offset())
336+ return ksft_exit_fail();
337+
201338 return ksft_exit_pass();
202339 }

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t