diff options
author | thompsa <thompsa@FreeBSD.org> | 2009-04-25 21:10:06 +0000 |
---|---|---|
committer | thompsa <thompsa@FreeBSD.org> | 2009-04-25 21:10:06 +0000 |
commit | 1253be32753b7ab96a90d57fc07991ae8a154177 (patch) | |
tree | 6204fa982868a9530323799ccff1606ec998c2ba /sys/dev/usb/usb_transfer.c | |
parent | 50a34549cf93908659f1fb58b36fc7ed8ecfc3b8 (diff) | |
download | FreeBSD-src-1253be32753b7ab96a90d57fc07991ae8a154177.zip FreeBSD-src-1253be32753b7ab96a90d57fc07991ae8a154177.tar.gz |
Track the usb device state as its powered on, addressed and configured. This helps
to avoid touching the device when it is not going to respond and would otherwise
timeout.
Implement the suspend tracking as a udev state too.
Diffstat (limited to 'sys/dev/usb/usb_transfer.c')
-rw-r--r-- | sys/dev/usb/usb_transfer.c | 43 |
1 files changed, 28 insertions, 15 deletions
diff --git a/sys/dev/usb/usb_transfer.c b/sys/dev/usb/usb_transfer.c index bc44177..d4efaff 100644 --- a/sys/dev/usb/usb_transfer.c +++ b/sys/dev/usb/usb_transfer.c @@ -1365,24 +1365,37 @@ error: void usb2_start_hardware(struct usb2_xfer *xfer) { + struct usb2_xfer_root *info; + struct usb2_bus *bus; usb2_frcount_t x; + info = xfer->xroot; + bus = info->bus; + DPRINTF("xfer=%p, pipe=%p, nframes=%d, dir=%s\n", xfer, xfer->pipe, xfer->nframes, USB_GET_DATA_ISREAD(xfer) ? "read" : "write"); + /* Check if the device is still alive */ + if (info->udev->state < USB_STATE_POWERED) { + USB_BUS_LOCK(bus); + usb2_transfer_done(xfer, USB_ERR_NOT_CONFIGURED); + USB_BUS_UNLOCK(bus); + return; + } + #if USB_DEBUG if (USB_DEBUG_VAR > 0) { - USB_BUS_LOCK(xfer->xroot->bus); + USB_BUS_LOCK(bus); usb2_dump_pipe(xfer->pipe); - USB_BUS_UNLOCK(xfer->xroot->bus); + USB_BUS_UNLOCK(bus); } #endif USB_XFER_LOCK_ASSERT(xfer, MA_OWNED); - USB_BUS_LOCK_ASSERT(xfer->xroot->bus, MA_NOTOWNED); + USB_BUS_LOCK_ASSERT(bus, MA_NOTOWNED); /* Only open the USB transfer once! */ if (!xfer->flags_int.open) { @@ -1390,9 +1403,9 @@ usb2_start_hardware(struct usb2_xfer *xfer) DPRINTF("open\n"); - USB_BUS_LOCK(xfer->xroot->bus); + USB_BUS_LOCK(bus); (xfer->pipe->methods->open) (xfer); - USB_BUS_UNLOCK(xfer->xroot->bus); + USB_BUS_UNLOCK(bus); } /* set "transferring" flag */ xfer->flags_int.transferring = 1; @@ -1406,9 +1419,9 @@ usb2_start_hardware(struct usb2_xfer *xfer) * frequently the "done_q": */ if (xfer->wait_queue) { - USB_BUS_LOCK(xfer->xroot->bus); + USB_BUS_LOCK(bus); usb2_transfer_dequeue(xfer); - USB_BUS_UNLOCK(xfer->xroot->bus); + USB_BUS_UNLOCK(bus); } /* clear "did_dma_delay" flag */ xfer->flags_int.did_dma_delay = 0; @@ -1441,16 +1454,16 @@ usb2_start_hardware(struct usb2_xfer *xfer) */ DPRINTF("xfer=%p nframes=0: stall " "or clear stall!\n", xfer); - USB_BUS_LOCK(xfer->xroot->bus); + USB_BUS_LOCK(bus); xfer->flags_int.can_cancel_immed = 1; /* start the transfer */ usb2_command_wrapper(&xfer->pipe->pipe_q, xfer); - USB_BUS_UNLOCK(xfer->xroot->bus); + USB_BUS_UNLOCK(bus); return; } - USB_BUS_LOCK(xfer->xroot->bus); + USB_BUS_LOCK(bus); usb2_transfer_done(xfer, USB_ERR_INVAL); - USB_BUS_UNLOCK(xfer->xroot->bus); + USB_BUS_UNLOCK(bus); return; } /* compute total transfer length */ @@ -1459,9 +1472,9 @@ usb2_start_hardware(struct usb2_xfer *xfer) xfer->sumlen += xfer->frlengths[x]; if (xfer->sumlen < xfer->frlengths[x]) { /* length wrapped around */ - USB_BUS_LOCK(xfer->xroot->bus); + USB_BUS_LOCK(bus); usb2_transfer_done(xfer, USB_ERR_INVAL); - USB_BUS_UNLOCK(xfer->xroot->bus); + USB_BUS_UNLOCK(bus); return; } } @@ -1476,9 +1489,9 @@ usb2_start_hardware(struct usb2_xfer *xfer) if (xfer->flags_int.control_xfr) { if (usb2_start_hardware_sub(xfer)) { - USB_BUS_LOCK(xfer->xroot->bus); + USB_BUS_LOCK(bus); usb2_transfer_done(xfer, USB_ERR_STALLED); - USB_BUS_UNLOCK(xfer->xroot->bus); + USB_BUS_UNLOCK(bus); return; } } |