Blame view

kernel/time/alarmtimer.c 21.4 KB
ff3ead96d   John Stultz   timers: Introduce...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  /*
   * Alarmtimer interface
   *
   * This interface provides a timer which is similarto hrtimers,
   * but triggers a RTC alarm if the box is suspend.
   *
   * This interface is influenced by the Android RTC Alarm timer
   * interface.
   *
   * Copyright (C) 2010 IBM Corperation
   *
   * Author: John Stultz <john.stultz@linaro.org>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License version 2 as
   * published by the Free Software Foundation.
   */
  #include <linux/time.h>
  #include <linux/hrtimer.h>
  #include <linux/timerqueue.h>
  #include <linux/rtc.h>
  #include <linux/alarmtimer.h>
  #include <linux/mutex.h>
  #include <linux/platform_device.h>
  #include <linux/posix-timers.h>
  #include <linux/workqueue.h>
  #include <linux/freezer.h>
180bf812c   John Stultz   timers: Improve a...
28
29
30
31
  /**
   * struct alarm_base - Alarm timer bases
   * @lock:		Lock for syncrhonized access to the base
   * @timerqueue:		Timerqueue head managing the list of events
180bf812c   John Stultz   timers: Improve a...
32
33
   * @gettime:		Function to read the time correlating to the base
   * @base_clockid:	clockid for the base
180bf812c   John Stultz   timers: Improve a...
34
   */
ff3ead96d   John Stultz   timers: Introduce...
35
36
37
  static struct alarm_base {
  	spinlock_t		lock;
  	struct timerqueue_head	timerqueue;
ff3ead96d   John Stultz   timers: Introduce...
38
39
  	ktime_t			(*gettime)(void);
  	clockid_t		base_clockid;
ff3ead96d   John Stultz   timers: Introduce...
40
  } alarm_bases[ALARM_NUMTYPE];
c008ba58a   John Stultz   alarmtimers: Hand...
41
42
43
  /* freezer delta & lock used to handle clock_nanosleep triggered wakeups */
  static ktime_t freezer_delta;
  static DEFINE_SPINLOCK(freezer_delta_lock);
59a93c27c   Todd Poynor   alarmtimer: Imple...
44
  static struct wakeup_source *ws;
472647dcd   John Stultz   timers: Fix alarm...
45
  #ifdef CONFIG_RTC_CLASS
180bf812c   John Stultz   timers: Improve a...
46
  /* rtc timer and device for setting alarm wakeups at suspend */
c5e14e763   Thomas Gleixner   alarmtimer: Don't...
47
  static struct rtc_timer		rtctimer;
ff3ead96d   John Stultz   timers: Introduce...
48
  static struct rtc_device	*rtcdev;
c008ba58a   John Stultz   alarmtimers: Hand...
49
  static DEFINE_SPINLOCK(rtcdev_lock);
ff3ead96d   John Stultz   timers: Introduce...
50

c008ba58a   John Stultz   alarmtimers: Hand...
51
  /**
c008ba58a   John Stultz   alarmtimers: Hand...
52
53
54
55
56
57
   * alarmtimer_get_rtcdev - Return selected rtcdevice
   *
   * This function returns the rtc device to use for wakealarms.
   * If one has not already been chosen, it checks to see if a
   * functional rtc device is available.
   */
57c498fa5   John Stultz   alarmtimer: Provi...
58
  struct rtc_device *alarmtimer_get_rtcdev(void)
c008ba58a   John Stultz   alarmtimers: Hand...
59
  {
c008ba58a   John Stultz   alarmtimers: Hand...
60
61
62
63
  	unsigned long flags;
  	struct rtc_device *ret;
  
  	spin_lock_irqsave(&rtcdev_lock, flags);
c008ba58a   John Stultz   alarmtimers: Hand...
64
65
66
67
68
  	ret = rtcdev;
  	spin_unlock_irqrestore(&rtcdev_lock, flags);
  
  	return ret;
  }
71d5d2b72   Pramod Gurav   alarmtimer: Expor...
69
  EXPORT_SYMBOL_GPL(alarmtimer_get_rtcdev);
8bc0dafb5   John Stultz   alarmtimers: Rewo...
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
  
  static int alarmtimer_rtc_add_device(struct device *dev,
  				struct class_interface *class_intf)
  {
  	unsigned long flags;
  	struct rtc_device *rtc = to_rtc_device(dev);
  
  	if (rtcdev)
  		return -EBUSY;
  
  	if (!rtc->ops->set_alarm)
  		return -1;
  	if (!device_may_wakeup(rtc->dev.parent))
  		return -1;
  
  	spin_lock_irqsave(&rtcdev_lock, flags);
  	if (!rtcdev) {
  		rtcdev = rtc;
  		/* hold a reference so it doesn't go away */
  		get_device(dev);
  	}
  	spin_unlock_irqrestore(&rtcdev_lock, flags);
  	return 0;
  }
c5e14e763   Thomas Gleixner   alarmtimer: Don't...
94
95
96
97
  static inline void alarmtimer_rtc_timer_init(void)
  {
  	rtc_timer_init(&rtctimer, NULL, NULL);
  }
8bc0dafb5   John Stultz   alarmtimers: Rewo...
98
99
100
  static struct class_interface alarmtimer_rtc_interface = {
  	.add_dev = &alarmtimer_rtc_add_device,
  };
4523f6ada   Thomas Gleixner   alarmtimers: Fix ...
101
  static int alarmtimer_rtc_interface_setup(void)
8bc0dafb5   John Stultz   alarmtimers: Rewo...
102
103
  {
  	alarmtimer_rtc_interface.class = rtc_class;
4523f6ada   Thomas Gleixner   alarmtimers: Fix ...
104
105
106
107
108
  	return class_interface_register(&alarmtimer_rtc_interface);
  }
  static void alarmtimer_rtc_interface_remove(void)
  {
  	class_interface_unregister(&alarmtimer_rtc_interface);
8bc0dafb5   John Stultz   alarmtimers: Rewo...
109
  }
