svn commit: r247090 - in stable/9/sys: dev/usb dev/usb/controller dev/usb/template sys
Hans Petter Selasky
hselasky at FreeBSD.org
Thu Feb 21 07:48:10 UTC 2013
Author: hselasky
Date: Thu Feb 21 07:48:07 2013
New Revision: 247090
URL: http://svnweb.freebsd.org/changeset/base/247090
Log:
MFC r246616 and r246759:
- 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.
- 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.
- Protect control requests using the USB device enumeration lock.
- Make sure all callers of usbd_enum_lock() check the return value.
- Remove the control transfer specific lock.
- Bump the FreeBSD version number, hence external USB modules may need
to be recompiled due to a USB device structure change.
Modified:
stable/9/sys/dev/usb/controller/usb_controller.c
stable/9/sys/dev/usb/template/usb_template.c
stable/9/sys/dev/usb/usb_bus.h
stable/9/sys/dev/usb/usb_controller.h
stable/9/sys/dev/usb/usb_dev.c
stable/9/sys/dev/usb/usb_dev.h
stable/9/sys/dev/usb/usb_device.c
stable/9/sys/dev/usb/usb_device.h
stable/9/sys/dev/usb/usb_generic.c
stable/9/sys/dev/usb/usb_handle_request.c
stable/9/sys/dev/usb/usb_hub.c
stable/9/sys/dev/usb/usb_msctest.c
stable/9/sys/dev/usb/usb_request.c
stable/9/sys/dev/usb/usb_transfer.c
stable/9/sys/dev/usb/usb_util.c
stable/9/sys/sys/param.h
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/boot/ (props changed)
stable/9/sys/dev/ (props changed)
Modified: stable/9/sys/dev/usb/controller/usb_controller.c
==============================================================================
--- stable/9/sys/dev/usb/controller/usb_controller.c Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/controller/usb_controller.c Thu Feb 21 07:48:07 2013 (r247090)
@@ -407,6 +407,7 @@ usb_bus_suspend(struct usb_proc_msg *pm)
struct usb_bus *bus;
struct usb_device *udev;
usb_error_t err;
+ uint8_t do_unlock;
bus = ((struct usb_bus_msg *)pm)->bus;
udev = bus->devices[USB_ROOT_HUB_ADDR];
@@ -427,7 +428,7 @@ usb_bus_suspend(struct usb_proc_msg *pm)
bus_generic_shutdown(bus->bdev);
- usbd_enum_lock(udev);
+ do_unlock = usbd_enum_lock(udev);
err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX);
if (err)
@@ -444,7 +445,8 @@ usb_bus_suspend(struct usb_proc_msg *pm)
if (bus->methods->set_hw_power_sleep != NULL)
(bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SUSPEND);
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_BUS_LOCK(bus);
}
@@ -460,6 +462,7 @@ usb_bus_resume(struct usb_proc_msg *pm)
struct usb_bus *bus;
struct usb_device *udev;
usb_error_t err;
+ uint8_t do_unlock;
bus = ((struct usb_bus_msg *)pm)->bus;
udev = bus->devices[USB_ROOT_HUB_ADDR];
@@ -469,7 +472,7 @@ usb_bus_resume(struct usb_proc_msg *pm)
USB_BUS_UNLOCK(bus);
- usbd_enum_lock(udev);
+ do_unlock = usbd_enum_lock(udev);
#if 0
DEVMETHOD(usb_take_controller, NULL); /* dummy */
#endif
@@ -503,7 +506,8 @@ usb_bus_resume(struct usb_proc_msg *pm)
"attach root HUB\n");
}
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_BUS_LOCK(bus);
}
@@ -519,6 +523,7 @@ usb_bus_shutdown(struct usb_proc_msg *pm
struct usb_bus *bus;
struct usb_device *udev;
usb_error_t err;
+ uint8_t do_unlock;
bus = ((struct usb_bus_msg *)pm)->bus;
udev = bus->devices[USB_ROOT_HUB_ADDR];
@@ -530,7 +535,7 @@ usb_bus_shutdown(struct usb_proc_msg *pm
bus_generic_shutdown(bus->bdev);
- usbd_enum_lock(udev);
+ do_unlock = usbd_enum_lock(udev);
err = usbd_set_config_index(udev, USB_UNCONFIG_INDEX);
if (err)
@@ -547,7 +552,8 @@ usb_bus_shutdown(struct usb_proc_msg *pm
if (bus->methods->set_hw_power_sleep != NULL)
(bus->methods->set_hw_power_sleep) (bus, USB_HW_POWER_SHUTDOWN);
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_BUS_LOCK(bus);
}
Modified: stable/9/sys/dev/usb/template/usb_template.c
==============================================================================
--- stable/9/sys/dev/usb/template/usb_template.c Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/template/usb_template.c Thu Feb 21 07:48:07 2013 (r247090)
@@ -845,20 +845,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 */
@@ -905,13 +905,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));
@@ -1232,13 +1231,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));
@@ -1251,17 +1255,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 */
@@ -1276,7 +1287,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 !
@@ -1287,7 +1298,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++) {
@@ -1300,14 +1311,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: stable/9/sys/dev/usb/usb_bus.h
==============================================================================
--- stable/9/sys/dev/usb/usb_bus.h Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_bus.h Thu Feb 21 07:48:07 2013 (r247090)
@@ -103,16 +103,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: stable/9/sys/dev/usb/usb_controller.h
==============================================================================
--- stable/9/sys/dev/usb/usb_controller.h Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_controller.h Thu Feb 21 07:48:07 2013 (r247090)
@@ -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 */
@@ -181,50 +180,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: stable/9/sys/dev/usb/usb_dev.c
==============================================================================
--- stable/9/sys/dev/usb/usb_dev.c Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_dev.c Thu Feb 21 07:48:07 2013 (r247090)
@@ -214,10 +214,10 @@ usb_ref_device(struct usb_cdev_privdata
mtx_unlock(&usb_ref_lock);
/*
- * We need to grab the sx-lock before grabbing the
- * FIFO refs to avoid deadlock at detach!
+ * We need to grab the enumeration SX-lock before
+ * grabbing the FIFO refs to avoid deadlock at detach!
*/
- usbd_enum_lock(cpd->udev);
+ crd->do_unlock = usbd_enum_lock(cpd->udev);
mtx_lock(&usb_ref_lock);
@@ -278,9 +278,10 @@ usb_ref_device(struct usb_cdev_privdata
return (0);
error:
- if (crd->is_uref) {
+ if (crd->do_unlock)
usbd_enum_unlock(cpd->udev);
+ if (crd->is_uref) {
if (--(cpd->udev->refcount) == 0) {
cv_signal(&cpd->udev->ref_cv);
}
@@ -332,7 +333,7 @@ usb_unref_device(struct usb_cdev_privdat
DPRINTFN(2, "cpd=%p is_uref=%d\n", cpd, crd->is_uref);
- if (crd->is_uref)
+ if (crd->do_unlock)
usbd_enum_unlock(cpd->udev);
mtx_lock(&usb_ref_lock);
Modified: stable/9/sys/dev/usb/usb_dev.h
==============================================================================
--- stable/9/sys/dev/usb/usb_dev.h Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_dev.h Thu Feb 21 07:48:07 2013 (r247090)
@@ -82,6 +82,7 @@ struct usb_cdev_refdata {
uint8_t is_write; /* location has write access */
uint8_t is_uref; /* USB refcount decr. needed */
uint8_t is_usbfs; /* USB-FS is active */
+ uint8_t do_unlock; /* USB enum unlock needed */
};
struct usb_fs_privdata {
Modified: stable/9/sys/dev/usb/usb_device.c
==============================================================================
--- stable/9/sys/dev/usb/usb_device.c Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_device.c Thu Feb 21 07:48:07 2013 (r247090)
@@ -443,13 +443,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);
@@ -512,13 +507,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);
@@ -871,13 +861,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;
@@ -914,7 +900,6 @@ usbd_set_alt_interface_index(struct usb_
done:
if (do_unlock)
usbd_enum_unlock(udev);
-
return (err);
}
@@ -1285,13 +1270,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 */
@@ -1378,7 +1358,6 @@ usb_probe_and_attach(struct usb_device *
done:
if (do_unlock)
usbd_enum_unlock(udev);
-
return (0);
}
@@ -1507,6 +1486,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",
@@ -1541,9 +1521,6 @@ usb_alloc_device(device_t parent_dev, st
return (NULL);
}
/* initialise our SX-lock */
- sx_init_flags(&udev->ctrl_sx, "USB device SX lock", SX_DUPOK);
-
- /* initialise our SX-lock */
sx_init_flags(&udev->enum_sx, "USB config SX lock", SX_DUPOK);
sx_init_flags(&udev->sr_sx, "USB suspend and resume SX lock", SX_NOWITNESS);
@@ -1725,7 +1702,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 ||
@@ -1750,7 +1731,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;
@@ -1771,6 +1752,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 */
@@ -2107,7 +2091,6 @@ usb_free_device(struct usb_device *udev,
&udev->cs_msg[0], &udev->cs_msg[1]);
USB_BUS_UNLOCK(udev->bus);
- sx_destroy(&udev->ctrl_sx);
sx_destroy(&udev->enum_sx);
sx_destroy(&udev->sr_sx);
@@ -2270,9 +2253,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);
@@ -2327,6 +2314,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);
}
/*
@@ -2639,11 +2629,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);
/*
@@ -2652,6 +2648,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. */
Modified: stable/9/sys/dev/usb/usb_device.h
==============================================================================
--- stable/9/sys/dev/usb/usb_device.h Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_device.h Thu Feb 21 07:48:07 2013 (r247090)
@@ -27,9 +27,18 @@
#ifndef _USB_DEVICE_H_
#define _USB_DEVICE_H_
-struct usb_symlink; /* UGEN */
+#ifndef USB_GLOBAL_INCLUDE_FILE
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_transfer.h>
+#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,13 +117,70 @@ 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.
*/
struct usb_device {
struct usb_clear_stall_msg cs_msg[2]; /* generic clear stall
* messages */
- struct sx ctrl_sx;
struct sx enum_sx;
struct sx sr_sx;
struct mtx device_mtx;
@@ -191,6 +257,8 @@ struct usb_device {
#endif
uint32_t clear_stall_errors; /* number of clear-stall failures */
+
+ union usb_device_scratch scratch;
};
/* globals */
@@ -227,7 +295,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: stable/9/sys/dev/usb/usb_generic.c
==============================================================================
--- stable/9/sys/dev/usb/usb_generic.c Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_generic.c Thu Feb 21 07:48:07 2013 (r247090)
@@ -713,13 +713,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: stable/9/sys/dev/usb/usb_handle_request.c
==============================================================================
--- stable/9/sys/dev/usb/usb_handle_request.c Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_handle_request.c Thu Feb 21 07:48:07 2013 (r247090)
@@ -145,6 +145,7 @@ usb_handle_set_config(struct usb_xfer *x
{
struct usb_device *udev = xfer->xroot->udev;
usb_error_t err = 0;
+ uint8_t do_unlock;
/*
* We need to protect against other threads doing probe and
@@ -152,7 +153,8 @@ usb_handle_set_config(struct usb_xfer *x
*/
USB_XFER_UNLOCK(xfer);
- usbd_enum_lock(udev);
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
if (conf_no == USB_UNCONFIG_NO) {
conf_no = USB_UNCONFIG_INDEX;
@@ -175,7 +177,8 @@ usb_handle_set_config(struct usb_xfer *x
goto done;
}
done:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (err);
}
@@ -187,13 +190,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;
@@ -222,6 +220,7 @@ usb_handle_iface_request(struct usb_xfer
int error;
uint8_t iface_index;
uint8_t temp_state;
+ uint8_t do_unlock;
if ((req.bmRequestType & 0x1F) == UT_INTERFACE) {
iface_index = req.wIndex[0]; /* unicast */
@@ -235,7 +234,8 @@ usb_handle_iface_request(struct usb_xfer
*/
USB_XFER_UNLOCK(xfer);
- usbd_enum_lock(udev);
+ /* Prevent re-enumeration */
+ do_unlock = usbd_enum_lock(udev);
error = ENXIO;
@@ -351,17 +351,20 @@ tr_repeat:
goto tr_stalled;
}
tr_valid:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (0);
tr_short:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (USB_ERR_SHORT_XFER);
tr_stalled:
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
USB_XFER_LOCK(xfer);
return (USB_ERR_STALLED);
}
Modified: stable/9/sys/dev/usb/usb_hub.c
==============================================================================
--- stable/9/sys/dev/usb/usb_hub.c Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_hub.c Thu Feb 21 07:48:07 2013 (r247090)
@@ -240,7 +240,9 @@ uhub_explore_sub(struct uhub_softc *sc,
/* check if device should be re-enumerated */
if (child->flags.usb_mode == USB_MODE_HOST) {
- usbd_enum_lock(child);
+ uint8_t do_unlock;
+
+ do_unlock = usbd_enum_lock(child);
if (child->re_enumerate_wait) {
err = usbd_set_config_index(child,
USB_UNCONFIG_INDEX);
@@ -259,7 +261,8 @@ uhub_explore_sub(struct uhub_softc *sc,
child->re_enumerate_wait = 0;
err = 0;
}
- usbd_enum_unlock(child);
+ if (do_unlock)
+ usbd_enum_unlock(child);
}
/* check if probe and attach should be done */
@@ -710,6 +713,7 @@ uhub_explore(struct usb_device *udev)
usb_error_t err;
uint8_t portno;
uint8_t x;
+ uint8_t do_unlock;
hub = udev->hub;
sc = hub->hubsoftc;
@@ -731,7 +735,7 @@ uhub_explore(struct usb_device *udev)
* Make sure we don't race against user-space applications
* like LibUSB:
*/
- usbd_enum_lock(udev);
+ do_unlock = usbd_enum_lock(udev);
for (x = 0; x != hub->nports; x++) {
up = hub->ports + x;
@@ -811,7 +815,8 @@ uhub_explore(struct usb_device *udev)
up->restartcnt = 0;
}
- usbd_enum_unlock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
/* initial status checked */
sc->sc_flags |= UHUB_FLAG_DID_EXPLORE;
Modified: stable/9/sys/dev/usb/usb_msctest.c
==============================================================================
--- stable/9/sys/dev/usb/usb_msctest.c Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_msctest.c Thu Feb 21 07:48:07 2013 (r247090)
@@ -501,13 +501,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: stable/9/sys/dev/usb/usb_request.c
==============================================================================
--- stable/9/sys/dev/usb/usb_request.c Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_request.c Thu Feb 21 07:48:07 2013 (r247090)
@@ -382,9 +382,8 @@ usbd_get_hr_func(struct usb_device *udev
* than 30 seconds is treated like a 30 second timeout. This USB stack
* does not allow control requests without a timeout.
*
- * NOTE: This function is thread safe. All calls to
- * "usbd_do_request_flags" will be serialised by the use of an
- * internal "sx_lock".
+ * NOTE: This function is thread safe. All calls to "usbd_do_request_flags"
+ * will be serialized by the use of the USB device enumeration lock.
*
* Returns:
* 0: Success
@@ -408,7 +407,7 @@ usbd_do_request_flags(struct usb_device
uint16_t length;
uint16_t temp;
uint16_t acttemp;
- uint8_t enum_locked;
+ uint8_t do_unlock;
if (timeout < 50) {
/* timeout is too small */
@@ -420,8 +419,6 @@ usbd_do_request_flags(struct usb_device
}
length = UGETW(req->wLength);
- enum_locked = usbd_enum_is_locked(udev);
-
DPRINTFN(5, "udev=%p bmRequestType=0x%02x bRequest=0x%02x "
"wValue=0x%02x%02x wIndex=0x%02x%02x wLength=0x%02x%02x\n",
udev, req->bmRequestType, req->bRequest,
@@ -452,17 +449,16 @@ usbd_do_request_flags(struct usb_device
}
/*
- * We need to allow suspend and resume at this point, else the
- * control transfer will timeout if the device is suspended!
+ * Grab the USB device enumeration SX-lock serialization is
+ * achieved when multiple threads are involved:
*/
- if (enum_locked)
- usbd_sr_unlock(udev);
+ do_unlock = usbd_enum_lock(udev);
/*
- * Grab the default sx-lock so that serialisation
- * is achieved when multiple threads are involved:
+ * We need to allow suspend and resume at this point, else the
+ * control transfer will timeout if the device is suspended!
*/
- sx_xlock(&udev->ctrl_sx);
+ usbd_sr_unlock(udev);
hr_func = usbd_get_hr_func(udev);
@@ -706,10 +702,10 @@ usbd_do_request_flags(struct usb_device
USB_XFER_UNLOCK(xfer);
done:
- sx_xunlock(&udev->ctrl_sx);
+ usbd_sr_lock(udev);
- if (enum_locked)
- usbd_sr_lock(udev);
+ if (do_unlock)
+ usbd_enum_unlock(udev);
if ((mtx != NULL) && (mtx != &Giant))
mtx_lock(mtx);
Modified: stable/9/sys/dev/usb/usb_transfer.c
==============================================================================
--- stable/9/sys/dev/usb/usb_transfer.c Thu Feb 21 07:19:50 2013 (r247089)
+++ stable/9/sys/dev/usb/usb_transfer.c Thu Feb 21 07:48:07 2013 (r247090)
@@ -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.
- */
+ */
#include <sys/stdint.h>
#include <sys/stddef.h>
@@ -810,20 +810,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!");
@@ -842,31 +839,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);
+
+ /* Protect scratch area */
+ do_unlock = usbd_enum_lock(udev);
- parm.udev = udev;
- parm.speed = usbd_get_speed(udev);
- parm.hc_max_packet_count = 1;
+ refcount = 0;
+ info = NULL;
- if (parm.speed >= USB_SPEED_MAX) {
- parm.err = USB_ERR_INVAL;
+ 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 */
@@ -881,22 +887,22 @@ usbd_transfer_setup(struct usb_device *u
info = USB_ADD_BYTES(buf, 0);
info->memory_base = buf;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-stable-9
mailing list