Commit cec8bb73 authored by John Stultz's avatar John Stultz Committed by Greg Kroah-Hartman

staging: alarm-dev: Refactor alarm-dev ioctl code in prep for compat_ioctl

Cleanup the Android alarm-dev driver's ioctl code to refactor it
in preparation for compat_ioctl support.

Cc: Serban Constantinescu <serban.constantinescu@arm.com>
Cc: Arve Hjønnevåg <arve@android.com>
Cc: Colin Cross <ccross@google.com>
Cc: Android Kernel Team <kernel-team@android.com>
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent be1a3e38
...@@ -92,40 +92,11 @@ static void devalarm_cancel(struct devalarm *alrm) ...@@ -92,40 +92,11 @@ static void devalarm_cancel(struct devalarm *alrm)
hrtimer_cancel(&alrm->u.hrt); hrtimer_cancel(&alrm->u.hrt);
} }
static void alarm_clear(enum android_alarm_type alarm_type)
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;
struct rtc_time new_rtc_tm;
struct rtc_device *rtc_dev;
enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
uint32_t alarm_type_mask = 1U << alarm_type; uint32_t alarm_type_mask = 1U << alarm_type;
unsigned long flags;
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); spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm %d clear\n", alarm_type); alarm_dbg(IO, "alarm %d clear\n", alarm_type);
devalarm_try_to_cancel(&alarms[alarm_type]); devalarm_try_to_cancel(&alarms[alarm_type]);
...@@ -136,28 +107,28 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -136,28 +107,28 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} }
alarm_enabled &= ~alarm_type_mask; alarm_enabled &= ~alarm_type_mask;
spin_unlock_irqrestore(&alarm_slock, flags); spin_unlock_irqrestore(&alarm_slock, flags);
break;
case ANDROID_ALARM_SET_AND_WAIT(0): }
case ANDROID_ALARM_SET(0):
if (copy_from_user(&new_alarm_time, (void __user *)arg, static void alarm_set(enum android_alarm_type alarm_type,
sizeof(new_alarm_time))) { struct timespec *ts)
rv = -EFAULT; {
goto err1; uint32_t alarm_type_mask = 1U << alarm_type;
} unsigned long flags;
spin_lock_irqsave(&alarm_slock, flags); spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm %d set %ld.%09ld\n", alarm_dbg(IO, "alarm %d set %ld.%09ld\n",
alarm_type, alarm_type, ts->tv_sec, ts->tv_nsec);
new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
alarm_enabled |= alarm_type_mask; alarm_enabled |= alarm_type_mask;
devalarm_start(&alarms[alarm_type], devalarm_start(&alarms[alarm_type], timespec_to_ktime(*ts));
timespec_to_ktime(new_alarm_time));
spin_unlock_irqrestore(&alarm_slock, flags); spin_unlock_irqrestore(&alarm_slock, flags);
if (ANDROID_ALARM_BASE_CMD(cmd) != }
ANDROID_ALARM_SET_AND_WAIT(0))
break; static int alarm_wait(void)
/* fall though */ {
case ANDROID_ALARM_WAIT: unsigned long flags;
int rv = 0;
spin_lock_irqsave(&alarm_slock, flags); spin_lock_irqsave(&alarm_slock, flags);
alarm_dbg(IO, "alarm wait\n"); alarm_dbg(IO, "alarm wait\n");
if (!alarm_pending && wait_pending) { if (!alarm_pending && wait_pending) {
...@@ -165,63 +136,142 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -165,63 +136,142 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
wait_pending = 0; wait_pending = 0;
} }
spin_unlock_irqrestore(&alarm_slock, flags); spin_unlock_irqrestore(&alarm_slock, flags);
rv = wait_event_interruptible(alarm_wait_queue, alarm_pending); rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
if (rv) if (rv)
goto err1; return rv;
spin_lock_irqsave(&alarm_slock, flags); spin_lock_irqsave(&alarm_slock, flags);
rv = alarm_pending; rv = alarm_pending;
wait_pending = 1; wait_pending = 1;
alarm_pending = 0; alarm_pending = 0;
spin_unlock_irqrestore(&alarm_slock, flags); spin_unlock_irqrestore(&alarm_slock, flags);
break;
case ANDROID_ALARM_SET_RTC: return rv;
if (copy_from_user(&new_rtc_time, (void __user *)arg, }
sizeof(new_rtc_time))) {
rv = -EFAULT; static int alarm_set_rtc(struct timespec *ts)
goto err1; {
} struct rtc_time new_rtc_tm;
rtc_time_to_tm(new_rtc_time.tv_sec, &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(); rtc_dev = alarmtimer_get_rtcdev();
rv = do_settimeofday(&new_rtc_time); rv = do_settimeofday(ts);
if (rv < 0) if (rv < 0)
goto err1; return rv;
if (rtc_dev) if (rtc_dev)
rv = rtc_set_time(rtc_dev, &new_rtc_tm); rv = rtc_set_time(rtc_dev, &new_rtc_tm);
spin_lock_irqsave(&alarm_slock, flags); spin_lock_irqsave(&alarm_slock, flags);
alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK; alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
wake_up(&alarm_wait_queue); wake_up(&alarm_wait_queue);
spin_unlock_irqrestore(&alarm_slock, flags); spin_unlock_irqrestore(&alarm_slock, flags);
if (rv < 0)
goto err1; return rv;
break; }
case ANDROID_ALARM_GET_TIME(0):
static int alarm_get_time(enum android_alarm_type alarm_type,
struct timespec *ts)
{
int rv = 0;
switch (alarm_type) { switch (alarm_type) {
case ANDROID_ALARM_RTC_WAKEUP: case ANDROID_ALARM_RTC_WAKEUP:
case ANDROID_ALARM_RTC: case ANDROID_ALARM_RTC:
getnstimeofday(&tmp_time); getnstimeofday(ts);
break; break;
case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP: case ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP:
case ANDROID_ALARM_ELAPSED_REALTIME: case ANDROID_ALARM_ELAPSED_REALTIME:
get_monotonic_boottime(&tmp_time); get_monotonic_boottime(ts);
break; break;
case ANDROID_ALARM_SYSTEMTIME: case ANDROID_ALARM_SYSTEMTIME:
ktime_get_ts(&tmp_time); ktime_get_ts(ts);
break; break;
default: default:
rv = -EINVAL; rv = -EINVAL;
goto err1;
} }
if (copy_to_user((void __user *)arg, &tmp_time, return rv;
sizeof(tmp_time))) { }
rv = -EFAULT;
goto err1; 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);
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):
alarm_clear(alarm_type);
break;
case ANDROID_ALARM_SET(0):
alarm_set(alarm_type, ts);
break;
case ANDROID_ALARM_SET_AND_WAIT(0):
alarm_set(alarm_type, ts);
/* fall though */
case ANDROID_ALARM_WAIT:
rv = alarm_wait();
break;
case ANDROID_ALARM_SET_RTC:
rv = alarm_set_rtc(ts);
break;
case ANDROID_ALARM_GET_TIME(0):
rv = alarm_get_time(alarm_type, ts);
break; break;
default: default:
rv = -EINVAL; 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; return rv;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment