USB: keyspan: fix null-deref at disconnect and release
[pandora-kernel.git] / drivers / usb / serial / ark3116.c
index 5cdb9d9..1a715f6 100644 (file)
@@ -42,14 +42,14 @@ static int debug;
  * Version information
  */
 
-#define DRIVER_VERSION "v0.6"
+#define DRIVER_VERSION "v0.7"
 #define DRIVER_AUTHOR "Bart Hartgers <bart.hartgers+ark3116@gmail.com>"
 #define DRIVER_DESC "USB ARK3116 serial/IrDA driver"
 #define DRIVER_DEV_DESC "ARK3116 RS232/IrDA"
 #define DRIVER_NAME "ark3116"
 
 /* usb timeout of 1 second */
-#define ARK_TIMEOUT (1*HZ)
+#define ARK_TIMEOUT 1000
 
 static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x6547, 0x0232) },
@@ -68,7 +68,6 @@ static int is_irda(struct usb_serial *serial)
 }
 
 struct ark3116_private {
-       wait_queue_head_t       delta_msr_wait;
        struct async_icount     icount;
        int                     irda;   /* 1 for irda device */
 
@@ -148,7 +147,6 @@ static int ark3116_attach(struct usb_serial *serial)
        if (!priv)
                return -ENOMEM;
 
-       init_waitqueue_head(&priv->delta_msr_wait);
        mutex_init(&priv->hw_lock);
        spin_lock_init(&priv->status_lock);
 
@@ -380,10 +378,6 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
                goto err_out;
        }
 
-       /* setup termios */
-       if (tty)
-               ark3116_set_termios(tty, port, NULL);
-
        /* remove any data still left: also clears error state */
        ark3116_read_reg(serial, UART_RX, buf);
 
@@ -406,6 +400,10 @@ static int ark3116_open(struct tty_struct *tty, struct usb_serial_port *port)
        /* enable DMA */
        ark3116_write_reg(port->serial, UART_FCR, UART_FCR_DMA_SELECT);
 
+       /* setup termios */
+       if (tty)
+               ark3116_set_termios(tty, port, NULL);
+
 err_out:
        kfree(buf);
        return result;
@@ -460,10 +458,14 @@ static int ark3116_ioctl(struct tty_struct *tty,
        case TIOCMIWAIT:
                for (;;) {
                        struct async_icount prev = priv->icount;
-                       interruptible_sleep_on(&priv->delta_msr_wait);
+                       interruptible_sleep_on(&port->delta_msr_wait);
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
                        if ((prev.rng == priv->icount.rng) &&
                            (prev.dsr == priv->icount.dsr) &&
                            (prev.dcd == priv->icount.dcd) &&
@@ -584,7 +586,7 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
                        priv->icount.dcd++;
                if (msr & UART_MSR_TERI)
                        priv->icount.rng++;
-               wake_up_interruptible(&priv->delta_msr_wait);
+               wake_up_interruptible(&port->delta_msr_wait);
        }
 }