Commit ea7802f630d356acaf66b3c0b28c00a945fc35dc
1 parent
971c90bfa2
Exists in
master
and in
4 other branches
alarmtimers: Memset itimerspec passed into alarm_timer_get
Following common_timer_get, zero out the itimerspec passed in. CC: Thomas Gleixner <tglx@linutronix.de> CC: stable@kernel.org Signed-off-by: John Stultz <john.stultz@linaro.org>
Showing 1 changed file with 2 additions and 0 deletions Inline Diff
kernel/time/alarmtimer.c
1 | /* | 1 | /* |
2 | * Alarmtimer interface | 2 | * Alarmtimer interface |
3 | * | 3 | * |
4 | * This interface provides a timer which is similarto hrtimers, | 4 | * This interface provides a timer which is similarto hrtimers, |
5 | * but triggers a RTC alarm if the box is suspend. | 5 | * but triggers a RTC alarm if the box is suspend. |
6 | * | 6 | * |
7 | * This interface is influenced by the Android RTC Alarm timer | 7 | * This interface is influenced by the Android RTC Alarm timer |
8 | * interface. | 8 | * interface. |
9 | * | 9 | * |
10 | * Copyright (C) 2010 IBM Corperation | 10 | * Copyright (C) 2010 IBM Corperation |
11 | * | 11 | * |
12 | * Author: John Stultz <john.stultz@linaro.org> | 12 | * Author: John Stultz <john.stultz@linaro.org> |
13 | * | 13 | * |
14 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
15 | * it under the terms of the GNU General Public License version 2 as | 15 | * it under the terms of the GNU General Public License version 2 as |
16 | * published by the Free Software Foundation. | 16 | * published by the Free Software Foundation. |
17 | */ | 17 | */ |
18 | #include <linux/time.h> | 18 | #include <linux/time.h> |
19 | #include <linux/hrtimer.h> | 19 | #include <linux/hrtimer.h> |
20 | #include <linux/timerqueue.h> | 20 | #include <linux/timerqueue.h> |
21 | #include <linux/rtc.h> | 21 | #include <linux/rtc.h> |
22 | #include <linux/alarmtimer.h> | 22 | #include <linux/alarmtimer.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | #include <linux/posix-timers.h> | 25 | #include <linux/posix-timers.h> |
26 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
27 | #include <linux/freezer.h> | 27 | #include <linux/freezer.h> |
28 | 28 | ||
29 | /** | 29 | /** |
30 | * struct alarm_base - Alarm timer bases | 30 | * struct alarm_base - Alarm timer bases |
31 | * @lock: Lock for syncrhonized access to the base | 31 | * @lock: Lock for syncrhonized access to the base |
32 | * @timerqueue: Timerqueue head managing the list of events | 32 | * @timerqueue: Timerqueue head managing the list of events |
33 | * @timer: hrtimer used to schedule events while running | 33 | * @timer: hrtimer used to schedule events while running |
34 | * @gettime: Function to read the time correlating to the base | 34 | * @gettime: Function to read the time correlating to the base |
35 | * @base_clockid: clockid for the base | 35 | * @base_clockid: clockid for the base |
36 | */ | 36 | */ |
37 | static struct alarm_base { | 37 | static struct alarm_base { |
38 | spinlock_t lock; | 38 | spinlock_t lock; |
39 | struct timerqueue_head timerqueue; | 39 | struct timerqueue_head timerqueue; |
40 | struct hrtimer timer; | 40 | struct hrtimer timer; |
41 | ktime_t (*gettime)(void); | 41 | ktime_t (*gettime)(void); |
42 | clockid_t base_clockid; | 42 | clockid_t base_clockid; |
43 | } alarm_bases[ALARM_NUMTYPE]; | 43 | } alarm_bases[ALARM_NUMTYPE]; |
44 | 44 | ||
45 | /* freezer delta & lock used to handle clock_nanosleep triggered wakeups */ | 45 | /* freezer delta & lock used to handle clock_nanosleep triggered wakeups */ |
46 | static ktime_t freezer_delta; | 46 | static ktime_t freezer_delta; |
47 | static DEFINE_SPINLOCK(freezer_delta_lock); | 47 | static DEFINE_SPINLOCK(freezer_delta_lock); |
48 | 48 | ||
49 | #ifdef CONFIG_RTC_CLASS | 49 | #ifdef CONFIG_RTC_CLASS |
50 | /* rtc timer and device for setting alarm wakeups at suspend */ | 50 | /* rtc timer and device for setting alarm wakeups at suspend */ |
51 | static struct rtc_timer rtctimer; | 51 | static struct rtc_timer rtctimer; |
52 | static struct rtc_device *rtcdev; | 52 | static struct rtc_device *rtcdev; |
53 | static DEFINE_SPINLOCK(rtcdev_lock); | 53 | static DEFINE_SPINLOCK(rtcdev_lock); |
54 | 54 | ||
55 | /** | 55 | /** |
56 | * has_wakealarm - check rtc device has wakealarm ability | 56 | * has_wakealarm - check rtc device has wakealarm ability |
57 | * @dev: current device | 57 | * @dev: current device |
58 | * @name_ptr: name to be returned | 58 | * @name_ptr: name to be returned |
59 | * | 59 | * |
60 | * This helper function checks to see if the rtc device can wake | 60 | * This helper function checks to see if the rtc device can wake |
61 | * from suspend. | 61 | * from suspend. |
62 | */ | 62 | */ |
63 | static int has_wakealarm(struct device *dev, void *name_ptr) | 63 | static int has_wakealarm(struct device *dev, void *name_ptr) |
64 | { | 64 | { |
65 | struct rtc_device *candidate = to_rtc_device(dev); | 65 | struct rtc_device *candidate = to_rtc_device(dev); |
66 | 66 | ||
67 | if (!candidate->ops->set_alarm) | 67 | if (!candidate->ops->set_alarm) |
68 | return 0; | 68 | return 0; |
69 | if (!device_may_wakeup(candidate->dev.parent)) | 69 | if (!device_may_wakeup(candidate->dev.parent)) |
70 | return 0; | 70 | return 0; |
71 | 71 | ||
72 | *(const char **)name_ptr = dev_name(dev); | 72 | *(const char **)name_ptr = dev_name(dev); |
73 | return 1; | 73 | return 1; |
74 | } | 74 | } |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * alarmtimer_get_rtcdev - Return selected rtcdevice | 77 | * alarmtimer_get_rtcdev - Return selected rtcdevice |
78 | * | 78 | * |
79 | * This function returns the rtc device to use for wakealarms. | 79 | * This function returns the rtc device to use for wakealarms. |
80 | * If one has not already been chosen, it checks to see if a | 80 | * If one has not already been chosen, it checks to see if a |
81 | * functional rtc device is available. | 81 | * functional rtc device is available. |
82 | */ | 82 | */ |
83 | static struct rtc_device *alarmtimer_get_rtcdev(void) | 83 | static struct rtc_device *alarmtimer_get_rtcdev(void) |
84 | { | 84 | { |
85 | struct device *dev; | 85 | struct device *dev; |
86 | char *str; | 86 | char *str; |
87 | unsigned long flags; | 87 | unsigned long flags; |
88 | struct rtc_device *ret; | 88 | struct rtc_device *ret; |
89 | 89 | ||
90 | spin_lock_irqsave(&rtcdev_lock, flags); | 90 | spin_lock_irqsave(&rtcdev_lock, flags); |
91 | if (!rtcdev) { | 91 | if (!rtcdev) { |
92 | /* Find an rtc device and init the rtc_timer */ | 92 | /* Find an rtc device and init the rtc_timer */ |
93 | dev = class_find_device(rtc_class, NULL, &str, has_wakealarm); | 93 | dev = class_find_device(rtc_class, NULL, &str, has_wakealarm); |
94 | /* If we have a device then str is valid. See has_wakealarm() */ | 94 | /* If we have a device then str is valid. See has_wakealarm() */ |
95 | if (dev) { | 95 | if (dev) { |
96 | rtcdev = rtc_class_open(str); | 96 | rtcdev = rtc_class_open(str); |
97 | /* | 97 | /* |
98 | * Drop the reference we got in class_find_device, | 98 | * Drop the reference we got in class_find_device, |
99 | * rtc_open takes its own. | 99 | * rtc_open takes its own. |
100 | */ | 100 | */ |
101 | put_device(dev); | 101 | put_device(dev); |
102 | rtc_timer_init(&rtctimer, NULL, NULL); | 102 | rtc_timer_init(&rtctimer, NULL, NULL); |
103 | } | 103 | } |
104 | } | 104 | } |
105 | ret = rtcdev; | 105 | ret = rtcdev; |
106 | spin_unlock_irqrestore(&rtcdev_lock, flags); | 106 | spin_unlock_irqrestore(&rtcdev_lock, flags); |
107 | 107 | ||
108 | return ret; | 108 | return ret; |
109 | } | 109 | } |
110 | #else | 110 | #else |
111 | #define alarmtimer_get_rtcdev() (0) | 111 | #define alarmtimer_get_rtcdev() (0) |
112 | #define rtcdev (0) | 112 | #define rtcdev (0) |
113 | #endif | 113 | #endif |
114 | 114 | ||
115 | 115 | ||
116 | /** | 116 | /** |
117 | * alarmtimer_enqueue - Adds an alarm timer to an alarm_base timerqueue | 117 | * alarmtimer_enqueue - Adds an alarm timer to an alarm_base timerqueue |
118 | * @base: pointer to the base where the timer is being run | 118 | * @base: pointer to the base where the timer is being run |
119 | * @alarm: pointer to alarm being enqueued. | 119 | * @alarm: pointer to alarm being enqueued. |
120 | * | 120 | * |
121 | * Adds alarm to a alarm_base timerqueue and if necessary sets | 121 | * Adds alarm to a alarm_base timerqueue and if necessary sets |
122 | * an hrtimer to run. | 122 | * an hrtimer to run. |
123 | * | 123 | * |
124 | * Must hold base->lock when calling. | 124 | * Must hold base->lock when calling. |
125 | */ | 125 | */ |
126 | static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) | 126 | static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) |
127 | { | 127 | { |
128 | timerqueue_add(&base->timerqueue, &alarm->node); | 128 | timerqueue_add(&base->timerqueue, &alarm->node); |
129 | if (&alarm->node == timerqueue_getnext(&base->timerqueue)) { | 129 | if (&alarm->node == timerqueue_getnext(&base->timerqueue)) { |
130 | hrtimer_try_to_cancel(&base->timer); | 130 | hrtimer_try_to_cancel(&base->timer); |
131 | hrtimer_start(&base->timer, alarm->node.expires, | 131 | hrtimer_start(&base->timer, alarm->node.expires, |
132 | HRTIMER_MODE_ABS); | 132 | HRTIMER_MODE_ABS); |
133 | } | 133 | } |
134 | } | 134 | } |
135 | 135 | ||
136 | /** | 136 | /** |
137 | * alarmtimer_remove - Removes an alarm timer from an alarm_base timerqueue | 137 | * alarmtimer_remove - Removes an alarm timer from an alarm_base timerqueue |
138 | * @base: pointer to the base where the timer is running | 138 | * @base: pointer to the base where the timer is running |
139 | * @alarm: pointer to alarm being removed | 139 | * @alarm: pointer to alarm being removed |
140 | * | 140 | * |
141 | * Removes alarm to a alarm_base timerqueue and if necessary sets | 141 | * Removes alarm to a alarm_base timerqueue and if necessary sets |
142 | * a new timer to run. | 142 | * a new timer to run. |
143 | * | 143 | * |
144 | * Must hold base->lock when calling. | 144 | * Must hold base->lock when calling. |
145 | */ | 145 | */ |
146 | static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm) | 146 | static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm) |
147 | { | 147 | { |
148 | struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue); | 148 | struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue); |
149 | 149 | ||
150 | timerqueue_del(&base->timerqueue, &alarm->node); | 150 | timerqueue_del(&base->timerqueue, &alarm->node); |
151 | if (next == &alarm->node) { | 151 | if (next == &alarm->node) { |
152 | hrtimer_try_to_cancel(&base->timer); | 152 | hrtimer_try_to_cancel(&base->timer); |
153 | next = timerqueue_getnext(&base->timerqueue); | 153 | next = timerqueue_getnext(&base->timerqueue); |
154 | if (!next) | 154 | if (!next) |
155 | return; | 155 | return; |
156 | hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS); | 156 | hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS); |
157 | } | 157 | } |
158 | } | 158 | } |
159 | 159 | ||
160 | 160 | ||
161 | /** | 161 | /** |
162 | * alarmtimer_fired - Handles alarm hrtimer being fired. | 162 | * alarmtimer_fired - Handles alarm hrtimer being fired. |
163 | * @timer: pointer to hrtimer being run | 163 | * @timer: pointer to hrtimer being run |
164 | * | 164 | * |
165 | * When a alarm timer fires, this runs through the timerqueue to | 165 | * When a alarm timer fires, this runs through the timerqueue to |
166 | * see which alarms expired, and runs those. If there are more alarm | 166 | * see which alarms expired, and runs those. If there are more alarm |
167 | * timers queued for the future, we set the hrtimer to fire when | 167 | * timers queued for the future, we set the hrtimer to fire when |
168 | * when the next future alarm timer expires. | 168 | * when the next future alarm timer expires. |
169 | */ | 169 | */ |
170 | static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) | 170 | static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) |
171 | { | 171 | { |
172 | struct alarm_base *base = container_of(timer, struct alarm_base, timer); | 172 | struct alarm_base *base = container_of(timer, struct alarm_base, timer); |
173 | struct timerqueue_node *next; | 173 | struct timerqueue_node *next; |
174 | unsigned long flags; | 174 | unsigned long flags; |
175 | ktime_t now; | 175 | ktime_t now; |
176 | int ret = HRTIMER_NORESTART; | 176 | int ret = HRTIMER_NORESTART; |
177 | 177 | ||
178 | spin_lock_irqsave(&base->lock, flags); | 178 | spin_lock_irqsave(&base->lock, flags); |
179 | now = base->gettime(); | 179 | now = base->gettime(); |
180 | while ((next = timerqueue_getnext(&base->timerqueue))) { | 180 | while ((next = timerqueue_getnext(&base->timerqueue))) { |
181 | struct alarm *alarm; | 181 | struct alarm *alarm; |
182 | ktime_t expired = next->expires; | 182 | ktime_t expired = next->expires; |
183 | 183 | ||
184 | if (expired.tv64 >= now.tv64) | 184 | if (expired.tv64 >= now.tv64) |
185 | break; | 185 | break; |
186 | 186 | ||
187 | alarm = container_of(next, struct alarm, node); | 187 | alarm = container_of(next, struct alarm, node); |
188 | 188 | ||
189 | timerqueue_del(&base->timerqueue, &alarm->node); | 189 | timerqueue_del(&base->timerqueue, &alarm->node); |
190 | alarm->enabled = 0; | 190 | alarm->enabled = 0; |
191 | /* Re-add periodic timers */ | 191 | /* Re-add periodic timers */ |
192 | if (alarm->period.tv64) { | 192 | if (alarm->period.tv64) { |
193 | alarm->node.expires = ktime_add(expired, alarm->period); | 193 | alarm->node.expires = ktime_add(expired, alarm->period); |
194 | timerqueue_add(&base->timerqueue, &alarm->node); | 194 | timerqueue_add(&base->timerqueue, &alarm->node); |
195 | alarm->enabled = 1; | 195 | alarm->enabled = 1; |
196 | } | 196 | } |
197 | spin_unlock_irqrestore(&base->lock, flags); | 197 | spin_unlock_irqrestore(&base->lock, flags); |
198 | if (alarm->function) | 198 | if (alarm->function) |
199 | alarm->function(alarm); | 199 | alarm->function(alarm); |
200 | spin_lock_irqsave(&base->lock, flags); | 200 | spin_lock_irqsave(&base->lock, flags); |
201 | } | 201 | } |
202 | 202 | ||
203 | if (next) { | 203 | if (next) { |
204 | hrtimer_set_expires(&base->timer, next->expires); | 204 | hrtimer_set_expires(&base->timer, next->expires); |
205 | ret = HRTIMER_RESTART; | 205 | ret = HRTIMER_RESTART; |
206 | } | 206 | } |
207 | spin_unlock_irqrestore(&base->lock, flags); | 207 | spin_unlock_irqrestore(&base->lock, flags); |
208 | 208 | ||
209 | return ret; | 209 | return ret; |
210 | 210 | ||
211 | } | 211 | } |
212 | 212 | ||
213 | #ifdef CONFIG_RTC_CLASS | 213 | #ifdef CONFIG_RTC_CLASS |
214 | /** | 214 | /** |
215 | * alarmtimer_suspend - Suspend time callback | 215 | * alarmtimer_suspend - Suspend time callback |
216 | * @dev: unused | 216 | * @dev: unused |
217 | * @state: unused | 217 | * @state: unused |
218 | * | 218 | * |
219 | * When we are going into suspend, we look through the bases | 219 | * When we are going into suspend, we look through the bases |
220 | * to see which is the soonest timer to expire. We then | 220 | * to see which is the soonest timer to expire. We then |
221 | * set an rtc timer to fire that far into the future, which | 221 | * set an rtc timer to fire that far into the future, which |
222 | * will wake us from suspend. | 222 | * will wake us from suspend. |
223 | */ | 223 | */ |
224 | static int alarmtimer_suspend(struct device *dev) | 224 | static int alarmtimer_suspend(struct device *dev) |
225 | { | 225 | { |
226 | struct rtc_time tm; | 226 | struct rtc_time tm; |
227 | ktime_t min, now; | 227 | ktime_t min, now; |
228 | unsigned long flags; | 228 | unsigned long flags; |
229 | struct rtc_device *rtc; | 229 | struct rtc_device *rtc; |
230 | int i; | 230 | int i; |
231 | 231 | ||
232 | spin_lock_irqsave(&freezer_delta_lock, flags); | 232 | spin_lock_irqsave(&freezer_delta_lock, flags); |
233 | min = freezer_delta; | 233 | min = freezer_delta; |
234 | freezer_delta = ktime_set(0, 0); | 234 | freezer_delta = ktime_set(0, 0); |
235 | spin_unlock_irqrestore(&freezer_delta_lock, flags); | 235 | spin_unlock_irqrestore(&freezer_delta_lock, flags); |
236 | 236 | ||
237 | rtc = rtcdev; | 237 | rtc = rtcdev; |
238 | /* If we have no rtcdev, just return */ | 238 | /* If we have no rtcdev, just return */ |
239 | if (!rtc) | 239 | if (!rtc) |
240 | return 0; | 240 | return 0; |
241 | 241 | ||
242 | /* Find the soonest timer to expire*/ | 242 | /* Find the soonest timer to expire*/ |
243 | for (i = 0; i < ALARM_NUMTYPE; i++) { | 243 | for (i = 0; i < ALARM_NUMTYPE; i++) { |
244 | struct alarm_base *base = &alarm_bases[i]; | 244 | struct alarm_base *base = &alarm_bases[i]; |
245 | struct timerqueue_node *next; | 245 | struct timerqueue_node *next; |
246 | ktime_t delta; | 246 | ktime_t delta; |
247 | 247 | ||
248 | spin_lock_irqsave(&base->lock, flags); | 248 | spin_lock_irqsave(&base->lock, flags); |
249 | next = timerqueue_getnext(&base->timerqueue); | 249 | next = timerqueue_getnext(&base->timerqueue); |
250 | spin_unlock_irqrestore(&base->lock, flags); | 250 | spin_unlock_irqrestore(&base->lock, flags); |
251 | if (!next) | 251 | if (!next) |
252 | continue; | 252 | continue; |
253 | delta = ktime_sub(next->expires, base->gettime()); | 253 | delta = ktime_sub(next->expires, base->gettime()); |
254 | if (!min.tv64 || (delta.tv64 < min.tv64)) | 254 | if (!min.tv64 || (delta.tv64 < min.tv64)) |
255 | min = delta; | 255 | min = delta; |
256 | } | 256 | } |
257 | if (min.tv64 == 0) | 257 | if (min.tv64 == 0) |
258 | return 0; | 258 | return 0; |
259 | 259 | ||
260 | /* XXX - Should we enforce a minimum sleep time? */ | 260 | /* XXX - Should we enforce a minimum sleep time? */ |
261 | WARN_ON(min.tv64 < NSEC_PER_SEC); | 261 | WARN_ON(min.tv64 < NSEC_PER_SEC); |
262 | 262 | ||
263 | /* Setup an rtc timer to fire that far in the future */ | 263 | /* Setup an rtc timer to fire that far in the future */ |
264 | rtc_timer_cancel(rtc, &rtctimer); | 264 | rtc_timer_cancel(rtc, &rtctimer); |
265 | rtc_read_time(rtc, &tm); | 265 | rtc_read_time(rtc, &tm); |
266 | now = rtc_tm_to_ktime(tm); | 266 | now = rtc_tm_to_ktime(tm); |
267 | now = ktime_add(now, min); | 267 | now = ktime_add(now, min); |
268 | 268 | ||
269 | rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); | 269 | rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); |
270 | 270 | ||
271 | return 0; | 271 | return 0; |
272 | } | 272 | } |
273 | #else | 273 | #else |
274 | static int alarmtimer_suspend(struct device *dev) | 274 | static int alarmtimer_suspend(struct device *dev) |
275 | { | 275 | { |
276 | return 0; | 276 | return 0; |
277 | } | 277 | } |
278 | #endif | 278 | #endif |
279 | 279 | ||
280 | static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) | 280 | static void alarmtimer_freezerset(ktime_t absexp, enum alarmtimer_type type) |
281 | { | 281 | { |
282 | ktime_t delta; | 282 | ktime_t delta; |
283 | unsigned long flags; | 283 | unsigned long flags; |
284 | struct alarm_base *base = &alarm_bases[type]; | 284 | struct alarm_base *base = &alarm_bases[type]; |
285 | 285 | ||
286 | delta = ktime_sub(absexp, base->gettime()); | 286 | delta = ktime_sub(absexp, base->gettime()); |
287 | 287 | ||
288 | spin_lock_irqsave(&freezer_delta_lock, flags); | 288 | spin_lock_irqsave(&freezer_delta_lock, flags); |
289 | if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64)) | 289 | if (!freezer_delta.tv64 || (delta.tv64 < freezer_delta.tv64)) |
290 | freezer_delta = delta; | 290 | freezer_delta = delta; |
291 | spin_unlock_irqrestore(&freezer_delta_lock, flags); | 291 | spin_unlock_irqrestore(&freezer_delta_lock, flags); |
292 | } | 292 | } |
293 | 293 | ||
294 | 294 | ||
295 | /** | 295 | /** |
296 | * alarm_init - Initialize an alarm structure | 296 | * alarm_init - Initialize an alarm structure |
297 | * @alarm: ptr to alarm to be initialized | 297 | * @alarm: ptr to alarm to be initialized |
298 | * @type: the type of the alarm | 298 | * @type: the type of the alarm |
299 | * @function: callback that is run when the alarm fires | 299 | * @function: callback that is run when the alarm fires |
300 | */ | 300 | */ |
301 | void alarm_init(struct alarm *alarm, enum alarmtimer_type type, | 301 | void alarm_init(struct alarm *alarm, enum alarmtimer_type type, |
302 | void (*function)(struct alarm *)) | 302 | void (*function)(struct alarm *)) |
303 | { | 303 | { |
304 | timerqueue_init(&alarm->node); | 304 | timerqueue_init(&alarm->node); |
305 | alarm->period = ktime_set(0, 0); | 305 | alarm->period = ktime_set(0, 0); |
306 | alarm->function = function; | 306 | alarm->function = function; |
307 | alarm->type = type; | 307 | alarm->type = type; |
308 | alarm->enabled = 0; | 308 | alarm->enabled = 0; |
309 | } | 309 | } |
310 | 310 | ||
311 | /** | 311 | /** |
312 | * alarm_start - Sets an alarm to fire | 312 | * alarm_start - Sets an alarm to fire |
313 | * @alarm: ptr to alarm to set | 313 | * @alarm: ptr to alarm to set |
314 | * @start: time to run the alarm | 314 | * @start: time to run the alarm |
315 | * @period: period at which the alarm will recur | 315 | * @period: period at which the alarm will recur |
316 | */ | 316 | */ |
317 | void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period) | 317 | void alarm_start(struct alarm *alarm, ktime_t start, ktime_t period) |
318 | { | 318 | { |
319 | struct alarm_base *base = &alarm_bases[alarm->type]; | 319 | struct alarm_base *base = &alarm_bases[alarm->type]; |
320 | unsigned long flags; | 320 | unsigned long flags; |
321 | 321 | ||
322 | spin_lock_irqsave(&base->lock, flags); | 322 | spin_lock_irqsave(&base->lock, flags); |
323 | if (alarm->enabled) | 323 | if (alarm->enabled) |
324 | alarmtimer_remove(base, alarm); | 324 | alarmtimer_remove(base, alarm); |
325 | alarm->node.expires = start; | 325 | alarm->node.expires = start; |
326 | alarm->period = period; | 326 | alarm->period = period; |
327 | alarmtimer_enqueue(base, alarm); | 327 | alarmtimer_enqueue(base, alarm); |
328 | alarm->enabled = 1; | 328 | alarm->enabled = 1; |
329 | spin_unlock_irqrestore(&base->lock, flags); | 329 | spin_unlock_irqrestore(&base->lock, flags); |
330 | } | 330 | } |
331 | 331 | ||
332 | /** | 332 | /** |
333 | * alarm_cancel - Tries to cancel an alarm timer | 333 | * alarm_cancel - Tries to cancel an alarm timer |
334 | * @alarm: ptr to alarm to be canceled | 334 | * @alarm: ptr to alarm to be canceled |
335 | */ | 335 | */ |
336 | void alarm_cancel(struct alarm *alarm) | 336 | void alarm_cancel(struct alarm *alarm) |
337 | { | 337 | { |
338 | struct alarm_base *base = &alarm_bases[alarm->type]; | 338 | struct alarm_base *base = &alarm_bases[alarm->type]; |
339 | unsigned long flags; | 339 | unsigned long flags; |
340 | 340 | ||
341 | spin_lock_irqsave(&base->lock, flags); | 341 | spin_lock_irqsave(&base->lock, flags); |
342 | if (alarm->enabled) | 342 | if (alarm->enabled) |
343 | alarmtimer_remove(base, alarm); | 343 | alarmtimer_remove(base, alarm); |
344 | alarm->enabled = 0; | 344 | alarm->enabled = 0; |
345 | spin_unlock_irqrestore(&base->lock, flags); | 345 | spin_unlock_irqrestore(&base->lock, flags); |
346 | } | 346 | } |
347 | 347 | ||
348 | 348 | ||
349 | /** | 349 | /** |
350 | * clock2alarm - helper that converts from clockid to alarmtypes | 350 | * clock2alarm - helper that converts from clockid to alarmtypes |
351 | * @clockid: clockid. | 351 | * @clockid: clockid. |
352 | */ | 352 | */ |
353 | static enum alarmtimer_type clock2alarm(clockid_t clockid) | 353 | static enum alarmtimer_type clock2alarm(clockid_t clockid) |
354 | { | 354 | { |
355 | if (clockid == CLOCK_REALTIME_ALARM) | 355 | if (clockid == CLOCK_REALTIME_ALARM) |
356 | return ALARM_REALTIME; | 356 | return ALARM_REALTIME; |
357 | if (clockid == CLOCK_BOOTTIME_ALARM) | 357 | if (clockid == CLOCK_BOOTTIME_ALARM) |
358 | return ALARM_BOOTTIME; | 358 | return ALARM_BOOTTIME; |
359 | return -1; | 359 | return -1; |
360 | } | 360 | } |
361 | 361 | ||
362 | /** | 362 | /** |
363 | * alarm_handle_timer - Callback for posix timers | 363 | * alarm_handle_timer - Callback for posix timers |
364 | * @alarm: alarm that fired | 364 | * @alarm: alarm that fired |
365 | * | 365 | * |
366 | * Posix timer callback for expired alarm timers. | 366 | * Posix timer callback for expired alarm timers. |
367 | */ | 367 | */ |
368 | static void alarm_handle_timer(struct alarm *alarm) | 368 | static void alarm_handle_timer(struct alarm *alarm) |
369 | { | 369 | { |
370 | struct k_itimer *ptr = container_of(alarm, struct k_itimer, | 370 | struct k_itimer *ptr = container_of(alarm, struct k_itimer, |
371 | it.alarmtimer); | 371 | it.alarmtimer); |
372 | if (posix_timer_event(ptr, 0) != 0) | 372 | if (posix_timer_event(ptr, 0) != 0) |
373 | ptr->it_overrun++; | 373 | ptr->it_overrun++; |
374 | } | 374 | } |
375 | 375 | ||
376 | /** | 376 | /** |
377 | * alarm_clock_getres - posix getres interface | 377 | * alarm_clock_getres - posix getres interface |
378 | * @which_clock: clockid | 378 | * @which_clock: clockid |
379 | * @tp: timespec to fill | 379 | * @tp: timespec to fill |
380 | * | 380 | * |
381 | * Returns the granularity of underlying alarm base clock | 381 | * Returns the granularity of underlying alarm base clock |
382 | */ | 382 | */ |
383 | static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp) | 383 | static int alarm_clock_getres(const clockid_t which_clock, struct timespec *tp) |
384 | { | 384 | { |
385 | clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid; | 385 | clockid_t baseid = alarm_bases[clock2alarm(which_clock)].base_clockid; |
386 | 386 | ||
387 | if (!alarmtimer_get_rtcdev()) | 387 | if (!alarmtimer_get_rtcdev()) |
388 | return -ENOTSUPP; | 388 | return -ENOTSUPP; |
389 | 389 | ||
390 | return hrtimer_get_res(baseid, tp); | 390 | return hrtimer_get_res(baseid, tp); |
391 | } | 391 | } |
392 | 392 | ||
393 | /** | 393 | /** |
394 | * alarm_clock_get - posix clock_get interface | 394 | * alarm_clock_get - posix clock_get interface |
395 | * @which_clock: clockid | 395 | * @which_clock: clockid |
396 | * @tp: timespec to fill. | 396 | * @tp: timespec to fill. |
397 | * | 397 | * |
398 | * Provides the underlying alarm base time. | 398 | * Provides the underlying alarm base time. |
399 | */ | 399 | */ |
400 | static int alarm_clock_get(clockid_t which_clock, struct timespec *tp) | 400 | static int alarm_clock_get(clockid_t which_clock, struct timespec *tp) |
401 | { | 401 | { |
402 | struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)]; | 402 | struct alarm_base *base = &alarm_bases[clock2alarm(which_clock)]; |
403 | 403 | ||
404 | if (!alarmtimer_get_rtcdev()) | 404 | if (!alarmtimer_get_rtcdev()) |
405 | return -ENOTSUPP; | 405 | return -ENOTSUPP; |
406 | 406 | ||
407 | *tp = ktime_to_timespec(base->gettime()); | 407 | *tp = ktime_to_timespec(base->gettime()); |
408 | return 0; | 408 | return 0; |
409 | } | 409 | } |
410 | 410 | ||
411 | /** | 411 | /** |
412 | * alarm_timer_create - posix timer_create interface | 412 | * alarm_timer_create - posix timer_create interface |
413 | * @new_timer: k_itimer pointer to manage | 413 | * @new_timer: k_itimer pointer to manage |
414 | * | 414 | * |
415 | * Initializes the k_itimer structure. | 415 | * Initializes the k_itimer structure. |
416 | */ | 416 | */ |
417 | static int alarm_timer_create(struct k_itimer *new_timer) | 417 | static int alarm_timer_create(struct k_itimer *new_timer) |
418 | { | 418 | { |
419 | enum alarmtimer_type type; | 419 | enum alarmtimer_type type; |
420 | struct alarm_base *base; | 420 | struct alarm_base *base; |
421 | 421 | ||
422 | if (!alarmtimer_get_rtcdev()) | 422 | if (!alarmtimer_get_rtcdev()) |
423 | return -ENOTSUPP; | 423 | return -ENOTSUPP; |
424 | 424 | ||
425 | if (!capable(CAP_WAKE_ALARM)) | 425 | if (!capable(CAP_WAKE_ALARM)) |
426 | return -EPERM; | 426 | return -EPERM; |
427 | 427 | ||
428 | type = clock2alarm(new_timer->it_clock); | 428 | type = clock2alarm(new_timer->it_clock); |
429 | base = &alarm_bases[type]; | 429 | base = &alarm_bases[type]; |
430 | alarm_init(&new_timer->it.alarmtimer, type, alarm_handle_timer); | 430 | alarm_init(&new_timer->it.alarmtimer, type, alarm_handle_timer); |
431 | return 0; | 431 | return 0; |
432 | } | 432 | } |
433 | 433 | ||
434 | /** | 434 | /** |
435 | * alarm_timer_get - posix timer_get interface | 435 | * alarm_timer_get - posix timer_get interface |
436 | * @new_timer: k_itimer pointer | 436 | * @new_timer: k_itimer pointer |
437 | * @cur_setting: itimerspec data to fill | 437 | * @cur_setting: itimerspec data to fill |
438 | * | 438 | * |
439 | * Copies the itimerspec data out from the k_itimer | 439 | * Copies the itimerspec data out from the k_itimer |
440 | */ | 440 | */ |
441 | static void alarm_timer_get(struct k_itimer *timr, | 441 | static void alarm_timer_get(struct k_itimer *timr, |
442 | struct itimerspec *cur_setting) | 442 | struct itimerspec *cur_setting) |
443 | { | 443 | { |
444 | memset(cur_setting, 0, sizeof(struct itimerspec)); | ||
445 | |||
444 | cur_setting->it_interval = | 446 | cur_setting->it_interval = |
445 | ktime_to_timespec(timr->it.alarmtimer.period); | 447 | ktime_to_timespec(timr->it.alarmtimer.period); |
446 | cur_setting->it_value = | 448 | cur_setting->it_value = |
447 | ktime_to_timespec(timr->it.alarmtimer.node.expires); | 449 | ktime_to_timespec(timr->it.alarmtimer.node.expires); |
448 | return; | 450 | return; |
449 | } | 451 | } |
450 | 452 | ||
451 | /** | 453 | /** |
452 | * alarm_timer_del - posix timer_del interface | 454 | * alarm_timer_del - posix timer_del interface |
453 | * @timr: k_itimer pointer to be deleted | 455 | * @timr: k_itimer pointer to be deleted |
454 | * | 456 | * |
455 | * Cancels any programmed alarms for the given timer. | 457 | * Cancels any programmed alarms for the given timer. |
456 | */ | 458 | */ |
457 | static int alarm_timer_del(struct k_itimer *timr) | 459 | static int alarm_timer_del(struct k_itimer *timr) |
458 | { | 460 | { |
459 | if (!rtcdev) | 461 | if (!rtcdev) |
460 | return -ENOTSUPP; | 462 | return -ENOTSUPP; |
461 | 463 | ||
462 | alarm_cancel(&timr->it.alarmtimer); | 464 | alarm_cancel(&timr->it.alarmtimer); |
463 | return 0; | 465 | return 0; |
464 | } | 466 | } |
465 | 467 | ||
466 | /** | 468 | /** |
467 | * alarm_timer_set - posix timer_set interface | 469 | * alarm_timer_set - posix timer_set interface |
468 | * @timr: k_itimer pointer to be deleted | 470 | * @timr: k_itimer pointer to be deleted |
469 | * @flags: timer flags | 471 | * @flags: timer flags |
470 | * @new_setting: itimerspec to be used | 472 | * @new_setting: itimerspec to be used |
471 | * @old_setting: itimerspec being replaced | 473 | * @old_setting: itimerspec being replaced |
472 | * | 474 | * |
473 | * Sets the timer to new_setting, and starts the timer. | 475 | * Sets the timer to new_setting, and starts the timer. |
474 | */ | 476 | */ |
475 | static int alarm_timer_set(struct k_itimer *timr, int flags, | 477 | static int alarm_timer_set(struct k_itimer *timr, int flags, |
476 | struct itimerspec *new_setting, | 478 | struct itimerspec *new_setting, |
477 | struct itimerspec *old_setting) | 479 | struct itimerspec *old_setting) |
478 | { | 480 | { |
479 | if (!rtcdev) | 481 | if (!rtcdev) |
480 | return -ENOTSUPP; | 482 | return -ENOTSUPP; |
481 | 483 | ||
482 | if (old_setting) | 484 | if (old_setting) |
483 | alarm_timer_get(timr, old_setting); | 485 | alarm_timer_get(timr, old_setting); |
484 | 486 | ||
485 | /* If the timer was already set, cancel it */ | 487 | /* If the timer was already set, cancel it */ |
486 | alarm_cancel(&timr->it.alarmtimer); | 488 | alarm_cancel(&timr->it.alarmtimer); |
487 | 489 | ||
488 | /* start the timer */ | 490 | /* start the timer */ |
489 | alarm_start(&timr->it.alarmtimer, | 491 | alarm_start(&timr->it.alarmtimer, |
490 | timespec_to_ktime(new_setting->it_value), | 492 | timespec_to_ktime(new_setting->it_value), |
491 | timespec_to_ktime(new_setting->it_interval)); | 493 | timespec_to_ktime(new_setting->it_interval)); |
492 | return 0; | 494 | return 0; |
493 | } | 495 | } |
494 | 496 | ||
495 | /** | 497 | /** |
496 | * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep | 498 | * alarmtimer_nsleep_wakeup - Wakeup function for alarm_timer_nsleep |
497 | * @alarm: ptr to alarm that fired | 499 | * @alarm: ptr to alarm that fired |
498 | * | 500 | * |
499 | * Wakes up the task that set the alarmtimer | 501 | * Wakes up the task that set the alarmtimer |
500 | */ | 502 | */ |
501 | static void alarmtimer_nsleep_wakeup(struct alarm *alarm) | 503 | static void alarmtimer_nsleep_wakeup(struct alarm *alarm) |
502 | { | 504 | { |
503 | struct task_struct *task = (struct task_struct *)alarm->data; | 505 | struct task_struct *task = (struct task_struct *)alarm->data; |
504 | 506 | ||
505 | alarm->data = NULL; | 507 | alarm->data = NULL; |
506 | if (task) | 508 | if (task) |
507 | wake_up_process(task); | 509 | wake_up_process(task); |
508 | } | 510 | } |
509 | 511 | ||
510 | /** | 512 | /** |
511 | * alarmtimer_do_nsleep - Internal alarmtimer nsleep implementation | 513 | * alarmtimer_do_nsleep - Internal alarmtimer nsleep implementation |
512 | * @alarm: ptr to alarmtimer | 514 | * @alarm: ptr to alarmtimer |
513 | * @absexp: absolute expiration time | 515 | * @absexp: absolute expiration time |
514 | * | 516 | * |
515 | * Sets the alarm timer and sleeps until it is fired or interrupted. | 517 | * Sets the alarm timer and sleeps until it is fired or interrupted. |
516 | */ | 518 | */ |
517 | static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp) | 519 | static int alarmtimer_do_nsleep(struct alarm *alarm, ktime_t absexp) |
518 | { | 520 | { |
519 | alarm->data = (void *)current; | 521 | alarm->data = (void *)current; |
520 | do { | 522 | do { |
521 | set_current_state(TASK_INTERRUPTIBLE); | 523 | set_current_state(TASK_INTERRUPTIBLE); |
522 | alarm_start(alarm, absexp, ktime_set(0, 0)); | 524 | alarm_start(alarm, absexp, ktime_set(0, 0)); |
523 | if (likely(alarm->data)) | 525 | if (likely(alarm->data)) |
524 | schedule(); | 526 | schedule(); |
525 | 527 | ||
526 | alarm_cancel(alarm); | 528 | alarm_cancel(alarm); |
527 | } while (alarm->data && !signal_pending(current)); | 529 | } while (alarm->data && !signal_pending(current)); |
528 | 530 | ||
529 | __set_current_state(TASK_RUNNING); | 531 | __set_current_state(TASK_RUNNING); |
530 | 532 | ||
531 | return (alarm->data == NULL); | 533 | return (alarm->data == NULL); |
532 | } | 534 | } |
533 | 535 | ||
534 | 536 | ||
535 | /** | 537 | /** |
536 | * update_rmtp - Update remaining timespec value | 538 | * update_rmtp - Update remaining timespec value |
537 | * @exp: expiration time | 539 | * @exp: expiration time |
538 | * @type: timer type | 540 | * @type: timer type |
539 | * @rmtp: user pointer to remaining timepsec value | 541 | * @rmtp: user pointer to remaining timepsec value |
540 | * | 542 | * |
541 | * Helper function that fills in rmtp value with time between | 543 | * Helper function that fills in rmtp value with time between |
542 | * now and the exp value | 544 | * now and the exp value |
543 | */ | 545 | */ |
544 | static int update_rmtp(ktime_t exp, enum alarmtimer_type type, | 546 | static int update_rmtp(ktime_t exp, enum alarmtimer_type type, |
545 | struct timespec __user *rmtp) | 547 | struct timespec __user *rmtp) |
546 | { | 548 | { |
547 | struct timespec rmt; | 549 | struct timespec rmt; |
548 | ktime_t rem; | 550 | ktime_t rem; |
549 | 551 | ||
550 | rem = ktime_sub(exp, alarm_bases[type].gettime()); | 552 | rem = ktime_sub(exp, alarm_bases[type].gettime()); |
551 | 553 | ||
552 | if (rem.tv64 <= 0) | 554 | if (rem.tv64 <= 0) |
553 | return 0; | 555 | return 0; |
554 | rmt = ktime_to_timespec(rem); | 556 | rmt = ktime_to_timespec(rem); |
555 | 557 | ||
556 | if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) | 558 | if (copy_to_user(rmtp, &rmt, sizeof(*rmtp))) |
557 | return -EFAULT; | 559 | return -EFAULT; |
558 | 560 | ||
559 | return 1; | 561 | return 1; |
560 | 562 | ||
561 | } | 563 | } |
562 | 564 | ||
563 | /** | 565 | /** |
564 | * alarm_timer_nsleep_restart - restartblock alarmtimer nsleep | 566 | * alarm_timer_nsleep_restart - restartblock alarmtimer nsleep |
565 | * @restart: ptr to restart block | 567 | * @restart: ptr to restart block |
566 | * | 568 | * |
567 | * Handles restarted clock_nanosleep calls | 569 | * Handles restarted clock_nanosleep calls |
568 | */ | 570 | */ |
569 | static long __sched alarm_timer_nsleep_restart(struct restart_block *restart) | 571 | static long __sched alarm_timer_nsleep_restart(struct restart_block *restart) |
570 | { | 572 | { |
571 | enum alarmtimer_type type = restart->nanosleep.clockid; | 573 | enum alarmtimer_type type = restart->nanosleep.clockid; |
572 | ktime_t exp; | 574 | ktime_t exp; |
573 | struct timespec __user *rmtp; | 575 | struct timespec __user *rmtp; |
574 | struct alarm alarm; | 576 | struct alarm alarm; |
575 | int ret = 0; | 577 | int ret = 0; |
576 | 578 | ||
577 | exp.tv64 = restart->nanosleep.expires; | 579 | exp.tv64 = restart->nanosleep.expires; |
578 | alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); | 580 | alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); |
579 | 581 | ||
580 | if (alarmtimer_do_nsleep(&alarm, exp)) | 582 | if (alarmtimer_do_nsleep(&alarm, exp)) |
581 | goto out; | 583 | goto out; |
582 | 584 | ||
583 | if (freezing(current)) | 585 | if (freezing(current)) |
584 | alarmtimer_freezerset(exp, type); | 586 | alarmtimer_freezerset(exp, type); |
585 | 587 | ||
586 | rmtp = restart->nanosleep.rmtp; | 588 | rmtp = restart->nanosleep.rmtp; |
587 | if (rmtp) { | 589 | if (rmtp) { |
588 | ret = update_rmtp(exp, type, rmtp); | 590 | ret = update_rmtp(exp, type, rmtp); |
589 | if (ret <= 0) | 591 | if (ret <= 0) |
590 | goto out; | 592 | goto out; |
591 | } | 593 | } |
592 | 594 | ||
593 | 595 | ||
594 | /* The other values in restart are already filled in */ | 596 | /* The other values in restart are already filled in */ |
595 | ret = -ERESTART_RESTARTBLOCK; | 597 | ret = -ERESTART_RESTARTBLOCK; |
596 | out: | 598 | out: |
597 | return ret; | 599 | return ret; |
598 | } | 600 | } |
599 | 601 | ||
600 | /** | 602 | /** |
601 | * alarm_timer_nsleep - alarmtimer nanosleep | 603 | * alarm_timer_nsleep - alarmtimer nanosleep |
602 | * @which_clock: clockid | 604 | * @which_clock: clockid |
603 | * @flags: determins abstime or relative | 605 | * @flags: determins abstime or relative |
604 | * @tsreq: requested sleep time (abs or rel) | 606 | * @tsreq: requested sleep time (abs or rel) |
605 | * @rmtp: remaining sleep time saved | 607 | * @rmtp: remaining sleep time saved |
606 | * | 608 | * |
607 | * Handles clock_nanosleep calls against _ALARM clockids | 609 | * Handles clock_nanosleep calls against _ALARM clockids |
608 | */ | 610 | */ |
609 | static int alarm_timer_nsleep(const clockid_t which_clock, int flags, | 611 | static int alarm_timer_nsleep(const clockid_t which_clock, int flags, |
610 | struct timespec *tsreq, struct timespec __user *rmtp) | 612 | struct timespec *tsreq, struct timespec __user *rmtp) |
611 | { | 613 | { |
612 | enum alarmtimer_type type = clock2alarm(which_clock); | 614 | enum alarmtimer_type type = clock2alarm(which_clock); |
613 | struct alarm alarm; | 615 | struct alarm alarm; |
614 | ktime_t exp; | 616 | ktime_t exp; |
615 | int ret = 0; | 617 | int ret = 0; |
616 | struct restart_block *restart; | 618 | struct restart_block *restart; |
617 | 619 | ||
618 | if (!alarmtimer_get_rtcdev()) | 620 | if (!alarmtimer_get_rtcdev()) |
619 | return -ENOTSUPP; | 621 | return -ENOTSUPP; |
620 | 622 | ||
621 | if (!capable(CAP_WAKE_ALARM)) | 623 | if (!capable(CAP_WAKE_ALARM)) |
622 | return -EPERM; | 624 | return -EPERM; |
623 | 625 | ||
624 | alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); | 626 | alarm_init(&alarm, type, alarmtimer_nsleep_wakeup); |
625 | 627 | ||
626 | exp = timespec_to_ktime(*tsreq); | 628 | exp = timespec_to_ktime(*tsreq); |
627 | /* Convert (if necessary) to absolute time */ | 629 | /* Convert (if necessary) to absolute time */ |
628 | if (flags != TIMER_ABSTIME) { | 630 | if (flags != TIMER_ABSTIME) { |
629 | ktime_t now = alarm_bases[type].gettime(); | 631 | ktime_t now = alarm_bases[type].gettime(); |
630 | exp = ktime_add(now, exp); | 632 | exp = ktime_add(now, exp); |
631 | } | 633 | } |
632 | 634 | ||
633 | if (alarmtimer_do_nsleep(&alarm, exp)) | 635 | if (alarmtimer_do_nsleep(&alarm, exp)) |
634 | goto out; | 636 | goto out; |
635 | 637 | ||
636 | if (freezing(current)) | 638 | if (freezing(current)) |
637 | alarmtimer_freezerset(exp, type); | 639 | alarmtimer_freezerset(exp, type); |
638 | 640 | ||
639 | /* abs timers don't set remaining time or restart */ | 641 | /* abs timers don't set remaining time or restart */ |
640 | if (flags == TIMER_ABSTIME) { | 642 | if (flags == TIMER_ABSTIME) { |
641 | ret = -ERESTARTNOHAND; | 643 | ret = -ERESTARTNOHAND; |
642 | goto out; | 644 | goto out; |
643 | } | 645 | } |
644 | 646 | ||
645 | if (rmtp) { | 647 | if (rmtp) { |
646 | ret = update_rmtp(exp, type, rmtp); | 648 | ret = update_rmtp(exp, type, rmtp); |
647 | if (ret <= 0) | 649 | if (ret <= 0) |
648 | goto out; | 650 | goto out; |
649 | } | 651 | } |
650 | 652 | ||
651 | restart = ¤t_thread_info()->restart_block; | 653 | restart = ¤t_thread_info()->restart_block; |
652 | restart->fn = alarm_timer_nsleep_restart; | 654 | restart->fn = alarm_timer_nsleep_restart; |
653 | restart->nanosleep.clockid = type; | 655 | restart->nanosleep.clockid = type; |
654 | restart->nanosleep.expires = exp.tv64; | 656 | restart->nanosleep.expires = exp.tv64; |
655 | restart->nanosleep.rmtp = rmtp; | 657 | restart->nanosleep.rmtp = rmtp; |
656 | ret = -ERESTART_RESTARTBLOCK; | 658 | ret = -ERESTART_RESTARTBLOCK; |
657 | 659 | ||
658 | out: | 660 | out: |
659 | return ret; | 661 | return ret; |
660 | } | 662 | } |
661 | 663 | ||
662 | 664 | ||
663 | /* Suspend hook structures */ | 665 | /* Suspend hook structures */ |
664 | static const struct dev_pm_ops alarmtimer_pm_ops = { | 666 | static const struct dev_pm_ops alarmtimer_pm_ops = { |
665 | .suspend = alarmtimer_suspend, | 667 | .suspend = alarmtimer_suspend, |
666 | }; | 668 | }; |
667 | 669 | ||
668 | static struct platform_driver alarmtimer_driver = { | 670 | static struct platform_driver alarmtimer_driver = { |
669 | .driver = { | 671 | .driver = { |
670 | .name = "alarmtimer", | 672 | .name = "alarmtimer", |
671 | .pm = &alarmtimer_pm_ops, | 673 | .pm = &alarmtimer_pm_ops, |
672 | } | 674 | } |
673 | }; | 675 | }; |
674 | 676 | ||
675 | /** | 677 | /** |
676 | * alarmtimer_init - Initialize alarm timer code | 678 | * alarmtimer_init - Initialize alarm timer code |
677 | * | 679 | * |
678 | * This function initializes the alarm bases and registers | 680 | * This function initializes the alarm bases and registers |
679 | * the posix clock ids. | 681 | * the posix clock ids. |
680 | */ | 682 | */ |
681 | static int __init alarmtimer_init(void) | 683 | static int __init alarmtimer_init(void) |
682 | { | 684 | { |
683 | int error = 0; | 685 | int error = 0; |
684 | int i; | 686 | int i; |
685 | struct k_clock alarm_clock = { | 687 | struct k_clock alarm_clock = { |
686 | .clock_getres = alarm_clock_getres, | 688 | .clock_getres = alarm_clock_getres, |
687 | .clock_get = alarm_clock_get, | 689 | .clock_get = alarm_clock_get, |
688 | .timer_create = alarm_timer_create, | 690 | .timer_create = alarm_timer_create, |
689 | .timer_set = alarm_timer_set, | 691 | .timer_set = alarm_timer_set, |
690 | .timer_del = alarm_timer_del, | 692 | .timer_del = alarm_timer_del, |
691 | .timer_get = alarm_timer_get, | 693 | .timer_get = alarm_timer_get, |
692 | .nsleep = alarm_timer_nsleep, | 694 | .nsleep = alarm_timer_nsleep, |
693 | }; | 695 | }; |
694 | 696 | ||
695 | posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock); | 697 | posix_timers_register_clock(CLOCK_REALTIME_ALARM, &alarm_clock); |
696 | posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock); | 698 | posix_timers_register_clock(CLOCK_BOOTTIME_ALARM, &alarm_clock); |
697 | 699 | ||
698 | /* Initialize alarm bases */ | 700 | /* Initialize alarm bases */ |
699 | alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME; | 701 | alarm_bases[ALARM_REALTIME].base_clockid = CLOCK_REALTIME; |
700 | alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real; | 702 | alarm_bases[ALARM_REALTIME].gettime = &ktime_get_real; |
701 | alarm_bases[ALARM_BOOTTIME].base_clockid = CLOCK_BOOTTIME; | 703 | alarm_bases[ALARM_BOOTTIME].base_clockid = CLOCK_BOOTTIME; |
702 | alarm_bases[ALARM_BOOTTIME].gettime = &ktime_get_boottime; | 704 | alarm_bases[ALARM_BOOTTIME].gettime = &ktime_get_boottime; |
703 | for (i = 0; i < ALARM_NUMTYPE; i++) { | 705 | for (i = 0; i < ALARM_NUMTYPE; i++) { |
704 | timerqueue_init_head(&alarm_bases[i].timerqueue); | 706 | timerqueue_init_head(&alarm_bases[i].timerqueue); |
705 | spin_lock_init(&alarm_bases[i].lock); | 707 | spin_lock_init(&alarm_bases[i].lock); |
706 | hrtimer_init(&alarm_bases[i].timer, | 708 | hrtimer_init(&alarm_bases[i].timer, |
707 | alarm_bases[i].base_clockid, | 709 | alarm_bases[i].base_clockid, |
708 | HRTIMER_MODE_ABS); | 710 | HRTIMER_MODE_ABS); |
709 | alarm_bases[i].timer.function = alarmtimer_fired; | 711 | alarm_bases[i].timer.function = alarmtimer_fired; |
710 | } | 712 | } |
711 | error = platform_driver_register(&alarmtimer_driver); | 713 | error = platform_driver_register(&alarmtimer_driver); |
712 | platform_device_register_simple("alarmtimer", -1, NULL, 0); | 714 | platform_device_register_simple("alarmtimer", -1, NULL, 0); |
713 | 715 | ||
714 | return error; | 716 | return error; |
715 | } | 717 | } |
716 | device_initcall(alarmtimer_init); | 718 | device_initcall(alarmtimer_init); |
717 | 719 | ||
718 | 720 |