1c6b39ad3   John Stultz   alarmtimers: Retu...
110
  #else
57c498fa5   John Stultz   alarmtimer: Provi...
111
  struct rtc_device *alarmtimer_get_rtcdev(void)
4523f6ada   Thomas Gleixner   alarmtimers: Fix ...
112
113
114
115
116
117
  {
  	return NULL;
  }
  #define rtcdev (NULL)
  static inline int alarmtimer_rtc_interface_setup(void) { return 0; }
  static inline void alarmtimer_rtc_interface_remove(void) { }
c5e14e763   Thomas Gleixner   alarmtimer: Don't...
118
  static inline void alarmtimer_rtc_timer_init(void) { }
c008ba58a   John Stultz   alarmtimers: Hand...
119
  #endif
ff3ead96d   John Stultz   timers: Introduce...
120

180bf812c   John Stultz   timers: Improve a...
121
  /**
ff3ead96d   John Stultz   timers: Introduce...
122
123
124
125
   * alarmtimer_enqueue - Adds an alarm timer to an alarm_base timerqueue
   * @base: pointer to the base where the timer is being run
   * @alarm: pointer to alarm being enqueued.
   *
dae373be9   John Stultz   alarmtimer: Use h...
126
   * Adds alarm to a alarm_base timerqueue
ff3ead96d   John Stultz   timers: Introduce...
127
128
129
130
131
   *
   * Must hold base->lock when calling.
   */
  static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm)
  {
dae373be9   John Stultz   alarmtimer: Use h...
132
133
  	if (alarm->state & ALARMTIMER_STATE_ENQUEUED)
  		timerqueue_del(&base->timerqueue, &alarm->node);
ff3ead96d   John Stultz   timers: Introduce...
134
  	timerqueue_add(&base->timerqueue, &alarm->node);
a28cde81a   John Stultz   alarmtimers: Add ...
135
  	alarm->state |= ALARMTIMER_STATE_ENQUEUED;
ff3ead96d   John Stultz   timers: Introduce...
136
  }
180bf812c   John Stultz   timers: Improve a...
137
  /**
a65bcc12a   John Stultz   alarmtimer: Renam...
138
   * alarmtimer_dequeue - Removes an alarm timer from an alarm_base timerqueue
ff3ead96d   John Stultz   timers: Introduce...
139
140
141
   * @base: pointer to the base where the timer is running
   * @alarm: pointer to alarm being removed
   *
dae373be9   John Stultz   alarmtimer: Use h...
142
   * Removes alarm to a alarm_base timerqueue
ff3ead96d   John Stultz   timers: Introduce...
143
144
145
   *
   * Must hold base->lock when calling.
   */
a65bcc12a   John Stultz   alarmtimer: Renam...
146
  static void alarmtimer_dequeue(struct alarm_base *base, struct alarm *alarm)
ff3ead96d   John Stultz   timers: Introduce...
147
  {
a28cde81a   John Stultz   alarmtimers: Add ...
148
149
  	if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED))
  		return;
ff3ead96d   John Stultz   timers: Introduce...
150
  	timerqueue_del(&base->timerqueue, &alarm->node);
a28cde81a   John Stultz   alarmtimers: Add ...
151
  	alarm->state &= ~ALARMTIMER_STATE_ENQUEUED;
ff3ead96d   John Stultz   timers: Introduce...
152
  }
7068b7a16   John Stultz   timers: Remove de...
153

180bf812c   John Stultz   timers: Improve a...
154
  /**
7068b7a16   John Stultz   timers: Remove de...
155
156
   * alarmtimer_fired - Handles alarm hrtimer being fired.
   * @timer: pointer to hrtimer being run
ff3ead96d   John Stultz   timers: Introduce...
157
   *
180bf812c   John Stultz   timers: Improve a...
158
159
160
161
   * When a alarm timer fires, this runs through the timerqueue to
   * see which alarms expired, and runs those. If there are more alarm
   * timers queued for the future, we set the hrtimer to fire when
   * when the next future alarm timer expires.
ff3ead96d   John Stultz   timers: Introduce...
162
   */
7068b7a16   John Stultz   timers: Remove de...
163
  static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer)
ff3ead96d   John Stultz   timers: Introduce...
164
  {
dae373be9   John Stultz   alarmtimer: Use h...
165
166
  	struct alarm *alarm = container_of(timer, struct alarm, timer);
  	struct alarm_base *base = &alarm_bases[alarm->type];
ff3ead96d   John Stultz   timers: Introduce...
167
  	unsigned long flags;
7068b7a16   John Stultz   timers: Remove de...
168
  	int ret = HRTIMER_NORESTART;
54da23b72   John Stultz   alarmtimers: Push...
169
  	int restart = ALARMTIMER_NORESTART;
ff3ead96d   John Stultz   timers: Introduce...
170
171
  
  	spin_lock_irqsave(&base->lock, flags);
a65bcc12a   John Stultz   alarmtimer: Renam...
172
  	alarmtimer_dequeue(base, alarm);
dae373be9   John Stultz   alarmtimer: Use h...
173
  	spin_unlock_irqrestore(&base->lock, flags);
54da23b72   John Stultz   alarmtimers: Push...
174

dae373be9   John Stultz   alarmtimer: Use h...
175
176
  	if (alarm->function)
  		restart = alarm->function(alarm, base->gettime());
ff3ead96d   John Stultz   timers: Introduce...
177

dae373be9   John Stultz   alarmtimer: Use h...
178
179
180
181
  	spin_lock_irqsave(&base->lock, flags);
  	if (restart != ALARMTIMER_NORESTART) {
  		hrtimer_set_expires(&alarm->timer, alarm->node.expires);
  		alarmtimer_enqueue(base, alarm);
7068b7a16   John Stultz   timers: Remove de...
182
  		ret = HRTIMER_RESTART;
ff3ead96d   John Stultz   timers: Introduce...
183
184
  	}
  	spin_unlock_irqrestore(&base->lock, flags);
ff3ead96d   John Stultz   timers: Introduce...
185

7068b7a16   John Stultz   timers: Remove de...
186
  	return ret;
ff3ead96d   John Stultz   timers: Introduce...
187

ff3ead96d   John Stultz   timers: Introduce...
188
  }
