Skip to content

Commit 9c557a7

Browse files
HermanChenrkhuangtao
authored andcommitted
video: rockchip: mpp: Fix deinit failure memory leak
The dmabuf allocated by video will leaked when media process exit abnormal, this patch changes the deinit for mpp driver to fix it. Tested on RK3588 Debian: step1: GST_DEBUG=fpsdisplaysink:6 gst-play-1.0 /data/1.mp4 --use-playbin3 \ --audiosink=fakesink --videosink="fpsdisplaysink \ video-sink=waylandsink signal-fps-measurements=true" step2: ctrl + c to kill process step3: cat /proc/rk_dmabuf/dev to check dmabuf stat Tested-by: Jianqun Xu <[email protected]> Signed-off-by: Herman Chen <[email protected]> Change-Id: Ia3906b3a0bb5ec6511fc8d8abefadc37d6287c89
1 parent b53829d commit 9c557a7

File tree

3 files changed

+84
-107
lines changed

3 files changed

+84
-107
lines changed

drivers/video/rockchip/mpp/mpp_common.c

Lines changed: 67 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ static struct mpp_task_msgs *get_task_msgs(struct mpp_session *session)
271271
session->msgs_cnt++;
272272
spin_unlock_irqrestore(&session->lock_msgs, flags);
273273

274-
mpp_debug_func(DEBUG_TASK_INFO, "session %p:%d msgs cnt %d\n",
275-
session, session->index, session->msgs_cnt);
274+
mpp_debug_func(DEBUG_TASK_INFO, "session %d:%d msgs cnt %d\n",
275+
session->pid, session->index, session->msgs_cnt);
276276

277277
return msgs;
278278
}
@@ -319,8 +319,7 @@ static void clear_task_msgs(struct mpp_session *session)
319319
kfree(msgs);
320320
}
321321

322-
static int mpp_session_clear(struct mpp_dev *mpp,
323-
struct mpp_session *session)
322+
static void mpp_session_clear_pending(struct mpp_session *session)
324323
{
325324
struct mpp_task *task = NULL, *n;
326325

@@ -335,8 +334,49 @@ static int mpp_session_clear(struct mpp_dev *mpp,
335334
kref_put(&task->ref, mpp_free_task);
336335
}
337336
mutex_unlock(&session->pending_lock);
337+
}
338338

339-
return 0;
339+
void mpp_session_cleanup_detach(struct mpp_taskqueue *queue, struct kthread_work *work)
340+
{
341+
struct mpp_session *session, *n;
342+
343+
if (!atomic_read(&queue->detach_count))
344+
return;
345+
346+
mutex_lock(&queue->session_lock);
347+
list_for_each_entry_safe(session, n, &queue->session_detach, session_link) {
348+
s32 task_count = atomic_read(&session->task_count);
349+
350+
if (!task_count) {
351+
list_del_init(&session->session_link);
352+
atomic_dec(&queue->detach_count);
353+
}
354+
355+
mutex_unlock(&queue->session_lock);
356+
357+
if (task_count) {
358+
mpp_dbg_session("session %d:%d task not finished %d\n",
359+
session->pid, session->index,
360+
atomic_read(&queue->detach_count));
361+
362+
mpp_session_clear_pending(session);
363+
} else {
364+
mpp_dbg_session("queue detach %d\n",
365+
atomic_read(&queue->detach_count));
366+
367+
mpp_session_deinit(session);
368+
}
369+
370+
mutex_lock(&queue->session_lock);
371+
}
372+
mutex_unlock(&queue->session_lock);
373+
374+
if (atomic_read(&queue->detach_count)) {
375+
mpp_dbg_session("queue detach %d again\n",
376+
atomic_read(&queue->detach_count));
377+
378+
kthread_queue_work(&queue->worker, work);
379+
}
340380
}
341381

342382
static struct mpp_session *mpp_session_init(void)
@@ -372,7 +412,7 @@ static void mpp_session_deinit_default(struct mpp_session *session)
372412
if (mpp->dev_ops->free_session)
373413
mpp->dev_ops->free_session(session);
374414

375-
mpp_session_clear(mpp, session);
415+
mpp_session_clear_pending(session);
376416

