diff options
author | hselasky <hselasky@FreeBSD.org> | 2014-06-11 05:39:08 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2014-06-11 05:39:08 +0000 |
commit | 6976be81b3b183e75f2ecf2a0fe39136ace8cb9f (patch) | |
tree | 48132ba6c7f1af2727c50cd208afbfc29b212dd5 /sys/dev/usb/usb_dev.c | |
parent | 150b18f93d81fc7c1cfeaaef8ccb23259a94e695 (diff) | |
download | FreeBSD-src-6976be81b3b183e75f2ecf2a0fe39136ace8cb9f.zip FreeBSD-src-6976be81b3b183e75f2ecf2a0fe39136ace8cb9f.tar.gz |
MFC r267240:
Resolve a deadlock setting the USB configuration index from userspace
on USB HUBs by moving the code into the USB explore threads. The
deadlock happens because child devices of the USB HUB don't have the
expected reference count when called from outside the explore
thread. Only the HUB device itself, which the IOCTL interface locks,
gets the correct reference count.
Diffstat (limited to 'sys/dev/usb/usb_dev.c')
-rw-r--r-- | sys/dev/usb/usb_dev.c | 11 |
1 files changed, 8 insertions, 3 deletions
diff --git a/sys/dev/usb/usb_dev.c b/sys/dev/usb/usb_dev.c index e4471ae..6ad02a7 100644 --- a/sys/dev/usb/usb_dev.c +++ b/sys/dev/usb/usb_dev.c @@ -1116,9 +1116,14 @@ usb_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int fflag, struct thread* usb_pause_mtx(NULL, hz / 128); - if (usb_ref_device(cpd, &refs, 1 /* need uref */)) { - err = ENXIO; - goto done; + while (usb_ref_device(cpd, &refs, 1 /* need uref */)) { + if (usb_ref_device(cpd, &refs, 0)) { + /* device no longer exits */ + err = ENXIO; + goto done; + } + usb_unref_device(cpd, &refs); + usb_pause_mtx(NULL, hz / 128); } } |