aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb
diff options
context:
space:
mode:
authorOlivier Sobrie <olivier@sobrie.be>2014-07-14 06:08:50 -0400
committerDavid S. Miller <davem@davemloft.net>2014-07-14 22:27:34 -0400
commit8f9818af4eaef1150282e18355aaea425474a411 (patch)
tree6dd457dfe72ca88b65ce041afe5124271f98f7ab /drivers/net/usb
parent5c763edfe4879ffc3a87fef64f743d4b5497aabb (diff)
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>
Diffstat (limited to 'drivers/net/usb')
-rw-r--r--drivers/net/usb/hso.c38
1 files changed, 17 insertions, 21 deletions
diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c
index 9ca2b418a3ee..a4272ed62da8 100644
--- a/drivers/net/usb/hso.c
+++ b/drivers/net/usb/hso.c
@@ -258,7 +258,6 @@ struct hso_serial {
258 * so as not to drop characters on the floor. 258 * so as not to drop characters on the floor.
259 */ 259 */
260 int curr_rx_urb_idx; 260 int curr_rx_urb_idx;
261 u16 curr_rx_urb_offset;
262 u8 rx_urb_filled[MAX_RX_URBS]; 261 u8 rx_urb_filled[MAX_RX_URBS];
263 struct tasklet_struct unthrottle_tasklet; 262 struct tasklet_struct unthrottle_tasklet;
264}; 263};
@@ -2001,8 +2000,7 @@ static void ctrl_callback(struct urb *urb)
2001static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial) 2000static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
2002{ 2001{
2003 struct tty_struct *tty; 2002 struct tty_struct *tty;
2004 int write_length_remaining = 0; 2003 int count;
2005 int curr_write_len;
2006 2004
2007 /* Sanity check */ 2005 /* Sanity check */
2008 if (urb == NULL || serial == NULL) { 2006 if (urb == NULL || serial == NULL) {
@@ -2012,29 +2010,28 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
2012 2010
2013 tty = tty_port_tty_get(&serial->port); 2011 tty = tty_port_tty_get(&serial->port);
2014 2012
2013 if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
2014 tty_kref_put(tty);
2015 return -1;
2016 }
2017
2015 /* Push data to tty */ 2018 /* Push data to tty */
2016 write_length_remaining = urb->actual_length -
2017 serial->curr_rx_urb_offset;
2018 D1("data to push to tty"); 2019 D1("data to push to tty");
2019 while (write_length_remaining) { 2020 count = tty_buffer_request_room(&serial->port, urb->actual_length);
2020 if (tty && test_bit(TTY_THROTTLED, &tty->flags)) { 2021 if (count >= urb->actual_length) {
2021 tty_kref_put(tty); 2022 tty_insert_flip_string(&serial->port, urb->transfer_buffer,
2022 return -1; 2023 urb->actual_length);
2023 }
2024 curr_write_len = tty_insert_flip_string(&serial->port,
2025 urb->transfer_buffer + serial->curr_rx_urb_offset,
2026 write_length_remaining);
2027 serial->curr_rx_urb_offset += curr_write_len;
2028 write_length_remaining -= curr_write_len;
2029 tty_flip_buffer_push(&serial->port); 2024 tty_flip_buffer_push(&serial->port);
2025 } else {
2026 dev_warn(&serial->parent->usb->dev,
2027 "dropping data, %d bytes lost\n", urb->actual_length);
2030 } 2028 }
2029
2031 tty_kref_put(tty); 2030 tty_kref_put(tty);
2032 2031
2033 if (write_length_remaining == 0) { 2032 serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
2034 serial->curr_rx_urb_offset = 0; 2033
2035 serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0; 2034 return 0;
2036 }
2037 return write_length_remaining;
2038} 2035}
2039 2036
2040 2037
@@ -2205,7 +2202,6 @@ static int hso_stop_serial_device(struct hso_device *hso_dev)
2205 } 2202 }
2206 } 2203 }
2207 serial->curr_rx_urb_idx = 0; 2204 serial->curr_rx_urb_idx = 0;
2208 serial->curr_rx_urb_offset = 0;
2209 2205
2210 if (serial->tx_urb) 2206 if (serial->tx_urb)
2211 usb_kill_urb(serial->tx_urb); 2207 usb_kill_urb(serial->tx_urb);