Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / char / lp.c
index c1437fb..e572605 100644 (file)
@@ -12,7 +12,7 @@
  * "lp=" command line parameters added by Grant Guenther, grant@torque.net
  * lp_read (Status readback) support added by Carsten Gross,
  *                                             carsten@sol.wohnheim.uni-ulm.de
- * Support for parport by Philip Blundell <Philip.Blundell@pobox.com>
+ * Support for parport by Philip Blundell <philb@gnu.org>
  * Parport sharing hacking by Andrea Arcangeli
  * Fixed kernel_(to/from)_user memory copy to check for errors
  *                             by Riccardo Facchetti <fizban@tin.it>
 #include <linux/poll.h>
 #include <linux/console.h>
 #include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/jiffies.h>
 
 #include <linux/parport.h>
 #undef LP_STATS
 /* ROUND_UP macro from fs/select.c */
 #define ROUND_UP(x,y) (((x)+(y)-1)/(y))
 
-struct lp_struct lp_table[LP_NO];
+static struct lp_struct lp_table[LP_NO];
 
 static unsigned int lp_count = 0;
-static struct class_simple *lp_class;
+static struct class *lp_class;
 
 #ifdef CONFIG_LP_CONSOLE
 static struct parport *console_registered; // initially NULL
@@ -218,6 +220,7 @@ static int lp_reset(int minor)
 
 static void lp_error (int minor)
 {
+       DEFINE_WAIT(wait);
        int polling;
 
        if (LP_F(minor) & LP_ABORT)
@@ -225,8 +228,9 @@ static void lp_error (int minor)
 
        polling = lp_table[minor].dev->port->irq == PARPORT_IRQ_NONE;
        if (polling) lp_release_parport (&lp_table[minor]);
-       interruptible_sleep_on_timeout (&lp_table[minor].waitq,
-                                       LP_TIMEOUT_POLLED);
+       prepare_to_wait(&lp_table[minor].waitq, &wait, TASK_INTERRUPTIBLE);
+       schedule_timeout(LP_TIMEOUT_POLLED);
+       finish_wait(&lp_table[minor].waitq, &wait);
        if (polling) lp_claim_parport_or_block (&lp_table[minor]);
        else parport_yield_blocking (lp_table[minor].dev);
 }
@@ -291,7 +295,7 @@ static int lp_wait_ready(int minor, int nonblock)
        return error;
 }
 
