summaryrefslogtreecommitdiff
path: root/fs/timerfd.c
diff options
context:
space:
mode:
authorMao Jinlong <c_jmao@codeaurora.org>2016-02-17 15:21:49 +0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:08:58 -0700
commitf0aafc992657d6a4128d65b375414878eaee0ea9 (patch)
tree0f927ec586703b1931b52d9d01b37d958417afdd /fs/timerfd.c
parent439e21802ec6ec29b959ef9c46abd93a7fd17b9a (diff)
rtc: alarm: Add power-on alarm feature
Android does not support powering-up the phone through alarm. Set rtc alarm in timerfd to power-up the phone after alarm expiration. Change-Id: I781389c658fb00ba7f0ce089d706c10f202a7dc6 Signed-off-by: Mao Jinlong <c_jmao@codeaurora.org>
Diffstat (limited to 'fs/timerfd.c')
-rw-r--r--fs/timerfd.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/fs/timerfd.c b/fs/timerfd.c
index b94fa6c3c6eb..35ecf938f862 100644
--- a/fs/timerfd.c
+++ b/fs/timerfd.c
@@ -49,7 +49,8 @@ static DEFINE_SPINLOCK(cancel_lock);
static inline bool isalarm(struct timerfd_ctx *ctx)
{
return ctx->clockid == CLOCK_REALTIME_ALARM ||
- ctx->clockid == CLOCK_BOOTTIME_ALARM;
+ ctx->clockid == CLOCK_BOOTTIME_ALARM ||
+ ctx->clockid == CLOCK_POWEROFF_ALARM;
}
/*
@@ -133,7 +134,8 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx)
static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
{
if ((ctx->clockid == CLOCK_REALTIME ||
- ctx->clockid == CLOCK_REALTIME_ALARM) &&
+ ctx->clockid == CLOCK_REALTIME_ALARM ||
+ ctx->clockid == CLOCK_POWEROFF_ALARM) &&
(flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
if (!ctx->might_cancel) {
ctx->might_cancel = true;
@@ -164,6 +166,7 @@ static int timerfd_setup(struct timerfd_ctx *ctx, int flags,
enum hrtimer_mode htmode;
ktime_t texp;
int clockid = ctx->clockid;
+ enum alarmtimer_type type;
htmode = (flags & TFD_TIMER_ABSTIME) ?
HRTIMER_MODE_ABS: HRTIMER_MODE_REL;
@@ -174,10 +177,8 @@ static int timerfd_setup(struct timerfd_ctx *ctx, int flags,
ctx->tintv = timespec_to_ktime(ktmr->it_interval);
if (isalarm(ctx)) {
- alarm_init(&ctx->t.alarm,
- ctx->clockid == CLOCK_REALTIME_ALARM ?
- ALARM_REALTIME : ALARM_BOOTTIME,
- timerfd_alarmproc);
+ type = clock2alarm(ctx->clockid);
+ alarm_init(&ctx->t.alarm, type, timerfd_alarmproc);
} else {
hrtimer_init(&ctx->t.tmr, clockid, htmode);
hrtimer_set_expires(&ctx->t.tmr, texp);
@@ -377,6 +378,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
{
int ufd;
struct timerfd_ctx *ctx;
+ enum alarmtimer_type type;
/* Check the TFD_* constants for consistency. */
BUILD_BUG_ON(TFD_CLOEXEC != O_CLOEXEC);
@@ -387,7 +389,8 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
clockid != CLOCK_REALTIME &&
clockid != CLOCK_REALTIME_ALARM &&
clockid != CLOCK_BOOTTIME &&
- clockid != CLOCK_BOOTTIME_ALARM))
+ clockid != CLOCK_BOOTTIME_ALARM &&
+ clockid != CLOCK_POWEROFF_ALARM))
return -EINVAL;
ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
@@ -397,13 +400,12 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
init_waitqueue_head(&ctx->wqh);
ctx->clockid = clockid;
- if (isalarm(ctx))
- alarm_init(&ctx->t.alarm,
- ctx->clockid == CLOCK_REALTIME_ALARM ?
- ALARM_REALTIME : ALARM_BOOTTIME,
- timerfd_alarmproc);
- else
+ if (isalarm(ctx)) {
+ type = clock2alarm(ctx->clockid);
+ alarm_init(&ctx->t.alarm, type, timerfd_alarmproc);
+ } else {
hrtimer_init(&ctx->t.tmr, clockid, HRTIMER_MODE_ABS);
+ }
ctx->moffs = ktime_mono_to_real((ktime_t){ .tv64 = 0 });
@@ -475,6 +477,10 @@ static int do_timerfd_settime(int ufd, int flags,
ret = timerfd_setup(ctx, flags, new);
spin_unlock_irq(&ctx->wqh.lock);
+
+ if (ctx->clockid == CLOCK_POWEROFF_ALARM)
+ set_power_on_alarm();
+
fdput(f);
return ret;
}