diff options
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r-- | drivers/usb/serial/ftdi_sio.c | 2 | ||||
-rw-r--r-- | drivers/usb/serial/generic.c | 20 | ||||
-rw-r--r-- | drivers/usb/serial/pl2303.c | 58 | ||||
-rw-r--r-- | drivers/usb/serial/usb-serial.c | 3 |
4 files changed, 51 insertions, 32 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 3dc3768ca71c..5f08702f672f 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -2121,7 +2121,7 @@ static void ftdi_process_read(struct work_struct *work) | |||
2121 | /* Note that the error flag is duplicated for | 2121 | /* Note that the error flag is duplicated for |
2122 | every character received since we don't know | 2122 | every character received since we don't know |
2123 | which character it applied to */ | 2123 | which character it applied to */ |
2124 | if (!usb_serial_handle_sysrq_char(port, | 2124 | if (!usb_serial_handle_sysrq_char(tty, port, |
2125 | data[packet_offset + i])) | 2125 | data[packet_offset + i])) |
2126 | tty_insert_flip_char(tty, | 2126 | tty_insert_flip_char(tty, |
2127 | data[packet_offset + i], | 2127 | data[packet_offset + i], |
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 932d6241b787..ce57f6a32bdf 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -424,10 +424,17 @@ static void flush_and_resubmit_read_urb(struct usb_serial_port *port) | |||
424 | if (!tty) | 424 | if (!tty) |
425 | goto done; | 425 | goto done; |
426 | 426 | ||
427 | /* Push data to tty */ | 427 | /* The per character mucking around with sysrq path it too slow for |
428 | for (i = 0; i < urb->actual_length; i++, ch++) { | 428 | stuff like 3G modems, so shortcircuit it in the 99.9999999% of cases |
429 | if (!usb_serial_handle_sysrq_char(port, *ch)) | 429 | where the USB serial is not a console anyway */ |
430 | tty_insert_flip_char(tty, *ch, TTY_NORMAL); | 430 | if (!port->console || !port->sysrq) |
431 | tty_insert_flip_string(tty, ch, urb->actual_length); | ||
432 | else { | ||
433 | /* Push data to tty */ | ||
434 | for (i = 0; i < urb->actual_length; i++, ch++) { | ||
435 | if (!usb_serial_handle_sysrq_char(tty, port, *ch)) | ||
436 | tty_insert_flip_char(tty, *ch, TTY_NORMAL); | ||
437 | } | ||
431 | } | 438 | } |
432 | tty_flip_buffer_push(tty); | 439 | tty_flip_buffer_push(tty); |
433 | tty_kref_put(tty); | 440 | tty_kref_put(tty); |
@@ -527,11 +534,12 @@ void usb_serial_generic_unthrottle(struct tty_struct *tty) | |||
527 | } | 534 | } |
528 | } | 535 | } |
529 | 536 | ||
530 | int usb_serial_handle_sysrq_char(struct usb_serial_port *port, unsigned int ch) | 537 | int usb_serial_handle_sysrq_char(struct tty_struct *tty, |
538 | struct usb_serial_port *port, unsigned int ch) | ||
531 | { | 539 | { |
532 | if (port->sysrq && port->console) { | 540 | if (port->sysrq && port->console) { |
533 | if (ch && time_before(jiffies, port->sysrq)) { | 541 | if (ch && time_before(jiffies, port->sysrq)) { |
534 | handle_sysrq(ch, tty_port_tty_get(&port->port)); | 542 | handle_sysrq(ch, tty); |
535 | port->sysrq = 0; | 543 | port->sysrq = 0; |
536 | return 1; | 544 | return 1; |
537 | } | 545 | } |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index ec6c132a25b5..efaf59c4f5d0 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -971,18 +971,46 @@ exit: | |||
971 | __func__, retval); | 971 | __func__, retval); |
972 | } | 972 | } |
973 | 973 | ||
974 | static void pl2303_push_data(struct tty_struct *tty, | ||
975 | struct usb_serial_port *port, struct urb *urb, | ||
976 | u8 line_status) | ||
977 | { | ||
978 | unsigned char *data = urb->transfer_buffer; | ||
979 | /* get tty_flag from status */ | ||
980 | char tty_flag = TTY_NORMAL; | ||
981 | /* break takes precedence over parity, */ | ||
982 | /* which takes precedence over framing errors */ | ||
983 | if (line_status & UART_BREAK_ERROR) | ||
984 | tty_flag = TTY_BREAK; | ||
985 | else if (line_status & UART_PARITY_ERROR) | ||
986 | tty_flag = TTY_PARITY; | ||
987 | else if (line_status & UART_FRAME_ERROR) | ||
988 | tty_flag = TTY_FRAME; | ||
989 | dbg("%s - tty_flag = %d", __func__, tty_flag); | ||
990 | |||
991 | tty_buffer_request_room(tty, urb->actual_length + 1); | ||
992 | /* overrun is special, not associated with a char */ | ||
993 | if (line_status & UART_OVERRUN_ERROR) | ||
994 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
995 | if (port->console && port->sysrq) { | ||
996 | int i; | ||
997 | for (i = 0; i < urb->actual_length; ++i) | ||
998 | if (!usb_serial_handle_sysrq_char(tty, port, data[i])) | ||
999 | tty_insert_flip_char(tty, data[i], tty_flag); | ||
1000 | } else | ||
1001 | tty_insert_flip_string(tty, data, urb->actual_length); | ||
1002 | tty_flip_buffer_push(tty); | ||
1003 | } | ||
1004 | |||
974 | static void pl2303_read_bulk_callback(struct urb *urb) | 1005 | static void pl2303_read_bulk_callback(struct urb *urb) |
975 | { | 1006 | { |
976 | struct usb_serial_port *port = urb->context; | 1007 | struct usb_serial_port *port = urb->context; |
977 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 1008 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
978 | struct tty_struct *tty; | 1009 | struct tty_struct *tty; |
979 | unsigned char *data = urb->transfer_buffer; | ||
980 | unsigned long flags; | 1010 | unsigned long flags; |
981 | int i; | ||
982 | int result; | 1011 | int result; |
983 | int status = urb->status; | 1012 | int status = urb->status; |
984 | u8 line_status; | 1013 | u8 line_status; |
985 | char tty_flag; | ||
986 | 1014 | ||
987 | dbg("%s - port %d", __func__, port->number); | 1015 | dbg("%s - port %d", __func__, port->number); |
988 | 1016 | ||
@@ -1010,10 +1038,7 @@ static void pl2303_read_bulk_callback(struct urb *urb) | |||
1010 | } | 1038 | } |
1011 | 1039 | ||
1012 | usb_serial_debug_data(debug, &port->dev, __func__, | 1040 | usb_serial_debug_data(debug, &port->dev, __func__, |
1013 | urb->actual_length, data); | 1041 | urb->actual_length, urb->transfer_buffer); |
1014 | |||
1015 | /* get tty_flag from status */ | ||
1016 | tty_flag = TTY_NORMAL; | ||
1017 | 1042 | ||
1018 | spin_lock_irqsave(&priv->lock, flags); | 1043 | spin_lock_irqsave(&priv->lock, flags); |
1019 | line_status = priv->line_status; | 1044 | line_status = priv->line_status; |
@@ -1021,26 +1046,9 @@ static void pl2303_read_bulk_callback(struct urb *urb) | |||
1021 | spin_unlock_irqrestore(&priv->lock, flags); | 1046 | spin_unlock_irqrestore(&priv->lock, flags); |
1022 | wake_up_interruptible(&priv->delta_msr_wait); | 1047 | wake_up_interruptible(&priv->delta_msr_wait); |
1023 | 1048 | ||
1024 | /* break takes precedence over parity, */ | ||
1025 | /* which takes precedence over framing errors */ | ||
1026 | if (line_status & UART_BREAK_ERROR) | ||
1027 | tty_flag = TTY_BREAK; | ||
1028 | else if (line_status & UART_PARITY_ERROR) | ||
1029 | tty_flag = TTY_PARITY; | ||
1030 | else if (line_status & UART_FRAME_ERROR) | ||
1031 | tty_flag = TTY_FRAME; | ||
1032 | dbg("%s - tty_flag = %d", __func__, tty_flag); | ||
1033 | |||
1034 | tty = tty_port_tty_get(&port->port); | 1049 | tty = tty_port_tty_get(&port->port); |
1035 | if (tty && urb->actual_length) { | 1050 | if (tty && urb->actual_length) { |
1036 | tty_buffer_request_room(tty, urb->actual_length + 1); | 1051 | pl2303_push_data(tty, port, urb, line_status); |
1037 | /* overrun is special, not associated with a char */ | ||
1038 | if (line_status & UART_OVERRUN_ERROR) | ||
1039 | tty_insert_flip_char(tty, 0, TTY_OVERRUN); | ||
1040 | for (i = 0; i < urb->actual_length; ++i) | ||
1041 | if (!usb_serial_handle_sysrq_char(port, data[i])) | ||
1042 | tty_insert_flip_char(tty, data[i], tty_flag); | ||
1043 | tty_flip_buffer_push(tty); | ||
1044 | } | 1052 | } |
1045 | tty_kref_put(tty); | 1053 | tty_kref_put(tty); |
1046 | /* Schedule the next read _if_ we are still open */ | 1054 | /* Schedule the next read _if_ we are still open */ |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index d595aa5586a7..a84216464ca0 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -333,6 +333,9 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
333 | { | 333 | { |
334 | struct usb_serial_port *port = tty->driver_data; | 334 | struct usb_serial_port *port = tty->driver_data; |
335 | 335 | ||
336 | if (!port) | ||
337 | return; | ||
338 | |||
336 | dbg("%s - port %d", __func__, port->number); | 339 | dbg("%s - port %d", __func__, port->number); |
337 | 340 | ||
338 | 341 | ||