From 8487afeae955956fa4fc8525fcf95bc7ad10e7d7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=E9=BB=84=E6=B6=9B?= Date: Sat, 30 Jul 2011 22:57:59 +0800 Subject: [PATCH] Revert "rtc: alarm: Add in-kernel alarm interface" This reverts commit d1d79061a9d4a184dc026ca6dc105d17da0693c3. --- drivers/rtc/Kconfig | 10 +- drivers/rtc/Makefile | 3 +- drivers/rtc/alarm-dev.c | 286 --------------- drivers/rtc/alarm.c | 664 +++++++++++++++++----------------- include/linux/android_alarm.h | 44 --- 5 files changed, 325 insertions(+), 682 deletions(-) delete mode 100644 drivers/rtc/alarm-dev.c diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 12d2c045bbfe..0c15aa0d277e 100755 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -116,17 +116,9 @@ config RTC_INTF_ALARM help Provides non-wakeup and rtc backed wakeup alarms based on rtc or elapsed realtime, and a non-wakeup alarm on the monotonic clock. - Also provides an interface to set the wall time which must be used + Also provides an ioctl to set the wall time which must be used for elapsed realtime to work. -config RTC_INTF_ALARM_DEV - bool "Android alarm device" - depends on RTC_INTF_ALARM - default y - help - Exports the alarm interface to user-space. - - config RTC_DRV_TEST tristate "Test driver/device" help diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index ffc421a089d6..d909552801c1 100755 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile @@ -11,8 +11,7 @@ obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o obj-$(CONFIG_RTC_CLASS) += rtc-core.o rtc-core-y := class.o interface.o -obj-$(CONFIG_RTC_INTF_ALARM) += alarm.o -obj-$(CONFIG_RTC_INTF_ALARM_DEV) += alarm-dev.o +rtc-core-$(CONFIG_RTC_INTF_ALARM) += alarm.o rtc-core-$(CONFIG_RTC_INTF_DEV) += rtc-dev.o rtc-core-$(CONFIG_RTC_INTF_PROC) += rtc-proc.o rtc-core-$(CONFIG_RTC_INTF_SYSFS) += rtc-sysfs.o diff --git a/drivers/rtc/alarm-dev.c b/drivers/rtc/alarm-dev.c deleted file mode 100644 index 686e6f7ed480..000000000000 --- a/drivers/rtc/alarm-dev.c +++ /dev/null @@ -1,286 +0,0 @@ -/* drivers/rtc/alarm-dev.c - * - * Copyright (C) 2007-2009 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ANDROID_ALARM_PRINT_INFO (1U << 0) -#define ANDROID_ALARM_PRINT_IO (1U << 1) -#define ANDROID_ALARM_PRINT_INT (1U << 2) - -static int debug_mask = ANDROID_ALARM_PRINT_INFO; -module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); - -#define pr_alarm(debug_level_mask, args...) \ - do { \ - if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \ - pr_info(args); \ - } \ - } while (0) - -#define ANDROID_ALARM_WAKEUP_MASK ( \ - ANDROID_ALARM_RTC_WAKEUP_MASK | \ - ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) - -/* support old usespace code */ -#define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */ -#define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t) - -static int alarm_opened; -static DEFINE_SPINLOCK(alarm_slock); -static struct wake_lock alarm_wake_lock; -static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue); -static uint32_t alarm_pending; -static uint32_t alarm_enabled; -static uint32_t wait_pending; - -static struct alarm alarms[ANDROID_ALARM_TYPE_COUNT]; - -static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int rv = 0; - unsigned long flags; - struct timespec new_alarm_time; - struct timespec new_rtc_time; - struct timespec tmp_time; - enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); - uint32_t alarm_type_mask = 1U << alarm_type; - - if (alarm_type >= ANDROID_ALARM_TYPE_COUNT) - return -EINVAL; - - if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) { - if ((file->f_flags & O_ACCMODE) == O_RDONLY) - return -EPERM; - if (file->private_data == NULL && - cmd != ANDROID_ALARM_SET_RTC) { - spin_lock_irqsave(&alarm_slock, flags); - if (alarm_opened) { - spin_unlock_irqrestore(&alarm_slock, flags); - return -EBUSY; - } - alarm_opened = 1; - file->private_data = (void *)1; - spin_unlock_irqrestore(&alarm_slock, flags); - } - } - - switch (ANDROID_ALARM_BASE_CMD(cmd)) { - case ANDROID_ALARM_CLEAR(0): - spin_lock_irqsave(&alarm_slock, flags); - pr_alarm(IO, "alarm %d clear\n", alarm_type); - alarm_try_to_cancel(&alarms[alarm_type]); - if (alarm_pending) { - alarm_pending &= ~alarm_type_mask; - if (!alarm_pending && !wait_pending) - wake_unlock(&alarm_wake_lock); - } - alarm_enabled &= ~alarm_type_mask; - spin_unlock_irqrestore(&alarm_slock, flags); - break; - - case ANDROID_ALARM_SET_OLD: - case ANDROID_ALARM_SET_AND_WAIT_OLD: - if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) { - rv = -EFAULT; - goto err1; - } - new_alarm_time.tv_nsec = 0; - goto from_old_alarm_set; - - case ANDROID_ALARM_SET_AND_WAIT(0): - case ANDROID_ALARM_SET(0): - if (copy_from_user(&new_alarm_time, (void __user *)arg, - sizeof(new_alarm_time))) { - rv = -EFAULT; - goto err1; - } -from_old_alarm_set: - spin_lock_irqsave(&alarm_slock, flags); - pr_alarm(IO, "alarm %d set %ld.%09ld\n", alarm_type, - new_alarm_time.tv_sec, new_alarm_time.tv_nsec); - alarm_enabled |= alarm_type_mask; - alarm_start_range(&alarms[alarm_type], - timespec_to_ktime(new_alarm_time), - timespec_to_ktime(new_alarm_time)); - spin_unlock_irqrestore(&alarm_slock, flags); - if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0) - && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD) - break; - /* fall though */ - case ANDROID_ALARM_WAIT: - spin_lock_irqsave(&alarm_slock, flags); - pr_alarm(IO, "alarm wait\n"); - if (!alarm_pending && wait_pending) { - wake_unlock(&alarm_wake_lock); - wait_pending = 0; - } - spin_unlock_irqrestore(&alarm_slock, flags); - rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); - if (rv) - goto err1; - spin_lock_irqsave(&alarm_slock, flags); - rv = alarm_pending; - wait_pending = 1; - alarm_pending = 0; - spin_unlock_irqrestore(&alarm_slock, flags); - break; - case ANDROID_ALARM_SET_RTC: - if (copy_from_user(&new_rtc_time, (void __user *)arg, - sizeof(new_rtc_time))) { - rv = -EFAULT; - goto err1; - } - rv = alarm_set_rtc(new_rtc_time); - spin_lock_irqsave(&alarm_slock, flags); - alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; - wake_up(&alarm_wait_queue); - spin_unlock_irqrestore(&alarm_slock, flags); - if (rv < 0) - goto err1; - break; - case ANDROID_ALARM_GET_TIME(0): - switch (alarm_type) { - case ANDROID_ALARM_RTC_WAKEUP: - case ANDROID_ALARM_RTC: - getnstimeofday(&tmp_time); - break; - case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP: - case ANDROID_ALARM_ELAPSED_REALTIME: - tmp_time = - ktime_to_timespec(alarm_get_elapsed_realtime()); - break; - case ANDROID_ALARM_TYPE_COUNT: - case ANDROID_ALARM_SYSTEMTIME: - ktime_get_ts(&tmp_time); - break; - } - if (copy_to_user((void __user *)arg, &tmp_time, - sizeof(tmp_time))) { - rv = -EFAULT; - goto err1; - } - break; - - default: - rv = -EINVAL; - goto err1; - } -err1: - return rv; -} - -static int alarm_open(struct inode *inode, struct file *file) -{ - file->private_data = NULL; - return 0; -} - -static int alarm_release(struct inode *inode, struct file *file) -{ - int i; - unsigned long flags; - - spin_lock_irqsave(&alarm_slock, flags); - if (file->private_data != 0) { - for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { - uint32_t alarm_type_mask = 1U << i; - if (alarm_enabled & alarm_type_mask) { - pr_alarm(INFO, "alarm_release: clear alarm, " - "pending %d\n", - !!(alarm_pending & alarm_type_mask)); - alarm_enabled &= ~alarm_type_mask; - } - spin_unlock_irqrestore(&alarm_slock, flags); - alarm_cancel(&alarms[i]); - spin_lock_irqsave(&alarm_slock, flags); - } - if (alarm_pending | wait_pending) { - if (alarm_pending) - pr_alarm(INFO, "alarm_release: clear " - "pending alarms %x\n", alarm_pending); - wake_unlock(&alarm_wake_lock); - wait_pending = 0; - alarm_pending = 0; - } - alarm_opened = 0; - } - spin_unlock_irqrestore(&alarm_slock, flags); - return 0; -} - -static void alarm_triggered(struct alarm *alarm) -{ - unsigned long flags; - uint32_t alarm_type_mask = 1U << alarm->type; - - pr_alarm(INT, "alarm_triggered type %d\n", alarm->type); - spin_lock_irqsave(&alarm_slock, flags); - if (alarm_enabled & alarm_type_mask) { - wake_lock_timeout(&alarm_wake_lock, 5 * HZ); - alarm_enabled &= ~alarm_type_mask; - alarm_pending |= alarm_type_mask; - wake_up(&alarm_wait_queue); - } - spin_unlock_irqrestore(&alarm_slock, flags); -} - -static const struct file_operations alarm_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = alarm_ioctl, - .open = alarm_open, - .release = alarm_release, -}; - -static struct miscdevice alarm_device = { - .minor = MISC_DYNAMIC_MINOR, - .name = "alarm", - .fops = &alarm_fops, -}; - -static int __init alarm_dev_init(void) -{ - int err; - int i; - - err = misc_register(&alarm_device); - if (err) - return err; - - for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) - alarm_init(&alarms[i], i, alarm_triggered); - wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm"); - - return 0; -} - -static void __exit alarm_dev_exit(void) -{ - misc_deregister(&alarm_device); - wake_lock_destroy(&alarm_wake_lock); -} - -module_init(alarm_dev_init); -module_exit(alarm_dev_exit); - diff --git a/drivers/rtc/alarm.c b/drivers/rtc/alarm.c index 7232a538d399..cd660eee3b27 100644 --- a/drivers/rtc/alarm.c +++ b/drivers/rtc/alarm.c @@ -1,6 +1,6 @@ /* drivers/rtc/alarm.c * - * Copyright (C) 2007-2009 Google, Inc. + * Copyright (C) 2007 Google, Inc. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and @@ -24,24 +24,24 @@ #include #include -#define ANDROID_ALARM_PRINT_ERROR (1U << 0) +#define ANDROID_ALARM_PRINT_ERRORS (1U << 0) #define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1) -#define ANDROID_ALARM_PRINT_TSET (1U << 2) -#define ANDROID_ALARM_PRINT_CALL (1U << 3) -#define ANDROID_ALARM_PRINT_SUSPEND (1U << 4) -#define ANDROID_ALARM_PRINT_INT (1U << 5) -#define ANDROID_ALARM_PRINT_FLOW (1U << 6) - -static int debug_mask = ANDROID_ALARM_PRINT_ERROR | \ - ANDROID_ALARM_PRINT_INIT_STATUS; -module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); - -#define pr_alarm(debug_level_mask, args...) \ +#define ANDROID_ALARM_PRINT_INFO (1U << 2) +#define ANDROID_ALARM_PRINT_IO (1U << 3) +#define ANDROID_ALARM_PRINT_INT (1U << 4) +#define ANDROID_ALARM_PRINT_FLOW (1U << 5) + +#if 0 +#define ANDROID_ALARM_DPRINTF_MASK (~0) +#define ANDROID_ALARM_DPRINTF(debug_level_mask, args...) \ do { \ - if (debug_mask & ANDROID_ALARM_PRINT_##debug_level_mask) { \ - pr_info(args); \ + if (ANDROID_ALARM_DPRINTF_MASK & debug_level_mask) { \ + printk(args); \ } \ } while (0) +#else +#define ANDROID_ALARM_DPRINTF(args...) +#endif #define ANDROID_ALARM_WAKEUP_MASK ( \ ANDROID_ALARM_RTC_WAKEUP_MASK | \ @@ -51,307 +51,264 @@ module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP); #define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */ #define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t) -struct alarm_queue { - struct rb_root alarms; - struct rb_node *first; - struct hrtimer timer; - ktime_t delta; - bool stopped; - ktime_t stopped_time; -}; - static struct rtc_device *alarm_rtc_dev; +static int alarm_opened; static DEFINE_SPINLOCK(alarm_slock); static DEFINE_MUTEX(alarm_setrtc_mutex); +static struct wake_lock alarm_wake_lock; static struct wake_lock alarm_rtc_wake_lock; +static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue); +static uint32_t alarm_pending; +static uint32_t alarm_enabled; +static uint32_t wait_pending; static struct platform_device *alarm_platform_dev; -struct alarm_queue alarms[ANDROID_ALARM_TYPE_COUNT]; -static bool suspended; +static struct hrtimer alarm_timer[ANDROID_ALARM_TYPE_COUNT]; +static struct timespec alarm_time[ANDROID_ALARM_TYPE_COUNT]; +static struct timespec elapsed_rtc_delta; -static void update_timer_locked(struct alarm_queue *base, bool head_removed) +static void alarm_start_hrtimer(enum android_alarm_type alarm_type) { - struct alarm *alarm; - bool is_wakeup = base == &alarms[ANDROID_ALARM_RTC_WAKEUP] || - base == &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]; - - if (base->stopped) { - pr_alarm(FLOW, "changed alarm while setting the wall time\n"); - return; - } - - if (is_wakeup && !suspended && head_removed) - wake_unlock(&alarm_rtc_wake_lock); - - if (!base->first) + struct timespec hr_alarm_time; + if (!(alarm_enabled & (1U << alarm_type))) return; - - alarm = container_of(base->first, struct alarm, node); - - pr_alarm(FLOW, "selected alarm, type %d, func %pF at %lld\n", - alarm->type, alarm->function, ktime_to_ns(alarm->expires)); - - if (is_wakeup && suspended) { - pr_alarm(FLOW, "changed alarm while suspened\n"); - wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ); - return; - } - - hrtimer_try_to_cancel(&base->timer); - base->timer._expires = ktime_add(base->delta, alarm->expires); - base->timer._softexpires = ktime_add(base->delta, alarm->softexpires); - hrtimer_start_expires(&base->timer, HRTIMER_MODE_ABS); + hr_alarm_time = alarm_time[alarm_type]; + if (alarm_type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP || + alarm_type == ANDROID_ALARM_ELAPSED_REALTIME) + set_normalized_timespec(&hr_alarm_time, + hr_alarm_time.tv_sec + elapsed_rtc_delta.tv_sec, + hr_alarm_time.tv_nsec + elapsed_rtc_delta.tv_nsec); + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_FLOW, + "alarm start hrtimer %d at %ld.%09ld\n", + alarm_type, hr_alarm_time.tv_sec, hr_alarm_time.tv_nsec); + hrtimer_start(&alarm_timer[alarm_type], + timespec_to_ktime(hr_alarm_time), HRTIMER_MODE_ABS); } -static void alarm_enqueue_locked(struct alarm *alarm) +static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct alarm_queue *base = &alarms[alarm->type]; - struct rb_node **link = &base->alarms.rb_node; - struct rb_node *parent = NULL; - struct alarm *entry; - int leftmost = 1; - - pr_alarm(FLOW, "added alarm, type %d, func %pF at %lld\n", - alarm->type, alarm->function, ktime_to_ns(alarm->expires)); - - if (base->first == &alarm->node) - base->first = rb_next(&alarm->node); - if (!RB_EMPTY_NODE(&alarm->node)) { - rb_erase(&alarm->node, &base->alarms); - RB_CLEAR_NODE(&alarm->node); - } + int rv = 0; + unsigned long flags; + int i; + struct timespec new_alarm_time; + struct timespec new_rtc_time; + struct timespec tmp_time; + struct rtc_time rtc_new_rtc_time; + enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd); + uint32_t alarm_type_mask = 1U << alarm_type; + + if (alarm_type >= ANDROID_ALARM_TYPE_COUNT) + return -EINVAL; - while (*link) { - parent = *link; - entry = rb_entry(parent, struct alarm, node); - /* - * We dont care about collisions. Nodes with - * the same expiry time stay together. - */ - if (alarm->expires.tv64 < entry->expires.tv64) { - link = &(*link)->rb_left; - } else { - link = &(*link)->rb_right; - leftmost = 0; + if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) { + if ((file->f_flags & O_ACCMODE) == O_RDONLY) + return -EPERM; + if (file->private_data == NULL && + cmd != ANDROID_ALARM_SET_RTC) { + spin_lock_irqsave(&alarm_slock, flags); + if (alarm_opened) { + spin_unlock_irqrestore(&alarm_slock, flags); + return -EBUSY; + } + alarm_opened = 1; + file->private_data = (void *)1; + spin_unlock_irqrestore(&alarm_slock, flags); } } - if (leftmost) { - base->first = &alarm->node; - update_timer_locked(base, false); - } - - rb_link_node(&alarm->node, parent, link); - rb_insert_color(&alarm->node, &base->alarms); -} -/** - * alarm_init - initialize an alarm - * @alarm: the alarm to be initialized - * @type: the alarm type to be used - * @function: alarm callback function - */ -void alarm_init(struct alarm *alarm, - enum android_alarm_type type, void (*function)(struct alarm *)) -{ - RB_CLEAR_NODE(&alarm->node); - alarm->type = type; - alarm->function = function; - - pr_alarm(FLOW, "created alarm, type %d, func %pF\n", type, function); -} - - -/** - * alarm_start_range - (re)start an alarm - * @alarm: the alarm to be added - * @start: earliest expiry time - * @end: expiry time - */ -void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end) -{ - unsigned long flags; + switch (ANDROID_ALARM_BASE_CMD(cmd)) { + case ANDROID_ALARM_CLEAR(0): + spin_lock_irqsave(&alarm_slock, flags); + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_IO, + "alarm %d clear\n", alarm_type); + hrtimer_try_to_cancel(&alarm_timer[alarm_type]); + if (alarm_pending) { + alarm_pending &= ~alarm_type_mask; + if (!alarm_pending && !wait_pending) + wake_unlock(&alarm_wake_lock); + } + alarm_enabled &= ~alarm_type_mask; + spin_unlock_irqrestore(&alarm_slock, flags); + break; - spin_lock_irqsave(&alarm_slock, flags); - alarm->softexpires = start; - alarm->expires = end; - alarm_enqueue_locked(alarm); - spin_unlock_irqrestore(&alarm_slock, flags); -} + case ANDROID_ALARM_SET_OLD: + case ANDROID_ALARM_SET_AND_WAIT_OLD: + if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) { + rv = -EFAULT; + goto err1; + } + new_alarm_time.tv_nsec = 0; + goto from_old_alarm_set; + + case ANDROID_ALARM_SET_AND_WAIT(0): + case ANDROID_ALARM_SET(0): + if (copy_from_user(&new_alarm_time, (void __user *)arg, + sizeof(new_alarm_time))) { + rv = -EFAULT; + goto err1; + } +from_old_alarm_set: + spin_lock_irqsave(&alarm_slock, flags); + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_IO, + "alarm %d set %ld.%09ld\n", alarm_type, + new_alarm_time.tv_sec, new_alarm_time.tv_nsec); + alarm_time[alarm_type] = new_alarm_time; + alarm_enabled |= alarm_type_mask; + alarm_start_hrtimer(alarm_type); + spin_unlock_irqrestore(&alarm_slock, flags); + if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0) + && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD) + break; + /* fall though */ + case ANDROID_ALARM_WAIT: + spin_lock_irqsave(&alarm_slock, flags); + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_IO, "alarm wait\n"); + if (!alarm_pending && wait_pending) { + wake_unlock(&alarm_wake_lock); + wait_pending = 0; + } + spin_unlock_irqrestore(&alarm_slock, flags); + rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); + if (rv) + goto err1; + spin_lock_irqsave(&alarm_slock, flags); + rv = alarm_pending; + wait_pending = 1; + alarm_pending = 0; + if (rv & ANDROID_ALARM_WAKEUP_MASK) + wake_unlock(&alarm_rtc_wake_lock); + spin_unlock_irqrestore(&alarm_slock, flags); + break; + case ANDROID_ALARM_SET_RTC: + if (copy_from_user(&new_rtc_time, (void __user *)arg, + sizeof(new_rtc_time))) { + rv = -EFAULT; + goto err1; + } + rtc_time_to_tm(new_rtc_time.tv_sec, &rtc_new_rtc_time); -/** - * alarm_try_to_cancel - try to deactivate an alarm - * @alarm: alarm to stop - * - * Returns: - * 0 when the alarm was not active - * 1 when the alarm was active - * -1 when the alarm may currently be excuting the callback function and - * cannot be stopped (it may also be inactive) - */ -int alarm_try_to_cancel(struct alarm *alarm) -{ - struct alarm_queue *base = &alarms[alarm->type]; - unsigned long flags; - bool first = false; - int ret = 0; + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_IO, + "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n", + new_rtc_time.tv_sec, new_rtc_time.tv_nsec, + rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min, + rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1, + rtc_new_rtc_time.tm_mday, + rtc_new_rtc_time.tm_year + 1900); - spin_lock_irqsave(&alarm_slock, flags); - if (!RB_EMPTY_NODE(&alarm->node)) { - pr_alarm(FLOW, "canceled alarm, type %d, func %pF at %lld\n", - alarm->type, alarm->function, - ktime_to_ns(alarm->expires)); - ret = 1; - if (base->first == &alarm->node) { - base->first = rb_next(&alarm->node); - first = true; + mutex_lock(&alarm_setrtc_mutex); + spin_lock_irqsave(&alarm_slock, flags); + for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) + hrtimer_try_to_cancel(&alarm_timer[i]); + getnstimeofday(&tmp_time); + elapsed_rtc_delta = timespec_sub(elapsed_rtc_delta, + timespec_sub(tmp_time, new_rtc_time)); + spin_unlock_irqrestore(&alarm_slock, flags); + rv = do_settimeofday(&new_rtc_time); + spin_lock_irqsave(&alarm_slock, flags); + for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) + alarm_start_hrtimer(i); + spin_unlock_irqrestore(&alarm_slock, flags); + if (rv < 0) { + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_ERRORS, + "Failed to set time\n"); + mutex_unlock(&alarm_setrtc_mutex); + goto err1; } - rb_erase(&alarm->node, &base->alarms); - RB_CLEAR_NODE(&alarm->node); - if (first) - update_timer_locked(base, true); - } else - pr_alarm(FLOW, "tried to cancel alarm, type %d, func %pF\n", - alarm->type, alarm->function); - spin_unlock_irqrestore(&alarm_slock, flags); - if (!ret && hrtimer_callback_running(&base->timer)) - ret = -1; - return ret; -} + rv = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time); + spin_lock_irqsave(&alarm_slock, flags); + alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; + wake_up(&alarm_wait_queue); + spin_unlock_irqrestore(&alarm_slock, flags); + mutex_unlock(&alarm_setrtc_mutex); + if (rv < 0) { + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_ERRORS, + "Failed to set RTC, time will be lost on reboot\n"); + goto err1; + } + break; + case ANDROID_ALARM_GET_TIME(0): + mutex_lock(&alarm_setrtc_mutex); + spin_lock_irqsave(&alarm_slock, flags); + if (alarm_type != ANDROID_ALARM_SYSTEMTIME) { + getnstimeofday(&tmp_time); + if (alarm_type >= ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP) + tmp_time = timespec_sub(tmp_time, + elapsed_rtc_delta); + } else + ktime_get_ts(&tmp_time); + spin_unlock_irqrestore(&alarm_slock, flags); + mutex_unlock(&alarm_setrtc_mutex); + if (copy_to_user((void __user *)arg, &tmp_time, + sizeof(tmp_time))) { + rv = -EFAULT; + goto err1; + } + break; -/** - * alarm_cancel - cancel an alarm and wait for the handler to finish. - * @alarm: the alarm to be cancelled - * - * Returns: - * 0 when the alarm was not active - * 1 when the alarm was active - */ -int alarm_cancel(struct alarm *alarm) -{ - for (;;) { - int ret = alarm_try_to_cancel(alarm); - if (ret >= 0) - return ret; - cpu_relax(); + default: + rv = -EINVAL; + goto err1; } +err1: + return rv; } -/** - * alarm_set_rtc - set the kernel and rtc walltime - * @new_time: timespec value containing the new time - */ -int alarm_set_rtc(struct timespec new_time) +static int alarm_open(struct inode *inode, struct file *file) { - int i; - int ret; - unsigned long flags; - struct rtc_time rtc_new_rtc_time; - struct timespec tmp_time; - - rtc_time_to_tm(new_time.tv_sec, &rtc_new_rtc_time); - - pr_alarm(TSET, "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n", - new_time.tv_sec, new_time.tv_nsec, - rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min, - rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1, - rtc_new_rtc_time.tm_mday, - rtc_new_rtc_time.tm_year + 1900); - - mutex_lock(&alarm_setrtc_mutex); - spin_lock_irqsave(&alarm_slock, flags); - wake_lock(&alarm_rtc_wake_lock); - getnstimeofday(&tmp_time); - for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { - hrtimer_try_to_cancel(&alarms[i].timer); - alarms[i].stopped = true; - alarms[i].stopped_time = timespec_to_ktime(tmp_time); - } - alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta = - alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta = - ktime_sub(alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta, - timespec_to_ktime(timespec_sub(tmp_time, new_time))); - spin_unlock_irqrestore(&alarm_slock, flags); - ret = do_settimeofday(&new_time); - spin_lock_irqsave(&alarm_slock, flags); - for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { - alarms[i].stopped = false; - update_timer_locked(&alarms[i], false); - } - spin_unlock_irqrestore(&alarm_slock, flags); - if (ret < 0) { - pr_alarm(ERROR, "alarm_set_rtc: Failed to set time\n"); - goto err; - } - if (!alarm_rtc_dev) { - pr_alarm(ERROR, - "alarm_set_rtc: no RTC, time will be lost on reboot\n"); - goto err; - } - ret = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time); - if (ret < 0) - pr_alarm(ERROR, "alarm_set_rtc: " - "Failed to set RTC, time will be lost on reboot\n"); -err: - wake_unlock(&alarm_rtc_wake_lock); - mutex_unlock(&alarm_setrtc_mutex); - return ret; + file->private_data = NULL; + return 0; } -/** - * alarm_get_elapsed_realtime - get the elapsed real time in ktime_t format - * - * returns the time in ktime_t format - */ -ktime_t alarm_get_elapsed_realtime(void) +static int alarm_release(struct inode *inode, struct file *file) { - ktime_t now; + int i; unsigned long flags; - struct alarm_queue *base = &alarms[ANDROID_ALARM_ELAPSED_REALTIME]; spin_lock_irqsave(&alarm_slock, flags); - now = base->stopped ? base->stopped_time : ktime_get_real(); - now = ktime_sub(now, base->delta); + if (file->private_data != 0) { + for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) { + uint32_t alarm_type_mask = 1U << i; + if (alarm_enabled & alarm_type_mask) { + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO, + "alarm_release: clear alarm, " + "pending %d\n", + !!(alarm_pending & alarm_type_mask)); + alarm_enabled &= ~alarm_type_mask; + } + spin_unlock_irqrestore(&alarm_slock, flags); + hrtimer_cancel(&alarm_timer[i]); + spin_lock_irqsave(&alarm_slock, flags); + } + if (alarm_pending | wait_pending) { + if (alarm_pending) + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO, + "alarm_release: clear pending alarms " + "%x\n", alarm_pending); + wake_unlock(&alarm_wake_lock); + wait_pending = 0; + alarm_pending = 0; + } + alarm_opened = 0; + } spin_unlock_irqrestore(&alarm_slock, flags); - return now; + return 0; } static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer) { - struct alarm_queue *base; - struct alarm *alarm; unsigned long flags; - ktime_t now; + enum android_alarm_type alarm_type = (timer - alarm_timer); + uint32_t alarm_type_mask = 1U << alarm_type; - spin_lock_irqsave(&alarm_slock, flags); - - base = container_of(timer, struct alarm_queue, timer); - now = base->stopped ? base->stopped_time : hrtimer_cb_get_time(timer); - now = ktime_sub(now, base->delta); - - pr_alarm(INT, "alarm_timer_triggered type %d at %lld\n", - base - alarms, ktime_to_ns(now)); - while (base->first) { - alarm = container_of(base->first, struct alarm, node); - if (alarm->softexpires.tv64 > now.tv64) { - pr_alarm(FLOW, "don't call alarm, %pF, %lld (s %lld)\n", - alarm->function, ktime_to_ns(alarm->expires), - ktime_to_ns(alarm->softexpires)); - break; - } - base->first = rb_next(&alarm->node); - rb_erase(&alarm->node, &base->alarms); - RB_CLEAR_NODE(&alarm->node); - pr_alarm(CALL, "call alarm, type %d, func %pF, %lld (s %lld)\n", - alarm->type, alarm->function, - ktime_to_ns(alarm->expires), - ktime_to_ns(alarm->softexpires)); - spin_unlock_irqrestore(&alarm_slock, flags); - alarm->function(alarm); - spin_lock_irqsave(&alarm_slock, flags); + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INT, + "alarm_timer_triggered type %d\n", alarm_type); + spin_lock_irqsave(&alarm_slock, flags); + if (alarm_enabled & alarm_type_mask) { + wake_lock_timeout(&alarm_wake_lock, 5 * HZ); + alarm_enabled &= ~alarm_type_mask; + alarm_pending |= alarm_type_mask; + wake_up(&alarm_wait_queue); } - if (!base->first) - pr_alarm(FLOW, "no more alarms of type %d\n", base - alarms); - update_timer_locked(base, true); spin_unlock_irqrestore(&alarm_slock, flags); return HRTIMER_NORESTART; } @@ -361,11 +318,11 @@ static void alarm_triggered_func(void *p) struct rtc_device *rtc = alarm_rtc_dev; if (!(rtc->irq_data & RTC_AF)) return; - pr_alarm(INT, "rtc alarm triggered\n"); + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INT, "rtc alarm triggered\n"); wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ); } -static int alarm_suspend(struct platform_device *pdev, pm_message_t state) +int alarm_suspend(struct platform_device *pdev, pm_message_t state) { int err = 0; unsigned long flags; @@ -375,85 +332,89 @@ static int alarm_suspend(struct platform_device *pdev, pm_message_t state) unsigned long rtc_alarm_time; struct timespec rtc_current_timespec; struct timespec rtc_delta; - struct alarm_queue *wakeup_queue = NULL; - struct alarm_queue *tmp_queue = NULL; - - pr_alarm(SUSPEND, "alarm_suspend(%p, %d)\n", pdev, state.event); + struct timespec elapsed_realtime_alarm_time; + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_FLOW, + "alarm_suspend(%p, %d)\n", pdev, state.event); spin_lock_irqsave(&alarm_slock, flags); - suspended = true; - spin_unlock_irqrestore(&alarm_slock, flags); + if (alarm_pending && !wake_lock_active(&alarm_wake_lock)) { + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO, + "alarm pending\n"); + err = -EBUSY; + goto err1; + } + if (alarm_enabled & ANDROID_ALARM_WAKEUP_MASK) { + spin_unlock_irqrestore(&alarm_slock, flags); + if (alarm_enabled & ANDROID_ALARM_RTC_WAKEUP_MASK) + hrtimer_cancel(&alarm_timer[ANDROID_ALARM_RTC_WAKEUP]); + if (alarm_enabled & ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) + hrtimer_cancel(&alarm_timer[ + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]); - hrtimer_cancel(&alarms[ANDROID_ALARM_RTC_WAKEUP].timer); - hrtimer_cancel(&alarms[ - ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK].timer); - - tmp_queue = &alarms[ANDROID_ALARM_RTC_WAKEUP]; - if (tmp_queue->first) - wakeup_queue = tmp_queue; - tmp_queue = &alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]; - if (tmp_queue->first && (!wakeup_queue || - hrtimer_get_expires(&tmp_queue->timer).tv64 < - hrtimer_get_expires(&wakeup_queue->timer).tv64)) - wakeup_queue = tmp_queue; - if (wakeup_queue) { rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time); rtc_current_timespec.tv_nsec = 0; rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_timespec.tv_sec); save_time_delta(&rtc_delta, &rtc_current_timespec); - - rtc_alarm_time = timespec_sub(ktime_to_timespec( - hrtimer_get_expires(&wakeup_queue->timer)), - rtc_delta).tv_sec; - + set_normalized_timespec(&elapsed_realtime_alarm_time, + alarm_time[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP] + .tv_sec + elapsed_rtc_delta.tv_sec, + alarm_time[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP] + .tv_nsec + elapsed_rtc_delta.tv_nsec); + if ((alarm_enabled & ANDROID_ALARM_RTC_WAKEUP_MASK) && + (!(alarm_enabled & + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) || + timespec_compare(&alarm_time[ANDROID_ALARM_RTC_WAKEUP], + &elapsed_realtime_alarm_time) < 0)) + rtc_alarm_time = timespec_sub( + alarm_time[ANDROID_ALARM_RTC_WAKEUP], + rtc_delta).tv_sec; + else + rtc_alarm_time = timespec_sub( + elapsed_realtime_alarm_time, rtc_delta).tv_sec; rtc_time_to_tm(rtc_alarm_time, &rtc_alarm.time); rtc_alarm.enabled = 1; rtc_set_alarm(alarm_rtc_dev, &rtc_alarm); rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time); rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time); - pr_alarm(SUSPEND, + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO, "rtc alarm set at %ld, now %ld, rtc delta %ld.%09ld\n", rtc_alarm_time, rtc_current_time, rtc_delta.tv_sec, rtc_delta.tv_nsec); if (rtc_current_time + 1 >= rtc_alarm_time) { - pr_alarm(SUSPEND, "alarm about to go off\n"); + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO, + "alarm about to go off\n"); memset(&rtc_alarm, 0, sizeof(rtc_alarm)); rtc_alarm.enabled = 0; rtc_set_alarm(alarm_rtc_dev, &rtc_alarm); spin_lock_irqsave(&alarm_slock, flags); - suspended = false; wake_lock_timeout(&alarm_rtc_wake_lock, 2 * HZ); - update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], - false); - update_timer_locked(&alarms[ - ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], false); + alarm_start_hrtimer(ANDROID_ALARM_RTC_WAKEUP); + alarm_start_hrtimer( + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP); err = -EBUSY; spin_unlock_irqrestore(&alarm_slock, flags); } + } else { +err1: + spin_unlock_irqrestore(&alarm_slock, flags); } return err; } -static int alarm_resume(struct platform_device *pdev) +int alarm_resume(struct platform_device *pdev) { struct rtc_wkalrm alarm; - unsigned long flags; - - pr_alarm(SUSPEND, "alarm_resume(%p)\n", pdev); - - memset(&alarm, 0, sizeof(alarm)); - alarm.enabled = 0; - rtc_set_alarm(alarm_rtc_dev, &alarm); - - spin_lock_irqsave(&alarm_slock, flags); - suspended = false; - update_timer_locked(&alarms[ANDROID_ALARM_RTC_WAKEUP], false); - update_timer_locked(&alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP], - false); - spin_unlock_irqrestore(&alarm_slock, flags); - + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_FLOW, + "alarm_resume(%p)\n", pdev); + if (alarm_enabled & ANDROID_ALARM_WAKEUP_MASK) { + memset(&alarm, 0, sizeof(alarm)); + alarm.enabled = 0; + rtc_set_alarm(alarm_rtc_dev, &alarm); + alarm_start_hrtimer(ANDROID_ALARM_RTC_WAKEUP); + alarm_start_hrtimer(ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP); + } return 0; } @@ -461,6 +422,19 @@ static struct rtc_task alarm_rtc_task = { .func = alarm_triggered_func }; +static struct file_operations alarm_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = alarm_ioctl, + .open = alarm_open, + .release = alarm_release, +}; + +static struct miscdevice alarm_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "alarm", + .fops = &alarm_fops, +}; + static int rtc_alarm_add_device(struct device *dev, struct class_interface *class_intf) { @@ -474,6 +448,9 @@ static int rtc_alarm_add_device(struct device *dev, goto err1; } + err = misc_register(&alarm_device); + if (err) + goto err1; alarm_platform_dev = platform_device_register_simple("alarm", -1, NULL, 0); if (IS_ERR(alarm_platform_dev)) { @@ -484,14 +461,16 @@ static int rtc_alarm_add_device(struct device *dev, if (err) goto err3; alarm_rtc_dev = rtc; - pr_alarm(INIT_STATUS, "using rtc device, %s, for alarms", rtc->name); mutex_unlock(&alarm_setrtc_mutex); + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO, "alarm: parent %p\n", + alarm_platform_dev->dev.power.pm_parent); return 0; err3: platform_device_unregister(alarm_platform_dev); err2: + misc_deregister(&alarm_device); err1: mutex_unlock(&alarm_setrtc_mutex); return err; @@ -501,9 +480,9 @@ static void rtc_alarm_remove_device(struct device *dev, struct class_interface *class_intf) { if (dev == &alarm_rtc_dev->dev) { - pr_alarm(INIT_STATUS, "lost rtc device for alarms"); rtc_irq_unregister(alarm_rtc_dev, &alarm_rtc_task); platform_device_unregister(alarm_platform_dev); + misc_deregister(&alarm_device); alarm_rtc_dev = NULL; } } @@ -524,7 +503,7 @@ static struct platform_driver alarm_driver = { static int __init alarm_late_init(void) { unsigned long flags; - struct timespec tmp_time, system_time; + struct timespec system_time; /* this needs to run after the rtc is read at boot */ spin_lock_irqsave(&alarm_slock, flags); @@ -532,32 +511,33 @@ static int __init alarm_late_init(void) * elasped realtime to be (boot_systemtime + rtc - boot_rtc) == * (rtc - (boot_rtc - boot_systemtime)) */ - getnstimeofday(&tmp_time); + getnstimeofday(&elapsed_rtc_delta); ktime_get_ts(&system_time); - alarms[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP].delta = - alarms[ANDROID_ALARM_ELAPSED_REALTIME].delta = - timespec_to_ktime(timespec_sub(tmp_time, system_time)); - + elapsed_rtc_delta = timespec_sub(elapsed_rtc_delta, system_time); spin_unlock_irqrestore(&alarm_slock, flags); + + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO, + "alarm_late_init: rtc to elapsed realtime delta %ld.%09ld\n", + elapsed_rtc_delta.tv_sec, elapsed_rtc_delta.tv_nsec); return 0; } -static int __init alarm_driver_init(void) +static int __init alarm_init(void) { int err; int i; for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) { - hrtimer_init(&alarms[i].timer, - CLOCK_REALTIME, HRTIMER_MODE_ABS); - alarms[i].timer.function = alarm_timer_triggered; + hrtimer_init(&alarm_timer[i], CLOCK_REALTIME, HRTIMER_MODE_ABS); + alarm_timer[i].function = alarm_timer_triggered; } - hrtimer_init(&alarms[ANDROID_ALARM_SYSTEMTIME].timer, + hrtimer_init(&alarm_timer[ANDROID_ALARM_SYSTEMTIME], CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - alarms[ANDROID_ALARM_SYSTEMTIME].timer.function = alarm_timer_triggered; + alarm_timer[ANDROID_ALARM_SYSTEMTIME].function = alarm_timer_triggered; err = platform_driver_register(&alarm_driver); if (err < 0) goto err1; + wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm"); wake_lock_init(&alarm_rtc_wake_lock, WAKE_LOCK_SUSPEND, "alarm_rtc"); rtc_alarm_interface.class = rtc_class; err = class_interface_register(&rtc_alarm_interface); @@ -568,6 +548,7 @@ static int __init alarm_driver_init(void) err2: wake_lock_destroy(&alarm_rtc_wake_lock); + wake_lock_destroy(&alarm_wake_lock); platform_driver_unregister(&alarm_driver); err1: return err; @@ -577,10 +558,11 @@ static void __exit alarm_exit(void) { class_interface_unregister(&rtc_alarm_interface); wake_lock_destroy(&alarm_rtc_wake_lock); + wake_lock_destroy(&alarm_wake_lock); platform_driver_unregister(&alarm_driver); } late_initcall(alarm_late_init); -module_init(alarm_driver_init); +module_init(alarm_init); module_exit(alarm_exit); diff --git a/include/linux/android_alarm.h b/include/linux/android_alarm.h index f8f14e793dbf..d0cafd637199 100644 --- a/include/linux/android_alarm.h +++ b/include/linux/android_alarm.h @@ -33,50 +33,6 @@ enum android_alarm_type { /* ANDROID_ALARM_TIME_CHANGE = 16 */ }; -#ifdef __KERNEL__ - -#include -#include - -/* - * The alarm interface is similar to the hrtimer interface but adds support - * for wakeup from suspend. It also adds an elapsed realtime clock that can - * be used for periodic timers that need to keep runing while the system is - * suspended and not be disrupted when the wall time is set. - */ - -/** - * struct alarm - the basic alarm structure - * @node: red black tree node for time ordered insertion - * @type: alarm type. rtc/elapsed-realtime/systemtime, wakeup/non-wakeup. - * @softexpires: the absolute earliest expiry time of the alarm. - * @expires: the absolute expiry time. - * @function: alarm expiry callback function - * - * The alarm structure must be initialized by alarm_init() - * - */ - -struct alarm { - struct rb_node node; - enum android_alarm_type type; - ktime_t softexpires; - ktime_t expires; - void (*function)(struct alarm *); -}; - -void alarm_init(struct alarm *alarm, - enum android_alarm_type type, void (*function)(struct alarm *)); -void alarm_start_range(struct alarm *alarm, ktime_t start, ktime_t end); -int alarm_try_to_cancel(struct alarm *alarm); -int alarm_cancel(struct alarm *alarm); -ktime_t alarm_get_elapsed_realtime(void); - -/* set rtc while preserving elapsed realtime */ -int alarm_set_rtc(const struct timespec ts); - -#endif - enum android_alarm_return_flags { ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP, ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC, -- 2.34.1