Re: [PATCH 3/7] v4l: videobuf2: add vmalloc allocator

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Marek,

On Friday 19 November 2010 16:55:40 Marek Szyprowski wrote:
> From: Pawel Osciak <p.osciak@xxxxxxxxxxx>
> 
> Add an implementation of contiguous virtual memory allocator and handling
> routines for videobuf2, implemented on top of vmalloc()/vfree() calls.
> 
> Signed-off-by: Pawel Osciak <p.osciak@xxxxxxxxxxx>
> Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
> Signed-off-by: Marek Szyprowski <m.szyprowski@xxxxxxxxxxx>
> CC: Pawel Osciak <pawel@xxxxxxxxxx>
> ---
>  drivers/media/video/Kconfig             |    5 +
>  drivers/media/video/Makefile            |    1 +
>  drivers/media/video/videobuf2-vmalloc.c |  177
> +++++++++++++++++++++++++++++++ include/media/videobuf2-vmalloc.h       | 
>  21 ++++
>  4 files changed, 204 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/videobuf2-vmalloc.c
>  create mode 100644 include/media/videobuf2-vmalloc.h
> 
> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> index 83ce858..9351423 100644
> --- a/drivers/media/video/Kconfig
> +++ b/drivers/media/video/Kconfig
> @@ -55,6 +55,11 @@ config VIDEOBUF2_CORE
>  config VIDEOBUF2_MEMOPS
>  	tristate
> 
> +config VIDEOBUF2_VMALLOC
> +	select VIDEOBUF2_CORE
> +	select VIDEOBUF2_MEMOPS
> +	tristate
> +
>  #
>  # Multimedia Video device configuration
>  #
> diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
> index a97a2a0..538bee9 100644
> --- a/drivers/media/video/Makefile
> +++ b/drivers/media/video/Makefile
> @@ -116,6 +116,7 @@ obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
> 
>  obj-$(CONFIG_VIDEOBUF2_CORE)		+= videobuf2-core.o
>  obj-$(CONFIG_VIDEOBUF2_MEMOPS)		+= videobuf2-memops.o
> +obj-$(CONFIG_VIDEOBUF2_VMALLOC)		+= videobuf2-vmalloc.o
> 
>  obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
> 
> diff --git a/drivers/media/video/videobuf2-vmalloc.c
> b/drivers/media/video/videobuf2-vmalloc.c new file mode 100644
> index 0000000..3310900
> --- /dev/null
> +++ b/drivers/media/video/videobuf2-vmalloc.c
> @@ -0,0 +1,177 @@
> +/*
> + * videobuf2-vmalloc.c - vmalloc memory allocator for videobuf2
> + *
> + * Copyright (C) 2010 Samsung Electronics
> + *
> + * Author: Pawel Osciak <p.osciak@xxxxxxxxxxx>
> + *
> + * 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.
> + */
> +
> +#include <linux/module.h>
> +#include <linux/mm.h>
> +#include <linux/slab.h>
> +#include <linux/vmalloc.h>
> +
> +#include <media/videobuf2-core.h>
> +#include <media/videobuf2-memops.h>
> +
> +struct vb2_vmalloc_conf {
> +	struct vb2_alloc_ctx	alloc_ctx;
> +};
> +
> +struct vb2_vmalloc_buf {
> +	void			*vaddr;
> +	unsigned long		size;
> +	unsigned int		refcount;
> +};
> +
> +static void *vb2_vmalloc_alloc(const struct vb2_alloc_ctx *alloc_ctx,
> +				unsigned long size)
> +{
> +	struct vb2_vmalloc_buf *buf;
> +
> +	buf = kzalloc(sizeof *buf, GFP_KERNEL);
> +	if (!buf)
> +		return NULL;
> +
> +	buf->size = size;
> +	buf->vaddr = vmalloc_user(buf->size);

Some drivers might need vmalloc_32_user instead.

> +	if (!buf->vaddr) {
> +		printk(KERN_ERR "vmalloc of size %ld failed\n", buf->size);
> +		kfree(buf);
> +		return NULL;
> +	}
> +
> +	buf->refcount++;
> +	printk(KERN_DEBUG "Allocated vmalloc buffer of size %ld at vaddr=%p\n",
> +			buf->size, buf->vaddr);
> +
> +	return buf;
> +}
> +
> +static void vb2_vmalloc_put(void *buf_priv)
> +{
> +	struct vb2_vmalloc_buf *buf = buf_priv;
> +
> +	buf->refcount--;
> +
> +	if (0 == buf->refcount) {
> +		printk(KERN_DEBUG "%s: Freeing vmalloc mem at vaddr=%p\n",
> +			__func__, buf->vaddr);
> +		vfree(buf->vaddr);
> +		kfree(buf);
> +	}
> +}
> +
> +static void *vb2_vmalloc_vaddr(void *buf_priv)
> +{
> +	struct vb2_vmalloc_buf *buf = buf_priv;
> +
> +	BUG_ON(!buf);
> +
> +	if (!buf->vaddr) {
> +		printk(KERN_ERR "Address of an unallocated "
> +				"plane requested\n");

Can this happen under normal circumstances, or is it a driver bug ? In the 
later case a WARN_ON might be better.

> +		return NULL;
> +	}
> +
> +	return buf->vaddr;
> +}
> +
> +static unsigned int vb2_vmalloc_num_users(void *buf_priv)
> +{
> +	struct vb2_vmalloc_buf *buf = buf_priv;
> +
> +	return buf->refcount;
> +}
> +
> +/* TODO generalize and extract to core as much as possible */

