USB problems
John Birrell
jb at cimlogic.com.au
Mon Dec 27 17:09:41 PST 2004
[ I'm not sure who the maintainer for FreeBSD's code is these days. ]
I've been encountering a number of problems with the USB implementation
in current. Although this message refers to current, I think the problems
are in RELENG_5 too.
1. The USB sub-system doesn't handle loading and unloading drivers properly.
If a driver is unloaded when a USB device is still attached, the next
time the driver is loaded, the kernel panics. This might not be such
a problem to normal users because they don't have a need to do that, but
during driver development when you want to load and unload repeatedly,
it's a pain.
2. I have two devices that are based on Philips' ISP1581 USB 2.0 controller.
Both are MPEG encoders and one has a TV tuner. The one without the
tuner is Philips' USB-MPEG2 evaluation board which has example firmware
on-board as a reference design. It isn't possible to use either of these
boards with FreeBSD's USB implementation because of the over-zealous
firmware code which stalls the control endpoint at every opportunity.
The Windows driver that Philips' supply without source code appears to
have no problems talking to the device. When I do the same things with
FreeBSD, the continual control endpoint stalls result in not being
able to even get the string descriptors for manufacturer and product
(the firmware code stalls those requests).
I think what is happening is that the uhci (and ehci etc) drivers are
detecting the stall and not processing the data that is actually
returned with the stall status. When I move the code:
if (nstatus & UHCI_TD_ACTIVE)
break;
in uhci_idone() to the bottom of the loop, it returns the actlen
properly (I think). At least I can get the data from the device despite
the stall.
3. The usbd_bulk_transfer function calls tsleep() to wait for streaming
data to become available. On current, this bumps into a KASSERT in
msleep because Giant is not locked and no mutex has been supplied.
In my driver, I need to run an 'encoder' thread which calls
usbd_bulk_transfer() to gobble the incoming MPEG data stream. While
this is going on, there is no syscall in progress because the
application is off doing other things. It might be looking at the
mmaped buffer or it may not.
For FreeBSD, usbd_bulk_transfer() needs to change to allow the driver
to specify it's mutex. I don't know what the implications are for
uhci given that it hasn't been converted to use mutexes. Can anyone
comment on that?
Where do we stand making architectural changes to the USB code given the
efforts to stay in sync with NetBSD/OpenBSD?
I'd love to get rid of the attach_args structure and just pass a
usbd_device_handle into the drivers, with struct usbd_device containing
a couple of extra variables for use during matching.
I'd like to remove the subdevs array from struct usbd_device under
FreeBSD because the parent/child device tree should only be managed by
bus routines. The relationship between a USB device and it's device_t
should just be a field in struct usbd_device and it should be cleared
when there is no device_t. Leaving a device_t hanging around when a
driver had been unloaded is what is causing the panics I am seeing.
I think that the uhub driver should have a uhub_driver_added routine rather
than using the generic one. I'd really like to see the uhub code re-match
vendor/product codes when a new driver is added, and if the new driver
matches, then uhub should detach ugen and use the new driver. Similarly,
when a driver is unloaded, if a USB device is still present, it should go
back to ugen.
--
John Birrell
More information about the freebsd-current
mailing list