summaryrefslogtreecommitdiffstats
path: root/src/drivers/bus
diff options
context:
space:
mode:
authorMichael Brown2015-05-06 17:38:28 +0200
committerMichael Brown2015-05-08 15:57:14 +0200
commitf6604627ff71d42bb63a3d81c2986a9d296d55cb (patch)
tree8eb038959b4e3429c4c15e9a1a7a5bd73e68c2b2 /src/drivers/bus
parent[pci] Provide PCI_CLASS() to calculate a scalar PCI class value (diff)
downloadipxe-f6604627ff71d42bb63a3d81c2986a9d296d55cb.tar.gz
ipxe-f6604627ff71d42bb63a3d81c2986a9d296d55cb.tar.xz
ipxe-f6604627ff71d42bb63a3d81c2986a9d296d55cb.zip
[usb] Detect missed disconnections
The USB core will currently fail to detect disconnections if a new device has attached by the time the port is examined in usb_hotplug(). Fix by recording the fact that a disconnection has taken place whenever the "connection status changed" (CSC) bit is observed to be set. (Whether the change represents a disconnection or a reconnection, it indicates that the port has experienced some time of being disconnected.) Note that the time at which a disconnection can be detected varies by hub type. In particular: root hubs can observe the CSC bit when polling, and so will record the disconnection before calling usb_port_changed(), but USB hubs read the port status (and hence the CSC bit) only during the call to hub_speed(), long after the call to usb_port_changed(). Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/drivers/bus')
-rw-r--r--src/drivers/bus/usb.c22
1 files changed, 12 insertions, 10 deletions
diff --git a/src/drivers/bus/usb.c b/src/drivers/bus/usb.c
index 2191867a..2b9efa45 100644
--- a/src/drivers/bus/usb.c
+++ b/src/drivers/bus/usb.c
@@ -1589,18 +1589,20 @@ static int usb_hotplug ( struct usb_port *port ) {
return rc;
}
- /* Handle attached/detached device as applicable */
- if ( port->speed && ! port->attached ) {
- /* Newly attached device */
- return usb_attached ( port );
- } else if ( port->attached && ! port->speed ) {
- /* Newly detached device */
+ /* Detach device, if applicable */
+ if ( port->attached && ( port->disconnected || ! port->speed ) )
usb_detached ( port );
- return 0;
- } else {
- /* Ignore */
- return 0;
+
+ /* Attach device, if applicable */
+ if ( port->speed && ! port->attached ) {
+ if ( ( rc = usb_attached ( port ) ) != 0 )
+ return rc;
}
+
+ /* Clear any recorded disconnections */
+ port->disconnected = 0;
+
+ return 0;
}
/******************************************************************************