| From c14829fad88dbeda57253590695b85ba51270621 Mon Sep 17 00:00:00 2001 |
| From: Johan Hovold <jhovold@gmail.com> |
| Date: Mon, 26 May 2014 19:23:33 +0200 |
| Subject: USB: serial: fix potential runtime pm imbalance at device remove |
| |
| From: Johan Hovold <jhovold@gmail.com> |
| |
| commit c14829fad88dbeda57253590695b85ba51270621 upstream. |
| |
| Only call usb_autopm_put_interface() if the corresponding |
| usb_autopm_get_interface() was successful. |
| |
| This prevents a potential runtime PM counter imbalance should |
| usb_autopm_get_interface() fail. Note that the USB PM usage counter is |
| reset when the interface is unbound, but that the runtime PM counter may |
| be left unbalanced. |
| |
| Also add comment on why we don't need to worry about racing |
| resume/suspend on autopm_get failures. |
| |
| Fixes: d5fd650cfc7f ("usb: serial: prevent suspend/resume from racing |
| against probe/remove") |
| |
| Signed-off-by: Johan Hovold <jhovold@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/usb/serial/bus.c | 14 +++++++++++--- |
| 1 file changed, 11 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/usb/serial/bus.c |
| +++ b/drivers/usb/serial/bus.c |
| @@ -97,13 +97,19 @@ static int usb_serial_device_remove(stru |
| struct usb_serial_port *port; |
| int retval = 0; |
| int minor; |
| + int autopm_err; |
| |
| port = to_usb_serial_port(dev); |
| if (!port) |
| return -ENODEV; |
| |
| - /* make sure suspend/resume doesn't race against port_remove */ |
| - usb_autopm_get_interface(port->serial->interface); |
| + /* |
| + * Make sure suspend/resume doesn't race against port_remove. |
| + * |
| + * Note that no further runtime PM callbacks will be made if |
| + * autopm_get fails. |
| + */ |
| + autopm_err = usb_autopm_get_interface(port->serial->interface); |
| |
| minor = port->minor; |
| tty_unregister_device(usb_serial_tty_driver, minor); |
| @@ -117,7 +123,9 @@ static int usb_serial_device_remove(stru |
| dev_info(dev, "%s converter now disconnected from ttyUSB%d\n", |
| driver->description, minor); |
| |
| - usb_autopm_put_interface(port->serial->interface); |
| + if (!autopm_err) |
| + usb_autopm_put_interface(port->serial->interface); |
| + |
| return retval; |
| } |
| |