I'm using the UPL device driver for the Prolific PL2301/PL2302
host-to-host bridge cable.
This driver doesn't employ the use of reference counts to protect
against device detaches preempting
in-progress I/O or control requests to/from the device.
I've noticed that most other USB device driver make use of reference
counts for this purpose.
For example, in ugen.c:
ugen_detach() {
... code to abort all pipes ...
if (--sc->sc_refcnt >= 0) {
/* Wake everyone */
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
wakeup(&sc->sc_endpoints[i][IN]);
/* Wait for processes to go away */
usb_detach_wait(USBDEV(sc->sc_dev)
}
... continue & exit from ugen_detach()
}
In all routines that initiate I/O, sc->sc_refcnt is incremented, I/O is
performed, and then decremented.
For example, in ugenread() :
sc->sc_refcnt++
error = ugen_do_read(sc, endpt, uio, flag);
if (--sc->sc_refcnt < 0)
usb_detach_wakeup(USBDEV(sc->sc_dev));
I've seen several crashes in the UPL driver which appear to be the
result of it's detach routine
being called and preempting in progress I/O, and hence deallocating
critical data-structures
that the I/O is dependent on.
For example, I see a crash in usbd_alloc_xfer(), on the following line:
usbd_alloc_xfer(usbd_device_handle dev)
usbd_xfer_handle xfer;
xfer = dev->bus->methods->allocx(dev->bus) <-- NULL pointer
dereference here
From the crash(es), either the 'bus' pointer or the 'methods' pointer
is invalid.
This is because the UPL detach routine has preempted the UPL init code,
deallocated the above data structures, and exited.
So I believe the correct fix for this is to utilize the reference count
approach
which I see is used in several other USB device drivers.
Can anybody comment on this approach (reference count approach),
and/or better explain to me why the reference counts are used,
and whether or not I should also implement them in the UPL driver.
Thanks for your help,
Dave