mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
video: rockchip: mpp: fix unused buffer move fail issue
When dmabuf cache disable: 1.move most recently used link node to link tail, instead of calculate oldest ktime when buffer full. 2.For those buffer import by ioctl MPP_CMD_TRANS_FD_TO_IOVA, move to static_list instead of used_list, and don't increase extra kref, so that it will release when user space call ioctl MPP_CMD_RELEASE_FD. Change-Id: I38f209c24f6cc7e831338e2417050e3ef39226f9 Signed-off-by: Chandler Chen <chandler.chen@rock-chips.com>
This commit is contained in:
@@ -1363,7 +1363,7 @@ static int mpp_process_request(struct mpp_session *session,
|
||||
|
||||
mpp_iommu_down_read(mpp->iommu_info);
|
||||
buffer = mpp_dma_import_fd(mpp->iommu_info,
|
||||
session->dma, fd);
|
||||
session->dma, fd, 1);
|
||||
mpp_iommu_up_read(mpp->iommu_info);
|
||||
if (IS_ERR_OR_NULL(buffer)) {
|
||||
mpp_err("can not import fd %d\n", fd);
|
||||
@@ -1770,7 +1770,7 @@ mpp_task_attach_fd(struct mpp_task *task, int fd)
|
||||
mem_region->is_dup = true;
|
||||
} else {
|
||||
mpp_iommu_down_read(mpp->iommu_info);
|
||||
buffer = mpp_dma_import_fd(mpp->iommu_info, dma, fd);
|
||||
buffer = mpp_dma_import_fd(mpp->iommu_info, dma, fd, 0);
|
||||
mpp_iommu_up_read(mpp->iommu_info);
|
||||
if (IS_ERR(buffer)) {
|
||||
mpp_err("can't import dma-buf %d\n", fd);
|
||||
|
||||
@@ -33,6 +33,7 @@ mpp_dma_find_buffer_fd(struct mpp_dma_session *dma, int fd)
|
||||
struct dma_buf *dmabuf;
|
||||
struct mpp_dma_buffer *out = NULL;
|
||||
struct mpp_dma_buffer *buffer = NULL, *n;
|
||||
int find = 0;
|
||||
|
||||
dmabuf = dma_buf_get(fd);
|
||||
if (IS_ERR(dmabuf))
|
||||
@@ -47,9 +48,26 @@ mpp_dma_find_buffer_fd(struct mpp_dma_session *dma, int fd)
|
||||
*/
|
||||
if (buffer->dmabuf == dmabuf) {
|
||||
out = buffer;
|
||||
find = 1;
|
||||
list_move_tail(&buffer->link, &buffer->dma->used_list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!find) {
|
||||
list_for_each_entry_safe(buffer, n,
|
||||
&dma->static_list, link) {
|
||||
/*
|
||||
* fd may dup several and point the same dambuf.
|
||||
* thus, here should be distinguish with the dmabuf.
|
||||
*/
|
||||
if (buffer->dmabuf == dmabuf) {
|
||||
out = buffer;
|
||||
list_move_tail(&buffer->link, &buffer->dma->static_list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&dma->list_mutex);
|
||||
dma_buf_put(dmabuf);
|
||||
|
||||
@@ -84,22 +102,20 @@ static int
|
||||
mpp_dma_remove_extra_buffer(struct mpp_dma_session *dma)
|
||||
{
|
||||
struct mpp_dma_buffer *n;
|
||||
struct mpp_dma_buffer *oldest = NULL, *buffer = NULL;
|
||||
ktime_t oldest_time = ktime_set(0, 0);
|
||||
struct mpp_dma_buffer *removable = NULL, *buffer = NULL;
|
||||
|
||||
if (dma->buffer_count > dma->max_buffers) {
|
||||
mutex_lock(&dma->list_mutex);
|
||||
list_for_each_entry_safe(buffer, n,
|
||||
&dma->used_list,
|
||||
link) {
|
||||
if (ktime_to_ns(oldest_time) == 0 ||
|
||||
ktime_after(oldest_time, buffer->last_used)) {
|
||||
oldest_time = buffer->last_used;
|
||||
oldest = buffer;
|
||||
if (kref_read(&buffer->ref) == 1) {
|
||||
removable = buffer;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (oldest && kref_read(&oldest->ref) == 1)
|
||||
kref_put(&oldest->ref, mpp_dma_release_buffer);
|
||||
if (removable)
|
||||
kref_put(&removable->ref, mpp_dma_release_buffer);
|
||||
mutex_unlock(&dma->list_mutex);
|
||||
}
|
||||
|
||||
@@ -176,7 +192,7 @@ int mpp_dma_free(struct mpp_dma_buffer *buffer)
|
||||
|
||||
struct mpp_dma_buffer *mpp_dma_import_fd(struct mpp_iommu_info *iommu_info,
|
||||
struct mpp_dma_session *dma,
|
||||
int fd)
|
||||
int fd, int static_use)
|
||||
{
|
||||
int ret = 0;
|
||||
struct sg_table *sgt;
|
||||
@@ -196,10 +212,8 @@ struct mpp_dma_buffer *mpp_dma_import_fd(struct mpp_iommu_info *iommu_info,
|
||||
/* Check whether in dma session */
|
||||
buffer = mpp_dma_find_buffer_fd(dma, fd);
|
||||
if (!IS_ERR_OR_NULL(buffer)) {
|
||||
if (kref_get_unless_zero(&buffer->ref)) {
|
||||
buffer->last_used = ktime_get();
|
||||
if (kref_get_unless_zero(&buffer->ref))
|
||||
return buffer;
|
||||
}
|
||||
dev_dbg(dma->dev, "missing the fd %d\n", fd);
|
||||
}
|
||||
|
||||
@@ -224,7 +238,6 @@ struct mpp_dma_buffer *mpp_dma_import_fd(struct mpp_iommu_info *iommu_info,
|
||||
|
||||
buffer->dmabuf = dmabuf;
|
||||
buffer->dir = DMA_BIDIRECTIONAL;
|
||||
buffer->last_used = ktime_get();
|
||||
|
||||
attach = dma_buf_attach(buffer->dmabuf, dma->dev);
|
||||
if (IS_ERR(attach)) {
|
||||
@@ -247,13 +260,16 @@ struct mpp_dma_buffer *mpp_dma_import_fd(struct mpp_iommu_info *iommu_info,
|
||||
|
||||
kref_init(&buffer->ref);
|
||||
|
||||
if (!IS_ENABLED(CONFIG_DMABUF_CACHE))
|
||||
if (!static_use && !IS_ENABLED(CONFIG_DMABUF_CACHE))
|
||||
/* Increase the reference for used outside the buffer pool */
|
||||
kref_get(&buffer->ref);
|
||||
|
||||
mutex_lock(&dma->list_mutex);
|
||||
dma->buffer_count++;
|
||||
list_add_tail(&buffer->link, &dma->used_list);
|
||||
if (static_use)
|
||||
list_add_tail(&buffer->link, &dma->static_list);
|
||||
else
|
||||
list_add_tail(&buffer->link, &dma->used_list);
|
||||
mutex_unlock(&dma->list_mutex);
|
||||
|
||||
return buffer;
|
||||
@@ -333,6 +349,11 @@ int mpp_dma_session_destroy(struct mpp_dma_session *dma)
|
||||
link) {
|
||||
kref_put(&buffer->ref, mpp_dma_release_buffer);
|
||||
}
|
||||
list_for_each_entry_safe(buffer, n,
|
||||
&dma->static_list,
|
||||
link) {
|
||||
kref_put(&buffer->ref, mpp_dma_release_buffer);
|
||||
}
|
||||
mutex_unlock(&dma->list_mutex);
|
||||
|
||||
kfree(dma);
|
||||
@@ -354,6 +375,7 @@ mpp_dma_session_create(struct device *dev, u32 max_buffers)
|
||||
mutex_init(&dma->list_mutex);
|
||||
INIT_LIST_HEAD(&dma->unused_list);
|
||||
INIT_LIST_HEAD(&dma->used_list);
|
||||
INIT_LIST_HEAD(&dma->static_list);
|
||||
|
||||
if (max_buffers > MPP_SESSION_MAX_BUFFERS) {
|
||||
mpp_debug(DEBUG_IOCTL, "session_max_buffer %d must less than %d\n",
|
||||
|
||||
@@ -57,6 +57,12 @@ struct mpp_dma_session {
|
||||
/* the buffer used in session */
|
||||
struct list_head unused_list;
|
||||
struct list_head used_list;
|
||||
/*
|
||||
* For those buffer import by ioctl MPP_CMD_TRANS_FD_TO_IOVA,
|
||||
* move to static_list instead of used_list and don't increase extra kref,
|
||||
* so that it will release when user space call ioctl MPP_CMD_RELEASE_FD.
|
||||
*/
|
||||
struct list_head static_list;
|
||||
struct mpp_dma_buffer dma_bufs[MPP_SESSION_MAX_BUFFERS];
|
||||
/* the mutex for the above buffer list */
|
||||
struct mutex list_mutex;
|
||||
@@ -108,7 +114,7 @@ int mpp_dma_free(struct mpp_dma_buffer *buffer);
|
||||
|
||||
struct mpp_dma_buffer *
|
||||
mpp_dma_import_fd(struct mpp_iommu_info *iommu_info,
|
||||
struct mpp_dma_session *dma, int fd);
|
||||
struct mpp_dma_session *dma, int fd, int static_use);
|
||||
int mpp_dma_release(struct mpp_dma_session *dma,
|
||||
struct mpp_dma_buffer *buffer);
|
||||
int mpp_dma_release_fd(struct mpp_dma_session *dma, int fd);
|
||||
|
||||
Reference in New Issue
Block a user