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,7 +243,6 @@ int usb_endpoint_described ( struct usb_endpoint *ep,
243 243
 			     struct usb_interface_descriptor *interface,
244 244
 			     unsigned int type, unsigned int index ) {
245 245
 	struct usb_device *usb = ep->usb;
246
-	struct usb_port *port = usb->port;
247 246
 	struct usb_endpoint_descriptor *desc;
248 247
 	struct usb_endpoint_companion_descriptor *descx;
249 248
 	unsigned int sizes;
@@ -267,7 +266,7 @@ int usb_endpoint_described ( struct usb_endpoint *ep,
267 266
 	/* Calculate interval */
268 267
 	if ( ( type & USB_ENDPOINT_ATTR_TYPE_MASK ) ==
269 268
 	     USB_ENDPOINT_ATTR_INTERRUPT ) {
270
-		if ( port->speed >= USB_SPEED_HIGH ) {
269
+		if ( usb->speed >= USB_SPEED_HIGH ) {
271 270
 			/* 2^(desc->interval-1) is a microframe count */
272 271
 			interval = ( 1 << ( desc->interval - 1 ) );
273 272
 		} else {
@@ -1492,8 +1491,9 @@ static int register_usb ( struct usb_device *usb ) {
1492 1491
 		       hub->name, port->address, strerror ( rc ) );
1493 1492
 		goto err_speed;
1494 1493
 	}
1494
+	usb->speed = port->speed;
1495 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 1498
 	/* Open device */
1499 1499
 	if ( ( rc = usb->host->open ( usb ) ) != 0 ) {
@@ -1503,7 +1503,7 @@ static int register_usb ( struct usb_device *usb ) {
1503 1503
 	}
1504 1504
 
1505 1505
 	/* Describe control endpoint */
1506
-	mtu = USB_EP0_DEFAULT_MTU ( port->speed );
1506
+	mtu = USB_EP0_DEFAULT_MTU ( usb->speed );
1507 1507
 	usb_endpoint_describe ( &usb->control, USB_EP0_ADDRESS,
1508 1508
 				USB_EP0_ATTRIBUTES, mtu, USB_EP0_BURST,
1509 1509
 				USB_EP0_INTERVAL );
@@ -1554,7 +1554,7 @@ static int register_usb ( struct usb_device *usb ) {
1554 1554
 	       le16_to_cpu ( usb->device.product ), usb->device.class.class,
1555 1555
 	       usb->device.class.subclass, usb->device.class.protocol,
1556 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 1559
 	/* Configure device */
1560 1560
 	if ( ( rc = usb_autoconfigure ( usb ) ) != 0 )
@@ -2233,12 +2233,12 @@ struct usb_port * usb_transaction_translator ( struct usb_device *usb ) {
2233 2233
 	struct usb_device *parent;
2234 2234
 
2235 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 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 2242
 			return usb->port;
2243 2243
 	}
2244 2244
 

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

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

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

@@ -697,7 +697,7 @@ static int uhci_endpoint_open ( struct usb_endpoint *ep ) {
697 697
 		goto err_ring_alloc;
698 698
 	endpoint->ring.mtu = ep->mtu;
699 699
 	endpoint->ring.flags = UHCI_FL_CERR_MAX;
700
-	if ( usb->port->speed < USB_SPEED_FULL )
700
+	if ( usb->speed < USB_SPEED_FULL )
701 701
 		endpoint->ring.flags |= UHCI_FL_LS;
702 702
 	endpoint->ring.control = ( UHCI_CONTROL_DEVICE ( usb->address ) |
703 703
 				   UHCI_CONTROL_ENDPOINT ( ep->address ) );

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

@@ -2753,7 +2753,6 @@ static void xhci_device_close ( struct usb_device *usb ) {
2753 2753
 static int xhci_device_address ( struct usb_device *usb ) {
2754 2754
 	struct xhci_slot *slot = usb_get_hostdata ( usb );
2755 2755
 	struct xhci_device *xhci = slot->xhci;
2756
-	struct usb_port *port = usb->port;
2757 2756
 	struct usb_port *root_port;
2758 2757
 	int psiv;
2759 2758
 	int rc;
@@ -2766,7 +2765,7 @@ static int xhci_device_address ( struct usb_device *usb ) {
2766 2765
 	slot->port = root_port->address;
2767 2766
 
2768 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 2769
 	if ( psiv < 0 ) {
2771 2770
 		rc = psiv;
2772 2771
 		return rc;

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

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

Loading…
Cancel
Save