From 30ad95f252c78c34bf768dc3e3cd50bb1a4672ea Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 15 Oct 2009 10:37:02 -0700 Subject: [PATCH] usb patches for .31 --- queue-2.6.31/series | 10 + ...p210x-add-support-for-the-dw700-uart.patch | 33 ++ ...igi_acceleport-fix-broken-unthrottle.patch | 43 ++ ...rottling-in-generic-usbserial-driver.patch | 33 ++ ...sio-clean-up-read-completion-handler.patch | 80 +++ ...tdi_sio-re-implement-read-processing.patch | 521 ++++++++++++++++++ ...q-fix-oops-when-device-is-plugged-in.patch | 41 ++ .../usb-option-toshiba-g450-device-id.patch | 34 ++ ...aracters-not-being-reported-to-ldisc.patch | 41 ++ ...al-don-t-call-release-without-attach.patch | 65 +++ ...-sense-data-call-it-a-hardware-error.patch | 75 +++ 11 files changed, 976 insertions(+) create mode 100644 queue-2.6.31/usb-cp210x-add-support-for-the-dw700-uart.patch create mode 100644 queue-2.6.31/usb-digi_acceleport-fix-broken-unthrottle.patch create mode 100644 queue-2.6.31/usb-fix-throttling-in-generic-usbserial-driver.patch create mode 100644 queue-2.6.31/usb-ftdi_sio-clean-up-read-completion-handler.patch create mode 100644 queue-2.6.31/usb-ftdi_sio-re-implement-read-processing.patch create mode 100644 queue-2.6.31/usb-ipaq-fix-oops-when-device-is-plugged-in.patch create mode 100644 queue-2.6.31/usb-option-toshiba-g450-device-id.patch create mode 100644 queue-2.6.31/usb-pl2303-fix-error-characters-not-being-reported-to-ldisc.patch create mode 100644 queue-2.6.31/usb-serial-don-t-call-release-without-attach.patch create mode 100644 queue-2.6.31/usb-storage-when-a-device-returns-no-sense-data-call-it-a-hardware-error.patch diff --git a/queue-2.6.31/series b/queue-2.6.31/series index 702dd1e5e86..10d3638f4db 100644 --- a/queue-2.6.31/series +++ b/queue-2.6.31/series @@ -6,3 +6,13 @@ tracing-filters-fix-memory-leak-when-setting-a-filter.patch x86-paravirt-use-normal-calling-sequences-for-irq-enable-disable.patch usb-ftdi_sio-remove-tty-low_latency.patch usb-ftdi_sio-remove-unused-rx_byte-counter.patch +usb-ftdi_sio-clean-up-read-completion-handler.patch +usb-ftdi_sio-re-implement-read-processing.patch +usb-pl2303-fix-error-characters-not-being-reported-to-ldisc.patch +usb-digi_acceleport-fix-broken-unthrottle.patch +usb-serial-don-t-call-release-without-attach.patch +usb-option-toshiba-g450-device-id.patch +usb-ipaq-fix-oops-when-device-is-plugged-in.patch +usb-cp210x-add-support-for-the-dw700-uart.patch +usb-fix-throttling-in-generic-usbserial-driver.patch +usb-storage-when-a-device-returns-no-sense-data-call-it-a-hardware-error.patch diff --git a/queue-2.6.31/usb-cp210x-add-support-for-the-dw700-uart.patch b/queue-2.6.31/usb-cp210x-add-support-for-the-dw700-uart.patch new file mode 100644 index 00000000000..1f4bcb29ebb --- /dev/null +++ b/queue-2.6.31/usb-cp210x-add-support-for-the-dw700-uart.patch @@ -0,0 +1,33 @@ +From 6f88139eb9eae8003683689f93402264a73fb754 Mon Sep 17 00:00:00 2001 +From: Éric Piel +Date: Sun, 4 Oct 2009 13:45:07 +0200 +Subject: USB: cp210x: Add support for the DW700 UART +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Éric Piel + +commit 6f88139eb9eae8003683689f93402264a73fb754 upstream. + +In the Dell inspiron mini 10, the GPS is connected via a cp2102. This patch +adds detection of this USB device. (I haven't managed to use the GPS under +Linux yet, though) + +Signed-off-by: Éric Piel +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/cp210x.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/usb/serial/cp210x.c ++++ b/drivers/usb/serial/cp210x.c +@@ -114,6 +114,7 @@ static struct usb_device_id id_table [] + { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ + { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ ++ { USB_DEVICE(0x413C, 0x9500) }, /* DW700 GPS USB interface */ + { } /* Terminating Entry */ + }; + diff --git a/queue-2.6.31/usb-digi_acceleport-fix-broken-unthrottle.patch b/queue-2.6.31/usb-digi_acceleport-fix-broken-unthrottle.patch new file mode 100644 index 00000000000..c88e6740873 --- /dev/null +++ b/queue-2.6.31/usb-digi_acceleport-fix-broken-unthrottle.patch @@ -0,0 +1,43 @@ +From ba6b702f85a61561d329c4c11d3ed95604924f9a Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Tue, 29 Sep 2009 12:39:23 +0200 +Subject: USB: digi_acceleport: Fix broken unthrottle. + +From: Johan Hovold + +commit ba6b702f85a61561d329c4c11d3ed95604924f9a upstream. + +This patch fixes a regression introduced in +39892da44b21b5362eb848ca424d73a25ccc488f. + +Signed-off-by: Johan Hovold +Acked-by: Oliver Neukum +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/digi_acceleport.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/drivers/usb/serial/digi_acceleport.c ++++ b/drivers/usb/serial/digi_acceleport.c +@@ -899,16 +899,16 @@ static void digi_rx_unthrottle(struct tt + + spin_lock_irqsave(&priv->dp_port_lock, flags); + +- /* turn throttle off */ +- priv->dp_throttled = 0; +- priv->dp_throttle_restart = 0; +- + /* restart read chain */ + if (priv->dp_throttle_restart) { + port->read_urb->dev = port->serial->dev; + ret = usb_submit_urb(port->read_urb, GFP_ATOMIC); + } + ++ /* turn throttle off */ ++ priv->dp_throttled = 0; ++ priv->dp_throttle_restart = 0; ++ + spin_unlock_irqrestore(&priv->dp_port_lock, flags); + + if (ret) diff --git a/queue-2.6.31/usb-fix-throttling-in-generic-usbserial-driver.patch b/queue-2.6.31/usb-fix-throttling-in-generic-usbserial-driver.patch new file mode 100644 index 00000000000..acdacf58127 --- /dev/null +++ b/queue-2.6.31/usb-fix-throttling-in-generic-usbserial-driver.patch @@ -0,0 +1,33 @@ +From 63a9609513007537a0b23ac511fd73f9bd609ea0 Mon Sep 17 00:00:00 2001 +From: Joris van Rantwijk +Date: Thu, 24 Sep 2009 20:20:20 +0200 +Subject: USB: Fix throttling in generic usbserial driver + +From: Joris van Rantwijk + +commit 63a9609513007537a0b23ac511fd73f9bd609ea0 upstream. + +The generic usbserial driver in Linux 2.6.31 halts its receiving +channel in response to throttle requests from the line discipline. +Unfortunately it drops the contents of the first URB received after +throttling takes effect. This patch corrects that problem. + +Signed-off-by: Joris van Rantwijk +Acked-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/generic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/serial/generic.c ++++ b/drivers/usb/serial/generic.c +@@ -530,7 +530,7 @@ void usb_serial_generic_unthrottle(struc + + if (was_throttled) { + /* Resume reading from device */ +- usb_serial_generic_resubmit_read_urb(port, GFP_KERNEL); ++ flush_and_resubmit_read_urb(port); + } + } + diff --git a/queue-2.6.31/usb-ftdi_sio-clean-up-read-completion-handler.patch b/queue-2.6.31/usb-ftdi_sio-clean-up-read-completion-handler.patch new file mode 100644 index 00000000000..bb2515894f7 --- /dev/null +++ b/queue-2.6.31/usb-ftdi_sio-clean-up-read-completion-handler.patch @@ -0,0 +1,80 @@ +From e63e278b4d2d867893962d3c7cd13a3a24ceb3f1 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 7 Oct 2009 20:05:06 +0200 +Subject: USB: ftdi_sio: clean up read completion handler + +From: Johan Hovold + +commit e63e278b4d2d867893962d3c7cd13a3a24ceb3f1 upstream. + +Remove superfluous error checks in completion handler: + + - No need to check private data and urb pointers as we check urb-status + before dereferencing priv (which is not freed until urb has been killed + on close). + - No need to check tty as it is checked again when processing. + - No need to check urb->number_of_packets on bulk urb. + +Note that both private data and tty are checked again before processing +(possibly from work queue which also is cancelled on close). + +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/ftdi_sio.c | 28 +--------------------------- + 1 file changed, 1 insertion(+), 27 deletions(-) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -2010,39 +2010,14 @@ static int ftdi_chars_in_buffer(struct t + static void ftdi_read_bulk_callback(struct urb *urb) + { + struct usb_serial_port *port = urb->context; +- struct tty_struct *tty; + struct ftdi_private *priv; + int status = urb->status; + +- if (urb->number_of_packets > 0) { +- dev_err(&port->dev, "%s transfer_buffer_length %d " +- "actual_length %d number of packets %d\n", __func__, +- urb->transfer_buffer_length, +- urb->actual_length, urb->number_of_packets); +- dev_err(&port->dev, "%s transfer_flags %x\n", __func__, +- urb->transfer_flags); +- } +- + dbg("%s - port %d", __func__, port->number); + + if (port->port.count <= 0) + return; + +- tty = tty_port_tty_get(&port->port); +- if (!tty) { +- dbg("%s - bad tty pointer - exiting", __func__); +- return; +- } +- +- priv = usb_get_serial_port_data(port); +- if (!priv) { +- dbg("%s - bad port private data pointer - exiting", __func__); +- goto out; +- } +- +- if (urb != port->read_urb) +- dev_err(&port->dev, "%s - Not my urb!\n", __func__); +- + if (status) { + /* This will happen at close every time so it is a dbg not an + err */ +@@ -2050,9 +2025,8 @@ static void ftdi_read_bulk_callback(stru + goto out; + } + ++ priv = usb_get_serial_port_data(port); + ftdi_process_read(&priv->rx_work.work); +-out: +- tty_kref_put(tty); + } /* ftdi_read_bulk_callback */ + + diff --git a/queue-2.6.31/usb-ftdi_sio-re-implement-read-processing.patch b/queue-2.6.31/usb-ftdi_sio-re-implement-read-processing.patch new file mode 100644 index 00000000000..5a9b8653c7e --- /dev/null +++ b/queue-2.6.31/usb-ftdi_sio-re-implement-read-processing.patch @@ -0,0 +1,521 @@ +From cc01f17d5cb8ac604108515735aeca72e17944c1 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Wed, 7 Oct 2009 20:05:07 +0200 +Subject: USB: ftdi_sio: re-implement read processing + +From: Johan Hovold + +commit cc01f17d5cb8ac604108515735aeca72e17944c1 upstream. + +- Re-structure read processing. + - Kill obsolete work queue and always push to tty in completion handler. + - Use tty_insert_flip_string instead of per character push when + possible. + - Fix stalled-read regression in 2.6.31 by using urb status to + determine when port is closed rather than port count. + - Fix race with open/close by checking ASYNCB_INITIALIZED in + unthrottle. + - Kill private rx_flag and lock and use throttle flags in + usb_serial_port instead. + +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/ftdi_sio.c | 383 ++++++++++++++---------------------------- + 1 file changed, 131 insertions(+), 252 deletions(-) + +--- a/drivers/usb/serial/ftdi_sio.c ++++ b/drivers/usb/serial/ftdi_sio.c +@@ -76,12 +76,7 @@ struct ftdi_private { + unsigned long last_dtr_rts; /* saved modem control outputs */ + wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ + char prev_status, diff_status; /* Used for TIOCMIWAIT */ +- __u8 rx_flags; /* receive state flags (throttling) */ +- spinlock_t rx_lock; /* spinlock for receive state */ +- struct delayed_work rx_work; + struct usb_serial_port *port; +- int rx_processed; +- + __u16 interface; /* FT2232C, FT2232H or FT4232H port interface + (0 for FT232/245) */ + +@@ -736,10 +731,6 @@ static const char *ftdi_chip_name[] = { + /* Constants for read urb and write urb */ + #define BUFSZ 512 + +-/* rx_flags */ +-#define THROTTLED 0x01 +-#define ACTUALLY_THROTTLED 0x02 +- + /* Used for TIOCMIWAIT */ + #define FTDI_STATUS_B0_MASK (FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD) + #define FTDI_STATUS_B1_MASK (FTDI_RS_BI) +@@ -763,7 +754,7 @@ static int ftdi_write_room(struct tty_s + static int ftdi_chars_in_buffer(struct tty_struct *tty); + static void ftdi_write_bulk_callback(struct urb *urb); + static void ftdi_read_bulk_callback(struct urb *urb); +-static void ftdi_process_read(struct work_struct *work); ++static void ftdi_process_read(struct usb_serial_port *port); + static void ftdi_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old); + static int ftdi_tiocmget(struct tty_struct *tty, struct file *file); +@@ -1526,7 +1517,6 @@ static int ftdi_sio_port_probe(struct us + } + + kref_init(&priv->kref); +- spin_lock_init(&priv->rx_lock); + spin_lock_init(&priv->tx_lock); + init_waitqueue_head(&priv->delta_msr_wait); + /* This will push the characters through immediately rather +@@ -1548,7 +1538,6 @@ static int ftdi_sio_port_probe(struct us + port->read_urb->transfer_buffer_length = BUFSZ; + } + +- INIT_DELAYED_WORK(&priv->rx_work, ftdi_process_read); + priv->port = port; + + /* Free port's existing write urb and transfer buffer. */ +@@ -1685,6 +1674,26 @@ static int ftdi_sio_port_remove(struct u + return 0; + } + ++static int ftdi_submit_read_urb(struct usb_serial_port *port, gfp_t mem_flags) ++{ ++ struct urb *urb = port->read_urb; ++ struct usb_serial *serial = port->serial; ++ int result; ++ ++ usb_fill_bulk_urb(urb, serial->dev, ++ usb_rcvbulkpipe(serial->dev, ++ port->bulk_in_endpointAddress), ++ urb->transfer_buffer, ++ urb->transfer_buffer_length, ++ ftdi_read_bulk_callback, port); ++ result = usb_submit_urb(urb, mem_flags); ++ if (result) ++ dev_err(&port->dev, ++ "%s - failed submitting read urb, error %d\n", ++ __func__, result); ++ return result; ++} ++ + static int ftdi_open(struct tty_struct *tty, + struct usb_serial_port *port, struct file *filp) + { /* ftdi_open */ +@@ -1719,23 +1728,14 @@ static int ftdi_open(struct tty_struct * + ftdi_set_termios(tty, port, tty->termios); + + /* Not throttled */ +- spin_lock_irqsave(&priv->rx_lock, flags); +- priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); +- spin_unlock_irqrestore(&priv->rx_lock, flags); ++ spin_lock_irqsave(&port->lock, flags); ++ port->throttled = 0; ++ port->throttle_req = 0; ++ spin_unlock_irqrestore(&port->lock, flags); + + /* Start reading from the device */ +- priv->rx_processed = 0; +- usb_fill_bulk_urb(port->read_urb, dev, +- usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress), +- port->read_urb->transfer_buffer, +- port->read_urb->transfer_buffer_length, +- ftdi_read_bulk_callback, port); +- result = usb_submit_urb(port->read_urb, GFP_KERNEL); +- if (result) +- dev_err(&port->dev, +- "%s - failed submitting read urb, error %d\n", +- __func__, result); +- else ++ result = ftdi_submit_read_urb(port, GFP_KERNEL); ++ if (!result) + kref_get(&priv->kref); + + return result; +@@ -1781,10 +1781,6 @@ static void ftdi_close(struct usb_serial + + dbg("%s", __func__); + +- +- /* cancel any scheduled reading */ +- cancel_delayed_work_sync(&priv->rx_work); +- + /* shutdown our bulk read */ + usb_kill_urb(port->read_urb); + kref_put(&priv->kref, ftdi_sio_priv_release); +@@ -2007,236 +2003,121 @@ static int ftdi_chars_in_buffer(struct t + return buffered; + } + +-static void ftdi_read_bulk_callback(struct urb *urb) ++static int ftdi_process_packet(struct tty_struct *tty, ++ struct usb_serial_port *port, struct ftdi_private *priv, ++ char *packet, int len) + { +- struct usb_serial_port *port = urb->context; +- struct ftdi_private *priv; +- int status = urb->status; +- +- dbg("%s - port %d", __func__, port->number); +- +- if (port->port.count <= 0) +- return; +- +- if (status) { +- /* This will happen at close every time so it is a dbg not an +- err */ +- dbg("(this is ok on close) nonzero read bulk status received: %d", status); +- goto out; +- } +- +- priv = usb_get_serial_port_data(port); +- ftdi_process_read(&priv->rx_work.work); +-} /* ftdi_read_bulk_callback */ +- +- +-static void ftdi_process_read(struct work_struct *work) +-{ /* ftdi_process_read */ +- struct ftdi_private *priv = +- container_of(work, struct ftdi_private, rx_work.work); +- struct usb_serial_port *port = priv->port; +- struct urb *urb; +- struct tty_struct *tty; +- char error_flag; +- unsigned char *data; +- + int i; +- int result; +- int need_flip; +- int packet_offset; +- unsigned long flags; ++ char status; ++ char flag; ++ char *ch; + + dbg("%s - port %d", __func__, port->number); + +- if (port->port.count <= 0) +- return; +- +- tty = tty_port_tty_get(&port->port); +- if (!tty) { +- dbg("%s - bad tty pointer - exiting", __func__); +- return; ++ if (len < 2) { ++ dbg("malformed packet"); ++ return 0; + } + +- priv = usb_get_serial_port_data(port); +- if (!priv) { +- dbg("%s - bad port private data pointer - exiting", __func__); +- goto out; ++ /* Compare new line status to the old one, signal if different/ ++ N.B. packet may be processed more than once, but differences ++ are only processed once. */ ++ status = packet[0] & FTDI_STATUS_B0_MASK; ++ if (status != priv->prev_status) { ++ priv->diff_status |= status ^ priv->prev_status; ++ wake_up_interruptible(&priv->delta_msr_wait); ++ priv->prev_status = status; + } + +- urb = port->read_urb; +- if (!urb) { +- dbg("%s - bad read_urb pointer - exiting", __func__); +- goto out; ++ /* ++ * Although the device uses a bitmask and hence can have multiple ++ * errors on a packet - the order here sets the priority the error is ++ * returned to the tty layer. ++ */ ++ flag = TTY_NORMAL; ++ if (packet[1] & FTDI_RS_OE) { ++ flag = TTY_OVERRUN; ++ dbg("OVERRRUN error"); + } +- +- data = urb->transfer_buffer; +- +- if (priv->rx_processed) { +- dbg("%s - already processed: %d bytes, %d remain", __func__, +- priv->rx_processed, +- urb->actual_length - priv->rx_processed); +- } else { +- /* The first two bytes of every read packet are status */ +- if (urb->actual_length > 2) +- usb_serial_debug_data(debug, &port->dev, __func__, +- urb->actual_length, data); +- else +- dbg("Status only: %03oo %03oo", data[0], data[1]); ++ if (packet[1] & FTDI_RS_BI) { ++ flag = TTY_BREAK; ++ dbg("BREAK received"); ++ usb_serial_handle_break(port); ++ } ++ if (packet[1] & FTDI_RS_PE) { ++ flag = TTY_PARITY; ++ dbg("PARITY error"); ++ } ++ if (packet[1] & FTDI_RS_FE) { ++ flag = TTY_FRAME; ++ dbg("FRAMING error"); + } + ++ len -= 2; ++ if (!len) ++ return 0; /* status only */ ++ ch = packet + 2; + +- /* TO DO -- check for hung up line and handle appropriately: */ +- /* send hangup */ +- /* See acm.c - you do a tty_hangup - eg tty_hangup(tty) */ +- /* if CD is dropped and the line is not CLOCAL then we should hangup */ +- +- need_flip = 0; +- for (packet_offset = priv->rx_processed; +- packet_offset < urb->actual_length; packet_offset += priv->max_packet_size) { +- int length; +- +- /* Compare new line status to the old one, signal if different/ +- N.B. packet may be processed more than once, but differences +- are only processed once. */ +- char new_status = data[packet_offset + 0] & +- FTDI_STATUS_B0_MASK; +- if (new_status != priv->prev_status) { +- priv->diff_status |= +- new_status ^ priv->prev_status; +- wake_up_interruptible(&priv->delta_msr_wait); +- priv->prev_status = new_status; +- } +- +- length = min_t(u32, priv->max_packet_size, urb->actual_length-packet_offset)-2; +- if (length < 0) { +- dev_err(&port->dev, "%s - bad packet length: %d\n", +- __func__, length+2); +- length = 0; ++ if (!(port->console && port->sysrq) && flag == TTY_NORMAL) ++ tty_insert_flip_string(tty, ch, len); ++ else { ++ for (i = 0; i < len; i++, ch++) { ++ if (!usb_serial_handle_sysrq_char(tty, port, *ch)) ++ tty_insert_flip_char(tty, *ch, flag); + } ++ } ++ return len; ++} + +- if (priv->rx_flags & THROTTLED) { +- dbg("%s - throttled", __func__); +- break; +- } +- if (tty_buffer_request_room(tty, length) < length) { +- /* break out & wait for throttling/unthrottling to +- happen */ +- dbg("%s - receive room low", __func__); +- break; +- } ++static void ftdi_process_read(struct usb_serial_port *port) ++{ ++ struct urb *urb = port->read_urb; ++ struct tty_struct *tty; ++ struct ftdi_private *priv = usb_get_serial_port_data(port); ++ char *data = (char *)urb->transfer_buffer; ++ int i; ++ int len; ++ int count = 0; + +- /* Handle errors and break */ +- error_flag = TTY_NORMAL; +- /* Although the device uses a bitmask and hence can have +- multiple errors on a packet - the order here sets the +- priority the error is returned to the tty layer */ +- +- if (data[packet_offset+1] & FTDI_RS_OE) { +- error_flag = TTY_OVERRUN; +- dbg("OVERRRUN error"); +- } +- if (data[packet_offset+1] & FTDI_RS_BI) { +- error_flag = TTY_BREAK; +- dbg("BREAK received"); +- usb_serial_handle_break(port); +- } +- if (data[packet_offset+1] & FTDI_RS_PE) { +- error_flag = TTY_PARITY; +- dbg("PARITY error"); +- } +- if (data[packet_offset+1] & FTDI_RS_FE) { +- error_flag = TTY_FRAME; +- dbg("FRAMING error"); +- } +- if (length > 0) { +- for (i = 2; i < length+2; i++) { +- /* Note that the error flag is duplicated for +- every character received since we don't know +- which character it applied to */ +- if (!usb_serial_handle_sysrq_char(tty, port, +- data[packet_offset + i])) +- tty_insert_flip_char(tty, +- data[packet_offset + i], +- error_flag); +- } +- need_flip = 1; +- } ++ tty = tty_port_tty_get(&port->port); ++ if (!tty) ++ return; + +-#ifdef NOT_CORRECT_BUT_KEEPING_IT_FOR_NOW +- /* if a parity error is detected you get status packets forever +- until a character is sent without a parity error. +- This doesn't work well since the application receives a +- never ending stream of bad data - even though new data +- hasn't been sent. Therefore I (bill) have taken this out. +- However - this might make sense for framing errors and so on +- so I am leaving the code in for now. +- */ +- else { +- if (error_flag != TTY_NORMAL) { +- dbg("error_flag is not normal"); +- /* In this case it is just status - if that is +- an error send a bad character */ +- if (tty->flip.count >= TTY_FLIPBUF_SIZE) +- tty_flip_buffer_push(tty); +- tty_insert_flip_char(tty, 0xff, error_flag); +- need_flip = 1; +- } +- } +-#endif +- } /* "for(packet_offset=0..." */ ++ for (i = 0; i < urb->actual_length; i += priv->max_packet_size) { ++ len = min_t(int, urb->actual_length - i, priv->max_packet_size); ++ count += ftdi_process_packet(tty, port, priv, &data[i], len); ++ } + +- /* Low latency */ +- if (need_flip) ++ if (count) + tty_flip_buffer_push(tty); ++ tty_kref_put(tty); ++} + +- if (packet_offset < urb->actual_length) { +- /* not completely processed - record progress */ +- priv->rx_processed = packet_offset; +- dbg("%s - incomplete, %d bytes processed, %d remain", +- __func__, packet_offset, +- urb->actual_length - packet_offset); +- /* check if we were throttled while processing */ +- spin_lock_irqsave(&priv->rx_lock, flags); +- if (priv->rx_flags & THROTTLED) { +- priv->rx_flags |= ACTUALLY_THROTTLED; +- spin_unlock_irqrestore(&priv->rx_lock, flags); +- dbg("%s - deferring remainder until unthrottled", +- __func__); +- goto out; +- } +- spin_unlock_irqrestore(&priv->rx_lock, flags); +- /* if the port is closed stop trying to read */ +- if (port->port.count > 0) +- /* delay processing of remainder */ +- schedule_delayed_work(&priv->rx_work, 1); +- else +- dbg("%s - port is closed", __func__); +- goto out; +- } +- +- /* urb is completely processed */ +- priv->rx_processed = 0; ++static void ftdi_read_bulk_callback(struct urb *urb) ++{ ++ struct usb_serial_port *port = urb->context; ++ unsigned long flags; + +- /* if the port is closed stop trying to read */ +- if (port->port.count > 0) { +- /* Continue trying to always read */ +- usb_fill_bulk_urb(port->read_urb, port->serial->dev, +- usb_rcvbulkpipe(port->serial->dev, +- port->bulk_in_endpointAddress), +- port->read_urb->transfer_buffer, +- port->read_urb->transfer_buffer_length, +- ftdi_read_bulk_callback, port); ++ dbg("%s - port %d", __func__, port->number); + +- result = usb_submit_urb(port->read_urb, GFP_ATOMIC); +- if (result) +- dev_err(&port->dev, +- "%s - failed resubmitting read urb, error %d\n", +- __func__, result); ++ if (urb->status) { ++ dbg("%s - nonzero read bulk status received: %d", ++ __func__, urb->status); ++ return; + } +-out: +- tty_kref_put(tty); +-} /* ftdi_process_read */ + ++ usb_serial_debug_data(debug, &port->dev, __func__, ++ urb->actual_length, urb->transfer_buffer); ++ ftdi_process_read(port); ++ ++ spin_lock_irqsave(&port->lock, flags); ++ port->throttled = port->throttle_req; ++ if (!port->throttled) { ++ spin_unlock_irqrestore(&port->lock, flags); ++ ftdi_submit_read_urb(port, GFP_ATOMIC); ++ } else ++ spin_unlock_irqrestore(&port->lock, flags); ++} + + static void ftdi_break_ctl(struct tty_struct *tty, int break_state) + { +@@ -2568,33 +2449,31 @@ static int ftdi_ioctl(struct tty_struct + static void ftdi_throttle(struct tty_struct *tty) + { + struct usb_serial_port *port = tty->driver_data; +- struct ftdi_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + + dbg("%s - port %d", __func__, port->number); + +- spin_lock_irqsave(&priv->rx_lock, flags); +- priv->rx_flags |= THROTTLED; +- spin_unlock_irqrestore(&priv->rx_lock, flags); ++ spin_lock_irqsave(&port->lock, flags); ++ port->throttle_req = 1; ++ spin_unlock_irqrestore(&port->lock, flags); + } + +- +-static void ftdi_unthrottle(struct tty_struct *tty) ++void ftdi_unthrottle(struct tty_struct *tty) + { + struct usb_serial_port *port = tty->driver_data; +- struct ftdi_private *priv = usb_get_serial_port_data(port); +- int actually_throttled; ++ int was_throttled; + unsigned long flags; + + dbg("%s - port %d", __func__, port->number); + +- spin_lock_irqsave(&priv->rx_lock, flags); +- actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; +- priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); +- spin_unlock_irqrestore(&priv->rx_lock, flags); +- +- if (actually_throttled) +- schedule_delayed_work(&priv->rx_work, 0); ++ spin_lock_irqsave(&port->lock, flags); ++ was_throttled = port->throttled; ++ port->throttled = port->throttle_req = 0; ++ spin_unlock_irqrestore(&port->lock, flags); ++ ++ /* Resubmit urb if throttled and open. */ ++ if (was_throttled && test_bit(ASYNCB_INITIALIZED, &port->port.flags)) ++ ftdi_submit_read_urb(port, GFP_KERNEL); + } + + static int __init ftdi_init(void) diff --git a/queue-2.6.31/usb-ipaq-fix-oops-when-device-is-plugged-in.patch b/queue-2.6.31/usb-ipaq-fix-oops-when-device-is-plugged-in.patch new file mode 100644 index 00000000000..45062d12b4b --- /dev/null +++ b/queue-2.6.31/usb-ipaq-fix-oops-when-device-is-plugged-in.patch @@ -0,0 +1,41 @@ +From 06bad89da686f6323e95cf925105e8cf88d87caf Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Mon, 5 Oct 2009 15:53:58 -0400 +Subject: USB: ipaq: fix oops when device is plugged in + +From: Alan Stern + +commit 06bad89da686f6323e95cf925105e8cf88d87caf upstream. + +This patch (as1293) fixes a problem with the ipaq serial driver. It +tries to bind to all the interfaces, even those that don't have enough +endpoints. The symptom is an invalid memory reference and oops when +the device is plugged in. + +Signed-off-by: Alan Stern +Tested-by: Matthias Geissert +Tested-by: Tilman Schmidt +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/ipaq.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/usb/serial/ipaq.c ++++ b/drivers/usb/serial/ipaq.c +@@ -971,6 +971,15 @@ static int ipaq_calc_num_ports(struct us + static int ipaq_startup(struct usb_serial *serial) + { + dbg("%s", __func__); ++ ++ /* Some of the devices in ipaq_id_table[] are composite, and we ++ * shouldn't bind to all the interfaces. This test will rule out ++ * some obviously invalid possibilities. ++ */ ++ if (serial->num_bulk_in < serial->num_ports || ++ serial->num_bulk_out < serial->num_ports) ++ return -ENODEV; ++ + if (serial->dev->actconfig->desc.bConfigurationValue != 1) { + /* + * FIXME: HP iPaq rx3715, possibly others, have 1 config that diff --git a/queue-2.6.31/usb-option-toshiba-g450-device-id.patch b/queue-2.6.31/usb-option-toshiba-g450-device-id.patch new file mode 100644 index 00000000000..77e9a3fb2b2 --- /dev/null +++ b/queue-2.6.31/usb-option-toshiba-g450-device-id.patch @@ -0,0 +1,34 @@ +From 75f47214f90e996eb184eb6e6b0e8b817999c8f7 Mon Sep 17 00:00:00 2001 +From: Peter Magdina +Date: Wed, 7 Oct 2009 16:22:17 +0200 +Subject: USB: option: Toshiba G450 device id + +From: Peter Magdina + +commit 75f47214f90e996eb184eb6e6b0e8b817999c8f7 upstream. + +Signed-off-by: Peter Magdina +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/option.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/usb/serial/option.c ++++ b/drivers/usb/serial/option.c +@@ -319,6 +319,7 @@ static int option_resume(struct usb_ser + /* TOSHIBA PRODUCTS */ + #define TOSHIBA_VENDOR_ID 0x0930 + #define TOSHIBA_PRODUCT_HSDPA_MINICARD 0x1302 ++#define TOSHIBA_PRODUCT_G450 0x0d45 + + #define ALINK_VENDOR_ID 0x1e0e + #define ALINK_PRODUCT_3GU 0x9200 +@@ -582,6 +583,7 @@ static struct usb_device_id option_ids[] + { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4523) }, + { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4515) }, + { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H20_4519) }, ++ { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_G450) }, + { USB_DEVICE(TOSHIBA_VENDOR_ID, TOSHIBA_PRODUCT_HSDPA_MINICARD ) }, /* Toshiba 3G HSDPA == Novatel Expedite EU870D MiniCard */ + { USB_DEVICE(ALINK_VENDOR_ID, 0x9000) }, + { USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) }, diff --git a/queue-2.6.31/usb-pl2303-fix-error-characters-not-being-reported-to-ldisc.patch b/queue-2.6.31/usb-pl2303-fix-error-characters-not-being-reported-to-ldisc.patch new file mode 100644 index 00000000000..5ad28bfdd29 --- /dev/null +++ b/queue-2.6.31/usb-pl2303-fix-error-characters-not-being-reported-to-ldisc.patch @@ -0,0 +1,41 @@ +From 9388e2e71a51fab0aa2309bbb45e8a23d89a95a9 Mon Sep 17 00:00:00 2001 +From: Johan Hovold +Date: Thu, 8 Oct 2009 11:36:46 +0200 +Subject: USB: pl2303: fix error characters not being reported to ldisc + +From: Johan Hovold + +commit 9388e2e71a51fab0aa2309bbb45e8a23d89a95a9 upstream. + +Fix regression introduced by commit +d4fc4a7bfc2dee626f4fec1e209e58eaa4312de6 (tty: Fix the PL2303 private +methods for sysrq). + +Signed-off-by: Johan Hovold +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/pl2303.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +--- a/drivers/usb/serial/pl2303.c ++++ b/drivers/usb/serial/pl2303.c +@@ -995,13 +995,15 @@ static void pl2303_push_data(struct tty_ + /* overrun is special, not associated with a char */ + if (line_status & UART_OVERRUN_ERROR) + tty_insert_flip_char(tty, 0, TTY_OVERRUN); +- if (port->console && port->sysrq) { ++ ++ if (tty_flag == TTY_NORMAL && !(port->console && port->sysrq)) ++ tty_insert_flip_string(tty, data, urb->actual_length); ++ else { + int i; + for (i = 0; i < urb->actual_length; ++i) + if (!usb_serial_handle_sysrq_char(tty, port, data[i])) + tty_insert_flip_char(tty, data[i], tty_flag); +- } else +- tty_insert_flip_string(tty, data, urb->actual_length); ++ } + tty_flip_buffer_push(tty); + } + diff --git a/queue-2.6.31/usb-serial-don-t-call-release-without-attach.patch b/queue-2.6.31/usb-serial-don-t-call-release-without-attach.patch new file mode 100644 index 00000000000..ea6fcca5f1f --- /dev/null +++ b/queue-2.6.31/usb-serial-don-t-call-release-without-attach.patch @@ -0,0 +1,65 @@ +From a4720c650b68a5fe7faed2edeb0ad12645f7ae63 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Fri, 9 Oct 2009 12:43:12 -0400 +Subject: USB: serial: don't call release without attach + +From: Alan Stern + +commit a4720c650b68a5fe7faed2edeb0ad12645f7ae63 upstream. + +This patch (as1295) fixes a recently-added bug in the USB serial core. +If certain kinds of errors occur during probing, the core may call a +serial driver's release method without previously calling the attach +method. This causes some drivers (io_ti in particular) to perform an +invalid memory access. + +The patch adds a new flag to keep track of whether or not attach has +been called. + +Signed-off-by: Alan Stern +Tested-by: Jean-Denis Girard +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/serial/usb-serial.c | 6 +++++- + include/linux/usb/serial.h | 1 + + 2 files changed, 6 insertions(+), 1 deletion(-) + +--- a/drivers/usb/serial/usb-serial.c ++++ b/drivers/usb/serial/usb-serial.c +@@ -155,7 +155,8 @@ static void destroy_serial(struct kref * + if (serial->minor != SERIAL_TTY_NO_MINOR) + return_serial(serial); + +- serial->type->release(serial); ++ if (serial->attached) ++ serial->type->release(serial); + + /* Now that nothing is using the ports, they can be freed */ + for (i = 0; i < serial->num_port_pointers; ++i) { +@@ -1060,12 +1061,15 @@ int usb_serial_probe(struct usb_interfac + module_put(type->driver.owner); + if (retval < 0) + goto probe_error; ++ serial->attached = 1; + if (retval > 0) { + /* quietly accept this device, but don't bind to a + serial port as it's about to disappear */ + serial->num_ports = 0; + goto exit; + } ++ } else { ++ serial->attached = 1; + } + + if (get_free_serial(serial, num_ports, &minor) == NULL) { +--- a/include/linux/usb/serial.h ++++ b/include/linux/usb/serial.h +@@ -148,6 +148,7 @@ struct usb_serial { + struct usb_interface *interface; + unsigned char disconnected:1; + unsigned char suspending:1; ++ unsigned char attached:1; + unsigned char minor; + unsigned char num_ports; + unsigned char num_port_pointers; diff --git a/queue-2.6.31/usb-storage-when-a-device-returns-no-sense-data-call-it-a-hardware-error.patch b/queue-2.6.31/usb-storage-when-a-device-returns-no-sense-data-call-it-a-hardware-error.patch new file mode 100644 index 00000000000..3e22bf049b2 --- /dev/null +++ b/queue-2.6.31/usb-storage-when-a-device-returns-no-sense-data-call-it-a-hardware-error.patch @@ -0,0 +1,75 @@ +From f1a0743bc0e7a30c032b1eb78f6a2b0f805b4597 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 6 Oct 2009 14:07:57 -0400 +Subject: USB: storage: When a device returns no sense data, call it a Hardware Error + +From: Alan Stern + +commit f1a0743bc0e7a30c032b1eb78f6a2b0f805b4597 upstream. + +This patch (as1294) fixes a problem that has plagued users for several +kernel releases. Some USB mass-storage devices don't return any sense +data when they encounter certain kinds of errors. The SCSI layer +interprets this to mean that the operation should be retried, and the +same thing happens -- over and over again with no limit. In some +circumstances (such as when a bus reset occurs) that is the right +thing to do, but not here. + +The patch checks for this condition (a transport failure with no sense +data) and changes the result code to DID_ERROR and the sense code to +Hardware Error. This does get only a limited number of retries, and +so the command will fail relatively quickly instead of getting stuck +in an infinite loop. + +This fixes a large part of Bugzilla #14118. + +Signed-off-by: Alan Stern +Tested-by: Mantas Mikulenas +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/usb/storage/transport.c | 29 ++++++++++++++++++++++------- + 1 file changed, 22 insertions(+), 7 deletions(-) + +--- a/drivers/usb/storage/transport.c ++++ b/drivers/usb/storage/transport.c +@@ -768,17 +768,32 @@ void usb_stor_invoke_transport(struct sc + /* set the result so the higher layers expect this data */ + srb->result = SAM_STAT_CHECK_CONDITION; + +- /* If things are really okay, then let's show that. Zero +- * out the sense buffer so the higher layers won't realize +- * we did an unsolicited auto-sense. */ +- if (result == USB_STOR_TRANSPORT_GOOD && +- /* Filemark 0, ignore EOM, ILI 0, no sense */ ++ /* We often get empty sense data. This could indicate that ++ * everything worked or that there was an unspecified ++ * problem. We have to decide which. ++ */ ++ if ( /* Filemark 0, ignore EOM, ILI 0, no sense */ + (srb->sense_buffer[2] & 0xaf) == 0 && + /* No ASC or ASCQ */ + srb->sense_buffer[12] == 0 && + srb->sense_buffer[13] == 0) { +- srb->result = SAM_STAT_GOOD; +- srb->sense_buffer[0] = 0x0; ++ ++ /* If things are really okay, then let's show that. ++ * Zero out the sense buffer so the higher layers ++ * won't realize we did an unsolicited auto-sense. ++ */ ++ if (result == USB_STOR_TRANSPORT_GOOD) { ++ srb->result = SAM_STAT_GOOD; ++ srb->sense_buffer[0] = 0x0; ++ ++ /* If there was a problem, report an unspecified ++ * hardware error to prevent the higher layers from ++ * entering an infinite retry loop. ++ */ ++ } else { ++ srb->result = DID_ERROR << 16; ++ srb->sense_buffer[2] = HARDWARE_ERROR; ++ } + } + } + -- 2.47.2