6cffe00f7   Todd Poynor   alarmtimer: Add f...
189
190
191
192
193
  ktime_t alarm_expires_remaining(const struct alarm *alarm)
  {
  	struct alarm_base *base = &alarm_bases[alarm->type];
  	return ktime_sub(alarm->node.expires, base->gettime());
  }
11682a416   Marcus Gelderie   alarmtimer: Expor...
194
  EXPORT_SYMBOL_GPL(alarm_expires_remaining);
6cffe00f7   Todd Poynor   alarmtimer: Add f...
195

472647dcd   John Stultz   timers: Fix alarm...
196
  #ifdef CONFIG_RTC_CLASS
180bf812c   John Stultz   timers: Improve a...
197
  /**
ff3ead96d   John Stultz   timers: Introduce...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
   * alarmtimer_suspend - Suspend time callback
   * @dev: unused
   * @state: unused
   *
   * When we are going into suspend, we look through the bases
   * to see which is the soonest timer to expire. We then
   * set an rtc timer to fire that far into the future, which
   * will wake us from suspend.
   */
  static int alarmtimer_suspend(struct device *dev)
  {
  	struct rtc_time tm;
  	ktime_t min, now;
  	unsigned long flags;
c008ba58a   John Stultz   alarmtimers: Hand...
212
  	struct rtc_device *rtc;
ff3ead96d   John Stultz   timers: Introduce...
213
  	int i;
59a93c27c   Todd Poynor   alarmtimer: Imple...
214
  	int ret;
ff3ead96d   John Stultz   timers: Introduce...
215
216
217
218
219
  
  	spin_lock_irqsave(&freezer_delta_lock, flags);
  	min = freezer_delta;
  	freezer_delta = ktime_set(0, 0);
  	spin_unlock_irqrestore(&freezer_delta_lock, flags);
8bc0dafb5   John Stultz   alarmtimers: Rewo...
220
  	rtc = alarmtimer_get_rtcdev();
ff3ead96d   John Stultz   timers: Introduce...
221
  	/* If we have no rtcdev, just return */
c008ba58a   John Stultz   alarmtimers: Hand...
222
  	if (!rtc)
ff3ead96d   John Stultz   timers: Introduce...
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  		return 0;
  
  	/* Find the soonest timer to expire*/
  	for (i = 0; i < ALARM_NUMTYPE; i++) {
  		struct alarm_base *base = &alarm_bases[i];
  		struct timerqueue_node *next;
  		ktime_t delta;
  
  		spin_lock_irqsave(&base->lock, flags);
  		next = timerqueue_getnext(&base->timerqueue);
  		spin_unlock_irqrestore(&base->lock, flags);
  		if (!next)
  			continue;
  		delta = ktime_sub(next->expires, base->gettime());
  		if (!min.tv64 || (delta.tv64 < min.tv64))
  			min = delta;
  	}
  	if (min.tv64 == 0)
  		return 0;
59a93c27c   Todd Poynor   alarmtimer: Imple...
242
243
244
245
  	if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) {
  		__pm_wakeup_event(ws, 2 * MSEC_PER_SEC);
  		return -EBUSY;
  	}
ff3ead96d   John Stultz   timers: Introduce...
246
247
  
  	/* Setup an rtc timer to fire that far in the future */
c008ba58a   John Stultz   alarmtimers: Hand...
248
249
  	rtc_timer_cancel(rtc, &rtctimer);
  	rtc_read_time(rtc, &tm);
ff3ead96d   John Stultz   timers: Introduce...
250
251
  	now = rtc_tm_to_ktime(tm);
  	now = ktime_add(now, min);
59a93c27c   Todd Poynor   alarmtimer: Imple...
252
253
254
255
256
  	/* Set alarm, if in the past reject suspend briefly to handle */
  	ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0));
  	if (ret < 0)
  		__pm_wakeup_event(ws, MSEC_PER_SEC);
  	return ret;
ff3ead96d   John Stultz   timers: Introduce...
257
  }
a0e3213f8   zhuo-hao   alarmtimer: Avoid...
258
259
260
261
262
263
264
265
266
267
  
  static int alarmtimer_resume(struct device *dev)
  {
  	struct rtc_device *rtc;
  
  	rtc = alarmtimer_get_rtcdev();
  	if (rtc)
  		rtc_timer_cancel(rtc, &rtctimer);
  	return 0;
  }
472647dcd   John Stultz   timers: Fix alarm...
268
269
270
271
272
  #else
  static int alarmtimer_suspend(struct device *dev)
  {
  	return 0;
  }
a0e3213f8   zhuo-hao   alarmtimer: Avoid...
273
274
275
276
277
  
  static int alarmtimer_resume(struct device *dev)
  {
  	return 0;
  }
472647dcd   John Stultz   timers: Fix alarm...
278
  #endif
ff3ead96d   John Stultz   timers: Introduce...
279

9a7adcf5c   John Stultz   timers: Posix int...
280
281
282
283
284
285
286
287
288
289
290
291
292
  static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type)
  {
  	ktime_t delta;
  	unsigned long flags;
  	struct alarm_base *base = &alarm_bases[type];
  
  	delta = ktime_sub(absexp, base->gettime());
  
  	spin_lock_irqsave(&freezer_delta_lock, flags);
  	if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64))
  		freezer_delta = delta;
  	spin_unlock_irqrestore(&freezer_delta_lock, flags);
  }
