]> err.no Git - linux-2.6/blobdiff - drivers/usb/serial/cypress_m8.c
[MIPS] Added missing cases for rdhwr emulation
[linux-2.6] / drivers / usb / serial / cypress_m8.c
index 163386336a5daa76852eda408974ace308bf2176..779d07851a4d820a4e32c372ed2e745798c82a27 100644 (file)
@@ -94,6 +94,7 @@ static struct usb_device_id id_table_earthmate [] = {
 
 static struct usb_device_id id_table_cyphidcomrs232 [] = {
        { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
+       { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
        { }                                             /* Terminating entry */
 };
 
@@ -106,6 +107,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB) },
        { USB_DEVICE(VENDOR_ID_DELORME, PRODUCT_ID_EARTHMATEUSB_LT20) },
        { USB_DEVICE(VENDOR_ID_CYPRESS, PRODUCT_ID_CYPHIDCOM) },
+       { USB_DEVICE(VENDOR_ID_POWERCOM, PRODUCT_ID_UPS) },
        { USB_DEVICE(VENDOR_ID_DAZZLE, PRODUCT_ID_CA42) },
        { }                                             /* Terminating entry */
 };
@@ -682,7 +684,6 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
 {
        struct cypress_private *priv = usb_get_serial_port_data(port);
        unsigned int c_cflag;
-       unsigned long flags;
        int bps;
        long timeout;
        wait_queue_t wait;
@@ -690,7 +691,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
        dbg("%s - port %d", __FUNCTION__, port->number);
 
        /* wait for data to drain from buffer */
-       spin_lock_irqsave(&priv->lock, flags);
+       spin_lock_irq(&priv->lock);
        timeout = CYPRESS_CLOSING_WAIT;
        init_waitqueue_entry(&wait, current);
        add_wait_queue(&port->tty->write_wait, &wait);
@@ -698,18 +699,25 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
                set_current_state(TASK_INTERRUPTIBLE);
                if (cypress_buf_data_avail(priv->buf) == 0
                || timeout == 0 || signal_pending(current)
-               || !usb_get_intfdata(port->serial->interface))
+               /* without mutex, allowed due to harmless failure mode */
+               || port->serial->disconnected)
                        break;
-               spin_unlock_irqrestore(&priv->lock, flags);
+               spin_unlock_irq(&priv->lock);
                timeout = schedule_timeout(timeout);
-               spin_lock_irqsave(&priv->lock, flags);
+               spin_lock_irq(&priv->lock);
        }
        set_current_state(TASK_RUNNING);
        remove_wait_queue(&port->tty->write_wait, &wait);
        /* clear out any remaining data in the buffer */
        cypress_buf_clear(priv->buf);
-       spin_unlock_irqrestore(&priv->lock, flags);
-       
+       spin_unlock_irq(&priv->lock);
+
+       /* writing is potentially harmful, lock must be taken */
+       mutex_lock(&port->serial->disc_mutex);
+       if (port->serial->disconnected) {
+               mutex_unlock(&port->serial->disc_mutex);
+               return;
+       }
        /* wait for characters to drain from device */
        bps = tty_get_baud_rate(port->tty);
        if (bps > 1200)
@@ -727,10 +735,10 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
                if (c_cflag & HUPCL) {
                        /* drop dtr and rts */
                        priv = usb_get_serial_port_data(port);
-                       spin_lock_irqsave(&priv->lock, flags);
+                       spin_lock_irq(&priv->lock);
                        priv->line_control = 0;
                        priv->cmd_ctrl = 1;
-                       spin_unlock_irqrestore(&priv->lock, flags);
+                       spin_unlock_irq(&priv->lock);
                        cypress_write(port, NULL, 0);
                }
        }
@@ -738,6 +746,7 @@ static void cypress_close(struct usb_serial_port *port, struct file * filp)
        if (stats)
                dev_info (&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
                          priv->bytes_in, priv->bytes_out, priv->cmd_count);
+       mutex_unlock(&port->serial->disc_mutex);
 } /* cypress_close */