Commit ebfb0e22 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

[PATCH] USB pl2303: add locking now that the usb-serial core doesn't protect us.

parent 760c712e
...@@ -148,7 +148,8 @@ static struct usb_serial_device_type pl2303_device = { ...@@ -148,7 +148,8 @@ static struct usb_serial_device_type pl2303_device = {
.shutdown = pl2303_shutdown, .shutdown = pl2303_shutdown,
}; };
struct pl2303_private { struct pl2303_private {
spinlock_t lock;
u8 line_control; u8 line_control;
u8 termios_initialized; u8 termios_initialized;
}; };
...@@ -164,6 +165,7 @@ static int pl2303_startup (struct usb_serial *serial) ...@@ -164,6 +165,7 @@ static int pl2303_startup (struct usb_serial *serial)
if (!priv) if (!priv)
return -ENOMEM; return -ENOMEM;
memset (priv, 0x00, sizeof (struct pl2303_private)); memset (priv, 0x00, sizeof (struct pl2303_private));
spin_lock_init(&priv->lock);
usb_set_serial_port_data(&serial->port[i], priv); usb_set_serial_port_data(&serial->port[i], priv);
} }
return 0; return 0;
...@@ -223,18 +225,21 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol ...@@ -223,18 +225,21 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
int baud; int baud;
int i; 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)) { if ((!port->tty) || (!port->tty->termios)) {
dbg("%s - no tty structures", __FUNCTION__); dbg("%s - no tty structures", __FUNCTION__);
return; return;
} }
spin_lock(&priv->lock);
if (!priv->termios_initialized) { if (!priv->termios_initialized) {
*(port->tty->termios) = tty_std_termios; *(port->tty->termios) = tty_std_termios;
port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
priv->termios_initialized = 1; priv->termios_initialized = 1;
} }
spin_unlock(&priv->lock);
cflag = port->tty->termios->c_cflag; cflag = port->tty->termios->c_cflag;
/* check that they really want us to change something */ /* check that they really want us to change something */
if (old_termios) { if (old_termios) {
...@@ -341,11 +346,16 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol ...@@ -341,11 +346,16 @@ static void pl2303_set_termios (struct usb_serial_port *port, struct termios *ol
dbg ("0x21:0x20:0:0 %d", i); dbg ("0x21:0x20:0:0 %d", i);
if (cflag && CBAUD) { if (cflag && CBAUD) {
u8 control;
spin_lock (&priv->lock);
if ((cflag && CBAUD) == B0) if ((cflag && CBAUD) == B0)
priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
else else
priv->line_control |= (CONTROL_DTR | CONTROL_RTS); 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; buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
...@@ -444,48 +454,50 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp) ...@@ -444,48 +454,50 @@ static void pl2303_close (struct usb_serial_port *port, struct file *filp)
dbg("%s - port %d", __FUNCTION__, port->number); dbg("%s - port %d", __FUNCTION__, port->number);
if (serial->dev) { /* shutdown our urbs */
if (port->tty) { dbg("%s - shutting down urbs", __FUNCTION__);
c_cflag = port->tty->termios->c_cflag; result = usb_unlink_urb (port->write_urb);
if (c_cflag & HUPCL) { if (result)
/* drop DTR and RTS */ dbg("%s - usb_unlink_urb (write_urb)"
priv = usb_get_serial_port_data(port); " failed with reason: %d", __FUNCTION__,
priv->line_control = 0; result);
set_control_lines (port->serial->dev,
priv->line_control);
}
}
/* shutdown our urbs */ result = usb_unlink_urb (port->read_urb);
dbg("%s - shutting down urbs", __FUNCTION__); if (result)
result = usb_unlink_urb (port->write_urb); dbg("%s - usb_unlink_urb (read_urb) "
if (result) "failed with reason: %d", __FUNCTION__,
dbg("%s - usb_unlink_urb (write_urb)" result);
" failed with reason: %d", __FUNCTION__,
result);
result = usb_unlink_urb (port->read_urb); result = usb_unlink_urb (port->interrupt_in_urb);
if (result) if (result)
dbg("%s - usb_unlink_urb (read_urb) " dbg("%s - usb_unlink_urb (interrupt_in_urb)"
"failed with reason: %d", __FUNCTION__, " failed with reason: %d", __FUNCTION__,
result); result);
result = usb_unlink_urb (port->interrupt_in_urb); if (port->tty) {
if (result) c_cflag = port->tty->termios->c_cflag;
dbg("%s - usb_unlink_urb (interrupt_in_urb)" if (c_cflag & HUPCL) {
" failed with reason: %d", __FUNCTION__, /* drop DTR and RTS */
result); 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) 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); struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int arg; unsigned int arg;
u8 control;
if (copy_from_user(&arg, value, sizeof(int))) if (copy_from_user(&arg, value, sizeof(int)))
return -EFAULT; return -EFAULT;
spin_lock (&priv->lock);
switch (cmd) { switch (cmd) {
case TIOCMBIS: case TIOCMBIS:
if (arg & TIOCM_RTS) if (arg & TIOCM_RTS)
...@@ -509,16 +521,22 @@ static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsig ...@@ -509,16 +521,22 @@ static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsig
priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0); priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0);
break; 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) static int get_modem_info (struct usb_serial_port *port, unsigned int *value)
{ {
struct pl2303_private *priv = usb_get_serial_port_data(port); struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned int mcr = priv->line_control; unsigned int mcr;
unsigned int result; unsigned int result;
spin_lock (&priv->lock);
mcr = priv->line_control;
spin_unlock (&priv->lock);
result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0) result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0)
| ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0); | ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment