mirror of
https://github.com/armbian/linux.git
synced 2026-01-06 10:13:00 -08:00
dma-buf: add release callback support
Change-Id: Ibfb4ffe3d97fae0a27f20032fdfbc3cc561aa375 Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user