Skip to content

Commit 5340ba8

Browse files
torvaldsgregkh
authored andcommitted
USB: don't use reset-resume if drivers don't support it
This patch tries to identify which devices are able to accept reset-resume handling, by checking that there is at least one interface driver bound and that all of the drivers have a reset_resume method defined. If these conditions don't hold then during resume processing, the device is logicall disconnected. This is only a temporary fix. Later on we will explicitly unbind drivers that can't handle reset-resumes. Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Alan Stern <[email protected]> Cc: Oliver Neukum <[email protected]> Cc: Pavel Machek <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent e6942d6 commit 5340ba8

File tree

1 file changed

+44
-2
lines changed

1 file changed

+44
-2
lines changed

drivers/usb/core/hub.c

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,48 @@ static void hub_stop(struct usb_hub *hub)
644644

645645
#ifdef CONFIG_PM
646646

647+
/* Try to identify which devices need USB-PERSIST handling */
648+
static int persistent_device(struct usb_device *udev)
649+
{
650+
int i;
651+
int retval;
652+
struct usb_host_config *actconfig;
653+
654+
/* Explicitly not marked persistent? */
655+
if (!udev->persist_enabled)
656+
return 0;
657+
658+
/* No active config? */
659+
actconfig = udev->actconfig;
660+
if (!actconfig)
661+
return 0;
662+
663+
/* FIXME! We should check whether it's open here or not! */
664+
665+
/*
666+
* Check that all the interface drivers have a
667+
* 'reset_resume' entrypoint
668+
*/
669+
retval = 0;
670+
for (i = 0; i < actconfig->desc.bNumInterfaces; i++) {
671+
struct usb_interface *intf;
672+
struct usb_driver *driver;
673+
674+
intf = actconfig->interface[i];
675+
if (!intf->dev.driver)
676+
continue;
677+
driver = to_usb_driver(intf->dev.driver);
678+
if (!driver->reset_resume)
679+
return 0;
680+
/*
681+
* We have at least one driver, and that one
682+
* has a reset_resume method.
683+
*/
684+
retval = 1;
685+
}
686+
return retval;
687+
}
688+
647689
static void hub_restart(struct usb_hub *hub, int type)
648690
{
649691
struct usb_device *hdev = hub->hdev;
@@ -689,8 +731,8 @@ static void hub_restart(struct usb_hub *hub, int type)
689731
* turn off the various status changes to prevent
690732
* khubd from disconnecting it later.
691733
*/
692-
if (udev->persist_enabled && status == 0 &&
693-
!(portstatus & USB_PORT_STAT_ENABLE)) {
734+
if (status == 0 && !(portstatus & USB_PORT_STAT_ENABLE) &&
735+
persistent_device(udev)) {
694736
if (portchange & USB_PORT_STAT_C_ENABLE)
695737
clear_port_feature(hub->hdev, port1,
696738
USB_PORT_FEAT_C_ENABLE);

0 commit comments

Comments
 (0)