377417
if (session->dma) {
378418
mpp_iommu_down_write(mpp->iommu_info);
@@ -393,32 +433,25 @@ static void mpp_session_deinit_default(struct mpp_session *session)
393433
list_del_init(&session->session_link);
394434
}
395435

396-
int mpp_session_deinit(struct mpp_session *session)
436+
void mpp_session_deinit(struct mpp_session *session)
397437
{
398-
u32 task_count = atomic_read(&session->task_count);
399-
400-
mpp_dbg_session("session %p:%d task %d release\n",
401-
session, session->index, task_count);
402-
if (task_count)
403-
return -1;
438+
mpp_dbg_session("session %d:%d task %d deinit\n", session->pid,
439+
session->index, atomic_read(&session->task_count));
404440

405441
if (likely(session->deinit))
406442
session->deinit(session);
407443
else
408444
pr_err("invalid NULL session deinit function\n");
409445

410-
mpp_dbg_session("session %p:%d deinit\n", session, session->index);
411-
412446
clear_task_msgs(session);
413447

414448
kfree(session);
415-
return 0;
416449
}
417450

418451
static void mpp_session_attach_workqueue(struct mpp_session *session,
419452
struct mpp_taskqueue *queue)
420453
{
421-
mpp_dbg_session("session %p:%d attach\n", session, session->index);
454+
mpp_dbg_session("session %d:%d attach\n", session->pid, session->index);
422455
mutex_lock(&queue->session_lock);
423456
list_add_tail(&session->session_link, &queue->session_attach);
424457
mutex_unlock(&queue->session_lock);
@@ -432,14 +465,14 @@ static void mpp_session_detach_workqueue(struct mpp_session *session)
432465
if (!session->mpp || !session->mpp->queue)
433466
return;
434467

435-
mpp_dbg_session("session %p:%d detach\n", session, session->index);
468+
mpp_dbg_session("session %d:%d detach\n", session->pid, session->index);
436469
mpp = session->mpp;
437470
queue = mpp->queue;
438471

439472
mutex_lock(&queue->session_lock);
440473
list_del_init(&session->session_link);
441474
list_add_tail(&session->session_link, &queue->session_detach);
442-
queue->detach_count++;
475+
atomic_inc(&queue->detach_count);
443476
mutex_unlock(&queue->session_lock);
444477

445478
mpp_taskqueue_trigger_work(mpp);
@@ -521,15 +554,18 @@ static void mpp_task_timeout_work(struct work_struct *work_s)
521554
return;
522555
}
523556

524-
mpp_err("task %p processing time out!\n", task);
525557
if (!task->session) {
526558
mpp_err("task %p, task->session is null.\n", task);
527559
return;
528560
}
561+
529562
session = task->session;
563+
mpp_err("task %d:%d:%d processing time out!\n", session->pid,
564+
session->index, task->task_id);
530565

531566
if (!session->mpp) {
532-
mpp_err("session %p, session->mpp is null.\n", session);
567+
mpp_err("session %d:%d, session mpp is null.\n", session->pid,
568+
session->index);
533569
return;
534570
}
535571

@@ -790,28 +826,7 @@ static void mpp_task_worker_default(struct kthread_work *work_s)
790826
}
791827

792828
done:
793-
mutex_lock(&queue->session_lock);
794-
while (queue->detach_count) {
795-
struct mpp_session *session = NULL;
796-
797-
session = list_first_entry_or_null(&queue->session_detach, struct mpp_session,
798-
session_link);
799-
if (session) {
800-
list_del_init(&session->session_link);
801-
queue->detach_count--;
802-
}
803-
804-
mutex_unlock(&queue->session_lock);
805-
806-
if (session) {
807-
mpp_dbg_session("%s detach count %d\n", dev_name(mpp->dev),
808-
queue->detach_count);
809-
mpp_session_deinit(session);
810-
}
811-
812-
mutex_lock(&queue->session_lock);
813-
}
814-
mutex_unlock(&queue->session_lock);
829+
mpp_session_cleanup_detach(queue, work_s);
815830
}
816831

