diff options
author | Julius Werner <jwerner@chromium.org> | 2013-02-21 13:41:40 -0800 |
---|---|---|
committer | Isaac Christensen <isaac.christensen@se-eng.com> | 2014-08-12 22:03:28 +0200 |
commit | e9738dbe2bb564f7be7930aa5b01e9ae3c1e2288 (patch) | |
tree | 83dc0c3c1463253ebbf76ebe81a69421744c26f7 /payloads/libpayload/drivers/usb/xhci.c | |
parent | 0f0c720621deacc3c51b409e10ea8100acc88c80 (diff) | |
download | coreboot-e9738dbe2bb564f7be7930aa5b01e9ae3c1e2288.tar.xz |
libpayload: Make USB transfer functions return amount of bytes
The USB bulk and control transfer functions in libpayload currently
always return 0 for success and 1 for all errors. This is sufficient for
current use cases (essentially just mass storage), but other classes
(like certain Ethernet adapters) need to be able to tell if a transfer
reached the intended amount of bytes, or if it fell short.
This patch slightly changes that USB API to return -1 on errors, and the
amount of transferred bytes on successes. All drivers in the current
libpayload mainline are modified to conform to the new error detection
model. Any third party users of this API will need to adapt their
if (...<controller>->bulk/control(...)) checks to
if (...<controller>->bulk/control(...) < 0) as well.
The host controller drivers for OHCI and EHCI correctly implement the
new behavior. UHCI and the XHCI stub just comply with the new API by
returning 0 or -1, but do not actually count the returned bytes.
Signed-off-by: Julius Werner <jwerner@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/48308
Reviewed-by: Gabe Black <gabeblack@chromium.org>
Reviewed-by: Stefan Reinauer <reinauer@google.com>
Tested-by: Gabe Black <gabeblack@chromium.org>
Commit-Queue: Gabe Black <gabeblack@chromium.org>
Updated the patch to support XHCI as well.
Change-Id: Ic2ea2810c5edb992cbe185bc9711d2f8f557cae6
(cherry picked from commit e39e2d84762a3804653d950a228ed2269c651458)
Signed-off-by: Isaac Christensen <isaac.christensen@se-eng.com>
Reviewed-on: http://review.coreboot.org/6390
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Reviewed-by: Patrick Georgi <patrick@georgi-clan.de>
Diffstat (limited to 'payloads/libpayload/drivers/usb/xhci.c')
-rw-r--r-- | payloads/libpayload/drivers/usb/xhci.c | 25 |
1 files changed, 13 insertions, 12 deletions
diff --git a/payloads/libpayload/drivers/usb/xhci.c b/payloads/libpayload/drivers/usb/xhci.c index d31a8e2a8e..184a370936 100644 --- a/payloads/libpayload/drivers/usb/xhci.c +++ b/payloads/libpayload/drivers/usb/xhci.c @@ -588,14 +588,14 @@ xhci_control(usbdev_t *const dev, const direction_t dir, const size_t off = (size_t)data & 0xffff; if ((off + dalen) > ((TRANSFER_RING_SIZE - 4) << 16)) { xhci_debug("Unsupported transfer size\n"); - return 1; + return -1; } /* Reset endpoint if it's halted */ const unsigned ep_state = EC_GET(STATE, di->devctx.ep0); if (ep_state == 2 || ep_state == 4) { if (xhci_reset_endpoint(dev, NULL, 0)) - return 1; + return -1; } /* Fill and enqueue setup TRB */ @@ -631,11 +631,12 @@ xhci_control(usbdev_t *const dev, const direction_t dir, xhci->dbreg[dev->address] = 1; /* Wait for transfer events */ - int i; + int i, transferred = 0; const int n_stages = 2 + !!dalen; for (i = 0; i < n_stages; ++i) { const int ret = xhci_wait_for_transfer(xhci, dev->address, 1); - if (ret != CC_SUCCESS) { + transferred += ret; + if (ret < 0) { if (ret == TIMEOUT) { xhci_debug("Stopping ID %d EP 1\n", dev->address); @@ -651,11 +652,11 @@ xhci_control(usbdev_t *const dev, const direction_t dir, tr->ring, setup, status, ep_state, EC_GET(STATE, di->devctx.ep0), xhci->opreg->usbsts); - return 1; + return ret; } } - return 0; + return transferred; } /* finalize == 1: if data is of packet aligned size, add a zero length packet */ @@ -675,14 +676,14 @@ xhci_bulk(endpoint_t *const ep, const size_t off = (size_t)data & 0xffff; if ((off + size) > ((TRANSFER_RING_SIZE - 2) << 16)) { xhci_debug("Unsupported transfer size\n"); - return 1; + return -1; } /* Reset endpoint if it's halted */ const unsigned ep_state = EC_GET(STATE, di->devctx.eps[ep_id]); if (ep_state == 2 || ep_state == 4) { if (xhci_reset_endpoint(ep->dev, ep, 0)) - return 1; + return -1; } /* Enqueue transfer and ring doorbell */ @@ -693,12 +694,12 @@ xhci_bulk(endpoint_t *const ep, /* Wait for transfer event */ const int ret = xhci_wait_for_transfer(xhci, ep->dev->address, ep_id); - if (ret != CC_SUCCESS) { + if (ret < 0) { if (ret == TIMEOUT) { xhci_debug("Stopping ID %d EP %d\n", ep->dev->address, ep_id); xhci_cmd_stop_endpoint(xhci, ep->dev->address, ep_id); - } else if (ret == CC_STALL_ERROR) { + } else if (ret == -CC_STALL_ERROR) { xhci_reset_endpoint(ep->dev, ep, 1); } xhci_debug("Bulk transfer failed: %d\n" @@ -707,10 +708,10 @@ xhci_bulk(endpoint_t *const ep, ret, ep_state, EC_GET(STATE, di->devctx.eps[ep_id]), xhci->opreg->usbsts); - return 1; + return ret; } - return 0; + return ret; } static trb_t * |