at v3.11-rc4 443 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 if (rv) 268 return rv; 269 270 switch (ANDROID_ALARM_BASE_CMD(cmd)) { 271 case ANDROID_ALARM_GET_TIME(0): 272 if (copy_to_user((void __user *)arg, &ts, sizeof(ts))) 273 return -EFAULT; 274 break; 275 } 276 277 return 0; 278} 279#ifdef CONFIG_COMPAT 280static long alarm_compat_ioctl(struct file *file, unsigned int cmd, 281 unsigned long arg) 282{ 283 284 struct timespec ts; 285 int rv; 286 287 switch (ANDROID_ALARM_BASE_CMD(cmd)) { 288 case ANDROID_ALARM_SET_AND_WAIT_COMPAT(0): 289 case ANDROID_ALARM_SET_COMPAT(0): 290 case ANDROID_ALARM_SET_RTC_COMPAT: 291 if (compat_get_timespec(&ts, (void __user *)arg)) 292 return -EFAULT; 293 /* fall through */ 294 case ANDROID_ALARM_GET_TIME_COMPAT(0): 295 cmd = ANDROID_ALARM_COMPAT_TO_NORM(cmd); 296 break; 297 } 298 299 rv = alarm_do_ioctl(file, cmd, &ts); 300 if (rv) 301 return rv; 302 303 switch (ANDROID_ALARM_BASE_CMD(cmd)) { 304 case ANDROID_ALARM_GET_TIME(0): /* NOTE: we modified cmd above */ 305 if (compat_put_timespec(&ts, (void __user *)arg)) 306 return -EFAULT; 307 break; 308 } 309 310 return 0; 311} 312#endif 313 314static int alarm_open(struct inode *inode, struct file *file) 315{ 316 file->private_data = NULL; 317 return 0; 318} 319 320static int alarm_release(struct inode *inode, struct file *file) 321{ 322 int i; 323 unsigned long flags; 324 325 spin_lock_irqsave(&alarm_slock, flags); 326 if (file->private_data) { 327 for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { 328 uint32_t alarm_type_mask = 1U << i; 329 if (alarm_enabled & alarm_type_mask) { 330 alarm_dbg(INFO, 331 "%s: clear alarm, pending %d\n", 332 __func__, 333 !!(alarm_pending & alarm_type_mask)); 334 alarm_enabled &= ~alarm_type_mask; 335 } 336 spin_unlock_irqrestore(&alarm_slock, flags); 337 devalarm_cancel(&alarms[i]); 338 spin_lock_irqsave(&alarm_slock, flags); 339 } 340 if (alarm_pending | wait_pending) { 341 if (alarm_pending) 342 alarm_dbg(INFO, "%s: clear pending alarms %x\n", 343 __func__, alarm_pending); 344 __pm_relax(&alarm_wake_lock); 345 wait_pending = 0; 346 alarm_pending = 0; 347 } 348 alarm_opened = 0; 349 } 350 spin_unlock_irqrestore(&alarm_slock, flags); 351 return 0; 352} 353 354static void devalarm_triggered(struct devalarm *alarm) 355{ 356 unsigned long flags; 357 uint32_t alarm_type_mask = 1U << alarm->type; 358 359 alarm_dbg(INT, "%s: type %d\n", __func__, alarm->type); 360 spin_lock_irqsave(&alarm_slock, flags); 361 if (alarm_enabled & alarm_type_mask) { 362 __pm_wakeup_event(&alarm_wake_lock, 5000); /* 5secs */ 363 alarm_enabled &= ~alarm_type_mask; 364 alarm_pending |= alarm_type_mask; 365 wake_up(&alarm_wait_queue); 366 } 367 spin_unlock_irqrestore(&alarm_slock, flags); 368} 369 370 371static enum hrtimer_restart devalarm_hrthandler(struct hrtimer *hrt) 372{ 373 struct devalarm *devalrm = container_of(hrt, struct devalarm, u.hrt); 374 375 devalarm_triggered(devalrm); 376 return HRTIMER_NORESTART; 377} 378 379static enum alarmtimer_restart devalarm_alarmhandler(struct alarm *alrm, 380 ktime_t now) 381{ 382 struct devalarm *devalrm = container_of(alrm, struct devalarm, u.alrm); 383 384 devalarm_triggered(devalrm); 385 return ALARMTIMER_NORESTART; 386} 387 388 389static const struct file_operations alarm_fops = { 390 .owner = THIS_MODULE, 391 .unlocked_ioctl = alarm_ioctl, 392 .open = alarm_open, 393 .release = alarm_release, 394#ifdef CONFIG_COMPAT 395 .compat_ioctl = alarm_compat_ioctl, 396#endif 397}; 398 399static struct miscdevice alarm_device = { 400 .minor = MISC_DYNAMIC_MINOR, 401 .name = "alarm", 402 .fops = &alarm_fops, 403}; 404 405static int __init alarm_dev_init(void) 406{ 407 int err; 408 int i; 409 410 err = misc_register(&alarm_device); 411 if (err) 412 return err; 413 414 alarm_init(&alarms[ANDROID_ALARM_RTC_WAKEUP].u.alrm, 415 ALARM_REALTIME, devalarm_alarmhandler); 416 hrtimer_init(&alarms[ANDROID_ALARM_RTC].u.hrt, 417 CLOCK_REALTIME, HRTIMER_MODE_ABS); 418 alarm_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].u.alrm, 419 ALARM_BOOTTIME, devalarm_alarmhandler); 420 hrtimer_init(&alarms[ANDROID_ALARM_ELAPSED_REALTIME].u.hrt, 421 CLOCK_BOOTTIME, HRTIMER_MODE_ABS); 422 hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].u.hrt, 423 CLOCK_MONOTONIC, HRTIMER_MODE_ABS); 424 425 for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { 426 alarms[i].type = i; 427 if (!is_wakeup(i)) 428 alarms[i].u.hrt.function = devalarm_hrthandler; 429 } 430 431 wakeup_source_init(&alarm_wake_lock, "alarm"); 432 return 0; 433} 434 435static void __exit alarm_dev_exit(void) 436{ 437 misc_deregister(&alarm_device); 438 wakeup_source_trash(&alarm_wake_lock); 439} 440 441module_init(alarm_dev_init); 442module_exit(alarm_dev_exit); 443