Author: thompsa
Date: Tue Jan 13 19:04:37 2009
New Revision: 187178
URL: http://svn.freebsd.org/changeset/base/187178

Log:
  MFp4: //depot/projects/u...@155936
  
        Save an USB transfer in UHUB driver by using
        the builtin clear-stall mechanism.
  
  Submitted by: Hans Petter Selasky

Modified:
  head/sys/dev/usb2/core/usb2_hub.c
  head/sys/dev/usb2/core/usb2_parse.c

Modified: head/sys/dev/usb2/core/usb2_hub.c
==============================================================================
--- head/sys/dev/usb2/core/usb2_hub.c   Tue Jan 13 19:04:12 2009        
(r187177)
+++ head/sys/dev/usb2/core/usb2_hub.c   Tue Jan 13 19:04:37 2009        
(r187178)
@@ -53,6 +53,7 @@
 #include <dev/usb2/controller/usb2_bus.h>
 
 #define        UHUB_INTR_INTERVAL 250          /* ms */
+#define        UHUB_N_TRANSFER 1
 
 #if USB_DEBUG
 static int uhub_debug = 0;
@@ -76,10 +77,9 @@ struct uhub_softc {
        struct uhub_current_state sc_st;/* current state */
        device_t sc_dev;                /* base device */
        struct usb2_device *sc_udev;    /* USB device */
-       struct usb2_xfer *sc_xfer[2];   /* interrupt xfer */
+       struct usb2_xfer *sc_xfer[UHUB_N_TRANSFER];     /* interrupt xfer */
        uint8_t sc_flags;
 #define        UHUB_FLAG_DID_EXPLORE 0x01
-#define        UHUB_FLAG_INTR_STALL 0x02
        char    sc_name[32];
 };
 
@@ -100,12 +100,11 @@ static bus_child_location_str_t uhub_chi
 static bus_child_pnpinfo_str_t uhub_child_pnpinfo_string;
 
 static usb2_callback_t uhub_intr_callback;
-static usb2_callback_t uhub_intr_clear_stall_callback;
 
 static void usb2_dev_resume_peer(struct usb2_device *udev);
 static void usb2_dev_suspend_peer(struct usb2_device *udev);
 
-static const struct usb2_config uhub_config[2] = {
+static const struct usb2_config uhub_config[UHUB_N_TRANSFER] = {
 
        [0] = {
                .type = UE_INTERRUPT,
@@ -117,17 +116,6 @@ static const struct usb2_config uhub_con
                .mh.callback = &uhub_intr_callback,
                .mh.interval = UHUB_INTR_INTERVAL,
        },
-
-       [1] = {
-               .type = UE_CONTROL,
-               .endpoint = 0,
-               .direction = UE_DIR_ANY,
-               .mh.timeout = 1000,     /* 1 second */
-               .mh.interval = 50,      /* 50ms */
-               .mh.flags = {},
-               .mh.bufsize = sizeof(struct usb2_device_request),
-               .mh.callback = &uhub_intr_clear_stall_callback,
-       },
 };
 
 /*
@@ -160,19 +148,6 @@ DRIVER_MODULE(ushub, usbus, uhub_driver,
 DRIVER_MODULE(ushub, ushub, uhub_driver, uhub_devclass, NULL, 0);
 
 static void
-uhub_intr_clear_stall_callback(struct usb2_xfer *xfer)
-{
-       struct uhub_softc *sc = xfer->priv_sc;
-       struct usb2_xfer *xfer_other = sc->sc_xfer[0];
-
-       if (usb2_clear_stall_callback(xfer, xfer_other)) {
-               DPRINTF("stall cleared\n");
-               sc->sc_flags &= ~UHUB_FLAG_INTR_STALL;
-               usb2_transfer_start(xfer_other);
-       }
-}
-
-static void
 uhub_intr_callback(struct usb2_xfer *xfer)
 {
        struct uhub_softc *sc = xfer->priv_sc;
@@ -189,21 +164,22 @@ uhub_intr_callback(struct usb2_xfer *xfe
                usb2_needs_explore(sc->sc_udev->bus, 0);
 
        case USB_ST_SETUP:
-               if (sc->sc_flags & UHUB_FLAG_INTR_STALL) {
-                       usb2_transfer_start(sc->sc_xfer[1]);
-               } else {
-                       xfer->frlengths[0] = xfer->max_data_length;
-                       usb2_start_hardware(xfer);
-               }
-               return;
+               xfer->frlengths[0] = xfer->max_data_length;
+               usb2_start_hardware(xfer);
+               break;
 
        default:                        /* Error */
                if (xfer->error != USB_ERR_CANCELLED) {
-                       /* start clear stall */
-                       sc->sc_flags |= UHUB_FLAG_INTR_STALL;
-                       usb2_transfer_start(sc->sc_xfer[1]);
+                       /*
+                        * Do a clear-stall. The "stall_pipe" flag
+                        * will get cleared before next callback by
+                        * the USB stack.
+                        */
+                       xfer->flags.stall_pipe = 1;
+                       xfer->frlengths[0] = xfer->max_data_length;
+                       usb2_start_hardware(xfer);
                }
-               return;
+               break;
        }
 }
 