180bf812c   John Stultz   timers: Improve a...
293
  /**
ff3ead96d   John Stultz   timers: Introduce...
294
295
296
297
   * alarm_init - Initialize an alarm structure
   * @alarm: ptr to alarm to be initialized
   * @type: the type of the alarm
   * @function: callback that is run when the alarm fires
ff3ead96d   John Stultz   timers: Introduce...
298
299
   */
  void alarm_init(struct alarm *alarm, enum alarmtimer_type type,
4b41308d2   John Stultz   alarmtimers: Chan...
300
  		enum alarmtimer_restart (*function)(struct alarm *, ktime_t))
ff3ead96d   John Stultz   timers: Introduce...
301
302
  {
  	timerqueue_init(&alarm->node);
dae373be9   John Stultz   alarmtimer: Use h...
303
304
305
  	hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid,
  			HRTIMER_MODE_ABS);
  	alarm->timer.function = alarmtimer_fired;
ff3ead96d   John Stultz   timers: Introduce...
306
307
  	alarm->function = function;
  	alarm->type = type;
a28cde81a   John Stultz   alarmtimers: Add ...
308
  	alarm->state = ALARMTIMER_STATE_INACTIVE;
ff3ead96d   John Stultz   timers: Introduce...
309
  }
11682a416   Marcus Gelderie   alarmtimer: Expor...
310
  EXPORT_SYMBOL_GPL(alarm_init);
ff3ead96d   John Stultz   timers: Introduce...
311

180bf812c   John Stultz   timers: Improve a...
312
  /**
6cffe00f7   Todd Poynor   alarmtimer: Add f...
313
   * alarm_start - Sets an absolute alarm to fire
ff3ead96d   John Stultz   timers: Introduce...
314
315
   * @alarm: ptr to alarm to set
   * @start: time to run the alarm
ff3ead96d   John Stultz   timers: Introduce...
316
   */
b193217e6   Thomas Gleixner   alarmtimer: Get r...
317
  void alarm_start(struct alarm *alarm, ktime_t start)
ff3ead96d   John Stultz   timers: Introduce...
318
319
320
321
322
  {
  	struct alarm_base *base = &alarm_bases[alarm->type];
  	unsigned long flags;
  
  	spin_lock_irqsave(&base->lock, flags);
ff3ead96d   John Stultz   timers: Introduce...
323
  	alarm->node.expires = start;
ff3ead96d   John Stultz   timers: Introduce...
324
  	alarmtimer_enqueue(base, alarm);
b193217e6   Thomas Gleixner   alarmtimer: Get r...
325
  	hrtimer_start(&alarm->timer, alarm->node.expires, HRTIMER_MODE_ABS);
ff3ead96d   John Stultz   timers: Introduce...
326
327
  	spin_unlock_irqrestore(&base->lock, flags);
  }
11682a416   Marcus Gelderie   alarmtimer: Expor...
328
  EXPORT_SYMBOL_GPL(alarm_start);
ff3ead96d   John Stultz   timers: Introduce...
329

180bf812c   John Stultz   timers: Improve a...
330
  /**
6cffe00f7   Todd Poynor   alarmtimer: Add f...
331
332
333
334
   * alarm_start_relative - Sets a relative alarm to fire
   * @alarm: ptr to alarm to set
   * @start: time relative to now to run the alarm
   */
b193217e6   Thomas Gleixner   alarmtimer: Get r...
335
  void alarm_start_relative(struct alarm *alarm, ktime_t start)
6cffe00f7   Todd Poynor   alarmtimer: Add f...
336
337
338
339
  {
  	struct alarm_base *base = &alarm_bases[alarm->type];
  
  	start = ktime_add(start, base->gettime());
b193217e6   Thomas Gleixner   alarmtimer: Get r...
340
  	alarm_start(alarm, start);
6cffe00f7   Todd Poynor   alarmtimer: Add f...
341
  }
11682a416   Marcus Gelderie   alarmtimer: Expor...
342
  EXPORT_SYMBOL_GPL(alarm_start_relative);
6cffe00f7   Todd Poynor   alarmtimer: Add f...
343
344
345
346
347
348
349
350
351
352
353
354
  
  void alarm_restart(struct alarm *alarm)
  {
  	struct alarm_base *base = &alarm_bases[alarm->type];
  	unsigned long flags;
  
  	spin_lock_irqsave(&base->lock, flags);
  	hrtimer_set_expires(&alarm->timer, alarm->node.expires);
  	hrtimer_restart(&alarm->timer);
  	alarmtimer_enqueue(base, alarm);
  	spin_unlock_irqrestore(&base->lock, flags);
  }
11682a416   Marcus Gelderie   alarmtimer: Expor...
355
  EXPORT_SYMBOL_GPL(alarm_restart);
6cffe00f7   Todd Poynor   alarmtimer: Add f...
356
357
  
  /**
9082c465a   John Stultz   alarmtimers: Add ...
358
   * alarm_try_to_cancel - Tries to cancel an alarm timer
ff3ead96d   John Stultz   timers: Introduce...
359
   * @alarm: ptr to alarm to be canceled
9082c465a   John Stultz   alarmtimers: Add ...
360
361
362
   *
   * Returns 1 if the timer was canceled, 0 if it was not running,
   * and -1 if the callback was running
ff3ead96d   John Stultz   timers: Introduce...
363
   */
9082c465a   John Stultz   alarmtimers: Add ...
364
  int alarm_try_to_cancel(struct alarm *alarm)
