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 92a54cb..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
 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);
 }
@@ -304,7 +308,7 @@ static ssize_t lp_write(struct file * file, const char __user * 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 __user * 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 __user * 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;
@@ -410,6 +416,7 @@ static ssize_t lp_write(struct file * file, const char __user * 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 __user * 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;
@@ -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);
@@ -899,7 +908,7 @@ static 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 @@ static 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);