PERFORCE change 153026 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Nov 16 01:57:15 PST 2008
http://perforce.freebsd.org/chv.cgi?CH=153026
Change 153026 by hselasky at hselasky_laptop001 on 2008/11/16 09:57:01
Fix a race freeing the generic USB transfers when
setting the configuration.
Affected files ...
.. //depot/projects/usb/src/lib/libusb20/libusb20_ugen20.c#11 edit
.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_device.c#32 edit
.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_generic.c#33 edit
.. //depot/projects/usb/src/sys/dev/usb2/core/usb2_generic.h#8 edit
Differences ...
==== //depot/projects/usb/src/lib/libusb20/libusb20_ugen20.c#11 (text+ko) ====
@@ -307,10 +307,27 @@
return (0); /* success */
}
+static void
+ugen20_tr_release(struct libusb20_device *pdev)
+{
+ struct usb2_fs_uninit fs_uninit;
+
+ if (pdev->nTransfer == 0) {
+ return;
+ }
+ /* release all pending USB transfers */
+ if (pdev->privBeData != NULL) {
+ memset(&fs_uninit, 0, sizeof(fs_uninit));
+ if (ioctl(pdev->file, USB_FS_UNINIT, &fs_uninit)) {
+ /* ignore any errors of this kind */
+ }
+ }
+ return;
+}
+
static int
ugen20_tr_renew(struct libusb20_device *pdev)
{
- struct usb2_fs_uninit fs_uninit;
struct usb2_fs_init fs_init;
struct usb2_fs_endpoint *pfse;
int error;
@@ -325,12 +342,7 @@
}
size = nMaxTransfer * sizeof(*pfse);
- if (pdev->privBeData != NULL) {
- memset(&fs_uninit, 0, sizeof(fs_uninit));
- if (ioctl(pdev->file, USB_FS_UNINIT, &fs_uninit)) {
- /* ignore any errors of this kind */
- }
- } else {
+ if (pdev->privBeData == NULL) {
pfse = malloc(size);
if (pfse == NULL) {
error = LIBUSB20_ERROR_NO_MEM;
@@ -338,7 +350,6 @@
}
pdev->privBeData = pfse;
}
-
/* reset endpoint data */
memset(pdev->privBeData, 0, size);
@@ -509,6 +520,9 @@
{
int temp = cfg_index;
+ /* release all active USB transfers */
+ ugen20_tr_release(pdev);
+
if (ioctl(pdev->file_ctrl, USB_SET_CONFIG, &temp)) {
return (LIBUSB20_ERROR_OTHER);
}
@@ -548,6 +562,9 @@
alt_iface.uai_interface_index = iface_index;
alt_iface.uai_alt_index = alt_index;
+ /* release all active USB transfers */
+ ugen20_tr_release(pdev);
+
if (ioctl(pdev->file_ctrl, USB_SET_ALTINTERFACE, &alt_iface)) {
return (LIBUSB20_ERROR_OTHER);
}
@@ -559,6 +576,9 @@
{
int temp = 0;
+ /* release all active USB transfers */
+ ugen20_tr_release(pdev);
+
if (ioctl(pdev->file_ctrl, USB_DEVICEENUMERATE, &temp)) {
return (LIBUSB20_ERROR_OTHER);
}
==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_device.c#32 (text+ko) ====
@@ -2114,38 +2114,23 @@
*/
continue;
}
- if (f->dev_ep_index == 0) {
- /*
- * Don't free the generic control endpoint
- * yet and make sure that any USB-FS
- * activity is stopped!
- */
- if (ugen_fs_uninit(f)) {
- /* ignore any failures */
- DPRINTFN(10, "udev=%p ugen_fs_uninit() "
- "failed! (ignored)\n", udev);
- }
+ if ((f->dev_ep_index == 0) &&
+ (f->fs_xfer == NULL)) {
+ /* no need to free this FIFO */
continue;
}
} else if (iface_index == USB_IFACE_INDEX_ANY) {
if ((f->methods == &usb2_ugen_methods) &&
- (f->dev_ep_index == 0) && (flag == 0)) {
- /*
- * Don't free the generic control endpoint
- * yet, but make sure that any USB-FS
- * activity is stopped!
- */
- if (ugen_fs_uninit(f)) {
- /* ignore any failures */
- DPRINTFN(10, "udev=%p ugen_fs_uninit() "
- "failed! (ignored)\n", udev);
- }
+ (f->dev_ep_index == 0) && (flag == 0) &&
+ (f->fs_xfer == NULL)) {
+ /* no need to free this FIFO */
continue;
}
} else {
+ /* no need to free this FIFO */
continue;
}
- /* free the FIFO */
+ /* free this FIFO */
usb2_fifo_free(f);
}
return;
==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_generic.c#33 (text+ko) ====
@@ -83,7 +83,7 @@
static int ugen_re_enumerate(struct usb2_fifo *f);
static int ugen_iface_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags);
static uint8_t ugen_fs_get_complete(struct usb2_fifo *f, uint8_t *pindex);
-
+static int ugen_fs_uninit(struct usb2_fifo *f);
/* structures */
@@ -192,6 +192,7 @@
if (ugen_fs_uninit(f)) {
/* ignore any errors - we are closing */
+ DPRINTFN(6, "no FIFOs\n");
}
return;
}
@@ -591,6 +592,12 @@
/* no change needed */
return (0);
}
+ /* make sure all FIFO's are gone */
+ /* else there can be a deadlock */
+ if (ugen_fs_uninit(f)) {
+ /* ignore any errors */
+ DPRINTFN(6, "no FIFOs\n");
+ }
/* change setting - will free generic FIFOs, if any */
if (usb2_set_config_index(f->udev, index)) {
return (EIO);
@@ -612,6 +619,12 @@
/* not possible in device side mode */
return (ENOTTY);
}
+ /* make sure all FIFO's are gone */
+ /* else there can be a deadlock */
+ if (ugen_fs_uninit(f)) {
+ /* ignore any errors */
+ DPRINTFN(6, "no FIFOs\n");
+ }
/* change setting - will free generic FIFOs, if any */
if (usb2_set_alt_interface_index(f->udev, iface_index, alt_index)) {
return (EIO);
==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_generic.h#8 (text+ko) ====
@@ -29,6 +29,5 @@
extern struct usb2_fifo_methods usb2_ugen_methods;
int ugen_do_request(struct usb2_fifo *f, struct usb2_ctl_request *ur);
-int ugen_fs_uninit(struct usb2_fifo *f);
#endif /* _USB2_GENERIC_H_ */
More information about the p4-projects
mailing list