aboutsummaryrefslogtreecommitdiffstats
path: root/usb/usb-serial-fix-stalled-writes.patch
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2010-08-05 12:57:01 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-08-05 12:57:01 -0700
commitbf55670de5a5934374946e00e633bcd6c7cb2c17 (patch)
treeefaea03e41249df94afbebd9c72183a8fbbc3c1c /usb/usb-serial-fix-stalled-writes.patch
parenta7c6d4fb3ad0fde884f9a83d33cae3bcb55a30e5 (diff)
downloadpatches-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.patch63
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). */