I agree with the TODO :-) This part doesn't seem very clean, and 
vm_open/vm_close handling certainly needs documentation.

> +static void vb2_vmalloc_vm_open(struct vm_area_struct *vma)
> +{
> +	struct vb2_vmalloc_buf *buf = vma->vm_private_data;
> +
> +	printk(KERN_DEBUG "%s vmalloc_priv: %p, refcount: %d, "
> +			"vma: %08lx-%08lx\n", __func__, buf, buf->refcount,
> +			vma->vm_start, vma->vm_end);
> +
> +	buf->refcount++;
> +}
> +
> +static void vb2_vmalloc_vm_close(struct vm_area_struct *vma)
> +{
> +	struct vb2_vmalloc_buf *buf = vma->vm_private_data;
> +
> +	printk(KERN_DEBUG "%s vmalloc_priv: %p, refcount: %d, "
> +			"vma: %08lx-%08lx\n", __func__, buf, buf->refcount,
> +			vma->vm_start, vma->vm_end);
> +
> +	vb2_vmalloc_put(buf);
> +}
> +
> +static const struct vm_operations_struct vb2_vmalloc_vm_ops = {
> +	.open = vb2_vmalloc_vm_open,
> +	.close = vb2_vmalloc_vm_close,
> +};
> +
> +static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
> +{
> +	struct vb2_vmalloc_buf *buf = buf_priv;
> +	int ret;
> +
> +	if (!buf) {
> +		printk(KERN_ERR "No memory to map\n");
> +		return -EINVAL;
> +	}

I think you should test that the VMA size is equal to (or smaller than) the 
buffer size. That could be done in the core.

> +	ret = remap_vmalloc_range(vma, buf->vaddr, 0);
> +	if (ret) {
> +		printk(KERN_ERR "Remapping vmalloc memory, error: %d\n", ret);
> +		return ret;
> +	}
> +
> +	vma->vm_flags		|= VM_DONTEXPAND | VM_RESERVED;

VM_RESERVED is set by remap_vmalloc_range(). What is VM_DONTEXPAND for ?

> +	vma->vm_private_data	= buf;
> +	vma->vm_ops		= &vb2_vmalloc_vm_ops;
> +
> +	vb2_vmalloc_vm_open(vma);
> +
> +	return 0;
> +}
> +
> +static const struct vb2_mem_ops vb2_vmalloc_ops = {
> +	.alloc		= vb2_vmalloc_alloc,
> +	.put		= vb2_vmalloc_put,
> +	.vaddr		= vb2_vmalloc_vaddr,
> +	.mmap		= vb2_vmalloc_mmap,
> +	.num_users	= vb2_vmalloc_num_users,
> +};
> +
> +struct vb2_alloc_ctx *vb2_vmalloc_init(void)
> +{
> +	struct vb2_vmalloc_conf *conf;
> +
> +	conf = kzalloc(sizeof *conf, GFP_KERNEL);
> +	if (!conf)
> +		return ERR_PTR(-ENOMEM);
> +
> +	conf->alloc_ctx.mem_ops = &vb2_vmalloc_ops;
> +
> +	return &conf->alloc_ctx;
> +}
> +EXPORT_SYMBOL_GPL(vb2_vmalloc_init);
> +
> +void vb2_vmalloc_cleanup(struct vb2_alloc_ctx *alloc_ctx)
> +{
> +	struct vb2_vmalloc_conf *conf =
> +		container_of(alloc_ctx, struct vb2_vmalloc_conf, alloc_ctx);
> +
> +	kfree(conf);
> +}
> +EXPORT_SYMBOL_GPL(vb2_vmalloc_cleanup);
> +
> +MODULE_DESCRIPTION("vmalloc memory handling routines for videobuf2");
> +MODULE_AUTHOR("Pawel Osciak");
> +MODULE_LICENSE("GPL");
> diff --git a/include/media/videobuf2-vmalloc.h
> b/include/media/videobuf2-vmalloc.h new file mode 100644
> index 0000000..0e7c303
> --- /dev/null
> +++ b/include/media/videobuf2-vmalloc.h
> @@ -0,0 +1,21 @@
> +/*
> + * videobuf2-vmalloc.h - vmalloc memory allocator for videobuf2
> + *
> + * Copyright (C) 2010 Samsung Electronics
> + *
> + * Author: Pawel Osciak <p.osciak@xxxxxxxxxxx>
> + *
> + * 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_VMALLOC_H
> +#define _MEDIA_VIDEOBUF2_VMALLOC_H
> +
> +#include <media/videobuf2-core.h>
> +
> +struct vb2_alloc_ctx *vb2_vmalloc_init(void);
> +void vb2_vmalloc_cleanup(struct vb2_alloc_ctx *alloc_ctx);
> +
> +#endif

-- 
Regards,

Laurent Pinchart
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]
  Powered by Linux