From patchwork Wed Nov 18 03:54:40 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ran Wang X-Patchwork-Id: 1401939 X-Patchwork-Delegate: marek.vasut@gmail.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=fail (p=none dis=none) header.from=nxp.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 4CbTJL67Xbz9s1l for ; Wed, 18 Nov 2020 14:46:42 +1100 (AEDT) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 3D54F8254F; Wed, 18 Nov 2020 04:46:17 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=fail (p=none dis=none) header.from=nxp.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 AD37E82304; Wed, 18 Nov 2020 04:46:15 +0100 (CET) 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 inva021.nxp.com (inva021.nxp.com [92.121.34.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id B9DFF82304 for ; Wed, 18 Nov 2020 04:46:12 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=nxp.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ran.wang_1@nxp.com Received: from inva021.nxp.com (localhost [127.0.0.1]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 3222020010B; Wed, 18 Nov 2020 04:46:12 +0100 (CET) Received: from invc005.ap-rdc01.nxp.com (invc005.ap-rdc01.nxp.com [165.114.16.14]) by inva021.eu-rdc02.nxp.com (Postfix) with ESMTP id 0F8832000DF; Wed, 18 Nov 2020 04:46:10 +0100 (CET) Received: from localhost.localdomain (mega.ap.freescale.net [10.192.208.232]) by invc005.ap-rdc01.nxp.com (Postfix) with ESMTP id 372E84027E; Wed, 18 Nov 2020 04:46:07 +0100 (CET) From: Ran Wang To: Bin Meng , Marek Vasut Cc: u-boot@lists.denx.de, Ran Wang Subject: [RESEND PATCH v3] usb: xhci: fix lack of short packet event trb handling Date: Wed, 18 Nov 2020 11:54:40 +0800 Message-Id: <20201118035440.26341-1-ran.wang_1@nxp.com> X-Mailer: git-send-email 2.17.1 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 For bulk IN transfer, the codes will set ISP flag to request event TRB being generated by xHC for case of short packet. So for the case of buffer-cross-64K-boundary (which we will divide payload and enqueuqe more than 1 transfer TRB), if the first TRB ends up with a short packet condition it will trigger an short packet code transfer event per that flag and cause more than 1 event TRB generated for this transfer. However, current codes will only handle the first transfer event TRB then mark current transfer completed, causing next transfer failure due to event TRB mis-match. Such issue has been observed on some Layerscape platforms (LS1028A, LS1088A, etc) with USB ethernet device. This patch adds a loop to make sure the event TRB for last transfer TRB has been handled in time. Signed-off-by: Ran Wang Reviewed-by: Bin Meng --- Change in v3: - Update commit message according to v2 feedback . - Replace (void *) with (uintptr_t) to fix below armv7 compile warning: ... drivers/usb/host/xhci-ring.c: In function 'xhci_bulk_tx': drivers/usb/host/xhci-ring.c:726:6: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast] 726 | if ((void *)le64_to_cpu(event->trans_event.buffer) != last_transfer_trb_addr) { | ^ ... Change in v2: - Re-write commit message to describe context more clearly. - Add prefix 'le64_to_cpu' for 'event->trans_event.buffer'. drivers/usb/host/xhci-ring.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 13065d7..d708fc9 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -580,10 +580,13 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, int ret; u32 trb_fields[4]; u64 val_64 = virt_to_phys(buffer); + void *last_transfer_trb_addr; + int available_length; debug("dev=%p, pipe=%lx, buffer=%p, length=%d\n", udev, pipe, buffer, length); + available_length = length; ep_index = usb_pipe_ep_index(pipe); virt_dev = ctrl->devs[slot_id]; @@ -697,7 +700,7 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, trb_fields[2] = length_field; trb_fields[3] = field | TRB_TYPE(TRB_NORMAL); - queue_trb(ctrl, ring, (num_trbs > 1), trb_fields); + last_transfer_trb_addr = queue_trb(ctrl, ring, (num_trbs > 1), trb_fields); --num_trbs; @@ -710,6 +713,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); if (!event) { debug("XHCI bulk transfer timed out, aborting...\n"); @@ -718,12 +722,20 @@ int xhci_bulk_tx(struct usb_device *udev, unsigned long pipe, udev->act_len = 0; return -ETIMEDOUT; } - field = le32_to_cpu(event->trans_event.flags); + if ((uintptr_t)(le64_to_cpu(event->trans_event.buffer)) + != (uintptr_t)last_transfer_trb_addr) { + available_length -= + (int)EVENT_TRB_LEN(le32_to_cpu(event->trans_event.transfer_len)); + xhci_acknowledge_event(ctrl); + goto again; + } + + field = le32_to_cpu(event->trans_event.flags); BUG_ON(TRB_TO_SLOT_ID(field) != slot_id); BUG_ON(TRB_TO_EP_INDEX(field) != ep_index); - record_transfer_result(udev, event, length); + record_transfer_result(udev, event, available_length); xhci_acknowledge_event(ctrl); xhci_inval_cache((uintptr_t)buffer, length);