mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
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:
@@ -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);
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user