From owner-p4-projects@FreeBSD.ORG Sat Nov 15 15:40:00 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 13DAE1065687; Sat, 15 Nov 2008 15:40:00 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C2A8E106567E for ; Sat, 15 Nov 2008 15:39:59 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id B14528FC18 for ; Sat, 15 Nov 2008 15:39:59 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id mAFFdxNx056560 for ; Sat, 15 Nov 2008 15:39:59 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id mAFFdxnc056558 for perforce@freebsd.org; Sat, 15 Nov 2008 15:39:59 GMT (envelope-from hselasky@FreeBSD.org) Date: Sat, 15 Nov 2008 15:39:59 GMT Message-Id: <200811151539.mAFFdxnc056558@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 153007 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 15 Nov 2008 15:40:00 -0000 http://perforce.freebsd.org/chv.cgi?CH=153007 Change 153007 by hselasky@hselasky_laptop001 on 2008/11/15 15:39:19 Cleanup USB IOCTL and USB reference handling. Fix a corner case where USB-FS was left initialised after setting a new configuration or alternate setting. Affected files ... .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_dev.c#42 edit .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_dev.h#15 edit .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_device.c#31 edit .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_generic.c#31 edit .. //depot/projects/usb/src/sys/dev/usb2/core/usb2_generic.h#7 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_dev.c#42 (text+ko) ==== @@ -464,22 +464,16 @@ struct usb2_fifo **ppf; struct usb2_fifo *f; int fflags; - uint8_t need_uref; uint8_t dev_ep_index; if (fp) { - /* check if we need uref hint */ - need_uref = devloc ? 0 : 1; + /* check if we need uref */ + ploc->is_uref = devloc ? 0 : 1; /* get devloc - already verified */ devloc = USB_P2U(fp->f_data); /* get file flags */ fflags = fp->f_flag; - /* only ref FIFO */ - ploc->is_uref = 0; - /* devloc should be valid */ } else { - /* we need uref */ - need_uref = 1; /* only ref device */ fflags = 0; /* search for FIFO */ @@ -602,27 +596,14 @@ if (ploc->is_write) { DPRINTFN(2, "ref write\n"); ploc->txfifo->refcount++; - if (ploc->txfifo->flag_no_uref == 0) { - /* we need extra locking */ - ploc->is_uref = 1; - } } if (ploc->is_read) { DPRINTFN(2, "ref read\n"); ploc->rxfifo->refcount++; - if (ploc->rxfifo->flag_no_uref == 0) { - /* we need extra locking */ - ploc->is_uref = 1; - } } if (ploc->is_uref) { - if (need_uref) { - DPRINTFN(2, "ref udev - needed\n"); - ploc->udev->refcount++; - } else { - DPRINTFN(2, "ref udev - not needed\n"); - ploc->is_uref = 0; - } + DPRINTFN(2, "ref udev - needed\n"); + ploc->udev->refcount++; } mtx_unlock(&usb2_ref_lock); @@ -643,6 +624,59 @@ } /*------------------------------------------------------------------------* + * usb2_uref_location + * + * This function is used to upgrade an USB reference to include the + * USB device reference on a USB location. + * + * Return values: + * 0: Success, refcount incremented on the given USB device. + * Else: Failure. + *------------------------------------------------------------------------*/ +static usb2_error_t +usb2_uref_location(struct usb2_location *ploc) +{ + /* + * Check if we already got an USB reference on this location: + */ + if (ploc->is_uref) { + return (0); /* success */ + } + mtx_lock(&usb2_ref_lock); + if (ploc->bus != devclass_get_softc(usb2_devclass_ptr, ploc->bus_index)) { + DPRINTFN(2, "bus changed at %u\n", ploc->bus_index); + goto error; + } + if (ploc->udev != ploc->bus->devices[ploc->dev_index]) { + DPRINTFN(2, "device changed at %u\n", ploc->dev_index); + goto error; + } + if (ploc->udev->refcount == USB_DEV_REF_MAX) { + DPRINTFN(2, "no dev ref\n"); + goto error; + } + DPRINTFN(2, "ref udev\n"); + ploc->udev->refcount++; + mtx_unlock(&usb2_ref_lock); + + /* set "uref" */ + ploc->is_uref = 1; + + /* + * We are about to alter the bus-state. Apply the + * required locks. + */ + sx_xlock(ploc->udev->default_sx + 1); + mtx_lock(&Giant); /* XXX */ + return (0); + +error: + mtx_unlock(&usb2_ref_lock); + DPRINTFN(2, "fail\n"); + return (USB_ERR_INVAL); +} + +/*------------------------------------------------------------------------* * usb2_unref_device * * This function will release the reference count by one unit for the @@ -799,9 +833,6 @@ f->methods = &usb2_ugen_methods; f->iface_index = iface_index; f->udev = udev; - if (dev_ep_index != 0) { - f->flag_no_uref = 1; - } mtx_lock(&usb2_ref_lock); udev->fifo[n + USB_FIFO_TX] = f; mtx_unlock(&usb2_ref_lock); @@ -827,9 +858,6 @@ f->methods = &usb2_ugen_methods; f->iface_index = iface_index; f->udev = udev; - if (dev_ep_index != 0) { - f->flag_no_uref = 1; - } mtx_lock(&usb2_ref_lock); udev->fifo[n + USB_FIFO_RX] = f; mtx_unlock(&usb2_ref_lock); @@ -1490,7 +1518,7 @@ DPRINTFN(2, "fflags=%u\n", fflags); - err = usb2_ref_device(fp, &loc, 0);; + err = usb2_ref_device(fp, &loc, 0 /* need uref */ );; /* restore some file variables */ fp->f_ops = usb2_old_f_ops; @@ -1555,7 +1583,7 @@ } break; default: - return (ENOTTY); + return (ENOIOCTL); } return (error); } @@ -1565,13 +1593,11 @@ struct ucred *cred, struct thread *td) { struct usb2_location loc; + struct usb2_fifo *f; int fflags; - int err_rx; - int err_tx; int err; - uint8_t is_common = 0; - err = usb2_ref_device(fp, &loc, 0);; + err = usb2_ref_device(fp, &loc, 1 /* no uref */ );; if (err) { return (ENXIO); } @@ -1579,43 +1605,31 @@ DPRINTFN(2, "fflags=%u, cmd=0x%lx\n", fflags, cmd); + f = NULL; /* set default value */ + err = ENOIOCTL; /* set default value */ + + if (fflags & FWRITE) { + f = loc.txfifo; + err = usb2_ioctl_f_sub(f, cmd, addr, td); + } if (fflags & FREAD) { - if (fflags & FWRITE) { - /* - * Make sure that the IOCTL is not - * duplicated: - */ - is_common = 1; - } - err_rx = usb2_ioctl_f_sub(loc.rxfifo, cmd, addr, td); - if (err_rx == ENOTTY) { - err_rx = (loc.rxfifo->methods->f_ioctl) ( - loc.rxfifo, cmd, addr, - is_common ? fflags : (fflags & ~FWRITE), td); - } - } else { - err_rx = 0; + f = loc.rxfifo; + err = usb2_ioctl_f_sub(f, cmd, addr, td); } - if (fflags & FWRITE) { - err_tx = usb2_ioctl_f_sub(loc.txfifo, cmd, addr, td); - if (err_tx == ENOTTY) { - if (is_common) - err_tx = 0; /* already handled this IOCTL */ - else - err_tx = (loc.txfifo->methods->f_ioctl) ( - loc.txfifo, cmd, addr, fflags & ~FREAD, td); + if (err == ENOIOCTL) { + err = (f->methods->f_ioctl) (f, cmd, addr, fflags, td); + if (err == ENOIOCTL) { + if (usb2_uref_location(&loc)) { + err = ENXIO; + goto done; + } + err = (f->methods->f_ioctl_post) (f, cmd, addr, fflags, td); } - } else { - err_tx = 0; } - - if (err_rx) { - err = err_rx; - } else if (err_tx) { - err = err_tx; - } else { - err = 0; /* no error */ + if (err == ENOIOCTL) { + err = ENOTTY; } +done: usb2_unref_device(&loc); return (err); } @@ -2113,7 +2127,7 @@ usb2_fifo_dummy_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, int fflags, struct thread *td) { - return (ENOTTY); + return (ENOIOCTL); } static void @@ -2137,6 +2151,9 @@ if (pm->f_ioctl == NULL) pm->f_ioctl = &usb2_fifo_dummy_ioctl; + if (pm->f_ioctl_post == NULL) + pm->f_ioctl_post = &usb2_fifo_dummy_ioctl; + if (pm->f_start_read == NULL) pm->f_start_read = &usb2_fifo_dummy_cmd; @@ -2220,7 +2237,6 @@ f_tx->methods = pm; f_tx->iface_index = iface_index; f_tx->udev = udev; - f_tx->flag_no_uref = 1; f_rx->fifo_index = n + USB_FIFO_RX; f_rx->dev_ep_index = (n / 2) + (USB_EP_MAX / 2); @@ -2229,7 +2245,6 @@ f_rx->methods = pm; f_rx->iface_index = iface_index; f_rx->udev = udev; - f_rx->flag_no_uref = 1; f_sc->fp[USB_FIFO_TX] = f_tx; f_sc->fp[USB_FIFO_RX] = f_rx; ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_dev.h#15 (text+ko) ==== @@ -66,6 +66,11 @@ usb2_fifo_open_t *f_open; usb2_fifo_close_t *f_close; usb2_fifo_ioctl_t *f_ioctl; + /* + * NOTE: The post-ioctl callback is called after the USB reference + * gets locked in the IOCTL handler: + */ + usb2_fifo_ioctl_t *f_ioctl_post; usb2_fifo_cmd_t *f_start_read; usb2_fifo_cmd_t *f_stop_read; usb2_fifo_cmd_t *f_start_write; @@ -102,7 +107,6 @@ uint32_t bufsize; /* BULK and INTERRUPT buffer size */ uint16_t nframes; /* for isochronous mode */ uint16_t dev_ep_index; /* our device endpoint index */ - uint8_t flag_no_uref; /* set if FIFO is not control endpoint */ uint8_t flag_sleeping; /* set if FIFO is sleeping */ uint8_t flag_iscomplete; /* set if a USB transfer is complete */ uint8_t flag_iserror; /* set if FIFO error happened */ ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_device.c#31 (text+ko) ==== @@ -677,7 +677,7 @@ * Free all generic FIFOs for this interface, except control * endpoint FIFOs: */ - usb2_fifo_free_wrap(udev, iface_index, 2); + usb2_fifo_free_wrap(udev, iface_index, 0); err = usb2_fill_iface_data(udev, iface_index, alt_index); if (err) { @@ -2081,13 +2081,14 @@ /*------------------------------------------------------------------------* * usb2_fifo_free_wrap * - * The function will free the FIFOs. + * This function will free the FIFOs. + * + * Flag values, if "iface_index" is equal to "USB_IFACE_INDEX_ANY". + * 0: Free all FIFOs except generic control endpoints. + * 1: Free all FIFOs. * - * Flag values: - * 0: Free all FIFOs except control endpoints matching "iface_index". - * 1: Free all FIFOs matching "iface_index". - * 2: Free all generic FIFOs except control endpoints matching - * "iface_index". + * Flag values, if "iface_index" is not equal to "USB_IFACE_INDEX_ANY". + * Not used. *------------------------------------------------------------------------*/ static void usb2_fifo_free_wrap(struct usb2_device *udev, @@ -2104,25 +2105,48 @@ if (f == NULL) { continue; } - /* Check if the FIFO is of generic type */ - if (f->methods == &usb2_ugen_methods) { - if ((f->dev_ep_index == 0) && - ((flag == 0) || (flag == 2))) { - /* don't free UGEN control endpoint yet */ + /* Check if the interface index matches */ + if (iface_index == f->iface_index) { + if (f->methods != &usb2_ugen_methods) { + /* + * Don't free any non-generic FIFOs in + * this case. + */ + 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); + } continue; } - } else { - if (flag == 2) { - /* don't free non-generic FIFO */ + } 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); + } continue; } + } else { + continue; } - - /* Check if the interface index matches */ - if ((iface_index == f->iface_index) || - (iface_index == USB_IFACE_INDEX_ANY)) { - usb2_fifo_free(f); - } + /* free the FIFO */ + usb2_fifo_free(f); } return; } ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_generic.c#31 (text+ko) ==== @@ -67,6 +67,7 @@ static usb2_fifo_open_t ugen_open; static usb2_fifo_close_t ugen_close; static usb2_fifo_ioctl_t ugen_ioctl; +static usb2_fifo_ioctl_t ugen_ioctl_post; static usb2_fifo_cmd_t ugen_start_read; static usb2_fifo_cmd_t ugen_start_write; static usb2_fifo_cmd_t ugen_stop_io; @@ -81,8 +82,6 @@ static int usb2_gen_fill_deviceinfo(struct usb2_fifo *f, struct usb2_device_info *di); 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 int ugen_ctrl_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags); -static int ugen_fs_uninit(struct usb2_fifo *f); static uint8_t ugen_fs_get_complete(struct usb2_fifo *f, uint8_t *pindex); @@ -92,6 +91,7 @@ .f_open = &ugen_open, .f_close = &ugen_close, .f_ioctl = &ugen_ioctl, + .f_ioctl_post = &ugen_ioctl_post, .f_start_read = &ugen_start_read, .f_stop_read = &ugen_stop_io, .f_start_write = &ugen_start_write, @@ -583,10 +583,6 @@ { DPRINTFN(2, "index %u\n", index); - if (f->flag_no_uref) { - /* not the control endpoint - just forget it */ - return (EINVAL); - } if (f->udev->flags.usb2_mode != USB_MODE_HOST) { /* not possible in device side mode */ return (ENOTTY); @@ -612,10 +608,6 @@ { DPRINTFN(2, "%u, %u\n", iface_index, alt_index); - if (f->flag_no_uref) { - /* not the control endpoint - just forget it */ - return (EINVAL); - } if (f->udev->flags.usb2_mode != USB_MODE_HOST) { /* not possible in device side mode */ return (ENOTTY); @@ -648,10 +640,6 @@ DPRINTFN(6, "\n"); - if (f->flag_no_uref) { - /* control endpoint only */ - return (EINVAL); - } if (ugd->ugd_data == NULL) { /* userland pointer should not be zero */ return (EINVAL); @@ -697,10 +685,6 @@ uint16_t size = sizeof(f->udev->bus->scratch[0].data); int error; - if (f->flag_no_uref) { - /* control endpoint only */ - return (EINVAL); - } if (usb2_req_get_string_desc(f->udev, &Giant, ptr, size, ugd->ugd_lang_id, ugd->ugd_string_index)) { error = EINVAL; @@ -743,10 +727,6 @@ uint8_t i; uint8_t first = 1; - if (f->flag_no_uref) { - /* control endpoint only */ - return (EINVAL); - } max_len = dn->udn_devnames_len; dst = dn->udn_devnames_ptr; @@ -805,10 +785,6 @@ struct usb2_device *udev; struct usb2_device *hub; - if (f->flag_no_uref) { - /* control endpoint only */ - return (EINVAL); - } udev = f->udev; bzero(di, sizeof(di[0])); @@ -911,10 +887,6 @@ uint16_t len; uint16_t actlen; - if (f->flag_no_uref) { - /* control endpoint only */ - return (EINVAL); - } if (ugen_check_request(f->udev, &ur->ucr_request)) { return (EPERM); } @@ -950,10 +922,6 @@ struct usb2_device *udev = f->udev; int error; - if (f->flag_no_uref) { - /* control endpoint only */ - return (EINVAL); - } /* * This request can be useful for testing USB drivers: */ @@ -971,7 +939,7 @@ return (0); } -static int +int ugen_fs_uninit(struct usb2_fifo *f) { if (f->fs_xfer == NULL) { @@ -983,7 +951,6 @@ f->fs_ep_max = 0; f->fs_ep_ptr = NULL; f->flag_iscomplete = 0; - f->flag_no_uref = 0; /* restore operation */ usb2_fifo_free_buffer(f); return (0); } @@ -1385,7 +1352,8 @@ } static int -ugen_fs_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags) +ugen_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags, + struct thread *td) { struct usb2_config usb2_config[1]; struct usb2_device_request req; @@ -1393,8 +1361,6 @@ struct usb2_fs_complete *pcomp; struct usb2_fs_start *pstart; struct usb2_fs_stop *pstop; - struct usb2_fs_init *pinit; - struct usb2_fs_uninit *puninit; struct usb2_fs_open *popen; struct usb2_fs_close *pclose; struct usb2_fs_clear_stall_sync *pstall; @@ -1409,6 +1375,8 @@ u.addr = addr; + DPRINTFN(6, "cmd=0x%08lx\n", cmd); + switch (cmd) { case USB_FS_COMPLETE: mtx_lock(f->priv_mtx); @@ -1443,59 +1411,6 @@ mtx_unlock(f->priv_mtx); break; - case USB_FS_INIT: - /* verify input parameters */ - if (u.pinit->pEndpoints == NULL) { - error = EINVAL; - break; - } - if (u.pinit->ep_index_max > 127) { - error = EINVAL; - break; - } - if (u.pinit->ep_index_max == 0) { - error = EINVAL; - break; - } - if (f->fs_xfer != NULL) { - error = EBUSY; - break; - } - if (f->flag_no_uref) { - error = EINVAL; - break; - } - if (f->dev_ep_index != 0) { - error = EINVAL; - break; - } - if (ugen_fifo_in_use(f, fflags)) { - error = EBUSY; - break; - } - error = usb2_fifo_alloc_buffer(f, 1, u.pinit->ep_index_max); - if (error) { - break; - } - f->fs_xfer = malloc(sizeof(f->fs_xfer[0]) * - u.pinit->ep_index_max, M_USB, M_WAITOK | M_ZERO); - if (f->fs_xfer == NULL) { - usb2_fifo_free_buffer(f); - error = ENOMEM; - break; - } - f->fs_ep_max = u.pinit->ep_index_max; - f->fs_ep_ptr = u.pinit->pEndpoints; - break; - - case USB_FS_UNINIT: - if (u.puninit->dummy != 0) { - error = EINVAL; - break; - } - error = ugen_fs_uninit(f); - break; - case USB_FS_OPEN: if (u.popen->ep_index >= f->fs_ep_max) { error = EINVAL; @@ -1583,11 +1498,6 @@ f->fs_xfer[u.popen->ep_index]->max_data_length; f->fs_xfer[u.popen->ep_index]->priv_fifo = ((uint8_t *)0) + u.popen->ep_index; - /* - * Increase performance by dropping locks we - * don't need: - */ - f->flag_no_uref = 1; } else { error = ENOMEM; } @@ -1644,9 +1554,12 @@ break; default: - error = ENOTTY; + error = ENOIOCTL; break; } + + DPRINTFN(6, "error=%d\n", error); + return (error); } @@ -1999,14 +1912,15 @@ break; default: - error = ENOTTY; + error = ENOIOCTL; break; } return (error); } static int -ugen_ctrl_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags) +ugen_ioctl_post(struct usb2_fifo *f, u_long cmd, void *addr, int fflags, + struct thread *td) { union { struct usb2_interface_descriptor *idesc; @@ -2014,6 +1928,8 @@ struct usb2_device_descriptor *ddesc; struct usb2_config_descriptor *cdesc; struct usb2_device_stats *stat; + struct usb2_fs_init *pinit; + struct usb2_fs_uninit *puninit; uint32_t *ptime; void *addr; int *pint; @@ -2026,6 +1942,8 @@ u.addr = addr; + DPRINTFN(6, "cmd=0x%08lx\n", cmd); + switch (cmd) { case USB_DISCOVER: usb2_needs_explore_all(); @@ -2170,29 +2088,60 @@ *u.pint, 0, UHF_PORT_ENABLE); break; - default: - error = EINVAL; + case USB_FS_INIT: + /* verify input parameters */ + if (u.pinit->pEndpoints == NULL) { + error = EINVAL; + break; + } + if (u.pinit->ep_index_max > 127) { + error = EINVAL; + break; + } + if (u.pinit->ep_index_max == 0) { + error = EINVAL; + break; + } + if (f->fs_xfer != NULL) { + error = EBUSY; + break; + } + if (f->dev_ep_index != 0) { + error = EINVAL; + break; + } + if (ugen_fifo_in_use(f, fflags)) { + error = EBUSY; + break; + } + error = usb2_fifo_alloc_buffer(f, 1, u.pinit->ep_index_max); + if (error) { + break; + } + f->fs_xfer = malloc(sizeof(f->fs_xfer[0]) * + u.pinit->ep_index_max, M_USB, M_WAITOK | M_ZERO); + if (f->fs_xfer == NULL) { + usb2_fifo_free_buffer(f); + error = ENOMEM; + break; + } + f->fs_ep_max = u.pinit->ep_index_max; + f->fs_ep_ptr = u.pinit->pEndpoints; break; - } - return (error); -} -static int -ugen_ioctl(struct usb2_fifo *f, u_long cmd, void *addr, int fflags, - struct thread *td) -{ - int error; + case USB_FS_UNINIT: + if (u.puninit->dummy != 0) { + error = EINVAL; + break; + } + error = ugen_fs_uninit(f); + break; - DPRINTFN(6, "cmd=%08lx\n", cmd); - error = ugen_fs_ioctl(f, cmd, addr, fflags); - if (error == ENOTTY) { - if (f->flag_no_uref) { - mtx_lock(f->priv_mtx); - error = ugen_iface_ioctl(f, cmd, addr, fflags); - mtx_unlock(f->priv_mtx); - } else { - error = ugen_ctrl_ioctl(f, cmd, addr, fflags); - } + default: + mtx_lock(f->priv_mtx); + error = ugen_iface_ioctl(f, cmd, addr, fflags); + mtx_unlock(f->priv_mtx); + break; } DPRINTFN(6, "error=%d\n", error); return (error); ==== //depot/projects/usb/src/sys/dev/usb2/core/usb2_generic.h#7 (text+ko) ==== @@ -29,5 +29,6 @@ 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_ */