| From 92aa5986f4f7b5a8bf282ca0f50967f4326559f5 Mon Sep 17 00:00:00 2001 |
| From: Oliver Neukum <oneukum@suse.com> |
| Date: Thu, 7 Nov 2019 15:28:55 +0100 |
| Subject: USB: chaoskey: fix error case of a timeout |
| |
| From: Oliver Neukum <oneukum@suse.com> |
| |
| commit 92aa5986f4f7b5a8bf282ca0f50967f4326559f5 upstream. |
| |
| In case of a timeout or if a signal aborts a read |
| communication with the device needs to be ended |
| lest we overwrite an active URB the next time we |
| do IO to the device, as the URB may still be active. |
| |
| Signed-off-by: Oliver Neukum <oneukum@suse.de> |
| Cc: stable <stable@vger.kernel.org> |
| Link: https://lore.kernel.org/r/20191107142856.16774-1-oneukum@suse.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/misc/chaoskey.c | 24 +++++++++++++++++++++--- |
| 1 file changed, 21 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/usb/misc/chaoskey.c |
| +++ b/drivers/usb/misc/chaoskey.c |
| @@ -384,13 +384,17 @@ static int _chaoskey_fill(struct chaoske |
| !dev->reading, |
| (started ? NAK_TIMEOUT : ALEA_FIRST_TIMEOUT) ); |
| |
| - if (result < 0) |
| + if (result < 0) { |
| + usb_kill_urb(dev->urb); |
| goto out; |
| + } |
| |
| - if (result == 0) |
| + if (result == 0) { |
| result = -ETIMEDOUT; |
| - else |
| + usb_kill_urb(dev->urb); |
| + } else { |
| result = dev->valid; |
| + } |
| out: |
| /* Let the device go back to sleep eventually */ |
| usb_autopm_put_interface(dev->interface); |
| @@ -526,7 +530,21 @@ static int chaoskey_suspend(struct usb_i |
| |
| static int chaoskey_resume(struct usb_interface *interface) |
| { |
| + struct chaoskey *dev; |
| + struct usb_device *udev = interface_to_usbdev(interface); |
| + |
| usb_dbg(interface, "resume"); |
| + dev = usb_get_intfdata(interface); |
| + |
| + /* |
| + * We may have lost power. |
| + * In that case the device that needs a long time |
| + * for the first requests needs an extended timeout |
| + * again |
| + */ |
| + if (le16_to_cpu(udev->descriptor.idVendor) == ALEA_VENDOR_ID) |
| + dev->reads_started = false; |
| + |
| return 0; |
| } |
| #else |