diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2011-09-22 17:10:30 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-11-03 18:33:46 -0200 |
commit | 9b6390bd95c65ad4a6c650955fa1e3f18f8a540c (patch) | |
tree | 3e1dcd35d28f0793dd62d1a3ff72b4831890a118 /drivers/media/video/omap3isp | |
parent | ed33ac8e0876a3016511ea0aaf9af1d965ee2c44 (diff) |
[media] omap3isp: Fix memory leaks in initialization error paths
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>
Diffstat (limited to 'drivers/media/video/omap3isp')
-rw-r--r-- | drivers/media/video/omap3isp/ispccdc.c | 19 | ||||
-rw-r--r-- | drivers/media/video/omap3isp/ispccp2.c | 22 | ||||
-rw-r--r-- | drivers/media/video/omap3isp/ispcsi2.c | 15 | ||||
-rw-r--r-- | drivers/media/video/omap3isp/isppreview.c | 27 | ||||
-rw-r--r-- | drivers/media/video/omap3isp/ispresizer.c | 27 | ||||
-rw-r--r-- | drivers/media/video/omap3isp/ispstat.c | 11 |
6 files changed, 74 insertions, 47 deletions
diff --git a/drivers/media/video/omap3isp/ispccdc.c b/drivers/media/video/omap3isp/ispccdc.c index 3a43be2f545..6330b1d57b1 100644 --- a/drivers/media/video/omap3isp/ispccdc.c +++ b/drivers/media/video/omap3isp/ispccdc.c @@ -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; } /* @@ -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); @@ -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; } /* diff --git a/drivers/media/video/omap3isp/ispccp2.c b/drivers/media/video/omap3isp/ispccp2.c index 883a2825cb4..904ca8c8b17 100644 --- a/drivers/media/video/omap3isp/ispccp2.c +++ b/drivers/media/video/omap3isp/ispccp2.c @@ -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; } /* @@ -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; } /* diff --git a/drivers/media/video/omap3isp/ispcsi2.c b/drivers/media/video/omap3isp/ispcsi2.c index 2c9bffcdc5c..0c5f1cb9d99 100644 --- a/drivers/media/video/omap3isp/ispcsi2.c +++ b/drivers/media/video/omap3isp/ispcsi2.c @@ -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; } /* @@ -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; @@ -1302,9 +1308,6 @@ int omap3isp_csi2_init(struct isp_device *isp) } return 0; -fail: - omap3isp_csi2_cleanup(isp); - return ret; } /* diff --git a/drivers/media/video/omap3isp/isppreview.c b/drivers/media/video/omap3isp/isppreview.c index b926ebbaca3..b3818356b6f 100644 --- a/drivers/media/video/omap3isp/isppreview.c +++ b/drivers/media/video/omap3isp/isppreview.c @@ -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; } /* @@ -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) diff --git a/drivers/media/video/omap3isp/ispresizer.c b/drivers/media/video/omap3isp/ispresizer.c index 224b0b90404..50e593bfcfa 100644 --- a/drivers/media/video/omap3isp/ispresizer.c +++ b/drivers/media/video/omap3isp/ispresizer.c @@ -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; } /* @@ -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) diff --git a/drivers/media/video/omap3isp/ispstat.c b/drivers/media/video/omap3isp/ispstat.c index 28b7cc61cba..68d539456c5 100644 --- a/drivers/media/video/omap3isp/ispstat.c +++ b/drivers/media/video/omap3isp/ispstat.c @@ -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) |