From patchwork Thu Aug 6 00:44:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 258934 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 747FAC433E0 for ; Thu, 6 Aug 2020 00:45:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 4D6AC20842 for ; Thu, 6 Aug 2020 00:45:07 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=synopsys.com header.i=@synopsys.com header.b="KY/9AR0h" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725779AbgHFApC (ORCPT ); Wed, 5 Aug 2020 20:45:02 -0400 Received: from smtprelay-out1.synopsys.com ([149.117.87.133]:59032 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726197AbgHFAox (ORCPT ); Wed, 5 Aug 2020 20:44:53 -0400 Received: from mailhost.synopsys.com (sv2-mailhost2.synopsys.com [10.205.2.134]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id 7D0FFC0BBD; Thu, 6 Aug 2020 00:44:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1596674692; bh=j3TZyohjlu7miEdDkUqXhS4KlhSz5WBxeTsWisi04to=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=KY/9AR0h7v1W65PhPPWjYhm6nkdwd7iJInPQ4JIydV36KXK/ojBG1s+ZkOYhJTZlL YJ+LvIxxTLmXHYu/kFdRboY7rFRF9km2zQwWyAmcRfROX7wE1il8Y2en/xKUaAeaZp pw+s2QYGLAtQO5kU4c/JPgrpgQ1pA+qZsmUNM+NoV3j6aBIvxeDN5t8NYfbRegiwpH sY3IMKlDcRF4UIDNH8EBjx9EHE7yqiMrH48Rszjg7yX7wzAa3gaEsInwtLjYE5UHcc TpVdhafKRL+j8c3XIuTe2ZTlHB+A1lo7t1HRkI79aKjV9G1sMzDCje2xEe+fEF71w5 kOVqnVkg6+nug== Received: from te-lab16 (nanobot.internal.synopsys.com [10.10.186.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mailhost.synopsys.com (Postfix) with ESMTPSA id 1485EA0096; Thu, 6 Aug 2020 00:44:50 +0000 (UTC) Received: by te-lab16 (sSMTP sendmail emulation); Wed, 05 Aug 2020 17:44:50 -0700 Date: Wed, 05 Aug 2020 17:44:50 -0700 Message-Id: In-Reply-To: References: X-SNPS-Relay: synopsys.com From: Thinh Nguyen Subject: [PATCH 1/7] usb: dwc3: gadget: Don't setup more than requested To: Felipe Balbi , Greg Kroah-Hartman , Thinh Nguyen , linux-usb@vger.kernel.org Cc: John Youn , stable@vger.kernel.org Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org The SG list may be set up with entry size more than the requested length. Check the usb_request->length and make sure that we don't setup the TRBs to send/receive more than requested. This case may occur when the SG entry is allocated up to a certain minimum size, but the request length is less than that. It can also occur when the request is reused for a different request length. Cc: stable@vger.kernel.org Fixes: a31e63b608ff ("usb: dwc3: gadget: Correct handling of scattergather lists") Signed-off-by: Thinh Nguyen --- drivers/usb/dwc3/gadget.c | 41 ++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index e44bfc3b5096..657616077502 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1054,27 +1054,25 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, * dwc3_prepare_one_trb - setup one TRB from one request * @dep: endpoint for which this request is prepared * @req: dwc3_request pointer + * @trb_length: buffer size of the TRB * @chain: should this TRB be chained to the next? * @node: only for isochronous endpoints. First TRB needs different type. */ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, - struct dwc3_request *req, unsigned chain, unsigned node) + struct dwc3_request *req, unsigned int trb_length, + unsigned chain, unsigned node) { struct dwc3_trb *trb; - unsigned int length; dma_addr_t dma; unsigned stream_id = req->request.stream_id; unsigned short_not_ok = req->request.short_not_ok; unsigned no_interrupt = req->request.no_interrupt; unsigned is_last = req->request.is_last; - if (req->request.num_sgs > 0) { - length = sg_dma_len(req->start_sg); + if (req->request.num_sgs > 0) dma = sg_dma_address(req->start_sg); - } else { - length = req->request.length; + else dma = req->request.dma; - } trb = &dep->trb_pool[dep->trb_enqueue]; @@ -1086,7 +1084,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, req->num_trbs++; - __dwc3_prepare_one_trb(dep, trb, dma, length, chain, node, + __dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node, stream_id, short_not_ok, no_interrupt, is_last); } @@ -1104,8 +1102,13 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, unsigned int length = req->request.length; unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); unsigned int rem = length % maxp; + unsigned int trb_length; unsigned chain = true; + trb_length = min_t(unsigned int, length, sg_dma_len(req->start_sg)); + + length -= trb_length; + /* * IOMMU driver is coalescing the list of sgs which shares a * page boundary into one and giving it to USB driver. With @@ -1113,7 +1116,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, * sgs passed. So mark the chain bit to false if it isthe last * mapped sg. */ - if (i == remaining - 1) + if ((i == remaining - 1) || !length) chain = false; if (rem && usb_endpoint_dir_out(dep->endpoint.desc) && !chain) { @@ -1123,7 +1126,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, req->needs_extra_trb = true; /* prepare normal TRB */ - dwc3_prepare_one_trb(dep, req, true, i); + dwc3_prepare_one_trb(dep, req, trb_length, true, i); /* Now prepare one extra TRB to align transfer size */ trb = &dep->trb_pool[dep->trb_enqueue]; @@ -1135,7 +1138,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, req->request.no_interrupt, req->request.is_last); } else { - dwc3_prepare_one_trb(dep, req, chain, i); + dwc3_prepare_one_trb(dep, req, trb_length, chain, i); } /* @@ -1150,6 +1153,16 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, req->num_queued_sgs++; + /* + * The number of pending SG entries may not correspond to the + * number of mapped SG entries. If all the data are queued, then + * don't include unused SG entries. + */ + if (length == 0) { + req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs; + break; + } + if (!dwc3_calc_trbs_left(dep)) break; } @@ -1169,7 +1182,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, req->needs_extra_trb = true; /* prepare normal TRB */ - dwc3_prepare_one_trb(dep, req, true, 0); + dwc3_prepare_one_trb(dep, req, length, true, 0); /* Now prepare one extra TRB to align transfer size */ trb = &dep->trb_pool[dep->trb_enqueue]; @@ -1187,7 +1200,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, req->needs_extra_trb = true; /* prepare normal TRB */ - dwc3_prepare_one_trb(dep, req, true, 0); + dwc3_prepare_one_trb(dep, req, length, true, 0); /* Now prepare one extra TRB to handle ZLP */ trb = &dep->trb_pool[dep->trb_enqueue]; @@ -1198,7 +1211,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, req->request.no_interrupt, req->request.is_last); } else { - dwc3_prepare_one_trb(dep, req, false, 0); + dwc3_prepare_one_trb(dep, req, length, false, 0); } } From patchwork Thu Aug 6 00:45:04 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 258933 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id E7042C433DF for ; Thu, 6 Aug 2020 00:45:14 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id C88752245C for ; Thu, 6 Aug 2020 00:45:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=synopsys.com header.i=@synopsys.com header.b="NT0d+H0v" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726802AbgHFApK (ORCPT ); Wed, 5 Aug 2020 20:45:10 -0400 Received: from smtprelay-out1.synopsys.com ([149.117.87.133]:59060 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726197AbgHFApF (ORCPT ); Wed, 5 Aug 2020 20:45:05 -0400 Received: from mailhost.synopsys.com (sv1-mailhost2.synopsys.com [10.205.2.132]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id 678A2C0BBF; Thu, 6 Aug 2020 00:45:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1596674705; bh=B2CaqTmgxgBVYNUsPl20YT5gQjJwQfyPhgyZTb3xa4E=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=NT0d+H0vHk5JnEzLXSVOFEVciIyZm3PurWEKZuLnV5hERyB3MEG3qj8N9VPgPVvAL ew4N6SfByYGF2iiShN+FMW2Gh+qgz+WirmGysBjU3wSZLZTX9SA7eoGhN/vmc+omA+ gKF/7vMkAvlstufrEqVzHyaEQALu7RYRsq3HSgPHdCWzTJQ+Y0qTRKQ8hVHRryixcG 1BmKeqeOgeKaI60J1naoz/+i/L7hU0BYLgyFq1VtjFJR/eQYT+7pcfm7KuwXFOjsf/ AdKVczhHKcbHeKoi2301LXM9T5DrleretQde53sbn+UBZdklryeDsHC1J9oEWGG5an uPGlFwxM4DxAg== Received: from te-lab16 (nanobot.internal.synopsys.com [10.10.186.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mailhost.synopsys.com (Postfix) with ESMTPSA id 372C2A0070; Thu, 6 Aug 2020 00:45:04 +0000 (UTC) Received: by te-lab16 (sSMTP sendmail emulation); Wed, 05 Aug 2020 17:45:04 -0700 Date: Wed, 05 Aug 2020 17:45:04 -0700 Message-Id: In-Reply-To: References: X-SNPS-Relay: synopsys.com From: Thinh Nguyen Subject: [PATCH 3/7] usb: dwc3: gadget: Handle ZLP for sg requests To: Felipe Balbi , Greg Kroah-Hartman , Thinh Nguyen , linux-usb@vger.kernel.org Cc: John Youn , stable@vger.kernel.org Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org Currently dwc3 doesn't handle usb_request->zero for SG requests. This change checks and prepares extra TRBs for the ZLP for SG requests. Cc: stable@vger.kernel.org Fixes: 04c03d10e507 ("usb: dwc3: gadget: handle request->zero") Signed-off-by: Thinh Nguyen --- drivers/usb/dwc3/gadget.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c0175dff194e..ced229aeccec 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1137,6 +1137,37 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, req->request.short_not_ok, req->request.no_interrupt, req->request.is_last); + } else if (req->request.zero && req->request.length && + !usb_endpoint_xfer_isoc(dep->endpoint.desc) && + !rem && !chain) { + struct dwc3 *dwc = dep->dwc; + struct dwc3_trb *trb; + + req->needs_extra_trb = true; + + /* Prepare normal TRB */ + dwc3_prepare_one_trb(dep, req, trb_length, true, i); + + /* Prepare one extra TRB to handle ZLP */ + trb = &dep->trb_pool[dep->trb_enqueue]; + req->num_trbs++; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, + !req->direction, 1, + req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt, + req->request.is_last); + + /* Prepare one more TRB to handle MPS alignment */ + if (!req->direction) { + trb = &dep->trb_pool[dep->trb_enqueue]; + req->num_trbs++; + __dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp, + false, 1, req->request.stream_id, + req->request.short_not_ok, + req->request.no_interrupt, + req->request.is_last); + } } else { dwc3_prepare_one_trb(dep, req, trb_length, chain, i); } From patchwork Thu Aug 6 00:45:16 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 258932 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 241F7C433E0 for ; Thu, 6 Aug 2020 00:45:31 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 045DC2065C for ; Thu, 6 Aug 2020 00:45:31 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=synopsys.com header.i=@synopsys.com header.b="XblceBsp" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726861AbgHFAp2 (ORCPT ); Wed, 5 Aug 2020 20:45:28 -0400 Received: from smtprelay-out1.synopsys.com ([149.117.87.133]:59068 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726851AbgHFApS (ORCPT ); Wed, 5 Aug 2020 20:45:18 -0400 Received: from mailhost.synopsys.com (sv2-mailhost1.synopsys.com [10.205.2.133]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id 93CB8C0BBC; Thu, 6 Aug 2020 00:45:17 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1596674717; bh=46iK6WNvgPP2R0Yvw6Zt6WK86o714OjwPjmekHO1DkQ=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=XblceBspz5uz/2a1clheql/HWM3Hn9PKmG2QSWRNKgiseW7gI3afh+LgHEek9FYZO pCmdTrf+DwMQp5o/EcpGcfXkQaXVczyeHz5UKu02o3OVKkUPGtn1Su7CqANit3dZMX VV72gA0IfKTr8QvR+D/hhuIRwucOqnmlKh2AyQWnFQghy4x+iMCEG6hcLehIK/pSdC crWm6UBZx5S+YSgz7ZlhiQDoDJHYjMWJmiXMOciMLwxOQF3VqXIkuG1LptN8AFwilf d8O9r1Q8MMmiWhhd5rLh10pENeac4uyCyGsvxym4/uiyqRkJNFGO/5UlIORGrXmALW Jm73rjUIWFx6A== Received: from te-lab16 (nanobot.internal.synopsys.com [10.10.186.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mailhost.synopsys.com (Postfix) with ESMTPSA id 64179A0096; Thu, 6 Aug 2020 00:45:16 +0000 (UTC) Received: by te-lab16 (sSMTP sendmail emulation); Wed, 05 Aug 2020 17:45:16 -0700 Date: Wed, 05 Aug 2020 17:45:16 -0700 Message-Id: In-Reply-To: References: X-SNPS-Relay: synopsys.com From: Thinh Nguyen Subject: [PATCH 5/7] usb: dwc3: gadget: Account for extra TRB To: Felipe Balbi , Greg Kroah-Hartman , Thinh Nguyen , linux-usb@vger.kernel.org Cc: John Youn Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org When checking for how many TRB remaining, make sure to account for extra TRBs for ZLP or MPS alignment transfers. Since the dwc3_prepare_trb* functions should know if we need the extra TRBs, make those functions return a status code -EAGAIN if there isn't enough TRB. Check against those status when preparing TRB instead. Fixes: c6267a51639b ("usb: dwc3: gadget: align transfers to wMaxPacketSize") Signed-off-by: Thinh Nguyen --- drivers/usb/dwc3/gadget.c | 79 ++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index dcadef105c2a..64c2ebacc73c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1057,8 +1057,10 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, * @trb_length: buffer size of the TRB * @chain: should this TRB be chained to the next? * @node: only for isochronous endpoints. First TRB needs different type. + * + * Return 0 on success or -EAGAIN if there is not enough TRBs. */ -static void dwc3_prepare_one_trb(struct dwc3_ep *dep, +static int dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_request *req, unsigned int trb_length, unsigned chain, unsigned node) { @@ -1069,6 +1071,9 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, unsigned no_interrupt = req->request.no_interrupt; unsigned is_last = req->request.is_last; + if (!dwc3_calc_trbs_left(dep)) + return -EAGAIN; + if (req->request.num_sgs > 0) dma = sg_dma_address(req->start_sg); else @@ -1086,6 +1091,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, __dwc3_prepare_one_trb(dep, trb, dma, trb_length, chain, node, stream_id, short_not_ok, no_interrupt, is_last); + + return 0; } /** @@ -1094,11 +1101,13 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, * @req: The request to prepare * @entry_length: The last SG entry size * @node: Indicates whether this is not the first entry (for isoc only) + * + * Returns 0 on success or -EAGAIN if there is not enough TRBs. */ -static void dwc3_prepare_last_sg(struct dwc3_ep *dep, - struct dwc3_request *req, - unsigned int entry_length, - unsigned int node) +static int dwc3_prepare_last_sg(struct dwc3_ep *dep, + struct dwc3_request *req, + unsigned int entry_length, + unsigned int node) { unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc); unsigned int rem = req->request.length % maxp; @@ -1118,6 +1127,9 @@ static void dwc3_prepare_last_sg(struct dwc3_ep *dep, if (num_extra_trbs > 0) req->needs_extra_trb = true; + if (dwc3_calc_trbs_left(dep) < num_extra_trbs + 1) + return -EAGAIN; + /* Prepare a normal TRB */ dwc3_prepare_one_trb(dep, req, entry_length, req->needs_extra_trb, node); @@ -1145,9 +1157,11 @@ static void dwc3_prepare_last_sg(struct dwc3_ep *dep, req->request.no_interrupt, req->request.is_last); } + + return 0; } -static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, +static int dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, struct dwc3_request *req) { struct scatterlist *sg = req->start_sg; @@ -1163,6 +1177,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, unsigned int rem = length % maxp; unsigned int trb_length; bool last_sg = false; + int ret = 0; trb_length = min_t(unsigned int, length, sg_dma_len(req->start_sg)); @@ -1179,9 +1194,13 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, last_sg = true; if (last_sg) - dwc3_prepare_last_sg(dep, req, trb_length, i); + ret = dwc3_prepare_last_sg(dep, req, trb_length, i); else - dwc3_prepare_one_trb(dep, req, trb_length, 1, i); + ret = dwc3_prepare_one_trb(dep, req, trb_length, 1, i); + + /* Ran out of TRBs */ + if (ret) + return ret; /* * There can be a situation where all sgs in sglist are not @@ -1204,16 +1223,14 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep, req->num_pending_sgs -= req->request.num_mapped_sgs - req->num_queued_sgs; break; } - - if (!dwc3_calc_trbs_left(dep)) - break; } + return 0; } -static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, +static int dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, struct dwc3_request *req) { - dwc3_prepare_last_sg(dep, req, req->request.length, 0); + return dwc3_prepare_last_sg(dep, req, req->request.length, 0); } /* @@ -1224,9 +1241,10 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep, * transfers. The function returns once there are no more TRBs available or * it runs out of requests. */ -static void dwc3_prepare_trbs(struct dwc3_ep *dep) +static int dwc3_prepare_trbs(struct dwc3_ep *dep) { struct dwc3_request *req, *n; + int ret = 0; BUILD_BUG_ON_NOT_POWER_OF_2(DWC3_TRB_NUM); @@ -1241,11 +1259,11 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) * break things. */ list_for_each_entry(req, &dep->started_list, list) { - if (req->num_pending_sgs > 0) - dwc3_prepare_one_trb_sg(dep, req); - - if (!dwc3_calc_trbs_left(dep)) - return; + if (req->num_pending_sgs > 0) { + ret = dwc3_prepare_one_trb_sg(dep, req); + if (ret) + return ret; + } /* * Don't prepare beyond a transfer. In DWC_usb32, its transfer @@ -1253,17 +1271,16 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) * active transfer instead of stopping. */ if (dep->stream_capable && req->request.is_last) - return; + return 0; } list_for_each_entry_safe(req, n, &dep->pending_list, list) { struct dwc3 *dwc = dep->dwc; - int ret; ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, dep->direction); if (ret) - return; + return ret; req->sg = req->request.sg; req->start_sg = req->sg; @@ -1271,12 +1288,12 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) req->num_pending_sgs = req->request.num_mapped_sgs; if (req->num_pending_sgs > 0) - dwc3_prepare_one_trb_sg(dep, req); + ret = dwc3_prepare_one_trb_sg(dep, req); else - dwc3_prepare_one_trb_linear(dep, req); + ret = dwc3_prepare_one_trb_linear(dep, req); - if (!dwc3_calc_trbs_left(dep)) - return; + if (ret) + return ret; /* * Don't prepare beyond a transfer. In DWC_usb32, its transfer @@ -1284,7 +1301,7 @@ static void dwc3_prepare_trbs(struct dwc3_ep *dep) * active transfer instead of stopping. */ if (dep->stream_capable && req->request.is_last) - return; + return 0; } } @@ -1298,12 +1315,12 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) int ret; u32 cmd; - if (!dwc3_calc_trbs_left(dep)) - return 0; - starting = !(dep->flags & DWC3_EP_TRANSFER_STARTED); - dwc3_prepare_trbs(dep); + ret = dwc3_prepare_trbs(dep); + if (ret) + return 0; + req = next_request(&dep->started_list); if (!req) { dep->flags |= DWC3_EP_PENDING_REQUEST; From patchwork Thu Aug 6 00:45:28 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thinh Nguyen X-Patchwork-Id: 258931 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-10.1 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH, MAILING_LIST_MULTI, SIGNED_OFF_BY, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C2C3BC433E0 for ; Thu, 6 Aug 2020 00:45:33 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A356D2245C for ; Thu, 6 Aug 2020 00:45:33 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=synopsys.com header.i=@synopsys.com header.b="IC51MT/z" Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726869AbgHFApb (ORCPT ); Wed, 5 Aug 2020 20:45:31 -0400 Received: from smtprelay-out1.synopsys.com ([149.117.73.133]:35942 "EHLO smtprelay-out1.synopsys.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726862AbgHFApa (ORCPT ); Wed, 5 Aug 2020 20:45:30 -0400 Received: from mailhost.synopsys.com (sv2-mailhost2.synopsys.com [10.205.2.134]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by smtprelay-out1.synopsys.com (Postfix) with ESMTPS id A377B407DB; Thu, 6 Aug 2020 00:45:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synopsys.com; s=mail; t=1596674729; bh=DlxA/Yuqr9J090SCVcL5aYY9XswWfbhtbnDRyo2GcE8=; h=Date:In-Reply-To:References:From:Subject:To:Cc:From; b=IC51MT/zDYOWckYQXCAbC50gPvuT1ciqkk8CP/EKfLaYYwaj2HvpBYLpiyXKoJf/V y9HzZIwp69dnkMPmqXTJDGD4Pt/PcS8XN6oZbmET2TBlippbwF4xIEG9OAxZd2KpDq o6fkBZH3NOTnqLwKcEKXKymArWMOSwTJTqjSydWxAKBewzxoVOvAW+Uhfjl9v4Fhbj pRS66mEji12xxAwLvL/aGMdKfeZmoY7jf/di9T/dFIdfGsAlkacjMft8KGn7LKVOiH 98fvh1gYWJcrBrhQ1r45MIaaIfvoaRWtbk5aEKX5gPU2C/C97cxrtbGVA12j80oash XCfs8OiK6E5lw== Received: from te-lab16 (nanobot.internal.synopsys.com [10.10.186.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mailhost.synopsys.com (Postfix) with ESMTPSA id 8D556A0096; Thu, 6 Aug 2020 00:45:28 +0000 (UTC) Received: by te-lab16 (sSMTP sendmail emulation); Wed, 05 Aug 2020 17:45:28 -0700 Date: Wed, 05 Aug 2020 17:45:28 -0700 Message-Id: <34883d133c8645bb258025aa170ddd5e01fdc0d9.1596674378.git.thinhn@synopsys.com> In-Reply-To: References: X-SNPS-Relay: synopsys.com From: Thinh Nguyen Subject: [PATCH 7/7] usb: dwc3: ep0: Skip ZLP setup for OUT To: Felipe Balbi , Greg Kroah-Hartman , Thinh Nguyen , linux-usb@vger.kernel.org Cc: John Youn Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org The current implementation for ZLP handling of usb_request->zero for ep0 is only for control IN requests. For OUT direction, DWC3 needs to check and set up for MPS boundary alignment, and it doesn't do that at the moment. Usually, control OUT requests can indicate its transfer size via the wLength field of the control message. So usb_request->zero is usually not needed for OUT direction. To handle ZLP OUT for control endpoint, we'd need to allocate at least 3 TRBs for control requests (we have 2 at the moment). For now, let's just make sure the current ZLP setup is only for IN direction. Signed-off-by: Thinh Nguyen --- drivers/usb/dwc3/ep0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 59f2e8c31bd1..ade9503cf876 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -979,7 +979,7 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, false); ret = dwc3_ep0_start_trans(dep); } else if (IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) && - req->request.length && req->request.zero) { + req->request.length && req->request.zero && req->direction) { ret = usb_gadget_map_request_by_dev(dwc->sysdev, &req->request, dep->number);