]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
[media] omap3isp: Fix memory leaks in initialization error paths
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Thu, 22 Sep 2011 20:10:30 +0000 (17:10 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 3 Nov 2011 20:33:46 +0000 (18:33 -0200)
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>
drivers/media/video/omap3isp/ispccdc.c
drivers/media/video/omap3isp/ispccp2.c
drivers/media/video/omap3isp/ispcsi2.c
drivers/media/video/omap3isp/isppreview.c
drivers/media/video/omap3isp/ispresizer.c
drivers/media/video/omap3isp/ispstat.c

index 3a43be2f54521578f6df8cc541f45a18080c5408..6330b1d57b1ee7df710362b9a797380569e64662 100644 (file)
@@ -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;
 }
 
 /*
index 883a2825cb41a267d559687c3d2efa2f8701d603..904ca8c8b17fb982e56faa32015336c1aea6435b 100644 (file)
@@ -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;
 }
 
 /*
index 2c9bffcdc5c9521ed7b3ca27b6b5c4eec34610cb..0c5f1cb9d99d874d3807db776357879726bf9a0e 100644 (file)
@@ -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;
 }
 
 /*
index b926ebbaca3afa0c84760977d1e23fd80159e928..b3818356b6f3196f79d203dfbd0316435e36d75b 100644 (file)
@@ -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)
index 224b0b90404d2309e636ba545e6adacb46b8bd31..50e593bfcfaf02d069311fe3f6543089eb0d749c 100644 (file)
@@ -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)
index 28b7cc61cba6a5208f2b34c38843e3fe12ee751c..68d539456c552aa0c5ee16bd999ed09f41dee712 100644 (file)
@@ -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)