|
@@ -184,6 +184,20 @@ static int usb_unbind_device(struct device *dev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Cancel any pending scheduled resets
|
|
|
|
+ *
|
|
|
|
+ * [see usb_queue_reset_device()]
|
|
|
|
+ *
|
|
|
|
+ * Called after unconfiguring / when releasing interfaces. See
|
|
|
|
+ * comments in __usb_queue_reset_device() regarding
|
|
|
|
+ * udev->reset_running.
|
|
|
|
+ */
|
|
|
|
+static void usb_cancel_queued_reset(struct usb_interface *iface)
|
|
|
|
+{
|
|
|
|
+ if (iface->reset_running == 0)
|
|
|
|
+ cancel_work_sync(&iface->reset_ws);
|
|
|
|
+}
|
|
|
|
|
|
/* called from driver core with dev locked */
|
|
/* called from driver core with dev locked */
|
|
static int usb_probe_interface(struct device *dev)
|
|
static int usb_probe_interface(struct device *dev)
|
|
@@ -242,6 +256,7 @@ static int usb_probe_interface(struct device *dev)
|
|
mark_quiesced(intf);
|
|
mark_quiesced(intf);
|
|
intf->needs_remote_wakeup = 0;
|
|
intf->needs_remote_wakeup = 0;
|
|
intf->condition = USB_INTERFACE_UNBOUND;
|
|
intf->condition = USB_INTERFACE_UNBOUND;
|
|
|
|
+ usb_cancel_queued_reset(intf);
|
|
} else
|
|
} else
|
|
intf->condition = USB_INTERFACE_BOUND;
|
|
intf->condition = USB_INTERFACE_BOUND;
|
|
|
|
|
|
@@ -272,6 +287,7 @@ static int usb_unbind_interface(struct device *dev)
|
|
usb_disable_interface(udev, intf);
|
|
usb_disable_interface(udev, intf);
|
|
|
|
|
|
driver->disconnect(intf);
|
|
driver->disconnect(intf);
|
|
|
|
+ usb_cancel_queued_reset(intf);
|
|
|
|
|
|
/* Reset other interface state.
|
|
/* Reset other interface state.
|
|
* We cannot do a Set-Interface if the device is suspended or
|
|
* We cannot do a Set-Interface if the device is suspended or
|
|
@@ -380,8 +396,10 @@ void usb_driver_release_interface(struct usb_driver *driver,
|
|
if (device_is_registered(dev)) {
|
|
if (device_is_registered(dev)) {
|
|
iface->condition = USB_INTERFACE_UNBINDING;
|
|
iface->condition = USB_INTERFACE_UNBINDING;
|
|
device_release_driver(dev);
|
|
device_release_driver(dev);
|
|
|
|
+ } else {
|
|
|
|
+ iface->condition = USB_INTERFACE_UNBOUND;
|
|
|
|
+ usb_cancel_queued_reset(iface);
|
|
}
|
|
}
|
|
-
|
|
|
|
dev->driver = NULL;
|
|
dev->driver = NULL;
|
|
usb_set_intfdata(iface, NULL);
|
|
usb_set_intfdata(iface, NULL);
|
|
|
|
|
|
@@ -942,7 +960,8 @@ static int usb_suspend_interface(struct usb_device *udev,
|
|
if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
|
|
if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf))
|
|
goto done;
|
|
goto done;
|
|
|
|
|
|
- if (intf->condition == USB_INTERFACE_UNBOUND) /* This can't happen */
|
|
|
|
|
|
+ /* This can happen; see usb_driver_release_interface() */
|
|
|
|
+ if (intf->condition == USB_INTERFACE_UNBOUND)
|
|
goto done;
|
|
goto done;
|
|
driver = to_usb_driver(intf->dev.driver);
|
|
driver = to_usb_driver(intf->dev.driver);
|
|
|
|
|