dma-buf: add release callback support

This patch is required by system on RK3368 SoCs.

Since its system used ion and drm drivers together, one dma-buf
may used by two devices, if one device deattached buffer, then
the other one need to map sg again, that takes time several ms.

The patch fix it by set buffer release operation in a list, and
do release after final dma_buf_put.

Change-Id: Ibfb4ffe3d97fae0a27f20032fdfbc3cc561aa375
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
Signed-off-by: Jianqun Xu <jay.xu@rock-chips.com>
This commit is contained in:
Mark Yao
2017-03-20 09:46:47 +08:00
committed by Tao Huang
parent 758a5b4ecb
commit 3841912481
2 changed files with 85 additions and 2 deletions

View File

@@ -41,6 +41,14 @@
static inline int is_dma_buf_file(struct file *);
#ifdef CONFIG_ARCH_ROCKCHIP
struct dma_buf_callback {
struct list_head list;
void (*callback)(void *);
void *data;
};
#endif
struct dma_buf_list {
struct list_head head;
struct mutex lock;
@@ -86,6 +94,9 @@ static struct file_system_type dma_buf_fs_type = {
static int dma_buf_release(struct inode *inode, struct file *file)
{
struct dma_buf *dmabuf;
#ifdef CONFIG_ARCH_ROCKCHIP
struct dma_buf_callback *cb, *tmp;
#endif
if (!is_dma_buf_file(file))
return -EINVAL;
@@ -104,6 +115,17 @@ static int dma_buf_release(struct inode *inode, struct file *file)
*/
BUG_ON(dmabuf->cb_shared.active || dmabuf->cb_excl.active);
#ifdef CONFIG_ARCH_ROCKCHIP
mutex_lock(&dmabuf->release_lock);
list_for_each_entry_safe(cb, tmp, &dmabuf->release_callbacks, list) {
if (cb->callback)
cb->callback(cb->data);
list_del(&cb->list);
kfree(cb);
}
mutex_unlock(&dmabuf->release_lock);
#endif
dmabuf->ops->release(dmabuf);
mutex_lock(&db_list.lock);
@@ -457,6 +479,47 @@ err_alloc_file:
return file;
}
#ifdef CONFIG_ARCH_ROCKCHIP
void *dma_buf_get_release_callback_data(struct dma_buf *dmabuf,
void (*callback)(void *))
{
struct dma_buf_callback *cb, *tmp;
void *result = NULL;
mutex_lock(&dmabuf->release_lock);
list_for_each_entry_safe(cb, tmp, &dmabuf->release_callbacks, list) {
if (cb->callback == callback) {
result = cb->data;
break;
}
}
mutex_unlock(&dmabuf->release_lock);
return result;
}
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;
mutex_lock(&dmabuf->release_lock);
list_add_tail(&cb->list, &dmabuf->release_callbacks);
mutex_unlock(&dmabuf->release_lock);
return 0;
}
#endif
/**
* DOC: dma buf device access
*
@@ -564,7 +627,10 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
mutex_init(&dmabuf->lock);
INIT_LIST_HEAD(&dmabuf->attachments);
#ifdef CONFIG_ARCH_ROCKCHIP
mutex_init(&dmabuf->release_lock);
INIT_LIST_HEAD(&dmabuf->release_callbacks);
#endif
mutex_lock(&db_list.lock);
list_add(&dmabuf->list_node, &db_list.head);
mutex_unlock(&db_list.lock);

View File

@@ -146,7 +146,12 @@ struct dma_buf_ops {
/* TODO: Add try_map_dma_buf version, to return immed with -EBUSY
* if the call would block.
*/
#ifdef CONFIG_ARCH_ROCKCHIP
int (*set_release_callback)(void (*release_callback)(void *data),
void *data);
void *(*get_release_callback_data)(void *callback);
/* after final dma_buf_put() */
#endif
/**
* @release:
*
@@ -283,6 +288,10 @@ struct dma_buf {
size_t size;
struct file *file;
struct list_head attachments;
#ifdef CONFIG_ARCH_ROCKCHIP
struct list_head release_callbacks;
struct mutex release_lock;
#endif
const struct dma_buf_ops *ops;
struct mutex lock;
unsigned vmapping_counter;
@@ -376,6 +385,14 @@ static inline void get_dma_buf(struct dma_buf *dmabuf)
get_file(dmabuf->file);
}
#ifdef CONFIG_ARCH_ROCKCHIP
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 *));
#endif
struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
struct device *dev);
void dma_buf_detach(struct dma_buf *dmabuf,