Browse Source

[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 9 years ago
parent
commit
5ecd16af04
1 changed files with 7 additions and 7 deletions
  1. 7
    7
      src/drivers/bus/usb.c

+ 7
- 7
src/drivers/bus/usb.c View File

1591
 	if ( ( rc = hub->driver->speed ( hub, port ) ) != 0 ) {
1591
 	if ( ( rc = hub->driver->speed ( hub, port ) ) != 0 ) {
1592
 		DBGC ( hub, "USB hub %s port %d could not get speed: %s\n",
1592
 		DBGC ( hub, "USB hub %s port %d could not get speed: %s\n",
1593
 		       hub->name, port->address, strerror ( rc ) );
1593
 		       hub->name, port->address, strerror ( rc ) );
1594
-		return rc;
1594
+		goto err_speed;
1595
 	}
1595
 	}
1596
 
1596
 
1597
 	/* Detach device, if applicable */
1597
 	/* Detach device, if applicable */
1599
 		usb_detached ( port );
1599
 		usb_detached ( port );
1600
 
1600
 
1601
 	/* Attach device, if applicable */
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
 	/* Clear any recorded disconnections */
1608
 	/* Clear any recorded disconnections */
1608
 	port->disconnected = 0;
1609
 	port->disconnected = 0;
1609
-
1610
-	return 0;
1610
+	return rc;
1611
 }
1611
 }
1612
 
1612
 
1613
 /******************************************************************************
1613
 /******************************************************************************

Loading…
Cancel
Save