ff3ead96d   John Stultz   timers: Introduce...
365
366
367
  {
  	struct alarm_base *base = &alarm_bases[alarm->type];
  	unsigned long flags;
dae373be9   John Stultz   alarmtimer: Use h...
368
  	int ret;
9082c465a   John Stultz   alarmtimers: Add ...
369

dae373be9   John Stultz   alarmtimer: Use h...
370
371
372
  	spin_lock_irqsave(&base->lock, flags);
  	ret = hrtimer_try_to_cancel(&alarm->timer);
  	if (ret >= 0)
a65bcc12a   John Stultz   alarmtimer: Renam...
373
  		alarmtimer_dequeue(base, alarm);
ff3ead96d   John Stultz   timers: Introduce...
374
  	spin_unlock_irqrestore(&base->lock, flags);
9082c465a   John Stultz   alarmtimers: Add ...
375
  	return ret;
ff3ead96d   John Stultz   timers: Introduce...
376
  }
11682a416   Marcus Gelderie   alarmtimer: Expor...
377
  EXPORT_SYMBOL_GPL(alarm_try_to_cancel);
ff3ead96d   John Stultz   timers: Introduce...
378

9082c465a   John Stultz   alarmtimers: Add ...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
  /**
   * alarm_cancel - Spins trying to cancel an alarm timer until it is done
   * @alarm: ptr to alarm to be canceled
   *
   * Returns 1 if the timer was canceled, 0 if it was not active.
   */
  int alarm_cancel(struct alarm *alarm)
  {
  	for (;;) {
  		int ret = alarm_try_to_cancel(alarm);
  		if (ret >= 0)
  			return ret;
  		cpu_relax();
  	}
  }
11682a416   Marcus Gelderie   alarmtimer: Expor...
394
  EXPORT_SYMBOL_GPL(alarm_cancel);
9082c465a   John Stultz   alarmtimers: Add ...
395

dce75a8c7   John Stultz   alarmtimers: Add ...
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
  
  u64 alarm_forward(struct alarm *alarm, ktime_t now, ktime_t interval)
  {
  	u64 overrun = 1;
  	ktime_t delta;
  
  	delta = ktime_sub(now, alarm->node.expires);
  
  	if (delta.tv64 < 0)
  		return 0;
  
  	if (unlikely(delta.tv64 >= interval.tv64)) {
  		s64 incr = ktime_to_ns(interval);
  
  		overrun = ktime_divns(delta, incr);
  
  		alarm->node.expires = ktime_add_ns(alarm->node.expires,
  							incr*overrun);
  
  		if (alarm->node.expires.tv64 > now.tv64)
  			return overrun;
  		/*
  		 * This (and the ktime_add() below) is the
  		 * correction for exact:
  		 */
  		overrun++;
  	}
  
  	alarm->node.expires = ktime_add(alarm->node.expires, interval);
  	return overrun;
  }
11682a416   Marcus Gelderie   alarmtimer: Expor...
427
  EXPORT_SYMBOL_GPL(alarm_forward);
dce75a8c7   John Stultz   alarmtimers: Add ...
428

6cffe00f7   Todd Poynor   alarmtimer: Add f...
429
430
431
432
433
434
  u64 alarm_forward_now(struct alarm *alarm, ktime_t interval)
  {
  	struct alarm_base *base = &alarm_bases[alarm->type];
  
  	return alarm_forward(alarm, base->gettime(), interval);
  }
11682a416   Marcus Gelderie   alarmtimer: Expor...
435
  EXPORT_SYMBOL_GPL(alarm_forward_now);
dce75a8c7   John Stultz   alarmtimers: Add ...
436

180bf812c   John Stultz   timers: Improve a...
437
  /**
9a7adcf5c   John Stultz   timers: Posix int...
438
439
   * clock2alarm - helper that converts from clockid to alarmtypes
   * @clockid: clockid.
9a7adcf5c   John Stultz   timers: Posix int...
440
441
442
443
444
445
446
447
448
   */
  static enum alarmtimer_type clock2alarm(clockid_t clockid)
  {
  	if (clockid == CLOCK_REALTIME_ALARM)
  		return ALARM_REALTIME;
  	if (clockid == CLOCK_BOOTTIME_ALARM)
  		return ALARM_BOOTTIME;
  	return -1;
  }
180bf812c   John Stultz   timers: Improve a...
449
  /**
9a7adcf5c   John Stultz   timers: Posix int...
450
451
452
453
454
   * alarm_handle_timer - Callback for posix timers
   * @alarm: alarm that fired
   *
   * Posix timer callback for expired alarm timers.
   */
4b41308d2   John Stultz   alarmtimers: Chan...
455
456
  static enum alarmtimer_restart alarm_handle_timer(struct alarm *alarm,
  							ktime_t now)
