diff options
-rw-r--r-- | include/linux/clockchips.h | 5 | ||||
-rw-r--r-- | kernel/time/clockevents.c | 13 | ||||
-rw-r--r-- | kernel/time/timer_list.c | 6 |
3 files changed, 22 insertions, 2 deletions
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h index 59af26b54d15..fcc570d5fe07 100644 --- a/include/linux/clockchips.h +++ b/include/linux/clockchips.h @@ -41,6 +41,7 @@ enum clock_event_mode { CLOCK_EVT_MODE_RESUME, /* Legacy ->set_mode() callback doesn't support below modes */ + CLOCK_EVT_MODE_ONESHOT_STOPPED, }; /* @@ -86,6 +87,7 @@ enum clock_event_mode { * @set_mode: legacy set mode function, only for modes <= CLOCK_EVT_MODE_RESUME. * @set_mode_periodic: switch mode to periodic, if !set_mode * @set_mode_oneshot: switch mode to oneshot, if !set_mode + * @set_mode_stop_oneshot: stop oneshot mode, if !set_mode * @set_mode_shutdown: switch mode to shutdown, if !set_mode * @set_mode_resume: resume clkevt device, if !set_mode * @broadcast: function to broadcast events @@ -118,12 +120,13 @@ struct clock_event_device { * Mode transition callback(s): Only one of the two groups should be * defined: * - set_mode(), only for modes <= CLOCK_EVT_MODE_RESUME. - * - set_mode_{shutdown|periodic|oneshot|resume}(). + * - set_mode_{shutdown|periodic|oneshot|stop_oneshot|resume}(). */ void (*set_mode)(enum clock_event_mode mode, struct clock_event_device *); int (*set_mode_periodic)(struct clock_event_device *); int (*set_mode_oneshot)(struct clock_event_device *); + int (*set_mode_stop_oneshot)(struct clock_event_device *); int (*set_mode_shutdown)(struct clock_event_device *); int (*set_mode_resume)(struct clock_event_device *); diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c index 489642b08d64..808ae0902379 100644 --- a/kernel/time/clockevents.c +++ b/kernel/time/clockevents.c @@ -133,6 +133,16 @@ static int __clockevents_set_mode(struct clock_event_device *dev, return -ENOSYS; return dev->set_mode_oneshot(dev); + case CLOCK_EVT_MODE_ONESHOT_STOPPED: + /* Core internal bug */ + WARN_ONCE(dev->mode != CLOCK_EVT_MODE_ONESHOT, + "Current mode: %d\n", dev->mode); + + if (dev->set_mode_stop_oneshot) + return dev->set_mode_stop_oneshot(dev); + else + return -ENOSYS; + case CLOCK_EVT_MODE_RESUME: /* Optional callback */ if (dev->set_mode_resume) @@ -433,7 +443,8 @@ static int clockevents_sanity_check(struct clock_event_device *dev) if (dev->set_mode) { /* We shouldn't be supporting new modes now */ WARN_ON(dev->set_mode_periodic || dev->set_mode_oneshot || - dev->set_mode_shutdown || dev->set_mode_resume); + dev->set_mode_shutdown || dev->set_mode_resume || + dev->set_mode_stop_oneshot); return 0; } diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c index 2cfd19485824..ee3ff65b679d 100644 --- a/kernel/time/timer_list.c +++ b/kernel/time/timer_list.c @@ -251,6 +251,12 @@ print_tickdevice(struct seq_file *m, struct tick_device *td, int cpu) SEQ_printf(m, "\n"); } + if (dev->set_mode_stop_oneshot) { + SEQ_printf(m, " stop_oneshot: "); + print_name_offset(m, dev->set_mode_stop_oneshot); + SEQ_printf(m, "\n"); + } + if (dev->set_mode_resume) { SEQ_printf(m, " resume: "); print_name_offset(m, dev->set_mode_resume); |