From patchwork Tue Nov 26 12:58:44 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ricardo Ribalda Delgado X-Patchwork-Id: 3238981 Return-Path: X-Original-To: patchwork-linux-media@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id DB4FCC045B for ; Tue, 26 Nov 2013 12:58:57 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 2DD2E203A3 for ; Tue, 26 Nov 2013 12:58:53 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id ED2212037A for ; Tue, 26 Nov 2013 12:58:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752755Ab3KZM6t (ORCPT ); Tue, 26 Nov 2013 07:58:49 -0500 Received: from mail-lb0-f169.google.com ([209.85.217.169]:43153 "EHLO mail-lb0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751115Ab3KZM6t (ORCPT ); Tue, 26 Nov 2013 07:58:49 -0500 Received: by mail-lb0-f169.google.com with SMTP id y6so4363684lbh.14 for ; Tue, 26 Nov 2013 04:58:47 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=CGcJrnV6seHyV0LwEcfcoowGUtv8kWVQ6GvZkg+29Vw=; b=0pzTmL/rJq6uI0SvfuYsHuklambL+nl08fCoiCd7xITGsXKJaOdZQPFSGnLxaDQEWy fdemakk3GRaDNS9pDSWD6t68+nQhuQNlsSWRJTucn4OKO/4OGz47XiMuJX7rIXb4Hq9o 6ECz5bVBsEXZAmBHIKizdYWjJUChZ/ctU+dzhkpdtvP9jY8nEE+/XHQcC4J99BVNM7Xc Zg3SuqiRw6ndIf6zytCetTzhtdd5C+IcZ9QIVSZ4nLJaqbZQowZbscQeNHYVZuULemUH uy5Qa9BMCE6DeoDazQzDHYRJZgWSEuOxuFVGjxmfJGDLT3EkeiU+oHhvkWBQu6uwW6AA PFtw== X-Received: by 10.112.138.164 with SMTP id qr4mr1198982lbb.49.1385470727884; Tue, 26 Nov 2013 04:58:47 -0800 (PST) Received: from neopili.qtec.com (0x4dd4aed9.adsl.cybercity.dk. [77.212.174.217]) by mx.google.com with ESMTPSA id c10sm38682201lbd.9.2013.11.26.04.58.45 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Nov 2013 04:58:46 -0800 (PST) From: Ricardo Ribalda Delgado To: Pawel Osciak , Marek Szyprowski , Kyungmin Park , Mauro Carvalho Chehab , linux-media@vger.kernel.org (open list:VIDEOBUF2 FRAMEWORK), sylvester.nawrocki@gmail.com, =?UTF-8?q?Matthias=20W=C3=A4chter?= Cc: Ricardo Ribalda Delgado Subject: [PATCH v2] videobuf2-dma-sg: Support io userptr operations on io memory Date: Tue, 26 Nov 2013 13:58:44 +0100 Message-Id: <1385470724-20632-1-git-send-email-ricardo.ribalda@gmail.com> X-Mailer: git-send-email 1.8.4.3 Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Memory exported via remap_pfn_range cannot be remapped via get_user_pages. Other videobuf2 methods (like the dma-contig) supports io memory. This patch adds support for this kind of memory. v2: Comments by Marek Szyprowski -Use vb2_get_vma and vb2_put_vma Signed-off-by: Ricardo Ribalda Delgado Acked-by: Marek Szyprowski --- drivers/media/v4l2-core/videobuf2-dma-sg.c | 54 +++++++++++++++++++++++++++--- 1 file changed, 49 insertions(+), 5 deletions(-) diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c index 2f86054..104e4b9 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-sg.c +++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c @@ -40,6 +40,7 @@ struct vb2_dma_sg_buf { unsigned int num_pages; atomic_t refcount; struct vb2_vmarea_handler handler; + struct vm_area_struct *vma; }; static void vb2_dma_sg_put(void *buf_priv); @@ -155,12 +156,18 @@ static void vb2_dma_sg_put(void *buf_priv) } } +static inline int vma_is_io(struct vm_area_struct *vma) +{ + return !!(vma->vm_flags & (VM_IO | VM_PFNMAP)); +} + static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, unsigned long size, int write) { struct vb2_dma_sg_buf *buf; unsigned long first, last; int num_pages_from_user; + struct vm_area_struct *vma; buf = kzalloc(sizeof *buf, GFP_KERNEL); if (!buf) @@ -178,9 +185,40 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, buf->pages = kzalloc(buf->num_pages * sizeof(struct page *), GFP_KERNEL); if (!buf->pages) - return NULL; + goto userptr_fail_alloc_pages; + + vma = find_vma(current->mm, vaddr); + if (!vma) { + dprintk(1, "no vma for address %lu\n", vaddr); + goto userptr_fail_find_vma; + } + + if (vma->vm_end < vaddr + size) { + dprintk(1, "vma at %lu is too small for %lu bytes\n", + vaddr, size); + goto userptr_fail_find_vma; + } + + buf->vma = vb2_get_vma(vma); + if (!buf->vma) { + dprintk(1, "failed to copy vma\n"); + goto userptr_fail_find_vma; + } + + if (vma_is_io(buf->vma)) { + for (num_pages_from_user = 0; + num_pages_from_user < buf->num_pages; + ++num_pages_from_user, vaddr += PAGE_SIZE) { + unsigned long pfn; - num_pages_from_user = get_user_pages(current, current->mm, + if (follow_pfn(buf->vma, vaddr, &pfn)) { + dprintk(1, "no page for address %lu\n", vaddr); + break; + } + buf->pages[num_pages_from_user] = pfn_to_page(pfn); + } + } else + num_pages_from_user = get_user_pages(current, current->mm, vaddr & PAGE_MASK, buf->num_pages, write, @@ -201,9 +239,13 @@ userptr_fail_alloc_table_from_pages: userptr_fail_get_user_pages: dprintk(1, "get_user_pages requested/got: %d/%d]\n", num_pages_from_user, buf->num_pages); - while (--num_pages_from_user >= 0) - put_page(buf->pages[num_pages_from_user]); + if (!vma_is_io(buf->vma)) + while (--num_pages_from_user >= 0) + put_page(buf->pages[num_pages_from_user]); + vb2_put_vma(buf->vma); +userptr_fail_find_vma: kfree(buf->pages); +userptr_fail_alloc_pages: kfree(buf); return NULL; } @@ -225,9 +267,11 @@ static void vb2_dma_sg_put_userptr(void *buf_priv) while (--i >= 0) { if (buf->write) set_page_dirty_lock(buf->pages[i]); - put_page(buf->pages[i]); + if (!vma_is_io(buf->vma)) + put_page(buf->pages[i]); } kfree(buf->pages); + vb2_put_vma(buf->vma); kfree(buf); }