Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

hso: fix deadlock when receiving bursts of data

When the module sends bursts of data, sometimes a deadlock happens in
the hso driver when the tty buffer doesn't get the chance to be flushed
quickly enough.

Remove the endless while loop in function put_rxbuf_data() which is
called by the urb completion handler.
If there isn't enough room in the tty buffer, discards all the data
received in the URB.

Cc: David Miller <davem@davemloft.net>
Cc: David Laight <David.Laight@ACULAB.COM>
Cc: One Thousand Gnomes <gnomes@lxorguk.ukuu.org.uk>
Cc: Dan Williams <dcbw@redhat.com>
Cc: Jan Dumon <j.dumon@option.com>
Signed-off-by: Olivier Sobrie <olivier@sobrie.be>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Olivier Sobrie and committed by
David S. Miller
8f9818af 5c763edf

+20 -24
+20 -24
drivers/net/usb/hso.c
··· 258 258 * so as not to drop characters on the floor. 259 259 */ 260 260 int curr_rx_urb_idx; 261 - u16 curr_rx_urb_offset; 262 261 u8 rx_urb_filled[MAX_RX_URBS]; 263 262 struct tasklet_struct unthrottle_tasklet; 264 263 }; ··· 2000 2001 static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) 2001 2002 { 2002 2003 struct tty_struct *tty; 2003 - int write_length_remaining = 0; 2004 - int curr_write_len; 2004 + int count; 2005 2005 2006 2006 /* Sanity check */ 2007 2007 if (urb == NULL || serial == NULL) { ··· 2010 2012 2011 2013 tty = tty_port_tty_get(&serial->port); 2012 2014 2013 - /* Push data to tty */ 2014 - write_length_remaining = urb->actual_length - 2015 - serial->curr_rx_urb_offset; 2016 - D1("data to push to tty"); 2017 - while (write_length_remaining) { 2018 - if (tty && test_bit(TTY_THROTTLED, &tty->flags)) { 2019 - tty_kref_put(tty); 2020 - return -1; 2021 - } 2022 - curr_write_len = tty_insert_flip_string(&serial->port, 2023 - urb->transfer_buffer + serial->curr_rx_urb_offset, 2024 - write_length_remaining); 2025 - serial->curr_rx_urb_offset += curr_write_len; 2026 - write_length_remaining -= curr_write_len; 2027 - tty_flip_buffer_push(&serial->port); 2015 + if (tty && test_bit(TTY_THROTTLED, &tty->flags)) { 2016 + tty_kref_put(tty); 2017 + return -1; 2028 2018 } 2019 + 2020 + /* Push data to tty */ 2021 + D1("data to push to tty"); 2022 + count = tty_buffer_request_room(&serial->port, urb->actual_length); 2023 + if (count >= urb->actual_length) { 2024 + tty_insert_flip_string(&serial->port, urb->transfer_buffer, 2025 + urb->actual_length); 2026 + tty_flip_buffer_push(&serial->port); 2027 + } else { 2028 + dev_warn(&serial->parent->usb->dev, 2029 + "dropping data, %d bytes lost\n", urb->actual_length); 2030 + } 2031 + 2029 2032 tty_kref_put(tty); 2030 2033 2031 - if (write_length_remaining == 0) { 2032 - serial->curr_rx_urb_offset = 0; 2033 - serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; 2034 - } 2035 - return write_length_remaining; 2034 + serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; 2035 + 2036 + return 0; 2036 2037 } 2037 2038 2038 2039 ··· 2202 2205 } 2203 2206 } 2204 2207 serial->curr_rx_urb_idx = 0; 2205 - serial->curr_rx_urb_offset = 0; 2206 2208 2207 2209 if (serial->tx_urb) 2208 2210 usb_kill_urb(serial->tx_urb);