Subject: ohci_abort_xfer and disappearing interfaces
To: None <current-users@netbsd.org>
From: Greg Troxel <gdt@ir.bbn.com>
List: current-users
Date: 03/30/2006 13:15:51
I have a Kyocera KPC650 EVDO interface card which has on it

ohci
 uhub
   ugensa
     [ucom]

This works fine with Verizon EVDO service.

When removing the card, I get a panic.  One backtrace shows ugensa's
detach routine calling ohci_abort_xfer.  This procedure checks
sc->sc_dying (which is 1 in my backtrace), but then doesn't return
after doing the 'software only' part.  This seems wrong, but I have
only a dim grasp of the USB stack.  In general, I'd think the card
removal event would walk the device tree rooted at the card and set
sc->sc_dying to true but without doing anything else, and then go back
and do state teardowns.  The tricky part is that ugensa wants to shutdown
bulk transfers (in case it was detached from a usb bus), but in this
case not only the bus but the controller are gone already.

Any clues?

void
ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
{
	struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
	ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
	ohci_soft_ed_t *sed = opipe->sed;
	ohci_soft_td_t *p, *n;
	ohci_physaddr_t headp;
	int s, hit;
	int wake;

	DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,sed));

	if (sc->sc_dying) {
		/* If we're dying, just do the software part. */
		s = splusb();
		xfer->status = status;	/* make software ignore it */
		usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
		usb_transfer_complete(xfer);
		splx(s);

GDT: why is there no return here?

	}

	if (xfer->device->bus->intr_context || !curproc)
		panic("ohci_abort_xfer: not in process context");