| From e4baed655b7754da9085d7cc74039831e2b490da Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <johan@kernel.org> |
| Date: Tue, 1 Oct 2019 10:49:05 +0200 |
| Subject: [PATCH] USB: usb-skeleton: fix runtime PM after driver unbind |
| |
| commit 5c290a5e42c3387e82de86965784d30e6c5270fd upstream. |
| |
| Since commit c2b71462d294 ("USB: core: Fix bug caused by duplicate |
| interface PM usage counter") USB drivers must always balance their |
| runtime PM gets and puts, including when the driver has already been |
| unbound from the interface. |
| |
| Leaving the interface with a positive PM usage counter would prevent a |
| later bound driver from suspending the device. |
| |
| Fixes: c2b71462d294 ("USB: core: Fix bug caused by duplicate interface PM usage counter") |
| Cc: stable <stable@vger.kernel.org> |
| Signed-off-by: Johan Hovold <johan@kernel.org> |
| Link: https://lore.kernel.org/r/20191001084908.2003-2-johan@kernel.org |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c |
| index f101347e3ea3..85b01f1fcd80 100644 |
| --- a/drivers/usb/usb-skeleton.c |
| +++ b/drivers/usb/usb-skeleton.c |
| @@ -71,6 +71,7 @@ static void skel_delete(struct kref *kref) |
| struct usb_skel *dev = to_skel_dev(kref); |
| |
| usb_free_urb(dev->bulk_in_urb); |
| + usb_put_intf(dev->interface); |
| usb_put_dev(dev->udev); |
| kfree(dev->bulk_in_buffer); |
| kfree(dev); |
| @@ -122,10 +123,7 @@ static int skel_release(struct inode *inode, struct file *file) |
| return -ENODEV; |
| |
| /* allow the device to be autosuspended */ |
| - mutex_lock(&dev->io_mutex); |
| - if (dev->interface) |
| - usb_autopm_put_interface(dev->interface); |
| - mutex_unlock(&dev->io_mutex); |
| + usb_autopm_put_interface(dev->interface); |
| |
| /* decrement the count on our device */ |
| kref_put(&dev->kref, skel_delete); |
| @@ -505,7 +503,7 @@ static int skel_probe(struct usb_interface *interface, |
| init_waitqueue_head(&dev->bulk_in_wait); |
| |
| dev->udev = usb_get_dev(interface_to_usbdev(interface)); |
| - dev->interface = interface; |
| + dev->interface = usb_get_intf(interface); |
| |
| /* set up the endpoint information */ |
| /* use only the first bulk-in and bulk-out endpoints */ |
| -- |
| 2.7.4 |
| |