aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2014-05-26 13:23:33 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-05-27 18:04:08 -0400
commitc14829fad88dbeda57253590695b85ba51270621 (patch)
tree911ee5af3c0c0df403ae5346bf6e442a2c32406c /drivers/usb/serial
parentb0a9aa6da8088b722326a858ab572a13b5b6f9cb (diff)
USB: serial: fix potential runtime pm imbalance at device remove
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>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/bus.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index 35a2373cde67..9374bd2aba20 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -97,13 +97,19 @@ static int usb_serial_device_remove(struct device *dev)
97 struct usb_serial_port *port; 97 struct usb_serial_port *port;
98 int retval = 0; 98 int retval = 0;
99 int minor; 99 int minor;
100 int autopm_err;
100 101
101 port = to_usb_serial_port(dev); 102 port = to_usb_serial_port(dev);
102 if (!port) 103 if (!port)
103 return -ENODEV; 104 return -ENODEV;
104 105
105 /* make sure suspend/resume doesn't race against port_remove */ 106 /*
106 usb_autopm_get_interface(port->serial->interface); 107 * Make sure suspend/resume doesn't race against port_remove.
108 *
109 * Note that no further runtime PM callbacks will be made if
110 * autopm_get fails.
111 */
112 autopm_err = usb_autopm_get_interface(port->serial->interface);
107 113
108 minor = port->minor; 114 minor = port->minor;
109 tty_unregister_device(usb_serial_tty_driver, minor); 115 tty_unregister_device(usb_serial_tty_driver, minor);
@@ -117,7 +123,9 @@ static int usb_serial_device_remove(struct device *dev)
117 dev_info(dev, "%s converter now disconnected from ttyUSB%d\n", 123 dev_info(dev, "%s converter now disconnected from ttyUSB%d\n",
118 driver->description, minor); 124 driver->description, minor);
119 125
120 usb_autopm_put_interface(port->serial->interface); 126 if (!autopm_err)
127 usb_autopm_put_interface(port->serial->interface);
128
121 return retval; 129 return retval;
122} 130}
123 131