|
@@ -958,13 +958,8 @@ void usb_rebind_intf(struct usb_interface *intf)
|
|
|
int rc;
|
|
|
|
|
|
/* Delayed unbind of an existing driver */
|
|
|
- if (intf->dev.driver) {
|
|
|
- struct usb_driver *driver =
|
|
|
- to_usb_driver(intf->dev.driver);
|
|
|
-
|
|
|
- dev_dbg(&intf->dev, "forced unbind\n");
|
|
|
- usb_driver_release_interface(driver, intf);
|
|
|
- }
|
|
|
+ if (intf->dev.driver)
|
|
|
+ usb_forced_unbind_intf(intf);
|
|
|
|
|
|
/* Try to rebind the interface */
|
|
|
if (!intf->dev.power.is_prepared) {
|
|
@@ -977,15 +972,13 @@ void usb_rebind_intf(struct usb_interface *intf)
|
|
|
|
|
|
#ifdef CONFIG_PM
|
|
|
|
|
|
-#define DO_UNBIND 0
|
|
|
-#define DO_REBIND 1
|
|
|
-
|
|
|
-/* Unbind drivers for @udev's interfaces that don't support suspend/resume,
|
|
|
- * or rebind interfaces that have been unbound, according to @action.
|
|
|
+/* Unbind drivers for @udev's interfaces that don't support suspend/resume
|
|
|
+ * There is no check for reset_resume here because it can be determined
|
|
|
+ * only during resume whether reset_resume is needed.
|
|
|
*
|
|
|
* The caller must hold @udev's device lock.
|
|
|
*/
|
|
|
-static void do_unbind_rebind(struct usb_device *udev, int action)
|
|
|
+static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
|
|
|
{
|
|
|
struct usb_host_config *config;
|
|
|
int i;
|
|
@@ -996,23 +989,53 @@ static void do_unbind_rebind(struct usb_device *udev, int action)
|
|
|
if (config) {
|
|
|
for (i = 0; i < config->desc.bNumInterfaces; ++i) {
|
|
|
intf = config->interface[i];
|
|
|
- switch (action) {
|
|
|
- case DO_UNBIND:
|
|
|
- if (intf->dev.driver) {
|
|
|
- drv = to_usb_driver(intf->dev.driver);
|
|
|
- if (!drv->suspend || !drv->resume)
|
|
|
- usb_forced_unbind_intf(intf);
|
|
|
- }
|
|
|
- break;
|
|
|
- case DO_REBIND:
|
|
|
- if (intf->needs_binding)
|
|
|
- usb_rebind_intf(intf);
|
|
|
- break;
|
|
|
+
|
|
|
+ if (intf->dev.driver) {
|
|
|
+ drv = to_usb_driver(intf->dev.driver);
|
|
|
+ if (!drv->suspend || !drv->resume)
|
|
|
+ usb_forced_unbind_intf(intf);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/* Unbind drivers for @udev's interfaces that failed to support reset-resume.
|
|
|
+ * These interfaces have the needs_binding flag set by usb_resume_interface().
|
|
|
+ *
|
|
|
+ * The caller must hold @udev's device lock.
|
|
|
+ */
|
|
|
+static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev)
|
|
|
+{
|
|
|
+ struct usb_host_config *config;
|
|
|
+ int i;
|
|
|
+ struct usb_interface *intf;
|
|
|
+
|
|
|
+ config = udev->actconfig;
|
|
|
+ if (config) {
|
|
|
+ for (i = 0; i < config->desc.bNumInterfaces; ++i) {
|
|
|
+ intf = config->interface[i];
|
|
|
+ if (intf->dev.driver && intf->needs_binding)
|
|
|
+ usb_forced_unbind_intf(intf);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void do_rebind_interfaces(struct usb_device *udev)
|
|
|
+{
|
|
|
+ struct usb_host_config *config;
|
|
|
+ int i;
|
|
|
+ struct usb_interface *intf;
|
|
|
+
|
|
|
+ config = udev->actconfig;
|
|
|
+ if (config) {
|
|
|
+ for (i = 0; i < config->desc.bNumInterfaces; ++i) {
|
|
|
+ intf = config->interface[i];
|
|
|
+ if (intf->needs_binding)
|
|
|
+ usb_rebind_intf(intf);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
|
|
|
{
|
|
|
struct usb_device_driver *udriver;
|
|
@@ -1302,7 +1325,12 @@ int usb_suspend(struct device *dev, pm_message_t msg)
|
|
|
{
|
|
|
struct usb_device *udev = to_usb_device(dev);
|
|
|
|
|
|
- do_unbind_rebind(udev, DO_UNBIND);
|
|
|
+ unbind_no_pm_drivers_interfaces(udev);
|
|
|
+
|
|
|
+ /* From now on we are sure all drivers support suspend/resume
|
|
|
+ * but not necessarily reset_resume()
|
|
|
+ * so we may still need to unbind and rebind upon resume
|
|
|
+ */
|
|
|
choose_wakeup(udev, msg);
|
|
|
return usb_suspend_both(udev, msg);
|
|
|
}
|
|
@@ -1313,15 +1341,20 @@ int usb_resume(struct device *dev, pm_message_t msg)
|
|
|
struct usb_device *udev = to_usb_device(dev);
|
|
|
int status;
|
|
|
|
|
|
- /* For PM complete calls, all we do is rebind interfaces */
|
|
|
+ /* For PM complete calls, all we do is rebind interfaces
|
|
|
+ * whose needs_binding flag is set
|
|
|
+ */
|
|
|
if (msg.event == PM_EVENT_ON) {
|
|
|
if (udev->state != USB_STATE_NOTATTACHED)
|
|
|
- do_unbind_rebind(udev, DO_REBIND);
|
|
|
+ do_rebind_interfaces(udev);
|
|
|
status = 0;
|
|
|
|
|
|
/* For all other calls, take the device back to full power and
|
|
|
* tell the PM core in case it was autosuspended previously.
|
|
|
- * Unbind the interfaces that will need rebinding later.
|
|
|
+ * Unbind the interfaces that will need rebinding later,
|
|
|
+ * because they fail to support reset_resume.
|
|
|
+ * (This can't be done in usb_resume_interface()
|
|
|
+ * above because it doesn't own the right set of locks.)
|
|
|
*/
|
|
|
} else {
|
|
|
status = usb_resume_both(udev, msg);
|
|
@@ -1329,7 +1362,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
|
|
|
pm_runtime_disable(dev);
|
|
|
pm_runtime_set_active(dev);
|
|
|
pm_runtime_enable(dev);
|
|
|
- do_unbind_rebind(udev, DO_REBIND);
|
|
|
+ unbind_no_reset_resume_drivers_interfaces(udev);
|
|
|
}
|
|
|
}
|
|
|
|