device_detach deletes the softc allocated for the device.
Drivers cache copies of softc in their ISRs and other places where
they sleep and count on the cached copy of softc to still be around
when they are woken up. If a pccard is ejected between these points,
these cached copies disappear because the ejection code deletes the
device from the device tree (an as a side effect calls detach, which
frees the softc for the device).
Suspend has a similar problem because it can come in while a
device is sleeping.
The device_detach routine *must* teardown all interrupt handlers and
release all resources. If this rule is followed, then the handler
shouldn't be called after detach, so there is no problem, right?
The problem is that the following occurs now:
DEVICE_DETACH called from device_delete_child wakes up all the sleepers
and exits. The sleepers actually start running after DEVICE_DETACH has
finished and the softc has been blown away by the device_delete_child
I think this cries for a loop: Call detach and if EAGAIN is returned
make sure sleepers can wake up and exit, and then try again.
I have no idea how this 'wait for sleepers to have run' could be
implemented, but this is I think the crucial part.