]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[usb] Use port->disconnected to check for disconnected devices
authorMichael Brown <mcb30@ipxe.org>
Sun, 6 Dec 2015 23:22:37 +0000 (23:22 +0000)
committerMichael Brown <mcb30@ipxe.org>
Mon, 7 Dec 2015 13:08:22 +0000 (13:08 +0000)
The usb_message() and usb_stream() functions currently check for
port->speed==USB_SPEED_NONE to determine whether or not a device has
been unplugged.  This test will give a false negative result if a new
device has been plugged in before the hotplug mechanism has finished
handling the removal of the old device.

Fix by checking instead the port->disconnected flag, which is now
cleared only after completing the removal of the old device.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/drivers/bus/usb.c
src/drivers/usb/usbhub.c

index 63a7e46a6daeebd84e5651721243a0bee76e8b35..53501b46cd0733affe6d0bf93f901e592751724b 100644 (file)
@@ -485,7 +485,7 @@ int usb_message ( struct usb_endpoint *ep, unsigned int request,
        assert ( iob_headroom ( iobuf ) >= sizeof ( *packet ) );
 
        /* Fail immediately if device has been unplugged */
-       if ( port->speed == USB_SPEED_NONE )
+       if ( port->disconnected )
                return -ENODEV;
 
        /* Reset endpoint if required */
@@ -534,7 +534,7 @@ int usb_stream ( struct usb_endpoint *ep, struct io_buffer *iobuf,
        int rc;
 
        /* Fail immediately if device has been unplugged */
-       if ( port->speed == USB_SPEED_NONE )
+       if ( port->disconnected )
                return -ENODEV;
 
        /* Reset endpoint if required */
@@ -1717,23 +1717,24 @@ static int usb_hotplugged ( struct usb_port *port ) {
        if ( ( rc = hub->driver->speed ( hub, port ) ) != 0 ) {
                DBGC ( hub, "USB hub %s port %d could not get speed: %s\n",
                       hub->name, port->address, strerror ( rc ) );
-               goto err_speed;
+               /* Treat as a disconnection */
+               port->disconnected = 1;
+               port->speed = USB_SPEED_NONE;
        }
 
        /* Detach device, if applicable */
        if ( port->attached && ( port->disconnected || ! port->speed ) )
                usb_detached ( port );
 
+       /* Clear any recorded disconnections */
+       port->disconnected = 0;
+
        /* Attach device, if applicable */
        if ( port->speed && ( ! port->attached ) &&
             ( ( rc = usb_attached ( port ) ) != 0 ) )
-               goto err_attached;
+               return rc;
 
- err_attached:
- err_speed:
-       /* Clear any recorded disconnections */
-       port->disconnected = 0;
-       return rc;
+       return 0;
 }
 
 /******************************************************************************
index 5cfc405203b9b7b5c06eb334155c0da4108e4469..a3e7bc00c66f666b78017b8c46ca654edd10ef2a 100644 (file)
@@ -496,9 +496,10 @@ static void hub_remove ( struct usb_function *func ) {
        unsigned int i;
 
        /* If hub has been unplugged, mark all ports as unplugged */
-       if ( usb->port->speed == USB_SPEED_NONE ) {
+       if ( usb->port->disconnected ) {
                for ( i = 1 ; i <= hub->ports ; i++ ) {
                        port = usb_port ( hub, i );
+                       port->disconnected = 1;
                        port->speed = USB_SPEED_NONE;
                }
        }