diff options
author | Johan Hovold <jhovold@gmail.com> | 2010-03-17 18:00:42 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-05-20 16:21:33 -0400 |
commit | 30af7fb5a40f8724c130428473edffa73170e04c (patch) | |
tree | 07c8fcd3493a06f67dc2b7b0aea4b48152dc2fa3 /drivers/usb/serial/generic.c | |
parent | 7919c2fd9e07276403b9a4d9ae52305e0d70f923 (diff) |
USB: serial: fix generic chars_in_buffer
Make sure chars_in_buffer accounts also for data in host stack queues.
This fixes the problem with tty_wait_until_sent returning too soon at
close which could cause the final write urb to be cancelled.
Reported-by: Pete Zaitcev <zaitcev@redhat.com>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/serial/generic.c')
-rw-r--r-- | drivers/usb/serial/generic.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index a5e610976689..8f78d7b8e888 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
@@ -309,10 +309,14 @@ static int usb_serial_generic_write_start(struct usb_serial_port *port) | |||
309 | /* don't have to grab the lock here, as we will | 309 | /* don't have to grab the lock here, as we will |
310 | retry if != 0 */ | 310 | retry if != 0 */ |
311 | port->write_urb_busy = 0; | 311 | port->write_urb_busy = 0; |
312 | } else | 312 | return result; |
313 | result = count; | 313 | } |
314 | 314 | ||
315 | return result; | 315 | spin_lock_irqsave(&port->lock, flags); |
316 | port->tx_bytes_flight += count; | ||
317 | spin_unlock_irqrestore(&port->lock, flags); | ||
318 | |||
319 | return count; | ||
316 | } | 320 | } |
317 | 321 | ||
318 | /** | 322 | /** |
@@ -400,7 +404,7 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) | |||
400 | if (serial->type->max_in_flight_urbs) | 404 | if (serial->type->max_in_flight_urbs) |
401 | chars = port->tx_bytes_flight; | 405 | chars = port->tx_bytes_flight; |
402 | else | 406 | else |
403 | chars = kfifo_len(&port->write_fifo); | 407 | chars = kfifo_len(&port->write_fifo) + port->tx_bytes_flight; |
404 | spin_unlock_irqrestore(&port->lock, flags); | 408 | spin_unlock_irqrestore(&port->lock, flags); |
405 | 409 | ||
406 | dbg("%s - returns %d", __func__, chars); | 410 | dbg("%s - returns %d", __func__, chars); |
@@ -510,7 +514,10 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) | |||
510 | port->urbs_in_flight = 0; | 514 | port->urbs_in_flight = 0; |
511 | spin_unlock_irqrestore(&port->lock, flags); | 515 | spin_unlock_irqrestore(&port->lock, flags); |
512 | } else { | 516 | } else { |
517 | spin_lock_irqsave(&port->lock, flags); | ||
518 | port->tx_bytes_flight -= urb->transfer_buffer_length; | ||
513 | port->write_urb_busy = 0; | 519 | port->write_urb_busy = 0; |
520 | spin_unlock_irqrestore(&port->lock, flags); | ||
514 | 521 | ||
515 | if (status) | 522 | if (status) |
516 | kfifo_reset_out(&port->write_fifo); | 523 | kfifo_reset_out(&port->write_fifo); |