USB: ftdi_sio: add Basic Micro ATOM Nano USB2Serial PID
[pandora-kernel.git] / drivers / usb / serial / mct_u232.c
index ba0d287..96a62dd 100644 (file)
@@ -168,8 +168,6 @@ struct mct_u232_private {
        unsigned char        last_msr;      /* Modem Status Register */
        unsigned int         rx_flags;      /* Throttling flags */
        struct async_icount  icount;
-       wait_queue_head_t    msr_wait;  /* for handling sleeping while waiting
-                                               for msr change to happen */
 };
 
 #define THROTTLED              0x01
@@ -359,13 +357,16 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial,
                        MCT_U232_SET_REQUEST_TYPE,
                        0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE,
                        WDR_TIMEOUT);
-       if (rc < 0)
-               dev_err(&serial->dev->dev,
-                       "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
+       kfree(buf);
+
        dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr);
 
-       kfree(buf);
-       return rc;
+       if (rc < 0) {
+               dev_err(&serial->dev->dev,
+                       "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc);
+               return rc;
+       }
+       return 0;
 } /* mct_u232_set_modem_ctrl */
 
 static int mct_u232_get_modem_stat(struct usb_serial *serial,
@@ -446,7 +447,6 @@ static int mct_u232_startup(struct usb_serial *serial)
        if (!priv)
                return -ENOMEM;
        spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->msr_wait);
        usb_set_serial_port_data(serial->port[0], priv);
 
        init_waitqueue_head(&serial->port[0]->write_wait);
@@ -555,31 +555,29 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
        unsigned int control_state;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
 
-       mutex_lock(&port->serial->disc_mutex);
-       if (!port->serial->disconnected) {
-               /* drop DTR and RTS */
-               spin_lock_irq(&priv->lock);
-               if (on)
-                       priv->control_state |= TIOCM_DTR | TIOCM_RTS;
-               else
-                       priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-               control_state = priv->control_state;
-               spin_unlock_irq(&priv->lock);
-               mct_u232_set_modem_ctrl(port->serial, control_state);
-       }
-       mutex_unlock(&port->serial->disc_mutex);
+       spin_lock_irq(&priv->lock);
+       if (on)
+               priv->control_state |= TIOCM_DTR | TIOCM_RTS;
+       else
+               priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+       control_state = priv->control_state;
+       spin_unlock_irq(&priv->lock);
+
+       mct_u232_set_modem_ctrl(port->serial, control_state);
 }
 
 static void mct_u232_close(struct usb_serial_port *port)
 {
        dbg("%s port %d", __func__, port->number);
 
-       if (port->serial->dev) {
-               /* shutdown our urbs */
-               usb_kill_urb(port->write_urb);
-               usb_kill_urb(port->read_urb);
-               usb_kill_urb(port->interrupt_in_urb);
-       }
+       /*
+        * Must kill the read urb as it is actually an interrupt urb, which
+        * generic close thus fails to kill.
+        */
+       usb_kill_urb(port->read_urb);
+       usb_kill_urb(port->interrupt_in_urb);
+
+       usb_serial_generic_close(port);
 } /* mct_u232_close */
 
 
@@ -674,7 +672,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
                tty_kref_put(tty);
        }
 #endif
-       wake_up_interruptible(&priv->msr_wait);
+       wake_up_interruptible(&port->delta_msr_wait);
        spin_unlock_irqrestore(&priv->lock, flags);
 exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -895,13 +893,17 @@ static int  mct_u232_ioctl(struct tty_struct *tty,
                cprev = mct_u232_port->icount;
                spin_unlock_irqrestore(&mct_u232_port->lock, flags);
                for ( ; ; ) {
-                       prepare_to_wait(&mct_u232_port->msr_wait,
+                       prepare_to_wait(&port->delta_msr_wait,
                                        &wait, TASK_INTERRUPTIBLE);
                        schedule();
-                       finish_wait(&mct_u232_port->msr_wait, &wait);
+                       finish_wait(&port->delta_msr_wait, &wait);
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
                        spin_lock_irqsave(&mct_u232_port->lock, flags);
                        cnow = mct_u232_port->icount;
                        spin_unlock_irqrestore(&mct_u232_port->lock, flags);