Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Feb 2013 10:56:14 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
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
Message-ID:  <201302101056.r1AAuEmK027828@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <dev/usb/usb_process.h>
 #include <dev/usb/usb_busdma.h>
 #include <dev/usb/usb_dynamic.h>
+#include <dev/usb/usb_transfer.h>
 #include <dev/usb/usb_device.h>
 #include <dev/usb/usb_hub.h>
 #include <dev/usb/usb_controller.h>
@@ -52,7 +53,6 @@
 #include <dev/usb/usb_pf.h>
 #include <dev/usb/usb_request.h>
 #include <dev/usb/usb_util.h>
-#include <dev/usb/usb_transfer.h>
 #include <dev/usb/usb_compat_linux.h>
 #include <dev/usb/usbhid.h>
 #include <dev/usb/usb_ioctl.h>

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 <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,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 ***



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