Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 354048
b: refs/heads/master
c: cec8bb7
h: refs/heads/master
v: v3
  • Loading branch information
John Stultz authored and Greg Kroah-Hartman committed Jan 18, 2013
1 parent da6a08e commit 42bc983
Show file tree
Hide file tree
Showing 2 changed files with 140 additions and 90 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: be1a3e38ad7ba682f1a71e61ba16289061627217
refs/heads/master: cec8bb73a2c603034b04b5d56e16878d0b0ef2dd
228 changes: 139 additions & 89 deletions trunk/drivers/staging/android/alarm-dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,18 +92,116 @@ static void devalarm_cancel(struct devalarm *alrm)
hrtimer_cancel(&alrm->u.hrt);
}

static void alarm_clear(enum android_alarm_type alarm_type)
{
uint32_t alarm_type_mask = 1U << alarm_type;
unsigned long flags;

static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm %d clear\n", alarm_type);
devalarm_try_to_cancel(&alarms[alarm_type]);
if (alarm_pending) {
alarm_pending &= ~alarm_type_mask;
if (!alarm_pending && !wait_pending)
__pm_relax(&alarm_wake_lock);
}
alarm_enabled &= ~alarm_type_mask;
spin_unlock_irqrestore(&alarm_slock, flags);

}

static void alarm_set(enum android_alarm_type alarm_type,
struct timespec *ts)
{
uint32_t alarm_type_mask = 1U << alarm_type;
unsigned long flags;

spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm %d set %ld.%09ld\n",
alarm_type, ts->tv_sec, ts->tv_nsec);
alarm_enabled |= alarm_type_mask;
devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts));
spin_unlock_irqrestore(&alarm_slock, flags);
}

static int alarm_wait(void)
{
int rv = 0;
unsigned long flags;
struct timespec new_alarm_time;
struct timespec new_rtc_time;
struct timespec tmp_time;
int rv = 0;

spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm wait\n");
if (!alarm_pending && wait_pending) {
__pm_relax(&alarm_wake_lock);
wait_pending = 0;
}
spin_unlock_irqrestore(&alarm_slock, flags);

rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
if (rv)
return rv;

spin_lock_irqsave(&alarm_slock, flags);
rv = alarm_pending;
wait_pending = 1;
alarm_pending = 0;
spin_unlock_irqrestore(&alarm_slock, flags);

return rv;
}

static int alarm_set_rtc(struct timespec *ts)
{
struct rtc_time new_rtc_tm;
struct rtc_device *rtc_dev;
unsigned long flags;
int rv = 0;

rtc_time_to_tm(ts->tv_sec, &new_rtc_tm);
rtc_dev = alarmtimer_get_rtcdev();
rv = do_settimeofday(ts);
if (rv < 0)
return rv;
if (rtc_dev)
rv = rtc_set_time(rtc_dev, &new_rtc_tm);

spin_lock_irqsave(&alarm_slock, flags);
alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
wake_up(&alarm_wait_queue);
spin_unlock_irqrestore(&alarm_slock, flags);

return rv;
}

static int alarm_get_time(enum android_alarm_type alarm_type,
struct timespec *ts)
{
int rv = 0;

switch (alarm_type) {
case ANDROID_ALARM_RTC_WAKEUP:
case ANDROID_ALARM_RTC:
getnstimeofday(ts);
break;
case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
case ANDROID_ALARM_ELAPSED_REALTIME:
get_monotonic_boottime(ts);
break;
case ANDROID_ALARM_SYSTEMTIME:
ktime_get_ts(ts);
break;
default:
rv = -EINVAL;
}
return rv;
}

static long alarm_do_ioctl(struct file *file, unsigned int cmd,
struct timespec *ts)
{
int rv = 0;
unsigned long flags;
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;
Expand All @@ -126,102 +224,54 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_CLEAR(0):
spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm %d clear\n", alarm_type);
devalarm_try_to_cancel(&alarms[alarm_type]);
if (alarm_pending) {
alarm_pending &= ~alarm_type_mask;
if (!alarm_pending && !wait_pending)
__pm_relax(&alarm_wake_lock);
}
alarm_enabled &= ~alarm_type_mask;
spin_unlock_irqrestore(&alarm_slock, flags);
alarm_clear(alarm_type);
break;

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;
}
spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm %d set %ld.%09ld\n",
alarm_type,
new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
alarm_enabled |= alarm_type_mask;
devalarm_start(&alarms[alarm_type],
timespec_to_ktime(new_alarm_time));
spin_unlock_irqrestore(&alarm_slock, flags);
if (ANDROID_ALARM_BASE_CMD(cmd) !=
ANDROID_ALARM_SET_AND_WAIT(0))
break;
alarm_set(alarm_type, ts);
break;
case ANDROID_ALARM_SET_AND_WAIT(0):
alarm_set(alarm_type, ts);
/* fall though */
case ANDROID_ALARM_WAIT:
spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm wait\n");
if (!alarm_pending && wait_pending) {
__pm_relax(&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);
rv = alarm_wait();
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, &new_rtc_tm);
rtc_dev = alarmtimer_get_rtcdev();
rv = do_settimeofday(&new_rtc_time);
if (rv < 0)
goto err1;
if (rtc_dev)
rv = rtc_set_time(rtc_dev, &new_rtc_tm);
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;
rv = alarm_set_rtc(ts);
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:
get_monotonic_boottime(&tmp_time);
break;
case ANDROID_ALARM_SYSTEMTIME:
ktime_get_ts(&tmp_time);
break;
default:
rv = -EINVAL;
goto err1;
}
if (copy_to_user((void __user *)arg, &tmp_time,
sizeof(tmp_time))) {
rv = -EFAULT;
goto err1;
}
rv = alarm_get_time(alarm_type, ts);
break;

default:
rv = -EINVAL;
}
err1:
return rv;
}

static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{

struct timespec ts;
int rv;

switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_SET_AND_WAIT(0):
case ANDROID_ALARM_SET(0):
case ANDROID_ALARM_SET_RTC:
if (copy_from_user(&ts, (void __user *)arg, sizeof(ts)))
return -EFAULT;
break;
}

rv = alarm_do_ioctl(file, cmd, &ts);

switch (ANDROID_ALARM_BASE_CMD(cmd)) {
case ANDROID_ALARM_GET_TIME(0):
if (copy_to_user((void __user *)arg, &ts, sizeof(ts)))
return -EFAULT;
break;
}

return rv;
}

Expand Down

0 comments on commit 42bc983

Please sign in to comment.