aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/time/clockevents.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/time/clockevents.c')
-rw-r--r--kernel/time/clockevents.c70
1 files changed, 68 insertions, 2 deletions
diff --git a/kernel/time/clockevents.c b/kernel/time/clockevents.c
index d7395fdfb9f3..e4c699dfa4e8 100644
--- a/kernel/time/clockevents.c
+++ b/kernel/time/clockevents.c
@@ -18,7 +18,6 @@
18#include <linux/notifier.h> 18#include <linux/notifier.h>
19#include <linux/smp.h> 19#include <linux/smp.h>
20#include <linux/sysdev.h> 20#include <linux/sysdev.h>
21#include <linux/tick.h>
22 21
23#include "tick-internal.h" 22#include "tick-internal.h"
24 23
@@ -183,7 +182,10 @@ void clockevents_register_device(struct clock_event_device *dev)
183 unsigned long flags; 182 unsigned long flags;
184 183
185 BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED); 184 BUG_ON(dev->mode != CLOCK_EVT_MODE_UNUSED);
186 BUG_ON(!dev->cpumask); 185 if (!dev->cpumask) {
186 WARN_ON(num_possible_cpus() > 1);
187 dev->cpumask = cpumask_of(smp_processor_id());
188 }
187 189
188 raw_spin_lock_irqsave(&clockevents_lock, flags); 190 raw_spin_lock_irqsave(&clockevents_lock, flags);
189 191
@@ -195,6 +197,70 @@ void clockevents_register_device(struct clock_event_device *dev)
195} 197}
196EXPORT_SYMBOL_GPL(clockevents_register_device); 198EXPORT_SYMBOL_GPL(clockevents_register_device);
197 199
200static void clockevents_config(struct clock_event_device *dev,
201 u32 freq)
202{
203 u64 sec;
204
205 if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT))
206 return;
207
208 /*
209 * Calculate the maximum number of seconds we can sleep. Limit
210 * to 10 minutes for hardware which can program more than
211 * 32bit ticks so we still get reasonable conversion values.
212 */
213 sec = dev->max_delta_ticks;
214 do_div(sec, freq);
215 if (!sec)
216 sec = 1;
217 else if (sec > 600 && dev->max_delta_ticks > UINT_MAX)
218 sec = 600;
219
220 clockevents_calc_mult_shift(dev, freq, sec);
221 dev->min_delta_ns = clockevent_delta2ns(dev->min_delta_ticks, dev);
222 dev->max_delta_ns = clockevent_delta2ns(dev->max_delta_ticks, dev);
223}
224
225/**
226 * clockevents_config_and_register - Configure and register a clock event device
227 * @dev: device to register
228 * @freq: The clock frequency
229 * @min_delta: The minimum clock ticks to program in oneshot mode
230 * @max_delta: The maximum clock ticks to program in oneshot mode
231 *
232 * min/max_delta can be 0 for devices which do not support oneshot mode.
233 */
234void clockevents_config_and_register(struct clock_event_device *dev,
235 u32 freq, unsigned long min_delta,
236 unsigned long max_delta)
237{
238 dev->min_delta_ticks = min_delta;
239 dev->max_delta_ticks = max_delta;
240 clockevents_config(dev, freq);
241 clockevents_register_device(dev);
242}
243
244/**
245 * clockevents_update_freq - Update frequency and reprogram a clock event device.
246 * @dev: device to modify
247 * @freq: new device frequency
248 *
249 * Reconfigure and reprogram a clock event device in oneshot
250 * mode. Must be called on the cpu for which the device delivers per
251 * cpu timer events with interrupts disabled! Returns 0 on success,
252 * -ETIME when the event is in the past.
253 */
254int clockevents_update_freq(struct clock_event_device *dev, u32 freq)
255{
256 clockevents_config(dev, freq);
257
258 if (dev->mode != CLOCK_EVT_MODE_ONESHOT)
259 return 0;
260
261 return clockevents_program_event(dev, dev->next_event, ktime_get());
262}
263
198/* 264/*
199 * Noop handler when we shut down an event device 265 * Noop handler when we shut down an event device
200 */ 266 */