diff options
author | Arnd Bergmann <arnd@arndb.de> | 2009-11-13 19:33:13 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2009-12-10 16:55:36 -0500 |
commit | 3695669cd4f5fb6d569fd4243312c1b4a05bd5ce (patch) | |
tree | 0e74dafb6f26ac2bbd9d0dcea019798380b55aeb /drivers/char/lp.c | |
parent | 43c6e7b97f9ea0f4dec430dbafb6afa6ac711eb1 (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.c | 115 |
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 | ||
574 | static int lp_ioctl(struct inode *inode, struct file *file, | 575 | static 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 | ||
657 | static 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 | |||
675 | static 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 | ||
703 | static 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 | |||
679 | static const struct file_operations lp_fops = { | 739 | static 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 |