aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/lp.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2009-11-13 19:33:13 -0500
committerArnd Bergmann <arnd@arndb.de>2009-12-10 16:55:36 -0500
commit3695669cd4f5fb6d569fd4243312c1b4a05bd5ce (patch)
tree0e74dafb6f26ac2bbd9d0dcea019798380b55aeb /drivers/char/lp.c
parent43c6e7b97f9ea0f4dec430dbafb6afa6ac711eb1 (diff)
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>
Diffstat (limited to 'drivers/char/lp.c')
-rw-r--r--drivers/char/lp.c115
1 files changed, 89 insertions, 26 deletions
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index e444c2dba160..938a3a273886 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -127,6 +127,7 @@
127#include <linux/wait.h> 127#include <linux/wait.h>
128#include <linux/jiffies.h> 128#include <linux/jiffies.h>
129#include <linux/smp_lock.h> 129#include <linux/smp_lock.h>
130#include <linux/compat.h>
130 131
131#include <linux/parport.h> 132#include <linux/parport.h>
132#undef LP_STATS 133#undef LP_STATS
@@ -571,13 +572,11 @@ static int lp_release(struct inode * inode, struct file * file)
571 return 0; 572 return 0;
572} 573}
573 574
574static int lp_ioctl(struct inode *inode, struct file *file, 575static int lp_do_ioctl(unsigned int minor, unsigned int cmd,
575 unsigned int cmd, unsigned long arg) 576 unsigned long arg, void __user *argp)
576{ 577{
577 unsigned int minor = iminor(inode);
578 int status; 578 int status;
579 int retval = 0; 579 int retval = 0;
580 void __user *argp = (void __user *)arg;
581 580
582#ifdef LP_DEBUG 581#ifdef LP_DEBUG
583 printk(KERN_DEBUG "lp%d ioctl, cmd: 0x%x, arg: 0x%lx\n", minor, cmd, arg); 582 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,
587 if ((LP_F(minor) & LP_EXIST) == 0) 586 if ((LP_F(minor) & LP_EXIST) == 0)
588 return -ENODEV; 587 return -ENODEV;
589 switch ( cmd ) { 588 switch ( cmd ) {
590 struct timeval par_timeout;
591 long to_jiffies;
592
593 case LPTIME: 589 case LPTIME:
594 LP_TIME(minor) = arg * HZ/100; 590 LP_TIME(minor) = arg * HZ/100;
595 break; 591 break;
@@ -652,34 +648,101 @@ static int lp_ioctl(struct inode *inode, struct file *file,
652 return -EFAULT; 648 return -EFAULT;
653 break; 649 break;
654 650
655 case LPSETTIMEOUT:
656 if (copy_from_user (&par_timeout, argp,
657 sizeof (struct timeval))) {
658 return -EFAULT;
659 }
660 /* Convert to jiffies, place in lp_table */
661 if ((par_timeout.tv_sec < 0) ||
662 (par_timeout.tv_usec < 0)) {
663 return -EINVAL;
664 }
665 to_jiffies = DIV_ROUND_UP(par_timeout.tv_usec, 1000000/HZ);
666 to_jiffies += par_timeout.tv_sec * (long) HZ;
667 if (to_jiffies <= 0) {
668 return -EINVAL;
669 }
670 lp_table[minor].timeout = to_jiffies;
671 break;
672
673 default: 651 default:
674 retval = -EINVAL; 652 retval = -EINVAL;
675 } 653 }
676 return retval; 654 return retval;
677} 655}
678 656
657static int lp_set_timeout(unsigned int minor, struct timeval *par_timeout)
658{
659 long to_jiffies;
660
661 /* Convert to jiffies, place in lp_table */
662 if ((par_timeout->tv_sec < 0) ||
663 (par_timeout->tv_usec < 0)) {
664 return -EINVAL;
665 }
666 to_jiffies = DIV_ROUND_UP(par_timeout->tv_usec, 1000000/HZ);
667 to_jiffies += par_timeout->tv_sec * (long) HZ;
668 if (to_jiffies <= 0) {
669 return -EINVAL;
670 }
671 lp_table[minor].timeout = to_jiffies;
672 return 0;
673}
674
675static long lp_ioctl(struct file *file, unsigned int cmd,
676 unsigned long arg)
677{
678 unsigned int minor;
679 struct timeval par_timeout;
680 int ret;
681
682 minor = iminor(file->f_path.dentry->d_inode);
683 lock_kernel();
684 switch (cmd) {
685 case LPSETTIMEOUT:
686 if (copy_from_user(&par_timeout, (void __user *)arg,
687 sizeof (struct timeval))) {
688 ret = -EFAULT;
689 break;
690 }
691 ret = lp_set_timeout(minor, &par_timeout);
692 break;
693 default:
694 ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg);
695 break;
696 }
697 unlock_kernel();
698
699 return ret;
700}
701
702#ifdef CONFIG_COMPAT
703static long lp_compat_ioctl(struct file *file, unsigned int cmd,
704 unsigned long arg)
705{
706 unsigned int minor;
707 struct timeval par_timeout;
708 struct compat_timeval __user *tc;
709 int ret;
710
711 minor = iminor(file->f_path.dentry->d_inode);
712 lock_kernel();
713 switch (cmd) {
714 case LPSETTIMEOUT:
715 tc = compat_ptr(arg);
716 if (get_user(par_timeout.tv_sec, &tc->tv_sec) ||
717 get_user(par_timeout.tv_usec, &tc->tv_usec)) {
718 ret = -EFAULT;
719 break;
720 }
721 ret = lp_set_timeout(minor, &par_timeout);
722 break;
723#ifdef LP_STATS
724 case LPGETSTATS:
725 /* FIXME: add an implementation if you set LP_STATS */
726 ret = -EINVAL;
727 break;
728#endif
729 default:
730 ret = lp_do_ioctl(minor, cmd, arg, compat_ptr(arg));
731 break;
732 }
733 unlock_kernel();
734
735 return ret;
736}
737#endif
738
679static const struct file_operations lp_fops = { 739static const struct file_operations lp_fops = {
680 .owner = THIS_MODULE, 740 .owner = THIS_MODULE,
681 .write = lp_write, 741 .write = lp_write,
682 .ioctl = lp_ioctl, 742 .unlocked_ioctl = lp_ioctl,
743#ifdef CONFIG_COMPAT
744 .compat_ioctl = lp_compat_ioctl,
745#endif
683 .open = lp_open, 746 .open = lp_open,
684 .release = lp_release, 747 .release = lp_release,
685#ifdef CONFIG_PARPORT_1284 748#ifdef CONFIG_PARPORT_1284