unbalanced calls to post_reset() from usb_reset_device()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

it seems to me that we have a subtle bug in usb_reset_device().
If we reset a device we may reprobe an interface. If that causes
another interface to be claimed we may call post_reset() for that
interface without having called pre_reset().

I think it is necessary to do the rebinding in a second pass after
doing the notifications. But this is subtle. Alan, what do you think?

	Regards
		Oliver

commit e6936977ba72a576a2365502dafb9f92d4260b32
Author: Oliver Neukum <oliver@xxxxxxxxxx>
Date:   Wed Nov 11 18:08:26 2009 +0100

    usb:fix unbalanced callbacks in usb_reset_device()
    
    if a driver needs to be rebound it may claim secondary interfaces
    in probe() for such interfaces post_reset() must not be called.
    Therefore rebinding must happen after all notifications.

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 691b0ea..5a3f797 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -3696,13 +3696,15 @@ int usb_reset_device(struct usb_device *udev)
 
 			if (!rebind && cintf->dev.driver) {
 				drv = to_usb_driver(cintf->dev.driver);
-				if (drv->post_reset)
-					rebind = (drv->post_reset)(cintf);
-				else if (cintf->condition ==
-						USB_INTERFACE_BOUND)
-					rebind = 1;
+				rebind = (drv->post_reset)(cintf);
 			}
-			if (ret == 0 && rebind)
+			cintf->needs_binding = rebind;
+		}
+		
+		/* second pass to not call post_reset on new drivers */
+		for (i = config->desc.bNumInterfaces - 1; i >= 0; --i){
+			struct usb_interface *cintf = config->interface[i];
+			if (ret == 0 && cintf->needs_binding)
 				usb_rebind_intf(cintf);
 		}
 	}
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux