Received: by 2002:a05:6a10:9e8c:0:0:0:0 with SMTP id y12csp349660pxx; Wed, 28 Oct 2020 06:28:16 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxWKBzu7LuOsOnAOR7GgJKa+7QlCPRpaXjfFG/YhNb0gy0BKgDfxO35oUXmvwXUK1GsLl8W X-Received: by 2002:a50:ef0e:: with SMTP id m14mr7896706eds.5.1603891696525; Wed, 28 Oct 2020 06:28:16 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603891696; cv=none; d=google.com; s=arc-20160816; b=WiAck6uV98DrIDkBXeGCYvQKSy9GmFxx7C3w+hHwpnpn4Mf+PTNe3xXnCQSn1cLTWk /FwWeGPnCT/m4EClEInfc6GDMi5p0FETURLWcPevzwO9CZx3pa1R5WgdxgC6P/kIo9cD oFzWf3JV6eQeU6yxwu289aiJMCS6Igvt5zNBnefhtgZj7ONIkr0YwqdgRZJy5LO7q+4t Lsrs0kBU2ZTNmCXReHD3I7wvxHkGSkCgBjoKk54YJpI21boXmAb5nFPp59qVfAkPMXrf tncOGAxYDTevPOWp2SAkcUQjROqI0Qq8aX2PYzuYrN3f5wHiiDDrpeLZvQe2uirxQwwk Om3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=PozFWhCQScTOPskhxdi1SL8F/btKGSYm1KJAvjG5XTY=; b=zDuDW7ySOoFoa9AQQNAnzuu3xUUKBWRnB2pyTQD7/FcnsKKTw2eIVguCWUNUq/dH34 VRtCO6K7gJaeOTsrA4wQOGvZoFgYElwqzIo4Tt+Bc0bUz/RPEPNmQFNG7DRrjHBa+pUl BKCL7eqmVcv/lccDgLil7zZln6OsV3eHyFUeiCBb9NfMSjqEU2S7xsvGBSkOZxV0xNMS tkndnBn9e+zBeS16prtIu9NXvaDM96ovxNgd1Vqyhcy0rWpi1QmFRl8Slcjfqs3cNIqv ZAL/0Tg+WYxWQZpCO++c2lToZBzUPm76/8z7tQSxtXpwh711qEfuOC74BdNzmrS79Kb9 2mSw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=fJeJQ06m; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id f19si2736409edx.542.2020.10.28.06.27.53; Wed, 28 Oct 2020 06:28:16 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=fJeJQ06m; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linuxfoundation.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1801706AbgJ0PnP (ORCPT + 99 others); Tue, 27 Oct 2020 11:43:15 -0400 Received: from mail.kernel.org ([198.145.29.99]:53598 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1800148AbgJ0PfM (ORCPT ); Tue, 27 Oct 2020 11:35:12 -0400 Received: from localhost (83-86-74-64.cable.dynamic.v4.ziggo.nl [83.86.74.64]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id AAB6B22275; Tue, 27 Oct 2020 15:35:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1603812910; bh=964bskyV8O3WcSQSOdmYBeLQY8q6cD1nKh/KLDJ0QcM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=fJeJQ06mXnKBu5GCj3N47lT7CeXGzRL86fZ3eZOTx6V/T0PPzO06fflANJhRUoMIt OskhwTC6sh9g9zvDOVagVYXGo8cPqXgHD2xw/H4Zo+k8U7PWUJcjkFD0ij/4H+60+g kPpMIDK1t+nLCOICZrdRa/v3Ot2R8vSzapQOp6g0= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Minas Harutyunyan , Felipe Balbi , Sasha Levin Subject: [PATCH 5.9 371/757] usb: dwc2: Fix INTR OUT transfers in DDMA mode. Date: Tue, 27 Oct 2020 14:50:21 +0100 Message-Id: <20201027135507.968665671@linuxfoundation.org> X-Mailer: git-send-email 2.29.1 In-Reply-To: <20201027135450.497324313@linuxfoundation.org> References: <20201027135450.497324313@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Minas Harutyunyan [ Upstream commit b2c586eb07efab982419f32b7c3bd96829bc8bcd ] In DDMA mode if INTR OUT transfers mps not multiple of 4 then single packet corresponds to single descriptor. Descriptor limit set to mps and desc chain limit set to mps * MAX_DMA_DESC_NUM_GENERIC. On that descriptors complete, to calculate transfer size should be considered correction value for each descriptor. In start request function, if "continue" is true then dma buffer address should be incremmented by offset for all type of transfers, not only for Control DATA_OUT transfers. Fixes: cf77b5fb9b394 ("usb: dwc2: gadget: Transfer length limit checking for DDMA") Fixes: e02f9aa6119e0 ("usb: dwc2: gadget: EP 0 specific DDMA programming") Fixes: aa3e8bc81311e ("usb: dwc2: gadget: DDMA transfer start and complete") Signed-off-by: Minas Harutyunyan Signed-off-by: Felipe Balbi Signed-off-by: Sasha Levin --- drivers/usb/dwc2/gadget.c | 40 ++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index 5b9d23991c99d..d367da4c6f850 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -713,8 +713,11 @@ static u32 dwc2_hsotg_read_frameno(struct dwc2_hsotg *hsotg) */ static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep) { + const struct usb_endpoint_descriptor *ep_desc = hs_ep->ep.desc; int is_isoc = hs_ep->isochronous; unsigned int maxsize; + u32 mps = hs_ep->ep.maxpacket; + int dir_in = hs_ep->dir_in; if (is_isoc) maxsize = (hs_ep->dir_in ? DEV_DMA_ISOC_TX_NBYTES_LIMIT : @@ -723,6 +726,11 @@ static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep) else maxsize = DEV_DMA_NBYTES_LIMIT * MAX_DMA_DESC_NUM_GENERIC; + /* Interrupt OUT EP with mps not multiple of 4 */ + if (hs_ep->index) + if (usb_endpoint_xfer_int(ep_desc) && !dir_in && (mps % 4)) + maxsize = mps * MAX_DMA_DESC_NUM_GENERIC; + return maxsize; } @@ -738,11 +746,14 @@ static unsigned int dwc2_gadget_get_chain_limit(struct dwc2_hsotg_ep *hs_ep) * Isochronous - descriptor rx/tx bytes bitfield limit, * Control In/Bulk/Interrupt - multiple of mps. This will allow to not * have concatenations from various descriptors within one packet. + * Interrupt OUT - if mps not multiple of 4 then a single packet corresponds + * to a single descriptor. * * Selects corresponding mask for RX/TX bytes as well. */ static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask) { + const struct usb_endpoint_descriptor *ep_desc = hs_ep->ep.desc; u32 mps = hs_ep->ep.maxpacket; int dir_in = hs_ep->dir_in; u32 desc_size = 0; @@ -766,6 +777,13 @@ static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask) desc_size -= desc_size % mps; } + /* Interrupt OUT EP with mps not multiple of 4 */ + if (hs_ep->index) + if (usb_endpoint_xfer_int(ep_desc) && !dir_in && (mps % 4)) { + desc_size = mps; + *mask = DEV_DMA_NBYTES_MASK; + } + return desc_size; } @@ -1123,13 +1141,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg, length += (mps - (length % mps)); } - /* - * If more data to send, adjust DMA for EP0 out data stage. - * ureq->dma stays unchanged, hence increment it by already - * passed passed data count before starting new transaction. - */ - if (!index && hsotg->ep0_state == DWC2_EP0_DATA_OUT && - continuing) + if (continuing) offset = ureq->actual; /* Fill DDMA chain entries */ @@ -2320,22 +2332,36 @@ static void dwc2_hsotg_change_ep_iso_parity(struct dwc2_hsotg *hsotg, */ static unsigned int dwc2_gadget_get_xfersize_ddma(struct dwc2_hsotg_ep *hs_ep) { + const struct usb_endpoint_descriptor *ep_desc = hs_ep->ep.desc; struct dwc2_hsotg *hsotg = hs_ep->parent; unsigned int bytes_rem = 0; + unsigned int bytes_rem_correction = 0; struct dwc2_dma_desc *desc = hs_ep->desc_list; int i; u32 status; + u32 mps = hs_ep->ep.maxpacket; + int dir_in = hs_ep->dir_in; if (!desc) return -EINVAL; + /* Interrupt OUT EP with mps not multiple of 4 */ + if (hs_ep->index) + if (usb_endpoint_xfer_int(ep_desc) && !dir_in && (mps % 4)) + bytes_rem_correction = 4 - (mps % 4); + for (i = 0; i < hs_ep->desc_count; ++i) { status = desc->status; bytes_rem += status & DEV_DMA_NBYTES_MASK; + bytes_rem -= bytes_rem_correction; if (status & DEV_DMA_STS_MASK) dev_err(hsotg->dev, "descriptor %d closed with %x\n", i, status & DEV_DMA_STS_MASK); + + if (status & DEV_DMA_L) + break; + desc++; } -- 2.25.1