ChangeSet 1.1002.3.13, 2003/02/21 17:03:07-08:00, greg@kroah.com [PATCH] USB pl2303: add locking now that the usb-serial core doesn't protect us. drivers/usb/serial/pl2303.c | 88 ++++++++++++++++++++++++++------------------ 1 files changed, 53 insertions(+), 35 deletions(-) diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c --- a/drivers/usb/serial/pl2303.c Fri Feb 28 14:50:42 2003 +++ b/drivers/usb/serial/pl2303.c Fri Feb 28 14:50:42 2003 @@ -148,7 +148,8 @@ .shutdown = pl2303_shutdown, }; -struct pl2303_private { +struct pl2303_private { + spinlock_t lock; u8 line_control; u8 termios_initialized; }; @@ -164,6 +165,7 @@ if (!priv) return -ENOMEM; memset (priv, 0x00, sizeof (struct pl2303_private)); + spin_lock_init(&priv->lock); usb_set_serial_port_data(&serial->port[i], priv); } return 0; @@ -223,18 +225,21 @@ int baud; int i; - dbg("%s - port %d, initialized = %d", __FUNCTION__, port->number, priv->termios_initialized); + dbg("%s - port %d", __FUNCTION__, port->number); if ((!port->tty) || (!port->tty->termios)) { dbg("%s - no tty structures", __FUNCTION__); return; } + spin_lock(&priv->lock); if (!priv->termios_initialized) { *(port->tty->termios) = tty_std_termios; port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; priv->termios_initialized = 1; } + spin_unlock(&priv->lock); + cflag = port->tty->termios->c_cflag; /* check that they really want us to change something */ if (old_termios) { @@ -341,11 +346,16 @@ dbg ("0x21:0x20:0:0 %d", i); if (cflag && CBAUD) { + u8 control; + + spin_lock (&priv->lock); if ((cflag && CBAUD) == B0) priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); else priv->line_control |= (CONTROL_DTR | CONTROL_RTS); - set_control_lines (serial->dev, priv->line_control); + control = priv->line_control; + spin_unlock (&priv->lock); + set_control_lines (serial->dev, control); } buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0; @@ -444,48 +454,50 @@ dbg("%s - port %d", __FUNCTION__, port->number); - if (serial->dev) { - if (port->tty) { - c_cflag = port->tty->termios->c_cflag; - if (c_cflag & HUPCL) { - /* drop DTR and RTS */ - priv = usb_get_serial_port_data(port); - priv->line_control = 0; - set_control_lines (port->serial->dev, - priv->line_control); - } - } + /* shutdown our urbs */ + dbg("%s - shutting down urbs", __FUNCTION__); + result = usb_unlink_urb (port->write_urb); + if (result) + dbg("%s - usb_unlink_urb (write_urb)" + " failed with reason: %d", __FUNCTION__, + result); + + result = usb_unlink_urb (port->read_urb); + if (result) + dbg("%s - usb_unlink_urb (read_urb) " + "failed with reason: %d", __FUNCTION__, + result); - /* shutdown our urbs */ - dbg("%s - shutting down urbs", __FUNCTION__); - result = usb_unlink_urb (port->write_urb); - if (result) - dbg("%s - usb_unlink_urb (write_urb)" - " failed with reason: %d", __FUNCTION__, - result); - - result = usb_unlink_urb (port->read_urb); - if (result) - dbg("%s - usb_unlink_urb (read_urb) " - "failed with reason: %d", __FUNCTION__, - result); - - result = usb_unlink_urb (port->interrupt_in_urb); - if (result) - dbg("%s - usb_unlink_urb (interrupt_in_urb)" - " failed with reason: %d", __FUNCTION__, - result); + result = usb_unlink_urb (port->interrupt_in_urb); + if (result) + dbg("%s - usb_unlink_urb (interrupt_in_urb)" + " failed with reason: %d", __FUNCTION__, + result); + + if (port->tty) { + c_cflag = port->tty->termios->c_cflag; + if (c_cflag & HUPCL) { + /* drop DTR and RTS */ + priv = usb_get_serial_port_data(port); + spin_lock (&priv->lock); + priv->line_control = 0; + spin_unlock (&priv->lock); + set_control_lines (port->serial->dev, 0); + } } + } static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsigned int *value) { struct pl2303_private *priv = usb_get_serial_port_data(port); unsigned int arg; + u8 control; if (copy_from_user(&arg, value, sizeof(int))) return -EFAULT; + spin_lock (&priv->lock); switch (cmd) { case TIOCMBIS: if (arg & TIOCM_RTS) @@ -509,15 +521,21 @@ priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0); break; } + control = priv->line_control; + spin_unlock (&priv->lock); - return set_control_lines (port->serial->dev, priv->line_control); + return set_control_lines (port->serial->dev, control); } static int get_modem_info (struct usb_serial_port *port, unsigned int *value) { struct pl2303_private *priv = usb_get_serial_port_data(port); - unsigned int mcr = priv->line_control; + unsigned int mcr; unsigned int result; + + spin_lock (&priv->lock); + mcr = priv->line_control; + spin_unlock (&priv->lock); result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0);