9a7adcf5c   John Stultz   timers: Posix int...
457
  {
474e941be   Richard Larocque   alarmtimer: Lock ...
458
  	unsigned long flags;
9a7adcf5c   John Stultz   timers: Posix int...
459
  	struct k_itimer *ptr = container_of(alarm, struct k_itimer,
9e2647624   John Stultz   alarmtimers: Remo...
460
  						it.alarm.alarmtimer);
474e941be   Richard Larocque   alarmtimer: Lock ...
461
462
463
  	enum alarmtimer_restart result = ALARMTIMER_NORESTART;
  
  	spin_lock_irqsave(&ptr->it_lock, flags);
265b81d23   Richard Larocque   alarmtimer: Do no...
464
465
466
467
  	if ((ptr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) {
  		if (posix_timer_event(ptr, 0) != 0)
  			ptr->it_overrun++;
  	}
4b41308d2   John Stultz   alarmtimers: Chan...
468

54da23b72   John Stultz   alarmtimers: Push...
469
  	/* Re-add periodic timers */
9e2647624   John Stultz   alarmtimers: Remo...
470
471
472
  	if (ptr->it.alarm.interval.tv64) {
  		ptr->it_overrun += alarm_forward(alarm, now,
  						ptr->it.alarm.interval);
474e941be   Richard Larocque   alarmtimer: Lock ...
473
  		result = ALARMTIMER_RESTART;
54da23b72   John Stultz   alarmtimers: Push...
474
  	}
474e941be   Richard Larocque   alarmtimer: Lock ...
475
476
477
  	spin_unlock_irqrestore(&ptr->it_lock, flags);
  
  	return result;
9a7adcf5c   John Stultz   timers: Posix int...
478
  }
180bf812c   John Stultz   timers: Improve a...
479
  /**
9a7adcf5c   John Stultz   timers: Posix int...
480
481
482
483
484
485
486
487
   * alarm_clock_getres - posix getres interface
   * @which_clock: clockid
   * @tp: timespec to fill
   *
   * Returns the granularity of underlying alarm base clock
   */
  static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp)
  {
1c6b39ad3   John Stultz   alarmtimers: Retu...
488
  	if (!alarmtimer_get_rtcdev())
98d6f4dd8   KOSAKI Motohiro   alarmtimer: retur...
489
  		return -EINVAL;
1c6b39ad3   John Stultz   alarmtimers: Retu...
490

056a3cacb   Thomas Gleixner   hrtimer: Get rid ...
491
492
493
  	tp->tv_sec = 0;
  	tp->tv_nsec = hrtimer_resolution;
  	return 0;
9a7adcf5c   John Stultz   timers: Posix int...
494
495
496
497
498
499
500
501
502
503
504
505
  }
  
  /**
   * alarm_clock_get - posix clock_get interface
   * @which_clock: clockid
   * @tp: timespec to fill.
   *
   * Provides the underlying alarm base time.
   */
  static int alarm_clock_get(clockid_t which_clock, struct timespec *tp)
  {
  	struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)];
1c6b39ad3   John Stultz   alarmtimers: Retu...
506
  	if (!alarmtimer_get_rtcdev())
98d6f4dd8   KOSAKI Motohiro   alarmtimer: retur...
507
  		return -EINVAL;
1c6b39ad3   John Stultz   alarmtimers: Retu...
508

9a7adcf5c   John Stultz   timers: Posix int...
509
510
511
512
513
514
515
516
517
518
519
520
521
  	*tp = ktime_to_timespec(base->gettime());
  	return 0;
  }
  
  /**
   * alarm_timer_create - posix timer_create interface
   * @new_timer: k_itimer pointer to manage
   *
   * Initializes the k_itimer structure.
   */
  static int alarm_timer_create(struct k_itimer *new_timer)
  {
  	enum  alarmtimer_type type;
9a7adcf5c   John Stultz   timers: Posix int...
522

1c6b39ad3   John Stultz   alarmtimers: Retu...
523
524
  	if (!alarmtimer_get_rtcdev())
  		return -ENOTSUPP;
9a7adcf5c   John Stultz   timers: Posix int...
525
526
527
528
  	if (!capable(CAP_WAKE_ALARM))
  		return -EPERM;
  
  	type = clock2alarm(new_timer->it_clock);
9e2647624   John Stultz   alarmtimers: Remo...
529
  	alarm_init(&new_timer->it.alarm.alarmtimer, type, alarm_handle_timer);
9a7adcf5c   John Stultz   timers: Posix int...
530
531
532
533
534
535
536
537
  	return 0;
  }
  
  /**
   * alarm_timer_get - posix timer_get interface
   * @new_timer: k_itimer pointer
   * @cur_setting: itimerspec data to fill
   *
e86fea764   Richard Larocque   alarmtimer: Retur...
538
   * Copies out the current itimerspec data
9a7adcf5c   John Stultz   timers: Posix int...
539
540
541
542
   */
  static void alarm_timer_get(struct k_itimer *timr,
  				struct itimerspec *cur_setting)
  {
e86fea764   Richard Larocque   alarmtimer: Retur...
543
544
545
546
547
548
549
550
551
  	ktime_t relative_expiry_time =
  		alarm_expires_remaining(&(timr->it.alarm.alarmtimer));
  
  	if (ktime_to_ns(relative_expiry_time) > 0) {
  		cur_setting->it_value = ktime_to_timespec(relative_expiry_time);
  	} else {
  		cur_setting->it_value.tv_sec = 0;
  		cur_setting->it_value.tv_nsec = 0;
  	}
ea7802f63   John Stultz   alarmtimers: Mems...
552

e86fea764   Richard Larocque   alarmtimer: Retur...
553
  	cur_setting->it_interval = ktime_to_timespec(timr->it.alarm.interval);
9a7adcf5c   John Stultz   timers: Posix int...
554
555
556
557
558
559
560
561
562
563
  }
  
  /**
   * alarm_timer_del - posix timer_del interface
   * @timr: k_itimer pointer to be deleted
   *
   * Cancels any programmed alarms for the given timer.
   */
  static int alarm_timer_del(struct k_itimer *timr)
  {
1c6b39ad3   John Stultz   alarmtimers: Retu...
564
565
  	if (!rtcdev)
  		return -ENOTSUPP;
9082c465a   John Stultz   alarmtimers: Add ...
566
567
  	if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0)
  		return TIMER_RETRY;
