diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-05 12:57:01 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-08-05 12:57:01 -0700 |
| commit | bf55670de5a5934374946e00e633bcd6c7cb2c17 (patch) | |
| tree | efaea03e41249df94afbebd9c72183a8fbbc3c1c /usb/usb-serial-fix-stalled-writes.patch | |
| parent | a7c6d4fb3ad0fde884f9a83d33cae3bcb55a30e5 (diff) | |
| download | patches-bf55670de5a5934374946e00e633bcd6c7cb2c17.tar.gz | |
2 usb bug fixes
Diffstat (limited to 'usb/usb-serial-fix-stalled-writes.patch')
| -rw-r--r-- | usb/usb-serial-fix-stalled-writes.patch | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/usb/usb-serial-fix-stalled-writes.patch b/usb/usb-serial-fix-stalled-writes.patch new file mode 100644 index 00000000000000..0dd51f9d1587a2 --- /dev/null +++ b/usb/usb-serial-fix-stalled-writes.patch @@ -0,0 +1,63 @@ +From jhovold@gmail.com Thu Aug 5 12:52:30 2010 +From: Johan Hovold <jhovold@gmail.com> +To: Greg KH <greg@kroah.com> +Cc: David VomLehn <dvomlehn@cisco.com>, + linux-usb@vger.kernel.org, + alexander.stein@systec-electronic.com, + Johan Hovold <jhovold@gmail.com> +Subject: USB: serial: fix stalled writes +Date: Wed, 4 Aug 2010 15:45:57 +0200 +Message-Id: <1280929557-5670-1-git-send-email-jhovold@gmail.com> + +As David VomLehn points out, it was possible to receive an interrupt +before clearing the free-urb flag which could lead to the urb being +incorrectly marked as busy. + +For the same reason, move tx_bytes accounting so that it will never be +negative. + +Note that the free-flags set and clear operations do not need any +additional locking as they are manipulated while USB_SERIAL_WRITE_BUSY +is set. + +Reported-by: David VomLehn <dvomlehn@cisco.com> +Tested-by: David VomLehn <dvomlehn@cisco.com> +Signed-off-by: Johan Hovold <jhovold@gmail.com> +Cc: stable <stable@kernel.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/usb/serial/generic.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +--- a/drivers/usb/serial/generic.c ++++ b/drivers/usb/serial/generic.c +@@ -208,18 +208,23 @@ retry: + urb->transfer_buffer_length = count; + usb_serial_debug_data(debug, &port->dev, __func__, count, + urb->transfer_buffer); ++ spin_lock_irqsave(&port->lock, flags); ++ port->tx_bytes += count; ++ spin_unlock_irqrestore(&port->lock, flags); ++ ++ clear_bit(i, &port->write_urbs_free); + result = usb_submit_urb(urb, GFP_ATOMIC); + if (result) { + dev_err(&port->dev, "%s - error submitting urb: %d\n", + __func__, result); ++ set_bit(i, &port->write_urbs_free); ++ spin_lock_irqsave(&port->lock, flags); ++ port->tx_bytes -= count; ++ spin_unlock_irqrestore(&port->lock, flags); ++ + clear_bit_unlock(USB_SERIAL_WRITE_BUSY, &port->flags); + return result; + } +- clear_bit(i, &port->write_urbs_free); +- +- spin_lock_irqsave(&port->lock, flags); +- port->tx_bytes += count; +- spin_unlock_irqrestore(&port->lock, flags); + + /* Try sending off another urb, unless in irq context (in which case + * there will be no free urb). */ |
