]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[usb] Record USB device speed separately from current port speed
authorMichael Brown <mcb30@ipxe.org>
Sun, 6 Dec 2015 23:41:26 +0000 (23:41 +0000)
committerMichael Brown <mcb30@ipxe.org>
Mon, 7 Dec 2015 13:08:23 +0000 (13:08 +0000)
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>
src/drivers/bus/usb.c
src/drivers/usb/ehci.c
src/drivers/usb/uhci.c
src/drivers/usb/xhci.c
src/include/ipxe/usb.h

index 53501b46cd0733affe6d0bf93f901e592751724b..a3718d831e7d2c51b72bbe5b5f8970e890d09652 100644 (file)
@@ -243,7 +243,6 @@ int usb_endpoint_described ( struct usb_endpoint *ep,
                             struct usb_interface_descriptor *interface,
                             unsigned int type, unsigned int index ) {
        struct usb_device *usb = ep->usb;
-       struct usb_port *port = usb->port;
        struct usb_endpoint_descriptor *desc;
        struct usb_endpoint_companion_descriptor *descx;
        unsigned int sizes;
@@ -267,7 +266,7 @@ int usb_endpoint_described ( struct usb_endpoint *ep,
        /* Calculate interval */
        if ( ( type & USB_ENDPOINT_ATTR_TYPE_MASK ) ==
             USB_ENDPOINT_ATTR_INTERRUPT ) {
-               if ( port->speed >= USB_SPEED_HIGH ) {
+               if ( usb->speed >= USB_SPEED_HIGH ) {
                        /* 2^(desc->interval-1) is a microframe count */
                        interval = ( 1 << ( desc->interval - 1 ) );
                } else {
@@ -1492,8 +1491,9 @@ static int register_usb ( struct usb_device *usb ) {
                       hub->name, port->address, strerror ( rc ) );
                goto err_speed;
        }
+       usb->speed = port->speed;
        DBGC2 ( usb, "USB %s attached as %s-speed device\n",
-               usb->name, usb_speed_name ( port->speed ) );
+               usb->name, usb_speed_name ( usb->speed ) );
 
        /* Open device */
        if ( ( rc = usb->host->open ( usb ) ) != 0 ) {
@@ -1503,7 +1503,7 @@ static int register_usb ( struct usb_device *usb ) {
        }
 
        /* Describe control endpoint */
-       mtu = USB_EP0_DEFAULT_MTU ( port->speed );
+       mtu = USB_EP0_DEFAULT_MTU ( usb->speed );
        usb_endpoint_describe ( &usb->control, USB_EP0_ADDRESS,
                                USB_EP0_ATTRIBUTES, mtu, USB_EP0_BURST,
                                USB_EP0_INTERVAL );
@@ -1554,7 +1554,7 @@ static int register_usb ( struct usb_device *usb ) {
               le16_to_cpu ( usb->device.product ), usb->device.class.class,
               usb->device.class.subclass, usb->device.class.protocol,
               usb_bcd ( le16_to_cpu ( usb->device.protocol ) ),
-              usb_speed_name ( port->speed ), usb->control.mtu );
+              usb_speed_name ( usb->speed ), usb->control.mtu );
 
        /* Configure device */
        if ( ( rc = usb_autoconfigure ( usb ) ) != 0 )
@@ -2233,12 +2233,12 @@ struct usb_port * usb_transaction_translator ( struct usb_device *usb ) {
        struct usb_device *parent;
 
        /* Navigate up to root hub.  If we find a low-speed or
-        * full-speed port with a higher-speed parent device, then
-        * that port is the transaction translator.
+        * full-speed device with a higher-speed parent hub, then that
+        * device's port is the transaction translator.
         */
        for ( ; ( parent = usb->port->hub->usb ) ; usb = parent ) {
-               if ( ( usb->port->speed <= USB_SPEED_FULL ) &&
-                    ( parent->port->speed > USB_SPEED_FULL ) )
+               if ( ( usb->speed <= USB_SPEED_FULL ) &&
+                    ( parent->speed > USB_SPEED_FULL ) )
                        return usb->port;
        }
 
index f90d6a91affbc961876bc918c8f15b7c8e758b12..617a43b0340a1094dcce289d49a7e022adb93b25 100644 (file)
@@ -970,10 +970,10 @@ static uint32_t ehci_endpoint_characteristics ( struct usb_endpoint *ep ) {
                chr |= EHCI_CHR_TOGGLE;
 
        /* Determine endpoint speed */
-       if ( usb->port->speed == USB_SPEED_HIGH ) {
+       if ( usb->speed == USB_SPEED_HIGH ) {
                chr |= EHCI_CHR_EPS_HIGH;
        } else {
-               if ( usb->port->speed == USB_SPEED_FULL ) {
+               if ( usb->speed == USB_SPEED_FULL ) {
                        chr |= EHCI_CHR_EPS_FULL;
                } else {
                        chr |= EHCI_CHR_EPS_LOW;
index 4220bef720c110d687f44649c3189ce526a57cb7..528c1be1d6e89928d7cd0b4b8c27088293fc5e2c 100644 (file)
@@ -697,7 +697,7 @@ static int uhci_endpoint_open ( struct usb_endpoint *ep ) {
                goto err_ring_alloc;
        endpoint->ring.mtu = ep->mtu;
        endpoint->ring.flags = UHCI_FL_CERR_MAX;
-       if ( usb->port->speed < USB_SPEED_FULL )
+       if ( usb->speed < USB_SPEED_FULL )
                endpoint->ring.flags |= UHCI_FL_LS;
        endpoint->ring.control = ( UHCI_CONTROL_DEVICE ( usb->address ) |
                                   UHCI_CONTROL_ENDPOINT ( ep->address ) );
index 110b432876b14ac7ff96adae21afe3a219827c13..67de0a83250e9902837a71c5e984eee76390f1ee 100644 (file)
@@ -2753,7 +2753,6 @@ static void xhci_device_close ( struct usb_device *usb ) {
 static int xhci_device_address ( struct usb_device *usb ) {
        struct xhci_slot *slot = usb_get_hostdata ( usb );
        struct xhci_device *xhci = slot->xhci;
-       struct usb_port *port = usb->port;
        struct usb_port *root_port;
        int psiv;
        int rc;
@@ -2766,7 +2765,7 @@ static int xhci_device_address ( struct usb_device *usb ) {
        slot->port = root_port->address;
 
        /* Calculate protocol speed ID */
-       psiv = xhci_port_psiv ( xhci, slot->port, port->speed );
+       psiv = xhci_port_psiv ( xhci, slot->port, usb->speed );
        if ( psiv < 0 ) {
                rc = psiv;
                return rc;
index b3ce7b7410890a5e57d7c82475f0a3c6020e8838..c268988f430d28d9273876a38488a0054dfc2d45 100644 (file)
@@ -698,6 +698,8 @@ struct usb_device {
        char name[32];
        /** USB port */
        struct usb_port *port;
+       /** Device speed */
+       unsigned int speed;
        /** List of devices on this bus */
        struct list_head list;
        /** Device address, if assigned */