From patchwork Tue Jul 31 20:17:08 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Federico Vaga X-Patchwork-Id: 13561 Received: from mail.tu-berlin.de ([130.149.7.33]) by www.linuxtv.org with esmtp (Exim 4.72) (envelope-from ) id 1SwIrT-0001wM-Ss for patchwork@linuxtv.org; Tue, 31 Jul 2012 22:16:11 +0200 X-tubIT-Incoming-IP: 209.132.180.67 Received: from vger.kernel.org ([209.132.180.67]) by mail.tu-berlin.de (exim-4.75/mailfrontend-2) with esmtp for id 1SwIrT-0000Ng-GG; Tue, 31 Jul 2012 22:16:11 +0200 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756480Ab2GaUP3 (ORCPT ); Tue, 31 Jul 2012 16:15:29 -0400 Received: from mail-bk0-f46.google.com ([209.85.214.46]:39464 "EHLO mail-bk0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756339Ab2GaUPZ (ORCPT ); Tue, 31 Jul 2012 16:15:25 -0400 Received: by mail-bk0-f46.google.com with SMTP id j10so3466888bkw.19 for ; Tue, 31 Jul 2012 13:15:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=qeSvFutowkGQliejzRokgfAAnJ20GEY5Ifsja5UmdC4=; b=pHYmQ/Gin19YjGmEmv4WY2rnzl7otFmolCAcw9gCCrH+aZi2t2iUEjhZHUofBFXeXo zAsYpo09DQIRzPffmaew1LQowhj20uUaWFkm9YLMs1YSzIvqnUxxE+G10bit7we5ydi7 nelMmYFWEbeJmi+9rAmRBVHFw+nRX6G2XRIG1dJLPhAL0iX6zok+MmprSi3dsWxd8uR2 v6csIDLBva7ytK7Tc0bgvqgMTV3HFIP0w6QqJVjYeQE9E8NXDSWj25AMpGgTJNYIRYmt bFKSs5SonXtLfqVNNZeJid85ivDSOxRLk6KsjwzWdxPwSs2U7nn/tIJCExp5Xz7sd0do 6spw== Received: by 10.205.118.14 with SMTP id fo14mr6011139bkc.130.1343765724346; Tue, 31 Jul 2012 13:15:24 -0700 (PDT) Received: from harkonnen.fastwebnet.it (2-225-41-194.ip174.fastwebnet.it. [2.225.41.194]) by mx.google.com with ESMTPS id n5sm642362bkv.14.2012.07.31.13.15.22 (version=SSLv3 cipher=OTHER); Tue, 31 Jul 2012 13:15:23 -0700 (PDT) From: Federico Vaga To: Mauro Carvalho Chehab , Pawel Osciak , Marek Szyprowski , Hans Verkuil Cc: Giancarlo Asnaghi , linux-media@vger.kernel.org, linux-kernel@vger.kernel.org, Jonathan Corbet , Federico Vaga Subject: [PATCH 2/3] [media] videobuf2-dma-streaming: new videobuf2 memory allocator Date: Tue, 31 Jul 2012 22:17:08 +0200 Message-Id: <1343765829-6006-3-git-send-email-federico.vaga@gmail.com> X-Mailer: git-send-email 1.7.11.2 In-Reply-To: <1343765829-6006-1-git-send-email-federico.vaga@gmail.com> References: <1343765829-6006-1-git-send-email-federico.vaga@gmail.com> Sender: linux-media-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-media@vger.kernel.org X-PMX-Version: 5.6.1.2065439, Antispam-Engine: 2.7.2.376379, Antispam-Data: 2012.7.31.200316 X-PMX-Spam: Gauge=IIIIIIIII, Probability=9%, Report=' FORGED_FROM_GMAIL 0.1, MULTIPLE_RCPTS 0.1, HTML_00_01 0.05, HTML_00_10 0.05, URI_ENDS_IN_HTML 0, __ANY_URI 0, __CP_MEDIA_BODY 0, __CP_URI_IN_BODY 0, __FRAUD_BODY_WEBMAIL 0, __FRAUD_WEBMAIL 0, __FRAUD_WEBMAIL_FROM 0, __FROM_GMAIL 0, __HAS_FROM 0, __HAS_MSGID 0, __HAS_X_MAILER 0, __HAS_X_MAILING_LIST 0, __MIME_TEXT_ONLY 0, __MULTIPLE_RCPTS_CC_X2 0, __PHISH_SPEAR_STRUCTURE_1 0, __SANE_MSGID 0, __SUBJ_ALPHA_END 0, __TO_MALFORMED_2 0, __URI_NO_WWW 0, __URI_NS ' Signed-off-by: Federico Vaga --- drivers/media/video/Kconfig | 6 +- drivers/media/video/Makefile | 1 + drivers/media/video/videobuf2-dma-streaming.c | 187 ++++++++++++++++++++++++++ include/media/videobuf2-dma-streaming.h | 24 ++++ 4 file modificati, 217 inserzioni(+). 1 rimozione(-) create mode 100644 drivers/media/video/videobuf2-dma-streaming.c create mode 100644 include/media/videobuf2-dma-streaming.h diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index be6d718..6c60b59 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -59,6 +59,10 @@ config VIDEOBUF2_DMA_NC select VIDEOBUF2_CORE select VIDEOBUF2_MEMOPS tristate +config VIDEOBUF2_DMA_STREAMING + select VIDEOBUF2_CORE + select VIDEOBUF2_MEMOPS + tristate config VIDEOBUF2_VMALLOC select VIDEOBUF2_CORE @@ -844,7 +848,7 @@ config STA2X11_VIP tristate "STA2X11 VIP Video For Linux" depends on STA2X11 select VIDEO_ADV7180 if VIDEO_HELPER_CHIPS_AUTO - select VIDEOBUF_DMA_CONTIG + select VIDEOBUF2_DMA_STREAMING depends on PCI && VIDEO_V4L2 && VIRT_TO_BUS help Say Y for support for STA2X11 VIP (Video Input Port) capture diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 30234af..c1a08b9e 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -140,6 +140,7 @@ obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o obj-$(CONFIG_VIDEOBUF2_DMA_SG) += videobuf2-dma-sg.o obj-$(CONFIG_VIDEOBUF2_DMA_NC) += videobuf2-dma-nc.o +obj-$(CONFIG_VIDEOBUF2_DMA_STREAMING) += videobuf2-dma-streaming.o obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o diff --git a/drivers/media/video/videobuf2-dma-streaming.c b/drivers/media/video/videobuf2-dma-streaming.c new file mode 100644 index 0000000..d96d3d9 --- /dev/null +++ b/drivers/media/video/videobuf2-dma-streaming.c @@ -0,0 +1,187 @@ +/* + * videobuf2-dma-streaming.c - DMA streaming memory allocator for videobuf2 + * + * Copyright (C) 2012 Federico Vaga + * * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include + +#include +#include +#include + +struct vb2_streaming_conf { + struct device *dev; +}; +struct vb2_streaming_buf { + struct vb2_streaming_conf *conf; + void *vaddr; + + dma_addr_t dma_handle; + + unsigned long size; + struct vm_area_struct *vma; + + atomic_t refcount; + struct vb2_vmarea_handler handler; +}; + +static void vb2_dma_streaming_put(void *buf_priv) +{ + struct vb2_streaming_buf *buf = buf_priv; + + if (atomic_dec_and_test(&buf->refcount)) { + dma_unmap_single(buf->conf->dev, buf->dma_handle, buf->size, + DMA_FROM_DEVICE); + free_pages_exact(buf->vaddr, buf->size); + kfree(buf); + } + +} + +static void *vb2_dma_streaming_alloc(void *alloc_ctx, unsigned long size) +{ + struct vb2_streaming_conf *conf = alloc_ctx; + struct vb2_streaming_buf *buf; + int err; + + buf = kzalloc(sizeof *buf, GFP_KERNEL); + if (!buf) + return ERR_PTR(-ENOMEM); + buf->vaddr = alloc_pages_exact(size, GFP_KERNEL | GFP_DMA); + if (!buf->vaddr) { + err = -ENOMEM; + goto out; + } + buf->dma_handle = dma_map_single(conf->dev, buf->vaddr, size, + DMA_FROM_DEVICE); + err = dma_mapping_error(conf->dev, buf->dma_handle); + if (err) { + dev_err(conf->dev, "dma_map_single failed\n"); + + free_pages_exact(buf->vaddr, size); + buf->vaddr = NULL; + goto out_pages; + } + buf->conf = conf; + buf->size = size; + buf->handler.refcount = &buf->refcount; + buf->handler.put = vb2_dma_streaming_put; + buf->handler.arg = buf; + + atomic_inc(&buf->refcount); + return buf; + +out_pages: + free_pages_exact(buf->vaddr, buf->size); +out: + kfree(buf); + return ERR_PTR(err); +} + +static void *vb2_dma_streaming_cookie(void *buf_priv) +{ + struct vb2_streaming_buf *buf = buf_priv; + + return (void *)buf->dma_handle; +} + +static void *vb2_dma_streaming_vaddr(void *buf_priv) +{ + struct vb2_streaming_buf *buf = buf_priv; + + if (!buf) + return NULL; + return buf->vaddr; +} + +static unsigned int vb2_dma_streaming_num_users(void *buf_priv) +{ + struct vb2_streaming_buf *buf = buf_priv; + + return atomic_read(&buf->refcount); +} + +static int vb2_dma_streaming_mmap(void *buf_priv, struct vm_area_struct *vma) +{ + struct vb2_streaming_buf *buf = buf_priv; + unsigned long pos, start = vma->vm_start; + unsigned long size; + struct page *page; + int err; + + /* Try to remap memory */ + size = vma->vm_end - vma->vm_start; + size = (size < buf->size) ? size : buf->size; + pos = (unsigned long)buf->vaddr; + + while (size > 0) { + page = virt_to_page((void *)pos); + if (!page) { + dev_err(buf->conf->dev, "mmap: virt_to_page failed\n"); + return -ENOMEM; + } + err = vm_insert_page(vma, start, page); + if (err) { + dev_err(buf->conf->dev, "mmap: insert failed %d\n", err); + return -ENOMEM; + } + start += PAGE_SIZE; + pos += PAGE_SIZE; + + if (size > PAGE_SIZE) + size -= PAGE_SIZE; + else + size = 0; + } + + + vma->vm_ops = &vb2_common_vm_ops; + vma->vm_flags |= VM_DONTEXPAND; + vma->vm_private_data = &buf->handler; + + vma->vm_ops->open(vma); + + return 0; +} + +const struct vb2_mem_ops vb2_dma_streaming_memops = { + .alloc = vb2_dma_streaming_alloc, + .put = vb2_dma_streaming_put, + .cookie = vb2_dma_streaming_cookie, + .vaddr = vb2_dma_streaming_vaddr, + .mmap = vb2_dma_streaming_mmap, + .num_users = vb2_dma_streaming_num_users, +}; +EXPORT_SYMBOL_GPL(vb2_dma_streaming_memops); + +void *vb2_dma_streaming_init_ctx(struct device *dev) +{ + struct vb2_streaming_conf *conf; + + conf = kmalloc(sizeof *conf, GFP_KERNEL); + if (!conf) + return ERR_PTR(-ENOMEM); + + conf->dev = dev; + + return conf; +} +EXPORT_SYMBOL_GPL(vb2_dma_streaming_init_ctx); + +void vb2_dma_streaming_cleanup_ctx(void *alloc_ctx) +{ + kfree(alloc_ctx); +} +EXPORT_SYMBOL_GPL(vb2_dma_streaming_cleanup_ctx); + +MODULE_DESCRIPTION("DMA-streaming memory allocator for videobuf2"); +MODULE_AUTHOR("Federico Vaga "); +MODULE_LICENSE("GPL v2"); diff --git a/include/media/videobuf2-dma-streaming.h b/include/media/videobuf2-dma-streaming.h new file mode 100644 index 0000000..89cbd06 --- /dev/null +++ b/include/media/videobuf2-dma-streaming.h @@ -0,0 +1,24 @@ +/* + * videobuf2-dma-streaming.h - DMA steaming memory allocator for videobuf2 + * + * Copyright (C) 2012 Federico Vaga + * + * Author: Federico Vaga + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation. + */ + +#ifndef _MEDIA_VIDEOBUF2_DMA_STREAMING_H +#define _MEDIA_VIDEOBUF2_DMA_STREAMING_H + +#include +#include + +void *vb2_dma_streaming_init_ctx(struct device *dev); +void vb2_dma_streaming_cleanup_ctx(void *alloc_ctx); + +extern const struct vb2_mem_ops vb2_dma_streaming_memops; + +#endif