aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2015-02-12 19:54:56 -0500
committerIngo Molnar <mingo@kernel.org>2015-02-18 09:16:23 -0500
commitbd624d75db21ea5402f9ecf4450b311794d80352 (patch)
treeff4343a02e3b46d633b923d68e35766c716c4793 /include
parentf40d149b58f5dea148ceaee5f9249da133e5004c (diff)
clockevents: Introduce mode specific callbacks
It is not possible for the clockevents core to know which modes (other than those with a corresponding feature flag) are supported by a particular implementation. And drivers are expected to handle transition to all modes elegantly, as ->set_mode() would be issued for them unconditionally. Now, adding support for a new mode complicates things a bit if we want to use the legacy ->set_mode() callback. We need to closely review all clockevents drivers to see if they would break on addition of a new mode. And after such reviews, it is found that we have to do non-trivial changes to most of the drivers [1]. Introduce mode-specific set_mode_*() callbacks, some of which the drivers may or may not implement. A missing callback would clearly convey the message that the corresponding mode isn't supported. A driver may still choose to keep supporting the legacy ->set_mode() callback, but ->set_mode() wouldn't be supporting any new modes beyond RESUME. If a driver wants to benefit from using a new mode, it would be required to migrate to the mode specific callbacks. The legacy ->set_mode() callback and the newly introduced mode-specific callbacks are mutually exclusive. Only one of them should be supported by the driver. Sanity check is done at the time of registration to distinguish between optional and required callbacks and to make error recovery and handling simpler. If the legacy ->set_mode() callback is provided, all mode specific ones would be ignored by the core but a warning is thrown if they are present. Call sites calling ->set_mode() directly are also updated to use __clockevents_set_mode() instead, as ->set_mode() may not be available anymore for few drivers. [1] https://lkml.org/lkml/2014/12/9/605 [2] https://lkml.org/lkml/2015/1/23/255 Suggested-by: Thomas Gleixner <tglx@linutronix.de> [2] Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: John Stultz <john.stultz@linaro.org> Cc: Kevin Hilman <khilman@linaro.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Preeti U Murthy <preeti@linux.vnet.ibm.com> Cc: linaro-kernel@lists.linaro.org Cc: linaro-networking@linaro.org Link: http://lkml.kernel.org/r/792d59a40423f0acffc9bb0bec9de1341a06fa02.1423788565.git.viresh.kumar@linaro.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/clockchips.h21
1 files changed, 19 insertions, 2 deletions
diff --git a/include/linux/clockchips.h b/include/linux/clockchips.h
index 2e4cb67f6e56..59af26b54d15 100644
--- a/include/linux/clockchips.h
+++ b/include/linux/clockchips.h
@@ -39,6 +39,8 @@ enum clock_event_mode {
39 CLOCK_EVT_MODE_PERIODIC, 39 CLOCK_EVT_MODE_PERIODIC,
40 CLOCK_EVT_MODE_ONESHOT, 40 CLOCK_EVT_MODE_ONESHOT,
41 CLOCK_EVT_MODE_RESUME, 41 CLOCK_EVT_MODE_RESUME,
42
43 /* Legacy ->set_mode() callback doesn't support below modes */
42}; 44};
43 45
44/* 46/*
@@ -81,7 +83,11 @@ enum clock_event_mode {
81 * @mode: operating mode assigned by the management code 83 * @mode: operating mode assigned by the management code
82 * @features: features 84 * @features: features
83 * @retries: number of forced programming retries 85 * @retries: number of forced programming retries
84 * @set_mode: set mode function 86 * @set_mode: legacy set mode function, only for modes <= CLOCK_EVT_MODE_RESUME.
87 * @set_mode_periodic: switch mode to periodic, if !set_mode
88 * @set_mode_oneshot: switch mode to oneshot, if !set_mode
89 * @set_mode_shutdown: switch mode to shutdown, if !set_mode
90 * @set_mode_resume: resume clkevt device, if !set_mode
85 * @broadcast: function to broadcast events 91 * @broadcast: function to broadcast events
86 * @min_delta_ticks: minimum delta value in ticks stored for reconfiguration 92 * @min_delta_ticks: minimum delta value in ticks stored for reconfiguration
87 * @max_delta_ticks: maximum delta value in ticks stored for reconfiguration 93 * @max_delta_ticks: maximum delta value in ticks stored for reconfiguration
@@ -108,9 +114,20 @@ struct clock_event_device {
108 unsigned int features; 114 unsigned int features;
109 unsigned long retries; 115 unsigned long retries;
110 116
111 void (*broadcast)(const struct cpumask *mask); 117 /*
118 * Mode transition callback(s): Only one of the two groups should be
119 * defined:
120 * - set_mode(), only for modes <= CLOCK_EVT_MODE_RESUME.
121 * - set_mode_{shutdown|periodic|oneshot|resume}().
122 */
112 void (*set_mode)(enum clock_event_mode mode, 123 void (*set_mode)(enum clock_event_mode mode,
113 struct clock_event_device *); 124 struct clock_event_device *);
125 int (*set_mode_periodic)(struct clock_event_device *);
126 int (*set_mode_oneshot)(struct clock_event_device *);
127 int (*set_mode_shutdown)(struct clock_event_device *);
128 int (*set_mode_resume)(struct clock_event_device *);
129
130 void (*broadcast)(const struct cpumask *mask);
114 void (*suspend)(struct clock_event_device *); 131 void (*suspend)(struct clock_event_device *);
115 void (*resume)(struct clock_event_device *); 132 void (*resume)(struct clock_event_device *);
116 unsigned long min_delta_ticks; 133 unsigned long min_delta_ticks;