lp: move compat_ioctl handling into lp.c
authorArnd Bergmann <arnd@arndb.de>
Sat, 14 Nov 2009 00:33:13 +0000 (01:33 +0100)
committerArnd Bergmann <arnd@arndb.de>
Thu, 10 Dec 2009 21:55:36 +0000 (22:55 +0100)
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>
drivers/char/lp.c
fs/compat_ioctl.c

index e444c2d..938a3a2 100644 (file)
 #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
index ae1f1e6..598763f 100644 (file)
@@ -953,20 +953,6 @@ static int rtc_ioctl(unsigned fd, unsigned cmd, void __user *argp)
        return -ENOIOCTLCMD;
 }
 
-static int
-lp_timeout_trans(unsigned int fd, unsigned int cmd,
-                       struct compat_timeval __user *tc)
-{
-       struct timeval __user *tn = compat_alloc_user_space(sizeof(struct timeval));
-       struct timeval ts;
-       if (get_user(ts.tv_sec, &tc->tv_sec) ||
-           get_user(ts.tv_usec, &tc->tv_usec) ||
-           put_user(ts.tv_sec, &tn->tv_sec) ||
-           put_user(ts.tv_usec, &tn->tv_usec))
-               return -EFAULT;
-       return sys_ioctl(fd, cmd, (unsigned long)tn);
-}
-
 /* on ia32 l_start is on a 32-bit boundary */
 #if defined(CONFIG_IA64) || defined(CONFIG_X86_64)
 struct space_resv_32 {
@@ -1212,8 +1198,6 @@ COMPATIBLE_IOCTL(PPPIOCGCHAN)
 /* PPPOX */
 COMPATIBLE_IOCTL(PPPOEIOCSFWD)
 COMPATIBLE_IOCTL(PPPOEIOCDFWD)
-/* LP */
-COMPATIBLE_IOCTL(LPGETSTATUS)
 /* ppdev */
 COMPATIBLE_IOCTL(PPSETMODE)
 COMPATIBLE_IOCTL(PPRSTATUS)
@@ -1623,19 +1607,6 @@ COMPATIBLE_IOCTL(TIOCSTOP)
 /* Usbdevfs */
 COMPATIBLE_IOCTL(USBDEVFS_IOCTL32)
 
-/* parport */
-COMPATIBLE_IOCTL(LPTIME)
-COMPATIBLE_IOCTL(LPCHAR)
-COMPATIBLE_IOCTL(LPABORTOPEN)
-COMPATIBLE_IOCTL(LPCAREFUL)
-COMPATIBLE_IOCTL(LPWAIT)
-COMPATIBLE_IOCTL(LPSETIRQ)
-COMPATIBLE_IOCTL(LPGETSTATUS)
-COMPATIBLE_IOCTL(LPGETSTATUS)
-COMPATIBLE_IOCTL(LPRESET)
-/*LPGETSTATS not implemented, but no kernels seem to compile it in anyways*/
-COMPATIBLE_IOCTL(LPGETFLAGS)
-
 /* fat 'r' ioctls. These are handled by fat with ->compat_ioctl,
    but we don't want warnings on other file systems. So declare
    them as compatible here. */
@@ -1734,10 +1705,6 @@ static long do_ioctl_trans(int fd, unsigned int cmd,
                return do_video_stillpicture(fd, cmd, argp);
        case VIDEO_SET_SPU_PALETTE:
                return do_video_set_spu_palette(fd, cmd, argp);
-
-       /* lp */
-       case LPSETTIMEOUT:
-               return lp_timeout_trans(fd, cmd, argp);
        }
 
        /*