video: rockchip: rga3: fix map/unmap buffers in mutex_lock

Signed-off-by: Yu Qiaowei <cerf.yu@rock-chips.com>
Change-Id: I9570af5ddef114c1cf322d62959589d0c2cc1b24
This commit is contained in:
Yu Qiaowei
2024-08-13 16:19:56 +08:00
committed by Tao Huang
parent 310cad87e0
commit c09c257b5d

View File

@@ -828,32 +828,46 @@ static int rga_mm_map_buffer(struct rga_external_buffer *external_buffer,
static void rga_mm_kref_release_buffer(struct kref *ref)
{
struct rga_internal_buffer *internal_buffer;
struct rga_mm *mm = rga_drvdata->mm;
internal_buffer = container_of(ref, struct rga_internal_buffer, refcount);
rga_mm_unmap_buffer(internal_buffer);
idr_remove(&mm->memory_idr, internal_buffer->handle);
mm->buffer_count--;
mutex_unlock(&mm->lock);
idr_remove(&rga_drvdata->mm->memory_idr, internal_buffer->handle);
rga_mm_unmap_buffer(internal_buffer);
kfree(internal_buffer);
rga_drvdata->mm->buffer_count--;
mutex_lock(&mm->lock);
}
/* Force release the current internal_buffer from the IDR. */
static void rga_mm_force_releaser_buffer(struct rga_internal_buffer *buffer)
{
struct rga_mm *mm = rga_drvdata->mm;
WARN_ON(!mutex_is_locked(&mm->lock));
idr_remove(&mm->memory_idr, buffer->handle);
mm->buffer_count--;
rga_mm_unmap_buffer(buffer);
kfree(buffer);
}
/*
* Called at driver close to release the memory's handle references.
*/
static int rga_mm_handle_remove(int id, void *ptr, void *data)
static int rga_mm_buffer_destroy_for_idr(int id, void *ptr, void *data)
{
struct rga_internal_buffer *internal_buffer = ptr;
rga_mm_kref_release_buffer(&internal_buffer->refcount);
rga_mm_force_releaser_buffer(internal_buffer);
return 0;
}
static void rga_mm_buffer_destroy(struct rga_internal_buffer *buffer)
{
rga_mm_kref_release_buffer(&buffer->refcount);
}
static struct rga_internal_buffer *
rga_mm_lookup_external(struct rga_mm *mm_session,
struct rga_external_buffer *external_buffer,
@@ -2324,6 +2338,8 @@ int rga_mm_import_buffer(struct rga_external_buffer *external_buffer,
return internal_buffer->handle;
}
mutex_unlock(&mm->lock);
/* finally, map and cached external_buffer in rga_mm */
internal_buffer = kzalloc(sizeof(struct rga_internal_buffer), GFP_KERNEL);
if (internal_buffer == NULL) {
@@ -2340,6 +2356,7 @@ int rga_mm_import_buffer(struct rga_external_buffer *external_buffer,
kref_init(&internal_buffer->refcount);
internal_buffer->session = session;
mutex_lock(&mm->lock);
/*
* Get the user-visible handle using idr. Preload and perform
* allocation under our spinlock.
@@ -2350,6 +2367,8 @@ int rga_mm_import_buffer(struct rga_external_buffer *external_buffer,
if (new_id < 0) {
pr_err("internal_buffer alloc id failed!\n");
ret = new_id;
mutex_unlock(&mm->lock);
goto FREE_INTERNAL_BUFFER;
}
@@ -2361,16 +2380,15 @@ int rga_mm_import_buffer(struct rga_external_buffer *external_buffer,
rga_mm_dump_buffer(internal_buffer);
}
mutex_unlock(&mm->lock);
if (DEBUGGER_EN(TIME))
pr_info("handle[%d], import buffer cost %lld us\n",
internal_buffer->handle, ktime_us_delta(ktime_get(), timestamp));
mutex_unlock(&mm->lock);
return internal_buffer->handle;
FREE_INTERNAL_BUFFER:
mutex_unlock(&mm->lock);
kfree(internal_buffer);
return ret;
@@ -2433,7 +2451,7 @@ int rga_mm_session_release_buffer(struct rga_session *session)
if (session == buffer->session) {
pr_err("[tgid:%d] Destroy handle[%d] when the user exits\n",
session->tgid, buffer->handle);
rga_mm_buffer_destroy(buffer);
rga_mm_force_releaser_buffer(buffer);
}
}
@@ -2465,7 +2483,7 @@ int rga_mm_remove(struct rga_mm **mm_session)
mutex_lock(&mm->lock);
idr_for_each(&mm->memory_idr, &rga_mm_handle_remove, mm);
idr_for_each(&mm->memory_idr, &rga_mm_buffer_destroy_for_idr, mm);
idr_destroy(&mm->memory_idr);
mutex_unlock(&mm->lock);