|
@@ -1011,8 +1011,7 @@ EXPORT_SYMBOL_GPL(usb_deregister);
|
|
|
* it doesn't support pre_reset/post_reset/reset_resume or
|
|
|
* because it doesn't support suspend/resume.
|
|
|
*
|
|
|
- * The caller must hold @intf's device's lock, but not its pm_mutex
|
|
|
- * and not @intf->dev.sem.
|
|
|
+ * The caller must hold @intf's device's lock, but not @intf's lock.
|
|
|
*/
|
|
|
void usb_forced_unbind_intf(struct usb_interface *intf)
|
|
|
{
|
|
@@ -1025,16 +1024,37 @@ void usb_forced_unbind_intf(struct usb_interface *intf)
|
|
|
intf->needs_binding = 1;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Unbind drivers for @udev's marked interfaces. These interfaces have
|
|
|
+ * the needs_binding flag set, for example by usb_resume_interface().
|
|
|
+ *
|
|
|
+ * The caller must hold @udev's device lock.
|
|
|
+ */
|
|
|
+static void unbind_marked_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);
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/* Delayed forced unbinding of a USB interface driver and scan
|
|
|
* for rebinding.
|
|
|
*
|
|
|
- * The caller must hold @intf's device's lock, but not its pm_mutex
|
|
|
- * and not @intf->dev.sem.
|
|
|
+ * The caller must hold @intf's device's lock, but not @intf's lock.
|
|
|
*
|
|
|
* Note: Rebinds will be skipped if a system sleep transition is in
|
|
|
* progress and the PM "complete" callback hasn't occurred yet.
|
|
|
*/
|
|
|
-void usb_rebind_intf(struct usb_interface *intf)
|
|
|
+static void usb_rebind_intf(struct usb_interface *intf)
|
|
|
{
|
|
|
int rc;
|
|
|
|
|
@@ -1051,68 +1071,66 @@ void usb_rebind_intf(struct usb_interface *intf)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-#ifdef CONFIG_PM
|
|
|
-
|
|
|
-/* 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.
|
|
|
+/*
|
|
|
+ * Rebind drivers to @udev's marked interfaces. These interfaces have
|
|
|
+ * the needs_binding flag set.
|
|
|
*
|
|
|
* The caller must hold @udev's device lock.
|
|
|
*/
|
|
|
-static void unbind_no_pm_drivers_interfaces(struct usb_device *udev)
|
|
|
+static void rebind_marked_interfaces(struct usb_device *udev)
|
|
|
{
|
|
|
struct usb_host_config *config;
|
|
|
int i;
|
|
|
struct usb_interface *intf;
|
|
|
- struct usb_driver *drv;
|
|
|
|
|
|
config = udev->actconfig;
|
|
|
if (config) {
|
|
|
for (i = 0; i < config->desc.bNumInterfaces; ++i) {
|
|
|
intf = config->interface[i];
|
|
|
-
|
|
|
- if (intf->dev.driver) {
|
|
|
- drv = to_usb_driver(intf->dev.driver);
|
|
|
- if (!drv->suspend || !drv->resume)
|
|
|
- usb_forced_unbind_intf(intf);
|
|
|
- }
|
|
|
+ if (intf->needs_binding)
|
|
|
+ usb_rebind_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().
|
|
|
+/*
|
|
|
+ * Unbind all of @udev's marked interfaces and then rebind all of them.
|
|
|
+ * This ordering is necessary because some drivers claim several interfaces
|
|
|
+ * when they are first probed.
|
|
|
*
|
|
|
* The caller must hold @udev's device lock.
|
|
|
*/
|
|
|
-static void unbind_no_reset_resume_drivers_interfaces(struct usb_device *udev)
|
|
|
+void usb_unbind_and_rebind_marked_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);
|
|
|
- }
|
|
|
- }
|
|
|
+ unbind_marked_interfaces(udev);
|
|
|
+ rebind_marked_interfaces(udev);
|
|
|
}
|
|
|
|
|
|
-static void do_rebind_interfaces(struct usb_device *udev)
|
|
|
+#ifdef CONFIG_PM
|
|
|
+
|
|
|
+/* 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 unbind_no_pm_drivers_interfaces(struct usb_device *udev)
|
|
|
{
|
|
|
struct usb_host_config *config;
|
|
|
int i;
|
|
|
struct usb_interface *intf;
|
|
|
+ struct usb_driver *drv;
|
|
|
|
|
|
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);
|
|
|
+
|
|
|
+ if (intf->dev.driver) {
|
|
|
+ drv = to_usb_driver(intf->dev.driver);
|
|
|
+ if (!drv->suspend || !drv->resume)
|
|
|
+ usb_forced_unbind_intf(intf);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -1441,7 +1459,7 @@ int usb_resume_complete(struct device *dev)
|
|
|
* whose needs_binding flag is set
|
|
|
*/
|
|
|
if (udev->state != USB_STATE_NOTATTACHED)
|
|
|
- do_rebind_interfaces(udev);
|
|
|
+ rebind_marked_interfaces(udev);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -1463,7 +1481,7 @@ int usb_resume(struct device *dev, pm_message_t msg)
|
|
|
pm_runtime_disable(dev);
|
|
|
pm_runtime_set_active(dev);
|
|
|
pm_runtime_enable(dev);
|
|
|
- unbind_no_reset_resume_drivers_interfaces(udev);
|
|
|
+ unbind_marked_interfaces(udev);
|
|
|
}
|
|
|
|
|
|
/* Avoid PM error messages for devices disconnected while suspended
|