Skip to content

Commit

Permalink
[media] omap3isp: Fix memory leaks in initialization error paths
Browse files Browse the repository at this point in the history
Make sure all modules init functions clean up after themselves in case
of error.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reported-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Laurent Pinchart authored and Mauro Carvalho Chehab committed Nov 3, 2011
1 parent ed33ac8 commit 9b6390b
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 47 deletions.
19 changes: 16 additions & 3 deletions drivers/media/video/omap3isp/ispccdc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2224,15 +2224,21 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)

ret = omap3isp_video_init(&ccdc->video_out, "CCDC");
if (ret < 0)
return ret;
goto error_video;

/* Connect the CCDC subdev to the video node. */
ret = media_entity_create_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
&ccdc->video_out.video.entity, 0, 0);
if (ret < 0)
return ret;
goto error_link;

return 0;

error_link:
omap3isp_video_cleanup(&ccdc->video_out);
error_video:
media_entity_cleanup(me);
return ret;
}

/*
Expand All @@ -2246,6 +2252,7 @@ static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
int omap3isp_ccdc_init(struct isp_device *isp)
{
struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
int ret;

spin_lock_init(&ccdc->lock);
init_waitqueue_head(&ccdc->wait);
Expand Down Expand Up @@ -2274,7 +2281,13 @@ int omap3isp_ccdc_init(struct isp_device *isp)
ccdc->update = OMAP3ISP_CCDC_BLCLAMP;
ccdc_apply_controls(ccdc);

return ccdc_init_entities(ccdc);
ret = ccdc_init_entities(ccdc);
if (ret < 0) {
mutex_destroy(&ccdc->ioctl_lock);
return ret;
}

return 0;
}

/*
Expand Down
22 changes: 13 additions & 9 deletions drivers/media/video/omap3isp/ispccp2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1125,15 +1125,21 @@ static int ccp2_init_entities(struct isp_ccp2_device *ccp2)

ret = omap3isp_video_init(&ccp2->video_in, "CCP2");
if (ret < 0)
return ret;
goto error_video;

/* Connect the video node to the ccp2 subdev. */
ret = media_entity_create_link(&ccp2->video_in.video.entity, 0,
&ccp2->subdev.entity, CCP2_PAD_SINK, 0);
if (ret < 0)
return ret;
goto error_link;

return 0;

error_link:
omap3isp_video_cleanup(&ccp2->video_in);
error_video:
media_entity_cleanup(&ccp2->subdev.entity);
return ret;
}

/*
Expand Down Expand Up @@ -1171,15 +1177,13 @@ int omap3isp_ccp2_init(struct isp_device *isp)
}

ret = ccp2_init_entities(ccp2);
if (ret < 0)
goto out;
if (ret < 0) {
regulator_put(ccp2->vdds_csib);
return ret;
}

ccp2_reset(ccp2);
out:
if (ret)
omap3isp_ccp2_cleanup(isp);

return ret;
return 0;
}

/*
Expand Down
15 changes: 9 additions & 6 deletions drivers/media/video/omap3isp/ispcsi2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1259,15 +1259,21 @@ static int csi2_init_entities(struct isp_csi2_device *csi2)

ret = omap3isp_video_init(&csi2->video_out, "CSI2a");
if (ret < 0)
return ret;
goto error_video;

/* Connect the CSI2 subdev to the video node. */
ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
&csi2->video_out.video.entity, 0, 0);
if (ret < 0)
return ret;
goto error_link;

return 0;

error_link:
omap3isp_video_cleanup(&csi2->video_out);
error_video:
media_entity_cleanup(&csi2->subdev.entity);
return ret;
}

/*
Expand All @@ -1289,7 +1295,7 @@ int omap3isp_csi2_init(struct isp_device *isp)

ret = csi2_init_entities(csi2a);
if (ret < 0)
goto fail;
return ret;

if (isp->revision == ISP_REVISION_15_0) {
csi2c->isp = isp;
Expand All @@ -1302,9 +1308,6 @@ int omap3isp_csi2_init(struct isp_device *isp)
}

return 0;
fail:
omap3isp_csi2_cleanup(isp);
return ret;
}

/*
Expand Down
27 changes: 13 additions & 14 deletions drivers/media/video/omap3isp/isppreview.c
Original file line number Diff line number Diff line change
Expand Up @@ -2060,24 +2060,32 @@ static int preview_init_entities(struct isp_prev_device *prev)

ret = omap3isp_video_init(&prev->video_in, "preview");
if (ret < 0)
return ret;
goto error_video_in;

ret = omap3isp_video_init(&prev->video_out, "preview");
if (ret < 0)
return ret;
goto error_video_out;

/* Connect the video nodes to the previewer subdev. */
ret = media_entity_create_link(&prev->video_in.video.entity, 0,
&prev->subdev.entity, PREV_PAD_SINK, 0);
if (ret < 0)
return ret;
goto error_link;

ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
&prev->video_out.video.entity, 0, 0);
if (ret < 0)
return ret;
goto error_link;