9a7adcf5c   John Stultz   timers: Posix int...
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
  	return 0;
  }
  
  /**
   * alarm_timer_set - posix timer_set interface
   * @timr: k_itimer pointer to be deleted
   * @flags: timer flags
   * @new_setting: itimerspec to be used
   * @old_setting: itimerspec being replaced
   *
   * Sets the timer to new_setting, and starts the timer.
   */
  static int alarm_timer_set(struct k_itimer *timr, int flags,
  				struct itimerspec *new_setting,
  				struct itimerspec *old_setting)
  {
16927776a   John Stultz   alarmtimer: Fix b...
584
  	ktime_t exp;
1c6b39ad3   John Stultz   alarmtimers: Retu...
585
586
  	if (!rtcdev)
  		return -ENOTSUPP;
16927776a   John Stultz   alarmtimer: Fix b...
587
588
  	if (flags & ~TIMER_ABSTIME)
  		return -EINVAL;
971c90bfa   John Stultz   alarmtimers: Avoi...
589
590
  	if (old_setting)
  		alarm_timer_get(timr, old_setting);
9a7adcf5c   John Stultz   timers: Posix int...
591
592
  
  	/* If the timer was already set, cancel it */
9082c465a   John Stultz   alarmtimers: Add ...
593
594
  	if (alarm_try_to_cancel(&timr->it.alarm.alarmtimer) < 0)
  		return TIMER_RETRY;
9a7adcf5c   John Stultz   timers: Posix int...
595
596
  
  	/* start the timer */
9e2647624   John Stultz   alarmtimers: Remo...
597
  	timr->it.alarm.interval = timespec_to_ktime(new_setting->it_interval);
16927776a   John Stultz   alarmtimer: Fix b...
598
599
600
601
602
603
604
605
606
607
  	exp = timespec_to_ktime(new_setting->it_value);
  	/* Convert (if necessary) to absolute time */
  	if (flags != TIMER_ABSTIME) {
  		ktime_t now;
  
  		now = alarm_bases[timr->it.alarm.alarmtimer.type].gettime();
  		exp = ktime_add(now, exp);
  	}
  
  	alarm_start(&timr->it.alarm.alarmtimer, exp);
9a7adcf5c   John Stultz   timers: Posix int...
608
609
610
611
612
613
614
615
616
  	return 0;
  }
  
  /**
   * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep
   * @alarm: ptr to alarm that fired
   *
   * Wakes up the task that set the alarmtimer
   */
4b41308d2   John Stultz   alarmtimers: Chan...
617
618
  static enum alarmtimer_restart alarmtimer_nsleep_wakeup(struct alarm *alarm,
  								ktime_t now)
9a7adcf5c   John Stultz   timers: Posix int...
619
620
621
622
623
624
  {
  	struct task_struct *task = (struct task_struct *)alarm->data;
  
  	alarm->data = NULL;
  	if (task)
  		wake_up_process(task);
4b41308d2   John Stultz   alarmtimers: Chan...
625
  	return ALARMTIMER_NORESTART;
9a7adcf5c   John Stultz   timers: Posix int...
626
627
628
629
630
631
632
633
634
635
636
637
638
639
  }
  
  /**
   * alarmtimer_do_nsleep - Internal alarmtimer nsleep implementation
   * @alarm: ptr to alarmtimer
   * @absexp: absolute expiration time
   *
   * Sets the alarm timer and sleeps until it is fired or interrupted.
   */
  static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp)
  {
  	alarm->data = (void *)current;
  	do {
  		set_current_state(TASK_INTERRUPTIBLE);
9e2647624   John Stultz   alarmtimers: Remo...
640
  		alarm_start(alarm, absexp);
9a7adcf5c   John Stultz   timers: Posix int...
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
  		if (likely(alarm->data))
  			schedule();
  
  		alarm_cancel(alarm);
  	} while (alarm->data && !signal_pending(current));
  
  	__set_current_state(TASK_RUNNING);
  
  	return (alarm->data == NULL);
  }
  
  
  /**
   * update_rmtp - Update remaining timespec value
   * @exp: expiration time
   * @type: timer type
   * @rmtp: user pointer to remaining timepsec value
   *
   * Helper function that fills in rmtp value with time between
   * now and the exp value
   */
  static int update_rmtp(ktime_t exp, enum  alarmtimer_type type,
  			struct timespec __user *rmtp)
  {
  	struct timespec rmt;
  	ktime_t rem;
  
  	rem = ktime_sub(exp, alarm_bases[type].gettime());
  
  	if (rem.tv64 <= 0)
  		return 0;
  	rmt = ktime_to_timespec(rem);
  
  	if (copy_to_user(rmtp, &rmt, sizeof(*rmtp)))
  		return -EFAULT;
  
  	return 1;
  
  }
  
  /**
   * alarm_timer_nsleep_restart - restartblock alarmtimer nsleep
   * @restart: ptr to restart block
   *
   * Handles restarted clock_nanosleep calls
   */
  static long __sched alarm_timer_nsleep_restart(struct restart_block *restart)
  {
ab8177bc5   Thomas Gleixner   hrtimers: Avoid t...
689
  	enum  alarmtimer_type type = restart->nanosleep.clockid;
9a7adcf5c   John Stultz   timers: Posix int...
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
  	ktime_t exp;
  	struct timespec __user  *rmtp;
  	struct alarm alarm;
  	int ret = 0;
  
  	exp.tv64 = restart->nanosleep.expires;
  	alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
  
  	if (alarmtimer_do_nsleep(&alarm, exp))
  		goto out;
  
  	if (freezing(current))
  		alarmtimer_freezerset(exp, type);
  
  	rmtp = restart->nanosleep.rmtp;
  	if (rmtp) {
  		ret = update_rmtp(exp, type, rmtp);
  		if (ret <= 0)
  			goto out;
  	}
  
  
  	/* The other values in restart are already filled in */
  	ret = -ERESTART_RESTARTBLOCK;
  out:
  	return ret;
  }
  
  /**
   * alarm_timer_nsleep - alarmtimer nanosleep
   * @which_clock: clockid
   * @flags: determins abstime or relative
   * @tsreq: requested sleep time (abs or rel)
   * @rmtp: remaining sleep time saved
   *
   * Handles clock_nanosleep calls against _ALARM clockids
   */
  static int alarm_timer_nsleep(const clockid_t which_clock, int flags,
  		     struct timespec *tsreq, struct timespec __user *rmtp)
  {
  	enum  alarmtimer_type type = clock2alarm(which_clock);
  	struct alarm alarm;
  	ktime_t exp;
  	int ret = 0;
  	struct restart_block *restart;
1c6b39ad3   John Stultz   alarmtimers: Retu...
735
736
  	if (!alarmtimer_get_rtcdev())
  		return -ENOTSUPP;
16927776a   John Stultz   alarmtimer: Fix b...
737
738
  	if (flags & ~TIMER_ABSTIME)
  		return -EINVAL;
9a7adcf5c   John Stultz   timers: Posix int...
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
  	if (!capable(CAP_WAKE_ALARM))
  		return -EPERM;
  
  	alarm_init(&alarm, type, alarmtimer_nsleep_wakeup);
  
  	exp = timespec_to_ktime(*tsreq);
  	/* Convert (if necessary) to absolute time */
  	if (flags != TIMER_ABSTIME) {
  		ktime_t now = alarm_bases[type].gettime();
  		exp = ktime_add(now, exp);
  	}
  
  	if (alarmtimer_do_nsleep(&alarm, exp))
  		goto out;
  
  	if (freezing(current))
  		alarmtimer_freezerset(exp, type);
  
  	/* abs timers don't set remaining time or restart */
  	if (flags == TIMER_ABSTIME) {
  		ret = -ERESTARTNOHAND;
  		goto out;
  	}
  
  	if (rmtp) {
  		ret = update_rmtp(exp, type, rmtp);
  		if (ret <= 0)
  			goto out;
  	}
f56141e3e   Andy Lutomirski   all arches, signa...
768
  	restart = &current->restart_block;
9a7adcf5c   John Stultz   timers: Posix int...
769
  	restart->fn = alarm_timer_nsleep_restart;
ab8177bc5   Thomas Gleixner   hrtimers: Avoid t...
770
  	restart->nanosleep.clockid = type;
9a7adcf5c   John Stultz   timers: Posix int...
771
772
773
774
775
776
777
  	restart->nanosleep.expires = exp.tv64;
  	restart->nanosleep.rmtp = rmtp;
  	ret = -ERESTART_RESTARTBLOCK;
  
  out:
  	return ret;
  }
