diff options
author | John Stultz <john.stultz@linaro.org> | 2012-04-20 15:31:46 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-04-20 17:59:03 -0400 |
commit | b8793260980b0fc356af3bf11abea82650b0d595 (patch) | |
tree | 6a9664ffa95b7c3c93bb3ed89e94ee945b3108d5 | |
parent | 57c498fa5df05e4bd410c101795368439fec7b4e (diff) |
staging: android-alarm: Rework alarm-dev.c to use upstreamed alarmtimers
This reworks the alarm-dev.c to use the upstreamed alarmtimers
interface.
CC: Colin Cross <ccross@android.com>
CC: Thomas Gleixner <tglx@linutronix.de>
CC: Android Kernel Team <kernel-team@android.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/staging/android/alarm-dev.c | 108 |
1 files changed, 98 insertions, 10 deletions
diff --git a/drivers/staging/android/alarm-dev.c b/drivers/staging/android/alarm-dev.c index 3840ca22d835..04075b309b87 100644 --- a/drivers/staging/android/alarm-dev.c +++ b/drivers/staging/android/alarm-dev.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
24 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
25 | #include <linux/alarmtimer.h> | ||
25 | #include "android_alarm.h" | 26 | #include "android_alarm.h" |
26 | 27 | ||
27 | /* XXX - Hack out wakelocks, while they are out of tree */ | 28 | /* XXX - Hack out wakelocks, while they are out of tree */ |
@@ -66,7 +67,53 @@ static uint32_t alarm_pending; | |||
66 | static uint32_t alarm_enabled; | 67 | static uint32_t alarm_enabled; |
67 | static uint32_t wait_pending; | 68 | static uint32_t wait_pending; |
68 | 69 | ||
69 | static struct android_alarm alarms[ANDROID_ALARM_TYPE_COUNT]; | 70 | struct devalarm { |
71 | union { | ||
72 | struct hrtimer hrt; | ||
73 | struct alarm alrm; | ||
74 | } u; | ||
75 | enum android_alarm_type type; | ||
76 | }; | ||
77 | |||
78 | static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT]; | ||
79 | |||
80 | |||
81 | static int is_wakeup(enum android_alarm_type type) | ||
82 | { | ||
83 | if (type == ANDROID_ALARM_RTC_WAKEUP || | ||
84 | type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP) | ||
85 | return 1; | ||
86 | return 0; | ||
87 | } | ||
88 | |||
89 | |||
90 | static void devalarm_start(struct devalarm *alrm, ktime_t exp) | ||
91 | { | ||
92 | if (is_wakeup(alrm->type)) | ||
93 | alarm_start(&alrm->u.alrm, exp); | ||
94 | else | ||
95 | hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS); | ||
96 | } | ||
97 | |||
98 | |||
99 | static int devalarm_try_to_cancel(struct devalarm *alrm) | ||
100 | { | ||
101 | int ret; | ||
102 | if (is_wakeup(alrm->type)) | ||
103 | ret = alarm_try_to_cancel(&alrm->u.alrm); | ||
104 | else | ||
105 | ret = hrtimer_try_to_cancel(&alrm->u.hrt); | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | static void devalarm_cancel(struct devalarm *alrm) | ||
110 | { | ||
111 | if (is_wakeup(alrm->type)) | ||
112 | alarm_cancel(&alrm->u.alrm); | ||
113 | else | ||
114 | hrtimer_cancel(&alrm->u.hrt); | ||
115 | } | ||
116 | |||
70 | 117 | ||
71 | static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 118 | static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
72 | { | 119 | { |
@@ -75,6 +122,8 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
75 | struct timespec new_alarm_time; | 122 | struct timespec new_alarm_time; |
76 | struct timespec new_rtc_time; | 123 | struct timespec new_rtc_time; |
77 | struct timespec tmp_time; | 124 | struct timespec tmp_time; |
125 | struct rtc_time new_rtc_tm; | ||
126 | struct rtc_device *rtc_dev; | ||
78 | enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); | 127 | enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); |
79 | uint32_t alarm_type_mask = 1U << alarm_type; | 128 | uint32_t alarm_type_mask = 1U << alarm_type; |
80 | 129 | ||
@@ -101,7 +150,7 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
101 | case ANDROID_ALARM_CLEAR(0): | 150 | case ANDROID_ALARM_CLEAR(0): |
102 | spin_lock_irqsave(&alarm_slock, flags); | 151 | spin_lock_irqsave(&alarm_slock, flags); |
103 | pr_alarm(IO, "alarm %d clear\n", alarm_type); | 152 | pr_alarm(IO, "alarm %d clear\n", alarm_type); |
104 | android_alarm_try_to_cancel(&alarms[alarm_type]); | 153 | devalarm_try_to_cancel(&alarms[alarm_type]); |
105 | if (alarm_pending) { | 154 | if (alarm_pending) { |
106 | alarm_pending &= ~alarm_type_mask; | 155 | alarm_pending &= ~alarm_type_mask; |
107 | if (!alarm_pending && !wait_pending) | 156 | if (!alarm_pending && !wait_pending) |
@@ -132,8 +181,7 @@ from_old_alarm_set: | |||
132 | pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type, | 181 | pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type, |
133 | new_alarm_time.tv_sec, new_alarm_time.tv_nsec); | 182 | new_alarm_time.tv_sec, new_alarm_time.tv_nsec); |
134 | alarm_enabled |= alarm_type_mask; | 183 | alarm_enabled |= alarm_type_mask; |
135 | android_alarm_start_range(&alarms[alarm_type], | 184 | devalarm_start(&alarms[alarm_type], |
136 | timespec_to_ktime(new_alarm_time), | ||
137 | timespec_to_ktime(new_alarm_time)); | 185 | timespec_to_ktime(new_alarm_time)); |
138 | spin_unlock_irqrestore(&alarm_slock, flags); | 186 | spin_unlock_irqrestore(&alarm_slock, flags); |
139 | if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0) | 187 | if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0) |
@@ -163,7 +211,13 @@ from_old_alarm_set: | |||
163 | rv = -EFAULT; | 211 | rv = -EFAULT; |
164 | goto err1; | 212 | goto err1; |
165 | } | 213 | } |
166 | rv = android_alarm_set_rtc(new_rtc_time); | 214 | rtc_time_to_tm(new_rtc_time.tv_sec, &new_rtc_tm); |
215 | rtc_dev = alarmtimer_get_rtcdev(); | ||
216 | rv = do_settimeofday(&new_rtc_time); | ||
217 | if (rv < 0) | ||
218 | goto err1; | ||
219 | if (rtc_dev) | ||
220 | rv = rtc_set_time(rtc_dev, &new_rtc_tm); | ||
167 | spin_lock_irqsave(&alarm_slock, flags); | 221 | spin_lock_irqsave(&alarm_slock, flags); |
168 | alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; | 222 | alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; |
169 | wake_up(&alarm_wait_queue); | 223 | wake_up(&alarm_wait_queue); |
@@ -223,7 +277,7 @@ static int alarm_release(struct inode *inode, struct file *file) | |||
223 | alarm_enabled &= ~alarm_type_mask; | 277 | alarm_enabled &= ~alarm_type_mask; |
224 | } | 278 | } |
225 | spin_unlock_irqrestore(&alarm_slock, flags); | 279 | spin_unlock_irqrestore(&alarm_slock, flags); |
226 | android_alarm_cancel(&alarms[i]); | 280 | devalarm_cancel(&alarms[i]); |
227 | spin_lock_irqsave(&alarm_slock, flags); | 281 | spin_lock_irqsave(&alarm_slock, flags); |
228 | } | 282 | } |
229 | if (alarm_pending | wait_pending) { | 283 | if (alarm_pending | wait_pending) { |
@@ -240,12 +294,12 @@ static int alarm_release(struct inode *inode, struct file *file) | |||
240 | return 0; | 294 | return 0; |
241 | } | 295 | } |
242 | 296 | ||
243 | static void alarm_triggered(struct android_alarm *alarm) | 297 | static void devalarm_triggered(struct devalarm *alarm) |
244 | { | 298 | { |
245 | unsigned long flags; | 299 | unsigned long flags; |
246 | uint32_t alarm_type_mask = 1U << alarm->type; | 300 | uint32_t alarm_type_mask = 1U << alarm->type; |
247 | 301 | ||
248 | pr_alarm(INT, "alarm_triggered type %d\n", alarm->type); | 302 | pr_alarm(INT, "devalarm_triggered type %d\n", alarm->type); |
249 | spin_lock_irqsave(&alarm_slock, flags); | 303 | spin_lock_irqsave(&alarm_slock, flags); |
250 | if (alarm_enabled & alarm_type_mask) { | 304 | if (alarm_enabled & alarm_type_mask) { |
251 | wake_lock_timeout(&alarm_wake_lock, 5 * HZ); | 305 | wake_lock_timeout(&alarm_wake_lock, 5 * HZ); |
@@ -256,6 +310,25 @@ static void alarm_triggered(struct android_alarm *alarm) | |||
256 | spin_unlock_irqrestore(&alarm_slock, flags); | 310 | spin_unlock_irqrestore(&alarm_slock, flags); |
257 | } | 311 | } |
258 | 312 | ||
313 | |||
314 | static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt) | ||
315 | { | ||
316 | struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt); | ||
317 | |||
318 | devalarm_triggered(devalrm); | ||
319 | return HRTIMER_NORESTART; | ||
320 | } | ||
321 | |||
322 | static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm, | ||
323 | ktime_t now) | ||
324 | { | ||
325 | struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm); | ||
326 | |||
327 | devalarm_triggered(devalrm); | ||
328 | return ALARMTIMER_NORESTART; | ||
329 | } | ||
330 | |||
331 | |||
259 | static const struct file_operations alarm_fops = { | 332 | static const struct file_operations alarm_fops = { |
260 | .owner = THIS_MODULE, | 333 | .owner = THIS_MODULE, |
261 | .unlocked_ioctl = alarm_ioctl, | 334 | .unlocked_ioctl = alarm_ioctl, |
@@ -278,8 +351,23 @@ static int __init alarm_dev_init(void) | |||
278 | if (err) | 351 | if (err) |
279 | return err; | 352 | return err; |
280 | 353 | ||
281 | for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) | 354 | alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm, |
282 | android_alarm_init(&alarms[i], i, alarm_triggered); | 355 | ALARM_REALTIME, devalarm_alarmhandler); |
356 | hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt, | ||
357 | CLOCK_REALTIME, HRTIMER_MODE_ABS); | ||
358 | alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm, | ||
359 | ALARM_BOOTTIME, devalarm_alarmhandler); | ||
360 | hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt, | ||
361 | CLOCK_BOOTTIME, HRTIMER_MODE_ABS); | ||
362 | hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt, | ||
363 | CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | ||
364 | |||
365 | for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { | ||
366 | alarms[i].type = i; | ||
367 | if (!is_wakeup(i)) | ||
368 | alarms[i].u.hrt.function = devalarm_hrthandler; | ||
369 | } | ||
370 | |||
283 | wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm"); | 371 | wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm"); |
284 | 372 | ||
285 | return 0; | 373 | return 0; |