Blame view

kernel/time/clockevents.c 19.3 KB
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  /*
   * linux/kernel/time/clockevents.c
   *
   * This file contains functions which manage clock event devices.
   *
   * Copyright(C) 2005-2006, Thomas Gleixner <tglx@linutronix.de>
   * Copyright(C) 2005-2007, Red Hat, Inc., Ingo Molnar
   * Copyright(C) 2006-2007, Timesys Corp., Thomas Gleixner
   *
   * This code is licenced under the GPL version 2. For details see
   * kernel-base/COPYING.
   */
  
  #include <linux/clockchips.h>
  #include <linux/hrtimer.h>
  #include <linux/init.h>
  #include <linux/module.h>
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
18
  #include <linux/smp.h>
501f86706   Thomas Gleixner   clockevents: Prov...
19
  #include <linux/device.h>
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
20

8e1a928a2   H Hartley Sweeten   clockevents: Add ...
21
  #include "tick-internal.h"
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
22
23
24
  /* The registered clock event devices */
  static LIST_HEAD(clockevent_devices);
  static LIST_HEAD(clockevents_released);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
25
  /* Protection for the above */
b5f91da0a   Thomas Gleixner   clockevents: Conv...
26
  static DEFINE_RAW_SPINLOCK(clockevents_lock);
03e13cf5e   Thomas Gleixner   clockevents: Impl...
27
28
29
30
31
32
33
  /* Protection for unbind operations */
  static DEFINE_MUTEX(clockevents_mutex);
  
  struct ce_unbind {
  	struct clock_event_device *ce;
  	int res;
  };
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
34

97b941064   Thomas Gleixner   clockevents: Sani...
35
36
  static u64 cev_delta2ns(unsigned long latch, struct clock_event_device *evt,
  			bool ismax)
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
37
  {
97813f2fe   Jon Hunter   nohz: Allow 32-bi...
38
  	u64 clc = (u64) latch << evt->shift;
97b941064   Thomas Gleixner   clockevents: Sani...
39
  	u64 rnd;
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
40

45fe4fe19   Ingo Molnar   x86: make clockev...
41
42
43
44
  	if (unlikely(!evt->mult)) {
  		evt->mult = 1;
  		WARN_ON(1);
  	}
97b941064   Thomas Gleixner   clockevents: Sani...
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
  	rnd = (u64) evt->mult - 1;
  
  	/*
  	 * Upper bound sanity check. If the backwards conversion is
  	 * not equal latch, we know that the above shift overflowed.
  	 */
  	if ((clc >> evt->shift) != (u64)latch)
  		clc = ~0ULL;
  
  	/*
  	 * Scaled math oddities:
  	 *
  	 * For mult <= (1 << shift) we can safely add mult - 1 to
  	 * prevent integer rounding loss. So the backwards conversion
  	 * from nsec to device ticks will be correct.
  	 *
  	 * For mult > (1 << shift), i.e. device frequency is > 1GHz we
  	 * need to be careful. Adding mult - 1 will result in a value
  	 * which when converted back to device ticks can be larger
  	 * than latch by up to (mult - 1) >> shift. For the min_delta
  	 * calculation we still want to apply this in order to stay
  	 * above the minimum device ticks limit. For the upper limit
  	 * we would end up with a latch value larger than the upper
  	 * limit of the device, so we omit the add to stay below the
  	 * device upper boundary.
  	 *
  	 * Also omit the add if it would overflow the u64 boundary.
  	 */
  	if ((~0ULL - clc > rnd) &&
10632008b   Thomas Gleixner   clockevents: Prev...
74
  	    (!ismax || evt->mult <= (1ULL << evt->shift)))
97b941064   Thomas Gleixner   clockevents: Sani...
75
  		clc += rnd;
45fe4fe19   Ingo Molnar   x86: make clockev...
76

d316c57ff   Thomas Gleixner   [PATCH] clockeven...
77
  	do_div(clc, evt->mult);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
78

97b941064   Thomas Gleixner   clockevents: Sani...
79
80
81
82
83
84
85
86
87
88
89
90
91
92
  	/* Deltas less than 1usec are pointless noise */
  	return clc > 1000 ? clc : 1000;
  }
  
  /**
   * clockevents_delta2ns - Convert a latch value (device ticks) to nanoseconds
   * @latch:	value to convert
   * @evt:	pointer to clock event device descriptor
   *
   * Math helper, returns latch value converted to nanoseconds (bound checked)
   */
  u64 clockevent_delta2ns(unsigned long latch, struct clock_event_device *evt)
  {
  	return cev_delta2ns(latch, evt, false);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
93
  }
c81fc2c33   Magnus Damm   clockevent: expor...
94
  EXPORT_SYMBOL_GPL(clockevent_delta2ns);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
95

