From owner-svn-src-head@FreeBSD.ORG Sun Feb 10 10:56:16 2013 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 79EE7744; Sun, 10 Feb 2013 10:56:16 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id 6BB1D3FD; Sun, 10 Feb 2013 10:56:16 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r1AAuGxB027840; Sun, 10 Feb 2013 10:56:16 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r1AAuEmK027828; Sun, 10 Feb 2013 10:56:14 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201302101056.r1AAuEmK027828@svn.freebsd.org> From: Hans Petter Selasky Date: Sun, 10 Feb 2013 10:56:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r246616 - in head/sys: boot/usb dev/usb dev/usb/template X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 10 Feb 2013 10:56:16 -0000 Author: hselasky Date: Sun Feb 10 10:56:13 2013 New Revision: 246616 URL: http://svnweb.freebsd.org/changeset/base/246616 Log: - Move scratch data from the USB bus structure to the USB device structure so that simultaneous access cannot happen. Protect scratch area using the enumeration lock. Also reduce stack usage in usbd_transfer_setup() by moving some big stack members to the scratch area. This saves around 200 bytes of stack. - Fix a whitespace. MFC after: 1 week Modified: head/sys/boot/usb/bsd_global.h head/sys/dev/usb/template/usb_template.c head/sys/dev/usb/usb_bus.h head/sys/dev/usb/usb_controller.h head/sys/dev/usb/usb_device.c head/sys/dev/usb/usb_device.h head/sys/dev/usb/usb_generic.c head/sys/dev/usb/usb_handle_request.c head/sys/dev/usb/usb_msctest.c head/sys/dev/usb/usb_transfer.c head/sys/dev/usb/usb_util.c Modified: head/sys/boot/usb/bsd_global.h ============================================================================== --- head/sys/boot/usb/bsd_global.h Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/boot/usb/bsd_global.h Sun Feb 10 10:56:13 2013 (r246616) @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -52,7 +53,6 @@ #include #include #include -#include #include #include #include Modified: head/sys/dev/usb/template/usb_template.c ============================================================================== --- head/sys/dev/usb/template/usb_template.c Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/dev/usb/template/usb_template.c Sun Feb 10 10:56:13 2013 (r246616) @@ -849,20 +849,20 @@ usb_hw_ep_resolve(struct usb_device *ude struct usb_device_descriptor *dd; uint16_t mps; - if (desc == NULL) { + if (desc == NULL) return (USB_ERR_INVAL); - } + /* get bus methods */ methods = udev->bus->methods; - if (methods->get_hw_ep_profile == NULL) { + if (methods->get_hw_ep_profile == NULL) return (USB_ERR_INVAL); - } + if (desc->bDescriptorType == UDESC_DEVICE) { - if (desc->bLength < sizeof(*dd)) { + if (desc->bLength < sizeof(*dd)) return (USB_ERR_INVAL); - } + dd = (void *)desc; /* get HW control endpoint 0 profile */ @@ -909,13 +909,12 @@ usb_hw_ep_resolve(struct usb_device *ude } return (0); /* success */ } - if (desc->bDescriptorType != UDESC_CONFIG) { + if (desc->bDescriptorType != UDESC_CONFIG) return (USB_ERR_INVAL); - } - if (desc->bLength < sizeof(*(ues->cd))) { + if (desc->bLength < sizeof(*(ues->cd))) return (USB_ERR_INVAL); - } - ues = udev->bus->scratch[0].hw_ep_scratch; + + ues = udev->scratch.hw_ep_scratch; memset(ues, 0, sizeof(*ues)); @@ -1236,13 +1235,18 @@ usb_temp_setup(struct usb_device *udev, { struct usb_temp_setup *uts; void *buf; + usb_error_t error; uint8_t n; + uint8_t do_unlock; - if (tdd == NULL) { - /* be NULL safe */ + /* be NULL safe */ + if (tdd == NULL) return (0); - } - uts = udev->bus->scratch[0].temp_setup; + + /* Protect scratch area */ + do_unlock = usbd_enum_lock(udev); + + uts = udev->scratch.temp_setup; memset(uts, 0, sizeof(*uts)); @@ -1255,17 +1259,24 @@ usb_temp_setup(struct usb_device *udev, if (uts->err) { /* some error happened */ - return (uts->err); + goto done; } /* sanity check */ if (uts->size == 0) { - return (USB_ERR_INVAL); + uts->err = USB_ERR_INVAL; + goto done; } /* allocate zeroed memory */ uts->buf = malloc(uts->size, M_USB, M_WAITOK | M_ZERO); + /* + * Allow malloc() to return NULL regardless of M_WAITOK flag. + * This helps when porting the software to non-FreeBSD + * systems. + */ if (uts->buf == NULL) { /* could not allocate memory */ - return (USB_ERR_NOMEM); + uts->err = USB_ERR_NOMEM; + goto done; } /* second pass */ @@ -1280,7 +1291,7 @@ usb_temp_setup(struct usb_device *udev, if (uts->err) { /* some error happened during second pass */ - goto error; + goto done; } /* * Resolve all endpoint addresses ! @@ -1291,7 +1302,7 @@ usb_temp_setup(struct usb_device *udev, DPRINTFN(0, "Could not resolve endpoints for " "Device Descriptor, error = %s\n", usbd_errstr(uts->err)); - goto error; + goto done; } for (n = 0;; n++) { @@ -1304,14 +1315,16 @@ usb_temp_setup(struct usb_device *udev, DPRINTFN(0, "Could not resolve endpoints for " "Config Descriptor %u, error = %s\n", n, usbd_errstr(uts->err)); - goto error; + goto done; } } - return (uts->err); - -error: - usb_temp_unsetup(udev); - return (uts->err); +done: + error = uts->err; + if (error) + usb_temp_unsetup(udev); + if (do_unlock) + usbd_enum_unlock(udev); + return (error); } /*------------------------------------------------------------------------* Modified: head/sys/dev/usb/usb_bus.h ============================================================================== --- head/sys/dev/usb/usb_bus.h Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/dev/usb/usb_bus.h Sun Feb 10 10:56:13 2013 (r246616) @@ -113,16 +113,6 @@ struct usb_bus { uint8_t devices_max; /* maximum number of USB devices */ uint8_t do_probe; /* set if USB should be re-probed */ uint8_t no_explore; /* don't explore USB ports */ - - /* - * The scratch area can only be used inside the explore thread - * belonging to the give serial bus. - */ - union { - struct usb_hw_ep_scratch hw_ep_scratch[1]; - struct usb_temp_setup temp_setup[1]; - uint8_t data[255]; - } scratch[1]; }; #endif /* _USB_BUS_H_ */ Modified: head/sys/dev/usb/usb_controller.h ============================================================================== --- head/sys/dev/usb/usb_controller.h Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/dev/usb/usb_controller.h Sun Feb 10 10:56:13 2013 (r246616) @@ -40,7 +40,6 @@ struct usb_page_cache; struct usb_setup_params; struct usb_hw_ep_profile; struct usb_fs_isoc_schedule; -struct usb_config_descriptor; struct usb_endpoint_descriptor; /* typedefs */ @@ -186,50 +185,6 @@ struct usb_hw_ep_profile { uint8_t support_out:1; /* OUT-token is supported */ }; -/* - * The following structure is used when trying to allocate hardware - * endpoints for an USB configuration in USB device side mode. - */ -struct usb_hw_ep_scratch_sub { - const struct usb_hw_ep_profile *pf; - uint16_t max_frame_size; - uint8_t hw_endpoint_out; - uint8_t hw_endpoint_in; - uint8_t needs_ep_type; - uint8_t needs_in:1; - uint8_t needs_out:1; -}; - -/* - * The following structure is used when trying to allocate hardware - * endpoints for an USB configuration in USB device side mode. - */ -struct usb_hw_ep_scratch { - struct usb_hw_ep_scratch_sub ep[USB_EP_MAX]; - struct usb_hw_ep_scratch_sub *ep_max; - struct usb_config_descriptor *cd; - struct usb_device *udev; - struct usb_bus_methods *methods; - uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16]; - uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16]; -}; - -/* - * The following structure is used when generating USB descriptors - * from USB templates. - */ -struct usb_temp_setup { - void *buf; - usb_size_t size; - enum usb_dev_speed usb_speed; - uint8_t self_powered; - uint8_t bNumEndpoints; - uint8_t bInterfaceNumber; - uint8_t bAlternateSetting; - uint8_t bConfigurationValue; - usb_error_t err; -}; - /* prototypes */ void usb_bus_mem_flush_all(struct usb_bus *bus, usb_bus_mem_cb_t *cb); Modified: head/sys/dev/usb/usb_device.c ============================================================================== --- head/sys/dev/usb/usb_device.c Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/dev/usb/usb_device.c Sun Feb 10 10:56:13 2013 (r246616) @@ -460,13 +460,8 @@ usb_unconfigure(struct usb_device *udev, { uint8_t do_unlock; - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); /* detach all interface drivers */ usb_detach_device(udev, USB_IFACE_INDEX_ANY, flag); @@ -529,13 +524,8 @@ usbd_set_config_index(struct usb_device DPRINTFN(6, "udev=%p index=%d\n", udev, index); - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); usb_unconfigure(udev, 0); @@ -888,13 +878,9 @@ usbd_set_alt_interface_index(struct usb_ usb_error_t err; uint8_t do_unlock; - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); + if (iface == NULL) { err = USB_ERR_INVAL; goto done; @@ -931,7 +917,6 @@ usbd_set_alt_interface_index(struct usb_ done: if (do_unlock) usbd_enum_unlock(udev); - return (err); } @@ -1310,13 +1295,8 @@ usb_probe_and_attach(struct usb_device * DPRINTF("udev == NULL\n"); return (USB_ERR_INVAL); } - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); if (udev->curr_config_index == USB_UNCONFIG_INDEX) { /* do nothing - no configuration has been set */ @@ -1403,7 +1383,6 @@ usb_probe_and_attach(struct usb_device * done: if (do_unlock) usbd_enum_unlock(udev); - return (0); } @@ -1532,6 +1511,7 @@ usb_alloc_device(device_t parent_dev, st uint8_t config_index; uint8_t config_quirk; uint8_t set_config_failed; + uint8_t do_unlock; DPRINTF("parent_dev=%p, bus=%p, parent_hub=%p, depth=%u, " "port_index=%u, port_no=%u, speed=%u, usb_mode=%u\n", @@ -1750,7 +1730,11 @@ usb_alloc_device(device_t parent_dev, st * device descriptor. If no strings are present there we * simply disable all USB strings. */ - scratch_ptr = udev->bus->scratch[0].data; + + /* Protect scratch area */ + do_unlock = usbd_enum_lock(udev); + + scratch_ptr = udev->scratch.data; if (udev->ddesc.iManufacturer || udev->ddesc.iProduct || @@ -1775,7 +1759,7 @@ usb_alloc_device(device_t parent_dev, st mask = usb_lang_mask; /* align length correctly */ - scratch_ptr[0] &= ~1; + scratch_ptr[0] &= ~1U; /* fix compiler warning */ langid = 0; @@ -1796,6 +1780,9 @@ usb_alloc_device(device_t parent_dev, st udev->langid = langid; } + if (do_unlock) + usbd_enum_unlock(udev); + /* assume 100mA bus powered for now. Changed when configured. */ udev->power = USB_MIN_POWER; /* fetch the vendor and product strings from the device */ @@ -2295,9 +2282,13 @@ usbd_set_device_strings(struct usb_devic size_t temp_size; uint16_t vendor_id; uint16_t product_id; + uint8_t do_unlock; - temp_ptr = (char *)udev->bus->scratch[0].data; - temp_size = sizeof(udev->bus->scratch[0].data); + /* Protect scratch area */ + do_unlock = usbd_enum_lock(udev); + + temp_ptr = (char *)udev->scratch.data; + temp_size = sizeof(udev->scratch.data); vendor_id = UGETW(udd->idVendor); product_id = UGETW(udd->idProduct); @@ -2352,6 +2343,9 @@ usbd_set_device_strings(struct usb_devic snprintf(temp_ptr, temp_size, "product 0x%04x", product_id); udev->product = strdup(temp_ptr, M_USB); } + + if (do_unlock) + usbd_enum_unlock(udev); } /* @@ -2664,11 +2658,17 @@ usbd_device_attached(struct usb_device * return (udev->state > USB_STATE_DETACHED); } -/* The following function locks enumerating the given USB device. */ - -void +/* + * The following function locks enumerating the given USB device. If + * the lock is already grabbed this function returns zero. Else a + * non-zero value is returned. + */ +uint8_t usbd_enum_lock(struct usb_device *udev) { + if (sx_xlocked(&udev->enum_sx)) + return (0); + sx_xlock(&udev->enum_sx); sx_xlock(&udev->sr_sx); /* @@ -2677,6 +2677,7 @@ usbd_enum_lock(struct usb_device *udev) * locked multiple times. */ mtx_lock(&Giant); + return (1); } /* The following function unlocks enumerating the given USB device. */ @@ -2783,13 +2784,8 @@ usbd_set_endpoint_mode(struct usb_device usb_error_t error; uint8_t do_unlock; - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); if (udev->bus->methods->set_endpoint_mode != NULL) { error = (udev->bus->methods->set_endpoint_mode) ( @@ -2805,7 +2801,6 @@ usbd_set_endpoint_mode(struct usb_device if (do_unlock) usbd_enum_unlock(udev); - return (error); } Modified: head/sys/dev/usb/usb_device.h ============================================================================== --- head/sys/dev/usb/usb_device.h Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/dev/usb/usb_device.h Sun Feb 10 10:56:13 2013 (r246616) @@ -27,9 +27,18 @@ #ifndef _USB_DEVICE_H_ #define _USB_DEVICE_H_ -struct usb_symlink; /* UGEN */ +#ifndef USB_GLOBAL_INCLUDE_FILE +#include +#include +#include +#endif + +struct usb_bus_methods; +struct usb_config_descriptor; struct usb_device; /* linux compat */ struct usb_fs_privdata; +struct usb_hw_ep_profile; +struct usb_symlink; /* UGEN */ #define USB_CTRL_XFER_MAX 2 @@ -108,6 +117,64 @@ struct usb_power_save { }; /* + * The following structure is used when trying to allocate hardware + * endpoints for an USB configuration in USB device side mode. + */ +struct usb_hw_ep_scratch_sub { + const struct usb_hw_ep_profile *pf; + uint16_t max_frame_size; + uint8_t hw_endpoint_out; + uint8_t hw_endpoint_in; + uint8_t needs_ep_type; + uint8_t needs_in:1; + uint8_t needs_out:1; +}; + +/* + * The following structure is used when trying to allocate hardware + * endpoints for an USB configuration in USB device side mode. + */ +struct usb_hw_ep_scratch { + struct usb_hw_ep_scratch_sub ep[USB_EP_MAX]; + struct usb_hw_ep_scratch_sub *ep_max; + struct usb_config_descriptor *cd; + struct usb_device *udev; + struct usb_bus_methods *methods; + uint8_t bmOutAlloc[(USB_EP_MAX + 15) / 16]; + uint8_t bmInAlloc[(USB_EP_MAX + 15) / 16]; +}; + +/* + * The following structure is used when generating USB descriptors + * from USB templates. + */ +struct usb_temp_setup { + void *buf; + usb_size_t size; + enum usb_dev_speed usb_speed; + uint8_t self_powered; + uint8_t bNumEndpoints; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bConfigurationValue; + usb_error_t err; +}; + +/* + * The scratch area for USB devices. Access to this structure is + * protected by the enumeration SX lock. + */ +union usb_device_scratch { + struct usb_hw_ep_scratch hw_ep_scratch[1]; + struct usb_temp_setup temp_setup[1]; + struct { + struct usb_xfer dummy; + struct usb_setup_params parm; + } xfer_setup[1]; + uint8_t data[255]; +}; + +/* * The following structure defines an USB device. There exists one of * these structures for every USB device. */ @@ -191,6 +258,8 @@ struct usb_device { #endif uint32_t clear_stall_errors; /* number of clear-stall failures */ + + union usb_device_scratch scratch; }; /* globals */ @@ -227,7 +296,7 @@ struct usb_endpoint *usb_endpoint_foreac void usb_set_device_state(struct usb_device *, enum usb_dev_state); enum usb_dev_state usb_get_device_state(struct usb_device *); -void usbd_enum_lock(struct usb_device *); +uint8_t usbd_enum_lock(struct usb_device *); void usbd_enum_unlock(struct usb_device *); void usbd_sr_lock(struct usb_device *); void usbd_sr_unlock(struct usb_device *); Modified: head/sys/dev/usb/usb_generic.c ============================================================================== --- head/sys/dev/usb/usb_generic.c Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/dev/usb/usb_generic.c Sun Feb 10 10:56:13 2013 (r246616) @@ -719,13 +719,20 @@ ugen_get_cdesc(struct usb_fifo *f, struc return (error); } +/* + * This function is called having the enumeration SX locked which + * protects the scratch area used. + */ static int ugen_get_sdesc(struct usb_fifo *f, struct usb_gen_descriptor *ugd) { - void *ptr = f->udev->bus->scratch[0].data; - uint16_t size = sizeof(f->udev->bus->scratch[0].data); + void *ptr; + uint16_t size; int error; + ptr = f->udev->scratch.data; + size = sizeof(f->udev->scratch.data); + if (usbd_req_get_string_desc(f->udev, NULL, ptr, size, ugd->ugd_lang_id, ugd->ugd_string_index)) { error = EINVAL; Modified: head/sys/dev/usb/usb_handle_request.c ============================================================================== --- head/sys/dev/usb/usb_handle_request.c Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/dev/usb/usb_handle_request.c Sun Feb 10 10:56:13 2013 (r246616) @@ -191,13 +191,8 @@ usb_check_alt_setting(struct usb_device uint8_t do_unlock; usb_error_t err = 0; - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); if (alt_index >= usbd_get_no_alts(udev->cdesc, iface->idesc)) err = USB_ERR_INVAL; Modified: head/sys/dev/usb/usb_msctest.c ============================================================================== --- head/sys/dev/usb/usb_msctest.c Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/dev/usb/usb_msctest.c Sun Feb 10 10:56:13 2013 (r246616) @@ -505,13 +505,8 @@ bbb_attach(struct usb_device *udev, uint usb_error_t err; uint8_t do_unlock; - /* automatic locking */ - if (usbd_enum_is_locked(udev)) { - do_unlock = 0; - } else { - do_unlock = 1; - usbd_enum_lock(udev); - } + /* Prevent re-enumeration */ + do_unlock = usbd_enum_lock(udev); /* * Make sure any driver which is hooked up to this interface, Modified: head/sys/dev/usb/usb_transfer.c ============================================================================== --- head/sys/dev/usb/usb_transfer.c Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/dev/usb/usb_transfer.c Sun Feb 10 10:56:13 2013 (r246616) @@ -22,7 +22,7 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - */ + */ #ifdef USB_GLOBAL_INCLUDE_FILE #include USB_GLOBAL_INCLUDE_FILE @@ -855,20 +855,17 @@ usbd_transfer_setup(struct usb_device *u const struct usb_config *setup_start, uint16_t n_setup, void *priv_sc, struct mtx *xfer_mtx) { - struct usb_xfer dummy; - struct usb_setup_params parm; const struct usb_config *setup_end = setup_start + n_setup; const struct usb_config *setup; + struct usb_setup_params *parm; struct usb_endpoint *ep; struct usb_xfer_root *info; struct usb_xfer *xfer; void *buf = NULL; + usb_error_t error = 0; uint16_t n; uint16_t refcount; - - parm.err = 0; - refcount = 0; - info = NULL; + uint8_t do_unlock; WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "usbd_transfer_setup can sleep!"); @@ -887,31 +884,40 @@ usbd_transfer_setup(struct usb_device *u DPRINTFN(6, "using global lock\n"); xfer_mtx = &Giant; } - /* sanity checks */ + + /* more sanity checks */ + for (setup = setup_start, n = 0; setup != setup_end; setup++, n++) { if (setup->bufsize == (usb_frlength_t)-1) { - parm.err = USB_ERR_BAD_BUFSIZE; + error = USB_ERR_BAD_BUFSIZE; DPRINTF("invalid bufsize\n"); } if (setup->callback == NULL) { - parm.err = USB_ERR_NO_CALLBACK; + error = USB_ERR_NO_CALLBACK; DPRINTF("no callback\n"); } ppxfer[n] = NULL; } - if (parm.err) { - goto done; - } - memset(&parm, 0, sizeof(parm)); + if (error) + return (error); - parm.udev = udev; - parm.speed = usbd_get_speed(udev); - parm.hc_max_packet_count = 1; + /* Protect scratch area */ + do_unlock = usbd_enum_lock(udev); - if (parm.speed >= USB_SPEED_MAX) { - parm.err = USB_ERR_INVAL; + refcount = 0; + info = NULL; + + parm = &udev->scratch.xfer_setup[0].parm; + memset(parm, 0, sizeof(*parm)); + + parm->udev = udev; + parm->speed = usbd_get_speed(udev); + parm->hc_max_packet_count = 1; + + if (parm->speed >= USB_SPEED_MAX) { + parm->err = USB_ERR_INVAL; goto done; } /* setup all transfers */ @@ -926,22 +932,22 @@ usbd_transfer_setup(struct usb_device *u info = USB_ADD_BYTES(buf, 0); info->memory_base = buf; - info->memory_size = parm.size[0]; + info->memory_size = parm->size[0]; #if USB_HAVE_BUSDMA - info->dma_page_cache_start = USB_ADD_BYTES(buf, parm.size[4]); - info->dma_page_cache_end = USB_ADD_BYTES(buf, parm.size[5]); + info->dma_page_cache_start = USB_ADD_BYTES(buf, parm->size[4]); + info->dma_page_cache_end = USB_ADD_BYTES(buf, parm->size[5]); #endif - info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm.size[5]); - info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm.size[2]); + info->xfer_page_cache_start = USB_ADD_BYTES(buf, parm->size[5]); + info->xfer_page_cache_end = USB_ADD_BYTES(buf, parm->size[2]); cv_init(&info->cv_drain, "WDRAIN"); info->xfer_mtx = xfer_mtx; #if USB_HAVE_BUSDMA usb_dma_tag_setup(&info->dma_parent_tag, - parm.dma_tag_p, udev->bus->dma_parent_tag[0].tag, - xfer_mtx, &usb_bdma_done_event, 32, parm.dma_tag_max); + parm->dma_tag_p, udev->bus->dma_parent_tag[0].tag, + xfer_mtx, &usb_bdma_done_event, 32, parm->dma_tag_max); #endif info->bus = udev->bus; @@ -976,9 +982,9 @@ usbd_transfer_setup(struct usb_device *u } /* reset sizes */ - parm.size[0] = 0; - parm.buf = buf; - parm.size[0] += sizeof(info[0]); + parm->size[0] = 0; + parm->buf = buf; + parm->size[0] += sizeof(info[0]); for (setup = setup_start, n = 0; setup != setup_end; setup++, n++) { @@ -1010,22 +1016,22 @@ usbd_transfer_setup(struct usb_device *u if ((setup->usb_mode != USB_MODE_DUAL) && (setup->usb_mode != udev->flags.usb_mode)) continue; - parm.err = USB_ERR_NO_PIPE; + parm->err = USB_ERR_NO_PIPE; goto done; } /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); /* store current setup pointer */ - parm.curr_setup = setup; + parm->curr_setup = setup; if (buf) { /* * Common initialization of the * "usb_xfer" structure. */ - xfer = USB_ADD_BYTES(buf, parm.size[0]); + xfer = USB_ADD_BYTES(buf, parm->size[0]); xfer->address = udev->address; xfer->priv_sc = priv_sc; xfer->xroot = info; @@ -1040,8 +1046,8 @@ usbd_transfer_setup(struct usb_device *u * before we have allocated any * memory: */ - xfer = &dummy; - memset(&dummy, 0, sizeof(dummy)); + xfer = &udev->scratch.xfer_setup[0].dummy; + memset(xfer, 0, sizeof(*xfer)); refcount++; } @@ -1051,18 +1057,18 @@ usbd_transfer_setup(struct usb_device *u /* set transfer stream ID */ xfer->stream_id = setup->stream_id; - parm.size[0] += sizeof(xfer[0]); - parm.methods = xfer->endpoint->methods; - parm.curr_xfer = xfer; + parm->size[0] += sizeof(xfer[0]); + parm->methods = xfer->endpoint->methods; + parm->curr_xfer = xfer; /* * Call the Host or Device controller transfer * setup routine: */ - (udev->bus->methods->xfer_setup) (&parm); + (udev->bus->methods->xfer_setup) (parm); /* check for error */ - if (parm.err) + if (parm->err) goto done; if (buf) { @@ -1077,7 +1083,7 @@ usbd_transfer_setup(struct usb_device *u */ USB_BUS_LOCK(info->bus); if (xfer->endpoint->refcount_alloc >= USB_EP_REF_MAX) - parm.err = USB_ERR_INVAL; + parm->err = USB_ERR_INVAL; xfer->endpoint->refcount_alloc++; @@ -1100,22 +1106,22 @@ usbd_transfer_setup(struct usb_device *u } /* check for error */ - if (parm.err) + if (parm->err) goto done; } - if (buf || parm.err) { + if (buf != NULL || parm->err != 0) goto done; - } - if (refcount == 0) { - /* no transfers - nothing to do ! */ + + /* if no transfers, nothing to do */ + if (refcount == 0) goto done; - } + /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); /* store offset temporarily */ - parm.size[1] = parm.size[0]; + parm->size[1] = parm->size[0]; /* * The number of DMA tags required depends on @@ -1126,72 +1132,72 @@ usbd_transfer_setup(struct usb_device *u * 2) for allocating memory * 3) for fixing memory [UHCI] */ - parm.dma_tag_max += 3 * MIN(n_setup, USB_EP_MAX); + parm->dma_tag_max += 3 * MIN(n_setup, USB_EP_MAX); /* * DMA tags for QH, TD, Data and more. */ - parm.dma_tag_max += 8; + parm->dma_tag_max += 8; - parm.dma_tag_p += parm.dma_tag_max; + parm->dma_tag_p += parm->dma_tag_max; - parm.size[0] += ((uint8_t *)parm.dma_tag_p) - + parm->size[0] += ((uint8_t *)parm->dma_tag_p) - ((uint8_t *)0); /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); /* store offset temporarily */ - parm.size[3] = parm.size[0]; + parm->size[3] = parm->size[0]; - parm.size[0] += ((uint8_t *)parm.dma_page_ptr) - + parm->size[0] += ((uint8_t *)parm->dma_page_ptr) - ((uint8_t *)0); /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); /* store offset temporarily */ - parm.size[4] = parm.size[0]; + parm->size[4] = parm->size[0]; - parm.size[0] += ((uint8_t *)parm.dma_page_cache_ptr) - + parm->size[0] += ((uint8_t *)parm->dma_page_cache_ptr) - ((uint8_t *)0); /* store end offset temporarily */ - parm.size[5] = parm.size[0]; + parm->size[5] = parm->size[0]; - parm.size[0] += ((uint8_t *)parm.xfer_page_cache_ptr) - + parm->size[0] += ((uint8_t *)parm->xfer_page_cache_ptr) - ((uint8_t *)0); /* store end offset temporarily */ - parm.size[2] = parm.size[0]; + parm->size[2] = parm->size[0]; /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); - parm.size[6] = parm.size[0]; + parm->size[6] = parm->size[0]; - parm.size[0] += ((uint8_t *)parm.xfer_length_ptr) - + parm->size[0] += ((uint8_t *)parm->xfer_length_ptr) - ((uint8_t *)0); /* align data properly */ - parm.size[0] += ((-parm.size[0]) & (USB_HOST_ALIGN - 1)); + parm->size[0] += ((-parm->size[0]) & (USB_HOST_ALIGN - 1)); /* allocate zeroed memory */ - buf = malloc(parm.size[0], M_USB, M_WAITOK | M_ZERO); + buf = malloc(parm->size[0], M_USB, M_WAITOK | M_ZERO); if (buf == NULL) { - parm.err = USB_ERR_NOMEM; + parm->err = USB_ERR_NOMEM; DPRINTFN(0, "cannot allocate memory block for " "configuration (%d bytes)\n", - parm.size[0]); + parm->size[0]); goto done; } - parm.dma_tag_p = USB_ADD_BYTES(buf, parm.size[1]); - parm.dma_page_ptr = USB_ADD_BYTES(buf, parm.size[3]); - parm.dma_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[4]); - parm.xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm.size[5]); - parm.xfer_length_ptr = USB_ADD_BYTES(buf, parm.size[6]); + parm->dma_tag_p = USB_ADD_BYTES(buf, parm->size[1]); + parm->dma_page_ptr = USB_ADD_BYTES(buf, parm->size[3]); + parm->dma_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[4]); + parm->xfer_page_cache_ptr = USB_ADD_BYTES(buf, parm->size[5]); + parm->xfer_length_ptr = USB_ADD_BYTES(buf, parm->size[6]); } done: @@ -1207,10 +1213,17 @@ done: usbd_transfer_unsetup_sub(info, 0); } } - if (parm.err) { + + /* check if any errors happened */ + if (parm->err) usbd_transfer_unsetup(ppxfer, n_setup); - } - return (parm.err); + + error = parm->err; + + if (do_unlock) + usbd_enum_unlock(udev); + + return (error); } /*------------------------------------------------------------------------* Modified: head/sys/dev/usb/usb_util.c ============================================================================== --- head/sys/dev/usb/usb_util.c Sun Feb 10 10:55:20 2013 (r246615) +++ head/sys/dev/usb/usb_util.c Sun Feb 10 10:56:13 2013 (r246616) @@ -75,6 +75,7 @@ device_set_usb_desc(device_t dev) struct usb_interface *iface; char *temp_p; usb_error_t err; + uint8_t do_unlock; if (dev == NULL) { /* should not happen */ @@ -96,19 +97,26 @@ device_set_usb_desc(device_t dev) err = 0; } - temp_p = (char *)udev->bus->scratch[0].data; + /* Protect scratch area */ + do_unlock = usbd_enum_lock(udev); - if (!err) { + temp_p = (char *)udev->scratch.data; + + if (err == 0) { /* try to get the interface string ! */ - err = usbd_req_get_string_any - (udev, NULL, temp_p, - sizeof(udev->bus->scratch), iface->idesc->iInterface); + err = usbd_req_get_string_any(udev, NULL, temp_p, + sizeof(udev->scratch.data), + iface->idesc->iInterface); } - if (err) { + if (err != 0) { /* use default description */ usb_devinfo(udev, temp_p, - sizeof(udev->bus->scratch)); + sizeof(udev->scratch.data)); } + + if (do_unlock) + usbd_enum_unlock(udev); + device_set_desc_copy(dev, temp_p); device_printf(dev, "<%s> on %s\n", temp_p, *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***