at v3.9-rc6 439 lines 11 kB view raw
1/* drivers/rtc/alarm-dev.c 2 * 3 * Copyright (C) 2007-2009 Google, Inc. 4 * 5 * This software is licensed under the terms of the GNU General Public 6 * License version 2, as published by the Free Software Foundation, and 7 * may be copied, distributed, and modified under those terms. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 */ 15 16#include <linux/time.h> 17#include <linux/module.h> 18#include <linux/device.h> 19#include <linux/miscdevice.h> 20#include <linux/fs.h> 21#include <linux/platform_device.h> 22#include <linux/sched.h> 23#include <linux/spinlock.h> 24#include <linux/uaccess.h> 25#include <linux/alarmtimer.h> 26#include "android_alarm.h" 27 28#define ANDROID_ALARM_PRINT_INFO (1U << 0) 29#define ANDROID_ALARM_PRINT_IO (1U << 1) 30#define ANDROID_ALARM_PRINT_INT (1U << 2) 31 32static int debug_mask = ANDROID_ALARM_PRINT_INFO; 33module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); 34 35#define alarm_dbg(debug_level_mask, fmt, ...) \ 36do { \ 37 if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) \ 38 pr_info(fmt, ##__VA_ARGS__); \ 39} while (0) 40 41#define ANDROID_ALARM_WAKEUP_MASK ( \ 42 ANDROID_ALARM_RTC_WAKEUP_MASK | \ 43 ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) 44 45static int alarm_opened; 46static DEFINE_SPINLOCK(alarm_slock); 47static struct wakeup_source alarm_wake_lock; 48static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue); 49static uint32_t alarm_pending; 50static uint32_t alarm_enabled; 51static uint32_t wait_pending; 52 53struct devalarm { 54 union { 55 struct hrtimer hrt; 56 struct alarm alrm; 57 } u; 58 enum android_alarm_type type; 59}; 60 61static struct devalarm alarms[ANDROID_ALARM_TYPE_COUNT]; 62 63 64static int is_wakeup(enum android_alarm_type type) 65{ 66 return (type == ANDROID_ALARM_RTC_WAKEUP || 67 type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP); 68} 69 70 71static void devalarm_start(struct devalarm *alrm, ktime_t exp) 72{ 73 if (is_wakeup(alrm->type)) 74 alarm_start(&alrm->u.alrm, exp); 75 else 76 hrtimer_start(&alrm->u.hrt, exp, HRTIMER_MODE_ABS); 77} 78 79 80static int devalarm_try_to_cancel(struct devalarm *alrm) 81{ 82 if (is_wakeup(alrm->type)) 83 return alarm_try_to_cancel(&alrm->u.alrm); 84 return hrtimer_try_to_cancel(&alrm->u.hrt); 85} 86 87static void devalarm_cancel(struct devalarm *alrm) 88{ 89 if (is_wakeup(alrm->type)) 90 alarm_cancel(&alrm->u.alrm); 91 else 92 hrtimer_cancel(&alrm->u.hrt); 93} 94 95static void alarm_clear(enum android_alarm_type alarm_type) 96{ 97 uint32_t alarm_type_mask = 1U << alarm_type; 98 unsigned long flags; 99 100 spin_lock_irqsave(&alarm_slock, flags); 101 alarm_dbg(IO, "alarm %d clear\n", alarm_type); 102 devalarm_try_to_cancel(&alarms[alarm_type]); 103 if (alarm_pending) { 104 alarm_pending &= ~alarm_type_mask; 105 if (!alarm_pending && !wait_pending) 106 __pm_relax(&alarm_wake_lock); 107 } 108 alarm_enabled &= ~alarm_type_mask; 109 spin_unlock_irqrestore(&alarm_slock, flags); 110 111} 112 113static void alarm_set(enum android_alarm_type alarm_type, 114 struct timespec *ts) 115{ 116 uint32_t alarm_type_mask = 1U << alarm_type; 117 unsigned long flags; 118 119 spin_lock_irqsave(&alarm_slock, flags); 120 alarm_dbg(IO, "alarm %d set %ld.%09ld\n", 121 alarm_type, ts->tv_sec, ts->tv_nsec); 122 alarm_enabled |= alarm_type_mask; 123 devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts)); 124 spin_unlock_irqrestore(&alarm_slock, flags); 125} 126 127static int alarm_wait(void) 128{ 129 unsigned long flags; 130 int rv = 0; 131 132 spin_lock_irqsave(&alarm_slock, flags); 133 alarm_dbg(IO, "alarm wait\n"); 134 if (!alarm_pending && wait_pending) { 135 __pm_relax(&alarm_wake_lock); 136 wait_pending = 0; 137 } 138 spin_unlock_irqrestore(&alarm_slock, flags); 139 140 rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); 141 if (rv) 142 return rv; 143 144 spin_lock_irqsave(&alarm_slock, flags); 145 rv = alarm_pending; 146 wait_pending = 1; 147 alarm_pending = 0; 148 spin_unlock_irqrestore(&alarm_slock, flags); 149 150 return rv; 151} 152 153static int alarm_set_rtc(struct timespec *ts) 154{ 155 struct rtc_time new_rtc_tm; 156 struct rtc_device *rtc_dev; 157 unsigned long flags; 158 int rv = 0; 159 160 rtc_time_to_tm(ts->tv_sec, &new_rtc_tm); 161 rtc_dev = alarmtimer_get_rtcdev(); 162 rv = do_settimeofday(ts); 163 if (rv < 0) 164 return rv; 165 if (rtc_dev) 166 rv = rtc_set_time(rtc_dev, &new_rtc_tm); 167 168 spin_lock_irqsave(&alarm_slock, flags); 169 alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; 170 wake_up(&alarm_wait_queue); 171 spin_unlock_irqrestore(&alarm_slock, flags); 172 173 return rv; 174} 175 176static int alarm_get_time(enum android_alarm_type alarm_type, 177 struct timespec *ts) 178{ 179 int rv = 0; 180 181 switch (alarm_type) { 182 case ANDROID_ALARM_RTC_WAKEUP: 183 case ANDROID_ALARM_RTC: 184 getnstimeofday(ts); 185 break; 186 case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP: 187 case ANDROID_ALARM_ELAPSED_REALTIME: 188 get_monotonic_boottime(ts); 189 break; 190 case ANDROID_ALARM_SYSTEMTIME: 191 ktime_get_ts(ts); 192 break; 193 default: 194 rv = -EINVAL; 195 } 196 return rv; 197} 198 199static long alarm_do_ioctl(struct file *file, unsigned int cmd, 200 struct timespec *ts) 201{ 202 int rv = 0; 203 unsigned long flags; 204 enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); 205 206 if (alarm_type >= ANDROID_ALARM_TYPE_COUNT) 207 return -EINVAL; 208 209 if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) { 210 if ((file->f_flags & O_ACCMODE) == O_RDONLY) 211 return -EPERM; 212 if (file->private_data == NULL && 213 cmd != ANDROID_ALARM_SET_RTC) { 214 spin_lock_irqsave(&alarm_slock, flags); 215 if (alarm_opened) { 216 spin_unlock_irqrestore(&alarm_slock, flags); 217 return -EBUSY; 218 } 219 alarm_opened = 1; 220 file->private_data = (void *)1; 221 spin_unlock_irqrestore(&alarm_slock, flags); 222 } 223 } 224 225 switch (ANDROID_ALARM_BASE_CMD(cmd)) { 226 case ANDROID_ALARM_CLEAR(0): 227 alarm_clear(alarm_type); 228 break; 229 case ANDROID_ALARM_SET(0): 230 alarm_set(alarm_type, ts); 231 break; 232 case ANDROID_ALARM_SET_AND_WAIT(0): 233 alarm_set(alarm_type, ts); 234 /* fall though */ 235 case ANDROID_ALARM_WAIT: 236 rv = alarm_wait(); 237 break; 238 case ANDROID_ALARM_SET_RTC: 239 rv = alarm_set_rtc(ts); 240 break; 241 case ANDROID_ALARM_GET_TIME(0): 242 rv = alarm_get_time(alarm_type, ts); 243 break; 244 245 default: 246 rv = -EINVAL; 247 } 248 return rv; 249} 250 251static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 252{ 253 254 struct timespec ts; 255 int rv; 256 257 switch (ANDROID_ALARM_BASE_CMD(cmd)) { 258 case ANDROID_ALARM_SET_AND_WAIT(0): 259 case ANDROID_ALARM_SET(0): 260 case ANDROID_ALARM_SET_RTC: 261 if (copy_from_user(&ts, (void __user *)arg, sizeof(ts))) 262 return -EFAULT; 263 break; 264 } 265 266 rv = alarm_do_ioctl(file, cmd, &ts); 267 268 switch (ANDROID_ALARM_BASE_CMD(cmd)) { 269 case ANDROID_ALARM_GET_TIME(0): 270 if (copy_to_user((void __user *)arg, &ts, sizeof(ts))) 271 return -EFAULT; 272 break; 273 } 274 275 return rv; 276} 277#ifdef CONFIG_COMPAT 278static long alarm_compat_ioctl(struct file *file, unsigned int cmd, 279 unsigned long arg) 280{ 281 282 struct timespec ts; 283 int rv; 284 285 switch (ANDROID_ALARM_BASE_CMD(cmd)) { 286 case ANDROID_ALARM_SET_AND_WAIT_COMPAT(0): 287 case ANDROID_ALARM_SET_COMPAT(0): 288 case ANDROID_ALARM_SET_RTC_COMPAT: 289 if (compat_get_timespec(&ts, (void __user *)arg)) 290 return -EFAULT; 291 /* fall through */ 292 case ANDROID_ALARM_GET_TIME_COMPAT(0): 293 cmd = ANDROID_ALARM_COMPAT_TO_NORM(cmd); 294 break; 295 } 296 297 rv = alarm_do_ioctl(file, cmd, &ts); 298 299 switch (ANDROID_ALARM_BASE_CMD(cmd)) { 300 case ANDROID_ALARM_GET_TIME(0): /* NOTE: we modified cmd above */ 301 if (compat_put_timespec(&ts, (void __user *)arg)) 302 return -EFAULT; 303 break; 304 } 305 306 return rv; 307} 308#endif 309 310static int alarm_open(struct inode *inode, struct file *file) 311{ 312 file->private_data = NULL; 313 return 0; 314} 315 316static int alarm_release(struct inode *inode, struct file *file) 317{ 318 int i; 319 unsigned long flags; 320 321 spin_lock_irqsave(&alarm_slock, flags); 322 if (file->private_data) { 323 for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { 324 uint32_t alarm_type_mask = 1U << i; 325 if (alarm_enabled & alarm_type_mask) { 326 alarm_dbg(INFO, 327 "%s: clear alarm, pending %d\n", 328 __func__, 329 !!(alarm_pending & alarm_type_mask)); 330 alarm_enabled &= ~alarm_type_mask; 331 } 332 spin_unlock_irqrestore(&alarm_slock, flags); 333 devalarm_cancel(&alarms[i]); 334 spin_lock_irqsave(&alarm_slock, flags); 335 } 336 if (alarm_pending | wait_pending) { 337 if (alarm_pending) 338 alarm_dbg(INFO, "%s: clear pending alarms %x\n", 339 __func__, alarm_pending); 340 __pm_relax(&alarm_wake_lock); 341 wait_pending = 0; 342 alarm_pending = 0; 343 } 344 alarm_opened = 0; 345 } 346 spin_unlock_irqrestore(&alarm_slock, flags); 347 return 0; 348} 349 350static void devalarm_triggered(struct devalarm *alarm) 351{ 352 unsigned long flags; 353 uint32_t alarm_type_mask = 1U << alarm->type; 354 355 alarm_dbg(INT, "%s: type %d\n", __func__, alarm->type); 356 spin_lock_irqsave(&alarm_slock, flags); 357 if (alarm_enabled & alarm_type_mask) { 358 __pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */ 359 alarm_enabled &= ~alarm_type_mask; 360 alarm_pending |= alarm_type_mask; 361 wake_up(&alarm_wait_queue); 362 } 363 spin_unlock_irqrestore(&alarm_slock, flags); 364} 365 366 367static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt) 368{ 369 struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt); 370 371 devalarm_triggered(devalrm); 372 return HRTIMER_NORESTART; 373} 374 375static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm, 376 ktime_t now) 377{ 378 struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm); 379 380 devalarm_triggered(devalrm); 381 return ALARMTIMER_NORESTART; 382} 383 384 385static const struct file_operations alarm_fops = { 386 .owner = THIS_MODULE, 387 .unlocked_ioctl = alarm_ioctl, 388 .open = alarm_open, 389 .release = alarm_release, 390#ifdef CONFIG_COMPAT 391 .compat_ioctl = alarm_compat_ioctl, 392#endif 393}; 394 395static struct miscdevice alarm_device = { 396 .minor = MISC_DYNAMIC_MINOR, 397 .name = "alarm", 398 .fops = &alarm_fops, 399}; 400 401static int __init alarm_dev_init(void) 402{ 403 int err; 404 int i; 405 406 err = misc_register(&alarm_device); 407 if (err) 408 return err; 409 410 alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm, 411 ALARM_REALTIME, devalarm_alarmhandler); 412 hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt, 413 CLOCK_REALTIME, HRTIMER_MODE_ABS); 414 alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm, 415 ALARM_BOOTTIME, devalarm_alarmhandler); 416 hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt, 417 CLOCK_BOOTTIME, HRTIMER_MODE_ABS); 418 hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt, 419 CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 420 421 for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { 422 alarms[i].type = i; 423 if (!is_wakeup(i)) 424 alarms[i].u.hrt.function = devalarm_hrthandler; 425 } 426 427 wakeup_source_init(&alarm_wake_lock, "alarm"); 428 return 0; 429} 430 431static void __exit alarm_dev_exit(void) 432{ 433 misc_deregister(&alarm_device); 434 wakeup_source_trash(&alarm_wake_lock); 435} 436 437module_init(alarm_dev_init); 438module_exit(alarm_dev_exit); 439