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

Reply via email to