@@ -736,7 +712,7 @@ uhub_attach(device_t dev)
        /* set up interrupt pipe */
        iface_index = 0;
        err = usb2_transfer_setup(udev, &iface_index, sc->sc_xfer,
-           uhub_config, 2, sc, &Giant);
+           uhub_config, UHUB_N_TRANSFER, sc, &Giant);
        if (err) {
                DPRINTFN(0, "cannot setup interrupt transfer, "
                    "errstr=%s!\n", usb2_errstr(err));
@@ -821,7 +797,7 @@ uhub_attach(device_t dev)
        return (0);
 
 error:
-       usb2_transfer_unsetup(sc->sc_xfer, 2);
+       usb2_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER);
 
        if (udev->hub) {
                free(udev->hub, M_USBDEV);
@@ -864,7 +840,7 @@ uhub_detach(device_t dev)
                child = NULL;
        }
 
-       usb2_transfer_unsetup(sc->sc_xfer, 2);
+       usb2_transfer_unsetup(sc->sc_xfer, UHUB_N_TRANSFER);
 
        free(hub, M_USBDEV);
        sc->sc_udev->hub = NULL;

Modified: head/sys/dev/usb2/core/usb2_parse.c
==============================================================================
--- head/sys/dev/usb2/core/usb2_parse.c Tue Jan 13 19:04:12 2009        
(r187177)
+++ head/sys/dev/usb2/core/usb2_parse.c Tue Jan 13 19:04:37 2009        
(r187178)
@@ -43,25 +43,44 @@
  *   Else: Next descriptor after "desc"
  *------------------------------------------------------------------------*/
 struct usb2_descriptor *
-usb2_desc_foreach(struct usb2_config_descriptor *cd, struct usb2_descriptor 
*desc)
+usb2_desc_foreach(struct usb2_config_descriptor *cd, 
+    struct usb2_descriptor *_desc)
 {
-       void *end;
+       uint8_t *desc_next;
+       uint8_t *start;
+       uint8_t *end;
+       uint8_t *desc;
 
-       if (cd == NULL) {
+       /* be NULL safe */
+       if (cd == NULL)
                return (NULL);
-       }
-       end = USB_ADD_BYTES(cd, UGETW(cd->wTotalLength));
 
-       if (desc == NULL) {
-               desc = USB_ADD_BYTES(cd, 0);
-       } else {
-               desc = USB_ADD_BYTES(desc, desc->bLength);
-       }
-       return (((((void *)desc) >= ((void *)cd)) &&
-           (((void *)desc) < end) &&
-           (USB_ADD_BYTES(desc, desc->bLength) >= ((void *)cd)) &&
-           (USB_ADD_BYTES(desc, desc->bLength) <= end) &&
-           (desc->bLength >= sizeof(*desc))) ? desc : NULL);
+       /* We assume that the "wTotalLength" has been checked. */
+       start = (uint8_t *)cd;
+       end = start + UGETW(cd->wTotalLength);
+       desc = (uint8_t *)_desc;
+
+       /* Get start of next USB descriptor. */
+       if (desc == NULL)
+               desc = start;
+       else
+               desc = desc + desc[0];
+
+       /* Check that the next USB descriptor is within the range. */
+       if ((desc < start) || (desc >= end))
+               return (NULL);          /* out of range, or EOD */
+
+       /* Check that the second next USB descriptor is within range. */
+       desc_next = desc + desc[0];
+       if ((desc_next < start) || (desc_next > end))
+               return (NULL);          /* out of range */
+
+       /* Check minimum descriptor length. */
+       if (desc[0] < 3)
+               return (NULL);          /* too short descriptor */
+
+       /* Return start of next descriptor. */
+       return ((struct usb2_descriptor *)desc);
 }
 
 /*------------------------------------------------------------------------*
@@ -140,7 +159,6 @@ usb2_find_edesc(struct usb2_config_descr
        desc = ((void *)d);
 
        while ((desc = usb2_desc_foreach(cd, desc))) {
-
                if (desc->bDescriptorType == UDESC_INTERFACE) {
                        break;
                }
@@ -195,7 +213,6 @@ usb2_get_no_alts(struct usb2_config_desc
        uint16_t n = 0;
 
        while ((desc = usb2_desc_foreach(cd, desc))) {
-
                if ((desc->bDescriptorType == UDESC_INTERFACE) &&
                    (desc->bLength >= sizeof(*id))) {
                        id = (void *)desc;
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to