dma-buf: add release callback support

Change-Id: Ibfb4ffe3d97fae0a27f20032fdfbc3cc561aa375
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
This commit is contained in:
Mark Yao
2017-03-20 09:46:47 +08:00
committed by Huang, Tao
parent 6db46c9e7e
commit faedd820db
2 changed files with 56 additions and 0 deletions

View File

@@ -36,6 +36,12 @@
static inline int is_dma_buf_file(struct file *);
struct dma_buf_callback {
struct list_head list;
void (*callback)(void *);
void *data;
};
struct dma_buf_list {
struct list_head head;
struct mutex lock;
@@ -46,6 +52,7 @@ static struct dma_buf_list db_list;
static int dma_buf_release(struct inode *inode, struct file *file)
{
struct dma_buf *dmabuf;
struct dma_buf_callback *cb, *tmp;
if (!is_dma_buf_file(file))
return -EINVAL;
@@ -64,6 +71,13 @@ static int dma_buf_release(struct inode *inode, struct file *file)
*/
BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active);
list_for_each_entry_safe(cb, tmp, &dmabuf->release_callbacks, list) {
if (cb->callback)
cb->callback(cb->data);
list_del(&cb->list);
kfree(cb);
}
dmabuf->ops->release(dmabuf);
mutex_lock(&db_list.lock);
@@ -266,6 +280,37 @@ static inline int is_dma_buf_file(struct file *file)
return file->f_op == &dma_buf_fops;
}
int dma_buf_set_release_callback(struct dma_buf *dmabuf,
void (*callback)(void *), void *data)
{
struct dma_buf_callback *cb;
if (WARN_ON(dma_buf_get_release_callback_data(dmabuf, callback)))
return -EINVAL;
cb = kzalloc(sizeof(*cb), GFP_KERNEL);
if (!cb)
return -ENOMEM;
cb->callback = callback;
cb->data = data;
list_add_tail(&cb->list, &dmabuf->release_callbacks);
return 0;
}
void *dma_buf_get_release_callback_data(struct dma_buf *dmabuf,
void (*callback)(void *))
{
struct dma_buf_callback *cb, *tmp;
list_for_each_entry_safe(cb, tmp, &dmabuf->release_callbacks, list) {
if (cb->callback == callback)
return cb->data;
}
return NULL;
}
/**
* dma_buf_export - Creates a new dma_buf, and associates an anon file
* with this buffer, so it can be exported.
@@ -341,6 +386,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
mutex_init(&dmabuf->lock);
INIT_LIST_HEAD(&dmabuf->attachments);
INIT_LIST_HEAD(&dmabuf->release_callbacks);
mutex_lock(&db_list.lock);
list_add(&dmabuf->list_node, &db_list.head);

View File

@@ -90,6 +90,9 @@ struct dma_buf_ops {
* if the call would block.
*/
int (*set_release_callback)(void (*release_callback)(void *data),
void *data);
void *(*get_release_callback_data)(void *callback);
/* after final dma_buf_put() */
void (*release)(struct dma_buf *);
@@ -125,6 +128,7 @@ struct dma_buf {
size_t size;
struct file *file;
struct list_head attachments;
struct list_head release_callbacks;
const struct dma_buf_ops *ops;
/* mutex to serialize list manipulation, attach/detach and vmap/unmap */
struct mutex lock;
@@ -209,6 +213,12 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
get_file(dmabuf->file);
}
int dma_buf_set_release_callback(struct dma_buf *dmabuf,
void (*callback)(void *), void *data);
void *dma_buf_get_release_callback_data(struct dma_buf *dmabuf,
void (*callback)(void *));
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
struct device *dev);
void dma_buf_detach(struct dma_buf *dmabuf,