ChangeSet 1.1119.3.3, 2003/09/04 08:52:26-07:00, [EMAIL PROTECTED]
[PATCH] USB: backport some pl2303 B0 fixes.
Also add proper locking for the port structure. This comes from the 2.6
kernel tree too.
drivers/usb/serial/pl2303.c | 111 ++++++++++++++++++++++++++++++++------------
1 files changed, 81 insertions(+), 30 deletions(-)
diff -Nru a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
--- a/drivers/usb/serial/pl2303.c Fri Sep 5 17:10:55 2003
+++ b/drivers/usb/serial/pl2303.c Fri Sep 5 17:10:55 2003
@@ -153,7 +153,8 @@
.shutdown = pl2303_shutdown,
};
-struct pl2303_private {
+struct pl2303_private {
+ spinlock_t lock;
u8 line_control;
u8 line_status;
u8 termios_initialized;
@@ -170,7 +171,8 @@
if (!priv)
return -ENOMEM;
memset (priv, 0x00, sizeof (struct pl2303_private));
- serial->port[i].private = priv;
+ spin_lock_init(&priv->lock);
+ usb_set_serial_port_data(&serial->port[i], priv);
}
return 0;
}
@@ -223,25 +225,30 @@
static void pl2303_set_termios (struct usb_serial_port *port, struct termios
*old_termios)
{
struct usb_serial *serial = port->serial;
- struct pl2303_private *priv;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
unsigned int cflag;
unsigned char *buf;
int baud;
int i;
+ u8 control;
dbg("%s - port %d, initialized = %d", __FUNCTION__, port->number,
- ((struct pl2303_private *) port->private)->termios_initialized);
+ priv->termios_initialized);
if ((!port->tty) || (!port->tty->termios)) {
dbg("%s - no tty structures", __FUNCTION__);
return;
}
- if (!(((struct pl2303_private *) port->private)->termios_initialized)) {
+ spin_lock_irqsave(&priv->lock, flags);
+ if (!priv->termios_initialized) {
*(port->tty->termios) = tty_std_termios;
port->tty->termios->c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
- ((struct pl2303_private *) port->private)->termios_initialized = 1;
+ priv->termios_initialized = 1;
}
+ spin_unlock_irqrestore(&priv->lock, flags);
+
cflag = port->tty->termios->c_cflag;
/* check that they really want us to change something */
if (old_termios) {
@@ -341,13 +348,19 @@
0, 0, buf, 7, 100);
dbg ("0x21:0x20:0:0 %d", i);
- if (cflag && CBAUD) {
- priv = port->private;
- 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);
+ /* change control lines if we are switching to or from B0 */
+ spin_lock_irqsave(&priv->lock, flags);
+ control = priv->line_control;
+ if ((cflag & CBAUD) == B0)
+ priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+ else
+ priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+ if (control != priv->line_control) {
+ control = priv->line_control;
+ spin_unlock_irqrestore(&priv->lock, flags);
+ set_control_lines(serial->dev, control);
+ } else {
+ spin_unlock_irqrestore(&priv->lock, flags);
}
buf[0] = buf[1] = buf[2] = buf[3] = buf[4] = buf[5] = buf[6] = 0;
@@ -435,6 +448,7 @@
{
struct usb_serial *serial;
struct pl2303_private *priv;
+ unsigned long flags;
unsigned int c_cflag;
int result;
@@ -451,10 +465,11 @@
c_cflag = port->tty->termios->c_cflag;
if (c_cflag & HUPCL) {
/* drop DTR and RTS */
- priv = port->private;
+ priv = usb_get_serial_port_data(port);
+ spin_lock_irqsave(&priv->lock, flags);
priv->line_control = 0;
- set_control_lines (port->serial->dev,
- priv->line_control);
+ spin_unlock_irqrestore (&priv->lock, flags);
+ set_control_lines (port->serial->dev, 0);
}
}
@@ -482,12 +497,15 @@
static int set_modem_info (struct usb_serial_port *port, unsigned int cmd, unsigned
int *value)
{
- struct pl2303_private *priv = port->private;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
unsigned int arg;
+ u8 control;
if (copy_from_user(&arg, value, sizeof(int)))
return -EFAULT;
+ spin_lock_irqsave (&priv->lock, flags);
switch (cmd) {
case TIOCMBIS:
if (arg & TIOCM_RTS)
@@ -511,17 +529,25 @@
priv->line_control |= ((arg & TIOCM_DTR) ? CONTROL_DTR : 0);
break;
}
+ control = priv->line_control;
+ spin_unlock_irqrestore (&priv->lock, flags);
- 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 = port->private;
- unsigned int mcr = priv->line_control;
- unsigned int status = priv->line_status;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+ unsigned long flags;
+ unsigned int mcr;
+ unsigned int status;
unsigned int result;
+ spin_lock_irqsave (&priv->lock, flags);
+ mcr = priv->line_control;
+ status = priv->line_status;
+ spin_unlock_irqrestore (&priv->lock, flags);
+
result = ((mcr & CONTROL_DTR) ? TIOCM_DTR : 0)
| ((mcr & CONTROL_RTS) ? TIOCM_RTS : 0)
| ((status & UART_CTS) ? TIOCM_CTS : 0)
@@ -560,7 +586,6 @@
return -ENOIOCTLCMD;
}
-
static void pl2303_break_ctl (struct usb_serial_port *port, int break_state)
{
struct usb_serial *serial = port->serial;
@@ -589,8 +614,10 @@
dbg("%s", __FUNCTION__);
- for (i = 0; i < serial->num_ports; ++i)
- kfree (serial->port[i].private);
+ for (i = 0; i < serial->num_ports; ++i) {
+ kfree (usb_get_serial_port_data(&serial->port[i]));
+ usb_set_serial_port_data(&serial->port[i], NULL);
+ }
}
@@ -598,17 +625,30 @@
{
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
- struct pl2303_private *priv = port->private;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
unsigned char *data = urb->transfer_buffer;
+ unsigned long flags;
+
+ dbg("%s (%d)", __FUNCTION__, port->number);
/* ints auto restart... */
- if (!serial) {
+ switch (urb->status) {
+ case 0:
+ /* success */
+ break;
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ /* this urb is terminated, clean up */
+ dbg("%s - urb shutting down with status: %d", __FUNCTION__,
urb->status);
+ return;
+ default:
+ dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status);
return;
}
- if (urb->status) {
- urb->status = 0;
+ if (!serial) {
return;
}
@@ -618,7 +658,9 @@
return;
/* Save off the uart status for others to look at */
+ spin_lock_irqsave(&priv->lock, flags);
priv->line_status = data[UART_STATE];
+ spin_unlock_irqrestore(&priv->lock, flags);
return;
}
@@ -628,9 +670,10 @@
{
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
struct usb_serial *serial = get_usb_serial (port, __FUNCTION__);
- struct pl2303_private *priv = port->private;
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
struct tty_struct *tty;
unsigned char *data = urb->transfer_buffer;
+ unsigned long flags;
int i;
int result;
u8 status;
@@ -670,7 +713,10 @@
/* get tty_flag from status */
tty_flag = TTY_NORMAL;
+
+ spin_lock_irqsave(&priv->lock, flags);
status = priv->line_status;
+ spin_unlock_irqrestore(&priv->lock, flags);
/* break takes precedence over parity, */
/* which takes precedence over framing errors */
@@ -745,9 +791,14 @@
static int __init pl2303_init (void)
{
- usb_serial_register (&pl2303_device);
+ int retval;
+ retval = usb_serial_register(&pl2303_device);
+ if (retval)
+ goto failed_usb_serial_register;
info(DRIVER_DESC " " DRIVER_VERSION);
return 0;
+failed_usb_serial_register:
+ return retval;
}
-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel