Explorar el Código

[usb] Always clear recorded disconnections after performing hotplug actions

The recorded disconnections (in port->disconnected) will currently be
left uncleared if usb_attached() returns an error (e.g. because there
are no drivers for a particular USB device).  This is incorrect
behaviour: the disconnection has been handled and the record should be
cleared until the next physical disconnection is detected (via the CSC
bit).

The problem is masked for EHCI, UHCI, and USB hubs, since these will
report a changed port (via usb_port_changed()) only when the
underlying hardware reports a change.  xHCI will call
usb_port_changed() in response to any port status event, at which
point the stale value of port->disconnected will be erroneously acted
upon.  This can lead to an endless loop of repeatedly enumerating the
same device when a driverless device is attached to an xHCI root hub
port.

Fix by unconditionally clearing port->disconnected in usb_hotplugged().

Reported-by: Robin Smidsrød <robin@smidsrod.no>
Tested-by: Robin Smidsrød <robin@smidsrod.no>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown hace 9 años
padre
commit
5ecd16af04
Se han modificado 1 ficheros con 7 adiciones y 7 borrados
  1. 7
    7
      src/drivers/bus/usb.c

+ 7
- 7
src/drivers/bus/usb.c Ver fichero

@@ -1591,7 +1591,7 @@ static int usb_hotplugged ( struct usb_port *port ) {
1591 1591
 	if ( ( rc = hub->driver->speed ( hub, port ) ) != 0 ) {
1592 1592
 		DBGC ( hub, "USB hub %s port %d could not get speed: %s\n",
1593 1593
 		       hub->name, port->address, strerror ( rc ) );
1594
-		return rc;
1594
+		goto err_speed;
1595 1595
 	}
1596 1596
 
1597 1597
 	/* Detach device, if applicable */
@@ -1599,15 +1599,15 @@ static int usb_hotplugged ( struct usb_port *port ) {
1599 1599
 		usb_detached ( port );
1600 1600
 
1601 1601
 	/* Attach device, if applicable */
1602
-	if ( port->speed && ! port->attached ) {
1603
-		if ( ( rc = usb_attached ( port ) ) != 0 )
1604
-			return rc;
1605
-	}
1602
+	if ( port->speed && ( ! port->attached ) &&
1603
+	     ( ( rc = usb_attached ( port ) ) != 0 ) )
1604
+		goto err_attached;
1606 1605
 
1606
+ err_attached:
1607
+ err_speed:
1607 1608
 	/* Clear any recorded disconnections */
1608 1609
 	port->disconnected = 0;
1609
-
1610
-	return 0;
1610
+	return rc;
1611 1611
 }
1612 1612
 
1613 1613
 /******************************************************************************

Loading…
Cancelar
Guardar