d7eb231c7   Thomas Gleixner   clockevents: Prov...
96
97
  static int __clockevents_switch_state(struct clock_event_device *dev,
  				      enum clock_event_state state)
bd624d75d   Viresh Kumar   clockevents: Intr...
98
  {
bd624d75d   Viresh Kumar   clockevents: Intr...
99
100
  	if (dev->features & CLOCK_EVT_FEAT_DUMMY)
  		return 0;
77e32c89a   Viresh Kumar   clockevents: Mana...
101
102
103
  	/* Transition with new state-specific callbacks */
  	switch (state) {
  	case CLOCK_EVT_STATE_DETACHED:
149aabcc4   Viresh Kumar   clockevents: Shut...
104
  		/* The clockevent device is getting replaced. Shut it down. */
bd624d75d   Viresh Kumar   clockevents: Intr...
105

77e32c89a   Viresh Kumar   clockevents: Mana...
106
  	case CLOCK_EVT_STATE_SHUTDOWN:
7c4a976cd   Viresh Kumar   clockevents: Allo...
107
108
109
  		if (dev->set_state_shutdown)
  			return dev->set_state_shutdown(dev);
  		return 0;
bd624d75d   Viresh Kumar   clockevents: Intr...
110

77e32c89a   Viresh Kumar   clockevents: Mana...
111
  	case CLOCK_EVT_STATE_PERIODIC:
bd624d75d   Viresh Kumar   clockevents: Intr...
112
113
114
  		/* Core internal bug */
  		if (!(dev->features & CLOCK_EVT_FEAT_PERIODIC))
  			return -ENOSYS;
7c4a976cd   Viresh Kumar   clockevents: Allo...
115
116
117
  		if (dev->set_state_periodic)
  			return dev->set_state_periodic(dev);
  		return 0;
bd624d75d   Viresh Kumar   clockevents: Intr...
118

77e32c89a   Viresh Kumar   clockevents: Mana...
119
  	case CLOCK_EVT_STATE_ONESHOT:
bd624d75d   Viresh Kumar   clockevents: Intr...
120
121
122
  		/* Core internal bug */
  		if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT))
  			return -ENOSYS;
7c4a976cd   Viresh Kumar   clockevents: Allo...
123
124
125
  		if (dev->set_state_oneshot)
  			return dev->set_state_oneshot(dev);
  		return 0;
bd624d75d   Viresh Kumar   clockevents: Intr...
126

8fff52fd5   Viresh Kumar   clockevents: Intr...
127
128
  	case CLOCK_EVT_STATE_ONESHOT_STOPPED:
  		/* Core internal bug */
472c4a943   Viresh Kumar   clockevents: Use ...
129
  		if (WARN_ONCE(!clockevent_state_oneshot(dev),
051ebd101   Thomas Gleixner   clockevents: Use ...
130
131
132
  			      "Current state: %d
  ",
  			      clockevent_get_state(dev)))
8fff52fd5   Viresh Kumar   clockevents: Intr...
133
134
135
136
137
138
  			return -EINVAL;
  
  		if (dev->set_state_oneshot_stopped)
  			return dev->set_state_oneshot_stopped(dev);
  		else
  			return -ENOSYS;
bd624d75d   Viresh Kumar   clockevents: Intr...
139
140
141
142
  	default:
  		return -ENOSYS;
  	}
  }
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
143
  /**
d7eb231c7   Thomas Gleixner   clockevents: Prov...
144
   * clockevents_switch_state - set the operating state of a clock event device
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
145
   * @dev:	device to modify
77e32c89a   Viresh Kumar   clockevents: Mana...
146
   * @state:	new state
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
147
148
149
   *
   * Must be called with interrupts disabled !
   */
d7eb231c7   Thomas Gleixner   clockevents: Prov...
150
151
  void clockevents_switch_state(struct clock_event_device *dev,
  			      enum clock_event_state state)
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
152
  {
051ebd101   Thomas Gleixner   clockevents: Use ...
153
  	if (clockevent_get_state(dev) != state) {
d7eb231c7   Thomas Gleixner   clockevents: Prov...
154
  		if (__clockevents_switch_state(dev, state))
bd624d75d   Viresh Kumar   clockevents: Intr...
155
  			return;
051ebd101   Thomas Gleixner   clockevents: Use ...
156
  		clockevent_set_state(dev, state);
2d68259db   Magnus Damm   clockevents: let ...
157
158
159
160
161
  
  		/*
  		 * A nsec2cyc multiplicator of 0 is invalid and we'd crash
  		 * on it, so fix it up and emit a warning:
  		 */
472c4a943   Viresh Kumar   clockevents: Use ...
162
  		if (clockevent_state_oneshot(dev)) {
2d68259db   Magnus Damm   clockevents: let ...
163
164
165
166
167
  			if (unlikely(!dev->mult)) {
  				dev->mult = 1;
  				WARN_ON(1);
  			}
  		}
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
168
169
170
171
  	}
  }
  
  /**
2344abbcb   Thomas Gleixner   clockevents: make...
172
173
174
175
176
   * clockevents_shutdown - shutdown the device and clear next_event
   * @dev:	device to shutdown
   */
  void clockevents_shutdown(struct clock_event_device *dev)
  {
d7eb231c7   Thomas Gleixner   clockevents: Prov...
177
  	clockevents_switch_state(dev, CLOCK_EVT_STATE_SHUTDOWN);
2456e8553   Thomas Gleixner   ktime: Get rid of...
178
  	dev->next_event = KTIME_MAX;
2344abbcb   Thomas Gleixner   clockevents: make...
179
  }
