Most of the changes are just error/debug messages improvements and the addition of uart_port statatistics.
Additionally, pl2303_update_line_status() was completely ported and pl2303_read_bulk_callback() modified to to handle -ECONNRESET and -ENOENT. Signed-off-by: Luiz Fernando N. Capitulino <[EMAIL PROTECTED]> --- drivers/usb/serial/pl2303.c | 119 +++++++++++++++++++++++++++---------------- 1 files changed, 74 insertions(+), 45 deletions(-) diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index f93da0b..6d24733 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -883,6 +883,7 @@ static void pl2303_update_line_status(st { struct pl2303_private *priv = usb_get_serial_port_data(port); + char delta_status; unsigned long flags; u8 status_idx = UART_STATE; u8 length = UART_STATE + 1; @@ -896,16 +897,29 @@ static void pl2303_update_line_status(st } if (actual_length < length) - goto exit; + return; /* Save off the uart status for others to look at */ spin_lock_irqsave(&priv->lock, flags); + delta_status = data[status_idx] ^ priv->line_status; priv->line_status = data[status_idx]; - spin_unlock_irqrestore(&priv->lock, flags); - wake_up_interruptible (&priv->delta_msr_wait); -exit: - return; + if (delta_status) { + if (delta_status & UART_RING) + port->uart_port.icount.rng++; + if (delta_status & UART_DSR) + port->uart_port.icount.dsr++; + if (delta_status & UART_DCD) + uart_handle_dcd_change(&port->uart_port, + delta_status & UART_DCD); + if (delta_status & UART_CTS) + uart_handle_cts_change(&port->uart_port, + delta_status & UART_CTS); + + wake_up_interruptible(&port->uart_port.info->delta_msr_wait); + } + + spin_unlock_irqrestore(&priv->lock, flags); } static void pl2303_read_int_callback (struct urb *urb, struct pt_regs *regs) @@ -915,11 +929,13 @@ static void pl2303_read_int_callback (st unsigned int actual_length = urb->actual_length; int status; - dbg("(%d)", port->number); + dbg("port %d", port->uart_port.line); switch (urb->status) { case 0: /* success */ + port->uart_port.icount.rx += actual_length; + dbg("URB transfered with success"); break; case -ECONNRESET: case -ENOENT: @@ -928,7 +944,8 @@ static void pl2303_read_int_callback (st dbg("urb shutting down with status: %d", urb->status); return; default: - dbg("nonzero urb status received: %d", urb->status); + dev_err(&urb->dev->dev, "nonzero urb status received: %d", + urb->status); goto exit; } @@ -942,7 +959,6 @@ exit: __FUNCTION__, status); } - static void pl2303_read_bulk_callback (struct urb *urb, struct pt_regs *regs) { struct usb_serial_port *port = (struct usb_serial_port *) urb->context; @@ -955,25 +971,33 @@ static void pl2303_read_bulk_callback (s u8 status; char tty_flag; - dbg("port %d", port->number); + dbg("port %d", port->uart_port.line); + dbg("urb->status = %d", urb->status); - if (urb->status) { - dbg("urb->status = %d", urb->status); - if (!port->open_count) { - dbg("port is closed, exiting."); - return; - } - if (urb->status == -EPROTO) { - /* PL2303 mysteriously fails with -EPROTO reschedule the read */ - dbg("caught -EPROTO, resubmitting the urb"); - urb->status = 0; - urb->dev = port->serial->dev; - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) - dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); - return; + switch (urb->status) { + case 0: + /* success */ + break; + case -EPROTO: + /* PL2303 mysteriously fails with -EPROTO reschedule the read */ + dbg("caught -EPROTO, resubmitting the urb"); + urb->status = 0; + urb->dev = port->serial->dev; + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) { + dev_err(&urb->dev->dev, + "%s - failed resubmitting read urb, error %d\n", + __FUNCTION__, result); } - dbg("unable to handle the error, exiting."); + return; + case -ECONNRESET: + case -ENOENT: + /* this urb is terminated, clean up */ + dbg("urb shutting down with status: %d", urb->status); + return; + default: + dev_err(&urb->dev->dev, "%s - unable to handle the error, exiting.", + __FUNCTION__); return; } @@ -986,53 +1010,59 @@ static void pl2303_read_bulk_callback (s status = priv->line_status; priv->line_status &= ~UART_STATE_TRANSIENT_MASK; spin_unlock_irqrestore(&priv->lock, flags); - wake_up_interruptible (&priv->delta_msr_wait); + wake_up_interruptible(&port->uart_port.info->delta_msr_wait); /* break takes precedence over parity, */ /* which takes precedence over framing errors */ - if (status & UART_BREAK_ERROR ) + if (status & UART_BREAK_ERROR ) { tty_flag = TTY_BREAK; - else if (status & UART_PARITY_ERROR) + port->uart_port.icount.brk++; + } else if (status & UART_PARITY_ERROR) { tty_flag = TTY_PARITY; - else if (status & UART_FRAME_ERROR) + port->uart_port.icount.parity++; + } else if (status & UART_FRAME_ERROR) { tty_flag = TTY_FRAME; + port->uart_port.icount.frame++; + } dbg("tty_flag = %d", tty_flag); - tty = port->tty; + tty = port->uart_port.info->tty; if (tty && urb->actual_length) { tty_buffer_request_room(tty, urb->actual_length + 1); /* overrun is special, not associated with a char */ - if (status & UART_OVERRUN_ERROR) + if (status & UART_OVERRUN_ERROR) { tty_insert_flip_char(tty, 0, TTY_OVERRUN); + port->uart_port.icount.overrun++; + } for (i = 0; i < urb->actual_length; ++i) tty_insert_flip_char (tty, data[i], tty_flag); tty_flip_buffer_push (tty); + port->uart_port.icount.rx += urb->actual_length; + dbg("pushed %d bytes to flip buffer", urb->actual_length); } - /* Schedule the next read _if_ we are still open */ - if (port->open_count) { - urb->dev = port->serial->dev; - result = usb_submit_urb(urb, GFP_ATOMIC); - if (result) - dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); + urb->dev = port->serial->dev; + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) { + dev_err(&urb->dev->dev, + "%s - failed resubmitting read urb, error %d\n", + __FUNCTION__, result); } - - return; } - - static void pl2303_write_bulk_callback (struct urb *urb, struct pt_regs *regs) { struct usb_serial_port *port = (struct usb_serial_port *) urb->context; struct pl2303_private *priv = usb_get_serial_port_data(port); int result; - dbg("port %d", port->number); + dbg("port %d", port->uart_port.line); switch (urb->status) { case 0: /* success */ + port->uart_port.icount.tx += urb->actual_length; + dbg("URB transfered with success"); break; case -ECONNRESET: case -ENOENT: @@ -1043,8 +1073,8 @@ static void pl2303_write_bulk_callback ( return; default: /* error in the urb, so we have to resubmit it */ - dbg("Overflow in write"); - dbg("nonzero write bulk status received: %d", urb->status); + dev_err(&urb->dev->dev, "Overflow in write"); + dev_err(&urb->dev->dev, "nonzero write bulk status received: %d", urb->status); port->write_urb->transfer_buffer_length = 1; port->write_urb->dev = port->serial->dev; result = usb_submit_urb (port->write_urb, GFP_ATOMIC); @@ -1060,7 +1090,6 @@ static void pl2303_write_bulk_callback ( pl2303_send(port); } - /* * pl2303_buf_alloc * -- 1.3.3.g0825d _______________________________________________ linux-usb-devel@lists.sourceforge.net To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel