
Now that the USB core passes through timeout info to the host controller, actually hook it up.
Signed-off-by: Hector Martin marcan@marcan.st --- drivers/usb/host/xhci-ring.c | 32 ++++++++++++++++++++------------ drivers/usb/host/xhci.c | 23 +++++++++++++---------- include/usb/xhci.h | 14 ++++++++++---- 3 files changed, 43 insertions(+), 26 deletions(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index dabe6cf86af2..14c0c60e8524 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -463,11 +463,16 @@ static int event_ready(struct xhci_ctrl *ctrl) * @param expected TRB type expected from Event TRB * Return: pointer to event trb */ -union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) +union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected, + int timeout) { trb_type type; unsigned long ts = get_timer(0);
+ /* Fallback in case someone passes in 0 */ + if (!timeout) + timeout = XHCI_TIMEOUT; + do { union xhci_trb *event = ctrl->event_ring->dequeue;
@@ -504,7 +509,7 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) le32_to_cpu(event->generic.field[3]));
xhci_acknowledge_event(ctrl); - } while (get_timer(ts) < XHCI_TIMEOUT); + } while (get_timer(ts) < timeout);
if (expected == TRB_TRANSFER) return NULL; @@ -528,7 +533,7 @@ static void reset_ep(struct usb_device *udev, int ep_index)
printf("Resetting EP %d...\n", ep_index); xhci_queue_command(ctrl, 0, udev->slot_id, ep_index, TRB_RESET_EP); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_SYS_TIMEOUT); if (!event) return;
@@ -539,7 +544,7 @@ static void reset_ep(struct usb_device *udev, int ep_index) addr = xhci_trb_virt_to_dma(ring->enq_seg, (void *)((uintptr_t)ring->enqueue | ring->cycle_state)); xhci_queue_command(ctrl, addr, udev->slot_id, ep_index, TRB_SET_DEQ); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_SYS_TIMEOUT); if (!event) return;
@@ -569,7 +574,7 @@ static void abort_td(struct usb_device *udev, int ep_index)
xhci_queue_command(ctrl, 0, udev->slot_id, ep_index, TRB_STOP_RING);
- event = xhci_wait_for_event(ctrl, TRB_NONE); + event = xhci_wait_for_event(ctrl, TRB_NONE, XHCI_SYS_TIMEOUT); if (!event) return;
@@ -582,7 +587,8 @@ static void abort_td(struct usb_device *udev, int ep_index) != COMP_STOP))); xhci_acknowledge_event(ctrl);
- event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, + XHCI_SYS_TIMEOUT); if (!event) return; type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags)); @@ -601,7 +607,7 @@ static void abort_td(struct usb_device *udev, int ep_index) addr = xhci_trb_virt_to_dma(ring->enq_seg, (void *)((uintptr_t)ring->enqueue | ring->cycle_state)); xhci_queue_command(ctrl, addr, udev->slot_id, ep_index, TRB_SET_DEQ); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_SYS_TIMEOUT); if (!event) return;
@@ -657,10 +663,11 @@ static void record_transfer_result(struct usb_device *udev, * @param pipe contains the DIR_IN or OUT , devnum * @param length length of the buffer * @param buffer buffer to be read/written based on the request + * @param timeout timeout in milliseconds * Return: returns 0 if successful else -1 on failure */ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer) + int length, void *buffer, int timeout) { int num_trbs = 0; struct xhci_generic_trb *start_trb; @@ -825,7 +832,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, giveback_first_trb(udev, ep_index, start_cycle, start_trb);
again: - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); + event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout); if (!event) { debug("XHCI bulk transfer timed out, aborting...\n"); abort_td(udev, ep_index); @@ -862,11 +869,12 @@ again: * @param req request type * @param length length of the buffer * @param buffer buffer to be read/written based on the request + * @param timeout timeout in milliseconds * Return: returns 0 if successful else error code on failure */ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, struct devrequest *req, int length, - void *buffer) + void *buffer, int timeout) { int ret; int start_cycle; @@ -1027,7 +1035,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe,
giveback_first_trb(udev, ep_index, start_cycle, start_trb);
- event = xhci_wait_for_event(ctrl, TRB_TRANSFER); + event = xhci_wait_for_event(ctrl, TRB_TRANSFER, timeout); if (!event) goto abort; field = le32_to_cpu(event->trans_event.flags); @@ -1052,7 +1060,7 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, if (GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len)) == COMP_SHORT_TX) { /* Short data stage, clear up additional status stage event */ - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); + event = xhci_wait_for_event(ctrl, TRB_TRANSFER, XHCI_SYS_TIMEOUT); if (!event) goto abort; BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a33a2460f74d..1c4afdf385f7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -450,7 +450,7 @@ static int xhci_configure_endpoints(struct usb_device *udev, bool ctx_change) xhci_flush_cache((uintptr_t)in_ctx->bytes, in_ctx->size); xhci_queue_command(ctrl, in_ctx->dma, udev->slot_id, 0, ctx_change ? TRB_EVAL_CONTEXT : TRB_CONFIG_EP); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_SYS_TIMEOUT); if (!event) return -ETIMEDOUT;
@@ -649,7 +649,7 @@ static int xhci_address_device(struct usb_device *udev, int root_portnr)
xhci_queue_command(ctrl, virt_dev->in_ctx->dma, slot_id, 0, TRB_ADDR_DEV); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_SYS_TIMEOUT); if (!event) return -ETIMEDOUT;
@@ -727,7 +727,7 @@ static int _xhci_alloc_device(struct usb_device *udev) }
xhci_queue_command(ctrl, 0, 0, 0, TRB_ENABLE_SLOT); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, XHCI_SYS_TIMEOUT); if (!event) return -ETIMEDOUT;
@@ -1125,7 +1125,7 @@ static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, * (at most) one TD. A TD (comprised of sg list entries) can * take several service intervals to transmit. */ - return xhci_bulk_tx(udev, pipe, length, buffer); + return xhci_bulk_tx(udev, pipe, length, buffer, XHCI_INT_TIMEOUT); }
/** @@ -1135,17 +1135,18 @@ static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, * @param pipe contains the DIR_IN or OUT , devnum * @param buffer buffer to be read/written based on the request * @param length length of the buffer + * @param timeout timeout in milliseconds * Return: returns 0 if successful else -1 on failure */ static int _xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe, - void *buffer, int length) + void *buffer, int length, int timeout) { if (usb_pipetype(pipe) != PIPE_BULK) { printf("non-bulk pipe (type=%lu)", usb_pipetype(pipe)); return -EINVAL; }
- return xhci_bulk_tx(udev, pipe, length, buffer); + return xhci_bulk_tx(udev, pipe, length, buffer, timeout); }
/** @@ -1157,11 +1158,13 @@ static int _xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe, * @param length length of the buffer * @param setup Request type * @param root_portnr Root port number that this device is on + * @param timeout timeout in milliseconds * Return: returns 0 if successful else -1 on failure */ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe, void *buffer, int length, - struct devrequest *setup, int root_portnr) + struct devrequest *setup, int root_portnr, + int timeout) { struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); int ret = 0; @@ -1187,7 +1190,7 @@ static int _xhci_submit_control_msg(struct usb_device *udev, unsigned long pipe, } }
- return xhci_ctrl_tx(udev, pipe, setup, length, buffer); + return xhci_ctrl_tx(udev, pipe, setup, length, buffer, timeout); }
static int xhci_lowlevel_init(struct xhci_ctrl *ctrl) @@ -1290,7 +1293,7 @@ static int xhci_submit_control_msg(struct udevice *dev, struct usb_device *udev, hop = hop->parent; */ return _xhci_submit_control_msg(udev, pipe, buffer, length, setup, - root_portnr); + root_portnr, timeout); }
static int xhci_submit_bulk_msg(struct udevice *dev, struct usb_device *udev, @@ -1298,7 +1301,7 @@ static int xhci_submit_bulk_msg(struct udevice *dev, struct usb_device *udev, int timeout) { debug("%s: dev='%s', udev=%p\n", __func__, dev->name, udev); - return _xhci_submit_bulk_msg(udev, pipe, buffer, length); + return _xhci_submit_bulk_msg(udev, pipe, buffer, length, timeout); }
static int xhci_submit_int_msg(struct udevice *dev, struct usb_device *udev, diff --git a/include/usb/xhci.h b/include/usb/xhci.h index 04d16a256bbd..02660803fdcf 100644 --- a/include/usb/xhci.h +++ b/include/usb/xhci.h @@ -27,7 +27,11 @@ #define MAX_EP_CTX_NUM 31 #define XHCI_ALIGNMENT 64 /* Generic timeout for XHCI events */ -#define XHCI_TIMEOUT 5000 +#define XHCI_TIMEOUT 1000 +/* Timeout for interrupt messages */ +#define XHCI_INT_TIMEOUT 1000 +/* Timeout for system commands */ +#define XHCI_SYS_TIMEOUT 200 /* Max number of USB devices for any host controller - limit in section 6.1 */ #define MAX_HC_SLOTS 256 /* Section 5.3.3 - MaxPorts */ @@ -1258,11 +1262,13 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, void xhci_queue_command(struct xhci_ctrl *ctrl, dma_addr_t addr, u32 slot_id, u32 ep_index, trb_type cmd); void xhci_acknowledge_event(struct xhci_ctrl *ctrl); -union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected); +union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected, + int timeout); int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer); + int length, void *buffer, int timeout); int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, - struct devrequest *req, int length, void *buffer); + struct devrequest *req, int length, void *buffer, + int timeout); int xhci_check_maxpacket(struct usb_device *udev); void xhci_flush_cache(uintptr_t addr, u32 type_len); void xhci_inval_cache(uintptr_t addr, u32 type_len);