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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel