Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Aug 2010 18:25:48 GMT
From:      Hans Petter Selasky <hselasky@skunkworks.freebsd.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 182097 for review
Message-ID:  <201008111825.o7BIPmqN083697@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@182097?ac=10

Change 182097 by hselasky@hselasky_laptop001 on 2010/08/08 18:42:59

	USB core + USB controller (XHCI):
		- patches related to USB re-enumeration using XHCI chip.
		- be smarter when reading the USB device descriptor
		by exploiting information about the device speed.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#19 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_device.c#77 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_request.c#42 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_request.h#14 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#19 (text+ko) ====

@@ -125,6 +125,7 @@
 static usb_error_t xhci_configure_endpoint(struct usb_device *, struct usb_endpoint_descriptor *, uint64_t, uint16_t, uint8_t, uint16_t, uint16_t);
 static usb_error_t xhci_configure_mask(struct usb_device *, uint32_t, uint8_t);
 static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *, uint64_t, uint8_t);
+static usb_error_t xhci_cmd_reset_dev(struct xhci_softc *, uint8_t);
 
 extern struct usb_bus_methods xhci_bus_methods;
 
@@ -624,7 +625,6 @@
 	if (xfer->flags_int.control_xfr &&
 	    !xfer->flags_int.control_act)
 		err = xhci_generic_done_sub(xfer);
-
 done:
 	/* transfer is complete */
 	xhci_device_done(xfer, err);
@@ -1072,14 +1072,21 @@
 	switch (hdev->state) {
 	case XHCI_ST_ADDRESSED:
 	case XHCI_ST_CONFIGURED:
-		err = 0;
-		break;
+		if (udev->address == 0) {
+			err = xhci_cmd_reset_dev(sc, index);
 
-	case XHCI_ST_DEFAULT:
-		if (address == 0) {
+			if (err != 0) {
+				DPRINTF("Device reset failed\n");
+			}
+		} else {
 			err = 0;
 			break;
 		}
+
+	case XHCI_ST_DEFAULT:
+
+		hdev->state = XHCI_ST_ENABLED;
+
 		/* FALLTHROUGH */
 
 	case XHCI_ST_ENABLED:
@@ -1129,7 +1136,8 @@
 
 		if (err != 0) {
 			DPRINTF("Could not set address\n");
-			break;
+			if (address != 0)
+				break;
 		}
 
 		/* update device address to new value */
@@ -1155,7 +1163,6 @@
 			}
 
 			err = xhci_cmd_evaluate_ctx(sc, buf_inp.physaddr, index);
-
 			if (err != 0) {
 				DPRINTF("Could not evaluate device context\n");
 				break;
@@ -1286,7 +1293,6 @@
 	return (xhci_do_command(sc, &trb, 50 /* ms */));
 }
 
-#if 0
 static usb_error_t
 xhci_cmd_reset_dev(struct xhci_softc *sc, uint8_t slot_id)
 {
@@ -1304,7 +1310,6 @@
 
 	return (xhci_do_command(sc, &trb, 50 /* ms */));
 }
-#endif
 
 /*------------------------------------------------------------------------*
  *	xhci_interrupt - XHCI interrupt handler
@@ -3166,6 +3171,10 @@
 		xfer->flags_int.curr_dma_set = 1;
 		goto alloc_dma_set;
 	}
+
+	/* make sure we catch any set address updates */
+	if (parm->buf != NULL)
+		xhci_set_address(xfer->xroot->udev, NULL, 0);
 }
 
 static usb_error_t

==== //depot/projects/usb/src/sys/dev/usb/usb_device.c#77 (text+ko) ====

@@ -1681,45 +1681,16 @@
 	}
 	usb_set_device_state(udev, USB_STATE_ADDRESSED);
 
