Browse Source

[usb] Record USB device speed separately from current port speed

Record the speed of a USB device based on the port's speed at the time
that the device was enabled.  This allows us to remember the device's
speed even after the device has been disconnected (and so the port's
current speed has changed).

In particular, this allows us to correctly identify the transaction
translator for a low-speed or full-speed device after the device has
been disconnected.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
eb1fc1e957
5 changed files with 15 additions and 14 deletions
  1. 9
    9
      src/drivers/bus/usb.c
  2. 2
    2
      src/drivers/usb/ehci.c
  3. 1
    1
      src/drivers/usb/uhci.c
  4. 1
    2
      src/drivers/usb/xhci.c
  5. 2
    0
      src/include/ipxe/usb.h

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

243
 			     struct usb_interface_descriptor *interface,
243
 			     struct usb_interface_descriptor *interface,
244
 			     unsigned int type, unsigned int index ) {
244
 			     unsigned int type, unsigned int index ) {
245
 	struct usb_device *usb = ep->usb;
245
 	struct usb_device *usb = ep->usb;
246
-	struct usb_port *port = usb->port;
247
 	struct usb_endpoint_descriptor *desc;
246
 	struct usb_endpoint_descriptor *desc;
248
 	struct usb_endpoint_companion_descriptor *descx;
247
 	struct usb_endpoint_companion_descriptor *descx;
249
 	unsigned int sizes;
248
 	unsigned int sizes;
267
 	/* Calculate interval */
266
 	/* Calculate interval */
268
 	if ( ( type & USB_ENDPOINT_ATTR_TYPE_MASK ) ==
267
 	if ( ( type & USB_ENDPOINT_ATTR_TYPE_MASK ) ==
269
 	     USB_ENDPOINT_ATTR_INTERRUPT ) {
268
 	     USB_ENDPOINT_ATTR_INTERRUPT ) {
270
-		if ( port->speed >= USB_SPEED_HIGH ) {
269
+		if ( usb->speed >= USB_SPEED_HIGH ) {
271
 			/* 2^(desc->interval-1) is a microframe count */
270
 			/* 2^(desc->interval-1) is a microframe count */
272
 			interval = ( 1 << ( desc->interval - 1 ) );
271
 			interval = ( 1 << ( desc->interval - 1 ) );
273
 		} else {
272
 		} else {
1492
 		       hub->name, port->address, strerror ( rc ) );
1491
 		       hub->name, port->address, strerror ( rc ) );
1493
 		goto err_speed;
1492
 		goto err_speed;
1494
 	}
1493
 	}
1494
+	usb->speed = port->speed;
1495
 	DBGC2 ( usb, "USB %s attached as %s-speed device\n",
1495
 	DBGC2 ( usb, "USB %s attached as %s-speed device\n",
1496
-		usb->name, usb_speed_name ( port->speed ) );
1496
+		usb->name, usb_speed_name ( usb->speed ) );
1497
 
1497
 
1498
 	/* Open device */
1498
 	/* Open device */
1499
 	if ( ( rc = usb->host->open ( usb ) ) != 0 ) {
1499
 	if ( ( rc = usb->host->open ( usb ) ) != 0 ) {
1503
 	}
1503
 	}
1504
 
1504
 
1505
 	/* Describe control endpoint */
1505
 	/* Describe control endpoint */
1506
-	mtu = USB_EP0_DEFAULT_MTU ( port->speed );
1506
+	mtu = USB_EP0_DEFAULT_MTU ( usb->speed );
1507
 	usb_endpoint_describe ( &usb->control, USB_EP0_ADDRESS,
1507
 	usb_endpoint_describe ( &usb->control, USB_EP0_ADDRESS,
1508
 				USB_EP0_ATTRIBUTES, mtu, USB_EP0_BURST,
1508
 				USB_EP0_ATTRIBUTES, mtu, USB_EP0_BURST,
1509
 				USB_EP0_INTERVAL );
1509
 				USB_EP0_INTERVAL );
1554
 	       le16_to_cpu ( usb->device.product ), usb->device.class.class,
1554
 	       le16_to_cpu ( usb->device.product ), usb->device.class.class,
1555
 	       usb->device.class.subclass, usb->device.class.protocol,
1555
 	       usb->device.class.subclass, usb->device.class.protocol,
1556
 	       usb_bcd ( le16_to_cpu ( usb->device.protocol ) ),
1556
 	       usb_bcd ( le16_to_cpu ( usb->device.protocol ) ),
1557
-	       usb_speed_name ( port->speed ), usb->control.mtu );
1557
+	       usb_speed_name ( usb->speed ), usb->control.mtu );
1558
 
1558
 
1559
 	/* Configure device */
1559
 	/* Configure device */
1560
 	if ( ( rc = usb_autoconfigure ( usb ) ) != 0 )
1560
 	if ( ( rc = usb_autoconfigure ( usb ) ) != 0 )
2233
 	struct usb_device *parent;
2233
 	struct usb_device *parent;
