aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/clockchips.h5
-rw-r--r--kernel/time/clockevents.c13
-rw-r--r--kernel/time/timer_list.c6
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);