diff options
Diffstat (limited to 'freebsd/sys/dev/usb/usb_dev.c')
-rw-r--r-- | freebsd/sys/dev/usb/usb_dev.c | 88 |
1 files changed, 39 insertions, 49 deletions
diff --git a/freebsd/sys/dev/usb/usb_dev.c b/freebsd/sys/dev/usb/usb_dev.c index eaad5952..a22de719 100644 --- a/freebsd/sys/dev/usb/usb_dev.c +++ b/freebsd/sys/dev/usb/usb_dev.c @@ -37,7 +37,6 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/bus.h> -#include <sys/linker_set.h> #include <sys/module.h> #include <rtems/bsd/sys/lock.h> #include <sys/mutex.h> @@ -87,9 +86,8 @@ static int usb_fifo_debug = 0; SYSCTL_NODE(_hw_usb, OID_AUTO, dev, CTLFLAG_RW, 0, "USB device"); -SYSCTL_INT(_hw_usb_dev, OID_AUTO, debug, CTLFLAG_RW, +SYSCTL_INT(_hw_usb_dev, OID_AUTO, debug, CTLFLAG_RW | CTLFLAG_TUN, &usb_fifo_debug, 0, "Debug Level"); - TUNABLE_INT("hw.usb.dev.debug", &usb_fifo_debug); #endif @@ -220,10 +218,10 @@ usb_ref_device(struct usb_cdev_privdata *cpd, 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); @@ -284,9 +282,10 @@ usb_ref_device(struct usb_cdev_privdata *cpd, 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); } @@ -338,7 +337,7 @@ usb_unref_device(struct usb_cdev_privdata *cpd, 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); @@ -916,10 +915,23 @@ usb_close(void *arg) DPRINTFN(2, "cpd=%p\n", cpd); - err = usb_ref_device(cpd, &refs, 1); - if (err) { - free(cpd, M_USBDEV); - return; + err = usb_ref_device(cpd, &refs, 0); + if (err) + goto done; + + /* + * If this function is not called directly from the root HUB + * thread, there is usually a need to lock the enumeration + * lock. Check this. + */ + if (!usbd_enum_is_locked(cpd->udev)) { + + DPRINTFN(2, "Locking enumeration\n"); + + /* reference device */ + err = usb_usb_ref_device(cpd, &refs); + if (err) + goto done; } if (cpd->fflags & FREAD) { usb_fifo_close(refs.rxfifo, cpd->fflags); @@ -927,10 +939,9 @@ usb_close(void *arg) if (cpd->fflags & FWRITE) { usb_fifo_close(refs.txfifo, cpd->fflags); } - usb_unref_device(cpd, &refs); +done: free(cpd, M_USBDEV); - return; } static void @@ -1646,14 +1657,13 @@ usb_fifo_check_methods(struct usb_fifo_methods *pm) int usb_fifo_attach(struct usb_device *udev, void *priv_sc, struct mtx *priv_mtx, struct usb_fifo_methods *pm, - struct usb_fifo_sc *f_sc, uint16_t unit, uint16_t subunit, + struct usb_fifo_sc *f_sc, uint16_t unit, int16_t subunit, uint8_t iface_index, uid_t uid, gid_t gid, int mode) { struct usb_fifo *f_tx; struct usb_fifo *f_rx; char devname[32]; uint8_t n; - struct usb_fs_privdata* pd; f_sc->fp[USB_FIFO_TX] = NULL; f_sc->fp[USB_FIFO_RX] = NULL; @@ -1724,7 +1734,7 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc, if (pm->basename[n] == NULL) { continue; } - if (subunit == 0xFFFF) { + if (subunit < 0) { if (snprintf(devname, sizeof(devname), "%s%u%s", pm->basename[n], unit, pm->postfix[n] ? @@ -1733,7 +1743,7 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc, } } else { if (snprintf(devname, sizeof(devname), - "%s%u.%u%s", pm->basename[n], + "%s%u.%d%s", pm->basename[n], unit, subunit, pm->postfix[n] ? pm->postfix[n] : "")) { /* ignore */ @@ -1751,22 +1761,10 @@ usb_fifo_attach(struct usb_device *udev, void *priv_sc, usb_alloc_symlink(devname); } - /* - * Initialize device private data - this is used to find the - * actual USB device itself. - */ - pd = malloc(sizeof(struct usb_fs_privdata), M_USBDEV, M_WAITOK | M_ZERO); - pd->bus_index = device_get_unit(udev->bus->bdev); - pd->dev_index = udev->device_index; - pd->ep_addr = -1; /* not an endpoint */ - pd->fifo_index = f_tx->fifo_index & f_rx->fifo_index; - pd->mode = FREAD|FWRITE; - - /* Now, create the device itself */ - f_sc->dev = make_dev(&usb_devsw, 0, uid, gid, mode, - "%s", devname); - /* XXX setting si_drv1 and creating the device is not atomic! */ - f_sc->dev->si_drv1 = pd; + /* Create the device */ + f_sc->dev = usb_make_dev(udev, devname, -1, + f_tx->fifo_index & f_rx->fifo_index, + FREAD|FWRITE, uid, gid, mode); } DPRINTFN(2, "attached %p/%p\n", f_tx, f_rx); @@ -1815,14 +1813,8 @@ usb_fifo_free_buffer(struct usb_fifo *f) } /* reset queues */ - bzero(&f->free_q, sizeof(f->free_q)); - bzero(&f->used_q, sizeof(f->used_q)); -} - -static void -usb_fifo_cleanup(void* ptr) -{ - free(ptr, M_USBDEV); + memset(&f->free_q, 0, sizeof(f->free_q)); + memset(&f->used_q, 0, sizeof(f->used_q)); } void @@ -1837,11 +1829,9 @@ usb_fifo_detach(struct usb_fifo_sc *f_sc) f_sc->fp[USB_FIFO_TX] = NULL; f_sc->fp[USB_FIFO_RX] = NULL; - if (f_sc->dev != NULL) { - destroy_dev_sched_cb(f_sc->dev, - usb_fifo_cleanup, f_sc->dev->si_drv1); - f_sc->dev = NULL; - } + usb_destroy_dev(f_sc->dev); + + f_sc->dev = NULL; DPRINTFN(2, "detached %p\n", f_sc); } @@ -1923,7 +1913,7 @@ usb_fifo_put_data_linear(struct usb_fifo *f, void *ptr, io_len = MIN(len, m->cur_data_len); - bcopy(ptr, m->cur_data_ptr, io_len); + memcpy(m->cur_data_ptr, ptr, io_len); m->cur_data_len = io_len; ptr = USB_ADD_BYTES(ptr, io_len); @@ -2066,7 +2056,7 @@ usb_fifo_get_data_linear(struct usb_fifo *f, void *ptr, io_len = MIN(len, m->cur_data_len); - bcopy(m->cur_data_ptr, ptr, io_len); + memcpy(ptr, m->cur_data_ptr, io_len); len -= io_len; ptr = USB_ADD_BYTES(ptr, io_len); |