817832
static int mpp_wait_result_default(struct mpp_session *session,
@@ -823,7 +838,8 @@ static int mpp_wait_result_default(struct mpp_session *session,
823838

824839
task = mpp_session_get_pending_task(session);
825840
if (!task) {
826-
mpp_err("session %p pending list is empty!\n", session);
841+
mpp_err("session %d:%d pending list is empty!\n",
842+
session->pid, session->index);
827843
return -EIO;
828844
}
829845
mpp = mpp_get_task_used_device(task, session);
@@ -837,8 +853,8 @@ static int mpp_wait_result_default(struct mpp_session *session,
837853
} else {
838854
atomic_inc(&task->abort_request);
839855
set_bit(TASK_STATE_ABORT, &task->state);
840-
mpp_err("timeout, pid %d session %p:%d count %d cur_task %p id %d\n",
841-
session->pid, session, session->index,
856+
mpp_err("timeout, pid %d session %d:%d count %d cur_task %p id %d\n",
857+
session->pid, session->pid, session->index,
842858
atomic_read(&session->task_count), task,
843859
task->task_id);
844860
}
@@ -947,6 +963,7 @@ struct mpp_taskqueue *mpp_taskqueue_init(struct device *dev)
947963
/* default taskqueue has max 16 task capacity */
948964
queue->task_capacity = MPP_MAX_TASK_CAPACITY;
949965
atomic_set(&queue->reset_request, 0);
966+
atomic_set(&queue->detach_count, 0);
950967
atomic_set(&queue->task_id, 0);
951968

952969
return queue;
@@ -1232,7 +1249,7 @@ static int mpp_process_request(struct mpp_session *session,
12321249
if (!mpp)
12331250
return -EINVAL;
12341251

1235-
mpp_session_clear(mpp, session);
1252+
mpp_session_clear_pending(session);
12361253
mpp_iommu_down_write(mpp->iommu_info);
12371254
ret = mpp_dma_session_destroy(session->dma);
12381255
mpp_iommu_up_write(mpp->iommu_info);
@@ -1435,8 +1452,8 @@ static int mpp_collect_msgs(struct list_head *head, struct mpp_session *session,
14351452
msgs = get_task_msgs(session);
14361453

14371454
if (!msgs) {
1438-
pr_err("session %p:%d failed to get task msgs",
1439-
session, session->index);
1455+
pr_err("session %d:%d failed to get task msgs",
1456+
session->pid, session->index);
14401457
return -EINVAL;
14411458
}
14421459

@@ -1621,7 +1638,7 @@ static int mpp_dev_release(struct inode *inode, struct file *filp)
16211638
/* wait for task all done */
16221639
atomic_inc(&session->release_request);
16231640

1624-
if (session->mpp)
1641+
if (session->mpp || atomic_read(&session->task_count))
16251642
mpp_session_detach_workqueue(session);
16261643
else
16271644
mpp_session_deinit(session);

drivers/video/rockchip/mpp/mpp_common.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ struct mpp_taskqueue {
471471
struct list_head session_attach;
472472
/* link to session session_link for detached sessions */
473473
struct list_head session_detach;
474-
u32 detach_count;
474+
atomic_t detach_count;
475475

476476
atomic_t task_id;
477477
/* lock for pending list */
@@ -635,7 +635,9 @@ int mpp_task_dump_reg(struct mpp_dev *mpp,
635635
int mpp_task_dump_hw_reg(struct mpp_dev *mpp);
636636
void mpp_free_task(struct kref *ref);
637637

638-
int mpp_session_deinit(struct mpp_session *session);
638+
void mpp_session_deinit(struct mpp_session *session);
639+
void mpp_session_cleanup_detach(struct mpp_taskqueue *queue,
640+
struct kthread_work *work);
639641

640642
int mpp_dev_probe(struct mpp_dev *mpp,
641643
struct platform_device *pdev);

drivers/video/rockchip/mpp/mpp_rkvdec2_link.c

Lines changed: 13 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,28 +1405,7 @@ void rkvdec2_link_worker(struct kthread_work *work_s)
14051405
rkvdec2_link_power_off(mpp);
14061406
}
14071407

1408-
mutex_lock(&queue->session_lock);
1409-
while (queue->detach_count) {
1410-
struct mpp_session *session = NULL;
1411-
1412-
session = list_first_entry_or_null(&queue->session_detach, struct mpp_session,
1413-
session_link);
1414-
if (session) {
1415-
list_del_init(&session->session_link);
1416-
queue->detach_count--;
1417-
}
1418-
1419-
mutex_unlock(&queue->session_lock);
1420-
1421-
if (session) {
1422-
mpp_dbg_session("%s detach count %d\n", dev_name(mpp->dev),
1423-
queue->detach_count);
1424-
mpp_session_deinit(session);
1425-
}
1426-
1427-
mutex_lock(&queue->session_lock);
1428-
}
1429-
mutex_unlock(&queue->session_lock);
1408+
mpp_session_cleanup_detach(queue, work_s);
14301409
}
14311410

14321411
void rkvdec2_link_session_deinit(struct mpp_session *session)
@@ -1439,9 +1418,9 @@ void rkvdec2_link_session_deinit(struct mpp_session *session)
14391418

14401419
if (session->dma) {
14411420
mpp_dbg_session("session %d destroy dma\n", session->index);
1442-
mpp_iommu_down_read(mpp->iommu_info);
1421+
mpp_iommu_down_write(mpp->iommu_info);
14431422
mpp_dma_session_destroy(session->dma);
1444-
mpp_iommu_up_read(mpp->iommu_info);
1423+
mpp_iommu_up_write(mpp->iommu_info);
14451424
session->dma = NULL;
14461425
}
14471426
if (session->srv) {
@@ -1569,36 +1548,6 @@ int rkvdec2_ccu_link_init(struct platform_device *pdev, struct rkvdec2_dev *dec)
15691548
return 0;
15701549
}
15711550

1572-
static int rkvdec2_ccu_link_session_detach(struct mpp_dev *mpp,
1573-
struct mpp_taskqueue *queue)
1574-
{
1575-
mutex_lock(&queue->session_lock);
1576-
while (queue->detach_count) {
1577-
struct mpp_session *session = NULL;
1578-
1579-
session = list_first_entry_or_null(&queue->session_detach,
1580-
struct mpp_session,
1581-
session_link);
1582-
if (session) {
1583-
list_del_init(&session->session_link);
1584-
queue->detach_count--;
1585-
}
1586-
1587-
mutex_unlock(&queue->session_lock);
1588-
1589-
if (session) {
1590-
mpp_dbg_session("%s detach count %d\n", dev_name(mpp->dev),
1591-
queue->detach_count);
1592-
mpp_session_deinit(session);
1593-
}
1594-
1595-
mutex_lock(&queue->session_lock);
1596-
}
1597-
mutex_unlock(&queue->session_lock);
1598-
1599-
return 0;
1600-
}
1601-
16021551
static int rkvdec2_ccu_power_on(struct mpp_taskqueue *queue,
16031552
struct rkvdec2_ccu *ccu)
16041553
{
@@ -1966,9 +1915,18 @@ void rkvdec2_soft_ccu_worker(struct kthread_work *work_s)
19661915
goto done;
19671916

19681917
if (test_bit(TASK_STATE_ABORT, &mpp_task->state)) {
1918+
struct rkvdec2_task *dec_task = to_rkvdec2_task(mpp_task);
1919+
19691920
mutex_lock(&queue->pending_lock);
19701921
list_del_init(&mpp_task->queue_link);
1922+
1923+
kref_get(&mpp_task->ref);
1924+
set_bit(TASK_STATE_ABORT_READY, &mpp_task->state);
1925+
set_bit(TASK_STATE_PROC_DONE, &mpp_task->state);
1926+
19711927
mutex_unlock(&queue->pending_lock);
1928+
wake_up(&dec_task->wait);
1929+
kref_put(&mpp_task->ref, rkvdec2_link_free_task);
19721930
goto get_task;
19731931
}
19741932
/* find one core is idle */
@@ -2001,7 +1959,7 @@ void rkvdec2_soft_ccu_worker(struct kthread_work *work_s)
20011959
rkvdec2_ccu_power_off(queue, dec->ccu);
20021960
out:
20031961
/* session detach out of queue */
2004-
rkvdec2_ccu_link_session_detach(mpp, queue);
1962+
mpp_session_cleanup_detach(queue, work_s);
20051963

20061964
mpp_debug_leave();
20071965
}

0 commit comments

Comments
 (0)