From: Tomasz Stanislawski t.stanislaws@samsung.com
This patch adds the framework for buffer sharing via a file descriptor. A driver that use shared buffer (shrbuf) can export a memory description by transforming it into a file descriptor. The reverse operation (import) is done by obtaining a memory description from a file descriptor. The driver is responsible to get and put callbacks to avoid resource leakage. Current implementation is dedicated for dma-contiguous buffers but scatter-gather lists will be use in the future.
The framework depends on anonfd framework which is used to create files that are not associated with any inode.
Signed-off-by: Tomasz Stanislawski t.stanislaws@samsung.com Signed-off-by: Kyungmin Park kyungmin.park@samsung.com Signed-off-by: Marek Szyprowski m.szyprowski@samsung.com --- drivers/base/Kconfig | 11 +++++ drivers/base/Makefile | 1 + drivers/base/shared-buffer.c | 96 +++++++++++++++++++++++++++++++++++++++++ include/linux/shared-buffer.h | 55 +++++++++++++++++++++++ 4 files changed, 163 insertions(+), 0 deletions(-) create mode 100644 drivers/base/shared-buffer.c create mode 100644 include/linux/shared-buffer.h
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index d57e8d0..d75a038 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -168,4 +168,15 @@ config SYS_HYPERVISOR bool default n
+config SHARED_BUFFER + bool "Framework for buffer sharing between drivers" + depends on ANON_INODES + help + This option enables the framework for buffer sharing between + multiple drivers. A buffer is associated with a file descriptor + using driver API's extensions. The descriptor is passed to other + driver. + + If you are unsure about this, Say N here. + endmenu diff --git a/drivers/base/Makefile b/drivers/base/Makefile index 4c5701c..eeeb813 100644 --- a/drivers/base/Makefile +++ b/drivers/base/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_DEVTMPFS) += devtmpfs.o obj-y += power/ obj-$(CONFIG_HAS_DMA) += dma-mapping.o obj-$(CONFIG_HAVE_GENERIC_DMA_COHERENT) += dma-coherent.o +obj-$(CONFIG_SHARED_BUFFER) += shared-buffer.o obj-$(CONFIG_ISA) += isa.o obj-$(CONFIG_FW_LOADER) += firmware_class.o obj-$(CONFIG_NUMA) += node.o diff --git a/drivers/base/shared-buffer.c b/drivers/base/shared-buffer.c new file mode 100644 index 0000000..105b696 --- /dev/null +++ b/drivers/base/shared-buffer.c @@ -0,0 +1,96 @@ +/* + * Framework for shared buffer + * + * Copyright (C) 2011 Samsung Electronics Co., Ltd. + * Author: Tomasz Stanislawski, t.stanislaws@samsung.com + * + * 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 <linux/anon_inodes.h> +#include <linux/dma-mapping.h> +#include <linux/fs.h> +#include <linux/file.h> +#include <linux/shared-buffer.h> + +/** + * shrbuf_release() - release resources of shrbuf file + * @inode: a file's inode, not used + * @file: file pointer + * + * The function unbinds shrbuf structure from a file + */ +static int shrbuf_release(struct inode *inode, struct file *file) +{ + struct shrbuf *sb = file->private_data; + + /* decrease reference counter increased in shrbuf_export */ + sb->put(sb); + return 0; +} + +static const struct file_operations shrbuf_fops = { + .release = shrbuf_release, +}; + +/** + * shrbuf_export() - transforms shrbuf into a file descriptor + * @sb: shared buffer instance to be exported + * + * The function creates a file descriptor associated with a shared buffer + * + * Returns file descriptor or appropriate error on failure + */ +int shrbuf_export(struct shrbuf *sb) +{ + int fd; + + BUG_ON(!sb || !sb->get || !sb->put); + /* binding shrbuf to a file so reference count in increased */ + sb->get(sb); + /* obtaing file descriptor without inode */ + fd = anon_inode_getfd("shrbuf", &shrbuf_fops, sb, 0); + /* releasing shrbuf on failure */ + if (fd < 0) + sb->put(sb); + return fd; +} + +EXPORT_SYMBOL(shrbuf_export); + +/** + * shrbuf_import() - obtain shrbuf structure from a file descriptor + * @fd: file descriptor + * + * The function obtains an instance of a shared buffer from a file descriptor + * Call sb->put when imported buffer is not longer needed + * + * Returns pointer to a shared buffer or error pointer on failure + */ +struct shrbuf *shrbuf_import(int fd) +{ + struct file *file; + struct shrbuf *sb; + + /* obtain a file, assure that it will not be released */ + file = fget(fd); + /* check if descriptor is incorrect */ + if (!file) + return ERR_PTR(-EBADF); + /* check if dealing with shrbuf-file */ + if (file->f_op != &shrbuf_fops) { + fput(file); + return ERR_PTR(-EINVAL); + } + /* add user of shared buffer */ + sb = file->private_data; + sb->get(sb); + /* release the file */ + fput(file); + + return sb; +} + +EXPORT_SYMBOL(shrbuf_import); + diff --git a/include/linux/shared-buffer.h b/include/linux/shared-buffer.h new file mode 100644 index 0000000..ac0822f --- /dev/null +++ b/include/linux/shared-buffer.h @@ -0,0 +1,55 @@ +/* + * Framework for shared buffer + * + * Copyright (C) 2011 Samsung Electronics Co., Ltd. + * Author: Tomasz Stanislawski, t.stanislaws@samsung.com + * + * 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. + */ + +#ifndef _LINUX_SHARED_BUFFER_H +#define _LINUX_SHARED_BUFFER_H + +#include <linux/err.h> + +/** + * struct shrbuf - shared buffer instance + * @get: increase number of a buffer's users + * @put: decrease number of a buffer's user, release resources if needed + * @dma_addr: start address of a contiguous buffer + * @size: size of a contiguous buffer + * + * Both get/put methods are required. The structure is dedicated for + * embedding. The fields dma_addr and size are used for proof-of-concept + * purpose. They will be substituted by scatter-gatter lists. + */ +struct shrbuf { + void (*get)(struct shrbuf *); + void (*put)(struct shrbuf *); + unsigned long dma_addr; + unsigned long size; +}; + +#ifdef CONFIG_SHARED_BUFFER + +int shrbuf_export(struct shrbuf *sb); + +struct shrbuf *shrbuf_import(int fd); + +#else + +static inline int shrbuf_export(struct shrbuf *sb) +{ + return -ENODEV; +} + +static inline struct shrbuf *shrbuf_import(int fd) +{ + return ERR_PTR(-ENODEV); +} + +#endif /* CONFIG_SHARED_BUFFER */ + +#endif /* _LINUX_SHARED_BUFFER_H */