Date: Tue, 13 Jan 2009 19:04:37 +0000 (UTC) From: Andrew Thompson <thompsa@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r187178 - head/sys/dev/usb2/core Message-ID: <200901131904.n0DJ4bdK012739@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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/usb@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;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901131904.n0DJ4bdK012739>