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: John Stultz <john.stultz@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
be1a3e38ad
commit
cec8bb73a2
|
@ -92,18 +92,116 @@ 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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
unsigned long flags;
|
||||||
|
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;
|
int rv = 0;
|
||||||
unsigned long flags;
|
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);
|
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)
|
if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -126,102 +224,54 @@ static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
|
||||||
|
|
||||||
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
|
switch (ANDROID_ALARM_BASE_CMD(cmd)) {
|
||||||
case ANDROID_ALARM_CLEAR(0):
|
case ANDROID_ALARM_CLEAR(0):
|
||||||
spin_lock_irqsave(&alarm_slock, flags);
|
alarm_clear(alarm_type);
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ANDROID_ALARM_SET_AND_WAIT(0):
|
|
||||||
case ANDROID_ALARM_SET(0):
|
case ANDROID_ALARM_SET(0):
|
||||||
if (copy_from_user(&new_alarm_time, (void __user *)arg,
|
alarm_set(alarm_type, ts);
|
||||||
sizeof(new_alarm_time))) {
|
break;
|
||||||
rv = -EFAULT;
|
case ANDROID_ALARM_SET_AND_WAIT(0):
|
||||||
goto err1;
|
alarm_set(alarm_type, ts);
|
||||||
}
|
|
||||||
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;
|
|
||||||
/* fall though */
|
/* fall though */
|
||||||
case ANDROID_ALARM_WAIT:
|
case ANDROID_ALARM_WAIT:
|
||||||
spin_lock_irqsave(&alarm_slock, flags);
|
rv = alarm_wait();
|
||||||
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);
|
|
||||||
break;
|
break;
|
||||||
case ANDROID_ALARM_SET_RTC:
|
case ANDROID_ALARM_SET_RTC:
|
||||||
if (copy_from_user(&new_rtc_time, (void __user *)arg,
|
rv = alarm_set_rtc(ts);
|
||||||
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;
|
|
||||||
break;
|
break;
|
||||||
case ANDROID_ALARM_GET_TIME(0):
|
case ANDROID_ALARM_GET_TIME(0):
|
||||||
switch (alarm_type) {
|
rv = alarm_get_time(alarm_type, ts);
|
||||||
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;
|
|
||||||
}
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue