From patchwork Tue Nov 6 16:26:40 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrzej Pietrasiewicz X-Patchwork-Id: 10670795 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 7F21D13BF for ; Tue, 6 Nov 2018 16:27:02 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6B56E2A7CF for ; Tue, 6 Nov 2018 16:27:02 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5F6222A7D9; Tue, 6 Nov 2018 16:27:02 +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 8BD262A7CF for ; Tue, 6 Nov 2018 16:27:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2389182AbeKGBw6 (ORCPT ); Tue, 6 Nov 2018 20:52:58 -0500 Received: from mailout1.w1.samsung.com ([210.118.77.11]:58352 "EHLO mailout1.w1.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2387685AbeKGBw6 (ORCPT ); Tue, 6 Nov 2018 20:52:58 -0500 Received: from eucas1p1.samsung.com (unknown [182.198.249.206]) by mailout1.w1.samsung.com (KnoxPortal) with ESMTP id 20181106162659euoutp0106788a8065f5c1c616451f1a83f6b664~klb7EVIv-0604806048euoutp01f; Tue, 6 Nov 2018 16:26:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 mailout1.w1.samsung.com 20181106162659euoutp0106788a8065f5c1c616451f1a83f6b664~klb7EVIv-0604806048euoutp01f DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=samsung.com; s=mail20170921; t=1541521619; bh=EE4DpM+4BPeeWJaU7YZAwmqq0P1TI8lAswV/70TJb38=; h=From:To:Cc:Subject:Date:In-reply-to:References:From; b=Um2omrrWfVbXJH/Sk4/LUyu9Gjy+Eu3rdkmlT3Nbf2rOST5hCNEzeeP/GeX/I0Txf D85XIoTKZcUCTQLodrBFiiOd5No7xvytwXUZwBpKR8Zbhf7Z4/XJx/yBL0+6tOW4lE tMSRvcqVSOLqxmNB3kFDSUuljZYJKckgmuMyAWqU= Received: from eusmges2new.samsung.com (unknown [203.254.199.244]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20181106162658eucas1p20012795383816c005cc5ce64a6b8f6ba~klb6g_LEA0048400484eucas1p2s; Tue, 6 Nov 2018 16:26:58 +0000 (GMT) Received: from eucas1p2.samsung.com ( [182.198.249.207]) by eusmges2new.samsung.com (EUCPMTA) with SMTP id 00.13.04294.2D0C1EB5; Tue, 6 Nov 2018 16:26:58 +0000 (GMT) Received: from eusmgms2.samsung.com (unknown [182.198.249.180]) by eucas1p2.samsung.com (KnoxPortal) with ESMTP id 20181106162657eucas1p2f33e07f6375427a1d7ceb01b66cb74ff~klb5sriNS3218132181eucas1p2E; Tue, 6 Nov 2018 16:26:57 +0000 (GMT) X-AuditID: cbfec7f4-84fff700000010c6-83-5be1c0d299b7 Received: from eusync3.samsung.com ( [203.254.199.213]) by eusmgms2.samsung.com (EUCPMTA) with SMTP id 2F.23.04128.1D0C1EB5; Tue, 6 Nov 2018 16:26:57 +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 <0PHS004XN5OR3N60@eusync3.samsung.com>; Tue, 06 Nov 2018 16:26:57 +0000 (GMT) From: Andrzej Pietrasiewicz To: linux-usb@vger.kernel.org Cc: Andrzej Pietrasiewicz , Greg Kroah-Hartman , Felipe Balbi , Marek Szyprowski , Bartlomiej Zolnierkiewicz , Michal Nazarewicz Subject: [PATCH] usb: gadget: f_fs: Allow scatter-gather buffers Date: Tue, 06 Nov 2018 17:26:40 +0100 Message-id: <20181106162640.4633-1-andrzej.p@samsung.com> X-Mailer: git-send-email 2.11.0 In-reply-to: <20181106161858.1471-1-andrzej.p@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFlrJIsWRmVeSWpSXmKPExsWy7djP87qXDjyMNvjZx2kx62U7i8XGGetZ LY61PWG3aF68ns1i0bJWZou1R+6yWyw43sLqwO6xaVUnm8f+uWvYPdb9ecXk0bdlFaPH501y AaxRXDYpqTmZZalF+nYJXBkr3rSyFczUrNh79iNzA2OrYhcjB4eEgInEzy6lLkYuDiGBFYwS r75fY4dwPjNKbJxzirmLkROsaMH0pcwQiWWMEo9vn2SFcJqYJO4+Og9WxSZgLLH3YAcjiC0i ICtx+MpvsA5mgclMEgfmPmcBSQgLOEjsfbcJrIFFQFXi64k/7CA2r4ClxMZdKxkh1slL7Gq7 yApicwpYSVz4f5YRZJCEQAebRMvXeUwQRS4SVw8ug7pPWOLV8S3sELaMxOXJ3SwQdr3Epi97 2CDsKYwS9+Z6Q9jWEoePQyxgFuCTmLRtOjMkMHglOtqEIEo8JM4/7oB6uZdR4vydTawTGCUX MDKsYhRPLS3OTU8tNspLLdcrTswtLs1L10vOz93ECIzA0/+Of9nBuOtP0iFGAQ5GJR7eC1sf RguxJpYVV+YeYpTgYFYS4T29GijEm5JYWZValB9fVJqTWnyIUZqDRUmct5rhQbSQQHpiSWp2 ampBahFMlomDU6qB0c/k69/453Jb7lwSUtvdszXlhsWU5VOUuJ3cbnEE73/p/bZ166roDI+H d7RiJjZf9K2dc29Jb0TZ49sHpsWvf7qrM36/6CPvtmULN0T1OPF92v9OZ8kK/n+GrjdlVxkK HSp8vXxvwIp5npemmW2UadO0Xc4YUKm2TuL5/LnyyUy+YSuWO7z7UanEUpyRaKjFXFScCAA9 x1fevAIAAA== X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFupgluLIzCtJLcpLzFFi42I5/e/4Vd2LBx5GG5y4xWsx62U7i8XGGetZ LY61PWG3aF68ns1i0bJWZou1R+6yWyw43sLqwO6xaVUnm8f+uWvYPdb9ecXk0bdlFaPH501y AaxRXDYpqTmZZalF+nYJXBkr3rSyFczUrNh79iNzA2OrYhcjJ4eEgInEgulLmbsYuTiEBJYw Ssy99AvKaWGSWHH6MStIFZuAscTegx2MILaIgKzE4Su/wYqYBaYySXzeNJ8JJCEs4CCx990m ZhCbRUBV4uuJP+wgNq+ApcTGXSsZIdbJS+xquwg2lFPASuLC/7NgcSGgmseXd7JMYORZwMiw ilEktbQ4Nz232EivODG3uDQvXS85P3cTIzB8th37uWUHY9e74EOMAhyMSjy8GjseRguxJpYV V+YeYpTgYFYS4T29GijEm5JYWZValB9fVJqTWnyIUZqDRUmc97xBZZSQQHpiSWp2ampBahFM lomDU6qB0d//7B6x559mz9qwcPO9PWGrJkX5nt+72Y9zzawy7yznHJu+e4oH9aal8JWsUDZR M4tf19cirvrB4afDBkm7k1t3ac55e+et+Hvb9OTw+Wls75wS/uxXPqd4Ieimy7+FRxKlA8yt XhyVNH2mZp1mdP28OdfNuutn5yY1bFwirv36zgTv+0KLfyixFGckGmoxFxUnAgAaoHJjGwIA AA== X-CMS-MailID: 20181106162657eucas1p2f33e07f6375427a1d7ceb01b66cb74ff X-Msg-Generator: CA CMS-TYPE: 201P X-CMS-RootMailID: 20181106162657eucas1p2f33e07f6375427a1d7ceb01b66cb74ff References: <20181106161858.1471-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 Some protocols implemented in userspace with FunctionFS might require large buffers, e.g. 64kB or more. Currently the said memory is allocated with kmalloc, which might fail should system memory be highly fragmented. On the other hand, some UDC hardware allows scatter-gather operation and this patch takes advantage of this capability: if the requested buffer is larger than PAGE_SIZE and the UDC allows scatter-gather operation, then the buffer is allocated with vmalloc and a scatterlist describing it is created and passed to usb request. Signed-off-by: Andrzej Pietrasiewicz --- @Felipe: This time I used your correct address. drivers/usb/gadget/function/f_fs.c | 92 +++++++++++++++++++++++++++++++++++--- 1 file changed, 87 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 3ada83d..e83fa63 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -219,6 +220,8 @@ struct ffs_io_data { struct usb_ep *ep; struct usb_request *req; + struct sg_table sgt; + bool use_sg; struct ffs_data *ffs; }; @@ -750,6 +753,70 @@ static ssize_t ffs_copy_to_iter(void *data, int data_len, struct iov_iter *iter) return ret; } +/* + * allocate a virtually contiguous buffer and create a scatterlist describing it + * @sg_table - pointer to a place to be filled with sg_table contents + * @size - required buffer size + */ +static void *ffs_build_sg_list(struct sg_table *sg_table, size_t size) +{ + struct page **pages; + void *vaddr; + unsigned long ptr; + unsigned int n_pages; + int i; + + vaddr = vmalloc(size); + if (!vaddr) + return NULL; + + n_pages = (PAGE_ALIGN((unsigned long)vaddr + size) - + ((unsigned long)vaddr & PAGE_MASK)) + >> PAGE_SHIFT; + pages = kvmalloc_array(n_pages, sizeof(struct page *), GFP_KERNEL); + if (!pages) { + vfree(vaddr); + + return NULL; + } + for (i = 0, ptr = (unsigned long)vaddr & PAGE_MASK; i < n_pages; + ++i, ptr += PAGE_SIZE) + pages[i] = vmalloc_to_page((void *)ptr); + + if (sg_alloc_table_from_pages(sg_table, pages, n_pages, + ((unsigned long)vaddr) & ~PAGE_MASK, size, GFP_KERNEL)) { + kvfree(pages); + vfree(vaddr); + + return NULL; + } + kvfree(pages); + + return vaddr; +} + +static inline void *ffs_alloc_buffer(struct ffs_io_data *io_data, + size_t data_len) +{ + if (io_data->use_sg) + return ffs_build_sg_list(&io_data->sgt, data_len); + + return kmalloc(data_len, GFP_KERNEL); +} + +static inline void ffs_free_buffer(struct ffs_io_data *io_data) +{ + if (!io_data->buf) + return; + + if (io_data->use_sg) { + sg_free_table(&io_data->sgt); + vfree(io_data->buf); + } else { + kfree(io_data->buf); + } +} + static void ffs_user_copy_worker(struct work_struct *work) { struct ffs_io_data *io_data = container_of(work, struct ffs_io_data, @@ -777,7 +844,7 @@ static void ffs_user_copy_worker(struct work_struct *work) if (io_data->read) kfree(io_data->to_free); - kfree(io_data->buf); + ffs_free_buffer(io_data); kfree(io_data); } @@ -933,6 +1000,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) * earlier */ gadget = epfile->ffs->gadget; + io_data->use_sg = gadget->sg_supported && data_len > PAGE_SIZE; spin_lock_irq(&epfile->ffs->eps_lock); /* In the meantime, endpoint got disabled or changed. */ @@ -949,7 +1017,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) data_len = usb_ep_align_maybe(gadget, ep->ep, data_len); spin_unlock_irq(&epfile->ffs->eps_lock); - data = kmalloc(data_len, GFP_KERNEL); + data = ffs_alloc_buffer(io_data, data_len); if (unlikely(!data)) { ret = -ENOMEM; goto error_mutex; @@ -989,9 +1057,17 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) bool interrupted = false; req = ep->req; - req->buf = data; + if (io_data->use_sg) { + req->buf = NULL; + req->sg = io_data->sgt.sgl; + req->num_sgs = io_data->sgt.nents; + } else { + req->buf = data; + } req->length = data_len; + io_data->buf = data; + req->context = &done; req->complete = ffs_epfile_io_complete; @@ -1023,7 +1099,13 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) } else if (!(req = usb_ep_alloc_request(ep->ep, GFP_ATOMIC))) { ret = -ENOMEM; } else { - req->buf = data; + if (io_data->use_sg) { + req->buf = NULL; + req->sg = io_data->sgt.sgl; + req->num_sgs = io_data->sgt.nents; + } else { + req->buf = data; + } req->length = data_len; io_data->buf = data; @@ -1053,7 +1135,7 @@ static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data) error_mutex: mutex_unlock(&epfile->mutex); error: - kfree(data); + ffs_free_buffer(io_data); return ret; }