return 0;

error_link:
omap3isp_video_cleanup(&prev->video_out);
error_video_out:
omap3isp_video_cleanup(&prev->video_in);
error_video_in:
media_entity_cleanup(&prev->subdev.entity);
return ret;
}

/*
Expand All @@ -2088,21 +2096,12 @@ static int preview_init_entities(struct isp_prev_device *prev)
int omap3isp_preview_init(struct isp_device *isp)
{
struct isp_prev_device *prev = &isp->isp_prev;
int ret;

spin_lock_init(&prev->lock);
init_waitqueue_head(&prev->wait);
preview_init_params(prev);

ret = preview_init_entities(prev);
if (ret < 0)
goto out;

out:
if (ret)
omap3isp_preview_cleanup(isp);

return ret;
return preview_init_entities(prev);
}

void omap3isp_preview_cleanup(struct isp_device *isp)
Expand Down
27 changes: 13 additions & 14 deletions drivers/media/video/omap3isp/ispresizer.c
Original file line number Diff line number Diff line change
Expand Up @@ -1688,24 +1688,32 @@ static int resizer_init_entities(struct isp_res_device *res)

ret = omap3isp_video_init(&res->video_in, "resizer");
if (ret < 0)
return ret;
goto error_video_in;

ret = omap3isp_video_init(&res->video_out, "resizer");
if (ret < 0)
return ret;
goto error_video_out;

/* Connect the video nodes to the resizer subdev. */
ret = media_entity_create_link(&res->video_in.video.entity, 0,
&res->subdev.entity, RESZ_PAD_SINK, 0);
if (ret < 0)
return ret;
goto error_link;

ret = media_entity_create_link(&res->subdev.entity, RESZ_PAD_SOURCE,
&res->video_out.video.entity, 0, 0);
if (ret < 0)
return ret;
goto error_link;

return 0;

error_link:
omap3isp_video_cleanup(&res->video_out);
error_video_out:
omap3isp_video_cleanup(&res->video_in);
error_video_in:
media_entity_cleanup(&res->subdev.entity);
return ret;
}

/*
Expand All @@ -1716,19 +1724,10 @@ static int resizer_init_entities(struct isp_res_device *res)
int omap3isp_resizer_init(struct isp_device *isp)
{
struct isp_res_device *res = &isp->isp_res;
int ret;

init_waitqueue_head(&res->wait);
atomic_set(&res->stopping, 0);
ret = resizer_init_entities(res);
if (ret < 0)
goto out;

out:
if (ret)
omap3isp_resizer_cleanup(isp);

return ret;
return resizer_init_entities(res);
}

void omap3isp_resizer_cleanup(struct isp_device *isp)
Expand Down
11 changes: 10 additions & 1 deletion drivers/media/video/omap3isp/ispstat.c
Original file line number Diff line number Diff line change
Expand Up @@ -1074,14 +1074,23 @@ static int isp_stat_init_entities(struct ispstat *stat, const char *name,
int omap3isp_stat_init(struct ispstat *stat, const char *name,
const struct v4l2_subdev_ops *sd_ops)
{
int ret;

stat->buf = kcalloc(STAT_MAX_BUFS, sizeof(*stat->buf), GFP_KERNEL);
if (!stat->buf)
return -ENOMEM;

isp_stat_buf_clear(stat);
mutex_init(&stat->ioctl_lock);
atomic_set(&stat->buf_err, 0);

return isp_stat_init_entities(stat, name, sd_ops);
ret = isp_stat_init_entities(stat, name, sd_ops);
if (ret < 0) {
mutex_destroy(&stat->ioctl_lock);
kfree(stat->buf);
}

return ret;
}

void omap3isp_stat_cleanup(struct ispstat *stat)
Expand Down

0 comments on commit 9b6390b

Please sign in to comment.