From 90e614bb4c581eb588ec26f130fcdd65aa047fa8 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 16 May 2012 11:35:04 -0300 Subject: [media] s5p-fimc: Fix bug in capture node open() When video pipeline initialization fails, the ST_CAPT_BUSY flag needs to be cleared before pm_runtime_put_sync is called. Otherwise the runtime suspend routine tries to suspend device, rather than just turning it off. Also fix potential null pointer dereference in fimc_pipeline_shutdown(). Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-mdevice.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers/media/video/s5p-fimc/fimc-mdevice.c') diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index 6753c45631b8..7450dcdafc87 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c @@ -193,9 +193,13 @@ int __fimc_pipeline_shutdown(struct fimc_pipeline *p) int fimc_pipeline_shutdown(struct fimc_pipeline *p) { - struct media_entity *me = &p->subdevs[IDX_SENSOR]->entity; + struct media_entity *me; int ret; + if (!p || !p->subdevs[IDX_SENSOR]) + return -EINVAL; + + me = &p->subdevs[IDX_SENSOR]->entity; mutex_lock(&me->parent->graph_mutex); ret = __fimc_pipeline_shutdown(p); mutex_unlock(&me->parent->graph_mutex); -- cgit v1.2.3 From d0da3c3565a1dd3cdfa374038d6ccae4b90fe142 Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Wed, 16 May 2012 13:08:30 -0300 Subject: [media] s5p-fimc: Don't create multiple active links to same sink entity The driver is supposed to create active media link from sensor N (or its corresponding s5p-mipi-csis entity) to FIMC.N by default. Instead s5p-mipi-csis.N entity gets always connected by a default active link to FIMC.N, regardless of there are parallel bus sensor entities already connected to FIMC.N. Correct this. Signed-off-by: Sylwester Nawrocki Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-mdevice.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'drivers/media/video/s5p-fimc/fimc-mdevice.c') diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index 7450dcdafc87..dffe4da5eaa0 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c @@ -502,12 +502,12 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) * @source: the source entity to create links to all fimc entities from * @sensor: sensor subdev linked to FIMC[fimc_id] entity, may be null * @pad: the source entity pad index - * @fimc_id: index of the fimc device for which link should be enabled + * @link_mask: bitmask of the fimc devices for which link should be enabled */ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, struct media_entity *source, struct v4l2_subdev *sensor, - int pad, int fimc_id) + int pad, int link_mask) { struct fimc_sensor_info *s_info; struct media_entity *sink; @@ -524,7 +524,7 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, if (!fmd->fimc[i]->variant->has_cam_if) continue; - flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0; + flags = ((1 << i) & link_mask) ? MEDIA_LNK_FL_ENABLED : 0; sink = &fmd->fimc[i]->vid_cap.subdev.entity; ret = media_entity_create_link(source, pad, sink, @@ -556,7 +556,10 @@ static int __fimc_md_create_fimc_sink_links(struct fimc_md *fmd, if (!fmd->fimc_lite[i]) continue; - flags = (i == fimc_id) ? MEDIA_LNK_FL_ENABLED : 0; + if (link_mask & (1 << (i + FIMC_MAX_DEVS))) + flags = MEDIA_LNK_FL_ENABLED; + else + flags = 0; sink = &fmd->fimc_lite[i]->subdev.entity; ret = media_entity_create_link(source, pad, sink, @@ -618,9 +621,8 @@ static int fimc_md_create_links(struct fimc_md *fmd) struct s5p_fimc_isp_info *pdata; struct fimc_sensor_info *s_info; struct media_entity *source, *sink; - int i, pad, fimc_id = 0; - int ret = 0; - u32 flags; + int i, pad, fimc_id = 0, ret = 0; + u32 flags, link_mask = 0; for (i = 0; i < fmd->num_sensors; i++) { if (fmd->sensor[i].subdev == NULL) @@ -672,19 +674,20 @@ static int fimc_md_create_links(struct fimc_md *fmd) if (source == NULL) continue; + link_mask = 1 << fimc_id++; ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor, - pad, fimc_id++); + pad, link_mask); } - fimc_id = 0; for (i = 0; i < ARRAY_SIZE(fmd->csis); i++) { if (fmd->csis[i].sd == NULL) continue; source = &fmd->csis[i].sd->entity; pad = CSIS_PAD_SOURCE; + link_mask = 1 << fimc_id++; ret = __fimc_md_create_fimc_sink_links(fmd, source, NULL, - pad, fimc_id++); + pad, link_mask); } /* Create immutable links between each FIMC's subdev and video node */ -- cgit v1.2.3 From e3fc82e8b9f550d28f05600b98bcc8c26beef2ef Mon Sep 17 00:00:00 2001 From: Sylwester Nawrocki Date: Thu, 17 May 2012 14:22:10 -0300 Subject: [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] [] (dump_backtrace+0x0/0x10c) from [] (dump_stack+0x18/0x1c) [13.070000] r7:00000009 r6:00000313 r5:c02d576c r4:00000000 [13.155000] [] (dump_stack+0x0/0x1c) from [] (warn_slowpath_common+0x54/0x6c) [13.285000] [] (warn_slowpath_common+0x0/0x6c) from [] (warn_slowpath_null+0x24/0x2c) [13.360000] r9:e1981010 r8:00000000 r7:c061d3fc r6:e1981010 r5:e1981030 [13.430000] r4:00000000 [13.430000] [] (warn_slowpath_null+0x0/0x2c) from [] (__fimc_md_set_camclk+0x1c0/0x1dc) [13.550000] [] (__fimc_md_set_camclk+0x0/0x1dc) from [] (fimc_md_set_camclk+0x28/0x2c) [13.630000] [] (fimc_md_set_camclk+0x0/0x2c) from [] (__fimc_pipeline_shutdown+0x34/0x50) [13.705000] [] (__fimc_pipeline_shutdown+0x0/0x50) from [] (fimc_pipeline_shutdown+0x40/0x58) [13.765000] r5:e2391200 r4:e2357704 [13.805000] [] (fimc_pipeline_shutdown+0x0/0x58) from [] (fimc_capture_close+0xcc/0xe4) [13.915000] r5:e1b396c0 r4:e2357410 [13.915000] [] (fimc_capture_close+0x0/0xe4) from [] (v4l2_release+0x5c/0x80) [13.970000] r7:00000010 r6:e1d2d990 r5:e1b396c0 r4:e2394800 [14.000000] [] (v4l2_release+0x0/0x80) from [] (fput+0xc0/0x22c) [14.015000] r5:c157ef30 r4:e1b396c0 [14.015000] [] (fput+0x0/0x22c) from [] (filp_close+0x60/0x80) [14.080000] [] (filp_close+0x0/0x80) from [] (sys_close+0xb8/0xf4) [14.125000] r7:00000001 r6:e1b396c0 r5:c1400340 r4:c1400300 [14.125000] [] (sys_close+0x0/0xf4) from [] (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 Signed-off-by: Kyungmin Park Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/s5p-fimc/fimc-mdevice.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'drivers/media/video/s5p-fimc/fimc-mdevice.c') diff --git a/drivers/media/video/s5p-fimc/fimc-mdevice.c b/drivers/media/video/s5p-fimc/fimc-mdevice.c index dffe4da5eaa0..52cef4865423 100644 --- a/drivers/media/video/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/video/s5p-fimc/fimc-mdevice.c @@ -741,8 +741,8 @@ static void fimc_md_put_clocks(struct fimc_md *fmd) } static int __fimc_md_set_camclk(struct fimc_md *fmd, - struct fimc_sensor_info *s_info, - bool on) + struct fimc_sensor_info *s_info, + bool on) { struct s5p_fimc_isp_info *pdata = s_info->pdata; struct fimc_camclk_info *camclk; @@ -751,12 +751,10 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, if (WARN_ON(pdata->clk_id >= FIMC_MAX_CAMCLKS) || fmd == NULL) return -EINVAL; - if (s_info->clk_on == on) - return 0; camclk = &fmd->camclk[pdata->clk_id]; - dbg("camclk %d, f: %lu, clk: %p, on: %d", - pdata->clk_id, pdata->clk_frequency, camclk, on); + dbg("camclk %d, f: %lu, use_count: %d, on: %d", + pdata->clk_id, pdata->clk_frequency, camclk->use_count, on); if (on) { if (camclk->use_count > 0 && @@ -767,11 +765,9 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, clk_set_rate(camclk->clock, pdata->clk_frequency); camclk->frequency = pdata->clk_frequency; ret = clk_enable(camclk->clock); + dbg("Enabled camclk %d: f: %lu", pdata->clk_id, + clk_get_rate(camclk->clock)); } - s_info->clk_on = 1; - dbg("Enabled camclk %d: f: %lu", pdata->clk_id, - clk_get_rate(camclk->clock)); - return ret; } @@ -780,7 +776,6 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, if (--camclk->use_count == 0) { clk_disable(camclk->clock); - s_info->clk_on = 0; dbg("Disabled camclk %d", pdata->clk_id); } return ret; @@ -796,8 +791,6 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, * devices to which sensors can be attached, either directly or through * the MIPI CSI receiver. The clock is allowed here to be used by * multiple sensors concurrently if they use same frequency. - * The per sensor subdev clk_on attribute helps to synchronize accesses - * to the sclk_cam clocks from the video and media device nodes. * This function should only be called when the graph mutex is held. */ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on) -- cgit v1.2.3