lp: move compat_ioctl handling into lp.c

Handling for LPSETTIMEOUT can easily be done in lp_ioctl, which
is the only user. As a positive side-effect, push the BKL
into the ioctl methods.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Arnd Bergmann
2009-11-14 01:33:13 +01:00
parent 43c6e7b97f
commit 3695669cd4
2 changed files with 89 additions and 59 deletions

View File

@@ -127,6 +127,7 @@
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/smp_lock.h>
#include <linux/compat.h>
#include <linux/parport.h>
#undef LP_STATS
@@ -571,13 +572,11 @@ static int lp_release(struct inode * inode, struct file * file)
return 0;
}
static int lp_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
static int lp_do_ioctl(unsigned int minor, unsigned int cmd,
unsigned long arg, void __user *argp)
{
unsigned int minor = iminor(inode);
int status;
int retval = 0;
void __user *argp = (void __user *)arg;
#ifdef LP_DEBUG
printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg);
@@ -587,9 +586,6 @@ static int lp_ioctl(struct inode *inode, struct file *file,
if ((LP_F(minor) & LP_EXIST) == 0)
return -ENODEV;
switch ( cmd ) {
struct timeval par_timeout;
long to_jiffies;
case LPTIME:
LP_TIME(minor) = arg * HZ/100;
break;
@@ -652,34 +648,101 @@ static int lp_ioctl(struct inode *inode, struct file *file,
return -EFAULT;
break;
case LPSETTIMEOUT:
if (copy_from_user (&par_timeout, argp,
sizeof (struct timeval))) {
return -EFAULT;
}
/* Convert to jiffies, place in lp_table */
if ((par_timeout.tv_sec < 0) ||
(par_timeout.tv_usec < 0)) {
return -EINVAL;
}
to_jiffies = DIV_ROUND_UP(par_timeout.tv_usec, 1000000/HZ);
to_jiffies += par_timeout.tv_sec * (long) HZ;
if (to_jiffies <= 0) {
return -EINVAL;
}
lp_table[minor].timeout = to_jiffies;
break;
default:
retval = -EINVAL;
}
return retval;
}
static int lp_set_timeout(unsigned int minor, struct timeval *par_timeout)
{
long to_jiffies;
/* Convert to jiffies, place in lp_table */
if ((par_timeout->tv_sec < 0) ||
(par_timeout->tv_usec < 0)) {
return -EINVAL;
}
to_jiffies = DIV_ROUND_UP(par_timeout->tv_usec, 1000000/HZ);
to_jiffies += par_timeout->tv_sec * (long) HZ;
if (to_jiffies <= 0) {
return -EINVAL;
}
lp_table[minor].timeout = to_jiffies;
return 0;
}
static long lp_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
unsigned int minor;
struct timeval par_timeout;
int ret;
minor = iminor(file->f_path.dentry->d_inode);
lock_kernel();
switch (cmd) {
case LPSETTIMEOUT:
if (copy_from_user(&par_timeout, (void __user *)arg,
sizeof (struct timeval))) {
ret = -EFAULT;
break;
}
ret = lp_set_timeout(minor, &par_timeout);
break;
default:
ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg);
break;
}
unlock_kernel();
return ret;
}
#ifdef CONFIG_COMPAT
static long lp_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
unsigned int minor;
struct timeval par_timeout;
struct compat_timeval __user *tc;
int ret;
minor = iminor(file->f_path.dentry->d_inode);
lock_kernel();
switch (cmd) {
case LPSETTIMEOUT:
tc = compat_ptr(arg);
if (get_user(par_timeout.tv_sec, &tc->tv_sec) ||
get_user(par_timeout.tv_usec, &tc->tv_usec)) {
ret = -EFAULT;
break;
}
ret = lp_set_timeout(minor, &par_timeout);
break;
#ifdef LP_STATS
case LPGETSTATS:
/* FIXME: add an implementation if you set LP_STATS */
ret = -EINVAL;
break;
#endif
default:
ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg));
break;
}
unlock_kernel();
return ret;
}
#endif
static const struct file_operations lp_fops = {
.owner = THIS_MODULE,
.write = lp_write,
.ioctl = lp_ioctl,
.unlocked_ioctl = lp_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = lp_compat_ioctl,
#endif
.open = lp_open,
.release = lp_release,
#ifdef CONFIG_PARPORT_1284