-static ssize_t lp_write(struct file * file, const char * buf,
+static ssize_t lp_write(struct file * file, const char __user * buf,
                        size_t count, loff_t *ppos)
 {
        unsigned int minor = iminor(file->f_dentry->d_inode);
@@ -304,7 +308,7 @@ static ssize_t lp_write(struct file * file, const char * buf,
                        (LP_F(minor) & LP_ABORT));
 
 #ifdef LP_STATS
-       if (jiffies-lp_table[minor].lastcall > LP_TIME(minor))
+       if (time_after(jiffies, lp_table[minor].lastcall + LP_TIME(minor)))
                lp_table[minor].runchars = 0;
 
        lp_table[minor].lastcall = jiffies;
@@ -314,12 +318,14 @@ static ssize_t lp_write(struct file * file, const char * buf,
        if (copy_size > LP_BUFFER_SIZE)
                copy_size = LP_BUFFER_SIZE;
 
-       if (copy_from_user (kbuf, buf, copy_size))
-               return -EFAULT;
-
        if (down_interruptible (&lp_table[minor].port_mutex))
                return -EINTR;
 
+       if (copy_from_user (kbuf, buf, copy_size)) {
+               retv = -EFAULT;
+               goto out_unlock;
+       }
+
        /* Claim Parport or sleep until it becomes available
         */
        lp_claim_parport_or_block (&lp_table[minor]);
@@ -398,7 +404,7 @@ static ssize_t lp_write(struct file * file, const char * buf,
                lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
                lp_release_parport (&lp_table[minor]);
        }
-
+out_unlock:
        up (&lp_table[minor].port_mutex);
 
        return retv;
@@ -407,9 +413,10 @@ static ssize_t lp_write(struct file * file, const char * buf,
 #ifdef CONFIG_PARPORT_1284
 
 /* Status readback conforming to ieee1284 */
-static ssize_t lp_read(struct file * file, char * buf,
+static ssize_t lp_read(struct file * file, char __user * buf,
                       size_t count, loff_t *ppos)
 {
+       DEFINE_WAIT(wait);
        unsigned int minor=iminor(file->f_dentry->d_inode);
        struct parport *port = lp_table[minor].dev->port;
        ssize_t retval = 0;
@@ -458,9 +465,11 @@ static ssize_t lp_read(struct file * file, char * buf,
                                retval = -EIO;
                                goto out;
                        }
-               } else
-                       interruptible_sleep_on_timeout (&lp_table[minor].waitq,
-                                                       LP_TIMEOUT_POLLED);
+               } else {
+                       prepare_to_wait(&lp_table[minor].waitq, &wait, TASK_INTERRUPTIBLE);
+                       schedule_timeout(LP_TIMEOUT_POLLED);
+                       finish_wait(&lp_table[minor].waitq, &wait);
+               }
 
                if (signal_pending (current)) {
                        retval = -ERESTARTSYS;
@@ -560,6 +569,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
        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);
@@ -603,7 +613,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                        return -EINVAL;
                        break;
                case LPGETIRQ:
-                       if (copy_to_user((int *) arg, &LP_IRQ(minor),
+                       if (copy_to_user(argp, &LP_IRQ(minor),
                                        sizeof(int)))
                                return -EFAULT;
                        break;
@@ -612,7 +622,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                        status = r_str(minor);
                        lp_release_parport (&lp_table[minor]);
 
-                       if (copy_to_user((int *) arg, &status, sizeof(int)))
+                       if (copy_to_user(argp, &status, sizeof(int)))
                                return -EFAULT;
                        break;
                case LPRESET:
@@ -620,7 +630,7 @@ static int lp_ioctl(struct inode *inode, struct file *file,
                        break;
 #ifdef LP_STATS
                case LPGETSTATS:
-                       if (copy_to_user((int *) arg, &LP_STAT(minor),
+                       if (copy_to_user(argp, &LP_STAT(minor),
                                        sizeof(struct lp_stats)))
                                return -EFAULT;
                        if (capable(CAP_SYS_ADMIN))
@@ -630,13 +640,12 @@ static int lp_ioctl(struct inode *inode, struct file *file,
 #endif
                case LPGETFLAGS:
                        status = LP_F(minor);
-                       if (copy_to_user((int *) arg, &status, sizeof(int)))
+                       if (copy_to_user(argp, &status, sizeof(int)))
                                return -EFAULT;
                        break;
 
                case LPSETTIMEOUT:
-                       if (copy_from_user (&par_timeout,
-                                           (struct timeval *) arg,
+                       if (copy_from_user (&par_timeout, argp,
                                            sizeof (struct timeval))) {
                                return -EFAULT;
                        }
@@ -749,8 +758,8 @@ static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC };
 static char *parport[LP_NO] = { NULL,  };
 static int reset = 0;
 
-MODULE_PARM(parport, "1-" __MODULE_STRING(LP_NO) "s");
-MODULE_PARM(reset, "i");
+module_param_array(parport, charp, NULL, 0);
+module_param(reset, bool, 0);
 
 #ifndef MODULE
 static int __init lp_setup (char *str)
@@ -796,7 +805,7 @@ static int lp_register(int nr, struct parport *port)
        if (reset)
                lp_reset(nr);
 
-       class_simple_device_add(lp_class, MKDEV(LP_MAJOR, nr), NULL,
+       class_device_create(lp_class, NULL, MKDEV(LP_MAJOR, nr), NULL,
                                "lp%d", nr);
        devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
                        "printers/%d", nr);
@@ -867,7 +876,7 @@ static struct parport_driver lp_driver = {
        .detach = lp_detach,
 };
 
-int __init lp_init (void)
+static int __init lp_init (void)
 {
        int i, err = 0;
 
@@ -899,7 +908,7 @@ int __init lp_init (void)
        }
 
        devfs_mk_dir("printers");
-       lp_class = class_simple_create(THIS_MODULE, "printer");
+       lp_class = class_create(THIS_MODULE, "printer");
        if (IS_ERR(lp_class)) {
                err = PTR_ERR(lp_class);
                goto out_devfs;
@@ -922,7 +931,7 @@ int __init lp_init (void)
        return 0;
 
 out_class:
-       class_simple_destroy(lp_class);
+       class_destroy(lp_class);
 out_devfs:
        devfs_remove("printers");
        unregister_chrdev(LP_MAJOR, "lp");
@@ -973,10 +982,10 @@ static void lp_cleanup_module (void)
                        continue;
                parport_unregister_device(lp_table[offset].dev);
                devfs_remove("printers/%d", offset);
-               class_simple_device_remove(MKDEV(LP_MAJOR, offset));
+               class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
        }
        devfs_remove("printers");
-       class_simple_destroy(lp_class);
+       class_destroy(lp_class);
 }
 
 __setup("lp=", lp_setup);