aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/s5p-fimc/fimc-capture.c
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2012-05-17 13:22:10 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-06-25 08:18:02 -0400
commite3fc82e8b9f550d28f05600b98bcc8c26beef2ef (patch)
tree63d5076084994e5057beed3f59c0ae15159b85fc /drivers/media/video/s5p-fimc/fimc-capture.c
parent0b4b1f199d367762ddb68cb3303431fa6c84a7d6 (diff)
[media] s5p-fimc: Prevent lock-up in multiple sensor systems
The camera clocks managed by the driver were improperly reference counted and remained disabled when multiple video nodes were opened simultaneously. It manifested itself with following warning: [12.920000] WARNING: at drivers/media/video/s5p-fimc/fimc-mdevice.c:787 __fimc_md_set_camclk+0x1c0/0x1dc() [13.005000] Modules linked in: [13.005000] Backtrace: [13.040000] [<c0013084>] (dump_backtrace+0x0/0x10c) from [<c0454b70>] (dump_stack+0x18/0x1c) [13.070000] r7:00000009 r6:00000313 r5:c02d576c r4:00000000 [13.155000] [<c0454b58>] (dump_stack+0x0/0x1c) from [<c0022ec4>] (warn_slowpath_common+0x54/0x6c) [13.285000] [<c0022e70>] (warn_slowpath_common+0x0/0x6c) from [<c0022f00>] (warn_slowpath_null+0x24/0x2c) [13.360000] r9:e1981010 r8:00000000 r7:c061d3fc r6:e1981010 r5:e1981030 [13.430000] r4:00000000 [13.430000] [<c0022edc>] (warn_slowpath_null+0x0/0x2c) from [<c02d576c>] (__fimc_md_set_camclk+0x1c0/0x1dc) [13.550000] [<c02d55ac>] (__fimc_md_set_camclk+0x0/0x1dc) from [<c02d57b0>] (fimc_md_set_camclk+0x28/0x2c) [13.630000] [<c02d5788>] (fimc_md_set_camclk+0x0/0x2c) from [<c02d57e8>] (__fimc_pipeline_shutdown+0x34/0x50) [13.705000] [<c02d57b4>] (__fimc_pipeline_shutdown+0x0/0x50) from [<c02d5844>] (fimc_pipeline_shutdown+0x40/0x58) [13.765000] r5:e2391200 r4:e2357704 [13.805000] [<c02d5804>] (fimc_pipeline_shutdown+0x0/0x58) from [<c02d4754>] (fimc_capture_close+0xcc/0xe4) [13.915000] r5:e1b396c0 r4:e2357410 [13.915000] [<c02d4688>] (fimc_capture_close+0x0/0xe4) from [<c02b2d5c>] (v4l2_release+0x5c/0x80) [13.970000] r7:00000010 r6:e1d2d990 r5:e1b396c0 r4:e2394800 [14.000000] [<c02b2d00>] (v4l2_release+0x0/0x80) from [<c00b66cc>] (fput+0xc0/0x22c) [14.015000] r5:c157ef30 r4:e1b396c0 [14.015000] [<c00b660c>] (fput+0x0/0x22c) from [<c00b2ca0>] (filp_close+0x60/0x80) [14.080000] [<c00b2c40>] (filp_close+0x0/0x80) from [<c00b2d78>] (sys_close+0xb8/0xf4) [14.125000] r7:00000001 r6:e1b396c0 r5:c1400340 r4:c1400300 [14.125000] [<c00b2cc0>] (sys_close+0x0/0xf4) from [<c000f300>] (ret_fast_syscall+0x0/0x30) [14.205000] r7:00000006 r6:beee5b94 r5:00000003 r4:b6f64fac Fix this, as well as potential memory leaks due to not calling v4l2_fh_release() on some error paths. Also remove some error logs printed for events that aren't critical and are normal conditions for some system configurations. Also check if the device have been properly run-time enabled during video node open. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/s5p-fimc/fimc-capture.c')
-rw-r--r--drivers/media/video/s5p-fimc/fimc-capture.c46
1 files changed, 24 insertions, 22 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-capture.c b/drivers/media/video/s5p-fimc/fimc-capture.c
index 0fd12dfbd3db..71e483847a17 100644
--- a/drivers/media/video/s5p-fimc/fimc-capture.c
+++ b/drivers/media/video/s5p-fimc/fimc-capture.c
@@ -480,37 +480,39 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc);
480static int fimc_capture_open(struct file *file) 480static int fimc_capture_open(struct file *file)
481{ 481{
482 struct fimc_dev *fimc = video_drvdata(file); 482 struct fimc_dev *fimc = video_drvdata(file);
483 int ret = v4l2_fh_open(file); 483 int ret;
484
485 if (ret)
486 return ret;
487 484
488 dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state); 485 dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
489 486
490 /* Return if the corresponding video mem2mem node is already opened. */
491 if (fimc_m2m_active(fimc)) 487 if (fimc_m2m_active(fimc))
492 return -EBUSY; 488 return -EBUSY;
493 489
494 set_bit(ST_CAPT_BUSY, &fimc->state); 490 set_bit(ST_CAPT_BUSY, &fimc->state);
495 pm_runtime_get_sync(&fimc->pdev->dev); 491 ret = pm_runtime_get_sync(&fimc->pdev->dev);
496 492 if (ret < 0)
497 if (++fimc->vid_cap.refcnt == 1) { 493 return ret;
498 ret = fimc_pipeline_initialize(&fimc->pipeline, 494
499 &fimc->vid_cap.vfd->entity, true); 495 ret = v4l2_fh_open(file);
500 if (ret < 0) { 496 if (ret)
501 dev_err(&fimc->pdev->dev, 497 return ret;
502 "Video pipeline initialization failed\n"); 498
503 clear_bit(ST_CAPT_BUSY, &fimc->state); 499 if (++fimc->vid_cap.refcnt != 1)
504 pm_runtime_put_sync(&fimc->pdev->dev); 500 return 0;
505 fimc->vid_cap.refcnt--;
506 v4l2_fh_release(file);
507 return ret;
508 }
509 ret = fimc_capture_ctrls_create(fimc);
510 501
511 if (!ret && !fimc->vid_cap.user_subdev_api) 502 ret = fimc_pipeline_initialize(&fimc->pipeline,
512 ret = fimc_capture_set_default_format(fimc); 503 &fimc->vid_cap.vfd->entity, true);
504 if (ret < 0) {
505 clear_bit(ST_CAPT_BUSY, &fimc->state);
506 pm_runtime_put_sync(&fimc->pdev->dev);
507 fimc->vid_cap.refcnt--;
508 v4l2_fh_release(file);
509 return ret;
513 } 510 }
511 ret = fimc_capture_ctrls_create(fimc);
512
513 if (!ret && !fimc->vid_cap.user_subdev_api)
514 ret = fimc_capture_set_default_format(fimc);
515
514 return ret; 516 return ret;
515} 517}
516 518