-	/*
-	 * Get the first 8 bytes of the device descriptor !
-	 *
-	 * NOTE: "usbd_do_request" will check the device descriptor
-	 * next time we do a request to see if the maximum packet size
-	 * changed! The 8 first bytes of the device descriptor
-	 * contains the maximum packet size to use on control endpoint
-	 * 0. If this value is different from "USB_MAX_IPACKET" a new
-	 * USB control request will be setup!
-	 */
-	err = usbd_req_get_desc(udev, NULL, NULL, &udev->ddesc,
-	    USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
-	if (err) {
-		DPRINTFN(0, "getting device descriptor "
-		    "at addr %d failed, %s\n", udev->address,
-		    usbd_errstr(err));
+	/* setup the device descriptor and the initial "wMaxPacketSize" */
+	err = usbd_setup_device_desc(udev, NULL);
+
+	if (err != 0) {
 		/* XXX try to re-enumerate the device */
 		err = usbd_req_re_enumerate(udev, NULL);
-		if (err) {
+		if (err)
 			goto done;
-		}
 	}
-	DPRINTF("adding unit addr=%d, rev=%02x, class=%d, "
-	    "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n",
-	    udev->address, UGETW(udev->ddesc.bcdUSB),
-	    udev->ddesc.bDeviceClass,
-	    udev->ddesc.bDeviceSubClass,
-	    udev->ddesc.bDeviceProtocol,
-	    udev->ddesc.bMaxPacketSize,
-	    udev->ddesc.bLength,
-	    udev->speed);
 
-	/* get the full device descriptor */
-	err = usbd_req_get_device_desc(udev, NULL, &udev->ddesc);
-	if (err) {
-		DPRINTF("addr=%d, getting full desc failed\n",
-		    udev->address);
-		goto done;
-	}
 	/*
 	 * Setup temporary USB attach args so that we can figure out some
 	 * basic quirks for this device.

==== //depot/projects/usb/src/sys/dev/usb/usb_request.c#42 (text+ko) ====

@@ -1763,6 +1763,68 @@
 }
 
 /*------------------------------------------------------------------------*
+ *	usbd_setup_device_desc
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_setup_device_desc(struct usb_device *udev, struct mtx *mtx)
+{
+	usb_error_t err;
+
+	/*
+	 * Get the first 8 bytes of the device descriptor !
+	 *
+	 * NOTE: "usbd_do_request()" will check the device descriptor
+	 * next time we do a request to see if the maximum packet size
+	 * changed! The 8 first bytes of the device descriptor
+	 * contains the maximum packet size to use on control endpoint
+	 * 0. If this value is different from "USB_MAX_IPACKET" a new
+	 * USB control request will be setup!
+	 */
+	switch (udev->speed) {
+	case USB_SPEED_FULL:
+	case USB_SPEED_LOW:
+		err = usbd_req_get_desc(udev, mtx, NULL, &udev->ddesc,
+		    USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
+		if (err != 0) {
+			DPRINTFN(0, "getting device descriptor "
+			    "at addr %d failed, %s\n", udev->address,
+			    usbd_errstr(err));
+			return (err);
+		}
+		break;
+	default:
+		DPRINTF("Minimum MaxPacketSize is large enough "
+		    "to hold the complete device descriptor\n");
+		break;
+	}
+
+	/* get the full device descriptor */
+	err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
+
+	/* try one more time, if error */
+	if (err)
+		err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
+
+	if (err) {
+		DPRINTF("addr=%d, getting full desc failed\n",
+		    udev->address);
+		return (err);
+	}
+
+	DPRINTF("adding unit addr=%d, rev=%02x, class=%d, "
+	    "subclass=%d, protocol=%d, maxpacket=%d, len=%d, speed=%d\n",
+	    udev->address, UGETW(udev->ddesc.bcdUSB),
+	    udev->ddesc.bDeviceClass,
+	    udev->ddesc.bDeviceSubClass,
+	    udev->ddesc.bDeviceProtocol,
+	    udev->ddesc.bMaxPacketSize,
+	    udev->ddesc.bLength,
+	    udev->speed);
+
+	return (err);
+}
+
+/*------------------------------------------------------------------------*
  *	usbd_req_re_enumerate
  *
  * NOTE: After this function returns the hardware is in the
@@ -1821,23 +1883,9 @@
 	if (udev->address == USB_START_ADDR)
 		udev->address = old_addr;
 
-	/* get the device descriptor */
-	err = usbd_req_get_desc(udev, mtx, NULL, &udev->ddesc,
-	    USB_MAX_IPACKET, USB_MAX_IPACKET, 0, UDESC_DEVICE, 0, 0);
-	if (err) {
-		DPRINTFN(0, "getting device descriptor "
-		    "at addr %d failed, %s\n", udev->address,
-		    usbd_errstr(err));
-		goto done;
-	}
-	/* get the full device descriptor */
-	err = usbd_req_get_device_desc(udev, mtx, &udev->ddesc);
-	if (err) {
-		DPRINTFN(0, "addr=%d, getting device "
-		    "descriptor failed, %s\n", old_addr, 
-		    usbd_errstr(err));
-		goto done;
-	}
+	/* setup the device descriptor and the initial "wMaxPacketSize" */
+	err = usbd_setup_device_desc(udev, mtx);
+
 done:
 	if (err && do_retry) {
 		/* give the USB firmware some time to load */

==== //depot/projects/usb/src/sys/dev/usb/usb_request.h#14 (text+ko) ====

@@ -71,6 +71,7 @@
 		    uint16_t sel);
 usb_error_t usbd_req_set_port_feature(struct usb_device *udev,
 		    struct mtx *mtx, uint8_t port, uint16_t sel);
+usb_error_t usbd_setup_device_desc(struct usb_device *udev, struct mtx *mtx);
 usb_error_t usbd_req_re_enumerate(struct usb_device *udev, struct mtx *mtx);
 usb_error_t usbd_req_clear_device_feature(struct usb_device *udev,
 		    struct mtx *mtx, uint16_t sel);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201008111825.o7BIPmqN083697>