554ef3876   Viresh Kumar   clockevents: Hand...
180
181
182
183
184
185
186
  /**
   * clockevents_tick_resume -	Resume the tick device before using it again
   * @dev:			device to resume
   */
  int clockevents_tick_resume(struct clock_event_device *dev)
  {
  	int ret = 0;
eef7635a2   Viresh Kumar   clockevents: Remo...
187
  	if (dev->tick_resume)
77e32c89a   Viresh Kumar   clockevents: Mana...
188
  		ret = dev->tick_resume(dev);
554ef3876   Viresh Kumar   clockevents: Hand...
189
190
191
  
  	return ret;
  }
d1748302f   Martin Schwidefsky   clockevents: Make...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
  #ifdef CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST
  
  /* Limit min_delta to a jiffie */
  #define MIN_DELTA_LIMIT		(NSEC_PER_SEC / HZ)
  
  /**
   * clockevents_increase_min_delta - raise minimum delta of a clock event device
   * @dev:       device to increase the minimum delta
   *
   * Returns 0 on success, -ETIME when the minimum delta reached the limit.
   */
  static int clockevents_increase_min_delta(struct clock_event_device *dev)
  {
  	/* Nothing to do if we already reached the limit */
  	if (dev->min_delta_ns >= MIN_DELTA_LIMIT) {
504d58745   Jan Kara   timer: Fix lock i...
207
208
209
  		printk_deferred(KERN_WARNING
  				"CE: Reprogramming failure. Giving up
  ");
2456e8553   Thomas Gleixner   ktime: Get rid of...
210
  		dev->next_event = KTIME_MAX;
d1748302f   Martin Schwidefsky   clockevents: Make...
211
212
213
214
215
216
217
218
219
220
  		return -ETIME;
  	}
  
  	if (dev->min_delta_ns < 5000)
  		dev->min_delta_ns = 5000;
  	else
  		dev->min_delta_ns += dev->min_delta_ns >> 1;
  
  	if (dev->min_delta_ns > MIN_DELTA_LIMIT)
  		dev->min_delta_ns = MIN_DELTA_LIMIT;
504d58745   Jan Kara   timer: Fix lock i...
221
222
223
224
225
  	printk_deferred(KERN_WARNING
  			"CE: %s increased min_delta_ns to %llu nsec
  ",
  			dev->name ? dev->name : "?",
  			(unsigned long long) dev->min_delta_ns);
d1748302f   Martin Schwidefsky   clockevents: Make...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
  	return 0;
  }
  
  /**
   * clockevents_program_min_delta - Set clock event device to the minimum delay.
   * @dev:	device to program
   *
   * Returns 0 on success, -ETIME when the retry loop failed.
   */
  static int clockevents_program_min_delta(struct clock_event_device *dev)
  {
  	unsigned long long clc;
  	int64_t delta;
  	int i;
  
  	for (i = 0;;) {
  		delta = dev->min_delta_ns;
  		dev->next_event = ktime_add_ns(ktime_get(), delta);
472c4a943   Viresh Kumar   clockevents: Use ...
244
  		if (clockevent_state_shutdown(dev))
d1748302f   Martin Schwidefsky   clockevents: Make...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
  			return 0;
  
  		dev->retries++;
  		clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
  		if (dev->set_next_event((unsigned long) clc, dev) == 0)
  			return 0;
  
  		if (++i > 2) {
  			/*
  			 * We tried 3 times to program the device with the
  			 * given min_delta_ns. Try to increase the minimum
  			 * delta, if that fails as well get out of here.
  			 */
  			if (clockevents_increase_min_delta(dev))
  				return -ETIME;
  			i = 0;
  		}
  	}
  }
  
  #else  /* CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST */
  
  /**
   * clockevents_program_min_delta - Set clock event device to the minimum delay.
   * @dev:	device to program
   *
   * Returns 0 on success, -ETIME when the retry loop failed.
   */
  static int clockevents_program_min_delta(struct clock_event_device *dev)
  {
  	unsigned long long clc;
e28d7c01e   James Hogan   clockevents: Retr...
276
277
  	int64_t delta = 0;
  	int i;
d1748302f   Martin Schwidefsky   clockevents: Make...
278

e28d7c01e   James Hogan   clockevents: Retr...
279
280
281
  	for (i = 0; i < 10; i++) {
  		delta += dev->min_delta_ns;
  		dev->next_event = ktime_add_ns(ktime_get(), delta);
d1748302f   Martin Schwidefsky   clockevents: Make...
282

e28d7c01e   James Hogan   clockevents: Retr...
283
284
  		if (clockevent_state_shutdown(dev))
  			return 0;
d1748302f   Martin Schwidefsky   clockevents: Make...
285

e28d7c01e   James Hogan   clockevents: Retr...
286
287
288
289
290
291
  		dev->retries++;
  		clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
  		if (dev->set_next_event((unsigned long) clc, dev) == 0)
  			return 0;
  	}
  	return -ETIME;
d1748302f   Martin Schwidefsky   clockevents: Make...
292
293
294
  }
  
  #endif /* CONFIG_GENERIC_CLOCKEVENTS_MIN_ADJUST */
2344abbcb   Thomas Gleixner   clockevents: make...
295
  /**
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
296
   * clockevents_program_event - Reprogram the clock event device.
d1748302f   Martin Schwidefsky   clockevents: Make...
297
   * @dev:	device to program
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
298
   * @expires:	absolute expiry time (monotonic clock)
d1748302f   Martin Schwidefsky   clockevents: Make...
299
   * @force:	program minimum delay if expires can not be set
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
300
301
302
303
   *
   * Returns 0 on success, -ETIME when the event is in the past.
   */
  int clockevents_program_event(struct clock_event_device *dev, ktime_t expires,
d1748302f   Martin Schwidefsky   clockevents: Make...
304
  			      bool force)
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
305
306
307
  {
  	unsigned long long clc;
  	int64_t delta;
d1748302f   Martin Schwidefsky   clockevents: Make...
308
  	int rc;
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
309

2456e8553   Thomas Gleixner   ktime: Get rid of...
310
  	if (unlikely(expires < 0)) {
167b1de3e   Thomas Gleixner   clockevents: warn...
311
312
313
  		WARN_ON_ONCE(1);
  		return -ETIME;
  	}
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
314
  	dev->next_event = expires;
472c4a943   Viresh Kumar   clockevents: Use ...
315
  	if (clockevent_state_shutdown(dev))
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
316
  		return 0;
d25408756   Viresh Kumar   clockevents: Stop...
317
  	/* We must be in ONESHOT state here */
472c4a943   Viresh Kumar   clockevents: Use ...
318
319
  	WARN_ONCE(!clockevent_state_oneshot(dev), "Current state: %d
  ",
051ebd101   Thomas Gleixner   clockevents: Use ...
320
  		  clockevent_get_state(dev));
d25408756   Viresh Kumar   clockevents: Stop...
321

65516f8a7   Martin Schwidefsky   clockevents: Add ...
322
323
324
  	/* Shortcut for clockevent devices that can deal with ktime. */
  	if (dev->features & CLOCK_EVT_FEAT_KTIME)
  		return dev->set_next_ktime(expires, dev);
d1748302f   Martin Schwidefsky   clockevents: Make...
325
326
327
  	delta = ktime_to_ns(ktime_sub(expires, ktime_get()));
  	if (delta <= 0)
  		return force ? clockevents_program_min_delta(dev) : -ETIME;
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
328

d1748302f   Martin Schwidefsky   clockevents: Make...
329
330
  	delta = min(delta, (int64_t) dev->max_delta_ns);
  	delta = max(delta, (int64_t) dev->min_delta_ns);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
331

d1748302f   Martin Schwidefsky   clockevents: Make...
332
333
334
335
  	clc = ((unsigned long long) delta * dev->mult) >> dev->shift;
  	rc = dev->set_next_event((unsigned long) clc, dev);
  
  	return (rc && force) ? clockevents_program_min_delta(dev) : rc;
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
336
  }
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
337
  /*
3eb056764   Li Zefan   time: fix typo in...
338
   * Called after a notify add to make devices available which were
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
339
340
341
342
343
344
345
346
347
348
349
   * released from the notifier call.
   */
  static void clockevents_notify_released(void)
  {
  	struct clock_event_device *dev;
  
  	while (!list_empty(&clockevents_released)) {
  		dev = list_entry(clockevents_released.next,
  				 struct clock_event_device, list);
  		list_del(&dev->list);
  		list_add(&dev->list, &clockevent_devices);
7172a286c   Thomas Gleixner   clockevents: Get ...
350
  		tick_check_new_device(dev);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
351
352
  	}
  }
03e13cf5e   Thomas Gleixner   clockevents: Impl...
353
354
355
356
357
358
359
360
  /*
   * Try to install a replacement clock event device
   */
  static int clockevents_replace(struct clock_event_device *ced)
  {
  	struct clock_event_device *dev, *newdev = NULL;
  
  	list_for_each_entry(dev, &clockevent_devices, list) {
472c4a943   Viresh Kumar   clockevents: Use ...
361
  		if (dev == ced || !clockevent_state_detached(dev))
03e13cf5e   Thomas Gleixner   clockevents: Impl...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
  			continue;
  
  		if (!tick_check_replacement(newdev, dev))
  			continue;
  
  		if (!try_module_get(dev->owner))
  			continue;
  
  		if (newdev)
  			module_put(newdev->owner);
  		newdev = dev;
  	}
  	if (newdev) {
  		tick_install_replacement(newdev);
  		list_del_init(&ced->list);
  	}
  	return newdev ? 0 : -EBUSY;
  }
  
  /*
   * Called with clockevents_mutex and clockevents_lock held
   */
  static int __clockevents_try_unbind(struct clock_event_device *ced, int cpu)
  {
  	/* Fast track. Device is unused */
472c4a943   Viresh Kumar   clockevents: Use ...
387
  	if (clockevent_state_detached(ced)) {
03e13cf5e   Thomas Gleixner   clockevents: Impl...
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
  		list_del_init(&ced->list);
  		return 0;
  	}
  
  	return ced == per_cpu(tick_cpu_device, cpu).evtdev ? -EAGAIN : -EBUSY;
  }
  
  /*
   * SMP function call to unbind a device
   */
  static void __clockevents_unbind(void *arg)
  {
  	struct ce_unbind *cu = arg;
  	int res;
  
  	raw_spin_lock(&clockevents_lock);
  	res = __clockevents_try_unbind(cu->ce, smp_processor_id());
  	if (res == -EAGAIN)
  		res = clockevents_replace(cu->ce);
  	cu->res = res;
  	raw_spin_unlock(&clockevents_lock);
  }
  
  /*
   * Issues smp function call to unbind a per cpu device. Called with
   * clockevents_mutex held.
   */
  static int clockevents_unbind(struct clock_event_device *ced, int cpu)
  {
  	struct ce_unbind cu = { .ce = ced, .res = -ENODEV };
  
  	smp_call_function_single(cpu, __clockevents_unbind, &cu, 1);
  	return cu.res;
  }
  
  /*
   * Unbind a clockevents device.
   */
  int clockevents_unbind_device(struct clock_event_device *ced, int cpu)
  {
  	int ret;
  
  	mutex_lock(&clockevents_mutex);
  	ret = clockevents_unbind(ced, cpu);
  	mutex_unlock(&clockevents_mutex);
  	return ret;
  }
32a158325   Vitaly Kuznetsov   clockevents: expo...
435
  EXPORT_SYMBOL_GPL(clockevents_unbind_device);
03e13cf5e   Thomas Gleixner   clockevents: Impl...
436

d316c57ff   Thomas Gleixner   [PATCH] clockeven...
437
438
439
440
441
442
  /**
   * clockevents_register_device - register a clock event device
   * @dev:	device to register
   */
  void clockevents_register_device(struct clock_event_device *dev)
  {
f833bab87   Suresh Siddha   clockevent: Preve...
443
  	unsigned long flags;
77e32c89a   Viresh Kumar   clockevents: Mana...
444
  	/* Initialize state to DETACHED */
051ebd101   Thomas Gleixner   clockevents: Use ...
445
  	clockevent_set_state(dev, CLOCK_EVT_STATE_DETACHED);
77e32c89a   Viresh Kumar   clockevents: Mana...
446

1b054b67d   Thomas Gleixner   clockevents: Hand...
447
448
449
450
  	if (!dev->cpumask) {
  		WARN_ON(num_possible_cpus() > 1);
  		dev->cpumask = cpumask_of(smp_processor_id());
  	}
320ab2b0b   Rusty Russell   cpumask: convert ...
451

b5f91da0a   Thomas Gleixner   clockevents: Conv...
452
  	raw_spin_lock_irqsave(&clockevents_lock, flags);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
453
454
  
  	list_add(&dev->list, &clockevent_devices);
7172a286c   Thomas Gleixner   clockevents: Get ...
455
  	tick_check_new_device(dev);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
456
  	clockevents_notify_released();
b5f91da0a   Thomas Gleixner   clockevents: Conv...
457
  	raw_spin_unlock_irqrestore(&clockevents_lock, flags);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
458
  }
c81fc2c33   Magnus Damm   clockevent: expor...
459
  EXPORT_SYMBOL_GPL(clockevents_register_device);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
460

0695bd99c   Nicolai Stange   clockevents: Make...
461
  static void clockevents_config(struct clock_event_device *dev, u32 freq)
57f0fcbe1   Thomas Gleixner   clockevents: Prov...
462
  {
c0e299b1a   Thomas Gleixner   clockevents/sourc...
463
  	u64 sec;
57f0fcbe1   Thomas Gleixner   clockevents: Prov...
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
  
  	if (!(dev->features & CLOCK_EVT_FEAT_ONESHOT))
  		return;
  
  	/*
  	 * Calculate the maximum number of seconds we can sleep. Limit
  	 * to 10 minutes for hardware which can program more than
  	 * 32bit ticks so we still get reasonable conversion values.
  	 */
  	sec = dev->max_delta_ticks;
  	do_div(sec, freq);
  	if (!sec)
  		sec = 1;
  	else if (sec > 600 && dev->max_delta_ticks > UINT_MAX)
  		sec = 600;
  
  	clockevents_calc_mult_shift(dev, freq, sec);
97b941064   Thomas Gleixner   clockevents: Sani...
481
482
  	dev->min_delta_ns = cev_delta2ns(dev->min_delta_ticks, dev, false);
  	dev->max_delta_ns = cev_delta2ns(dev->max_delta_ticks, dev, true);
57f0fcbe1   Thomas Gleixner   clockevents: Prov...
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
  }
  
  /**
   * clockevents_config_and_register - Configure and register a clock event device
   * @dev:	device to register
   * @freq:	The clock frequency
   * @min_delta:	The minimum clock ticks to program in oneshot mode
   * @max_delta:	The maximum clock ticks to program in oneshot mode
   *
   * min/max_delta can be 0 for devices which do not support oneshot mode.
   */
  void clockevents_config_and_register(struct clock_event_device *dev,
  				     u32 freq, unsigned long min_delta,
  				     unsigned long max_delta)
  {
  	dev->min_delta_ticks = min_delta;
  	dev->max_delta_ticks = max_delta;
  	clockevents_config(dev, freq);
  	clockevents_register_device(dev);
  }
c35ef95c2   Shawn Guo   clockevents: expo...
503
  EXPORT_SYMBOL_GPL(clockevents_config_and_register);
57f0fcbe1   Thomas Gleixner   clockevents: Prov...
504

627ee7947   Thomas Gleixner   clockevents: Seri...
505
506
507
  int __clockevents_update_freq(struct clock_event_device *dev, u32 freq)
  {
  	clockevents_config(dev, freq);
472c4a943   Viresh Kumar   clockevents: Use ...
508
  	if (clockevent_state_oneshot(dev))
fe79a9ba1   Soren Brinkmann   clockevents: Adju...
509
  		return clockevents_program_event(dev, dev->next_event, false);
472c4a943   Viresh Kumar   clockevents: Use ...
510
  	if (clockevent_state_periodic(dev))
d7eb231c7   Thomas Gleixner   clockevents: Prov...
511
  		return __clockevents_switch_state(dev, CLOCK_EVT_STATE_PERIODIC);
627ee7947   Thomas Gleixner   clockevents: Seri...
512

fe79a9ba1   Soren Brinkmann   clockevents: Adju...
513
  	return 0;
627ee7947   Thomas Gleixner   clockevents: Seri...
514
  }
80b816b73   Thomas Gleixner   clockevents: Prov...
515
516
517
518
519
520
521
  /**
   * clockevents_update_freq - Update frequency and reprogram a clock event device.
   * @dev:	device to modify
   * @freq:	new device frequency
   *
   * Reconfigure and reprogram a clock event device in oneshot
   * mode. Must be called on the cpu for which the device delivers per
627ee7947   Thomas Gleixner   clockevents: Seri...
522
523
524
525
   * cpu timer events. If called for the broadcast device the core takes
   * care of serialization.
   *
   * Returns 0 on success, -ETIME when the event is in the past.
80b816b73   Thomas Gleixner   clockevents: Prov...
526
527
528
   */
  int clockevents_update_freq(struct clock_event_device *dev, u32 freq)
  {
627ee7947   Thomas Gleixner   clockevents: Seri...
529
530
  	unsigned long flags;
  	int ret;
80b816b73   Thomas Gleixner   clockevents: Prov...
531

627ee7947   Thomas Gleixner   clockevents: Seri...
532
533
534
535
536
537
  	local_irq_save(flags);
  	ret = tick_broadcast_update_freq(dev, freq);
  	if (ret == -ENODEV)
  		ret = __clockevents_update_freq(dev, freq);
  	local_irq_restore(flags);
  	return ret;
80b816b73   Thomas Gleixner   clockevents: Prov...
538
  }
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
539
540
541
  /*
   * Noop handler when we shut down an event device
   */
7c1e76897   Venkatesh Pallipadi   clockevents: prev...
542
  void clockevents_handle_noop(struct clock_event_device *dev)
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
543
544
545
546
547
548
549
550
  {
  }
  
  /**
   * clockevents_exchange_device - release and request clock devices
   * @old:	device to release (can be NULL)
   * @new:	device to request (can be NULL)
   *
db6f672ef   Thomas Gleixner   clockevents: Remo...
551
552
   * Called from various tick functions with clockevents_lock held and
   * interrupts disabled.
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
553
554
555
556
   */
  void clockevents_exchange_device(struct clock_event_device *old,
  				 struct clock_event_device *new)
  {
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
557
558
559
560
561
  	/*
  	 * Caller releases a clock event device. We queue it into the
  	 * released list and do a notify add later.
  	 */
  	if (old) {
ccf33d688   Thomas Gleixner   clockevents: Add ...
562
  		module_put(old->owner);
d7eb231c7   Thomas Gleixner   clockevents: Prov...
563
  		clockevents_switch_state(old, CLOCK_EVT_STATE_DETACHED);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
564
565
566
567
568
  		list_del(&old->list);
  		list_add(&old->list, &clockevents_released);
  	}
  
  	if (new) {
472c4a943   Viresh Kumar   clockevents: Use ...
569
  		BUG_ON(!clockevent_state_detached(new));
2344abbcb   Thomas Gleixner   clockevents: make...
570
  		clockevents_shutdown(new);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
571
  	}
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
572
  }
adc78e6b9   Rafael J. Wysocki   timekeeping: Add ...
573
574
575
576
577
578
579
580
  /**
   * clockevents_suspend - suspend clock devices
   */
  void clockevents_suspend(void)
  {
  	struct clock_event_device *dev;
  
  	list_for_each_entry_reverse(dev, &clockevent_devices, list)
a9d20988a   Viresh Kumar   clockevents: Chec...
581
  		if (dev->suspend && !clockevent_state_detached(dev))
adc78e6b9   Rafael J. Wysocki   timekeeping: Add ...
582
583
584
585
586
587
588
589
590
591
592
  			dev->suspend(dev);
  }
  
  /**
   * clockevents_resume - resume clock devices
   */
  void clockevents_resume(void)
  {
  	struct clock_event_device *dev;
  
  	list_for_each_entry(dev, &clockevent_devices, list)
a9d20988a   Viresh Kumar   clockevents: Chec...
593
  		if (dev->resume && !clockevent_state_detached(dev))
adc78e6b9   Rafael J. Wysocki   timekeeping: Add ...
594
595
  			dev->resume(dev);
  }
a49b116dc   Thomas Gleixner   clockevents: Clea...
596
  #ifdef CONFIG_HOTPLUG_CPU
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
597
  /**
a49b116dc   Thomas Gleixner   clockevents: Clea...
598
   * tick_cleanup_dead_cpu - Cleanup the tick and clockevents of a dead cpu
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
599
   */
a49b116dc   Thomas Gleixner   clockevents: Clea...
600
  void tick_cleanup_dead_cpu(int cpu)
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
601
  {
bb6eddf76   Thomas Gleixner   clockevents: Prev...
602
  	struct clock_event_device *dev, *tmp;
f833bab87   Suresh Siddha   clockevent: Preve...
603
  	unsigned long flags;
0b858e6ff   Li Zefan   clockevent: simpl...
604

b5f91da0a   Thomas Gleixner   clockevents: Conv...
605
  	raw_spin_lock_irqsave(&clockevents_lock, flags);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
606

a49b116dc   Thomas Gleixner   clockevents: Clea...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
  	tick_shutdown_broadcast_oneshot(cpu);
  	tick_shutdown_broadcast(cpu);
  	tick_shutdown(cpu);
  	/*
  	 * Unregister the clock event devices which were
  	 * released from the users in the notify chain.
  	 */
  	list_for_each_entry_safe(dev, tmp, &clockevents_released, list)
  		list_del(&dev->list);
  	/*
  	 * Now check whether the CPU has left unused per cpu devices
  	 */
  	list_for_each_entry_safe(dev, tmp, &clockevent_devices, list) {
  		if (cpumask_test_cpu(cpu, dev->cpumask) &&
  		    cpumask_weight(dev->cpumask) == 1 &&
  		    !tick_is_broadcast_device(dev)) {
472c4a943   Viresh Kumar   clockevents: Use ...
623
  			BUG_ON(!clockevent_state_detached(dev));
bb6eddf76   Thomas Gleixner   clockevents: Prev...
624
  			list_del(&dev->list);
bb6eddf76   Thomas Gleixner   clockevents: Prev...
625
  		}
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
626
  	}
b5f91da0a   Thomas Gleixner   clockevents: Conv...
627
  	raw_spin_unlock_irqrestore(&clockevents_lock, flags);
d316c57ff   Thomas Gleixner   [PATCH] clockeven...
628
  }
a49b116dc   Thomas Gleixner   clockevents: Clea...
629
  #endif
501f86706   Thomas Gleixner   clockevents: Prov...
630
631
  
  #ifdef CONFIG_SYSFS
775be5062   Ben Dooks   clockevents: Make...
632
  static struct bus_type clockevents_subsys = {
501f86706   Thomas Gleixner   clockevents: Prov...
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
  	.name		= "clockevents",
  	.dev_name       = "clockevent",
  };
  
  static DEFINE_PER_CPU(struct device, tick_percpu_dev);
  static struct tick_device *tick_get_tick_dev(struct device *dev);
  
  static ssize_t sysfs_show_current_tick_dev(struct device *dev,
  					   struct device_attribute *attr,
  					   char *buf)
  {
  	struct tick_device *td;
  	ssize_t count = 0;
  
  	raw_spin_lock_irq(&clockevents_lock);
  	td = tick_get_tick_dev(dev);
  	if (td && td->evtdev)
  		count = snprintf(buf, PAGE_SIZE, "%s
  ", td->evtdev->name);
  	raw_spin_unlock_irq(&clockevents_lock);
  	return count;
  }
  static DEVICE_ATTR(current_device, 0444, sysfs_show_current_tick_dev, NULL);
03e13cf5e   Thomas Gleixner   clockevents: Impl...
656
657
658
659
660
661
  /* We don't support the abomination of removable broadcast devices */
  static ssize_t sysfs_unbind_tick_dev(struct device *dev,
  				     struct device_attribute *attr,
  				     const char *buf, size_t count)
  {
  	char name[CS_NAME_LEN];
891292a76   Patrick Palka   time: Fix signedn...
662
  	ssize_t ret = sysfs_get_uname(buf, name, count);
03e13cf5e   Thomas Gleixner   clockevents: Impl...
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
  	struct clock_event_device *ce;
  
  	if (ret < 0)
  		return ret;
  
  	ret = -ENODEV;
  	mutex_lock(&clockevents_mutex);
  	raw_spin_lock_irq(&clockevents_lock);
  	list_for_each_entry(ce, &clockevent_devices, list) {
  		if (!strcmp(ce->name, name)) {
  			ret = __clockevents_try_unbind(ce, dev->id);
  			break;
  		}
  	}
  	raw_spin_unlock_irq(&clockevents_lock);
  	/*
  	 * We hold clockevents_mutex, so ce can't go away
  	 */
  	if (ret == -EAGAIN)
  		ret = clockevents_unbind(ce, dev->id);
  	mutex_unlock(&clockevents_mutex);
  	return ret ? ret : count;
  }
  static DEVICE_ATTR(unbind_device, 0200, NULL, sysfs_unbind_tick_dev);
501f86706   Thomas Gleixner   clockevents: Prov...
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
  #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST
  static struct device tick_bc_dev = {
  	.init_name	= "broadcast",
  	.id		= 0,
  	.bus		= &clockevents_subsys,
  };
  
  static struct tick_device *tick_get_tick_dev(struct device *dev)
  {
  	return dev == &tick_bc_dev ? tick_get_broadcast_device() :
  		&per_cpu(tick_cpu_device, dev->id);
  }
  
  static __init int tick_broadcast_init_sysfs(void)
  {
  	int err = device_register(&tick_bc_dev);
  
  	if (!err)
  		err = device_create_file(&tick_bc_dev, &dev_attr_current_device);
  	return err;
  }
  #else
  static struct tick_device *tick_get_tick_dev(struct device *dev)
  {
  	return &per_cpu(tick_cpu_device, dev->id);
  }
  static inline int tick_broadcast_init_sysfs(void) { return 0; }
de68d9b17   Thomas Gleixner   clockevents: Allo...
714
  #endif
501f86706   Thomas Gleixner   clockevents: Prov...
715
716
717
718
719
720
721
722
723
724
725
726
727
728
  
  static int __init tick_init_sysfs(void)
  {
  	int cpu;
  
  	for_each_possible_cpu(cpu) {
  		struct device *dev = &per_cpu(tick_percpu_dev, cpu);
  		int err;
  
  		dev->id = cpu;
  		dev->bus = &clockevents_subsys;
  		err = device_register(dev);
  		if (!err)
  			err = device_create_file(dev, &dev_attr_current_device);
03e13cf5e   Thomas Gleixner   clockevents: Impl...
729
730
  		if (!err)
  			err = device_create_file(dev, &dev_attr_unbind_device);
501f86706   Thomas Gleixner   clockevents: Prov...
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
  		if (err)
  			return err;
  	}
  	return tick_broadcast_init_sysfs();
  }
  
  static int __init clockevents_init_sysfs(void)
  {
  	int err = subsys_system_register(&clockevents_subsys, NULL);
  
  	if (!err)
  		err = tick_init_sysfs();
  	return err;
  }
  device_initcall(clockevents_init_sysfs);
  #endif /* SYSFS */