From patchwork Mon Sep 14 02:39:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wessel X-Patchwork-Id: 1363197 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=windriver.com Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BqVv959Ybz9sTN for ; Mon, 14 Sep 2020 12:39:47 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 6542081B88; Mon, 14 Sep 2020 04:39:40 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=windriver.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 7E46C81996; Mon, 14 Sep 2020 04:39:38 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail1.windriver.com (mail1.windriver.com [147.11.146.13]) (using TLSv1.1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 8933881996 for ; Mon, 14 Sep 2020 04:39:34 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=windriver.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=jwessel@windriver.com Received: from ALA-HCA.corp.ad.wrs.com (ala-hca.corp.ad.wrs.com [147.11.189.40]) by mail1.windriver.com (8.15.2/8.15.2) with ESMTPS id 08E2dU3J028725 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Sun, 13 Sep 2020 19:39:31 -0700 (PDT) Received: from ala-lpggp2.wrs.com (147.11.105.123) by ALA-HCA.corp.ad.wrs.com (147.11.189.50) with Microsoft SMTP Server id 14.3.487.0; Sun, 13 Sep 2020 19:39:22 -0700 Received: by ala-lpggp2.wrs.com (Postfix, from userid 5002) id C47C7D6082C; Sun, 13 Sep 2020 19:39:22 -0700 (PDT) From: Jason Wessel To: CC: Subject: [PATCH v2 1/4] xhci.c: Add retry in xhci_address_device() Date: Sun, 13 Sep 2020 19:39:18 -0700 Message-ID: <20200914023921.119630-2-jason.wessel@windriver.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200914023921.119630-1-jason.wessel@windriver.com> References: <20200914023921.119630-1-jason.wessel@windriver.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean After a port reset some usb keyboard devices do not respond immediately, and instead the controller reports COMP_TX_ERR. Adding a retry after the first TX error is returned resolves the issue. Without the patch u-boot prints: Starting the controller USB XHCI 1.00 scanning bus xhci_pci for devices... Device not responding to set address. USB device not accepting new address (error=80000000) Signed-off-by: Jason Wessel --- drivers/usb/host/xhci.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 126dabc11b..9a31eba2bb 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -675,6 +675,7 @@ static int xhci_address_device(struct usb_device *udev, int root_portnr) struct xhci_virt_device *virt_dev; int slot_id = udev->slot_id; union xhci_trb *event; + int retry_cnt = 0; virt_dev = ctrl->devs[slot_id]; @@ -685,6 +686,7 @@ static int xhci_address_device(struct usb_device *udev, int root_portnr) debug("Setting up addressable devices %p\n", ctrl->dcbaa); xhci_setup_addressable_virt_dev(ctrl, udev, root_portnr); +retry: ctrl_ctx = xhci_get_input_control_ctx(virt_dev->in_ctx); ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG); ctrl_ctx->drop_flags = 0; @@ -701,6 +703,13 @@ static int xhci_address_device(struct usb_device *udev, int root_portnr) ret = -EINVAL; break; case COMP_TX_ERR: + retry_cnt++; + if (retry_cnt < 2) { + /* Retry in case this was just after a port reset */ + debug("COMP_TX_ERR retry\n"); + xhci_acknowledge_event(ctrl); + goto retry; + } puts("Device not responding to set address.\n"); ret = -EPROTO; break; From patchwork Mon Sep 14 02:39:19 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wessel X-Patchwork-Id: 1363200 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=windriver.com Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BqVvv3vRgz9sTN for ; Mon, 14 Sep 2020 12:40:27 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 140F78231E; Mon, 14 Sep 2020 04:39:47 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=windriver.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id 72196822FA; Mon, 14 Sep 2020 04:39:41 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail1.windriver.com (mail1.windriver.com [147.11.146.13]) (using TLSv1.1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 3829B821A4 for ; Mon, 14 Sep 2020 04:39:35 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=windriver.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=jwessel@windriver.com Received: from ALA-HCA.corp.ad.wrs.com (ala-hca.corp.ad.wrs.com [147.11.189.40]) by mail1.windriver.com (8.15.2/8.15.2) with ESMTPS id 08E2dU3I028725 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Sun, 13 Sep 2020 19:39:31 -0700 (PDT) Received: from ala-lpggp2.wrs.com (147.11.105.123) by ALA-HCA.corp.ad.wrs.com (147.11.189.50) with Microsoft SMTP Server id 14.3.487.0; Sun, 13 Sep 2020 19:39:22 -0700 Received: by ala-lpggp2.wrs.com (Postfix, from userid 5002) id C54C3D60EC8; Sun, 13 Sep 2020 19:39:22 -0700 (PDT) From: Jason Wessel To: CC: Subject: [PATCH v2 2/4] xhci.c: Add polling support for USB keyboards Date: Sun, 13 Sep 2020 19:39:19 -0700 Message-ID: <20200914023921.119630-3-jason.wessel@windriver.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200914023921.119630-1-jason.wessel@windriver.com> References: <20200914023921.119630-1-jason.wessel@windriver.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean The xhci driver was causing intermittent 5 second delays from the USB keyboard polling hook. Executing something like a "sleep 1" for example would sleep for 5 seconds, unless an event occurred on the USB bus to shorten the delay. Modeled after the code in the DWC2 driver, a nonblock state was added to quickly return instead of blocking for up to 5 seconds waiting for an event before timing out. Signed-off-by: Jason Wessel --- drivers/usb/host/xhci-ring.c | 26 +++++++++++++++++--------- drivers/usb/host/xhci.c | 11 ++++++----- include/usb/xhci.h | 5 +++-- 3 files changed, 26 insertions(+), 16 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 092ed6eaf1..607d4f715e 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -432,9 +432,11 @@ static int event_ready(struct xhci_ctrl *ctrl) * * @param ctrl Host controller data structure * @param expected TRB type expected from Event TRB + * @param nonblock when true do not block waiting for response * @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, + bool nonblock) { trb_type type; unsigned long ts = get_timer(0); @@ -442,8 +444,11 @@ union xhci_trb *xhci_wait_for_event(struct xhci_ctrl *ctrl, trb_type expected) do { union xhci_trb *event = ctrl->event_ring->dequeue; - if (!event_ready(ctrl)) + if (!event_ready(ctrl)) { + if (nonblock) + return NULL; continue; + } type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->event_cmd.flags)); if (type == expected) @@ -493,7 +498,7 @@ static void abort_td(struct usb_device *udev, int ep_index) xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_STOP_RING); - event = xhci_wait_for_event(ctrl, TRB_TRANSFER); + event = xhci_wait_for_event(ctrl, TRB_TRANSFER, false); field = le32_to_cpu(event->trans_event.flags); BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); @@ -501,7 +506,7 @@ 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, false); BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != udev->slot_id || GET_COMP_CODE(le32_to_cpu( event->event_cmd.status)) != COMP_SUCCESS); @@ -509,7 +514,7 @@ static void abort_td(struct usb_device *udev, int ep_index) xhci_queue_command(ctrl, (void *)((uintptr_t)ring->enqueue | ring->cycle_state), udev->slot_id, ep_index, TRB_SET_DEQ); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, false); BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != udev->slot_id || GET_COMP_CODE(le32_to_cpu( event->event_cmd.status)) != COMP_SUCCESS); @@ -552,10 +557,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 nonblock when true do not block waiting for response * @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, bool nonblock) { int num_trbs = 0; struct xhci_generic_trb *start_trb; @@ -714,8 +720,10 @@ int xhci_bulk_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, nonblock); if (!event) { + if (nonblock) + return -EINVAL; debug("XHCI bulk transfer timed out, aborting...\n"); abort_td(udev, ep_index); udev->status = USB_ST_NAK_REC; /* closest thing to a timeout */ @@ -911,7 +919,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, false); if (!event) goto abort; field = le32_to_cpu(event->trans_event.flags); @@ -929,7 +937,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, false); 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 9a31eba2bb..3a359f0adc 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -495,7 +495,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->bytes, 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, false); BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != udev->slot_id); @@ -692,7 +692,7 @@ retry: ctrl_ctx->drop_flags = 0; xhci_queue_command(ctrl, (void *)ctrl_ctx, slot_id, 0, TRB_ADDR_DEV); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, false); BUG_ON(TRB_TO_SLOT_ID(le32_to_cpu(event->event_cmd.flags)) != slot_id); switch (GET_COMP_CODE(le32_to_cpu(event->event_cmd.status))) { @@ -774,7 +774,7 @@ static int _xhci_alloc_device(struct usb_device *udev) } xhci_queue_command(ctrl, NULL, 0, 0, TRB_ENABLE_SLOT); - event = xhci_wait_for_event(ctrl, TRB_COMPLETION); + event = xhci_wait_for_event(ctrl, TRB_COMPLETION, false); BUG_ON(GET_COMP_CODE(le32_to_cpu(event->event_cmd.status)) != COMP_SUCCESS); @@ -1160,6 +1160,7 @@ unknown: * @param buffer buffer to be read/written based on the request * @param length length of the buffer * @param interval interval of the interrupt + * @param nonblock when true do not block waiting for response * @return 0 */ static int _xhci_submit_int_msg(struct usb_device *udev, unsigned long pipe, @@ -1177,7 +1178,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, nonblock); } /** @@ -1197,7 +1198,7 @@ static int _xhci_submit_bulk_msg(struct usb_device *udev, unsigned long pipe, return -EINVAL; } - return xhci_bulk_tx(udev, pipe, length, buffer); + return xhci_bulk_tx(udev, pipe, length, buffer, false); } /** diff --git a/include/usb/xhci.h b/include/usb/xhci.h index 7d34103fd5..73db77fc02 100644 --- a/include/usb/xhci.h +++ b/include/usb/xhci.h @@ -1249,9 +1249,10 @@ void xhci_setup_addressable_virt_dev(struct xhci_ctrl *ctrl, void xhci_queue_command(struct xhci_ctrl *ctrl, u8 *ptr, 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, + bool nonblock); int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer); + int length, void *buffer, bool nonblock); int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, struct devrequest *req, int length, void *buffer); int xhci_check_maxpacket(struct usb_device *udev); From patchwork Mon Sep 14 02:39:20 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wessel X-Patchwork-Id: 1363201 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=windriver.com Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BqVw16bLkz9sTN for ; Mon, 14 Sep 2020 12:40:33 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id F0D1C82329; Mon, 14 Sep 2020 04:39:47 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=windriver.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id C1699821A4; Mon, 14 Sep 2020 04:39:42 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail1.windriver.com (mail1.windriver.com [147.11.146.13]) (using TLSv1.1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id CA426821D8 for ; Mon, 14 Sep 2020 04:39:37 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=windriver.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=jwessel@windriver.com Received: from ALA-HCA.corp.ad.wrs.com (ala-hca.corp.ad.wrs.com [147.11.189.40]) by mail1.windriver.com (8.15.2/8.15.2) with ESMTPS id 08E2dU3F028725 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Sun, 13 Sep 2020 19:39:30 -0700 (PDT) Received: from ala-lpggp2.wrs.com (147.11.105.123) by ALA-HCA.corp.ad.wrs.com (147.11.189.50) with Microsoft SMTP Server id 14.3.487.0; Sun, 13 Sep 2020 19:39:22 -0700 Received: by ala-lpggp2.wrs.com (Postfix, from userid 5002) id C627ED60ECB; Sun, 13 Sep 2020 19:39:22 -0700 (PDT) From: Jason Wessel To: CC: Subject: [PATCH v2 3/4] xhci-ring.c: Add poll pending state to properly abort transactions Date: Sun, 13 Sep 2020 19:39:20 -0700 Message-ID: <20200914023921.119630-4-jason.wessel@windriver.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200914023921.119630-1-jason.wessel@windriver.com> References: <20200914023921.119630-1-jason.wessel@windriver.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean Both xhci_ctrl_tx() and xhci_bulk_tx() can be called synchronously by other drivers such as the usb storage or network, while the keyboard driver exclusively uses the polling mode. The reason the abort needs to happen is for the case when a keyboard poll was issue but there was no response packet. If another driver such as the usb mass storage is called, it could receive the response from the keyboard because only a single TRB queue is used. Any pending polling transactions must be aborted before switching modes to avoid corrupting the state of the controller and the driver which expects a series of commands and responses from a specific device. Signed-off-by: Jason Wessel --- drivers/usb/host/xhci-ring.c | 80 ++++++++++++++++++++++++++++-------- include/usb/xhci.h | 5 +++ 2 files changed, 69 insertions(+), 16 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 607d4f715e..00a0491771 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -549,19 +549,8 @@ static void record_transfer_result(struct usb_device *udev, } } -/**** Bulk and Control transfer methods ****/ -/** - * Queues up the BULK Request - * - * @param udev pointer to the USB device structure - * @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 nonblock when true do not block waiting for response - * @return returns 0 if successful else -1 on failure - */ -int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, - int length, void *buffer, bool nonblock) +static int _xhci_bulk_tx_queue(struct usb_device *udev, unsigned long pipe, + int length, void *buffer) { int num_trbs = 0; struct xhci_generic_trb *start_trb; @@ -575,7 +564,6 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, struct xhci_virt_device *virt_dev; struct xhci_ep_ctx *ep_ctx; struct xhci_ring *ring; /* EP transfer ring */ - union xhci_trb *event; int running_total, trb_buff_len; unsigned int total_packet_count; @@ -719,20 +707,73 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, } while (running_total < length); giveback_first_trb(udev, ep_index, start_cycle, start_trb); + return 0; +} + +/**** Bulk and Control transfer methods ****/ +/** + * Queues up the BULK Request + * + * @param udev pointer to the USB device structure + * @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 nonblock when true do not block waiting for response + * @return returns 0 if successful else -1 on failure + */ +int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, + int length, void *buffer, bool nonblock) +{ + u32 field; + int ret; + union xhci_trb *event; + struct xhci_ctrl *ctrl = xhci_get_ctrl(udev); + int ep_index = usb_pipe_ep_index(pipe); + if (ctrl->poll_pend) { + /* + * Abort a pending poll operation if it should have + * timed out, or if this is a different buffer from a + * separate request + */ + if (get_timer(ctrl->bulk_tx_poll_ts) > XHCI_TIMEOUT || + ctrl->last_bulk_tx_buf != buffer || ctrl->poll_last_udev != udev || + ep_index != ctrl->poll_last_ep_index) { + abort_td(ctrl->poll_last_udev, ctrl->poll_last_ep_index); + ctrl->poll_last_udev->status = USB_ST_NAK_REC; /* closest thing to a timeout */ + ctrl->poll_last_udev->act_len = 0; + ctrl->poll_pend = false; + } + } /* No else here because poll_pend might have changed above */ + if (!ctrl->poll_pend) { + ctrl->last_bulk_tx_buf = buffer; + ret = _xhci_bulk_tx_queue(udev, pipe, length, buffer); + if (ret) + return ret; + } event = xhci_wait_for_event(ctrl, TRB_TRANSFER, nonblock); if (!event) { - if (nonblock) + if (nonblock) { + if (!ctrl->poll_pend) { + /* Start the timer */ + ctrl->bulk_tx_poll_ts = get_timer(0); + ctrl->poll_last_udev = udev; + ctrl->poll_last_ep_index = ep_index; + ctrl->poll_pend = true; + } return -EINVAL; + } debug("XHCI bulk transfer timed out, aborting...\n"); abort_td(udev, ep_index); udev->status = USB_ST_NAK_REC; /* closest thing to a timeout */ udev->act_len = 0; + ctrl->poll_pend = false; return -ETIMEDOUT; } + ctrl->poll_pend = false; field = le32_to_cpu(event->trans_event.flags); - BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); + BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); BUG_ON(*(void **)(uintptr_t)le64_to_cpu(event->trans_event.buffer) - buffer > (size_t)length); @@ -779,6 +820,13 @@ int xhci_ctrl_tx(struct usb_device *udev, unsigned long pipe, le16_to_cpu(req->value), le16_to_cpu(req->value), le16_to_cpu(req->index)); + if (ctrl->poll_pend) { + abort_td(ctrl->poll_last_udev, ctrl->poll_last_ep_index); + ctrl->poll_last_udev->status = USB_ST_NAK_REC; /* closest thing to a timeout */ + ctrl->poll_last_udev->act_len = 0; + ctrl->poll_pend = false; + } + ep_index = usb_pipe_ep_index(pipe); ep_ring = virt_dev->eps[ep_index].ring; diff --git a/include/usb/xhci.h b/include/usb/xhci.h index 73db77fc02..72082b3775 100644 --- a/include/usb/xhci.h +++ b/include/usb/xhci.h @@ -1227,6 +1227,11 @@ struct xhci_ctrl { struct xhci_scratchpad *scratchpad; struct xhci_virt_device *devs[MAX_HC_SLOTS]; int rootdev; + bool poll_pend; /* Pending state for polling for an event for a udev */ + unsigned long bulk_tx_poll_ts; + void *last_bulk_tx_buf; + struct usb_device *poll_last_udev; + int poll_last_ep_index; }; unsigned long trb_addr(struct xhci_segment *seg, union xhci_trb *trb); From patchwork Mon Sep 14 02:39:21 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Wessel X-Patchwork-Id: 1363198 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=windriver.com Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BqVvK6FM9z9sTN for ; Mon, 14 Sep 2020 12:39:57 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 704BB821A4; Mon, 14 Sep 2020 04:39:44 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=windriver.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Received: by phobos.denx.de (Postfix, from userid 109) id F3D7F822D2; Mon, 14 Sep 2020 04:39:39 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,SPF_HELO_NONE, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mail1.windriver.com (mail1.windriver.com [147.11.146.13]) (using TLSv1.1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id BF91981B88 for ; Mon, 14 Sep 2020 04:39:34 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=windriver.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=jwessel@windriver.com Received: from ALA-HCA.corp.ad.wrs.com (ala-hca.corp.ad.wrs.com [147.11.189.40]) by mail1.windriver.com (8.15.2/8.15.2) with ESMTPS id 08E2dU3H028725 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL); Sun, 13 Sep 2020 19:39:31 -0700 (PDT) Received: from ala-lpggp2.wrs.com (147.11.105.123) by ALA-HCA.corp.ad.wrs.com (147.11.189.50) with Microsoft SMTP Server id 14.3.487.0; Sun, 13 Sep 2020 19:39:22 -0700 Received: by ala-lpggp2.wrs.com (Postfix, from userid 5002) id CAA4ED60ECE; Sun, 13 Sep 2020 19:39:22 -0700 (PDT) From: Jason Wessel To: CC: Subject: [PATCH v2 4/4] xhci-ring.c: Fix crash when issuing "usb reset" Date: Sun, 13 Sep 2020 19:39:21 -0700 Message-ID: <20200914023921.119630-5-jason.wessel@windriver.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200914023921.119630-1-jason.wessel@windriver.com> References: <20200914023921.119630-1-jason.wessel@windriver.com> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean When TRB_TRANSFER is set for a call to xhci_wait_for_event, it can return null, which causes u-boot to crash. This is an intermittent problem found during "usb reset" testing. If the null return occurs it means there was a timeout, and the abort_td() should return immediately vs crashing u-boot from a null dereference. Signed-off-by: Jason Wessel --- drivers/usb/host/xhci-ring.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 00a0491771..bbb4410908 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -499,11 +499,16 @@ static void abort_td(struct usb_device *udev, int ep_index) xhci_queue_command(ctrl, NULL, udev->slot_id, ep_index, TRB_STOP_RING); event = xhci_wait_for_event(ctrl, TRB_TRANSFER, false); - field = le32_to_cpu(event->trans_event.flags); - BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); - BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - BUG_ON(GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len - != COMP_STOP))); + if (event) { + field = le32_to_cpu(event->trans_event.flags); + BUG_ON(TRB_TO_SLOT_ID(field) != udev->slot_id); + BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); + BUG_ON(GET_COMP_CODE(le32_to_cpu(event->trans_event.transfer_len + != COMP_STOP))); + } else { + debug("XHCI abort timeout\n"); + return; + } xhci_acknowledge_event(ctrl); event = xhci_wait_for_event(ctrl, TRB_COMPLETION, false);