From patchwork Fri Dec 14 14:07:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Pietrasiewicz X-Patchwork-Id: 10731223 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7BBCE112C for ; Fri, 14 Dec 2018 14:08:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 747BF28FE7 for ; Fri, 14 Dec 2018 14:08:03 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 689482CE22; Fri, 14 Dec 2018 14:08:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 817A628FE7 for ; Fri, 14 Dec 2018 14:08:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1730039AbeLNOIB (ORCPT ); Fri, 14 Dec 2018 09:08:01 -0500 Received: from mailout1.w1.samsung.com ([210.118.77.11]:59191 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1729758AbeLNOIB (ORCPT ); Fri, 14 Dec 2018 09:08:01 -0500 Received: from eucas1p2.samsung.com (unknown [182.198.249.207]) by mailout1.w1.samsung.com (KnoxPortal) with ESMTP id 20181214140758euoutp01069380e77adc7094eb43f9a51c17976b~wODZnzDAQ2279922799euoutp01F; Fri, 14 Dec 2018 14:07:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.w1.samsung.com 20181214140758euoutp01069380e77adc7094eb43f9a51c17976b~wODZnzDAQ2279922799euoutp01F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1544796478; bh=cQequvU+eITHrOBDVYJGWVvLNYnezRsFuiTOLT+TZ/s=; h=From:To:Cc:Subject:Date:In-reply-to:References:From; b=CLX3ZbgtiTf35Gou2gOA7JgGE1y7uRZ5m7cVjXbFCWB61suOAUylY00zaDPGi/Zxh 21KVdzlJyHjfcyHWuyaByMpcTsqPhHBAv+ry55qsFKkMvSPT4PX+V1DUd6p91kGZnT LazHfzbT0ugr6lsNcIquuKjdHV1yXmbp35O6JO88= Received: from eusmges1new.samsung.com (unknown [203.254.199.242]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20181214140757eucas1p21c472d3b4b76e5103aac221ff037a17a~wODY4TMut1279112791eucas1p2A; Fri, 14 Dec 2018 14:07:57 +0000 (GMT) Received: from eucas1p2.samsung.com ( [182.198.249.207]) by eusmges1new.samsung.com (EUCPMTA) with SMTP id 70.9A.04441.D39B31C5; Fri, 14 Dec 2018 14:07:57 +0000 (GMT) Received: from eusmgms2.samsung.com (unknown [182.198.249.180]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20181214140756eucas1p2678e1c409922b8bbbd1a51d5f9714355~wODYLcheF1279112791eucas1p2-; Fri, 14 Dec 2018 14:07:56 +0000 (GMT) X-AuditID: cbfec7f2-5e3ff70000001159-ed-5c13b93dc1b9 Received: from eusync3.samsung.com ( [203.254.199.213]) by eusmgms2.samsung.com (EUCPMTA) with SMTP id 6A.9F.04128.C39B31C5; Fri, 14 Dec 2018 14:07:56 +0000 (GMT) Received: from mcdsrvbld02.digital.local ([106.116.37.23]) by eusync3.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0PJQ004IDCL4ZA30@eusync3.samsung.com>; Fri, 14 Dec 2018 14:07:56 +0000 (GMT) From: Andrzej Pietrasiewicz To: linux-usb@vger.kernel.org Cc: Minas Harutyunyan , Andrzej Pietrasiewicz , Greg Kroah-Hartman , Marek Szyprowski , Bartlomiej Zolnierkiewicz Subject: [PATCHv2] usb: dwc2: gadget: Add scatter-gather mode Date: Fri, 14 Dec 2018 15:07:41 +0100 Message-id: <20181214140741.21856-1-andrzej.p@samsung.com> X-Mailer: git-send-email 2.11.0 In-reply-to: <20181214103336.23240-1-andrzej.p@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrAIsWRmVeSWpSXmKPExsWy7djP87q2O4VjDG4/l7KY9bKdxWLjjPWs Fs2L17NZNP7ay26xaFkrs8XaI3fZHdg89s9dw+7Rt2UVo8eW/Z8ZPT5vkgtgieKySUnNySxL LdK3S+DKmHG4kbnggUnFn93fGRsYp2h1MXJySAiYSCw/spq9i5GLQ0hgBaPEnsNHmSGcz4wS XevvscJUTXk/lREisYxRYt+Wj2wQThOTxNMdx9hAqtgEjCX2HuxgBLFFBGQlDl/5DTaKWeAL o8SXo40sIAlhAVuJ7v4l7CA2i4CqRO+6LrA4r4CVxKurLcwQ6+QldrVdBFvNKWAt0b1hCyvI IAmBr6wS937dZIcocpGYfbsZ6j5hiVfHt0DFZSQuT+5mgbDrJTZ92cMGYU9hlLg31xvCtpY4 fBxiAbMAn8SkbdOBFnMAxXklOtqEIEo8JNZvOQX1ch+jxKyWd4wTGCUXMDKsYhRPLS3OTU8t NsxLLdcrTswtLs1L10vOz93ECIy30/+Of9rB+PVS0iFGAQ5GJR7ejElCMUKsiWXFlbmHGCU4 mJVEeMNahWOEeFMSK6tSi/Lji0pzUosPMUpzsCiJ81YzPIgWEkhPLEnNTk0tSC2CyTJxcEo1 MG78Mv3o10t6XIVNP7TtH7oJVswJnvLSVd2Q499h3zmbF60KPOuwzTr31M8VPTImKZdePPjN wS8TOrP9DuvWvF/aKe57WvaJzZu//rNFxR0fgzqGAHHzs//eCB9J7tYtKGzimK/awRDp+9f4 mn/9dvFraVes7VSPGCm5XY9vkglybA/5fMS5VYmlOCPRUIu5qDgRAKrwLMuzAgAA X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrDJMWRmVeSWpSXmKPExsVy+t/xq7o2O4VjDLY80LaY9bKdxWLjjPWs Fs2L17NZNP7ay26xaFkrs8XaI3fZHdg89s9dw+7Rt2UVo8eW/Z8ZPT5vkgtgieKySUnNySxL LdK3S+DKmHG4kbnggUnFn93fGRsYp2h1MXJySAiYSEx5P5URxBYSWMIo8futfRcjF5DdwiTx ZH8DO0iCTcBYYu/BDrAiEQFZicNXfjOD2MwC3xgl5j0KArGFBWwluvuXgNWzCKhK9K7rYgGx eQWsJF5dbWGGWCYvsavtIiuIzSlgLdG9YQsrxGIrie9nvjFNYORZwMiwilEktbQ4Nz232Eiv ODG3uDQvXS85P3cTIzBMth37uWUHY9e74EOMAhyMSjy8B6YIxQixJpYVV+YeYpTgYFYS4Q1r FY4R4k1JrKxKLcqPLyrNSS0+xCjNwaIkznveoDJKSCA9sSQ1OzW1ILUIJsvEwSnVwLhZP8vJ VG/Z9mlf9984xLTu2sw7DKuK75R13JfZJDeHQ68lcCfzCb+0xXv+dljanXXvC/Mq+pkR+6ZC yfL+UoHr+XzvHPUsPp/YUrmhTm7dTZ/Ce7rdXJeWdL9tZWI63ZsqvcxAvulnTVz+8Rzxqcc5 5s//kPKhYkpLnPzO79xXG3+JZTI7HlViKc5INNRiLipOBABt5wE8DwIAAA== X-CMS-MailID: 20181214140756eucas1p2678e1c409922b8bbbd1a51d5f9714355 X-Msg-Generator: CA CMS-TYPE: 201P X-CMS-RootMailID: 20181214140756eucas1p2678e1c409922b8bbbd1a51d5f9714355 References: <20181214103336.23240-1-andrzej.p@samsung.com> Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Non-isochronous transfers: dwc2_gadget_config_nonisoc_xfer_ddma() name is prepended with underscore and the function is adapted to process descriptors passed from outside and to handle end of current sg list element differently from handling the end of the entire buffer. A wrapper for the said function is added which, for sg mode, iterates over scatterlist elements and for each of them calls the function mentioned above. Isochronous transfers: If the usb request contains a scatterlist, the address from the first element is used as dma address at dwc2_gadget_fill_isoc_desc() invocations. Current code for isoc transfers does not allow more than 4096 bytes per transfer, so it is assumed there is only one element in the scatterlist. If there are more, a warning is issued. Please see the fragment under the comment: /* In DDMA mode for ISOC's don't queue request if length greater * than descriptor limits. */ in dwc2_hsotg_ep_queue() to see the limits for isoc transfers. Signed-off-by: Andrzej Pietrasiewicz --- v1..v2: - using_desc_dma() called to check if DDMA available @Minas: I was actually unable to test the isochronous transfers. drivers/usb/dwc2/gadget.c | 104 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 73 insertions(+), 31 deletions(-) diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c index d9bb6cb..c880c2c 100644 --- a/drivers/usb/dwc2/gadget.c +++ b/drivers/usb/dwc2/gadget.c @@ -768,22 +768,13 @@ static u32 dwc2_gadget_get_desc_params(struct dwc2_hsotg_ep *hs_ep, u32 *mask) return desc_size; } -/* - * dwc2_gadget_config_nonisoc_xfer_ddma - prepare non ISOC DMA desc chain. - * @hs_ep: The endpoint - * @dma_buff: DMA address to use - * @len: Length of the transfer - * - * This function will iterate over descriptor chain and fill its entries - * with corresponding information based on transfer data. - */ -static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, +static void _dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, + struct dwc2_dma_desc **desc, dma_addr_t dma_buff, - unsigned int len) + unsigned int len, + bool true_last) { - struct dwc2_hsotg *hsotg = hs_ep->parent; int dir_in = hs_ep->dir_in; - struct dwc2_dma_desc *desc = hs_ep->desc_list; u32 mps = hs_ep->ep.maxpacket; u32 maxsize = 0; u32 offset = 0; @@ -798,42 +789,80 @@ static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, hs_ep->desc_count = 1; for (i = 0; i < hs_ep->desc_count; ++i) { - desc->status = 0; - desc->status |= (DEV_DMA_BUFF_STS_HBUSY + (*desc)->status = 0; + (*desc)->status |= (DEV_DMA_BUFF_STS_HBUSY << DEV_DMA_BUFF_STS_SHIFT); if (len > maxsize) { if (!hs_ep->index && !dir_in) - desc->status |= (DEV_DMA_L | DEV_DMA_IOC); + (*desc)->status |= (DEV_DMA_L | DEV_DMA_IOC); - desc->status |= (maxsize << - DEV_DMA_NBYTES_SHIFT & mask); - desc->buf = dma_buff + offset; + (*desc)->status |= + maxsize << DEV_DMA_NBYTES_SHIFT & mask; + (*desc)->buf = dma_buff + offset; len -= maxsize; offset += maxsize; } else { - desc->status |= (DEV_DMA_L | DEV_DMA_IOC); + if (true_last) + (*desc)->status |= (DEV_DMA_L | DEV_DMA_IOC); if (dir_in) - desc->status |= (len % mps) ? DEV_DMA_SHORT : - ((hs_ep->send_zlp) ? DEV_DMA_SHORT : 0); - if (len > maxsize) - dev_err(hsotg->dev, "wrong len %d\n", len); + (*desc)->status |= (len % mps) ? DEV_DMA_SHORT : + ((hs_ep->send_zlp && true_last) ? + DEV_DMA_SHORT : 0); - desc->status |= + (*desc)->status |= len << DEV_DMA_NBYTES_SHIFT & mask; - desc->buf = dma_buff + offset; + (*desc)->buf = dma_buff + offset; } - desc->status &= ~DEV_DMA_BUFF_STS_MASK; - desc->status |= (DEV_DMA_BUFF_STS_HREADY + (*desc)->status &= ~DEV_DMA_BUFF_STS_MASK; + (*desc)->status |= (DEV_DMA_BUFF_STS_HREADY << DEV_DMA_BUFF_STS_SHIFT); - desc++; + (*desc)++; } } /* + * dwc2_gadget_config_nonisoc_xfer_ddma - prepare non ISOC DMA desc chain. + * @hs_ep: The endpoint + * @dma_buff: DMA address to use + * @len: Length of the transfer + * + * This function will iterate over descriptor chain and fill its entries + * with corresponding information based on transfer data. + */ +static void dwc2_gadget_config_nonisoc_xfer_ddma(struct dwc2_hsotg_ep *hs_ep, + dma_addr_t dma_buff, + unsigned int len) +{ + struct usb_request *ureq = &hs_ep->req->req; + struct dwc2_dma_desc *desc = hs_ep->desc_list; + struct scatterlist *sg; + int i; + u8 desc_count = 0; + + /* non-DMA sg buffer */ + if (!ureq->num_sgs) { + _dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, &desc, + dma_buff, len, true); + + return; + } + + /* DMA sg buffer */ + for_each_sg(ureq->sg, sg, ureq->num_sgs, i) { + _dwc2_gadget_config_nonisoc_xfer_ddma(hs_ep, &desc, + sg_dma_address(sg) + sg->offset, sg_dma_len(sg), + sg_is_last(sg)); + desc_count += hs_ep->desc_count; + } + + hs_ep->desc_count = desc_count; +} + +/* * dwc2_gadget_fill_isoc_desc - fills next isochronous descriptor in chain. * @hs_ep: The isochronous endpoint. * @dma_buff: usb requests dma buffer. @@ -944,7 +973,13 @@ static void dwc2_gadget_start_isoc_ddma(struct dwc2_hsotg_ep *hs_ep) hs_ep->next_desc = 0; list_for_each_entry_safe(hs_req, treq, &hs_ep->queue, queue) { - ret = dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma, + dma_addr_t dma_addr = hs_req->req.dma; + + if (hs_req->req.num_sgs) { + WARN_ON(hs_req->req.num_sgs > 1); + dma_addr = sg_dma_address(hs_req->req.sg); + } + ret = dwc2_gadget_fill_isoc_desc(hs_ep, dma_addr, hs_req->req.length); if (ret) break; @@ -1399,7 +1434,13 @@ static int dwc2_hsotg_ep_queue(struct usb_ep *ep, struct usb_request *req, */ if (using_desc_dma(hs) && hs_ep->isochronous) { if (hs_ep->target_frame != TARGET_FRAME_INITIAL) { - dwc2_gadget_fill_isoc_desc(hs_ep, hs_req->req.dma, + dma_addr_t dma_addr = hs_req->req.dma; + + if (hs_req->req.num_sgs) { + WARN_ON(hs_req->req.num_sgs > 1); + dma_addr = sg_dma_address(hs_req->req.sg); + } + dwc2_gadget_fill_isoc_desc(hs_ep, dma_addr, hs_req->req.length); } return 0; @@ -4364,6 +4405,7 @@ static int dwc2_hsotg_udc_start(struct usb_gadget *gadget, hsotg->enabled = 0; spin_unlock_irqrestore(&hsotg->lock, flags); + gadget->sg_supported = using_desc_dma(hsotg); dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name); return 0;