summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/dev/usb/usb_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/dev/usb/usb_dev.c')
-rw-r--r--freebsd/sys/dev/usb/usb_dev.c88
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);