2234
 
2234
 
2235
 	/* Navigate up to root hub.  If we find a low-speed or
2235
 	/* Navigate up to root hub.  If we find a low-speed or
2236
-	 * full-speed port with a higher-speed parent device, then
2237
-	 * that port is the transaction translator.
2236
+	 * full-speed device with a higher-speed parent hub, then that
2237
+	 * device's port is the transaction translator.
2238
 	 */
2238
 	 */
2239
 	for ( ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
2239
 	for ( ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
2240
-		if ( ( usb->port->speed <= USB_SPEED_FULL ) &&
2241
-		     ( parent->port->speed > USB_SPEED_FULL ) )
2240
+		if ( ( usb->speed <= USB_SPEED_FULL ) &&
2241
+		     ( parent->speed > USB_SPEED_FULL ) )
2242
 			return usb->port;
2242
 			return usb->port;
2243
 	}
2243
 	}
2244
 
2244
 

+ 2
- 2
src/drivers/usb/ehci.c View File

970
 		chr |= EHCI_CHR_TOGGLE;
970
 		chr |= EHCI_CHR_TOGGLE;
971
 
971
 
972
 	/* Determine endpoint speed */
972
 	/* Determine endpoint speed */
973
-	if ( usb->port->speed == USB_SPEED_HIGH ) {
973
+	if ( usb->speed == USB_SPEED_HIGH ) {
974
 		chr |= EHCI_CHR_EPS_HIGH;
974
 		chr |= EHCI_CHR_EPS_HIGH;
975
 	} else {
975
 	} else {
976
-		if ( usb->port->speed == USB_SPEED_FULL ) {
976
+		if ( usb->speed == USB_SPEED_FULL ) {
977
 			chr |= EHCI_CHR_EPS_FULL;
977
 			chr |= EHCI_CHR_EPS_FULL;
978
 		} else {
978
 		} else {
979
 			chr |= EHCI_CHR_EPS_LOW;
979
 			chr |= EHCI_CHR_EPS_LOW;

+ 1
- 1
src/drivers/usb/uhci.c View File

697
 		goto err_ring_alloc;
697
 		goto err_ring_alloc;
698
 	endpoint->ring.mtu = ep->mtu;
698
 	endpoint->ring.mtu = ep->mtu;
699
 	endpoint->ring.flags = UHCI_FL_CERR_MAX;
699
 	endpoint->ring.flags = UHCI_FL_CERR_MAX;
700
-	if ( usb->port->speed < USB_SPEED_FULL )
700
+	if ( usb->speed < USB_SPEED_FULL )
701
 		endpoint->ring.flags |= UHCI_FL_LS;
701
 		endpoint->ring.flags |= UHCI_FL_LS;
702
 	endpoint->ring.control = ( UHCI_CONTROL_DEVICE ( usb->address ) |
702
 	endpoint->ring.control = ( UHCI_CONTROL_DEVICE ( usb->address ) |
703
 				   UHCI_CONTROL_ENDPOINT ( ep->address ) );
703
 				   UHCI_CONTROL_ENDPOINT ( ep->address ) );

+ 1
- 2
src/drivers/usb/xhci.c View File

2753
 static int xhci_device_address ( struct usb_device *usb ) {
2753
 static int xhci_device_address ( struct usb_device *usb ) {
2754
 	struct xhci_slot *slot = usb_get_hostdata ( usb );
2754
 	struct xhci_slot *slot = usb_get_hostdata ( usb );
2755
 	struct xhci_device *xhci = slot->xhci;
2755
 	struct xhci_device *xhci = slot->xhci;
2756
-	struct usb_port *port = usb->port;
2757
 	struct usb_port *root_port;
2756
 	struct usb_port *root_port;
2758
 	int psiv;
2757
 	int psiv;
2759
 	int rc;
2758
 	int rc;
2766
 	slot->port = root_port->address;
2765
 	slot->port = root_port->address;
2767
 
2766
 
2768
 	/* Calculate protocol speed ID */
2767
 	/* Calculate protocol speed ID */
2769
-	psiv = xhci_port_psiv ( xhci, slot->port, port->speed );
2768
+	psiv = xhci_port_psiv ( xhci, slot->port, usb->speed );
2770
 	if ( psiv < 0 ) {
2769
 	if ( psiv < 0 ) {
2771
 		rc = psiv;
2770
 		rc = psiv;
2772
 		return rc;
2771
 		return rc;

+ 2
- 0
src/include/ipxe/usb.h View File

698
 	char name[32];
698
 	char name[32];
699
 	/** USB port */
699
 	/** USB port */
700
 	struct usb_port *port;
700
 	struct usb_port *port;
701
+	/** Device speed */
702
+	unsigned int speed;
701
 	/** List of devices on this bus */
703
 	/** List of devices on this bus */
702
 	struct list_head list;
704
 	struct list_head list;
703
 	/** Device address, if assigned */
705
 	/** Device address, if assigned */

Loading…
Cancel
Save