ff3ead96d   John Stultz   timers: Introduce...
778

ff3ead96d   John Stultz   timers: Introduce...
779
780
781
782
  
  /* Suspend hook structures */
  static const struct dev_pm_ops alarmtimer_pm_ops = {
  	.suspend = alarmtimer_suspend,
a0e3213f8   zhuo-hao   alarmtimer: Avoid...
783
  	.resume = alarmtimer_resume,
ff3ead96d   John Stultz   timers: Introduce...
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
  };
  
  static struct platform_driver alarmtimer_driver = {
  	.driver = {
  		.name = "alarmtimer",
  		.pm = &alarmtimer_pm_ops,
  	}
  };
  
  /**
   * alarmtimer_init - Initialize alarm timer code
   *
   * This function initializes the alarm bases and registers
   * the posix clock ids.
   */
  static int __init alarmtimer_init(void)
  {
4523f6ada   Thomas Gleixner   alarmtimers: Fix ...
801
  	struct platform_device *pdev;
ff3ead96d   John Stultz   timers: Introduce...
802
803
  	int error = 0;
  	int i;
9a7adcf5c   John Stultz   timers: Posix int...
804
805
806
807
808
809
810
811
812
  	struct k_clock alarm_clock = {
  		.clock_getres	= alarm_clock_getres,
  		.clock_get	= alarm_clock_get,
  		.timer_create	= alarm_timer_create,
  		.timer_set	= alarm_timer_set,
  		.timer_del	= alarm_timer_del,
  		.timer_get	= alarm_timer_get,
  		.nsleep		= alarm_timer_nsleep,
  	};
c5e14e763   Thomas Gleixner   alarmtimer: Don't...
813
  	alarmtimer_rtc_timer_init();
ad30dfa94   John Stultz   alarmtimer: Make ...
814

9a7adcf5c   John Stultz   timers: Posix int...
815
816
  	posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock);
  	posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock);
ff3ead96d   John Stultz   timers: Introduce...
817
818
819
820
821
822
823
824
825
  
  	/* Initialize alarm bases */
  	alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME;
  	alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real;
  	alarm_bases[ALARM_BOOTTIME].base_clockid = CLOCK_BOOTTIME;
  	alarm_bases[ALARM_BOOTTIME].gettime = &ktime_get_boottime;
  	for (i = 0; i < ALARM_NUMTYPE; i++) {
  		timerqueue_init_head(&alarm_bases[i].timerqueue);
  		spin_lock_init(&alarm_bases[i].lock);
ff3ead96d   John Stultz   timers: Introduce...
826
  	}
8bc0dafb5   John Stultz   alarmtimers: Rewo...
827

4523f6ada   Thomas Gleixner   alarmtimers: Fix ...
828
829
830
  	error = alarmtimer_rtc_interface_setup();
  	if (error)
  		return error;
ff3ead96d   John Stultz   timers: Introduce...
831
  	error = platform_driver_register(&alarmtimer_driver);
4523f6ada   Thomas Gleixner   alarmtimers: Fix ...
832
833
  	if (error)
  		goto out_if;
ff3ead96d   John Stultz   timers: Introduce...
834

4523f6ada   Thomas Gleixner   alarmtimers: Fix ...
835
836
837
838
839
  	pdev = platform_device_register_simple("alarmtimer", -1, NULL, 0);
  	if (IS_ERR(pdev)) {
  		error = PTR_ERR(pdev);
  		goto out_drv;
  	}
59a93c27c   Todd Poynor   alarmtimer: Imple...
840
  	ws = wakeup_source_register("alarmtimer");
4523f6ada   Thomas Gleixner   alarmtimers: Fix ...
841
842
843
844
845
846
  	return 0;
  
  out_drv:
  	platform_driver_unregister(&alarmtimer_driver);
  out_if:
  	alarmtimer_rtc_interface_remove();
ff3ead96d   John Stultz   timers: Introduce...
847
848
849
  	return error;
  }
  device_initcall(alarmtimer_init);